[U-Boot] [PATCH v2 00/11] x86: quark: Convert to driver model

This series converts to use driver model for PCI/USB/ETH on Intel Galileo board, as well as optimizing the boot time.
Boot time performance degradation is observed with the conversion to use dm pci. Intel Quark SoC has a low end x86 processor with only 400MHz frequency and the most time consuming part is with MRC. Each MRC register programming requires indirect access via pci bus. With dm pci, accessing pci configuration space has some overhead. Unfortunately this single access overhead gets accumulated in the whole MRC process, and finally leads to twice boot time (25s) than before (12s).
To speed up the boot, create an optimized version of pci config read/write routines without bothering to go through driver model. Now it only takes about 3 seconds to finish MRC, which is really fast (8 times faster than dm pci, or 4 times faster than before).
The v2 series add complete PCIe root port and USB host support, which are the last 2 features on the Galileo board to enable.
Tested with a Mini-PCIe card (probe only) and a USB flash disk.
Simon, I reordered the patches so that the MRC optimizatin patch comes first. If you want to investigate driver model PCI overhead, you need to try the v1 patch series.
Changes in v2: - Drop v1 patch: "x86: quark: Make host bridge (b.d.f=0.0.0) visible", as pci_skip_dev() is not needed with the conversion to dm pci. - Drop v1 patch: "dm: pci: Allow skipping device configuration", as full PCIe root port support has been added and there is no need to add such feature at this point. We can still add such capability to dm pci in the future whenever needed. - Reorder to put patch "Optimize MRC execution time" as the first one in v2, as this patch addressed the slow boot time issue which exists before dm pci conversion, although it significantly improves more after dm pci conversion :-) - Move qrk_pci_write_config_dword() and qrk_pci_read_config_dword() to arch/x86/cpu/quark/quark.c - Rewrite this commit's message (ie: not mentioning dm pci conversion) - New patch to avoid chicken and egg problem - New patch to enable PCIe controller on quark/galileo - Remove arch/x86/cpu/quark/pci.c completely - New patch to add USB PHY initialization support - Update commit message to remove "USB not working" statement, as in v2, full USB support has been added. - New patch to add an inline API to test if a device is on a PCI bus - Change to use device_is_on_pci_bus() - New patch to add PCIe/USB static register programming after memory init
Bin Meng (11): x86: quark: Optimize MRC execution time x86: quark: Avoid chicken and egg problem x86: Enable PCIe controller on quark/galileo x86: Convert to use driver model pci on quark/galileo x86: quark: Add USB PHY initialization support x86: galileo: Convert to use CONFIG_DM_USB net: designware: Fix build warnings dm: pci: Add an inline API to test if a device is on a PCI bus net: designware: Add support to PCI designware devices x86: Convert to use driver model eth on quark/galileo x86: quark: Add PCIe/USB static register programming after memory init
arch/x86/cpu/quark/Makefile | 1 - arch/x86/cpu/quark/msg_port.c | 44 +++---- arch/x86/cpu/quark/pci.c | 70 ----------- arch/x86/cpu/quark/quark.c | 212 +++++++++++++++++++++++++++----- arch/x86/dts/galileo.dts | 8 +- arch/x86/include/asm/arch-quark/quark.h | 107 ++++++++++++++++ board/intel/galileo/galileo.c | 56 +++++++++ configs/galileo_defconfig | 5 +- drivers/net/designware.c | 47 ++++++- drivers/pci/pci-uclass.c | 4 +- include/configs/galileo.h | 13 +- include/pci.h | 15 +++ 12 files changed, 434 insertions(+), 148 deletions(-) delete mode 100644 arch/x86/cpu/quark/pci.c

Intel Quark SoC has a low end x86 processor with only 400MHz frequency. Currently it takes about 15 seconds for U-Boot to boot to shell and the most time consuming part is with MRC, which is about 12 seconds. MRC programs lots of registers on the SoC internal message bus indirectly accessed via pci bus.
To speed up the boot, create an optimized version of pci config read/write dword routines which directly operate on PCI I/O ports. These two routines are inlined to provide better performance too. Now it only takes about 3 seconds to finish MRC, which is really fast (4 times faster than before).
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - Drop v1 patch: "x86: quark: Make host bridge (b.d.f=0.0.0) visible", as pci_skip_dev() is not needed with the conversion to dm pci. - Drop v1 patch: "dm: pci: Allow skipping device configuration", as full PCIe root port support has been added and there is no need to add such feature at this point. We can still add such capability to dm pci in the future whenever needed. - Reorder to put patch "Optimize MRC execution time" as the first one in v2, as this patch addressed the slow boot time issue which exists before dm pci conversion, although it significantly improves more after dm pci conversion :-) - Move qrk_pci_write_config_dword() and qrk_pci_read_config_dword() to arch/x86/cpu/quark/quark.c - Rewrite this commit's message (ie: not mentioning dm pci conversion)
arch/x86/cpu/quark/msg_port.c | 44 ++++++++++++++++----------------- arch/x86/include/asm/arch-quark/quark.h | 35 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 22 deletions(-)
diff --git a/arch/x86/cpu/quark/msg_port.c b/arch/x86/cpu/quark/msg_port.c index 31713e3..cf828f2 100644 --- a/arch/x86/cpu/quark/msg_port.c +++ b/arch/x86/cpu/quark/msg_port.c @@ -5,34 +5,34 @@ */
#include <common.h> -#include <pci.h> #include <asm/arch/device.h> #include <asm/arch/msg_port.h> +#include <asm/arch/quark.h>
void msg_port_setup(int op, int port, int reg) { - pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG, - (((op) << 24) | ((port) << 16) | - (((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE)); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG, + (((op) << 24) | ((port) << 16) | + (((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE)); }
u32 msg_port_read(u8 port, u32 reg) { u32 value;
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, - reg & 0xffffff00); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, + reg & 0xffffff00); msg_port_setup(MSG_OP_READ, port, reg); - pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value); + qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value; }
void msg_port_write(u8 port, u32 reg, u32 value) { - pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value); - pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, - reg & 0xffffff00); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, + reg & 0xffffff00); msg_port_setup(MSG_OP_WRITE, port, reg); }
@@ -40,19 +40,19 @@ u32 msg_port_alt_read(u8 port, u32 reg) { u32 value;
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, - reg & 0xffffff00); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, + reg & 0xffffff00); msg_port_setup(MSG_OP_ALT_READ, port, reg); - pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value); + qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value; }
void msg_port_alt_write(u8 port, u32 reg, u32 value) { - pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value); - pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, - reg & 0xffffff00); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, + reg & 0xffffff00); msg_port_setup(MSG_OP_ALT_WRITE, port, reg); }
@@ -60,18 +60,18 @@ u32 msg_port_io_read(u8 port, u32 reg) { u32 value;
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, - reg & 0xffffff00); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, + reg & 0xffffff00); msg_port_setup(MSG_OP_IO_READ, port, reg); - pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value); + qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value; }
void msg_port_io_write(u8 port, u32 reg, u32 value) { - pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value); - pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, - reg & 0xffffff00); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value); + qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, + reg & 0xffffff00); msg_port_setup(MSG_OP_IO_WRITE, port, reg); } diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h index c997928..1ce5693 100644 --- a/arch/x86/include/asm/arch-quark/quark.h +++ b/arch/x86/include/asm/arch-quark/quark.h @@ -89,6 +89,41 @@ struct quark_rcba { u16 d20d21_ir; };
+#include <asm/io.h> +#include <asm/pci.h> + +/** + * qrk_pci_read_config_dword() - Read a configuration value + * + * @dev: PCI device address: bus, device and function + * @offset: Dword offset within the device's configuration space + * @valuep: Place to put the returned value + * + * Note: This routine is inlined to provide better performance on Quark + */ +static inline void qrk_pci_read_config_dword(pci_dev_t dev, int offset, + u32 *valuep) +{ + outl(dev | offset | PCI_CFG_EN, PCI_REG_ADDR); + *valuep = inl(PCI_REG_DATA); +} + +/** + * qrk_pci_write_config_dword() - Write a PCI configuration value + * + * @dev: PCI device address: bus, device and function + * @offset: Dword offset within the device's configuration space + * @value: Value to write + * + * Note: This routine is inlined to provide better performance on Quark + */ +static inline void qrk_pci_write_config_dword(pci_dev_t dev, int offset, + u32 value) +{ + outl(dev | offset | PCI_CFG_EN, PCI_REG_ADDR); + outl(value, PCI_REG_DATA); +} + #endif /* __ASSEMBLY__ */
#endif /* _QUARK_H_ */

