blob: 57a14534dee7757737a8f21a5cda13d224a5b137 [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.
Stefan Reinauerbb01f602009-07-21 21:20:45 +000015 */
Uwe Hermann06694a82010-09-23 18:16:46 +000016
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000017#include <stddef.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000018#include <console/console.h>
Kyösti Mälkkie2227a22014-02-05 13:02:55 +020019#include <console/usb.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000020#include <arch/io.h>
Stefan Reinauerfd4f4132013-06-19 12:25:44 -070021#include <arch/early_variables.h>
Kyösti Mälkkie23c22d2013-07-28 23:16:47 +030022#include <string.h>
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +030023#include <cbmem.h>
Yinghai Lud57241f2007-02-28 11:17:02 +000024
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +020025#include "ehci_debug.h"
Kyösti Mälkkie2227a22014-02-05 13:02:55 +020026#include "usb_ch9.h"
27#include "ehci.h"
Yinghai Lud57241f2007-02-28 11:17:02 +000028
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030029struct ehci_debug_info {
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +020030 void *ehci_base;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +030031 void *ehci_debug;
32
33 struct dbgp_pipe ep_pipe[DBGP_MAX_ENDPOINTS];
34};
35
Kyösti Mälkki3be80cc2013-06-06 10:46:37 +030036#if CONFIG_DEBUG_USBDEBUG
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030037static void dbgp_print_data(struct ehci_dbg_port *ehci_debug);
Kyösti Mälkkid7991402013-08-12 16:11:34 +030038static int dbgp_enabled(void);
39# define dprintk(LEVEL, args...) \
40 do { if (!dbgp_enabled()) printk(LEVEL, ##args); } while (0)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000041#else
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030042# define dbgp_print_data(x) do {} while(0)
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +030043# define dprintk(LEVEL, args...) do {} while(0)
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000044#endif
45
Yinghai Lud57241f2007-02-28 11:17:02 +000046#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))
Yinghai Lud57241f2007-02-28 11:17:02 +000047
Yinghai Lud57241f2007-02-28 11:17:02 +000048#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
49
Yinghai Lud57241f2007-02-28 11:17:02 +000050#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
51#define HUB_SHORT_RESET_TIME 10
52#define HUB_LONG_RESET_TIME 200
53#define HUB_RESET_TIMEOUT 500
54
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030055#define DBGP_MICROFRAME_TIMEOUT_LOOPS 1000
56#define DBGP_MICROFRAME_RETRIES 10
Yinghai Lud57241f2007-02-28 11:17:02 +000057#define DBGP_MAX_PACKET 8
58
Kyösti Mälkki8ee04d72013-07-06 11:41:09 +030059static struct ehci_debug_info glob_dbg_info CAR_GLOBAL;
Kyösti Mälkki618d1792014-10-27 08:01:55 +020060static struct ehci_debug_info * glob_dbg_info_p CAR_GLOBAL;
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +030061
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +030062static inline struct ehci_debug_info *dbgp_ehci_info(void)
63{
Kyösti Mälkki618d1792014-10-27 08:01:55 +020064 if (car_get_var(glob_dbg_info_p) == NULL)
65 car_set_var(glob_dbg_info_p, &glob_dbg_info);
66
67 return car_get_var(glob_dbg_info_p);
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +030068}
69
Yinghai Lud57241f2007-02-28 11:17:02 +000070static int dbgp_wait_until_complete(struct ehci_dbg_port *ehci_debug)
71{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000072 u32 ctrl;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030073 int loop = 0;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +000074
Yinghai Lud57241f2007-02-28 11:17:02 +000075 do {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080076 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +000077 /* Stop when the transaction is finished */
78 if (ctrl & DBGP_DONE)
79 break;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030080 } while (++loop < DBGP_MICROFRAME_TIMEOUT_LOOPS);
Yinghai Lud57241f2007-02-28 11:17:02 +000081
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030082 if (! (ctrl & DBGP_DONE)) {
83 dprintk(BIOS_ERR, "dbgp_wait_until_complete: retry timeout.\n");
Kyösti Mälkki2de841b32013-08-19 12:45:16 +030084 return -DBGP_ERR_SIGNAL;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +030085 }
Yinghai Lud57241f2007-02-28 11:17:02 +000086
87 /* Now that we have observed the completed transaction,
88 * clear the done bit.
89 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080090 write32(&ehci_debug->control, ctrl | DBGP_DONE);
Yinghai Lud57241f2007-02-28 11:17:02 +000091 return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
92}
93
Yinghai Lud57241f2007-02-28 11:17:02 +000094static void dbgp_breath(void)
95{
96 /* Sleep to give the debug port a chance to breathe */
97}
98
Kyösti Mälkki75d00622013-08-10 10:34:01 +030099static int dbgp_wait_until_done(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300100 unsigned ctrl, const int timeout)
Yinghai Lud57241f2007-02-28 11:17:02 +0000101{
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300102 u32 rd_ctrl, rd_pids;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300103 u32 ctrl_prev = 0, pids_prev = 0;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300104 u8 lpid;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300105 int ret, host_retries;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300106 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000107
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300108 loop = 0;
109device_retry:
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300110 host_retries = 0;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300111 if (loop++ >= timeout)
112 return -DBGP_ERR_BAD;
113
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300114host_retry:
115 if (host_retries++ >= DBGP_MICROFRAME_RETRIES)
116 return -DBGP_ERR_BAD;
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300117 if (loop == 1 || host_retries > 1)
118 dprintk(BIOS_SPEW, "dbgp: start (@ %3d,%d) ctrl=%08x\n",
119 loop, host_retries, ctrl | DBGP_GO);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800120 write32(&ehci_debug->control, ctrl | DBGP_GO);
Yinghai Lud57241f2007-02-28 11:17:02 +0000121 ret = dbgp_wait_until_complete(ehci_debug);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800122 rd_ctrl = read32(&ehci_debug->control);
123 rd_pids = read32(&ehci_debug->pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000124
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300125 if (rd_ctrl != ctrl_prev || rd_pids != pids_prev || (ret<0)) {
126 ctrl_prev = rd_ctrl;
127 pids_prev = rd_pids;
128 dprintk(BIOS_SPEW, "dbgp: status (@ %3d,%d) ctrl=%08x pids=%08x ret=%d\n",
129 loop, host_retries, rd_ctrl, rd_pids, ret);
130 }
131
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300132 /* Controller hardware failure. */
133 if (ret == -DBGP_ERR_SIGNAL) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000134 return ret;
Kyösti Mälkki2de841b32013-08-19 12:45:16 +0300135
136 /* Bus failure (corrupted microframe). */
137 } else if (ret == -DBGP_ERR_BAD) {
138 goto host_retry;
Sven Schnelle10680872012-07-25 14:19:45 +0200139 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000140
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300141 lpid = DBGP_PID_GET(rd_pids);
142
143 /* If I get an ACK or in-sync DATA PID, we are done. */
144 if ((lpid == USB_PID_ACK) || (lpid == pipe->pid)) {
Kyösti Mälkki48e899d2014-01-21 10:44:08 +0200145 pipe->pid ^= USB_PID_DATA_TOGGLE;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300146 }
147
Yinghai Lud57241f2007-02-28 11:17:02 +0000148 /* If the port is getting full or it has dropped data
149 * start pacing ourselves, not necessary but it's friendly.
150 */
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300151 else if (lpid == USB_PID_NYET) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000152 dbgp_breath();
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300153 goto device_retry;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300154 }
155
156 /* If I get a NACK or out-of-sync DATA PID, reissue the transmission. */
157 else if ((lpid == USB_PID_NAK) || (lpid == (pipe->pid ^ USB_PID_DATA_TOGGLE))) {
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300158 goto device_retry;
Yinghai Lud57241f2007-02-28 11:17:02 +0000159 }
160
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300161 /* Abort on STALL handshake for endpoint 0.*/
162 else if ((lpid == USB_PID_STALL) && (pipe->endpoint == 0x0)) {
163 ret = -DBGP_ERR_BAD;
164 }
165
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300166 dbgp_print_data(ehci_debug);
167
Yinghai Lud57241f2007-02-28 11:17:02 +0000168 return ret;
169}
170
171static void dbgp_set_data(struct ehci_dbg_port *ehci_debug, const void *buf, int size)
172{
173 const unsigned char *bytes = buf;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000174 u32 lo, hi;
Yinghai Lud57241f2007-02-28 11:17:02 +0000175 int i;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000176
Yinghai Lud57241f2007-02-28 11:17:02 +0000177 lo = hi = 0;
178 for (i = 0; i < 4 && i < size; i++)
179 lo |= bytes[i] << (8*i);
180 for (; i < 8 && i < size; i++)
181 hi |= bytes[i] << (8*(i - 4));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800182 write32(&ehci_debug->data03, lo);
183 write32(&ehci_debug->data47, hi);
Yinghai Lud57241f2007-02-28 11:17:02 +0000184}
185
186static void dbgp_get_data(struct ehci_dbg_port *ehci_debug, void *buf, int size)
187{
188 unsigned char *bytes = buf;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000189 u32 lo, hi;
Yinghai Lud57241f2007-02-28 11:17:02 +0000190 int i;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000191
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800192 lo = read32(&ehci_debug->data03);
193 hi = read32(&ehci_debug->data47);
Yinghai Lud57241f2007-02-28 11:17:02 +0000194 for (i = 0; i < 4 && i < size; i++)
195 bytes[i] = (lo >> (8*i)) & 0xff;
196 for (; i < 8 && i < size; i++)
197 bytes[i] = (hi >> (8*(i - 4))) & 0xff;
198}
199
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300200#if CONFIG_DEBUG_USBDEBUG
201static void dbgp_print_data(struct ehci_dbg_port *ehci_debug)
202{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800203 u32 ctrl = read32(&ehci_debug->control);
204 u32 lo = read32(&ehci_debug->data03);
205 u32 hi = read32(&ehci_debug->data47);
Kyösti Mälkkie53cece2013-08-10 10:50:43 +0300206 int len = DBGP_LEN(ctrl);
207 if (len) {
208 int i;
209 dprintk(BIOS_SPEW, "dbgp: buf:");
210 for (i = 0; i < 4 && i < len; i++)
211 dprintk(BIOS_SPEW, " %02x", (lo >> (8*i)) & 0xff);
212 for (; i < 8 && i < len; i++)
213 dprintk(BIOS_SPEW, " %02x", (hi >> (8*(i - 4))) & 0xff);
214 dprintk(BIOS_SPEW, "\n");
215 }
216}
217#endif
218
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300219static int dbgp_bulk_write(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
220 const char *bytes, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000221{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000222 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000223 int ret;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000224
Yinghai Lud57241f2007-02-28 11:17:02 +0000225 if (size > DBGP_MAX_PACKET)
226 return -1;
227
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300228 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300229 pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000230
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800231 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000232 ctrl = DBGP_LEN_UPDATE(ctrl, size);
233 ctrl |= DBGP_OUT;
Yinghai Lud57241f2007-02-28 11:17:02 +0000234
235 dbgp_set_data(ehci_debug, bytes, size);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800236 write32(&ehci_debug->address, addr);
237 write32(&ehci_debug->pids, pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000238
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300239 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000240
Yinghai Lud57241f2007-02-28 11:17:02 +0000241 return ret;
242}
243
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300244int dbgp_bulk_write_x(struct dbgp_pipe *pipe, const char *bytes, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000245{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300246 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300247 return dbgp_bulk_write(dbg_info->ehci_debug, pipe, bytes, size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000248}
249
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300250static int dbgp_bulk_read(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe,
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300251 void *data, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000252{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000253 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000254 int ret;
255
256 if (size > DBGP_MAX_PACKET)
257 return -1;
258
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300259 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300260 pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000261
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800262 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000263 ctrl = DBGP_LEN_UPDATE(ctrl, size);
264 ctrl &= ~DBGP_OUT;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000265
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800266 write32(&ehci_debug->address, addr);
267 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300268 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Yinghai Lud57241f2007-02-28 11:17:02 +0000269 if (ret < 0)
270 return ret;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000271
Yinghai Lud57241f2007-02-28 11:17:02 +0000272 if (size > ret)
273 size = ret;
274 dbgp_get_data(ehci_debug, data, size);
275 return ret;
276}
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000277
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300278int dbgp_bulk_read_x(struct dbgp_pipe *pipe, void *data, int size)
Yinghai Lud57241f2007-02-28 11:17:02 +0000279{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300280 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300281 return dbgp_bulk_read(dbg_info->ehci_debug, pipe, data, size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000282}
283
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200284void dbgp_mdelay(int ms)
Yinghai Lud57241f2007-02-28 11:17:02 +0000285{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000286 int i;
287
288 while (ms--) {
289 for (i = 0; i < 1000; i++)
290 inb(0x80);
291 }
292}
293
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200294int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, int requesttype,
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000295 int request, int value, int index, void *data, int size)
296{
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300297 struct ehci_debug_info *info = dbgp_ehci_info();
298 struct dbgp_pipe *pipe = &info->ep_pipe[DBGP_SETUP_EP0];
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000299 u32 pids, addr, ctrl;
Yinghai Lud57241f2007-02-28 11:17:02 +0000300 struct usb_ctrlrequest req;
301 int read;
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300302 int ret, ret2;
Yinghai Lud57241f2007-02-28 11:17:02 +0000303
304 read = (requesttype & USB_DIR_IN) != 0;
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300305 if (size > DBGP_MAX_PACKET)
Yinghai Lud57241f2007-02-28 11:17:02 +0000306 return -1;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000307
Yinghai Lud57241f2007-02-28 11:17:02 +0000308 /* Compute the control message */
309 req.bRequestType = requesttype;
310 req.bRequest = request;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000311 req.wValue = cpu_to_le16(value);
312 req.wIndex = cpu_to_le16(index);
313 req.wLength = cpu_to_le16(size);
Yinghai Lud57241f2007-02-28 11:17:02 +0000314
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300315 pipe->devnum = devnum;
316 pipe->endpoint = 0;
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300317 pipe->pid = USB_PID_DATA0;
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300318 pipe->timeout = 1000;
Kyösti Mälkki75d00622013-08-10 10:34:01 +0300319 addr = DBGP_EPADDR(pipe->devnum, pipe->endpoint);
Kyösti Mälkkie29584c2013-08-10 10:50:38 +0300320 pids = DBGP_PID_SET(pipe->pid, USB_PID_SETUP);
Yinghai Lud57241f2007-02-28 11:17:02 +0000321
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800322 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000323 ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req));
324 ctrl |= DBGP_OUT;
Yinghai Lud57241f2007-02-28 11:17:02 +0000325
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300326 /* Setup stage */
Yinghai Lud57241f2007-02-28 11:17:02 +0000327 dbgp_set_data(ehci_debug, &req, sizeof(req));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800328 write32(&ehci_debug->address, addr);
329 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300330 ret = dbgp_wait_until_done(ehci_debug, pipe, ctrl, 1);
Yinghai Lud57241f2007-02-28 11:17:02 +0000331 if (ret < 0)
332 return ret;
333
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300334 /* Data stage (optional) */
335 if (read && size)
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300336 ret = dbgp_bulk_read(ehci_debug, pipe, data, size);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300337 else if (!read && size)
338 ret = dbgp_bulk_write(ehci_debug, pipe, data, size);
339
340 /* Status stage in opposite direction */
341 pipe->pid = USB_PID_DATA1;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800342 ctrl = read32(&ehci_debug->control);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300343 ctrl = DBGP_LEN_UPDATE(ctrl, 0);
344 if (read) {
345 pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
346 ctrl |= DBGP_OUT;
347 } else {
348 pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
349 ctrl &= ~DBGP_OUT;
350 }
351
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800352 write32(&ehci_debug->pids, pids);
Kyösti Mälkki5c87d2f12013-08-19 12:45:16 +0300353 ret2 = dbgp_wait_until_done(ehci_debug, pipe, ctrl, pipe->timeout);
Kyösti Mälkkidcccbd12013-08-10 10:08:38 +0300354 if (ret2 < 0)
355 return ret2;
356
Yinghai Lud57241f2007-02-28 11:17:02 +0000357 return ret;
358}
359
360static int ehci_reset_port(struct ehci_regs *ehci_regs, int port)
361{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000362 u32 portsc;
Yinghai Lud57241f2007-02-28 11:17:02 +0000363 int loop;
364
365 /* Reset the usb debug port */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800366 portsc = read32(&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000367 portsc &= ~PORT_PE;
368 portsc |= PORT_RESET;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800369 write32(&ehci_regs->port_status[port - 1], portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000370
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300371 dbgp_mdelay(HUB_ROOT_RESET_TIME);
Yinghai Lud57241f2007-02-28 11:17:02 +0000372
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800373 portsc = read32(&ehci_regs->port_status[port - 1]);
374 write32(&ehci_regs->port_status[port - 1],
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300375 portsc & ~(PORT_RWC_BITS | PORT_RESET));
376
377 loop = 100;
378 do {
379 dbgp_mdelay(1);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800380 portsc = read32(&ehci_regs->port_status[port - 1]);
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300381 } while ((portsc & PORT_RESET) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000382
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300383 /* Device went away? */
384 if (!(portsc & PORT_CONNECT))
385 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000386
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300387 /* bomb out completely if something weird happened */
388 if ((portsc & PORT_CSC))
389 return -2; //-EINVAL;
Yinghai Lud57241f2007-02-28 11:17:02 +0000390
Kyösti Mälkkib8ef4c92013-08-12 21:35:20 +0300391 /* If we've finished resetting, then break out of the loop */
392 if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
393 return 0;
394
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000395 return -3; //-EBUSY;
Yinghai Lud57241f2007-02-28 11:17:02 +0000396}
397
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000398static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port)
Yinghai Lud57241f2007-02-28 11:17:02 +0000399{
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000400 u32 status;
Yinghai Lud57241f2007-02-28 11:17:02 +0000401 int ret, reps;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000402
Yinghai Lud57241f2007-02-28 11:17:02 +0000403 for (reps = 0; reps < 3; reps++) {
404 dbgp_mdelay(100);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800405 status = read32(&ehci_regs->status);
Yinghai Lud57241f2007-02-28 11:17:02 +0000406 if (status & STS_PCD) {
407 ret = ehci_reset_port(ehci_regs, port);
408 if (ret == 0)
409 return 0;
410 }
411 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000412 return -1; //-ENOTCONN;
Yinghai Lud57241f2007-02-28 11:17:02 +0000413}
414
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300415
Kyösti Mälkki8101aa62013-08-15 16:27:06 +0300416
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300417static int usbdebug_init_(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info)
Yinghai Lud57241f2007-02-28 11:17:02 +0000418{
419 struct ehci_caps *ehci_caps;
420 struct ehci_regs *ehci_regs;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000421
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000422 u32 cmd, ctrl, status, portsc, hcs_params;
423 u32 debug_port, new_debug_port = 0, n_ports;
Kyösti Mälkki46249be22014-10-27 14:07:28 +0200424 int ret, i;
Yinghai Lud57241f2007-02-28 11:17:02 +0000425 int loop;
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000426 int port_map_tried;
427 int playtimes = 3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000428
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200429 /* Keep all endpoints disabled before any printk() call. */
430 memset(info, 0, sizeof (*info));
431 info->ehci_base = (void *)ehci_bar;
432 info->ehci_debug = (void *)(ehci_bar + offset);
433
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200434 dprintk(BIOS_INFO, "ehci_bar: 0x%x debug_offset 0x%x\n", ehci_bar, offset);
435
Yinghai Lud57241f2007-02-28 11:17:02 +0000436 ehci_caps = (struct ehci_caps *)ehci_bar;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700437 ehci_regs = (struct ehci_regs *)(ehci_bar +
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800438 HC_LENGTH(read32(&ehci_caps->hc_capbase)));
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200439
440 struct ehci_dbg_port *ehci_debug = info->ehci_debug;
Kyösti Mälkki24100102013-08-12 20:40:37 +0300441
442 if (CONFIG_USBDEBUG_DEFAULT_PORT > 0)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200443 ehci_debug_select_port(CONFIG_USBDEBUG_DEFAULT_PORT);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300444 else
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200445 ehci_debug_select_port(1);
Kyösti Mälkki24100102013-08-12 20:40:37 +0300446
Yinghai Lud57241f2007-02-28 11:17:02 +0000447try_next_time:
448 port_map_tried = 0;
449
450try_next_port:
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800451 hcs_params = read32(&ehci_caps->hcs_params);
Yinghai Lud57241f2007-02-28 11:17:02 +0000452 debug_port = HCS_DEBUG_PORT(hcs_params);
453 n_ports = HCS_N_PORTS(hcs_params);
454
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300455 dprintk(BIOS_INFO, "debug_port: %d\n", debug_port);
456 dprintk(BIOS_INFO, "n_ports: %d\n", n_ports);
Yinghai Lud57241f2007-02-28 11:17:02 +0000457
Yinghai Lud57241f2007-02-28 11:17:02 +0000458 for (i = 1; i <= n_ports; i++) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800459 portsc = read32(&ehci_regs->port_status[i-1]);
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300460 dprintk(BIOS_INFO, "PORTSC #%d: %08x\n", i, portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000461 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000462
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000463 if(port_map_tried && (new_debug_port != debug_port)) {
Yinghai Lud57241f2007-02-28 11:17:02 +0000464 if(--playtimes) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200465 ehci_debug_select_port(debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000466 goto try_next_time;
467 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000468 return -1;
Yinghai Lud57241f2007-02-28 11:17:02 +0000469 }
470
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300471 /* Wait until the controller is halted */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800472 status = read32(&ehci_regs->status);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300473 if (!(status & STS_HALT)) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800474 cmd = read32(&ehci_regs->command);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300475 cmd &= ~CMD_RUN;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800476 write32(&ehci_regs->command, cmd);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300477 loop = 100;
478 do {
479 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800480 status = read32(&ehci_regs->status);
Kyösti Mälkki16c01452013-08-12 15:32:25 +0300481 } while (!(status & STS_HALT) && (--loop > 0));
482 if (status & STS_HALT)
483 dprintk(BIOS_INFO, "EHCI controller halted successfully.\n");
484 else
485 dprintk(BIOS_INFO, "EHCI controller is not halted. Reset may fail.\n");
486 }
487
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000488 loop = 100;
Yinghai Lud57241f2007-02-28 11:17:02 +0000489 /* Reset the EHCI controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800490 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000491 cmd |= CMD_RESET;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800492 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000493 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000494 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800495 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000496 } while ((cmd & CMD_RESET) && (--loop > 0));
497
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000498 if(!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300499 dprintk(BIOS_INFO, "Could not reset EHCI controller.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000500 // on some systems it works without succeeding here.
501 // return -2;
502 } else {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300503 dprintk(BIOS_INFO, "EHCI controller reset successfully.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000504 }
Yinghai Lud57241f2007-02-28 11:17:02 +0000505
506 /* Claim ownership, but do not enable yet */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800507 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000508 ctrl |= DBGP_OWNER;
509 ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800510 write32(&ehci_debug->control, ctrl);
Yinghai Lud57241f2007-02-28 11:17:02 +0000511
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000512 /* Start EHCI controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800513 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000514 cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
515 cmd |= CMD_RUN;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800516 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000517
518 /* Ensure everything is routed to the EHCI */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800519 write32(&ehci_regs->configured_flag, FLAG_CF);
Yinghai Lud57241f2007-02-28 11:17:02 +0000520
521 /* Wait until the controller is no longer halted */
522 loop = 10;
523 do {
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000524 dbgp_mdelay(10);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800525 status = read32(&ehci_regs->status);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000526 } while ((status & STS_HALT) && (--loop > 0));
Yinghai Lud57241f2007-02-28 11:17:02 +0000527
528 if(!loop) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300529 dprintk(BIOS_INFO, "EHCI could not be started.\n");
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000530 return -3;
Yinghai Lud57241f2007-02-28 11:17:02 +0000531 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300532 dprintk(BIOS_INFO, "EHCI started.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000533
534 /* Wait for a device to show up in the debug port */
535 ret = ehci_wait_for_port(ehci_regs, debug_port);
536 if (ret < 0) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300537 dprintk(BIOS_INFO, "No device found in debug port %d\n", debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000538 goto next_debug_port;
539 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300540 dprintk(BIOS_INFO, "EHCI done waiting for port.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000541
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200542
Yinghai Lud57241f2007-02-28 11:17:02 +0000543 /* Enable the debug port */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800544 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000545 ctrl |= DBGP_CLAIM;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800546 write32(&ehci_debug->control, ctrl);
547 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000548 if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300549 dprintk(BIOS_INFO, "No device in EHCI debug port.\n");
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800550 write32(&ehci_debug->control, ctrl & ~DBGP_CLAIM);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000551 ret = -4;
Yinghai Lud57241f2007-02-28 11:17:02 +0000552 goto err;
553 }
Kyösti Mälkki8ff3d682013-08-12 16:11:34 +0300554 dprintk(BIOS_INFO, "EHCI debug port enabled.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000555
Kyösti Mälkki9e999d62013-06-06 10:33:39 +0300556#if 0
Yinghai Lud57241f2007-02-28 11:17:02 +0000557 /* Completely transfer the debug device to the debug controller */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800558 portsc = read32(&ehci_regs->port_status[debug_port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000559 portsc &= ~PORT_PE;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800560 write32(&ehci_regs->port_status[debug_port - 1], portsc);
Kyösti Mälkki9e999d62013-06-06 10:33:39 +0300561#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000562
563 dbgp_mdelay(100);
564
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200565 ret = dbgp_probe_gadget(info->ehci_debug, &info->ep_pipe[0]);
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300566 if (ret < 0) {
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200567 dprintk(BIOS_INFO, "Could not probe gadget on debug port.\n");
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300568 ret = -6;
569 goto err;
570 }
Kyösti Mälkkid2dac0a2013-08-23 23:33:16 +0300571
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000572 return 0;
Yinghai Lud57241f2007-02-28 11:17:02 +0000573err:
574 /* Things didn't work so remove my claim */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800575 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000576 ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800577 write32(&ehci_debug->control, ctrl);
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000578 //return ret;
Yinghai Lud57241f2007-02-28 11:17:02 +0000579
580next_debug_port:
Kyösti Mälkki24100102013-08-12 20:40:37 +0300581#if CONFIG_USBDEBUG_DEFAULT_PORT==0
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000582 port_map_tried |= (1 << (debug_port - 1));
583 new_debug_port = ((debug_port-1 + 1) % n_ports) + 1;
584 if (port_map_tried != ((1 << n_ports) - 1)) {
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200585 ehci_debug_select_port(new_debug_port);
Yinghai Lud57241f2007-02-28 11:17:02 +0000586 goto try_next_port;
587 }
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000588 if (--playtimes) {
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_time;
591 }
Kyösti Mälkki24100102013-08-12 20:40:37 +0300592#else
593 if (0)
594 goto try_next_port;
595 if (--playtimes)
596 goto try_next_time;
597#endif
Yinghai Lud57241f2007-02-28 11:17:02 +0000598
Stefan Reinauer16ce01b2011-01-28 08:05:54 +0000599 return -10;
600}
601
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300602#if CONFIG_DEBUG_USBDEBUG
603static int dbgp_enabled(void)
604{
605 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
606 return (globals->status & DBGP_EP_ENABLED);
607}
608#endif
609
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200610int dbgp_try_get(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300611{
612 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
613 if (!dbgp_ep_is_active(pipe) || (globals->status & DBGP_EP_BUSY))
614 return 0;
615 globals->status |= DBGP_EP_BUSY;
616 pipe->status |= DBGP_EP_BUSY;
617 return 1;
618}
619
Kyösti Mälkki8cde8522014-02-09 23:35:39 +0200620void dbgp_put(struct dbgp_pipe *pipe)
Kyösti Mälkkid7991402013-08-12 16:11:34 +0300621{
622 struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0];
623 globals->status &= ~DBGP_EP_BUSY;
624 pipe->status &= ~DBGP_EP_BUSY;
625}
626
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300627#if !defined(__PRE_RAM__) && !defined(__SMM__)
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200628void usbdebug_re_enable(unsigned ehci_base)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300629{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300630 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300631 unsigned diff;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300632 int i;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300633
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200634 diff = (unsigned)dbg_info->ehci_base - ehci_base;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300635 dbg_info->ehci_debug -= diff;
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200636 dbg_info->ehci_base = (void*)ehci_base;
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300637
638 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
Kyösti Mälkki7bb4f862014-10-27 15:07:20 +0200639 if (dbg_info->ep_pipe[i].status & DBGP_EP_VALID)
640 dbg_info->ep_pipe[i].status |= DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300641}
642
Kyösti Mälkkicb141bc2014-02-07 19:24:23 +0200643void usbdebug_disable(void)
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300644{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300645 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300646 int i;
647 for (i=0; i<DBGP_MAX_ENDPOINTS; i++)
648 dbg_info->ep_pipe[i].status &= ~DBGP_EP_ENABLED;
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300649}
650
Kyösti Mälkki41c10cd2013-07-09 04:19:22 +0300651#endif
652
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300653#if !defined(__PRE_RAM__) && !defined(__SMM__)
654static int get_usbdebug_from_cbmem(struct ehci_debug_info *info)
655{
656 struct ehci_debug_info *dbg_info_cbmem;
657
658 dbg_info_cbmem = cbmem_find(CBMEM_ID_EHCI_DEBUG);
659 if (dbg_info_cbmem == NULL)
660 return -1;
661
662 memcpy(info, dbg_info_cbmem, sizeof (*info));
663 printk(BIOS_DEBUG, "EHCI debug port found in CBMEM.\n");
664
665 return 0;
666}
667
668#elif defined(__PRE_RAM__)
Aaron Durbin41607a42015-06-09 13:54:10 -0500669static void migrate_ehci_debug(int is_recovery)
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300670{
671 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
672 struct ehci_debug_info *dbg_info_cbmem;
673
674 dbg_info_cbmem = cbmem_add(CBMEM_ID_EHCI_DEBUG, sizeof(*dbg_info));
675 if (dbg_info_cbmem == NULL)
676 return;
677
678 memcpy(dbg_info_cbmem, dbg_info, sizeof(*dbg_info));
Kyösti Mälkki618d1792014-10-27 08:01:55 +0200679 car_set_var(glob_dbg_info_p, dbg_info_cbmem);
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300680}
Kyösti Mälkki4fbac462015-01-07 04:48:43 +0200681ROMSTAGE_CBMEM_INIT_HOOK(migrate_ehci_debug);
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300682#endif
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300683
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300684int dbgp_ep_is_active(struct dbgp_pipe *pipe)
Kyösti Mälkki4d409b52013-07-05 21:38:54 +0300685{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300686 return (pipe->status & DBGP_EP_STATMASK) == (DBGP_EP_VALID | DBGP_EP_ENABLED);
Yinghai Lud57241f2007-02-28 11:17:02 +0000687}
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300688
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300689struct dbgp_pipe *dbgp_console_output(void)
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300690{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300691 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPOUT];
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300692}
693
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300694struct dbgp_pipe *dbgp_console_input(void)
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300695{
Kyösti Mälkki026ff3e2013-07-08 18:11:44 +0300696 return &dbgp_ehci_info()->ep_pipe[DBGP_CONSOLE_EPIN];
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300697}
698
699int usbdebug_init(void)
700{
Kyösti Mälkkicbe2ede2013-07-11 07:49:46 +0300701 struct ehci_debug_info *dbg_info = dbgp_ehci_info();
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200702 unsigned int ehci_base, dbg_offset;
Kyösti Mälkki8ee04d72013-07-06 11:41:09 +0300703
Kyösti Mälkkicbf5bdf2013-09-10 00:07:21 +0300704#if !defined(__PRE_RAM__) && !defined(__SMM__)
Kyösti Mälkki690bf2f2013-07-06 11:41:21 +0300705 if (!get_usbdebug_from_cbmem(dbg_info))
706 return 0;
707#endif
Kyösti Mälkki6f6a2492014-02-09 19:21:30 +0200708 if (ehci_debug_hw_enable(&ehci_base, &dbg_offset))
709 return -1;
710 return usbdebug_init_(ehci_base, dbg_offset, dbg_info);
Kyösti Mälkki9e7806a2013-07-06 11:56:49 +0300711}