xref: /openbmc/linux/drivers/net/ethernet/broadcom/bgmac-bcma.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1f6a95a24SJon Mason /*
2f6a95a24SJon Mason  * Driver for (BCM4706)? GBit MAC core on BCMA bus.
3f6a95a24SJon Mason  *
4f6a95a24SJon Mason  * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
5f6a95a24SJon Mason  *
6f6a95a24SJon Mason  * Licensed under the GNU/GPL. See COPYING for details.
7f6a95a24SJon Mason  */
8f6a95a24SJon Mason 
9f6a95a24SJon Mason #define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
10f6a95a24SJon Mason 
11f6a95a24SJon Mason #include <linux/bcma/bcma.h>
12f6a95a24SJon Mason #include <linux/brcmphy.h>
13f6a95a24SJon Mason #include <linux/etherdevice.h>
14b5375509SRafał Miłecki #include <linux/of_mdio.h>
152f771399SSteve Lin #include <linux/of_net.h>
16f6a95a24SJon Mason #include "bgmac.h"
17f6a95a24SJon Mason 
bgmac_is_bcm4707_family(struct bcma_device * core)18f6a95a24SJon Mason static inline bool bgmac_is_bcm4707_family(struct bcma_device *core)
19f6a95a24SJon Mason {
20f6a95a24SJon Mason 	switch (core->bus->chipinfo.id) {
21f6a95a24SJon Mason 	case BCMA_CHIP_ID_BCM4707:
22f6a95a24SJon Mason 	case BCMA_CHIP_ID_BCM47094:
23f6a95a24SJon Mason 	case BCMA_CHIP_ID_BCM53018:
24f6a95a24SJon Mason 		return true;
25f6a95a24SJon Mason 	default:
26f6a95a24SJon Mason 		return false;
27f6a95a24SJon Mason 	}
28f6a95a24SJon Mason }
29f6a95a24SJon Mason 
30f6a95a24SJon Mason /**************************************************
31f6a95a24SJon Mason  * BCMA bus ops
32f6a95a24SJon Mason  **************************************************/
33f6a95a24SJon Mason 
bcma_bgmac_read(struct bgmac * bgmac,u16 offset)34f6a95a24SJon Mason static u32 bcma_bgmac_read(struct bgmac *bgmac, u16 offset)
35f6a95a24SJon Mason {
36f6a95a24SJon Mason 	return bcma_read32(bgmac->bcma.core, offset);
37f6a95a24SJon Mason }
38f6a95a24SJon Mason 
bcma_bgmac_write(struct bgmac * bgmac,u16 offset,u32 value)39f6a95a24SJon Mason static void bcma_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value)
40f6a95a24SJon Mason {
41f6a95a24SJon Mason 	bcma_write32(bgmac->bcma.core, offset, value);
42f6a95a24SJon Mason }
43f6a95a24SJon Mason 
bcma_bgmac_idm_read(struct bgmac * bgmac,u16 offset)44f6a95a24SJon Mason static u32 bcma_bgmac_idm_read(struct bgmac *bgmac, u16 offset)
45f6a95a24SJon Mason {
46f6a95a24SJon Mason 	return bcma_aread32(bgmac->bcma.core, offset);
47f6a95a24SJon Mason }
48f6a95a24SJon Mason 
bcma_bgmac_idm_write(struct bgmac * bgmac,u16 offset,u32 value)49f6a95a24SJon Mason static void bcma_bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value)
50f6a95a24SJon Mason {
51f6a95a24SJon Mason 	return bcma_awrite32(bgmac->bcma.core, offset, value);
52f6a95a24SJon Mason }
53f6a95a24SJon Mason 
bcma_bgmac_clk_enabled(struct bgmac * bgmac)54f6a95a24SJon Mason static bool bcma_bgmac_clk_enabled(struct bgmac *bgmac)
55f6a95a24SJon Mason {
56f6a95a24SJon Mason 	return bcma_core_is_enabled(bgmac->bcma.core);
57f6a95a24SJon Mason }
58f6a95a24SJon Mason 
bcma_bgmac_clk_enable(struct bgmac * bgmac,u32 flags)59f6a95a24SJon Mason static void bcma_bgmac_clk_enable(struct bgmac *bgmac, u32 flags)
60f6a95a24SJon Mason {
61f6a95a24SJon Mason 	bcma_core_enable(bgmac->bcma.core, flags);
62f6a95a24SJon Mason }
63f6a95a24SJon Mason 
bcma_bgmac_cco_ctl_maskset(struct bgmac * bgmac,u32 offset,u32 mask,u32 set)64f6a95a24SJon Mason static void bcma_bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset,
65f6a95a24SJon Mason 				       u32 mask, u32 set)
66f6a95a24SJon Mason {
67f6a95a24SJon Mason 	struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc;
68f6a95a24SJon Mason 
69f6a95a24SJon Mason 	bcma_chipco_chipctl_maskset(cc, offset, mask, set);
70f6a95a24SJon Mason }
71f6a95a24SJon Mason 
bcma_bgmac_get_bus_clock(struct bgmac * bgmac)72f6a95a24SJon Mason static u32 bcma_bgmac_get_bus_clock(struct bgmac *bgmac)
73f6a95a24SJon Mason {
74f6a95a24SJon Mason 	struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc;
75f6a95a24SJon Mason 
76f6a95a24SJon Mason 	return bcma_pmu_get_bus_clock(cc);
77f6a95a24SJon Mason }
78f6a95a24SJon Mason 
bcma_bgmac_cmn_maskset32(struct bgmac * bgmac,u16 offset,u32 mask,u32 set)79f6a95a24SJon Mason static void bcma_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset, u32 mask,
80f6a95a24SJon Mason 				     u32 set)
81f6a95a24SJon Mason {
82f6a95a24SJon Mason 	bcma_maskset32(bgmac->bcma.cmn, offset, mask, set);
83f6a95a24SJon Mason }
84f6a95a24SJon Mason 
bcma_phy_connect(struct bgmac * bgmac)851676aba5SJon Mason static int bcma_phy_connect(struct bgmac *bgmac)
861676aba5SJon Mason {
871676aba5SJon Mason 	struct phy_device *phy_dev;
881676aba5SJon Mason 	char bus_id[MII_BUS_ID_SIZE + 3];
891676aba5SJon Mason 
90b5375509SRafał Miłecki 	/* DT info should be the most accurate */
91b5375509SRafał Miłecki 	phy_dev = of_phy_get_and_connect(bgmac->net_dev, bgmac->dev->of_node,
92b5375509SRafał Miłecki 					 bgmac_adjust_link);
93b5375509SRafał Miłecki 	if (phy_dev)
94b5375509SRafał Miłecki 		return 0;
95b5375509SRafał Miłecki 
961676aba5SJon Mason 	/* Connect to the PHY */
97b5375509SRafał Miłecki 	if (bgmac->mii_bus && bgmac->phyaddr != BGMAC_PHY_NOREGS) {
981676aba5SJon Mason 		snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
991676aba5SJon Mason 			 bgmac->phyaddr);
1001676aba5SJon Mason 		phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link,
1011676aba5SJon Mason 				      PHY_INTERFACE_MODE_MII);
1021676aba5SJon Mason 		if (IS_ERR(phy_dev)) {
1031676aba5SJon Mason 			dev_err(bgmac->dev, "PHY connection failed\n");
1041676aba5SJon Mason 			return PTR_ERR(phy_dev);
1051676aba5SJon Mason 		}
1061676aba5SJon Mason 
1071676aba5SJon Mason 		return 0;
1081676aba5SJon Mason 	}
1091676aba5SJon Mason 
110b5375509SRafał Miłecki 	/* Assume a fixed link to the switch port */
111b5375509SRafał Miłecki 	return bgmac_phy_connect_direct(bgmac);
112b5375509SRafał Miłecki }
113b5375509SRafał Miłecki 
114f6a95a24SJon Mason static const struct bcma_device_id bgmac_bcma_tbl[] = {
115f6a95a24SJon Mason 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT,
116f6a95a24SJon Mason 		  BCMA_ANY_REV, BCMA_ANY_CLASS),
117f6a95a24SJon Mason 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV,
118f6a95a24SJon Mason 		  BCMA_ANY_CLASS),
119f6a95a24SJon Mason 	{},
120f6a95a24SJon Mason };
121f6a95a24SJon Mason MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl);
122f6a95a24SJon Mason 
123f6a95a24SJon Mason /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
bgmac_probe(struct bcma_device * core)124f6a95a24SJon Mason static int bgmac_probe(struct bcma_device *core)
125f6a95a24SJon Mason {
1261cb94db3SRafał Miłecki 	struct bcma_chipinfo *ci = &core->bus->chipinfo;
127f6a95a24SJon Mason 	struct ssb_sprom *sprom = &core->bus->sprom;
128f6a95a24SJon Mason 	struct mii_bus *mii_bus;
129f6a95a24SJon Mason 	struct bgmac *bgmac;
13083216e39SMichael Walle 	const u8 *mac;
131f6a95a24SJon Mason 	int err;
132f6a95a24SJon Mason 
13334a5102cSRafał Miłecki 	bgmac = bgmac_alloc(&core->dev);
134f6a95a24SJon Mason 	if (!bgmac)
135f6a95a24SJon Mason 		return -ENOMEM;
136f6a95a24SJon Mason 
137f6a95a24SJon Mason 	bgmac->bcma.core = core;
138f6a95a24SJon Mason 	bgmac->dma_dev = core->dma_dev;
139f6a95a24SJon Mason 	bgmac->irq = core->irq;
140f6a95a24SJon Mason 
141f6a95a24SJon Mason 	bcma_set_drvdata(core, bgmac);
142f6a95a24SJon Mason 
1439ca01b25SJakub Kicinski 	err = of_get_ethdev_address(bgmac->dev->of_node, bgmac->net_dev);
144029497e6SChristian Lamparter 	if (err == -EPROBE_DEFER)
145029497e6SChristian Lamparter 		return err;
1462f771399SSteve Lin 
1472f771399SSteve Lin 	/* If no MAC address assigned via device tree, check SPROM */
14883216e39SMichael Walle 	if (err) {
149f6a95a24SJon Mason 		switch (core->core_unit) {
150f6a95a24SJon Mason 		case 0:
151f6a95a24SJon Mason 			mac = sprom->et0mac;
152f6a95a24SJon Mason 			break;
153f6a95a24SJon Mason 		case 1:
154f6a95a24SJon Mason 			mac = sprom->et1mac;
155f6a95a24SJon Mason 			break;
156f6a95a24SJon Mason 		case 2:
157f6a95a24SJon Mason 			mac = sprom->et2mac;
158f6a95a24SJon Mason 			break;
159f6a95a24SJon Mason 		default:
160f6a95a24SJon Mason 			dev_err(bgmac->dev, "Unsupported core_unit %d\n",
161f6a95a24SJon Mason 				core->core_unit);
162f6a95a24SJon Mason 			err = -ENOTSUPP;
163f6a95a24SJon Mason 			goto err;
164f6a95a24SJon Mason 		}
165f3956ebbSJakub Kicinski 		eth_hw_addr_set(bgmac->net_dev, mac);
16683216e39SMichael Walle 	}
167f6a95a24SJon Mason 
168f6a95a24SJon Mason 	/* On BCM4706 we need common core to access PHY */
169f6a95a24SJon Mason 	if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
170f6a95a24SJon Mason 	    !core->bus->drv_gmac_cmn.core) {
171f6a95a24SJon Mason 		dev_err(bgmac->dev, "GMAC CMN core not found (required for BCM4706)\n");
172f6a95a24SJon Mason 		err = -ENODEV;
173f6a95a24SJon Mason 		goto err;
174f6a95a24SJon Mason 	}
175f6a95a24SJon Mason 	bgmac->bcma.cmn = core->bus->drv_gmac_cmn.core;
176f6a95a24SJon Mason 
177f6a95a24SJon Mason 	switch (core->core_unit) {
178f6a95a24SJon Mason 	case 0:
179f6a95a24SJon Mason 		bgmac->phyaddr = sprom->et0phyaddr;
180f6a95a24SJon Mason 		break;
181f6a95a24SJon Mason 	case 1:
182f6a95a24SJon Mason 		bgmac->phyaddr = sprom->et1phyaddr;
183f6a95a24SJon Mason 		break;
184f6a95a24SJon Mason 	case 2:
185f6a95a24SJon Mason 		bgmac->phyaddr = sprom->et2phyaddr;
186f6a95a24SJon Mason 		break;
187f6a95a24SJon Mason 	}
188f6a95a24SJon Mason 	bgmac->phyaddr &= BGMAC_PHY_MASK;
189f6a95a24SJon Mason 	if (bgmac->phyaddr == BGMAC_PHY_MASK) {
190f6a95a24SJon Mason 		dev_err(bgmac->dev, "No PHY found\n");
191f6a95a24SJon Mason 		err = -ENODEV;
192f6a95a24SJon Mason 		goto err;
193f6a95a24SJon Mason 	}
194f6a95a24SJon Mason 	dev_info(bgmac->dev, "Found PHY addr: %d%s\n", bgmac->phyaddr,
195f6a95a24SJon Mason 		 bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");
196f6a95a24SJon Mason 
1971cb94db3SRafał Miłecki 	if (!bgmac_is_bcm4707_family(core) &&
1981cb94db3SRafał Miłecki 	    !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) {
19912acd136SRafał Miłecki 		struct phy_device *phydev;
20012acd136SRafał Miłecki 
201aa8863e5SRafał Miłecki 		mii_bus = bcma_mdio_mii_register(bgmac);
202b9f63ae7SRafał Miłecki 		if (IS_ERR(mii_bus)) {
203f6a95a24SJon Mason 			err = PTR_ERR(mii_bus);
204f6a95a24SJon Mason 			goto err;
205f6a95a24SJon Mason 		}
206f6a95a24SJon Mason 		bgmac->mii_bus = mii_bus;
20712acd136SRafał Miłecki 
20812acd136SRafał Miłecki 		phydev = mdiobus_get_phy(bgmac->mii_bus, bgmac->phyaddr);
20912acd136SRafał Miłecki 		if (ci->id == BCMA_CHIP_ID_BCM53573 && phydev &&
21012acd136SRafał Miłecki 		    (phydev->drv->phy_id & phydev->drv->phy_id_mask) == PHY_ID_BCM54210E)
21112acd136SRafał Miłecki 			phydev->dev_flags |= PHY_BRCM_EN_MASTER_MODE;
212f6a95a24SJon Mason 	}
213f6a95a24SJon Mason 
214f6a95a24SJon Mason 	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
215f6a95a24SJon Mason 		dev_err(bgmac->dev, "PCI setup not implemented\n");
216f6a95a24SJon Mason 		err = -ENOTSUPP;
217f6a95a24SJon Mason 		goto err1;
218f6a95a24SJon Mason 	}
219f6a95a24SJon Mason 
220cb1b0f90SJon Mason 	bgmac->has_robosw = !!(sprom->boardflags_lo & BGMAC_BFL_ENETROBO);
221f6a95a24SJon Mason 	if (bgmac->has_robosw)
222f6a95a24SJon Mason 		dev_warn(bgmac->dev, "Support for Roboswitch not implemented\n");
223f6a95a24SJon Mason 
224cb1b0f90SJon Mason 	if (sprom->boardflags_lo & BGMAC_BFL_ENETADM)
225f6a95a24SJon Mason 		dev_warn(bgmac->dev, "Support for ADMtek ethernet switch not implemented\n");
226f6a95a24SJon Mason 
227f6a95a24SJon Mason 	/* Feature Flags */
228cb1b0f90SJon Mason 	switch (ci->id) {
229cb1b0f90SJon Mason 	/* BCM 471X/535X family */
230f6a95a24SJon Mason 	case BCMA_CHIP_ID_BCM4716:
231f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
232df561f66SGustavo A. R. Silva 		fallthrough;
233f6a95a24SJon Mason 	case BCMA_CHIP_ID_BCM47162:
234f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL2;
235f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
236f6a95a24SJon Mason 		break;
237cb1b0f90SJon Mason 	case BCMA_CHIP_ID_BCM5357:
238cb1b0f90SJon Mason 	case BCMA_CHIP_ID_BCM53572:
239cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
240f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
241cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
242cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
243*d61615c3SRafał Miłecki 		if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) ||
244*d61615c3SRafał Miłecki 		    (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) {
245cb1b0f90SJon Mason 			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
246cb1b0f90SJon Mason 			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
247cb1b0f90SJon Mason 		}
248*d61615c3SRafał Miłecki 		if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM5358)
249cb1b0f90SJon Mason 			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII;
250f6a95a24SJon Mason 		break;
2511cb94db3SRafał Miłecki 	case BCMA_CHIP_ID_BCM53573:
2521cb94db3SRafał Miłecki 		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
2531cb94db3SRafał Miłecki 		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
2541cb94db3SRafał Miłecki 		if (ci->pkg == BCMA_PKG_ID_BCM47189)
2551cb94db3SRafał Miłecki 			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
2561cb94db3SRafał Miłecki 		if (core->core_unit == 0) {
2571cb94db3SRafał Miłecki 			bgmac->feature_flags |= BGMAC_FEAT_CC4_IF_SW_TYPE;
2581cb94db3SRafał Miłecki 			if (ci->pkg == BCMA_PKG_ID_BCM47189)
2591cb94db3SRafał Miłecki 				bgmac->feature_flags |=
2601cb94db3SRafał Miłecki 					BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII;
2611cb94db3SRafał Miłecki 		} else if (core->core_unit == 1) {
2621cb94db3SRafał Miłecki 			bgmac->feature_flags |= BGMAC_FEAT_IRQ_ID_OOB_6;
2631cb94db3SRafał Miłecki 			bgmac->feature_flags |= BGMAC_FEAT_CC7_IF_TYPE_RGMII;
2641cb94db3SRafał Miłecki 		}
2651cb94db3SRafał Miłecki 		break;
266cb1b0f90SJon Mason 	case BCMA_CHIP_ID_BCM4749:
267cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
268cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
269cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
270cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
271cb1b0f90SJon Mason 		if (ci->pkg == 10) {
272cb1b0f90SJon Mason 			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
273cb1b0f90SJon Mason 			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
274cb1b0f90SJon Mason 		}
275cb1b0f90SJon Mason 		break;
276cb1b0f90SJon Mason 	/* bcm4707_family */
277cb1b0f90SJon Mason 	case BCMA_CHIP_ID_BCM4707:
278cb1b0f90SJon Mason 	case BCMA_CHIP_ID_BCM47094:
279cb1b0f90SJon Mason 	case BCMA_CHIP_ID_BCM53018:
280cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
281cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
282cb1b0f90SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
283cb1b0f90SJon Mason 		break;
284f6a95a24SJon Mason 	default:
285f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
286f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
287f6a95a24SJon Mason 	}
288f6a95a24SJon Mason 
289f6a95a24SJon Mason 	if (!bgmac_is_bcm4707_family(core) && core->id.rev > 2)
290f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_MISC_PLL_REQ;
291f6a95a24SJon Mason 
292f6a95a24SJon Mason 	if (core->id.id == BCMA_CORE_4706_MAC_GBIT) {
293f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_CMN_PHY_CTL;
294f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_NO_CLR_MIB;
295f6a95a24SJon Mason 	}
296f6a95a24SJon Mason 
297f6a95a24SJon Mason 	if (core->id.rev >= 4) {
298f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
299f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
300f6a95a24SJon Mason 		bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
301f6a95a24SJon Mason 	}
302f6a95a24SJon Mason 
303f6a95a24SJon Mason 	bgmac->read = bcma_bgmac_read;
304f6a95a24SJon Mason 	bgmac->write = bcma_bgmac_write;
305f6a95a24SJon Mason 	bgmac->idm_read = bcma_bgmac_idm_read;
306f6a95a24SJon Mason 	bgmac->idm_write = bcma_bgmac_idm_write;
307f6a95a24SJon Mason 	bgmac->clk_enabled = bcma_bgmac_clk_enabled;
308f6a95a24SJon Mason 	bgmac->clk_enable = bcma_bgmac_clk_enable;
309f6a95a24SJon Mason 	bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
310f6a95a24SJon Mason 	bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
311f6a95a24SJon Mason 	bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
3121676aba5SJon Mason 	bgmac->phy_connect = bcma_phy_connect;
313f6a95a24SJon Mason 
314f6a95a24SJon Mason 	err = bgmac_enet_probe(bgmac);
315f6a95a24SJon Mason 	if (err)
316f6a95a24SJon Mason 		goto err1;
317f6a95a24SJon Mason 
318f6a95a24SJon Mason 	return 0;
319f6a95a24SJon Mason 
320f6a95a24SJon Mason err1:
321f6a95a24SJon Mason 	bcma_mdio_mii_unregister(bgmac->mii_bus);
322f6a95a24SJon Mason err:
323f6a95a24SJon Mason 	bcma_set_drvdata(core, NULL);
324f6a95a24SJon Mason 
325f6a95a24SJon Mason 	return err;
326f6a95a24SJon Mason }
327f6a95a24SJon Mason 
bgmac_remove(struct bcma_device * core)328f6a95a24SJon Mason static void bgmac_remove(struct bcma_device *core)
329f6a95a24SJon Mason {
330f6a95a24SJon Mason 	struct bgmac *bgmac = bcma_get_drvdata(core);
331f6a95a24SJon Mason 
332f6a95a24SJon Mason 	bcma_mdio_mii_unregister(bgmac->mii_bus);
333f6a95a24SJon Mason 	bgmac_enet_remove(bgmac);
334f6a95a24SJon Mason 	bcma_set_drvdata(core, NULL);
335f6a95a24SJon Mason }
336f6a95a24SJon Mason 
337f6a95a24SJon Mason static struct bcma_driver bgmac_bcma_driver = {
338f6a95a24SJon Mason 	.name		= KBUILD_MODNAME,
339f6a95a24SJon Mason 	.id_table	= bgmac_bcma_tbl,
340f6a95a24SJon Mason 	.probe		= bgmac_probe,
341f6a95a24SJon Mason 	.remove		= bgmac_remove,
342f6a95a24SJon Mason };
343f6a95a24SJon Mason 
bgmac_init(void)344f6a95a24SJon Mason static int __init bgmac_init(void)
345f6a95a24SJon Mason {
346f6a95a24SJon Mason 	int err;
347f6a95a24SJon Mason 
348f6a95a24SJon Mason 	err = bcma_driver_register(&bgmac_bcma_driver);
349f6a95a24SJon Mason 	if (err)
350f6a95a24SJon Mason 		return err;
351f6a95a24SJon Mason 	pr_info("Broadcom 47xx GBit MAC driver loaded\n");
352f6a95a24SJon Mason 
353f6a95a24SJon Mason 	return 0;
354f6a95a24SJon Mason }
355f6a95a24SJon Mason 
bgmac_exit(void)356f6a95a24SJon Mason static void __exit bgmac_exit(void)
357f6a95a24SJon Mason {
358f6a95a24SJon Mason 	bcma_driver_unregister(&bgmac_bcma_driver);
359f6a95a24SJon Mason }
360f6a95a24SJon Mason 
361f6a95a24SJon Mason module_init(bgmac_init)
362f6a95a24SJon Mason module_exit(bgmac_exit)
363f6a95a24SJon Mason 
364f6a95a24SJon Mason MODULE_AUTHOR("Rafał Miłecki");
365f6a95a24SJon Mason MODULE_LICENSE("GPL");
366