Hi Bin,
On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
Intel Quark SoC has a low end x86 processor with only 400MHz frequency. Currently it takes about 15 seconds for U-Boot to boot to shell and the most time consuming part is with MRC, which is about 12 seconds. MRC programs lots of registers on the SoC internal message bus indirectly accessed via pci bus.
To speed up the boot, create an optimized version of pci config read/write dword routines which directly operate on PCI I/O ports. These two routines are inlined to provide better performance too. Now it only takes about 3 seconds to finish MRC, which is really fast (4 times faster than before).
Is it possible to use the new memory-mapped-based PCI configuration approach on Quark. Also I wonder if we should adjust the functions in arch/x86/cpu.c to do this?
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- Drop v1 patch: "x86: quark: Make host bridge (b.d.f=0.0.0) visible", as pci_skip_dev() is not needed with the conversion to dm pci.
- Drop v1 patch: "dm: pci: Allow skipping device configuration", as full PCIe root port support has been added and there is no need to add such feature at this point. We can still add such capability to dm pci in the future whenever needed.
- Reorder to put patch "Optimize MRC execution time" as the first one in v2, as this patch addressed the slow boot time issue which exists before dm pci conversion, although it significantly improves more after dm pci conversion :-)
- Move qrk_pci_write_config_dword() and qrk_pci_read_config_dword() to arch/x86/cpu/quark/quark.c
- Rewrite this commit's message (ie: not mentioning dm pci conversion)
arch/x86/cpu/quark/msg_port.c | 44 ++++++++++++++++----------------- arch/x86/include/asm/arch-quark/quark.h | 35 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 22 deletions(-)
Acked-by: Simon Glass sjg@chromium.org
Regards, Simon

Hi Simon,
On Wed, Sep 2, 2015 at 10:05 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
Intel Quark SoC has a low end x86 processor with only 400MHz frequency. Currently it takes about 15 seconds for U-Boot to boot to shell and the most time consuming part is with MRC, which is about 12 seconds. MRC programs lots of registers on the SoC internal message bus indirectly accessed via pci bus.
To speed up the boot, create an optimized version of pci config read/write dword routines which directly operate on PCI I/O ports. These two routines are inlined to provide better performance too. Now it only takes about 3 seconds to finish MRC, which is really fast (4 times faster than before).
Is it possible to use the new memory-mapped-based PCI configuration approach on Quark. Also I wonder if we should adjust the functions in arch/x86/cpu.c to do this?
Yes, it is possible to use PCIe ECAM on quark. For arch/x86/cpu.c, I think we have two choices: 1). use ECAM for every chipset 2). use a config option for this new capability. Given PCIe ECAM is a must-have for PCIe, we can do option 1. But so far U-Boot still supports QEMU i440FX which is an old PCI chipset, this looks like the only exception that does not support ECAM. QEMU q35 supports it. We may drop the i440FX support instead. (note the ACPI support that Saket did is also for q35, not for i440FX)
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- Drop v1 patch: "x86: quark: Make host bridge (b.d.f=0.0.0) visible", as pci_skip_dev() is not needed with the conversion to dm pci.
- Drop v1 patch: "dm: pci: Allow skipping device configuration", as full PCIe root port support has been added and there is no need to add such feature at this point. We can still add such capability to dm pci in the future whenever needed.
- Reorder to put patch "Optimize MRC execution time" as the first one in v2, as this patch addressed the slow boot time issue which exists before dm pci conversion, although it significantly improves more after dm pci conversion :-)
- Move qrk_pci_write_config_dword() and qrk_pci_read_config_dword() to arch/x86/cpu/quark/quark.c
- Rewrite this commit's message (ie: not mentioning dm pci conversion)
arch/x86/cpu/quark/msg_port.c | 44 ++++++++++++++++----------------- arch/x86/include/asm/arch-quark/quark.h | 35 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 22 deletions(-)
Acked-by: Simon Glass sjg@chromium.org
Regards, Simon

If we convert to use driver model pci on quark, we will encounter some chicken and egg problems like below:
- To enable PCIe root ports, we need program some registers on the message bus via pci bus. With driver model, the first time to access pci bus, the pci enumeration process will be triggered. But without first enabling PCIe root ports, pci enumeration just hangs when scanning PCIe root ports. - Similar situation happens when trying to access GPIO from the PCIe enabling codes, as GPIO requires its block base address to be assigned via a pci configuration register in the bridge.
To avoid such dilemma, replace all pci calls in the quark codes to use the local version which does not go through driver model.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - New patch to avoid chicken and egg problem
arch/x86/cpu/quark/quark.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 12ac376..2688a70 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -31,32 +31,32 @@ static void unprotect_spi_flash(void) { u32 bc;
- bc = x86_pci_read_config32(QUARK_LEGACY_BRIDGE, 0xd8); + qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, 0xd8, &bc); bc |= 0x1; /* unprotect the flash */ - x86_pci_write_config32(QUARK_LEGACY_BRIDGE, 0xd8, bc); + qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, 0xd8, bc); }
static void quark_setup_bars(void) { /* GPIO - D31:F0:R44h */ - pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA, - CONFIG_GPIO_BASE | IO_BAR_EN); + qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA, + CONFIG_GPIO_BASE | IO_BAR_EN);
/* ACPI PM1 Block - D31:F0:R48h */ - pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK, - CONFIG_ACPI_PM1_BASE | IO_BAR_EN); + qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK, + CONFIG_ACPI_PM1_BASE | IO_BAR_EN);
/* GPE0 - D31:F0:R4Ch */ - pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK, - CONFIG_ACPI_GPE0_BASE | IO_BAR_EN); + qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK, + CONFIG_ACPI_GPE0_BASE | IO_BAR_EN);
/* WDT - D31:F0:R84h */ - pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA, - CONFIG_WDT_BASE | IO_BAR_EN); + qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA, + CONFIG_WDT_BASE | IO_BAR_EN);
/* RCBA - D31:F0:RF0h */ - pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, - CONFIG_RCBA_BASE | MEM_BAR_EN); + qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, + CONFIG_RCBA_BASE | MEM_BAR_EN);
/* ACPI P Block - Msg Port 04:R70h */ msg_port_write(MSG_PORT_RMU, PBLK_BA, @@ -137,10 +137,10 @@ int cpu_eth_init(bd_t *bis) u32 base; int ret0, ret1;
- pci_read_config_dword(QUARK_EMAC0, PCI_BASE_ADDRESS_0, &base); + qrk_pci_read_config_dword(QUARK_EMAC0, PCI_BASE_ADDRESS_0, &base); ret0 = designware_initialize(base, PHY_INTERFACE_MODE_RMII);
- pci_read_config_dword(QUARK_EMAC1, PCI_BASE_ADDRESS_0, &base); + qrk_pci_read_config_dword(QUARK_EMAC1, PCI_BASE_ADDRESS_0, &base); ret1 = designware_initialize(base, PHY_INTERFACE_MODE_RMII);
if (ret0 < 0 && ret1 < 0) @@ -154,7 +154,7 @@ void cpu_irq_init(void) struct quark_rcba *rcba; u32 base;
- base = x86_pci_read_config32(QUARK_LEGACY_BRIDGE, LB_RCBA); + qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base); base &= ~MEM_BAR_EN; rcba = (struct quark_rcba *)base;

