blob: 5098f97ff592678d0b07f788bb1f1b98515c310f [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
Patrick Georgib890a122015-03-26 15:17:45 +010018 * Foundation, Inc.
Stefan Reinauerbb01f602009-07-21 21:20:45 +000019 */
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 Reinauerfd4f4132013-06-19 12:25:44 -070025#include <arch/early_variables.h>
Kyösti Mälkkie23c22d2013-07-28 23:16:47 +030026#include <string.h>
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +030027#include <cbmem.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000028
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +020029#include "ehci_debug.h"
Kyösti Mälkkie2227a22014-02-05 13:02:55 +020030#include "usb_ch9.h"
31#include "ehci.h"
Yinghai Lud57241f2007-02-28 11:17:02 +000032
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030033struct ehci_debug_info {
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +020034 void *ehci_base;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030035 void *ehci_debug;
36
37 struct dbgp_pipe ep_pipe[DBGP_MAX_ENDPOINTS];
38};
39
Kyösti Mälkki3be80cc2013-06-06 10:46:37 +030040#if CONFIG_DEBUG_USBDEBUG
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030041static void dbgp_print_data(struct ehci_dbg_port *ehci_debug);
Kyösti Mälkkid7991402013-08-12 16:11:34 +030042static int dbgp_enabled(void);
43# define dprintk(LEVEL, args...) \
44 do { if (!dbgp_enabled()) printk(LEVEL, ##args); } while (0)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000045#else
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030046# define dbgp_print_data(x) do {} while(0)
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +030047# define dprintk(LEVEL, args...) do {} while(0)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000048#endif
49
Yinghai Lud57241f2007-02-28 11:17:02 +000050#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))
Yinghai Lud57241f2007-02-28 11:17:02 +000051
Yinghai Lud57241f2007-02-28 11:17:02 +000052#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
53
Yinghai Lud57241f2007-02-28 11:17:02 +000054#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
55#define HUB_SHORT_RESET_TIME 10
56#define HUB_LONG_RESET_TIME 200
57#define HUB_RESET_TIMEOUT 500
58
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030059#define DBGP_MICROFRAME_TIMEOUT_LOOPS 1000
60#define DBGP_MICROFRAME_RETRIES 10
Yinghai Lud57241f2007-02-28 11:17:02 +000061#define DBGP_MAX_PACKET 8
62
Kyösti Mälkki8ee04d72013-07-06 11:41:09 +030063static struct ehci_debug_info glob_dbg_info CAR_GLOBAL;
Kyösti Mälkki618d1792014-10-27 08:01:55 +020064static struct ehci_debug_info * glob_dbg_info_p CAR_GLOBAL;
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +030065
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +030066static inline struct ehci_debug_info *dbgp_ehci_info(void)
67{
Kyösti Mälkki618d1792014-10-27 08:01:55 +020068 if (car_get_var(glob_dbg_info_p) == NULL)
69 car_set_var(glob_dbg_info_p, &glob_dbg_info);
70
71 return car_get_var(glob_dbg_info_p);
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +030072}
73
Yinghai Lud57241f2007-02-28 11:17:02 +000074static int dbgp_wait_until_complete(struct ehci_dbg_port *ehci_debug)
75{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000076 u32 ctrl;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030077 int loop = 0;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000078
Yinghai Lud57241f2007-02-28 11:17:02 +000079 do {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080080 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +000081 /* Stop when the transaction is finished */
82 if (ctrl & DBGP_DONE)
83 break;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030084 } while (++loop < DBGP_MICROFRAME_TIMEOUT_LOOPS);
Yinghai Lud57241f2007-02-28 11:17:02 +000085
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030086 if (! (ctrl & DBGP_DONE)) {
87 dprintk(BIOS_ERR, "dbgp_wait_until_complete: retry timeout.\n");
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030088 return -DBGP_ERR_SIGNAL;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030089 }
Yinghai Lud57241f2007-02-28 11:17:02 +000090
91 /* Now that we have observed the completed transaction,
92 * clear the done bit.
93 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080094 write32(&ehci_debug->control, ctrl | DBGP_DONE);
Yinghai Lud57241f2007-02-28 11:17:02 +000095 return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
96}
97
Yinghai Lud57241f2007-02-28 11:17:02 +000098static void dbgp_breath(void)
99{
100 /* Sleep to give the debug port a chance to breathe */
101}
102
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300103static int dbgp_wait_until_done(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300104 unsigned ctrl, const int timeout)
Yinghai Lud57241f2007-02-28 11:17:02 +0000105{
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300106 u32 rd_ctrl, rd_pids;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300107 u32 ctrl_prev = 0, pids_prev = 0;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300108 u8 lpid;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300109 int ret, host_retries;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300110 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000111
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300112 loop = 0;
113device_retry:
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300114 host_retries = 0;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300115 if (loop++ >= timeout)
116 return -DBGP_ERR_BAD;
117
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300118host_retry:
119 if (host_retries++ >= DBGP_MICROFRAME_RETRIES)
120 return -DBGP_ERR_BAD;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300121 if (loop == 1 || host_retries > 1)
122 dprintk(BIOS_SPEW, "dbgp: start (@ %3d,%d) ctrl=%08x\n",
123 loop, host_retries, ctrl | DBGP_GO);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800124 write32(&ehci_debug->control, ctrl | DBGP_GO);
Yinghai Lud57241f2007-02-28 11:17:02 +0000125 ret = dbgp_wait_until_complete(ehci_debug);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800126 rd_ctrl = read32(&ehci_debug->control);
127 rd_pids = read32(&ehci_debug->pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000128
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300129 if (rd_ctrl != ctrl_prev || rd_pids != pids_prev || (ret<0)) {
130 ctrl_prev = rd_ctrl;
131 pids_prev = rd_pids;
132 dprintk(BIOS_SPEW, "dbgp: status (@ %3d,%d) ctrl=%08x pids=%08x ret=%d\n",
133 loop, host_retries, rd_ctrl, rd_pids, ret);
134 }
135
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300136 /* Controller hardware failure. */
137 if (ret == -DBGP_ERR_SIGNAL) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000138 return ret;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300139
140 /* Bus failure (corrupted microframe). */
141 } else if (ret == -DBGP_ERR_BAD) {
142 goto host_retry;
Sven Schnelle10680872012-07-25 14:19:45 +0200143 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000144
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300145 lpid = DBGP_PID_GET(rd_pids);
146
147 /* If I get an ACK or in-sync DATA PID, we are done. */
148 if ((lpid == USB_PID_ACK) || (lpid == pipe->pid)) {
Kyösti Mälkki48e899d2014-01-21 10:44:08 +0200149 pipe->pid ^= USB_PID_DATA_TOGGLE;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300150 }
151
Yinghai Lud57241f2007-02-28 11:17:02 +0000152 /* If the port is getting full or it has dropped data
153 * start pacing ourselves, not necessary but it's friendly.
154 */
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300155 else if (lpid == USB_PID_NYET) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000156 dbgp_breath();
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300157 goto device_retry;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300158 }
159
160 /* If I get a NACK or out-of-sync DATA PID, reissue the transmission. */
161 else if ((lpid == USB_PID_NAK) || (lpid == (pipe->pid ^ USB_PID_DATA_TOGGLE))) {
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300162 goto device_retry;
Yinghai Lud57241f2007-02-28 11:17:02 +0000163 }
164
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300165 /* Abort on STALL handshake for endpoint 0.*/
166 else if ((lpid == USB_PID_STALL) && (pipe->endpoint == 0x0)) {
167 ret = -DBGP_ERR_BAD;
168 }
169
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300170 dbgp_print_data(ehci_debug);
171
Yinghai Lud57241f2007-02-28 11:17:02 +0000172 return ret;
173}
174
175static void dbgp_set_data(struct ehci_dbg_port *ehci_debug, const void *buf, int size)
176{
177 const unsigned char *bytes = buf;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000178 u32 lo, hi;
Yinghai Lud57241f2007-02-28 11:17:02 +0000179 int i;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000180
Yinghai Lud57241f2007-02-28 11:17:02 +0000181 lo = hi = 0;
182 for (i = 0; i < 4 && i < size; i++)
183 lo |= bytes[i] << (8*i);
184 for (; i < 8 && i < size; i++)
185 hi |= bytes[i] << (8*(i - 4));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800186 write32(&ehci_debug->data03, lo);
187 write32(&ehci_debug->data47, hi);
Yinghai Lud57241f2007-02-28 11:17:02 +0000188}
189
190static void dbgp_get_data(struct ehci_dbg_port *ehci_debug, void *buf, int size)
191{
192 unsigned char *bytes = buf;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000193 u32 lo, hi;
Yinghai Lud57241f2007-02-28 11:17:02 +0000194 int i;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000195
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800196 lo = read32(&ehci_debug->data03);
197 hi = read32(&ehci_debug->data47);
Yinghai Lud57241f2007-02-28 11:17:02 +0000198 for (i = 0; i < 4 && i < size; i++)
199 bytes[i] = (lo >> (8*i)) & 0xff;
200 for (; i < 8 && i < size; i++)
201 bytes[i] = (hi >> (8*(i - 4))) & 0xff;
202}
203
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300204#if CONFIG_DEBUG_USBDEBUG
205static void dbgp_print_data(struct ehci_dbg_port *ehci_debug)
206{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800207 u32 ctrl = read32(&ehci_debug->control);
208 u32 lo = read32(&ehci_debug->data03);
209 u32 hi = read32(&ehci_debug->data47);
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300210 int len = DBGP_LEN(ctrl);
211 if (len) {
212 int i;
213 dprintk(BIOS_SPEW, "dbgp: buf:");
214 for (i = 0; i < 4 && i < len; i++)
215 dprintk(BIOS_SPEW, " %02x", (lo >> (8*i)) & 0xff);
216 for (; i < 8 && i < len; i++)
217 dprintk(BIOS_SPEW, " %02x", (hi >> (8*(i - 4))) & 0xff);
218 dprintk(BIOS_SPEW, "\n");
219 }
220}
221#endif
222
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300223static int dbgp_bulk_write(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
224 const char *bytes, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000225{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000226 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000227 int ret;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000228
Yinghai Lud57241f2007-02-28 11:17:02 +0000229 if (size > DBGP_MAX_PACKET)
230 return -1;
231
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300232 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300233 pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000234
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800235 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000236 ctrl = DBGP_LEN_UPDATE(ctrl, size);
237 ctrl |= DBGP_OUT;
Yinghai Lud57241f2007-02-28 11:17:02 +0000238
239 dbgp_set_data(ehci_debug, bytes, size);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800240 write32(&ehci_debug->address, addr);
241 write32(&ehci_debug->pids, pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000242
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300243 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000244
Yinghai Lud57241f2007-02-28 11:17:02 +0000245 return ret;
246}
247
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300248int dbgp_bulk_write_x(struct dbgp_pipe *pipe, const char *bytes, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000249{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300250 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300251 return dbgp_bulk_write(dbg_info->ehci_debug, pipe, bytes, size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000252}
253
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300254static int dbgp_bulk_read(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300255 void *data, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000256{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000257 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000258 int ret;
259
260 if (size > DBGP_MAX_PACKET)
261 return -1;
262
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300263 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300264 pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000265
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800266 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000267 ctrl = DBGP_LEN_UPDATE(ctrl, size);
268 ctrl &= ~DBGP_OUT;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000269
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800270 write32(&ehci_debug->address, addr);
271 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300272 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Yinghai Lud57241f2007-02-28 11:17:02 +0000273 if (ret < 0)
274 return ret;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000275
Yinghai Lud57241f2007-02-28 11:17:02 +0000276 if (size > ret)
277 size = ret;
278 dbgp_get_data(ehci_debug, data, size);
279 return ret;
280}
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000281
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300282int dbgp_bulk_read_x(struct dbgp_pipe *pipe, void *data, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000283{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300284 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300285 return dbgp_bulk_read(dbg_info->ehci_debug, pipe, data, size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000286}
287
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200288void dbgp_mdelay(int ms)
Yinghai Lud57241f2007-02-28 11:17:02 +0000289{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000290 int i;
291
292 while (ms--) {
293 for (i = 0; i < 1000; i++)
294 inb(0x80);
295 }
296}
297
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200298int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, int requesttype,
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000299 int request, int value, int index, void *data, int size)
300{
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300301 struct ehci_debug_info *info = dbgp_ehci_info();
302 struct dbgp_pipe *pipe = &info->ep_pipe[DBGP_SETUP_EP0];
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000303 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000304 struct usb_ctrlrequest req;
305 int read;
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300306 int ret, ret2;
Yinghai Lud57241f2007-02-28 11:17:02 +0000307
308 read = (requesttype & USB_DIR_IN) != 0;
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300309 if (size > DBGP_MAX_PACKET)
Yinghai Lud57241f2007-02-28 11:17:02 +0000310 return -1;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000311
Yinghai Lud57241f2007-02-28 11:17:02 +0000312 /* Compute the control message */
313 req.bRequestType = requesttype;
314 req.bRequest = request;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000315 req.wValue = cpu_to_le16(value);
316 req.wIndex = cpu_to_le16(index);
317 req.wLength = cpu_to_le16(size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000318
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300319 pipe->devnum = devnum;
320 pipe->endpoint = 0;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300321 pipe->pid = USB_PID_DATA0;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300322 pipe->timeout = 1000;
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300323 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300324 pids = DBGP_PID_SET(pipe->pid, USB_PID_SETUP);
Yinghai Lud57241f2007-02-28 11:17:02 +0000325
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800326 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000327 ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req));
328 ctrl |= DBGP_OUT;
Yinghai Lud57241f2007-02-28 11:17:02 +0000329
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300330 /* Setup stage */
Yinghai Lud57241f2007-02-28 11:17:02 +0000331 dbgp_set_data(ehci_debug, &req, sizeof(req));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800332 write32(&ehci_debug->address, addr);
333 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300334 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, 1);
Yinghai Lud57241f2007-02-28 11:17:02 +0000335 if (ret < 0)
336 return ret;
337
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300338 /* Data stage (optional) */
339 if (read && size)
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300340 ret = dbgp_bulk_read(ehci_debug, pipe, data, size);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300341 else if (!read && size)
342 ret = dbgp_bulk_write(ehci_debug, pipe, data, size);
343
344 /* Status stage in opposite direction */
345 pipe->pid = USB_PID_DATA1;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800346 ctrl = read32(&ehci_debug->control);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300347 ctrl = DBGP_LEN_UPDATE(ctrl, 0);
348 if (read) {
349 pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
350 ctrl |= DBGP_OUT;
351 } else {
352 pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
353 ctrl &= ~DBGP_OUT;
354 }
355
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800356 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300357 ret2 = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300358 if (ret2 < 0)
359 return ret2;
360
Yinghai Lud57241f2007-02-28 11:17:02 +0000361 return ret;
362}
363
364static int ehci_reset_port(struct ehci_regs *ehci_regs, int port)
365{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000366 u32 portsc;
Yinghai Lud57241f2007-02-28 11:17:02 +0000367 int loop;
368
369 /* Reset the usb debug port */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800370 portsc = read32(&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000371 portsc &= ~PORT_PE;
372 portsc |= PORT_RESET;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800373 write32(&ehci_regs->port_status[port - 1], portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000374
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300375 dbgp_mdelay(HUB_ROOT_RESET_TIME);
Yinghai Lud57241f2007-02-28 11:17:02 +0000376
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800377 portsc = read32(&ehci_regs->port_status[port - 1]);
378 write32(&ehci_regs->port_status[port - 1],
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300379 portsc & ~(PORT_RWC_BITS | PORT_RESET));
380
381 loop = 100;
382 do {
383 dbgp_mdelay(1);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800384 portsc = read32(&ehci_regs->port_status[port - 1]);
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300385 } while ((portsc & PORT_RESET) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000386
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300387 /* Device went away? */
388 if (!(portsc & PORT_CONNECT))
389 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000390
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300391 /* bomb out completely if something weird happened */
392 if ((portsc & PORT_CSC))
393 return -2; //-EINVAL;
Yinghai Lud57241f2007-02-28 11:17:02 +0000394
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300395 /* If we've finished resetting, then break out of the loop */
396 if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
397 return 0;
398
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000399 return -3; //-EBUSY;
Yinghai Lud57241f2007-02-28 11:17:02 +0000400}
401
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000402static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port)
Yinghai Lud57241f2007-02-28 11:17:02 +0000403{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000404 u32 status;
Yinghai Lud57241f2007-02-28 11:17:02 +0000405 int ret, reps;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000406
Yinghai Lud57241f2007-02-28 11:17:02 +0000407 for (reps = 0; reps < 3; reps++) {
408 dbgp_mdelay(100);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800409 status = read32(&ehci_regs->status);
Yinghai Lud57241f2007-02-28 11:17:02 +0000410 if (status & STS_PCD) {
411 ret = ehci_reset_port(ehci_regs, port);
412 if (ret == 0)
413 return 0;
414 }
415 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000416 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000417}
418
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300419
Kyösti Mälkki8101aa62013-08-15 16:27:06 +0300420
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300421static int usbdebug_init_(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info)
Yinghai Lud57241f2007-02-28 11:17:02 +0000422{
423 struct ehci_caps *ehci_caps;
424 struct ehci_regs *ehci_regs;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000425
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000426 u32 cmd, ctrl, status, portsc, hcs_params;
427 u32 debug_port, new_debug_port = 0, n_ports;
Kyösti Mälkki46249be22014-10-27 14:07:28 +0200428 int ret, i;
Yinghai Lud57241f2007-02-28 11:17:02 +0000429 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000430 int port_map_tried;
431 int playtimes = 3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000432
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200433 /* Keep all endpoints disabled before any printk() call. */
434 memset(info, 0, sizeof (*info));
435 info->ehci_base = (void *)ehci_bar;
436 info->ehci_debug = (void *)(ehci_bar + offset);
437
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200438 dprintk(BIOS_INFO, "ehci_bar: 0x%x debug_offset 0x%x\n", ehci_bar, offset);
439
Yinghai Lud57241f2007-02-28 11:17:02 +0000440 ehci_caps = (struct ehci_caps *)ehci_bar;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700441 ehci_regs = (struct ehci_regs *)(ehci_bar +
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800442 HC_LENGTH(read32(&ehci_caps->hc_capbase)));
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200443
444 struct ehci_dbg_port *ehci_debug = info->ehci_debug;
Kyösti Mälkki24100102013-08-12 20:40:37 +0300445
446 if (CONFIG_USBDEBUG_DEFAULT_PORT > 0)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200447 ehci_debug_select_port(CONFIG_USBDEBUG_DEFAULT_PORT);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300448 else
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200449 ehci_debug_select_port(1);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300450
Yinghai Lud57241f2007-02-28 11:17:02 +0000451try_next_time:
452 port_map_tried = 0;
453
454try_next_port:
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800455 hcs_params = read32(&ehci_caps->hcs_params);
Yinghai Lud57241f2007-02-28 11:17:02 +0000456 debug_port = HCS_DEBUG_PORT(hcs_params);
457 n_ports = HCS_N_PORTS(hcs_params);
458
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300459 dprintk(BIOS_INFO, "debug_port: %d\n", debug_port);
460 dprintk(BIOS_INFO, "n_ports: %d\n", n_ports);
Yinghai Lud57241f2007-02-28 11:17:02 +0000461
Yinghai Lud57241f2007-02-28 11:17:02 +0000462 for (i = 1; i <= n_ports; i++) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800463 portsc = read32(&ehci_regs->port_status[i-1]);
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300464 dprintk(BIOS_INFO, "PORTSC #%d: %08x\n", i, portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000465 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000466
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000467 if(port_map_tried && (new_debug_port != debug_port)) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000468 if(--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200469 ehci_debug_select_port(debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000470 goto try_next_time;
471 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000472 return -1;
Yinghai Lud57241f2007-02-28 11:17:02 +0000473 }
474
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300475 /* Wait until the controller is halted */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800476 status = read32(&ehci_regs->status);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300477 if (!(status & STS_HALT)) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800478 cmd = read32(&ehci_regs->command);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300479 cmd &= ~CMD_RUN;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800480 write32(&ehci_regs->command, cmd);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300481 loop = 100;
482 do {
483 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800484 status = read32(&ehci_regs->status);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300485 } while (!(status & STS_HALT) && (--loop > 0));
486 if (status & STS_HALT)
487 dprintk(BIOS_INFO, "EHCI controller halted successfully.\n");
488 else
489 dprintk(BIOS_INFO, "EHCI controller is not halted. Reset may fail.\n");
490 }
491
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000492 loop = 100;
Yinghai Lud57241f2007-02-28 11:17:02 +0000493 /* Reset the EHCI controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800494 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000495 cmd |= CMD_RESET;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800496 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000497 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000498 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800499 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000500 } while ((cmd & CMD_RESET) && (--loop > 0));
501
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000502 if(!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300503 dprintk(BIOS_INFO, "Could not reset EHCI controller.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000504 // on some systems it works without succeeding here.
505 // return -2;
506 } else {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300507 dprintk(BIOS_INFO, "EHCI controller reset successfully.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000508 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000509
510 /* Claim ownership, but do not enable yet */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800511 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000512 ctrl |= DBGP_OWNER;
513 ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800514 write32(&ehci_debug->control, ctrl);
Yinghai Lud57241f2007-02-28 11:17:02 +0000515
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000516 /* Start EHCI controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800517 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000518 cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
519 cmd |= CMD_RUN;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800520 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000521
522 /* Ensure everything is routed to the EHCI */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800523 write32(&ehci_regs->configured_flag, FLAG_CF);
Yinghai Lud57241f2007-02-28 11:17:02 +0000524
525 /* Wait until the controller is no longer halted */
526 loop = 10;
527 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000528 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800529 status = read32(&ehci_regs->status);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000530 } while ((status & STS_HALT) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000531
532 if(!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300533 dprintk(BIOS_INFO, "EHCI could not be started.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000534 return -3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000535 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300536 dprintk(BIOS_INFO, "EHCI started.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000537
538 /* Wait for a device to show up in the debug port */
539 ret = ehci_wait_for_port(ehci_regs, debug_port);
540 if (ret < 0) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300541 dprintk(BIOS_INFO, "No device found in debug port %d\n", debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000542 goto next_debug_port;
543 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300544 dprintk(BIOS_INFO, "EHCI done waiting for port.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000545
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200546
Yinghai Lud57241f2007-02-28 11:17:02 +0000547 /* Enable the debug port */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800548 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000549 ctrl |= DBGP_CLAIM;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800550 write32(&ehci_debug->control, ctrl);
551 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000552 if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300553 dprintk(BIOS_INFO, "No device in EHCI debug port.\n");
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800554 write32(&ehci_debug->control, ctrl & ~DBGP_CLAIM);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000555 ret = -4;
Yinghai Lud57241f2007-02-28 11:17:02 +0000556 goto err;
557 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300558 dprintk(BIOS_INFO, "EHCI debug port enabled.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000559
Kyösti Mälkki9e999d62013-06-06 10:33:39 +0300560#if 0
Yinghai Lud57241f2007-02-28 11:17:02 +0000561 /* Completely transfer the debug device to the debug controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800562 portsc = read32(&ehci_regs->port_status[debug_port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000563 portsc &= ~PORT_PE;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800564 write32(&ehci_regs->port_status[debug_port - 1], portsc);
Kyösti Mälkki9e999d62013-06-06 10:33:39 +0300565#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000566
567 dbgp_mdelay(100);
568
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200569 ret = dbgp_probe_gadget(info->ehci_debug, &info->ep_pipe[0]);
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300570 if (ret < 0) {
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200571 dprintk(BIOS_INFO, "Could not probe gadget on debug port.\n");
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300572 ret = -6;
573 goto err;
574 }
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300575
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000576 return 0;
Yinghai Lud57241f2007-02-28 11:17:02 +0000577err:
578 /* Things didn't work so remove my claim */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800579 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000580 ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800581 write32(&ehci_debug->control, ctrl);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000582 //return ret;
Yinghai Lud57241f2007-02-28 11:17:02 +0000583
584next_debug_port:
Kyösti Mälkki24100102013-08-12 20:40:37 +0300585#if CONFIG_USBDEBUG_DEFAULT_PORT==0
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000586 port_map_tried |= (1 << (debug_port - 1));
587 new_debug_port = ((debug_port-1 + 1) % n_ports) + 1;
588 if (port_map_tried != ((1 << n_ports) - 1)) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200589 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000590 goto try_next_port;
591 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000592 if (--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200593 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000594 goto try_next_time;
595 }
Kyösti Mälkki24100102013-08-12 20:40:37 +0300596#else
597 if (0)
598 goto try_next_port;
599 if (--playtimes)
600 goto try_next_time;
601#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000602
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000603 return -10;
604}
605
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300606#if CONFIG_DEBUG_USBDEBUG
607static int dbgp_enabled(void)
608{
609 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
610 return (globals->status & DBGP_EP_ENABLED);
611}
612#endif
613
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200614int dbgp_try_get(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300615{
616 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
617 if (!dbgp_ep_is_active(pipe) || (globals->status & DBGP_EP_BUSY))
618 return 0;
619 globals->status |= DBGP_EP_BUSY;
620 pipe->status |= DBGP_EP_BUSY;
621 return 1;
622}
623
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200624void dbgp_put(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300625{
626 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
627 globals->status &= ~DBGP_EP_BUSY;
628 pipe->status &= ~DBGP_EP_BUSY;
629}
630
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300631#if !defined(__PRE_RAM__) && !defined(__SMM__)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200632void usbdebug_re_enable(unsigned ehci_base)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300633{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300634 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300635 unsigned diff;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300636 int i;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300637
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200638 diff = (unsigned)dbg_info->ehci_base - ehci_base;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300639 dbg_info->ehci_debug -= diff;
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200640 dbg_info->ehci_base = (void*)ehci_base;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300641
642 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200643 if (dbg_info->ep_pipe[i].status & DBGP_EP_VALID)
644 dbg_info->ep_pipe[i].status |= DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300645}
646
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200647void usbdebug_disable(void)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300648{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300649 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300650 int i;
651 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
652 dbg_info->ep_pipe[i].status &= ~DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300653}
654
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300655#endif
656
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300657#if !defined(__PRE_RAM__) && !defined(__SMM__)
658static int get_usbdebug_from_cbmem(struct ehci_debug_info *info)
659{
660 struct ehci_debug_info *dbg_info_cbmem;
661
662 dbg_info_cbmem = cbmem_find(CBMEM_ID_EHCI_DEBUG);
663 if (dbg_info_cbmem == NULL)
664 return -1;
665
666 memcpy(info, dbg_info_cbmem, sizeof (*info));
667 printk(BIOS_DEBUG, "EHCI debug port found in CBMEM.\n");
668
669 return 0;
670}
671
672#elif defined(__PRE_RAM__)
Aaron Durbin41607a42015-06-09 13:54:10 -0500673static void migrate_ehci_debug(int is_recovery)
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300674{
675 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
676 struct ehci_debug_info *dbg_info_cbmem;
677
678 dbg_info_cbmem = cbmem_add(CBMEM_ID_EHCI_DEBUG, sizeof(*dbg_info));
679 if (dbg_info_cbmem == NULL)
680 return;
681
682 memcpy(dbg_info_cbmem, dbg_info, sizeof(*dbg_info));
Kyösti Mälkki618d1792014-10-27 08:01:55 +0200683 car_set_var(glob_dbg_info_p, dbg_info_cbmem);
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300684}
Kyösti Mälkki4fbac462015-01-07 04:48:43 +0200685ROMSTAGE_CBMEM_INIT_HOOK(migrate_ehci_debug);
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300686#endif
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300687
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300688int dbgp_ep_is_active(struct dbgp_pipe *pipe)
Kyösti Mälkki4d409b52013-07-05 21:38:54 +0300689{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300690 return (pipe->status & DBGP_EP_STATMASK) == (DBGP_EP_VALID | DBGP_EP_ENABLED);
Yinghai Lud57241f2007-02-28 11:17:02 +0000691}
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300692
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300693struct dbgp_pipe *dbgp_console_output(void)
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300694{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300695 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPOUT];
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300696}
697
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300698struct dbgp_pipe *dbgp_console_input(void)
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300699{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300700 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPIN];
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300701}
702
703int usbdebug_init(void)
704{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300705 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200706 unsigned int ehci_base, dbg_offset;
Kyösti Mälkki8ee04d72013-07-06 11:41:09 +0300707
Kyösti Mälkkicbf5bdf2013-09-10 00:07:21 +0300708#if !defined(__PRE_RAM__) && !defined(__SMM__)
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300709 if (!get_usbdebug_from_cbmem(dbg_info))
710 return 0;
711#endif
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200712 if (ehci_debug_hw_enable(&ehci_base, &dbg_offset))
713 return -1;
714 return usbdebug_init_(ehci_base, dbg_offset, dbg_info);
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300715}