VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
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) }