File Index
Files and directories
Sign in
FILE

macio-adb.c

File preview with syntax highlighting.

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