[U-Boot] [PATCH 0/8] boston: Ethernet support for MIPS Boston board

This series fixes some issues with PCIe support on the MIPS Boston development board, adds a driver for the EG20T GPIO controller that we use to control ethernet PHY reset & enables support for ethernet on the Boston board.
Note that QEMU currently (as of v2.10) does not emulate the EG20T ethernet device, so this leads to delays during boot in QEMU whilst the pch_gbe driver times out on attempted access to the PHY.
Applies atop u-boot-mips/next as of 50bff5194d7e ("MIPS: Break out of cache loops for unimplemented caches").
Paul Burton (8): pci: Make PCI bridge memory alignment configurable boston: Disable PCI bridge memory space alignment pci: xilinx: Initialise the root bridge during probe gpio: Provide dummy get/request & is_valid functions gpio: eg20t: Add driver for Intel EG20T GPIO controllers net: pch_gbe: Support PHY reset GPIOs net: pch_gbe: Use wait_for_bit() helper boston: Enable ethernet PHY, reset GPIO, device probe
arch/mips/Kconfig | 1 + arch/mips/dts/img,boston.dts | 8 +-- configs/boston32r2_defconfig | 2 + configs/boston32r2el_defconfig | 2 + configs/boston64r2_defconfig | 2 + configs/boston64r2el_defconfig | 2 + drivers/gpio/Kconfig | 8 +++ drivers/gpio/Makefile | 1 + drivers/gpio/eg20t-gpio.c | 139 +++++++++++++++++++++++++++++++++++++++++ drivers/net/pch_gbe.c | 96 +++++++++++++--------------- drivers/net/pch_gbe.h | 1 + drivers/pci/Kconfig | 7 +++ drivers/pci/pci_auto.c | 24 ++++--- drivers/pci/pcie_xilinx.c | 36 ++++++++++- include/asm-generic/gpio.h | 38 +++++++++++ include/configs/boston.h | 5 ++ 16 files changed, 307 insertions(+), 65 deletions(-) create mode 100644 drivers/gpio/eg20t-gpio.c

On some systems aligning PCI memory to a 1MB boundary every time a bridge is encountered may lead to exhausting the available memory space before all devices have been assigned addresses.
For example on the MIPS Boston development board we have an Intel EG20T Platform Controller Hub connected to a Xilinx AXI to PCIe root port which is only assigned a 1MB memory region. The Intel EG20T contains a bridge device beneath which all of its peripheral devices can be found, and that bridge device contains a ROM. If we align to 1MB when we encounter each bridge device we therefore do something like this:
- Start with bus_lower at 0x16000000.
- Find the Xilinx root bridge, which has no visible BARs so we do very little to it.
- Probe the bus beneath the Xilinx bridge device, aligning bus_lower to a 1MB boundary first. That leaves it still at 0x16000000.
- Find the EG20T bridge device, which we find has a 64KiB ROM. We assign it the address range 0x16000000-0x1600ffff which leaves bus_lower at 0x16010000.
- Probe the bus beneath the EG20T bridge device, aligning bus_lower to a 1MB boundary first. This leaves bus_lower at 0x16100000, which is the end of the available memory space.
- Find the various peripheral devices the EG20T contains, but fail to assign any memory space to them since bus_lower is at the end of the memory space available to the PCI bus.
This patch allows that 1MB alignment to be changed or disabled via Kconfig, so that systems such as this can select an alignment which works for them.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com ---
drivers/pci/Kconfig | 7 +++++++ drivers/pci/pci_auto.c | 24 ++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 58f128d8a6..1605cfc8fa 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -26,6 +26,13 @@ config DM_PCI_COMPAT measure when porting a board to use driver model for PCI. Once the board is fully supported, this option should be disabled.
+config DM_PCI_BRIDGE_MEM_ALIGN + hex "PCI bridge memory alignment" + default 0x100000 + help + PCI memory space will be aligned to be a multiple of this value + whenever a PCI-to-PCI bridge is encountered. + config PCI_PNP bool "Enable Plug & Play support for PCI" depends on PCI || DM_PCI diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index c2bc32678a..c4eee6f0ba 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -186,8 +186,10 @@ void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus) dm_pci_write_config8(dev, PCI_SUBORDINATE_BUS, 0xff);
if (pci_mem) { - /* Round memory allocator to 1MB boundary */ - pciauto_region_align(pci_mem, 0x100000); + /* Round memory allocator to a suitable boundary */ + if (CONFIG_DM_PCI_BRIDGE_MEM_ALIGN) + pciauto_region_align(pci_mem, + CONFIG_DM_PCI_BRIDGE_MEM_ALIGN);
/* * Set up memory and I/O filter limits, assume 32-bit @@ -200,8 +202,10 @@ void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus) }
if (pci_prefetch) { - /* Round memory allocator to 1MB boundary */ - pciauto_region_align(pci_prefetch, 0x100000); + /* Round memory allocator to a suitable boundary */ + if (CONFIG_DM_PCI_BRIDGE_MEM_ALIGN) + pciauto_region_align(pci_prefetch, + CONFIG_DM_PCI_BRIDGE_MEM_ALIGN);
/* * Set up memory and I/O filter limits, assume 32-bit @@ -260,8 +264,10 @@ void dm_pciauto_postscan_setup_bridge(struct udevice *dev, int sub_bus) dm_pci_write_config8(dev, PCI_SUBORDINATE_BUS, sub_bus - ctlr->seq);
if (pci_mem) { - /* Round memory allocator to 1MB boundary */ - pciauto_region_align(pci_mem, 0x100000); + /* Round memory allocator to a suitable boundary */ + if (CONFIG_DM_PCI_BRIDGE_MEM_ALIGN) + pciauto_region_align(pci_mem, + CONFIG_DM_PCI_BRIDGE_MEM_ALIGN);
dm_pci_write_config16(dev, PCI_MEMORY_LIMIT, (pci_mem->bus_lower - 1) >> 16); @@ -274,8 +280,10 @@ void dm_pciauto_postscan_setup_bridge(struct udevice *dev, int sub_bus) &prefechable_64); prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
- /* Round memory allocator to 1MB boundary */ - pciauto_region_align(pci_prefetch, 0x100000); + /* Round memory allocator to a suitable boundary */ + if (CONFIG_DM_PCI_BRIDGE_MEM_ALIGN) + pciauto_region_align(pci_prefetch, + CONFIG_DM_PCI_BRIDGE_MEM_ALIGN);
dm_pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT, (pci_prefetch->bus_lower - 1) >> 16);

