1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Device driver for the via ADB on (many) Mac II-class machines
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Based on the original ADB keyboard handler Copyright (c) 1997 Alan Cox
61da177e4SLinus Torvalds * Also derived from code Copyright (C) 1996 Paul Mackerras.
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * With various updates provided over the years by Michael Schmitz,
91da177e4SLinus Torvalds * Guideo Koerber and others.
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds * Rewrite for Unified ADB by Joshua M. Thompson (funaho@jurai.org)
121da177e4SLinus Torvalds *
131da177e4SLinus Torvalds * 1999-08-02 (jmt) - Initial rewrite for Unified ADB.
141da177e4SLinus Torvalds * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org>
151da177e4SLinus Torvalds * - Big overhaul, should actually work now.
16d0c2c269SFinn Thain * 2006-12-31 Finn Thain - Another overhaul.
17d95fd5fcSFinn Thain *
18d95fd5fcSFinn Thain * Suggested reading:
19d95fd5fcSFinn Thain * Inside Macintosh, ch. 5 ADB Manager
20d95fd5fcSFinn Thain * Guide to the Macinstosh Family Hardware, ch. 8 Apple Desktop Bus
21d95fd5fcSFinn Thain * Rockwell R6522 VIA datasheet
22d95fd5fcSFinn Thain *
23d95fd5fcSFinn Thain * Apple's "ADB Analyzer" bus sniffer is invaluable:
24d95fd5fcSFinn Thain * ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/
251da177e4SLinus Torvalds */
261da177e4SLinus Torvalds #include <linux/types.h>
271da177e4SLinus Torvalds #include <linux/errno.h>
281da177e4SLinus Torvalds #include <linux/kernel.h>
291da177e4SLinus Torvalds #include <linux/delay.h>
301da177e4SLinus Torvalds #include <linux/adb.h>
311da177e4SLinus Torvalds #include <linux/interrupt.h>
321da177e4SLinus Torvalds #include <linux/init.h>
331da177e4SLinus Torvalds #include <asm/macintosh.h>
341da177e4SLinus Torvalds #include <asm/macints.h>
351da177e4SLinus Torvalds #include <asm/mac_via.h>
361da177e4SLinus Torvalds
371da177e4SLinus Torvalds static volatile unsigned char *via;
381da177e4SLinus Torvalds
391da177e4SLinus Torvalds /* VIA registers - spaced 0x200 bytes apart */
401da177e4SLinus Torvalds #define RS 0x200 /* skip between registers */
411da177e4SLinus Torvalds #define B 0 /* B-side data */
421da177e4SLinus Torvalds #define A RS /* A-side data */
431da177e4SLinus Torvalds #define DIRB (2*RS) /* B-side direction (1=output) */
441da177e4SLinus Torvalds #define DIRA (3*RS) /* A-side direction (1=output) */
451da177e4SLinus Torvalds #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
461da177e4SLinus Torvalds #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
471da177e4SLinus Torvalds #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
481da177e4SLinus Torvalds #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
491da177e4SLinus Torvalds #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */
501da177e4SLinus Torvalds #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */
511da177e4SLinus Torvalds #define SR (10*RS) /* Shift register */
521da177e4SLinus Torvalds #define ACR (11*RS) /* Auxiliary control register */
531da177e4SLinus Torvalds #define PCR (12*RS) /* Peripheral control register */
541da177e4SLinus Torvalds #define IFR (13*RS) /* Interrupt flag register */
551da177e4SLinus Torvalds #define IER (14*RS) /* Interrupt enable register */
561da177e4SLinus Torvalds #define ANH (15*RS) /* A-side data, no handshake */
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds /* Bits in B data register: all active low */
59d95fd5fcSFinn Thain #define CTLR_IRQ 0x08 /* Controller rcv status (input) */
601da177e4SLinus Torvalds #define ST_MASK 0x30 /* mask for selecting ADB state bits */
611da177e4SLinus Torvalds
621da177e4SLinus Torvalds /* Bits in ACR */
631da177e4SLinus Torvalds #define SR_CTRL 0x1c /* Shift register control bits */
641da177e4SLinus Torvalds #define SR_EXT 0x0c /* Shift on external clock */
651da177e4SLinus Torvalds #define SR_OUT 0x10 /* Shift out if 1 */
661da177e4SLinus Torvalds
671da177e4SLinus Torvalds /* Bits in IFR and IER */
681da177e4SLinus Torvalds #define IER_SET 0x80 /* set bits in IER */
691da177e4SLinus Torvalds #define IER_CLR 0 /* clear bits in IER */
701da177e4SLinus Torvalds #define SR_INT 0x04 /* Shift register full/empty */
711da177e4SLinus Torvalds
721da177e4SLinus Torvalds /* ADB transaction states according to GMHW */
731da177e4SLinus Torvalds #define ST_CMD 0x00 /* ADB state: command byte */
741da177e4SLinus Torvalds #define ST_EVEN 0x10 /* ADB state: even data byte */
751da177e4SLinus Torvalds #define ST_ODD 0x20 /* ADB state: odd data byte */
761da177e4SLinus Torvalds #define ST_IDLE 0x30 /* ADB state: idle, nothing to send */
771da177e4SLinus Torvalds
78f93bfeb5SFinn Thain /* ADB command byte structure */
79f93bfeb5SFinn Thain #define ADDR_MASK 0xF0
80f93bfeb5SFinn Thain #define CMD_MASK 0x0F
81b4d76c28SFinn Thain #define OP_MASK 0x0C
82b4d76c28SFinn Thain #define TALK 0x0C
83f93bfeb5SFinn Thain
841da177e4SLinus Torvalds static int macii_init_via(void);
851da177e4SLinus Torvalds static void macii_start(void);
867d12e780SDavid Howells static irqreturn_t macii_interrupt(int irq, void *arg);
871da177e4SLinus Torvalds static void macii_queue_poll(void);
881da177e4SLinus Torvalds
891da177e4SLinus Torvalds static int macii_probe(void);
901da177e4SLinus Torvalds static int macii_init(void);
911da177e4SLinus Torvalds static int macii_send_request(struct adb_request *req, int sync);
921da177e4SLinus Torvalds static int macii_write(struct adb_request *req);
931da177e4SLinus Torvalds static int macii_autopoll(int devs);
941da177e4SLinus Torvalds static void macii_poll(void);
951da177e4SLinus Torvalds static int macii_reset_bus(void);
961da177e4SLinus Torvalds
971da177e4SLinus Torvalds struct adb_driver via_macii_driver = {
983a52f6f9SFinn Thain .name = "Mac II",
993a52f6f9SFinn Thain .probe = macii_probe,
1003a52f6f9SFinn Thain .init = macii_init,
1013a52f6f9SFinn Thain .send_request = macii_send_request,
1023a52f6f9SFinn Thain .autopoll = macii_autopoll,
1033a52f6f9SFinn Thain .poll = macii_poll,
1043a52f6f9SFinn Thain .reset_bus = macii_reset_bus,
1051da177e4SLinus Torvalds };
1061da177e4SLinus Torvalds
1071da177e4SLinus Torvalds static enum macii_state {
1081da177e4SLinus Torvalds idle,
1091da177e4SLinus Torvalds sending,
1101da177e4SLinus Torvalds reading,
1111da177e4SLinus Torvalds } macii_state;
1121da177e4SLinus Torvalds
113d95fd5fcSFinn Thain static struct adb_request *current_req; /* first request struct in the queue */
114d95fd5fcSFinn Thain static struct adb_request *last_req; /* last request struct in the queue */
115d95fd5fcSFinn Thain static unsigned char reply_buf[16]; /* storage for autopolled replies */
116eb4da4ceSFinn Thain static unsigned char *reply_ptr; /* next byte in reply_buf or req->reply */
117f87a1625SFinn Thain static bool reading_reply; /* store reply in reply_buf else req->reply */
118d95fd5fcSFinn Thain static int data_index; /* index of the next byte to send from req->data */
119d95fd5fcSFinn Thain static int reply_len; /* number of bytes received in reply_buf or req->reply */
120d95fd5fcSFinn Thain static int status; /* VIA's ADB status bits captured upon interrupt */
121b4d76c28SFinn Thain static bool bus_timeout; /* no data was sent by the device */
122b4d76c28SFinn Thain static bool srq_asserted; /* have to poll for the device that asserted it */
123f93bfeb5SFinn Thain static u8 last_cmd; /* the most recent command byte transmitted */
124b4d76c28SFinn Thain static u8 last_talk_cmd; /* the most recent Talk command byte transmitted */
125f93bfeb5SFinn Thain static u8 last_poll_cmd; /* the most recent Talk R0 command byte transmitted */
1265c0c15a1SFinn Thain static unsigned int autopoll_devs; /* bits set are device addresses to poll */
1271da177e4SLinus Torvalds
1281da177e4SLinus Torvalds /* Check for MacII style ADB */
macii_probe(void)1291da177e4SLinus Torvalds static int macii_probe(void)
1301da177e4SLinus Torvalds {
13147fd2060SFinn Thain if (macintosh_config->adb_type != MAC_ADB_II)
13247fd2060SFinn Thain return -ENODEV;
1331da177e4SLinus Torvalds
1341da177e4SLinus Torvalds via = via1;
1351da177e4SLinus Torvalds
136351e5ad3SFinn Thain pr_info("adb: Mac II ADB Driver v1.0 for Unified ADB\n");
1371da177e4SLinus Torvalds return 0;
1381da177e4SLinus Torvalds }
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvalds /* Initialize the driver */
macii_init(void)1413327e58aSFinn Thain static int macii_init(void)
1421da177e4SLinus Torvalds {
1431da177e4SLinus Torvalds int err;
1441da177e4SLinus Torvalds
1451da177e4SLinus Torvalds err = macii_init_via();
14647fd2060SFinn Thain if (err)
147*d43a8c7eSFinn Thain return err;
1481da177e4SLinus Torvalds
1495a239453SGeert Uytterhoeven err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
1501da177e4SLinus Torvalds macii_interrupt);
15147fd2060SFinn Thain if (err)
152*d43a8c7eSFinn Thain return err;
1531da177e4SLinus Torvalds
1541da177e4SLinus Torvalds macii_state = idle;
155*d43a8c7eSFinn Thain return 0;
1561da177e4SLinus Torvalds }
1571da177e4SLinus Torvalds
1581da177e4SLinus Torvalds /* initialize the hardware */
macii_init_via(void)1591da177e4SLinus Torvalds static int macii_init_via(void)
1601da177e4SLinus Torvalds {
1611da177e4SLinus Torvalds unsigned char x;
1621da177e4SLinus Torvalds
163d95fd5fcSFinn Thain /* We want CTLR_IRQ as input and ST_EVEN | ST_ODD as output lines. */
164d95fd5fcSFinn Thain via[DIRB] = (via[DIRB] | ST_EVEN | ST_ODD) & ~CTLR_IRQ;
1651da177e4SLinus Torvalds
1661da177e4SLinus Torvalds /* Set up state: idle */
1671da177e4SLinus Torvalds via[B] |= ST_IDLE;
1681da177e4SLinus Torvalds
1691da177e4SLinus Torvalds /* Shift register on input */
1701da177e4SLinus Torvalds via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT;
1711da177e4SLinus Torvalds
1721da177e4SLinus Torvalds /* Wipe any pending data and int */
1731da177e4SLinus Torvalds x = via[SR];
1741da177e4SLinus Torvalds
1751da177e4SLinus Torvalds return 0;
1761da177e4SLinus Torvalds }
1771da177e4SLinus Torvalds
178d95fd5fcSFinn Thain /* Send an ADB poll (Talk Register 0 command prepended to the request queue) */
macii_queue_poll(void)1791da177e4SLinus Torvalds static void macii_queue_poll(void)
1801da177e4SLinus Torvalds {
1811da177e4SLinus Torvalds static struct adb_request req;
182f93bfeb5SFinn Thain unsigned char poll_command;
183f93bfeb5SFinn Thain unsigned int poll_addr;
1841da177e4SLinus Torvalds
185f93bfeb5SFinn Thain /* This only polls devices in the autopoll list, which assumes that
186f93bfeb5SFinn Thain * unprobed devices never assert SRQ. That could happen if a device was
187f93bfeb5SFinn Thain * plugged in after the adb bus scan. Unplugging it again will resolve
188f93bfeb5SFinn Thain * the problem. This behaviour is similar to MacOS.
189f93bfeb5SFinn Thain */
19047fd2060SFinn Thain if (!autopoll_devs)
19147fd2060SFinn Thain return;
1921da177e4SLinus Torvalds
193f93bfeb5SFinn Thain /* The device most recently polled may not be the best device to poll
194f93bfeb5SFinn Thain * right now. Some other device(s) may have signalled SRQ (the active
195f93bfeb5SFinn Thain * device won't do that). Or the autopoll list may have been changed.
196f93bfeb5SFinn Thain * Try polling the next higher address.
197f93bfeb5SFinn Thain */
198f93bfeb5SFinn Thain poll_addr = (last_poll_cmd & ADDR_MASK) >> 4;
199f93bfeb5SFinn Thain if ((srq_asserted && last_cmd == last_poll_cmd) ||
200f93bfeb5SFinn Thain !(autopoll_devs & (1 << poll_addr))) {
201f93bfeb5SFinn Thain unsigned int higher_devs;
2021da177e4SLinus Torvalds
203f93bfeb5SFinn Thain higher_devs = autopoll_devs & -(1 << (poll_addr + 1));
204f93bfeb5SFinn Thain poll_addr = ffs(higher_devs ? higher_devs : autopoll_devs) - 1;
205f93bfeb5SFinn Thain }
206f93bfeb5SFinn Thain
207f93bfeb5SFinn Thain /* Send a Talk Register 0 command */
208f93bfeb5SFinn Thain poll_command = ADB_READREG(poll_addr, 0);
209f93bfeb5SFinn Thain
210f93bfeb5SFinn Thain /* No need to repeat this Talk command. The transceiver will do that
211f93bfeb5SFinn Thain * as long as it is idle.
212f93bfeb5SFinn Thain */
213f93bfeb5SFinn Thain if (poll_command == last_cmd)
214f93bfeb5SFinn Thain return;
215f93bfeb5SFinn Thain
216f93bfeb5SFinn Thain adb_request(&req, NULL, ADBREQ_NOSEND, 1, poll_command);
2171da177e4SLinus Torvalds
218d95fd5fcSFinn Thain req.sent = 0;
219d95fd5fcSFinn Thain req.complete = 0;
220d95fd5fcSFinn Thain req.reply_len = 0;
2211da177e4SLinus Torvalds req.next = current_req;
2221da177e4SLinus Torvalds
223f93bfeb5SFinn Thain if (WARN_ON(current_req)) {
224d95fd5fcSFinn Thain current_req = &req;
2251da177e4SLinus Torvalds } else {
226d95fd5fcSFinn Thain current_req = &req;
227d95fd5fcSFinn Thain last_req = &req;
2281da177e4SLinus Torvalds }
2291da177e4SLinus Torvalds }
2301da177e4SLinus Torvalds
2311da177e4SLinus Torvalds /* Send an ADB request; if sync, poll out the reply 'till it's done */
macii_send_request(struct adb_request * req,int sync)2321da177e4SLinus Torvalds static int macii_send_request(struct adb_request *req, int sync)
2331da177e4SLinus Torvalds {
234d95fd5fcSFinn Thain int err;
2351da177e4SLinus Torvalds
236d95fd5fcSFinn Thain err = macii_write(req);
2375ce6185cSFinn Thain if (err)
2385ce6185cSFinn Thain return err;
239d95fd5fcSFinn Thain
2405ce6185cSFinn Thain if (sync)
2415f93d708SFinn Thain while (!req->complete)
242d95fd5fcSFinn Thain macii_poll();
243d95fd5fcSFinn Thain
2445ce6185cSFinn Thain return 0;
245d95fd5fcSFinn Thain }
246d95fd5fcSFinn Thain
247d95fd5fcSFinn Thain /* Send an ADB request (append to request queue) */
macii_write(struct adb_request * req)248d95fd5fcSFinn Thain static int macii_write(struct adb_request *req)
249d95fd5fcSFinn Thain {
2505ce6185cSFinn Thain unsigned long flags;
2515ce6185cSFinn Thain
2521da177e4SLinus Torvalds if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) {
2531da177e4SLinus Torvalds req->complete = 1;
2541da177e4SLinus Torvalds return -EINVAL;
2551da177e4SLinus Torvalds }
2561da177e4SLinus Torvalds
257a5d361fcSAl Viro req->next = NULL;
2581da177e4SLinus Torvalds req->sent = 0;
2591da177e4SLinus Torvalds req->complete = 0;
2601da177e4SLinus Torvalds req->reply_len = 0;
2611da177e4SLinus Torvalds
2625ce6185cSFinn Thain local_irq_save(flags);
2635ce6185cSFinn Thain
2641da177e4SLinus Torvalds if (current_req != NULL) {
2651da177e4SLinus Torvalds last_req->next = req;
2661da177e4SLinus Torvalds last_req = req;
2671da177e4SLinus Torvalds } else {
2681da177e4SLinus Torvalds current_req = req;
2691da177e4SLinus Torvalds last_req = req;
27047fd2060SFinn Thain if (macii_state == idle)
27147fd2060SFinn Thain macii_start();
2721da177e4SLinus Torvalds }
2735ce6185cSFinn Thain
2745ce6185cSFinn Thain local_irq_restore(flags);
2755ce6185cSFinn Thain
2761da177e4SLinus Torvalds return 0;
2771da177e4SLinus Torvalds }
2781da177e4SLinus Torvalds
2791da177e4SLinus Torvalds /* Start auto-polling */
macii_autopoll(int devs)2801da177e4SLinus Torvalds static int macii_autopoll(int devs)
2811da177e4SLinus Torvalds {
282d95fd5fcSFinn Thain unsigned long flags;
283d95fd5fcSFinn Thain
28459ea38f6SFinn Thain local_irq_save(flags);
28559ea38f6SFinn Thain
286d95fd5fcSFinn Thain /* bit 1 == device 1, and so on. */
2875c0c15a1SFinn Thain autopoll_devs = (unsigned int)devs & 0xFFFE;
288d95fd5fcSFinn Thain
289f93bfeb5SFinn Thain if (!current_req) {
290f93bfeb5SFinn Thain macii_queue_poll();
291f93bfeb5SFinn Thain if (current_req && macii_state == idle)
292f93bfeb5SFinn Thain macii_start();
293d95fd5fcSFinn Thain }
294d95fd5fcSFinn Thain
295d95fd5fcSFinn Thain local_irq_restore(flags);
296d95fd5fcSFinn Thain
2971da177e4SLinus Torvalds return 0;
2981da177e4SLinus Torvalds }
2991da177e4SLinus Torvalds
3001da177e4SLinus Torvalds /* Prod the chip without interrupts */
macii_poll(void)3011da177e4SLinus Torvalds static void macii_poll(void)
3021da177e4SLinus Torvalds {
303d95fd5fcSFinn Thain macii_interrupt(0, NULL);
3041da177e4SLinus Torvalds }
3051da177e4SLinus Torvalds
3061da177e4SLinus Torvalds /* Reset the bus */
macii_reset_bus(void)3071da177e4SLinus Torvalds static int macii_reset_bus(void)
3081da177e4SLinus Torvalds {
309046ace82SFinn Thain struct adb_request req;
3101da177e4SLinus Torvalds
3111da177e4SLinus Torvalds /* Command = 0, Address = ignored */
312b52dce87SFinn Thain adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET);
313b52dce87SFinn Thain macii_send_request(&req, 1);
3141da177e4SLinus Torvalds
315d95fd5fcSFinn Thain /* Don't want any more requests during the Global Reset low time. */
316d95fd5fcSFinn Thain udelay(3000);
317d95fd5fcSFinn Thain
3181da177e4SLinus Torvalds return 0;
3191da177e4SLinus Torvalds }
3201da177e4SLinus Torvalds
3211da177e4SLinus Torvalds /* Start sending ADB packet */
macii_start(void)3221da177e4SLinus Torvalds static void macii_start(void)
3231da177e4SLinus Torvalds {
3241da177e4SLinus Torvalds struct adb_request *req;
3251da177e4SLinus Torvalds
3261da177e4SLinus Torvalds req = current_req;
3271da177e4SLinus Torvalds
328d95fd5fcSFinn Thain /* Now send it. Be careful though, that first byte of the request
329d95fd5fcSFinn Thain * is actually ADB_PACKET; the real data begins at index 1!
330d95fd5fcSFinn Thain * And req->nbytes is the number of bytes of real data plus one.
3311da177e4SLinus Torvalds */
3321da177e4SLinus Torvalds
3331da177e4SLinus Torvalds /* Output mode */
3341da177e4SLinus Torvalds via[ACR] |= SR_OUT;
3351da177e4SLinus Torvalds /* Load data */
3361da177e4SLinus Torvalds via[SR] = req->data[1];
3371da177e4SLinus Torvalds /* set ADB state to 'command' */
3381da177e4SLinus Torvalds via[B] = (via[B] & ~ST_MASK) | ST_CMD;
3391da177e4SLinus Torvalds
3401da177e4SLinus Torvalds macii_state = sending;
3411da177e4SLinus Torvalds data_index = 2;
342b4d76c28SFinn Thain
343b4d76c28SFinn Thain bus_timeout = false;
344b4d76c28SFinn Thain srq_asserted = false;
3451da177e4SLinus Torvalds }
3461da177e4SLinus Torvalds
3471da177e4SLinus Torvalds /*
348d95fd5fcSFinn Thain * The notorious ADB interrupt handler - does all of the protocol handling.
349d95fd5fcSFinn Thain * Relies on the ADB controller sending and receiving data, thereby
350d95fd5fcSFinn Thain * generating shift register interrupts (SR_INT) for us. This means there has
351d95fd5fcSFinn Thain * to be activity on the ADB bus. The chip will poll to achieve this.
3521da177e4SLinus Torvalds *
353b4d76c28SFinn Thain * The VIA Port B output signalling works as follows. After the ADB transceiver
354b4d76c28SFinn Thain * sees a transition on the PB4 and PB5 lines it will crank over the VIA shift
355b4d76c28SFinn Thain * register which eventually raises the SR_INT interrupt. The PB4/PB5 outputs
356b4d76c28SFinn Thain * are toggled with each byte as the ADB transaction progresses.
357b4d76c28SFinn Thain *
358b4d76c28SFinn Thain * Request with no reply expected (and empty transceiver buffer):
359b4d76c28SFinn Thain * CMD -> IDLE
360b4d76c28SFinn Thain * Request with expected reply packet (or with buffered autopoll packet):
361b4d76c28SFinn Thain * CMD -> EVEN -> ODD -> EVEN -> ... -> IDLE
362b4d76c28SFinn Thain * Unsolicited packet:
363b4d76c28SFinn Thain * IDLE -> EVEN -> ODD -> EVEN -> ... -> IDLE
3641da177e4SLinus Torvalds */
macii_interrupt(int irq,void * arg)3657d12e780SDavid Howells static irqreturn_t macii_interrupt(int irq, void *arg)
3661da177e4SLinus Torvalds {
367d95fd5fcSFinn Thain int x;
3681da177e4SLinus Torvalds struct adb_request *req;
3695ce6185cSFinn Thain unsigned long flags;
3705ce6185cSFinn Thain
3715ce6185cSFinn Thain local_irq_save(flags);
3721da177e4SLinus Torvalds
373d95fd5fcSFinn Thain if (!arg) {
374d95fd5fcSFinn Thain /* Clear the SR IRQ flag when polling. */
375d95fd5fcSFinn Thain if (via[IFR] & SR_INT)
376d95fd5fcSFinn Thain via[IFR] = SR_INT;
3775ce6185cSFinn Thain else {
3785ce6185cSFinn Thain local_irq_restore(flags);
3791da177e4SLinus Torvalds return IRQ_NONE;
3801da177e4SLinus Torvalds }
3815ce6185cSFinn Thain }
3821da177e4SLinus Torvalds
383d95fd5fcSFinn Thain status = via[B] & (ST_MASK | CTLR_IRQ);
3841da177e4SLinus Torvalds
3851da177e4SLinus Torvalds switch (macii_state) {
3861da177e4SLinus Torvalds case idle:
387b4d76c28SFinn Thain WARN_ON((status & ST_MASK) != ST_IDLE);
388b4d76c28SFinn Thain
389d95fd5fcSFinn Thain reply_ptr = reply_buf;
390f87a1625SFinn Thain reading_reply = false;
391b4d76c28SFinn Thain
392b4d76c28SFinn Thain bus_timeout = false;
393b4d76c28SFinn Thain srq_asserted = false;
394d95fd5fcSFinn Thain
3951da177e4SLinus Torvalds x = via[SR];
396d95fd5fcSFinn Thain
397b4d76c28SFinn Thain if (!(status & CTLR_IRQ)) {
398b4d76c28SFinn Thain /* /CTLR_IRQ asserted in idle state means we must
399b4d76c28SFinn Thain * read an autopoll reply from the transceiver buffer.
400d95fd5fcSFinn Thain */
401d95fd5fcSFinn Thain macii_state = reading;
402d95fd5fcSFinn Thain *reply_ptr = x;
403d95fd5fcSFinn Thain reply_len = 1;
404b4d76c28SFinn Thain } else {
405b4d76c28SFinn Thain /* bus timeout */
406b4d76c28SFinn Thain reply_len = 0;
407b16b6768SFinn Thain break;
408d95fd5fcSFinn Thain }
409d95fd5fcSFinn Thain
4101da177e4SLinus Torvalds /* set ADB state = even for first data byte */
4111da177e4SLinus Torvalds via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
4121da177e4SLinus Torvalds break;
4131da177e4SLinus Torvalds
4141da177e4SLinus Torvalds case sending:
4151da177e4SLinus Torvalds req = current_req;
416b4d76c28SFinn Thain
417b4d76c28SFinn Thain if (status == (ST_CMD | CTLR_IRQ)) {
418b4d76c28SFinn Thain /* /CTLR_IRQ de-asserted after the command byte means
419b4d76c28SFinn Thain * the host can continue with the transaction.
420b4d76c28SFinn Thain */
421b4d76c28SFinn Thain
422b4d76c28SFinn Thain /* Store command byte */
423b4d76c28SFinn Thain last_cmd = req->data[1];
424b4d76c28SFinn Thain if ((last_cmd & OP_MASK) == TALK) {
425b4d76c28SFinn Thain last_talk_cmd = last_cmd;
426b4d76c28SFinn Thain if ((last_cmd & CMD_MASK) == ADB_READREG(0, 0))
427b4d76c28SFinn Thain last_poll_cmd = last_cmd;
428b4d76c28SFinn Thain }
429b4d76c28SFinn Thain }
430b4d76c28SFinn Thain
431b4d76c28SFinn Thain if (status == ST_CMD) {
432b4d76c28SFinn Thain /* /CTLR_IRQ asserted after the command byte means we
433b4d76c28SFinn Thain * must read an autopoll reply. The first byte was
434b4d76c28SFinn Thain * lost because the shift register was an output.
435b4d76c28SFinn Thain */
436b4d76c28SFinn Thain macii_state = reading;
437b4d76c28SFinn Thain
438f87a1625SFinn Thain reading_reply = false;
439b4d76c28SFinn Thain reply_ptr = reply_buf;
440b4d76c28SFinn Thain *reply_ptr = last_talk_cmd;
441b4d76c28SFinn Thain reply_len = 1;
442b4d76c28SFinn Thain
443b4d76c28SFinn Thain /* reset to shift in */
444b4d76c28SFinn Thain via[ACR] &= ~SR_OUT;
445b4d76c28SFinn Thain x = via[SR];
446b4d76c28SFinn Thain } else if (data_index >= req->nbytes) {
447d95fd5fcSFinn Thain req->sent = 1;
448d95fd5fcSFinn Thain
449d95fd5fcSFinn Thain if (req->reply_expected) {
450b4d76c28SFinn Thain macii_state = reading;
451b4d76c28SFinn Thain
452f87a1625SFinn Thain reading_reply = true;
453b4d76c28SFinn Thain reply_ptr = req->reply;
454b4d76c28SFinn Thain *reply_ptr = req->data[1];
455b4d76c28SFinn Thain reply_len = 1;
456b4d76c28SFinn Thain
457b4d76c28SFinn Thain via[ACR] &= ~SR_OUT;
458b4d76c28SFinn Thain x = via[SR];
459624cf5b5SFinn Thain } else if ((req->data[1] & OP_MASK) == TALK) {
460624cf5b5SFinn Thain macii_state = reading;
461624cf5b5SFinn Thain
462f87a1625SFinn Thain reading_reply = false;
463624cf5b5SFinn Thain reply_ptr = reply_buf;
464624cf5b5SFinn Thain *reply_ptr = req->data[1];
465624cf5b5SFinn Thain reply_len = 1;
466624cf5b5SFinn Thain
467624cf5b5SFinn Thain via[ACR] &= ~SR_OUT;
468624cf5b5SFinn Thain x = via[SR];
469624cf5b5SFinn Thain
470624cf5b5SFinn Thain req->complete = 1;
471624cf5b5SFinn Thain current_req = req->next;
472624cf5b5SFinn Thain if (req->done)
473624cf5b5SFinn Thain (*req->done)(req);
474d95fd5fcSFinn Thain } else {
475b4d76c28SFinn Thain macii_state = idle;
476b4d76c28SFinn Thain
477d95fd5fcSFinn Thain req->complete = 1;
478d95fd5fcSFinn Thain current_req = req->next;
47947fd2060SFinn Thain if (req->done)
48047fd2060SFinn Thain (*req->done)(req);
481b4d76c28SFinn Thain break;
482b4d76c28SFinn Thain }
4831da177e4SLinus Torvalds } else {
4841da177e4SLinus Torvalds via[SR] = req->data[data_index++];
485b4d76c28SFinn Thain }
4861da177e4SLinus Torvalds
4871da177e4SLinus Torvalds if ((via[B] & ST_MASK) == ST_CMD) {
4881da177e4SLinus Torvalds /* just sent the command byte, set to EVEN */
4891da177e4SLinus Torvalds via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
4901da177e4SLinus Torvalds } else {
4911da177e4SLinus Torvalds /* invert state bits, toggle ODD/EVEN */
4921da177e4SLinus Torvalds via[B] ^= ST_MASK;
4931da177e4SLinus Torvalds }
4941da177e4SLinus Torvalds break;
4951da177e4SLinus Torvalds
4961da177e4SLinus Torvalds case reading:
497d95fd5fcSFinn Thain x = via[SR];
4985f93d708SFinn Thain WARN_ON((status & ST_MASK) == ST_CMD ||
499d95fd5fcSFinn Thain (status & ST_MASK) == ST_IDLE);
5001da177e4SLinus Torvalds
501d95fd5fcSFinn Thain if (!(status & CTLR_IRQ)) {
502b4d76c28SFinn Thain if (status == ST_EVEN && reply_len == 1) {
503b4d76c28SFinn Thain bus_timeout = true;
504b4d76c28SFinn Thain } else if (status == ST_ODD && reply_len == 2) {
505b4d76c28SFinn Thain srq_asserted = true;
506b4d76c28SFinn Thain } else {
507b16b6768SFinn Thain macii_state = idle;
508b16b6768SFinn Thain
509b16b6768SFinn Thain if (bus_timeout)
510b16b6768SFinn Thain reply_len = 0;
511b16b6768SFinn Thain
512b16b6768SFinn Thain if (reading_reply) {
513b16b6768SFinn Thain struct adb_request *req = current_req;
514b16b6768SFinn Thain
515b16b6768SFinn Thain req->reply_len = reply_len;
516b16b6768SFinn Thain
517b16b6768SFinn Thain req->complete = 1;
518b16b6768SFinn Thain current_req = req->next;
519b16b6768SFinn Thain if (req->done)
520b16b6768SFinn Thain (*req->done)(req);
521624cf5b5SFinn Thain } else if (reply_len && autopoll_devs &&
522624cf5b5SFinn Thain reply_buf[0] == last_poll_cmd) {
523624cf5b5SFinn Thain adb_input(reply_buf, reply_len, 1);
524b16b6768SFinn Thain }
525b16b6768SFinn Thain break;
526d95fd5fcSFinn Thain }
527d95fd5fcSFinn Thain }
5281da177e4SLinus Torvalds
529b16b6768SFinn Thain if (reply_len < ARRAY_SIZE(reply_buf)) {
5301da177e4SLinus Torvalds reply_ptr++;
531d95fd5fcSFinn Thain *reply_ptr = x;
5321da177e4SLinus Torvalds reply_len++;
5331da177e4SLinus Torvalds }
5341da177e4SLinus Torvalds
5351da177e4SLinus Torvalds /* invert state bits, toggle ODD/EVEN */
5361da177e4SLinus Torvalds via[B] ^= ST_MASK;
5371da177e4SLinus Torvalds break;
5381da177e4SLinus Torvalds
539b16b6768SFinn Thain default:
540b16b6768SFinn Thain break;
541b16b6768SFinn Thain }
542d95fd5fcSFinn Thain
543b16b6768SFinn Thain if (macii_state == idle) {
544f93bfeb5SFinn Thain if (!current_req)
5451da177e4SLinus Torvalds macii_queue_poll();
5461da177e4SLinus Torvalds
5471da177e4SLinus Torvalds if (current_req)
5481da177e4SLinus Torvalds macii_start();
549d95fd5fcSFinn Thain
550b16b6768SFinn Thain if (macii_state == idle) {
551b16b6768SFinn Thain via[ACR] &= ~SR_OUT;
552b16b6768SFinn Thain x = via[SR];
553d95fd5fcSFinn Thain via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
554b16b6768SFinn Thain }
5551da177e4SLinus Torvalds }
556d95fd5fcSFinn Thain
5575ce6185cSFinn Thain local_irq_restore(flags);
5581da177e4SLinus Torvalds return IRQ_HANDLED;
5591da177e4SLinus Torvalds }
560