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 <reinauer@google.com>
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 <rminnich@gmail.com>
This commit is contained in:
Stefan Reinauer 2013-05-02 16:16:41 -07:00 committed by Stefan Reinauer
parent 441a4baf87
commit 8992e53c23
16 changed files with 142 additions and 58 deletions

View File

@ -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

View File

@ -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

View File

@ -33,7 +33,8 @@
#include <pci.h>
#include <usb/usb.h>
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);

View File

@ -30,7 +30,6 @@
#ifndef __EHCI_PRIVATE_H
#define __EHCI_PRIVATE_H
#include <pci.h>
#include <usb/usb.h>
#define USBBASE 0x10

View File

@ -27,6 +27,8 @@
* SUCH DAMAGE.
*/
//#define USB_DEBUG
#include <libpayload.h>
#include "ehci.h"
#include "ehci_private.h"

View File

@ -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)
{

View File

@ -33,8 +33,9 @@
#include <pci.h>
#include <usb/usb.h>
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

View File

@ -30,7 +30,6 @@
#ifndef __OHCI_PRIVATE_H
#define __OHCI_PRIVATE_H
#include <pci.h>
#include <usb/usb.h>
#define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit))

View File

@ -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)

View File

@ -33,8 +33,8 @@
#include <pci.h>
#include <usb/usb.h>
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

View File

@ -27,6 +27,8 @@
* SUCH DAMAGE.
*/
//#define USB_DEBUG
#include <usb/usb.h>
#include "generic_hub.h"

View File

@ -27,6 +27,7 @@
* SUCH DAMAGE.
*/
//#define USB_DEBUG
#include <libpayload-config.h>
#include <usb/usb.h>
#include "uhci.h"
@ -35,6 +36,7 @@
#include "xhci.h"
#include <usb/usbdisk.h>
#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;
}

View File

@ -27,6 +27,7 @@
* SUCH DAMAGE.
*/
//#define USB_DEBUG
#include <endian.h>
#include <usb/usb.h>
#include <usb/usbmsc.h>

View File

@ -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)
{

View File

@ -33,8 +33,9 @@
#include <pci.h>
#include <usb/usb.h>
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

View File

@ -30,7 +30,7 @@
#ifndef __USB_H
#define __USB_H
#include <libpayload.h>
#include <pci.h>
#include <pci/pci.h>
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