From d635711daa98be86d4c7fd01499c34f566b54ccb Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Fri, 10 Jun 2016 05:30:17 -0300 Subject: Linux-libre 4.6.2-gnu --- drivers/net/ethernet/ezchip/nps_enet.c | 248 +++++++++++++---------- drivers/net/ethernet/ezchip/nps_enet.h | 350 +++++++++++---------------------- 2 files changed, 260 insertions(+), 338 deletions(-) (limited to 'drivers/net/ethernet/ezchip') diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c index b1026689b..085f9125c 100644 --- a/drivers/net/ethernet/ezchip/nps_enet.c +++ b/drivers/net/ethernet/ezchip/nps_enet.c @@ -43,20 +43,21 @@ static void nps_enet_read_rx_fifo(struct net_device *ndev, bool dst_is_aligned = IS_ALIGNED((unsigned long)dst, sizeof(u32)); /* In case dst is not aligned we need an intermediate buffer */ - if (dst_is_aligned) - for (i = 0; i < len; i++, reg++) - *reg = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF); + if (dst_is_aligned) { + ioread32_rep(priv->regs_base + NPS_ENET_REG_RX_BUF, reg, len); + reg += len; + } else { /* !dst_is_aligned */ for (i = 0; i < len; i++, reg++) { u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF); - put_unaligned(buf, reg); + put_unaligned_be32(buf, reg); } } - /* copy last bytes (if any) */ if (last) { - u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF); - memcpy((u8*)reg, &buf, last); + u32 buf; + ioread32_rep(priv->regs_base + NPS_ENET_REG_RX_BUF, &buf, 1); + memcpy((u8 *)reg, &buf, last); } } @@ -66,26 +67,28 @@ static u32 nps_enet_rx_handler(struct net_device *ndev) u32 work_done = 0; struct nps_enet_priv *priv = netdev_priv(ndev); struct sk_buff *skb; - struct nps_enet_rx_ctl rx_ctrl; + u32 rx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); + u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT; + u32 rx_ctrl_er = (rx_ctrl_value & RX_CTL_ER_MASK) >> RX_CTL_ER_SHIFT; + u32 rx_ctrl_crc = (rx_ctrl_value & RX_CTL_CRC_MASK) >> RX_CTL_CRC_SHIFT; - rx_ctrl.value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); - frame_len = rx_ctrl.nr; + frame_len = (rx_ctrl_value & RX_CTL_NR_MASK) >> RX_CTL_NR_SHIFT; /* Check if we got RX */ - if (!rx_ctrl.cr) + if (!rx_ctrl_cr) return work_done; /* If we got here there is a work for us */ work_done++; /* Check Rx error */ - if (rx_ctrl.er) { + if (rx_ctrl_er) { ndev->stats.rx_errors++; err = 1; } /* Check Rx CRC error */ - if (rx_ctrl.crc) { + if (rx_ctrl_crc) { ndev->stats.rx_crc_errors++; ndev->stats.rx_dropped++; err = 1; @@ -136,27 +139,28 @@ rx_irq_frame_done: static void nps_enet_tx_handler(struct net_device *ndev) { struct nps_enet_priv *priv = netdev_priv(ndev); - struct nps_enet_tx_ctl tx_ctrl; - - tx_ctrl.value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); + u32 tx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); + u32 tx_ctrl_ct = (tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT; + u32 tx_ctrl_et = (tx_ctrl_value & TX_CTL_ET_MASK) >> TX_CTL_ET_SHIFT; + u32 tx_ctrl_nt = (tx_ctrl_value & TX_CTL_NT_MASK) >> TX_CTL_NT_SHIFT; /* Check if we got TX */ - if (!priv->tx_packet_sent || tx_ctrl.ct) + if (!priv->tx_skb || tx_ctrl_ct) return; /* Ack Tx ctrl register */ nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, 0); /* Check Tx transmit error */ - if (unlikely(tx_ctrl.et)) { + if (unlikely(tx_ctrl_et)) { ndev->stats.tx_errors++; } else { ndev->stats.tx_packets++; - ndev->stats.tx_bytes += tx_ctrl.nt; + ndev->stats.tx_bytes += tx_ctrl_nt; } dev_kfree_skb(priv->tx_skb); - priv->tx_packet_sent = false; + priv->tx_skb = NULL; if (netif_queue_stopped(ndev)) netif_wake_queue(ndev); @@ -178,13 +182,31 @@ static int nps_enet_poll(struct napi_struct *napi, int budget) nps_enet_tx_handler(ndev); work_done = nps_enet_rx_handler(ndev); if (work_done < budget) { - struct nps_enet_buf_int_enable buf_int_enable; + u32 buf_int_enable_value = 0; + u32 tx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); + u32 tx_ctrl_ct = + (tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT; napi_complete(napi); - buf_int_enable.rx_rdy = NPS_ENET_ENABLE; - buf_int_enable.tx_done = NPS_ENET_ENABLE; + + /* set tx_done and rx_rdy bits */ + buf_int_enable_value |= NPS_ENET_ENABLE << RX_RDY_SHIFT; + buf_int_enable_value |= NPS_ENET_ENABLE << TX_DONE_SHIFT; + nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, - buf_int_enable.value); + buf_int_enable_value); + + /* in case we will get a tx interrupt while interrupts + * are masked, we will lose it since the tx is edge interrupt. + * specifically, while executing the code section above, + * between nps_enet_tx_handler and the interrupts enable, all + * tx requests will be stuck until we will get an rx interrupt. + * the two code lines below will solve this situation by + * re-adding ourselves to the poll list. + */ + + if (priv->tx_skb && !tx_ctrl_ct) + napi_reschedule(napi); } return work_done; @@ -205,13 +227,12 @@ static irqreturn_t nps_enet_irq_handler(s32 irq, void *dev_instance) { struct net_device *ndev = dev_instance; struct nps_enet_priv *priv = netdev_priv(ndev); - struct nps_enet_rx_ctl rx_ctrl; - struct nps_enet_tx_ctl tx_ctrl; - - rx_ctrl.value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); - tx_ctrl.value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); + u32 rx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); + u32 tx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); + u32 tx_ctrl_ct = (tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT; + u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT; - if ((!tx_ctrl.ct && priv->tx_packet_sent) || rx_ctrl.cr) + if ((!tx_ctrl_ct && priv->tx_skb) || rx_ctrl_cr) if (likely(napi_schedule_prep(&priv->napi))) { nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0); __napi_schedule(&priv->napi); @@ -223,22 +244,24 @@ static irqreturn_t nps_enet_irq_handler(s32 irq, void *dev_instance) static void nps_enet_set_hw_mac_address(struct net_device *ndev) { struct nps_enet_priv *priv = netdev_priv(ndev); - struct nps_enet_ge_mac_cfg_1 ge_mac_cfg_1; - struct nps_enet_ge_mac_cfg_2 *ge_mac_cfg_2 = &priv->ge_mac_cfg_2; + u32 ge_mac_cfg_1_value = 0; + u32 *ge_mac_cfg_2_value = &priv->ge_mac_cfg_2_value; /* set MAC address in HW */ - ge_mac_cfg_1.octet_0 = ndev->dev_addr[0]; - ge_mac_cfg_1.octet_1 = ndev->dev_addr[1]; - ge_mac_cfg_1.octet_2 = ndev->dev_addr[2]; - ge_mac_cfg_1.octet_3 = ndev->dev_addr[3]; - ge_mac_cfg_2->octet_4 = ndev->dev_addr[4]; - ge_mac_cfg_2->octet_5 = ndev->dev_addr[5]; + ge_mac_cfg_1_value |= ndev->dev_addr[0] << CFG_1_OCTET_0_SHIFT; + ge_mac_cfg_1_value |= ndev->dev_addr[1] << CFG_1_OCTET_1_SHIFT; + ge_mac_cfg_1_value |= ndev->dev_addr[2] << CFG_1_OCTET_2_SHIFT; + ge_mac_cfg_1_value |= ndev->dev_addr[3] << CFG_1_OCTET_3_SHIFT; + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_OCTET_4_MASK) + | ndev->dev_addr[4] << CFG_2_OCTET_4_SHIFT; + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_OCTET_5_MASK) + | ndev->dev_addr[5] << CFG_2_OCTET_5_SHIFT; nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_1, - ge_mac_cfg_1.value); + ge_mac_cfg_1_value); nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, - ge_mac_cfg_2->value); + *ge_mac_cfg_2_value); } /** @@ -254,93 +277,97 @@ static void nps_enet_set_hw_mac_address(struct net_device *ndev) static void nps_enet_hw_reset(struct net_device *ndev) { struct nps_enet_priv *priv = netdev_priv(ndev); - struct nps_enet_ge_rst ge_rst; - struct nps_enet_phase_fifo_ctl phase_fifo_ctl; + u32 ge_rst_value = 0, phase_fifo_ctl_value = 0; - ge_rst.value = 0; - phase_fifo_ctl.value = 0; /* Pcs reset sequence*/ - ge_rst.gmac_0 = NPS_ENET_ENABLE; - nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, ge_rst.value); + ge_rst_value |= NPS_ENET_ENABLE << RST_GMAC_0_SHIFT; + nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, ge_rst_value); usleep_range(10, 20); - ge_rst.value = 0; - nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, ge_rst.value); + nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, ge_rst_value); /* Tx fifo reset sequence */ - phase_fifo_ctl.rst = NPS_ENET_ENABLE; - phase_fifo_ctl.init = NPS_ENET_ENABLE; + phase_fifo_ctl_value |= NPS_ENET_ENABLE << PHASE_FIFO_CTL_RST_SHIFT; + phase_fifo_ctl_value |= NPS_ENET_ENABLE << PHASE_FIFO_CTL_INIT_SHIFT; nps_enet_reg_set(priv, NPS_ENET_REG_PHASE_FIFO_CTL, - phase_fifo_ctl.value); + phase_fifo_ctl_value); usleep_range(10, 20); - phase_fifo_ctl.value = 0; + phase_fifo_ctl_value = 0; nps_enet_reg_set(priv, NPS_ENET_REG_PHASE_FIFO_CTL, - phase_fifo_ctl.value); + phase_fifo_ctl_value); } static void nps_enet_hw_enable_control(struct net_device *ndev) { struct nps_enet_priv *priv = netdev_priv(ndev); - struct nps_enet_ge_mac_cfg_0 ge_mac_cfg_0; - struct nps_enet_buf_int_enable buf_int_enable; - struct nps_enet_ge_mac_cfg_2 *ge_mac_cfg_2 = &priv->ge_mac_cfg_2; - struct nps_enet_ge_mac_cfg_3 *ge_mac_cfg_3 = &priv->ge_mac_cfg_3; + u32 ge_mac_cfg_0_value = 0, buf_int_enable_value = 0; + u32 *ge_mac_cfg_2_value = &priv->ge_mac_cfg_2_value; + u32 *ge_mac_cfg_3_value = &priv->ge_mac_cfg_3_value; s32 max_frame_length; - ge_mac_cfg_0.value = 0; - buf_int_enable.value = 0; /* Enable Rx and Tx statistics */ - ge_mac_cfg_2->stat_en = NPS_ENET_GE_MAC_CFG_2_STAT_EN; + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_STAT_EN_MASK) + | NPS_ENET_GE_MAC_CFG_2_STAT_EN << CFG_2_STAT_EN_SHIFT; /* Discard packets with different MAC address */ - ge_mac_cfg_2->disc_da = NPS_ENET_ENABLE; + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) + | NPS_ENET_ENABLE << CFG_2_DISK_DA_SHIFT; /* Discard multicast packets */ - ge_mac_cfg_2->disc_mc = NPS_ENET_ENABLE; + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) + | NPS_ENET_ENABLE << CFG_2_DISK_MC_SHIFT; nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, - ge_mac_cfg_2->value); + *ge_mac_cfg_2_value); /* Discard Packets bigger than max frame length */ max_frame_length = ETH_HLEN + ndev->mtu + ETH_FCS_LEN; - if (max_frame_length <= NPS_ENET_MAX_FRAME_LENGTH) - ge_mac_cfg_3->max_len = max_frame_length; + if (max_frame_length <= NPS_ENET_MAX_FRAME_LENGTH) { + *ge_mac_cfg_3_value = + (*ge_mac_cfg_3_value & ~CFG_3_MAX_LEN_MASK) + | max_frame_length << CFG_3_MAX_LEN_SHIFT; + } /* Enable interrupts */ - buf_int_enable.rx_rdy = NPS_ENET_ENABLE; - buf_int_enable.tx_done = NPS_ENET_ENABLE; + buf_int_enable_value |= NPS_ENET_ENABLE << RX_RDY_SHIFT; + buf_int_enable_value |= NPS_ENET_ENABLE << TX_DONE_SHIFT; nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, - buf_int_enable.value); + buf_int_enable_value); /* Write device MAC address to HW */ nps_enet_set_hw_mac_address(ndev); /* Rx and Tx HW features */ - ge_mac_cfg_0.tx_pad_en = NPS_ENET_ENABLE; - ge_mac_cfg_0.tx_crc_en = NPS_ENET_ENABLE; - ge_mac_cfg_0.rx_crc_strip = NPS_ENET_ENABLE; + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_PAD_EN_SHIFT; + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_CRC_EN_SHIFT; + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_CRC_STRIP_SHIFT; /* IFG configuration */ - ge_mac_cfg_0.rx_ifg = NPS_ENET_GE_MAC_CFG_0_RX_IFG; - ge_mac_cfg_0.tx_ifg = NPS_ENET_GE_MAC_CFG_0_TX_IFG; + ge_mac_cfg_0_value |= + NPS_ENET_GE_MAC_CFG_0_RX_IFG << CFG_0_RX_IFG_SHIFT; + ge_mac_cfg_0_value |= + NPS_ENET_GE_MAC_CFG_0_TX_IFG << CFG_0_TX_IFG_SHIFT; /* preamble configuration */ - ge_mac_cfg_0.rx_pr_check_en = NPS_ENET_ENABLE; - ge_mac_cfg_0.tx_pr_len = NPS_ENET_GE_MAC_CFG_0_TX_PR_LEN; + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_PR_CHECK_EN_SHIFT; + ge_mac_cfg_0_value |= + NPS_ENET_GE_MAC_CFG_0_TX_PR_LEN << CFG_0_TX_PR_LEN_SHIFT; /* enable flow control frames */ - ge_mac_cfg_0.tx_fc_en = NPS_ENET_ENABLE; - ge_mac_cfg_0.rx_fc_en = NPS_ENET_ENABLE; - ge_mac_cfg_0.tx_fc_retr = NPS_ENET_GE_MAC_CFG_0_TX_FC_RETR; - ge_mac_cfg_3->cf_drop = NPS_ENET_ENABLE; + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_FC_EN_SHIFT; + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_FC_EN_SHIFT; + ge_mac_cfg_0_value |= + NPS_ENET_GE_MAC_CFG_0_TX_FC_RETR << CFG_0_TX_FC_RETR_SHIFT; + *ge_mac_cfg_3_value = (*ge_mac_cfg_3_value & ~CFG_3_CF_DROP_MASK) + | NPS_ENET_ENABLE << CFG_3_CF_DROP_SHIFT; /* Enable Rx and Tx */ - ge_mac_cfg_0.rx_en = NPS_ENET_ENABLE; - ge_mac_cfg_0.tx_en = NPS_ENET_ENABLE; + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_EN_SHIFT; + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_EN_SHIFT; nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_3, - ge_mac_cfg_3->value); + *ge_mac_cfg_3_value); nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_0, - ge_mac_cfg_0.value); + ge_mac_cfg_0_value); } static void nps_enet_hw_disable_control(struct net_device *ndev) @@ -358,31 +385,26 @@ static void nps_enet_send_frame(struct net_device *ndev, struct sk_buff *skb) { struct nps_enet_priv *priv = netdev_priv(ndev); - struct nps_enet_tx_ctl tx_ctrl; + u32 tx_ctrl_value = 0; short length = skb->len; u32 i, len = DIV_ROUND_UP(length, sizeof(u32)); u32 *src = (void *)skb->data; bool src_is_aligned = IS_ALIGNED((unsigned long)src, sizeof(u32)); - tx_ctrl.value = 0; /* In case src is not aligned we need an intermediate buffer */ if (src_is_aligned) - for (i = 0; i < len; i++, src++) - nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, *src); + iowrite32_rep(priv->regs_base + NPS_ENET_REG_TX_BUF, src, len); else /* !src_is_aligned */ for (i = 0; i < len; i++, src++) nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, - get_unaligned(src)); + get_unaligned_be32(src)); /* Write the length of the Frame */ - tx_ctrl.nt = length; - - /* Indicate SW is done */ - priv->tx_packet_sent = true; - tx_ctrl.ct = NPS_ENET_ENABLE; + tx_ctrl_value |= length << TX_CTL_NT_SHIFT; + tx_ctrl_value |= NPS_ENET_ENABLE << TX_CTL_CT_SHIFT; /* Send Frame */ - nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, tx_ctrl.value); + nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, tx_ctrl_value); } /** @@ -422,19 +444,23 @@ static s32 nps_enet_set_mac_address(struct net_device *ndev, void *p) static void nps_enet_set_rx_mode(struct net_device *ndev) { struct nps_enet_priv *priv = netdev_priv(ndev); - struct nps_enet_ge_mac_cfg_2 ge_mac_cfg_2; - - ge_mac_cfg_2.value = priv->ge_mac_cfg_2.value; + u32 ge_mac_cfg_2_value = priv->ge_mac_cfg_2_value; if (ndev->flags & IFF_PROMISC) { - ge_mac_cfg_2.disc_da = NPS_ENET_DISABLE; - ge_mac_cfg_2.disc_mc = NPS_ENET_DISABLE; + ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) + | NPS_ENET_DISABLE << CFG_2_DISK_DA_SHIFT; + ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) + | NPS_ENET_DISABLE << CFG_2_DISK_MC_SHIFT; + } else { - ge_mac_cfg_2.disc_da = NPS_ENET_ENABLE; - ge_mac_cfg_2.disc_mc = NPS_ENET_ENABLE; + ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) + | NPS_ENET_ENABLE << CFG_2_DISK_DA_SHIFT; + ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) + | NPS_ENET_ENABLE << CFG_2_DISK_MC_SHIFT; + } - nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, ge_mac_cfg_2.value); + nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, ge_mac_cfg_2_value); } /** @@ -452,13 +478,16 @@ static s32 nps_enet_open(struct net_device *ndev) s32 err; /* Reset private variables */ - priv->tx_packet_sent = false; - priv->ge_mac_cfg_2.value = 0; - priv->ge_mac_cfg_3.value = 0; + priv->tx_skb = NULL; + priv->ge_mac_cfg_2_value = 0; + priv->ge_mac_cfg_3_value = 0; /* ge_mac_cfg_3 default values */ - priv->ge_mac_cfg_3.rx_ifg_th = NPS_ENET_GE_MAC_CFG_3_RX_IFG_TH; - priv->ge_mac_cfg_3.max_len = NPS_ENET_GE_MAC_CFG_3_MAX_LEN; + priv->ge_mac_cfg_3_value |= + NPS_ENET_GE_MAC_CFG_3_RX_IFG_TH << CFG_3_RX_IFG_TH_SHIFT; + + priv->ge_mac_cfg_3_value |= + NPS_ENET_GE_MAC_CFG_3_MAX_LEN << CFG_3_MAX_LEN_SHIFT; /* Disable HW device */ nps_enet_hw_disable_control(ndev); @@ -518,6 +547,11 @@ static netdev_tx_t nps_enet_start_xmit(struct sk_buff *skb, priv->tx_skb = skb; + /* make sure tx_skb is actually written to the memory + * before the HW is informed and the IRQ is fired. + */ + wmb(); + nps_enet_send_frame(ndev, skb); return NETDEV_TX_OK; diff --git a/drivers/net/ethernet/ezchip/nps_enet.h b/drivers/net/ethernet/ezchip/nps_enet.h index 6703674d6..3939ca20c 100644 --- a/drivers/net/ethernet/ezchip/nps_enet.h +++ b/drivers/net/ethernet/ezchip/nps_enet.h @@ -43,250 +43,138 @@ #define NPS_ENET_REG_GE_RST 0x1400 #define NPS_ENET_REG_PHASE_FIFO_CTL 0x1404 -/* Tx control register */ -struct nps_enet_tx_ctl { - union { - /* ct: SW sets to indicate frame ready in Tx buffer for - * transmission. HW resets to when transmission done - * et: Transmit error - * nt: Length in bytes of Tx frame loaded to Tx buffer - */ - struct { - u32 - __reserved_1:16, - ct:1, - et:1, - __reserved_2:3, - nt:11; - }; - - u32 value; - }; -}; - -/* Rx control register */ -struct nps_enet_rx_ctl { - union { - /* cr: HW sets to indicate frame ready in Rx buffer. - * SW resets to indicate host read received frame - * and new frames can be written to Rx buffer - * er: Rx error indication - * crc: Rx CRC error indication - * nr: Length in bytes of Rx frame loaded by MAC to Rx buffer - */ - struct { - u32 - __reserved_1:16, - cr:1, - er:1, - crc:1, - __reserved_2:2, - nr:11; - }; - - u32 value; - }; -}; - -/* Interrupt enable for data buffer events register */ -struct nps_enet_buf_int_enable { - union { - /* tx_done: Interrupt generation in the case when new frame - * is ready in Rx buffer - * rx_rdy: Interrupt generation in the case when current frame - * was read from TX buffer - */ - struct { - u32 - __reserved:30, - tx_done:1, - rx_rdy:1; - }; - - u32 value; - }; -}; - -/* Gbps Eth MAC Configuration 0 register */ -struct nps_enet_ge_mac_cfg_0 { - union { - /* tx_pr_len: Transmit preamble length in bytes - * tx_ifg_nib: Tx idle pattern - * nib_mode: Nibble (4-bit) Mode - * rx_pr_check_en: Receive preamble Check Enable - * tx_ifg: Transmit inter-Frame Gap - * rx_ifg: Receive inter-Frame Gap - * tx_fc_retr: Transmit Flow Control Retransmit Mode - * rx_length_check_en: Receive Length Check Enable - * rx_crc_ignore: Results of the CRC check are ignored - * rx_crc_strip: MAC strips the CRC from received frames - * rx_fc_en: Receive Flow Control Enable - * tx_crc_en: Transmit CRC Enabled - * tx_pad_en: Transmit Padding Enable - * tx_cf_en: Transmit Flow Control Enable - * tx_en: Transmit Enable - * rx_en: Receive Enable - */ - struct { - u32 - tx_pr_len:4, - tx_ifg_nib:4, - nib_mode:1, - rx_pr_check_en:1, - tx_ifg:6, - rx_ifg:4, - tx_fc_retr:3, - rx_length_check_en:1, - rx_crc_ignore:1, - rx_crc_strip:1, - rx_fc_en:1, - tx_crc_en:1, - tx_pad_en:1, - tx_fc_en:1, - tx_en:1, - rx_en:1; - }; - - u32 value; - }; -}; - -/* Gbps Eth MAC Configuration 1 register */ -struct nps_enet_ge_mac_cfg_1 { - union { - /* octet_3: MAC address octet 3 - * octet_2: MAC address octet 2 - * octet_1: MAC address octet 1 - * octet_0: MAC address octet 0 - */ - struct { - u32 - octet_3:8, - octet_2:8, - octet_1:8, - octet_0:8; - }; - - u32 value; - }; -}; - -/* Gbps Eth MAC Configuration 2 register */ -struct nps_enet_ge_mac_cfg_2 { - union { - /* transmit_flush_en: MAC flush enable - * stat_en: RMON statistics interface enable - * disc_da: Discard frames with DA different - * from MAC address - * disc_bc: Discard broadcast frames - * disc_mc: Discard multicast frames - * octet_5: MAC address octet 5 - * octet_4: MAC address octet 4 - */ - struct { - u32 - transmit_flush_en:1, - __reserved_1:5, - stat_en:2, - __reserved_2:1, - disc_da:1, - disc_bc:1, - disc_mc:1, - __reserved_3:4, - octet_5:8, - octet_4:8; - }; - - u32 value; - }; -}; - -/* Gbps Eth MAC Configuration 3 register */ -struct nps_enet_ge_mac_cfg_3 { - union { - /* ext_oob_cbfc_sel: Selects one of the 4 profiles for - * extended OOB in-flow-control indication - * max_len: Maximum receive frame length in bytes - * tx_cbfc_en: Enable transmission of class-based - * flow control packets - * rx_ifg_th: Threshold for IFG status reporting via OOB - * cf_timeout: Configurable time to decrement FC counters - * cf_drop: Drop control frames - * redirect_cbfc_sel: Selects one of CBFC redirect profiles - * rx_cbfc_redir_en: Enable Rx class-based flow - * control redirect - * rx_cbfc_en: Enable Rx class-based flow control - * tm_hd_mode: TM header mode - */ - struct { - u32 - ext_oob_cbfc_sel:2, - max_len:14, - tx_cbfc_en:1, - rx_ifg_th:5, - cf_timeout:4, - cf_drop:1, - redirect_cbfc_sel:2, - rx_cbfc_redir_en:1, - rx_cbfc_en:1, - tm_hd_mode:1; - }; - - u32 value; - }; -}; - -/* GE MAC, PCS reset control register */ -struct nps_enet_ge_rst { - union { - /* gmac_0: GE MAC reset - * spcs_0: SGMII PCS reset - */ - struct { - u32 - __reserved_1:23, - gmac_0:1, - __reserved_2:7, - spcs_0:1; - }; - - u32 value; - }; -}; - -/* Tx phase sync FIFO control register */ -struct nps_enet_phase_fifo_ctl { - union { - /* init: initialize serdes TX phase sync FIFO pointers - * rst: reset serdes TX phase sync FIFO - */ - struct { - u32 - __reserved:30, - init:1, - rst:1; - }; - - u32 value; - }; -}; +/* Tx control register masks and shifts */ +#define TX_CTL_NT_MASK 0x7FF +#define TX_CTL_NT_SHIFT 0 +#define TX_CTL_ET_MASK 0x4000 +#define TX_CTL_ET_SHIFT 14 +#define TX_CTL_CT_MASK 0x8000 +#define TX_CTL_CT_SHIFT 15 + +/* Rx control register masks and shifts */ +#define RX_CTL_NR_MASK 0x7FF +#define RX_CTL_NR_SHIFT 0 +#define RX_CTL_CRC_MASK 0x2000 +#define RX_CTL_CRC_SHIFT 13 +#define RX_CTL_ER_MASK 0x4000 +#define RX_CTL_ER_SHIFT 14 +#define RX_CTL_CR_MASK 0x8000 +#define RX_CTL_CR_SHIFT 15 + +/* Interrupt enable for data buffer events register masks and shifts */ +#define RX_RDY_MASK 0x1 +#define RX_RDY_SHIFT 0 +#define TX_DONE_MASK 0x2 +#define TX_DONE_SHIFT 1 + +/* Gbps Eth MAC Configuration 0 register masks and shifts */ +#define CFG_0_RX_EN_MASK 0x1 +#define CFG_0_RX_EN_SHIFT 0 +#define CFG_0_TX_EN_MASK 0x2 +#define CFG_0_TX_EN_SHIFT 1 +#define CFG_0_TX_FC_EN_MASK 0x4 +#define CFG_0_TX_FC_EN_SHIFT 2 +#define CFG_0_TX_PAD_EN_MASK 0x8 +#define CFG_0_TX_PAD_EN_SHIFT 3 +#define CFG_0_TX_CRC_EN_MASK 0x10 +#define CFG_0_TX_CRC_EN_SHIFT 4 +#define CFG_0_RX_FC_EN_MASK 0x20 +#define CFG_0_RX_FC_EN_SHIFT 5 +#define CFG_0_RX_CRC_STRIP_MASK 0x40 +#define CFG_0_RX_CRC_STRIP_SHIFT 6 +#define CFG_0_RX_CRC_IGNORE_MASK 0x80 +#define CFG_0_RX_CRC_IGNORE_SHIFT 7 +#define CFG_0_RX_LENGTH_CHECK_EN_MASK 0x100 +#define CFG_0_RX_LENGTH_CHECK_EN_SHIFT 8 +#define CFG_0_TX_FC_RETR_MASK 0xE00 +#define CFG_0_TX_FC_RETR_SHIFT 9 +#define CFG_0_RX_IFG_MASK 0xF000 +#define CFG_0_RX_IFG_SHIFT 12 +#define CFG_0_TX_IFG_MASK 0x3F0000 +#define CFG_0_TX_IFG_SHIFT 16 +#define CFG_0_RX_PR_CHECK_EN_MASK 0x400000 +#define CFG_0_RX_PR_CHECK_EN_SHIFT 22 +#define CFG_0_NIB_MODE_MASK 0x800000 +#define CFG_0_NIB_MODE_SHIFT 23 +#define CFG_0_TX_IFG_NIB_MASK 0xF000000 +#define CFG_0_TX_IFG_NIB_SHIFT 24 +#define CFG_0_TX_PR_LEN_MASK 0xF0000000 +#define CFG_0_TX_PR_LEN_SHIFT 28 + +/* Gbps Eth MAC Configuration 1 register masks and shifts */ +#define CFG_1_OCTET_0_MASK 0x000000FF +#define CFG_1_OCTET_0_SHIFT 0 +#define CFG_1_OCTET_1_MASK 0x0000FF00 +#define CFG_1_OCTET_1_SHIFT 8 +#define CFG_1_OCTET_2_MASK 0x00FF0000 +#define CFG_1_OCTET_2_SHIFT 16 +#define CFG_1_OCTET_3_MASK 0xFF000000 +#define CFG_1_OCTET_3_SHIFT 24 + +/* Gbps Eth MAC Configuration 2 register masks and shifts */ +#define CFG_2_OCTET_4_MASK 0x000000FF +#define CFG_2_OCTET_4_SHIFT 0 +#define CFG_2_OCTET_5_MASK 0x0000FF00 +#define CFG_2_OCTET_5_SHIFT 8 +#define CFG_2_DISK_MC_MASK 0x00100000 +#define CFG_2_DISK_MC_SHIFT 20 +#define CFG_2_DISK_BC_MASK 0x00200000 +#define CFG_2_DISK_BC_SHIFT 21 +#define CFG_2_DISK_DA_MASK 0x00400000 +#define CFG_2_DISK_DA_SHIFT 22 +#define CFG_2_STAT_EN_MASK 0x3000000 +#define CFG_2_STAT_EN_SHIFT 24 +#define CFG_2_TRANSMIT_FLUSH_EN_MASK 0x80000000 +#define CFG_2_TRANSMIT_FLUSH_EN_SHIFT 31 + +/* Gbps Eth MAC Configuration 3 register masks and shifts */ +#define CFG_3_TM_HD_MODE_MASK 0x1 +#define CFG_3_TM_HD_MODE_SHIFT 0 +#define CFG_3_RX_CBFC_EN_MASK 0x2 +#define CFG_3_RX_CBFC_EN_SHIFT 1 +#define CFG_3_RX_CBFC_REDIR_EN_MASK 0x4 +#define CFG_3_RX_CBFC_REDIR_EN_SHIFT 2 +#define CFG_3_REDIRECT_CBFC_SEL_MASK 0x18 +#define CFG_3_REDIRECT_CBFC_SEL_SHIFT 3 +#define CFG_3_CF_DROP_MASK 0x20 +#define CFG_3_CF_DROP_SHIFT 5 +#define CFG_3_CF_TIMEOUT_MASK 0x3C0 +#define CFG_3_CF_TIMEOUT_SHIFT 6 +#define CFG_3_RX_IFG_TH_MASK 0x7C00 +#define CFG_3_RX_IFG_TH_SHIFT 10 +#define CFG_3_TX_CBFC_EN_MASK 0x8000 +#define CFG_3_TX_CBFC_EN_SHIFT 15 +#define CFG_3_MAX_LEN_MASK 0x3FFF0000 +#define CFG_3_MAX_LEN_SHIFT 16 +#define CFG_3_EXT_OOB_CBFC_SEL_MASK 0xC0000000 +#define CFG_3_EXT_OOB_CBFC_SEL_SHIFT 30 + +/* GE MAC, PCS reset control register masks and shifts */ +#define RST_SPCS_MASK 0x1 +#define RST_SPCS_SHIFT 0 +#define RST_GMAC_0_MASK 0x100 +#define RST_GMAC_0_SHIFT 8 + +/* Tx phase sync FIFO control register masks and shifts */ +#define PHASE_FIFO_CTL_RST_MASK 0x1 +#define PHASE_FIFO_CTL_RST_SHIFT 0 +#define PHASE_FIFO_CTL_INIT_MASK 0x2 +#define PHASE_FIFO_CTL_INIT_SHIFT 1 /** * struct nps_enet_priv - Storage of ENET's private information. * @regs_base: Base address of ENET memory-mapped control registers. * @irq: For RX/TX IRQ number. - * @tx_packet_sent: SW indication if frame is being sent. * @tx_skb: socket buffer of sent frame. * @napi: Structure for NAPI. */ struct nps_enet_priv { void __iomem *regs_base; s32 irq; - bool tx_packet_sent; struct sk_buff *tx_skb; struct napi_struct napi; - struct nps_enet_ge_mac_cfg_2 ge_mac_cfg_2; - struct nps_enet_ge_mac_cfg_3 ge_mac_cfg_3; + u32 ge_mac_cfg_2_value; + u32 ge_mac_cfg_3_value; }; /** -- cgit v1.2.3-54-g00ecf