Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/78437?usp=email )
Change subject: [WIP]sb/intel/bd82x6x/pch: Prepare for devicetree USB devices ......................................................................
[WIP]sb/intel/bd82x6x/pch: Prepare for devicetree USB devices
Add support to read the USB port enable state from devicetree tree instead of mainboard code. The to be added USB port devices must follow the "chip drivers/usb/acpi" syntax. Under every PCI device there will be a 0 usb devices that hold the USB ports. USB2 and USB3 ports are supported.
The first 8 USB2.0 ports must be defined in EHCI1, the remaining 6 in EHCI2. If XHCI is available and being used all 14 USB2.0 ports can reside in XHCI.
USB3.0 ports can only reside in XHCI.
Change-Id: I9027c952dd51a9d45c05a39c5417040f65c8a3f3 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/southbridge/intel/bd82x6x/Makefile.inc M src/southbridge/intel/bd82x6x/early_usb.c M src/southbridge/intel/bd82x6x/pch.c M src/southbridge/intel/bd82x6x/pch.h M src/southbridge/intel/bd82x6x/usb_xhci.c 5 files changed, 192 insertions(+), 4 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/37/78437/1
diff --git a/src/southbridge/intel/bd82x6x/Makefile.inc b/src/southbridge/intel/bd82x6x/Makefile.inc index 5ca3471..b6d9e23 100644 --- a/src/southbridge/intel/bd82x6x/Makefile.inc +++ b/src/southbridge/intel/bd82x6x/Makefile.inc @@ -30,6 +30,7 @@ romstage-y += me_status.c romstage-y += early_rcba.c romstage-y += early_pch.c +romstage-y += pch.c
ifeq ($(CONFIG_USE_NATIVE_RAMINIT),y) romstage-y += early_thermal.c early_me.c early_usb.c diff --git a/src/southbridge/intel/bd82x6x/early_usb.c b/src/southbridge/intel/bd82x6x/early_usb.c index 654d44b..452578b 100644 --- a/src/southbridge/intel/bd82x6x/early_usb.c +++ b/src/southbridge/intel/bd82x6x/early_usb.c @@ -34,17 +34,19 @@ RCBA32(0x3580 + 4 * i) = 0; reg32 = 0; for (i = 0; i < 14; i++) - if (!portmap[i].enabled) + if (!portmap[i].enabled && !usb20_port_enabled(i)) reg32 |= (1 << i); RCBA32(USBPDO) = reg32; reg32 = 0; for (i = 0; i < 8; i++) - if (portmap[i].enabled && portmap[i].oc_pin >= 0) + if ((!portmap[i].enabled && !usb20_port_enabled(i)) && + portmap[i].oc_pin >= 0) reg32 |= (1 << (i + 8 * portmap[i].oc_pin)); RCBA32(USBOCM1) = reg32; reg32 = 0; for (i = 8; i < 14; i++) - if (portmap[i].enabled && portmap[i].oc_pin >= 4) + if ((!portmap[i].enabled && !usb20_port_enabled(i)) && + portmap[i].oc_pin >= 4) reg32 |= (1 << (i - 8 + 8 * (portmap[i].oc_pin - 4))); RCBA32(USBOCM2) = reg32; for (i = 0; i < 22; i++) diff --git a/src/southbridge/intel/bd82x6x/pch.c b/src/southbridge/intel/bd82x6x/pch.c index a7ab83a..788eaca 100644 --- a/src/southbridge/intel/bd82x6x/pch.c +++ b/src/southbridge/intel/bd82x6x/pch.c @@ -41,6 +41,184 @@ return pch_type; }
+/* + * Return the enabled USB2.0 ports as bitmap. + * The ports can be defined in EHCI1/EHCI2 or XHCI (Panther Point only). + * + * The USB controller must have a root hub defined in devicetree under + * which the USB ports reside: + * device pci XX.X on -> device usb 0.0 on -> device usb 2.Y on + * + * Warns about missing or conflicting devicetree settings. + */ +uint16_t usb20_port_enable_bitmap(void) +{ + DEVTREE_CONST struct device *port, *hub; + uint16_t ehci_bitmap, xhci_bitmap; + static uint16_t bitmap; + static bool done; + bool found_one; + + if (done) + return bitmap; + + ehci_bitmap = 0; + found_one = false; + + const struct device *const ehci1 = pcidev_path_on_root(PCH_EHCI1_DEV); + if (ehci1 && ehci1->enabled) { + hub = NULL; + while ((hub = dev_bus_each_child(ehci1->link_list, hub)) != NULL) { + port = NULL; + while ((port = dev_bus_each_child(ehci1->link_list, port)) != NULL) { + if (port->path.type != DEVICE_PATH_USB) + continue; + if (port->path.usb.port_type != 2) + continue; + + found_one = true; + + if (port->enabled) + ehci_bitmap |= 1 << port->path.usb.port_id; + } + } + } + + const struct device *const ehci2 = pcidev_path_on_root(PCH_EHCI2_DEV); + if (ehci2 && ehci2->enabled) { + hub = NULL; + while ((hub = dev_bus_each_child(ehci2->link_list, hub)) != NULL) { + port = NULL; + while ((port = dev_bus_each_child(ehci2->link_list, port)) != NULL) { + if (port->path.type != DEVICE_PATH_USB) + continue; + if (port->path.usb.port_type != 2) + continue; + + found_one = true; + + if (port->enabled) + ehci_bitmap |= 1 << (port->path.usb.port_id + 8); + } + } + } + + if (pch_silicon_type() != PCH_TYPE_PPT) { + /* Warn about incomplete devicetree */ + if (((ehci1 && ehci1->enabled) || + (ehci2 && ehci2->enabled)) && + !found_one) { + printk(BIOS_WARNING, "%s: No USB2 ports defined under EHCI\n", __func__); + printk(BIOS_WARNING, "%s: Check your devicetree.cb.", __func__); + } + done = true; + bitmap = ehci_bitmap; + return bitmap; + } + + xhci_bitmap = 0; + + const struct device *const xhci = pcidev_path_on_root(PCH_XHCI_DEV); + if (xhci && xhci->enabled) { + hub = NULL; + while ((hub = dev_bus_each_child(xhci->link_list, hub)) != NULL) { + port = NULL; + while ((port = dev_bus_each_child(xhci->link_list, port)) != NULL) { + if (port->path.type != DEVICE_PATH_USB) + continue; + if (port->path.usb.port_type != 2) + continue; + + found_one = true; + + if (port->enabled) + xhci_bitmap |= 1 << port->path.usb.port_id; + } + } + } + + /* Check for duplicates */ + if ((ehci_bitmap & xhci_bitmap) != 0) { + printk(BIOS_ERR, "%s: Same USB port defined in EHCI and XHCI: 0x%x\n", + __func__, ehci_bitmap & xhci_bitmap); + } + + /* Warn about incomplete devicetree */ + if (((ehci1 && ehci1->enabled) || + (ehci2 && ehci2->enabled) || + (xhci && xhci->enabled)) && + !found_one) { + printk(BIOS_WARNING, "%s: No USB2 ports defined under EHCI/XHCI\n", __func__); + printk(BIOS_WARNING, "%s: Check your devicetree.cb.", __func__); + } + done = true; + bitmap = xhci_bitmap; + return bitmap; +} + +bool usb20_port_enabled(const int idx) +{ + return !!(usb20_port_enable_bitmap() & (1 << idx)); +} + +/* + * Return the enabled USB3.0 ports as bitmap. + * The ports can be defined in XHCI on Panther Point only. + * + * The USB controller must have a root hub defined in devicetree under + * which the USB ports reside: + * device pci XX.X on -> device usb 0.0 on -> device usb 3.Y on + * + * Warns about missing devicetree settings. + */ +uint8_t usb30_port_enable_bitmap(void) +{ + DEVTREE_CONST struct device *port = NULL, *hub = NULL; + static uint8_t bitmap; + static bool done; + bool found_one; + + if (pch_silicon_type() != PCH_TYPE_PPT) + return 0; + + if (done) + return bitmap; + + found_one = false; + bitmap = 0; + + const struct device *const xhci = pcidev_path_on_root(PCH_XHCI_DEV); + if (xhci && xhci->enabled) { + while ((hub = dev_bus_each_child(xhci->link_list, hub)) != NULL) { + while ((port = dev_bus_each_child(xhci->link_list, port)) != NULL) { + if (port->path.type != DEVICE_PATH_USB) + continue; + if (port->path.usb.port_type != 3) + continue; + + found_one = true; + + if (port->enabled) + bitmap |= 1 << port->path.usb.port_id; + } + } + } + + /* Warn about incomplete devicetree */ + if ((xhci && xhci->enabled) && + !found_one) { + printk(BIOS_WARNING, "%s: No USB3 ports defined under XHCI\n", __func__); + printk(BIOS_WARNING, "%s: Check your devicetree.cb.", __func__); + } + done = true; + return bitmap; +} + +bool usb30_port_enabled(const int idx) +{ + return !!(usb30_port_enable_bitmap() & (1 << idx)); +} + static int pch_silicon_supported(int type, int rev) { int cur_type = pch_silicon_type(); diff --git a/src/southbridge/intel/bd82x6x/pch.h b/src/southbridge/intel/bd82x6x/pch.h index 6d164ea..d942148 100644 --- a/src/southbridge/intel/bd82x6x/pch.h +++ b/src/southbridge/intel/bd82x6x/pch.h @@ -34,6 +34,12 @@
int pch_silicon_revision(void); int pch_silicon_type(void); + +uint16_t usb20_port_enable_bitmap(void); +bool usb20_port_enabled(const int idx); +uint8_t usb30_port_enable_bitmap(void); +bool usb30_port_enabled(const int idx); + void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue);
void enable_usb_bar(void); diff --git a/src/southbridge/intel/bd82x6x/usb_xhci.c b/src/southbridge/intel/bd82x6x/usb_xhci.c index 5607b16..8ef10d4 100644 --- a/src/southbridge/intel/bd82x6x/usb_xhci.c +++ b/src/southbridge/intel/bd82x6x/usb_xhci.c @@ -23,7 +23,8 @@ pci_or_config32(dev, 0x44, 1);
pci_write_config32(dev, XUSB2PRM, config->xhci_switchable_ports); - pci_write_config32(dev, USB3PRM, config->superspeed_capable_ports); + pci_write_config32(dev, USB3PRM, config->superspeed_capable_ports | + usb30_port_enable_bitmap());
/* Enable clock gating */ reg32 = pci_read_config32(dev, 0x40);