📄 mac-fec.c
字号:
* Set maximum receive buffer size. */ FW(fecp, r_buff_size, PKT_MAXBLR_SIZE); FW(fecp, r_hash, PKT_MAXBUF_SIZE); /* get physical address */ rx_bd_base_phys = fep->ring_mem_addr; tx_bd_base_phys = rx_bd_base_phys + sizeof(cbd_t) * fpi->rx_ring; /* * Set receive and transmit descriptor base. */ FW(fecp, r_des_start, rx_bd_base_phys); FW(fecp, x_des_start, tx_bd_base_phys); fs_init_bds(dev); /* * Enable big endian and don't care about SDMA FC. */ FW(fecp, fun_code, 0x78000000); /* * Set MII speed. */ FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed); /* * Clear any outstanding interrupt. */ FW(fecp, ievent, 0xffc0); FW(fecp, ivec, (fep->interrupt / 2) << 29); /* * adjust to speed (only for DUET & RMII) */#ifdef CONFIG_DUET if (fpi->use_rmii) { cptr = in_be32(&immap->im_cpm.cp_cptr); switch (fs_get_fec_index(fpi->fs_no)) { case 0: cptr |= 0x100; if (fep->speed == 10) cptr |= 0x0000010; else if (fep->speed == 100) cptr &= ~0x0000010; break; case 1: cptr |= 0x80; if (fep->speed == 10) cptr |= 0x0000008; else if (fep->speed == 100) cptr &= ~0x0000008; break; default: BUG(); /* should never happen */ break; } out_be32(&immap->im_cpm.cp_cptr, cptr); }#endif FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ /* * adjust to duplex mode */ if (fep->duplex) { FC(fecp, r_cntrl, FEC_RCNTRL_DRT); FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ } else { FS(fecp, r_cntrl, FEC_RCNTRL_DRT); FC(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD disable */ } /* * Enable interrupts we wish to service. */ FW(fecp, imask, FEC_ENET_TXF | FEC_ENET_TXB | FEC_ENET_RXF | FEC_ENET_RXB); /* * And last, enable the transmit and receive processing. */ FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); FW(fecp, r_des_active, 0x01000000);}static void stop(struct net_device *dev){ struct fs_enet_private *fep = netdev_priv(dev); fec_t *fecp = fep->fec.fecp; struct fs_enet_mii_bus *bus = fep->mii_bus; const struct fs_mii_bus_info *bi = bus->bus_info; int i; if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0) return; /* already down */ FW(fecp, x_cntrl, 0x01); /* Graceful transmit stop */ for (i = 0; ((FR(fecp, ievent) & 0x10000000) == 0) && i < FEC_RESET_DELAY; i++) udelay(1); if (i == FEC_RESET_DELAY) printk(KERN_WARNING DRV_MODULE_NAME ": %s FEC timeout on graceful transmit stop\n", dev->name); /* * Disable FEC. Let only MII interrupts. */ FW(fecp, imask, 0); FC(fecp, ecntrl, FEC_ECNTRL_ETHER_EN); fs_cleanup_bds(dev); /* shut down FEC1? that's where the mii bus is */ if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) { FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); FW(fecp, ievent, FEC_ENET_MII); FW(fecp, mii_speed, bus->fec.mii_speed); }}static void pre_request_irq(struct net_device *dev, int irq){ immap_t *immap = fs_enet_immap; u32 siel; /* SIU interrupt */ if (irq >= SIU_IRQ0 && irq < SIU_LEVEL7) { siel = in_be32(&immap->im_siu_conf.sc_siel); if ((irq & 1) == 0) siel |= (0x80000000 >> irq); else siel &= ~(0x80000000 >> (irq & ~1)); out_be32(&immap->im_siu_conf.sc_siel, siel); }}static void post_free_irq(struct net_device *dev, int irq){ /* nothing */}static void napi_clear_rx_event(struct net_device *dev){ struct fs_enet_private *fep = netdev_priv(dev); fec_t *fecp = fep->fec.fecp; FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK);}static void napi_enable_rx(struct net_device *dev){ struct fs_enet_private *fep = netdev_priv(dev); fec_t *fecp = fep->fec.fecp; FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK);}static void napi_disable_rx(struct net_device *dev){ struct fs_enet_private *fep = netdev_priv(dev); fec_t *fecp = fep->fec.fecp; FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);}static void rx_bd_done(struct net_device *dev){ struct fs_enet_private *fep = netdev_priv(dev); fec_t *fecp = fep->fec.fecp; FW(fecp, r_des_active, 0x01000000);}static void tx_kickstart(struct net_device *dev){ struct fs_enet_private *fep = netdev_priv(dev); fec_t *fecp = fep->fec.fecp; FW(fecp, x_des_active, 0x01000000);}static u32 get_int_events(struct net_device *dev){ struct fs_enet_private *fep = netdev_priv(dev); fec_t *fecp = fep->fec.fecp; return FR(fecp, ievent) & FR(fecp, imask);}static void clear_int_events(struct net_device *dev, u32 int_events){ struct fs_enet_private *fep = netdev_priv(dev); fec_t *fecp = fep->fec.fecp; FW(fecp, ievent, int_events);}static void ev_error(struct net_device *dev, u32 int_events){ printk(KERN_WARNING DRV_MODULE_NAME ": %s FEC ERROR(s) 0x%x\n", dev->name, int_events);}int get_regs(struct net_device *dev, void *p, int *sizep){ struct fs_enet_private *fep = netdev_priv(dev); if (*sizep < sizeof(fec_t)) return -EINVAL; memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t)); return 0;}int get_regs_len(struct net_device *dev){ return sizeof(fec_t);}void tx_restart(struct net_device *dev){ /* nothing */}/*************************************************************************/const struct fs_ops fs_fec_ops = { .setup_data = setup_data, .cleanup_data = cleanup_data, .set_multicast_list = set_multicast_list, .restart = restart, .stop = stop, .pre_request_irq = pre_request_irq, .post_free_irq = post_free_irq, .napi_clear_rx_event = napi_clear_rx_event, .napi_enable_rx = napi_enable_rx, .napi_disable_rx = napi_disable_rx, .rx_bd_done = rx_bd_done, .tx_kickstart = tx_kickstart, .get_int_events = get_int_events, .clear_int_events = clear_int_events, .ev_error = ev_error, .get_regs = get_regs, .get_regs_len = get_regs_len, .tx_restart = tx_restart, .allocate_bd = allocate_bd, .free_bd = free_bd,};/***********************************************************************/static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location){ fec_t *fecp = bus->fec.fecp; int i, ret = -1; if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) BUG(); /* Add PHY address to register command. */ FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location)); for (i = 0; i < FEC_MII_LOOPS; i++) if ((FR(fecp, ievent) & FEC_ENET_MII) != 0) break; if (i < FEC_MII_LOOPS) { FW(fecp, ievent, FEC_ENET_MII); ret = FR(fecp, mii_data) & 0xffff; } return ret;}static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value){ fec_t *fecp = bus->fec.fecp; int i; /* this must never happen */ if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) BUG(); /* Add PHY address to register command. */ FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value)); for (i = 0; i < FEC_MII_LOOPS; i++) if ((FR(fecp, ievent) & FEC_ENET_MII) != 0) break; if (i < FEC_MII_LOOPS) FW(fecp, ievent, FEC_ENET_MII);}int fs_mii_fec_init(struct fs_enet_mii_bus *bus){ bd_t *bd = (bd_t *)__res; const struct fs_mii_bus_info *bi = bus->bus_info; fec_t *fecp; if (bi->id != 0) return -1; bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec; bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; fecp = bus->fec.fecp; FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); FW(fecp, ievent, FEC_ENET_MII); FW(fecp, mii_speed, bus->fec.mii_speed); bus->mii_read = mii_read; bus->mii_write = mii_write; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -