xref: /openbmc/linux/drivers/macintosh/adb-iop.c (revision 52cdded0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * I/O Processor (IOP) ADB Driver
4  * Written and (C) 1999 by Joshua M. Thompson (funaho@jurai.org)
5  * Based on via-cuda.c by Paul Mackerras.
6  *
7  * 1999-07-01 (jmt) - First implementation for new driver architecture.
8  *
9  * 1999-07-31 (jmt) - First working version.
10  */
11 
12 #include <linux/types.h>
13 #include <linux/kernel.h>
14 #include <linux/mm.h>
15 #include <linux/delay.h>
16 #include <linux/init.h>
17 
18 #include <asm/macintosh.h>
19 #include <asm/macints.h>
20 #include <asm/mac_iop.h>
21 #include <asm/adb_iop.h>
22 
23 #include <linux/adb.h>
24 
25 static struct adb_request *current_req;
26 static struct adb_request *last_req;
27 static unsigned int autopoll_devs;
28 
29 static enum adb_iop_state {
30 	idle,
31 	sending,
32 	awaiting_reply
33 } adb_iop_state;
34 
35 static void adb_iop_start(void);
36 static int adb_iop_probe(void);
37 static int adb_iop_init(void);
38 static int adb_iop_send_request(struct adb_request *, int);
39 static int adb_iop_write(struct adb_request *);
40 static int adb_iop_autopoll(int);
41 static void adb_iop_poll(void);
42 static int adb_iop_reset_bus(void);
43 
44 struct adb_driver adb_iop_driver = {
45 	.name         = "ISM IOP",
46 	.probe        = adb_iop_probe,
47 	.init         = adb_iop_init,
48 	.send_request = adb_iop_send_request,
49 	.autopoll     = adb_iop_autopoll,
50 	.poll         = adb_iop_poll,
51 	.reset_bus    = adb_iop_reset_bus
52 };
53 
54 static void adb_iop_done(void)
55 {
56 	struct adb_request *req = current_req;
57 
58 	adb_iop_state = idle;
59 
60 	req->complete = 1;
61 	current_req = req->next;
62 	if (req->done)
63 		(*req->done)(req);
64 
65 	if (adb_iop_state == idle)
66 		adb_iop_start();
67 }
68 
69 /*
70  * Completion routine for ADB commands sent to the IOP.
71  *
72  * This will be called when a packet has been successfully sent.
73  */
74 
75 static void adb_iop_complete(struct iop_msg *msg)
76 {
77 	unsigned long flags;
78 
79 	local_irq_save(flags);
80 
81 	if (current_req->reply_expected)
82 		adb_iop_state = awaiting_reply;
83 	else
84 		adb_iop_done();
85 
86 	local_irq_restore(flags);
87 }
88 
89 /*
90  * Listen for ADB messages from the IOP.
91  *
92  * This will be called when unsolicited messages (usually replies to TALK
93  * commands or autopoll packets) are received.
94  */
95 
96 static void adb_iop_listen(struct iop_msg *msg)
97 {
98 	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
99 	unsigned long flags;
100 	bool req_done = false;
101 
102 	local_irq_save(flags);
103 
104 	/* Handle a timeout. Timeout packets seem to occur even after
105 	 * we've gotten a valid reply to a TALK, presumably because of
106 	 * autopolling.
107 	 */
108 
109 	if (amsg->flags & ADB_IOP_EXPLICIT) {
110 		if (adb_iop_state == awaiting_reply) {
111 			struct adb_request *req = current_req;
112 
113 			req->reply_len = amsg->count + 1;
114 			memcpy(req->reply, &amsg->cmd, req->reply_len);
115 
116 			req_done = true;
117 		}
118 	} else if (!(amsg->flags & ADB_IOP_TIMEOUT)) {
119 		adb_input(&amsg->cmd, amsg->count + 1,
120 			  amsg->flags & ADB_IOP_AUTOPOLL);
121 	}
122 
123 	msg->reply[0] = autopoll_devs ? ADB_IOP_AUTOPOLL : 0;
124 	iop_complete_message(msg);
125 
126 	if (req_done)
127 		adb_iop_done();
128 
129 	local_irq_restore(flags);
130 }
131 
132 /*
133  * Start sending an ADB packet, IOP style
134  *
135  * There isn't much to do other than hand the packet over to the IOP
136  * after encapsulating it in an adb_iopmsg.
137  */
138 
139 static void adb_iop_start(void)
140 {
141 	struct adb_request *req;
142 	struct adb_iopmsg amsg;
143 
144 	/* get the packet to send */
145 	req = current_req;
146 	if (!req)
147 		return;
148 
149 	/* The IOP takes MacII-style packets, so strip the initial
150 	 * ADB_PACKET byte.
151 	 */
152 	amsg.flags = ADB_IOP_EXPLICIT;
153 	amsg.count = req->nbytes - 2;
154 
155 	/* amsg.data immediately follows amsg.cmd, effectively making
156 	 * &amsg.cmd a pointer to the beginning of a full ADB packet.
157 	 */
158 	memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);
159 
160 	req->sent = 1;
161 	adb_iop_state = sending;
162 
163 	/* Now send it. The IOP manager will call adb_iop_complete
164 	 * when the message has been sent.
165 	 */
166 	iop_send_message(ADB_IOP, ADB_CHAN, req, sizeof(amsg), (__u8 *)&amsg,
167 			 adb_iop_complete);
168 }
169 
170 static int adb_iop_probe(void)
171 {
172 	if (!iop_ism_present)
173 		return -ENODEV;
174 	return 0;
175 }
176 
177 static int adb_iop_init(void)
178 {
179 	pr_info("adb: IOP ISM driver v0.4 for Unified ADB\n");
180 	iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
181 	return 0;
182 }
183 
184 static int adb_iop_send_request(struct adb_request *req, int sync)
185 {
186 	int err;
187 
188 	err = adb_iop_write(req);
189 	if (err)
190 		return err;
191 
192 	if (sync) {
193 		while (!req->complete)
194 			adb_iop_poll();
195 	}
196 	return 0;
197 }
198 
199 static int adb_iop_write(struct adb_request *req)
200 {
201 	unsigned long flags;
202 
203 	if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) {
204 		req->complete = 1;
205 		return -EINVAL;
206 	}
207 
208 	req->next = NULL;
209 	req->sent = 0;
210 	req->complete = 0;
211 	req->reply_len = 0;
212 
213 	local_irq_save(flags);
214 
215 	if (current_req) {
216 		last_req->next = req;
217 		last_req = req;
218 	} else {
219 		current_req = req;
220 		last_req = req;
221 	}
222 
223 	if (adb_iop_state == idle)
224 		adb_iop_start();
225 
226 	local_irq_restore(flags);
227 
228 	return 0;
229 }
230 
231 static void adb_iop_set_ap_complete(struct iop_msg *msg)
232 {
233 	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
234 
235 	autopoll_devs = (amsg->data[1] << 8) | amsg->data[0];
236 }
237 
238 static int adb_iop_autopoll(int devs)
239 {
240 	struct adb_iopmsg amsg;
241 	unsigned long flags;
242 	unsigned int mask = (unsigned int)devs & 0xFFFE;
243 
244 	local_irq_save(flags);
245 
246 	amsg.flags = ADB_IOP_SET_AUTOPOLL | (mask ? ADB_IOP_AUTOPOLL : 0);
247 	amsg.count = 2;
248 	amsg.cmd = 0;
249 	amsg.data[0] = mask & 0xFF;
250 	amsg.data[1] = (mask >> 8) & 0xFF;
251 
252 	iop_send_message(ADB_IOP, ADB_CHAN, NULL, sizeof(amsg), (__u8 *)&amsg,
253 			 adb_iop_set_ap_complete);
254 
255 	local_irq_restore(flags);
256 
257 	return 0;
258 }
259 
260 static void adb_iop_poll(void)
261 {
262 	iop_ism_irq_poll(ADB_IOP);
263 }
264 
265 static int adb_iop_reset_bus(void)
266 {
267 	struct adb_request req;
268 
269 	/* Command = 0, Address = ignored */
270 	adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET);
271 	adb_iop_send_request(&req, 1);
272 
273 	/* Don't want any more requests during the Global Reset low time. */
274 	mdelay(3);
275 
276 	return 0;
277 }
278