⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sungem.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
			gem_init_bcm5400_phy(gp);			gp->gigabit_capable = 1;			break;		case 0x206050:			printk("BCM 5401\n");			gp->phy_mod = phymod_bcm5401;			gem_init_bcm5401_phy(gp);			gp->gigabit_capable = 1;			break;		case 0x206070:			printk("BCM 5411\n");			gp->phy_mod = phymod_bcm5411;			gem_init_bcm5411_phy(gp);			gp->gigabit_capable = 1;			break;		case 0x1410c60:			printk("M1011 (Marvel ?)\n");			gp->phy_mod = phymod_m1011;			gp->gigabit_capable = 1;			break;		case 0x18074c0:			printk("Lucent\n");			gp->phy_mod = phymod_generic;			break;		case 0x437420:			printk("Enable Semiconductor\n");			gp->phy_mod = phymod_generic;			break;		default:			printk("Unknown (Using generic mode)\n");			gp->phy_mod = phymod_generic;			break;		};		/* Init advertisement and enable autonegotiation. */		val = phy_read(gp, MII_BMCR);		val &= ~BMCR_ANENABLE;		phy_write(gp, MII_BMCR, val);		udelay(10);				phy_write(gp, MII_ADVERTISE,			  phy_read(gp, MII_ADVERTISE) |			  (ADVERTISE_10HALF | ADVERTISE_10FULL |			   ADVERTISE_100HALF | ADVERTISE_100FULL));	} else {		u32 val;		int limit;		/* Reset PCS unit. */		val = readl(gp->regs + PCS_MIICTRL);		val |= PCS_MIICTRL_RST;		writeb(val, gp->regs + PCS_MIICTRL);		limit = 32;		while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) {			udelay(100);			if (limit-- <= 0)				break;		}		if (limit <= 0)			printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",			       gp->dev->name);		/* Make sure PCS is disabled while changing advertisement		 * configuration.		 */		val = readl(gp->regs + PCS_CFG);		val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);		writel(val, gp->regs + PCS_CFG);		/* Advertise all capabilities. */		val = readl(gp->regs + PCS_MIIADV);		val |= (PCS_MIIADV_FD | PCS_MIIADV_HD |			PCS_MIIADV_SP | PCS_MIIADV_AP);		writel(val, gp->regs + PCS_MIIADV);		/* Enable and restart auto-negotiation, disable wrapback/loopback,		 * and re-enable PCS.		 */		val = readl(gp->regs + PCS_MIICTRL);		val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE);		val &= ~PCS_MIICTRL_WB;		writel(val, gp->regs + PCS_MIICTRL);		val = readl(gp->regs + PCS_CFG);		val |= PCS_CFG_ENABLE;		writel(val, gp->regs + PCS_CFG);		/* Make sure serialink loopback is off.  The meaning		 * of this bit is logically inverted based upon whether		 * you are in Serialink or SERDES mode.		 */		val = readl(gp->regs + PCS_SCTRL);		if (gp->phy_type == phy_serialink)			val &= ~PCS_SCTRL_LOOP;		else			val |= PCS_SCTRL_LOOP;		writel(val, gp->regs + PCS_SCTRL);		gp->gigabit_capable = 1;	}	/* BMCR_SPD2 is a broadcom 54xx specific thing afaik */	if (gp->phy_mod != phymod_bcm5400 && gp->phy_mod != phymod_bcm5401 &&	    gp->phy_mod != phymod_bcm5411)	    	gp->link_cntl &= ~BMCR_SPD2;	    }static void gem_init_dma(struct gem *gp){	u64 desc_dma = (u64) gp->gblock_dvma;	u32 val;	val = (TXDMA_CFG_BASE | (0x7ff << 10) | TXDMA_CFG_PMODE);	writel(val, gp->regs + TXDMA_CFG);	writel(desc_dma >> 32, gp->regs + TXDMA_DBHI);	writel(desc_dma & 0xffffffff, gp->regs + TXDMA_DBLOW);	desc_dma += (INIT_BLOCK_TX_RING_SIZE * sizeof(struct gem_txd));	writel(0, gp->regs + TXDMA_KICK);	val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) |	       ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_512);	writel(val, gp->regs + RXDMA_CFG);	writel(desc_dma >> 32, gp->regs + RXDMA_DBHI);	writel(desc_dma & 0xffffffff, gp->regs + RXDMA_DBLOW);	writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);	val  = (((gp->rx_pause_off / 64) << 0) & RXDMA_PTHRESH_OFF);	val |= (((gp->rx_pause_on / 64) << 12) & RXDMA_PTHRESH_ON);	writel(val, gp->regs + RXDMA_PTHRESH);	if (readl(gp->regs + GREG_BIFCFG) & GREG_BIFCFG_M66EN)		writel(((5 & RXDMA_BLANK_IPKTS) |			((8 << 12) & RXDMA_BLANK_ITIME)),		       gp->regs + RXDMA_BLANK);	else		writel(((5 & RXDMA_BLANK_IPKTS) |			((4 << 12) & RXDMA_BLANK_ITIME)),		       gp->regs + RXDMA_BLANK);}#define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */static u32gem_setup_multicast(struct gem *gp){	u32 rxcfg = 0;	int i;		if ((gp->dev->flags & IFF_ALLMULTI) ||	    (gp->dev->mc_count > 256)) {	    	for (i=0; i<16; i++)			writel(0xffff, gp->regs + MAC_HASH0 + (i << 2));		rxcfg |= MAC_RXCFG_HFE;	} else if (gp->dev->flags & IFF_PROMISC) {		rxcfg |= MAC_RXCFG_PROM;	} else {		u16 hash_table[16];		u32 crc, poly = CRC_POLYNOMIAL_LE;		struct dev_mc_list *dmi = gp->dev->mc_list;		int i, j, bit, byte;		for (i = 0; i < 16; i++)			hash_table[i] = 0;		for (i = 0; i < gp->dev->mc_count; i++) {			char *addrs = dmi->dmi_addr;			dmi = dmi->next;			if (!(*addrs & 1))				continue;			crc = 0xffffffffU;			for (byte = 0; byte < 6; byte++) {				for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {					int test;					test = ((bit ^ crc) & 0x01);					crc >>= 1;					if (test)						crc = crc ^ poly;				}			}			crc >>= 24;			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));		}	    	for (i=0; i<16; i++)			writel(hash_table[i], gp->regs + MAC_HASH0 + (i << 2));		rxcfg |= MAC_RXCFG_HFE;	}	return rxcfg;}static void gem_init_mac(struct gem *gp){	unsigned char *e = &gp->dev->dev_addr[0];	u32 rxcfg;	if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&	    gp->pdev->device == PCI_DEVICE_ID_SUN_GEM)		writel(0x1bf0, gp->regs + MAC_SNDPAUSE);	writel(0x00, gp->regs + MAC_IPG0);	writel(0x08, gp->regs + MAC_IPG1);	writel(0x04, gp->regs + MAC_IPG2);	writel(0x40, gp->regs + MAC_STIME);	writel(0x40, gp->regs + MAC_MINFSZ);	writel(0x20000000 | (gp->dev->mtu + 18), gp->regs + MAC_MAXFSZ);	writel(0x07, gp->regs + MAC_PASIZE);	writel(0x04, gp->regs + MAC_JAMSIZE);	writel(0x10, gp->regs + MAC_ATTLIM);	writel(0x8808, gp->regs + MAC_MCTYPE);	writel((e[5] | (e[4] << 8)) & 0x3ff, gp->regs + MAC_RANDSEED);	writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);	writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);	writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);	writel(0, gp->regs + MAC_ADDR3);	writel(0, gp->regs + MAC_ADDR4);	writel(0, gp->regs + MAC_ADDR5);	writel(0x0001, gp->regs + MAC_ADDR6);	writel(0xc200, gp->regs + MAC_ADDR7);	writel(0x0180, gp->regs + MAC_ADDR8);	writel(0, gp->regs + MAC_AFILT0);	writel(0, gp->regs + MAC_AFILT1);	writel(0, gp->regs + MAC_AFILT2);	writel(0, gp->regs + MAC_AF21MSK);	writel(0, gp->regs + MAC_AF0MSK);	rxcfg = gem_setup_multicast(gp);	writel(0, gp->regs + MAC_NCOLL);	writel(0, gp->regs + MAC_FASUCC);	writel(0, gp->regs + MAC_ECOLL);	writel(0, gp->regs + MAC_LCOLL);	writel(0, gp->regs + MAC_DTIMER);	writel(0, gp->regs + MAC_PATMPS);	writel(0, gp->regs + MAC_RFCTR);	writel(0, gp->regs + MAC_LERR);	writel(0, gp->regs + MAC_AERR);	writel(0, gp->regs + MAC_FCSERR);	writel(0, gp->regs + MAC_RXCVERR);	/* Clear RX/TX/MAC/XIF config, we will set these up and enable	 * them once a link is established.	 */	writel(0, gp->regs + MAC_TXCFG);	writel(rxcfg, gp->regs + MAC_RXCFG);	writel(0, gp->regs + MAC_MCCFG);	writel(0, gp->regs + MAC_XIFCFG);	/* Setup MAC interrupts.  We want to get all of the interesting	 * counter expiration events, but we do not want to hear about	 * normal rx/tx as the DMA engine tells us that.	 */	writel(MAC_TXSTAT_XMIT, gp->regs + MAC_TXMASK);	writel(MAC_RXSTAT_RCV, gp->regs + MAC_RXMASK);	/* Don't enable even the PAUSE interrupts for now, we	 * make no use of those events other than to record them.	 */	writel(0xffffffff, gp->regs + MAC_MCMASK);}static void gem_init_pause_thresholds(struct gem *gp){	/* Calculate pause thresholds.  Setting the OFF threshold to the	 * full RX fifo size effectively disables PAUSE generation which	 * is what we do for 10/100 only GEMs which have FIFOs too small	 * to make real gains from PAUSE.	 */	if (gp->rx_fifo_sz <= (2 * 1024)) {		gp->rx_pause_off = gp->rx_pause_on = gp->rx_fifo_sz;	} else {		int off = (gp->rx_fifo_sz - (5 * 1024));		int on = off - 1024;		gp->rx_pause_off = off;		gp->rx_pause_on = on;	}	{		u32 cfg;		cfg  = GREG_CFG_IBURST;		cfg |= ((31 << 1) & GREG_CFG_TXDMALIM);		cfg |= ((31 << 6) & GREG_CFG_RXDMALIM);		writel(cfg, gp->regs + GREG_CFG);	}}static int gem_check_invariants(struct gem *gp){	struct pci_dev *pdev = gp->pdev;	u32 mif_cfg;	/* On Apple's sungem, we can't rely on registers as the chip	 * was been powered down by the firmware. The PHY is looked	 * up later on.	 */	if (pdev->vendor == PCI_VENDOR_ID_APPLE) {		gp->phy_type = phy_mii_mdio0;		gp->tx_fifo_sz = readl(gp->regs + TXDMA_FSZ) * 64;		gp->rx_fifo_sz = readl(gp->regs + RXDMA_FSZ) * 64;		return 0;	}	mif_cfg = readl(gp->regs + MIF_CFG);	if (pdev->vendor == PCI_VENDOR_ID_SUN &&	    pdev->device == PCI_DEVICE_ID_SUN_RIO_GEM) {		/* One of the MII PHYs _must_ be present		 * as this chip has no gigabit PHY.		 */		if ((mif_cfg & (MIF_CFG_MDI0 | MIF_CFG_MDI1)) == 0) {			printk(KERN_ERR PFX "RIO GEM lacks MII phy, mif_cfg[%08x]\n",			       mif_cfg);			return -1;		}	}	/* Determine initial PHY interface type guess.  MDIO1 is the	 * external PHY and thus takes precedence over MDIO0.	 */		if (mif_cfg & MIF_CFG_MDI1) {		gp->phy_type = phy_mii_mdio1;		mif_cfg |= MIF_CFG_PSELECT;		writel(mif_cfg, gp->regs + MIF_CFG);	} else if (mif_cfg & MIF_CFG_MDI0) {		gp->phy_type = phy_mii_mdio0;		mif_cfg &= ~MIF_CFG_PSELECT;		writel(mif_cfg, gp->regs + MIF_CFG);	} else {		gp->phy_type = phy_serialink;	}	if (gp->phy_type == phy_mii_mdio1 ||	    gp->phy_type == phy_mii_mdio0) {		int i;		for (i = 0; i < 32; i++) {			gp->mii_phy_addr = i;			if (phy_read(gp, MII_BMCR) != 0xffff)				break;		}		if (i == 32) {			if (pdev->device != PCI_DEVICE_ID_SUN_GEM) {				printk(KERN_ERR PFX "RIO MII phy will not respond.\n");				return -1;			}			gp->phy_type = phy_serdes;		}	}	/* Fetch the FIFO configurations now too. */	gp->tx_fifo_sz = readl(gp->regs + TXDMA_FSZ) * 64;	gp->rx_fifo_sz = readl(gp->regs + RXDMA_FSZ) * 64;	if (pdev->vendor == PCI_VENDOR_ID_SUN) {		if (pdev->device == PCI_DEVICE_ID_SUN_GEM) {			if (gp->tx_fifo_sz != (9 * 1024) ||			    gp->rx_fifo_sz != (20 * 1024)) {				printk(KERN_ERR PFX "GEM has bogus fifo sizes tx(%d) rx(%d)\n",				       gp->tx_fifo_sz, gp->rx_fifo_sz);				return -1;			}		} else {			if (gp->tx_fifo_sz != (2 * 1024) ||			    gp->rx_fifo_sz != (2 * 1024)) {				printk(KERN_ERR PFX "RIO GEM has bogus fifo sizes tx(%d) rx(%d)\n",				       gp->tx_fifo_sz, gp->rx_fifo_sz);				return -1;			}		}	}	return 0;}static void gem_init_hw(struct gem *gp, int restart_link){	/* On Apple's gmac, I initialize the PHY only after	 * setting up the chip. It appears the gigabit PHYs	 * don't quite like beeing talked to on the GII when	 * the chip is not running, I suspect it might not	 * be clocked at that point. --BenH	 */	if (restart_link)		gem_init_phy(gp);	gem_init_dma(gp);	gem_init_mac(gp);	gem_init_pause_thresholds(gp);	spin_lock_irq(&gp->lock);	if (restart_link) {		/* Default aneg parameters */		gp->timer_ticks = 0;		gp->lstate = link_down;		spin_unlock_irq(&gp->lock);		/* Can I advertise gigabit here ? I'd need BCM PHY docs... */		gem_begin_auto_negotiation(gp, NULL);	} else {		if (gp->lstate == link_up)			gem_set_link_modes(gp);		spin_unlock_irq(&gp->lock);	}}#ifdef CONFIG_ALL_PPC/* Enable the chip's clock and make sure it's config space is * setup properly. There appear to be no need to restore the * base addresses. */static void gem_apple_powerup(struct gem *gp){	u16 cmd;	u32 mif_cfg;	pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 1);	current->state = TASK_UNINTERRUPTIBLE;	schedule_timeout((21 * HZ) / 1000);	pci_read_config_word(gp->pdev, PCI_COMMAND, &cmd);	cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;    	pci_write_config_word(gp->pdev, PCI_COMMAND, cmd);    	pci_write_config_byte(gp->pdev, PCI_LATENCY_TIMER, 6);    	pci_write_config_byte(gp->pdev, PCI_CACHE_LINE_SIZE, 8);	mdelay(1);		mif_cfg = readl(gp->regs + MIF_CFG);	mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);	mif_cfg |= MIF_CFG_MDI0;	writel(mif_cfg, gp->regs + MIF_CFG);	writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);	writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);	mdelay(1);}/* Turn off the chip's clock */static void gem_apple_powerdown(struct gem *gp){	pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 0);}#endif /* CONFIG_ALL_PPC */static void gem_stop_phy(struct gem *gp){	u32 mifcfg;	if (!gp->wake_on_lan && gp->phy_mod == phymod_bcm5201)		phy_write(gp, MII_BCM5201_INTERRUPT, 0);	/* Make sure we aren't polling PHY status change. We	 * don't currently use that feature though	 */	mifcfg = readl(gp->regs + MIF_CFG);	mifcfg &= ~MIF_CFG_POLL;	writel(mifcfg, gp->regs + MIF_CFG);	/* Here's a strange hack used by both MacOS 9 and X */	phy_write(gp, MII_LPA, phy_read(gp, MII_LPA));	if (gp->wake_on_lan) {		/* Setup wake-on-lan */	} else		writel(0, gp->regs + MAC_RXCFG);	writel(0, gp->regs + MAC_TXCFG);	writel(0, gp->regs + MAC_XIFCFG);	writel(0, gp->regs + TXDMA_CFG);	writel(0, gp->regs + RXDMA_CFG);	if (!gp->wake_on_lan) {		gem_stop(gp);		writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);		writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);		if (gp->phy_mod == phymod_bcm5400 || gp->phy_mod == phymod_bcm5401 ||		    gp->phy_mod == phymod_bcm5411) {#if 0 /* Commented out in Darwin... someone has those dawn docs ? */			phy_write(gp, MII_BMCR, BMCR_PDOWN);#endif		} else if (gp->phy_mod == phymod_bcm5201 || gp->phy_mod == phymod_bcm5221) {#if 0 /* Commented out in Darwin... someone has those dawn docs ? */			u16 val = phy_read(gp, MII_BCM5201_AUXMODE2)			phy_write(gp, MII_BCM5201_AUXMODE2,				  val & ~MII_BCM5201_AUXMODE2_LOWPOWER);#endif							phy_write(gp, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);		} else if (gp->phy_mod == phymod_m1011)			phy_write(gp, MII_BMCR, BMCR_PDOWN);		/* According to Apple, we must set the MDIO pins to this begnign		 * state or we may 1) eat more current, 2) damage some PHYs		 */		writel(mifcfg | MIF_CFG_BBMODE, gp->regs + MIF_CFG);		writel(0, gp->regs + MIF_BBCLK);		writel(0, gp->regs + MIF_BBDATA);		writel(0, gp->regs + MIF_BBOENAB);		writel(MAC_XIFCFG_GMII | MAC_XIFCFG_LBCK, gp->regs + MAC_XIFCFG);		(void) readl(gp->regs + MAC_XIFCFG);	}}/* Shut down the chip, must be called with pm_sem held.  */static void gem_shutdown(struct gem *gp){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -