xref: /aosp_15_r20/external/coreboot/payloads/libpayload/drivers/udc/chipidea.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /*
2  *
3  * Copyright (C) 2015 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <libpayload.h>
30 #include <arch/cache.h>
31 #include <assert.h>
32 #include <endian.h>
33 #include <queue.h>
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <usb/usb.h>
38 
39 #include <udc/udc.h>
40 #include <udc/chipidea.h>
41 #include "chipidea_priv.h"
42 
43 #ifdef DEBUG
44 #define debug(x...) printf(x)
45 #else
46 #define debug(x...) do {} while (0)
47 #endif
48 
49 #define min(a, b) (((a) < (b)) ? (a) : (b))
50 
get_qh(struct chipidea_pdata * p,int endpoint,int in_dir)51 static struct qh *get_qh(struct chipidea_pdata *p, int endpoint, int in_dir)
52 {
53 	assert(in_dir <= 1);
54 	return &p->qhlist[2 * endpoint + in_dir];
55 }
56 
ep_to_bits(int ep,int in_dir)57 static unsigned int ep_to_bits(int ep, int in_dir)
58 {
59 	return ep + (in_dir ? 16 : 0);
60 }
61 
clear_setup_ep(struct chipidea_pdata * p,int endpoint)62 static void clear_setup_ep(struct chipidea_pdata *p, int endpoint)
63 {
64 	writel(1 << endpoint, &p->opreg->epsetupstat);
65 }
66 
clear_ep(struct chipidea_pdata * p,int endpoint,int in_dir)67 static void clear_ep(struct chipidea_pdata *p, int endpoint, int in_dir)
68 {
69 	writel(1 << ep_to_bits(endpoint, in_dir), &p->opreg->epcomplete);
70 }
71 
chipidea_hw_init(struct usbdev_ctrl * this,void * _opreg,const device_descriptor_t * dd)72 static int chipidea_hw_init(struct usbdev_ctrl *this, void *_opreg,
73 	const device_descriptor_t *dd)
74 {
75 	struct chipidea_opreg *opreg = _opreg;
76 	struct chipidea_pdata *p = CI_PDATA(this);
77 
78 	p->opreg = phys_to_virt(opreg);
79 	p->qhlist = dma_memalign(4096, sizeof(struct qh) * CI_QHELEMENTS);
80 	memcpy(&this->device_descriptor, dd, sizeof(*dd));
81 
82 	if (p->qhlist == NULL)
83 		die("failed to allocate memory for USB device mode");
84 
85 	memset(p->qhlist, 0, sizeof(struct qh) * CI_QHELEMENTS);
86 
87 	SLIST_INIT(&this->configs);
88 
89 	int i;
90 	for (i = 0; i < 16; i++) {
91 		SIMPLEQ_INIT(&p->job_queue[i][0]);
92 		SIMPLEQ_INIT(&p->job_queue[i][1]);
93 	}
94 
95 	for (i = 0; i < CI_QHELEMENTS; i++) {
96 		p->qhlist[i].config = QH_MPS(512) | QH_NO_AUTO_ZLT | QH_IOS;
97 		p->qhlist[i].td.next = TD_TERMINATE;
98 	}
99 	/* EP0 in/out are hardwired for SETUP */
100 	p->qhlist[0].config = QH_MPS(64) | QH_NO_AUTO_ZLT | QH_IOS;
101 	p->qhlist[1].config = QH_MPS(64) | QH_NO_AUTO_ZLT | QH_IOS;
102 
103 	do {
104 		debug("waiting for USB phy clk valid: %x\n",
105 			readl(&p->opreg->susp_ctrl));
106 		mdelay(1);
107 	} while ((readl(&p->opreg->susp_ctrl) & (1 << 7)) == 0);
108 
109 	writel(USBCMD_8MICRO | USBCMD_RST, &p->opreg->usbcmd);
110 	mdelay(1);
111 
112 	/* enable device mode */
113 	writel(2, &p->opreg->usbmode);
114 
115 	dcache_clean_by_mva(p->qhlist, sizeof(struct qh) * CI_QHELEMENTS);
116 
117 	writel(virt_to_phys(p->qhlist), &p->opreg->epbase);
118 	writel(0xffffffff, &p->opreg->epflush);
119 
120 	/* enable EP0 */
121 	writel((1 << 23) | (1 << 22) | (1 << 7) | (1 << 6),
122 		&p->opreg->epctrl[0]);
123 
124 	/* clear status register */
125 	writel(readl(&p->opreg->usbsts), &p->opreg->usbsts);
126 
127 	debug("taking controller out of reset\n");
128 	writel(USBCMD_8MICRO | USBCMD_RUN, &p->opreg->usbcmd);
129 
130 	this->stall(this, 0, 0, 0);
131 	this->stall(this, 0, 1, 0);
132 
133 	return 1;
134 }
135 
chipidea_halt_ep(struct usbdev_ctrl * this,int ep,int in_dir)136 static void chipidea_halt_ep(struct usbdev_ctrl *this, int ep, int in_dir)
137 {
138 	struct chipidea_pdata *p = CI_PDATA(this);
139 	writel(1 << ep_to_bits(ep, in_dir), &p->opreg->epflush);
140 	while (readl(&p->opreg->epflush))
141 		;
142 	clrbits32(&p->opreg->epctrl[ep], 1 << (7 + (in_dir ? 16 : 0)));
143 
144 	while (!SIMPLEQ_EMPTY(&p->job_queue[ep][in_dir])) {
145 		struct job *job = SIMPLEQ_FIRST(&p->job_queue[ep][in_dir]);
146 		if (job->autofree)
147 			free(job->data);
148 
149 		SIMPLEQ_REMOVE_HEAD(&p->job_queue[ep][in_dir], queue);
150 	}
151 }
152 
chipidea_start_ep(struct usbdev_ctrl * this,int ep,int in_dir,int ep_type,int mps)153 static void chipidea_start_ep(struct usbdev_ctrl *this,
154 	int ep, int in_dir, int ep_type, int mps)
155 {
156 	struct chipidea_pdata *p = CI_PDATA(this);
157 	struct qh *qh = get_qh(p, ep, in_dir);
158 	qh->config = (mps << 16) | QH_NO_AUTO_ZLT | QH_IOS;
159 	dcache_clean_by_mva(qh, sizeof(*qh));
160 	in_dir = in_dir ? 1 : 0;
161 	debug("enabling %d-%d (type %d)\n", ep, in_dir, ep_type);
162 	/* enable endpoint, reset data toggle */
163 	setbits32(&p->opreg->epctrl[ep],
164 		((1 << 7) | (1 << 6) | (ep_type << 2)) << (in_dir*16));
165 	p->ep_busy[ep][in_dir] = 0;
166 	this->ep_mps[ep][in_dir] = mps;
167 }
168 
advance_endpoint(struct chipidea_pdata * p,int endpoint,int in_dir)169 static void advance_endpoint(struct chipidea_pdata *p, int endpoint, int in_dir)
170 {
171 	if (p->ep_busy[endpoint][in_dir])
172 		return;
173 	if (SIMPLEQ_EMPTY(&p->job_queue[endpoint][in_dir]))
174 		return;
175 
176 	struct job *job = SIMPLEQ_FIRST(&p->job_queue[endpoint][in_dir]);
177 	struct qh *qh = get_qh(p, endpoint, in_dir);
178 
179 	uint32_t start = (uint32_t)(uintptr_t)job->data;
180 	uint32_t offset = (start & 0xfff);
181 	/* unlike with typical EHCI controllers,
182 	 * a full TD transfers either 0x5000 bytes if
183 	 * page aligned or 0x4000 bytes if not.
184 	 */
185 	int maxsize = 0x5000;
186 	if (offset > 0)
187 		maxsize = 0x4000;
188 	uint32_t td_count = (job->length + maxsize - 1) / maxsize;
189 
190 	/* special case for zero length packets */
191 	if (td_count == 0)
192 		td_count = 1;
193 
194 	if (job->zlp)
195 		td_count++;
196 
197 	struct td *tds = dma_memalign(32, sizeof(struct td) * td_count);
198 	memset(tds, 0, sizeof(struct td) * td_count);
199 
200 	int i;
201 	int remaining = job->length;
202 	for (i = 0; i < td_count; i++) {
203 		int datacount = min(maxsize, remaining);
204 
205 		debug("td %d, %d bytes\n", i, datacount);
206 		tds[i].next = (uint32_t)virt_to_phys(&tds[i+1]);
207 		tds[i].info = TD_INFO_LEN(datacount) | TD_INFO_ACTIVE;
208 		tds[i].page0 = start;
209 		tds[i].page1 = (start & 0xfffff000) + 0x1000;
210 		tds[i].page2 = (start & 0xfffff000) + 0x2000;
211 		tds[i].page3 = (start & 0xfffff000) + 0x3000;
212 		tds[i].page4 = (start & 0xfffff000) + 0x4000;
213 		remaining -= datacount;
214 		start = start + datacount;
215 	}
216 	tds[td_count - 1].next = TD_TERMINATE;
217 	tds[td_count - 1].info |= TD_INFO_IOC;
218 
219 	qh->td.next = (uint32_t)virt_to_phys(tds);
220 	qh->td.info = 0;
221 
222 	job->tds = tds;
223 	job->td_count = td_count;
224 	dcache_clean_by_mva(tds, sizeof(struct td) * td_count);
225 	dcache_clean_by_mva(qh, sizeof(*qh));
226 	if (!dma_coherent(job->data))
227 		dcache_clean_by_mva(job->data, job->length);
228 
229 	debug("priming EP %d-%d with %zx bytes starting at %x (%p)\n", endpoint,
230 		in_dir, job->length, tds[0].page0, job->data);
231 	writel(1 << ep_to_bits(endpoint, in_dir), &p->opreg->epprime);
232 	while (readl(&p->opreg->epprime))
233 		;
234 	p->ep_busy[endpoint][in_dir] = 1;
235 }
236 
handle_endpoint(struct usbdev_ctrl * this,int endpoint,int in_dir)237 static void handle_endpoint(struct usbdev_ctrl *this, int endpoint, int in_dir)
238 {
239 	struct chipidea_pdata *p = CI_PDATA(this);
240 	struct job *job = SIMPLEQ_FIRST(&p->job_queue[endpoint][in_dir]);
241 	SIMPLEQ_REMOVE_HEAD(&p->job_queue[endpoint][in_dir], queue);
242 
243 	if (in_dir && !dma_coherent(job->data))
244 		dcache_invalidate_by_mva(job->data, job->length);
245 
246 	int length = job->length;
247 
248 	int i = 0;
249 	do {
250 		int active;
251 		do {
252 			dcache_invalidate_by_mva(&job->tds[i],
253 				sizeof(struct td));
254 			active = job->tds[i].info & TD_INFO_ACTIVE;
255 			debug("%d-%d: info %08x, page0 %x, next %x\n",
256 				endpoint, in_dir, job->tds[i].info,
257 				job->tds[i].page0, job->tds[i].next);
258 		} while (active);
259 		/*
260 		 * The controller writes back the length field in info
261 		 * with the number of bytes it did _not_ process.
262 		 * Hence, take the originally scheduled length and
263 		 * subtract whatever lengths we still find - that gives
264 		 * us the data that the controller did transfer.
265 		 */
266 		int remaining = job->tds[i].info >> 16;
267 		length -= remaining;
268 	} while (job->tds[i++].next != TD_TERMINATE);
269 	debug("%d-%d: scheduled %zd, now %d bytes\n", endpoint, in_dir,
270 		job->length, length);
271 
272 	if (this->current_config &&
273 	    this->current_config->interfaces[0].handle_packet)
274 		this->current_config->interfaces[0].handle_packet(this,
275 			endpoint, in_dir, job->data, length);
276 
277 	free(job->tds);
278 	if (job->autofree)
279 		free(job->data);
280 	free(job);
281 	p->ep_busy[endpoint][in_dir] = 0;
282 
283 	advance_endpoint(p, endpoint, in_dir);
284 }
285 
start_setup(struct usbdev_ctrl * this,int ep)286 static void start_setup(struct usbdev_ctrl *this, int ep)
287 {
288 	dev_req_t dr;
289 	struct chipidea_pdata *p = CI_PDATA(this);
290 	struct qh *qh = get_qh(p, ep, 0);
291 
292 	dcache_invalidate_by_mva(qh, sizeof(*qh));
293 	memcpy(&dr, qh->setup_data, sizeof(qh->setup_data));
294 	clear_setup_ep(p, ep);
295 
296 #ifdef DEBUG
297 	hexdump((unsigned long)&dr, sizeof(dr));
298 #endif
299 
300 	udc_handle_setup(this, ep, &dr);
301 }
302 
chipidea_enqueue_packet(struct usbdev_ctrl * this,int endpoint,int in_dir,void * data,int len,int zlp,int autofree)303 static void chipidea_enqueue_packet(struct usbdev_ctrl *this, int endpoint,
304 	int in_dir, void *data, int len, int zlp, int autofree)
305 {
306 	struct chipidea_pdata *p = CI_PDATA(this);
307 	struct job *job = malloc(sizeof(*job));
308 
309 	job->data = data;
310 	job->length = len;
311 	job->zlp = zlp;
312 	job->autofree = autofree;
313 
314 	debug("adding job of %d bytes to EP %d-%d\n", len, endpoint, in_dir);
315 	SIMPLEQ_INSERT_TAIL(&p->job_queue[endpoint][in_dir], job, queue);
316 
317 	if ((endpoint == 0) || (this->initialized))
318 		advance_endpoint(p, endpoint, in_dir);
319 }
320 
chipidea_poll(struct usbdev_ctrl * this)321 static int chipidea_poll(struct usbdev_ctrl *this)
322 {
323 	struct chipidea_pdata *p = CI_PDATA(this);
324 	uint32_t sts = readl(&p->opreg->usbsts);
325 	writel(sts, &p->opreg->usbsts); /* clear */
326 
327 	/* new information if the bus is high speed or not */
328 	if (sts & USBSTS_PCI) {
329 		debug("USB speed negotiation: ");
330 		if ((readl(&p->opreg->devlc) & DEVLC_HOSTSPEED_MASK)
331 		   == DEVLC_HOSTSPEED(2)) {
332 			debug("high speed\n");
333 			// TODO: implement
334 		} else {
335 			debug("full speed\n");
336 			// TODO: implement
337 		}
338 	}
339 
340 	/* reset requested. stop all activities */
341 	if (sts & USBSTS_URI) {
342 		int i;
343 		debug("USB reset requested\n");
344 		if (this->initialized) {
345 			writel(readl(&p->opreg->epstat), &p->opreg->epstat);
346 			writel(readl(&p->opreg->epsetupstat),
347 				&p->opreg->epsetupstat);
348 			writel(0xffffffff, &p->opreg->epflush);
349 			for (i = 1; i < 16; i++)
350 				writel(0, &p->opreg->epctrl[i]);
351 			this->initialized = 0;
352 		}
353 		writel((1 << 22) | (1 << 6), &p->opreg->epctrl[0]);
354 		p->qhlist[0].config = QH_MPS(64) | QH_NO_AUTO_ZLT | QH_IOS;
355 		p->qhlist[1].config = QH_MPS(64) | QH_NO_AUTO_ZLT | QH_IOS;
356 		dcache_clean_by_mva(p->qhlist, 2 * sizeof(struct qh));
357 	}
358 
359 	if (sts & (USBSTS_UEI | USBSTS_UI)) {
360 		uint32_t bitmap;
361 		int ep;
362 
363 		/* This slightly deviates from the recommendation in the
364 		 * data sheets, but the strict ordering is to simplify
365 		 * handling control transfers, which are initialized in
366 		 * the third step with a SETUP packet, then proceed in
367 		 * the next poll loop with in transfers (either data or
368 		 * status phase), then optionally out transfers (status
369 		 * phase).
370 		 */
371 
372 		/* in transfers */
373 		bitmap = (readl(&p->opreg->epcomplete) >> 16) & 0xffff;
374 		ep = 0;
375 		while (bitmap) {
376 			if (bitmap & 1) {
377 				debug("incoming packet on EP %d (in)\n", ep);
378 				handle_endpoint(this, ep, 1);
379 				clear_ep(p, ep & 0xf, 1);
380 			}
381 			bitmap >>= 1;
382 			ep++;
383 		}
384 
385 		/* out transfers */
386 		bitmap = readl(&p->opreg->epcomplete) & 0xffff;
387 		ep = 0;
388 		while (bitmap) {
389 			if (bitmap & 1) {
390 				debug("incoming packet on EP %d (out)\n", ep);
391 				handle_endpoint(this, ep, 0);
392 				clear_ep(p, ep, 0);
393 			}
394 			bitmap >>= 1;
395 			ep++;
396 		}
397 
398 		/* setup transfers */
399 		bitmap = readl(&p->opreg->epsetupstat);
400 		ep = 0;
401 		while (bitmap) {
402 			if (bitmap & 1) {
403 				debug("incoming packet on EP %d (setup)\n", ep);
404 				start_setup(this, ep);
405 			}
406 			bitmap >>= 1;
407 			ep++;
408 		}
409 	}
410 
411 	return 1;
412 }
413 
chipidea_force_shutdown(struct usbdev_ctrl * this)414 static void chipidea_force_shutdown(struct usbdev_ctrl *this)
415 {
416 	struct chipidea_pdata *p = CI_PDATA(this);
417 	writel(0xffffffff, &p->opreg->epflush);
418 	writel(USBCMD_8MICRO | USBCMD_RST, &p->opreg->usbcmd);
419 	writel(0, &p->opreg->usbmode);
420 	writel(USBCMD_8MICRO, &p->opreg->usbcmd);
421 	free(p->qhlist);
422 	free(p);
423 	free(this);
424 }
425 
chipidea_shutdown(struct usbdev_ctrl * this)426 static void chipidea_shutdown(struct usbdev_ctrl *this)
427 {
428 	struct chipidea_pdata *p = CI_PDATA(this);
429 	int i, j;
430 	int is_empty = 0;
431 	while (!is_empty) {
432 		is_empty = 1;
433 		this->poll(this);
434 		for (i = 0; i < 16; i++)
435 			for (j = 0; j < 2; j++)
436 				if (!SIMPLEQ_EMPTY(&p->job_queue[i][j]))
437 					is_empty = 0;
438 	}
439 	chipidea_force_shutdown(this);
440 }
441 
chipidea_set_address(struct usbdev_ctrl * this,int address)442 static void chipidea_set_address(struct usbdev_ctrl *this, int address)
443 {
444 	struct chipidea_pdata *p = CI_PDATA(this);
445 	writel((address << 25) | (1 << 24), &p->opreg->usbadr);
446 }
447 
chipidea_stall(struct usbdev_ctrl * this,uint8_t ep,int in_dir,int set)448 static void chipidea_stall(struct usbdev_ctrl *this,
449 	uint8_t ep, int in_dir, int set)
450 {
451 	struct chipidea_pdata *p = CI_PDATA(this);
452 	assert(ep < 16);
453 	uint32_t *ctrl = &p->opreg->epctrl[ep];
454 	in_dir = in_dir ? 1 : 0;
455 	if (set) {
456 		if (in_dir)
457 			setbits32(ctrl, 1 << 16);
458 		else
459 			setbits32(ctrl, 1 << 0);
460 	} else {
461 		/* reset STALL bit, reset data toggle */
462 		if (in_dir) {
463 			setbits32(ctrl, 1 << 22);
464 			clrbits32(ctrl, 1 << 16);
465 		} else {
466 			setbits32(ctrl, 1 << 6);
467 			clrbits32(ctrl, 1 << 0);
468 		}
469 	}
470 	this->ep_halted[ep][in_dir] = set;
471 }
472 
chipidea_malloc(size_t size)473 static void *chipidea_malloc(size_t size)
474 {
475 	return dma_malloc(size);
476 }
477 
chipidea_free(void * ptr)478 static void chipidea_free(void *ptr)
479 {
480 	free(ptr);
481 }
482 
chipidea_init(device_descriptor_t * dd)483 struct usbdev_ctrl *chipidea_init(device_descriptor_t *dd)
484 {
485 	struct usbdev_ctrl *ctrl = calloc(1, sizeof(*ctrl));
486 	if (ctrl == NULL)
487 		return NULL;
488 	ctrl->pdata = calloc(1, sizeof(struct chipidea_pdata));
489 	if (ctrl->pdata == NULL) {
490 		free(ctrl);
491 		return NULL;
492 	}
493 
494 	ctrl->poll = chipidea_poll;
495 	ctrl->add_gadget = udc_add_gadget;
496 	ctrl->add_strings = udc_add_strings;
497 	ctrl->enqueue_packet = chipidea_enqueue_packet;
498 	ctrl->force_shutdown = chipidea_force_shutdown;
499 	ctrl->shutdown = chipidea_shutdown;
500 	ctrl->set_address = chipidea_set_address;
501 	ctrl->stall = chipidea_stall;
502 	ctrl->halt_ep = chipidea_halt_ep;
503 	ctrl->start_ep = chipidea_start_ep;
504 	ctrl->alloc_data = chipidea_malloc;
505 	ctrl->free_data = chipidea_free;
506 	ctrl->initialized = 0;
507 
508 	int i;
509 	ctrl->ep_mps[0][0] = 64;
510 	ctrl->ep_mps[0][1] = 64;
511 	for (i = 1; i < 16; i++) {
512 		ctrl->ep_mps[i][0] = 512;
513 		ctrl->ep_mps[i][1] = 512;
514 	}
515 
516 	if (!chipidea_hw_init(ctrl, (void *)0x7d000000, dd)) {
517 		free(ctrl->pdata);
518 		free(ctrl);
519 		return NULL;
520 	}
521 	return ctrl;
522 }
523