On 21.11.2017 21:33, Paul Burton wrote:
On some systems aligning PCI memory to a 1MB boundary every time a bridge is encountered may lead to exhausting the available memory space before all devices have been assigned addresses.
For example on the MIPS Boston development board we have an Intel EG20T Platform Controller Hub connected to a Xilinx AXI to PCIe root port which is only assigned a 1MB memory region. The Intel EG20T contains a bridge device beneath which all of its peripheral devices can be found, and that bridge device contains a ROM. If we align to 1MB when we encounter each bridge device we therefore do something like this:
Start with bus_lower at 0x16000000.
Find the Xilinx root bridge, which has no visible BARs so we do very little to it.
Probe the bus beneath the Xilinx bridge device, aligning bus_lower to a 1MB boundary first. That leaves it still at 0x16000000.
Find the EG20T bridge device, which we find has a 64KiB ROM. We assign it the address range 0x16000000-0x1600ffff which leaves bus_lower at 0x16010000.
Probe the bus beneath the EG20T bridge device, aligning bus_lower to a 1MB boundary first. This leaves bus_lower at 0x16100000, which is the end of the available memory space.
Find the various peripheral devices the EG20T contains, but fail to assign any memory space to them since bus_lower is at the end of the memory space available to the PCI bus.
This patch allows that 1MB alignment to be changed or disabled via Kconfig, so that systems such as this can select an alignment which works for them.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com
drivers/pci/Kconfig | 7 +++++++ drivers/pci/pci_auto.c | 24 ++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-)
Reviewed-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com

On the MIPS Boston development board we have an Intel EG20T Platform Controller Hub connected to a Xilinx AXI to PCIe root port which is only assigned a 1MB memory region. The Intel EG20T contains a bridge device beneath which all of its peripheral devices can be found, and that bridge device contains a ROM. If we align to 1MB when we encounter each bridge device we therefore do something like this:
- Start with bus_lower at 0x16000000.
- Find the Xilinx root bridge, which has no visible BARs so we do very little to it.
- Probe the bus beneath the Xilinx bridge device, aligning bus_lower to a 1MB boundary first. That leaves it still at 0x16000000.
- Find the EG20T bridge device, which we find has a 64KiB ROM. We assign it the address range 0x16000000-0x1600ffff which leaves bus_lower at 0x16010000.
- Probe the bus beneath the EG20T bridge device, aligning bus_lower to a 1MB boundary first. This leaves bus_lower at 0x16100000, which is the end of the available memory space.
- Find the various peripheral devices the EG20T contains, but fail to assign any memory space to them since bus_lower is at the end of the memory space available to the PCI bus.
Fix this by disabling that 1MB alignment, which allows all of the EG20T peripheral devices to be assigned memory space within the 1MB region available.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com ---
configs/boston32r2_defconfig | 1 + configs/boston32r2el_defconfig | 1 + configs/boston64r2_defconfig | 1 + configs/boston64r2el_defconfig | 1 + 4 files changed, 4 insertions(+)
diff --git a/configs/boston32r2_defconfig b/configs/boston32r2_defconfig index b8c87caaf8..1d21f1643c 100644 --- a/configs/boston32r2_defconfig +++ b/configs/boston32r2_defconfig @@ -35,6 +35,7 @@ CONFIG_DM_ETH=y CONFIG_PCH_GBE=y CONFIG_PCI=y CONFIG_DM_PCI=y +CONFIG_DM_PCI_BRIDGE_MEM_ALIGN=0x0 CONFIG_PCI_XILINX=y CONFIG_SYS_NS16550=y CONFIG_LZ4=y diff --git a/configs/boston32r2el_defconfig b/configs/boston32r2el_defconfig index 5cc43880a3..d26adc68f2 100644 --- a/configs/boston32r2el_defconfig +++ b/configs/boston32r2el_defconfig @@ -36,6 +36,7 @@ CONFIG_DM_ETH=y CONFIG_PCH_GBE=y CONFIG_PCI=y CONFIG_DM_PCI=y +CONFIG_DM_PCI_BRIDGE_MEM_ALIGN=0x0 CONFIG_PCI_XILINX=y CONFIG_SYS_NS16550=y CONFIG_LZ4=y diff --git a/configs/boston64r2_defconfig b/configs/boston64r2_defconfig index c30e0b0903..1491575af5 100644 --- a/configs/boston64r2_defconfig +++ b/configs/boston64r2_defconfig @@ -36,6 +36,7 @@ CONFIG_DM_ETH=y CONFIG_PCH_GBE=y CONFIG_PCI=y CONFIG_DM_PCI=y +CONFIG_DM_PCI_BRIDGE_MEM_ALIGN=0x0 CONFIG_PCI_XILINX=y CONFIG_SYS_NS16550=y CONFIG_LZ4=y diff --git a/configs/boston64r2el_defconfig b/configs/boston64r2el_defconfig index b9506ccb7b..933b5bfc48 100644 --- a/configs/boston64r2el_defconfig +++ b/configs/boston64r2el_defconfig @@ -37,6 +37,7 @@ CONFIG_DM_ETH=y CONFIG_PCH_GBE=y CONFIG_PCI=y CONFIG_DM_PCI=y +CONFIG_DM_PCI_BRIDGE_MEM_ALIGN=0x0 CONFIG_PCI_XILINX=y CONFIG_SYS_NS16550=y CONFIG_LZ4=y

