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_PADRING_CFG 0x00000004
25 #define NICPM_IOMUX_CTRL 0x00000008
27 #define NICPM_PADRING_CFG_INIT_VAL 0x74000000
28 #define NICPM_IOMUX_CTRL_INIT_VAL_AX 0x21880000
30 #define NICPM_IOMUX_CTRL_INIT_VAL 0x3196e000
31 #define NICPM_IOMUX_CTRL_SPD_SHIFT 10
32 #define NICPM_IOMUX_CTRL_SPD_10M 0
33 #define NICPM_IOMUX_CTRL_SPD_100M 1
34 #define NICPM_IOMUX_CTRL_SPD_1000M 2
36 static u32
platform_bgmac_read(struct bgmac
*bgmac
, u16 offset
)
38 return readl(bgmac
->plat
.base
+ offset
);
41 static void platform_bgmac_write(struct bgmac
*bgmac
, u16 offset
, u32 value
)
43 writel(value
, bgmac
->plat
.base
+ offset
);
46 static u32
platform_bgmac_idm_read(struct bgmac
*bgmac
, u16 offset
)
48 return readl(bgmac
->plat
.idm_base
+ offset
);
51 static void platform_bgmac_idm_write(struct bgmac
*bgmac
, u16 offset
, u32 value
)
53 writel(value
, bgmac
->plat
.idm_base
+ offset
);
56 static bool platform_bgmac_clk_enabled(struct bgmac
*bgmac
)
58 if (!bgmac
->plat
.idm_base
)
61 if ((bgmac_idm_read(bgmac
, BCMA_IOCTL
) & BGMAC_CLK_EN
) != BGMAC_CLK_EN
)
63 if (bgmac_idm_read(bgmac
, BCMA_RESET_CTL
) & BCMA_RESET_CTL_RESET
)
68 static void platform_bgmac_clk_enable(struct bgmac
*bgmac
, u32 flags
)
72 if (!bgmac
->plat
.idm_base
)
75 /* The Reset Control register only contains a single bit to show if the
76 * controller is currently in reset. Do a sanity check here, just in
77 * case the bootloader happened to leave the device in reset.
79 val
= bgmac_idm_read(bgmac
, BCMA_RESET_CTL
);
81 bgmac_idm_write(bgmac
, BCMA_RESET_CTL
, 0);
82 bgmac_idm_read(bgmac
, BCMA_RESET_CTL
);
86 val
= bgmac_idm_read(bgmac
, BCMA_IOCTL
);
87 /* Some bits of BCMA_IOCTL set by HW/ATF and should not change */
88 val
|= flags
& ~(BGMAC_AWCACHE
| BGMAC_ARCACHE
| BGMAC_AWUSER
|
91 bgmac_idm_write(bgmac
, BCMA_IOCTL
, val
);
92 bgmac_idm_read(bgmac
, BCMA_IOCTL
);
96 static void platform_bgmac_cco_ctl_maskset(struct bgmac
*bgmac
, u32 offset
,
99 /* This shouldn't be encountered */
103 static u32
platform_bgmac_get_bus_clock(struct bgmac
*bgmac
)
105 /* This shouldn't be encountered */
111 static void platform_bgmac_cmn_maskset32(struct bgmac
*bgmac
, u16 offset
,
114 /* This shouldn't be encountered */
118 static void bgmac_nicpm_speed_set(struct net_device
*net_dev
)
120 struct bgmac
*bgmac
= netdev_priv(net_dev
);
123 if (!bgmac
->plat
.nicpm_base
)
126 /* SET RGMII IO CONFIG */
127 writel(NICPM_PADRING_CFG_INIT_VAL
,
128 bgmac
->plat
.nicpm_base
+ NICPM_PADRING_CFG
);
130 val
= NICPM_IOMUX_CTRL_INIT_VAL
;
131 switch (bgmac
->net_dev
->phydev
->speed
) {
133 netdev_err(net_dev
, "Unsupported speed. Defaulting to 1000Mb\n");
136 val
|= NICPM_IOMUX_CTRL_SPD_1000M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
139 val
|= NICPM_IOMUX_CTRL_SPD_100M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
142 val
|= NICPM_IOMUX_CTRL_SPD_10M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
146 writel(val
, bgmac
->plat
.nicpm_base
+ NICPM_IOMUX_CTRL
);
148 bgmac_adjust_link(bgmac
->net_dev
);
151 static int platform_phy_connect(struct bgmac
*bgmac
)
153 struct phy_device
*phy_dev
;
155 if (bgmac
->plat
.nicpm_base
)
156 phy_dev
= of_phy_get_and_connect(bgmac
->net_dev
,
158 bgmac_nicpm_speed_set
);
160 phy_dev
= of_phy_get_and_connect(bgmac
->net_dev
,
164 dev_err(bgmac
->dev
, "PHY connection failed\n");
171 static int bgmac_probe(struct platform_device
*pdev
)
173 struct device_node
*np
= pdev
->dev
.of_node
;
175 struct resource
*regs
;
178 bgmac
= bgmac_alloc(&pdev
->dev
);
182 platform_set_drvdata(pdev
, bgmac
);
184 /* Set the features of the 4707 family */
185 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
186 bgmac
->feature_flags
|= BGMAC_FEAT_NO_RESET
;
187 bgmac
->feature_flags
|= BGMAC_FEAT_CMDCFG_SR_REV4
;
188 bgmac
->feature_flags
|= BGMAC_FEAT_TX_MASK_SETUP
;
189 bgmac
->feature_flags
|= BGMAC_FEAT_RX_MASK_SETUP
;
190 bgmac
->feature_flags
|= BGMAC_FEAT_IDM_MASK
;
192 bgmac
->dev
= &pdev
->dev
;
193 bgmac
->dma_dev
= &pdev
->dev
;
195 mac_addr
= of_get_mac_address(np
);
196 if (!IS_ERR(mac_addr
))
197 ether_addr_copy(bgmac
->net_dev
->dev_addr
, mac_addr
);
199 dev_warn(&pdev
->dev
, "MAC address not present in device tree\n");
201 bgmac
->irq
= platform_get_irq(pdev
, 0);
206 devm_platform_ioremap_resource_byname(pdev
, "amac_base");
207 if (IS_ERR(bgmac
->plat
.base
))
208 return PTR_ERR(bgmac
->plat
.base
);
210 regs
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "idm_base");
212 bgmac
->plat
.idm_base
= devm_ioremap_resource(&pdev
->dev
, regs
);
213 if (IS_ERR(bgmac
->plat
.idm_base
))
214 return PTR_ERR(bgmac
->plat
.idm_base
);
215 bgmac
->feature_flags
&= ~BGMAC_FEAT_IDM_MASK
;
218 regs
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "nicpm_base");
220 bgmac
->plat
.nicpm_base
= devm_ioremap_resource(&pdev
->dev
,
222 if (IS_ERR(bgmac
->plat
.nicpm_base
))
223 return PTR_ERR(bgmac
->plat
.nicpm_base
);
226 bgmac
->read
= platform_bgmac_read
;
227 bgmac
->write
= platform_bgmac_write
;
228 bgmac
->idm_read
= platform_bgmac_idm_read
;
229 bgmac
->idm_write
= platform_bgmac_idm_write
;
230 bgmac
->clk_enabled
= platform_bgmac_clk_enabled
;
231 bgmac
->clk_enable
= platform_bgmac_clk_enable
;
232 bgmac
->cco_ctl_maskset
= platform_bgmac_cco_ctl_maskset
;
233 bgmac
->get_bus_clock
= platform_bgmac_get_bus_clock
;
234 bgmac
->cmn_maskset32
= platform_bgmac_cmn_maskset32
;
235 if (of_parse_phandle(np
, "phy-handle", 0)) {
236 bgmac
->phy_connect
= platform_phy_connect
;
238 bgmac
->phy_connect
= bgmac_phy_connect_direct
;
239 bgmac
->feature_flags
|= BGMAC_FEAT_FORCE_SPEED_2500
;
242 return bgmac_enet_probe(bgmac
);
245 static int bgmac_remove(struct platform_device
*pdev
)
247 struct bgmac
*bgmac
= platform_get_drvdata(pdev
);
249 bgmac_enet_remove(bgmac
);
255 static int bgmac_suspend(struct device
*dev
)
257 struct bgmac
*bgmac
= dev_get_drvdata(dev
);
259 return bgmac_enet_suspend(bgmac
);
262 static int bgmac_resume(struct device
*dev
)
264 struct bgmac
*bgmac
= dev_get_drvdata(dev
);
266 return bgmac_enet_resume(bgmac
);
269 static const struct dev_pm_ops bgmac_pm_ops
= {
270 .suspend
= bgmac_suspend
,
271 .resume
= bgmac_resume
274 #define BGMAC_PM_OPS (&bgmac_pm_ops)
276 #define BGMAC_PM_OPS NULL
277 #endif /* CONFIG_PM */
279 static const struct of_device_id bgmac_of_enet_match
[] = {
280 {.compatible
= "brcm,amac",},
281 {.compatible
= "brcm,nsp-amac",},
282 {.compatible
= "brcm,ns2-amac",},
286 MODULE_DEVICE_TABLE(of
, bgmac_of_enet_match
);
288 static struct platform_driver bgmac_enet_driver
= {
290 .name
= "bgmac-enet",
291 .of_match_table
= bgmac_of_enet_match
,
294 .probe
= bgmac_probe
,
295 .remove
= bgmac_remove
,
298 module_platform_driver(bgmac_enet_driver
);
299 MODULE_LICENSE("GPL");