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 bcma_chipinfo
*ci
= &core
->bus
->chipinfo
;
96 struct ssb_sprom
*sprom
= &core
->bus
->sprom
;
97 struct mii_bus
*mii_bus
;
102 bgmac
= kzalloc(sizeof(*bgmac
), GFP_KERNEL
);
106 bgmac
->bcma
.core
= core
;
107 bgmac
->dev
= &core
->dev
;
108 bgmac
->dma_dev
= core
->dma_dev
;
109 bgmac
->irq
= core
->irq
;
111 bcma_set_drvdata(core
, bgmac
);
113 switch (core
->core_unit
) {
124 dev_err(bgmac
->dev
, "Unsupported core_unit %d\n",
130 ether_addr_copy(bgmac
->mac_addr
, mac
);
132 /* On BCM4706 we need common core to access PHY */
133 if (core
->id
.id
== BCMA_CORE_4706_MAC_GBIT
&&
134 !core
->bus
->drv_gmac_cmn
.core
) {
135 dev_err(bgmac
->dev
, "GMAC CMN core not found (required for BCM4706)\n");
139 bgmac
->bcma
.cmn
= core
->bus
->drv_gmac_cmn
.core
;
141 switch (core
->core_unit
) {
143 bgmac
->phyaddr
= sprom
->et0phyaddr
;
146 bgmac
->phyaddr
= sprom
->et1phyaddr
;
149 bgmac
->phyaddr
= sprom
->et2phyaddr
;
152 bgmac
->phyaddr
&= BGMAC_PHY_MASK
;
153 if (bgmac
->phyaddr
== BGMAC_PHY_MASK
) {
154 dev_err(bgmac
->dev
, "No PHY found\n");
158 dev_info(bgmac
->dev
, "Found PHY addr: %d%s\n", bgmac
->phyaddr
,
159 bgmac
->phyaddr
== BGMAC_PHY_NOREGS
? " (NOREGS)" : "");
161 if (!bgmac_is_bcm4707_family(core
) &&
162 !(ci
->id
== BCMA_CHIP_ID_BCM53573
&& core
->core_unit
== 1)) {
163 mii_bus
= bcma_mdio_mii_register(core
, bgmac
->phyaddr
);
164 if (IS_ERR(mii_bus
)) {
165 err
= PTR_ERR(mii_bus
);
169 bgmac
->mii_bus
= mii_bus
;
172 if (core
->bus
->hosttype
== BCMA_HOSTTYPE_PCI
) {
173 dev_err(bgmac
->dev
, "PCI setup not implemented\n");
178 bgmac
->has_robosw
= !!(core
->bus
->sprom
.boardflags_lo
&
180 if (bgmac
->has_robosw
)
181 dev_warn(bgmac
->dev
, "Support for Roboswitch not implemented\n");
183 if (core
->bus
->sprom
.boardflags_lo
& BGMAC_BFL_ENETADM
)
184 dev_warn(bgmac
->dev
, "Support for ADMtek ethernet switch not implemented\n");
187 switch (core
->bus
->chipinfo
.id
) {
188 case BCMA_CHIP_ID_BCM5357
:
189 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
190 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
191 bgmac
->feature_flags
|= BGMAC_FEAT_FLW_CTRL1
;
192 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_PHY
;
193 if (core
->bus
->chipinfo
.pkg
== BCMA_PKG_ID_BCM47186
) {
194 bgmac
->feature_flags
|= BGMAC_FEAT_IOST_ATTACHED
;
195 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_RGMII
;
197 if (core
->bus
->chipinfo
.pkg
== BCMA_PKG_ID_BCM5358
)
198 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_EPHYRMII
;
200 case BCMA_CHIP_ID_BCM53572
:
201 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
202 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
203 bgmac
->feature_flags
|= BGMAC_FEAT_FLW_CTRL1
;
204 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_PHY
;
205 if (core
->bus
->chipinfo
.pkg
== BCMA_PKG_ID_BCM47188
) {
206 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_RGMII
;
207 bgmac
->feature_flags
|= BGMAC_FEAT_IOST_ATTACHED
;
210 case BCMA_CHIP_ID_BCM4749
:
211 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
212 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
213 bgmac
->feature_flags
|= BGMAC_FEAT_FLW_CTRL1
;
214 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_PHY
;
215 if (core
->bus
->chipinfo
.pkg
== 10) {
216 bgmac
->feature_flags
|= BGMAC_FEAT_SW_TYPE_RGMII
;
217 bgmac
->feature_flags
|= BGMAC_FEAT_IOST_ATTACHED
;
220 case BCMA_CHIP_ID_BCM4716
:
221 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
223 case BCMA_CHIP_ID_BCM47162
:
224 bgmac
->feature_flags
|= BGMAC_FEAT_FLW_CTRL2
;
225 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
228 case BCMA_CHIP_ID_BCM4707
:
229 case BCMA_CHIP_ID_BCM47094
:
230 case BCMA_CHIP_ID_BCM53018
:
231 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
232 bgmac
->feature_flags
|= BGMAC_FEAT_NO_RESET
;
233 bgmac
->feature_flags
|= BGMAC_FEAT_FORCE_SPEED_2500
;
235 case BCMA_CHIP_ID_BCM53573
:
236 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
237 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
238 if (ci
->pkg
== BCMA_PKG_ID_BCM47189
)
239 bgmac
->feature_flags
|= BGMAC_FEAT_IOST_ATTACHED
;
240 if (core
->core_unit
== 0) {
241 bgmac
->feature_flags
|= BGMAC_FEAT_CC4_IF_SW_TYPE
;
242 if (ci
->pkg
== BCMA_PKG_ID_BCM47189
)
243 bgmac
->feature_flags
|=
244 BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII
;
245 } else if (core
->core_unit
== 1) {
246 bgmac
->feature_flags
|= BGMAC_FEAT_IRQ_ID_OOB_6
;
247 bgmac
->feature_flags
|= BGMAC_FEAT_CC7_IF_TYPE_RGMII
;
251 bgmac
->feature_flags
|= BGMAC_FEAT_CLKCTLST
;
252 bgmac
->feature_flags
|= BGMAC_FEAT_SET_RXQ_CLK
;
255 if (!bgmac_is_bcm4707_family(core
) && core
->id
.rev
> 2)
256 bgmac
->feature_flags
|= BGMAC_FEAT_MISC_PLL_REQ
;
258 if (core
->id
.id
== BCMA_CORE_4706_MAC_GBIT
) {
259 bgmac
->feature_flags
|= BGMAC_FEAT_CMN_PHY_CTL
;
260 bgmac
->feature_flags
|= BGMAC_FEAT_NO_CLR_MIB
;
263 if (core
->id
.rev
>= 4) {
264 bgmac
->feature_flags
|= BGMAC_FEAT_CMDCFG_SR_REV4
;
265 bgmac
->feature_flags
|= BGMAC_FEAT_TX_MASK_SETUP
;
266 bgmac
->feature_flags
|= BGMAC_FEAT_RX_MASK_SETUP
;
269 bgmac
->read
= bcma_bgmac_read
;
270 bgmac
->write
= bcma_bgmac_write
;
271 bgmac
->idm_read
= bcma_bgmac_idm_read
;
272 bgmac
->idm_write
= bcma_bgmac_idm_write
;
273 bgmac
->clk_enabled
= bcma_bgmac_clk_enabled
;
274 bgmac
->clk_enable
= bcma_bgmac_clk_enable
;
275 bgmac
->cco_ctl_maskset
= bcma_bgmac_cco_ctl_maskset
;
276 bgmac
->get_bus_clock
= bcma_bgmac_get_bus_clock
;
277 bgmac
->cmn_maskset32
= bcma_bgmac_cmn_maskset32
;
279 err
= bgmac_enet_probe(bgmac
);
286 bcma_mdio_mii_unregister(bgmac
->mii_bus
);
289 bcma_set_drvdata(core
, NULL
);
294 static void bgmac_remove(struct bcma_device
*core
)
296 struct bgmac
*bgmac
= bcma_get_drvdata(core
);
298 bcma_mdio_mii_unregister(bgmac
->mii_bus
);
299 bgmac_enet_remove(bgmac
);
300 bcma_set_drvdata(core
, NULL
);
304 static struct bcma_driver bgmac_bcma_driver
= {
305 .name
= KBUILD_MODNAME
,
306 .id_table
= bgmac_bcma_tbl
,
307 .probe
= bgmac_probe
,
308 .remove
= bgmac_remove
,
311 static int __init
bgmac_init(void)
315 err
= bcma_driver_register(&bgmac_bcma_driver
);
318 pr_info("Broadcom 47xx GBit MAC driver loaded\n");
323 static void __exit
bgmac_exit(void)
325 bcma_driver_unregister(&bgmac_bcma_driver
);
328 module_init(bgmac_init
)
329 module_exit(bgmac_exit
)
331 MODULE_AUTHOR("Rafał Miłecki");
332 MODULE_LICENSE("GPL");