[U-Boot] [PATCH v2 0/6] sunxi: update sun8i-emac driver and A64 DTs

This patch set updates the latest device trees for Allwinner A64 based boards from Linux. In contrast to v1 I now took the actual 4.13-rc1 DTs from Linux, which restructures the patch set a bit.
The big advantage of having the very same DTs in U-Boot is that we can use UEFI boot much more easily, because U-Boot can just pass on its own DT, without having to find and load some external version. This makes UEFI based installers boot out of the box, which is a big relief. Linux 4.13-rc1 saw the addition of the sun8i-emac Ethernet driver, for which U-Boot has a driver for quite a while, but with a slightly different binding, so this series makes it compatible. Patch 1/6 adds some missing compatible strings, it was on the list before, but I add it to this series because it is a prerequisite for the following patches. Patches 2 till 4 add some code to be able to parse the new pinctrl bindings that newer Allwinner DTs use. Patch 5 extends U-Boot sun8i-emac driver to be able to properly parse the DT binding used by the new Linux driver as well. Patch 6 then actually replaces the DTs for A64 boards with the exact version as of the Linux tree (v4.13-rc1). This allows us to *almost* get rid of out *-u-boot.dtsi kludge, but we still need the alias, which the Linux version doesn't have, so this file still contains this one line, effectively.
I am still not convinced that having a full featured pinctrl driver in U-Boot is the right thing, so I cheekily ignore this part of the comments. If people consider this a requirement, we can have a look at this, but I don't see any reply since the first patch was posted some months ago, so I guess this takes much more time.
Also my apologies for not having looked at the syscon driver change Simon asked. It looks like a reasonable change, but I am about to leave for holidays and didn't want to postpone an updated version any longer.
Cheers, Andre.
Andre Przywara (6): sunxi: gpio: add missing compatible strings libfdt: add fdtdec_lookup_phandle_index() sunxi: GPIO: introduce sunxi_gpio_setup_dt_pins() net: sun8i-emac: use new, generic GPIO setup routine net: sun8i-emac: add support for new DT binding sunxi: A64: update Linux DTs
arch/arm/dts/sun50i-a64-bananapi-m64-u-boot.dtsi | 5 + arch/arm/dts/sun50i-a64-bananapi-m64.dts | 16 ++- arch/arm/dts/sun50i-a64-orangepi-win.dts | 7 +- arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi | 45 ------- arch/arm/dts/sun50i-a64-pine64-plus.dts | 17 ++- arch/arm/dts/sun50i-a64-pine64.dts | 57 +++++++++ arch/arm/dts/sun50i-a64.dtsi | 142 ++++++++++++++++++++--- arch/arm/include/asm/arch-sunxi/gpio.h | 3 + arch/arm/mach-sunxi/pinmux.c | 79 +++++++++++++ drivers/gpio/sunxi_gpio.c | 4 + drivers/net/sun8i_emac.c | 105 +++++++++-------- include/dt-bindings/clock/sun8i-r-ccu.h | 59 ++++++++++ include/fdtdec.h | 12 ++ lib/fdtdec.c | 16 ++- 14 files changed, 441 insertions(+), 126 deletions(-) create mode 100644 arch/arm/dts/sun50i-a64-bananapi-m64-u-boot.dtsi create mode 100644 include/dt-bindings/clock/sun8i-r-ccu.h

The sunxi GPIO driver is missing some compatible strings for recent SoCs. While most of the sunxi GPIO code seems to not rely on this (and so works anyway), the sunxi_name_to_gpio() function does and fails at the moment (for instance when resolving the MMC CD pin name). Add the compatible strings for the A64, H5 and V3s, which were missing from the list. This now covers all pinctrl nodes in our own DTs. Strictly speaking the V3s has only ports B, C, E, F and G, but I think the other SoCs have gaps in there as well and for the pin number computation this does not matter.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- drivers/gpio/sunxi_gpio.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index b47cc66..d20a7e7 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -353,12 +353,16 @@ static const struct udevice_id sunxi_gpio_ids[] = { ID("allwinner,sun8i-a83t-pinctrl", a_all), ID("allwinner,sun8i-h3-pinctrl", a_all), ID("allwinner,sun8i-r40-pinctrl", a_all), + ID("allwinner,sun8i-v3s-pinctrl", a_all), ID("allwinner,sun9i-a80-pinctrl", a_all), + ID("allwinner,sun50i-a64-pinctrl", a_all), + ID("allwinner,sun50i-h5-pinctrl", a_all), ID("allwinner,sun6i-a31-r-pinctrl", l_2), ID("allwinner,sun8i-a23-r-pinctrl", l_1), ID("allwinner,sun8i-a83t-r-pinctrl", l_1), ID("allwinner,sun8i-h3-r-pinctrl", l_1), ID("allwinner,sun9i-a80-r-pinctrl", l_3), + ID("allwinner,sun50i-a64-r-pinctrl", l_1), { } };

