brintos

brintos / linux-shallow public Read only

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