Whilst the pcie_xilinx driver was sufficient to run under QEMU, it was failing on FPGA because it wasn't configuring the root bridge, and access from the PCI auto-configuration code to subordinate busses would lead to data bus errors. Fix this by configuring the root bridge to allow access to all possible subordinate busses based upon the size of the ECAM region, and disable interrupts since U-Boot isn't using them.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com ---
drivers/pci/pcie_xilinx.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c index 57112f5333..877087d4f1 100644 --- a/drivers/pci/pcie_xilinx.c +++ b/drivers/pci/pcie_xilinx.c @@ -21,8 +21,14 @@ struct xilinx_pcie { };
/* Register definitions */ -#define XILINX_PCIE_REG_PSCR 0x144 -#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11) +#define XILINX_PCIE_REG_BRIDGE_INFO 0x130 +#define XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_SHIFT 16 +#define XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_MASK (0x7 << 16) +#define XILINX_PCIE_REG_INT_MASK 0x13c +#define XILINX_PCIE_REG_PSCR 0x144 +#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11) +#define XILINX_PCIE_REG_RPSC 0x148 +#define XILINX_PCIE_REG_RPSC_BRIDGEEN BIT(0)
/** * pcie_xilinx_link_up() - Check whether the PCIe link is up @@ -159,6 +165,31 @@ static int pcie_xilinx_ofdata_to_platdata(struct udevice *dev) return 0; }
+static int pcie_xilinx_probe(struct udevice *dev) +{ + struct xilinx_pcie *pcie = dev_get_priv(dev); + u32 bridge_info, ecam_sz, rpsc; + + /* Disable all interrupts */ + writel(0, pcie->cfg_base + XILINX_PCIE_REG_INT_MASK); + + /* Enable the bridge */ + rpsc = readl(pcie->cfg_base + XILINX_PCIE_REG_RPSC); + rpsc |= XILINX_PCIE_REG_RPSC_BRIDGEEN; + writel(rpsc, pcie->cfg_base + XILINX_PCIE_REG_RPSC); + + /* Discover the size of the ECAM region */ + bridge_info = readl(pcie->cfg_base + XILINX_PCIE_REG_BRIDGE_INFO); + ecam_sz = bridge_info & XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_MASK; + ecam_sz >>= XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_SHIFT; + + /* Enable access to all possible subordinate buses */ + writel((0 << 0) | (1 << 8) | (GENMASK(ecam_sz - 1, 0) << 16), + pcie->cfg_base + PCI_PRIMARY_BUS); + + return 0; +} + static const struct dm_pci_ops pcie_xilinx_ops = { .read_config = pcie_xilinx_read_config, .write_config = pcie_xilinx_write_config, @@ -175,5 +206,6 @@ U_BOOT_DRIVER(pcie_xilinx) = { .of_match = pcie_xilinx_ids, .ops = &pcie_xilinx_ops, .ofdata_to_platdata = pcie_xilinx_ofdata_to_platdata, + .probe = pcie_xilinx_probe, .priv_auto_alloc_size = sizeof(struct xilinx_pcie), };

+cc Michal for Xilinx stuff
On 21.11.2017 21:33, Paul Burton wrote:
Whilst the pcie_xilinx driver was sufficient to run under QEMU, it was failing on FPGA because it wasn't configuring the root bridge, and access from the PCI auto-configuration code to subordinate busses would lead to data bus errors. Fix this by configuring the root bridge to allow access to all possible subordinate busses based upon the size of the ECAM region, and disable interrupts since U-Boot isn't using them.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com
drivers/pci/pcie_xilinx.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c index 57112f5333..877087d4f1 100644 --- a/drivers/pci/pcie_xilinx.c +++ b/drivers/pci/pcie_xilinx.c @@ -21,8 +21,14 @@ struct xilinx_pcie { };
/* Register definitions */ -#define XILINX_PCIE_REG_PSCR 0x144 -#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11) +#define XILINX_PCIE_REG_BRIDGE_INFO 0x130 +#define XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_SHIFT 16 +#define XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_MASK (0x7 << 16) +#define XILINX_PCIE_REG_INT_MASK 0x13c +#define XILINX_PCIE_REG_PSCR 0x144 +#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11) +#define XILINX_PCIE_REG_RPSC 0x148 +#define XILINX_PCIE_REG_RPSC_BRIDGEEN BIT(0)
/**
- pcie_xilinx_link_up() - Check whether the PCIe link is up
@@ -159,6 +165,31 @@ static int pcie_xilinx_ofdata_to_platdata(struct udevice *dev) return 0; }
+static int pcie_xilinx_probe(struct udevice *dev) +{
- struct xilinx_pcie *pcie = dev_get_priv(dev);
- u32 bridge_info, ecam_sz, rpsc;
- /* Disable all interrupts */
- writel(0, pcie->cfg_base + XILINX_PCIE_REG_INT_MASK);
- /* Enable the bridge */
- rpsc = readl(pcie->cfg_base + XILINX_PCIE_REG_RPSC);
- rpsc |= XILINX_PCIE_REG_RPSC_BRIDGEEN;
- writel(rpsc, pcie->cfg_base + XILINX_PCIE_REG_RPSC);
- /* Discover the size of the ECAM region */
- bridge_info = readl(pcie->cfg_base + XILINX_PCIE_REG_BRIDGE_INFO);
- ecam_sz = bridge_info & XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_MASK;
- ecam_sz >>= XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_SHIFT;
- /* Enable access to all possible subordinate buses */
- writel((0 << 0) | (1 << 8) | (GENMASK(ecam_sz - 1, 0) << 16),
pcie->cfg_base + PCI_PRIMARY_BUS);
- return 0;
+}
static const struct dm_pci_ops pcie_xilinx_ops = { .read_config = pcie_xilinx_read_config, .write_config = pcie_xilinx_write_config, @@ -175,5 +206,6 @@ U_BOOT_DRIVER(pcie_xilinx) = { .of_match = pcie_xilinx_ids, .ops = &pcie_xilinx_ops, .ofdata_to_platdata = pcie_xilinx_ofdata_to_platdata,
- .probe = pcie_xilinx_probe, .priv_auto_alloc_size = sizeof(struct xilinx_pcie),
};

Hi
On 21.11.2017 22:31, Daniel Schwierzeck wrote:
+cc Michal for Xilinx stuff
On 21.11.2017 21:33, Paul Burton wrote:
Whilst the pcie_xilinx driver was sufficient to run under QEMU, it was failing on FPGA because it wasn't configuring the root bridge, and access from the PCI auto-configuration code to subordinate busses would lead to data bus errors. Fix this by configuring the root bridge to allow access to all possible subordinate busses based upon the size of the ECAM region, and disable interrupts since U-Boot isn't using them.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com
drivers/pci/pcie_xilinx.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c index 57112f5333..877087d4f1 100644 --- a/drivers/pci/pcie_xilinx.c +++ b/drivers/pci/pcie_xilinx.c @@ -21,8 +21,14 @@ struct xilinx_pcie { };
/* Register definitions */ -#define XILINX_PCIE_REG_PSCR 0x144 -#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11) +#define XILINX_PCIE_REG_BRIDGE_INFO 0x130 +#define XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_SHIFT 16 +#define XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_MASK (0x7 << 16) +#define XILINX_PCIE_REG_INT_MASK 0x13c +#define XILINX_PCIE_REG_PSCR 0x144 +#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11) +#define XILINX_PCIE_REG_RPSC 0x148 +#define XILINX_PCIE_REG_RPSC_BRIDGEEN BIT(0)
/**
- pcie_xilinx_link_up() - Check whether the PCIe link is up
@@ -159,6 +165,31 @@ static int pcie_xilinx_ofdata_to_platdata(struct udevice *dev) return 0; }
+static int pcie_xilinx_probe(struct udevice *dev) +{
- struct xilinx_pcie *pcie = dev_get_priv(dev);
- u32 bridge_info, ecam_sz, rpsc;
- /* Disable all interrupts */
- writel(0, pcie->cfg_base + XILINX_PCIE_REG_INT_MASK);
- /* Enable the bridge */
- rpsc = readl(pcie->cfg_base + XILINX_PCIE_REG_RPSC);
- rpsc |= XILINX_PCIE_REG_RPSC_BRIDGEEN;
- writel(rpsc, pcie->cfg_base + XILINX_PCIE_REG_RPSC);
- /* Discover the size of the ECAM region */
- bridge_info = readl(pcie->cfg_base + XILINX_PCIE_REG_BRIDGE_INFO);
- ecam_sz = bridge_info & XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_MASK;
- ecam_sz >>= XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_SHIFT;
- /* Enable access to all possible subordinate buses */
- writel((0 << 0) | (1 << 8) | (GENMASK(ecam_sz - 1, 0) << 16),
pcie->cfg_base + PCI_PRIMARY_BUS);
- return 0;
+}
static const struct dm_pci_ops pcie_xilinx_ops = { .read_config = pcie_xilinx_read_config, .write_config = pcie_xilinx_write_config, @@ -175,5 +206,6 @@ U_BOOT_DRIVER(pcie_xilinx) = { .of_match = pcie_xilinx_ids, .ops = &pcie_xilinx_ops, .ofdata_to_platdata = pcie_xilinx_ofdata_to_platdata,
- .probe = pcie_xilinx_probe, .priv_auto_alloc_size = sizeof(struct xilinx_pcie),
};
Sorry I am not running this configuration and we have never tried to use this driver in connection to xilinx arm/microblaze socs. That's why I simply don't know.
Thanks, Michal

Allow for drivers to make use of driver model GPIOs when they're enabled & available without needing to #ifdef on CONFIG_DM_GPIO by providing dummy functions covering GPIO requests. Each will simply return -ENODEV or -EINVAL, depending upon which the real implementation returns when a GPIO isn't found. Only the driver model versions of the GPIO request functions are covered & dm_gpio_request is excluded since it's documented as only being of use for debugging, so drivers shouldn't be calling it anyway.
Also provide a dummy dm_gpio_is_valid, with the idea that all other GPIO functions called would be within an if (dm_gpio_is_valid(...)) statement and have been optimised out in cases where that returns a compile-time constant false.
This parallels the clock API, keeping the #ifdefs & checks in a single location allowing drivers or other code to use GPIOs without needing to perform such checks themselves.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com ---
include/asm-generic/gpio.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index bf230c15ba..7f1f9031ff 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -139,6 +139,9 @@ struct gpio_desc { */ static inline bool dm_gpio_is_valid(const struct gpio_desc *desc) { + if (!IS_ENABLED(CONFIG_DM_GPIO)) + return false; + return desc->dev != NULL; }
@@ -346,7 +349,14 @@ const char *gpio_get_bank_info(struct udevice *dev, int *offset_count); * @desc: Returns description, on success * @return 0 if OK, -ve on error */ +#ifdef CONFIG_DM_GPIO int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc); +#else +static inline int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) +{ + return -EINVAL; +} +#endif
/** * gpio_lookup_name - Look up a GPIO name and return its details @@ -359,8 +369,17 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc); * @offsetp: Returns the offset number within this device * @gpiop: Returns the absolute GPIO number, numbered from 0 */ +#ifdef CONFIG_DM_GPIO int gpio_lookup_name(const char *name, struct udevice **devp, unsigned int *offsetp, unsigned int *gpiop); +#else +static inline int +gpio_lookup_name(const char *name, struct udevice **devp, + unsigned int *offsetp, unsigned int *gpiop) +{ + return -EINVAL; +} +#endif
/** * gpio_get_values_as_int() - Turn the values of a list of GPIOs into an int @@ -431,8 +450,17 @@ int gpio_claim_vector(const int *gpio_num_array, const char *fmt); * something wrong with the list, or other -ve for another error (e.g. * -EBUSY if a GPIO was already requested) */ +#ifdef CONFIG_DM_GPIO int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, struct gpio_desc *desc, int flags); +#else +static inline int +gpio_request_by_name(struct udevice *dev, const char *list_name, + int index, struct gpio_desc *desc, int flags) +{ + return -ENOENT; +} +#endif
/** * gpio_request_list_by_name() - Request a list of GPIOs @@ -455,9 +483,19 @@ int gpio_request_by_name(struct udevice *dev, const char *list_name, * @flags: Indicates the GPIO input/output settings (GPIOD_...) * @return number of GPIOs requested, or -ve on error */ +#ifdef CONFIG_DM_GPIO int gpio_request_list_by_name(struct udevice *dev, const char *list_name, struct gpio_desc *desc_list, int max_count, int flags); +#else +static inline int +gpio_request_list_by_name(struct udevice *dev, const char *list_name, + struct gpio_desc *desc_list, int max_count, + int flags) +{ + return -ENOENT; +} +#endif
/** * dm_gpio_request() - manually request a GPIO

On 21.11.2017 21:33, Paul Burton wrote:
Allow for drivers to make use of driver model GPIOs when they're enabled & available without needing to #ifdef on CONFIG_DM_GPIO by providing dummy functions covering GPIO requests. Each will simply return -ENODEV or -EINVAL, depending upon which the real implementation returns when a GPIO isn't found. Only the driver model versions of the GPIO request functions are covered & dm_gpio_request is excluded since it's documented as only being of use for debugging, so drivers shouldn't be calling it anyway.
Also provide a dummy dm_gpio_is_valid, with the idea that all other GPIO functions called would be within an if (dm_gpio_is_valid(...)) statement and have been optimised out in cases where that returns a compile-time constant false.
This parallels the clock API, keeping the #ifdefs & checks in a single location allowing drivers or other code to use GPIOs without needing to perform such checks themselves.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com
include/asm-generic/gpio.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
Reviewed-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com

Add a driver for the GPIO controller found in the Intel EG20T Platform Controller Hub. This is used on the MIPS Boston development board to provide GPIOs including ethernet PHY reset.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com ---
drivers/gpio/Kconfig | 8 +++ drivers/gpio/Makefile | 1 + drivers/gpio/eg20t-gpio.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 drivers/gpio/eg20t-gpio.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6240c39539..ac7c911951 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -294,4 +294,12 @@ config MPC85XX_GPIO
The driver has been tested on MPC85XX, but it is likely that other PowerQUICC III devices will work as well. + +config EG20T_GPIO + bool "Intel EG20T GPIO driver" + depends on DM_GPIO && DM_PCI + help + Enable this to support the GPIO controller found in the Intel EG20T + Platform Controller Hub. + endmenu diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 81f55a576b..150c7b3eb5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o obj-$(CONFIG_MSM_GPIO) += msm_gpio.o obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o obj-$(CONFIG_PM8916_GPIO) += pm8916_gpio.o +obj-$(CONFIG_EG20T_GPIO) += eg20t-gpio.o diff --git a/drivers/gpio/eg20t-gpio.c b/drivers/gpio/eg20t-gpio.c new file mode 100644 index 0000000000..958541689a --- /dev/null +++ b/drivers/gpio/eg20t-gpio.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 Imagination Technologies + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <pci.h> +#include <asm/io.h> +#include <asm/gpio.h> + +enum { + REG_IEN = 0x00, + REG_ISTATUS = 0x04, + REG_IDISP = 0x08, + REG_ICLR = 0x0c, + REG_IMASK = 0x10, + REG_IMASKCLR = 0x14, + REG_PO = 0x18, + REG_PI = 0x1c, + REG_PM = 0x20, +}; + +struct eg20t_gpio_priv { + void *base; +}; + +static int eg20t_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct eg20t_gpio_priv *priv = dev_get_priv(dev); + u32 pm, pval; + + pm = readl(priv->base + REG_PM); + if ((pm >> offset) & 0x1) + pval = readl(priv->base + REG_PO); + else + pval = readl(priv->base + REG_PI); + + return (pval >> offset) & 0x1; +} + +static int eg20t_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + struct eg20t_gpio_priv *priv = dev_get_priv(dev); + u32 po; + + po = readl(priv->base + REG_PO); + if (value) + po |= 1 << offset; + else + po &= ~(1 << offset); + writel(po, priv->base + REG_PO); + return 0; +} + +static int eg20t_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + struct eg20t_gpio_priv *priv = dev_get_priv(dev); + u32 pm; + + pm = readl(priv->base + REG_PM); + pm &= ~(1 << offset); + writel(pm, priv->base + REG_PM); + return 0; +} + +static int eg20t_gpio_direction_output(struct udevice *dev, unsigned int offset, + int value) +{ + struct eg20t_gpio_priv *priv = dev_get_priv(dev); + u32 pm; + + pm = readl(priv->base + REG_PM); + pm |= 1 << offset; + writel(pm, priv->base + REG_PM); + + return eg20t_gpio_set_value(dev, offset, value); +} + +static int eg20t_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct eg20t_gpio_priv *priv = dev_get_priv(dev); + u32 pm; + + pm = readl(priv->base + REG_PM); + + if ((pm >> offset) & 0x1) + return GPIOF_OUTPUT; + + return GPIOF_INPUT; +} + +static const struct dm_gpio_ops eg20t_gpio_ops = { + .direction_input = eg20t_gpio_direction_input, + .direction_output = eg20t_gpio_direction_output, + .get_value = eg20t_gpio_get_value, + .set_value = eg20t_gpio_set_value, + .get_function = eg20t_gpio_get_function, +}; + +static int eg20t_gpio_probe(struct udevice *dev) +{ + struct eg20t_gpio_priv *priv = dev_get_priv(dev); + struct gpio_dev_priv *uc_priv = dev->uclass_priv; + + priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM); + if (!priv->base) { + debug("failed to map GPIO registers\n"); + return -EINVAL; + } + + uc_priv->gpio_count = 12; + uc_priv->bank_name = "eg20t"; + return 0; +} + +static const struct udevice_id eg20t_gpio_ids[] = { + { .compatible = "intel,eg20t-gpio" }, + { } +}; + +U_BOOT_DRIVER(eg20t_gpio) = { + .name = "eg20t-gpio", + .id = UCLASS_GPIO, + .of_match = eg20t_gpio_ids, + .probe = eg20t_gpio_probe, + .priv_auto_alloc_size = sizeof(struct eg20t_gpio_priv), + .ops = &eg20t_gpio_ops, +}; + +static struct pci_device_id eg20t_gpio_supported[] = { + { PCI_VENDOR_ID_INTEL, 0x8803 }, + { }, +}; + +U_BOOT_PCI_DEVICE(eg20t_gpio, eg20t_gpio_supported);

On 21.11.2017 21:33, Paul Burton wrote:
Add a driver for the GPIO controller found in the Intel EG20T Platform Controller Hub. This is used on the MIPS Boston development board to provide GPIOs including ethernet PHY reset.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com
drivers/gpio/Kconfig | 8 +++ drivers/gpio/Makefile | 1 + drivers/gpio/eg20t-gpio.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 drivers/gpio/eg20t-gpio.c
Reviewed-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
nits below
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6240c39539..ac7c911951 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -294,4 +294,12 @@ config MPC85XX_GPIO
The driver has been tested on MPC85XX, but it is likely that other PowerQUICC III devices will work as well.
+config EG20T_GPIO
- bool "Intel EG20T GPIO driver"
- depends on DM_GPIO && DM_PCI
- help
Enable this to support the GPIO controller found in the Intel EG20T
Platform Controller Hub.
endmenu diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 81f55a576b..150c7b3eb5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o obj-$(CONFIG_MSM_GPIO) += msm_gpio.o obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o obj-$(CONFIG_PM8916_GPIO) += pm8916_gpio.o +obj-$(CONFIG_EG20T_GPIO) += eg20t-gpio.o diff --git a/drivers/gpio/eg20t-gpio.c b/drivers/gpio/eg20t-gpio.c new file mode 100644 index 0000000000..958541689a --- /dev/null +++ b/drivers/gpio/eg20t-gpio.c @@ -0,0 +1,139 @@ +/*
- Copyright (C) 2016 Imagination Technologies
- SPDX-License-Identifier: GPL-2.0
- */
+#include <common.h> +#include <dm.h> +#include <errno.h> +#include <pci.h> +#include <asm/io.h> +#include <asm/gpio.h>
+enum {
- REG_IEN = 0x00,
- REG_ISTATUS = 0x04,
- REG_IDISP = 0x08,
- REG_ICLR = 0x0c,
- REG_IMASK = 0x10,
- REG_IMASKCLR = 0x14,
- REG_PO = 0x18,
- REG_PI = 0x1c,
- REG_PM = 0x20,
+};
+struct eg20t_gpio_priv {
- void *base;
+};
+static int eg20t_gpio_get_value(struct udevice *dev, unsigned int offset) +{
- struct eg20t_gpio_priv *priv = dev_get_priv(dev);
- u32 pm, pval;
- pm = readl(priv->base + REG_PM);
- if ((pm >> offset) & 0x1)
pval = readl(priv->base + REG_PO);
- else
pval = readl(priv->base + REG_PI);
- return (pval >> offset) & 0x1;
+}
+static int eg20t_gpio_set_value(struct udevice *dev, unsigned int offset,
int value)
+{
- struct eg20t_gpio_priv *priv = dev_get_priv(dev);
- u32 po;
- po = readl(priv->base + REG_PO);
- if (value)
po |= 1 << offset;
- else
po &= ~(1 << offset);
- writel(po, priv->base + REG_PO);
you could use the macros setbits_32() and co. which are available for MIPS. If we get another user for this driver, he could add possibly missing macros to his architecture (e.g. ARM only has setbits_le32() but not setbits_32()).
- return 0;
+}
+static int eg20t_gpio_direction_input(struct udevice *dev, unsigned int offset) +{
- struct eg20t_gpio_priv *priv = dev_get_priv(dev);
- u32 pm;
- pm = readl(priv->base + REG_PM);
- pm &= ~(1 << offset);
- writel(pm, priv->base + REG_PM);
- return 0;
+}
+static int eg20t_gpio_direction_output(struct udevice *dev, unsigned int offset,
int value)
+{
- struct eg20t_gpio_priv *priv = dev_get_priv(dev);
- u32 pm;
- pm = readl(priv->base + REG_PM);
- pm |= 1 << offset;
- writel(pm, priv->base + REG_PM);
- return eg20t_gpio_set_value(dev, offset, value);
+}
+static int eg20t_gpio_get_function(struct udevice *dev, unsigned int offset) +{
- struct eg20t_gpio_priv *priv = dev_get_priv(dev);
- u32 pm;
- pm = readl(priv->base + REG_PM);
- if ((pm >> offset) & 0x1)
return GPIOF_OUTPUT;
- return GPIOF_INPUT;
+}
+static const struct dm_gpio_ops eg20t_gpio_ops = {
- .direction_input = eg20t_gpio_direction_input,
- .direction_output = eg20t_gpio_direction_output,
- .get_value = eg20t_gpio_get_value,
- .set_value = eg20t_gpio_set_value,
- .get_function = eg20t_gpio_get_function,
+};
+static int eg20t_gpio_probe(struct udevice *dev) +{
- struct eg20t_gpio_priv *priv = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM);
- if (!priv->base) {
debug("failed to map GPIO registers\n");
return -EINVAL;
- }
- uc_priv->gpio_count = 12;
- uc_priv->bank_name = "eg20t";
- return 0;
+}
+static const struct udevice_id eg20t_gpio_ids[] = {
- { .compatible = "intel,eg20t-gpio" },
- { }
+};
+U_BOOT_DRIVER(eg20t_gpio) = {
- .name = "eg20t-gpio",
- .id = UCLASS_GPIO,
- .of_match = eg20t_gpio_ids,
- .probe = eg20t_gpio_probe,
- .priv_auto_alloc_size = sizeof(struct eg20t_gpio_priv),
- .ops = &eg20t_gpio_ops,
+};
+static struct pci_device_id eg20t_gpio_supported[] = {
- { PCI_VENDOR_ID_INTEL, 0x8803 },
- { },
+};
+U_BOOT_PCI_DEVICE(eg20t_gpio, eg20t_gpio_supported);

Add support to the pch_gbe driver for resetting the PHY using a GPIO specified in the device tree. This matches the support already in Linux.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Joe Hershberger joe.hershberger@ni.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com ---
drivers/net/pch_gbe.c | 29 +++++++++++++++++++++++++++-- drivers/net/pch_gbe.h | 1 + 2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index 8866f6632f..351debbd9b 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -12,6 +12,7 @@ #include <asm/io.h> #include <pci.h> #include <miiphy.h> +#include <asm/gpio.h> #include "pch_gbe.h"
#if !defined(CONFIG_PHYLIB) @@ -72,6 +73,14 @@ static int pch_gbe_reset(struct udevice *dev) priv->rx_idx = 0; priv->tx_idx = 0;
+ if (dm_gpio_is_valid(&priv->gpio_phy_reset)) { + /* Reset the PHY */ + dm_gpio_set_value(&priv->gpio_phy_reset, 1); + mdelay(15); + dm_gpio_set_value(&priv->gpio_phy_reset, 0); + mdelay(5); + } + writel(PCH_GBE_ALL_RST, &mac_regs->reset);
/* @@ -451,6 +460,11 @@ int pch_gbe_probe(struct udevice *dev) plat->iobase = (ulong)iobase; priv->mac_regs = (struct pch_gbe_regs *)iobase;
+ err = gpio_request_by_name(dev, "phy-reset-gpios", 0, + &priv->gpio_phy_reset, GPIOD_IS_OUT); + if (err && (err != -ENOENT)) + return err; + /* Read MAC address from SROM and initialize dev->enetaddr with it */ pch_gbe_mac_read(priv->mac_regs, plat->enetaddr);
@@ -460,9 +474,17 @@ int pch_gbe_probe(struct udevice *dev)
err = pch_gbe_reset(dev); if (err) - return err; + goto out_err;
- return pch_gbe_phy_init(dev); + err = pch_gbe_phy_init(dev); + if (err) + goto out_err; + + return 0; +out_err: + if (dm_gpio_is_valid(&priv->gpio_phy_reset)) + dm_gpio_free(dev, &priv->gpio_phy_reset); + return err; }
int pch_gbe_remove(struct udevice *dev) @@ -473,6 +495,9 @@ int pch_gbe_remove(struct udevice *dev) mdio_unregister(priv->bus); mdio_free(priv->bus);
+ if (dm_gpio_is_valid(&priv->gpio_phy_reset)) + dm_gpio_free(dev, &priv->gpio_phy_reset); + return 0; }
diff --git a/drivers/net/pch_gbe.h b/drivers/net/pch_gbe.h index 0ea0c73a4f..1d13380837 100644 --- a/drivers/net/pch_gbe.h +++ b/drivers/net/pch_gbe.h @@ -293,6 +293,7 @@ struct pch_gbe_priv { struct udevice *dev; int rx_idx; int tx_idx; + struct gpio_desc gpio_phy_reset; };
#endif /* _PCH_GBE_H_ */