In some bindings a property points to multiple nodes, using a list of phandles. A prominent example are UART pinctrl nodes, which use one node to contain the RX/TX pins and another node to describe the lines used for the hardware handshake. The current fdtdec_lookup_phandle() helper function to chase a phandle is quite convienent, but can only lookup the first of those handles.
Introduce an extra function fdtdec_lookup_phandle_index() to take an index parameter and implement fdtdec_lookup_phandle() as a special case of that.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- include/fdtdec.h | 12 ++++++++++++ lib/fdtdec.c | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/include/fdtdec.h b/include/fdtdec.h index eda2ffa..529e0fe 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -650,6 +650,18 @@ int fdtdec_get_chosen_node(const void *blob, const char *name); */ const char *fdtdec_get_compatible(enum fdt_compat_id id);
+/* Look up a phandle with a given index and follow it to its node. + * Then return the offset of that node. + * + * @param blob FDT blob + * @param node node to examine + * @param prop_name name of property to find + * @param index index of the desired phandle in the list + * @return node offset if found, -ve error code on error + */ +int fdtdec_lookup_phandle_index(const void *blob, int node, + const char *prop_name, int index); + /* Look up a phandle and follow it to its node. Then return the offset * of that node. * diff --git a/lib/fdtdec.c b/lib/fdtdec.c index fbb48bf..9ce5e41 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -618,20 +618,28 @@ int fdtdec_prepare_fdt(void) return 0; }
-int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name) +int fdtdec_lookup_phandle_index(const void *blob, int node, + const char *prop_name, int index) { const u32 *phandle; int lookup; + int length;
debug("%s: %s\n", __func__, prop_name); - phandle = fdt_getprop(blob, node, prop_name, NULL); - if (!phandle) + phandle = fdt_getprop(blob, node, prop_name, &length); + if (!phandle || index * 4 >= length) return -FDT_ERR_NOTFOUND;
- lookup = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*phandle)); + lookup = fdt_node_offset_by_phandle(blob, + fdt32_to_cpu(phandle[index])); return lookup; }
+int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name) +{ + return fdtdec_lookup_phandle_index(blob, node, prop_name, 0); +} + /** * Look up a property in a node and check that it has a minimum length. *

Instead of hard-coding GPIO pins used for a certain peripheral, we should just use the pinctrl information from the DT. The sun8i-emac driver has some simple implementation of that, so let's just generalize this and copy the code to a more common location. On the way we add support for the new, generic pinctrl binding now used by all Allwinner SoCs.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- arch/arm/include/asm/arch-sunxi/gpio.h | 3 ++ arch/arm/mach-sunxi/pinmux.c | 79 ++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+)
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 24f8520..b5a4b32 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -240,4 +240,7 @@ int axp_gpio_init(void); static inline int axp_gpio_init(void) { return 0; } #endif
+int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node, + int mux_sel); + #endif /* _SUNXI_GPIO_H */ diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c index b026f78..ae36fe9 100644 --- a/arch/arm/mach-sunxi/pinmux.c +++ b/arch/arm/mach-sunxi/pinmux.c @@ -9,6 +9,9 @@ #include <common.h> #include <asm/io.h> #include <asm/arch/gpio.h> +#include <fdtdec.h> +#include <fdt_support.h> +#include <dt-bindings/pinctrl/sun4i-a10.h>
void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val) { @@ -69,3 +72,79 @@ int sunxi_gpio_set_pull(u32 pin, u32 val)
return 0; } + +static int sunxi_gpio_setup_single_node(const void * volatile fdt_blob, + int offset, int mux_sel) +{ + int drive, pull, pin, i; + const char *pin_name; + + drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0, + "drive-strength", ~0); + if (drive != ~0) { + if (drive <= 10) + drive = SUN4I_PINCTRL_10_MA; + else if (drive <= 20) + drive = SUN4I_PINCTRL_20_MA; + else if (drive <= 30) + drive = SUN4I_PINCTRL_30_MA; + else + drive = SUN4I_PINCTRL_40_MA; + } else { + drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0, + "allwinner,drive", ~0); + } + + if (fdt_get_property(fdt_blob, offset, "bias-pull-up", NULL)) + pull = SUN4I_PINCTRL_PULL_UP; + else if (fdt_get_property(fdt_blob, offset, "bias-disable", NULL)) + pull = SUN4I_PINCTRL_NO_PULL; + else if (fdt_get_property(fdt_blob, offset, "bias-pull-down", NULL)) + pull = SUN4I_PINCTRL_PULL_DOWN; + else + pull = fdt_getprop_u32_default_node(fdt_blob, offset, 0, + "allwinner,pull", ~0); + + for (i = 0; ; i++) { + pin_name = fdt_stringlist_get(fdt_blob, offset, + "allwinner,pins", i, NULL); + if (!pin_name) { + pin_name = fdt_stringlist_get(fdt_blob, offset, + "pins", i, NULL); + if (!pin_name) + break; + } + pin = sunxi_name_to_gpio(pin_name); + if (pin < 0) + continue; + + sunxi_gpio_set_cfgpin(pin, mux_sel); + if (drive != ~0) + sunxi_gpio_set_drv(pin, drive); + if (pull != ~0) + sunxi_gpio_set_pull(pin, pull); + } + + return i; +} + +int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node, + int mux_sel) +{ + int offset, pins = 0, idx; + + for (idx = 0; ; idx++) { + offset = fdtdec_lookup_phandle_index(fdt_blob, node, + "pinctrl-0", idx); + if (offset < 0) { + if (idx == 0) + return offset; + + return pins; + } + + pins += sunxi_gpio_setup_single_node(fdt_blob, offset, mux_sel); + } + + return pins; +}

