fec.c

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

C
2,492
字号
	switch((mii_reg >> 2) & 7) {	case 1: status |= PHY_STAT_10HDX; break;	case 2: status |= PHY_STAT_100HDX; break;	case 5: status |= PHY_STAT_10FDX; break;	case 6: status |= PHY_STAT_100FDX; break;}	*s = status;}static phy_cmd_t const phy_cmd_qs6612_config[] = {		/* The PHY powers up isolated on the RPX,		 * so send a command to allow operation.		 */		{ mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL },		/* parse cr and anar to get some info */		{ mk_mii_read(MII_REG_CR), mii_parse_cr },		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_qs6612_startup[] = {  /* enable interrupts */		{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_qs6612_ack_int[] = {		/* we need to read ISR, SR and ANER to acknowledge */		{ mk_mii_read(MII_QS6612_ISR), NULL },		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_read(MII_REG_ANER), NULL },		/* read pcr to get info */		{ mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */		{ mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },		{ mk_mii_end, }	};static phy_info_t const phy_info_qs6612 = {	.id = 0x00181440,	.name = "QS6612",	.config = phy_cmd_qs6612_config,	.startup = phy_cmd_qs6612_startup,	.ack_int = phy_cmd_qs6612_ack_int,	.shutdown = phy_cmd_qs6612_shutdown};/* ------------------------------------------------------------------------- *//* AMD AM79C874 phy                                                          *//* register definitions for the 874 */#define MII_AM79C874_MFR       16  /* Miscellaneous Feature Register */#define MII_AM79C874_ICSR      17  /* Interrupt/Status Register      */#define MII_AM79C874_DR        18  /* Diagnostic Register            */#define MII_AM79C874_PMLR      19  /* Power and Loopback Register    */#define MII_AM79C874_MCR       21  /* ModeControl Register           */#define MII_AM79C874_DC        23  /* Disconnect Counter             */#define MII_AM79C874_REC       24  /* Recieve Error Counter          */static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev){	struct fec_enet_private *fep = netdev_priv(dev);	volatile uint *s = &(fep->phy_status);	uint status;	status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);	if (mii_reg & 0x0080)		status |= PHY_STAT_ANC;	if (mii_reg & 0x0400)		status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);	else		status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);	*s = status;}static phy_cmd_t const phy_cmd_am79c874_config[] = {		{ mk_mii_read(MII_REG_CR), mii_parse_cr },		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },		{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_am79c874_startup[] = {  /* enable interrupts */		{ mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_am79c874_ack_int[] = {		/* find out the current status */		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },		/* we only need to read ISR to acknowledge */		{ mk_mii_read(MII_AM79C874_ICSR), NULL },		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */		{ mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },		{ mk_mii_end, }	};static phy_info_t const phy_info_am79c874 = {	.id = 0x00022561,	.name = "AM79C874",	.config = phy_cmd_am79c874_config,	.startup = phy_cmd_am79c874_startup,	.ack_int = phy_cmd_am79c874_ack_int,	.shutdown = phy_cmd_am79c874_shutdown};/* ------------------------------------------------------------------------- *//* Kendin KS8721BL phy                                                       *//* register definitions for the 8721 */#define MII_KS8721BL_RXERCR	21#define MII_KS8721BL_ICSR	22#define	MII_KS8721BL_PHYCR	31static phy_cmd_t const phy_cmd_ks8721bl_config[] = {		{ mk_mii_read(MII_REG_CR), mii_parse_cr },		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_ks8721bl_startup[] = {  /* enable interrupts */		{ mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL },		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = {		/* find out the current status */		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		/* we only need to read ISR to acknowledge */		{ mk_mii_read(MII_KS8721BL_ICSR), NULL },		{ mk_mii_end, }	};static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */		{ mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL },		{ mk_mii_end, }	};static phy_info_t const phy_info_ks8721bl = {	.id = 0x00022161,	.name = "KS8721BL",	.config = phy_cmd_ks8721bl_config,	.startup = phy_cmd_ks8721bl_startup,	.ack_int = phy_cmd_ks8721bl_ack_int,	.shutdown = phy_cmd_ks8721bl_shutdown};/* ------------------------------------------------------------------------- *//* register definitions for the DP83848 */#define MII_DP8384X_PHYSTST    16  /* PHY Status Register */static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	volatile uint *s = &(fep->phy_status);	*s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);	/* Link up */	if (mii_reg & 0x0001) {		fep->link = 1;		*s |= PHY_STAT_LINK;	} else		fep->link = 0;	/* Status of link */	if (mii_reg & 0x0010)   /* Autonegotioation complete */		*s |= PHY_STAT_ANC;	if (mii_reg & 0x0002) {   /* 10MBps? */		if (mii_reg & 0x0004)   /* Full Duplex? */			*s |= PHY_STAT_10FDX;		else			*s |= PHY_STAT_10HDX;	} else {                  /* 100 Mbps? */		if (mii_reg & 0x0004)   /* Full Duplex? */			*s |= PHY_STAT_100FDX;		else			*s |= PHY_STAT_100HDX;	}	if (mii_reg & 0x0008)		*s |= PHY_STAT_FAULT;}static phy_info_t phy_info_dp83848= {	0x020005c9,	"DP83848",	(const phy_cmd_t []) {  /* config */		{ mk_mii_read(MII_REG_CR), mii_parse_cr },		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },		{ mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 },		{ mk_mii_end, }	},	(const phy_cmd_t []) {  /* startup - enable interrupts */		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_end, }	},	(const phy_cmd_t []) { /* ack_int - never happens, no interrupt */		{ mk_mii_end, }	},	(const phy_cmd_t []) {  /* shutdown */		{ mk_mii_end, }	},};/* ------------------------------------------------------------------------- */static phy_info_t const * const phy_info[] = {	&phy_info_lxt970,	&phy_info_lxt971,	&phy_info_qs6612,	&phy_info_am79c874,	&phy_info_ks8721bl,	&phy_info_dp83848,	NULL};/* ------------------------------------------------------------------------- */#if !defined(CONFIG_M532x)#ifdef CONFIG_RPXCLASSICstatic voidmii_link_interrupt(void *dev_id);#elsestatic irqreturn_tmii_link_interrupt(int irq, void * dev_id);#endif#endif#if defined(CONFIG_M5272)/* *	Code specific to Coldfire 5272 setup. */static void __inline__ fec_request_intrs(struct net_device *dev){	volatile unsigned long *icrp;	static const struct idesc {		char *name;		unsigned short irq;		irq_handler_t handler;	} *idp, id[] = {		{ "fec(RX)", 86, fec_enet_interrupt },		{ "fec(TX)", 87, fec_enet_interrupt },		{ "fec(OTHER)", 88, fec_enet_interrupt },		{ "fec(MII)", 66, mii_link_interrupt },		{ NULL },	};	/* Setup interrupt handlers. */	for (idp = id; idp->name; idp++) {		if (request_irq(idp->irq, idp->handler, 0, idp->name, dev) != 0)			printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, idp->irq);	}	/* Unmask interrupt at ColdFire 5272 SIM */	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);	*icrp = 0x00000ddd;	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);	*icrp = 0x0d000000;}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 5272 manual section 11.5.8: MSCR	 */	fep->phy_speed = ((((MCF_CLK / 4) / (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 = (unsigned char *)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){	volatile unsigned long *icrp;	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);	*icrp = 0x08000000;}static void __inline__ fec_phy_ack_intr(void){	volatile unsigned long *icrp;	/* Acknowledge the interrupt */	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);	*icrp = 0x0d000000;}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_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)/* *	Code specific to Coldfire 5230/5231/5232/5234/5235, *	the 5270/5271/5274/5275 and 5280/5282 setups. */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 = (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 at ColdFire 5280/5282 interrupt controller */	{		volatile unsigned char  *icrp;		volatile unsigned long  *imrp;		int i, ilip;		b = (fep->index) ? MCFICM_INTC1 : MCFICM_INTC0;		icrp = (volatile unsigned char *) (MCF_IPSBAR + b +			MCFINTC_ICR0);		for (i = 23, ilip = 0x28; (i < 36); i++)			icrp[i] = ilip--;		imrp = (volatile unsigned long *) (MCF_IPSBAR + b +			MCFINTC_IMRH);		*imrp &= ~0x0000000f;		imrp = (volatile unsigned long *) (MCF_IPSBAR + b +			MCFINTC_IMRL);		*imrp &= ~0xff800001;	}#if defined(CONFIG_M528x)	/* Set up gpio outputs for MII lines */	{		volatile u16 *gpio_paspar;		volatile u8 *gpio_pehlpar;		gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);		gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);		*gpio_paspar |= 0x0f00;		*gpio_pehlpar = 0xc0;	}#endif#if defined(CONFIG_M527x)	/* Set up gpio outputs for MII lines */	{		volatile u8 *gpio_par_fec;		volatile u16 *gpio_par_feci2c;		gpio_par_feci2c = (volatile u16 *)(MCF_IPSBAR + 0x100082);		/* Set up gpio outputs for FEC0 MII lines */		gpio_par_fec = (volatile u8 *)(MCF_IPSBAR + 0x100078);		*gpio_par_feci2c |= 0x0f00;		*gpio_par_fec |= 0xc0;#if defined(CONFIG_FEC2)		/* Set up gpio outputs for FEC1 MII lines */		gpio_par_fec = (volatile u8 *)(MCF_IPSBAR + 0x100079);		*gpio_par_feci2c |= 0x00a0;		*gpio_par_fec |= 0xc0;#endif /* CONFIG_FEC2 */	}#endif /* CONFIG_M527x */}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)

⌨️ 快捷键说明

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