usbdebug: Refactor descriptor probing of dongle
Organized such that it is easy to support devices that do not export special Debug Descriptor. Some of these can still work in a fixed configuration and/or require additional initialisation for UART clocks etc. Change-Id: Id07fd6b69007332d67d9e9a456f58fdbca1999cd Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: http://review.coreboot.org/7209 Reviewed-by: Nico Huber <nico.h@gmx.de> Tested-by: build bot (Jenkins)
This commit is contained in:
parent
83fe6d7fd2
commit
46249be267
|
@ -31,11 +31,6 @@
|
||||||
#include "usb_ch9.h"
|
#include "usb_ch9.h"
|
||||||
#include "ehci.h"
|
#include "ehci.h"
|
||||||
|
|
||||||
#define DBGP_MAX_ENDPOINTS 4
|
|
||||||
#define DBGP_SETUP_EP0 0 /* Compulsory endpoint 0. */
|
|
||||||
#define DBGP_CONSOLE_EPOUT 1
|
|
||||||
#define DBGP_CONSOLE_EPIN 2
|
|
||||||
|
|
||||||
struct ehci_debug_info {
|
struct ehci_debug_info {
|
||||||
void *ehci_base;
|
void *ehci_base;
|
||||||
void *ehci_debug;
|
void *ehci_debug;
|
||||||
|
@ -54,33 +49,7 @@ static int dbgp_enabled(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))
|
#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))
|
||||||
/*
|
|
||||||
* USB Packet IDs (PIDs)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* token */
|
|
||||||
#define USB_PID_OUT 0xe1
|
|
||||||
#define USB_PID_IN 0x69
|
|
||||||
#define USB_PID_SOF 0xa5
|
|
||||||
#define USB_PID_SETUP 0x2d
|
|
||||||
/* handshake */
|
|
||||||
#define USB_PID_ACK 0xd2
|
|
||||||
#define USB_PID_NAK 0x5a
|
|
||||||
#define USB_PID_STALL 0x1e
|
|
||||||
#define USB_PID_NYET 0x96
|
|
||||||
/* data */
|
|
||||||
#define USB_PID_DATA0 0xc3
|
|
||||||
#define USB_PID_DATA1 0x4b
|
|
||||||
#define USB_PID_DATA2 0x87
|
|
||||||
#define USB_PID_MDATA 0x0f
|
|
||||||
/* Special */
|
|
||||||
#define USB_PID_PREAMBLE 0x3c
|
|
||||||
#define USB_PID_ERR 0x3c
|
|
||||||
#define USB_PID_SPLIT 0x78
|
|
||||||
#define USB_PID_PING 0xb4
|
|
||||||
#define USB_PID_UNDEF_0 0xf0
|
|
||||||
|
|
||||||
#define USB_PID_DATA_TOGGLE 0x88
|
|
||||||
#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
|
#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
|
||||||
|
|
||||||
#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
|
#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
|
||||||
|
@ -465,11 +434,9 @@ static int usbdebug_init_(unsigned ehci_bar, unsigned offset, struct ehci_debug_
|
||||||
struct ehci_caps *ehci_caps;
|
struct ehci_caps *ehci_caps;
|
||||||
struct ehci_regs *ehci_regs;
|
struct ehci_regs *ehci_regs;
|
||||||
|
|
||||||
struct usb_debug_descriptor dbgp_desc;
|
|
||||||
u32 cmd, ctrl, status, portsc, hcs_params;
|
u32 cmd, ctrl, status, portsc, hcs_params;
|
||||||
u32 debug_port, new_debug_port = 0, n_ports;
|
u32 debug_port, new_debug_port = 0, n_ports;
|
||||||
u32 devnum;
|
int ret, i;
|
||||||
int ret, i, configured;
|
|
||||||
int loop;
|
int loop;
|
||||||
int port_map_tried;
|
int port_map_tried;
|
||||||
int playtimes = 3;
|
int playtimes = 3;
|
||||||
|
@ -615,90 +582,6 @@ try_next_port:
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the debug device and make it device number 127 */
|
|
||||||
devnum = 0;
|
|
||||||
debug_dev_retry:
|
|
||||||
memset(&dbgp_desc, 0, sizeof(dbgp_desc));
|
|
||||||
ret = dbgp_control_msg(ehci_debug, devnum,
|
|
||||||
USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
|
|
||||||
USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
|
|
||||||
&dbgp_desc, sizeof(dbgp_desc));
|
|
||||||
if (ret == sizeof(dbgp_desc)) {
|
|
||||||
if (dbgp_desc.bLength == sizeof(dbgp_desc) && dbgp_desc.bDescriptorType==USB_DT_DEBUG)
|
|
||||||
goto debug_dev_found;
|
|
||||||
else
|
|
||||||
dprintk(BIOS_INFO, "Invalid debug device descriptor.\n");
|
|
||||||
}
|
|
||||||
if (devnum == 0) {
|
|
||||||
devnum = USB_DEBUG_DEVNUM;
|
|
||||||
goto debug_dev_retry;
|
|
||||||
} else {
|
|
||||||
dprintk(BIOS_INFO, "Could not find attached debug device.\n");
|
|
||||||
ret = -5;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
debug_dev_found:
|
|
||||||
|
|
||||||
/* Move the device to 127 if it isn't already there */
|
|
||||||
if (devnum != USB_DEBUG_DEVNUM) {
|
|
||||||
ret = dbgp_control_msg(ehci_debug, devnum,
|
|
||||||
USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
|
|
||||||
USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
dprintk(BIOS_INFO, "Could not move attached device to %d.\n",
|
|
||||||
USB_DEBUG_DEVNUM);
|
|
||||||
ret = -7;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
devnum = USB_DEBUG_DEVNUM;
|
|
||||||
dprintk(BIOS_INFO, "EHCI debug device renamed to 127.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable the debug interface */
|
|
||||||
ret = dbgp_control_msg(ehci_debug, USB_DEBUG_DEVNUM,
|
|
||||||
USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
|
|
||||||
USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
dprintk(BIOS_INFO, "Could not enable EHCI debug device.\n");
|
|
||||||
ret = -8;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
dprintk(BIOS_INFO, "EHCI debug interface enabled.\n");
|
|
||||||
|
|
||||||
/* Prepare endpoint pipes. */
|
|
||||||
for (i=1; i<DBGP_MAX_ENDPOINTS; i++) {
|
|
||||||
info->ep_pipe[i].devnum = USB_DEBUG_DEVNUM;
|
|
||||||
info->ep_pipe[i].pid = USB_PID_DATA0;
|
|
||||||
info->ep_pipe[i].timeout = 1000;
|
|
||||||
}
|
|
||||||
info->ep_pipe[DBGP_CONSOLE_EPOUT].endpoint = dbgp_desc.bDebugOutEndpoint;
|
|
||||||
info->ep_pipe[DBGP_CONSOLE_EPIN].endpoint = dbgp_desc.bDebugInEndpoint;
|
|
||||||
|
|
||||||
/* Perform a small write. */
|
|
||||||
configured = 0;
|
|
||||||
small_write:
|
|
||||||
ret = dbgp_bulk_write(ehci_debug, &info->ep_pipe[DBGP_CONSOLE_EPOUT], "USB\r\n",5);
|
|
||||||
if (ret < 0) {
|
|
||||||
dprintk(BIOS_INFO, "dbgp_bulk_write failed: %d\n", ret);
|
|
||||||
if (!configured) {
|
|
||||||
/* Send Set Configure request to device. This is required for FX2
|
|
||||||
(CY7C68013) to transfer from USB state Addressed to Configured,
|
|
||||||
only then endpoints other than 0 are enabled. */
|
|
||||||
if (dbgp_control_msg(ehci_debug, USB_DEBUG_DEVNUM,
|
|
||||||
USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
|
|
||||||
USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0) >= 0) {
|
|
||||||
configured = 1;
|
|
||||||
goto small_write;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = -9;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
dprintk(BIOS_INFO, "Test write done\n");
|
|
||||||
|
|
||||||
info->ep_pipe[DBGP_SETUP_EP0].status |= DBGP_EP_ENABLED | DBGP_EP_VALID;
|
|
||||||
info->ep_pipe[DBGP_CONSOLE_EPOUT].status |= DBGP_EP_ENABLED | DBGP_EP_VALID;
|
|
||||||
info->ep_pipe[DBGP_CONSOLE_EPIN].status |= DBGP_EP_ENABLED | DBGP_EP_VALID;
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
/* Things didn't work so remove my claim */
|
/* Things didn't work so remove my claim */
|
||||||
|
|
|
@ -37,6 +37,11 @@ void ehci_debug_select_port(unsigned int port);
|
||||||
#define DBGP_EP_BUSY (1<<2)
|
#define DBGP_EP_BUSY (1<<2)
|
||||||
#define DBGP_EP_STATMASK (DBGP_EP_VALID | DBGP_EP_ENABLED)
|
#define DBGP_EP_STATMASK (DBGP_EP_VALID | DBGP_EP_ENABLED)
|
||||||
|
|
||||||
|
#define DBGP_MAX_ENDPOINTS 4
|
||||||
|
#define DBGP_SETUP_EP0 0 /* Compulsory endpoint 0. */
|
||||||
|
#define DBGP_CONSOLE_EPOUT 1
|
||||||
|
#define DBGP_CONSOLE_EPIN 2
|
||||||
|
|
||||||
struct ehci_dbg_port;
|
struct ehci_dbg_port;
|
||||||
|
|
||||||
struct dbgp_pipe
|
struct dbgp_pipe
|
||||||
|
|
|
@ -17,11 +17,13 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "ehci_debug.h"
|
#include "ehci_debug.h"
|
||||||
#include "usb_ch9.h"
|
#include "usb_ch9.h"
|
||||||
#include "ehci.h"
|
#include "ehci.h"
|
||||||
|
|
||||||
|
#define dprintk printk
|
||||||
|
|
||||||
#define USB_HUB_PORT_CONNECTION 0
|
#define USB_HUB_PORT_CONNECTION 0
|
||||||
#define USB_HUB_PORT_ENABLED 1
|
#define USB_HUB_PORT_ENABLED 1
|
||||||
|
@ -120,6 +122,108 @@ err:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ack_set_configuration(struct dbgp_pipe *pipe, u8 devnum, int timeout)
|
||||||
|
{
|
||||||
|
int i = DBGP_SETUP_EP0;
|
||||||
|
while (++i < DBGP_MAX_ENDPOINTS) {
|
||||||
|
if (pipe[i].endpoint != 0) {
|
||||||
|
pipe[i].devnum = devnum;
|
||||||
|
pipe[i].pid = USB_PID_DATA0;
|
||||||
|
pipe[i].timeout = timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void activate_endpoints(struct dbgp_pipe *pipe)
|
||||||
|
{
|
||||||
|
int i = DBGP_SETUP_EP0;
|
||||||
|
pipe[i].status |= DBGP_EP_ENABLED | DBGP_EP_VALID;
|
||||||
|
while (++i < DBGP_MAX_ENDPOINTS) {
|
||||||
|
if (pipe[i].endpoint != 0)
|
||||||
|
pipe[i].status |= DBGP_EP_ENABLED | DBGP_EP_VALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int probe_for_debug_descriptor(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe)
|
||||||
|
{
|
||||||
|
struct usb_debug_descriptor dbgp_desc;
|
||||||
|
int configured = 0, ret;
|
||||||
|
u8 devnum = 0;
|
||||||
|
|
||||||
|
/* Find the debug device and make it device number 127 */
|
||||||
|
debug_dev_retry:
|
||||||
|
memset(&dbgp_desc, 0, sizeof(dbgp_desc));
|
||||||
|
ret = dbgp_control_msg(ehci_debug, devnum,
|
||||||
|
USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
|
||||||
|
USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
|
||||||
|
&dbgp_desc, sizeof(dbgp_desc));
|
||||||
|
if (ret == sizeof(dbgp_desc)) {
|
||||||
|
if (dbgp_desc.bLength == sizeof(dbgp_desc) && dbgp_desc.bDescriptorType==USB_DT_DEBUG)
|
||||||
|
goto debug_dev_found;
|
||||||
|
else
|
||||||
|
dprintk(BIOS_INFO, "Invalid debug device descriptor.\n");
|
||||||
|
}
|
||||||
|
if (devnum == 0) {
|
||||||
|
devnum = USB_DEBUG_DEVNUM;
|
||||||
|
goto debug_dev_retry;
|
||||||
|
} else {
|
||||||
|
dprintk(BIOS_INFO, "Could not find attached debug device.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
debug_dev_found:
|
||||||
|
|
||||||
|
/* Move the device to 127 if it isn't already there */
|
||||||
|
if (devnum != USB_DEBUG_DEVNUM) {
|
||||||
|
ret = dbgp_control_msg(ehci_debug, devnum,
|
||||||
|
USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
|
||||||
|
USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
dprintk(BIOS_INFO, "Could not move attached device to %d.\n",
|
||||||
|
USB_DEBUG_DEVNUM);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
devnum = USB_DEBUG_DEVNUM;
|
||||||
|
dprintk(BIOS_INFO, "EHCI debug device renamed to 127.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable the debug interface */
|
||||||
|
ret = dbgp_control_msg(ehci_debug, USB_DEBUG_DEVNUM,
|
||||||
|
USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
|
||||||
|
USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
dprintk(BIOS_INFO, "Could not enable EHCI debug device.\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
dprintk(BIOS_INFO, "EHCI debug interface enabled.\n");
|
||||||
|
|
||||||
|
pipe[DBGP_CONSOLE_EPOUT].endpoint = dbgp_desc.bDebugOutEndpoint;
|
||||||
|
pipe[DBGP_CONSOLE_EPIN].endpoint = dbgp_desc.bDebugInEndpoint;
|
||||||
|
|
||||||
|
ack_set_configuration(pipe, devnum, 1000);
|
||||||
|
|
||||||
|
/* Perform a small write. */
|
||||||
|
configured = 0;
|
||||||
|
small_write:
|
||||||
|
ret = dbgp_bulk_write_x(&pipe[DBGP_CONSOLE_EPOUT], "USB\r\n",5);
|
||||||
|
if (ret < 0) {
|
||||||
|
dprintk(BIOS_INFO, "dbgp_bulk_write failed: %d\n", ret);
|
||||||
|
if (!configured) {
|
||||||
|
/* Send Set Configure request to device. This is required for FX2
|
||||||
|
(CY7C68013) to transfer from USB state Addressed to Configured,
|
||||||
|
only then endpoints other than 0 are enabled. */
|
||||||
|
if (dbgp_control_msg(ehci_debug, USB_DEBUG_DEVNUM,
|
||||||
|
USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
|
||||||
|
USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0) >= 0) {
|
||||||
|
configured = 1;
|
||||||
|
goto small_write;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
dprintk(BIOS_INFO, "Test write done\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int dbgp_probe_gadget(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe)
|
int dbgp_probe_gadget(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe)
|
||||||
{
|
{
|
||||||
|
@ -134,5 +238,12 @@ int dbgp_probe_gadget(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = probe_for_debug_descriptor(ehci_debug, pipe);
|
||||||
|
if (ret < 0) {
|
||||||
|
dprintk(BIOS_INFO, "Could not enable gadget using Debug Descriptor.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
activate_endpoints(pipe);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,34 @@
|
||||||
|
|
||||||
#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
|
#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Packet IDs (PIDs)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* token */
|
||||||
|
#define USB_PID_OUT 0xe1
|
||||||
|
#define USB_PID_IN 0x69
|
||||||
|
#define USB_PID_SOF 0xa5
|
||||||
|
#define USB_PID_SETUP 0x2d
|
||||||
|
/* handshake */
|
||||||
|
#define USB_PID_ACK 0xd2
|
||||||
|
#define USB_PID_NAK 0x5a
|
||||||
|
#define USB_PID_STALL 0x1e
|
||||||
|
#define USB_PID_NYET 0x96
|
||||||
|
/* data */
|
||||||
|
#define USB_PID_DATA0 0xc3
|
||||||
|
#define USB_PID_DATA1 0x4b
|
||||||
|
#define USB_PID_DATA2 0x87
|
||||||
|
#define USB_PID_MDATA 0x0f
|
||||||
|
/* Special */
|
||||||
|
#define USB_PID_PREAMBLE 0x3c
|
||||||
|
#define USB_PID_ERR 0x3c
|
||||||
|
#define USB_PID_SPLIT 0x78
|
||||||
|
#define USB_PID_PING 0xb4
|
||||||
|
#define USB_PID_UNDEF_0 0xf0
|
||||||
|
|
||||||
|
#define USB_PID_DATA_TOGGLE 0x88
|
||||||
|
|
||||||
struct usb_ctrlrequest {
|
struct usb_ctrlrequest {
|
||||||
u8 bRequestType;
|
u8 bRequestType;
|
||||||
u8 bRequest;
|
u8 bRequest;
|
||||||
|
|
Loading…
Reference in New Issue