aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
diff options
context:
space:
mode:
authorLey Foon Tan <lftan@altera.com>2014-08-20 02:33:33 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-22 15:33:48 -0400
commitb4834c86e11bafc2bf7d3af6a6a5d9ea48b54b41 (patch)
treebc0c1a85f50ffa30ec39c80e8add7d162c91a82f /drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
parent6e1d0b8988188956dac091441c1492a79a342666 (diff)
net: stmmac: add fix_mac_speed support for socfpga
This patch adds fix_mac_speed() support for Altera socfpga Ethernet controller. Emac splitter is a soft IP core in FPGA system that converts GMII interface from Synopsys mac to RGMII/SGMII interface. This splitter core is an optional IP if user would like to use RGMII/SGMII interface in their system. Software needs to update a register in splitter core when there is speed change. Signed-off-by: Ley Foon Tan <lftan@altera.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index ec632e666c56..cd613d711108 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -17,6 +17,7 @@
17 17
18#include <linux/mfd/syscon.h> 18#include <linux/mfd/syscon.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h>
20#include <linux/of_net.h> 21#include <linux/of_net.h>
21#include <linux/phy.h> 22#include <linux/phy.h>
22#include <linux/regmap.h> 23#include <linux/regmap.h>
@@ -30,6 +31,12 @@
30#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 31#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
31#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003 32#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
32 33
34#define EMAC_SPLITTER_CTRL_REG 0x0
35#define EMAC_SPLITTER_CTRL_SPEED_MASK 0x3
36#define EMAC_SPLITTER_CTRL_SPEED_10 0x2
37#define EMAC_SPLITTER_CTRL_SPEED_100 0x3
38#define EMAC_SPLITTER_CTRL_SPEED_1000 0x0
39
33struct socfpga_dwmac { 40struct socfpga_dwmac {
34 int interface; 41 int interface;
35 u32 reg_offset; 42 u32 reg_offset;
@@ -37,14 +44,46 @@ struct socfpga_dwmac {
37 struct device *dev; 44 struct device *dev;
38 struct regmap *sys_mgr_base_addr; 45 struct regmap *sys_mgr_base_addr;
39 struct reset_control *stmmac_rst; 46 struct reset_control *stmmac_rst;
47 void __iomem *splitter_base;
40}; 48};
41 49
50static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
51{
52 struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
53 void __iomem *splitter_base = dwmac->splitter_base;
54 u32 val;
55
56 if (!splitter_base)
57 return;
58
59 val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG);
60 val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK;
61
62 switch (speed) {
63 case 1000:
64 val |= EMAC_SPLITTER_CTRL_SPEED_1000;
65 break;
66 case 100:
67 val |= EMAC_SPLITTER_CTRL_SPEED_100;
68 break;
69 case 10:
70 val |= EMAC_SPLITTER_CTRL_SPEED_10;
71 break;
72 default:
73 return;
74 }
75
76 writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG);
77}
78
42static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) 79static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
43{ 80{
44 struct device_node *np = dev->of_node; 81 struct device_node *np = dev->of_node;
45 struct regmap *sys_mgr_base_addr; 82 struct regmap *sys_mgr_base_addr;
46 u32 reg_offset, reg_shift; 83 u32 reg_offset, reg_shift;
47 int ret; 84 int ret;
85 struct device_node *np_splitter;
86 struct resource res_splitter;
48 87
49 dwmac->stmmac_rst = devm_reset_control_get(dev, 88 dwmac->stmmac_rst = devm_reset_control_get(dev,
50 STMMAC_RESOURCE_NAME); 89 STMMAC_RESOURCE_NAME);
@@ -73,6 +112,21 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
73 return -EINVAL; 112 return -EINVAL;
74 } 113 }
75 114
115 np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0);
116 if (np_splitter) {
117 if (of_address_to_resource(np_splitter, 0, &res_splitter)) {
118 dev_info(dev, "Missing emac splitter address\n");
119 return -EINVAL;
120 }
121
122 dwmac->splitter_base = (void *)devm_ioremap_resource(dev,
123 &res_splitter);
124 if (!dwmac->splitter_base) {
125 dev_info(dev, "Failed to mapping emac splitter\n");
126 return -EINVAL;
127 }
128 }
129
76 dwmac->reg_offset = reg_offset; 130 dwmac->reg_offset = reg_offset;
77 dwmac->reg_shift = reg_shift; 131 dwmac->reg_shift = reg_shift;
78 dwmac->sys_mgr_base_addr = sys_mgr_base_addr; 132 dwmac->sys_mgr_base_addr = sys_mgr_base_addr;
@@ -91,6 +145,7 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
91 145
92 switch (phymode) { 146 switch (phymode) {
93 case PHY_INTERFACE_MODE_RGMII: 147 case PHY_INTERFACE_MODE_RGMII:
148 case PHY_INTERFACE_MODE_RGMII_ID:
94 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; 149 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
95 break; 150 break;
96 case PHY_INTERFACE_MODE_MII: 151 case PHY_INTERFACE_MODE_MII:
@@ -102,6 +157,13 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
102 return -EINVAL; 157 return -EINVAL;
103 } 158 }
104 159
160 /* Overwrite val to GMII if splitter core is enabled. The phymode here
161 * is the actual phy mode on phy hardware, but phy interface from
162 * EMAC core is GMII.
163 */
164 if (dwmac->splitter_base)
165 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
166
105 regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); 167 regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
106 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); 168 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
107 ctrl |= val << reg_shift; 169 ctrl |= val << reg_shift;
@@ -196,4 +258,5 @@ const struct stmmac_of_data socfpga_gmac_data = {
196 .setup = socfpga_dwmac_probe, 258 .setup = socfpga_dwmac_probe,
197 .init = socfpga_dwmac_init, 259 .init = socfpga_dwmac_init,
198 .exit = socfpga_dwmac_exit, 260 .exit = socfpga_dwmac_exit,
261 .fix_mac_speed = socfpga_dwmac_fix_mac_speed,
199}; 262};