summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyösti Mälkki <kyosti.malkki@gmail.com>2013-08-15 16:27:06 +0300
committerKyösti Mälkki <kyosti.malkki@gmail.com>2013-08-29 18:36:20 +0200
commit8101aa6bb02c586cd0d1ab2cf99148329319aaf9 (patch)
tree5609cabef4a330fa5438c74c749f763c39565693
parent24100100181bd770ce0f1181a1770a0808790cde (diff)
downloadcoreboot-8101aa6bb02c586cd0d1ab2cf99148329319aaf9.tar.gz
coreboot-8101aa6bb02c586cd0d1ab2cf99148329319aaf9.tar.bz2
coreboot-8101aa6bb02c586cd0d1ab2cf99148329319aaf9.zip
usbdebug: Support choice of EHCI controller
Nowadays, chipsets or boards do not only have one USB port with the capabilities of a debug port but several ones. Some of these ports are easier accessible than others, so making them configurable is also necessary. This change adds infrastructure to switch between EHCI controllers, but does not implement it for any chipset. Change-Id: I079643870104fbc64091a54e1bfd56ad24422c9f Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: http://review.coreboot.org/3438 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@google.com>
-rw-r--r--src/console/Kconfig19
-rw-r--r--src/include/usbdebug.h10
-rw-r--r--src/lib/usbdebug.c32
-rw-r--r--src/southbridge/amd/agesa/hudson/enable_usbdebug.c18
-rw-r--r--src/southbridge/amd/sb600/enable_usbdebug.c13
-rw-r--r--src/southbridge/amd/sb700/enable_usbdebug.c26
-rw-r--r--src/southbridge/amd/sb800/enable_usbdebug.c18
-rw-r--r--src/southbridge/intel/common/usb_debug.c16
-rw-r--r--src/southbridge/nvidia/ck804/enable_usbdebug.c14
-rw-r--r--src/southbridge/nvidia/mcp55/enable_usbdebug.c14
-rw-r--r--src/southbridge/sis/sis966/enable_usbdebug.c14
11 files changed, 132 insertions, 62 deletions
diff --git a/src/console/Kconfig b/src/console/Kconfig
index b753be402332..38f51e361b3f 100644
--- a/src/console/Kconfig
+++ b/src/console/Kconfig
@@ -143,6 +143,13 @@ config SPKMODEM
# Use "select HAVE_USBDEBUG" on southbridges which have Debug Port code.
config HAVE_USBDEBUG
+ bool
+ default y if HAVE_USBDEBUG_OPTIONS
+ default n
+
+# Use "select HAVE_USBDEBUG_OPTIONS" on southbridges with multiple
+# EHCI controllers or multiple ports with Debug Port capability
+config HAVE_USBDEBUG_OPTIONS
def_bool n
config USBDEBUG
@@ -166,6 +173,18 @@ config USBDEBUG
If unsure, say N.
+config USBDEBUG_HCD_INDEX
+ int "Index for EHCI controller to use with usbdebug"
+ default 0
+ depends on USBDEBUG
+ help
+ Some boards have multiple EHCI controllers with possibly only
+ one having the Debug Port capability on an external USB port.
+
+ Mapping of this index to PCI device functions is southbridge
+ specific and mainboard level Kconfig should already provide
+ a working default value here.
+
config USBDEBUG_DEFAULT_PORT
int "Default USB port to use as Debug Port"
default 0
diff --git a/src/include/usbdebug.h b/src/include/usbdebug.h
index 2728be0e4f1b..926d6585d035 100644
--- a/src/include/usbdebug.h
+++ b/src/include/usbdebug.h
@@ -22,6 +22,13 @@
#define USBDEBUG_H
#define EHCI_BAR_INDEX 0x10
+#define PCI_EHCI_CLASSCODE 0x0c0320 /* USB2.0 with EHCI controller */
+
+typedef u32 pci_devfn_t;
+pci_devfn_t pci_ehci_dbg_dev(unsigned hcd_idx);
+unsigned long pci_ehci_base_regs(pci_devfn_t dev);
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port);
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base);
#ifndef __PRE_RAM__
#if !CONFIG_USBDEBUG
@@ -42,9 +49,6 @@ void pci_ehci_read_resources(struct device *dev);
struct dbgp_pipe;
-void enable_usbdebug(unsigned int port);
-void set_debug_port(unsigned port);
-
int usbdebug_init(void);
struct dbgp_pipe *dbgp_console_output(void);
diff --git a/src/lib/usbdebug.c b/src/lib/usbdebug.c
index c9247881f04b..a319da92b864 100644
--- a/src/lib/usbdebug.c
+++ b/src/lib/usbdebug.c
@@ -22,6 +22,7 @@
#include <console/console.h>
#include <arch/io.h>
#include <device/pci.h>
+#include <device/pci_def.h>
#include <arch/byteorder.h>
#include <cpu/x86/car.h>
#include <string.h>
@@ -401,6 +402,20 @@ static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port)
return -1; //-ENOTCONN;
}
+#if defined(__PRE_RAM__) || !CONFIG_EARLY_CONSOLE
+static void enable_usbdebug(void)
+{
+ pci_devfn_t dbg_dev = pci_ehci_dbg_dev(CONFIG_USBDEBUG_HCD_INDEX);
+ pci_ehci_dbg_enable(dbg_dev, CONFIG_EHCI_BAR);
+}
+#endif
+
+static void set_debug_port(unsigned int port)
+{
+ pci_devfn_t dbg_dev = pci_ehci_dbg_dev(CONFIG_USBDEBUG_HCD_INDEX);
+ pci_ehci_dbg_set_port(dbg_dev, port);
+}
+
static int usbdebug_init_(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info)
{
struct ehci_caps *ehci_caps;
@@ -751,7 +766,9 @@ static void pci_ehci_set_resources(struct device *dev)
void pci_ehci_read_resources(struct device *dev)
{
- if (!ehci_drv_ops) {
+ pci_devfn_t dbg_dev = pci_ehci_dbg_dev(CONFIG_USBDEBUG_HCD_INDEX);
+
+ if (!ehci_drv_ops && pci_match_simple_dev(dev, dbg_dev)) {
memcpy(&ehci_dbg_ops, dev->ops, sizeof(ehci_dbg_ops));
ehci_drv_ops = dev->ops;
ehci_dbg_ops.set_resources = pci_ehci_set_resources;
@@ -765,6 +782,17 @@ void pci_ehci_read_resources(struct device *dev)
}
#endif
+unsigned long pci_ehci_base_regs(pci_devfn_t sdev)
+{
+#ifdef __SIMPLE_DEVICE__
+ unsigned long base = pci_read_config32(sdev, EHCI_BAR_INDEX) & ~0x0f;
+#else
+ device_t dev = dev_find_slot(PCI_DEV2SEGBUS(sdev), PCI_DEV2DEVFN(sdev));
+ unsigned long base = pci_read_config32(dev, EHCI_BAR_INDEX) & ~0x0f;
+#endif
+ return base + HC_LENGTH(read32(base));
+}
+
int dbgp_ep_is_active(struct dbgp_pipe *pipe)
{
return (pipe->status & DBGP_EP_STATMASK) == (DBGP_EP_VALID | DBGP_EP_ENABLED);
@@ -785,7 +813,7 @@ int usbdebug_init(void)
struct ehci_debug_info *dbg_info = dbgp_ehci_info();
#if defined(__PRE_RAM__) || !CONFIG_EARLY_CONSOLE
- enable_usbdebug(0);
+ enable_usbdebug();
#endif
return usbdebug_init_(CONFIG_EHCI_BAR, CONFIG_EHCI_DEBUG_OFFSET, dbg_info);
}
diff --git a/src/southbridge/amd/agesa/hudson/enable_usbdebug.c b/src/southbridge/amd/agesa/hudson/enable_usbdebug.c
index 6fa17817f9a4..459df6ffad75 100644
--- a/src/southbridge/amd/agesa/hudson/enable_usbdebug.c
+++ b/src/southbridge/amd/agesa/hudson/enable_usbdebug.c
@@ -30,12 +30,16 @@
#define HUDSON_DEVN_BASE 0
#endif
-#define EHCI_EOR 0x20
#define DEBUGPORT_MISC_CONTROL 0x80
-void set_debug_port(unsigned int port)
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
{
- u32 base_regs = CONFIG_EHCI_BAR + EHCI_EOR;
+ return PCI_DEV(0, HUDSON_DEVN_BASE + 0x12, 2);
+}
+
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
+{
+ u32 base_regs = pci_ehci_base_regs(dev);
u32 reg32;
/* Write the port number to DEBUGPORT_MISC_CONTROL[31:28]. */
@@ -47,14 +51,12 @@ void set_debug_port(unsigned int port)
}
-void enable_usbdebug(unsigned int port)
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base)
{
/* Enable all of the USB controllers */
outb(0xEF, PM_INDEX);
outb(0x7F, PM_DATA);
- pci_write_config32(PCI_DEV(0, HUDSON_DEVN_BASE + 0x12, 2),
- EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
- pci_write_config8(PCI_DEV(0, HUDSON_DEVN_BASE + 0x12, 2),
- PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_write_config32(dev, EHCI_BAR_INDEX, base);
+ pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
}
diff --git a/src/southbridge/amd/sb600/enable_usbdebug.c b/src/southbridge/amd/sb600/enable_usbdebug.c
index 40c53aecfa26..09fce2f145a3 100644
--- a/src/southbridge/amd/sb600/enable_usbdebug.c
+++ b/src/southbridge/amd/sb600/enable_usbdebug.c
@@ -26,18 +26,21 @@
#include <device/pci_def.h>
#include "sb600.h"
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
+{
+ return PCI_DEV(0, 0x13, 5); /* USB EHCI, D19:F5 */
+}
+
/* Required for successful build, but currently empty. */
-void set_debug_port(unsigned int port)
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
/* TODO: Allow changing the physical USB port used as Debug Port. */
}
-void enable_usbdebug(unsigned int port)
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base)
{
- pci_devfn_t dev = PCI_DEV(0, 0x13, 5); /* USB EHCI, D19:F5 */
-
/* Set the EHCI BAR address. */
- pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
+ pci_write_config32(dev, EHCI_BAR_INDEX, base);
/* Enable access to the EHCI memory space registers. */
pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
diff --git a/src/southbridge/amd/sb700/enable_usbdebug.c b/src/southbridge/amd/sb700/enable_usbdebug.c
index 0712d2af2d03..3d44a1ac0c14 100644
--- a/src/southbridge/amd/sb700/enable_usbdebug.c
+++ b/src/southbridge/amd/sb700/enable_usbdebug.c
@@ -27,12 +27,21 @@
#include <device/pci_def.h>
#include "sb700.h"
-#define EHCI_EOR 0x20
#define DEBUGPORT_MISC_CONTROL 0x80
-void set_debug_port(unsigned int port)
+/*
+ * Note: The SB700 has two EHCI devices, D18:F2 and D19:F2.
+ * This code currently only supports the first one, i.e., USB Debug devices
+ * attached to physical USB ports belonging to the first EHCI device.
+ */
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
+{
+ return PCI_DEV(0, 0x12, 2);
+}
+
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
- u32 base_regs = CONFIG_EHCI_BAR + EHCI_EOR;
+ u32 base_regs = pci_ehci_base_regs(dev);
u32 reg32;
/* Write the port number to DEBUGPORT_MISC_CONTROL[31:28]. */
@@ -43,17 +52,10 @@ void set_debug_port(unsigned int port)
write32(base_regs + DEBUGPORT_MISC_CONTROL, reg32);
}
-/*
- * Note: The SB700 has two EHCI devices, D18:F2 and D19:F2.
- * This code currently only supports the first one, i.e., USB Debug devices
- * attached to physical USB ports belonging to the first EHCI device.
- */
-void enable_usbdebug(unsigned int port)
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base)
{
- pci_devfn_t dev = PCI_DEV(0, 0x12, 2); /* USB EHCI, D18:F2 */
-
/* Set the EHCI BAR address. */
- pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
+ pci_write_config32(dev, EHCI_BAR_INDEX, base);
/* Enable access to the EHCI memory space registers. */
pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
diff --git a/src/southbridge/amd/sb800/enable_usbdebug.c b/src/southbridge/amd/sb800/enable_usbdebug.c
index 6422fa229570..92778698f211 100644
--- a/src/southbridge/amd/sb800/enable_usbdebug.c
+++ b/src/southbridge/amd/sb800/enable_usbdebug.c
@@ -30,12 +30,16 @@
#define SB800_DEVN_BASE 0
#endif
-#define EHCI_EOR 0x20
#define DEBUGPORT_MISC_CONTROL 0x80
-void set_debug_port(unsigned int port)
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
{
- u32 base_regs = CONFIG_EHCI_BAR + EHCI_EOR;
+ return PCI_DEV(0, SB800_DEVN_BASE + 0x12, 2);
+}
+
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
+{
+ u32 base_regs = pci_ehci_base_regs(dev);
u32 reg32;
/* Write the port number to DEBUGPORT_MISC_CONTROL[31:28]. */
@@ -47,14 +51,12 @@ void set_debug_port(unsigned int port)
}
-void enable_usbdebug(unsigned int port)
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base)
{
/* Enable all of the USB controllers */
outb(0xEF, PM_INDEX);
outb(0x7F, PM_DATA);
- pci_write_config32(PCI_DEV(0, SB800_DEVN_BASE + 0x12, 2),
- EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
- pci_write_config8(PCI_DEV(0, SB800_DEVN_BASE + 0x12, 2),
- PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_write_config32(dev, EHCI_BAR_INDEX, base);
+ pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
}
diff --git a/src/southbridge/intel/common/usb_debug.c b/src/southbridge/intel/common/usb_debug.c
index 6b934f4fa07e..3fed2ab85452 100644
--- a/src/southbridge/intel/common/usb_debug.c
+++ b/src/southbridge/intel/common/usb_debug.c
@@ -26,25 +26,29 @@
#include <usbdebug.h>
#include <device/pci_def.h>
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
+{
+ return PCI_DEV(0, 0x1d, 7);
+}
+
/* Required for successful build, but currently empty. */
-void set_debug_port(unsigned int port)
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
/* Not needed, the ICH* southbridges hardcode physical USB port 1. */
}
-void enable_usbdebug(unsigned int port)
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base)
{
u32 dbgctl;
- pci_devfn_t dev = PCI_DEV(0, 0x1d, 7); /* USB EHCI, D29:F7 */
/* Set the EHCI BAR address. */
- pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
+ pci_write_config32(dev, EHCI_BAR_INDEX, base);
/* Enable access to the EHCI memory space registers. */
pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
/* Force ownership of the Debug Port to the EHCI controller. */
- dbgctl = read32(CONFIG_EHCI_BAR + CONFIG_EHCI_DEBUG_OFFSET);
+ dbgctl = read32(base + CONFIG_EHCI_DEBUG_OFFSET);
dbgctl |= (1 << 30);
- write32(CONFIG_EHCI_BAR + CONFIG_EHCI_DEBUG_OFFSET, dbgctl);
+ write32(base + CONFIG_EHCI_DEBUG_OFFSET, dbgctl);
}
diff --git a/src/southbridge/nvidia/ck804/enable_usbdebug.c b/src/southbridge/nvidia/ck804/enable_usbdebug.c
index d65fea212d08..d98bc984fb8d 100644
--- a/src/southbridge/nvidia/ck804/enable_usbdebug.c
+++ b/src/southbridge/nvidia/ck804/enable_usbdebug.c
@@ -36,10 +36,14 @@
#define CK804_DEVN_BASE CONFIG_HT_CHAIN_UNITID_BASE
#endif
-void set_debug_port(unsigned int port)
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
+{
+ return PCI_DEV(0, CK804_DEVN_BASE + 2, 1); /* USB EHCI */
+}
+
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
u32 dword;
- pci_devfn_t dev = PCI_DEV(0, CK804_DEVN_BASE + 2, 1); /* USB EHCI */
/* Write the port number to 0x74[15:12]. */
dword = pci_read_config32(dev, 0x74);
@@ -48,12 +52,10 @@ void set_debug_port(unsigned int port)
pci_write_config32(dev, 0x74, dword);
}
-void enable_usbdebug(unsigned int port)
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base)
{
- pci_devfn_t dev = PCI_DEV(0, CK804_DEVN_BASE + 2, 1); /* USB EHCI */
-
/* Set the EHCI BAR address. */
- pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
+ pci_write_config32(dev, EHCI_BAR_INDEX, base);
/* Enable access to the EHCI memory space registers. */
pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
diff --git a/src/southbridge/nvidia/mcp55/enable_usbdebug.c b/src/southbridge/nvidia/mcp55/enable_usbdebug.c
index f629c505c39c..b0afec28a423 100644
--- a/src/southbridge/nvidia/mcp55/enable_usbdebug.c
+++ b/src/southbridge/nvidia/mcp55/enable_usbdebug.c
@@ -30,10 +30,14 @@
#include <device/pci_def.h>
#include "mcp55.h"
-void set_debug_port(unsigned int port)
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
+{
+ return PCI_DEV(0, MCP55_DEVN_BASE + 2, 1); /* USB EHCI */
+}
+
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
u32 dword;
- pci_devfn_t dev = PCI_DEV(0, MCP55_DEVN_BASE + 2, 1); /* USB EHCI */
/* Write the port number to 0x74[15:12]. */
dword = pci_read_config32(dev, 0x74);
@@ -42,12 +46,10 @@ void set_debug_port(unsigned int port)
pci_write_config32(dev, 0x74, dword);
}
-void enable_usbdebug(unsigned int port)
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base)
{
- pci_devfn_t dev = PCI_DEV(0, MCP55_DEVN_BASE + 2, 1); /* USB EHCI */
-
/* Set the EHCI BAR address. */
- pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
+ pci_write_config32(dev, EHCI_BAR_INDEX, base);
/* Enable access to the EHCI memory space registers. */
pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
diff --git a/src/southbridge/sis/sis966/enable_usbdebug.c b/src/southbridge/sis/sis966/enable_usbdebug.c
index 04384ba9ac36..0d7503d66e7c 100644
--- a/src/southbridge/sis/sis966/enable_usbdebug.c
+++ b/src/southbridge/sis/sis966/enable_usbdebug.c
@@ -32,10 +32,14 @@
#include <device/pci_def.h>
#include "sis966.h"
-void set_debug_port(unsigned int port)
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
+{
+ return PCI_DEV(0, SIS966_DEVN_BASE + 2, 1); /* USB EHCI */
+}
+
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
u32 dword;
- pci_devfn_t dev = PCI_DEV(0, SIS966_DEVN_BASE + 2, 1); /* USB EHCI */
/* Write the port number to 0x74[15:12]. */
dword = pci_read_config32(dev, 0x74);
@@ -44,12 +48,10 @@ void set_debug_port(unsigned int port)
pci_write_config32(dev, 0x74, dword);
}
-void enable_usbdebug(unsigned int port)
+void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base)
{
- pci_devfn_t dev = PCI_DEV(0, SIS966_DEVN_BASE + 2, 1); /* USB EHCI */
-
/* Set the EHCI BAR address. */
- pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
+ pci_write_config32(dev, EHCI_BAR_INDEX, base);
/* Enable access to the EHCI memory space registers. */
pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);