2 * Driver for (BCM4706)? GBit MAC core on BCMA bus.
4 * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
6 * Licensed under the GNU/GPL. See COPYING for details.
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #include <linux/bcma/bcma.h>
12 #include <linux/brcmphy.h>
13 #include <linux/etherdevice.h>
16 static inline bool bgmac_is_bcm4707_family(struct bcma_device
*core
)
18 switch (core
->bus
->chipinfo
.id
) {
19 case BCMA_CHIP_ID_BCM4707
:
20 case BCMA_CHIP_ID_BCM47094
:
21 case BCMA_CHIP_ID_BCM53018
:
28 /**************************************************
30 **************************************************/
32 static u32
bcma_bgmac_read(struct bgmac
*bgmac
, u16 offset
)
34 return bcma_read32(bgmac
->bcma
.core
, offset
);
37 static void bcma_bgmac_write(struct bgmac
*bgmac
, u16 offset
, u32 value
)
39 bcma_write32(bgmac
->bcma
.core
, offset
, value
);
42 static u32
bcma_bgmac_idm_read(struct bgmac
*bgmac
, u16 offset
)
44 return bcma_aread32(bgmac
->bcma
.core
, offset
);
47 static void bcma_bgmac_idm_write(struct bgmac
*bgmac
, u16 offset
, u32 value
)
49 return bcma_awrite32(bgmac
->bcma
.core
, offset
, value
);
52 static bool bcma_bgmac_clk_enabled(struct bgmac
*bgmac
)
54 return bcma_core_is_enabled(bgmac
->bcma
.core
);
57 static void bcma_bgmac_clk_enable(struct bgmac
*bgmac
, u32 flags
)
59 bcma_core_enable(bgmac
->bcma
.core
, flags
);
62 static void bcma_bgmac_cco_ctl_maskset(struct bgmac
*bgmac
, u32 offset
,
65 struct bcma_drv_cc
*cc
= &bgmac
->bcma
.core
->bus
->drv_cc
;
67 bcma_chipco_chipctl_maskset(cc
, offset
, mask
, set
);
70 static u32
bcma_bgmac_get_bus_clock(struct bgmac
*bgmac
)
72 struct bcma_drv_cc
*cc
= &bgmac
->bcma
.core
->bus
->drv_cc
;
74 return bcma_pmu_get_bus_clock(cc
);
77 static void bcma_bgmac_cmn_maskset32(struct bgmac
*bgmac
, u16 offset
, u32 mask
,
80 bcma_maskset32(bgmac
->bcma
.cmn
, offset
, mask
, set
);
83 static const struct bcma_device_id bgmac_bcma_tbl
[] = {
84 BCMA_CORE(BCMA_MANUF_BCM
, BCMA_CORE_4706_MAC_GBIT
,
85 BCMA_ANY_REV
, BCMA_ANY_CLASS
),
86 BCMA_CORE(BCMA_MANUF_BCM
, BCMA_CORE_MAC_GBIT
, BCMA_ANY_REV
,
90 MODULE_DEVICE_TABLE(bcma
, bgmac_bcma_tbl
);
92 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
93 static int bgmac_probe(struct bcma_device
*core
)
95 struct ssb_sprom
*sprom
= &core
->bus
->sprom
;
96 struct mii_bus
*mii_bus
;
101 bgmac
= kzalloc(sizeof(*bgmac
), GFP_KERNEL
);
105 bgmac
->bcma
.core
= core
;
106 bgmac
->dev
= &core
->dev
;
107 bgmac
->dma_dev
= core
->dma_dev
;
108 bgmac
->irq
= core
->irq
;
110 bcma_set_drvdata(core
, bgmac
);
112 switch (core
->core_unit
) {
123 dev_err(bgmac
->dev
, "Unsupported core_unit %d\n",
129 ether_addr_copy(bgmac
->mac_addr
, mac
);
131 /* On BCM4706 we need common core to access PHY */
132 if (core
->id
.id
== BCMA_CORE_4706_MAC_GBIT
&&
133 !core
->bus
->drv_gmac_cmn
.core
) {
134 dev_err(bgmac
->dev
, "GMAC CMN core not found (required for BCM4706)\n");
138 bgmac
->bcma
.cmn
= core
->bus
->drv_gmac_cmn
.core
;
140 switch (core
->core_unit
) {
142 bgmac
->phyaddr
= sprom
->et0phyaddr
;
145 bgmac
->phyaddr
= sprom
->et1phyaddr
;
148 bgmac
->phyaddr
= sprom
->et2phyaddr
;
151 bgmac
->phyaddr
&= BGMAC_PHY_MASK
;
152 if (bgmac
->phyaddr
== BGMAC_PHY_MASK
) {
153 dev_err(bgmac
->dev
, "No PHY found\n");
157 dev_info(bgmac
->dev
, "Found PHY addr: %d%s\n", bgmac
->phyaddr
,
158 bgmac
->phyaddr
== BGMAC_PHY_NOREGS
? " (NOREGS)" : "");
160 if (!bgmac_is_bcm4707_family(core
)) {
161 mii_bus
= bcma_mdio_mii_register(core
, bgmac
->phyaddr
);
162 if (IS_ERR(mii_bus
)) {
163 err
= PTR_ERR(mii_bus
);
167 bgmac
->mii_bus
= mii_bus
;
170 if (core
->bus
->hosttype
== BCMA_HOSTTYPE_PCI
) {
171 dev_err(bgmac
->dev
, "PCI setup not implemented\n");
176 bgmac
->has_robosw
= !!(core
->bus
->sprom
.boardflags_lo
&
178 if (bgmac
->has_robosw
)
179 dev_warn(bgmac
->dev
, "Support for Roboswitch not implemented\n");
181 if (core
->bus
->sprom
.boardflags_lo
& BGMAC_BFL_ENETADM
)
182 dev_warn(bgmac
->dev
, "Support for ADMtek ethernet switch not implemented\n");
185 switch (core
->bus
->chipinfo
.id
) {
186 case BCMA_CHIP_ID_BCM5357
:
187 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
188 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
189 bgmac
->feature_flags
|= BGMAC_FEAT_FLW_CTRL1
;
190 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_PHY
;
191 if (core
->bus
->chipinfo
.pkg
== BCMA_PKG_ID_BCM47186
) {
192 bgmac
->feature_flags
|= BGMAC_FEAT_IOST_ATTACHED
;
193 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_RGMII
;
195 if (core
->bus
->chipinfo
.pkg
== BCMA_PKG_ID_BCM5358
)
196 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_EPHYRMII
;
198 case BCMA_CHIP_ID_BCM53572
:
199 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
200 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
201 bgmac
->feature_flags
|= BGMAC_FEAT_FLW_CTRL1
;
202 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_PHY
;
203 if (core
->bus
->chipinfo
.pkg
== BCMA_PKG_ID_BCM47188
) {
204 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_RGMII
;
205 bgmac
->feature_flags
|= BGMAC_FEAT_IOST_ATTACHED
;
208 case BCMA_CHIP_ID_BCM4749
:
209 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
210 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
211 bgmac
->feature_flags
|= BGMAC_FEAT_FLW_CTRL1
;
212 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_PHY
;
213 if (core
->bus
->chipinfo
.pkg
== 10) {
214 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_RGMII
;
215 bgmac
->feature_flags
|= BGMAC_FEAT_IOST_ATTACHED
;
218 case BCMA_CHIP_ID_BCM4716
:
219 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
221 case BCMA_CHIP_ID_BCM47162
:
222 bgmac
->feature_flags
|= BGMAC_FEAT_FLW_CTRL2
;
223 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
226 case BCMA_CHIP_ID_BCM4707
:
227 case BCMA_CHIP_ID_BCM47094
:
228 case BCMA_CHIP_ID_BCM53018
:
229 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
230 bgmac
->feature_flags
|= BGMAC_FEAT_NO_RESET
;
231 bgmac
->feature_flags
|= BGMAC_FEAT_FORCE_SPEED_2500
;
234 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
235 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
238 if (!bgmac_is_bcm4707_family(core
) && core
->id
.rev
> 2)
239 bgmac
->feature_flags
|= BGMAC_FEAT_MISC_PLL_REQ
;
241 if (core
->id
.id
== BCMA_CORE_4706_MAC_GBIT
) {
242 bgmac
->feature_flags
|= BGMAC_FEAT_CMN_PHY_CTL
;
243 bgmac
->feature_flags
|= BGMAC_FEAT_NO_CLR_MIB
;
246 if (core
->id
.rev
>= 4) {
247 bgmac
->feature_flags
|= BGMAC_FEAT_CMDCFG_SR_REV4
;
248 bgmac
->feature_flags
|= BGMAC_FEAT_TX_MASK_SETUP
;
249 bgmac
->feature_flags
|= BGMAC_FEAT_RX_MASK_SETUP
;
252 bgmac
->read
= bcma_bgmac_read
;
253 bgmac
->write
= bcma_bgmac_write
;
254 bgmac
->idm_read
= bcma_bgmac_idm_read
;
255 bgmac
->idm_write
= bcma_bgmac_idm_write
;
256 bgmac
->clk_enabled
= bcma_bgmac_clk_enabled
;
257 bgmac
->clk_enable
= bcma_bgmac_clk_enable
;
258 bgmac
->cco_ctl_maskset
= bcma_bgmac_cco_ctl_maskset
;
259 bgmac
->get_bus_clock
= bcma_bgmac_get_bus_clock
;
260 bgmac
->cmn_maskset32
= bcma_bgmac_cmn_maskset32
;
262 err
= bgmac_enet_probe(bgmac
);
269 bcma_mdio_mii_unregister(bgmac
->mii_bus
);
272 bcma_set_drvdata(core
, NULL
);
277 static void bgmac_remove(struct bcma_device
*core
)
279 struct bgmac
*bgmac
= bcma_get_drvdata(core
);
281 bcma_mdio_mii_unregister(bgmac
->mii_bus
);
282 bgmac_enet_remove(bgmac
);
283 bcma_set_drvdata(core
, NULL
);
287 static struct bcma_driver bgmac_bcma_driver
= {
288 .name
= KBUILD_MODNAME
,
289 .id_table
= bgmac_bcma_tbl
,
290 .probe
= bgmac_probe
,
291 .remove
= bgmac_remove
,
294 static int __init
bgmac_init(void)
298 err
= bcma_driver_register(&bgmac_bcma_driver
);
301 pr_info("Broadcom 47xx GBit MAC driver loaded\n");
306 static void __exit
bgmac_exit(void)
308 bcma_driver_unregister(&bgmac_bcma_driver
);
311 module_init(bgmac_init
)
312 module_exit(bgmac_exit
)
314 MODULE_AUTHOR("Rafał Miłecki");
315 MODULE_LICENSE("GPL");