xref: /OK3568_Linux_fs/kernel/drivers/macintosh/via-macii.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Device driver for the via ADB on (many) Mac II-class machines
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Based on the original ADB keyboard handler Copyright (c) 1997 Alan Cox
6*4882a593Smuzhiyun  * Also derived from code Copyright (C) 1996 Paul Mackerras.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * With various updates provided over the years by Michael Schmitz,
9*4882a593Smuzhiyun  * Guideo Koerber and others.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Rewrite for Unified ADB by Joshua M. Thompson (funaho@jurai.org)
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * 1999-08-02 (jmt) - Initial rewrite for Unified ADB.
14*4882a593Smuzhiyun  * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org>
15*4882a593Smuzhiyun  *            - Big overhaul, should actually work now.
16*4882a593Smuzhiyun  * 2006-12-31 Finn Thain - Another overhaul.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * Suggested reading:
19*4882a593Smuzhiyun  *   Inside Macintosh, ch. 5 ADB Manager
20*4882a593Smuzhiyun  *   Guide to the Macinstosh Family Hardware, ch. 8 Apple Desktop Bus
21*4882a593Smuzhiyun  *   Rockwell R6522 VIA datasheet
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * Apple's "ADB Analyzer" bus sniffer is invaluable:
24*4882a593Smuzhiyun  *   ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/
25*4882a593Smuzhiyun  */
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <stdarg.h>
28*4882a593Smuzhiyun #include <linux/types.h>
29*4882a593Smuzhiyun #include <linux/errno.h>
30*4882a593Smuzhiyun #include <linux/kernel.h>
31*4882a593Smuzhiyun #include <linux/delay.h>
32*4882a593Smuzhiyun #include <linux/adb.h>
33*4882a593Smuzhiyun #include <linux/interrupt.h>
34*4882a593Smuzhiyun #include <linux/init.h>
35*4882a593Smuzhiyun #include <asm/macintosh.h>
36*4882a593Smuzhiyun #include <asm/macints.h>
37*4882a593Smuzhiyun #include <asm/mac_via.h>
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun static volatile unsigned char *via;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /* VIA registers - spaced 0x200 bytes apart */
42*4882a593Smuzhiyun #define RS		0x200		/* skip between registers */
43*4882a593Smuzhiyun #define B		0		/* B-side data */
44*4882a593Smuzhiyun #define A		RS		/* A-side data */
45*4882a593Smuzhiyun #define DIRB		(2*RS)		/* B-side direction (1=output) */
46*4882a593Smuzhiyun #define DIRA		(3*RS)		/* A-side direction (1=output) */
47*4882a593Smuzhiyun #define T1CL		(4*RS)		/* Timer 1 ctr/latch (low 8 bits) */
48*4882a593Smuzhiyun #define T1CH		(5*RS)		/* Timer 1 counter (high 8 bits) */
49*4882a593Smuzhiyun #define T1LL		(6*RS)		/* Timer 1 latch (low 8 bits) */
50*4882a593Smuzhiyun #define T1LH		(7*RS)		/* Timer 1 latch (high 8 bits) */
51*4882a593Smuzhiyun #define T2CL		(8*RS)		/* Timer 2 ctr/latch (low 8 bits) */
52*4882a593Smuzhiyun #define T2CH		(9*RS)		/* Timer 2 counter (high 8 bits) */
53*4882a593Smuzhiyun #define SR		(10*RS)		/* Shift register */
54*4882a593Smuzhiyun #define ACR		(11*RS)		/* Auxiliary control register */
55*4882a593Smuzhiyun #define PCR		(12*RS)		/* Peripheral control register */
56*4882a593Smuzhiyun #define IFR		(13*RS)		/* Interrupt flag register */
57*4882a593Smuzhiyun #define IER		(14*RS)		/* Interrupt enable register */
58*4882a593Smuzhiyun #define ANH		(15*RS)		/* A-side data, no handshake */
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /* Bits in B data register: all active low */
61*4882a593Smuzhiyun #define CTLR_IRQ	0x08		/* Controller rcv status (input) */
62*4882a593Smuzhiyun #define ST_MASK		0x30		/* mask for selecting ADB state bits */
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /* Bits in ACR */
65*4882a593Smuzhiyun #define SR_CTRL		0x1c		/* Shift register control bits */
66*4882a593Smuzhiyun #define SR_EXT		0x0c		/* Shift on external clock */
67*4882a593Smuzhiyun #define SR_OUT		0x10		/* Shift out if 1 */
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun /* Bits in IFR and IER */
70*4882a593Smuzhiyun #define IER_SET		0x80		/* set bits in IER */
71*4882a593Smuzhiyun #define IER_CLR		0		/* clear bits in IER */
72*4882a593Smuzhiyun #define SR_INT		0x04		/* Shift register full/empty */
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /* ADB transaction states according to GMHW */
75*4882a593Smuzhiyun #define ST_CMD		0x00		/* ADB state: command byte */
76*4882a593Smuzhiyun #define ST_EVEN		0x10		/* ADB state: even data byte */
77*4882a593Smuzhiyun #define ST_ODD		0x20		/* ADB state: odd data byte */
78*4882a593Smuzhiyun #define ST_IDLE		0x30		/* ADB state: idle, nothing to send */
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun /* ADB command byte structure */
81*4882a593Smuzhiyun #define ADDR_MASK	0xF0
82*4882a593Smuzhiyun #define CMD_MASK	0x0F
83*4882a593Smuzhiyun #define OP_MASK		0x0C
84*4882a593Smuzhiyun #define TALK		0x0C
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static int macii_init_via(void);
87*4882a593Smuzhiyun static void macii_start(void);
88*4882a593Smuzhiyun static irqreturn_t macii_interrupt(int irq, void *arg);
89*4882a593Smuzhiyun static void macii_queue_poll(void);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun static int macii_probe(void);
92*4882a593Smuzhiyun static int macii_init(void);
93*4882a593Smuzhiyun static int macii_send_request(struct adb_request *req, int sync);
94*4882a593Smuzhiyun static int macii_write(struct adb_request *req);
95*4882a593Smuzhiyun static int macii_autopoll(int devs);
96*4882a593Smuzhiyun static void macii_poll(void);
97*4882a593Smuzhiyun static int macii_reset_bus(void);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun struct adb_driver via_macii_driver = {
100*4882a593Smuzhiyun 	.name         = "Mac II",
101*4882a593Smuzhiyun 	.probe        = macii_probe,
102*4882a593Smuzhiyun 	.init         = macii_init,
103*4882a593Smuzhiyun 	.send_request = macii_send_request,
104*4882a593Smuzhiyun 	.autopoll     = macii_autopoll,
105*4882a593Smuzhiyun 	.poll         = macii_poll,
106*4882a593Smuzhiyun 	.reset_bus    = macii_reset_bus,
107*4882a593Smuzhiyun };
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun static enum macii_state {
110*4882a593Smuzhiyun 	idle,
111*4882a593Smuzhiyun 	sending,
112*4882a593Smuzhiyun 	reading,
113*4882a593Smuzhiyun } macii_state;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun static struct adb_request *current_req; /* first request struct in the queue */
116*4882a593Smuzhiyun static struct adb_request *last_req;     /* last request struct in the queue */
117*4882a593Smuzhiyun static unsigned char reply_buf[16];        /* storage for autopolled replies */
118*4882a593Smuzhiyun static unsigned char *reply_ptr;     /* next byte in reply_buf or req->reply */
119*4882a593Smuzhiyun static bool reading_reply;       /* store reply in reply_buf else req->reply */
120*4882a593Smuzhiyun static int data_index;      /* index of the next byte to send from req->data */
121*4882a593Smuzhiyun static int reply_len; /* number of bytes received in reply_buf or req->reply */
122*4882a593Smuzhiyun static int status;          /* VIA's ADB status bits captured upon interrupt */
123*4882a593Smuzhiyun static bool bus_timeout;                   /* no data was sent by the device */
124*4882a593Smuzhiyun static bool srq_asserted;    /* have to poll for the device that asserted it */
125*4882a593Smuzhiyun static u8 last_cmd;              /* the most recent command byte transmitted */
126*4882a593Smuzhiyun static u8 last_talk_cmd;    /* the most recent Talk command byte transmitted */
127*4882a593Smuzhiyun static u8 last_poll_cmd; /* the most recent Talk R0 command byte transmitted */
128*4882a593Smuzhiyun static unsigned int autopoll_devs;  /* bits set are device addresses to poll */
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun /* Check for MacII style ADB */
macii_probe(void)131*4882a593Smuzhiyun static int macii_probe(void)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	if (macintosh_config->adb_type != MAC_ADB_II)
134*4882a593Smuzhiyun 		return -ENODEV;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	via = via1;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	pr_info("adb: Mac II ADB Driver v1.0 for Unified ADB\n");
139*4882a593Smuzhiyun 	return 0;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun /* Initialize the driver */
macii_init(void)143*4882a593Smuzhiyun static int macii_init(void)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	unsigned long flags;
146*4882a593Smuzhiyun 	int err;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	local_irq_save(flags);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	err = macii_init_via();
151*4882a593Smuzhiyun 	if (err)
152*4882a593Smuzhiyun 		goto out;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
155*4882a593Smuzhiyun 			  macii_interrupt);
156*4882a593Smuzhiyun 	if (err)
157*4882a593Smuzhiyun 		goto out;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	macii_state = idle;
160*4882a593Smuzhiyun out:
161*4882a593Smuzhiyun 	local_irq_restore(flags);
162*4882a593Smuzhiyun 	return err;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun /* initialize the hardware */
macii_init_via(void)166*4882a593Smuzhiyun static int macii_init_via(void)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	unsigned char x;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/* We want CTLR_IRQ as input and ST_EVEN | ST_ODD as output lines. */
171*4882a593Smuzhiyun 	via[DIRB] = (via[DIRB] | ST_EVEN | ST_ODD) & ~CTLR_IRQ;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	/* Set up state: idle */
174*4882a593Smuzhiyun 	via[B] |= ST_IDLE;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	/* Shift register on input */
177*4882a593Smuzhiyun 	via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	/* Wipe any pending data and int */
180*4882a593Smuzhiyun 	x = via[SR];
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	return 0;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun /* Send an ADB poll (Talk Register 0 command prepended to the request queue) */
macii_queue_poll(void)186*4882a593Smuzhiyun static void macii_queue_poll(void)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	static struct adb_request req;
189*4882a593Smuzhiyun 	unsigned char poll_command;
190*4882a593Smuzhiyun 	unsigned int poll_addr;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	/* This only polls devices in the autopoll list, which assumes that
193*4882a593Smuzhiyun 	 * unprobed devices never assert SRQ. That could happen if a device was
194*4882a593Smuzhiyun 	 * plugged in after the adb bus scan. Unplugging it again will resolve
195*4882a593Smuzhiyun 	 * the problem. This behaviour is similar to MacOS.
196*4882a593Smuzhiyun 	 */
197*4882a593Smuzhiyun 	if (!autopoll_devs)
198*4882a593Smuzhiyun 		return;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/* The device most recently polled may not be the best device to poll
201*4882a593Smuzhiyun 	 * right now. Some other device(s) may have signalled SRQ (the active
202*4882a593Smuzhiyun 	 * device won't do that). Or the autopoll list may have been changed.
203*4882a593Smuzhiyun 	 * Try polling the next higher address.
204*4882a593Smuzhiyun 	 */
205*4882a593Smuzhiyun 	poll_addr = (last_poll_cmd & ADDR_MASK) >> 4;
206*4882a593Smuzhiyun 	if ((srq_asserted && last_cmd == last_poll_cmd) ||
207*4882a593Smuzhiyun 	    !(autopoll_devs & (1 << poll_addr))) {
208*4882a593Smuzhiyun 		unsigned int higher_devs;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		higher_devs = autopoll_devs & -(1 << (poll_addr + 1));
211*4882a593Smuzhiyun 		poll_addr = ffs(higher_devs ? higher_devs : autopoll_devs) - 1;
212*4882a593Smuzhiyun 	}
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	/* Send a Talk Register 0 command */
215*4882a593Smuzhiyun 	poll_command = ADB_READREG(poll_addr, 0);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	/* No need to repeat this Talk command. The transceiver will do that
218*4882a593Smuzhiyun 	 * as long as it is idle.
219*4882a593Smuzhiyun 	 */
220*4882a593Smuzhiyun 	if (poll_command == last_cmd)
221*4882a593Smuzhiyun 		return;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	adb_request(&req, NULL, ADBREQ_NOSEND, 1, poll_command);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	req.sent = 0;
226*4882a593Smuzhiyun 	req.complete = 0;
227*4882a593Smuzhiyun 	req.reply_len = 0;
228*4882a593Smuzhiyun 	req.next = current_req;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	if (WARN_ON(current_req)) {
231*4882a593Smuzhiyun 		current_req = &req;
232*4882a593Smuzhiyun 	} else {
233*4882a593Smuzhiyun 		current_req = &req;
234*4882a593Smuzhiyun 		last_req = &req;
235*4882a593Smuzhiyun 	}
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun /* Send an ADB request; if sync, poll out the reply 'till it's done */
macii_send_request(struct adb_request * req,int sync)239*4882a593Smuzhiyun static int macii_send_request(struct adb_request *req, int sync)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	int err;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	err = macii_write(req);
244*4882a593Smuzhiyun 	if (err)
245*4882a593Smuzhiyun 		return err;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	if (sync)
248*4882a593Smuzhiyun 		while (!req->complete)
249*4882a593Smuzhiyun 			macii_poll();
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	return 0;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun /* Send an ADB request (append to request queue) */
macii_write(struct adb_request * req)255*4882a593Smuzhiyun static int macii_write(struct adb_request *req)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	unsigned long flags;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) {
260*4882a593Smuzhiyun 		req->complete = 1;
261*4882a593Smuzhiyun 		return -EINVAL;
262*4882a593Smuzhiyun 	}
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	req->next = NULL;
265*4882a593Smuzhiyun 	req->sent = 0;
266*4882a593Smuzhiyun 	req->complete = 0;
267*4882a593Smuzhiyun 	req->reply_len = 0;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	local_irq_save(flags);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	if (current_req != NULL) {
272*4882a593Smuzhiyun 		last_req->next = req;
273*4882a593Smuzhiyun 		last_req = req;
274*4882a593Smuzhiyun 	} else {
275*4882a593Smuzhiyun 		current_req = req;
276*4882a593Smuzhiyun 		last_req = req;
277*4882a593Smuzhiyun 		if (macii_state == idle)
278*4882a593Smuzhiyun 			macii_start();
279*4882a593Smuzhiyun 	}
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	local_irq_restore(flags);
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	return 0;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /* Start auto-polling */
macii_autopoll(int devs)287*4882a593Smuzhiyun static int macii_autopoll(int devs)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 	unsigned long flags;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	local_irq_save(flags);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	/* bit 1 == device 1, and so on. */
294*4882a593Smuzhiyun 	autopoll_devs = (unsigned int)devs & 0xFFFE;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	if (!current_req) {
297*4882a593Smuzhiyun 		macii_queue_poll();
298*4882a593Smuzhiyun 		if (current_req && macii_state == idle)
299*4882a593Smuzhiyun 			macii_start();
300*4882a593Smuzhiyun 	}
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	local_irq_restore(flags);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return 0;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun /* Prod the chip without interrupts */
macii_poll(void)308*4882a593Smuzhiyun static void macii_poll(void)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	macii_interrupt(0, NULL);
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun /* Reset the bus */
macii_reset_bus(void)314*4882a593Smuzhiyun static int macii_reset_bus(void)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	struct adb_request req;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	/* Command = 0, Address = ignored */
319*4882a593Smuzhiyun 	adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET);
320*4882a593Smuzhiyun 	macii_send_request(&req, 1);
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	/* Don't want any more requests during the Global Reset low time. */
323*4882a593Smuzhiyun 	udelay(3000);
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	return 0;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun /* Start sending ADB packet */
macii_start(void)329*4882a593Smuzhiyun static void macii_start(void)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	struct adb_request *req;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	req = current_req;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	/* Now send it. Be careful though, that first byte of the request
336*4882a593Smuzhiyun 	 * is actually ADB_PACKET; the real data begins at index 1!
337*4882a593Smuzhiyun 	 * And req->nbytes is the number of bytes of real data plus one.
338*4882a593Smuzhiyun 	 */
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/* Output mode */
341*4882a593Smuzhiyun 	via[ACR] |= SR_OUT;
342*4882a593Smuzhiyun 	/* Load data */
343*4882a593Smuzhiyun 	via[SR] = req->data[1];
344*4882a593Smuzhiyun 	/* set ADB state to 'command' */
345*4882a593Smuzhiyun 	via[B] = (via[B] & ~ST_MASK) | ST_CMD;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	macii_state = sending;
348*4882a593Smuzhiyun 	data_index = 2;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	bus_timeout = false;
351*4882a593Smuzhiyun 	srq_asserted = false;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun /*
355*4882a593Smuzhiyun  * The notorious ADB interrupt handler - does all of the protocol handling.
356*4882a593Smuzhiyun  * Relies on the ADB controller sending and receiving data, thereby
357*4882a593Smuzhiyun  * generating shift register interrupts (SR_INT) for us. This means there has
358*4882a593Smuzhiyun  * to be activity on the ADB bus. The chip will poll to achieve this.
359*4882a593Smuzhiyun  *
360*4882a593Smuzhiyun  * The VIA Port B output signalling works as follows. After the ADB transceiver
361*4882a593Smuzhiyun  * sees a transition on the PB4 and PB5 lines it will crank over the VIA shift
362*4882a593Smuzhiyun  * register which eventually raises the SR_INT interrupt. The PB4/PB5 outputs
363*4882a593Smuzhiyun  * are toggled with each byte as the ADB transaction progresses.
364*4882a593Smuzhiyun  *
365*4882a593Smuzhiyun  * Request with no reply expected (and empty transceiver buffer):
366*4882a593Smuzhiyun  *     CMD -> IDLE
367*4882a593Smuzhiyun  * Request with expected reply packet (or with buffered autopoll packet):
368*4882a593Smuzhiyun  *     CMD -> EVEN -> ODD -> EVEN -> ... -> IDLE
369*4882a593Smuzhiyun  * Unsolicited packet:
370*4882a593Smuzhiyun  *     IDLE -> EVEN -> ODD -> EVEN -> ... -> IDLE
371*4882a593Smuzhiyun  */
macii_interrupt(int irq,void * arg)372*4882a593Smuzhiyun static irqreturn_t macii_interrupt(int irq, void *arg)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun 	int x;
375*4882a593Smuzhiyun 	struct adb_request *req;
376*4882a593Smuzhiyun 	unsigned long flags;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	local_irq_save(flags);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	if (!arg) {
381*4882a593Smuzhiyun 		/* Clear the SR IRQ flag when polling. */
382*4882a593Smuzhiyun 		if (via[IFR] & SR_INT)
383*4882a593Smuzhiyun 			via[IFR] = SR_INT;
384*4882a593Smuzhiyun 		else {
385*4882a593Smuzhiyun 			local_irq_restore(flags);
386*4882a593Smuzhiyun 			return IRQ_NONE;
387*4882a593Smuzhiyun 		}
388*4882a593Smuzhiyun 	}
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	status = via[B] & (ST_MASK | CTLR_IRQ);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	switch (macii_state) {
393*4882a593Smuzhiyun 	case idle:
394*4882a593Smuzhiyun 		WARN_ON((status & ST_MASK) != ST_IDLE);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 		reply_ptr = reply_buf;
397*4882a593Smuzhiyun 		reading_reply = false;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 		bus_timeout = false;
400*4882a593Smuzhiyun 		srq_asserted = false;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 		x = via[SR];
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 		if (!(status & CTLR_IRQ)) {
405*4882a593Smuzhiyun 			/* /CTLR_IRQ asserted in idle state means we must
406*4882a593Smuzhiyun 			 * read an autopoll reply from the transceiver buffer.
407*4882a593Smuzhiyun 			 */
408*4882a593Smuzhiyun 			macii_state = reading;
409*4882a593Smuzhiyun 			*reply_ptr = x;
410*4882a593Smuzhiyun 			reply_len = 1;
411*4882a593Smuzhiyun 		} else {
412*4882a593Smuzhiyun 			/* bus timeout */
413*4882a593Smuzhiyun 			reply_len = 0;
414*4882a593Smuzhiyun 			break;
415*4882a593Smuzhiyun 		}
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 		/* set ADB state = even for first data byte */
418*4882a593Smuzhiyun 		via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
419*4882a593Smuzhiyun 		break;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	case sending:
422*4882a593Smuzhiyun 		req = current_req;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 		if (status == (ST_CMD | CTLR_IRQ)) {
425*4882a593Smuzhiyun 			/* /CTLR_IRQ de-asserted after the command byte means
426*4882a593Smuzhiyun 			 * the host can continue with the transaction.
427*4882a593Smuzhiyun 			 */
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 			/* Store command byte */
430*4882a593Smuzhiyun 			last_cmd = req->data[1];
431*4882a593Smuzhiyun 			if ((last_cmd & OP_MASK) == TALK) {
432*4882a593Smuzhiyun 				last_talk_cmd = last_cmd;
433*4882a593Smuzhiyun 				if ((last_cmd & CMD_MASK) == ADB_READREG(0, 0))
434*4882a593Smuzhiyun 					last_poll_cmd = last_cmd;
435*4882a593Smuzhiyun 			}
436*4882a593Smuzhiyun 		}
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 		if (status == ST_CMD) {
439*4882a593Smuzhiyun 			/* /CTLR_IRQ asserted after the command byte means we
440*4882a593Smuzhiyun 			 * must read an autopoll reply. The first byte was
441*4882a593Smuzhiyun 			 * lost because the shift register was an output.
442*4882a593Smuzhiyun 			 */
443*4882a593Smuzhiyun 			macii_state = reading;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 			reading_reply = false;
446*4882a593Smuzhiyun 			reply_ptr = reply_buf;
447*4882a593Smuzhiyun 			*reply_ptr = last_talk_cmd;
448*4882a593Smuzhiyun 			reply_len = 1;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 			/* reset to shift in */
451*4882a593Smuzhiyun 			via[ACR] &= ~SR_OUT;
452*4882a593Smuzhiyun 			x = via[SR];
453*4882a593Smuzhiyun 		} else if (data_index >= req->nbytes) {
454*4882a593Smuzhiyun 			req->sent = 1;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 			if (req->reply_expected) {
457*4882a593Smuzhiyun 				macii_state = reading;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 				reading_reply = true;
460*4882a593Smuzhiyun 				reply_ptr = req->reply;
461*4882a593Smuzhiyun 				*reply_ptr = req->data[1];
462*4882a593Smuzhiyun 				reply_len = 1;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 				via[ACR] &= ~SR_OUT;
465*4882a593Smuzhiyun 				x = via[SR];
466*4882a593Smuzhiyun 			} else if ((req->data[1] & OP_MASK) == TALK) {
467*4882a593Smuzhiyun 				macii_state = reading;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 				reading_reply = false;
470*4882a593Smuzhiyun 				reply_ptr = reply_buf;
471*4882a593Smuzhiyun 				*reply_ptr = req->data[1];
472*4882a593Smuzhiyun 				reply_len = 1;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 				via[ACR] &= ~SR_OUT;
475*4882a593Smuzhiyun 				x = via[SR];
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 				req->complete = 1;
478*4882a593Smuzhiyun 				current_req = req->next;
479*4882a593Smuzhiyun 				if (req->done)
480*4882a593Smuzhiyun 					(*req->done)(req);
481*4882a593Smuzhiyun 			} else {
482*4882a593Smuzhiyun 				macii_state = idle;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 				req->complete = 1;
485*4882a593Smuzhiyun 				current_req = req->next;
486*4882a593Smuzhiyun 				if (req->done)
487*4882a593Smuzhiyun 					(*req->done)(req);
488*4882a593Smuzhiyun 				break;
489*4882a593Smuzhiyun 			}
490*4882a593Smuzhiyun 		} else {
491*4882a593Smuzhiyun 			via[SR] = req->data[data_index++];
492*4882a593Smuzhiyun 		}
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 		if ((via[B] & ST_MASK) == ST_CMD) {
495*4882a593Smuzhiyun 			/* just sent the command byte, set to EVEN */
496*4882a593Smuzhiyun 			via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
497*4882a593Smuzhiyun 		} else {
498*4882a593Smuzhiyun 			/* invert state bits, toggle ODD/EVEN */
499*4882a593Smuzhiyun 			via[B] ^= ST_MASK;
500*4882a593Smuzhiyun 		}
501*4882a593Smuzhiyun 		break;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	case reading:
504*4882a593Smuzhiyun 		x = via[SR];
505*4882a593Smuzhiyun 		WARN_ON((status & ST_MASK) == ST_CMD ||
506*4882a593Smuzhiyun 			(status & ST_MASK) == ST_IDLE);
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 		if (!(status & CTLR_IRQ)) {
509*4882a593Smuzhiyun 			if (status == ST_EVEN && reply_len == 1) {
510*4882a593Smuzhiyun 				bus_timeout = true;
511*4882a593Smuzhiyun 			} else if (status == ST_ODD && reply_len == 2) {
512*4882a593Smuzhiyun 				srq_asserted = true;
513*4882a593Smuzhiyun 			} else {
514*4882a593Smuzhiyun 				macii_state = idle;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 				if (bus_timeout)
517*4882a593Smuzhiyun 					reply_len = 0;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 				if (reading_reply) {
520*4882a593Smuzhiyun 					struct adb_request *req = current_req;
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 					req->reply_len = reply_len;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 					req->complete = 1;
525*4882a593Smuzhiyun 					current_req = req->next;
526*4882a593Smuzhiyun 					if (req->done)
527*4882a593Smuzhiyun 						(*req->done)(req);
528*4882a593Smuzhiyun 				} else if (reply_len && autopoll_devs &&
529*4882a593Smuzhiyun 					   reply_buf[0] == last_poll_cmd) {
530*4882a593Smuzhiyun 					adb_input(reply_buf, reply_len, 1);
531*4882a593Smuzhiyun 				}
532*4882a593Smuzhiyun 				break;
533*4882a593Smuzhiyun 			}
534*4882a593Smuzhiyun 		}
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 		if (reply_len < ARRAY_SIZE(reply_buf)) {
537*4882a593Smuzhiyun 			reply_ptr++;
538*4882a593Smuzhiyun 			*reply_ptr = x;
539*4882a593Smuzhiyun 			reply_len++;
540*4882a593Smuzhiyun 		}
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 		/* invert state bits, toggle ODD/EVEN */
543*4882a593Smuzhiyun 		via[B] ^= ST_MASK;
544*4882a593Smuzhiyun 		break;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	default:
547*4882a593Smuzhiyun 		break;
548*4882a593Smuzhiyun 	}
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	if (macii_state == idle) {
551*4882a593Smuzhiyun 		if (!current_req)
552*4882a593Smuzhiyun 			macii_queue_poll();
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 		if (current_req)
555*4882a593Smuzhiyun 			macii_start();
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 		if (macii_state == idle) {
558*4882a593Smuzhiyun 			via[ACR] &= ~SR_OUT;
559*4882a593Smuzhiyun 			x = via[SR];
560*4882a593Smuzhiyun 			via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
561*4882a593Smuzhiyun 		}
562*4882a593Smuzhiyun 	}
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	local_irq_restore(flags);
565*4882a593Smuzhiyun 	return IRQ_HANDLED;
566*4882a593Smuzhiyun }
567