Instead of open-coding the fairly generic pinmux setup in the sun8i-emac driver, let's just use the new common implementation of that. This has also the advantage of supporting the new, generic pinctrl bindings, so the driver can cope with the upstream Linux DTs.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- drivers/net/sun8i_emac.c | 54 +++++++----------------------------------------- 1 file changed, 8 insertions(+), 46 deletions(-)
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index 09bbb2c..af77134 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -451,50 +451,6 @@ static int _sun8i_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr) return 0; }
-static int parse_phy_pins(struct udevice *dev) -{ - int offset; - const char *pin_name; - int drive, pull, i; - - offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev), - "pinctrl-0"); - if (offset < 0) { - printf("WARNING: emac: cannot find pinctrl-0 node\n"); - return offset; - } - - drive = fdt_getprop_u32_default_node(gd->fdt_blob, offset, 0, - "allwinner,drive", 4); - pull = fdt_getprop_u32_default_node(gd->fdt_blob, offset, 0, - "allwinner,pull", 0); - for (i = 0; ; i++) { - int pin; - - pin_name = fdt_stringlist_get(gd->fdt_blob, offset, - "allwinner,pins", i, NULL); - if (!pin_name) - break; - if (pin_name[0] != 'P') - continue; - pin = (pin_name[1] - 'A') << 5; - if (pin >= 26 << 5) - continue; - pin += simple_strtol(&pin_name[2], NULL, 10); - - sunxi_gpio_set_cfgpin(pin, SUN8I_GPD8_GMAC); - sunxi_gpio_set_drv(pin, drive); - sunxi_gpio_set_pull(pin, pull); - } - - if (!i) { - printf("WARNING: emac: cannot find allwinner,pins property\n"); - return -2; - } - - return 0; -} - static int _sun8i_eth_recv(struct emac_eth_dev *priv, uchar **packetp) { u32 status, desc_num = priv->rx_currdescnum; @@ -816,8 +772,14 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
priv->interface = pdata->phy_interface;
- if (!priv->use_internal_phy) - parse_phy_pins(dev); + if (!priv->use_internal_phy) { + ret = sunxi_gpio_setup_dt_pins(gd->fdt_blob, dev_of_offset(dev), + SUN8I_GPD8_GMAC); + if (ret < 0) { + printf("%s: cannot setup pinmuxes\n", __func__); + return -EINVAL; + } + }
#ifdef CONFIG_DM_GPIO if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),

The Ethernet MAC used in newer Allwinner SoCs (H3, A64, H5) is about to get an upstream Linux driver very soon (it's already lurking in -next). This one uses a slightly different binding from the original one used by the U-Boot driver. The differences to the old binding are: - The "syscon" address is held in a separate node, referenced via a phandle in the "syscon" property. - The reference to the PHY is held in a property called "phy-handle", not "phy". - The PHY register is at offset 0x30 in the syscon device, not at 0. - The internal PHY is activated when a capable SoC selects MII mode.
Teach the U-Boot driver how to find its resources in a "new-style" DT, so that we can use a Linux kernel compatible DT for U-Boot as well. This keeps support for the old binding (for now?), to allow a smooth transition.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- drivers/net/sun8i_emac.c | 51 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-)
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index af77134..8320518 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -278,7 +278,7 @@ static int sun8i_emac_set_syscon(struct emac_eth_dev *priv) int ret; u32 reg;
- reg = readl(priv->sysctl_reg); + reg = readl(priv->sysctl_reg + 0x30);
if (priv->variant == H3_EMAC) { ret = sun8i_emac_set_syscon_ephy(priv, ®); @@ -309,7 +309,7 @@ static int sun8i_emac_set_syscon(struct emac_eth_dev *priv) return -EINVAL; }
- writel(reg, priv->sysctl_reg); + writel(reg, priv->sysctl_reg + 0x30);
return 0; } @@ -733,17 +733,50 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev) #endif
pdata->iobase = devfdt_get_addr_name(dev, "emac"); + if (pdata->iobase == FDT_ADDR_T_NONE) + pdata->iobase = devfdt_get_addr(dev); + if (pdata->iobase == FDT_ADDR_T_NONE) { + debug("%s: Cannot find MAC base address\n", __func__); + return -EINVAL; + } + priv->sysctl_reg = devfdt_get_addr_name(dev, "syscon"); + if (priv->sysctl_reg == FDT_ADDR_T_NONE) { + const fdt32_t *reg; + + offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "syscon"); + if (offset < 0) { + debug("%s: cannot find syscon node\n", __func__); + return -EINVAL; + } + reg = fdt_getprop(gd->fdt_blob, offset, "reg", NULL); + if (!reg) { + debug("%s: cannot find reg property in syscon node\n", + __func__); + return -EINVAL; + } + priv->sysctl_reg = fdt_translate_address((void *)gd->fdt_blob, + offset, reg); + } else + priv->sysctl_reg -= 0x30; + if (priv->sysctl_reg == FDT_ADDR_T_NONE) { + debug("%s: Cannot find syscon base address\n", __func__); + return -EINVAL; + }
pdata->phy_interface = -1; priv->phyaddr = -1; priv->use_internal_phy = false;
- offset = fdtdec_lookup_phandle(gd->fdt_blob, node, - "phy"); - if (offset > 0) - priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", - -1); + offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy"); + if (offset < 0) + offset = fdtdec_lookup_phandle(gd->fdt_blob, node, + "phy-handle"); + if (offset < 0) { + debug("%s: Cannot find PHY address\n", __func__); + return -EINVAL; + } + priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
@@ -768,6 +801,10 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev) if (fdt_getprop(gd->fdt_blob, node, "allwinner,use-internal-phy", NULL)) priv->use_internal_phy = true; + else { + if (pdata->phy_interface == PHY_INTERFACE_MODE_MII) + priv->use_internal_phy = true; + } }
priv->interface = pdata->phy_interface;

