aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/renesas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/renesas')
-rw-r--r--drivers/net/ethernet/renesas/ravb.h14
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c139
-rw-r--r--drivers/net/ethernet/renesas/ravb_ptp.c6
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c22
4 files changed, 138 insertions, 43 deletions
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index 08062d73df10..e0f8276cffed 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -189,6 +189,7 @@ enum ravb_reg {
PSR = 0x0528,
PIPR = 0x052c,
CXR31 = 0x0530, /* RZ/G2L only */
+ CXR35 = 0x0540, /* RZ/G2L only */
MPR = 0x0558,
PFTCR = 0x055c,
PFRCR = 0x0560,
@@ -965,6 +966,13 @@ enum CXR31_BIT {
CXR31_SEL_LINK1 = 0x00000008,
};
+enum CXR35_BIT {
+ CXR35_SEL_XMII = 0x00000003,
+ CXR35_SEL_XMII_RGMII = 0x00000000,
+ CXR35_SEL_XMII_MII = 0x00000002,
+ CXR35_HALFCYC_CLKSW = 0xffff0000,
+};
+
enum CSR0_BIT {
CSR0_TPE = 0x00000010,
CSR0_RPE = 0x00000020,
@@ -1027,8 +1035,11 @@ struct ravb_hw_info {
unsigned tx_counters:1; /* E-MAC has TX counters */
unsigned carrier_counters:1; /* E-MAC has carrier counters */
unsigned multi_irqs:1; /* AVB-DMAC and E-MAC has multiple irqs */
+ unsigned irq_en_dis:1; /* Has separate irq enable and disable regs */
+ unsigned err_mgmt_irqs:1; /* Line1 (Err) and Line2 (Mgmt) irqs are separate */
unsigned gptp:1; /* AVB-DMAC has gPTP support */
unsigned ccc_gac:1; /* AVB-DMAC has gPTP support active in config mode */
+ unsigned gptp_ref_clk:1; /* gPTP has separate reference clock */
unsigned nc_queues:1; /* AVB-DMAC has RX and TX NC queues */
unsigned magic_pkt:1; /* E-MAC supports magic packet detection */
unsigned half_duplex:1; /* E-MAC supports half duplex mode */
@@ -1040,6 +1051,7 @@ struct ravb_private {
void __iomem *addr;
struct clk *clk;
struct clk *refclk;
+ struct clk *gptp_clk;
struct mdiobb_ctrl mdiobb;
u32 num_rx_ring[NUM_RX_QUEUE];
u32 num_tx_ring[NUM_TX_QUEUE];
@@ -1077,6 +1089,8 @@ struct ravb_private {
int msg_enable;
int speed;
int emac_irq;
+ int erra_irq;
+ int mgmta_irq;
int rx_irqs[NUM_RX_QUEUE];
int tx_irqs[NUM_TX_QUEUE];
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index b215cde68e10..36324126db6d 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -475,7 +475,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
goto error;
for (i = 0; i < priv->num_rx_ring[q]; i++) {
- skb = netdev_alloc_skb(ndev, info->max_rx_len);
+ skb = __netdev_alloc_skb(ndev, info->max_rx_len, GFP_KERNEL);
if (!skb)
goto error;
ravb_set_buffer_align(skb);
@@ -540,7 +540,13 @@ static void ravb_emac_init_gbeth(struct net_device *ndev)
/* E-MAC interrupt enable register */
ravb_write(ndev, ECSIPR_ICDIP, ECSIPR);
- ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, CXR31_SEL_LINK0);
+ if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
+ ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, 0);
+ ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_MII, CXR35);
+ } else {
+ ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1,
+ CXR31_SEL_LINK0);
+ }
}
static void ravb_emac_init_rcar(struct net_device *ndev)
@@ -1124,7 +1130,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 +1312,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 {
@@ -1432,11 +1438,7 @@ static int ravb_phy_init(struct net_device *ndev)
* at this time.
*/
if (soc_device_match(r8a7795es10)) {
- err = phy_set_max_speed(phydev, SPEED_100);
- if (err) {
- netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n");
- goto err_phy_disconnect;
- }
+ phy_set_max_speed(phydev, SPEED_100);
netdev_info(ndev, "limited PHY to 100Mbit/s\n");
}
@@ -1453,12 +1455,12 @@ static int ravb_phy_init(struct net_device *ndev)
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
}
+ /* Indicate that the MAC is responsible for managing PHY PM */
+ phydev->mac_managed_pm = true;
phy_attached_info(phydev);
return 0;
-err_phy_disconnect:
- phy_disconnect(phydev);
err_deregister_fixed_link:
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
@@ -1804,12 +1806,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 */
@@ -1829,9 +1842,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);
@@ -2172,6 +2191,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);
@@ -2416,6 +2439,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,
@@ -2444,6 +2468,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,
@@ -2471,6 +2520,8 @@ 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-rcar-gen4", .data = &ravb_gen3_hw_info },
+ { .compatible = "renesas,etheravb-rzv2m", .data = &ravb_rzv2m_hw_info },
{ .compatible = "renesas,rzg2l-gbeth", .data = &gbeth_hw_info },
{ }
};
@@ -2479,11 +2530,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;
@@ -2600,10 +2655,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;
@@ -2645,7 +2704,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;
@@ -2667,6 +2729,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);
@@ -2682,6 +2760,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;
@@ -2703,7 +2790,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);
@@ -2723,7 +2810,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;
@@ -2754,9 +2841,9 @@ static int ravb_probe(struct platform_device *pdev)
goto out_dma_free;
}
- netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll, 64);
+ netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll);
if (info->nc_queues)
- netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll, 64);
+ netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll);
/* Network device register */
error = register_netdev(ndev);
@@ -2786,6 +2873,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:
@@ -2807,6 +2896,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,
@@ -2854,7 +2944,6 @@ static int ravb_wol_restore(struct net_device *ndev)
{
struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info;
- int ret;
if (info->nc_queues)
napi_enable(&priv->napi[RAVB_NC]);
@@ -2863,9 +2952,7 @@ static int ravb_wol_restore(struct net_device *ndev)
/* Disable MagicPacket */
ravb_modify(ndev, ECMR, ECMR_MPDE, 0);
- ret = ravb_close(ndev);
- if (ret < 0)
- return ret;
+ ravb_close(ndev);
return disable_irq_wake(priv->emac_irq);
}
diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c
index c099656dd75b..87c4306d66ec 100644
--- a/drivers/net/ethernet/renesas/ravb_ptp.c
+++ b/drivers/net/ethernet/renesas/ravb_ptp.c
@@ -198,7 +198,7 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp,
priv->ptp.extts[req->index] = on;
spin_lock_irqsave(&priv->lock, flags);
- if (!info->multi_irqs)
+ if (!info->irq_en_dis)
ravb_modify(ndev, GIC, GIC_PTCE, on ? GIC_PTCE : 0);
else if (on)
ravb_write(ndev, GIE_PTCS, GIE);
@@ -254,7 +254,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp,
error = ravb_ptp_update_compare(priv, (u32)start_ns);
if (!error) {
/* Unmask interrupt */
- if (!info->multi_irqs)
+ if (!info->irq_en_dis)
ravb_modify(ndev, GIC, GIC_PTME, GIC_PTME);
else
ravb_write(ndev, GIE_PTMS0, GIE);
@@ -266,7 +266,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp,
perout->period = 0;
/* Mask interrupt */
- if (!info->multi_irqs)
+ if (!info->irq_en_dis)
ravb_modify(ndev, GIC, GIC_PTME, 0);
else
ravb_write(ndev, GID_PTMD0, GID);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index d947a628e166..71a499113308 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2026,15 +2026,11 @@ static int sh_eth_phy_init(struct net_device *ndev)
}
/* mask with MAC supported features */
- if (mdp->cd->register_type != SH_ETH_REG_GIGABIT) {
- int err = phy_set_max_speed(phydev, SPEED_100);
- if (err) {
- netdev_err(ndev, "failed to limit PHY to 100 Mbit/s\n");
- phy_disconnect(phydev);
- return err;
- }
- }
+ if (mdp->cd->register_type != SH_ETH_REG_GIGABIT)
+ phy_set_max_speed(phydev, SPEED_100);
+ /* Indicate that the MAC is responsible for managing PHY PM */
+ phydev->mac_managed_pm = true;
phy_attached_info(phydev);
return 0;
@@ -3372,7 +3368,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
goto out_release;
}
- netif_napi_add(ndev, &mdp->napi, sh_eth_poll, 64);
+ netif_napi_add(ndev, &mdp->napi, sh_eth_poll);
/* network device register */
ret = register_netdev(ndev);
@@ -3450,9 +3446,7 @@ static int sh_eth_wol_restore(struct net_device *ndev)
* both be reset and all registers restored. This is what
* happens during suspend and resume without WoL enabled.
*/
- ret = sh_eth_close(ndev);
- if (ret < 0)
- return ret;
+ sh_eth_close(ndev);
ret = sh_eth_open(ndev);
if (ret < 0)
return ret;
@@ -3464,7 +3458,7 @@ static int sh_eth_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct sh_eth_private *mdp = netdev_priv(ndev);
- int ret = 0;
+ int ret;
if (!netif_running(ndev))
return 0;
@@ -3483,7 +3477,7 @@ static int sh_eth_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct sh_eth_private *mdp = netdev_priv(ndev);
- int ret = 0;
+ int ret;
if (!netif_running(ndev))
return 0;