On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
If we convert to use driver model pci on quark, we will encounter some chicken and egg problems like below:
- To enable PCIe root ports, we need program some registers on the message bus via pci bus. With driver model, the first time to access pci bus, the pci enumeration process will be triggered. But without first enabling PCIe root ports, pci enumeration just hangs when scanning PCIe root ports.
- Similar situation happens when trying to access GPIO from the PCIe enabling codes, as GPIO requires its block base address to be assigned via a pci configuration register in the bridge.
To avoid such dilemma, replace all pci calls in the quark codes to use the local version which does not go through driver model.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- New patch to avoid chicken and egg problem
arch/x86/cpu/quark/quark.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
Acked-by: Simon Glass sjg@chromium.org

Quark SoC holds the PCIe controller in reset following a power on. U-Boot needs to release the PCIe controller from reset. The PCIe controller (D23:F0/F1) will not be visible in PCI configuration space and any access to its PCI configuration registers will cause system hang while it is held in reset.
Enable PCIe controller per Quark firmware writer manual.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - New patch to enable PCIe controller on quark/galileo
arch/x86/cpu/quark/quark.c | 63 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 42 ++++++++++++++++++++++ board/intel/galileo/galileo.c | 56 +++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+)
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 2688a70..7c55d9e 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -73,6 +73,58 @@ static void quark_setup_bars(void) CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN); }
+static void quark_pcie_early_init(void) +{ + u32 pcie_cfg; + + /* + * Step1: Assert PCIe signal PERST# + * + * The CPU interface to the PERST# signal is platform dependent. + * Call the board-specific codes to perform this task. + */ + board_assert_perst(); + + /* Step2: PHY common lane reset */ + pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); + pcie_cfg |= PCIE_PHY_LANE_RST; + msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); + /* wait 1 ms for PHY common lane reset */ + mdelay(1); + + /* Step3: PHY sideband interface reset and controller main reset */ + pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); + pcie_cfg |= (PCIE_PHY_SB_RST | PCIE_CTLR_MAIN_RST); + msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); + /* wait 80ms for PLL to lock */ + mdelay(80); + + /* Step4: Controller sideband interface reset */ + pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); + pcie_cfg |= PCIE_CTLR_SB_RST; + msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); + /* wait 20ms for controller sideband interface reset */ + mdelay(20); + + /* Step5: De-assert PERST# */ + board_deassert_perst(); + + /* Step6: Controller primary interface reset */ + pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); + pcie_cfg |= PCIE_CTLR_PRI_RST; + msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); + + /* Mixer Load Lane 0 */ + pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0); + pcie_cfg &= ~((1 << 6) | (1 << 7)); + msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0, pcie_cfg); + + /* Mixer Load Lane 1 */ + pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1); + pcie_cfg &= ~((1 << 6) | (1 << 7)); + msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, pcie_cfg); +} + static void quark_enable_legacy_seg(void) { u32 hmisc2; @@ -106,6 +158,17 @@ int arch_cpu_init(void) */ quark_setup_bars();
+ /* + * Initialize PCIe controller + * + * Quark SoC holds the PCIe controller in reset following a power on. + * U-Boot needs to release the PCIe controller from reset. The PCIe + * controller (D23:F0/F1) will not be visible in PCI configuration + * space and any access to its PCI configuration registers will cause + * system hang while it is held in reset. + */ + quark_pcie_early_init(); + /* Turn on legacy segments (A/B/E/F) decode to system RAM */ quark_enable_legacy_seg();
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h index 1ce5693..aad7fbe 100644 --- a/arch/x86/include/asm/arch-quark/quark.h +++ b/arch/x86/include/asm/arch-quark/quark.h @@ -12,6 +12,7 @@ #define MSG_PORT_HOST_BRIDGE 0x03 #define MSG_PORT_RMU 0x04 #define MSG_PORT_MEM_MGR 0x05 +#define MSG_PORT_PCIE_AFE 0x16 #define MSG_PORT_SOC_UNIT 0x31
/* Port 0x00: Memory Arbiter Message Port Registers */ @@ -48,6 +49,21 @@ #define ESRAM_BLK_CTRL 0x82 #define ESRAM_BLOCK_MODE 0x10000000
+/* Port 0x16: PCIe AFE Unit Port Registers */ + +#define PCIE_RXPICTRL0_L0 0x2080 +#define PCIE_RXPICTRL0_L1 0x2180 + +/* Port 0x31: SoC Unit Port Registers */ + +/* PCIe Controller Config */ +#define PCIE_CFG 0x36 +#define PCIE_CTLR_PRI_RST 0x00010000 +#define PCIE_PHY_SB_RST 0x00020000 +#define PCIE_CTLR_SB_RST 0x00040000 +#define PCIE_PHY_LANE_RST 0x00090000 +#define PCIE_CTLR_MAIN_RST 0x00100000 + /* DRAM */ #define DRAM_BASE 0x00000000 #define DRAM_MAX_SIZE 0x80000000 @@ -124,6 +140,32 @@ static inline void qrk_pci_write_config_dword(pci_dev_t dev, int offset, outl(value, PCI_REG_DATA); }
+/** + * board_assert_perst() - Assert the PERST# pin + * + * The CPU interface to the PERST# signal on Quark is platform dependent. + * Board-specific codes need supply this routine to assert PCIe slot reset. + * + * The tricky part in this routine is that any APIs that may trigger PCI + * enumeration process are strictly forbidden, as any access to PCIe root + * port's configuration registers will cause system hang while it is held + * in reset. + */ +void board_assert_perst(void); + +/** + * board_deassert_perst() - De-assert the PERST# pin + * + * The CPU interface to the PERST# signal on Quark is platform dependent. + * Board-specific codes need supply this routine to de-assert PCIe slot reset. + * + * The tricky part in this routine is that any APIs that may trigger PCI + * enumeration process are strictly forbidden, as any access to PCIe root + * port's configuration registers will cause system hang while it is held + * in reset. + */ +void board_deassert_perst(void); + #endif /* __ASSEMBLY__ */
#endif /* _QUARK_H_ */ diff --git a/board/intel/galileo/galileo.c b/board/intel/galileo/galileo.c index 746ab27..fce973b 100644 --- a/board/intel/galileo/galileo.c +++ b/board/intel/galileo/galileo.c @@ -5,12 +5,68 @@ */
#include <common.h> +#include <asm/io.h> +#include <asm/arch/device.h> +#include <asm/arch/gpio.h> +#include <asm/arch/quark.h>
int board_early_init_f(void) { return 0; }
+/* + * Intel Galileo gen2 board uses GPIO Resume Well bank pin0 as the PERST# pin. + * + * We cannot use any public GPIO APIs in <asm-generic/gpio.h> to control this + * pin, as these APIs will eventually call into gpio_ich6_ofdata_to_platdata() + * in the Intel ICH6 GPIO driver where it calls PCI configuration space access + * APIs which will trigger PCI enueration process. + * + * Check <asm/arch-quark/quark.h> for more details. + */ +void board_assert_perst(void) +{ + u32 base, port, val; + + /* retrieve the GPIO IO base */ + qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, PCI_CFG_GPIOBASE, &base); + base = (base & 0xffff) & ~0x7f; + + /* enable the pin */ + port = base + 0x20; + val = inl(port); + val |= (1 << 0); + outl(val, port); + + /* configure the pin as output */ + port = base + 0x24; + val = inl(port); + val &= ~(1 << 0); + outl(val, port); + + /* pull it down (assert) */ + port = base + 0x28; + val = inl(port); + val &= ~(1 << 0); + outl(val, port); +} + +void board_deassert_perst(void) +{ + u32 base, port, val; + + /* retrieve the GPIO IO base */ + qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, PCI_CFG_GPIOBASE, &base); + base = (base & 0xffff) & ~0x7f; + + /* pull it up (de-assert) */ + port = base + 0x28; + val = inl(port); + val |= (1 << 0); + outl(val, port); +} + void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio) { return;

Hi Bin,
On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
Quark SoC holds the PCIe controller in reset following a power on. U-Boot needs to release the PCIe controller from reset. The PCIe controller (D23:F0/F1) will not be visible in PCI configuration space and any access to its PCI configuration registers will cause system hang while it is held in reset.
Enable PCIe controller per Quark firmware writer manual.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- New patch to enable PCIe controller on quark/galileo
arch/x86/cpu/quark/quark.c | 63 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 42 ++++++++++++++++++++++ board/intel/galileo/galileo.c | 56 +++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
There are definitely some strange ordering problems with init on this board. I wonder if it is worth adding some notes to the bottom of README.x86?
Regards, Simon

Hi Simon,
On Wed, Sep 2, 2015 at 10:05 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
Quark SoC holds the PCIe controller in reset following a power on. U-Boot needs to release the PCIe controller from reset. The PCIe controller (D23:F0/F1) will not be visible in PCI configuration space and any access to its PCI configuration registers will cause system hang while it is held in reset.
Enable PCIe controller per Quark firmware writer manual.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- New patch to enable PCIe controller on quark/galileo
arch/x86/cpu/quark/quark.c | 63 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 42 ++++++++++++++++++++++ board/intel/galileo/galileo.c | 56 +++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
There are definitely some strange ordering problems with init on this board. I wonder if it is worth adding some notes to the bottom of README.x86?
Yep, I can try to document something in a follow-on patch.
Regards, Bin

Move to driver model pci for Intel quark/galileo.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
---
Changes in v2: - Remove arch/x86/cpu/quark/pci.c completely
arch/x86/cpu/quark/Makefile | 1 - arch/x86/cpu/quark/pci.c | 70 --------------------------------------------- arch/x86/cpu/quark/quark.c | 5 ---- arch/x86/dts/galileo.dts | 8 ++++-- configs/galileo_defconfig | 1 + include/configs/galileo.h | 12 -------- 6 files changed, 7 insertions(+), 90 deletions(-) delete mode 100644 arch/x86/cpu/quark/pci.c
diff --git a/arch/x86/cpu/quark/Makefile b/arch/x86/cpu/quark/Makefile index e87b424..8f1d018 100644 --- a/arch/x86/cpu/quark/Makefile +++ b/arch/x86/cpu/quark/Makefile @@ -6,4 +6,3 @@
obj-y += car.o dram.o msg_port.o quark.o obj-y += mrc.o mrc_util.o hte.o smc.o -obj-$(CONFIG_PCI) += pci.o diff --git a/arch/x86/cpu/quark/pci.c b/arch/x86/cpu/quark/pci.c deleted file mode 100644 index 354e15a..0000000 --- a/arch/x86/cpu/quark/pci.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2015, Bin Meng bmeng.cn@gmail.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <pci.h> -#include <asm/pci.h> -#include <asm/arch/device.h> - -DECLARE_GLOBAL_DATA_PTR; - -void board_pci_setup_hose(struct pci_controller *hose) -{ - hose->first_busno = 0; - hose->last_busno = 0; - - /* PCI memory space */ - pci_set_region(hose->regions + 0, - CONFIG_PCI_MEM_BUS, - CONFIG_PCI_MEM_PHYS, - CONFIG_PCI_MEM_SIZE, - PCI_REGION_MEM); - - /* PCI IO space */ - pci_set_region(hose->regions + 1, - CONFIG_PCI_IO_BUS, - CONFIG_PCI_IO_PHYS, - CONFIG_PCI_IO_SIZE, - PCI_REGION_IO); - - pci_set_region(hose->regions + 2, - CONFIG_PCI_PREF_BUS, - CONFIG_PCI_PREF_PHYS, - CONFIG_PCI_PREF_SIZE, - PCI_REGION_PREFETCH); - - pci_set_region(hose->regions + 3, - 0, - 0, - gd->ram_size, - PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); - - hose->region_count = 4; -} - -int board_pci_post_scan(struct pci_controller *hose) -{ - return 0; -} - -int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) -{ - /* - * TODO: - * - * For some unknown reason, the PCI enumeration process hangs - * when it scans to the PCIe root port 0 (D23:F0) & 1 (D23:F1). - * - * For now we just skip these two devices, and this needs to - * be revisited later. - */ - if (dev == QUARK_HOST_BRIDGE || - dev == QUARK_PCIE0 || dev == QUARK_PCIE1) { - return 1; - } - - return 0; -} diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 7c55d9e..dda3c7c 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -136,7 +136,6 @@ static void quark_enable_legacy_seg(void)
int arch_cpu_init(void) { - struct pci_controller *hose; int ret;
post_code(POST_CPU_INIT); @@ -148,10 +147,6 @@ int arch_cpu_init(void) if (ret) return ret;
- ret = pci_early_init_hose(&hose); - if (ret) - return ret; - /* * Quark SoC has some non-standard BARs (excluding PCI standard BARs) * which need be initialized with suggested values diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts index d77ff8a..f119bf7 100644 --- a/arch/x86/dts/galileo.dts +++ b/arch/x86/dts/galileo.dts @@ -54,8 +54,11 @@ pci { #address-cells = <3>; #size-cells = <2>; - compatible = "intel,pci"; - device_type = "pci"; + compatible = "pci-x86"; + u-boot,dm-pre-reloc; + ranges = <0x02000000 0x0 0x90000000 0x90000000 0 0x20000000 + 0x42000000 0x0 0xb0000000 0xb0000000 0 0x20000000 + 0x01000000 0x0 0x2000 0x2000 0 0xe000>;
pciuart0: uart@14,5 { compatible = "pci8086,0936.00", @@ -63,6 +66,7 @@ "pciclass,070002", "pciclass,0700", "x86-uart"; + u-boot,dm-pre-reloc; reg = <0x0000a500 0x0 0x0 0x0 0x0 0x0200a510 0x0 0x0 0x0 0x0>; reg-shift = <2>; diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig index 6ef1090..358e87b 100644 --- a/configs/galileo_defconfig +++ b/configs/galileo_defconfig @@ -11,6 +11,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y +CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/include/configs/galileo.h b/include/configs/galileo.h index 3c3c6e9..b7ec279 100644 --- a/include/configs/galileo.h +++ b/include/configs/galileo.h @@ -20,18 +20,6 @@ /* ns16550 UART is memory-mapped in Quark SoC */ #undef CONFIG_SYS_NS16550_PORT_MAPPED
-#define CONFIG_PCI_MEM_BUS 0x90000000 -#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS -#define CONFIG_PCI_MEM_SIZE 0x20000000 - -#define CONFIG_PCI_PREF_BUS 0xb0000000 -#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS -#define CONFIG_PCI_PREF_SIZE 0x20000000 - -#define CONFIG_PCI_IO_BUS 0x2000 -#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS -#define CONFIG_PCI_IO_SIZE 0xe000 - #define CONFIG_SYS_EARLY_PCI_INIT #define CONFIG_PCI_PNP

USB PHY needs to be properly initialized per Quark firmware writer guide, otherwise the EHCI controller on Quark SoC won't work.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - New patch to add USB PHY initialization support
arch/x86/cpu/quark/quark.c | 41 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 8 +++++++ 2 files changed, 49 insertions(+)
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index dda3c7c..637c370 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -125,6 +125,44 @@ static void quark_pcie_early_init(void) msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, pcie_cfg); }
+static void quark_usb_early_init(void) +{ + u32 usb; + + /* The sequence below comes from Quark firmware writer guide */ + + usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT); + usb &= ~(1 << 1); + usb |= ((1 << 6) | (1 << 7)); + msg_port_alt_write(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT, usb); + + usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_COMPBG); + usb &= ~((1 << 8) | (1 << 9)); + usb |= ((1 << 7) | (1 << 10)); + msg_port_alt_write(MSG_PORT_USB_AFE, USB2_COMPBG, usb); + + usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2); + usb |= (1 << 29); + msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb); + + usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1); + usb |= (1 << 1); + msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb); + + usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1); + usb &= ~((1 << 3) | (1 << 4) | (1 << 5)); + usb |= (1 << 6); + msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb); + + usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2); + usb &= ~(1 << 29); + msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb); + + usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2); + usb |= (1 << 24); + msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb); +} + static void quark_enable_legacy_seg(void) { u32 hmisc2; @@ -164,6 +202,9 @@ int arch_cpu_init(void) */ quark_pcie_early_init();
+ /* Initialize USB2 PHY */ + quark_usb_early_init(); + /* Turn on legacy segments (A/B/E/F) decode to system RAM */ quark_enable_legacy_seg();
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h index aad7fbe..5d81976 100644 --- a/arch/x86/include/asm/arch-quark/quark.h +++ b/arch/x86/include/asm/arch-quark/quark.h @@ -12,6 +12,7 @@ #define MSG_PORT_HOST_BRIDGE 0x03 #define MSG_PORT_RMU 0x04 #define MSG_PORT_MEM_MGR 0x05 +#define MSG_PORT_USB_AFE 0x14 #define MSG_PORT_PCIE_AFE 0x16 #define MSG_PORT_SOC_UNIT 0x31
@@ -49,6 +50,13 @@ #define ESRAM_BLK_CTRL 0x82 #define ESRAM_BLOCK_MODE 0x10000000
+/* Port 0x14: USB2 AFE Unit Port Registers */ + +#define USB2_GLOBAL_PORT 0x4001 +#define USB2_PLL1 0x7f02 +#define USB2_PLL2 0x7f03 +#define USB2_COMPBG 0x7f04 + /* Port 0x16: PCIe AFE Unit Port Registers */
#define PCIE_RXPICTRL0_L0 0x2080

Hi Bin,
On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
USB PHY needs to be properly initialized per Quark firmware writer guide, otherwise the EHCI controller on Quark SoC won't work.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- New patch to add USB PHY initialization support
arch/x86/cpu/quark/quark.c | 41 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 8 +++++++ 2 files changed, 49 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
But please see below.
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index dda3c7c..637c370 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -125,6 +125,44 @@ static void quark_pcie_early_init(void) msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, pcie_cfg); }
+static void quark_usb_early_init(void) +{
u32 usb;
/* The sequence below comes from Quark firmware writer guide */
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT);
usb &= ~(1 << 1);
usb |= ((1 << 6) | (1 << 7));
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT, usb);
How about adding new a function so you can do something like:
msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT, 1 << 1, (1 << 6) | (1 << 7))
We did this with pmic also. It seems like you have enough code doing this read/write dance that it would be worthwhile, perhaps as a follow-on patch.
Also these shifts should have enums/#defines.
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_COMPBG);
usb &= ~((1 << 8) | (1 << 9));
usb |= ((1 << 7) | (1 << 10));
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_COMPBG, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
usb |= (1 << 29);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1);
usb |= (1 << 1);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1);
usb &= ~((1 << 3) | (1 << 4) | (1 << 5));
usb |= (1 << 6);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
usb &= ~(1 << 29);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
usb |= (1 << 24);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
+}
static void quark_enable_legacy_seg(void) { u32 hmisc2; @@ -164,6 +202,9 @@ int arch_cpu_init(void) */ quark_pcie_early_init();
/* Initialize USB2 PHY */
quark_usb_early_init();
/* Turn on legacy segments (A/B/E/F) decode to system RAM */ quark_enable_legacy_seg();
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h index aad7fbe..5d81976 100644 --- a/arch/x86/include/asm/arch-quark/quark.h +++ b/arch/x86/include/asm/arch-quark/quark.h @@ -12,6 +12,7 @@ #define MSG_PORT_HOST_BRIDGE 0x03 #define MSG_PORT_RMU 0x04 #define MSG_PORT_MEM_MGR 0x05 +#define MSG_PORT_USB_AFE 0x14 #define MSG_PORT_PCIE_AFE 0x16 #define MSG_PORT_SOC_UNIT 0x31
@@ -49,6 +50,13 @@ #define ESRAM_BLK_CTRL 0x82 #define ESRAM_BLOCK_MODE 0x10000000
+/* Port 0x14: USB2 AFE Unit Port Registers */
+#define USB2_GLOBAL_PORT 0x4001 +#define USB2_PLL1 0x7f02 +#define USB2_PLL2 0x7f03 +#define USB2_COMPBG 0x7f04
/* Port 0x16: PCIe AFE Unit Port Registers */
#define PCIE_RXPICTRL0_L0 0x2080
1.8.2.1
Regards, Simon

Hi Simon,
On Wed, Sep 2, 2015 at 10:05 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
USB PHY needs to be properly initialized per Quark firmware writer guide, otherwise the EHCI controller on Quark SoC won't work.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- New patch to add USB PHY initialization support
arch/x86/cpu/quark/quark.c | 41 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 8 +++++++ 2 files changed, 49 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
But please see below.
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index dda3c7c..637c370 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -125,6 +125,44 @@ static void quark_pcie_early_init(void) msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, pcie_cfg); }
+static void quark_usb_early_init(void) +{
u32 usb;
/* The sequence below comes from Quark firmware writer guide */
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT);
usb &= ~(1 << 1);
usb |= ((1 << 6) | (1 << 7));
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT, usb);
How about adding new a function so you can do something like:
msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT, 1 << 1, (1 << 6) | (1 << 7))
We did this with pmic also. It seems like you have enough code doing this read/write dance that it would be worthwhile, perhaps as a follow-on patch.
Yep, I can do in a follow-on patch.
Also these shifts should have enums/#defines.
Sorry I tried my best to give these magic numbers some names. These registers/bits are undocumented in the Quark datasheet. They are just mentioned in the firmware writer guide, but still magic numbers, no detailed description at all. I referred to Intel's UEFI BIOS for Quark, still BIT0, BIT1 macros, like the one we dealt with on the MRC codes. So I have to use the (1 << n) format here (not the BITn macro)
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_COMPBG);
usb &= ~((1 << 8) | (1 << 9));
usb |= ((1 << 7) | (1 << 10));
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_COMPBG, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
usb |= (1 << 29);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1);
usb |= (1 << 1);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1);
usb &= ~((1 << 3) | (1 << 4) | (1 << 5));
usb |= (1 << 6);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
usb &= ~(1 << 29);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
usb |= (1 << 24);
msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
+}
[snip]
Regards, Bin

