2 * Copyright (C) 2016 Broadcom
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 #include <linux/bcma/bcma.h>
17 #include <linux/brcmphy.h>
18 #include <linux/etherdevice.h>
19 #include <linux/of_address.h>
20 #include <linux/of_mdio.h>
21 #include <linux/of_net.h>
24 #define NICPM_IOMUX_CTRL 0x00000008
26 #define NICPM_IOMUX_CTRL_INIT_VAL 0x3196e000
27 #define NICPM_IOMUX_CTRL_SPD_SHIFT 10
28 #define NICPM_IOMUX_CTRL_SPD_10M 0
29 #define NICPM_IOMUX_CTRL_SPD_100M 1
30 #define NICPM_IOMUX_CTRL_SPD_1000M 2
32 static u32
platform_bgmac_read(struct bgmac
*bgmac
, u16 offset
)
34 return readl(bgmac
->plat
.base
+ offset
);
37 static void platform_bgmac_write(struct bgmac
*bgmac
, u16 offset
, u32 value
)
39 writel(value
, bgmac
->plat
.base
+ offset
);
42 static u32
platform_bgmac_idm_read(struct bgmac
*bgmac
, u16 offset
)
44 return readl(bgmac
->plat
.idm_base
+ offset
);
47 static void platform_bgmac_idm_write(struct bgmac
*bgmac
, u16 offset
, u32 value
)
49 return writel(value
, bgmac
->plat
.idm_base
+ offset
);
52 static bool platform_bgmac_clk_enabled(struct bgmac
*bgmac
)
54 if ((bgmac_idm_read(bgmac
, BCMA_IOCTL
) &
55 (BCMA_IOCTL_CLK
| BCMA_IOCTL_FGC
)) != BCMA_IOCTL_CLK
)
57 if (bgmac_idm_read(bgmac
, BCMA_RESET_CTL
) & BCMA_RESET_CTL_RESET
)
62 static void platform_bgmac_clk_enable(struct bgmac
*bgmac
, u32 flags
)
64 bgmac_idm_write(bgmac
, BCMA_IOCTL
,
65 (BCMA_IOCTL_CLK
| BCMA_IOCTL_FGC
| flags
));
66 bgmac_idm_read(bgmac
, BCMA_IOCTL
);
68 bgmac_idm_write(bgmac
, BCMA_RESET_CTL
, 0);
69 bgmac_idm_read(bgmac
, BCMA_RESET_CTL
);
72 bgmac_idm_write(bgmac
, BCMA_IOCTL
, (BCMA_IOCTL_CLK
| flags
));
73 bgmac_idm_read(bgmac
, BCMA_IOCTL
);
77 static void platform_bgmac_cco_ctl_maskset(struct bgmac
*bgmac
, u32 offset
,
80 /* This shouldn't be encountered */
84 static u32
platform_bgmac_get_bus_clock(struct bgmac
*bgmac
)
86 /* This shouldn't be encountered */
92 static void platform_bgmac_cmn_maskset32(struct bgmac
*bgmac
, u16 offset
,
95 /* This shouldn't be encountered */
99 static void bgmac_nicpm_speed_set(struct net_device
*net_dev
)
101 struct bgmac
*bgmac
= netdev_priv(net_dev
);
104 if (!bgmac
->plat
.nicpm_base
)
107 val
= NICPM_IOMUX_CTRL_INIT_VAL
;
108 switch (bgmac
->net_dev
->phydev
->speed
) {
110 netdev_err(net_dev
, "Unsupported speed. Defaulting to 1000Mb\n");
112 val
|= NICPM_IOMUX_CTRL_SPD_1000M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
115 val
|= NICPM_IOMUX_CTRL_SPD_100M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
118 val
|= NICPM_IOMUX_CTRL_SPD_10M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
122 writel(val
, bgmac
->plat
.nicpm_base
+ NICPM_IOMUX_CTRL
);
124 bgmac_adjust_link(bgmac
->net_dev
);
127 static int platform_phy_connect(struct bgmac
*bgmac
)
129 struct phy_device
*phy_dev
;
131 if (bgmac
->plat
.nicpm_base
)
132 phy_dev
= of_phy_get_and_connect(bgmac
->net_dev
,
134 bgmac_nicpm_speed_set
);
136 phy_dev
= of_phy_get_and_connect(bgmac
->net_dev
,
140 dev_err(bgmac
->dev
, "PHY connection failed\n");
147 static int bgmac_probe(struct platform_device
*pdev
)
149 struct device_node
*np
= pdev
->dev
.of_node
;
151 struct resource
*regs
;
154 bgmac
= bgmac_alloc(&pdev
->dev
);
158 platform_set_drvdata(pdev
, bgmac
);
160 /* Set the features of the 4707 family */
161 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
162 bgmac
->feature_flags
|= BGMAC_FEAT_NO_RESET
;
163 bgmac
->feature_flags
|= BGMAC_FEAT_CMDCFG_SR_REV4
;
164 bgmac
->feature_flags
|= BGMAC_FEAT_TX_MASK_SETUP
;
165 bgmac
->feature_flags
|= BGMAC_FEAT_RX_MASK_SETUP
;
167 bgmac
->dev
= &pdev
->dev
;
168 bgmac
->dma_dev
= &pdev
->dev
;
170 mac_addr
= of_get_mac_address(np
);
172 ether_addr_copy(bgmac
->net_dev
->dev_addr
, mac_addr
);
174 dev_warn(&pdev
->dev
, "MAC address not present in device tree\n");
176 bgmac
->irq
= platform_get_irq(pdev
, 0);
177 if (bgmac
->irq
< 0) {
178 dev_err(&pdev
->dev
, "Unable to obtain IRQ\n");
182 regs
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "amac_base");
184 dev_err(&pdev
->dev
, "Unable to obtain base resource\n");
188 bgmac
->plat
.base
= devm_ioremap_resource(&pdev
->dev
, regs
);
189 if (IS_ERR(bgmac
->plat
.base
))
190 return PTR_ERR(bgmac
->plat
.base
);
192 regs
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "idm_base");
194 dev_err(&pdev
->dev
, "Unable to obtain idm resource\n");
198 bgmac
->plat
.idm_base
= devm_ioremap_resource(&pdev
->dev
, regs
);
199 if (IS_ERR(bgmac
->plat
.idm_base
))
200 return PTR_ERR(bgmac
->plat
.idm_base
);
202 regs
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "nicpm_base");
204 bgmac
->plat
.nicpm_base
= devm_ioremap_resource(&pdev
->dev
,
206 if (IS_ERR(bgmac
->plat
.nicpm_base
))
207 return PTR_ERR(bgmac
->plat
.nicpm_base
);
210 bgmac
->read
= platform_bgmac_read
;
211 bgmac
->write
= platform_bgmac_write
;
212 bgmac
->idm_read
= platform_bgmac_idm_read
;
213 bgmac
->idm_write
= platform_bgmac_idm_write
;
214 bgmac
->clk_enabled
= platform_bgmac_clk_enabled
;
215 bgmac
->clk_enable
= platform_bgmac_clk_enable
;
216 bgmac
->cco_ctl_maskset
= platform_bgmac_cco_ctl_maskset
;
217 bgmac
->get_bus_clock
= platform_bgmac_get_bus_clock
;
218 bgmac
->cmn_maskset32
= platform_bgmac_cmn_maskset32
;
219 if (of_parse_phandle(np
, "phy-handle", 0)) {
220 bgmac
->phy_connect
= platform_phy_connect
;
222 bgmac
->phy_connect
= bgmac_phy_connect_direct
;
223 bgmac
->feature_flags
|= BGMAC_FEAT_FORCE_SPEED_2500
;
226 return bgmac_enet_probe(bgmac
);
229 static int bgmac_remove(struct platform_device
*pdev
)
231 struct bgmac
*bgmac
= platform_get_drvdata(pdev
);
233 bgmac_enet_remove(bgmac
);
238 static const struct of_device_id bgmac_of_enet_match
[] = {
239 {.compatible
= "brcm,amac",},
240 {.compatible
= "brcm,nsp-amac",},
241 {.compatible
= "brcm,ns2-amac",},
245 MODULE_DEVICE_TABLE(of
, bgmac_of_enet_match
);
247 static struct platform_driver bgmac_enet_driver
= {
249 .name
= "bgmac-enet",
250 .of_match_table
= bgmac_of_enet_match
,
252 .probe
= bgmac_probe
,
253 .remove
= bgmac_remove
,
256 module_platform_driver(bgmac_enet_driver
);
257 MODULE_LICENSE("GPL");