blob: f0b18bffba4123c8dfb33a8083f953b5c5514764 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +09002/*
3 * R8A66597 HCD (Host Controller Driver) for u-boot
4 *
5 * Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +09006 */
7
Simon Glassa73bda42015-11-08 23:47:45 -07008#include <console.h>
Marek Vasut5e890c52019-08-11 12:34:38 +02009#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090011#include <usb.h>
12#include <asm/io.h>
Simon Glass9bc15642020-02-03 07:36:16 -070013#include <dm/device_compat.h>
Simon Glassdbd79542020-05-10 11:40:11 -060014#include <linux/delay.h>
Chris Brandtc85f3cc2017-11-29 14:49:21 -050015#include <linux/iopoll.h>
Rui Miguel Silvafb0c70c2022-06-29 11:06:14 +010016#include <linux/usb/usb_urb_compat.h>
Marek Vasutc1214092019-08-22 17:53:04 +020017#include <power/regulator.h>
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090018
19#include "r8a66597.h"
20
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090021#ifdef R8A66597_DEBUG
22#define R8A66597_DPRINT printf
23#else
24#define R8A66597_DPRINT(...)
25#endif
26
Yoshihiro Shimoda8e6cc002008-10-29 20:05:18 +090027static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport)
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090028{
Marek Vasut5e890c52019-08-11 12:34:38 +020029 struct usb_device *parent = usb_dev_get_parent(dev);
Yoshihiro Shimoda8e6cc002008-10-29 20:05:18 +090030
31 *hub_devnum = 0;
32 *hubport = 0;
33
34 /* check a device connected to root_hub */
Marek Vasut5e890c52019-08-11 12:34:38 +020035 if ((parent && parent->devnum == 1) ||
Marek Vasutb3935f12019-08-11 13:44:10 +020036 dev->devnum == 1)
Yoshihiro Shimoda8e6cc002008-10-29 20:05:18 +090037 return;
38
Marek Vasut5e890c52019-08-11 12:34:38 +020039 *hub_devnum = (u8)parent->devnum;
40 *hubport = parent->portnr - 1;
Yoshihiro Shimoda8e6cc002008-10-29 20:05:18 +090041}
42
43static void set_devadd(struct r8a66597 *r8a66597, u8 r8a66597_address,
Marek Vasutb3935f12019-08-11 13:44:10 +020044 struct usb_device *dev, int port)
Yoshihiro Shimoda8e6cc002008-10-29 20:05:18 +090045{
46 u16 val, usbspd, upphub, hubport;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090047 unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
48
Yoshihiro Shimoda8e6cc002008-10-29 20:05:18 +090049 get_hub_data(dev, &upphub, &hubport);
50 usbspd = r8a66597->speed;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090051 val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001);
52 r8a66597_write(r8a66597, val, devadd_reg);
53}
54
55static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
56{
57 u16 tmp;
58 int i = 0;
59
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090060 do {
61 r8a66597_write(r8a66597, USBE, SYSCFG0);
62 tmp = r8a66597_read(r8a66597, SYSCFG0);
63 if (i++ > 1000) {
64 printf("register access fail.\n");
65 return -1;
66 }
67 } while ((tmp & USBE) != USBE);
68 r8a66597_bclr(r8a66597, USBE, SYSCFG0);
Chris Brandtfaecead2017-11-27 14:04:10 -050069 /*
70 * RZ/A Only:
71 * Bits XTAL(UCKSEL) and UPLLE in SYSCFG0 for USB0 controls both USB0
72 * and USB1, so we must always set the USB0 register
73 */
74#if (CONFIG_R8A66597_XTAL == 1)
Marek Vasut2c11a3c2019-08-11 12:34:38 +020075 r8a66597_bset(r8a66597, XTAL, SYSCFG0);
Chris Brandtfaecead2017-11-27 14:04:10 -050076#endif
77 mdelay(1);
Marek Vasut2c11a3c2019-08-11 12:34:38 +020078 r8a66597_bset(r8a66597, UPLLE, SYSCFG0);
Chris Brandtfaecead2017-11-27 14:04:10 -050079 mdelay(1);
80 r8a66597_bset(r8a66597, SUSPM, SUSPMODE0);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090081
82 return 0;
83}
84
85static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
86{
Chris Brandtfaecead2017-11-27 14:04:10 -050087 r8a66597_bclr(r8a66597, SUSPM, SUSPMODE0);
88
Marek Vasut2c11a3c2019-08-11 12:34:38 +020089 r8a66597_bclr(r8a66597, UPLLE, SYSCFG0);
Chris Brandtfaecead2017-11-27 14:04:10 -050090 mdelay(1);
91 r8a66597_bclr(r8a66597, USBE, SYSCFG0);
92 mdelay(1);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +090093}
94
95static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
96{
97 u16 val;
98
99 val = port ? DRPD : DCFM | DRPD;
100 r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
101 r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900102}
103
104static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
105{
106 u16 val, tmp;
107
108 r8a66597_write(r8a66597, 0, get_intenb_reg(port));
109 r8a66597_write(r8a66597, 0, get_intsts_reg(port));
110
111 r8a66597_port_power(r8a66597, port, 0);
112
113 do {
114 tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
115 udelay(640);
116 } while (tmp == EDGESTS);
117
118 val = port ? DRPD : DCFM | DRPD;
119 r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
120 r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
121}
122
123static int enable_controller(struct r8a66597 *r8a66597)
124{
125 int ret, port;
126
127 ret = r8a66597_clock_enable(r8a66597);
128 if (ret < 0)
129 return ret;
130
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900131 r8a66597_bset(r8a66597, USBE, SYSCFG0);
132
133 r8a66597_bset(r8a66597, INTL, SOFCFG);
134 r8a66597_write(r8a66597, 0, INTENB0);
yasuhisa umanoea33c6a2014-04-18 11:33:08 +0900135 for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
136 r8a66597_write(r8a66597, 0, get_intenb_reg(port));
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900137
Marek Vasutcf8a6272019-08-11 13:23:11 +0200138 r8a66597_bclr(r8a66597, BIGEND, CFIFOSEL);
139 r8a66597_bclr(r8a66597, BIGEND, D0FIFOSEL);
140 r8a66597_bclr(r8a66597, BIGEND, D1FIFOSEL);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900141 r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
142
143 for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
144 r8a66597_enable_port(r8a66597, port);
145
146 return 0;
147}
148
149static void disable_controller(struct r8a66597 *r8a66597)
150{
151 int i;
152
153 if (!(r8a66597_read(r8a66597, SYSCFG0) & USBE))
154 return;
155
156 r8a66597_write(r8a66597, 0, INTENB0);
157 r8a66597_write(r8a66597, 0, INTSTS0);
158
159 r8a66597_write(r8a66597, 0, D0FIFOSEL);
160 r8a66597_write(r8a66597, 0, D1FIFOSEL);
161 r8a66597_write(r8a66597, 0, DCPCFG);
162 r8a66597_write(r8a66597, 0x40, DCPMAXP);
163 r8a66597_write(r8a66597, 0, DCPCTR);
164
165 for (i = 0; i <= 10; i++)
166 r8a66597_write(r8a66597, 0, get_devadd_addr(i));
167 for (i = 1; i <= 5; i++) {
168 r8a66597_write(r8a66597, 0, get_pipetre_addr(i));
169 r8a66597_write(r8a66597, 0, get_pipetrn_addr(i));
170 }
171 for (i = 1; i < R8A66597_MAX_NUM_PIPE; i++) {
172 r8a66597_write(r8a66597, 0, get_pipectr_addr(i));
173 r8a66597_write(r8a66597, i, PIPESEL);
174 r8a66597_write(r8a66597, 0, PIPECFG);
175 r8a66597_write(r8a66597, 0, PIPEBUF);
176 r8a66597_write(r8a66597, 0, PIPEMAXP);
177 r8a66597_write(r8a66597, 0, PIPEPERI);
178 }
179
180 for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++)
181 r8a66597_disable_port(r8a66597, i);
182
183 r8a66597_clock_disable(r8a66597);
184}
185
186static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
187 u16 mask, u16 loop)
188{
189 u16 tmp;
190 int i = 0;
191
192 do {
193 tmp = r8a66597_read(r8a66597, reg);
194 if (i++ > 1000000) {
195 printf("register%lx, loop %x is timeout\n", reg, loop);
196 break;
197 }
198 } while ((tmp & mask) != loop);
199}
200
201static void pipe_buffer_setting(struct r8a66597 *r8a66597,
202 struct usb_device *dev, unsigned long pipe)
203{
204 u16 val = 0;
205 u16 pipenum, bufnum, maxpacket;
206
207 if (usb_pipein(pipe)) {
208 pipenum = BULK_IN_PIPENUM;
209 bufnum = BULK_IN_BUFNUM;
210 maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
211 } else {
212 pipenum = BULK_OUT_PIPENUM;
213 bufnum = BULK_OUT_BUFNUM;
214 maxpacket = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
215 }
216
217 if (r8a66597->pipe_config & (1 << pipenum))
218 return;
219 r8a66597->pipe_config |= (1 << pipenum);
220
221 r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(pipenum));
222 r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(pipenum));
223 r8a66597_write(r8a66597, pipenum, PIPESEL);
224
225 /* FIXME: This driver support bulk transfer only. */
226 if (!usb_pipein(pipe))
227 val |= R8A66597_DIR;
228 else
229 val |= R8A66597_SHTNAK;
230 val |= R8A66597_BULK | R8A66597_DBLB | usb_pipeendpoint(pipe);
231 r8a66597_write(r8a66597, val, PIPECFG);
232
233 r8a66597_write(r8a66597, (8 << 10) | bufnum, PIPEBUF);
234 r8a66597_write(r8a66597, make_devsel(usb_pipedevice(pipe)) |
235 maxpacket, PIPEMAXP);
236 r8a66597_write(r8a66597, 0, PIPEPERI);
237 r8a66597_write(r8a66597, SQCLR, get_pipectr_addr(pipenum));
238}
239
240static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
241 struct devrequest *setup)
242{
243 int i;
244 unsigned short *p = (unsigned short *)setup;
245 unsigned long setup_addr = USBREQ;
246 u16 intsts1;
247 int timeout = 3000;
Chris Brandtfaecead2017-11-27 14:04:10 -0500248 u16 dcpctr;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900249 u16 devsel = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum;
250
251 r8a66597_write(r8a66597, make_devsel(devsel) |
252 (8 << dev->maxpacketsize), DCPMAXP);
253 r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1);
254
Chris Brandtfaecead2017-11-27 14:04:10 -0500255 dcpctr = r8a66597_read(r8a66597, DCPCTR);
256 if ((dcpctr & PID) == PID_BUF) {
Chris Brandtc85f3cc2017-11-29 14:49:21 -0500257 if (readw_poll_timeout(r8a66597->reg + DCPCTR, dcpctr,
258 dcpctr & BSTS, 1000) < 0) {
259 printf("DCPCTR BSTS timeout!\n");
260 return -ETIMEDOUT;
Chris Brandtfaecead2017-11-27 14:04:10 -0500261 }
262 }
Chris Brandtfaecead2017-11-27 14:04:10 -0500263
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900264 for (i = 0; i < 4; i++) {
265 r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr);
266 setup_addr += 2;
267 }
268 r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
269 r8a66597_write(r8a66597, SUREQ, DCPCTR);
270
271 while (1) {
272 intsts1 = r8a66597_read(r8a66597, INTSTS1);
273 if (intsts1 & SACK)
274 break;
275 if (intsts1 & SIGN) {
276 printf("setup packet send error\n");
277 return -1;
278 }
279 if (timeout-- < 0) {
280 printf("setup packet timeout\n");
281 return -1;
282 }
283 udelay(500);
284 }
285
286 return 0;
287}
288
289static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
290 unsigned long pipe, void *buffer, int transfer_len)
291{
292 u16 tmp, bufsize;
293 u16 *buf;
294 size_t size;
295
296 R8A66597_DPRINT("%s\n", __func__);
297
298 r8a66597_mdfy(r8a66597, MBW | BULK_OUT_PIPENUM,
Marek Vasutb3935f12019-08-11 13:44:10 +0200299 MBW | CURPIPE, CFIFOSEL);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900300 r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, BULK_OUT_PIPENUM);
301 tmp = r8a66597_read(r8a66597, CFIFOCTR);
302 if ((tmp & FRDY) == 0) {
303 printf("%s FRDY is not set (%x)\n", __func__, tmp);
304 return -1;
305 }
306
307 /* prepare parameters */
308 bufsize = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
309 buf = (u16 *)(buffer + dev->act_len);
310 size = min((int)bufsize, transfer_len - dev->act_len);
311
312 /* write fifo */
313 r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
314 if (buffer) {
315 r8a66597_write_fifo(r8a66597, CFIFO, buf, size);
316 r8a66597_write(r8a66597, BVAL, CFIFOCTR);
317 }
318
319 /* update parameters */
320 dev->act_len += size;
321
322 r8a66597_mdfy(r8a66597, PID_BUF, PID,
Marek Vasutb3935f12019-08-11 13:44:10 +0200323 get_pipectr_addr(BULK_OUT_PIPENUM));
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900324
325 while (!(r8a66597_read(r8a66597, BEMPSTS) & (1 << BULK_OUT_PIPENUM)))
326 if (ctrlc())
327 return -1;
328 r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
329
330 if (dev->act_len >= transfer_len)
331 r8a66597_mdfy(r8a66597, PID_NAK, PID,
Marek Vasutb3935f12019-08-11 13:44:10 +0200332 get_pipectr_addr(BULK_OUT_PIPENUM));
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900333
334 return 0;
335}
336
337static int receive_bulk_packet(struct r8a66597 *r8a66597,
338 struct usb_device *dev,
339 unsigned long pipe,
340 void *buffer, int transfer_len)
341{
342 u16 tmp;
343 u16 *buf;
344 const u16 pipenum = BULK_IN_PIPENUM;
345 int rcv_len;
346 int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
347
348 R8A66597_DPRINT("%s\n", __func__);
349
350 /* prepare */
351 if (dev->act_len == 0) {
352 r8a66597_mdfy(r8a66597, PID_NAK, PID,
Marek Vasutb3935f12019-08-11 13:44:10 +0200353 get_pipectr_addr(pipenum));
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900354 r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
355
356 r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum));
357 r8a66597_write(r8a66597,
Marek Vasutb3935f12019-08-11 13:44:10 +0200358 (transfer_len + maxpacket - 1) / maxpacket,
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900359 get_pipetrn_addr(pipenum));
360 r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum));
361
362 r8a66597_mdfy(r8a66597, PID_BUF, PID,
Marek Vasutb3935f12019-08-11 13:44:10 +0200363 get_pipectr_addr(pipenum));
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900364 }
365
366 r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
367 r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
368
369 while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum)))
370 if (ctrlc())
371 return -1;
372 r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
373
374 tmp = r8a66597_read(r8a66597, CFIFOCTR);
375 if ((tmp & FRDY) == 0) {
376 printf("%s FRDY is not set. (%x)\n", __func__, tmp);
377 return -1;
378 }
379
380 buf = (u16 *)(buffer + dev->act_len);
381 rcv_len = tmp & DTLN;
382 dev->act_len += rcv_len;
383
384 if (buffer) {
385 if (rcv_len == 0)
386 r8a66597_write(r8a66597, BCLR, CFIFOCTR);
387 else
388 r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len);
389 }
390
391 return 0;
392}
393
394static int receive_control_packet(struct r8a66597 *r8a66597,
395 struct usb_device *dev,
396 void *buffer, int transfer_len)
397{
398 u16 tmp;
399 int rcv_len;
400
401 /* FIXME: limit transfer size : 64byte or less */
402
403 r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
404 r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
405 r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
406 r8a66597_bset(r8a66597, SQSET, DCPCTR);
407 r8a66597_write(r8a66597, BCLR, CFIFOCTR);
408 r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
409
410 while (!(r8a66597_read(r8a66597, BRDYSTS) & 0x0001))
411 if (ctrlc())
412 return -1;
413 r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
414
415 r8a66597_mdfy(r8a66597, MBW, MBW | CURPIPE, CFIFOSEL);
416 r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
417
418 tmp = r8a66597_read(r8a66597, CFIFOCTR);
419 if ((tmp & FRDY) == 0) {
420 printf("%s FRDY is not set. (%x)\n", __func__, tmp);
421 return -1;
422 }
423
424 rcv_len = tmp & DTLN;
425 dev->act_len += rcv_len;
426
427 r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
428
429 if (buffer) {
430 if (rcv_len == 0)
431 r8a66597_write(r8a66597, BCLR, DCPCTR);
432 else
433 r8a66597_read_fifo(r8a66597, CFIFO, buffer, rcv_len);
434 }
435
436 return 0;
437}
438
439static int send_status_packet(struct r8a66597 *r8a66597,
Marek Vasutb3935f12019-08-11 13:44:10 +0200440 unsigned long pipe)
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900441{
442 r8a66597_bset(r8a66597, SQSET, DCPCTR);
443 r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
444
445 if (usb_pipein(pipe)) {
446 r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
447 r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
448 r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
449 r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
450 r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR);
451 } else {
452 r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
453 r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
454 r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
455 r8a66597_write(r8a66597, BCLR, CFIFOCTR);
456 }
457 r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
458
459 while (!(r8a66597_read(r8a66597, BEMPSTS) & 0x0001))
460 if (ctrlc())
461 return -1;
462
463 return 0;
464}
465
466static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port)
467{
468 int count = R8A66597_MAX_SAMPLING;
469 unsigned short syssts, old_syssts;
470
471 R8A66597_DPRINT("%s\n", __func__);
472
473 old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
474 while (count > 0) {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000475 mdelay(R8A66597_RH_POLL_TIME);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900476
477 syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
478 if (syssts == old_syssts) {
479 count--;
480 } else {
481 count = R8A66597_MAX_SAMPLING;
482 old_syssts = syssts;
483 }
484 }
485}
486
487static void r8a66597_bus_reset(struct r8a66597 *r8a66597, int port)
488{
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000489 mdelay(10);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900490 r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port));
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000491 mdelay(50);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900492 r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port));
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000493 mdelay(50);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900494}
495
496static int check_usb_device_connecting(struct r8a66597 *r8a66597)
497{
498 int timeout = 10000; /* 100usec * 10000 = 1sec */
499 int i;
500
501 for (i = 0; i < 5; i++) {
502 /* check a usb cable connect */
503 while (!(r8a66597_read(r8a66597, INTSTS1) & ATTCH)) {
504 if (timeout-- < 0) {
505 printf("%s timeout.\n", __func__);
506 return -1;
507 }
508 udelay(100);
509 }
510
511 /* check a data line */
512 r8a66597_check_syssts(r8a66597, 0);
513
514 r8a66597_bus_reset(r8a66597, 0);
515 r8a66597->speed = get_rh_usb_speed(r8a66597, 0);
516
517 if (!(r8a66597_read(r8a66597, INTSTS1) & DTCH)) {
518 r8a66597->port_change = USB_PORT_STAT_C_CONNECTION;
519 r8a66597->port_status = USB_PORT_STAT_CONNECTION |
520 USB_PORT_STAT_ENABLE;
521 return 0; /* success */
522 }
523
524 R8A66597_DPRINT("USB device has detached. retry = %d\n", i);
525 r8a66597_write(r8a66597, ~DTCH, INTSTS1);
526 }
527
528 return -1; /* fail */
529}
530
Marek Vasutb3935f12019-08-11 13:44:10 +0200531/* Virtual Root Hub */
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900532
Stephen Warren39c89682014-02-13 21:15:18 -0700533#include <usbroothubdes.h>
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900534
Marek Vasut5e890c52019-08-11 12:34:38 +0200535static int r8a66597_submit_rh_msg(struct udevice *udev, struct usb_device *dev,
536 unsigned long pipe, void *buffer,
537 int transfer_len, struct devrequest *cmd)
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900538{
Marek Vasut5e890c52019-08-11 12:34:38 +0200539 struct r8a66597 *r8a66597 = dev_get_priv(udev);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900540 int leni = transfer_len;
541 int len = 0;
542 int stat = 0;
543 __u16 bmRType_bReq;
544 __u16 wValue;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900545 __u16 wLength;
546 unsigned char data[32];
547
548 R8A66597_DPRINT("%s\n", __func__);
549
Remy Bohmerd8c55ab2008-10-10 10:23:22 +0200550 if (usb_pipeint(pipe)) {
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900551 printf("Root-Hub submit IRQ: NOT implemented");
552 return 0;
553 }
554
555 bmRType_bReq = cmd->requesttype | (cmd->request << 8);
556 wValue = cpu_to_le16 (cmd->value);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900557 wLength = cpu_to_le16 (cmd->length);
558
559 switch (bmRType_bReq) {
560 case RH_GET_STATUS:
561 *(__u16 *)buffer = cpu_to_le16(1);
562 len = 2;
563 break;
564 case RH_GET_STATUS | RH_INTERFACE:
565 *(__u16 *)buffer = cpu_to_le16(0);
566 len = 2;
567 break;
568 case RH_GET_STATUS | RH_ENDPOINT:
569 *(__u16 *)buffer = cpu_to_le16(0);
570 len = 2;
571 break;
572 case RH_GET_STATUS | RH_CLASS:
573 *(__u32 *)buffer = cpu_to_le32(0);
574 len = 4;
575 break;
576 case RH_GET_STATUS | RH_OTHER | RH_CLASS:
577 *(__u32 *)buffer = cpu_to_le32(r8a66597->port_status |
578 (r8a66597->port_change << 16));
579 len = 4;
580 break;
581 case RH_CLEAR_FEATURE | RH_ENDPOINT:
582 case RH_CLEAR_FEATURE | RH_CLASS:
583 break;
584
585 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
586 switch (wValue) {
587 case RH_C_PORT_CONNECTION:
588 r8a66597->port_change &= ~USB_PORT_STAT_C_CONNECTION;
589 break;
590 }
591 break;
592
593 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
594 switch (wValue) {
595 case (RH_PORT_SUSPEND):
596 break;
597 case (RH_PORT_RESET):
598 r8a66597_bus_reset(r8a66597, 0);
599 break;
600 case (RH_PORT_POWER):
601 break;
602 case (RH_PORT_ENABLE):
603 break;
604 }
605 break;
606 case RH_SET_ADDRESS:
Marek Vasut5e890c52019-08-11 12:34:38 +0200607 r8a66597->rh_devnum = wValue;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900608 break;
609 case RH_GET_DESCRIPTOR:
610 switch ((wValue & 0xff00) >> 8) {
611 case (0x01): /* device descriptor */
612 len = min_t(unsigned int,
Marek Vasutb3935f12019-08-11 13:44:10 +0200613 leni,
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900614 min_t(unsigned int,
Marek Vasutb3935f12019-08-11 13:44:10 +0200615 sizeof(root_hub_dev_des),
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900616 wLength));
617 memcpy(buffer, root_hub_dev_des, len);
618 break;
619 case (0x02): /* configuration descriptor */
620 len = min_t(unsigned int,
Marek Vasutb3935f12019-08-11 13:44:10 +0200621 leni,
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900622 min_t(unsigned int,
Marek Vasutb3935f12019-08-11 13:44:10 +0200623 sizeof(root_hub_config_des),
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900624 wLength));
625 memcpy(buffer, root_hub_config_des, len);
626 break;
627 case (0x03): /* string descriptors */
628 if (wValue == 0x0300) {
629 len = min_t(unsigned int,
Marek Vasutb3935f12019-08-11 13:44:10 +0200630 leni,
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900631 min_t(unsigned int,
Marek Vasutb3935f12019-08-11 13:44:10 +0200632 sizeof(root_hub_str_index0),
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900633 wLength));
634 memcpy(buffer, root_hub_str_index0, len);
635 }
636 if (wValue == 0x0301) {
637 len = min_t(unsigned int,
Marek Vasutb3935f12019-08-11 13:44:10 +0200638 leni,
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900639 min_t(unsigned int,
Marek Vasutb3935f12019-08-11 13:44:10 +0200640 sizeof(root_hub_str_index1),
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900641 wLength));
642 memcpy(buffer, root_hub_str_index1, len);
643 }
644 break;
645 default:
646 stat = USB_ST_STALLED;
647 }
648 break;
649
650 case RH_GET_DESCRIPTOR | RH_CLASS:
651 {
652 __u32 temp = 0x00000001;
653
654 data[0] = 9; /* min length; */
655 data[1] = 0x29;
656 data[2] = temp & RH_A_NDP;
657 data[3] = 0;
658 if (temp & RH_A_PSM)
659 data[3] |= 0x1;
660 if (temp & RH_A_NOCP)
661 data[3] |= 0x10;
662 else if (temp & RH_A_OCPM)
663 data[3] |= 0x8;
664
665 /* corresponds to data[4-7] */
666 data[5] = (temp & RH_A_POTPGT) >> 24;
667 data[7] = temp & RH_B_DR;
668 if (data[2] < 7) {
669 data[8] = 0xff;
670 } else {
671 data[0] += 2;
672 data[8] = (temp & RH_B_DR) >> 8;
Marek Vasutb3935f12019-08-11 13:44:10 +0200673 data[9] = 0xff;
674 data[10] = 0xff;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900675 }
676
677 len = min_t(unsigned int, leni,
678 min_t(unsigned int, data[0], wLength));
679 memcpy(buffer, data, len);
680 break;
681 }
682
683 case RH_GET_CONFIGURATION:
Marek Vasutb3935f12019-08-11 13:44:10 +0200684 *(__u8 *)buffer = 0x01;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900685 len = 1;
686 break;
687 case RH_SET_CONFIGURATION:
688 break;
689 default:
Nobuhiro Iwamatsu9d58a012008-09-18 20:13:08 +0900690 R8A66597_DPRINT("unsupported root hub command");
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900691 stat = USB_ST_STALLED;
692 }
693
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000694 mdelay(1);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900695
696 len = min_t(int, len, leni);
697
698 dev->act_len = len;
699 dev->status = stat;
700
701 return stat;
702}
703
Marek Vasutb3935f12019-08-11 13:44:10 +0200704static int r8a66597_submit_control_msg(struct udevice *udev,
705 struct usb_device *dev,
706 unsigned long pipe, void *buffer,
707 int length, struct devrequest *setup)
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900708{
Marek Vasut5e890c52019-08-11 12:34:38 +0200709 struct r8a66597 *r8a66597 = dev_get_priv(udev);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900710 u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ?
711 0 : dev->devnum;
712
Marek Vasut5e890c52019-08-11 12:34:38 +0200713 debug("%s: dev='%s', udev=%p, udev->dev='%s', portnr=%d\n", __func__,
714 udev->name, dev, dev->dev->name, dev->portnr);
715
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900716 R8A66597_DPRINT("%s\n", __func__);
717 if (usb_pipedevice(pipe) == r8a66597->rh_devnum)
Marek Vasut5e890c52019-08-11 12:34:38 +0200718 return r8a66597_submit_rh_msg(udev, dev, pipe, buffer,
719 length, setup);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900720
721 R8A66597_DPRINT("%s: setup\n", __func__);
Yoshihiro Shimoda8e6cc002008-10-29 20:05:18 +0900722 set_devadd(r8a66597, r8a66597_address, dev, 0);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900723
724 if (send_setup_packet(r8a66597, dev, setup) < 0) {
725 printf("setup packet send error\n");
726 return -1;
727 }
728
Yoshihiro Shimoda8e6cc002008-10-29 20:05:18 +0900729 dev->act_len = 0;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900730 if (usb_pipein(pipe))
731 if (receive_control_packet(r8a66597, dev, buffer,
Marek Vasutb3935f12019-08-11 13:44:10 +0200732 length) < 0)
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900733 return -1;
734
735 if (send_status_packet(r8a66597, pipe) < 0)
736 return -1;
737
738 dev->status = 0;
739
740 return 0;
741}
742
Marek Vasutb3935f12019-08-11 13:44:10 +0200743static int r8a66597_submit_bulk_msg(struct udevice *udev,
744 struct usb_device *dev, unsigned long pipe,
745 void *buffer, int length)
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900746{
Marek Vasut5e890c52019-08-11 12:34:38 +0200747 struct r8a66597 *r8a66597 = dev_get_priv(udev);
748 int ret = 0;
749
750 debug("%s: dev='%s', udev=%p\n", __func__, udev->name, dev);
751
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900752 R8A66597_DPRINT("%s\n", __func__);
Marek Vasut5e890c52019-08-11 12:34:38 +0200753 R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n",
754 pipe, buffer, length, dev->devnum);
755
756 set_devadd(r8a66597, dev->devnum, dev, 0);
757
758 pipe_buffer_setting(r8a66597, dev, pipe);
759
760 dev->act_len = 0;
761 while (dev->act_len < length && ret == 0) {
762 if (ctrlc())
763 return -1;
764
765 if (usb_pipein(pipe))
766 ret = receive_bulk_packet(r8a66597, dev, pipe, buffer,
Marek Vasutb3935f12019-08-11 13:44:10 +0200767 length);
Marek Vasut5e890c52019-08-11 12:34:38 +0200768 else
769 ret = send_bulk_packet(r8a66597, dev, pipe, buffer,
Marek Vasutb3935f12019-08-11 13:44:10 +0200770 length);
Marek Vasut5e890c52019-08-11 12:34:38 +0200771 }
772
773 if (ret == 0)
774 dev->status = 0;
775
776 return ret;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900777}
778
Simon Glassaad29ae2020-12-03 16:55:21 -0700779static int r8a66597_usb_of_to_plat(struct udevice *dev)
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900780{
Marek Vasut5e890c52019-08-11 12:34:38 +0200781 struct r8a66597 *priv = dev_get_priv(dev);
782 fdt_addr_t addr;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900783
Marek Vasut5e890c52019-08-11 12:34:38 +0200784 addr = dev_read_addr(dev);
785 if (addr == FDT_ADDR_T_NONE)
786 return -EINVAL;
787 priv->reg = addr;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900788
Marek Vasut5e890c52019-08-11 12:34:38 +0200789 return 0;
790}
791
792static int r8a66597_usb_probe(struct udevice *dev)
793{
794 struct r8a66597 *priv = dev_get_priv(dev);
795 struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev);
Marek Vasutc1214092019-08-22 17:53:04 +0200796 int ret;
Marek Vasut5e890c52019-08-11 12:34:38 +0200797
798 bus_priv->desc_before_addr = true;
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900799
Marek Vasutc1214092019-08-22 17:53:04 +0200800 if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
801 ret = device_get_supply_regulator(dev, "vbus-supply",
802 &priv->vbus_supply);
803 if (ret) {
804 dev_err(dev,
805 "can't get VBUS supply\n");
806 return ret;
807 }
808
809 ret = regulator_set_enable(priv->vbus_supply, true);
810 if (ret) {
811 dev_err(dev,
812 "can't enable VBUS supply\n");
813 return ret;
814 }
815 }
816
Marek Vasut5e890c52019-08-11 12:34:38 +0200817 disable_controller(priv);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000818 mdelay(100);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900819
Marek Vasut5e890c52019-08-11 12:34:38 +0200820 enable_controller(priv);
Marek Vasutb3935f12019-08-11 13:44:10 +0200821 r8a66597_port_power(priv, 0, 1);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900822
823 /* check usb device */
Marek Vasut5e890c52019-08-11 12:34:38 +0200824 check_usb_device_connecting(priv);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900825
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000826 mdelay(50);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900827
828 return 0;
829}
830
Marek Vasut5e890c52019-08-11 12:34:38 +0200831static int r8a66597_usb_remove(struct udevice *dev)
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900832{
Marek Vasut5e890c52019-08-11 12:34:38 +0200833 struct r8a66597 *priv = dev_get_priv(dev);
Marek Vasutc1214092019-08-22 17:53:04 +0200834 int ret;
Marek Vasut5e890c52019-08-11 12:34:38 +0200835
836 disable_controller(priv);
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900837
Marek Vasutc1214092019-08-22 17:53:04 +0200838 if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
839 ret = regulator_set_enable(priv->vbus_supply, false);
840 if (ret) {
841 dev_err(dev,
842 "can't disable VBUS supply\n");
843 return ret;
844 }
845 }
846
Yoshihiro Shimodaf66d9982008-07-09 21:07:38 +0900847 return 0;
848}
Marek Vasut5e890c52019-08-11 12:34:38 +0200849
850struct dm_usb_ops r8a66597_usb_ops = {
851 .control = r8a66597_submit_control_msg,
852 .bulk = r8a66597_submit_bulk_msg,
853};
854
855static const struct udevice_id r8a66597_usb_ids[] = {
856 { .compatible = "renesas,rza1-usbhs" },
857 { }
858};
859
860U_BOOT_DRIVER(usb_r8a66597) = {
861 .name = "r8a66597_usb",
862 .id = UCLASS_USB,
863 .of_match = r8a66597_usb_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700864 .of_to_plat = r8a66597_usb_of_to_plat,
Marek Vasut5e890c52019-08-11 12:34:38 +0200865 .probe = r8a66597_usb_probe,
866 .remove = r8a66597_usb_remove,
867 .ops = &r8a66597_usb_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700868 .priv_auto = sizeof(struct r8a66597),
Marek Vasut5e890c52019-08-11 12:34:38 +0200869 .flags = DM_FLAG_ALLOC_PRIV_DMA,
870};