blob: d2e46729d104d5da0549489605401d4879c59a74 [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)
5 *
Stefan Reinauerbb01f602009-07-21 21:20:45 +00006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
Yinghai Lud57241f2007-02-28 11:17:02 +00009 *
Stefan Reinauerbb01f602009-07-21 21:20:45 +000010 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
18 */
19/*
Stefan Reinauerf8ee1802008-01-18 15:08:58 +000020 * 2006.12.10 yhlu moved it to corbeoot and use struct instead
Yinghai Lud57241f2007-02-28 11:17:02 +000021 */
Myles Watson1d6d45e2009-11-06 17:02:51 +000022#if !defined(__ROMCC__)
Yinghai Lud57241f2007-02-28 11:17:02 +000023#include <console/console.h>
24#else
25#if CONFIG_USE_PRINTK_IN_CAR==0
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000026#define printk(BIOS_DEBUG, fmt, arg...) do {} while(0)
Yinghai Lud57241f2007-02-28 11:17:02 +000027#endif
28#endif
29
Yinghai Lud57241f2007-02-28 11:17:02 +000030#include <arch/io.h>
31
32#include <usb_ch9.h>
33#include <ehci.h>
34#include <usbdebug_direct.h>
35
36#define USB_DEBUG_DEVNUM 127
37
38#define DBGP_DATA_TOGGLE 0x8800
39#define DBGP_PID_UPDATE(x, tok) \
40 ((((x) ^ DBGP_DATA_TOGGLE) & 0xffff00) | ((tok) & 0xff))
41
42#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))
43/*
44 * USB Packet IDs (PIDs)
45 */
46
47/* token */
48#define USB_PID_OUT 0xe1
49#define USB_PID_IN 0x69
50#define USB_PID_SOF 0xa5
51#define USB_PID_SETUP 0x2d
52/* handshake */
53#define USB_PID_ACK 0xd2
54#define USB_PID_NAK 0x5a
55#define USB_PID_STALL 0x1e
56#define USB_PID_NYET 0x96
57/* data */
58#define USB_PID_DATA0 0xc3
59#define USB_PID_DATA1 0x4b
60#define USB_PID_DATA2 0x87
61#define USB_PID_MDATA 0x0f
62/* Special */
63#define USB_PID_PREAMBLE 0x3c
64#define USB_PID_ERR 0x3c
65#define USB_PID_SPLIT 0x78
66#define USB_PID_PING 0xb4
67#define USB_PID_UNDEF_0 0xf0
68
69#define USB_PID_DATA_TOGGLE 0x88
70#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
71
72#define PCI_CAP_ID_EHCI_DEBUG 0xa
73
74#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
75#define HUB_SHORT_RESET_TIME 10
76#define HUB_LONG_RESET_TIME 200
77#define HUB_RESET_TIMEOUT 500
78
79#define DBGP_MAX_PACKET 8
80
81static int dbgp_wait_until_complete(struct ehci_dbg_port *ehci_debug)
82{
83 unsigned ctrl;
84 int loop = 0x100000;
85 do {
Stefan Reinauer9fe4d792010-01-16 17:53:38 +000086 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +000087 /* Stop when the transaction is finished */
88 if (ctrl & DBGP_DONE)
89 break;
Stefan Reinauer14e22772010-04-27 06:56:47 +000090 } while(--loop>0);
Yinghai Lud57241f2007-02-28 11:17:02 +000091
92 if (!loop) return -1000;
93
94 /* Now that we have observed the completed transaction,
95 * clear the done bit.
96 */
Stefan Reinauer9fe4d792010-01-16 17:53:38 +000097 write32(&ehci_debug->control, ctrl | DBGP_DONE);
Yinghai Lud57241f2007-02-28 11:17:02 +000098 return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
99}
100
101static void dbgp_mdelay(int ms)
102{
103 int i;
104 while (ms--) {
105 for (i = 0; i < 1000; i++)
Stefan Reinauerf8c77e82009-03-06 17:21:23 +0000106 inb(0x80);
Yinghai Lud57241f2007-02-28 11:17:02 +0000107 }
108}
109
110static void dbgp_breath(void)
111{
112 /* Sleep to give the debug port a chance to breathe */
113}
114
115static int dbgp_wait_until_done(struct ehci_dbg_port *ehci_debug, unsigned ctrl)
116{
117 unsigned pids, lpid;
118 int ret;
119
120 int loop = 3;
121retry:
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000122 write32(&ehci_debug->control, ctrl | DBGP_GO);
Yinghai Lud57241f2007-02-28 11:17:02 +0000123 ret = dbgp_wait_until_complete(ehci_debug);
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000124 pids = read32(&ehci_debug->pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000125 lpid = DBGP_PID_GET(pids);
126
127 if (ret < 0)
128 return ret;
129
130 /* If the port is getting full or it has dropped data
131 * start pacing ourselves, not necessary but it's friendly.
132 */
133 if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET))
134 dbgp_breath();
Stefan Reinauer14e22772010-04-27 06:56:47 +0000135
Yinghai Lud57241f2007-02-28 11:17:02 +0000136 /* If I get a NACK reissue the transmission */
137 if (lpid == USB_PID_NAK) {
138 if (--loop > 0) goto retry;
139 }
140
141 return ret;
142}
143
144static void dbgp_set_data(struct ehci_dbg_port *ehci_debug, const void *buf, int size)
145{
146 const unsigned char *bytes = buf;
147 unsigned lo, hi;
148 int i;
149 lo = hi = 0;
150 for (i = 0; i < 4 && i < size; i++)
151 lo |= bytes[i] << (8*i);
152 for (; i < 8 && i < size; i++)
153 hi |= bytes[i] << (8*(i - 4));
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000154 write32(&ehci_debug->data03, lo);
155 write32(&ehci_debug->data47, hi);
Yinghai Lud57241f2007-02-28 11:17:02 +0000156}
157
158static void dbgp_get_data(struct ehci_dbg_port *ehci_debug, void *buf, int size)
159{
160 unsigned char *bytes = buf;
161 unsigned lo, hi;
162 int i;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000163 lo = read32(&ehci_debug->data03);
164 hi = read32(&ehci_debug->data47);
Yinghai Lud57241f2007-02-28 11:17:02 +0000165 for (i = 0; i < 4 && i < size; i++)
166 bytes[i] = (lo >> (8*i)) & 0xff;
167 for (; i < 8 && i < size; i++)
168 bytes[i] = (hi >> (8*(i - 4))) & 0xff;
169}
170
171static int dbgp_bulk_write(struct ehci_dbg_port *ehci_debug, unsigned devnum, unsigned endpoint, const char *bytes, int size)
172{
173 unsigned pids, addr, ctrl;
174 int ret;
175 if (size > DBGP_MAX_PACKET)
176 return -1;
177
178 addr = DBGP_EPADDR(devnum, endpoint);
179
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000180 pids = read32(&ehci_debug->pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000181 pids = DBGP_PID_UPDATE(pids, USB_PID_OUT);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000182
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000183 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000184 ctrl = DBGP_LEN_UPDATE(ctrl, size);
185 ctrl |= DBGP_OUT;
186 ctrl |= DBGP_GO;
187
188 dbgp_set_data(ehci_debug, bytes, size);
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000189 write32(&ehci_debug->address, addr);
190 write32(&ehci_debug->pids, pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000191
192 ret = dbgp_wait_until_done(ehci_debug, ctrl);
193 if (ret < 0) {
194 return ret;
195 }
196 return ret;
197}
198
199int dbgp_bulk_write_x(struct ehci_debug_info *dbg_info, const char *bytes, int size)
200{
201 return dbgp_bulk_write(dbg_info->ehci_debug, dbg_info->devnum, dbg_info->endpoint_out, bytes, size);
202}
203
204static int dbgp_bulk_read(struct ehci_dbg_port *ehci_debug, unsigned devnum, unsigned endpoint, void *data, int size)
205{
206 unsigned pids, addr, ctrl;
207 int ret;
208
209 if (size > DBGP_MAX_PACKET)
210 return -1;
211
212 addr = DBGP_EPADDR(devnum, endpoint);
213
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000214 pids = read32(&ehci_debug->pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000215 pids = DBGP_PID_UPDATE(pids, USB_PID_IN);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000216
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000217 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000218 ctrl = DBGP_LEN_UPDATE(ctrl, size);
219 ctrl &= ~DBGP_OUT;
220 ctrl |= DBGP_GO;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000221
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000222 write32(&ehci_debug->address, addr);
223 write32(&ehci_debug->pids, pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000224 ret = dbgp_wait_until_done(ehci_debug, ctrl);
225 if (ret < 0)
226 return ret;
227 if (size > ret)
228 size = ret;
229 dbgp_get_data(ehci_debug, data, size);
230 return ret;
231}
232int dbgp_bulk_read_x(struct ehci_debug_info *dbg_info, void *data, int size)
233{
234 return dbgp_bulk_read(dbg_info->ehci_debug, dbg_info->devnum, dbg_info->endpoint_in, data, size);
235}
236
Stefan Reinauer14e22772010-04-27 06:56:47 +0000237static int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, int requesttype, int request,
Yinghai Lud57241f2007-02-28 11:17:02 +0000238 int value, int index, void *data, int size)
239{
240 unsigned pids, addr, ctrl;
241 struct usb_ctrlrequest req;
242 int read;
243 int ret;
244
245 read = (requesttype & USB_DIR_IN) != 0;
246 if (size > (read?DBGP_MAX_PACKET:0))
247 return -1;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000248
Yinghai Lud57241f2007-02-28 11:17:02 +0000249 /* Compute the control message */
250 req.bRequestType = requesttype;
251 req.bRequest = request;
252 req.wValue = value;
253 req.wIndex = index;
254 req.wLength = size;
255
256 pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP);
257 addr = DBGP_EPADDR(devnum, 0);
258
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000259 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000260 ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req));
261 ctrl |= DBGP_OUT;
262 ctrl |= DBGP_GO;
263
264 /* Send the setup message */
265 dbgp_set_data(ehci_debug, &req, sizeof(req));
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000266 write32(&ehci_debug->address, addr);
267 write32(&ehci_debug->pids, pids);
Yinghai Lud57241f2007-02-28 11:17:02 +0000268 ret = dbgp_wait_until_done(ehci_debug, ctrl);
269 if (ret < 0)
270 return ret;
271
272
273 /* Read the result */
274 ret = dbgp_bulk_read(ehci_debug, devnum, 0, data, size);
275 return ret;
276}
277
278static int ehci_reset_port(struct ehci_regs *ehci_regs, int port)
279{
280 unsigned portsc;
281 unsigned delay_time, delay;
282 int loop;
283
284 /* Reset the usb debug port */
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000285 portsc = read32(&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000286 portsc &= ~PORT_PE;
287 portsc |= PORT_RESET;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000288 write32(&ehci_regs->port_status[port - 1], portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000289
290 delay = HUB_ROOT_RESET_TIME;
291 for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT;
292 delay_time += delay) {
293 dbgp_mdelay(delay);
294
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000295 portsc = read32(&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000296 if (portsc & PORT_RESET) {
297 /* force reset to complete */
298 loop = 2;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000299 write32(&ehci_regs->port_status[port - 1],
300 portsc & ~(PORT_RWC_BITS | PORT_RESET));
Stefan Reinauer14e22772010-04-27 06:56:47 +0000301 do {
Yinghai Lud57241f2007-02-28 11:17:02 +0000302 dbgp_mdelay(delay);
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000303 portsc = read32(&ehci_regs->port_status[port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000304 delay_time += delay;
305 } while ((portsc & PORT_RESET) && (--loop > 0));
306 if (!loop) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000307 printk(BIOS_DEBUG, "ehci_reset_port forced done");
Yinghai Lud57241f2007-02-28 11:17:02 +0000308 }
309 }
310
311 /* Device went away? */
312 if (!(portsc & PORT_CONNECT))
313 return -107;//-ENOTCONN;
314
315 /* bomb out completely if something weird happend */
316 if ((portsc & PORT_CSC))
317 return -22;//-EINVAL;
318
319 /* If we've finished resetting, then break out of the loop */
320 if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
321 return 0;
322 }
323 return -16;//-EBUSY;
324}
325
326static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port)
327{
328 unsigned status;
329 int ret, reps;
330 for (reps = 0; reps < 3; reps++) {
331 dbgp_mdelay(100);
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000332 status = read32(&ehci_regs->status);
Yinghai Lud57241f2007-02-28 11:17:02 +0000333 if (status & STS_PCD) {
334 ret = ehci_reset_port(ehci_regs, port);
335 if (ret == 0)
336 return 0;
337 }
338 }
339 return -107; //-ENOTCONN;
340}
341
342
343#define DBGP_DEBUG 1
344#if DBGP_DEBUG
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000345# define dbgp_printk(fmt, arg...) printk(BIOS_DEBUG, fmt, arg)
Yinghai Lud57241f2007-02-28 11:17:02 +0000346#else
347#define dbgp_printk(fmt, arg...) do {} while(0)
348#endif
349static void usbdebug_direct_init(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info)
350{
351 struct ehci_caps *ehci_caps;
352 struct ehci_regs *ehci_regs;
353 struct ehci_dbg_port *ehci_debug;
354 unsigned dbgp_endpoint_out;
355 unsigned dbgp_endpoint_in;
356 struct usb_debug_descriptor dbgp_desc;
357 unsigned ctrl, devnum;
358 int ret;
359 unsigned delay_time, delay;
360 int loop;
361
362 unsigned cmd, status, portsc, hcs_params, debug_port, n_ports, new_debug_port;
363 int i;
364 unsigned port_map_tried;
365
366 unsigned playtimes = 3;
367
368 ehci_caps = (struct ehci_caps *)ehci_bar;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000369 ehci_regs = (struct ehci_regs *)(ehci_bar + HC_LENGTH(read32(&ehci_caps->hc_capbase)));
Yinghai Lud57241f2007-02-28 11:17:02 +0000370 ehci_debug = (struct ehci_dbg_port *)(ehci_bar + offset);
371
372 info->ehci_debug = (void *)0;
373
374try_next_time:
375 port_map_tried = 0;
376
377try_next_port:
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000378 hcs_params = read32(&ehci_caps->hcs_params);
Yinghai Lud57241f2007-02-28 11:17:02 +0000379 debug_port = HCS_DEBUG_PORT(hcs_params);
380 n_ports = HCS_N_PORTS(hcs_params);
381
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000382 dbgp_printk("ehci_bar: 0x%x\n", ehci_bar);
Yinghai Lud57241f2007-02-28 11:17:02 +0000383 dbgp_printk("debug_port: %d\n", debug_port);
384 dbgp_printk("n_ports: %d\n", n_ports);
385
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000386#if 1
Yinghai Lud57241f2007-02-28 11:17:02 +0000387 for (i = 1; i <= n_ports; i++) {
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000388 portsc = read32(&ehci_regs->port_status[i-1]);
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000389 dbgp_printk("PORTSC #%d: %08x\n", i, portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000390 }
391#endif
392
393 if(port_map_tried && (new_debug_port!=debug_port)) {
394 if(--playtimes) {
395 set_debug_port(debug_port);
396 goto try_next_time;
397 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000398 return;
Yinghai Lud57241f2007-02-28 11:17:02 +0000399 }
400
401 /* Reset the EHCI controller */
402 loop = 10;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000403 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000404 cmd |= CMD_RESET;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000405 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000406 do {
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000407 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000408 } while ((cmd & CMD_RESET) && (--loop > 0));
409
Stefan Reinauerb53bed12009-10-24 13:02:14 +0000410 if(!loop)
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000411 dbgp_printk("Could not reset EHCI controller.\n");
Stefan Reinauerb53bed12009-10-24 13:02:14 +0000412 else
413 dbgp_printk("EHCI controller reset successfully.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000414
415 /* Claim ownership, but do not enable yet */
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000416 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000417 ctrl |= DBGP_OWNER;
418 ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000419 write32(&ehci_debug->control, ctrl);
Yinghai Lud57241f2007-02-28 11:17:02 +0000420
421 /* Start the ehci running */
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000422 cmd = read32(&ehci_regs->command);
Yinghai Lud57241f2007-02-28 11:17:02 +0000423 cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
424 cmd |= CMD_RUN;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000425 write32(&ehci_regs->command, cmd);
Yinghai Lud57241f2007-02-28 11:17:02 +0000426
427 /* Ensure everything is routed to the EHCI */
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000428 write32(&ehci_regs->configured_flag, FLAG_CF);
Yinghai Lud57241f2007-02-28 11:17:02 +0000429
430 /* Wait until the controller is no longer halted */
431 loop = 10;
432 do {
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000433 status = read32(&ehci_regs->status);
Yinghai Lud57241f2007-02-28 11:17:02 +0000434 } while ((status & STS_HALT) && (--loop>0));
435
436 if(!loop) {
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000437 dbgp_printk("EHCI could not be started.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000438 return;
439 }
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000440 dbgp_printk("EHCI started.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000441
442 /* Wait for a device to show up in the debug port */
443 ret = ehci_wait_for_port(ehci_regs, debug_port);
444 if (ret < 0) {
445 dbgp_printk("No device found in debug port %d\n", debug_port);
446 goto next_debug_port;
447 }
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000448 dbgp_printk("EHCI done waiting for port.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000449
450 /* Enable the debug port */
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000451 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000452 ctrl |= DBGP_CLAIM;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000453 write32(&ehci_debug->control, ctrl);
454 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000455 if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000456 dbgp_printk("No device in EHCI debug port.\n");
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000457 write32(&ehci_debug->control, ctrl & ~DBGP_CLAIM);
Yinghai Lud57241f2007-02-28 11:17:02 +0000458 goto err;
459 }
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000460 dbgp_printk("EHCI debug port enabled.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000461
462 /* Completely transfer the debug device to the debug controller */
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000463 portsc = read32(&ehci_regs->port_status[debug_port - 1]);
Yinghai Lud57241f2007-02-28 11:17:02 +0000464 portsc &= ~PORT_PE;
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000465 write32(&ehci_regs->port_status[debug_port - 1], portsc);
Yinghai Lud57241f2007-02-28 11:17:02 +0000466
467 dbgp_mdelay(100);
468
469 /* Find the debug device and make it device number 127 */
470 for (devnum = 0; devnum <= 127; devnum++) {
471 ret = dbgp_control_msg(ehci_debug, devnum,
472 USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
473 USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
474 &dbgp_desc, sizeof(dbgp_desc));
475 if (ret > 0)
476 break;
477 }
478 if (devnum > 127) {
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000479 dbgp_printk("Could not find attached debug device.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000480 goto err;
481 }
482 if (ret < 0) {
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000483 dbgp_printk("Attached device is not a debug device.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000484 goto err;
485 }
486 dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint;
487 dbgp_endpoint_in = dbgp_desc.bDebugInEndpoint;
488
489 /* Move the device to 127 if it isn't already there */
490 if (devnum != USB_DEBUG_DEVNUM) {
491 ret = dbgp_control_msg(ehci_debug, devnum,
492 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
493 USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, (void *)0, 0);
494 if (ret < 0) {
Stefan Reinauer14e22772010-04-27 06:56:47 +0000495 dbgp_printk("Could not move attached device to %d.\n",
Yinghai Lud57241f2007-02-28 11:17:02 +0000496 USB_DEBUG_DEVNUM);
497 goto err;
498 }
499 devnum = USB_DEBUG_DEVNUM;
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000500 dbgp_printk("EHCI debug device renamed to 127.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000501 }
502
503 /* Enable the debug interface */
504 ret = dbgp_control_msg(ehci_debug, USB_DEBUG_DEVNUM,
505 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
506 USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, (void *)0, 0);
507 if (ret < 0) {
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000508 dbgp_printk("Could not enable EHCI debug device.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000509 goto err;
510 }
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000511 dbgp_printk("EHCI debug interface enabled.\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000512
513 /* Perform a small write to get the even/odd data state in sync
514 */
515 ret = dbgp_bulk_write(ehci_debug, USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ",1);
516 if (ret < 0) {
517 dbgp_printk("dbgp_bulk_write failed: %d\n", ret);
518 goto err;
519 }
Stefan Reinauer7e16bf32009-04-21 23:05:13 +0000520 dbgp_printk("Test write done\n");
Yinghai Lud57241f2007-02-28 11:17:02 +0000521
522 info->ehci_caps = ehci_caps;
523 info->ehci_regs = ehci_regs;
524 info->ehci_debug = ehci_debug;
525 info->devnum = devnum;
526 info->endpoint_out = dbgp_endpoint_out;
527 info->endpoint_in = dbgp_endpoint_in;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000528
Yinghai Lud57241f2007-02-28 11:17:02 +0000529 return;
530err:
531 /* Things didn't work so remove my claim */
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000532 ctrl = read32(&ehci_debug->control);
Yinghai Lud57241f2007-02-28 11:17:02 +0000533 ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
Stefan Reinauer9fe4d792010-01-16 17:53:38 +0000534 write32(&ehci_debug->control, ctrl);
Yinghai Lud57241f2007-02-28 11:17:02 +0000535
536next_debug_port:
537 port_map_tried |= (1<<(debug_port-1));
538 if(port_map_tried != ((1<<n_ports) -1)) {
539 new_debug_port = ((debug_port-1+1)%n_ports) + 1;
540 set_debug_port(new_debug_port);
541 goto try_next_port;
542 }
543 if(--playtimes) {
544 set_debug_port(debug_port);
545 goto try_next_time;
546 }
547
548}
549
550