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
) & BGMAC_CLK_EN
) != BGMAC_CLK_EN
)
56 if (bgmac_idm_read(bgmac
, BCMA_RESET_CTL
) & BCMA_RESET_CTL_RESET
)
61 static void platform_bgmac_clk_enable(struct bgmac
*bgmac
, u32 flags
)
65 /* The Reset Control register only contains a single bit to show if the
66 * controller is currently in reset. Do a sanity check here, just in
67 * case the bootloader happened to leave the device in reset.
69 val
= bgmac_idm_read(bgmac
, BCMA_RESET_CTL
);
71 bgmac_idm_write(bgmac
, BCMA_RESET_CTL
, 0);
72 bgmac_idm_read(bgmac
, BCMA_RESET_CTL
);
76 val
= bgmac_idm_read(bgmac
, BCMA_IOCTL
);
77 /* Some bits of BCMA_IOCTL set by HW/ATF and should not change */
78 val
|= flags
& ~(BGMAC_AWCACHE
| BGMAC_ARCACHE
| BGMAC_AWUSER
|
81 bgmac_idm_write(bgmac
, BCMA_IOCTL
, val
);
82 bgmac_idm_read(bgmac
, BCMA_IOCTL
);
86 static void platform_bgmac_cco_ctl_maskset(struct bgmac
*bgmac
, u32 offset
,
89 /* This shouldn't be encountered */
93 static u32
platform_bgmac_get_bus_clock(struct bgmac
*bgmac
)
95 /* This shouldn't be encountered */
101 static void platform_bgmac_cmn_maskset32(struct bgmac
*bgmac
, u16 offset
,
104 /* This shouldn't be encountered */
108 static void bgmac_nicpm_speed_set(struct net_device
*net_dev
)
110 struct bgmac
*bgmac
= netdev_priv(net_dev
);
113 if (!bgmac
->plat
.nicpm_base
)
116 val
= NICPM_IOMUX_CTRL_INIT_VAL
;
117 switch (bgmac
->net_dev
->phydev
->speed
) {
119 netdev_err(net_dev
, "Unsupported speed. Defaulting to 1000Mb\n");
121 val
|= NICPM_IOMUX_CTRL_SPD_1000M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
124 val
|= NICPM_IOMUX_CTRL_SPD_100M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
127 val
|= NICPM_IOMUX_CTRL_SPD_10M
<< NICPM_IOMUX_CTRL_SPD_SHIFT
;
131 writel(val
, bgmac
->plat
.nicpm_base
+ NICPM_IOMUX_CTRL
);
133 bgmac_adjust_link(bgmac
->net_dev
);
136 static int platform_phy_connect(struct bgmac
*bgmac
)
138 struct phy_device
*phy_dev
;
140 if (bgmac
->plat
.nicpm_base
)
141 phy_dev
= of_phy_get_and_connect(bgmac
->net_dev
,
143 bgmac_nicpm_speed_set
);
145 phy_dev
= of_phy_get_and_connect(bgmac
->net_dev
,
149 dev_err(bgmac
->dev
, "PHY connection failed\n");
156 static int bgmac_probe(struct platform_device
*pdev
)
158 struct device_node
*np
= pdev
->dev
.of_node
;
160 struct resource
*regs
;
163 bgmac
= bgmac_alloc(&pdev
->dev
);
167 platform_set_drvdata(pdev
, bgmac
);
169 /* Set the features of the 4707 family */
170 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
171 bgmac
->feature_flags
|= BGMAC_FEAT_NO_RESET
;
172 bgmac
->feature_flags
|= BGMAC_FEAT_CMDCFG_SR_REV4
;
173 bgmac
->feature_flags
|= BGMAC_FEAT_TX_MASK_SETUP
;
174 bgmac
->feature_flags
|= BGMAC_FEAT_RX_MASK_SETUP
;
176 bgmac
->dev
= &pdev
->dev
;
177 bgmac
->dma_dev
= &pdev
->dev
;
179 mac_addr
= of_get_mac_address(np
);
181 ether_addr_copy(bgmac
->net_dev
->dev_addr
, mac_addr
);
183 dev_warn(&pdev
->dev
, "MAC address not present in device tree\n");
185 bgmac
->irq
= platform_get_irq(pdev
, 0);
186 if (bgmac
->irq
< 0) {
187 dev_err(&pdev
->dev
, "Unable to obtain IRQ\n");
191 regs
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "amac_base");
193 dev_err(&pdev
->dev
, "Unable to obtain base resource\n");
197 bgmac
->plat
.base
= devm_ioremap_resource(&pdev
->dev
, regs
);
198 if (IS_ERR(bgmac
->plat
.base
))
199 return PTR_ERR(bgmac
->plat
.base
);
201 regs
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "idm_base");
203 dev_err(&pdev
->dev
, "Unable to obtain idm resource\n");
207 bgmac
->plat
.idm_base
= devm_ioremap_resource(&pdev
->dev
, regs
);
208 if (IS_ERR(bgmac
->plat
.idm_base
))
209 return PTR_ERR(bgmac
->plat
.idm_base
);
211 regs
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "nicpm_base");
213 bgmac
->plat
.nicpm_base
= devm_ioremap_resource(&pdev
->dev
,
215 if (IS_ERR(bgmac
->plat
.nicpm_base
))
216 return PTR_ERR(bgmac
->plat
.nicpm_base
);
219 bgmac
->read
= platform_bgmac_read
;
220 bgmac
->write
= platform_bgmac_write
;
221 bgmac
->idm_read
= platform_bgmac_idm_read
;
222 bgmac
->idm_write
= platform_bgmac_idm_write
;
223 bgmac
->clk_enabled
= platform_bgmac_clk_enabled
;
224 bgmac
->clk_enable
= platform_bgmac_clk_enable
;
225 bgmac
->cco_ctl_maskset
= platform_bgmac_cco_ctl_maskset
;
226 bgmac
->get_bus_clock
= platform_bgmac_get_bus_clock
;
227 bgmac
->cmn_maskset32
= platform_bgmac_cmn_maskset32
;
228 if (of_parse_phandle(np
, "phy-handle", 0)) {
229 bgmac
->phy_connect
= platform_phy_connect
;
231 bgmac
->phy_connect
= bgmac_phy_connect_direct
;
232 bgmac
->feature_flags
|= BGMAC_FEAT_FORCE_SPEED_2500
;
235 return bgmac_enet_probe(bgmac
);
238 static int bgmac_remove(struct platform_device
*pdev
)
240 struct bgmac
*bgmac
= platform_get_drvdata(pdev
);
242 bgmac_enet_remove(bgmac
);
247 static const struct of_device_id bgmac_of_enet_match
[] = {
248 {.compatible
= "brcm,amac",},
249 {.compatible
= "brcm,nsp-amac",},
250 {.compatible
= "brcm,ns2-amac",},
254 MODULE_DEVICE_TABLE(of
, bgmac_of_enet_match
);
256 static struct platform_driver bgmac_enet_driver
= {
258 .name
= "bgmac-enet",
259 .of_match_table
= bgmac_of_enet_match
,
261 .probe
= bgmac_probe
,
262 .remove
= bgmac_remove
,
265 module_platform_driver(bgmac_enet_driver
);
266 MODULE_LICENSE("GPL");