diff options
Diffstat (limited to 'target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch')
-rw-r--r-- | target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch b/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch new file mode 100644 index 0000000..d0d9f13 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch @@ -0,0 +1,273 @@ +From af0bd4e9ba809391f275d0c094ac0bfbfbb3f430 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Fri, 17 Jan 2014 21:24:47 +0800 +Subject: [PATCH] net: stmmac: sunxi platform extensions for GMAC in Allwinner + A20 SoC's + +The Allwinner A20 has an ethernet controller that seems to be +an early version of Synopsys DesignWare MAC 10/100/1000 Universal, +which is supported by the stmmac driver. + +Allwinner's GMAC requires setting additional registers in the SoC's +clock control unit. + +The exact version of the DWMAC IP that Allwinner uses is unknown, +thus the exact feature set is unknown. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + .../bindings/net/allwinner,sun7i-a20-gmac.txt | 27 ++++ + drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++ + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + + drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 140 +++++++++++++++++++++ + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 + + .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 + + 6 files changed, 185 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt + create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c + +diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt +new file mode 100644 +index 0000000..ea4d752 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt +@@ -0,0 +1,27 @@ ++* Allwinner GMAC ethernet controller ++ ++This device is a platform glue layer for stmmac. ++Please see stmmac.txt for the other unchanged properties. ++ ++Required properties: ++ - compatible: Should be "allwinner,sun7i-a20-gmac" ++ - clocks: Should contain the GMAC main clock, and tx clock ++ The tx clock type should be "allwinner,sun7i-a20-gmac-clk" ++ - clock-names: Should contain the clock names "stmmaceth", ++ and "allwinner_gmac_tx" ++ ++Optional properties: ++- phy-supply: phandle to a regulator if the PHY needs one ++ ++Examples: ++ ++ gmac: ethernet@01c50000 { ++ compatible = "allwinner,sun7i-a20-gmac"; ++ reg = <0x01c50000 0x10000>, ++ <0x01c20164 0x4>; ++ interrupts = <0 85 1>; ++ interrupt-names = "macirq"; ++ clocks = <&ahb_gates 49>, <&gmac_tx>; ++ clock-names = "stmmaceth", "allwinner_gmac_tx"; ++ phy-mode = "mii"; ++ }; +diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig +index b59d1ef..e2f202e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig ++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig +@@ -26,6 +26,17 @@ config STMMAC_PLATFORM + + If unsure, say N. + ++config DWMAC_SUNXI ++ bool "Allwinner GMAC support" ++ depends on STMMAC_PLATFORM && ARCH_SUNXI ++ default y ++ ---help--- ++ Support for Allwinner A20/A31 GMAC ethernet controllers. ++ ++ This selects Allwinner SoC glue layer support for the ++ stmmac device driver. This driver is used for A20/A31 ++ GMAC ethernet controller. ++ + config STMMAC_PCI + bool "STMMAC PCI bus support" + depends on STMMAC_ETH && PCI +diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile +index 356a9dd..ecadece 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Makefile ++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile +@@ -1,6 +1,7 @@ + obj-$(CONFIG_STMMAC_ETH) += stmmac.o + stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o + stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o ++stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o + stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ + chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ + dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +new file mode 100644 +index 0000000..771cd15f +--- /dev/null ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +@@ -0,0 +1,140 @@ ++/** ++ * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer ++ * ++ * Copyright (C) 2013 Chen-Yu Tsai ++ * ++ * Chen-Yu Tsai <wens@csie.org> ++ * ++ * This program 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 program 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. ++ */ ++ ++#include <linux/stmmac.h> ++#include <linux/clk.h> ++#include <linux/phy.h> ++#include <linux/of_net.h> ++#include <linux/regulator/consumer.h> ++ ++struct sunxi_priv_data { ++ int interface; ++ int clk_enabled; ++ struct clk *tx_clk; ++ struct regulator *regulator; ++}; ++ ++static void *sun7i_gmac_setup(struct platform_device *pdev) ++{ ++ struct sunxi_priv_data *gmac; ++ struct device *dev = &pdev->dev; ++ ++ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); ++ if (!gmac) ++ return ERR_PTR(-ENOMEM); ++ ++ gmac->interface = of_get_phy_mode(dev->of_node); ++ ++ gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx"); ++ if (IS_ERR(gmac->tx_clk)) { ++ dev_err(dev, "could not get tx clock\n"); ++ return gmac->tx_clk; ++ } ++ ++ /* Optional regulator for PHY */ ++ gmac->regulator = devm_regulator_get_optional(dev, "phy"); ++ if (IS_ERR(gmac->regulator)) { ++ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) ++ return ERR_PTR(-EPROBE_DEFER); ++ dev_info(dev, "no regulator found\n"); ++ gmac->regulator = NULL; ++ } ++ ++ return gmac; ++} ++ ++#define SUN7I_GMAC_GMII_RGMII_RATE 125000000 ++#define SUN7I_GMAC_MII_RATE 25000000 ++ ++static int sun7i_gmac_init(struct platform_device *pdev, void *priv) ++{ ++ struct sunxi_priv_data *gmac = priv; ++ int ret; ++ ++ if (gmac->regulator) { ++ ret = regulator_enable(gmac->regulator); ++ if (ret) ++ return ret; ++ } ++ ++ /* Set GMAC interface port mode ++ * ++ * The GMAC TX clock lines are configured by setting the clock ++ * rate, which then uses the auto-reparenting feature of the ++ * clock driver, and enabling/disabling the clock. ++ */ ++ if (gmac->interface == PHY_INTERFACE_MODE_RGMII) { ++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE); ++ clk_prepare_enable(gmac->tx_clk); ++ gmac->clk_enabled = 1; ++ } else { ++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE); ++ clk_prepare(gmac->tx_clk); ++ } ++ ++ return 0; ++} ++ ++static void sun7i_gmac_exit(struct platform_device *pdev, void *priv) ++{ ++ struct sunxi_priv_data *gmac = priv; ++ ++ if (gmac->clk_enabled) { ++ clk_disable(gmac->tx_clk); ++ gmac->clk_enabled = 0; ++ } ++ clk_unprepare(gmac->tx_clk); ++ ++ if (gmac->regulator) ++ regulator_disable(gmac->regulator); ++} ++ ++static void sun7i_fix_speed(void *priv, unsigned int speed) ++{ ++ struct sunxi_priv_data *gmac = priv; ++ ++ /* only GMII mode requires us to reconfigure the clock lines */ ++ if (gmac->interface != PHY_INTERFACE_MODE_GMII) ++ return; ++ ++ if (gmac->clk_enabled) { ++ clk_disable(gmac->tx_clk); ++ gmac->clk_enabled = 0; ++ } ++ clk_unprepare(gmac->tx_clk); ++ ++ if (speed == 1000) { ++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE); ++ clk_prepare_enable(gmac->tx_clk); ++ gmac->clk_enabled = 1; ++ } else { ++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE); ++ clk_prepare(gmac->tx_clk); ++ } ++} ++ ++/* of_data specifying hardware features and callbacks. ++ * hardware features were copied from Allwinner drivers. */ ++const struct stmmac_of_data sun7i_gmac_data = { ++ .has_gmac = 1, ++ .tx_coe = 1, ++ .fix_mac_speed = sun7i_fix_speed, ++ .setup = sun7i_gmac_setup, ++ .init = sun7i_gmac_init, ++ .exit = sun7i_gmac_exit, ++}; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index c1c141f..d9af26e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -130,6 +130,9 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, + bool stmmac_eee_init(struct stmmac_priv *priv); + + #ifdef CONFIG_STMMAC_PLATFORM ++#ifdef CONFIG_DWMAC_SUNXI ++extern const struct stmmac_of_data sun7i_gmac_data; ++#endif + extern struct platform_driver stmmac_pltfr_driver; + static inline int stmmac_register_platform(void) + { +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index bf119db..9d4baa8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -30,6 +30,9 @@ + #include "stmmac.h" + + static const struct of_device_id stmmac_dt_ids[] = { ++#ifdef CONFIG_DWMAC_SUNXI ++ { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, ++#endif + /* SoC specific glue layers should come before generic bindings */ + { .compatible = "st,spear600-gmac"}, + { .compatible = "snps,dwmac-3.610"}, +-- +1.8.5.5 + |