Skip to content

Commit 801d233

Browse files
Dinh Nguyendavem330
authored andcommitted
net: stmmac: Add SOCFPGA glue driver
Like the STi and sunxi series SOCs, Altera's SOCFPGA also needs a glue layer on top of the Synopsys gmac IP. This patch adds the platform driver for the glue layer which configures the IP before the generic STMMAC driver takes over. Signed-off-by: Dinh Nguyen <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bfd2793 commit 801d233

File tree

5 files changed

+147
-0
lines changed

5 files changed

+147
-0
lines changed

drivers/net/ethernet/stmicro/stmmac/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ config STMMAC_PLATFORM
2626

2727
If unsure, say N.
2828

29+
config DWMAC_SOCFPGA
30+
bool "SOCFPGA dwmac support"
31+
depends on STMMAC_PLATFORM && MFD_SYSCON && (ARCH_SOCFPGA || COMPILE_TEST)
32+
help
33+
Support for ethernet controller on Altera SOCFPGA
34+
35+
This selects the Altera SOCFPGA SoC glue layer support
36+
for the stmmac device driver. This driver is used for
37+
arria5 and cyclone5 FPGA SoCs.
38+
2939
config DWMAC_SUNXI
3040
bool "Allwinner GMAC support"
3141
depends on STMMAC_PLATFORM && ARCH_SUNXI

drivers/net/ethernet/stmicro/stmmac/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
33
stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
44
stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
55
stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o
6+
stmmac-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o
67
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
78
chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
89
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/* Copyright Altera Corporation (C) 2014. All rights reserved.
2+
*
3+
* This program is free software; you can redistribute it and/or modify
4+
* it under the terms of the GNU General Public License, version 2,
5+
* as published by the Free Software Foundation.
6+
*
7+
* This program is distributed in the hope that it will be useful,
8+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
* GNU General Public License for more details.
11+
*
12+
* You should have received a copy of the GNU General Public License
13+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
14+
*
15+
* Adopted from dwmac-sti.c
16+
*/
17+
18+
#include <linux/mfd/syscon.h>
19+
#include <linux/of.h>
20+
#include <linux/of_net.h>
21+
#include <linux/phy.h>
22+
#include <linux/regmap.h>
23+
#include <linux/stmmac.h>
24+
25+
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
26+
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
27+
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
28+
#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
29+
#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
30+
31+
struct socfpga_dwmac {
32+
int interface;
33+
u32 reg_offset;
34+
u32 reg_shift;
35+
struct device *dev;
36+
struct regmap *sys_mgr_base_addr;
37+
};
38+
39+
static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
40+
{
41+
struct device_node *np = dev->of_node;
42+
struct regmap *sys_mgr_base_addr;
43+
u32 reg_offset, reg_shift;
44+
int ret;
45+
46+
dwmac->interface = of_get_phy_mode(np);
47+
48+
sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
49+
if (IS_ERR(sys_mgr_base_addr)) {
50+
dev_info(dev, "No sysmgr-syscon node found\n");
51+
return PTR_ERR(sys_mgr_base_addr);
52+
}
53+
54+
ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 1, &reg_offset);
55+
if (ret) {
56+
dev_info(dev, "Could not read reg_offset from sysmgr-syscon!\n");
57+
return -EINVAL;
58+
}
59+
60+
ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 2, &reg_shift);
61+
if (ret) {
62+
dev_info(dev, "Could not read reg_shift from sysmgr-syscon!\n");
63+
return -EINVAL;
64+
}
65+
66+
dwmac->reg_offset = reg_offset;
67+
dwmac->reg_shift = reg_shift;
68+
dwmac->sys_mgr_base_addr = sys_mgr_base_addr;
69+
dwmac->dev = dev;
70+
71+
return 0;
72+
}
73+
74+
static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
75+
{
76+
struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr;
77+
int phymode = dwmac->interface;
78+
u32 reg_offset = dwmac->reg_offset;
79+
u32 reg_shift = dwmac->reg_shift;
80+
u32 ctrl, val;
81+
82+
switch (phymode) {
83+
case PHY_INTERFACE_MODE_RGMII:
84+
val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
85+
break;
86+
case PHY_INTERFACE_MODE_MII:
87+
case PHY_INTERFACE_MODE_GMII:
88+
val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
89+
break;
90+
default:
91+
dev_err(dwmac->dev, "bad phy mode %d\n", phymode);
92+
return -EINVAL;
93+
}
94+
95+
regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
96+
ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
97+
ctrl |= val << reg_shift;
98+
99+
regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
100+
return 0;
101+
}
102+
103+
static void *socfpga_dwmac_probe(struct platform_device *pdev)
104+
{
105+
struct device *dev = &pdev->dev;
106+
int ret;
107+
struct socfpga_dwmac *dwmac;
108+
109+
dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
110+
if (!dwmac)
111+
return ERR_PTR(-ENOMEM);
112+
113+
ret = socfpga_dwmac_parse_data(dwmac, dev);
114+
if (ret) {
115+
dev_err(dev, "Unable to parse OF data\n");
116+
return ERR_PTR(ret);
117+
}
118+
119+
ret = socfpga_dwmac_setup(dwmac);
120+
if (ret) {
121+
dev_err(dev, "couldn't setup SoC glue (%d)\n", ret);
122+
return ERR_PTR(ret);
123+
}
124+
125+
return dwmac;
126+
}
127+
128+
const struct stmmac_of_data socfpga_gmac_data = {
129+
.setup = socfpga_dwmac_probe,
130+
};

drivers/net/ethernet/stmicro/stmmac/stmmac.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ extern const struct stmmac_of_data sun7i_gmac_data;
136136
#ifdef CONFIG_DWMAC_STI
137137
extern const struct stmmac_of_data sti_gmac_data;
138138
#endif
139+
#ifdef CONFIG_DWMAC_SOCFPGA
140+
extern const struct stmmac_of_data socfpga_gmac_data;
141+
#endif
139142
extern struct platform_driver stmmac_pltfr_driver;
140143
static inline int stmmac_register_platform(void)
141144
{

drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ static const struct of_device_id stmmac_dt_ids[] = {
3737
{ .compatible = "st,stih415-dwmac", .data = &sti_gmac_data},
3838
{ .compatible = "st,stih416-dwmac", .data = &sti_gmac_data},
3939
{ .compatible = "st,stid127-dwmac", .data = &sti_gmac_data},
40+
#endif
41+
#ifdef CONFIG_DWMAC_SOCFPGA
42+
{ .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
4043
#endif
4144
/* SoC specific glue layers should come before generic bindings */
4245
{ .compatible = "st,spear600-gmac"},

0 commit comments

Comments
 (0)