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:
parent
441a4baf87
commit
8992e53c23
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#ifndef __EHCI_PRIVATE_H
|
||||
#define __EHCI_PRIVATE_H
|
||||
|
||||
#include <pci.h>
|
||||
#include <usb/usb.h>
|
||||
|
||||
#define USBBASE 0x10
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
//#define USB_DEBUG
|
||||
|
||||
#include <libpayload.h>
|
||||
#include "ehci.h"
|
||||
#include "ehci_private.h"
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
//#define USB_DEBUG
|
||||
|
||||
#include <usb/usb.h>
|
||||
#include "generic_hub.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
//#define USB_DEBUG
|
||||
#include <endian.h>
|
||||
#include <usb/usb.h>
|
||||
#include <usb/usbmsc.h>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue