Lines Matching +full:ast2600 +full:- +full:scu

1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * (C) Copyright 2009-2011 Faraday Technology
6 * Po-Yu Chuang <ratbert@faraday-tech.com>
12 #include <linux/dma-mapping.h>
92 /* AST2500/AST2600 RMII ref clock gate */
116 struct net_device *netdev = priv->netdev; in ftgmac100_reset_mac()
120 iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR); in ftgmac100_reset_mac()
122 priv->base + FTGMAC100_OFFSET_MACCR); in ftgmac100_reset_mac()
126 maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR); in ftgmac100_reset_mac()
134 return -EIO; in ftgmac100_reset_mac()
141 switch (priv->cur_speed) { in ftgmac100_reset_and_config_mac()
154 netdev_err(priv->netdev, "Unknown speed %d !\n", in ftgmac100_reset_and_config_mac()
155 priv->cur_speed); in ftgmac100_reset_and_config_mac()
160 priv->rx_pointer = 0; in ftgmac100_reset_and_config_mac()
161 priv->tx_clean_pointer = 0; in ftgmac100_reset_and_config_mac()
162 priv->tx_pointer = 0; in ftgmac100_reset_and_config_mac()
166 return -EIO; in ftgmac100_reset_and_config_mac()
176 iowrite32(maddr, priv->base + FTGMAC100_OFFSET_MAC_MADR); in ftgmac100_write_mac_addr()
177 iowrite32(laddr, priv->base + FTGMAC100_OFFSET_MAC_LADR); in ftgmac100_write_mac_addr()
186 if (!device_get_ethdev_address(priv->dev, priv->netdev)) { in ftgmac100_initial_mac()
187 dev_info(priv->dev, "Read MAC address %pM from device tree\n", in ftgmac100_initial_mac()
188 priv->netdev->dev_addr); in ftgmac100_initial_mac()
192 m = ioread32(priv->base + FTGMAC100_OFFSET_MAC_MADR); in ftgmac100_initial_mac()
193 l = ioread32(priv->base + FTGMAC100_OFFSET_MAC_LADR); in ftgmac100_initial_mac()
203 eth_hw_addr_set(priv->netdev, mac); in ftgmac100_initial_mac()
204 dev_info(priv->dev, "Read MAC address %pM from chip\n", mac); in ftgmac100_initial_mac()
206 eth_hw_addr_random(priv->netdev); in ftgmac100_initial_mac()
207 dev_info(priv->dev, "Generated random MAC address %pM\n", in ftgmac100_initial_mac()
208 priv->netdev->dev_addr); in ftgmac100_initial_mac()
221 ftgmac100_write_mac_addr(netdev_priv(dev), dev->dev_addr); in ftgmac100_set_mac_addr()
231 if (priv->rx_pause) in ftgmac100_config_pause()
237 if (priv->tx_pause) in ftgmac100_config_pause()
240 iowrite32(fcr, priv->base + FTGMAC100_OFFSET_FCR); in ftgmac100_config_pause()
248 reg = ioread32(priv->base + FTGMAC100_OFFSET_ISR); in ftgmac100_init_hw()
249 iowrite32(reg, priv->base + FTGMAC100_OFFSET_ISR); in ftgmac100_init_hw()
252 iowrite32(priv->rxdes_dma, priv->base + FTGMAC100_OFFSET_RXR_BADR); in ftgmac100_init_hw()
255 iowrite32(priv->txdes_dma, priv->base + FTGMAC100_OFFSET_NPTXR_BADR); in ftgmac100_init_hw()
259 priv->base + FTGMAC100_OFFSET_RBSR); in ftgmac100_init_hw()
263 priv->base + FTGMAC100_OFFSET_APTC); in ftgmac100_init_hw()
266 ftgmac100_write_mac_addr(priv, priv->netdev->dev_addr); in ftgmac100_init_hw()
269 iowrite32(priv->maht0, priv->base + FTGMAC100_OFFSET_MAHT0); in ftgmac100_init_hw()
270 iowrite32(priv->maht1, priv->base + FTGMAC100_OFFSET_MAHT1); in ftgmac100_init_hw()
284 priv->base + FTGMAC100_OFFSET_DBLAC); in ftgmac100_init_hw()
292 priv->base + FTGMAC100_OFFSET_ITC); in ftgmac100_init_hw()
295 reg = ioread32(priv->base + FTGMAC100_OFFSET_FEAR); in ftgmac100_init_hw()
298 reg = ioread32(priv->base + FTGMAC100_OFFSET_TPAFCR); in ftgmac100_init_hw()
302 iowrite32(reg, priv->base + FTGMAC100_OFFSET_TPAFCR); in ftgmac100_init_hw()
307 u32 maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR); in ftgmac100_start_hw()
323 if (priv->cur_duplex == DUPLEX_FULL) in ftgmac100_start_hw()
325 if (priv->netdev->flags & IFF_PROMISC) in ftgmac100_start_hw()
327 if (priv->netdev->flags & IFF_ALLMULTI) in ftgmac100_start_hw()
329 else if (netdev_mc_count(priv->netdev)) in ftgmac100_start_hw()
333 if (priv->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) in ftgmac100_start_hw()
337 iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR); in ftgmac100_start_hw()
342 iowrite32(0, priv->base + FTGMAC100_OFFSET_MACCR); in ftgmac100_stop_hw()
349 priv->maht1 = 0; in ftgmac100_calc_mc_hash()
350 priv->maht0 = 0; in ftgmac100_calc_mc_hash()
351 netdev_for_each_mc_addr(ha, priv->netdev) { in ftgmac100_calc_mc_hash()
352 u32 crc_val = ether_crc_le(ETH_ALEN, ha->addr); in ftgmac100_calc_mc_hash()
356 priv->maht1 |= 1ul << (crc_val - 32); in ftgmac100_calc_mc_hash()
358 priv->maht0 |= 1ul << (crc_val); in ftgmac100_calc_mc_hash()
374 iowrite32(priv->maht0, priv->base + FTGMAC100_OFFSET_MAHT0); in ftgmac100_set_rx_mode()
375 iowrite32(priv->maht1, priv->base + FTGMAC100_OFFSET_MAHT1); in ftgmac100_set_rx_mode()
384 struct net_device *netdev = priv->netdev; in ftgmac100_alloc_rx_buf()
393 err = -ENOMEM; in ftgmac100_alloc_rx_buf()
394 map = priv->rx_scratch_dma; in ftgmac100_alloc_rx_buf()
396 map = dma_map_single(priv->dev, skb->data, RX_BUF_SIZE, in ftgmac100_alloc_rx_buf()
398 if (unlikely(dma_mapping_error(priv->dev, map))) { in ftgmac100_alloc_rx_buf()
402 map = priv->rx_scratch_dma; in ftgmac100_alloc_rx_buf()
404 err = -ENOMEM; in ftgmac100_alloc_rx_buf()
409 priv->rx_skbs[entry] = skb; in ftgmac100_alloc_rx_buf()
412 rxdes->rxdes3 = cpu_to_le32(map); in ftgmac100_alloc_rx_buf()
418 if (entry == (priv->rx_q_entries - 1)) in ftgmac100_alloc_rx_buf()
419 rxdes->rxdes0 = cpu_to_le32(priv->rxdes0_edorr_mask); in ftgmac100_alloc_rx_buf()
421 rxdes->rxdes0 = 0; in ftgmac100_alloc_rx_buf()
429 return (pointer + 1) & (priv->rx_q_entries - 1); in ftgmac100_next_rx_pointer()
434 struct net_device *netdev = priv->netdev; in ftgmac100_rx_packet_error()
437 netdev->stats.rx_errors++; in ftgmac100_rx_packet_error()
440 netdev->stats.rx_crc_errors++; in ftgmac100_rx_packet_error()
445 netdev->stats.rx_length_errors++; in ftgmac100_rx_packet_error()
450 struct net_device *netdev = priv->netdev; in ftgmac100_rx_packet()
458 pointer = priv->rx_pointer; in ftgmac100_rx_packet()
459 rxdes = &priv->rxdes[pointer]; in ftgmac100_rx_packet()
462 status = le32_to_cpu(rxdes->rxdes0); in ftgmac100_rx_packet()
478 csum_vlan = le32_to_cpu(rxdes->rxdes1); in ftgmac100_rx_packet()
502 skb = priv->rx_skbs[pointer]; in ftgmac100_rx_packet()
509 netdev->stats.multicast++; in ftgmac100_rx_packet()
517 if (netdev->features & NETIF_F_RXCSUM) { in ftgmac100_rx_packet()
523 skb->ip_summed = CHECKSUM_NONE; in ftgmac100_rx_packet()
525 skb->ip_summed = CHECKSUM_UNNECESSARY; in ftgmac100_rx_packet()
532 if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && in ftgmac100_rx_packet()
538 map = le32_to_cpu(rxdes->rxdes3); in ftgmac100_rx_packet()
545 dma_unmap_single(priv->dev, map, size, DMA_FROM_DEVICE); in ftgmac100_rx_packet()
547 dma_unmap_single(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE); in ftgmac100_rx_packet()
553 priv->rx_pointer = ftgmac100_next_rx_pointer(priv, pointer); in ftgmac100_rx_packet()
555 skb->protocol = eth_type_trans(skb, netdev); in ftgmac100_rx_packet()
557 netdev->stats.rx_packets++; in ftgmac100_rx_packet()
558 netdev->stats.rx_bytes += size; in ftgmac100_rx_packet()
561 if (skb->ip_summed == CHECKSUM_NONE) in ftgmac100_rx_packet()
564 napi_gro_receive(&priv->napi, skb); in ftgmac100_rx_packet()
571 rxdes->rxdes0 = cpu_to_le32(status & priv->rxdes0_edorr_mask); in ftgmac100_rx_packet()
572 priv->rx_pointer = ftgmac100_next_rx_pointer(priv, pointer); in ftgmac100_rx_packet()
573 netdev->stats.rx_dropped++; in ftgmac100_rx_packet()
580 if (index == (priv->tx_q_entries - 1)) in ftgmac100_base_tx_ctlstat()
581 return priv->txdes0_edotr_mask; in ftgmac100_base_tx_ctlstat()
589 return (pointer + 1) & (priv->tx_q_entries - 1); in ftgmac100_next_tx_pointer()
600 return (priv->tx_clean_pointer - priv->tx_pointer - 1) & in ftgmac100_tx_buf_avail()
601 (priv->tx_q_entries - 1); in ftgmac100_tx_buf_avail()
606 return priv->tx_pointer != priv->tx_clean_pointer; in ftgmac100_tx_buf_cleanable()
615 dma_addr_t map = le32_to_cpu(txdes->txdes3); in ftgmac100_free_tx_packet()
620 dma_unmap_single(priv->dev, map, len, DMA_TO_DEVICE); in ftgmac100_free_tx_packet()
623 dma_unmap_page(priv->dev, map, len, DMA_TO_DEVICE); in ftgmac100_free_tx_packet()
629 priv->tx_skbs[pointer] = NULL; in ftgmac100_free_tx_packet()
634 struct net_device *netdev = priv->netdev; in ftgmac100_tx_complete_packet()
640 pointer = priv->tx_clean_pointer; in ftgmac100_tx_complete_packet()
641 txdes = &priv->txdes[pointer]; in ftgmac100_tx_complete_packet()
643 ctl_stat = le32_to_cpu(txdes->txdes0); in ftgmac100_tx_complete_packet()
647 skb = priv->tx_skbs[pointer]; in ftgmac100_tx_complete_packet()
648 netdev->stats.tx_packets++; in ftgmac100_tx_complete_packet()
649 netdev->stats.tx_bytes += skb->len; in ftgmac100_tx_complete_packet()
651 txdes->txdes0 = cpu_to_le32(ctl_stat & priv->txdes0_edotr_mask); in ftgmac100_tx_complete_packet()
653 priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv, pointer); in ftgmac100_tx_complete_packet()
660 struct net_device *netdev = priv->netdev; in ftgmac100_tx_complete()
684 if (skb->protocol == cpu_to_be16(ETH_P_IP)) { in ftgmac100_prep_tx_csum()
685 u8 ip_proto = ip_hdr(skb)->protocol; in ftgmac100_prep_tx_csum()
713 netdev->stats.tx_dropped++; in ftgmac100_hard_start_xmit()
718 if (unlikely(skb->len > MAX_PKT_SIZE)) { in ftgmac100_hard_start_xmit()
727 nfrags = skb_shinfo(skb)->nr_frags; in ftgmac100_hard_start_xmit()
731 if (skb->ip_summed == CHECKSUM_PARTIAL && in ftgmac100_hard_start_xmit()
745 map = dma_map_single(priv->dev, skb->data, len, DMA_TO_DEVICE); in ftgmac100_hard_start_xmit()
746 if (dma_mapping_error(priv->dev, map)) { in ftgmac100_hard_start_xmit()
753 pointer = priv->tx_pointer; in ftgmac100_hard_start_xmit()
754 txdes = first = &priv->txdes[pointer]; in ftgmac100_hard_start_xmit()
759 priv->tx_skbs[pointer] = skb; in ftgmac100_hard_start_xmit()
766 txdes->txdes3 = cpu_to_le32(map); in ftgmac100_hard_start_xmit()
767 txdes->txdes1 = cpu_to_le32(csum_vlan); in ftgmac100_hard_start_xmit()
774 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; in ftgmac100_hard_start_xmit()
779 map = skb_frag_dma_map(priv->dev, frag, 0, len, in ftgmac100_hard_start_xmit()
781 if (dma_mapping_error(priv->dev, map)) in ftgmac100_hard_start_xmit()
785 priv->tx_skbs[pointer] = skb; in ftgmac100_hard_start_xmit()
786 txdes = &priv->txdes[pointer]; in ftgmac100_hard_start_xmit()
790 if (i == (nfrags - 1)) in ftgmac100_hard_start_xmit()
792 txdes->txdes0 = cpu_to_le32(ctl_stat); in ftgmac100_hard_start_xmit()
793 txdes->txdes1 = 0; in ftgmac100_hard_start_xmit()
794 txdes->txdes3 = cpu_to_le32(map); in ftgmac100_hard_start_xmit()
804 first->txdes0 = cpu_to_le32(f_ctl_stat); in ftgmac100_hard_start_xmit()
807 priv->tx_pointer = pointer; in ftgmac100_hard_start_xmit()
822 iowrite32(1, priv->base + FTGMAC100_OFFSET_NPTXPD); in ftgmac100_hard_start_xmit()
831 pointer = priv->tx_pointer; in ftgmac100_hard_start_xmit()
833 first->txdes0 = cpu_to_le32(f_ctl_stat & priv->txdes0_edotr_mask); in ftgmac100_hard_start_xmit()
838 txdes = &priv->txdes[pointer]; in ftgmac100_hard_start_xmit()
839 ctl_stat = le32_to_cpu(txdes->txdes0); in ftgmac100_hard_start_xmit()
841 txdes->txdes0 = cpu_to_le32(ctl_stat & priv->txdes0_edotr_mask); in ftgmac100_hard_start_xmit()
851 netdev->stats.tx_dropped++; in ftgmac100_hard_start_xmit()
861 for (i = 0; i < priv->rx_q_entries; i++) { in ftgmac100_free_buffers()
862 struct ftgmac100_rxdes *rxdes = &priv->rxdes[i]; in ftgmac100_free_buffers()
863 struct sk_buff *skb = priv->rx_skbs[i]; in ftgmac100_free_buffers()
864 dma_addr_t map = le32_to_cpu(rxdes->rxdes3); in ftgmac100_free_buffers()
869 priv->rx_skbs[i] = NULL; in ftgmac100_free_buffers()
870 dma_unmap_single(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE); in ftgmac100_free_buffers()
875 for (i = 0; i < priv->tx_q_entries; i++) { in ftgmac100_free_buffers()
876 struct ftgmac100_txdes *txdes = &priv->txdes[i]; in ftgmac100_free_buffers()
877 struct sk_buff *skb = priv->tx_skbs[i]; in ftgmac100_free_buffers()
882 le32_to_cpu(txdes->txdes0)); in ftgmac100_free_buffers()
889 kfree(priv->rx_skbs); in ftgmac100_free_rings()
890 kfree(priv->tx_skbs); in ftgmac100_free_rings()
893 if (priv->rxdes) in ftgmac100_free_rings()
894 dma_free_coherent(priv->dev, MAX_RX_QUEUE_ENTRIES * in ftgmac100_free_rings()
896 priv->rxdes, priv->rxdes_dma); in ftgmac100_free_rings()
897 priv->rxdes = NULL; in ftgmac100_free_rings()
899 if (priv->txdes) in ftgmac100_free_rings()
900 dma_free_coherent(priv->dev, MAX_TX_QUEUE_ENTRIES * in ftgmac100_free_rings()
902 priv->txdes, priv->txdes_dma); in ftgmac100_free_rings()
903 priv->txdes = NULL; in ftgmac100_free_rings()
906 if (priv->rx_scratch) in ftgmac100_free_rings()
907 dma_free_coherent(priv->dev, RX_BUF_SIZE, in ftgmac100_free_rings()
908 priv->rx_scratch, priv->rx_scratch_dma); in ftgmac100_free_rings()
914 priv->rx_skbs = kcalloc(MAX_RX_QUEUE_ENTRIES, sizeof(void *), in ftgmac100_alloc_rings()
916 if (!priv->rx_skbs) in ftgmac100_alloc_rings()
917 return -ENOMEM; in ftgmac100_alloc_rings()
918 priv->tx_skbs = kcalloc(MAX_TX_QUEUE_ENTRIES, sizeof(void *), in ftgmac100_alloc_rings()
920 if (!priv->tx_skbs) in ftgmac100_alloc_rings()
921 return -ENOMEM; in ftgmac100_alloc_rings()
924 priv->rxdes = dma_alloc_coherent(priv->dev, in ftgmac100_alloc_rings()
926 &priv->rxdes_dma, GFP_KERNEL); in ftgmac100_alloc_rings()
927 if (!priv->rxdes) in ftgmac100_alloc_rings()
928 return -ENOMEM; in ftgmac100_alloc_rings()
929 priv->txdes = dma_alloc_coherent(priv->dev, in ftgmac100_alloc_rings()
931 &priv->txdes_dma, GFP_KERNEL); in ftgmac100_alloc_rings()
932 if (!priv->txdes) in ftgmac100_alloc_rings()
933 return -ENOMEM; in ftgmac100_alloc_rings()
936 priv->rx_scratch = dma_alloc_coherent(priv->dev, in ftgmac100_alloc_rings()
938 &priv->rx_scratch_dma, in ftgmac100_alloc_rings()
940 if (!priv->rx_scratch) in ftgmac100_alloc_rings()
941 return -ENOMEM; in ftgmac100_alloc_rings()
953 priv->rx_q_entries = priv->new_rx_q_entries; in ftgmac100_init_rings()
954 priv->tx_q_entries = priv->new_tx_q_entries; in ftgmac100_init_rings()
956 if (WARN_ON(priv->rx_q_entries < MIN_RX_QUEUE_ENTRIES)) in ftgmac100_init_rings()
960 for (i = 0; i < priv->rx_q_entries; i++) { in ftgmac100_init_rings()
961 rxdes = &priv->rxdes[i]; in ftgmac100_init_rings()
962 rxdes->rxdes0 = 0; in ftgmac100_init_rings()
963 rxdes->rxdes3 = cpu_to_le32(priv->rx_scratch_dma); in ftgmac100_init_rings()
966 rxdes->rxdes0 |= cpu_to_le32(priv->rxdes0_edorr_mask); in ftgmac100_init_rings()
968 if (WARN_ON(priv->tx_q_entries < MIN_RX_QUEUE_ENTRIES)) in ftgmac100_init_rings()
972 for (i = 0; i < priv->tx_q_entries; i++) { in ftgmac100_init_rings()
973 txdes = &priv->txdes[i]; in ftgmac100_init_rings()
974 txdes->txdes0 = 0; in ftgmac100_init_rings()
976 txdes->txdes0 |= cpu_to_le32(priv->txdes0_edotr_mask); in ftgmac100_init_rings()
983 for (i = 0; i < priv->rx_q_entries; i++) { in ftgmac100_alloc_rx_buffers()
984 struct ftgmac100_rxdes *rxdes = &priv->rxdes[i]; in ftgmac100_alloc_rx_buffers()
987 return -ENOMEM; in ftgmac100_alloc_rx_buffers()
994 struct net_device *netdev = bus->priv; in ftgmac100_mdiobus_read()
999 phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR); in ftgmac100_mdiobus_read()
1008 iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR); in ftgmac100_mdiobus_read()
1011 phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR); in ftgmac100_mdiobus_read()
1016 data = ioread32(priv->base + FTGMAC100_OFFSET_PHYDATA); in ftgmac100_mdiobus_read()
1024 return -EIO; in ftgmac100_mdiobus_read()
1030 struct net_device *netdev = bus->priv; in ftgmac100_mdiobus_write()
1036 phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR); in ftgmac100_mdiobus_write()
1047 iowrite32(data, priv->base + FTGMAC100_OFFSET_PHYDATA); in ftgmac100_mdiobus_write()
1048 iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR); in ftgmac100_mdiobus_write()
1051 phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR); in ftgmac100_mdiobus_write()
1060 return -EIO; in ftgmac100_mdiobus_write()
1066 strscpy(info->driver, DRV_NAME, sizeof(info->driver)); in ftgmac100_get_drvinfo()
1067 strscpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info)); in ftgmac100_get_drvinfo()
1079 ering->rx_max_pending = MAX_RX_QUEUE_ENTRIES; in ftgmac100_get_ringparam()
1080 ering->tx_max_pending = MAX_TX_QUEUE_ENTRIES; in ftgmac100_get_ringparam()
1081 ering->rx_pending = priv->rx_q_entries; in ftgmac100_get_ringparam()
1082 ering->tx_pending = priv->tx_q_entries; in ftgmac100_get_ringparam()
1093 if (ering->rx_pending > MAX_RX_QUEUE_ENTRIES || in ftgmac100_set_ringparam()
1094 ering->tx_pending > MAX_TX_QUEUE_ENTRIES || in ftgmac100_set_ringparam()
1095 ering->rx_pending < MIN_RX_QUEUE_ENTRIES || in ftgmac100_set_ringparam()
1096 ering->tx_pending < MIN_TX_QUEUE_ENTRIES || in ftgmac100_set_ringparam()
1097 !is_power_of_2(ering->rx_pending) || in ftgmac100_set_ringparam()
1098 !is_power_of_2(ering->tx_pending)) in ftgmac100_set_ringparam()
1099 return -EINVAL; in ftgmac100_set_ringparam()
1101 priv->new_rx_q_entries = ering->rx_pending; in ftgmac100_set_ringparam()
1102 priv->new_tx_q_entries = ering->tx_pending; in ftgmac100_set_ringparam()
1104 schedule_work(&priv->reset_task); in ftgmac100_set_ringparam()
1114 pause->autoneg = priv->aneg_pause; in ftgmac100_get_pauseparam()
1115 pause->tx_pause = priv->tx_pause; in ftgmac100_get_pauseparam()
1116 pause->rx_pause = priv->rx_pause; in ftgmac100_get_pauseparam()
1123 struct phy_device *phydev = netdev->phydev; in ftgmac100_set_pauseparam()
1125 priv->aneg_pause = pause->autoneg; in ftgmac100_set_pauseparam()
1126 priv->tx_pause = pause->tx_pause; in ftgmac100_set_pauseparam()
1127 priv->rx_pause = pause->rx_pause; in ftgmac100_set_pauseparam()
1130 phy_set_asym_pause(phydev, pause->rx_pause, pause->tx_pause); in ftgmac100_set_pauseparam()
1133 if (!(phydev && priv->aneg_pause)) in ftgmac100_set_pauseparam()
1159 status = ioread32(priv->base + FTGMAC100_OFFSET_ISR); in ftgmac100_interrupt()
1160 iowrite32(status, priv->base + FTGMAC100_OFFSET_ISR); in ftgmac100_interrupt()
1165 netdev->stats.rx_over_errors++; in ftgmac100_interrupt()
1169 netdev->stats.rx_fifo_errors++; in ftgmac100_interrupt()
1173 netdev->stats.tx_fifo_errors++; in ftgmac100_interrupt()
1175 /* AHB error -> Reset the chip */ in ftgmac100_interrupt()
1180 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_interrupt()
1181 schedule_work(&priv->reset_task); in ftgmac100_interrupt()
1188 priv->need_mac_restart = true; in ftgmac100_interrupt()
1195 iowrite32(new_mask, priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_interrupt()
1198 napi_schedule_irqoff(&priv->napi); in ftgmac100_interrupt()
1205 struct ftgmac100_rxdes *rxdes = &priv->rxdes[priv->rx_pointer]; in ftgmac100_check_rx()
1208 return !!(rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RXPKT_RDY)); in ftgmac100_check_rx()
1230 if (unlikely(priv->need_mac_restart)) { in ftgmac100_poll()
1232 priv->need_mac_restart = false; in ftgmac100_poll()
1234 /* Re-enable "bad" interrupts */ in ftgmac100_poll()
1236 priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_poll()
1246 /* We are about to re-enable all interrupts. However in ftgmac100_poll()
1249 * to re-check if there's something to process in ftgmac100_poll()
1252 priv->base + FTGMAC100_OFFSET_ISR); in ftgmac100_poll()
1257 ioread32(priv->base + FTGMAC100_OFFSET_ISR); in ftgmac100_poll()
1269 priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_poll()
1279 /* Re-init descriptors (adjust queue sizes) */ in ftgmac100_init_all()
1292 /* Re-enable the device */ in ftgmac100_init_all()
1293 napi_enable(&priv->napi); in ftgmac100_init_all()
1294 netif_start_queue(priv->netdev); in ftgmac100_init_all()
1297 iowrite32(FTGMAC100_INT_ALL, priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_init_all()
1304 struct net_device *netdev = priv->netdev; in ftgmac100_reset()
1311 if (netdev->phydev) in ftgmac100_reset()
1312 mutex_lock(&netdev->phydev->lock); in ftgmac100_reset()
1313 if (priv->mii_bus) in ftgmac100_reset()
1314 mutex_lock(&priv->mii_bus->mdio_lock); in ftgmac100_reset()
1323 napi_disable(&priv->napi); in ftgmac100_reset()
1342 if (priv->mii_bus) in ftgmac100_reset()
1343 mutex_unlock(&priv->mii_bus->mdio_lock); in ftgmac100_reset()
1344 if (netdev->phydev) in ftgmac100_reset()
1345 mutex_unlock(&netdev->phydev->lock); in ftgmac100_reset()
1360 struct phy_device *phydev = netdev->phydev; in ftgmac100_adjust_link()
1365 if (!phydev->link) in ftgmac100_adjust_link()
1368 new_speed = phydev->speed; in ftgmac100_adjust_link()
1371 if (priv->aneg_pause) { in ftgmac100_adjust_link()
1372 rx_pause = tx_pause = phydev->pause; in ftgmac100_adjust_link()
1373 if (phydev->asym_pause) in ftgmac100_adjust_link()
1376 rx_pause = priv->rx_pause; in ftgmac100_adjust_link()
1377 tx_pause = priv->tx_pause; in ftgmac100_adjust_link()
1381 if (phydev->speed == priv->cur_speed && in ftgmac100_adjust_link()
1382 phydev->duplex == priv->cur_duplex && in ftgmac100_adjust_link()
1383 rx_pause == priv->rx_pause && in ftgmac100_adjust_link()
1384 tx_pause == priv->tx_pause) in ftgmac100_adjust_link()
1390 if (new_speed || priv->cur_speed) in ftgmac100_adjust_link()
1393 priv->cur_speed = new_speed; in ftgmac100_adjust_link()
1394 priv->cur_duplex = phydev->duplex; in ftgmac100_adjust_link()
1395 priv->rx_pause = rx_pause; in ftgmac100_adjust_link()
1396 priv->tx_pause = tx_pause; in ftgmac100_adjust_link()
1403 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_adjust_link()
1408 if (netdev->phydev) in ftgmac100_adjust_link()
1409 mutex_unlock(&netdev->phydev->lock); in ftgmac100_adjust_link()
1413 if (netdev->phydev) in ftgmac100_adjust_link()
1414 mutex_lock(&netdev->phydev->lock); in ftgmac100_adjust_link()
1421 struct platform_device *pdev = to_platform_device(priv->dev); in ftgmac100_mii_probe()
1422 struct device_node *np = pdev->dev.of_node; in ftgmac100_mii_probe()
1438 * On the Aspeed SoC there are additionally straps and SCU in ftgmac100_mii_probe()
1442 * those SoC specific bits and assume the device-tree is in ftgmac100_mii_probe()
1443 * right and the SCU has been configured properly by pinmux in ftgmac100_mii_probe()
1446 if (priv->is_aspeed && !(phy_interface_mode_is_rgmii(phy_intf))) { in ftgmac100_mii_probe()
1452 phydev = phy_find_first(priv->mii_bus); in ftgmac100_mii_probe()
1454 netdev_info(netdev, "%s: no PHY found\n", netdev->name); in ftgmac100_mii_probe()
1455 return -ENODEV; in ftgmac100_mii_probe()
1462 netdev_err(netdev, "%s: Could not attach to PHY\n", netdev->name); in ftgmac100_mii_probe()
1489 /* When using NC-SI we force the speed to 100Mbit/s full duplex, in ftgmac100_open()
1495 if (priv->use_ncsi) { in ftgmac100_open()
1496 priv->cur_duplex = DUPLEX_FULL; in ftgmac100_open()
1497 priv->cur_speed = SPEED_100; in ftgmac100_open()
1499 priv->cur_duplex = 0; in ftgmac100_open()
1500 priv->cur_speed = 0; in ftgmac100_open()
1509 netif_napi_add(netdev, &priv->napi, ftgmac100_poll); in ftgmac100_open()
1512 err = request_irq(netdev->irq, ftgmac100_interrupt, 0, netdev->name, netdev); in ftgmac100_open()
1514 netdev_err(netdev, "failed to request irq %d\n", netdev->irq); in ftgmac100_open()
1525 if (netdev->phydev) { in ftgmac100_open()
1527 phy_start(netdev->phydev); in ftgmac100_open()
1528 } else if (priv->use_ncsi) { in ftgmac100_open()
1529 /* If using NC-SI, set our carrier on and start the stack */ in ftgmac100_open()
1533 err = ncsi_start_dev(priv->ndev); in ftgmac100_open()
1541 napi_disable(&priv->napi); in ftgmac100_open()
1545 free_irq(netdev->irq, netdev); in ftgmac100_open()
1547 netif_napi_del(&priv->napi); in ftgmac100_open()
1549 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_open()
1567 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_stop()
1570 napi_disable(&priv->napi); in ftgmac100_stop()
1571 netif_napi_del(&priv->napi); in ftgmac100_stop()
1572 if (netdev->phydev) in ftgmac100_stop()
1573 phy_stop(netdev->phydev); in ftgmac100_stop()
1574 else if (priv->use_ncsi) in ftgmac100_stop()
1575 ncsi_stop_dev(priv->ndev); in ftgmac100_stop()
1578 free_irq(netdev->irq, netdev); in ftgmac100_stop()
1590 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER); in ftgmac100_tx_timeout()
1593 schedule_work(&priv->reset_task); in ftgmac100_tx_timeout()
1600 netdev_features_t changed = netdev->features ^ features; in ftgmac100_set_features()
1609 maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR); in ftgmac100_set_features()
1610 if (priv->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) in ftgmac100_set_features()
1614 iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR); in ftgmac100_set_features()
1626 ftgmac100_interrupt(netdev->irq, netdev); in ftgmac100_poll_controller()
1651 struct platform_device *pdev = to_platform_device(priv->dev); in ftgmac100_setup_mdio()
1652 struct device_node *np = pdev->dev.of_node; in ftgmac100_setup_mdio()
1658 priv->mii_bus = mdiobus_alloc(); in ftgmac100_setup_mdio()
1659 if (!priv->mii_bus) in ftgmac100_setup_mdio()
1660 return -EIO; in ftgmac100_setup_mdio()
1662 if (of_device_is_compatible(np, "aspeed,ast2400-mac") || in ftgmac100_setup_mdio()
1663 of_device_is_compatible(np, "aspeed,ast2500-mac")) { in ftgmac100_setup_mdio()
1664 /* The AST2600 has a separate MDIO controller */ in ftgmac100_setup_mdio()
1669 reg = ioread32(priv->base + FTGMAC100_OFFSET_REVR); in ftgmac100_setup_mdio()
1671 iowrite32(reg, priv->base + FTGMAC100_OFFSET_REVR); in ftgmac100_setup_mdio()
1674 priv->mii_bus->name = "ftgmac100_mdio"; in ftgmac100_setup_mdio()
1675 snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%d", in ftgmac100_setup_mdio()
1676 pdev->name, pdev->id); in ftgmac100_setup_mdio()
1677 priv->mii_bus->parent = priv->dev; in ftgmac100_setup_mdio()
1678 priv->mii_bus->priv = priv->netdev; in ftgmac100_setup_mdio()
1679 priv->mii_bus->read = ftgmac100_mdiobus_read; in ftgmac100_setup_mdio()
1680 priv->mii_bus->write = ftgmac100_mdiobus_write; in ftgmac100_setup_mdio()
1683 priv->mii_bus->irq[i] = PHY_POLL; in ftgmac100_setup_mdio()
1687 err = of_mdiobus_register(priv->mii_bus, mdio_np); in ftgmac100_setup_mdio()
1689 dev_err(priv->dev, "Cannot register MDIO bus!\n"); in ftgmac100_setup_mdio()
1698 mdiobus_free(priv->mii_bus); in ftgmac100_setup_mdio()
1706 if (!netdev->phydev) in ftgmac100_phy_disconnect()
1709 phy_disconnect(netdev->phydev); in ftgmac100_phy_disconnect()
1710 if (of_phy_is_fixed_link(priv->dev->of_node)) in ftgmac100_phy_disconnect()
1711 of_phy_deregister_fixed_link(priv->dev->of_node); in ftgmac100_phy_disconnect()
1718 if (!priv->mii_bus) in ftgmac100_destroy_mdio()
1721 mdiobus_unregister(priv->mii_bus); in ftgmac100_destroy_mdio()
1722 mdiobus_free(priv->mii_bus); in ftgmac100_destroy_mdio()
1727 if (unlikely(nd->state != ncsi_dev_state_functional)) in ftgmac100_ncsi_handler()
1730 netdev_dbg(nd->dev, "NCSI interface %s\n", in ftgmac100_ncsi_handler()
1731 nd->link_up ? "up" : "down"); in ftgmac100_ncsi_handler()
1739 clk = devm_clk_get(priv->dev, NULL /* MACCLK */); in ftgmac100_setup_clk()
1742 priv->clk = clk; in ftgmac100_setup_clk()
1743 rc = clk_prepare_enable(priv->clk); in ftgmac100_setup_clk()
1751 rc = clk_set_rate(priv->clk, priv->use_ncsi ? FTGMAC_25MHZ : in ftgmac100_setup_clk()
1758 * RGMII, or the controller is not an ASPEED-based controller. in ftgmac100_setup_clk()
1760 priv->rclk = devm_clk_get_optional(priv->dev, "RCLK"); in ftgmac100_setup_clk()
1761 rc = clk_prepare_enable(priv->rclk); in ftgmac100_setup_clk()
1766 clk_disable_unprepare(priv->clk); in ftgmac100_setup_clk()
1795 return -ENXIO; in ftgmac100_probe()
1804 err = -ENOMEM; in ftgmac100_probe()
1808 SET_NETDEV_DEV(netdev, &pdev->dev); in ftgmac100_probe()
1810 netdev->ethtool_ops = &ftgmac100_ethtool_ops; in ftgmac100_probe()
1811 netdev->netdev_ops = &ftgmac100_netdev_ops; in ftgmac100_probe()
1812 netdev->watchdog_timeo = 5 * HZ; in ftgmac100_probe()
1818 priv->netdev = netdev; in ftgmac100_probe()
1819 priv->dev = &pdev->dev; in ftgmac100_probe()
1820 INIT_WORK(&priv->reset_task, ftgmac100_reset_task); in ftgmac100_probe()
1823 priv->res = request_mem_region(res->start, resource_size(res), in ftgmac100_probe()
1824 dev_name(&pdev->dev)); in ftgmac100_probe()
1825 if (!priv->res) { in ftgmac100_probe()
1826 dev_err(&pdev->dev, "Could not reserve memory region\n"); in ftgmac100_probe()
1827 err = -ENOMEM; in ftgmac100_probe()
1831 priv->base = ioremap(res->start, resource_size(res)); in ftgmac100_probe()
1832 if (!priv->base) { in ftgmac100_probe()
1833 dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n"); in ftgmac100_probe()
1834 err = -EIO; in ftgmac100_probe()
1838 netdev->irq = irq; in ftgmac100_probe()
1841 priv->tx_pause = true; in ftgmac100_probe()
1842 priv->rx_pause = true; in ftgmac100_probe()
1843 priv->aneg_pause = true; in ftgmac100_probe()
1848 np = pdev->dev.of_node; in ftgmac100_probe()
1849 if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac") || in ftgmac100_probe()
1850 of_device_is_compatible(np, "aspeed,ast2500-mac") || in ftgmac100_probe()
1851 of_device_is_compatible(np, "aspeed,ast2600-mac"))) { in ftgmac100_probe()
1852 priv->rxdes0_edorr_mask = BIT(30); in ftgmac100_probe()
1853 priv->txdes0_edotr_mask = BIT(30); in ftgmac100_probe()
1854 priv->is_aspeed = true; in ftgmac100_probe()
1856 priv->rxdes0_edorr_mask = BIT(15); in ftgmac100_probe()
1857 priv->txdes0_edotr_mask = BIT(15); in ftgmac100_probe()
1860 if (np && of_get_property(np, "use-ncsi", NULL)) { in ftgmac100_probe()
1862 dev_err(&pdev->dev, "NCSI stack not enabled\n"); in ftgmac100_probe()
1863 err = -EINVAL; in ftgmac100_probe()
1867 dev_info(&pdev->dev, "Using NCSI interface\n"); in ftgmac100_probe()
1868 priv->use_ncsi = true; in ftgmac100_probe()
1869 priv->ndev = ncsi_register_dev(netdev, ftgmac100_ncsi_handler); in ftgmac100_probe()
1870 if (!priv->ndev) { in ftgmac100_probe()
1871 err = -EINVAL; in ftgmac100_probe()
1879 dev_err(&pdev->dev, "Failed to register fixed PHY\n"); in ftgmac100_probe()
1883 phy = of_phy_get_and_connect(priv->netdev, np, in ftgmac100_probe()
1886 dev_err(&pdev->dev, "Failed to connect to fixed PHY\n"); in ftgmac100_probe()
1888 err = -EINVAL; in ftgmac100_probe()
1894 } else if (np && of_get_property(np, "phy-handle", NULL)) { in ftgmac100_probe()
1901 if (of_device_is_compatible(np, "aspeed,ast2400-mac") || in ftgmac100_probe()
1902 of_device_is_compatible(np, "aspeed,ast2500-mac")) { in ftgmac100_probe()
1908 phy = of_phy_get_and_connect(priv->netdev, np, in ftgmac100_probe()
1911 dev_err(&pdev->dev, "Failed to connect to phy\n"); in ftgmac100_probe()
1912 err = -EINVAL; in ftgmac100_probe()
1929 priv->use_ncsi = false; in ftgmac100_probe()
1936 dev_err(priv->dev, "MII probe failed!\n"); in ftgmac100_probe()
1942 if (priv->is_aspeed) { in ftgmac100_probe()
1947 /* Disable ast2600 problematic HW arbitration */ in ftgmac100_probe()
1948 if (of_device_is_compatible(np, "aspeed,ast2600-mac")) in ftgmac100_probe()
1950 priv->base + FTGMAC100_OFFSET_TM); in ftgmac100_probe()
1954 priv->rx_q_entries = priv->new_rx_q_entries = DEF_RX_QUEUE_ENTRIES; in ftgmac100_probe()
1955 priv->tx_q_entries = priv->new_tx_q_entries = DEF_TX_QUEUE_ENTRIES; in ftgmac100_probe()
1958 netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM | in ftgmac100_probe()
1962 if (priv->use_ncsi) in ftgmac100_probe()
1963 netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; in ftgmac100_probe()
1966 if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac"))) in ftgmac100_probe()
1967 netdev->hw_features &= ~NETIF_F_HW_CSUM; in ftgmac100_probe()
1969 /* AST2600 tx checksum with NCSI is broken */ in ftgmac100_probe()
1970 if (priv->use_ncsi && of_device_is_compatible(np, "aspeed,ast2600-mac")) in ftgmac100_probe()
1971 netdev->hw_features &= ~NETIF_F_HW_CSUM; in ftgmac100_probe()
1973 if (np && of_get_property(np, "no-hw-checksum", NULL)) in ftgmac100_probe()
1974 netdev->hw_features &= ~(NETIF_F_HW_CSUM | NETIF_F_RXCSUM); in ftgmac100_probe()
1975 netdev->features |= netdev->hw_features; in ftgmac100_probe()
1980 dev_err(&pdev->dev, "Failed to register netdev\n"); in ftgmac100_probe()
1984 netdev_info(netdev, "irq %d, mapped at %p\n", netdev->irq, priv->base); in ftgmac100_probe()
1989 clk_disable_unprepare(priv->rclk); in ftgmac100_probe()
1990 clk_disable_unprepare(priv->clk); in ftgmac100_probe()
1994 if (priv->ndev) in ftgmac100_probe()
1995 ncsi_unregister_dev(priv->ndev); in ftgmac100_probe()
1998 iounmap(priv->base); in ftgmac100_probe()
2000 release_resource(priv->res); in ftgmac100_probe()
2015 if (priv->ndev) in ftgmac100_remove()
2016 ncsi_unregister_dev(priv->ndev); in ftgmac100_remove()
2019 clk_disable_unprepare(priv->rclk); in ftgmac100_remove()
2020 clk_disable_unprepare(priv->clk); in ftgmac100_remove()
2022 /* There's a small chance the reset task will have been re-queued, in ftgmac100_remove()
2025 cancel_work_sync(&priv->reset_task); in ftgmac100_remove()
2030 iounmap(priv->base); in ftgmac100_remove()
2031 release_resource(priv->res); in ftgmac100_remove()
2033 netif_napi_del(&priv->napi); in ftgmac100_remove()
2054 MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");