diff options
Diffstat (limited to 'drivers/net/ethernet/renesas/ravb_main.c')
-rw-r--r-- | drivers/net/ethernet/renesas/ravb_main.c | 109 |
1 files changed, 98 insertions, 11 deletions
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 525d66f71f02..b357ac4c56c5 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1124,7 +1124,7 @@ static bool ravb_queue_interrupt(struct net_device *ndev, int q) if (((ris0 & ric0) & BIT(q)) || ((tis & tic) & BIT(q))) { if (napi_schedule_prep(&priv->napi[q])) { /* Mask RX and TX interrupts */ - if (!info->multi_irqs) { + if (!info->irq_en_dis) { ravb_write(ndev, ric0 & ~BIT(q), RIC0); ravb_write(ndev, tic & ~BIT(q), TIC); } else { @@ -1306,7 +1306,7 @@ static int ravb_poll(struct napi_struct *napi, int budget) /* Re-enable RX/TX interrupts */ spin_lock_irqsave(&priv->lock, flags); - if (!info->multi_irqs) { + if (!info->irq_en_dis) { ravb_modify(ndev, RIC0, mask, mask); ravb_modify(ndev, TIC, mask, mask); } else { @@ -1798,12 +1798,23 @@ static int ravb_open(struct net_device *ndev) ndev, dev, "ch19:tx_nc"); if (error) goto out_free_irq_nc_rx; + + if (info->err_mgmt_irqs) { + error = ravb_hook_irq(priv->erra_irq, ravb_multi_interrupt, + ndev, dev, "err_a"); + if (error) + goto out_free_irq_nc_tx; + error = ravb_hook_irq(priv->mgmta_irq, ravb_multi_interrupt, + ndev, dev, "mgmt_a"); + if (error) + goto out_free_irq_erra; + } } /* Device init */ error = ravb_dmac_init(ndev); if (error) - goto out_free_irq_nc_tx; + goto out_free_irq_mgmta; ravb_emac_init(ndev); /* Initialise PTP Clock driver */ @@ -1823,9 +1834,15 @@ out_ptp_stop: /* Stop PTP Clock driver */ if (info->gptp) ravb_ptp_stop(ndev); -out_free_irq_nc_tx: +out_free_irq_mgmta: if (!info->multi_irqs) goto out_free_irq; + if (info->err_mgmt_irqs) + free_irq(priv->mgmta_irq, ndev); +out_free_irq_erra: + if (info->err_mgmt_irqs) + free_irq(priv->erra_irq, ndev); +out_free_irq_nc_tx: free_irq(priv->tx_irqs[RAVB_NC], ndev); out_free_irq_nc_rx: free_irq(priv->rx_irqs[RAVB_NC], ndev); @@ -2166,6 +2183,10 @@ static int ravb_close(struct net_device *ndev) free_irq(priv->tx_irqs[RAVB_BE], ndev); free_irq(priv->rx_irqs[RAVB_BE], ndev); free_irq(priv->emac_irq, ndev); + if (info->err_mgmt_irqs) { + free_irq(priv->erra_irq, ndev); + free_irq(priv->mgmta_irq, ndev); + } } free_irq(ndev->irq, ndev); @@ -2410,6 +2431,7 @@ static const struct ravb_hw_info ravb_gen3_hw_info = { .internal_delay = 1, .tx_counters = 1, .multi_irqs = 1, + .irq_en_dis = 1, .ccc_gac = 1, .nc_queues = 1, .magic_pkt = 1, @@ -2438,6 +2460,31 @@ static const struct ravb_hw_info ravb_gen2_hw_info = { .magic_pkt = 1, }; +static const struct ravb_hw_info ravb_rzv2m_hw_info = { + .rx_ring_free = ravb_rx_ring_free_rcar, + .rx_ring_format = ravb_rx_ring_format_rcar, + .alloc_rx_desc = ravb_alloc_rx_desc_rcar, + .receive = ravb_rx_rcar, + .set_rate = ravb_set_rate_rcar, + .set_feature = ravb_set_features_rcar, + .dmac_init = ravb_dmac_init_rcar, + .emac_init = ravb_emac_init_rcar, + .gstrings_stats = ravb_gstrings_stats, + .gstrings_size = sizeof(ravb_gstrings_stats), + .net_hw_features = NETIF_F_RXCSUM, + .net_features = NETIF_F_RXCSUM, + .stats_len = ARRAY_SIZE(ravb_gstrings_stats), + .max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1, + .tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, + .rx_max_buf_size = SZ_2K, + .multi_irqs = 1, + .err_mgmt_irqs = 1, + .gptp = 1, + .gptp_ref_clk = 1, + .nc_queues = 1, + .magic_pkt = 1, +}; + static const struct ravb_hw_info gbeth_hw_info = { .rx_ring_free = ravb_rx_ring_free_gbeth, .rx_ring_format = ravb_rx_ring_format_gbeth, @@ -2465,6 +2512,7 @@ static const struct of_device_id ravb_match_table[] = { { .compatible = "renesas,etheravb-rcar-gen2", .data = &ravb_gen2_hw_info }, { .compatible = "renesas,etheravb-r8a7795", .data = &ravb_gen3_hw_info }, { .compatible = "renesas,etheravb-rcar-gen3", .data = &ravb_gen3_hw_info }, + { .compatible = "renesas,etheravb-rzv2m", .data = &ravb_rzv2m_hw_info }, { .compatible = "renesas,rzg2l-gbeth", .data = &gbeth_hw_info }, { } }; @@ -2473,11 +2521,15 @@ MODULE_DEVICE_TABLE(of, ravb_match_table); static int ravb_set_gti(struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); + const struct ravb_hw_info *info = priv->info; struct device *dev = ndev->dev.parent; unsigned long rate; uint64_t inc; - rate = clk_get_rate(priv->clk); + if (info->gptp_ref_clk) + rate = clk_get_rate(priv->gptp_clk); + else + rate = clk_get_rate(priv->clk); if (!rate) return -EINVAL; @@ -2594,10 +2646,14 @@ static int ravb_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - if (info->multi_irqs) - irq = platform_get_irq_byname(pdev, "ch22"); - else + if (info->multi_irqs) { + if (info->err_mgmt_irqs) + irq = platform_get_irq_byname(pdev, "dia"); + else + irq = platform_get_irq_byname(pdev, "ch22"); + } else { irq = platform_get_irq(pdev, 0); + } if (irq < 0) { error = irq; goto out_release; @@ -2639,7 +2695,10 @@ static int ravb_probe(struct platform_device *pdev) of_property_read_bool(np, "renesas,ether-link-active-low"); if (info->multi_irqs) { - irq = platform_get_irq_byname(pdev, "ch24"); + if (info->err_mgmt_irqs) + irq = platform_get_irq_byname(pdev, "line3"); + else + irq = platform_get_irq_byname(pdev, "ch24"); if (irq < 0) { error = irq; goto out_release; @@ -2661,6 +2720,22 @@ static int ravb_probe(struct platform_device *pdev) } priv->tx_irqs[i] = irq; } + + if (info->err_mgmt_irqs) { + irq = platform_get_irq_byname(pdev, "err_a"); + if (irq < 0) { + error = irq; + goto out_release; + } + priv->erra_irq = irq; + + irq = platform_get_irq_byname(pdev, "mgmt_a"); + if (irq < 0) { + error = irq; + goto out_release; + } + priv->mgmta_irq = irq; + } } priv->clk = devm_clk_get(&pdev->dev, NULL); @@ -2676,6 +2751,15 @@ static int ravb_probe(struct platform_device *pdev) } clk_prepare_enable(priv->refclk); + if (info->gptp_ref_clk) { + priv->gptp_clk = devm_clk_get(&pdev->dev, "gptp"); + if (IS_ERR(priv->gptp_clk)) { + error = PTR_ERR(priv->gptp_clk); + goto out_disable_refclk; + } + clk_prepare_enable(priv->gptp_clk); + } + ndev->max_mtu = info->rx_max_buf_size - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); ndev->min_mtu = ETH_MIN_MTU; @@ -2697,7 +2781,7 @@ static int ravb_probe(struct platform_device *pdev) /* Set GTI value */ error = ravb_set_gti(ndev); if (error) - goto out_disable_refclk; + goto out_disable_gptp_clk; /* Request GTI loading */ ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); @@ -2717,7 +2801,7 @@ static int ravb_probe(struct platform_device *pdev) "Cannot allocate desc base address table (size %d bytes)\n", priv->desc_bat_size); error = -ENOMEM; - goto out_disable_refclk; + goto out_disable_gptp_clk; } for (q = RAVB_BE; q < DBAT_ENTRY_NUM; q++) priv->desc_bat[q].die_dt = DT_EOS; @@ -2780,6 +2864,8 @@ out_dma_free: /* Stop PTP Clock driver */ if (info->ccc_gac) ravb_ptp_stop(ndev); +out_disable_gptp_clk: + clk_disable_unprepare(priv->gptp_clk); out_disable_refclk: clk_disable_unprepare(priv->refclk); out_release: @@ -2801,6 +2887,7 @@ static int ravb_remove(struct platform_device *pdev) if (info->ccc_gac) ravb_ptp_stop(ndev); + clk_disable_unprepare(priv->gptp_clk); clk_disable_unprepare(priv->refclk); dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, |