From 83fe6d7fd270aeca7b703dbd0f7e23902144840b Mon Sep 17 00:00:00 2001 From: Kyösti Mälkki Date: Tue, 25 Feb 2014 20:11:52 +0200 Subject: usbdebug: Move initialisation of the optional hub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new file for device-specific initialisation transactions. Change-Id: I339df400a41675f178c7af613f03b2b44c826189 Signed-off-by: Kyösti Mälkki Reviewed-on: http://review.coreboot.org/7208 Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/drivers/usb/Makefile.inc | 4 +- src/drivers/usb/ehci.h | 3 + src/drivers/usb/ehci_debug.c | 107 ++------------------------------- src/drivers/usb/ehci_debug.h | 8 +++ src/drivers/usb/gadget.c | 138 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 105 deletions(-) create mode 100644 src/drivers/usb/gadget.c (limited to 'src/drivers/usb') diff --git a/src/drivers/usb/Makefile.inc b/src/drivers/usb/Makefile.inc index bab6737101..ff9a12462b 100644 --- a/src/drivers/usb/Makefile.inc +++ b/src/drivers/usb/Makefile.inc @@ -1,3 +1,3 @@ -romstage-$(CONFIG_USBDEBUG_IN_ROMSTAGE) += ehci_debug.c pci_ehci.c console.c +romstage-$(CONFIG_USBDEBUG_IN_ROMSTAGE) += ehci_debug.c pci_ehci.c console.c gadget.c -ramstage-$(CONFIG_USBDEBUG) += ehci_debug.c pci_ehci.c console.c +ramstage-$(CONFIG_USBDEBUG) += ehci_debug.c pci_ehci.c console.c gadget.c diff --git a/src/drivers/usb/ehci.h b/src/drivers/usb/ehci.h index f9203522a5..6904656314 100644 --- a/src/drivers/usb/ehci.h +++ b/src/drivers/usb/ehci.h @@ -197,4 +197,7 @@ struct ehci_dbg_port { u32 address; #define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) } __attribute__ ((packed)); + +#define USB_DEBUG_DEVNUM 127 + #endif diff --git a/src/drivers/usb/ehci_debug.c b/src/drivers/usb/ehci_debug.c index 1ab6688a3c..cb6b23ecd5 100644 --- a/src/drivers/usb/ehci_debug.c +++ b/src/drivers/usb/ehci_debug.c @@ -53,8 +53,6 @@ static int dbgp_enabled(void); # define dprintk(LEVEL, args...) do {} while(0) #endif -#define USB_DEBUG_DEVNUM 127 - #define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f)) /* * USB Packet IDs (PIDs) @@ -319,7 +317,7 @@ int dbgp_bulk_read_x(struct dbgp_pipe *pipe, void *data, int size) return dbgp_bulk_read(dbg_info->ehci_debug, pipe, data, size); } -static void dbgp_mdelay(int ms) +void dbgp_mdelay(int ms) { int i; @@ -329,7 +327,7 @@ static void dbgp_mdelay(int ms) } } -static int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, int requesttype, +int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, int requesttype, int request, int value, int index, void *data, int size) { struct ehci_debug_info *info = dbgp_ehci_info(); @@ -460,101 +458,6 @@ static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port) return -1; //-ENOTCONN; } -#define USB_HUB_PORT_CONNECTION 0 -#define USB_HUB_PORT_ENABLED 1 -#define USB_HUB_PORT_RESET 4 -#define USB_HUB_PORT_POWER 8 -#define USB_HUB_C_PORT_CONNECTION 16 -#define USB_HUB_C_PORT_RESET 20 - -#if CONFIG_USBDEBUG_OPTIONAL_HUB_PORT - -static int hub_port_status(const char * buf, int feature) -{ - return !!(buf[feature>>3] & (1<<(feature&0x7))); -} - -static int dbgp_hub_enable(struct ehci_dbg_port *ehci_debug, unsigned int port) -{ - const u8 hub_addr = USB_DEBUG_DEVNUM-1; - char status[8]; - int ret, loop; - - /* Move hub to address 126. */ - ret = dbgp_control_msg(ehci_debug, 0, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_REQ_SET_ADDRESS, hub_addr, 0, NULL, 0); - if (ret < 0) - goto err; - - /* Enter configured state on hub. */ - ret = dbgp_control_msg(ehci_debug, hub_addr, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0); - if (ret < 0) - goto err; - - /* Set PORT_POWER, poll for PORT_CONNECTION. */ - ret = dbgp_control_msg(ehci_debug, hub_addr, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, - USB_REQ_SET_FEATURE, USB_HUB_PORT_POWER, port, NULL, 0); - if (ret < 0) - goto err; - - loop = 100; - do { - dbgp_mdelay(10); - ret = dbgp_control_msg(ehci_debug, hub_addr, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER, - USB_REQ_GET_STATUS, 0, port, status, 4); - if (ret < 0) - goto err; - if (hub_port_status(status, USB_HUB_PORT_CONNECTION)) - break; - } while (--loop); - if (! loop) - goto err; - - ret = dbgp_control_msg(ehci_debug, hub_addr, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, - USB_REQ_CLEAR_FEATURE, USB_HUB_C_PORT_CONNECTION, port, NULL, 0); - if (ret < 0) - goto err; - - - /* Set PORT_RESET, poll for C_PORT_RESET. */ - ret = dbgp_control_msg(ehci_debug, hub_addr, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, - USB_REQ_SET_FEATURE, USB_HUB_PORT_RESET, port, NULL, 0); - if (ret < 0) - goto err; - - loop = 100; - do { - dbgp_mdelay(10); - ret = dbgp_control_msg(ehci_debug, hub_addr, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER, - USB_REQ_GET_STATUS, 0, port, status, 4); - if (ret < 0) - goto err; - if (hub_port_status(status, USB_HUB_C_PORT_RESET)) - break; - } while (--loop); - if (! loop) - goto err; - - ret = dbgp_control_msg(ehci_debug, hub_addr, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, - USB_REQ_CLEAR_FEATURE, USB_HUB_C_PORT_RESET, port, NULL, 0); - if (ret < 0) - goto err; - - if (hub_port_status(status, USB_HUB_PORT_ENABLED)) - return 0; -err: - return -1; -} -#endif /* CONFIG_USBDEBUG_OPTIONAL_HUB_PORT */ static int usbdebug_init_(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info) @@ -705,14 +608,12 @@ try_next_port: dbgp_mdelay(100); -#if CONFIG_USBDEBUG_OPTIONAL_HUB_PORT - ret = dbgp_hub_enable(ehci_debug, CONFIG_USBDEBUG_OPTIONAL_HUB_PORT); + ret = dbgp_probe_gadget(info->ehci_debug, &info->ep_pipe[0]); if (ret < 0) { - dprintk(BIOS_INFO, "Could not enable USB hub on debug port.\n"); + dprintk(BIOS_INFO, "Could not probe gadget on debug port.\n"); ret = -6; goto err; } -#endif /* Find the debug device and make it device number 127 */ devnum = 0; diff --git a/src/drivers/usb/ehci_debug.h b/src/drivers/usb/ehci_debug.h index 39f5f7239a..d7ea91b4f9 100644 --- a/src/drivers/usb/ehci_debug.h +++ b/src/drivers/usb/ehci_debug.h @@ -37,6 +37,8 @@ void ehci_debug_select_port(unsigned int port); #define DBGP_EP_BUSY (1<<2) #define DBGP_EP_STATMASK (DBGP_EP_VALID | DBGP_EP_ENABLED) +struct ehci_dbg_port; + struct dbgp_pipe { u8 devnum; @@ -59,4 +61,10 @@ int dbgp_ep_is_active(struct dbgp_pipe *pipe); int dbgp_bulk_write_x(struct dbgp_pipe *pipe, const char *bytes, int size); int dbgp_bulk_read_x(struct dbgp_pipe *pipe, void *data, int size); +int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, + int requesttype, int request, int value, int index, void *data, int size); +void dbgp_mdelay(int ms); + +int dbgp_probe_gadget(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe); + #endif /* _EHCI_DEBUG_H_ */ diff --git a/src/drivers/usb/gadget.c b/src/drivers/usb/gadget.c new file mode 100644 index 0000000000..d3b496375d --- /dev/null +++ b/src/drivers/usb/gadget.c @@ -0,0 +1,138 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include + +#include "ehci_debug.h" +#include "usb_ch9.h" +#include "ehci.h" + + +#define USB_HUB_PORT_CONNECTION 0 +#define USB_HUB_PORT_ENABLED 1 +#define USB_HUB_PORT_RESET 4 +#define USB_HUB_PORT_POWER 8 +#define USB_HUB_C_PORT_CONNECTION 16 +#define USB_HUB_C_PORT_RESET 20 + + +static int hub_port_status(const char * buf, int feature) +{ + return !!(buf[feature>>3] & (1<<(feature&0x7))); +} + +/* After USB port reset, treat device number 0 as an USB hub. Assign it with + * a device number hub_addr. Then apply enable and reset on downstream port. + */ + static int dbgp_hub_enable(struct ehci_dbg_port *ehci_debug, unsigned char hub_addr, + unsigned char port) +{ + char status[8]; + int ret, loop; + + /* Assign a devicenumber for the hub. */ + ret = dbgp_control_msg(ehci_debug, 0, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_ADDRESS, hub_addr, 0, NULL, 0); + if (ret < 0) + goto err; + + /* Enter configured state on hub. */ + ret = dbgp_control_msg(ehci_debug, hub_addr, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0); + if (ret < 0) + goto err; + + /* Set PORT_POWER, poll for PORT_CONNECTION. */ + ret = dbgp_control_msg(ehci_debug, hub_addr, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, + USB_REQ_SET_FEATURE, USB_HUB_PORT_POWER, port, NULL, 0); + if (ret < 0) + goto err; + + loop = 100; + do { + dbgp_mdelay(10); + ret = dbgp_control_msg(ehci_debug, hub_addr, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER, + USB_REQ_GET_STATUS, 0, port, status, 4); + if (ret < 0) + goto err; + if (hub_port_status(status, USB_HUB_PORT_CONNECTION)) + break; + } while (--loop); + if (! loop) + goto err; + + ret = dbgp_control_msg(ehci_debug, hub_addr, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, + USB_REQ_CLEAR_FEATURE, USB_HUB_C_PORT_CONNECTION, port, NULL, 0); + if (ret < 0) + goto err; + + + /* Set PORT_RESET, poll for C_PORT_RESET. */ + ret = dbgp_control_msg(ehci_debug, hub_addr, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, + USB_REQ_SET_FEATURE, USB_HUB_PORT_RESET, port, NULL, 0); + if (ret < 0) + goto err; + + loop = 100; + do { + dbgp_mdelay(10); + ret = dbgp_control_msg(ehci_debug, hub_addr, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER, + USB_REQ_GET_STATUS, 0, port, status, 4); + if (ret < 0) + goto err; + if (hub_port_status(status, USB_HUB_C_PORT_RESET)) + break; + } while (--loop); + if (! loop) + goto err; + + ret = dbgp_control_msg(ehci_debug, hub_addr, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, + USB_REQ_CLEAR_FEATURE, USB_HUB_C_PORT_RESET, port, NULL, 0); + if (ret < 0) + goto err; + + if (hub_port_status(status, USB_HUB_PORT_ENABLED)) + return 0; +err: + return -1; +} + + +int dbgp_probe_gadget(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe) +{ + int ret; + + if (CONFIG_USBDEBUG_OPTIONAL_HUB_PORT != 0) { + ret = dbgp_hub_enable(ehci_debug, USB_DEBUG_DEVNUM-1, + CONFIG_USBDEBUG_OPTIONAL_HUB_PORT); + if (ret < 0) { + printk(BIOS_INFO, "Could not enable USB hub on debug port.\n"); + return ret; + } + } + + return 0; +} -- cgit v1.2.3