blob: 55530b73b4392df5ee89436d9ca4d302f0530e62 [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 {
Stefan Reinauer75a05dc2010-05-25 16:35:51 +000081 ctrl = read32((unsigned long)&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 */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +000095 write32((unsigned long)&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);
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000125 write32((unsigned long)&ehci_debug->control, ctrl | DBGP_GO);
Yinghai Lud57241f2007-02-28 11:17:02 +0000126 ret = dbgp_wait_until_complete(ehci_debug);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300127 rd_ctrl = read32((unsigned long)&ehci_debug->control);
128 rd_pids = read32((unsigned long)&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));
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000187 write32((unsigned long)&ehci_debug->data03, lo);
188 write32((unsigned long)&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
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000197 lo = read32((unsigned long)&ehci_debug->data03);
198 hi = read32((unsigned long)&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{
208 u32 ctrl = read32((unsigned long)&ehci_debug->control);
209 u32 lo = read32((unsigned long)&ehci_debug->data03);
210 u32 hi = read32((unsigned long)&ehci_debug->data47);
211 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
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000236 ctrl = read32((unsigned long)&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);
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000241 write32((unsigned long)&ehci_debug->address, addr);
242 write32((unsigned long)&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
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000267 ctrl = read32((unsigned long)&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
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000271 write32((unsigned long)&ehci_debug->address, addr);
272 write32((unsigned long)&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
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000327 ctrl = read32((unsigned long)&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));
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000333 write32((unsigned long)&ehci_debug->address, addr);
334 write32((unsigned long)&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;
347 ctrl = read32((unsigned long)&ehci_debug->control);
348 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
357 write32((unsigned long)&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;
368 u32 delay_time, delay_ms;
Yinghai Lud57241f2007-02-28 11:17:02 +0000369 int loop;
370
371 /* Reset the usb debug port */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000372 portsc = read32((unsigned long)&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000373 portsc &= ~PORT_PE;
374 portsc |= PORT_RESET;
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000375 write32((unsigned long)&ehci_regs->port_status[port - 1], portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000376
Uwe Hermanna34a0b12010-09-22 23:42:32 +0000377 delay_ms = HUB_ROOT_RESET_TIME;
Yinghai Lud57241f2007-02-28 11:17:02 +0000378 for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT;
Uwe Hermanna34a0b12010-09-22 23:42:32 +0000379 delay_time += delay_ms) {
380 dbgp_mdelay(delay_ms);
Yinghai Lud57241f2007-02-28 11:17:02 +0000381
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000382 portsc = read32((unsigned long)&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000383 if (portsc & PORT_RESET) {
384 /* force reset to complete */
385 loop = 2;
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000386 write32((unsigned long)&ehci_regs->port_status[port - 1],
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000387 portsc & ~(PORT_RWC_BITS | PORT_RESET));
Stefan Reinauer14e22772010-04-27 06:56:47 +0000388 do {
Uwe Hermanna34a0b12010-09-22 23:42:32 +0000389 dbgp_mdelay(delay_ms);
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000390 portsc = read32((unsigned long)&ehci_regs->port_status[port - 1]);
Uwe Hermanna34a0b12010-09-22 23:42:32 +0000391 delay_time += delay_ms;
Yinghai Lud57241f2007-02-28 11:17:02 +0000392 } while ((portsc & PORT_RESET) && (--loop > 0));
393 if (!loop) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000394 printk(BIOS_DEBUG, "ehci_reset_port forced done");
Yinghai Lud57241f2007-02-28 11:17:02 +0000395 }
396 }
397
398 /* Device went away? */
399 if (!(portsc & PORT_CONNECT))
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000400 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000401
Martin Rothcbf2bd72013-07-09 21:51:14 -0600402 /* bomb out completely if something weird happened */
Yinghai Lud57241f2007-02-28 11:17:02 +0000403 if ((portsc & PORT_CSC))
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000404 return -2; //-EINVAL;
Yinghai Lud57241f2007-02-28 11:17:02 +0000405
406 /* If we've finished resetting, then break out of the loop */
407 if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
408 return 0;
409 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000410 return -3; //-EBUSY;
Yinghai Lud57241f2007-02-28 11:17:02 +0000411}
412
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000413static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port)
Yinghai Lud57241f2007-02-28 11:17:02 +0000414{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000415 u32 status;
Yinghai Lud57241f2007-02-28 11:17:02 +0000416 int ret, reps;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000417
Yinghai Lud57241f2007-02-28 11:17:02 +0000418 for (reps = 0; reps < 3; reps++) {
419 dbgp_mdelay(100);
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000420 status = read32((unsigned long)&ehci_regs->status);
Yinghai Lud57241f2007-02-28 11:17:02 +0000421 if (status & STS_PCD) {
422 ret = ehci_reset_port(ehci_regs, port);
423 if (ret == 0)
424 return 0;
425 }
426 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000427 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000428}
429
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300430
Kyösti Mälkki8101aa62013-08-15 16:27:06 +0300431
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300432static int usbdebug_init_(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info)
Yinghai Lud57241f2007-02-28 11:17:02 +0000433{
434 struct ehci_caps *ehci_caps;
435 struct ehci_regs *ehci_regs;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000436
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000437 u32 cmd, ctrl, status, portsc, hcs_params;
438 u32 debug_port, new_debug_port = 0, n_ports;
Kyösti Mälkki46249be22014-10-27 14:07:28 +0200439 int ret, i;
Yinghai Lud57241f2007-02-28 11:17:02 +0000440 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000441 int port_map_tried;
442 int playtimes = 3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000443
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200444 /* Keep all endpoints disabled before any printk() call. */
445 memset(info, 0, sizeof (*info));
446 info->ehci_base = (void *)ehci_bar;
447 info->ehci_debug = (void *)(ehci_bar + offset);
448
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200449 dprintk(BIOS_INFO, "ehci_bar: 0x%x debug_offset 0x%x\n", ehci_bar, offset);
450
Yinghai Lud57241f2007-02-28 11:17:02 +0000451 ehci_caps = (struct ehci_caps *)ehci_bar;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700452 ehci_regs = (struct ehci_regs *)(ehci_bar +
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000453 HC_LENGTH(read32((unsigned long)&ehci_caps->hc_capbase)));
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200454
455 struct ehci_dbg_port *ehci_debug = info->ehci_debug;
Kyösti Mälkki24100102013-08-12 20:40:37 +0300456
457 if (CONFIG_USBDEBUG_DEFAULT_PORT > 0)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200458 ehci_debug_select_port(CONFIG_USBDEBUG_DEFAULT_PORT);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300459 else
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200460 ehci_debug_select_port(1);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300461
Yinghai Lud57241f2007-02-28 11:17:02 +0000462try_next_time:
463 port_map_tried = 0;
464
465try_next_port:
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000466 hcs_params = read32((unsigned long)&ehci_caps->hcs_params);
Yinghai Lud57241f2007-02-28 11:17:02 +0000467 debug_port = HCS_DEBUG_PORT(hcs_params);
468 n_ports = HCS_N_PORTS(hcs_params);
469
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300470 dprintk(BIOS_INFO, "debug_port: %d\n", debug_port);
471 dprintk(BIOS_INFO, "n_ports: %d\n", n_ports);
Yinghai Lud57241f2007-02-28 11:17:02 +0000472
Yinghai Lud57241f2007-02-28 11:17:02 +0000473 for (i = 1; i <= n_ports; i++) {
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000474 portsc = read32((unsigned long)&ehci_regs->port_status[i-1]);
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300475 dprintk(BIOS_INFO, "PORTSC #%d: %08x\n", i, portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000476 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000477
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000478 if(port_map_tried && (new_debug_port != debug_port)) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000479 if(--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200480 ehci_debug_select_port(debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000481 goto try_next_time;
482 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000483 return -1;
Yinghai Lud57241f2007-02-28 11:17:02 +0000484 }
485
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300486 /* Wait until the controller is halted */
487 status = read32((unsigned long)&ehci_regs->status);
488 if (!(status & STS_HALT)) {
489 cmd = read32((unsigned long)&ehci_regs->command);
490 cmd &= ~CMD_RUN;
491 write32((unsigned long)&ehci_regs->command, cmd);
492 loop = 100;
493 do {
494 dbgp_mdelay(10);
495 status = read32((unsigned long)&ehci_regs->status);
496 } while (!(status & STS_HALT) && (--loop > 0));
497 if (status & STS_HALT)
498 dprintk(BIOS_INFO, "EHCI controller halted successfully.\n");
499 else
500 dprintk(BIOS_INFO, "EHCI controller is not halted. Reset may fail.\n");
501 }
502
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000503 loop = 100;
Yinghai Lud57241f2007-02-28 11:17:02 +0000504 /* Reset the EHCI controller */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000505 cmd = read32((unsigned long)&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000506 cmd |= CMD_RESET;
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000507 write32((unsigned long)&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000508 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000509 dbgp_mdelay(10);
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000510 cmd = read32((unsigned long)&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000511 } while ((cmd & CMD_RESET) && (--loop > 0));
512
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000513 if(!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300514 dprintk(BIOS_INFO, "Could not reset EHCI controller.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000515 // on some systems it works without succeeding here.
516 // return -2;
517 } else {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300518 dprintk(BIOS_INFO, "EHCI controller reset successfully.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000519 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000520
521 /* Claim ownership, but do not enable yet */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000522 ctrl = read32((unsigned long)&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000523 ctrl |= DBGP_OWNER;
524 ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000525 write32((unsigned long)&ehci_debug->control, ctrl);
Yinghai Lud57241f2007-02-28 11:17:02 +0000526
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000527 /* Start EHCI controller */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000528 cmd = read32((unsigned long)&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000529 cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
530 cmd |= CMD_RUN;
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000531 write32((unsigned long)&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000532
533 /* Ensure everything is routed to the EHCI */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000534 write32((unsigned long)&ehci_regs->configured_flag, FLAG_CF);
Yinghai Lud57241f2007-02-28 11:17:02 +0000535
536 /* Wait until the controller is no longer halted */
537 loop = 10;
538 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000539 dbgp_mdelay(10);
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000540 status = read32((unsigned long)&ehci_regs->status);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000541 } while ((status & STS_HALT) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000542
543 if(!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300544 dprintk(BIOS_INFO, "EHCI could not be started.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000545 return -3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000546 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300547 dprintk(BIOS_INFO, "EHCI started.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000548
549 /* Wait for a device to show up in the debug port */
550 ret = ehci_wait_for_port(ehci_regs, debug_port);
551 if (ret < 0) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300552 dprintk(BIOS_INFO, "No device found in debug port %d\n", debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000553 goto next_debug_port;
554 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300555 dprintk(BIOS_INFO, "EHCI done waiting for port.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000556
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200557
Yinghai Lud57241f2007-02-28 11:17:02 +0000558 /* Enable the debug port */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000559 ctrl = read32((unsigned long)&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000560 ctrl |= DBGP_CLAIM;
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000561 write32((unsigned long)&ehci_debug->control, ctrl);
562 ctrl = read32((unsigned long)&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000563 if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300564 dprintk(BIOS_INFO, "No device in EHCI debug port.\n");
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000565 write32((unsigned long)&ehci_debug->control, ctrl & ~DBGP_CLAIM);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000566 ret = -4;
Yinghai Lud57241f2007-02-28 11:17:02 +0000567 goto err;
568 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300569 dprintk(BIOS_INFO, "EHCI debug port enabled.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000570
571 /* Completely transfer the debug device to the debug controller */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000572 portsc = read32((unsigned long)&ehci_regs->port_status[debug_port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000573 portsc &= ~PORT_PE;
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000574 write32((unsigned long)&ehci_regs->port_status[debug_port - 1], portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000575
576 dbgp_mdelay(100);
577
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200578 ret = dbgp_probe_gadget(info->ehci_debug, &info->ep_pipe[0]);
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300579 if (ret < 0) {
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200580 dprintk(BIOS_INFO, "Could not probe gadget on debug port.\n");
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300581 ret = -6;
582 goto err;
583 }
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300584
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000585 return 0;
Yinghai Lud57241f2007-02-28 11:17:02 +0000586err:
587 /* Things didn't work so remove my claim */
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000588 ctrl = read32((unsigned long)&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000589 ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
Stefan Reinauer75a05dc2010-05-25 16:35:51 +0000590 write32((unsigned long)(unsigned long)&ehci_debug->control, ctrl);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000591 //return ret;
Yinghai Lud57241f2007-02-28 11:17:02 +0000592
593next_debug_port:
Kyösti Mälkki24100102013-08-12 20:40:37 +0300594#if CONFIG_USBDEBUG_DEFAULT_PORT==0
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000595 port_map_tried |= (1 << (debug_port - 1));
596 new_debug_port = ((debug_port-1 + 1) % n_ports) + 1;
597 if (port_map_tried != ((1 << n_ports) - 1)) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200598 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000599 goto try_next_port;
600 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000601 if (--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200602 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000603 goto try_next_time;
604 }
Kyösti Mälkki24100102013-08-12 20:40:37 +0300605#else
606 if (0)
607 goto try_next_port;
608 if (--playtimes)
609 goto try_next_time;
610#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000611
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000612 return -10;
613}
614
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300615#if CONFIG_DEBUG_USBDEBUG
616static int dbgp_enabled(void)
617{
618 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
619 return (globals->status & DBGP_EP_ENABLED);
620}
621#endif
622
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200623int dbgp_try_get(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300624{
625 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
626 if (!dbgp_ep_is_active(pipe) || (globals->status & DBGP_EP_BUSY))
627 return 0;
628 globals->status |= DBGP_EP_BUSY;
629 pipe->status |= DBGP_EP_BUSY;
630 return 1;
631}
632
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200633void dbgp_put(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300634{
635 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
636 globals->status &= ~DBGP_EP_BUSY;
637 pipe->status &= ~DBGP_EP_BUSY;
638}
639
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300640#if !defined(__PRE_RAM__) && !defined(__SMM__)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200641void usbdebug_re_enable(unsigned ehci_base)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300642{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300643 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300644 unsigned diff;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300645 int i;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300646
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200647 diff = (unsigned)dbg_info->ehci_base - ehci_base;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300648 dbg_info->ehci_debug -= diff;
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200649 dbg_info->ehci_base = (void*)ehci_base;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300650
651 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200652 if (dbg_info->ep_pipe[i].status & DBGP_EP_VALID)
653 dbg_info->ep_pipe[i].status |= DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300654}
655
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200656void usbdebug_disable(void)
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älkki026ff3e2013-07-08 18:11:44 +0300659 int i;
660 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
661 dbg_info->ep_pipe[i].status &= ~DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300662}
663
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300664#endif
665
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300666#if !defined(__PRE_RAM__) && !defined(__SMM__)
667static int get_usbdebug_from_cbmem(struct ehci_debug_info *info)
668{
669 struct ehci_debug_info *dbg_info_cbmem;
670
671 dbg_info_cbmem = cbmem_find(CBMEM_ID_EHCI_DEBUG);
672 if (dbg_info_cbmem == NULL)
673 return -1;
674
675 memcpy(info, dbg_info_cbmem, sizeof (*info));
676 printk(BIOS_DEBUG, "EHCI debug port found in CBMEM.\n");
677
678 return 0;
679}
680
681#elif defined(__PRE_RAM__)
682static void migrate_ehci_debug(void)
683{
684 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
685 struct ehci_debug_info *dbg_info_cbmem;
686
687 dbg_info_cbmem = cbmem_add(CBMEM_ID_EHCI_DEBUG, sizeof(*dbg_info));
688 if (dbg_info_cbmem == NULL)
689 return;
690
691 memcpy(dbg_info_cbmem, dbg_info, sizeof(*dbg_info));
Kyösti Mälkki618d1792014-10-27 08:01:55 +0200692 car_set_var(glob_dbg_info_p, dbg_info_cbmem);
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300693}
694CAR_MIGRATE(migrate_ehci_debug);
695#endif
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300696
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300697int dbgp_ep_is_active(struct dbgp_pipe *pipe)
Kyösti Mälkki4d409b52013-07-05 21:38:54 +0300698{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300699 return (pipe->status & DBGP_EP_STATMASK) == (DBGP_EP_VALID | DBGP_EP_ENABLED);
Yinghai Lud57241f2007-02-28 11:17:02 +0000700}
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300701
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300702struct dbgp_pipe *dbgp_console_output(void)
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300703{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300704 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPOUT];
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300705}
706
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300707struct dbgp_pipe *dbgp_console_input(void)
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300708{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300709 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPIN];
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300710}
711
712int usbdebug_init(void)
713{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300714 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200715 unsigned int ehci_base, dbg_offset;
Kyösti Mälkki8ee04d72013-07-06 11:41:09 +0300716
Kyösti Mälkkicbf5bdf2013-09-10 00:07:21 +0300717#if !defined(__PRE_RAM__) && !defined(__SMM__)
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300718 if (!get_usbdebug_from_cbmem(dbg_info))
719 return 0;
720#endif
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200721 if (ehci_debug_hw_enable(&ehci_base, &dbg_offset))
722 return -1;
723 return usbdebug_init_(ehci_base, dbg_offset, dbg_info);
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300724}