Move to driver model for USB on Intel Galileo.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
---
Changes in v2: - Update commit message to remove "USB not working" statement, as in v2, full USB support has been added.
configs/galileo_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig index 358e87b..55a002f 100644 --- a/configs/galileo_defconfig +++ b/configs/galileo_defconfig @@ -15,6 +15,8 @@ CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y +CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_DM_RTC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y

When building dm version of designware eth driver on a platform with 64-bit phys_addr_t, it reports the following warnings:
drivers/net/designware.c: In function 'designware_eth_probe': drivers/net/designware.c:599:2: warning: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'phys_addr_t' [-Wformat] drivers/net/designware.c:600:21: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] drivers/net/designware.c:601:21: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
This commit fixes the build warnings.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/net/designware.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index d9cb507..ae78d21 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -562,12 +562,12 @@ static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); struct dw_eth_dev *priv = dev_get_priv(dev); + u32 iobase = pdata->iobase; int ret;
- debug("%s, iobase=%lx, priv=%p\n", __func__, pdata->iobase, priv); - priv->mac_regs_p = (struct eth_mac_regs *)pdata->iobase; - priv->dma_regs_p = (struct eth_dma_regs *)(pdata->iobase + - DW_DMA_BASE_OFFSET); + debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); + priv->mac_regs_p = (struct eth_mac_regs *)iobase; + priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET); priv->interface = pdata->phy_interface;
dw_mdio_init(dev->name, priv->mac_regs_p);

