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