static int _set_linkstat(struct hieth_netdev_local *ld, int mode) { int old; old = hieth_readl_bits(ld, UD_REG_NAME(MAC_PORTSET), BITS_MACSTAT); hieth_writel_bits(ld, mode, UD_REG_NAME(MAC_PORTSET), BITS_MACSTAT); return old; }
static int _set_negmode(struct hieth_netdev_local *ld, int mode) { int old; old = hieth_readl_bits(ld, UD_REG_NAME(MAC_PORTSEL), BITS_NEGMODE); hieth_writel_bits(ld, mode, UD_REG_NAME(MAC_PORTSEL), BITS_NEGMODE); return old; }
int hieth_set_endian_mode(struct hieth_netdev_local *ld, int mode) { int old; local_lock(ld); old = hieth_readl_bits(ld, GLB_ENDIAN_MOD, BITS_ENDIAN); hieth_writel_bits(ld, mode, GLB_ENDIAN_MOD, BITS_ENDIAN); local_unlock(ld); return old; }
int hieth_set_mac_fc_interval(struct hieth_netdev_local *ld, int para) { int old; local_lock(ld); old = hieth_readl_bits(ld, UD_REG_NAME(MAC_TX_IPGCTRL), BITS_FC_INTER); hieth_writel_bits(ld, para, UD_REG_NAME(MAC_TX_IPGCTRL), BITS_FC_INTER); local_unlock(ld); return old; }
int hieth_set_mii_mode(struct hieth_netdev_local *ld, int mode) { int old; local_lock(ld); old = hieth_readl_bits(ld, UD_REG_NAME(MAC_PORTSEL), BITS_MII_MODE); hieth_writel_bits(ld, mode, UD_REG_NAME(MAC_PORTSEL), BITS_MII_MODE); local_unlock(ld); return old; }
int hieth_set_mac_leadcode_cnt_limit(struct hieth_netdev_local *ld, int cnt) { int old; local_lock(ld); old = hieth_readl_bits(ld, UD_REG_NAME(MAC_TX_IPGCTRL), BITS_PRE_CNT_LIMIT); hieth_writel_bits(ld, cnt, UD_REG_NAME(MAC_TX_IPGCTRL), BITS_PRE_CNT_LIMIT); local_unlock(ld); return old; }
int hieth_port_reset(struct hieth_netdev_local *ld, int port) { hieth_assert(port == ld->port); /*soft reset*/ if (ld->port == UP_PORT) { /* Note: sf ip need reset twice */ hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_UP); msleep(20); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_UP); msleep(20); hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_UP); msleep(20); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_UP); } else if (ld->port == DOWN_PORT) { /* Note: sf ip need reset twice */ hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_DOWN); msleep(20); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_DOWN); msleep(20); hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_DOWN); msleep(20); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_DOWN); } else { BUG(); } return 0; }
int hieth_set_mac_trans_interval_bits(struct hieth_netdev_local *ld, int nbits) { int old; int linkstat, negmode; local_lock(ld); negmode = _set_negmode(ld, HIETH_NEGMODE_CPUSET); linkstat = _set_linkstat(ld, 0); udelay(1000); old = hieth_readl_bits(ld, UD_REG_NAME(MAC_TX_IPGCTRL), BITS_IPG); hieth_writel_bits(ld, nbits, UD_REG_NAME(MAC_TX_IPGCTRL), BITS_IPG); udelay(100); _set_negmode(ld, negmode); _set_linkstat(ld, linkstat); local_unlock(ld); return old; }
static int hieth_net_open(struct net_device *dev) { struct hieth_netdev_local *ld = netdev_priv(dev); unsigned int data; unsigned long phy_id; try_module_get(THIS_MODULE); /* init tasklet */ ld->bf_recv.next = NULL; ld->bf_recv.state = 0; ld->bf_recv.func = hieth_bfproc_recv; ld->bf_recv.data = (unsigned long)dev; atomic_set(&ld->bf_recv.count, 0); /* setup hardware */ hieth_set_hwq_depth(ld); hieth_clear_irqstatus(ld, UD_BIT_NAME(BITS_IRQS_MASK)); netif_carrier_off(dev); hieth_feed_hw(ld); netif_start_queue(dev); ld->link_stat = 0; phy_start(ld->phy); hieth_irq_enable(ld, UD_BIT_NAME(HIETH_INT_MULTI_RXRDY)); hieth_writel_bits(ld, 1, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS_ENA)); hieth_writel_bits(ld, 1, GLB_RW_IRQ_ENA, BITS_IRQS_ENA_ALLPORT); init_timer(&ld->monitor); ld->monitor.function = hieth_monitor_func; ld->monitor.data = (unsigned long)dev; ld->monitor.expires = jiffies + msecs_to_jiffies(CONFIG_HIETH_MONITOR_TIMER); add_timer(&ld->monitor); data = readl(ld->iobase + 0x210); data |= 0x40000000; /* do CRC check in mac*/ writel(data, ld->iobase + 0x210); phy_id = phy_id_read(); #ifdef CONFIG_EEE_SUPPORT hiphyinfo = phy_search_ids(phy_id); if (hiphyinfo) { eee_available = hiphyinfo->with_eee; if (DEBUG) printk(KERN_INFO "fit_phy_id : %x, phy_name: %s," "eee :%x\n", (unsigned int)hiphyinfo->phy_id, hiphyinfo->name, (unsigned int)eee_available); ld->driver = hiphyinfo->driver; if (eee_available > NO_EEE) { data = 0x0; data_tmp = ld->driver->eee_enable(); if (eee_available == MAC_EEE) { /* init EEE timer */ /* 0x35 only for FPGA(54M)*/ writel(0x35, ld->iobase + 0x494); writel(0x1e03e8, ld->iobase + 0x48c); writel(0xf42400, ld->iobase + 0x488); data = readl(ld->iobase + 0x490); data |= 0x2; writel(data, ld->iobase + 0x490); /* enable EEE */ writel(0x10, ld->iobase + 0x484); if (DEBUG) printk(KERN_INFO "mac eee mode start " "to enable, eee :%x\n", eee_available); data = readl(ld->iobase + 0x488); data |= 0x1; /* mac-eee_enable */ writel(data, ld->iobase + 0x488); } } } else { printk(KERN_INFO "non-EEE mode\n"); eee_available = NO_EEE; } #endif return 0; }
static irqreturn_t hieth_net_isr(int irq, void *dev_id) { int ints; struct hieth_netdev_local *ld; if (hieth_devs_save[UP_PORT]) ld = netdev_priv(hieth_devs_save[UP_PORT]); else if (hieth_devs_save[DOWN_PORT]) ld = netdev_priv(hieth_devs_save[DOWN_PORT]); else { BUG(); return IRQ_NONE; } /*mask the all interrupt*/ hieth_writel_bits(ld, 0, GLB_RW_IRQ_ENA, BITS_IRQS_ENA_ALLPORT); #ifdef CONFIG_EEE_SUPPORT if (eee_available == MAC_EEE) { /* what eee intr we get? */ eee_ints = readl(ld->iobase + 0x480); /* get ready for LPI */ if (eee_ints & TX_LPI_COND) { /* clear eee_intr status */ writel(0x10, ld->iobase + 0x480); data = readl(ld->iobase + 0x488); /* tx_lpi_assert enable */ data |= 0x2; writel(data, ld->iobase + 0x488); /*LPI entry*/ } if (eee_ints & TX_ENTRY_LPI) { /* clear eee_intr status */ writel(0x1, ld->iobase + 0x480); } if (eee_ints & TX_LEAVE_LPI) { /* clear eee_intr status */ writel(0x2, ld->iobase + 0x480); } } #endif ints = hieth_read_irqstatus(ld); if (likely(ints & BITS_IRQS_MASK_U) && hieth_devs_save[UP_PORT]) { hieth_net_isr_proc(netdev_priv(hieth_devs_save[UP_PORT]), (ints & BITS_IRQS_MASK_U)); hieth_clear_irqstatus(ld, (ints & BITS_IRQS_MASK_U)); ints &= ~BITS_IRQS_MASK_U; } if (likely(ints & BITS_IRQS_MASK_D) && hieth_devs_save[DOWN_PORT]) { hieth_net_isr_proc( netdev_priv(hieth_devs_save[DOWN_PORT]), (ints & BITS_IRQS_MASK_D)); hieth_clear_irqstatus(ld, (ints & BITS_IRQS_MASK_D)); ints &= ~BITS_IRQS_MASK_D; } if (unlikely(ints)) { hieth_error("unknown ints=0x%.8x\n", ints); hieth_clear_irqstatus(ld, ints); } /*unmask the all interrupt*/ hieth_writel_bits(ld, 1, GLB_RW_IRQ_ENA, BITS_IRQS_ENA_ALLPORT); return IRQ_HANDLED; }
int hieth_port_reset(struct hieth_netdev_local *ld, int port) { long long chipid = get_chipid(); hieth_assert(port == ld->port); /*soft reset */ if (chipid == _HI3712_V100) { hieth_writel_bits(ld, 1, GLB_SOFT_RESET, HI3712_BITS_ETH_SOFT_RESET); msleep(1); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, HI3712_BITS_ETH_SOFT_RESET); msleep(1); hieth_writel_bits(ld, 1, GLB_SOFT_RESET, HI3712_BITS_ETH_SOFT_RESET); msleep(1); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, HI3712_BITS_ETH_SOFT_RESET); } else { if (ld->port == UP_PORT) { /* Note: sf ip need reset twice */ hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_UP); msleep(1); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_UP); msleep(1); hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_UP); msleep(1); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_UP); } else if (ld->port == DOWN_PORT) { /* Note: sf ip need reset twice */ hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_DOWN); msleep(1); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_DOWN); msleep(1); hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_DOWN); msleep(1); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET_DOWN); } else BUG(); } return 0; }
int hieth_glb_preinit_dummy(struct hieth_netdev_local *ld) { local_lock_init(ld); //FIXME: hieth_glb_preinit_dummy //HW MAX DEFAULT RX-PKT-LEN [42,1518] //HW MAC FILTER TABLE DISABLE /*soft reset */ hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET); udelay(1000); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET); hieth_set_endian_mode(ld, HIETH_LITTLE_ENDIAN); hieth_set_linkstat(ld, 0); hieth_set_negmode(ld, HIETH_NEGMODE_CPUSET); /* RMII mode */ hieth_set_mii_mode(ld, UD_BIT_NAME(HIETH_MII_RMII_MODE)); hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS)); hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS_ENA)); hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, BITS_IRQS_ENA_ALLPORT); hieth_irq_disable(ld, ~0); /* init */ hieth_writel(ld, 0, GLB_FWCTRL); hieth_writel(ld, 0, GLB_MACTCTRL); /*disable vlan func */ hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_VLAN_ENABLE); /*enable UpEther<->CPU */ hieth_writel_bits(ld, 1, GLB_FWCTRL, BITS_FW2CPU_ENA_UP); hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_FWALL2CPU_UP); hieth_writel_bits(ld, 0, GLB_MACTCTRL, BITS_BROAD2CPU_UP); hieth_writel_bits(ld, 1, GLB_MACTCTRL, BITS_MACT_ENA_UP); /*enable DownEther<->CPU and UpEther<->CPU */ hieth_writel_bits(ld, 1, GLB_FWCTRL, BITS_FW2CPU_ENA_DOWN); hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_FWALL2CPU_DOWN); hieth_writel_bits(ld, 0, GLB_MACTCTRL, BITS_BROAD2CPU_DOWN); hieth_writel_bits(ld, 1, GLB_MACTCTRL, BITS_MACT_ENA_DOWN); hieth_set_mac_leadcode_cnt_limit(ld, 0); return 0; }