Introduce device_is_on_pci_bus() which can be utilized by driver to test if a device is on a PCI bus.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - New patch to add an inline API to test if a device is on a PCI bus
drivers/pci/pci-uclass.c | 4 ++-- include/pci.h | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index b25298f..79a05cb 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -218,7 +218,7 @@ int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, { struct udevice *bus;
- for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;) + for (bus = dev; device_is_on_pci_bus(bus);) bus = bus->parent; return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size); } @@ -283,7 +283,7 @@ int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, { struct udevice *bus;
- for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;) + for (bus = dev; device_is_on_pci_bus(bus);) bus = bus->parent; return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep, size); diff --git a/include/pci.h b/include/pci.h index e24c970..293a021 100644 --- a/include/pci.h +++ b/include/pci.h @@ -1273,5 +1273,20 @@ struct pci_driver_entry { .match = __match, \ }
+#ifdef CONFIG_DM +#include <dm.h> + +/** + * device_is_on_pci_bus - Test if a device is on a PCI bus + * + * @dev: device to test + * @return: true if it is on a PCI bus, false otherwise + */ +static inline bool device_is_on_pci_bus(struct udevice *dev) +{ + return device_get_uclass_id(dev->parent) == UCLASS_PCI; +} +#endif + #endif /* __ASSEMBLY__ */ #endif /* _PCI_H */

