Lines Matching +full:mac +full:- +full:clk +full:- +full:rx

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Hisilicon Fast Ethernet MAC Driver
9 #include <linux/clk.h>
18 /* MAC control register list */
38 #define HW_RX_FIFO_DEPTH (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH)
84 #define MAX_MULTICAST_ADDRESSES (MAX_MAC_FILTER_NUM - \
86 /* software tx and rx queue number, should be power of 2 */
91 #define PHY_RESET_DELAYS_PROPERTY "hisilicon,phy-reset-delays-us"
111 struct clk *clk; member
130 val = readl(priv->glb_base + GLB_IRQ_ENA); in hisi_femac_irq_enable()
131 writel(val | irqs, priv->glb_base + GLB_IRQ_ENA); in hisi_femac_irq_enable()
138 val = readl(priv->glb_base + GLB_IRQ_ENA); in hisi_femac_irq_disable()
139 writel(val & (~irqs), priv->glb_base + GLB_IRQ_ENA); in hisi_femac_irq_disable()
147 dma_addr = priv->txq.dma_phys[pos]; in hisi_femac_tx_dma_unmap()
148 dma_unmap_single(priv->dev, dma_addr, skb->len, DMA_TO_DEVICE); in hisi_femac_tx_dma_unmap()
155 struct hisi_femac_queue *txq = &priv->txq; in hisi_femac_xmit_reclaim()
161 val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK; in hisi_femac_xmit_reclaim()
162 while (val < priv->tx_fifo_used_cnt) { in hisi_femac_xmit_reclaim()
163 skb = txq->skb[txq->tail]; in hisi_femac_xmit_reclaim()
166 val, priv->tx_fifo_used_cnt); in hisi_femac_xmit_reclaim()
169 hisi_femac_tx_dma_unmap(priv, skb, txq->tail); in hisi_femac_xmit_reclaim()
171 bytes_compl += skb->len; in hisi_femac_xmit_reclaim()
174 priv->tx_fifo_used_cnt--; in hisi_femac_xmit_reclaim()
176 val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK; in hisi_femac_xmit_reclaim()
177 txq->skb[txq->tail] = NULL; in hisi_femac_xmit_reclaim()
178 txq->tail = (txq->tail + 1) % txq->num; in hisi_femac_xmit_reclaim()
192 struct phy_device *phy = dev->phydev; in hisi_femac_adjust_link()
195 if (phy->link) in hisi_femac_adjust_link()
197 if (phy->duplex == DUPLEX_FULL) in hisi_femac_adjust_link()
199 if (phy->speed == SPEED_100) in hisi_femac_adjust_link()
202 if ((status != priv->link_status) && in hisi_femac_adjust_link()
203 ((status | priv->link_status) & MAC_PORTSET_LINKED)) { in hisi_femac_adjust_link()
204 writel(status, priv->port_base + MAC_PORTSET); in hisi_femac_adjust_link()
205 priv->link_status = status; in hisi_femac_adjust_link()
212 struct hisi_femac_queue *rxq = &priv->rxq; in hisi_femac_rx_refill()
218 pos = rxq->head; in hisi_femac_rx_refill()
219 while (readl(priv->port_base + ADDRQ_STAT) & BIT_RX_READY) { in hisi_femac_rx_refill()
220 if (!CIRC_SPACE(pos, rxq->tail, rxq->num)) in hisi_femac_rx_refill()
222 if (unlikely(rxq->skb[pos])) { in hisi_femac_rx_refill()
223 netdev_err(priv->ndev, "err skb[%d]=%p\n", in hisi_femac_rx_refill()
224 pos, rxq->skb[pos]); in hisi_femac_rx_refill()
227 skb = netdev_alloc_skb_ip_align(priv->ndev, len); in hisi_femac_rx_refill()
231 addr = dma_map_single(priv->dev, skb->data, len, in hisi_femac_rx_refill()
233 if (dma_mapping_error(priv->dev, addr)) { in hisi_femac_rx_refill()
237 rxq->dma_phys[pos] = addr; in hisi_femac_rx_refill()
238 rxq->skb[pos] = skb; in hisi_femac_rx_refill()
239 writel(addr, priv->port_base + IQ_ADDR); in hisi_femac_rx_refill()
240 pos = (pos + 1) % rxq->num; in hisi_femac_rx_refill()
242 rxq->head = pos; in hisi_femac_rx_refill()
248 struct hisi_femac_queue *rxq = &priv->rxq; in hisi_femac_rx()
253 pos = rxq->tail; in hisi_femac_rx()
254 while (readl(priv->glb_base + GLB_IRQ_RAW) & IRQ_INT_RX_RDY) { in hisi_femac_rx()
255 rx_pkt_info = readl(priv->port_base + IQFRM_DES); in hisi_femac_rx()
257 len -= ETH_FCS_LEN; in hisi_femac_rx()
260 writel(IRQ_INT_RX_RDY, priv->glb_base + GLB_IRQ_RAW); in hisi_femac_rx()
264 skb = rxq->skb[pos]; in hisi_femac_rx()
266 netdev_err(dev, "rx skb NULL. pos=%d\n", pos); in hisi_femac_rx()
269 rxq->skb[pos] = NULL; in hisi_femac_rx()
271 addr = rxq->dma_phys[pos]; in hisi_femac_rx()
272 dma_unmap_single(priv->dev, addr, MAX_FRAME_SIZE, in hisi_femac_rx()
275 if (unlikely(skb->len > MAX_FRAME_SIZE)) { in hisi_femac_rx()
276 netdev_err(dev, "rcv len err, len = %d\n", skb->len); in hisi_femac_rx()
277 dev->stats.rx_errors++; in hisi_femac_rx()
278 dev->stats.rx_length_errors++; in hisi_femac_rx()
283 skb->protocol = eth_type_trans(skb, dev); in hisi_femac_rx()
284 napi_gro_receive(&priv->napi, skb); in hisi_femac_rx()
285 dev->stats.rx_packets++; in hisi_femac_rx()
286 dev->stats.rx_bytes += len; in hisi_femac_rx()
288 pos = (pos + 1) % rxq->num; in hisi_femac_rx()
292 rxq->tail = pos; in hisi_femac_rx()
303 struct net_device *dev = priv->ndev; in hisi_femac_poll()
311 task -= num; in hisi_femac_poll()
315 ints = readl(priv->glb_base + GLB_IRQ_RAW); in hisi_femac_poll()
317 priv->glb_base + GLB_IRQ_RAW); in hisi_femac_poll()
335 ints = readl(priv->glb_base + GLB_IRQ_RAW); in hisi_femac_interrupt()
339 priv->glb_base + GLB_IRQ_RAW); in hisi_femac_interrupt()
341 napi_schedule(&priv->napi); in hisi_femac_interrupt()
351 queue->skb = devm_kcalloc(dev, num, sizeof(struct sk_buff *), in hisi_femac_init_queue()
353 if (!queue->skb) in hisi_femac_init_queue()
354 return -ENOMEM; in hisi_femac_init_queue()
356 queue->dma_phys = devm_kcalloc(dev, num, sizeof(dma_addr_t), in hisi_femac_init_queue()
358 if (!queue->dma_phys) in hisi_femac_init_queue()
359 return -ENOMEM; in hisi_femac_init_queue()
361 queue->num = num; in hisi_femac_init_queue()
362 queue->head = 0; in hisi_femac_init_queue()
363 queue->tail = 0; in hisi_femac_init_queue()
372 ret = hisi_femac_init_queue(priv->dev, &priv->txq, TXQ_NUM); in hisi_femac_init_tx_and_rx_queues()
376 ret = hisi_femac_init_queue(priv->dev, &priv->rxq, RXQ_NUM); in hisi_femac_init_tx_and_rx_queues()
380 priv->tx_fifo_used_cnt = 0; in hisi_femac_init_tx_and_rx_queues()
387 struct hisi_femac_queue *txq = &priv->txq; in hisi_femac_free_skb_rings()
388 struct hisi_femac_queue *rxq = &priv->rxq; in hisi_femac_free_skb_rings()
393 pos = rxq->tail; in hisi_femac_free_skb_rings()
394 while (pos != rxq->head) { in hisi_femac_free_skb_rings()
395 skb = rxq->skb[pos]; in hisi_femac_free_skb_rings()
397 netdev_err(priv->ndev, "NULL rx skb. pos=%d, head=%d\n", in hisi_femac_free_skb_rings()
398 pos, rxq->head); in hisi_femac_free_skb_rings()
402 dma_addr = rxq->dma_phys[pos]; in hisi_femac_free_skb_rings()
403 dma_unmap_single(priv->dev, dma_addr, MAX_FRAME_SIZE, in hisi_femac_free_skb_rings()
407 rxq->skb[pos] = NULL; in hisi_femac_free_skb_rings()
408 pos = (pos + 1) % rxq->num; in hisi_femac_free_skb_rings()
410 rxq->tail = pos; in hisi_femac_free_skb_rings()
412 pos = txq->tail; in hisi_femac_free_skb_rings()
413 while (pos != txq->head) { in hisi_femac_free_skb_rings()
414 skb = txq->skb[pos]; in hisi_femac_free_skb_rings()
416 netdev_err(priv->ndev, "NULL tx skb. pos=%d, head=%d\n", in hisi_femac_free_skb_rings()
417 pos, txq->head); in hisi_femac_free_skb_rings()
422 txq->skb[pos] = NULL; in hisi_femac_free_skb_rings()
423 pos = (pos + 1) % txq->num; in hisi_femac_free_skb_rings()
425 txq->tail = pos; in hisi_femac_free_skb_rings()
426 priv->tx_fifo_used_cnt = 0; in hisi_femac_free_skb_rings()
430 const unsigned char *mac) in hisi_femac_set_hw_mac_addr() argument
434 reg = mac[1] | (mac[0] << 8); in hisi_femac_set_hw_mac_addr()
435 writel(reg, priv->glb_base + GLB_HOSTMAC_H16); in hisi_femac_set_hw_mac_addr()
437 reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24); in hisi_femac_set_hw_mac_addr()
438 writel(reg, priv->glb_base + GLB_HOSTMAC_L32); in hisi_femac_set_hw_mac_addr()
447 val = readl(priv->glb_base + GLB_SOFT_RESET); in hisi_femac_port_reset()
449 writel(val, priv->glb_base + GLB_SOFT_RESET); in hisi_femac_port_reset()
454 writel(val, priv->glb_base + GLB_SOFT_RESET); in hisi_femac_port_reset()
464 hisi_femac_set_hw_mac_addr(priv, dev->dev_addr); in hisi_femac_net_open()
470 napi_enable(&priv->napi); in hisi_femac_net_open()
472 priv->link_status = 0; in hisi_femac_net_open()
473 if (dev->phydev) in hisi_femac_net_open()
474 phy_start(dev->phydev); in hisi_femac_net_open()
476 writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW); in hisi_femac_net_open()
488 if (dev->phydev) in hisi_femac_net_close()
489 phy_stop(dev->phydev); in hisi_femac_net_close()
492 napi_disable(&priv->napi); in hisi_femac_net_close()
503 struct hisi_femac_queue *txq = &priv->txq; in hisi_femac_net_xmit()
507 val = readl(priv->port_base + ADDRQ_STAT); in hisi_femac_net_xmit()
511 dev->stats.tx_dropped++; in hisi_femac_net_xmit()
512 dev->stats.tx_fifo_errors++; in hisi_femac_net_xmit()
517 if (unlikely(!CIRC_SPACE(txq->head, txq->tail, in hisi_femac_net_xmit()
518 txq->num))) { in hisi_femac_net_xmit()
520 dev->stats.tx_dropped++; in hisi_femac_net_xmit()
521 dev->stats.tx_fifo_errors++; in hisi_femac_net_xmit()
526 addr = dma_map_single(priv->dev, skb->data, in hisi_femac_net_xmit()
527 skb->len, DMA_TO_DEVICE); in hisi_femac_net_xmit()
528 if (unlikely(dma_mapping_error(priv->dev, addr))) { in hisi_femac_net_xmit()
530 dev->stats.tx_dropped++; in hisi_femac_net_xmit()
533 txq->dma_phys[txq->head] = addr; in hisi_femac_net_xmit()
535 txq->skb[txq->head] = skb; in hisi_femac_net_xmit()
536 txq->head = (txq->head + 1) % txq->num; in hisi_femac_net_xmit()
538 writel(addr, priv->port_base + EQ_ADDR); in hisi_femac_net_xmit()
539 writel(skb->len + ETH_FCS_LEN, priv->port_base + EQFRM_LEN); in hisi_femac_net_xmit()
541 priv->tx_fifo_used_cnt++; in hisi_femac_net_xmit()
543 dev->stats.tx_packets++; in hisi_femac_net_xmit()
544 dev->stats.tx_bytes += skb->len; in hisi_femac_net_xmit()
545 netdev_sent_queue(dev, skb->len); in hisi_femac_net_xmit()
555 if (!is_valid_ether_addr(skaddr->sa_data)) in hisi_femac_set_mac_address()
556 return -EADDRNOTAVAIL; in hisi_femac_set_mac_address()
558 eth_hw_addr_set(dev, skaddr->sa_data); in hisi_femac_set_mac_address()
559 dev->addr_assign_type &= ~NET_ADDR_RANDOM; in hisi_femac_set_mac_address()
561 hisi_femac_set_hw_mac_addr(priv, dev->dev_addr); in hisi_femac_set_mac_address()
571 val = readl(priv->glb_base + GLB_MAC_H16(reg_n)); in hisi_femac_enable_hw_addr_filter()
576 writel(val, priv->glb_base + GLB_MAC_H16(reg_n)); in hisi_femac_enable_hw_addr_filter()
590 writel(val, priv->glb_base + low); in hisi_femac_set_hw_addr_filter()
592 val = readl(priv->glb_base + high); in hisi_femac_set_hw_addr_filter()
596 writel(val, priv->glb_base + high); in hisi_femac_set_hw_addr_filter()
604 val = readl(priv->glb_base + GLB_FWCTRL); in hisi_femac_set_promisc_mode()
609 writel(val, priv->glb_base + GLB_FWCTRL); in hisi_femac_set_promisc_mode()
615 struct net_device *dev = priv->ndev; in hisi_femac_set_mc_addr_filter()
618 val = readl(priv->glb_base + GLB_MACTCTRL); in hisi_femac_set_mc_addr_filter()
620 (dev->flags & IFF_ALLMULTI)) { in hisi_femac_set_mc_addr_filter()
631 hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); in hisi_femac_set_mc_addr_filter()
636 writel(val, priv->glb_base + GLB_MACTCTRL); in hisi_femac_set_mc_addr_filter()
642 struct net_device *dev = priv->ndev; in hisi_femac_set_uc_addr_filter()
645 val = readl(priv->glb_base + GLB_MACTCTRL); in hisi_femac_set_uc_addr_filter()
657 hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); in hisi_femac_set_uc_addr_filter()
662 writel(val, priv->glb_base + GLB_MACTCTRL); in hisi_femac_set_uc_addr_filter()
669 if (dev->flags & IFF_PROMISC) { in hisi_femac_net_set_rx_mode()
695 reset_control_assert(priv->mac_rst); in hisi_femac_core_reset()
696 reset_control_deassert(priv->mac_rst); in hisi_femac_core_reset()
719 reset_control_deassert(priv->phy_rst); in hisi_femac_phy_reset()
720 hisi_femac_sleep_us(priv->phy_reset_delays[PRE_DELAY]); in hisi_femac_phy_reset()
722 reset_control_assert(priv->phy_rst); in hisi_femac_phy_reset()
726 hisi_femac_sleep_us(priv->phy_reset_delays[PULSE]); in hisi_femac_phy_reset()
727 reset_control_deassert(priv->phy_rst); in hisi_femac_phy_reset()
729 hisi_femac_sleep_us(priv->phy_reset_delays[POST_DELAY]); in hisi_femac_phy_reset()
736 /* MAC gets link status info and phy mode by software config */ in hisi_femac_port_init()
738 if (priv->ndev->phydev->interface == PHY_INTERFACE_MODE_RMII) in hisi_femac_port_init()
740 writel(val, priv->port_base + MAC_PORTSEL); in hisi_femac_port_init()
743 writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW); in hisi_femac_port_init()
746 val = readl(priv->glb_base + GLB_FWCTRL); in hisi_femac_port_init()
749 writel(val, priv->glb_base + GLB_FWCTRL); in hisi_femac_port_init()
751 val = readl(priv->glb_base + GLB_MACTCTRL); in hisi_femac_port_init()
753 writel(val, priv->glb_base + GLB_MACTCTRL); in hisi_femac_port_init()
755 val = readl(priv->port_base + MAC_SET); in hisi_femac_port_init()
758 writel(val, priv->port_base + MAC_SET); in hisi_femac_port_init()
762 writel(val, priv->port_base + RX_COALESCE_SET); in hisi_femac_port_init()
765 writel(val, priv->port_base + QLEN_SET); in hisi_femac_port_init()
770 struct device *dev = &pdev->dev; in hisi_femac_drv_probe()
771 struct device_node *node = dev->of_node; in hisi_femac_drv_probe()
779 return -ENOMEM; in hisi_femac_drv_probe()
782 SET_NETDEV_DEV(ndev, &pdev->dev); in hisi_femac_drv_probe()
785 priv->dev = dev; in hisi_femac_drv_probe()
786 priv->ndev = ndev; in hisi_femac_drv_probe()
788 priv->port_base = devm_platform_ioremap_resource(pdev, 0); in hisi_femac_drv_probe()
789 if (IS_ERR(priv->port_base)) { in hisi_femac_drv_probe()
790 ret = PTR_ERR(priv->port_base); in hisi_femac_drv_probe()
794 priv->glb_base = devm_platform_ioremap_resource(pdev, 1); in hisi_femac_drv_probe()
795 if (IS_ERR(priv->glb_base)) { in hisi_femac_drv_probe()
796 ret = PTR_ERR(priv->glb_base); in hisi_femac_drv_probe()
800 priv->clk = devm_clk_get(&pdev->dev, NULL); in hisi_femac_drv_probe()
801 if (IS_ERR(priv->clk)) { in hisi_femac_drv_probe()
802 dev_err(dev, "failed to get clk\n"); in hisi_femac_drv_probe()
803 ret = -ENODEV; in hisi_femac_drv_probe()
807 ret = clk_prepare_enable(priv->clk); in hisi_femac_drv_probe()
809 dev_err(dev, "failed to enable clk %d\n", ret); in hisi_femac_drv_probe()
813 priv->mac_rst = devm_reset_control_get(dev, "mac"); in hisi_femac_drv_probe()
814 if (IS_ERR(priv->mac_rst)) { in hisi_femac_drv_probe()
815 ret = PTR_ERR(priv->mac_rst); in hisi_femac_drv_probe()
820 priv->phy_rst = devm_reset_control_get(dev, "phy"); in hisi_femac_drv_probe()
821 if (IS_ERR(priv->phy_rst)) { in hisi_femac_drv_probe()
822 priv->phy_rst = NULL; in hisi_femac_drv_probe()
826 priv->phy_reset_delays, in hisi_femac_drv_probe()
836 ret = -ENODEV; in hisi_femac_drv_probe()
841 (unsigned long)phy->phy_id, in hisi_femac_drv_probe()
842 phy_modes(phy->interface)); in hisi_femac_drv_probe()
847 dev_warn(dev, "using random MAC address %pM\n", in hisi_femac_drv_probe()
848 ndev->dev_addr); in hisi_femac_drv_probe()
851 ndev->watchdog_timeo = 6 * HZ; in hisi_femac_drv_probe()
852 ndev->priv_flags |= IFF_UNICAST_FLT; in hisi_femac_drv_probe()
853 ndev->netdev_ops = &hisi_femac_netdev_ops; in hisi_femac_drv_probe()
854 ndev->ethtool_ops = &hisi_femac_ethtools_ops; in hisi_femac_drv_probe()
855 netif_napi_add_weight(ndev, &priv->napi, hisi_femac_poll, in hisi_femac_drv_probe()
864 ndev->irq = platform_get_irq(pdev, 0); in hisi_femac_drv_probe()
865 if (ndev->irq < 0) { in hisi_femac_drv_probe()
866 ret = ndev->irq; in hisi_femac_drv_probe()
870 ret = devm_request_irq(dev, ndev->irq, hisi_femac_interrupt, in hisi_femac_drv_probe()
871 IRQF_SHARED, pdev->name, ndev); in hisi_femac_drv_probe()
873 dev_err(dev, "devm_request_irq %d failed!\n", ndev->irq); in hisi_femac_drv_probe()
886 netif_napi_del(&priv->napi); in hisi_femac_drv_probe()
889 clk_disable_unprepare(priv->clk); in hisi_femac_drv_probe()
901 netif_napi_del(&priv->napi); in hisi_femac_drv_remove()
904 phy_disconnect(ndev->phydev); in hisi_femac_drv_remove()
905 clk_disable_unprepare(priv->clk); in hisi_femac_drv_remove()
916 disable_irq(ndev->irq); in hisi_femac_drv_suspend()
922 clk_disable_unprepare(priv->clk); in hisi_femac_drv_suspend()
932 clk_prepare_enable(priv->clk); in hisi_femac_drv_resume()
933 if (priv->phy_rst) in hisi_femac_drv_resume()
941 enable_irq(ndev->irq); in hisi_femac_drv_resume()
948 {.compatible = "hisilicon,hisi-femac-v1",},
949 {.compatible = "hisilicon,hisi-femac-v2",},
950 {.compatible = "hisilicon,hi3516cv300-femac",},
958 .name = "hisi-femac",
971 MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC driver");
974 MODULE_ALIAS("platform:hisi-femac");