On 21.11.2017 21:33, Paul Burton wrote:
Add support to the pch_gbe driver for resetting the PHY using a GPIO specified in the device tree. This matches the support already in Linux.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Joe Hershberger joe.hershberger@ni.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com
drivers/net/pch_gbe.c | 29 +++++++++++++++++++++++++++-- drivers/net/pch_gbe.h | 1 + 2 files changed, 28 insertions(+), 2 deletions(-)
Reviewed-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com

On Tue, Nov 21, 2017 at 2:33 PM, Paul Burton paul.burton@mips.com wrote:
Add support to the pch_gbe driver for resetting the PHY using a GPIO specified in the device tree. This matches the support already in Linux.
Signed-off-by: Paul Burton paul.burton@imgtec.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Joe Hershberger joe.hershberger@ni.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de Signed-off-by: Paul Burton paul.burton@mips.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

The pch_gbe driver has 4 paths which open-code the equivalent of wait_for_bit(). Replace these with use of wait_for_bit() in order to shorten the code & avoid duplication.
Signed-off-by: Paul Burton paul.burton@mips.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Joe Hershberger joe.hershberger@ni.com Cc: u-boot@lists.denx.de ---
drivers/net/pch_gbe.c | 67 ++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 49 deletions(-)
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index 351debbd9b..052650c036 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -13,6 +13,7 @@ #include <pci.h> #include <miiphy.h> #include <asm/gpio.h> +#include <wait_bit.h> #include "pch_gbe.h"
#if !defined(CONFIG_PHYLIB) @@ -43,7 +44,6 @@ static void pch_gbe_mac_read(struct pch_gbe_regs *mac_regs, u8 *addr) static int pch_gbe_mac_write(struct pch_gbe_regs *mac_regs, u8 *addr) { u32 macid_hi, macid_lo; - ulong start;
macid_hi = addr[0] + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24); macid_lo = addr[4] + (addr[5] << 8); @@ -52,15 +52,8 @@ static int pch_gbe_mac_write(struct pch_gbe_regs *mac_regs, u8 *addr) writel(macid_lo, &mac_regs->mac_adr[0].low); writel(0xfffe, &mac_regs->addr_mask);
- start = get_timer(0); - while (get_timer(start) < PCH_GBE_TIMEOUT) { - if (!(readl(&mac_regs->addr_mask) & PCH_GBE_BUSY)) - return 0; - - udelay(10); - } - - return -ETIME; + return wait_for_bit(__func__, &mac_regs->addr_mask, PCH_GBE_BUSY, + false, PCH_GBE_TIMEOUT, false); }
static int pch_gbe_reset(struct udevice *dev) @@ -68,7 +61,7 @@ static int pch_gbe_reset(struct udevice *dev) struct pch_gbe_priv *priv = dev_get_priv(dev); struct eth_pdata *plat = dev_get_platdata(dev); struct pch_gbe_regs *mac_regs = priv->mac_regs; - ulong start; + int err;
priv->rx_idx = 0; priv->tx_idx = 0; @@ -99,22 +92,17 @@ static int pch_gbe_reset(struct udevice *dev) writel(PCH_GBE_RGMII_MODE_RGMII | PCH_GBE_CHIP_TYPE_INTERNAL, &mac_regs->rgmii_ctrl);
- start = get_timer(0); - while (get_timer(start) < PCH_GBE_TIMEOUT) { - if (!(readl(&mac_regs->reset) & PCH_GBE_ALL_RST)) { - /* - * Soft reset clears hardware MAC address registers, - * so we have to reload MAC address here in order to - * make linux pch_gbe driver happy. - */ - return pch_gbe_mac_write(mac_regs, plat->enetaddr); - } - - udelay(10); - } + err = wait_for_bit(__func__, &mac_regs->reset, PCH_GBE_ALL_RST, + false, PCH_GBE_TIMEOUT, false); + if (err) + return err;
- debug("pch_gbe: reset timeout\n"); - return -ETIME; + /* + * Soft reset clears hardware MAC address registers, + * so we have to reload MAC address here in order to + * make linux pch_gbe driver happy. + */ + return pch_gbe_mac_write(mac_regs, plat->enetaddr); }
static void pch_gbe_rx_descs_init(struct udevice *dev) @@ -255,8 +243,6 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length) struct pch_gbe_regs *mac_regs = priv->mac_regs; struct pch_gbe_tx_desc *tx_head, *tx_desc; u16 frame_ctrl = 0; - u32 int_st; - ulong start;
flush_dcache_range((ulong)packet, (ulong)packet + length);
@@ -282,17 +268,8 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length) writel(dm_pci_virt_to_mem(priv->dev, tx_head + priv->tx_idx), &mac_regs->tx_dsc_sw_p);
- start = get_timer(0); - while (get_timer(start) < PCH_GBE_TIMEOUT) { - int_st = readl(&mac_regs->int_st); - if (int_st & PCH_GBE_INT_TX_CMPLT) - return 0; - - udelay(10); - } - - debug("pch_gbe: sent failed\n"); - return -ETIME; + return wait_for_bit(__func__, &mac_regs->int_st, PCH_GBE_INT_TX_CMPLT, + true, PCH_GBE_TIMEOUT, false); }
static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp) @@ -345,16 +322,8 @@ static int pch_gbe_free_pkt(struct udevice *dev, uchar *packet, int length)
static int pch_gbe_mdio_ready(struct pch_gbe_regs *mac_regs) { - ulong start = get_timer(0); - - while (get_timer(start) < PCH_GBE_TIMEOUT) { - if (readl(&mac_regs->miim) & PCH_GBE_MIIM_OPER_READY) - return 0; - - udelay(10); - } - - return -ETIME; + return wait_for_bit(__func__, &mac_regs->miim, PCH_GBE_MIIM_OPER_READY, + true, PCH_GBE_TIMEOUT, false); }
static int pch_gbe_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)