On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
Introduce device_is_on_pci_bus() which can be utilized by driver to test if a device is on a PCI bus.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- New patch to add an inline API to test if a device is on a PCI bus
drivers/pci/pci-uclass.c | 4 ++-- include/pci.h | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-)
Acked-by: Simon Glass sjg@chromium.org

The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{ + static int num_cards; + char name[20]; + + /* Create a unique device name for PCI type devices */ + if (device_is_on_pci_bus(dev)) { + sprintf(name, "eth_designware#%u", num_cards++); + device_set_name(dev, name); + } + + return 0; +} + static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
+ /* + * If we are on PCI bus, either directly attached to a PCI root port, + * or via a PCI bridge, fill in platdata before we probe the hardware. + */ + if (device_is_on_pci_bus(dev)) { + pci_dev_t bdf; + + bdf = pci_get_bdf(dev); + pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase); + iobase &= PCI_BASE_ADDRESS_MEM_MASK; + iobase = pci_mem_to_phys(bdf, iobase); + + pdata->iobase = iobase; + pdata->phy_interface = PHY_INTERFACE_MODE_RMII; + } + debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET); @@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata, + .bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA, }; + +static struct pci_device_id supported[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) }, + { } +}; + +U_BOOT_PCI_DEVICE(eth_designware, supported); #endif

Hi Bin,
On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
return 0;
+}
static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf;
bdf = pci_get_bdf(dev);
pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase);
Can we use a dm_pci_...() function here?
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
}
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
+};
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
1.8.2.1
Regards, Simon

Hi Simon,
On Wed, Sep 2, 2015 at 10:05 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
return 0;
+}
static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf;
bdf = pci_get_bdf(dev);
pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase);
Can we use a dm_pci_...() function here?
Yes, I think so. Will do it in v3.
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
}
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
+};
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
Regards, Bin

