fec.c

来自「linux 内核源代码」· C语言 代码 · 共 2,492 行 · 第 1/5 页

C
2,492
字号
{}static void __inline__ fec_disable_phy_intr(void){}static void __inline__ fec_phy_ack_intr(void){}static void __inline__ fec_localhw_setup(void){}/* *	Do not need to make region uncached on 5272. */static void __inline__ fec_uncache(unsigned long addr){}/* ------------------------------------------------------------------------- */#elif defined(CONFIG_M520x)/* *	Code specific to Coldfire 520x */static void __inline__ fec_request_intrs(struct net_device *dev){	struct fec_enet_private *fep;	int b;	static const struct idesc {		char *name;		unsigned short irq;	} *idp, id[] = {		{ "fec(TXF)", 23 },		{ "fec(TXB)", 24 },		{ "fec(TXFIFO)", 25 },		{ "fec(TXCR)", 26 },		{ "fec(RXF)", 27 },		{ "fec(RXB)", 28 },		{ "fec(MII)", 29 },		{ "fec(LC)", 30 },		{ "fec(HBERR)", 31 },		{ "fec(GRA)", 32 },		{ "fec(EBERR)", 33 },		{ "fec(BABT)", 34 },		{ "fec(BABR)", 35 },		{ NULL },	};	fep = netdev_priv(dev);	b = 64 + 13;	/* Setup interrupt handlers. */	for (idp = id; idp->name; idp++) {		if (request_irq(b+idp->irq,fec_enet_interrupt,0,idp->name,dev)!=0)			printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);	}	/* Unmask interrupts at ColdFire interrupt controller */	{		volatile unsigned char  *icrp;		volatile unsigned long  *imrp;		icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +			MCFINTC_ICR0);		for (b = 36; (b < 49); b++)			icrp[b] = 0x04;		imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 +			MCFINTC_IMRH);		*imrp &= ~0x0001FFF0;	}	*(volatile unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FEC) |= 0xf0;	*(volatile unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C) |= 0x0f;}static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep){	volatile fec_t *fecp;	fecp = fep->hwp;	fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;	fecp->fec_x_cntrl = 0x00;	/*	 * Set MII speed to 2.5 MHz	 * See 5282 manual section 17.5.4.7: MSCR	 */	fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;	fecp->fec_mii_speed = fep->phy_speed;	fec_restart(dev, 0);}static void __inline__ fec_get_mac(struct net_device *dev){	struct fec_enet_private *fep = netdev_priv(dev);	volatile fec_t *fecp;	unsigned char *iap, tmpaddr[ETH_ALEN];	fecp = fep->hwp;	if (FEC_FLASHMAC) {		/*		 * Get MAC address from FLASH.		 * If it is all 1's or 0's, use the default.		 */		iap = FEC_FLASHMAC;		if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&		   (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))			iap = fec_mac_default;		if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&		   (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))			iap = fec_mac_default;	} else {		*((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;		*((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);		iap = &tmpaddr[0];	}	memcpy(dev->dev_addr, iap, ETH_ALEN);	/* Adjust MAC if using default MAC address */	if (iap == fec_mac_default)		dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;}static void __inline__ fec_enable_phy_intr(void){}static void __inline__ fec_disable_phy_intr(void){}static void __inline__ fec_phy_ack_intr(void){}static void __inline__ fec_localhw_setup(void){}static void __inline__ fec_uncache(unsigned long addr){}/* ------------------------------------------------------------------------- */#elif defined(CONFIG_M532x)/* * Code specific for M532x */static void __inline__ fec_request_intrs(struct net_device *dev){	struct fec_enet_private *fep;	int b;	static const struct idesc {		char *name;		unsigned short irq;	} *idp, id[] = {	    { "fec(TXF)", 36 },	    { "fec(TXB)", 37 },	    { "fec(TXFIFO)", 38 },	    { "fec(TXCR)", 39 },	    { "fec(RXF)", 40 },	    { "fec(RXB)", 41 },	    { "fec(MII)", 42 },	    { "fec(LC)", 43 },	    { "fec(HBERR)", 44 },	    { "fec(GRA)", 45 },	    { "fec(EBERR)", 46 },	    { "fec(BABT)", 47 },	    { "fec(BABR)", 48 },	    { NULL },	};	fep = netdev_priv(dev);	b = (fep->index) ? 128 : 64;	/* Setup interrupt handlers. */	for (idp = id; idp->name; idp++) {		if (request_irq(b+idp->irq,fec_enet_interrupt,0,idp->name,dev)!=0)			printk("FEC: Could not allocate %s IRQ(%d)!\n",				idp->name, b+idp->irq);	}	/* Unmask interrupts */	MCF_INTC0_ICR36 = 0x2;	MCF_INTC0_ICR37 = 0x2;	MCF_INTC0_ICR38 = 0x2;	MCF_INTC0_ICR39 = 0x2;	MCF_INTC0_ICR40 = 0x2;	MCF_INTC0_ICR41 = 0x2;	MCF_INTC0_ICR42 = 0x2;	MCF_INTC0_ICR43 = 0x2;	MCF_INTC0_ICR44 = 0x2;	MCF_INTC0_ICR45 = 0x2;	MCF_INTC0_ICR46 = 0x2;	MCF_INTC0_ICR47 = 0x2;	MCF_INTC0_ICR48 = 0x2;	MCF_INTC0_IMRH &= ~(		MCF_INTC_IMRH_INT_MASK36 |		MCF_INTC_IMRH_INT_MASK37 |		MCF_INTC_IMRH_INT_MASK38 |		MCF_INTC_IMRH_INT_MASK39 |		MCF_INTC_IMRH_INT_MASK40 |		MCF_INTC_IMRH_INT_MASK41 |		MCF_INTC_IMRH_INT_MASK42 |		MCF_INTC_IMRH_INT_MASK43 |		MCF_INTC_IMRH_INT_MASK44 |		MCF_INTC_IMRH_INT_MASK45 |		MCF_INTC_IMRH_INT_MASK46 |		MCF_INTC_IMRH_INT_MASK47 |		MCF_INTC_IMRH_INT_MASK48 );	/* Set up gpio outputs for MII lines */	MCF_GPIO_PAR_FECI2C |= (0 |		MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |		MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);	MCF_GPIO_PAR_FEC = (0 |		MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |		MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);}static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep){	volatile fec_t *fecp;	fecp = fep->hwp;	fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;	fecp->fec_x_cntrl = 0x00;	/*	 * Set MII speed to 2.5 MHz	 */	fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;	fecp->fec_mii_speed = fep->phy_speed;	fec_restart(dev, 0);}static void __inline__ fec_get_mac(struct net_device *dev){	struct fec_enet_private *fep = netdev_priv(dev);	volatile fec_t *fecp;	unsigned char *iap, tmpaddr[ETH_ALEN];	fecp = fep->hwp;	if (FEC_FLASHMAC) {		/*		 * Get MAC address from FLASH.		 * If it is all 1's or 0's, use the default.		 */		iap = FEC_FLASHMAC;		if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&		    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))			iap = fec_mac_default;		if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&		    (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))			iap = fec_mac_default;	} else {		*((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;		*((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);		iap = &tmpaddr[0];	}	memcpy(dev->dev_addr, iap, ETH_ALEN);	/* Adjust MAC if using default MAC address */	if (iap == fec_mac_default)		dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;}static void __inline__ fec_enable_phy_intr(void){}static void __inline__ fec_disable_phy_intr(void){}static void __inline__ fec_phy_ack_intr(void){}static void __inline__ fec_localhw_setup(void){}/* *	Do not need to make region uncached on 532x. */static void __inline__ fec_uncache(unsigned long addr){}/* ------------------------------------------------------------------------- */#else/* *	Code specific to the MPC860T setup. */static void __inline__ fec_request_intrs(struct net_device *dev){	volatile immap_t *immap;	immap = (immap_t *)IMAP_ADDR;	/* pointer to internal registers */	if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0)		panic("Could not allocate FEC IRQ!");#ifdef CONFIG_RPXCLASSIC	/* Make Port C, bit 15 an input that causes interrupts.	*/	immap->im_ioport.iop_pcpar &= ~0x0001;	immap->im_ioport.iop_pcdir &= ~0x0001;	immap->im_ioport.iop_pcso &= ~0x0001;	immap->im_ioport.iop_pcint |= 0x0001;	cpm_install_handler(CPMVEC_PIO_PC15, mii_link_interrupt, dev);	/* Make LEDS reflect Link status.	*/	*((uint *) RPX_CSR_ADDR) &= ~BCSR2_FETHLEDMODE;#endif#ifdef CONFIG_FADS	if (request_8xxirq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0)		panic("Could not allocate MII IRQ!");#endif}static void __inline__ fec_get_mac(struct net_device *dev){	bd_t *bd;	bd = (bd_t *)__res;	memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);#ifdef CONFIG_RPXCLASSIC	/* The Embedded Planet boards have only one MAC address in	 * the EEPROM, but can have two Ethernet ports.  For the	 * FEC port, we create another address by setting one of	 * the address bits above something that would have (up to	 * now) been allocated.	 */	dev->dev_adrd[3] |= 0x80;#endif}static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep){	extern uint _get_IMMR(void);	volatile immap_t *immap;	volatile fec_t *fecp;	fecp = fep->hwp;	immap = (immap_t *)IMAP_ADDR;	/* pointer to internal registers */	/* Configure all of port D for MII.	*/	immap->im_ioport.iop_pdpar = 0x1fff;	/* Bits moved from Rev. D onward.	*/	if ((_get_IMMR() & 0xffff) < 0x0501)		immap->im_ioport.iop_pddir = 0x1c58;	/* Pre rev. D */	else		immap->im_ioport.iop_pddir = 0x1fff;	/* Rev. D and later */	/* Set MII speed to 2.5 MHz	*/	fecp->fec_mii_speed = fep->phy_speed =		((bd->bi_busfreq * 1000000) / 2500000) & 0x7e;}static void __inline__ fec_enable_phy_intr(void){	volatile fec_t *fecp;	fecp = fep->hwp;	/* Enable MII command finished interrupt	*/	fecp->fec_ivec = (FEC_INTERRUPT/2) << 29;}static void __inline__ fec_disable_phy_intr(void){}static void __inline__ fec_phy_ack_intr(void){}static void __inline__ fec_localhw_setup(void){	volatile fec_t *fecp;	fecp = fep->hwp;	fecp->fec_r_hash = PKT_MAXBUF_SIZE;	/* Enable big endian and don't care about SDMA FC.	*/	fecp->fec_fun_code = 0x78000000;}static void __inline__ fec_uncache(unsigned long addr){	pte_t *pte;	pte = va_to_pte(mem_addr);	pte_val(*pte) |= _PAGE_NO_CACHE;	flush_tlb_page(init_mm.mmap, mem_addr);}#endif/* ------------------------------------------------------------------------- */static void mii_display_status(struct net_device *dev){	struct fec_enet_private *fep = netdev_priv(dev);	volatile uint *s = &(fep->phy_status);	if (!fep->link && !fep->old_link) {		/* Link is still down - don't print anything */		return;	}	printk("%s: status: ", dev->name);	if (!fep->link) {		printk("link down");	} else {		printk("link up");		switch(*s & PHY_STAT_SPMASK) {		case PHY_STAT_100FDX: printk(", 100MBit Full Duplex"); break;		case PHY_STAT_100HDX: printk(", 100MBit Half Duplex"); break;		case PHY_STAT_10FDX: printk(", 10MBit Full Duplex"); break;		case PHY_STAT_10HDX: printk(", 10MBit Half Duplex"); break;		default:			printk(", Unknown speed/duplex");		}		if (*s & PHY_STAT_ANC)			printk(", auto-negotiation complete");	}	if (*s & PHY_STAT_FAULT)		printk(", remote fault");	printk(".\n");}static void mii_display_config(struct work_struct *work){	struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task);	struct net_device *dev = fep->netdev;	uint status = fep->phy_status;	/*	** When we get here, phy_task is already removed from	** the workqueue.  It is thus safe to allow to reuse it.	*/	fep->mii_phy_task_queued = 0;	printk("%s: config: auto-negotiation ", dev->name);	if (status & PHY_CONF_ANE)		printk("on");	else		printk("off");	if (status & PHY_CONF_100FDX)		printk(", 100FDX");	if (status & PHY_CONF_100HDX)		printk(", 100HDX");	if (status & PHY_CONF_10FDX)		printk(", 10FDX");	if (status & PHY_CONF_10HDX)		printk(", 10HDX");	if (!(status & PHY_CONF_SPMASK))		printk(", No speed/duplex selected?");	if (status & PHY_CONF_LOOP)		printk(", loopback enabled");	printk(".\n");	fep->sequence_done = 1;}static void mii_relink(struct work_struct *work){

⌨️ 快捷键说明

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