On 21.11.2017 21:33, Paul Burton wrote:
The pch_gbe driver has 4 paths which open-code the equivalent of wait_for_bit(). Replace these with use of wait_for_bit() in order to shorten the code & avoid duplication.
Signed-off-by: Paul Burton paul.burton@mips.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Joe Hershberger joe.hershberger@ni.com Cc: u-boot@lists.denx.de
drivers/net/pch_gbe.c | 67 ++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 49 deletions(-)
Reviewed-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com

On Tue, Nov 21, 2017 at 2:33 PM, Paul Burton paul.burton@mips.com wrote:
The pch_gbe driver has 4 paths which open-code the equivalent of wait_for_bit(). Replace these with use of wait_for_bit() in order to shorten the code & avoid duplication.
Signed-off-by: Paul Burton paul.burton@mips.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Joe Hershberger joe.hershberger@ni.com Cc: u-boot@lists.denx.de
Acked-by: Joe Hershberger joe.hershberger@ni.com

Add compatible strings for the PCIe bridges & EG20T ethernet controller such that the devices are probed during boot, without the user needing to manually cause that to happen by running "pci enum" after boot. This allows for use of the ethernet controller without the manual PCI enumeration step.
We also enable the EG20T GPIO driver to provide the PHY reset GPIO, and support for the Realtek RTL8211E PHY used on the Boston board in order to make ethernet usable.
Signed-off-by: Paul Burton paul.burton@mips.com Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com Cc: Simon Glass sjg@chromium.org Cc: u-boot@lists.denx.de
---
arch/mips/Kconfig | 1 + arch/mips/dts/img,boston.dts | 8 ++++---- configs/boston32r2_defconfig | 1 + configs/boston32r2el_defconfig | 1 + configs/boston64r2_defconfig | 1 + configs/boston64r2el_defconfig | 1 + include/configs/boston.h | 5 +++++ 7 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d07b92d1b4..a05c65c507 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -92,6 +92,7 @@ config MACH_PIC32 config TARGET_BOSTON bool "Support Boston" select DM + select DM_GPIO select DM_SERIAL select OF_CONTROL select MIPS_CM diff --git a/arch/mips/dts/img,boston.dts b/arch/mips/dts/img,boston.dts index 1d4eeda4e8..78a24dc4a4 100644 --- a/arch/mips/dts/img,boston.dts +++ b/arch/mips/dts/img,boston.dts @@ -130,7 +130,7 @@ };
pci2_root@0,0,0 { - compatible = "pci10ee,7021"; + compatible = "pci10ee,7021", "pci-bridge"; reg = <0x00000000 0 0 0 0>;
#address-cells = <3>; @@ -138,7 +138,7 @@ #interrupt-cells = <1>;
eg20t_bridge@1,0,0 { - compatible = "pci8086,8800"; + compatible = "pci8086,8800", "pci-bridge"; reg = <0x00010000 0 0 0 0>;
#address-cells = <3>; @@ -146,13 +146,13 @@ #interrupt-cells = <1>;
eg20t_mac@2,0,1 { - compatible = "pci8086,8802"; + compatible = "pci8086,8802", "intel,pch-gbe"; reg = <0x00020100 0 0 0 0>; phy-reset-gpios = <&eg20t_gpio 6 GPIO_ACTIVE_LOW>; };
eg20t_gpio: eg20t_gpio@2,0,2 { - compatible = "pci8086,8803"; + compatible = "pci8086,8803", "intel,eg20t-gpio"; reg = <0x00020200 0 0 0 0>;
gpio-controller; diff --git a/configs/boston32r2_defconfig b/configs/boston32r2_defconfig index 1d21f1643c..3876672ce9 100644 --- a/configs/boston32r2_defconfig +++ b/configs/boston32r2_defconfig @@ -28,6 +28,7 @@ CONFIG_OF_EMBED=y CONFIG_ENV_IS_IN_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_CLK=y +CONFIG_EG20T_GPIO=y CONFIG_MTD=y CONFIG_MTD_NOR_FLASH=y CONFIG_CFI_FLASH=y diff --git a/configs/boston32r2el_defconfig b/configs/boston32r2el_defconfig index d26adc68f2..715d02a2b9 100644 --- a/configs/boston32r2el_defconfig +++ b/configs/boston32r2el_defconfig @@ -29,6 +29,7 @@ CONFIG_OF_EMBED=y CONFIG_ENV_IS_IN_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_CLK=y +CONFIG_EG20T_GPIO=y CONFIG_MTD=y CONFIG_MTD_NOR_FLASH=y CONFIG_CFI_FLASH=y diff --git a/configs/boston64r2_defconfig b/configs/boston64r2_defconfig index 1491575af5..ba69f5b45f 100644 --- a/configs/boston64r2_defconfig +++ b/configs/boston64r2_defconfig @@ -29,6 +29,7 @@ CONFIG_OF_EMBED=y CONFIG_ENV_IS_IN_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_CLK=y +CONFIG_EG20T_GPIO=y CONFIG_MTD=y CONFIG_MTD_NOR_FLASH=y CONFIG_CFI_FLASH=y diff --git a/configs/boston64r2el_defconfig b/configs/boston64r2el_defconfig index 933b5bfc48..465abbd570 100644 --- a/configs/boston64r2el_defconfig +++ b/configs/boston64r2el_defconfig @@ -30,6 +30,7 @@ CONFIG_OF_EMBED=y CONFIG_ENV_IS_IN_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_CLK=y +CONFIG_EG20T_GPIO=y CONFIG_MTD=y CONFIG_MTD_NOR_FLASH=y CONFIG_CFI_FLASH=y diff --git a/include/configs/boston.h b/include/configs/boston.h index ee4e4a37ea..2ddd1ae6ad 100644 --- a/include/configs/boston.h +++ b/include/configs/boston.h @@ -69,4 +69,9 @@ (0xb8000000 + (128 << 20) - CONFIG_ENV_SIZE) #endif
+/* + * Ethernet + */ +#define CONFIG_PHY_REALTEK + #endif /* __CONFIGS_BOSTON_H__ */
participants (4)
-
Daniel Schwierzeck
-
Joe Hershberger
-
Michal Simek
-
Paul Burton