Hi Bin,
On Wed, Sep 2, 2015 at 4:17 AM, Bin Meng bmeng.cn@gmail.com wrote:
The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Looks good. One question below.
Changes in v2:
- Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
return 0;
+}
static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf;
bdf = pci_get_bdf(dev);
pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
Is this just assumed for all PCI devices? Seems like it could vary, but I don't know the specifics of all the implementations this is expected to support. Should it be part of a quirk based on PID or something?
}
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
+};
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
1.8.2.1
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Hi Joe,
On Fri, Sep 4, 2015 at 11:29 PM, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Bin,
On Wed, Sep 2, 2015 at 4:17 AM, Bin Meng bmeng.cn@gmail.com wrote:
The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Looks good. One question below.
Changes in v2:
- Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
return 0;
+}
static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf;
bdf = pci_get_bdf(dev);
pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
Is this just assumed for all PCI devices? Seems like it could vary, but I don't know the specifics of all the implementations this is expected to support. Should it be part of a quirk based on PID or something?
I think it could vary, but given so far the driver only supports Intel Quark PCI variant, so I did not put a test logic against PCI vendor/device ID here. When in the future we support another PCI variant, we can add such logic.
}
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
+};
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
Regards, Bin

Hi Joe,
On 4 September 2015 at 23:57, Bin Meng bmeng.cn@gmail.com wrote:
Hi Joe,
On Fri, Sep 4, 2015 at 11:29 PM, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Bin,
On Wed, Sep 2, 2015 at 4:17 AM, Bin Meng bmeng.cn@gmail.com wrote:
The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Looks good. One question below.
Changes in v2:
- Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
return 0;
+}
static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf;
bdf = pci_get_bdf(dev);
pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
Is this just assumed for all PCI devices? Seems like it could vary, but I don't know the specifics of all the implementations this is expected to support. Should it be part of a quirk based on PID or something?
I think it could vary, but given so far the driver only supports Intel Quark PCI variant, so I did not put a test logic against PCI vendor/device ID here. When in the future we support another PCI variant, we can add such logic.
Does this sound OK to you? I'd like to apply this series to u-boot-x86 but want to make sure you are happy with it.
}
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
+};
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
Regards, Bin
Regards, Simon

Hi Simon,
On Tue, Sep 8, 2015 at 9:22 AM, Simon Glass sjg@chromium.org wrote:
Hi Joe,
On 4 September 2015 at 23:57, Bin Meng bmeng.cn@gmail.com wrote:
Hi Joe,
On Fri, Sep 4, 2015 at 11:29 PM, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Bin,
On Wed, Sep 2, 2015 at 4:17 AM, Bin Meng bmeng.cn@gmail.com wrote:
The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Looks good. One question below.
Changes in v2:
- Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
return 0;
+}
static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf;
bdf = pci_get_bdf(dev);
pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
Is this just assumed for all PCI devices? Seems like it could vary, but I don't know the specifics of all the implementations this is expected to support. Should it be part of a quirk based on PID or something?
I think it could vary, but given so far the driver only supports Intel Quark PCI variant, so I did not put a test logic against PCI vendor/device ID here. When in the future we support another PCI variant, we can add such logic.
Does this sound OK to you? I'd like to apply this series to u-boot-x86 but want to make sure you are happy with it.
This is fine. It will be up to the next developer to design the way to select this attribute. I'm guessing this is the first driver of its kind (PCI - different PHY connections) so there isn't anything to model after yet.
}
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
+};
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
Regards, Bin
Regards, Simon

Hi Joe,
On 8 September 2015 at 09:09, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Simon,
On Tue, Sep 8, 2015 at 9:22 AM, Simon Glass sjg@chromium.org wrote:
Hi Joe,
On 4 September 2015 at 23:57, Bin Meng bmeng.cn@gmail.com wrote:
Hi Joe,
On Fri, Sep 4, 2015 at 11:29 PM, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Bin,
On Wed, Sep 2, 2015 at 4:17 AM, Bin Meng bmeng.cn@gmail.com wrote:
The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Looks good. One question below.
Changes in v2:
- Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
return 0;
+}
static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf;
bdf = pci_get_bdf(dev);
pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
Is this just assumed for all PCI devices? Seems like it could vary, but I don't know the specifics of all the implementations this is expected to support. Should it be part of a quirk based on PID or something?
I think it could vary, but given so far the driver only supports Intel Quark PCI variant, so I did not put a test logic against PCI vendor/device ID here. When in the future we support another PCI variant, we can add such logic.
Does this sound OK to you? I'd like to apply this series to u-boot-x86 but want to make sure you are happy with it.
This is fine. It will be up to the next developer to design the way to select this attribute. I'm guessing this is the first driver of its kind (PCI - different PHY connections) so there isn't anything to model after yet.
OK, I'll go ahead and apply the rest of this series then.
}
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
+};
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
Regards, Simon

