brintos

brintos / linux-shallow public Read only

0
0
Text · 6.6 KiB · 19c6395 Raw
289 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for the ADB controller in the Mac I/O (Hydra) chip.4 */5#include <linux/types.h>6#include <linux/errno.h>7#include <linux/kernel.h>8#include <linux/delay.h>9#include <linux/spinlock.h>10#include <linux/interrupt.h>11#include <linux/pgtable.h>12#include <linux/of.h>13#include <linux/of_address.h>14#include <linux/of_irq.h>15#include <linux/adb.h>16 17#include <asm/io.h>18#include <asm/hydra.h>19#include <asm/irq.h>20#include <linux/init.h>21#include <linux/ioport.h>22 23struct preg {24	unsigned char r;25	char pad[15];26};27 28struct adb_regs {29	struct preg intr;30	struct preg data[9];31	struct preg intr_enb;32	struct preg dcount;33	struct preg error;34	struct preg ctrl;35	struct preg autopoll;36	struct preg active_hi;37	struct preg active_lo;38	struct preg test;39};40 41/* Bits in intr and intr_enb registers */42#define DFB	1		/* data from bus */43#define TAG	2		/* transfer access grant */44 45/* Bits in dcount register */46#define HMB	0x0f		/* how many bytes */47#define APD	0x10		/* auto-poll data */48 49/* Bits in error register */50#define NRE	1		/* no response error */51#define DLE	2		/* data lost error */52 53/* Bits in ctrl register */54#define TAR	1		/* transfer access request */55#define DTB	2		/* data to bus */56#define CRE	4		/* command response expected */57#define ADB_RST	8		/* ADB reset */58 59/* Bits in autopoll register */60#define APE	1		/* autopoll enable */61 62static volatile struct adb_regs __iomem *adb;63static struct adb_request *current_req, *last_req;64static DEFINE_SPINLOCK(macio_lock);65 66static int macio_probe(void);67static int macio_init(void);68static irqreturn_t macio_adb_interrupt(int irq, void *arg);69static int macio_send_request(struct adb_request *req, int sync);70static int macio_adb_autopoll(int devs);71static void macio_adb_poll(void);72static int macio_adb_reset_bus(void);73 74struct adb_driver macio_adb_driver = {75	.name         = "MACIO",76	.probe        = macio_probe,77	.init         = macio_init,78	.send_request = macio_send_request,79	.autopoll     = macio_adb_autopoll,80	.poll         = macio_adb_poll,81	.reset_bus    = macio_adb_reset_bus,82};83 84int macio_probe(void)85{86	struct device_node *np __free(device_node) =87		of_find_compatible_node(NULL, "adb", "chrp,adb0");88 89	if (np)90		return 0;91 92	return -ENODEV;93}94 95int macio_init(void)96{97	struct device_node *adbs __free(device_node) =98		of_find_compatible_node(NULL, "adb", "chrp,adb0");99	struct resource r;100	unsigned int irq;101 102	if (!adbs)103		return -ENXIO;104 105	if (of_address_to_resource(adbs, 0, &r))106		return -ENXIO;107 108	adb = ioremap(r.start, sizeof(struct adb_regs));109	if (!adb)110		return -ENOMEM;111 112 113	out_8(&adb->ctrl.r, 0);114	out_8(&adb->intr.r, 0);115	out_8(&adb->error.r, 0);116	out_8(&adb->active_hi.r, 0xff); /* for now, set all devices active */117	out_8(&adb->active_lo.r, 0xff);118	out_8(&adb->autopoll.r, APE);119 120	irq = irq_of_parse_and_map(adbs, 0);121	if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) {122		iounmap(adb);123		printk(KERN_ERR "ADB: can't get irq %d\n", irq);124		return -EAGAIN;125	}126	out_8(&adb->intr_enb.r, DFB | TAG);127 128	printk("adb: mac-io driver 1.0 for unified ADB\n");129 130	return 0;131}132 133static int macio_adb_autopoll(int devs)134{135	unsigned long flags;136	137	spin_lock_irqsave(&macio_lock, flags);138	out_8(&adb->active_hi.r, devs >> 8);139	out_8(&adb->active_lo.r, devs);140	out_8(&adb->autopoll.r, devs? APE: 0);141	spin_unlock_irqrestore(&macio_lock, flags);142	return 0;143}144 145static int macio_adb_reset_bus(void)146{147	unsigned long flags;148	int timeout = 1000000;149 150	/* Hrm... we may want to not lock interrupts for so151	 * long ... oh well, who uses that chip anyway ? :)152	 * That function will be seldom used during boot153	 * on rare machines, so...154	 */155	spin_lock_irqsave(&macio_lock, flags);156	out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | ADB_RST);157	while ((in_8(&adb->ctrl.r) & ADB_RST) != 0) {158		if (--timeout == 0) {159			out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) & ~ADB_RST);160			spin_unlock_irqrestore(&macio_lock, flags);161			return -1;162		}163	}164	spin_unlock_irqrestore(&macio_lock, flags);165	return 0;166}167 168/* Send an ADB command */169static int macio_send_request(struct adb_request *req, int sync)170{171	unsigned long flags;172	int i;173	174	if (req->data[0] != ADB_PACKET)175		return -EINVAL;176	177	for (i = 0; i < req->nbytes - 1; ++i)178		req->data[i] = req->data[i+1];179	--req->nbytes;180	181	req->next = NULL;182	req->sent = 0;183	req->complete = 0;184	req->reply_len = 0;185 186	spin_lock_irqsave(&macio_lock, flags);187	if (current_req) {188		last_req->next = req;189		last_req = req;190	} else {191		current_req = last_req = req;192		out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);193	}194	spin_unlock_irqrestore(&macio_lock, flags);195	196	if (sync) {197		while (!req->complete)198			macio_adb_poll();199	}200 201	return 0;202}203 204static irqreturn_t macio_adb_interrupt(int irq, void *arg)205{206	int i, n, err;207	struct adb_request *req = NULL;208	unsigned char ibuf[16];209	int ibuf_len = 0;210	int complete = 0;211	int autopoll = 0;212	int handled = 0;213 214	spin_lock(&macio_lock);215	if (in_8(&adb->intr.r) & TAG) {216		handled = 1;217		req = current_req;218		if (req) {219			/* put the current request in */220			for (i = 0; i < req->nbytes; ++i)221				out_8(&adb->data[i].r, req->data[i]);222			out_8(&adb->dcount.r, req->nbytes & HMB);223			req->sent = 1;224			if (req->reply_expected) {225				out_8(&adb->ctrl.r, DTB + CRE);226			} else {227				out_8(&adb->ctrl.r, DTB);228				current_req = req->next;229				complete = 1;230				if (current_req)231					out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);232			}233		}234		out_8(&adb->intr.r, 0);235	}236 237	if (in_8(&adb->intr.r) & DFB) {238		handled = 1;239		err = in_8(&adb->error.r);240		if (current_req && current_req->sent) {241			/* this is the response to a command */242			req = current_req;243			if (err == 0) {244				req->reply_len = in_8(&adb->dcount.r) & HMB;245				for (i = 0; i < req->reply_len; ++i)246					req->reply[i] = in_8(&adb->data[i].r);247			}248			current_req = req->next;249			complete = 1;250			if (current_req)251				out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);252		} else if (err == 0) {253			/* autopoll data */254			n = in_8(&adb->dcount.r) & HMB;255			for (i = 0; i < n; ++i)256				ibuf[i] = in_8(&adb->data[i].r);257			ibuf_len = n;258			autopoll = (in_8(&adb->dcount.r) & APD) != 0;259		}260		out_8(&adb->error.r, 0);261		out_8(&adb->intr.r, 0);262	}263	spin_unlock(&macio_lock);264	if (complete && req) {265	    void (*done)(struct adb_request *) = req->done;266	    mb();267	    req->complete = 1;268	    /* Here, we assume that if the request has a done member, the269    	     * struct request will survive to setting req->complete to 1270	     */271	    if (done)272		(*done)(req);273	}274	if (ibuf_len)275		adb_input(ibuf, ibuf_len, autopoll);276 277	return IRQ_RETVAL(handled);278}279 280static void macio_adb_poll(void)281{282	unsigned long flags;283 284	local_irq_save(flags);285	if (in_8(&adb->intr.r) != 0)286		macio_adb_interrupt(0, NULL);287	local_irq_restore(flags);288}289