blob: 2451cf96e8795eab1f1730c0d89d84d5303e2d7f [file] [log] [blame]
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +020012 */
13
14#include <stddef.h>
15#include <console/console.h>
Kyösti Mälkki46249be22014-10-27 14:07:28 +020016#include <string.h>
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +020017
18#include "ehci_debug.h"
19#include "usb_ch9.h"
20#include "ehci.h"
21
Kyösti Mälkki46249be22014-10-27 14:07:28 +020022#define dprintk printk
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +020023
24#define USB_HUB_PORT_CONNECTION 0
25#define USB_HUB_PORT_ENABLED 1
26#define USB_HUB_PORT_RESET 4
27#define USB_HUB_PORT_POWER 8
28#define USB_HUB_C_PORT_CONNECTION 16
29#define USB_HUB_C_PORT_RESET 20
30
31
32static int hub_port_status(const char * buf, int feature)
33{
34 return !!(buf[feature>>3] & (1<<(feature&0x7)));
35}
36
37/* After USB port reset, treat device number 0 as an USB hub. Assign it with
38 * a device number hub_addr. Then apply enable and reset on downstream port.
39 */
40 static int dbgp_hub_enable(struct ehci_dbg_port *ehci_debug, unsigned char hub_addr,
41 unsigned char port)
42{
43 char status[8];
44 int ret, loop;
45
46 /* Assign a devicenumber for the hub. */
47 ret = dbgp_control_msg(ehci_debug, 0,
48 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
49 USB_REQ_SET_ADDRESS, hub_addr, 0, NULL, 0);
50 if (ret < 0)
51 goto err;
52
53 /* Enter configured state on hub. */
54 ret = dbgp_control_msg(ehci_debug, hub_addr,
55 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
56 USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0);
57 if (ret < 0)
58 goto err;
59
60 /* Set PORT_POWER, poll for PORT_CONNECTION. */
61 ret = dbgp_control_msg(ehci_debug, hub_addr,
62 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
63 USB_REQ_SET_FEATURE, USB_HUB_PORT_POWER, port, NULL, 0);
64 if (ret < 0)
65 goto err;
66
67 loop = 100;
68 do {
69 dbgp_mdelay(10);
70 ret = dbgp_control_msg(ehci_debug, hub_addr,
71 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER,
72 USB_REQ_GET_STATUS, 0, port, status, 4);
73 if (ret < 0)
74 goto err;
75 if (hub_port_status(status, USB_HUB_PORT_CONNECTION))
76 break;
77 } while (--loop);
78 if (! loop)
79 goto err;
80
81 ret = dbgp_control_msg(ehci_debug, hub_addr,
82 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
83 USB_REQ_CLEAR_FEATURE, USB_HUB_C_PORT_CONNECTION, port, NULL, 0);
84 if (ret < 0)
85 goto err;
86
87
88 /* Set PORT_RESET, poll for C_PORT_RESET. */
89 ret = dbgp_control_msg(ehci_debug, hub_addr,
90 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
91 USB_REQ_SET_FEATURE, USB_HUB_PORT_RESET, port, NULL, 0);
92 if (ret < 0)
93 goto err;
94
95 loop = 100;
96 do {
97 dbgp_mdelay(10);
98 ret = dbgp_control_msg(ehci_debug, hub_addr,
99 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER,
100 USB_REQ_GET_STATUS, 0, port, status, 4);
101 if (ret < 0)
102 goto err;
103 if (hub_port_status(status, USB_HUB_C_PORT_RESET))
104 break;
105 } while (--loop);
106 if (! loop)
107 goto err;
108
109 ret = dbgp_control_msg(ehci_debug, hub_addr,
110 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
111 USB_REQ_CLEAR_FEATURE, USB_HUB_C_PORT_RESET, port, NULL, 0);
112 if (ret < 0)
113 goto err;
114
115 if (hub_port_status(status, USB_HUB_PORT_ENABLED))
116 return 0;
117err:
118 return -1;
119}
120
Kyösti Mälkki46249be22014-10-27 14:07:28 +0200121static void ack_set_configuration(struct dbgp_pipe *pipe, u8 devnum, int timeout)
122{
123 int i = DBGP_SETUP_EP0;
124 while (++i < DBGP_MAX_ENDPOINTS) {
125 if (pipe[i].endpoint != 0) {
126 pipe[i].devnum = devnum;
127 pipe[i].pid = USB_PID_DATA0;
128 pipe[i].timeout = timeout;
129 }
130 }
131}
132
133static void activate_endpoints(struct dbgp_pipe *pipe)
134{
135 int i = DBGP_SETUP_EP0;
136 pipe[i].status |= DBGP_EP_ENABLED | DBGP_EP_VALID;
137 while (++i < DBGP_MAX_ENDPOINTS) {
138 if (pipe[i].endpoint != 0)
139 pipe[i].status |= DBGP_EP_ENABLED | DBGP_EP_VALID;
140 }
141}
142
143static int probe_for_debug_descriptor(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe)
144{
145 struct usb_debug_descriptor dbgp_desc;
146 int configured = 0, ret;
147 u8 devnum = 0;
148
149 /* Find the debug device and make it device number 127 */
150debug_dev_retry:
151 memset(&dbgp_desc, 0, sizeof(dbgp_desc));
152 ret = dbgp_control_msg(ehci_debug, devnum,
153 USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
154 USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
155 &dbgp_desc, sizeof(dbgp_desc));
156 if (ret == sizeof(dbgp_desc)) {
157 if (dbgp_desc.bLength == sizeof(dbgp_desc) && dbgp_desc.bDescriptorType==USB_DT_DEBUG)
158 goto debug_dev_found;
159 else
160 dprintk(BIOS_INFO, "Invalid debug device descriptor.\n");
161 }
162 if (devnum == 0) {
163 devnum = USB_DEBUG_DEVNUM;
164 goto debug_dev_retry;
165 } else {
166 dprintk(BIOS_INFO, "Could not find attached debug device.\n");
167 return -1;
168 }
169debug_dev_found:
170
171 /* Move the device to 127 if it isn't already there */
172 if (devnum != USB_DEBUG_DEVNUM) {
173 ret = dbgp_control_msg(ehci_debug, devnum,
174 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
175 USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0);
176 if (ret < 0) {
177 dprintk(BIOS_INFO, "Could not move attached device to %d.\n",
178 USB_DEBUG_DEVNUM);
179 return -2;
180 }
181 devnum = USB_DEBUG_DEVNUM;
182 dprintk(BIOS_INFO, "EHCI debug device renamed to 127.\n");
183 }
184
185 /* Enable the debug interface */
186 ret = dbgp_control_msg(ehci_debug, USB_DEBUG_DEVNUM,
187 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
188 USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0);
189 if (ret < 0) {
190 dprintk(BIOS_INFO, "Could not enable EHCI debug device.\n");
191 return -3;
192 }
193 dprintk(BIOS_INFO, "EHCI debug interface enabled.\n");
194
195 pipe[DBGP_CONSOLE_EPOUT].endpoint = dbgp_desc.bDebugOutEndpoint;
196 pipe[DBGP_CONSOLE_EPIN].endpoint = dbgp_desc.bDebugInEndpoint;
197
198 ack_set_configuration(pipe, devnum, 1000);
199
200 /* Perform a small write. */
201 configured = 0;
202small_write:
203 ret = dbgp_bulk_write_x(&pipe[DBGP_CONSOLE_EPOUT], "USB\r\n",5);
204 if (ret < 0) {
205 dprintk(BIOS_INFO, "dbgp_bulk_write failed: %d\n", ret);
206 if (!configured) {
207 /* Send Set Configure request to device. This is required for FX2
208 (CY7C68013) to transfer from USB state Addressed to Configured,
209 only then endpoints other than 0 are enabled. */
210 if (dbgp_control_msg(ehci_debug, USB_DEBUG_DEVNUM,
211 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
212 USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0) >= 0) {
213 configured = 1;
214 goto small_write;
215 }
216 }
217 return -4;
218 }
219 dprintk(BIOS_INFO, "Test write done\n");
220 return 0;
221}
222
Kyösti Mälkkicc4d3092015-05-03 06:27:11 +0300223/* FTDI FT232H UART programming. */
224#define FTDI_SIO_SET_FLOW_CTRL_REQUEST 0x02
225#define FTDI_SIO_SET_BAUDRATE_REQUEST 0x03
226#define FTDI_SIO_SET_DATA_REQUEST 0x04
227#define FTDI_SIO_SET_BITMODE_REQUEST 0x0b
228
229static int probe_for_ftdi(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe)
230{
231 int ret;
232 u8 devnum = 0;
233 u8 uart_if = 1; /* FTDI_INTERFACE_A 1 */
234
235 /* Move the device to 127 if it isn't already there */
236 ret = dbgp_control_msg(ehci_debug, devnum,
237 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
238 USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0);
239 if (ret < 0) {
240 dprintk(BIOS_INFO, "Could not move attached device to %d.\n",
241 USB_DEBUG_DEVNUM);
242 return -2;
243 }
244 devnum = USB_DEBUG_DEVNUM;
245 dprintk(BIOS_INFO, "EHCI debug device renamed to %d.\n", devnum);
246
247 /* Send Set Configure request to device. */
248 ret = dbgp_control_msg(ehci_debug, devnum,
249 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
250 USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0);
251 if (ret < 0) {
252 dprintk(BIOS_INFO, "FTDI set configuration failed.\n");
253 return -2;
254 }
255
256 ret = dbgp_control_msg(ehci_debug, devnum,
257 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
258 FTDI_SIO_SET_BITMODE_REQUEST, 0, uart_if, NULL, 0);
259 if (ret < 0) {
260 dprintk(BIOS_INFO, "FTDI SET_BITMODE failed.\n");
261 return -3;
262 }
263 ret = dbgp_control_msg(ehci_debug, devnum,
264 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
265 FTDI_SIO_SET_BAUDRATE_REQUEST,
266 0xc068, 0x0200 | uart_if, NULL, 0);
267 if (ret < 0) {
268 dprintk(BIOS_INFO, "FTDI SET_BAUDRATE failed.\n");
269 return -3;
270 }
271 ret = dbgp_control_msg(ehci_debug, devnum,
272 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
273 FTDI_SIO_SET_DATA_REQUEST,
274 0x0008, uart_if, NULL, 0);
275 if (ret < 0) {
276 dprintk(BIOS_INFO, "FTDI SET_DATA failed.\n");
277 return -3;
278 }
279 ret = dbgp_control_msg(ehci_debug, devnum,
280 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
281 FTDI_SIO_SET_FLOW_CTRL_REQUEST,
282 0x0000, uart_if, NULL, 0);
283 if (ret < 0) {
284 dprintk(BIOS_INFO, "FTDI SET_FLOW_CTRL failed.\n");
285 return -3;
286 }
287
288 pipe[DBGP_CONSOLE_EPOUT].endpoint = 0x02;
289 pipe[DBGP_CONSOLE_EPIN].endpoint = 0x81;
290
291 ack_set_configuration(pipe, devnum, 1000);
292
293 /* Perform a small write. */
294 ret = dbgp_bulk_write_x(&pipe[DBGP_CONSOLE_EPOUT], "USB\r\n", 5);
295 if (ret < 0) {
296 dprintk(BIOS_INFO, "dbgp_bulk_write failed: %d\n", ret);
297 return -4;
298 }
299 dprintk(BIOS_INFO, "Test write done\n");
300 return 0;
301}
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200302
303int dbgp_probe_gadget(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe)
304{
305 int ret;
306
307 if (CONFIG_USBDEBUG_OPTIONAL_HUB_PORT != 0) {
308 ret = dbgp_hub_enable(ehci_debug, USB_DEBUG_DEVNUM-1,
309 CONFIG_USBDEBUG_OPTIONAL_HUB_PORT);
310 if (ret < 0) {
311 printk(BIOS_INFO, "Could not enable USB hub on debug port.\n");
312 return ret;
313 }
314 }
315
Kyösti Mälkkicc4d3092015-05-03 06:27:11 +0300316 if (IS_ENABLED(CONFIG_USBDEBUG_DONGLE_FTDI_FT232H)) {
317 ret = probe_for_ftdi(ehci_debug, pipe);
318 } else {
319 ret = probe_for_debug_descriptor(ehci_debug, pipe);
320 }
Kyösti Mälkki46249be22014-10-27 14:07:28 +0200321 if (ret < 0) {
Kyösti Mälkkicc4d3092015-05-03 06:27:11 +0300322 dprintk(BIOS_INFO, "Could not enable debug dongle.\n");
Kyösti Mälkki46249be22014-10-27 14:07:28 +0200323 return ret;
324 }
325
326 activate_endpoints(pipe);
Kyösti Mälkki83fe6d72014-02-25 20:11:52 +0200327 return 0;
328}