An Ethernet driver for the sun8i-emac IP has reached the Linux kernel, so the DT in there have been updated. Since U-Boot's EMAC driver can now cope with the slightly different kernel DT binding as well, let's copy the .dtsi and .dts files as of commit bdecc9cb214e from the kernel. This allows us to get *almost* rid of our sun50i-a64-pine64-plus-u-boot.dtsi file, which was just there to add the Ethernet nodes. We still need the one line for the Ethernet alias, though. Also this enables Ethernet on the BananaPi-M64, since the Linux DT has the respective nodes.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- arch/arm/dts/sun50i-a64-bananapi-m64-u-boot.dtsi | 5 + arch/arm/dts/sun50i-a64-bananapi-m64.dts | 16 ++- arch/arm/dts/sun50i-a64-orangepi-win.dts | 7 +- arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi | 45 ------- arch/arm/dts/sun50i-a64-pine64-plus.dts | 17 ++- arch/arm/dts/sun50i-a64-pine64.dts | 57 +++++++++ arch/arm/dts/sun50i-a64.dtsi | 142 ++++++++++++++++++++--- include/dt-bindings/clock/sun8i-r-ccu.h | 59 ++++++++++ 8 files changed, 279 insertions(+), 69 deletions(-) create mode 100644 arch/arm/dts/sun50i-a64-bananapi-m64-u-boot.dtsi create mode 100644 include/dt-bindings/clock/sun8i-r-ccu.h
diff --git a/arch/arm/dts/sun50i-a64-bananapi-m64-u-boot.dtsi b/arch/arm/dts/sun50i-a64-bananapi-m64-u-boot.dtsi new file mode 100644 index 0000000..c66359c --- /dev/null +++ b/arch/arm/dts/sun50i-a64-bananapi-m64-u-boot.dtsi @@ -0,0 +1,5 @@ +/ { + aliases { + ethernet0 = &emac; + }; +}; diff --git a/arch/arm/dts/sun50i-a64-bananapi-m64.dts b/arch/arm/dts/sun50i-a64-bananapi-m64.dts index 02db114..0d1f026 100644 --- a/arch/arm/dts/sun50i-a64-bananapi-m64.dts +++ b/arch/arm/dts/sun50i-a64-bananapi-m64.dts @@ -1,6 +1,5 @@ /* * Copyright (c) 2016 ARM Ltd. - * Copyright (C) 2017 Jagan Teki jteki@openedev.com * * This file is dual-licensed: you can use it either under the terms * of the GPL or the X11 license, at your option. Note that this dual @@ -68,6 +67,14 @@ }; };
+&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + status = "okay"; +}; + &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins>; @@ -78,6 +85,13 @@ bias-pull-up; };
+&mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; diff --git a/arch/arm/dts/sun50i-a64-orangepi-win.dts b/arch/arm/dts/sun50i-a64-orangepi-win.dts index cf76c35..5f8ff40 100644 --- a/arch/arm/dts/sun50i-a64-orangepi-win.dts +++ b/arch/arm/dts/sun50i-a64-orangepi-win.dts @@ -67,7 +67,7 @@ };
&ehci1 { - status = "okay"; + status = "okay"; };
&mmc0 { @@ -80,7 +80,7 @@ };
&ohci1 { - status = "okay"; + status = "okay"; };
&uart0 { @@ -90,5 +90,6 @@ };
&usbphy { - status = "okay"; + status = "okay"; }; + diff --git a/arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi b/arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi index 9c61bea..c66359c 100644 --- a/arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi +++ b/arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi @@ -2,49 +2,4 @@ aliases { ethernet0 = &emac; }; - - soc { - emac: ethernet@01c30000 { - compatible = "allwinner,sun50i-a64-emac"; - reg = <0x01c30000 0x2000>, <0x01c00030 0x4>; - reg-names = "emac", "syscon"; - interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; - resets = <&ccu RST_BUS_EMAC>; - reset-names = "ahb"; - clocks = <&ccu CLK_BUS_EMAC>; - clock-names = "ahb"; - #address-cells = <1>; - #size-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&rgmii_pins>; - phy-mode = "rgmii"; - phy = <&phy1>; - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - }; -}; - -&pio { - rmii_pins: rmii_pins { - allwinner,pins = "PD10", "PD11", "PD13", "PD14", - "PD17", "PD18", "PD19", "PD20", - "PD22", "PD23"; - allwinner,function = "emac"; - allwinner,drive = <3>; - allwinner,pull = <0>; - }; - - rgmii_pins: rgmii_pins { - allwinner,pins = "PD8", "PD9", "PD10", "PD11", - "PD12", "PD13", "PD15", - "PD16", "PD17", "PD18", "PD19", - "PD20", "PD21", "PD22", "PD23"; - allwinner,function = "emac"; - allwinner,drive = <3>; - allwinner,pull = <0>; - }; }; diff --git a/arch/arm/dts/sun50i-a64-pine64-plus.dts b/arch/arm/dts/sun50i-a64-pine64-plus.dts index 790d14d..24f1aac 100644 --- a/arch/arm/dts/sun50i-a64-pine64-plus.dts +++ b/arch/arm/dts/sun50i-a64-pine64-plus.dts @@ -46,5 +46,20 @@ model = "Pine64+"; compatible = "pine64,pine64-plus", "allwinner,sun50i-a64";
- /* TODO: Camera, Ethernet PHY, touchscreen, etc. */ + /* TODO: Camera, touchscreen, etc. */ +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + status = "okay"; +}; + +&mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; }; diff --git a/arch/arm/dts/sun50i-a64-pine64.dts b/arch/arm/dts/sun50i-a64-pine64.dts index c680ed3..08cda24 100644 --- a/arch/arm/dts/sun50i-a64-pine64.dts +++ b/arch/arm/dts/sun50i-a64-pine64.dts @@ -52,6 +52,10 @@
aliases { serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; };
chosen { @@ -66,10 +70,23 @@ }; };
+&ehci0 { + status = "okay"; +}; + &ehci1 { status = "okay"; };
+&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rmii_pins>; + phy-mode = "rmii"; + phy-handle = <&ext_rmii_phy1>; + status = "okay"; + +}; + &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins>; @@ -80,6 +97,13 @@ bias-pull-up; };
+&mdio { + ext_rmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; @@ -91,16 +115,49 @@ status = "okay"; };
+&ohci0 { + status = "okay"; +}; + &ohci1 { status = "okay"; };
+/* On Exp and Euler connectors */ &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins_a>; status = "okay"; };
+/* On Wifi/BT connector, with RTS/CTS */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; + status = "disabled"; +}; + +/* On Pi-2 connector */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "disabled"; +}; + +/* On Euler connector */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + status = "disabled"; +}; + +/* On Euler connector, RTS/CTS optional */ +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins>; + status = "disabled"; +}; + &usb_otg { dr_mode = "host"; status = "okay"; diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi index c7f669f..9d00622 100644 --- a/arch/arm/dts/sun50i-a64.dtsi +++ b/arch/arm/dts/sun50i-a64.dtsi @@ -43,6 +43,7 @@ */
#include <dt-bindings/clock/sun50i-a64-ccu.h> +#include <dt-bindings/clock/sun8i-r-ccu.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/reset/sun50i-a64-ccu.h>
@@ -129,6 +130,12 @@ #size-cells = <1>; ranges;
+ syscon: syscon@1c00000 { + compatible = "allwinner,sun50i-a64-system-controller", + "syscon"; + reg = <0x01c00000 0x1000>; + }; + mmc0: mmc@1c0f000 { compatible = "allwinner,sun50i-a64-mmc"; reg = <0x01c0f000 0x1000>; @@ -204,6 +211,28 @@ #phy-cells = <1>; };
+ ehci0: usb@01c1a000 { + compatible = "allwinner,sun50i-a64-ehci", "generic-ehci"; + reg = <0x01c1a000 0x100>; + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu CLK_BUS_OHCI0>, + <&ccu CLK_BUS_EHCI0>, + <&ccu CLK_USB_OHCI0>; + resets = <&ccu RST_BUS_OHCI0>, + <&ccu RST_BUS_EHCI0>; + status = "disabled"; + }; + + ohci0: usb@01c1a400 { + compatible = "allwinner,sun50i-a64-ohci", "generic-ohci"; + reg = <0x01c1a400 0x100>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu CLK_BUS_OHCI0>, + <&ccu CLK_USB_OHCI0>; + resets = <&ccu RST_BUS_OHCI0>; + status = "disabled"; + }; + ehci1: usb@01c1b000 { compatible = "allwinner,sun50i-a64-ehci", "generic-ehci"; reg = <0x01c1b000 0x100>; @@ -281,6 +310,21 @@ bias-pull-up; };
+ rmii_pins: rmii_pins { + pins = "PD10", "PD11", "PD13", "PD14", "PD17", + "PD18", "PD19", "PD20", "PD22", "PD23"; + function = "emac"; + drive-strength = <40>; + }; + + rgmii_pins: rgmii_pins { + pins = "PD8", "PD9", "PD10", "PD11", "PD12", + "PD13", "PD15", "PD16", "PD17", "PD18", + "PD19", "PD20", "PD21", "PD22", "PD23"; + function = "emac"; + drive-strength = <40>; + }; + uart0_pins_a: uart0@0 { pins = "PB8", "PB9"; function = "uart0"; @@ -295,6 +339,26 @@ pins = "PG8", "PG9"; function = "uart1"; }; + + uart2_pins: uart2-pins { + pins = "PB0", "PB1"; + function = "uart2"; + }; + + uart3_pins: uart3-pins { + pins = "PD0", "PD1"; + function = "uart3"; + }; + + uart4_pins: uart4-pins { + pins = "PD2", "PD3"; + function = "uart4"; + }; + + uart4_rts_cts_pins: uart4-rts-cts-pins { + pins = "PD4", "PD5"; + function = "uart4"; + }; };
uart0: serial@1c28000 { @@ -303,8 +367,8 @@ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 67>; - resets = <&ccu 46>; + clocks = <&ccu CLK_BUS_UART0>; + resets = <&ccu RST_BUS_UART0>; status = "disabled"; };
@@ -314,8 +378,8 @@ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 68>; - resets = <&ccu 47>; + clocks = <&ccu CLK_BUS_UART1>; + resets = <&ccu RST_BUS_UART1>; status = "disabled"; };
@@ -325,8 +389,8 @@ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 69>; - resets = <&ccu 48>; + clocks = <&ccu CLK_BUS_UART2>; + resets = <&ccu RST_BUS_UART2>; status = "disabled"; };
@@ -336,8 +400,8 @@ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 70>; - resets = <&ccu 49>; + clocks = <&ccu CLK_BUS_UART3>; + resets = <&ccu RST_BUS_UART3>; status = "disabled"; };
@@ -347,8 +411,8 @@ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 71>; - resets = <&ccu 50>; + clocks = <&ccu CLK_BUS_UART4>; + resets = <&ccu RST_BUS_UART4>; status = "disabled"; };
@@ -356,8 +420,8 @@ compatible = "allwinner,sun6i-a31-i2c"; reg = <0x01c2ac00 0x400>; interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&ccu 63>; - resets = <&ccu 42>; + clocks = <&ccu CLK_BUS_I2C0>; + resets = <&ccu RST_BUS_I2C0>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -367,8 +431,8 @@ compatible = "allwinner,sun6i-a31-i2c"; reg = <0x01c2b000 0x400>; interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&ccu 64>; - resets = <&ccu 43>; + clocks = <&ccu CLK_BUS_I2C1>; + resets = <&ccu RST_BUS_I2C1>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -378,11 +442,31 @@ compatible = "allwinner,sun6i-a31-i2c"; reg = <0x01c2b400 0x400>; interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&ccu 65>; - resets = <&ccu 44>; + clocks = <&ccu CLK_BUS_I2C2>; + resets = <&ccu RST_BUS_I2C2>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + emac: ethernet@1c30000 { + compatible = "allwinner,sun50i-a64-emac"; + syscon = <&syscon>; + reg = <0x01c30000 0x100>; + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq"; + resets = <&ccu RST_BUS_EMAC>; + reset-names = "stmmaceth"; + clocks = <&ccu CLK_BUS_EMAC>; + clock-names = "stmmaceth"; status = "disabled"; #address-cells = <1>; #size-cells = <0>; + + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + }; };
gic: interrupt-controller@1c81000 { @@ -406,8 +490,9 @@ r_ccu: clock@1f01400 { compatible = "allwinner,sun50i-a64-r-ccu"; reg = <0x01f01400 0x100>; - clocks = <&osc24M>, <&osc32k>, <&iosc>; - clock-names = "hosc", "losc", "iosc"; + clocks = <&osc24M>, <&osc32k>, <&iosc>, + <&ccu 11>; + clock-names = "hosc", "losc", "iosc", "pll-periph"; #clock-cells = <1>; #reset-cells = <1>; }; @@ -416,12 +501,31 @@ compatible = "allwinner,sun50i-a64-r-pinctrl"; reg = <0x01f02c00 0x400>; interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&r_ccu 3>, <&osc24M>, <&osc32k>; + clocks = <&r_ccu CLK_APB0_PIO>, <&osc24M>, <&osc32k>; clock-names = "apb", "hosc", "losc"; gpio-controller; #gpio-cells = <3>; interrupt-controller; #interrupt-cells = <3>; + + r_rsb_pins: rsb@0 { + pins = "PL0", "PL1"; + function = "s_rsb"; + }; + }; + + r_rsb: rsb@1f03400 { + compatible = "allwinner,sun8i-a23-rsb"; + reg = <0x01f03400 0x400>; + interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&r_ccu 6>; + clock-frequency = <3000000>; + resets = <&r_ccu 2>; + pinctrl-names = "default"; + pinctrl-0 = <&r_rsb_pins>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; }; }; diff --git a/include/dt-bindings/clock/sun8i-r-ccu.h b/include/dt-bindings/clock/sun8i-r-ccu.h new file mode 100644 index 0000000..779d20a --- /dev/null +++ b/include/dt-bindings/clock/sun8i-r-ccu.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016 Icenowy Zheng icenowy@aosc.xyz + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_CLK_SUN8I_R_CCU_H_ +#define _DT_BINDINGS_CLK_SUN8I_R_CCU_H_ + +#define CLK_AR100 0 + +#define CLK_APB0_PIO 3 +#define CLK_APB0_IR 4 +#define CLK_APB0_TIMER 5 +#define CLK_APB0_RSB 6 +#define CLK_APB0_UART 7 +/* 8 is reserved for CLK_APB0_W1 on A31 */ +#define CLK_APB0_I2C 9 +#define CLK_APB0_TWD 10 + +#define CLK_IR 11 + +#endif /* _DT_BINDINGS_CLK_SUN8I_R_CCU_H_ */

On Mon, Jul 24, 2017 at 4:26 AM, Andre Przywara andre.przywara@arm.com wrote:
This patch set updates the latest device trees for Allwinner A64 based boards from Linux. In contrast to v1 I now took the actual 4.13-rc1 DTs from Linux, which restructures the patch set a bit.
The big advantage of having the very same DTs in U-Boot is that we can use UEFI boot much more easily, because U-Boot can just pass on its own DT, without having to find and load some external version. This makes UEFI based installers boot out of the box, which is a big relief. Linux 4.13-rc1 saw the addition of the sun8i-emac Ethernet driver, for which U-Boot has a driver for quite a while, but with a slightly different binding, so this series makes it compatible. Patch 1/6 adds some missing compatible strings, it was on the list before, but I add it to this series because it is a prerequisite for the following patches. Patches 2 till 4 add some code to be able to parse the new pinctrl bindings that newer Allwinner DTs use. Patch 5 extends U-Boot sun8i-emac driver to be able to properly parse the DT binding used by the new Linux driver as well. Patch 6 then actually replaces the DTs for A64 boards with the exact version as of the Linux tree (v4.13-rc1). This allows us to *almost* get rid of out *-u-boot.dtsi kludge, but we still need the alias, which the Linux version doesn't have, so this file still contains this one line, effectively.
I am still not convinced that having a full featured pinctrl driver in U-Boot is the right thing, so I cheekily ignore this part of the comments. If people consider this a requirement, we can have a look at this, but I don't see any reply since the first patch was posted some months ago, so I guess this takes much more time.
Also my apologies for not having looked at the syscon driver change Simon asked. It looks like a reasonable change, but I am about to leave for holidays and didn't want to postpone an updated version any longer.
Cheers, Andre.
Andre Przywara (6): sunxi: gpio: add missing compatible strings libfdt: add fdtdec_lookup_phandle_index() sunxi: GPIO: introduce sunxi_gpio_setup_dt_pins() net: sun8i-emac: use new, generic GPIO setup routine net: sun8i-emac: add support for new DT binding sunxi: A64: update Linux DTs
This series look OK, to me. Will test emac and update. Meanwhile any comments please let me know.
thanks!
participants (2)
-
Andre Przywara
-
Jagan Teki