aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorChen-Yu Tsai <wens@csie.org>2014-01-17 08:24:47 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-19 23:02:41 -0500
commitaf0bd4e9ba809391f275d0c094ac0bfbfbb3f430 (patch)
tree883ebd0c4ccd98de59579a8b665ff7e7bbcf58e7 /drivers/net
parent022066f50f53000679d31eb407693085f37b3f14 (diff)
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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c140
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c3
5 files changed, 158 insertions, 0 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index b59d1ef5f6d4..e2f202e3932f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -26,6 +26,17 @@ config STMMAC_PLATFORM
26 26
27 If unsure, say N. 27 If unsure, say N.
28 28
29config DWMAC_SUNXI
30 bool "Allwinner GMAC support"
31 depends on STMMAC_PLATFORM && ARCH_SUNXI
32 default y
33 ---help---
34 Support for Allwinner A20/A31 GMAC ethernet controllers.
35
36 This selects Allwinner SoC glue layer support for the
37 stmmac device driver. This driver is used for A20/A31
38 GMAC ethernet controller.
39
29config STMMAC_PCI 40config STMMAC_PCI
30 bool "STMMAC PCI bus support" 41 bool "STMMAC PCI bus support"
31 depends on STMMAC_ETH && PCI 42 depends on STMMAC_ETH && PCI
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 356a9dd32be7..ecadecea79b2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,6 +1,7 @@
1obj-$(CONFIG_STMMAC_ETH) += stmmac.o 1obj-$(CONFIG_STMMAC_ETH) += stmmac.o
2stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o 2stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
3stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o 3stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
4stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
4stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ 5stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
5 chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ 6 chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
6 dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ 7 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 000000000000..771cd15fca18
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -0,0 +1,140 @@
1/**
2 * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer
3 *
4 * Copyright (C) 2013 Chen-Yu Tsai
5 *
6 * Chen-Yu Tsai <wens@csie.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/stmmac.h>
20#include <linux/clk.h>
21#include <linux/phy.h>
22#include <linux/of_net.h>
23#include <linux/regulator/consumer.h>
24
25struct sunxi_priv_data {
26 int interface;
27 int clk_enabled;
28 struct clk *tx_clk;
29 struct regulator *regulator;
30};
31
32static void *sun7i_gmac_setup(struct platform_device *pdev)
33{
34 struct sunxi_priv_data *gmac;
35 struct device *dev = &pdev->dev;
36
37 gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
38 if (!gmac)
39 return ERR_PTR(-ENOMEM);
40
41 gmac->interface = of_get_phy_mode(dev->of_node);
42
43 gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
44 if (IS_ERR(gmac->tx_clk)) {
45 dev_err(dev, "could not get tx clock\n");
46 return gmac->tx_clk;
47 }
48
49 /* Optional regulator for PHY */
50 gmac->regulator = devm_regulator_get_optional(dev, "phy");
51 if (IS_ERR(gmac->regulator)) {
52 if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
53 return ERR_PTR(-EPROBE_DEFER);
54 dev_info(dev, "no regulator found\n");
55 gmac->regulator = NULL;
56 }
57
58 return gmac;
59}
60
61#define SUN7I_GMAC_GMII_RGMII_RATE 125000000
62#define SUN7I_GMAC_MII_RATE 25000000
63
64static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
65{
66 struct sunxi_priv_data *gmac = priv;
67 int ret;
68
69 if (gmac->regulator) {
70 ret = regulator_enable(gmac->regulator);
71 if (ret)
72 return ret;
73 }
74
75 /* Set GMAC interface port mode
76 *
77 * The GMAC TX clock lines are configured by setting the clock
78 * rate, which then uses the auto-reparenting feature of the
79 * clock driver, and enabling/disabling the clock.
80 */
81 if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
82 clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
83 clk_prepare_enable(gmac->tx_clk);
84 gmac->clk_enabled = 1;
85 } else {
86 clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
87 clk_prepare(gmac->tx_clk);
88 }
89
90 return 0;
91}
92
93static void sun7i_gmac_exit(struct platform_device *pdev, void *priv)
94{
95 struct sunxi_priv_data *gmac = priv;
96
97 if (gmac->clk_enabled) {
98 clk_disable(gmac->tx_clk);
99 gmac->clk_enabled = 0;
100 }
101 clk_unprepare(gmac->tx_clk);
102
103 if (gmac->regulator)
104 regulator_disable(gmac->regulator);
105}
106
107static void sun7i_fix_speed(void *priv, unsigned int speed)
108{
109 struct sunxi_priv_data *gmac = priv;
110
111 /* only GMII mode requires us to reconfigure the clock lines */
112 if (gmac->interface != PHY_INTERFACE_MODE_GMII)
113 return;
114
115 if (gmac->clk_enabled) {
116 clk_disable(gmac->tx_clk);
117 gmac->clk_enabled = 0;
118 }
119 clk_unprepare(gmac->tx_clk);
120
121 if (speed == 1000) {
122 clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
123 clk_prepare_enable(gmac->tx_clk);
124 gmac->clk_enabled = 1;
125 } else {
126 clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
127 clk_prepare(gmac->tx_clk);
128 }
129}
130
131/* of_data specifying hardware features and callbacks.
132 * hardware features were copied from Allwinner drivers. */
133const struct stmmac_of_data sun7i_gmac_data = {
134 .has_gmac = 1,
135 .tx_coe = 1,
136 .fix_mac_speed = sun7i_fix_speed,
137 .setup = sun7i_gmac_setup,
138 .init = sun7i_gmac_init,
139 .exit = sun7i_gmac_exit,
140};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index c1c141fe15e7..d9af26ed58ee 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -130,6 +130,9 @@ void stmmac_disable_eee_mode(struct stmmac_priv *priv);
130bool stmmac_eee_init(struct stmmac_priv *priv); 130bool stmmac_eee_init(struct stmmac_priv *priv);
131 131
132#ifdef CONFIG_STMMAC_PLATFORM 132#ifdef CONFIG_STMMAC_PLATFORM
133#ifdef CONFIG_DWMAC_SUNXI
134extern const struct stmmac_of_data sun7i_gmac_data;
135#endif
133extern struct platform_driver stmmac_pltfr_driver; 136extern struct platform_driver stmmac_pltfr_driver;
134static inline int stmmac_register_platform(void) 137static inline int stmmac_register_platform(void)
135{ 138{
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index bf119db15212..9d4baa8b94ad 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -30,6 +30,9 @@
30#include "stmmac.h" 30#include "stmmac.h"
31 31
32static const struct of_device_id stmmac_dt_ids[] = { 32static const struct of_device_id stmmac_dt_ids[] = {
33#ifdef CONFIG_DWMAC_SUNXI
34 { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
35#endif
33 /* SoC specific glue layers should come before generic bindings */ 36 /* SoC specific glue layers should come before generic bindings */
34 { .compatible = "st,spear600-gmac"}, 37 { .compatible = "st,spear600-gmac"},
35 { .compatible = "snps,dwmac-3.610"}, 38 { .compatible = "snps,dwmac-3.610"},