diff --git a/armv7-boards b/armv7-boards index e5d27bc..5f68bcd 100644 --- a/armv7-boards +++ b/armv7-boards @@ -72,6 +72,7 @@ omap4_panda omap5_uevm Orangepi orangepi_2 +orangepi_lite Orangepi_mini orangepi_pc orangepi_plus diff --git a/net-Add-EMAC-driver-for-H3-A83T-A64-SoCs..patch b/net-Add-EMAC-driver-for-H3-A83T-A64-SoCs..patch deleted file mode 100644 index 4f48807..0000000 --- a/net-Add-EMAC-driver-for-H3-A83T-A64-SoCs..patch +++ /dev/null @@ -1,1076 +0,0 @@ -From patchwork Wed Jul 6 12:29:44 2016 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [U-Boot,U-BOOT,v2] net:Add EMAC driver for H3/A83T/A64 SoCs. -From: Amit Tomar -X-Patchwork-Id: 645258 -X-Patchwork-Delegate: hdegoede@redhat.com -Message-Id: <1467808184-21998-1-git-send-email-amittomer25@gmail.com> -To: u-boot@lists.denx.de -Cc: Andre Przywara , - LABBE Corentin -Date: Wed, 6 Jul 2016 17:59:44 +0530 - -This patch add EMAC driver support for H3/A83T/A64 SoCs. -Tested on Pine64(A64-External PHY) and Orangepipc(H3-Internal PHY). - -BIG Thanks to Andre for providing some of the DT code. - -Signed-off-by: Amit Singh Tomar ---- -Changes since v1: - * Addressed LABBE's comments. - * Made it compatible with External PHY. ---- - arch/arm/dts/sun50i-a64-pine64-plus.dts | 13 + - arch/arm/dts/sun50i-a64.dtsi | 33 ++ - arch/arm/dts/sun8i-h3-orangepi-2.dts | 13 + - arch/arm/dts/sun8i-h3-orangepi-pc.dts | 12 + - arch/arm/dts/sun8i-h3.dtsi | 25 + - arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 4 +- - arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 3 +- - configs/orangepi_pc_defconfig | 1 + - configs/pine64_plus_defconfig | 1 + - drivers/net/Kconfig | 9 + - drivers/net/Makefile | 1 + - drivers/net/sun8i_emac.c | 789 +++++++++++++++++++++++++ - 12 files changed, 902 insertions(+), 2 deletions(-) - create mode 100644 drivers/net/sun8i_emac.c - -diff --git a/arch/arm/dts/sun50i-a64-pine64-plus.dts b/arch/arm/dts/sun50i-a64-pine64-plus.dts -index 549dc15..389c609 100644 ---- a/arch/arm/dts/sun50i-a64-pine64-plus.dts -+++ b/arch/arm/dts/sun50i-a64-pine64-plus.dts -@@ -57,3 +57,16 @@ - reg = <0x40000000 0x40000000>; - }; - }; -+ -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rgmii_pins>; -+ phy-mode = "rgmii"; -+ phy = <&phy1>; -+ status = "okay"; -+ -+ phy1: ethernet-phy@1 { -+ reg = <1>; -+ }; -+}; -+ -diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi -index 1bd436f..7d0dc76 100644 ---- a/arch/arm/dts/sun50i-a64.dtsi -+++ b/arch/arm/dts/sun50i-a64.dtsi -@@ -506,6 +506,25 @@ - allwinner,drive = ; - allwinner,pull = ; - }; -+ -+ rmii_pins: rmii_pins { -+ allwinner,pins = "PD10", "PD11", "PD13", "PD14", -+ "PD17", "PD18", "PD19", "PD20", -+ "PD22", "PD23"; -+ allwinner,function = "emac"; -+ allwinner,drive = ; -+ allwinner,pull = ; -+ }; -+ -+ 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 = ; -+ allwinner,pull = ; -+ }; - }; - - ahb_rst: reset@1c202c0 { -@@ -620,5 +639,19 @@ - #address-cells = <1>; - #size-cells = <0>; - }; -+ -+ emac: ethernet@01c30000 { -+ compatible = "allwinner,sun50i-a64-emac"; -+ reg = <0x01c30000 0x2000>, <0x01c00030 0x4>; -+ reg-names = "emac", "syscon"; -+ interrupts = ; -+ resets = <&ahb_rst 17>; -+ reset-names = "ahb"; -+ clocks = <&bus_gates 17>; -+ clock-names = "ahb"; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; - }; - }; -diff --git a/arch/arm/dts/sun8i-h3-orangepi-2.dts b/arch/arm/dts/sun8i-h3-orangepi-2.dts -index f93f5d1..d3f8f55 100644 ---- a/arch/arm/dts/sun8i-h3-orangepi-2.dts -+++ b/arch/arm/dts/sun8i-h3-orangepi-2.dts -@@ -184,3 +184,16 @@ - usb1_vbus-supply = <®_usb1_vbus>; - status = "okay"; - }; -+ -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rgmii_pins>; -+ phy-mode = "rgmii"; -+ phy = <&phy1>; -+ status = "okay"; -+ -+ phy1: ethernet-phy@1 { -+ reg = <1>; -+ }; -+}; -+ -diff --git a/arch/arm/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/dts/sun8i-h3-orangepi-pc.dts -index 30ccca0..0a74a91 100644 ---- a/arch/arm/dts/sun8i-h3-orangepi-pc.dts -+++ b/arch/arm/dts/sun8i-h3-orangepi-pc.dts -@@ -173,3 +173,15 @@ - /* USB VBUS is always on */ - status = "okay"; - }; -+ -+&emac { -+ phy = <&phy1>; -+ phy-mode = "mii"; -+ allwinner,use-internal-phy; -+ allwinner,leds-active-low; -+ status = "okay"; -+ -+ phy1: ethernet-phy@1 { -+ reg = <1>; -+ }; -+}; -diff --git a/arch/arm/dts/sun8i-h3.dtsi b/arch/arm/dts/sun8i-h3.dtsi -index c2f63c5..6ca5e34 100644 ---- a/arch/arm/dts/sun8i-h3.dtsi -+++ b/arch/arm/dts/sun8i-h3.dtsi -@@ -501,6 +501,17 @@ - interrupt-controller; - #interrupt-cells = <3>; - -+ rgmii_pins: rgmii_pins { -+ allwinner,pins = "PD0", "PD1", "PD2", "PD3", -+ "PD4", "PD5", "PD7", -+ "PD8", "PD9", "PD10", -+ "PD12", "PD13", "PD15", -+ "PD16", "PD17"; -+ allwinner,function = "emac"; -+ allwinner,drive = ; -+ allwinner,pull = ; -+ }; -+ - uart0_pins_a: uart0@0 { - allwinner,pins = "PA4", "PA5"; - allwinner,function = "uart0"; -@@ -616,6 +627,20 @@ - status = "disabled"; - }; - -+ emac: ethernet@01c30000 { -+ compatible = "allwinner,sun8i-h3-emac"; -+ reg = <0x01c30000 0x2000>, <0x01c00030 0x4>; -+ reg-names = "emac", "syscon"; -+ interrupts = ; -+ resets = <&ahb_rst 17>, <&ahb_rst 66>; -+ reset-names = "ahb", "ephy"; -+ clocks = <&bus_gates 17>, <&bus_gates 128>; -+ clock-names = "ahb", "ephy"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ - gic: interrupt-controller@01c81000 { - compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; - reg = <0x01c81000 0x1000>, -diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h -index c2e72f5..d4dff1e 100644 ---- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h -+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h -@@ -40,7 +40,8 @@ struct sunxi_ccm_reg { - u32 ahb_gate1; /* 0x64 ahb module clock gating 1 */ - u32 apb1_gate; /* 0x68 apb1 module clock gating */ - u32 apb2_gate; /* 0x6c apb2 module clock gating */ -- u32 reserved9[4]; -+ u32 bus_gate4; /* 0x70 gate 4 module clock gating */ -+ u8 res3[0xc]; - u32 nand0_clk_cfg; /* 0x80 nand0 clock control */ - u32 nand1_clk_cfg; /* 0x84 nand1 clock control */ - u32 sd0_clk_cfg; /* 0x88 sd0 clock control */ -@@ -387,6 +388,7 @@ struct sunxi_ccm_reg { - #define AHB_RESET_OFFSET_LCD0 4 - - /* ahb_reset2 offsets */ -+#define AHB_RESET_OFFSET_EPHY 2 - #define AHB_RESET_OFFSET_LVDS 0 - - /* apb2 reset */ -diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h -index c5e9d88..cd009d7 100644 ---- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h -+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h -@@ -87,7 +87,8 @@ - #define SUNXI_KEYPAD_BASE 0x01c23000 - #define SUNXI_TZPC_BASE 0x01c23400 - --#if defined(CONFIG_MACH_SUN8I_A83T) || defined(CONFIG_MACH_SUN8I_H3) -+#if defined(CONFIG_MACH_SUN8I_A83T) || defined(CONFIG_MACH_SUN8I_H3) || \ -+defined(CONFIG_MACH_SUN50I) - /* SID address space starts at 0x01c1400, but e-fuse is at offset 0x200 */ - #define SUNXI_SID_BASE 0x01c14200 - #else -diff --git a/configs/orangepi_pc_defconfig b/configs/orangepi_pc_defconfig -index 7eaa795..294f7ab 100644 ---- a/configs/orangepi_pc_defconfig -+++ b/configs/orangepi_pc_defconfig -@@ -13,3 +13,4 @@ CONFIG_SPL=y - # CONFIG_CMD_FPGA is not set - CONFIG_SY8106A_POWER=y - CONFIG_USB_EHCI_HCD=y -+CONFIG_SUN8I_EMAC=y -diff --git a/configs/pine64_plus_defconfig b/configs/pine64_plus_defconfig -index 0bf79bf..5c97de1 100644 ---- a/configs/pine64_plus_defconfig -+++ b/configs/pine64_plus_defconfig -@@ -10,3 +10,4 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pine64-plus" - # CONFIG_CMD_FLASH is not set - # CONFIG_CMD_FPGA is not set - CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y -+CONFIG_SUN8I_EMAC=y -diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig -index c1cb689..88d8e83 100644 ---- a/drivers/net/Kconfig -+++ b/drivers/net/Kconfig -@@ -152,6 +152,15 @@ config RTL8169 - This driver supports Realtek 8169 series gigabit ethernet family of - PCI/PCIe chipsets/adapters. - -+config SUN8I_EMAC -+ bool "Allwinner Sun8i Ethernet MAC support" -+ depends on DM_ETH -+ select PHYLIB -+ help -+ This driver supports the Allwinner based SUN8I/SUN50I Ethernet MAC. -+ It can be found in H3/A64/A83T based SoCs and compatible with both -+ External and Internal PHY's. -+ - config XILINX_AXIEMAC - depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP) - select PHYLIB -diff --git a/drivers/net/Makefile b/drivers/net/Makefile -index 5702592..a448526 100644 ---- a/drivers/net/Makefile -+++ b/drivers/net/Makefile -@@ -24,6 +24,7 @@ obj-$(CONFIG_E1000) += e1000.o - obj-$(CONFIG_E1000_SPI) += e1000_spi.o - obj-$(CONFIG_EEPRO100) += eepro100.o - obj-$(CONFIG_SUNXI_EMAC) += sunxi_emac.o -+obj-$(CONFIG_SUN8I_EMAC) += sun8i_emac.o - obj-$(CONFIG_ENC28J60) += enc28j60.o - obj-$(CONFIG_EP93XX) += ep93xx_eth.o - obj-$(CONFIG_ETHOC) += ethoc.o -diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c -new file mode 100644 -index 0000000..4bed50d ---- /dev/null -+++ b/drivers/net/sun8i_emac.c -@@ -0,0 +1,789 @@ -+/* -+ * (C) Copyright 2016 -+ * Author: Amit Singh Tomar, amittomer25@gmail.com -+ * -+ * SPDX-License-Identifier: GPL-2.0+ -+ * -+ * Ethernet driver for H3/A64/A83T based SoC's -+ * -+ * It is derived from the work done by -+ * LABBE Corentin & Chen-Yu Tsai for Linux, THANKS! -+ * -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define SCTL_EMAC_TX_CLK_SRC_MII BIT(0) -+#define SCTL_EMAC_EPIT_MII BIT(2) -+#define SCTL_EMAC_CLK_SEL BIT(18) /* 25 Mhz */ -+ -+#define MDIO_CMD_MII_BUSY BIT(0) -+#define MDIO_CMD_MII_WRITE BIT(1) -+ -+#define MDIO_CMD_MII_PHY_REG_ADDR_MASK 0x000001f0 -+#define MDIO_CMD_MII_PHY_REG_ADDR_SHIFT 4 -+#define MDIO_CMD_MII_PHY_ADDR_MASK 0x0001f000 -+#define MDIO_CMD_MII_PHY_ADDR_SHIFT 12 -+ -+#define CONFIG_TX_DESCR_NUM 32 -+#define CONFIG_RX_DESCR_NUM 32 -+#define CONFIG_ETH_BUFSIZE 2024 -+ -+#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM) -+#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM) -+ -+#define H3_EPHY_DEFAULT_VALUE 0x58000 -+#define H3_EPHY_DEFAULT_MASK GENMASK(31, 15) -+#define H3_EPHY_ADDR_SHIFT 20 -+#define REG_PHY_ADDR_MASK GENMASK(4, 0) -+#define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */ -+#define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */ -+#define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */ -+ -+#define SC_RMII_EN BIT(13) -+#define SC_EPIT BIT(2) /* 1: RGMII, 0: MII */ -+#define SC_ETCS_MASK GENMASK(1, 0) -+#define SC_ETCS_EXT_GMII 0x1 -+#define SC_ETCS_INT_GMII 0x2 -+ -+#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ) -+ -+#define AHB_GATE_OFFSET_EPHY 0 -+ -+#if defined(CONFIG_MACH_SUN8I_H3) -+#define SUN8I_GPD8_GMAC 2 -+#else -+#define SUN8I_GPD8_GMAC 4 -+#endif -+ -+/* H3/A64 EMAC Register's offset */ -+#define EMAC_CTL0 0x00 -+#define EMAC_CTL1 0x04 -+#define EMAC_INT_STA 0x08 -+#define EMAC_INT_EN 0x0c -+#define EMAC_TX_CTL0 0x10 -+#define EMAC_TX_CTL1 0x14 -+#define EMAC_TX_FLOW_CTL 0x1c -+#define EMAC_TX_DMA_DESC 0x20 -+#define EMAC_RX_CTL0 0x24 -+#define EMAC_RX_CTL1 0x28 -+#define EMAC_RX_DMA_DESC 0x34 -+#define EMAC_MII_CMD 0x48 -+#define EMAC_MII_DATA 0x4c -+#define EMAC_ADDR0_HIGH 0x50 -+#define EMAC_ADDR0_LOW 0x54 -+#define EMAC_TX_DMA_STA 0xb0 -+#define EMAC_TX_CUR_DESC 0xb4 -+#define EMAC_TX_CUR_BUF 0xb8 -+#define EMAC_RX_DMA_STA 0xc0 -+#define EMAC_RX_CUR_DESC 0xc4 -+ -+DECLARE_GLOBAL_DATA_PTR; -+ -+enum emac_variant { -+ A83T_EMAC = 1, -+ H3_EMAC, -+ A64_EMAC, -+}; -+ -+struct emac_dma_desc { -+ u32 status; -+ u32 st; -+ u32 buf_addr; -+ u32 next; -+} __aligned(ARCH_DMA_MINALIGN); -+ -+struct emac_eth_dev { -+ struct emac_dma_desc rx_chain[CONFIG_TX_DESCR_NUM]; -+ struct emac_dma_desc tx_chain[CONFIG_RX_DESCR_NUM]; -+ char rxbuffer[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN); -+ char txbuffer[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN); -+ -+ u32 interface; -+ u32 phyaddr; -+ u32 link; -+ u32 speed; -+ u32 duplex; -+ u32 phy_configured; -+ u32 tx_currdescnum; -+ u32 rx_currdescnum; -+ u32 addr; -+ u32 tx_slot; -+ bool use_internal_phy; -+ -+ enum emac_variant variant; -+ void *mac_reg; -+ phys_addr_t sysctl_reg; -+ struct phy_device *phydev; -+ struct mii_dev *bus; -+}; -+ -+static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) -+{ -+ struct emac_eth_dev *priv = bus->priv; -+ ulong start; -+ u32 miiaddr = 0; -+ int timeout = CONFIG_MDIO_TIMEOUT; -+ -+ miiaddr &= ~MDIO_CMD_MII_WRITE; -+ miiaddr &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK; -+ miiaddr |= (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) & -+ MDIO_CMD_MII_PHY_REG_ADDR_MASK; -+ -+ miiaddr &= ~MDIO_CMD_MII_PHY_ADDR_MASK; -+ -+ miiaddr |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) & -+ MDIO_CMD_MII_PHY_ADDR_MASK; -+ -+ miiaddr |= MDIO_CMD_MII_BUSY; -+ -+ writel(miiaddr, priv->mac_reg + EMAC_MII_CMD); -+ -+ start = get_timer(0); -+ while (get_timer(start) < timeout) { -+ if (!(readl(priv->mac_reg + EMAC_MII_CMD) & MDIO_CMD_MII_BUSY)) -+ return readl(priv->mac_reg + EMAC_MII_DATA); -+ udelay(10); -+ }; -+ -+ return -1; -+} -+ -+static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, -+ u16 val) -+{ -+ struct emac_eth_dev *priv = bus->priv; -+ ulong start; -+ u32 miiaddr = 0; -+ int ret = -1, timeout = CONFIG_MDIO_TIMEOUT; -+ -+ miiaddr &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK; -+ miiaddr |= (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) & -+ MDIO_CMD_MII_PHY_REG_ADDR_MASK; -+ -+ miiaddr &= ~MDIO_CMD_MII_PHY_ADDR_MASK; -+ miiaddr |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) & -+ MDIO_CMD_MII_PHY_ADDR_MASK; -+ -+ miiaddr |= MDIO_CMD_MII_WRITE; -+ miiaddr |= MDIO_CMD_MII_BUSY; -+ -+ writel(miiaddr, priv->mac_reg + EMAC_MII_CMD); -+ writel(val, priv->mac_reg + EMAC_MII_DATA); -+ -+ start = get_timer(0); -+ while (get_timer(start) < timeout) { -+ if (!(readl(priv->mac_reg + EMAC_MII_CMD) & -+ MDIO_CMD_MII_BUSY)) { -+ ret = 0; -+ break; -+ } -+ udelay(10); -+ }; -+ -+ return ret; -+} -+ -+static int _sun8i_write_hwaddr(struct emac_eth_dev *priv, u8 *mac_id) -+{ -+ u32 macid_lo, macid_hi; -+ -+ macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) + -+ (mac_id[3] << 24); -+ macid_hi = mac_id[4] + (mac_id[5] << 8); -+ -+ writel(macid_hi, priv->mac_reg + EMAC_ADDR0_HIGH); -+ writel(macid_lo, priv->mac_reg + EMAC_ADDR0_LOW); -+ -+ return 0; -+} -+ -+static void sun8i_adjust_link(struct emac_eth_dev *priv, -+ struct phy_device *phydev) -+{ -+ u32 v; -+ -+ v = readl(priv->mac_reg + EMAC_CTL0); -+ -+ if (phydev->duplex) -+ v |= BIT(0); -+ else -+ v &= ~BIT(0); -+ -+ v &= ~0x0C; -+ -+ switch (phydev->speed) { -+ case 1000: -+ break; -+ case 100: -+ v |= BIT(2); -+ v |= BIT(3); -+ break; -+ case 10: -+ v |= BIT(3); -+ break; -+ } -+ writel(v, priv->mac_reg + EMAC_CTL0); -+} -+ -+static int sun8i_emac_set_syscon_ephy(struct emac_eth_dev *priv, u32 *reg) -+{ -+ if (priv->use_internal_phy) { -+ /* H3 based SoC's that has an Internal 100MBit PHY -+ * needs to be configured and powered up before use -+ */ -+ *reg &= ~H3_EPHY_DEFAULT_MASK; -+ *reg |= H3_EPHY_DEFAULT_VALUE; -+ *reg |= priv->phyaddr << H3_EPHY_ADDR_SHIFT; -+ *reg &= ~H3_EPHY_SHUTDOWN; -+ *reg |= H3_EPHY_SELECT; -+ } else -+ /* This is to select External Gigabit PHY on -+ * the boards with H3 SoC. -+ */ -+ *reg &= ~H3_EPHY_SELECT; -+ -+ return 0; -+} -+ -+static int sun8i_emac_set_syscon(struct emac_eth_dev *priv) -+{ -+ int ret; -+ u32 reg; -+ -+ reg = readl(priv->sysctl_reg); -+ -+ if (priv->variant == H3_EMAC) { -+ ret = sun8i_emac_set_syscon_ephy(priv, ®); -+ if (ret) -+ return ret; -+ } -+ -+ reg &= ~(SC_ETCS_MASK | SC_EPIT); -+ if (priv->variant == H3_EMAC || priv->variant == A64_EMAC) -+ reg &= ~SC_RMII_EN; -+ -+ switch (priv->interface) { -+ case PHY_INTERFACE_MODE_MII: -+ /* default */ -+ break; -+ case PHY_INTERFACE_MODE_RGMII: -+ reg |= SC_EPIT | SC_ETCS_INT_GMII; -+ break; -+ case PHY_INTERFACE_MODE_RMII: -+ if (priv->variant == H3_EMAC || -+ priv->variant == A64_EMAC) { -+ reg |= SC_RMII_EN | SC_ETCS_EXT_GMII; -+ break; -+ } -+ /* RMII not supported on A83T */ -+ default: -+ debug("%s: Invalid PHY interface\n", __func__); -+ return -EINVAL; -+ } -+ -+ writel(reg, priv->sysctl_reg); -+ -+ return 0; -+} -+ -+static int sun8i_phy_init(struct emac_eth_dev *priv, void *dev) -+{ -+ struct phy_device *phydev; -+ -+ phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface); -+ if (!phydev) -+ return -ENODEV; -+ -+ phy_connect_dev(phydev, dev); -+ -+ priv->phydev = phydev; -+ phy_config(priv->phydev); -+ -+ return 0; -+} -+ -+static void rx_descs_init(struct emac_eth_dev *priv) -+{ -+ struct emac_dma_desc *desc_table_p = &priv->rx_chain[0]; -+ char *rxbuffs = &priv->rxbuffer[0]; -+ struct emac_dma_desc *desc_p; -+ u32 idx; -+ -+ /* flush Rx buffers */ -+ flush_dcache_range((uintptr_t)rxbuffs, (ulong)rxbuffs + -+ RX_TOTAL_BUFSIZE); -+ -+ for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) { -+ desc_p = &desc_table_p[idx]; -+ desc_p->buf_addr = (uintptr_t)&rxbuffs[idx * CONFIG_ETH_BUFSIZE] -+ ; -+ desc_p->next = (uintptr_t)&desc_table_p[idx + 1]; -+ desc_p->st |= CONFIG_ETH_BUFSIZE; -+ desc_p->status = BIT(31); -+ } -+ -+ /* Correcting the last pointer of the chain */ -+ desc_p->next = (uintptr_t)&desc_table_p[0]; -+ -+ flush_dcache_range((uintptr_t)priv->rx_chain, -+ (uintptr_t)priv->rx_chain + -+ sizeof(priv->rx_chain)); -+ -+ writel((uintptr_t)&desc_table_p[0], (priv->mac_reg + EMAC_RX_DMA_DESC)); -+ priv->rx_currdescnum = 0; -+} -+ -+static void tx_descs_init(struct emac_eth_dev *priv) -+{ -+ struct emac_dma_desc *desc_table_p = &priv->tx_chain[0]; -+ char *txbuffs = &priv->txbuffer[0]; -+ struct emac_dma_desc *desc_p; -+ u32 idx; -+ -+ for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) { -+ desc_p = &desc_table_p[idx]; -+ desc_p->buf_addr = (uintptr_t)&txbuffs[idx * CONFIG_ETH_BUFSIZE] -+ ; -+ desc_p->next = (uintptr_t)&desc_table_p[idx + 1]; -+ desc_p->status = (1 << 31); -+ desc_p->st = 0; -+ } -+ -+ /* Correcting the last pointer of the chain */ -+ desc_p->next = (uintptr_t)&desc_table_p[0]; -+ -+ /* Flush all Tx buffer descriptors */ -+ flush_dcache_range((uintptr_t)priv->tx_chain, -+ (uintptr_t)priv->tx_chain + -+ sizeof(priv->tx_chain)); -+ -+ writel((uintptr_t)&desc_table_p[0], priv->mac_reg + EMAC_TX_DMA_DESC); -+ priv->tx_currdescnum = 0; -+} -+ -+static int _sun8i_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr) -+{ -+ u32 reg, v; -+ int timeout = 100; -+ -+ reg = readl((priv->mac_reg + EMAC_CTL1)); -+ -+ if (!(reg & 0x1)) { -+ /* Soft reset MAC */ -+ setbits_le32((priv->mac_reg + EMAC_CTL1), 0x1); -+ do { -+ reg = readl(priv->mac_reg + EMAC_CTL1); -+ } while ((reg & 0x01) != 0 && (--timeout)); -+ if (!timeout) { -+ printf("%s: Timeout\n", __func__); -+ return -1; -+ } -+ } -+ -+ /* Rewrite mac address after reset */ -+ _sun8i_write_hwaddr(priv, enetaddr); -+ -+ v = readl(priv->mac_reg + EMAC_TX_CTL1); -+ /* TX_MD Transmission starts after a full frame located in TX DMA FIFO*/ -+ v |= BIT(1); -+ writel(v, priv->mac_reg + EMAC_TX_CTL1); -+ -+ v = readl(priv->mac_reg + EMAC_RX_CTL1); -+ /* RX_MD RX DMA reads data from RX DMA FIFO to host memory after a -+ * complete frame has been written to RX DMA FIFO -+ */ -+ v |= BIT(1); -+ writel(v, priv->mac_reg + EMAC_RX_CTL1); -+ -+ /* DMA */ -+ writel(8 << 24, priv->mac_reg + EMAC_CTL1); -+ -+ /* Initialize rx/tx descriptors */ -+ rx_descs_init(priv); -+ tx_descs_init(priv); -+ -+ /* PHY Start Up */ -+ genphy_parse_link(priv->phydev); -+ -+ sun8i_adjust_link(priv, priv->phydev); -+ -+ /* Start RX DMA */ -+ v = readl(priv->mac_reg + EMAC_RX_CTL1); -+ v |= BIT(30); -+ writel(v, priv->mac_reg + EMAC_RX_CTL1); -+ /* Start TX DMA */ -+ v = readl(priv->mac_reg + EMAC_TX_CTL1); -+ v |= BIT(30); -+ writel(v, priv->mac_reg + EMAC_TX_CTL1); -+ -+ /* Enable RX/TX */ -+ setbits_le32(priv->mac_reg + EMAC_RX_CTL0, BIT(31)); -+ setbits_le32(priv->mac_reg + EMAC_TX_CTL0, BIT(31)); -+ -+ 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, -+ "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; -+ -+ if (fdt_get_string_index(gd->fdt_blob, offset, -+ "allwinner,pins", i, &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; -+ struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num]; -+ int length = -EAGAIN; -+ int good_packet = 1; -+ uintptr_t desc_start = (uintptr_t)desc_p; -+ uintptr_t desc_end = desc_start + -+ roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN); -+ -+ ulong data_start = (uintptr_t)desc_p->buf_addr; -+ ulong data_end; -+ -+ /* Invalidate entire buffer descriptor */ -+ invalidate_dcache_range(desc_start, desc_end); -+ -+ status = desc_p->status; -+ -+ /* Check for DMA own bit */ -+ if (!(status & BIT(31))) { -+ length = (desc_p->status >> 16) & 0x3FFF; -+ -+ if (length < 0x40) { -+ good_packet = 0; -+ debug("RX: Bad Packet (runt)\n"); -+ } -+ -+ data_end = data_start + length; -+ /* Invalidate received data */ -+ invalidate_dcache_range(rounddown(data_start, -+ ARCH_DMA_MINALIGN), -+ roundup(data_end, -+ ARCH_DMA_MINALIGN)); -+ if (good_packet) { -+ if (length > CONFIG_ETH_BUFSIZE) { -+ printf("Received packet is too big (len=%d)\n", -+ length); -+ return -EMSGSIZE; -+ } -+ *packetp = (uchar *)(ulong)desc_p->buf_addr; -+ return length; -+ } -+ } -+ -+ return length; -+} -+ -+static int _sun8i_emac_eth_send(struct emac_eth_dev *priv, void *packet, -+ int len) -+{ -+ u32 v, desc_num = priv->tx_currdescnum; -+ struct emac_dma_desc *desc_p = &priv->tx_chain[desc_num]; -+ uintptr_t desc_start = (uintptr_t)desc_p; -+ uintptr_t desc_end = desc_start + -+ roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN); -+ -+ uintptr_t data_start = (uintptr_t)desc_p->buf_addr; -+ uintptr_t data_end = data_start + -+ roundup(len, ARCH_DMA_MINALIGN); -+ -+ /* Invalidate entire buffer descriptor */ -+ invalidate_dcache_range(desc_start, desc_end); -+ -+ desc_p->st = len; -+ /* Mandatory undocumented bit */ -+ desc_p->st |= BIT(24); -+ -+ memcpy((void *)data_start, packet, len); -+ -+ /* Flush data to be sent */ -+ flush_dcache_range(data_start, data_end); -+ -+ /* frame end */ -+ desc_p->st |= BIT(30); -+ desc_p->st |= BIT(31); -+ -+ /*frame begin */ -+ desc_p->st |= BIT(29); -+ desc_p->status = BIT(31); -+ -+ /*Descriptors st and status field has changed, so FLUSH it */ -+ flush_dcache_range(desc_start, desc_end); -+ -+ /* Move to next Descriptor and wrap around */ -+ if (++desc_num >= CONFIG_TX_DESCR_NUM) -+ desc_num = 0; -+ priv->tx_currdescnum = desc_num; -+ -+ /* Start the DMA */ -+ v = readl(priv->mac_reg + EMAC_TX_CTL1); -+ v |= BIT(31);/* mandatory */ -+ v |= BIT(30);/* mandatory */ -+ writel(v, priv->mac_reg + EMAC_TX_CTL1); -+ -+ return 0; -+} -+ -+static int sun8i_eth_write_hwaddr(struct udevice *dev) -+{ -+ struct eth_pdata *pdata = dev_get_platdata(dev); -+ struct emac_eth_dev *priv = dev_get_priv(dev); -+ -+ return _sun8i_write_hwaddr(priv, pdata->enetaddr); -+} -+ -+static void sun8i_emac_board_setup(struct emac_eth_dev *priv) -+{ -+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; -+ -+ if (priv->use_internal_phy) { -+ /* Set clock gating for ephy */ -+ setbits_le32(&ccm->bus_gate4, BIT(AHB_GATE_OFFSET_EPHY)); -+ -+ /* Set Tx clock source as MII with rate 25 MZ */ -+ setbits_le32(priv->sysctl_reg, SCTL_EMAC_TX_CLK_SRC_MII | -+ SCTL_EMAC_EPIT_MII | SCTL_EMAC_CLK_SEL); -+ /* Deassert EPHY */ -+ setbits_le32(&ccm->ahb_reset2_cfg, BIT(AHB_RESET_OFFSET_EPHY)); -+ } -+ -+ /* Set clock gating for emac */ -+ setbits_le32(&ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_GMAC)); -+ -+ /* Set EMAC clock */ -+ setbits_le32(&ccm->axi_gate, (BIT(1) | BIT(0))); -+ -+ /* De-assert EMAC */ -+ setbits_le32(&ccm->ahb_reset0_cfg, BIT(AHB_RESET_OFFSET_GMAC)); -+} -+ -+static int sun8i_mdio_init(const char *name, struct emac_eth_dev *priv) -+{ -+ struct mii_dev *bus = mdio_alloc(); -+ -+ if (!bus) { -+ debug("Failed to allocate MDIO bus\n"); -+ return -ENOMEM; -+ } -+ -+ bus->read = sun8i_mdio_read; -+ bus->write = sun8i_mdio_write; -+ snprintf(bus->name, sizeof(bus->name), name); -+ bus->priv = (void *)priv; -+ -+ return mdio_register(bus); -+} -+ -+static int sun8i_emac_eth_start(struct udevice *dev) -+{ -+ struct eth_pdata *pdata = dev_get_platdata(dev); -+ -+ return _sun8i_emac_eth_init(dev->priv, pdata->enetaddr); -+} -+ -+static int sun8i_emac_eth_send(struct udevice *dev, void *packet, int length) -+{ -+ struct emac_eth_dev *priv = dev_get_priv(dev); -+ -+ return _sun8i_emac_eth_send(priv, packet, length); -+} -+ -+static int sun8i_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp) -+{ -+ struct emac_eth_dev *priv = dev_get_priv(dev); -+ -+ return _sun8i_eth_recv(priv, packetp); -+} -+ -+static int _sun8i_free_pkt(struct emac_eth_dev *priv) -+{ -+ u32 desc_num = priv->rx_currdescnum; -+ struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num]; -+ uintptr_t desc_start = (uintptr_t)desc_p; -+ uintptr_t desc_end = desc_start + -+ roundup(sizeof(u32), ARCH_DMA_MINALIGN); -+ -+ /* Make the current descriptor valid again */ -+ desc_p->status |= BIT(31); -+ -+ /* Flush Status field of descriptor */ -+ flush_dcache_range(desc_start, desc_end); -+ -+ /* Move to next desc and wrap-around condition. */ -+ if (++desc_num >= CONFIG_RX_DESCR_NUM) -+ desc_num = 0; -+ priv->rx_currdescnum = desc_num; -+ -+ return 0; -+} -+ -+static int sun8i_eth_free_pkt(struct udevice *dev, uchar *packet, -+ int length) -+{ -+ struct emac_eth_dev *priv = dev_get_priv(dev); -+ -+ return _sun8i_free_pkt(priv); -+} -+ -+static void sun8i_emac_eth_stop(struct udevice *dev) -+{ -+ struct emac_eth_dev *priv = dev_get_priv(dev); -+ -+ /* Stop Rx/Tx transmitter */ -+ clrbits_le32(priv->mac_reg + EMAC_RX_CTL0, BIT(31)); -+ clrbits_le32(priv->mac_reg + EMAC_TX_CTL0, BIT(31)); -+ -+ /* Stop TX DMA */ -+ clrbits_le32(priv->mac_reg + EMAC_TX_CTL1, BIT(30)); -+ -+ phy_shutdown(priv->phydev); -+} -+ -+static int sun8i_emac_eth_probe(struct udevice *dev) -+{ -+ struct eth_pdata *pdata = dev_get_platdata(dev); -+ struct emac_eth_dev *priv = dev_get_priv(dev); -+ -+ priv->mac_reg = (void *)pdata->iobase; -+ -+ sun8i_emac_board_setup(priv); -+ -+ sun8i_mdio_init(dev->name, priv); -+ priv->bus = miiphy_get_dev_by_name(dev->name); -+ -+ sun8i_emac_set_syscon(priv); -+ -+ return sun8i_phy_init(priv, dev); -+} -+ -+static const struct eth_ops sun8i_emac_eth_ops = { -+ .start = sun8i_emac_eth_start, -+ .write_hwaddr = sun8i_eth_write_hwaddr, -+ .send = sun8i_emac_eth_send, -+ .recv = sun8i_emac_eth_recv, -+ .free_pkt = sun8i_eth_free_pkt, -+ .stop = sun8i_emac_eth_stop, -+}; -+ -+static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev) -+{ -+ struct eth_pdata *pdata = dev_get_platdata(dev); -+ struct emac_eth_dev *priv = dev_get_priv(dev); -+ const char *phy_mode; -+ int offset = 0; -+ -+ pdata->iobase = dev_get_addr_name(dev, "emac"); -+ priv->sysctl_reg = dev_get_addr_name(dev, "syscon"); -+ -+ pdata->phy_interface = -1; -+ priv->phyaddr = -1; -+ priv->use_internal_phy = false; -+ -+ offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, -+ "phy"); -+ if (offset > 0) -+ priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -+ -1); -+ -+ phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL); -+ -+ if (phy_mode) -+ pdata->phy_interface = phy_get_interface_by_name(phy_mode); -+ printf("phy interface%d\n", pdata->phy_interface); -+ -+ if (pdata->phy_interface == -1) { -+ debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); -+ return -EINVAL; -+ } -+ -+ priv->variant = dev_get_driver_data(dev); -+ -+ if (!priv->variant) { -+ printf("%s: Missing variant '%s'\n", __func__, -+ (char *)priv->variant); -+ return -EINVAL; -+ } -+ -+ if (priv->variant == H3_EMAC) { -+ if (fdt_getprop(gd->fdt_blob, dev->of_offset, -+ "allwinner,use-internal-phy", NULL)) -+ priv->use_internal_phy = true; -+ } -+ -+ priv->interface = pdata->phy_interface; -+ -+ if (!priv->use_internal_phy) -+ parse_phy_pins(dev); -+ -+ return 0; -+} -+ -+static const struct udevice_id sun8i_emac_eth_ids[] = { -+ {.compatible = "allwinner,sun8i-h3-emac", .data = (uintptr_t)H3_EMAC }, -+ {.compatible = "allwinner,sun50i-a64-emac", -+ .data = (uintptr_t)A64_EMAC }, -+ {.compatible = "allwinner,sun8i-a83t-emac", -+ .data = (uintptr_t)A83T_EMAC }, -+ { } -+}; -+ -+U_BOOT_DRIVER(eth_sun8i_emac) = { -+ .name = "eth_sun8i_emac", -+ .id = UCLASS_ETH, -+ .of_match = sun8i_emac_eth_ids, -+ .ofdata_to_platdata = sun8i_emac_eth_ofdata_to_platdata, -+ .probe = sun8i_emac_eth_probe, -+ .ops = &sun8i_emac_eth_ops, -+ .priv_auto_alloc_size = sizeof(struct emac_eth_dev), -+ .platdata_auto_alloc_size = sizeof(struct eth_pdata), -+ .flags = DM_FLAG_ALLOC_PRIV_DMA, -+}; diff --git a/sources b/sources index 31ddb09..a549b9d 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -425a3fa610a7d972e5092a0e92276c70 u-boot-2016.07.tar.bz2 +1b3b22c73d38bbb7b7895d6d318f5c91 u-boot-2016.09-rc1.tar.bz2 diff --git a/sunxi-mmc-increase-status-register-polling-rate-for-data-transfers.patch b/sunxi-mmc-increase-status-register-polling-rate-for-data-transfers.patch deleted file mode 100644 index 6d16e43..0000000 --- a/sunxi-mmc-increase-status-register-polling-rate-for-data-transfers.patch +++ /dev/null @@ -1,55 +0,0 @@ -From patchwork Fri Jul 8 10:40:14 2016 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [U-Boot, - RESEND] sunxi: mmc: increase status register polling rate for data - transfers -From: Tobias Doerffel -X-Patchwork-Id: 646568 -X-Patchwork-Delegate: hdegoede@redhat.com -Message-Id: <1467974414-18845-1-git-send-email-tobias.doerffel@ed-chemnitz.de> -To: u-boot@lists.denx.de -Cc: Tobias Doerffel , ijc@hellion.org.uk -Date: Fri, 8 Jul 2016 12:40:14 +0200 - -With a recent bunch of SD3.0 cards in our A20-based board we -experienced data transfer rates of about 250 KiB/s instead of 10 MiB/s -with previous cards from the same vendor (both 4 GB/class 10). By -increasing status register polling rate from 1 kHz to 1 MHz we were -able to reach the original transfer rates again. With the old cards -we now even reach about 16 MiB/s. - -Signed-off-by: Tobias Doerffel ---- - drivers/mmc/sunxi_mmc.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c -index ce2dc4a..36da3b3 100644 ---- a/drivers/mmc/sunxi_mmc.c -+++ b/drivers/mmc/sunxi_mmc.c -@@ -269,18 +269,18 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data) - unsigned i; - unsigned *buff = (unsigned int *)(reading ? data->dest : data->src); - unsigned byte_cnt = data->blocksize * data->blocks; -- unsigned timeout_msecs = byte_cnt >> 8; -- if (timeout_msecs < 2000) -- timeout_msecs = 2000; -+ unsigned timeout_usecs = (byte_cnt >> 8) * 1000; -+ if (timeout_usecs < 2000000) -+ timeout_usecs = 2000000; - - /* Always read / write data through the CPU */ - setbits_le32(&mmchost->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB); - - for (i = 0; i < (byte_cnt >> 2); i++) { - while (readl(&mmchost->reg->status) & status_bit) { -- if (!timeout_msecs--) -+ if (!timeout_usecs--) - return -1; -- udelay(1000); -+ udelay(1); - } - - if (reading) diff --git a/uboot-tools.spec b/uboot-tools.spec index faf7627..3c1daae 100644 --- a/uboot-tools.spec +++ b/uboot-tools.spec @@ -1,7 +1,7 @@ -#global candidate rc3 +%global candidate rc1 Name: uboot-tools -Version: 2016.07 +Version: 2016.09 Release: 1%{?candidate:.%{candidate}}%{?dist} Summary: U-Boot utilities @@ -15,8 +15,6 @@ Source2: armv8-boards Patch1: add-BOOTENV_INIT_COMMAND-for-commands-that-may-be-ne.patch Patch2: port-utilite-to-distro-generic-boot-commands.patch Patch3: mvebu-enable-generic-distro-boot-config.patch -Patch4: sunxi-mmc-increase-status-register-polling-rate-for-data-transfers.patch -Patch5: net-Add-EMAC-driver-for-H3-A83T-A64-SoCs..patch BuildRequires: bc BuildRequires: dtc @@ -205,6 +203,9 @@ cp -p board/amlogic/odroid-c2/README doc/README.odroid-c2 %endif %changelog +* Wed Jul 27 2016 Peter Robinson 2016.09-0.1rc1 +- 2016.0r97 RC1 + * Tue Jul 12 2016 Peter Robinson 2016.07-1 - Update to 2016.07 GA