blob: 5a3f2a6e896f8e39939047178f17d28d68b80599 [file] [log] [blame]
Yinghai Lud57241f2007-02-28 11:17:02 +00001/*
Stefan Reinauerbb01f602009-07-21 21:20:45 +00002 * This file is part of the coreboot project.
3 *
Stefan Reinauerbb01f602009-07-21 21:20:45 +00004 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
Yinghai Lud57241f2007-02-28 11:17:02 +00007 *
Stefan Reinauerbb01f602009-07-21 21:20:45 +00008 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
Stefan Reinauerbb01f602009-07-21 21:20:45 +000012 */
Uwe Hermann06694a82010-09-23 18:16:46 +000013
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000014#include <stddef.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000015#include <console/console.h>
Kyösti Mälkkie2227a22014-02-05 13:02:55 +020016#include <console/usb.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000017#include <arch/io.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020018#include <device/mmio.h>
Arthur Heymans4cc9b6c2018-12-28 17:53:36 +010019#include <arch/symbols.h>
Kyösti Mälkkie23c22d2013-07-28 23:16:47 +030020#include <string.h>
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +030021#include <cbmem.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000022
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +020023#include "ehci_debug.h"
Kyösti Mälkkie2227a22014-02-05 13:02:55 +020024#include "usb_ch9.h"
25#include "ehci.h"
Yinghai Lud57241f2007-02-28 11:17:02 +000026
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030027struct ehci_debug_info {
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +020028 u64 ehci_base;
29 u64 ehci_debug;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030030
31 struct dbgp_pipe ep_pipe[DBGP_MAX_ENDPOINTS];
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +020032} __packed;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030033
Julius Wernercd49cce2019-03-05 16:53:33 -080034#if CONFIG(DEBUG_CONSOLE_INIT)
Kyösti Mälkki8c1258a2019-01-10 13:07:42 +020035/* When selected, you can debug the connection of usbdebug dongle.
36 * EHCI port register bits and USB packets are dumped on console,
37 * assuming some other console already works.
38 */
Kyösti Mälkkid7991402013-08-12 16:11:34 +030039# define dprintk(LEVEL, args...) \
40 do { if (!dbgp_enabled()) printk(LEVEL, ##args); } while (0)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000041#else
Elyes HAOUAS2e4d8062016-08-25 20:50:50 +020042# define dprintk(LEVEL, args...) do {} while (0)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000043#endif
44
Yinghai Lud57241f2007-02-28 11:17:02 +000045#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))
Yinghai Lud57241f2007-02-28 11:17:02 +000046
Yinghai Lud57241f2007-02-28 11:17:02 +000047#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
48
Yinghai Lud57241f2007-02-28 11:17:02 +000049#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
50#define HUB_SHORT_RESET_TIME 10
51#define HUB_LONG_RESET_TIME 200
52#define HUB_RESET_TIMEOUT 500
53
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030054#define DBGP_MICROFRAME_TIMEOUT_LOOPS 1000
55#define DBGP_MICROFRAME_RETRIES 10
Yinghai Lud57241f2007-02-28 11:17:02 +000056#define DBGP_MAX_PACKET 8
57
Kyösti Mälkki8c1258a2019-01-10 13:07:42 +020058static int dbgp_enabled(void);
59static void dbgp_print_data(struct ehci_dbg_port *ehci_debug);
60
Arthur Heymans2b778812019-11-20 21:27:33 +010061static struct ehci_debug_info glob_dbg_info;
Patrick Georgi2c2df5b2019-11-29 10:41:40 +010062static struct ehci_debug_info *glob_dbg_info_p;
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +030063
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +030064static inline struct ehci_debug_info *dbgp_ehci_info(void)
65{
Arthur Heymans2b778812019-11-20 21:27:33 +010066 if (glob_dbg_info_p == NULL) {
Kyösti Mälkkif88208e2019-01-31 08:29:32 +020067 struct ehci_debug_info *info;
68 if (ENV_BOOTBLOCK || ENV_VERSTAGE || ENV_ROMSTAGE) {
69 /* The message likely does not show if we hit this. */
70 if (sizeof(*info) > _car_ehci_dbg_info_size)
71 die("BUG: Increase ehci_dbg_info reserve in CAR");
Arthur Heymansdf9cdcf2019-11-09 06:50:20 +010072 info = (void *)_car_ehci_dbg_info;
Kyösti Mälkkif88208e2019-01-31 08:29:32 +020073 } else {
74 info = &glob_dbg_info;
75 }
Arthur Heymans2b778812019-11-20 21:27:33 +010076 glob_dbg_info_p = info;
Kyösti Mälkkif88208e2019-01-31 08:29:32 +020077 }
Arthur Heymans2b778812019-11-20 21:27:33 +010078 return glob_dbg_info_p;
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +030079}
80
Yinghai Lud57241f2007-02-28 11:17:02 +000081static int dbgp_wait_until_complete(struct ehci_dbg_port *ehci_debug)
82{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000083 u32 ctrl;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030084 int loop = 0;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000085
Yinghai Lud57241f2007-02-28 11:17:02 +000086 do {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080087 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +000088 /* Stop when the transaction is finished */
89 if (ctrl & DBGP_DONE)
90 break;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030091 } while (++loop < DBGP_MICROFRAME_TIMEOUT_LOOPS);
Yinghai Lud57241f2007-02-28 11:17:02 +000092
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030093 if (! (ctrl & DBGP_DONE)) {
94 dprintk(BIOS_ERR, "dbgp_wait_until_complete: retry timeout.\n");
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030095 return -DBGP_ERR_SIGNAL;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030096 }
Yinghai Lud57241f2007-02-28 11:17:02 +000097
98 /* Now that we have observed the completed transaction,
99 * clear the done bit.
100 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800101 write32(&ehci_debug->control, ctrl | DBGP_DONE);
Yinghai Lud57241f2007-02-28 11:17:02 +0000102 return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
103}
104
Yinghai Lud57241f2007-02-28 11:17:02 +0000105static void dbgp_breath(void)
106{
107 /* Sleep to give the debug port a chance to breathe */
108}
109
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300110static int dbgp_wait_until_done(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
Martin Roth38ddbfb2019-10-23 21:41:00 -0600111 unsigned int ctrl, const int timeout)
Yinghai Lud57241f2007-02-28 11:17:02 +0000112{
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300113 u32 rd_ctrl, rd_pids;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300114 u32 ctrl_prev = 0, pids_prev = 0;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300115 u8 lpid;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300116 int ret, host_retries;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300117 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000118
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300119 loop = 0;
120device_retry:
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300121 host_retries = 0;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300122 if (loop++ >= timeout)
123 return -DBGP_ERR_BAD;
124
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300125host_retry:
126 if (host_retries++ >= DBGP_MICROFRAME_RETRIES)
127 return -DBGP_ERR_BAD;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300128 if (loop == 1 || host_retries > 1)
129 dprintk(BIOS_SPEW, "dbgp: start (@ %3d,%d) ctrl=%08x\n",
130 loop, host_retries, ctrl | DBGP_GO);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800131 write32(&ehci_debug->control, ctrl | DBGP_GO);
Yinghai Lud57241f2007-02-28 11:17:02 +0000132 ret = dbgp_wait_until_complete(ehci_debug);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800133 rd_ctrl = read32(&ehci_debug->control);
134 rd_pids = read32(&ehci_debug->pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000135
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300136 if (rd_ctrl != ctrl_prev || rd_pids != pids_prev || (ret<0)) {
137 ctrl_prev = rd_ctrl;
138 pids_prev = rd_pids;
139 dprintk(BIOS_SPEW, "dbgp: status (@ %3d,%d) ctrl=%08x pids=%08x ret=%d\n",
140 loop, host_retries, rd_ctrl, rd_pids, ret);
141 }
142
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300143 /* Controller hardware failure. */
144 if (ret == -DBGP_ERR_SIGNAL) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000145 return ret;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300146
147 /* Bus failure (corrupted microframe). */
148 } else if (ret == -DBGP_ERR_BAD) {
149 goto host_retry;
Sven Schnelle10680872012-07-25 14:19:45 +0200150 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000151
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300152 lpid = DBGP_PID_GET(rd_pids);
153
154 /* If I get an ACK or in-sync DATA PID, we are done. */
155 if ((lpid == USB_PID_ACK) || (lpid == pipe->pid)) {
Kyösti Mälkki48e899d2014-01-21 10:44:08 +0200156 pipe->pid ^= USB_PID_DATA_TOGGLE;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300157 }
158
Yinghai Lud57241f2007-02-28 11:17:02 +0000159 /* If the port is getting full or it has dropped data
160 * start pacing ourselves, not necessary but it's friendly.
161 */
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300162 else if (lpid == USB_PID_NYET) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000163 dbgp_breath();
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300164 goto device_retry;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300165 }
166
167 /* If I get a NACK or out-of-sync DATA PID, reissue the transmission. */
168 else if ((lpid == USB_PID_NAK) || (lpid == (pipe->pid ^ USB_PID_DATA_TOGGLE))) {
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300169 goto device_retry;
Yinghai Lud57241f2007-02-28 11:17:02 +0000170 }
171
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300172 /* Abort on STALL handshake for endpoint 0.*/
173 else if ((lpid == USB_PID_STALL) && (pipe->endpoint == 0x0)) {
174 ret = -DBGP_ERR_BAD;
175 }
176
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300177 dbgp_print_data(ehci_debug);
178
Yinghai Lud57241f2007-02-28 11:17:02 +0000179 return ret;
180}
181
182static void dbgp_set_data(struct ehci_dbg_port *ehci_debug, const void *buf, int size)
183{
184 const unsigned char *bytes = buf;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000185 u32 lo, hi;
Yinghai Lud57241f2007-02-28 11:17:02 +0000186 int i;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000187
Yinghai Lud57241f2007-02-28 11:17:02 +0000188 lo = hi = 0;
189 for (i = 0; i < 4 && i < size; i++)
190 lo |= bytes[i] << (8*i);
191 for (; i < 8 && i < size; i++)
192 hi |= bytes[i] << (8*(i - 4));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800193 write32(&ehci_debug->data03, lo);
194 write32(&ehci_debug->data47, hi);
Yinghai Lud57241f2007-02-28 11:17:02 +0000195}
196
197static void dbgp_get_data(struct ehci_dbg_port *ehci_debug, void *buf, int size)
198{
199 unsigned char *bytes = buf;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000200 u32 lo, hi;
Yinghai Lud57241f2007-02-28 11:17:02 +0000201 int i;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000202
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800203 lo = read32(&ehci_debug->data03);
204 hi = read32(&ehci_debug->data47);
Yinghai Lud57241f2007-02-28 11:17:02 +0000205 for (i = 0; i < 4 && i < size; i++)
206 bytes[i] = (lo >> (8*i)) & 0xff;
207 for (; i < 8 && i < size; i++)
208 bytes[i] = (hi >> (8*(i - 4))) & 0xff;
209}
210
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300211static void dbgp_print_data(struct ehci_dbg_port *ehci_debug)
212{
Kyösti Mälkki8c1258a2019-01-10 13:07:42 +0200213 int len;
214 u32 ctrl, lo, hi;
215
Julius Wernercd49cce2019-03-05 16:53:33 -0800216 if (!CONFIG(DEBUG_CONSOLE_INIT) || dbgp_enabled())
Kyösti Mälkki8c1258a2019-01-10 13:07:42 +0200217 return;
218
219 ctrl = read32(&ehci_debug->control);
220 lo = read32(&ehci_debug->data03);
221 hi = read32(&ehci_debug->data47);
222
223 len = DBGP_LEN(ctrl);
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300224 if (len) {
225 int i;
226 dprintk(BIOS_SPEW, "dbgp: buf:");
227 for (i = 0; i < 4 && i < len; i++)
228 dprintk(BIOS_SPEW, " %02x", (lo >> (8*i)) & 0xff);
229 for (; i < 8 && i < len; i++)
230 dprintk(BIOS_SPEW, " %02x", (hi >> (8*(i - 4))) & 0xff);
231 dprintk(BIOS_SPEW, "\n");
232 }
233}
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300234
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300235static int dbgp_bulk_write(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
236 const char *bytes, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000237{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000238 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000239 int ret;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000240
Yinghai Lud57241f2007-02-28 11:17:02 +0000241 if (size > DBGP_MAX_PACKET)
242 return -1;
243
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300244 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300245 pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000246
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800247 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000248 ctrl = DBGP_LEN_UPDATE(ctrl, size);
249 ctrl |= DBGP_OUT;
Yinghai Lud57241f2007-02-28 11:17:02 +0000250
251 dbgp_set_data(ehci_debug, bytes, size);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800252 write32(&ehci_debug->address, addr);
253 write32(&ehci_debug->pids, pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000254
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300255 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000256
Yinghai Lud57241f2007-02-28 11:17:02 +0000257 return ret;
258}
259
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300260int dbgp_bulk_write_x(struct dbgp_pipe *pipe, const char *bytes, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000261{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300262 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200263 struct ehci_dbg_port *port;
264 port = (void *)(uintptr_t)dbg_info->ehci_debug;
265 return dbgp_bulk_write(port, pipe, bytes, size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000266}
267
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300268static int dbgp_bulk_read(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300269 void *data, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000270{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000271 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000272 int ret;
273
274 if (size > DBGP_MAX_PACKET)
275 return -1;
276
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300277 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300278 pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000279
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800280 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000281 ctrl = DBGP_LEN_UPDATE(ctrl, size);
282 ctrl &= ~DBGP_OUT;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000283
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800284 write32(&ehci_debug->address, addr);
285 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300286 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Yinghai Lud57241f2007-02-28 11:17:02 +0000287 if (ret < 0)
288 return ret;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000289
Yinghai Lud57241f2007-02-28 11:17:02 +0000290 if (size > ret)
291 size = ret;
292 dbgp_get_data(ehci_debug, data, size);
293 return ret;
294}
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000295
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300296int dbgp_bulk_read_x(struct dbgp_pipe *pipe, void *data, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000297{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300298 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200299 struct ehci_dbg_port *port;
300 port = (void *)(uintptr_t)dbg_info->ehci_debug;
301 return dbgp_bulk_read(port, pipe, data, size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000302}
303
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200304void dbgp_mdelay(int ms)
Yinghai Lud57241f2007-02-28 11:17:02 +0000305{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000306 int i;
307
308 while (ms--) {
309 for (i = 0; i < 1000; i++)
310 inb(0x80);
311 }
312}
313
Martin Roth38ddbfb2019-10-23 21:41:00 -0600314int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned int devnum, int requesttype,
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000315 int request, int value, int index, void *data, int size)
316{
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300317 struct ehci_debug_info *info = dbgp_ehci_info();
318 struct dbgp_pipe *pipe = &info->ep_pipe[DBGP_SETUP_EP0];
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000319 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000320 struct usb_ctrlrequest req;
321 int read;
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300322 int ret, ret2;
Yinghai Lud57241f2007-02-28 11:17:02 +0000323
324 read = (requesttype & USB_DIR_IN) != 0;
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300325 if (size > DBGP_MAX_PACKET)
Yinghai Lud57241f2007-02-28 11:17:02 +0000326 return -1;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000327
Yinghai Lud57241f2007-02-28 11:17:02 +0000328 /* Compute the control message */
329 req.bRequestType = requesttype;
330 req.bRequest = request;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000331 req.wValue = cpu_to_le16(value);
332 req.wIndex = cpu_to_le16(index);
333 req.wLength = cpu_to_le16(size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000334
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300335 pipe->devnum = devnum;
336 pipe->endpoint = 0;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300337 pipe->pid = USB_PID_DATA0;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300338 pipe->timeout = 1000;
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300339 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300340 pids = DBGP_PID_SET(pipe->pid, USB_PID_SETUP);
Yinghai Lud57241f2007-02-28 11:17:02 +0000341
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800342 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000343 ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req));
344 ctrl |= DBGP_OUT;
Yinghai Lud57241f2007-02-28 11:17:02 +0000345
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300346 /* Setup stage */
Yinghai Lud57241f2007-02-28 11:17:02 +0000347 dbgp_set_data(ehci_debug, &req, sizeof(req));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800348 write32(&ehci_debug->address, addr);
349 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300350 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, 1);
Yinghai Lud57241f2007-02-28 11:17:02 +0000351 if (ret < 0)
352 return ret;
353
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300354 /* Data stage (optional) */
355 if (read && size)
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300356 ret = dbgp_bulk_read(ehci_debug, pipe, data, size);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300357 else if (!read && size)
358 ret = dbgp_bulk_write(ehci_debug, pipe, data, size);
359
360 /* Status stage in opposite direction */
361 pipe->pid = USB_PID_DATA1;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800362 ctrl = read32(&ehci_debug->control);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300363 ctrl = DBGP_LEN_UPDATE(ctrl, 0);
364 if (read) {
365 pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
366 ctrl |= DBGP_OUT;
367 } else {
368 pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
369 ctrl &= ~DBGP_OUT;
370 }
371
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800372 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300373 ret2 = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300374 if (ret2 < 0)
375 return ret2;
376
Yinghai Lud57241f2007-02-28 11:17:02 +0000377 return ret;
378}
379
380static int ehci_reset_port(struct ehci_regs *ehci_regs, int port)
381{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000382 u32 portsc;
Yinghai Lud57241f2007-02-28 11:17:02 +0000383 int loop;
384
385 /* Reset the usb debug port */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800386 portsc = read32(&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000387 portsc &= ~PORT_PE;
388 portsc |= PORT_RESET;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800389 write32(&ehci_regs->port_status[port - 1], portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000390
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300391 dbgp_mdelay(HUB_ROOT_RESET_TIME);
Yinghai Lud57241f2007-02-28 11:17:02 +0000392
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800393 portsc = read32(&ehci_regs->port_status[port - 1]);
394 write32(&ehci_regs->port_status[port - 1],
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300395 portsc & ~(PORT_RWC_BITS | PORT_RESET));
396
397 loop = 100;
398 do {
399 dbgp_mdelay(1);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800400 portsc = read32(&ehci_regs->port_status[port - 1]);
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300401 } while ((portsc & PORT_RESET) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000402
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300403 /* Device went away? */
404 if (!(portsc & PORT_CONNECT))
405 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000406
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300407 /* bomb out completely if something weird happened */
408 if ((portsc & PORT_CSC))
409 return -2; //-EINVAL;
Yinghai Lud57241f2007-02-28 11:17:02 +0000410
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300411 /* If we've finished resetting, then break out of the loop */
412 if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
413 return 0;
414
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000415 return -3; //-EBUSY;
Yinghai Lud57241f2007-02-28 11:17:02 +0000416}
417
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000418static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port)
Yinghai Lud57241f2007-02-28 11:17:02 +0000419{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000420 u32 status;
Yinghai Lud57241f2007-02-28 11:17:02 +0000421 int ret, reps;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000422
Yinghai Lud57241f2007-02-28 11:17:02 +0000423 for (reps = 0; reps < 3; reps++) {
424 dbgp_mdelay(100);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800425 status = read32(&ehci_regs->status);
Yinghai Lud57241f2007-02-28 11:17:02 +0000426 if (status & STS_PCD) {
427 ret = ehci_reset_port(ehci_regs, port);
428 if (ret == 0)
429 return 0;
430 }
431 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000432 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000433}
434
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300435
Kyösti Mälkki8101aa62013-08-15 16:27:06 +0300436
Patrick Rudolphae64f222019-11-30 09:42:20 +0100437static int usbdebug_init_(uintptr_t ehci_bar, unsigned int offset, struct ehci_debug_info *info)
Yinghai Lud57241f2007-02-28 11:17:02 +0000438{
439 struct ehci_caps *ehci_caps;
440 struct ehci_regs *ehci_regs;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000441
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000442 u32 cmd, ctrl, status, portsc, hcs_params;
443 u32 debug_port, new_debug_port = 0, n_ports;
Kyösti Mälkki46249be22014-10-27 14:07:28 +0200444 int ret, i;
Yinghai Lud57241f2007-02-28 11:17:02 +0000445 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000446 int port_map_tried;
447 int playtimes = 3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000448
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200449 /* Keep all endpoints disabled before any printk() call. */
450 memset(info, 0, sizeof (*info));
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200451 info->ehci_base = ehci_bar;
452 info->ehci_debug = ehci_bar + offset;
Kyösti Mälkki954ed552019-01-02 08:08:56 +0200453 info->ep_pipe[0].status |= DBGP_EP_NOT_PRESENT;
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200454
Kyösti Mälkki34804572019-12-30 13:09:05 +0200455 dprintk(BIOS_INFO, "ehci_bar: 0x%lx debug_offset 0x%x\n", ehci_bar, offset);
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200456
Yinghai Lud57241f2007-02-28 11:17:02 +0000457 ehci_caps = (struct ehci_caps *)ehci_bar;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700458 ehci_regs = (struct ehci_regs *)(ehci_bar +
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800459 HC_LENGTH(read32(&ehci_caps->hc_capbase)));
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200460
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200461 struct ehci_dbg_port *ehci_debug = (void *)(uintptr_t)info->ehci_debug;
Kyösti Mälkki24100102013-08-12 20:40:37 +0300462
463 if (CONFIG_USBDEBUG_DEFAULT_PORT > 0)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200464 ehci_debug_select_port(CONFIG_USBDEBUG_DEFAULT_PORT);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300465 else
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200466 ehci_debug_select_port(1);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300467
Yinghai Lud57241f2007-02-28 11:17:02 +0000468try_next_time:
469 port_map_tried = 0;
470
471try_next_port:
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800472 hcs_params = read32(&ehci_caps->hcs_params);
Yinghai Lud57241f2007-02-28 11:17:02 +0000473 debug_port = HCS_DEBUG_PORT(hcs_params);
474 n_ports = HCS_N_PORTS(hcs_params);
475
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300476 dprintk(BIOS_INFO, "debug_port: %d\n", debug_port);
477 dprintk(BIOS_INFO, "n_ports: %d\n", n_ports);
Yinghai Lud57241f2007-02-28 11:17:02 +0000478
Martin Rothb9810a42017-07-23 20:00:04 -0600479 for (i = 1; i <= n_ports; i++) {
480 portsc = read32(&ehci_regs->port_status[i-1]);
481 dprintk(BIOS_INFO, "PORTSC #%d: %08x\n", i, portsc);
482 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000483
Elyes HAOUAS2e4d8062016-08-25 20:50:50 +0200484 if (port_map_tried && (new_debug_port != debug_port)) {
485 if (--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200486 ehci_debug_select_port(debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000487 goto try_next_time;
488 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000489 return -1;
Yinghai Lud57241f2007-02-28 11:17:02 +0000490 }
491
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300492 /* Wait until the controller is halted */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800493 status = read32(&ehci_regs->status);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300494 if (!(status & STS_HALT)) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800495 cmd = read32(&ehci_regs->command);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300496 cmd &= ~CMD_RUN;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800497 write32(&ehci_regs->command, cmd);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300498 loop = 100;
499 do {
500 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800501 status = read32(&ehci_regs->status);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300502 } while (!(status & STS_HALT) && (--loop > 0));
503 if (status & STS_HALT)
504 dprintk(BIOS_INFO, "EHCI controller halted successfully.\n");
505 else
506 dprintk(BIOS_INFO, "EHCI controller is not halted. Reset may fail.\n");
507 }
508
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000509 loop = 100;
Yinghai Lud57241f2007-02-28 11:17:02 +0000510 /* Reset the EHCI controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800511 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000512 cmd |= CMD_RESET;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800513 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000514 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000515 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800516 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000517 } while ((cmd & CMD_RESET) && (--loop > 0));
518
Elyes HAOUAS2e4d8062016-08-25 20:50:50 +0200519 if (!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300520 dprintk(BIOS_INFO, "Could not reset EHCI controller.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000521 // on some systems it works without succeeding here.
522 // return -2;
523 } else {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300524 dprintk(BIOS_INFO, "EHCI controller reset successfully.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000525 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000526
527 /* Claim ownership, but do not enable yet */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800528 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000529 ctrl |= DBGP_OWNER;
530 ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800531 write32(&ehci_debug->control, ctrl);
Yinghai Lud57241f2007-02-28 11:17:02 +0000532
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000533 /* Start EHCI controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800534 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000535 cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
536 cmd |= CMD_RUN;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800537 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000538
539 /* Ensure everything is routed to the EHCI */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800540 write32(&ehci_regs->configured_flag, FLAG_CF);
Yinghai Lud57241f2007-02-28 11:17:02 +0000541
542 /* Wait until the controller is no longer halted */
543 loop = 10;
544 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000545 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800546 status = read32(&ehci_regs->status);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000547 } while ((status & STS_HALT) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000548
Elyes HAOUAS2e4d8062016-08-25 20:50:50 +0200549 if (!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300550 dprintk(BIOS_INFO, "EHCI could not be started.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000551 return -3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000552 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300553 dprintk(BIOS_INFO, "EHCI started.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000554
555 /* Wait for a device to show up in the debug port */
556 ret = ehci_wait_for_port(ehci_regs, debug_port);
557 if (ret < 0) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300558 dprintk(BIOS_INFO, "No device found in debug port %d\n", debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000559 goto next_debug_port;
560 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300561 dprintk(BIOS_INFO, "EHCI done waiting for port.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000562
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200563
Yinghai Lud57241f2007-02-28 11:17:02 +0000564 /* Enable the debug port */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800565 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000566 ctrl |= DBGP_CLAIM;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800567 write32(&ehci_debug->control, ctrl);
568 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000569 if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300570 dprintk(BIOS_INFO, "No device in EHCI debug port.\n");
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800571 write32(&ehci_debug->control, ctrl & ~DBGP_CLAIM);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000572 ret = -4;
Yinghai Lud57241f2007-02-28 11:17:02 +0000573 goto err;
574 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300575 dprintk(BIOS_INFO, "EHCI debug port enabled.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000576
Kyösti Mälkki9e999d62013-06-06 10:33:39 +0300577#if 0
Yinghai Lud57241f2007-02-28 11:17:02 +0000578 /* Completely transfer the debug device to the debug controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800579 portsc = read32(&ehci_regs->port_status[debug_port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000580 portsc &= ~PORT_PE;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800581 write32(&ehci_regs->port_status[debug_port - 1], portsc);
Kyösti Mälkki9e999d62013-06-06 10:33:39 +0300582#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000583
584 dbgp_mdelay(100);
585
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200586 struct ehci_dbg_port *port = (void *)(uintptr_t)info->ehci_debug;
587 ret = dbgp_probe_gadget(port, &info->ep_pipe[0]);
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300588 if (ret < 0) {
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200589 dprintk(BIOS_INFO, "Could not probe gadget on debug port.\n");
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300590 ret = -6;
591 goto err;
592 }
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300593
Kyösti Mälkki954ed552019-01-02 08:08:56 +0200594 info->ep_pipe[0].status &= ~DBGP_EP_NOT_PRESENT;
595
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000596 return 0;
Yinghai Lud57241f2007-02-28 11:17:02 +0000597err:
598 /* Things didn't work so remove my claim */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800599 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000600 ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800601 write32(&ehci_debug->control, ctrl);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000602 //return ret;
Yinghai Lud57241f2007-02-28 11:17:02 +0000603
604next_debug_port:
Martin Roth32c27c22017-06-24 14:07:25 -0600605#if CONFIG_USBDEBUG_DEFAULT_PORT == 0
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000606 port_map_tried |= (1 << (debug_port - 1));
607 new_debug_port = ((debug_port-1 + 1) % n_ports) + 1;
608 if (port_map_tried != ((1 << n_ports) - 1)) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200609 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000610 goto try_next_port;
611 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000612 if (--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200613 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000614 goto try_next_time;
615 }
Kyösti Mälkki24100102013-08-12 20:40:37 +0300616#else
617 if (0)
618 goto try_next_port;
619 if (--playtimes)
620 goto try_next_time;
621#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000622
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000623 return -10;
624}
625
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300626static int dbgp_enabled(void)
627{
628 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
629 return (globals->status & DBGP_EP_ENABLED);
630}
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300631
Kyösti Mälkki954ed552019-01-02 08:08:56 +0200632static int dbgp_not_present(void)
633{
634 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
635 return (globals->status & DBGP_EP_NOT_PRESENT);
636}
637
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200638int dbgp_try_get(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300639{
640 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
641 if (!dbgp_ep_is_active(pipe) || (globals->status & DBGP_EP_BUSY))
642 return 0;
643 globals->status |= DBGP_EP_BUSY;
644 pipe->status |= DBGP_EP_BUSY;
645 return 1;
646}
647
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200648void dbgp_put(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300649{
650 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
651 globals->status &= ~DBGP_EP_BUSY;
652 pipe->status &= ~DBGP_EP_BUSY;
653}
654
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300655#if ENV_RAMSTAGE
Patrick Rudolphae64f222019-11-30 09:42:20 +0100656void usbdebug_re_enable(uintptr_t ehci_base)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300657{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300658 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200659 u64 diff;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300660 int i;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300661
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200662 diff = dbg_info->ehci_base - ehci_base;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300663 dbg_info->ehci_debug -= diff;
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200664 dbg_info->ehci_base = ehci_base;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300665
666 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200667 if (dbg_info->ep_pipe[i].status & DBGP_EP_VALID)
668 dbg_info->ep_pipe[i].status |= DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300669}
670
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200671void usbdebug_disable(void)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300672{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300673 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300674 int i;
675 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
676 dbg_info->ep_pipe[i].status &= ~DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300677}
678
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300679#endif
680
Kyösti Mälkki63649d22018-12-29 09:40:40 +0200681int usbdebug_hw_init(bool force)
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300682{
683 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki45ad4f02019-01-31 19:24:04 +0200684 u32 ehci_base, dbg_offset;
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300685
Kyösti Mälkki63649d22018-12-29 09:40:40 +0200686 if (dbgp_enabled() && !force)
687 return 0;
688
Kyösti Mälkki954ed552019-01-02 08:08:56 +0200689 if (dbgp_not_present() && !force)
690 return -1;
691
Kyösti Mälkki63649d22018-12-29 09:40:40 +0200692 /* Do not attempt slow gadget init in postcar. */
693 if (ENV_POSTCAR)
694 return -1;
695
696 /* Do full init if state claims we are still not enabled. */
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300697 if (ehci_debug_hw_enable(&ehci_base, &dbg_offset))
698 return -1;
699 return usbdebug_init_(ehci_base, dbg_offset, dbg_info);
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300700}
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300701
702static void migrate_ehci_debug(int is_recovery)
703{
704 struct ehci_debug_info *dbg_info_cbmem;
705 int rv;
706
707 if (ENV_ROMSTAGE) {
708 /* Move state from CAR to CBMEM. */
709 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
710 dbg_info_cbmem = cbmem_add(CBMEM_ID_EHCI_DEBUG,
711 sizeof(*dbg_info));
712 if (dbg_info_cbmem == NULL)
713 return;
714 memcpy(dbg_info_cbmem, dbg_info, sizeof(*dbg_info));
Arthur Heymans2b778812019-11-20 21:27:33 +0100715 glob_dbg_info_p = dbg_info_cbmem;
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300716 return;
717 }
718
Julius Wernercd49cce2019-03-05 16:53:33 -0800719 if (CONFIG(USBDEBUG_IN_PRE_RAM)) {
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300720 /* Use state in CBMEM. */
721 dbg_info_cbmem = cbmem_find(CBMEM_ID_EHCI_DEBUG);
722 if (dbg_info_cbmem)
Arthur Heymans2b778812019-11-20 21:27:33 +0100723 glob_dbg_info_p = dbg_info_cbmem;
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300724 }
725
Kyösti Mälkki63649d22018-12-29 09:40:40 +0200726 rv = usbdebug_hw_init(false);
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300727 if (rv < 0)
728 printk(BIOS_DEBUG, "usbdebug: Failed hardware init\n");
729 else
730 printk(BIOS_DEBUG, "usbdebug: " ENV_STRING " starting...\n");
731}
732
Kyösti Mälkki4fbac462015-01-07 04:48:43 +0200733ROMSTAGE_CBMEM_INIT_HOOK(migrate_ehci_debug);
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300734POSTCAR_CBMEM_INIT_HOOK(migrate_ehci_debug);
735RAMSTAGE_CBMEM_INIT_HOOK(migrate_ehci_debug);
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300736
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300737int dbgp_ep_is_active(struct dbgp_pipe *pipe)
Kyösti Mälkki4d409b52013-07-05 21:38:54 +0300738{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300739 return (pipe->status & DBGP_EP_STATMASK) == (DBGP_EP_VALID | DBGP_EP_ENABLED);
Yinghai Lud57241f2007-02-28 11:17:02 +0000740}
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300741
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300742struct dbgp_pipe *dbgp_console_output(void)
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300743{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300744 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPOUT];
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300745}
746
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300747struct dbgp_pipe *dbgp_console_input(void)
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300748{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300749 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPIN];
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300750}
751
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300752void usbdebug_init(void)
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300753{
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300754 /* USB console init is done early in romstage, yet delayed to
755 * CBMEM_INIT_HOOKs for postcar and ramstage as we recover state
756 * from CBMEM.
757 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800758 if (CONFIG(USBDEBUG_IN_PRE_RAM)
Arthur Heymansadc47532018-12-28 15:48:58 +0100759 && (ENV_ROMSTAGE || ENV_BOOTBLOCK))
Kyösti Mälkki63649d22018-12-29 09:40:40 +0200760 usbdebug_hw_init(false);
Kyösti Mälkki8ee04d72013-07-06 11:41:09 +0300761
Kyösti Mälkkid07f3772017-09-07 19:16:27 +0300762 /* USB console init is done early in ramstage if it was
763 * not done in romstage, this does not require CBMEM.
764 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800765 if (!CONFIG(USBDEBUG_IN_PRE_RAM) && ENV_RAMSTAGE)
Kyösti Mälkki63649d22018-12-29 09:40:40 +0200766 usbdebug_hw_init(false);
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300767}