From 95b7b79c3db9a1ca96ea08dde1e74c2f10a93577 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Thu, 2 May 2013 16:16:41 -0700 Subject: [PATCH] libpayload: Add USB support for non-PCI controllers Restructure USB stack to not depend on PCI, and make PCI stub available on x86, but provide fixed BARs for ARM (Exynos 5) BUG=chrome-os-partner:18635 TEST=Boot from USB in depthcharge on Snow Change-Id: Iee7c8b134c22b661a9a515e24943470c9dbadd1f Signed-off-by: Stefan Reinauer Reviewed-on: https://gerrit.chromium.org/gerrit/49970 --- payloads/libpayload/Config.in | 29 ++++++++++++- payloads/libpayload/drivers/usb/ehci.c | 41 +++++++++++-------- payloads/libpayload/drivers/usb/ehci.h | 3 +- .../libpayload/drivers/usb/ehci_private.h | 1 - payloads/libpayload/drivers/usb/ehci_rh.c | 2 + payloads/libpayload/drivers/usb/ohci.c | 24 ++++++++--- payloads/libpayload/drivers/usb/ohci.h | 5 ++- .../libpayload/drivers/usb/ohci_private.h | 1 - payloads/libpayload/drivers/usb/uhci.c | 11 ++--- payloads/libpayload/drivers/usb/uhci.h | 4 +- payloads/libpayload/drivers/usb/usbhub.c | 2 + payloads/libpayload/drivers/usb/usbinit.c | 33 ++++++++++++--- payloads/libpayload/drivers/usb/usbmsc.c | 1 + payloads/libpayload/drivers/usb/xhci.c | 25 +++++++---- payloads/libpayload/drivers/usb/xhci.h | 5 ++- payloads/libpayload/include/usb/usb.h | 3 +- 16 files changed, 137 insertions(+), 53 deletions(-) diff --git a/payloads/libpayload/Config.in b/payloads/libpayload/Config.in index 9d083ea239..85feed8dcf 100644 --- a/payloads/libpayload/Config.in +++ b/payloads/libpayload/Config.in @@ -326,7 +326,7 @@ config USB config USB_UHCI bool "Support for USB UHCI controllers" - depends on USB + depends on USB && ARCH_X86 help Select this option if you are going to use USB 1.1 on an Intel based system. @@ -335,7 +335,7 @@ config USB_OHCI bool "Support for USB OHCI controllers" depends on USB help - Select this option if you are going to use USB 1.1 on an AMD based + Select this option if you are going to use USB 1.1 on a non-Intel based system. config USB_EHCI @@ -378,6 +378,31 @@ config USB_MSC storage devices (USB memory sticks, hard drives, CDROM/DVD drives) Say Y here unless you know exactly what you are doing. +config USB_PCI + bool + default y if ARCH_X86 + default n + +config USB_MEMORY + bool + default y if ARCH_ARMV7 + default n + +config USB_OHCI_BASE_ADDRESS + hex + depends on USB_MEMORY && USB_OHCI + default 0x12120000 + +config USB_EHCI_BASE_ADDRESS + hex + depends on USB_MEMORY && USB_EHCI + default 0x12110000 + +config USB_XHCI_BASE_ADDRESS + hex + depends on USB_MEMORY && USB_XHCI + default 0x12000000 + endmenu menu "Debugging" diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c index 5af99e0f53..6e9f03aff0 100644 --- a/payloads/libpayload/drivers/usb/ehci.c +++ b/payloads/libpayload/drivers/usb/ehci.c @@ -69,7 +69,7 @@ static void dump_td(u32 addr) usb_debug("+---------------------------------------------------+\n"); } -#ifdef USB_DEBUG +#if 0 && defined(USB_DEBUG) static void dump_qh(ehci_qh_t *cur) { qtd_t *tmp_qtd = NULL; @@ -724,7 +724,7 @@ static u8 *ehci_poll_intr_queue(void *const queue) } hci_t * -ehci_init (pcidev_t addr) +ehci_init (void *bar) { int i; hci_t *controller = new_controller (); @@ -736,15 +736,6 @@ ehci_init (pcidev_t addr) if(!controller->instance) fatal("Not enough memory creating USB controller instance.\n"); -#define PCI_COMMAND 4 -#define PCI_COMMAND_IO 1 -#define PCI_COMMAND_MEMORY 2 -#define PCI_COMMAND_MASTER 4 - - u32 pci_command = pci_read_config32(addr, PCI_COMMAND); - pci_command = (pci_command | PCI_COMMAND_MEMORY) & ~PCI_COMMAND_IO ; - pci_write_config32(addr, PCI_COMMAND, pci_command); - controller->type = EHCI; controller->start = ehci_start; @@ -757,8 +748,7 @@ ehci_init (pcidev_t addr) controller->create_intr_queue = ehci_create_intr_queue; controller->destroy_intr_queue = ehci_destroy_intr_queue; controller->poll_intr_queue = ehci_poll_intr_queue; - controller->bus_address = addr; - controller->reg_base = pci_read_config32 (controller->bus_address, USBBASE); + controller->reg_base = (u32)(unsigned long)bar; for (i = 0; i < 128; i++) { controller->devices[i] = 0; } @@ -767,9 +757,6 @@ ehci_init (pcidev_t addr) EHCI_INST(controller)->capabilities = phys_to_virt(controller->reg_base); EHCI_INST(controller)->operation = (hc_op_t *)(phys_to_virt(controller->reg_base) + EHCI_INST(controller)->capabilities->caplength); - /* default value for frame length adjust */ - pci_write_config8(addr, FLADJ, FLADJ_framelength(60000)); - /* Set the high address word (aka segment) if controller is 64-bit */ if (EHCI_INST(controller)->capabilities->hccparams & 1) EHCI_INST(controller)->operation->ctrldssegment = 0; @@ -815,3 +802,25 @@ ehci_init (pcidev_t addr) return controller; } + +#ifdef CONFIG_USB_PCI +hci_t * +ehci_pci_init (pcidev_t addr) +{ + hci_t *controller; + u32 reg_base; + + u32 pci_command = pci_read_config32(addr, PCI_COMMAND); + pci_command = (pci_command | PCI_COMMAND_MEMORY) & ~PCI_COMMAND_IO ; + pci_write_config32(addr, PCI_COMMAND, pci_command); + + reg_base = pci_read_config32 (addr, USBBASE); + + /* default value for frame length adjust */ + pci_write_config8(addr, FLADJ, FLADJ_framelength(60000)); + + controller = ehci_init((void *)(unsigned long)reg_base); + + return controller; +} +#endif diff --git a/payloads/libpayload/drivers/usb/ehci.h b/payloads/libpayload/drivers/usb/ehci.h index c66643c702..c1b1fa9f70 100644 --- a/payloads/libpayload/drivers/usb/ehci.h +++ b/payloads/libpayload/drivers/usb/ehci.h @@ -33,7 +33,8 @@ #include #include -hci_t *ehci_init (pcidev_t addr); +hci_t *ehci_pci_init (pcidev_t addr); +hci_t *ehci_init (void *bar); void ehci_rh_init (usbdev_t *dev); diff --git a/payloads/libpayload/drivers/usb/ehci_private.h b/payloads/libpayload/drivers/usb/ehci_private.h index 3365be1977..986ee791bf 100644 --- a/payloads/libpayload/drivers/usb/ehci_private.h +++ b/payloads/libpayload/drivers/usb/ehci_private.h @@ -30,7 +30,6 @@ #ifndef __EHCI_PRIVATE_H #define __EHCI_PRIVATE_H -#include #include #define USBBASE 0x10 diff --git a/payloads/libpayload/drivers/usb/ehci_rh.c b/payloads/libpayload/drivers/usb/ehci_rh.c index 89828040d1..5c4daeda8a 100644 --- a/payloads/libpayload/drivers/usb/ehci_rh.c +++ b/payloads/libpayload/drivers/usb/ehci_rh.c @@ -27,6 +27,8 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG + #include #include "ehci.h" #include "ehci_private.h" diff --git a/payloads/libpayload/drivers/usb/ohci.c b/payloads/libpayload/drivers/usb/ohci.c index 44eba310c3..51ea8fb433 100644 --- a/payloads/libpayload/drivers/usb/ohci.c +++ b/payloads/libpayload/drivers/usb/ohci.c @@ -136,7 +136,7 @@ ohci_reinit (hci_t *controller) { } -#ifdef USB_DEBUG +#if 0 && defined(USB_DEBUG) /* Section 4.3.3 */ static const char *completion_codes[] = { "No error", @@ -167,7 +167,7 @@ static const char *direction[] = { #endif hci_t * -ohci_init (pcidev_t addr) +ohci_init (void *bar) { int i; @@ -198,10 +198,7 @@ ohci_init (pcidev_t addr) init_device_entry (controller, 0); OHCI_INST (controller)->roothub = controller->devices[0]; - controller->bus_address = addr; - /* regarding OHCI spec, Appendix A, BAR_OHCI register description, Table A-4 - * BASE ADDRESS only [31-12] bits. All other usually 0, but not all */ - controller->reg_base = pci_read_config32 (controller->bus_address, 0x10) & 0xfffff000; // OHCI mandates MMIO, so bit 0 is clear + controller->reg_base = (u32)(unsigned long)bar; OHCI_INST (controller)->opreg = (opreg_t*)phys_to_virt(controller->reg_base); usb_debug("OHCI Version %x.%x\n", (OHCI_INST (controller)->opreg->HcRevision >> 4) & 0xf, OHCI_INST (controller)->opreg->HcRevision & 0xf); @@ -252,6 +249,21 @@ ohci_init (pcidev_t addr) return controller; } +#ifdef CONFIG_USB_PCI +hci_t * +ohci_pci_init (pcidev_t addr) +{ + u32 reg_base; + + /* regarding OHCI spec, Appendix A, BAR_OHCI register description, Table A-4 + * BASE ADDRESS only [31-12] bits. All other usually 0, but not all. + * OHCI mandates MMIO, so bit 0 is clear */ + reg_base = pci_read_config32 (addr, 0x10) & 0xfffff000; + + return ohci_init((void *)(unsigned long)reg_base); +} +#endif + static void ohci_shutdown (hci_t *controller) { diff --git a/payloads/libpayload/drivers/usb/ohci.h b/payloads/libpayload/drivers/usb/ohci.h index f5011676a1..9c31d9c015 100644 --- a/payloads/libpayload/drivers/usb/ohci.h +++ b/payloads/libpayload/drivers/usb/ohci.h @@ -33,8 +33,9 @@ #include #include - hci_t *ohci_init (pcidev_t addr); +hci_t *ohci_pci_init (pcidev_t addr); +hci_t *ohci_init (void *bar); - void ohci_rh_init (usbdev_t *dev); +void ohci_rh_init (usbdev_t *dev); #endif diff --git a/payloads/libpayload/drivers/usb/ohci_private.h b/payloads/libpayload/drivers/usb/ohci_private.h index a32203c582..b6eaf6b449 100644 --- a/payloads/libpayload/drivers/usb/ohci_private.h +++ b/payloads/libpayload/drivers/usb/ohci_private.h @@ -30,7 +30,6 @@ #ifndef __OHCI_PRIVATE_H #define __OHCI_PRIVATE_H -#include #include #define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit)) diff --git a/payloads/libpayload/drivers/usb/uhci.c b/payloads/libpayload/drivers/usb/uhci.c index bfa1b57d43..df9bdca03c 100644 --- a/payloads/libpayload/drivers/usb/uhci.c +++ b/payloads/libpayload/drivers/usb/uhci.c @@ -147,7 +147,7 @@ uhci_reinit (hci_t *controller) } hci_t * -uhci_init (pcidev_t addr) +uhci_pci_init (pcidev_t addr) { int i; u16 reg16; @@ -179,16 +179,17 @@ uhci_init (pcidev_t addr) init_device_entry (controller, 0); UHCI_INST (controller)->roothub = controller->devices[0]; - controller->bus_address = addr; - controller->reg_base = pci_read_config32 (controller->bus_address, 0x20) & ~1; /* ~1 clears the register type indicator that is set to 1 for IO space */ + /* ~1 clears the register type indicator that is set to 1 + * for IO space */ + controller->reg_base = pci_read_config32 (addr, 0x20) & ~1; /* kill legacy support handler */ uhci_stop (controller); mdelay (1); uhci_reg_write16 (controller, USBSTS, 0x3f); - reg16 = pci_read_config16(controller->bus_address, 0xc0); + reg16 = pci_read_config16(addr, 0xc0); reg16 &= 0xdf80; - pci_write_config16 (controller->bus_address, 0xc0, reg16); + pci_write_config16 (addr, 0xc0, reg16); UHCI_INST (controller)->framelistptr = memalign (0x1000, 1024 * sizeof (flistp_t)); /* 4kb aligned to 4kb */ if (! UHCI_INST (controller)->framelistptr) diff --git a/payloads/libpayload/drivers/usb/uhci.h b/payloads/libpayload/drivers/usb/uhci.h index 2ef3f0b499..6bb5c17528 100644 --- a/payloads/libpayload/drivers/usb/uhci.h +++ b/payloads/libpayload/drivers/usb/uhci.h @@ -33,8 +33,8 @@ #include #include - hci_t *uhci_init (pcidev_t addr); +hci_t *uhci_pci_init (pcidev_t addr); - void uhci_rh_init (usbdev_t *dev); +void uhci_rh_init (usbdev_t *dev); #endif diff --git a/payloads/libpayload/drivers/usb/usbhub.c b/payloads/libpayload/drivers/usb/usbhub.c index 90e08dbde4..6ba1ed61c3 100644 --- a/payloads/libpayload/drivers/usb/usbhub.c +++ b/payloads/libpayload/drivers/usb/usbhub.c @@ -27,6 +27,8 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG + #include // assume that host_to_device is overwritten if necessary diff --git a/payloads/libpayload/drivers/usb/usbinit.c b/payloads/libpayload/drivers/usb/usbinit.c index 76653ff0d0..f74a833584 100644 --- a/payloads/libpayload/drivers/usb/usbinit.c +++ b/payloads/libpayload/drivers/usb/usbinit.c @@ -27,6 +27,7 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG #include #include #include "uhci.h" @@ -35,6 +36,7 @@ #include "xhci.h" #include +#ifdef CONFIG_USB_PCI /** * Initializes USB controller attached to PCI * @@ -58,8 +60,6 @@ static int usb_controller_initialize(int bus, int dev, int func) prog_if = (class >> 8) & 0xff; /* enable busmaster */ -#define PCI_COMMAND 4 -#define PCI_COMMAND_MASTER 4 if (devclass == 0xc03) { u32 pci_command; @@ -73,7 +73,7 @@ static int usb_controller_initialize(int bus, int dev, int func) case 0x00: #ifdef CONFIG_USB_UHCI usb_debug("UHCI controller\n"); - uhci_init (pci_device); + uhci_pci_init (pci_device); #else usb_debug("UHCI controller (not supported)\n"); #endif @@ -82,7 +82,7 @@ static int usb_controller_initialize(int bus, int dev, int func) case 0x10: #ifdef CONFIG_USB_OHCI usb_debug("OHCI controller\n"); - ohci_init(pci_device); + ohci_pci_init(pci_device); #else usb_debug("OHCI controller (not supported)\n"); #endif @@ -91,7 +91,7 @@ static int usb_controller_initialize(int bus, int dev, int func) case 0x20: #ifdef CONFIG_USB_EHCI usb_debug("EHCI controller\n"); - ehci_init(pci_device); + ehci_pci_init(pci_device); #else usb_debug("EHCI controller (not supported)\n"); #endif @@ -100,7 +100,7 @@ static int usb_controller_initialize(int bus, int dev, int func) case 0x30: #ifdef CONFIG_USB_XHCI usb_debug("xHCI controller\n"); - xhci_init(pci_device); + xhci_pci_init(pci_device); #else usb_debug("xHCI controller (not supported)\n"); #endif @@ -154,12 +154,33 @@ static void usb_scan_pci_bus(int bus) } } } +#endif + +#ifdef CONFIG_USB_MEMORY +static void usb_scan_memory(void) +{ +#ifdef CONFIG_USB_XHCI + xhci_init((void *)(unsigned long)CONFIG_USB_XHCI_BASE_ADDRESS); +#endif +#ifdef CONFIG_USB_EHCI + ehci_init((void *)(unsigned long)CONFIG_USB_EHCI_BASE_ADDRESS); +#endif +#ifdef CONFIG_USB_OHCI + ohci_init((void *)(unsigned long)CONFIG_USB_OHCI_BASE_ADDRESS); +#endif +} +#endif /** * Initialize all USB controllers attached to PCI. */ int usb_initialize(void) { +#ifdef CONFIG_USB_PCI usb_scan_pci_bus(0); +#endif +#ifdef CONFIG_USB_MEMORY + usb_scan_memory(); +#endif return 0; } diff --git a/payloads/libpayload/drivers/usb/usbmsc.c b/payloads/libpayload/drivers/usb/usbmsc.c index 16af44888e..ad7e82f3b0 100644 --- a/payloads/libpayload/drivers/usb/usbmsc.c +++ b/payloads/libpayload/drivers/usb/usbmsc.c @@ -27,6 +27,7 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG #include #include #include diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c index 083b331548..341b5969c2 100644 --- a/payloads/libpayload/drivers/usb/xhci.c +++ b/payloads/libpayload/drivers/usb/xhci.c @@ -55,7 +55,7 @@ xhci_reinit (hci_t *controller) } hci_t * -xhci_init (pcidev_t addr) +xhci_init (void *bar) { int i; @@ -86,12 +86,7 @@ xhci_init (pcidev_t addr) init_device_entry (controller, 0); XHCI_INST (controller)->roothub = controller->devices[0]; - controller->bus_address = addr; - controller->reg_base = (u32)phys_to_virt(pci_read_config32 (controller->bus_address, 0x10) & ~0xf); - //controller->reg_base = pci_read_config32 (controller->bus_address, 0x14) & ~0xf; - if (pci_read_config32 (controller->bus_address, 0x14) > 0) { - fatal("We don't do 64bit addressing.\n"); - } + controller->reg_base = (u32)(unsigned long)bar; usb_debug("regbase: %lx\n", controller->reg_base); XHCI_INST (controller)->capreg = (void*)controller->reg_base; @@ -204,6 +199,22 @@ xhci_init (pcidev_t addr) return controller; } +#ifdef CONFIG_USB_PCI +hci_t * +xhci_pci_init (pcidev_t addr) +{ + u32 reg_addr; + + reg_addr = (u32)phys_to_virt(pci_read_config32 (addr, 0x10) & ~0xf); + //controller->reg_base = pci_read_config32 (addr, 0x14) & ~0xf; + if (pci_read_config32 (addr, 0x14) > 0) { + fatal("We don't do 64bit addressing.\n"); + } + + return xhci_init((void *)(unsigned long)reg_addr); +} +#endif + static void xhci_shutdown (hci_t *controller) { diff --git a/payloads/libpayload/drivers/usb/xhci.h b/payloads/libpayload/drivers/usb/xhci.h index b900b12200..b76c9829b3 100644 --- a/payloads/libpayload/drivers/usb/xhci.h +++ b/payloads/libpayload/drivers/usb/xhci.h @@ -33,8 +33,9 @@ #include #include - hci_t *xhci_init (pcidev_t addr); +hci_t *xhci_pci_init (pcidev_t addr); +hci_t *xhci_init (void *bar); - void xhci_rh_init (usbdev_t *dev); +void xhci_rh_init (usbdev_t *dev); #endif diff --git a/payloads/libpayload/include/usb/usb.h b/payloads/libpayload/include/usb/usb.h index d82ce2710f..2dcc536c63 100644 --- a/payloads/libpayload/include/usb/usb.h +++ b/payloads/libpayload/include/usb/usb.h @@ -30,7 +30,7 @@ #ifndef __USB_H #define __USB_H #include -#include +#include typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir; typedef enum { standard_type = 0, class_type = 1, vendor_type = @@ -115,7 +115,6 @@ typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type; struct usbdev_hc { struct usbdev_hc *next; - pcidev_t bus_address; u32 reg_base; hc_type type; usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable