blob: 379a1bdebee37b1f88e674fbaa8ca27e3c08fd84 [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 *
Yinghai Lud57241f2007-02-28 11:17:02 +00004 * Copyright (C) 2006 Eric Biederman (ebiederm@xmission.com)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +00005 * Copyright (C) 2007 AMD
Yinghai Lud57241f2007-02-28 11:17:02 +00006 *
Stefan Reinauerbb01f602009-07-21 21:20:45 +00007 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
Yinghai Lud57241f2007-02-28 11:17:02 +000010 *
Stefan Reinauerbb01f602009-07-21 21:20:45 +000011 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
19 */
Uwe Hermann06694a82010-09-23 18:16:46 +000020
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000021#include <stddef.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000022#include <console/console.h>
Kyösti Mälkkie2227a22014-02-05 13:02:55 +020023#include <console/usb.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000024#include <arch/io.h>
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000025#include <arch/byteorder.h>
Stefan Reinauerfd4f4132013-06-19 12:25:44 -070026#include <arch/early_variables.h>
Kyösti Mälkkie23c22d2013-07-28 23:16:47 +030027#include <string.h>
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +030028#include <cbmem.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000029
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +020030#include "ehci_debug.h"
Kyösti Mälkkie2227a22014-02-05 13:02:55 +020031#include "usb_ch9.h"
32#include "ehci.h"
Yinghai Lud57241f2007-02-28 11:17:02 +000033
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030034struct ehci_debug_info {
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +020035 void *ehci_base;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030036 void *ehci_debug;
37
38 struct dbgp_pipe ep_pipe[DBGP_MAX_ENDPOINTS];
39};
40
Kyösti Mälkki3be80cc2013-06-06 10:46:37 +030041#if CONFIG_DEBUG_USBDEBUG
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030042static void dbgp_print_data(struct ehci_dbg_port *ehci_debug);
Kyösti Mälkkid7991402013-08-12 16:11:34 +030043static int dbgp_enabled(void);
44# define dprintk(LEVEL, args...) \
45 do { if (!dbgp_enabled()) printk(LEVEL, ##args); } while (0)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000046#else
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030047# define dbgp_print_data(x) do {} while(0)
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +030048# define dprintk(LEVEL, args...) do {} while(0)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000049#endif
50
Yinghai Lud57241f2007-02-28 11:17:02 +000051#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))
Yinghai Lud57241f2007-02-28 11:17:02 +000052
Yinghai Lud57241f2007-02-28 11:17:02 +000053#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
54
Yinghai Lud57241f2007-02-28 11:17:02 +000055#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
56#define HUB_SHORT_RESET_TIME 10
57#define HUB_LONG_RESET_TIME 200
58#define HUB_RESET_TIMEOUT 500
59
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030060#define DBGP_MICROFRAME_TIMEOUT_LOOPS 1000
61#define DBGP_MICROFRAME_RETRIES 10
Yinghai Lud57241f2007-02-28 11:17:02 +000062#define DBGP_MAX_PACKET 8
63
Kyösti Mälkki8ee04d72013-07-06 11:41:09 +030064static struct ehci_debug_info glob_dbg_info CAR_GLOBAL;
Kyösti Mälkki618d1792014-10-27 08:01:55 +020065static struct ehci_debug_info * glob_dbg_info_p CAR_GLOBAL;
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +030066
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +030067static inline struct ehci_debug_info *dbgp_ehci_info(void)
68{
Kyösti Mälkki618d1792014-10-27 08:01:55 +020069 if (car_get_var(glob_dbg_info_p) == NULL)
70 car_set_var(glob_dbg_info_p, &glob_dbg_info);
71
72 return car_get_var(glob_dbg_info_p);
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +030073}
74
Yinghai Lud57241f2007-02-28 11:17:02 +000075static int dbgp_wait_until_complete(struct ehci_dbg_port *ehci_debug)
76{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000077 u32 ctrl;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030078 int loop = 0;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000079
Yinghai Lud57241f2007-02-28 11:17:02 +000080 do {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080081 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +000082 /* Stop when the transaction is finished */
83 if (ctrl & DBGP_DONE)
84 break;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030085 } while (++loop < DBGP_MICROFRAME_TIMEOUT_LOOPS);
Yinghai Lud57241f2007-02-28 11:17:02 +000086
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030087 if (! (ctrl & DBGP_DONE)) {
88 dprintk(BIOS_ERR, "dbgp_wait_until_complete: retry timeout.\n");
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030089 return -DBGP_ERR_SIGNAL;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030090 }
Yinghai Lud57241f2007-02-28 11:17:02 +000091
92 /* Now that we have observed the completed transaction,
93 * clear the done bit.
94 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080095 write32(&ehci_debug->control, ctrl | DBGP_DONE);
Yinghai Lud57241f2007-02-28 11:17:02 +000096 return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
97}
98
Yinghai Lud57241f2007-02-28 11:17:02 +000099static void dbgp_breath(void)
100{
101 /* Sleep to give the debug port a chance to breathe */
102}
103
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300104static int dbgp_wait_until_done(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300105 unsigned ctrl, const int timeout)
Yinghai Lud57241f2007-02-28 11:17:02 +0000106{
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300107 u32 rd_ctrl, rd_pids;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300108 u32 ctrl_prev = 0, pids_prev = 0;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300109 u8 lpid;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300110 int ret, host_retries;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300111 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000112
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300113 loop = 0;
114device_retry:
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300115 host_retries = 0;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300116 if (loop++ >= timeout)
117 return -DBGP_ERR_BAD;
118
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300119host_retry:
120 if (host_retries++ >= DBGP_MICROFRAME_RETRIES)
121 return -DBGP_ERR_BAD;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300122 if (loop == 1 || host_retries > 1)
123 dprintk(BIOS_SPEW, "dbgp: start (@ %3d,%d) ctrl=%08x\n",
124 loop, host_retries, ctrl | DBGP_GO);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800125 write32(&ehci_debug->control, ctrl | DBGP_GO);
Yinghai Lud57241f2007-02-28 11:17:02 +0000126 ret = dbgp_wait_until_complete(ehci_debug);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800127 rd_ctrl = read32(&ehci_debug->control);
128 rd_pids = read32(&ehci_debug->pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000129
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300130 if (rd_ctrl != ctrl_prev || rd_pids != pids_prev || (ret<0)) {
131 ctrl_prev = rd_ctrl;
132 pids_prev = rd_pids;
133 dprintk(BIOS_SPEW, "dbgp: status (@ %3d,%d) ctrl=%08x pids=%08x ret=%d\n",
134 loop, host_retries, rd_ctrl, rd_pids, ret);
135 }
136
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300137 /* Controller hardware failure. */
138 if (ret == -DBGP_ERR_SIGNAL) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000139 return ret;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300140
141 /* Bus failure (corrupted microframe). */
142 } else if (ret == -DBGP_ERR_BAD) {
143 goto host_retry;
Sven Schnelle10680872012-07-25 14:19:45 +0200144 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000145
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300146 lpid = DBGP_PID_GET(rd_pids);
147
148 /* If I get an ACK or in-sync DATA PID, we are done. */
149 if ((lpid == USB_PID_ACK) || (lpid == pipe->pid)) {
Kyösti Mälkki48e899d2014-01-21 10:44:08 +0200150 pipe->pid ^= USB_PID_DATA_TOGGLE;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300151 }
152
Yinghai Lud57241f2007-02-28 11:17:02 +0000153 /* If the port is getting full or it has dropped data
154 * start pacing ourselves, not necessary but it's friendly.
155 */
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300156 else if (lpid == USB_PID_NYET) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000157 dbgp_breath();
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300158 goto device_retry;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300159 }
160
161 /* If I get a NACK or out-of-sync DATA PID, reissue the transmission. */
162 else if ((lpid == USB_PID_NAK) || (lpid == (pipe->pid ^ USB_PID_DATA_TOGGLE))) {
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300163 goto device_retry;
Yinghai Lud57241f2007-02-28 11:17:02 +0000164 }
165
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300166 /* Abort on STALL handshake for endpoint 0.*/
167 else if ((lpid == USB_PID_STALL) && (pipe->endpoint == 0x0)) {
168 ret = -DBGP_ERR_BAD;
169 }
170
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300171 dbgp_print_data(ehci_debug);
172
Yinghai Lud57241f2007-02-28 11:17:02 +0000173 return ret;
174}
175
176static void dbgp_set_data(struct ehci_dbg_port *ehci_debug, const void *buf, int size)
177{
178 const unsigned char *bytes = buf;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000179 u32 lo, hi;
Yinghai Lud57241f2007-02-28 11:17:02 +0000180 int i;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000181
Yinghai Lud57241f2007-02-28 11:17:02 +0000182 lo = hi = 0;
183 for (i = 0; i < 4 && i < size; i++)
184 lo |= bytes[i] << (8*i);
185 for (; i < 8 && i < size; i++)
186 hi |= bytes[i] << (8*(i - 4));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800187 write32(&ehci_debug->data03, lo);
188 write32(&ehci_debug->data47, hi);
Yinghai Lud57241f2007-02-28 11:17:02 +0000189}
190
191static void dbgp_get_data(struct ehci_dbg_port *ehci_debug, void *buf, int size)
192{
193 unsigned char *bytes = buf;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000194 u32 lo, hi;
Yinghai Lud57241f2007-02-28 11:17:02 +0000195 int i;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000196
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800197 lo = read32(&ehci_debug->data03);
198 hi = read32(&ehci_debug->data47);
Yinghai Lud57241f2007-02-28 11:17:02 +0000199 for (i = 0; i < 4 && i < size; i++)
200 bytes[i] = (lo >> (8*i)) & 0xff;
201 for (; i < 8 && i < size; i++)
202 bytes[i] = (hi >> (8*(i - 4))) & 0xff;
203}
204
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300205#if CONFIG_DEBUG_USBDEBUG
206static void dbgp_print_data(struct ehci_dbg_port *ehci_debug)
207{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800208 u32 ctrl = read32(&ehci_debug->control);
209 u32 lo = read32(&ehci_debug->data03);
210 u32 hi = read32(&ehci_debug->data47);
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300211 int len = DBGP_LEN(ctrl);
212 if (len) {
213 int i;
214 dprintk(BIOS_SPEW, "dbgp: buf:");
215 for (i = 0; i < 4 && i < len; i++)
216 dprintk(BIOS_SPEW, " %02x", (lo >> (8*i)) & 0xff);
217 for (; i < 8 && i < len; i++)
218 dprintk(BIOS_SPEW, " %02x", (hi >> (8*(i - 4))) & 0xff);
219 dprintk(BIOS_SPEW, "\n");
220 }
221}
222#endif
223
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300224static int dbgp_bulk_write(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
225 const char *bytes, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000226{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000227 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000228 int ret;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000229
Yinghai Lud57241f2007-02-28 11:17:02 +0000230 if (size > DBGP_MAX_PACKET)
231 return -1;
232
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300233 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300234 pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000235
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800236 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000237 ctrl = DBGP_LEN_UPDATE(ctrl, size);
238 ctrl |= DBGP_OUT;
Yinghai Lud57241f2007-02-28 11:17:02 +0000239
240 dbgp_set_data(ehci_debug, bytes, size);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800241 write32(&ehci_debug->address, addr);
242 write32(&ehci_debug->pids, pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000243
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300244 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000245
Yinghai Lud57241f2007-02-28 11:17:02 +0000246 return ret;
247}
248
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300249int dbgp_bulk_write_x(struct dbgp_pipe *pipe, const char *bytes, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000250{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300251 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300252 return dbgp_bulk_write(dbg_info->ehci_debug, pipe, bytes, size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000253}
254
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300255static int dbgp_bulk_read(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300256 void *data, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000257{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000258 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000259 int ret;
260
261 if (size > DBGP_MAX_PACKET)
262 return -1;
263
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300264 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300265 pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000266
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800267 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000268 ctrl = DBGP_LEN_UPDATE(ctrl, size);
269 ctrl &= ~DBGP_OUT;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000270
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800271 write32(&ehci_debug->address, addr);
272 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300273 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Yinghai Lud57241f2007-02-28 11:17:02 +0000274 if (ret < 0)
275 return ret;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000276
Yinghai Lud57241f2007-02-28 11:17:02 +0000277 if (size > ret)
278 size = ret;
279 dbgp_get_data(ehci_debug, data, size);
280 return ret;
281}
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000282
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300283int dbgp_bulk_read_x(struct dbgp_pipe *pipe, void *data, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000284{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300285 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300286 return dbgp_bulk_read(dbg_info->ehci_debug, pipe, data, size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000287}
288
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200289void dbgp_mdelay(int ms)
Yinghai Lud57241f2007-02-28 11:17:02 +0000290{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000291 int i;
292
293 while (ms--) {
294 for (i = 0; i < 1000; i++)
295 inb(0x80);
296 }
297}
298
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200299int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, int requesttype,
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000300 int request, int value, int index, void *data, int size)
301{
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300302 struct ehci_debug_info *info = dbgp_ehci_info();
303 struct dbgp_pipe *pipe = &info->ep_pipe[DBGP_SETUP_EP0];
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000304 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000305 struct usb_ctrlrequest req;
306 int read;
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300307 int ret, ret2;
Yinghai Lud57241f2007-02-28 11:17:02 +0000308
309 read = (requesttype & USB_DIR_IN) != 0;
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300310 if (size > DBGP_MAX_PACKET)
Yinghai Lud57241f2007-02-28 11:17:02 +0000311 return -1;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000312
Yinghai Lud57241f2007-02-28 11:17:02 +0000313 /* Compute the control message */
314 req.bRequestType = requesttype;
315 req.bRequest = request;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000316 req.wValue = cpu_to_le16(value);
317 req.wIndex = cpu_to_le16(index);
318 req.wLength = cpu_to_le16(size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000319
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300320 pipe->devnum = devnum;
321 pipe->endpoint = 0;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300322 pipe->pid = USB_PID_DATA0;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300323 pipe->timeout = 1000;
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300324 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300325 pids = DBGP_PID_SET(pipe->pid, USB_PID_SETUP);
Yinghai Lud57241f2007-02-28 11:17:02 +0000326
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800327 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000328 ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req));
329 ctrl |= DBGP_OUT;
Yinghai Lud57241f2007-02-28 11:17:02 +0000330
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300331 /* Setup stage */
Yinghai Lud57241f2007-02-28 11:17:02 +0000332 dbgp_set_data(ehci_debug, &req, sizeof(req));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800333 write32(&ehci_debug->address, addr);
334 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300335 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, 1);
Yinghai Lud57241f2007-02-28 11:17:02 +0000336 if (ret < 0)
337 return ret;
338
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300339 /* Data stage (optional) */
340 if (read && size)
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300341 ret = dbgp_bulk_read(ehci_debug, pipe, data, size);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300342 else if (!read && size)
343 ret = dbgp_bulk_write(ehci_debug, pipe, data, size);
344
345 /* Status stage in opposite direction */
346 pipe->pid = USB_PID_DATA1;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800347 ctrl = read32(&ehci_debug->control);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300348 ctrl = DBGP_LEN_UPDATE(ctrl, 0);
349 if (read) {
350 pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
351 ctrl |= DBGP_OUT;
352 } else {
353 pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
354 ctrl &= ~DBGP_OUT;
355 }
356
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800357 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300358 ret2 = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300359 if (ret2 < 0)
360 return ret2;
361
Yinghai Lud57241f2007-02-28 11:17:02 +0000362 return ret;
363}
364
365static int ehci_reset_port(struct ehci_regs *ehci_regs, int port)
366{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000367 u32 portsc;
Yinghai Lud57241f2007-02-28 11:17:02 +0000368 int loop;
369
370 /* Reset the usb debug port */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800371 portsc = read32(&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000372 portsc &= ~PORT_PE;
373 portsc |= PORT_RESET;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800374 write32(&ehci_regs->port_status[port - 1], portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000375
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300376 dbgp_mdelay(HUB_ROOT_RESET_TIME);
Yinghai Lud57241f2007-02-28 11:17:02 +0000377
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800378 portsc = read32(&ehci_regs->port_status[port - 1]);
379 write32(&ehci_regs->port_status[port - 1],
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300380 portsc & ~(PORT_RWC_BITS | PORT_RESET));
381
382 loop = 100;
383 do {
384 dbgp_mdelay(1);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800385 portsc = read32(&ehci_regs->port_status[port - 1]);
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300386 } while ((portsc & PORT_RESET) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000387
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300388 /* Device went away? */
389 if (!(portsc & PORT_CONNECT))
390 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000391
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300392 /* bomb out completely if something weird happened */
393 if ((portsc & PORT_CSC))
394 return -2; //-EINVAL;
Yinghai Lud57241f2007-02-28 11:17:02 +0000395
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300396 /* If we've finished resetting, then break out of the loop */
397 if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
398 return 0;
399
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000400 return -3; //-EBUSY;
Yinghai Lud57241f2007-02-28 11:17:02 +0000401}
402
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000403static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port)
Yinghai Lud57241f2007-02-28 11:17:02 +0000404{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000405 u32 status;
Yinghai Lud57241f2007-02-28 11:17:02 +0000406 int ret, reps;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000407
Yinghai Lud57241f2007-02-28 11:17:02 +0000408 for (reps = 0; reps < 3; reps++) {
409 dbgp_mdelay(100);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800410 status = read32(&ehci_regs->status);
Yinghai Lud57241f2007-02-28 11:17:02 +0000411 if (status & STS_PCD) {
412 ret = ehci_reset_port(ehci_regs, port);
413 if (ret == 0)
414 return 0;
415 }
416 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000417 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000418}
419
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300420
Kyösti Mälkki8101aa62013-08-15 16:27:06 +0300421
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300422static int usbdebug_init_(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info)
Yinghai Lud57241f2007-02-28 11:17:02 +0000423{
424 struct ehci_caps *ehci_caps;
425 struct ehci_regs *ehci_regs;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000426
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000427 u32 cmd, ctrl, status, portsc, hcs_params;
428 u32 debug_port, new_debug_port = 0, n_ports;
Kyösti Mälkki46249be22014-10-27 14:07:28 +0200429 int ret, i;
Yinghai Lud57241f2007-02-28 11:17:02 +0000430 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000431 int port_map_tried;
432 int playtimes = 3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000433
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200434 /* Keep all endpoints disabled before any printk() call. */
435 memset(info, 0, sizeof (*info));
436 info->ehci_base = (void *)ehci_bar;
437 info->ehci_debug = (void *)(ehci_bar + offset);
438
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200439 dprintk(BIOS_INFO, "ehci_bar: 0x%x debug_offset 0x%x\n", ehci_bar, offset);
440
Yinghai Lud57241f2007-02-28 11:17:02 +0000441 ehci_caps = (struct ehci_caps *)ehci_bar;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700442 ehci_regs = (struct ehci_regs *)(ehci_bar +
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800443 HC_LENGTH(read32(&ehci_caps->hc_capbase)));
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200444
445 struct ehci_dbg_port *ehci_debug = info->ehci_debug;
Kyösti Mälkki24100102013-08-12 20:40:37 +0300446
447 if (CONFIG_USBDEBUG_DEFAULT_PORT > 0)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200448 ehci_debug_select_port(CONFIG_USBDEBUG_DEFAULT_PORT);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300449 else
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200450 ehci_debug_select_port(1);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300451
Yinghai Lud57241f2007-02-28 11:17:02 +0000452try_next_time:
453 port_map_tried = 0;
454
455try_next_port:
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800456 hcs_params = read32(&ehci_caps->hcs_params);
Yinghai Lud57241f2007-02-28 11:17:02 +0000457 debug_port = HCS_DEBUG_PORT(hcs_params);
458 n_ports = HCS_N_PORTS(hcs_params);
459
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300460 dprintk(BIOS_INFO, "debug_port: %d\n", debug_port);
461 dprintk(BIOS_INFO, "n_ports: %d\n", n_ports);
Yinghai Lud57241f2007-02-28 11:17:02 +0000462
Yinghai Lud57241f2007-02-28 11:17:02 +0000463 for (i = 1; i <= n_ports; i++) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800464 portsc = read32(&ehci_regs->port_status[i-1]);
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300465 dprintk(BIOS_INFO, "PORTSC #%d: %08x\n", i, portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000466 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000467
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000468 if(port_map_tried && (new_debug_port != debug_port)) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000469 if(--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200470 ehci_debug_select_port(debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000471 goto try_next_time;
472 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000473 return -1;
Yinghai Lud57241f2007-02-28 11:17:02 +0000474 }
475
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300476 /* Wait until the controller is halted */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800477 status = read32(&ehci_regs->status);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300478 if (!(status & STS_HALT)) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800479 cmd = read32(&ehci_regs->command);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300480 cmd &= ~CMD_RUN;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800481 write32(&ehci_regs->command, cmd);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300482 loop = 100;
483 do {
484 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800485 status = read32(&ehci_regs->status);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300486 } while (!(status & STS_HALT) && (--loop > 0));
487 if (status & STS_HALT)
488 dprintk(BIOS_INFO, "EHCI controller halted successfully.\n");
489 else
490 dprintk(BIOS_INFO, "EHCI controller is not halted. Reset may fail.\n");
491 }
492
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000493 loop = 100;
Yinghai Lud57241f2007-02-28 11:17:02 +0000494 /* Reset the EHCI controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800495 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000496 cmd |= CMD_RESET;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800497 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000498 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000499 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800500 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000501 } while ((cmd & CMD_RESET) && (--loop > 0));
502
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000503 if(!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300504 dprintk(BIOS_INFO, "Could not reset EHCI controller.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000505 // on some systems it works without succeeding here.
506 // return -2;
507 } else {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300508 dprintk(BIOS_INFO, "EHCI controller reset successfully.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000509 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000510
511 /* Claim ownership, but do not enable yet */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800512 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000513 ctrl |= DBGP_OWNER;
514 ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800515 write32(&ehci_debug->control, ctrl);
Yinghai Lud57241f2007-02-28 11:17:02 +0000516
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000517 /* Start EHCI controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800518 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000519 cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
520 cmd |= CMD_RUN;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800521 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000522
523 /* Ensure everything is routed to the EHCI */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800524 write32(&ehci_regs->configured_flag, FLAG_CF);
Yinghai Lud57241f2007-02-28 11:17:02 +0000525
526 /* Wait until the controller is no longer halted */
527 loop = 10;
528 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000529 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800530 status = read32(&ehci_regs->status);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000531 } while ((status & STS_HALT) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000532
533 if(!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300534 dprintk(BIOS_INFO, "EHCI could not be started.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000535 return -3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000536 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300537 dprintk(BIOS_INFO, "EHCI started.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000538
539 /* Wait for a device to show up in the debug port */
540 ret = ehci_wait_for_port(ehci_regs, debug_port);
541 if (ret < 0) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300542 dprintk(BIOS_INFO, "No device found in debug port %d\n", debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000543 goto next_debug_port;
544 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300545 dprintk(BIOS_INFO, "EHCI done waiting for port.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000546
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200547
Yinghai Lud57241f2007-02-28 11:17:02 +0000548 /* Enable the debug port */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800549 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000550 ctrl |= DBGP_CLAIM;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800551 write32(&ehci_debug->control, ctrl);
552 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000553 if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300554 dprintk(BIOS_INFO, "No device in EHCI debug port.\n");
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800555 write32(&ehci_debug->control, ctrl & ~DBGP_CLAIM);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000556 ret = -4;
Yinghai Lud57241f2007-02-28 11:17:02 +0000557 goto err;
558 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300559 dprintk(BIOS_INFO, "EHCI debug port enabled.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000560
Kyösti Mälkki9e999d62013-06-06 10:33:39 +0300561#if 0
Yinghai Lud57241f2007-02-28 11:17:02 +0000562 /* Completely transfer the debug device to the debug controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800563 portsc = read32(&ehci_regs->port_status[debug_port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000564 portsc &= ~PORT_PE;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800565 write32(&ehci_regs->port_status[debug_port - 1], portsc);
Kyösti Mälkki9e999d62013-06-06 10:33:39 +0300566#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000567
568 dbgp_mdelay(100);
569
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200570 ret = dbgp_probe_gadget(info->ehci_debug, &info->ep_pipe[0]);
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300571 if (ret < 0) {
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200572 dprintk(BIOS_INFO, "Could not probe gadget on debug port.\n");
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300573 ret = -6;
574 goto err;
575 }
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300576
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000577 return 0;
Yinghai Lud57241f2007-02-28 11:17:02 +0000578err:
579 /* Things didn't work so remove my claim */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800580 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000581 ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800582 write32(&ehci_debug->control, ctrl);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000583 //return ret;
Yinghai Lud57241f2007-02-28 11:17:02 +0000584
585next_debug_port:
Kyösti Mälkki24100102013-08-12 20:40:37 +0300586#if CONFIG_USBDEBUG_DEFAULT_PORT==0
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000587 port_map_tried |= (1 << (debug_port - 1));
588 new_debug_port = ((debug_port-1 + 1) % n_ports) + 1;
589 if (port_map_tried != ((1 << n_ports) - 1)) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200590 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000591 goto try_next_port;
592 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000593 if (--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200594 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000595 goto try_next_time;
596 }
Kyösti Mälkki24100102013-08-12 20:40:37 +0300597#else
598 if (0)
599 goto try_next_port;
600 if (--playtimes)
601 goto try_next_time;
602#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000603
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000604 return -10;
605}
606
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300607#if CONFIG_DEBUG_USBDEBUG
608static int dbgp_enabled(void)
609{
610 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
611 return (globals->status & DBGP_EP_ENABLED);
612}
613#endif
614
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200615int dbgp_try_get(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300616{
617 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
618 if (!dbgp_ep_is_active(pipe) || (globals->status & DBGP_EP_BUSY))
619 return 0;
620 globals->status |= DBGP_EP_BUSY;
621 pipe->status |= DBGP_EP_BUSY;
622 return 1;
623}
624
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200625void dbgp_put(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300626{
627 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
628 globals->status &= ~DBGP_EP_BUSY;
629 pipe->status &= ~DBGP_EP_BUSY;
630}
631
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300632#if !defined(__PRE_RAM__) && !defined(__SMM__)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200633void usbdebug_re_enable(unsigned ehci_base)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300634{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300635 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300636 unsigned diff;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300637 int i;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300638
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200639 diff = (unsigned)dbg_info->ehci_base - ehci_base;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300640 dbg_info->ehci_debug -= diff;
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200641 dbg_info->ehci_base = (void*)ehci_base;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300642
643 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200644 if (dbg_info->ep_pipe[i].status & DBGP_EP_VALID)
645 dbg_info->ep_pipe[i].status |= DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300646}
647
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200648void usbdebug_disable(void)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300649{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300650 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300651 int i;
652 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
653 dbg_info->ep_pipe[i].status &= ~DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300654}
655
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300656#endif
657
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300658#if !defined(__PRE_RAM__) && !defined(__SMM__)
659static int get_usbdebug_from_cbmem(struct ehci_debug_info *info)
660{
661 struct ehci_debug_info *dbg_info_cbmem;
662
663 dbg_info_cbmem = cbmem_find(CBMEM_ID_EHCI_DEBUG);
664 if (dbg_info_cbmem == NULL)
665 return -1;
666
667 memcpy(info, dbg_info_cbmem, sizeof (*info));
668 printk(BIOS_DEBUG, "EHCI debug port found in CBMEM.\n");
669
670 return 0;
671}
672
673#elif defined(__PRE_RAM__)
674static void migrate_ehci_debug(void)
675{
676 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
677 struct ehci_debug_info *dbg_info_cbmem;
678
679 dbg_info_cbmem = cbmem_add(CBMEM_ID_EHCI_DEBUG, sizeof(*dbg_info));
680 if (dbg_info_cbmem == NULL)
681 return;
682
683 memcpy(dbg_info_cbmem, dbg_info, sizeof(*dbg_info));
Kyösti Mälkki618d1792014-10-27 08:01:55 +0200684 car_set_var(glob_dbg_info_p, dbg_info_cbmem);
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300685}
686CAR_MIGRATE(migrate_ehci_debug);
687#endif
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300688
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300689int dbgp_ep_is_active(struct dbgp_pipe *pipe)
Kyösti Mälkki4d409b52013-07-05 21:38:54 +0300690{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300691 return (pipe->status & DBGP_EP_STATMASK) == (DBGP_EP_VALID | DBGP_EP_ENABLED);
Yinghai Lud57241f2007-02-28 11:17:02 +0000692}
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300693
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300694struct dbgp_pipe *dbgp_console_output(void)
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300695{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300696 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPOUT];
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300697}
698
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300699struct dbgp_pipe *dbgp_console_input(void)
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300700{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300701 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPIN];
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300702}
703
704int usbdebug_init(void)
705{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300706 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200707 unsigned int ehci_base, dbg_offset;
Kyösti Mälkki8ee04d72013-07-06 11:41:09 +0300708
Kyösti Mälkkicbf5bdf2013-09-10 00:07:21 +0300709#if !defined(__PRE_RAM__) && !defined(__SMM__)
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300710 if (!get_usbdebug_from_cbmem(dbg_info))
711 return 0;
712#endif
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200713 if (ehci_debug_hw_enable(&ehci_base, &dbg_offset))
714 return -1;
715 return usbdebug_init_(ehci_base, dbg_offset, dbg_info);
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300716}