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 + -
显示快捷键?