On 9 September 2015 at 12:05, Simon Glass sjg@chromium.org wrote:
Hi Joe,
On 8 September 2015 at 09:09, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Simon,
On Tue, Sep 8, 2015 at 9:22 AM, Simon Glass sjg@chromium.org wrote:
Hi Joe,
On 4 September 2015 at 23:57, Bin Meng bmeng.cn@gmail.com wrote:
Hi Joe,
On Fri, Sep 4, 2015 at 11:29 PM, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Bin,
On Wed, Sep 2, 2015 at 4:17 AM, Bin Meng bmeng.cn@gmail.com wrote:
The Designware ethernet controller is also seen on PCI bus, e.g. on Intel Quark SoC. Add this support in the DM version driver.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Looks good. One question below.
Changes in v2:
- Change to use device_is_on_pci_bus()
drivers/net/designware.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ae78d21..39a9e6b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -14,6 +14,7 @@ #include <errno.h> #include <miiphy.h> #include <malloc.h> +#include <pci.h> #include <linux/compiler.h> #include <linux/err.h> #include <asm/io.h> @@ -558,6 +559,20 @@ static int designware_eth_write_hwaddr(struct udevice *dev) return _dw_write_hwaddr(priv, pdata->enetaddr); }
+static int designware_eth_bind(struct udevice *dev) +{
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
return 0;
+}
static int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -565,6 +580,22 @@ static int designware_eth_probe(struct udevice *dev) u32 iobase = pdata->iobase; int ret;
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf;
bdf = pci_get_bdf(dev);
pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
Is this just assumed for all PCI devices? Seems like it could vary, but I don't know the specifics of all the implementations this is expected to support. Should it be part of a quirk based on PID or something?
I think it could vary, but given so far the driver only supports Intel Quark PCI variant, so I did not put a test logic against PCI vendor/device ID here. When in the future we support another PCI variant, we can add such logic.
Does this sound OK to you? I'd like to apply this series to u-boot-x86 but want to make sure you are happy with it.
This is fine. It will be up to the next developer to design the way to select this attribute. I'm guessing this is the first driver of its kind (PCI - different PHY connections) so there isn't anything to model after yet.
OK, I'll go ahead and apply the rest of this series then.
}
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv); priv->mac_regs_p = (struct eth_mac_regs *)iobase; priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +648,18 @@ U_BOOT_DRIVER(eth_designware) = { .id = UCLASS_ETH, .of_match = designware_eth_ids, .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind, .probe = designware_eth_probe, .ops = &designware_eth_ops, .priv_auto_alloc_size = sizeof(struct dw_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
+};
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
Regards, Simon
Applied to u-boot-x86, thanks!

Convert to use DM version of Designware ethernet driver on Intel quark/galileo.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
---
Changes in v2: None
arch/x86/cpu/quark/quark.c | 19 ------------------- configs/galileo_defconfig | 2 +- 2 files changed, 1 insertion(+), 20 deletions(-)
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 637c370..caa3875 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -6,8 +6,6 @@
#include <common.h> #include <mmc.h> -#include <netdev.h> -#include <phy.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/pci.h> @@ -231,23 +229,6 @@ int cpu_mmc_init(bd_t *bis) ARRAY_SIZE(mmc_supported)); }
-int cpu_eth_init(bd_t *bis) -{ - u32 base; - int ret0, ret1; - - qrk_pci_read_config_dword(QUARK_EMAC0, PCI_BASE_ADDRESS_0, &base); - ret0 = designware_initialize(base, PHY_INTERFACE_MODE_RMII); - - qrk_pci_read_config_dword(QUARK_EMAC1, PCI_BASE_ADDRESS_0, &base); - ret1 = designware_initialize(base, PHY_INTERFACE_MODE_RMII); - - if (ret0 < 0 && ret1 < 0) - return -1; - else - return 0; -} - void cpu_irq_init(void) { struct quark_rcba *rcba; diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig index 55a002f..481b964 100644 --- a/configs/galileo_defconfig +++ b/configs/galileo_defconfig @@ -13,7 +13,7 @@ CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y -CONFIG_NETDEVICES=y +CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_USB=y CONFIG_DM_USB=y

On Wed, Sep 2, 2015 at 4:17 AM, Bin Meng bmeng.cn@gmail.com wrote:
Convert to use DM version of Designware ethernet driver on Intel quark/galileo.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
Acked-by: Joe Hershberger joe.hershberger@ni.com

This adds static register programming for PCIe and USB after memory init as required by Quark firmware writer guide. Although not doing this did not cause any malfunction, just do it for safety.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - New patch to add PCIe/USB static register programming after memory init
arch/x86/cpu/quark/quark.c | 64 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 22 ++++++++++++ include/configs/galileo.h | 1 + 3 files changed, 87 insertions(+)
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index caa3875..934250b 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -223,6 +223,53 @@ void reset_cpu(ulong addr) x86_full_reset(); }
+static void quark_pcie_init(void) +{ + u32 val; + + /* PCIe upstream non-posted & posted request size */ + qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_CCFG, + CCFG_UPRS | CCFG_UNRS); + qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_CCFG, + CCFG_UPRS | CCFG_UNRS); + + /* PCIe packet fast transmit mode (IPF) */ + qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_MPC2, MPC2_IPF); + qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_MPC2, MPC2_IPF); + + /* PCIe message bus idle counter (SBIC) */ + qrk_pci_read_config_dword(QUARK_PCIE0, PCIE_RP_MBC, &val); + val |= MBC_SBIC; + qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_MBC, val); + qrk_pci_read_config_dword(QUARK_PCIE1, PCIE_RP_MBC, &val); + val |= MBC_SBIC; + qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_MBC, val); +} + +static void quark_usb_init(void) +{ + u32 bar; + + /* Change USB EHCI packet buffer OUT/IN threshold */ + qrk_pci_read_config_dword(QUARK_USB_EHCI, PCI_BASE_ADDRESS_0, &bar); + writel((0x7f << 16) | 0x7f, bar + EHCI_INSNREG01); + + /* Disable USB device interrupts */ + qrk_pci_read_config_dword(QUARK_USB_DEVICE, PCI_BASE_ADDRESS_0, &bar); + writel(0x7f, bar + USBD_INT_MASK); + writel((0xf << 16) | 0xf, bar + USBD_EP_INT_MASK); + writel((0xf << 16) | 0xf, bar + USBD_EP_INT_STS); +} + +int arch_early_init_r(void) +{ + quark_pcie_init(); + + quark_usb_init(); + + return 0; +} + int cpu_mmc_init(bd_t *bis) { return pci_mmc_init("Quark SDHCI", mmc_supported, @@ -256,3 +303,20 @@ int arch_misc_init(void) { return pirq_init(); } + +void board_final_cleanup(void) +{ + struct quark_rcba *rcba; + u32 base, val; + + qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base); + base &= ~MEM_BAR_EN; + rcba = (struct quark_rcba *)base; + + /* Initialize 'Component ID' to zero */ + val = readl(&rcba->esd); + val &= ~0xff0000; + writel(val, &rcba->esd); + + return; +} diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h index 5d81976..eb3afbf 100644 --- a/arch/x86/include/asm/arch-quark/quark.h +++ b/arch/x86/include/asm/arch-quark/quark.h @@ -88,6 +88,20 @@ /* 64KiB of RMU binary in flash */ #define RMU_BINARY_SIZE 0x10000
+/* PCIe Root Port Configuration Registers */ + +#define PCIE_RP_CCFG 0xd0 +#define CCFG_UPRS (1 << 14) +#define CCFG_UNRS (1 << 15) +#define CCFG_UNSD (1 << 23) +#define CCFG_UPSD (1 << 24) + +#define PCIE_RP_MPC2 0xd4 +#define MPC2_IPF (1 << 11) + +#define PCIE_RP_MBC 0xf4 +#define MBC_SBIC (3 << 16) + /* Legacy Bridge PCI Configuration Registers */ #define LB_GBA 0x44 #define LB_PM1BLK 0x48 @@ -100,6 +114,14 @@ #define LB_BC 0xd8 #define LB_RCBA 0xf0
+/* USB EHCI memory-mapped registers */ +#define EHCI_INSNREG01 0x94 + +/* USB device memory-mapped registers */ +#define USBD_INT_MASK 0x410 +#define USBD_EP_INT_STS 0x414 +#define USBD_EP_INT_MASK 0x418 + #ifndef __ASSEMBLY__
/* Root Complex Register Block */ diff --git a/include/configs/galileo.h b/include/configs/galileo.h index b7ec279..ba6c8f1 100644 --- a/include/configs/galileo.h +++ b/include/configs/galileo.h @@ -15,6 +15,7 @@
#define CONFIG_SYS_MONITOR_LEN (1 << 20) #define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_ARCH_EARLY_INIT_R #define CONFIG_ARCH_MISC_INIT
/* ns16550 UART is memory-mapped in Quark SoC */

On 2 September 2015 at 03:17, Bin Meng bmeng.cn@gmail.com wrote:
This adds static register programming for PCIe and USB after memory init as required by Quark firmware writer guide. Although not doing this did not cause any malfunction, just do it for safety.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- New patch to add PCIe/USB static register programming after memory init
arch/x86/cpu/quark/quark.c | 64 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 22 ++++++++++++ include/configs/galileo.h | 1 + 3 files changed, 87 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
participants (3)
-
Bin Meng
-
Joe Hershberger
-
Simon Glass