From 8992e53c23cb088efbdafbf3e2ba77e7d8778d71 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Thu, 2 May 2013 16:16:41 -0700 Subject: 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) Change-Id: Iee7c8b134c22b661a9a515e24943470c9dbadd1f Signed-off-by: Stefan Reinauer Reviewed-on: https://gerrit.chromium.org/gerrit/49970 Reviewed-on: http://review.coreboot.org/4175 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich --- payloads/libpayload/Config.in | 28 ++++++++++++++++-- payloads/libpayload/drivers/usb/ehci.c | 41 ++++++++++++++++---------- payloads/libpayload/drivers/usb/ehci.h | 3 +- payloads/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 ++-- payloads/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 | 36 ++++++++++++++-------- payloads/libpayload/drivers/usb/xhci.h | 5 ++-- payloads/libpayload/include/usb/usb.h | 3 +- 16 files changed, 142 insertions(+), 58 deletions(-) (limited to 'payloads') diff --git a/payloads/libpayload/Config.in b/payloads/libpayload/Config.in index 6610f8f785..bb5176f712 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 @@ -382,6 +382,30 @@ config USB_GEN_HUB bool default n if (!USB_HUB && !USB_XHCI) default y if (USB_HUB || USB_XHCI) +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 diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c index f5c14d5031..e61e806345 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; @@ -760,8 +751,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; } @@ -770,9 +760,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; @@ -818,3 +805,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 95db5f4af8..edd275bb19 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; @@ -201,10 +201,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); @@ -255,6 +252,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 f9c361de22..b81b911eef 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; @@ -182,16 +182,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 20e064e872..4e077f6848 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 #include "generic_hub.h" 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 51f9422ceb..aa2fe579a2 100644 --- a/payloads/libpayload/drivers/usb/xhci.c +++ b/payloads/libpayload/drivers/usb/xhci.c @@ -143,7 +143,7 @@ xhci_wait_ready(xhci_t *const xhci) } hci_t * -xhci_init (const pcidev_t addr) +xhci_init (const void *bar) { int i; @@ -192,14 +192,7 @@ xhci_init (const pcidev_t addr) goto _free_xhci; } - /* Now, gather information and check for compatibility */ - - controller->bus_address = addr; - controller->reg_base = pci_read_config32(addr, REG_BAR0) & ~0xf; - if (pci_read_config32(addr, REG_BAR1) > 0) { - xhci_debug("We don't do 64bit addressing\n"); - goto _free_xhci; - } + controller->reg_base = (u32)(unsigned long)bar; xhci->capreg = phys_to_virt(controller->reg_base); xhci->opreg = ((void *)xhci->capreg) + xhci->capreg->caplength; @@ -270,7 +263,6 @@ xhci_init (const pcidev_t addr) } /* Now start working on the hardware */ - if (xhci_wait_ready(xhci)) goto _free_xhci; @@ -279,8 +271,6 @@ xhci_init (const pcidev_t addr) xhci_reset(controller); xhci_reinit(controller); - xhci_switch_ppt_ports(addr); - xhci->roothub->controller = controller; xhci->roothub->init = xhci_rh_init; xhci->roothub->init(xhci->roothub); @@ -308,6 +298,28 @@ _free_controller: return NULL; } +#ifdef CONFIG_USB_PCI +hci_t * +xhci_pci_init (pcidev_t addr) +{ + u32 reg_addr; + hci_t controller; + + 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"); + } + + controller = xhci_init((void *)(unsigned long)reg_addr); + controller->bus_address = addr; + + xhci_switch_ppt_ports(addr); + + return controller; +} +#endif + static void xhci_reset(hci_t *const 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 ab457088f8..a351690418 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 = @@ -118,7 +118,6 @@ typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type; struct usbdev_hc { hci_t *next; - pcidev_t bus_address; u32 reg_base; hc_type type; usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable -- cgit v1.2.3