diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index d6136fe5c206..b03fae7a0f72 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -34,6 +34,7 @@ config RAVB select MII select MDIO_BITBANG select PHYLIB + select RESET_CONTROLLER help Renesas Ethernet AVB device driver. diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h index e0f8276cffed..268ccfafe7aa 100644 --- a/drivers/net/ethernet/renesas/ravb.h +++ b/drivers/net/ethernet/renesas/ravb.h @@ -1089,10 +1089,6 @@ 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]; unsigned no_avb_link:1; unsigned avb_link_active_low:1; @@ -1106,6 +1102,8 @@ struct ravb_private { const struct ravb_hw_info *info; struct reset_control *rstc; + + u32 gti_tiv; }; static inline u32 ravb_read(struct net_device *ndev, enum ravb_reg reg) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 0e3731f50fc2..9521cd054274 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -38,16 +38,6 @@ NETIF_MSG_RX_ERR | \ NETIF_MSG_TX_ERR) -static const char *ravb_rx_irqs[NUM_RX_QUEUE] = { - "ch0", /* RAVB_BE */ - "ch1", /* RAVB_NC */ -}; - -static const char *ravb_tx_irqs[NUM_TX_QUEUE] = { - "ch18", /* RAVB_BE */ - "ch19", /* RAVB_NC */ -}; - void ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear, u32 set) { @@ -96,13 +86,13 @@ static void ravb_set_rate_gbeth(struct net_device *ndev) struct ravb_private *priv = netdev_priv(ndev); switch (priv->speed) { - case 10: /* 10BASE */ + case 10: /* 10BASE */ ravb_write(ndev, GBETH_GECMR_SPEED_10, GECMR); break; - case 100: /* 100BASE */ + case 100: /* 100BASE */ ravb_write(ndev, GBETH_GECMR_SPEED_100, GECMR); break; - case 1000: /* 1000BASE */ + case 1000: /* 1000BASE */ ravb_write(ndev, GBETH_GECMR_SPEED_1000, GECMR); break; } @@ -1092,11 +1082,23 @@ static irqreturn_t ravb_emac_interrupt(int irq, void *dev_id) { struct net_device *ndev = dev_id; struct ravb_private *priv = netdev_priv(ndev); + struct device *dev = &priv->pdev->dev; + irqreturn_t result = IRQ_HANDLED; + + pm_runtime_get_noresume(dev); + + if (unlikely(!pm_runtime_active(dev))) { + result = IRQ_NONE; + goto out_rpm_put; + } spin_lock(&priv->lock); ravb_emac_interrupt_unlocked(ndev); spin_unlock(&priv->lock); - return IRQ_HANDLED; + +out_rpm_put: + pm_runtime_put_noidle(dev); + return result; } /* Error interrupt handler */ @@ -1176,9 +1178,15 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id) struct net_device *ndev = dev_id; struct ravb_private *priv = netdev_priv(ndev); const struct ravb_hw_info *info = priv->info; + struct device *dev = &priv->pdev->dev; irqreturn_t result = IRQ_NONE; u32 iss; + pm_runtime_get_noresume(dev); + + if (unlikely(!pm_runtime_active(dev))) + goto out_rpm_put; + spin_lock(&priv->lock); /* Get interrupt status */ iss = ravb_read(ndev, ISS); @@ -1222,6 +1230,9 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id) } spin_unlock(&priv->lock); + +out_rpm_put: + pm_runtime_put_noidle(dev); return result; } @@ -1230,9 +1241,15 @@ static irqreturn_t ravb_multi_interrupt(int irq, void *dev_id) { struct net_device *ndev = dev_id; struct ravb_private *priv = netdev_priv(ndev); + struct device *dev = &priv->pdev->dev; irqreturn_t result = IRQ_NONE; u32 iss; + pm_runtime_get_noresume(dev); + + if (unlikely(!pm_runtime_active(dev))) + goto out_rpm_put; + spin_lock(&priv->lock); /* Get interrupt status */ iss = ravb_read(ndev, ISS); @@ -1254,6 +1271,9 @@ static irqreturn_t ravb_multi_interrupt(int irq, void *dev_id) } spin_unlock(&priv->lock); + +out_rpm_put: + pm_runtime_put_noidle(dev); return result; } @@ -1261,8 +1281,14 @@ static irqreturn_t ravb_dma_interrupt(int irq, void *dev_id, int q) { struct net_device *ndev = dev_id; struct ravb_private *priv = netdev_priv(ndev); + struct device *dev = &priv->pdev->dev; irqreturn_t result = IRQ_NONE; + pm_runtime_get_noresume(dev); + + if (unlikely(!pm_runtime_active(dev))) + goto out_rpm_put; + spin_lock(&priv->lock); /* Network control/Best effort queue RX/TX */ @@ -1270,6 +1296,9 @@ static irqreturn_t ravb_dma_interrupt(int irq, void *dev_id, int q) result = IRQ_HANDLED; spin_unlock(&priv->lock); + +out_rpm_put: + pm_runtime_put_noidle(dev); return result; } @@ -1288,25 +1317,16 @@ static int ravb_poll(struct napi_struct *napi, int budget) struct net_device *ndev = napi->dev; struct ravb_private *priv = netdev_priv(ndev); const struct ravb_hw_info *info = priv->info; - bool gptp = info->gptp || info->ccc_gac; - struct ravb_rx_desc *desc; unsigned long flags; int q = napi - priv->napi; int mask = BIT(q); int quota = budget; - unsigned int entry; - if (!gptp) { - entry = priv->cur_rx[q] % priv->num_rx_ring[q]; - desc = &priv->gbeth_rx_ring[entry]; - } /* Processing RX Descriptor Ring */ /* Clear RX interrupt */ ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0); - if (gptp || desc->die_dt != DT_FEMPTY) { - if (ravb_rx(ndev, "a, q)) - goto out; - } + if (ravb_rx(ndev, "a, q)) + goto out; /* Processing TX Descriptor Ring */ spin_lock_irqsave(&priv->lock, flags); @@ -1736,89 +1756,154 @@ static const struct ethtool_ops ravb_ethtool_ops = { .set_wol = ravb_set_wol, }; -static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler, - struct net_device *ndev, struct device *dev, - const char *ch) +static int ravb_set_config_mode(struct net_device *ndev) { - char *name; + struct ravb_private *priv = netdev_priv(ndev); + const struct ravb_hw_info *info = priv->info; int error; - name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch); - if (!name) - return -ENOMEM; - error = request_irq(irq, handler, 0, name, ndev); - if (error) - netdev_err(ndev, "cannot request IRQ %s\n", name); + if (info->gptp) { + error = ravb_set_opmode(ndev, CCC_OPC_CONFIG); + if (error) + return error; + /* Set CSEL value */ + ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB); + } else if (info->ccc_gac) { + error = ravb_set_opmode(ndev, CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB); + } else { + error = ravb_set_opmode(ndev, CCC_OPC_CONFIG); + } return error; } +static void ravb_set_gti(struct net_device *ndev) +{ + struct ravb_private *priv = netdev_priv(ndev); + const struct ravb_hw_info *info = priv->info; + + if (!(info->gptp || info->ccc_gac)) + return; + + ravb_write(ndev, priv->gti_tiv, GTI); + + /* Request GTI loading */ + ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); +} + +static int ravb_compute_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; + u64 inc; + + if (!(info->gptp || info->ccc_gac)) + return 0; + + if (info->gptp_ref_clk) + rate = clk_get_rate(priv->gptp_clk); + else + rate = clk_get_rate(priv->clk); + if (!rate) + return -EINVAL; + + inc = div64_ul(1000000000ULL << 20, rate); + + if (inc < GTI_TIV_MIN || inc > GTI_TIV_MAX) { + dev_err(dev, "gti.tiv increment 0x%llx is outside the range 0x%x - 0x%x\n", + inc, GTI_TIV_MIN, GTI_TIV_MAX); + return -EINVAL; + } + priv->gti_tiv = inc; + + return 0; +} + +/* Set tx and rx clock internal delay modes */ +static void ravb_parse_delay_mode(struct device_node *np, struct net_device *ndev) +{ + struct ravb_private *priv = netdev_priv(ndev); + bool explicit_delay = false; + u32 delay; + + if (!priv->info->internal_delay) + return; + + if (!of_property_read_u32(np, "rx-internal-delay-ps", &delay)) { + /* Valid values are 0 and 1800, according to DT bindings */ + priv->rxcidm = !!delay; + explicit_delay = true; + } + if (!of_property_read_u32(np, "tx-internal-delay-ps", &delay)) { + /* Valid values are 0 and 2000, according to DT bindings */ + priv->txcidm = !!delay; + explicit_delay = true; + } + + if (explicit_delay) + return; + + /* Fall back to legacy rgmii-*id behavior */ + if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || + priv->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) { + priv->rxcidm = 1; + priv->rgmii_override = 1; + } + + if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || + priv->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) { + priv->txcidm = 1; + priv->rgmii_override = 1; + } +} + +static void ravb_set_delay_mode(struct net_device *ndev) +{ + struct ravb_private *priv = netdev_priv(ndev); + u32 set = 0; + + if (!priv->info->internal_delay) + return; + + if (priv->rxcidm) + set |= APSR_RDM; + if (priv->txcidm) + set |= APSR_TDM; + ravb_modify(ndev, APSR, APSR_RDM | APSR_TDM, set); +} + /* Network device open function for Ethernet AVB */ static int ravb_open(struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); const struct ravb_hw_info *info = priv->info; - struct platform_device *pdev = priv->pdev; - struct device *dev = &pdev->dev; int error; napi_enable(&priv->napi[RAVB_BE]); if (info->nc_queues) napi_enable(&priv->napi[RAVB_NC]); - if (!info->multi_irqs) { - error = request_irq(ndev->irq, ravb_interrupt, IRQF_SHARED, - ndev->name, ndev); - if (error) { - netdev_err(ndev, "cannot request IRQ\n"); - goto out_napi_off; - } - } else { - error = ravb_hook_irq(ndev->irq, ravb_multi_interrupt, ndev, - dev, "ch22:multi"); - if (error) - goto out_napi_off; - error = ravb_hook_irq(priv->emac_irq, ravb_emac_interrupt, ndev, - dev, "ch24:emac"); - if (error) - goto out_free_irq; - error = ravb_hook_irq(priv->rx_irqs[RAVB_BE], ravb_be_interrupt, - ndev, dev, "ch0:rx_be"); - if (error) - goto out_free_irq_emac; - error = ravb_hook_irq(priv->tx_irqs[RAVB_BE], ravb_be_interrupt, - ndev, dev, "ch18:tx_be"); - if (error) - goto out_free_irq_be_rx; - error = ravb_hook_irq(priv->rx_irqs[RAVB_NC], ravb_nc_interrupt, - ndev, dev, "ch1:rx_nc"); - if (error) - goto out_free_irq_be_tx; - error = ravb_hook_irq(priv->tx_irqs[RAVB_NC], ravb_nc_interrupt, - ndev, dev, "ch19:tx_nc"); - if (error) - goto out_free_irq_nc_rx; + /* Set AVB config mode */ + error = ravb_set_config_mode(ndev); + if (error) + goto out_napi_off; - 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; - } - } + ravb_set_delay_mode(ndev); + ravb_write(ndev, priv->desc_bat_dma, DBAT); /* Device init */ error = ravb_dmac_init(ndev); if (error) - goto out_free_irq_mgmta; + goto out_set_reset; + ravb_emac_init(ndev); + ravb_set_gti(ndev); + /* Initialise PTP Clock driver */ - if (info->gptp) + if (info->gptp || info->ccc_gac) ravb_ptp_init(ndev, priv->pdev); /* PHY control start */ @@ -1832,29 +1917,11 @@ static int ravb_open(struct net_device *ndev) out_ptp_stop: /* Stop PTP Clock driver */ - if (info->gptp) + if (info->gptp || info->ccc_gac) ravb_ptp_stop(ndev); ravb_stop_dma(ndev); -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); -out_free_irq_be_tx: - free_irq(priv->tx_irqs[RAVB_BE], ndev); -out_free_irq_be_rx: - free_irq(priv->rx_irqs[RAVB_BE], ndev); -out_free_irq_emac: - free_irq(priv->emac_irq, ndev); -out_free_irq: - free_irq(ndev->irq, ndev); +out_set_reset: + ravb_set_opmode(ndev, CCC_OPC_RESET); out_napi_off: if (info->nc_queues) napi_disable(&priv->napi[RAVB_NC]); @@ -2162,7 +2229,7 @@ static int ravb_close(struct net_device *ndev) ravb_write(ndev, 0, TIC); /* Stop PTP Clock driver */ - if (info->gptp) + if (info->gptp || info->ccc_gac) ravb_ptp_stop(ndev); /* Set the config mode to stop the AVB-DMAC's processes */ @@ -2189,19 +2256,6 @@ static int ravb_close(struct net_device *ndev) cancel_work_sync(&priv->work); - if (info->multi_irqs) { - free_irq(priv->tx_irqs[RAVB_NC], ndev); - free_irq(priv->rx_irqs[RAVB_NC], 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); - if (info->nc_queues) napi_disable(&priv->napi[RAVB_NC]); napi_disable(&priv->napi[RAVB_BE]); @@ -2211,7 +2265,8 @@ static int ravb_close(struct net_device *ndev) if (info->nc_queues) ravb_ring_free(ndev, RAVB_NC); - return 0; + /* Set reset mode. */ + return ravb_set_opmode(ndev, CCC_OPC_RESET); } static int ravb_hwtstamp_get(struct net_device *ndev, struct ifreq *req) @@ -2541,100 +2596,88 @@ static const struct of_device_id ravb_match_table[] = { }; MODULE_DEVICE_TABLE(of, ravb_match_table); -static int ravb_set_gti(struct net_device *ndev) +static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name, + const char *ch, int *irq, irq_handler_t handler) { - 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; - - if (info->gptp_ref_clk) - rate = clk_get_rate(priv->gptp_clk); - else - rate = clk_get_rate(priv->clk); - if (!rate) - return -EINVAL; - - inc = div64_ul(1000000000ULL << 20, rate); - - if (inc < GTI_TIV_MIN || inc > GTI_TIV_MAX) { - dev_err(dev, "gti.tiv increment 0x%llx is outside the range 0x%x - 0x%x\n", - inc, GTI_TIV_MIN, GTI_TIV_MAX); - return -EINVAL; - } - - ravb_write(ndev, inc, GTI); - - return 0; -} - -static int ravb_set_config_mode(struct net_device *ndev) -{ - struct ravb_private *priv = netdev_priv(ndev); - const struct ravb_hw_info *info = priv->info; + struct platform_device *pdev = priv->pdev; + struct net_device *ndev = priv->ndev; + struct device *dev = &pdev->dev; + const char *dev_name; + unsigned long flags; int error; - if (info->gptp) { - error = ravb_set_opmode(ndev, CCC_OPC_CONFIG); - if (error) - return error; - /* Set CSEL value */ - ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB); - } else if (info->ccc_gac) { - error = ravb_set_opmode(ndev, CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB); + if (irq_name) { + dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch); + if (!dev_name) + return -ENOMEM; + + *irq = platform_get_irq_byname(pdev, irq_name); + flags = 0; } else { - error = ravb_set_opmode(ndev, CCC_OPC_CONFIG); + dev_name = ndev->name; + *irq = platform_get_irq(pdev, 0); + flags = IRQF_SHARED; } + if (*irq < 0) + return *irq; + + error = devm_request_irq(dev, *irq, handler, flags, dev_name, ndev); + if (error) + netdev_err(ndev, "cannot request IRQ %s\n", dev_name); return error; } -/* Set tx and rx clock internal delay modes */ -static void ravb_parse_delay_mode(struct device_node *np, struct net_device *ndev) +static int ravb_setup_irqs(struct ravb_private *priv) { - struct ravb_private *priv = netdev_priv(ndev); - bool explicit_delay = false; - u32 delay; + const struct ravb_hw_info *info = priv->info; + struct net_device *ndev = priv->ndev; + const char *irq_name, *emac_irq_name; + int error, irq; - if (!of_property_read_u32(np, "rx-internal-delay-ps", &delay)) { - /* Valid values are 0 and 1800, according to DT bindings */ - priv->rxcidm = !!delay; - explicit_delay = true; - } - if (!of_property_read_u32(np, "tx-internal-delay-ps", &delay)) { - /* Valid values are 0 and 2000, according to DT bindings */ - priv->txcidm = !!delay; - explicit_delay = true; + if (!info->multi_irqs) + return ravb_setup_irq(priv, NULL, NULL, &ndev->irq, ravb_interrupt); + + if (info->err_mgmt_irqs) { + irq_name = "dia"; + emac_irq_name = "line3"; + } else { + irq_name = "ch22"; + emac_irq_name = "ch24"; } - if (explicit_delay) - return; + error = ravb_setup_irq(priv, irq_name, "ch22:multi", &ndev->irq, ravb_multi_interrupt); + if (error) + return error; - /* Fall back to legacy rgmii-*id behavior */ - if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || - priv->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) { - priv->rxcidm = 1; - priv->rgmii_override = 1; + error = ravb_setup_irq(priv, emac_irq_name, "ch24:emac", &priv->emac_irq, + ravb_emac_interrupt); + if (error) + return error; + + if (info->err_mgmt_irqs) { + error = ravb_setup_irq(priv, "err_a", "err_a", &irq, ravb_multi_interrupt); + if (error) + return error; + + error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", &irq, ravb_multi_interrupt); + if (error) + return error; } - if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || - priv->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) { - priv->txcidm = 1; - priv->rgmii_override = 1; - } -} + error = ravb_setup_irq(priv, "ch0", "ch0:rx_be", &irq, ravb_be_interrupt); + if (error) + return error; -static void ravb_set_delay_mode(struct net_device *ndev) -{ - struct ravb_private *priv = netdev_priv(ndev); - u32 set = 0; + error = ravb_setup_irq(priv, "ch1", "ch1:rx_nc", &irq, ravb_nc_interrupt); + if (error) + return error; - if (priv->rxcidm) - set |= APSR_RDM; - if (priv->txcidm) - set |= APSR_TDM; - ravb_modify(ndev, APSR, APSR_RDM | APSR_TDM, set); + error = ravb_setup_irq(priv, "ch18", "ch18:tx_be", &irq, ravb_be_interrupt); + if (error) + return error; + + return ravb_setup_irq(priv, "ch19", "ch19:tx_nc", &irq, ravb_nc_interrupt); } static int ravb_probe(struct platform_device *pdev) @@ -2644,9 +2687,8 @@ static int ravb_probe(struct platform_device *pdev) struct reset_control *rstc; struct ravb_private *priv; struct net_device *ndev; - int error, irq, q; struct resource *res; - int i; + int error, q; if (!np) { dev_err(&pdev->dev, @@ -2654,7 +2696,7 @@ static int ravb_probe(struct platform_device *pdev) return -EINVAL; } - rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(rstc)) return dev_err_probe(&pdev->dev, PTR_ERR(rstc), "failed to get cpg reset\n"); @@ -2673,25 +2715,6 @@ static int ravb_probe(struct platform_device *pdev) if (error) goto out_free_netdev; - pm_runtime_enable(&pdev->dev); - error = pm_runtime_resume_and_get(&pdev->dev); - if (error < 0) - goto out_rpm_disable; - - 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; - } - ndev->irq = irq; - SET_NETDEV_DEV(ndev, &pdev->dev); priv = netdev_priv(ndev); @@ -2706,10 +2729,41 @@ static int ravb_probe(struct platform_device *pdev) priv->num_rx_ring[RAVB_NC] = NC_RX_RING_SIZE; } + error = ravb_setup_irqs(priv); + if (error) + goto out_reset_assert; + + priv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) { + error = PTR_ERR(priv->clk); + goto out_reset_assert; + } + + 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_reset_assert; + } + } + + priv->refclk = devm_clk_get_optional(&pdev->dev, "refclk"); + if (IS_ERR(priv->refclk)) { + error = PTR_ERR(priv->refclk); + goto out_reset_assert; + } + clk_prepare(priv->refclk); + + platform_set_drvdata(pdev, ndev); + pm_runtime_enable(&pdev->dev); + error = pm_runtime_resume_and_get(&pdev->dev); + if (error < 0) + goto out_rpm_disable; + priv->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(priv->addr)) { error = PTR_ERR(priv->addr); - goto out_release; + goto out_rpm_put; } /* The Ether-specific entries in the device structure. */ @@ -2720,78 +2774,12 @@ static int ravb_probe(struct platform_device *pdev) error = of_get_phy_mode(np, &priv->phy_interface); if (error && error != -ENODEV) - goto out_release; + goto out_rpm_put; priv->no_avb_link = of_property_read_bool(np, "renesas,no-ether-link"); priv->avb_link_active_low = of_property_read_bool(np, "renesas,ether-link-active-low"); - if (info->multi_irqs) { - 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; - } - priv->emac_irq = irq; - for (i = 0; i < NUM_RX_QUEUE; i++) { - irq = platform_get_irq_byname(pdev, ravb_rx_irqs[i]); - if (irq < 0) { - error = irq; - goto out_release; - } - priv->rx_irqs[i] = irq; - } - for (i = 0; i < NUM_TX_QUEUE; i++) { - irq = platform_get_irq_byname(pdev, ravb_tx_irqs[i]); - if (irq < 0) { - error = irq; - goto out_release; - } - 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); - if (IS_ERR(priv->clk)) { - error = PTR_ERR(priv->clk); - goto out_release; - } - - priv->refclk = devm_clk_get_optional(&pdev->dev, "refclk"); - if (IS_ERR(priv->refclk)) { - error = PTR_ERR(priv->refclk); - goto out_release; - } - 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; @@ -2806,25 +2794,11 @@ static int ravb_probe(struct platform_device *pdev) ndev->netdev_ops = &ravb_netdev_ops; ndev->ethtool_ops = &ravb_ethtool_ops; - /* Set AVB config mode */ - error = ravb_set_config_mode(ndev); + error = ravb_compute_gti(ndev); if (error) - goto out_disable_gptp_clk; + goto out_rpm_put; - if (info->gptp || info->ccc_gac) { - /* Set GTI value */ - error = ravb_set_gti(ndev); - if (error) - goto out_disable_gptp_clk; - - /* Request GTI loading */ - ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); - } - - if (info->internal_delay) { - ravb_parse_delay_mode(np, ndev); - ravb_set_delay_mode(ndev); - } + ravb_parse_delay_mode(np, ndev); /* Allocate descriptor base address table */ priv->desc_bat_size = sizeof(struct ravb_desc) * DBAT_ENTRY_NUM; @@ -2835,22 +2809,22 @@ 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_gptp_clk; + goto out_rpm_put; } for (q = RAVB_BE; q < DBAT_ENTRY_NUM; q++) priv->desc_bat[q].die_dt = DT_EOS; - ravb_write(ndev, priv->desc_bat_dma, DBAT); /* Initialise HW timestamp list */ INIT_LIST_HEAD(&priv->ts_skb_list); - /* Initialise PTP Clock driver */ - if (info->ccc_gac) - ravb_ptp_init(ndev, pdev); - /* Debug message level */ priv->msg_enable = RAVB_DEF_MSG_ENABLE; + /* Set config mode as this is needed for PHY initialization. */ + error = ravb_set_opmode(ndev, CCC_OPC_CONFIG); + if (error) + goto out_rpm_put; + /* Read and set MAC address */ ravb_read_mac_address(np, ndev); if (!is_valid_ether_addr(ndev->dev_addr)) { @@ -2863,9 +2837,14 @@ static int ravb_probe(struct platform_device *pdev) error = ravb_mdio_init(priv); if (error) { dev_err(&pdev->dev, "failed to initialize MDIO\n"); - goto out_dma_free; + goto out_reset_mode; } + /* Undo previous switch to config opmode. */ + error = ravb_set_opmode(ndev, CCC_OPC_RESET); + if (error) + goto out_mdio_release; + netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll); if (info->nc_queues) netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll); @@ -2881,8 +2860,6 @@ static int ravb_probe(struct platform_device *pdev) netdev_info(ndev, "Base address at %#x, %pM, IRQ %d.\n", (u32)ndev->base_addr, ndev->dev_addr, ndev->irq); - platform_set_drvdata(pdev, ndev); - return 0; out_napi_del: @@ -2890,22 +2867,18 @@ out_napi_del: netif_napi_del(&priv->napi[RAVB_NC]); netif_napi_del(&priv->napi[RAVB_BE]); +out_mdio_release: ravb_mdio_release(priv); -out_dma_free: +out_reset_mode: + ravb_set_opmode(ndev, CCC_OPC_RESET); dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, priv->desc_bat_dma); - - /* 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: +out_rpm_put: pm_runtime_put(&pdev->dev); out_rpm_disable: pm_runtime_disable(&pdev->dev); + clk_unprepare(priv->refclk); +out_reset_assert: reset_control_assert(rstc); out_free_netdev: free_netdev(ndev); @@ -2925,20 +2898,12 @@ static void ravb_remove(struct platform_device *pdev) ravb_mdio_release(priv); - /* Stop PTP Clock driver */ - if (info->ccc_gac) - ravb_ptp_stop(ndev); - dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, priv->desc_bat_dma); - ravb_set_opmode(ndev, CCC_OPC_RESET); - - clk_disable_unprepare(priv->gptp_clk); - clk_disable_unprepare(priv->refclk); - pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); + clk_unprepare(priv->refclk); reset_control_assert(priv->rstc); free_netdev(ndev); platform_set_drvdata(pdev, NULL); @@ -2964,6 +2929,9 @@ static int ravb_wol_setup(struct net_device *ndev) /* Enable MagicPacket */ ravb_modify(ndev, ECMR, ECMR_MPDE, ECMR_MPDE); + if (priv->info->ccc_gac) + ravb_ptp_stop(ndev); + return enable_irq_wake(priv->emac_irq); } @@ -2971,6 +2939,20 @@ 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 error; + + /* Set reset mode to rearm the WoL logic. */ + error = ravb_set_opmode(ndev, CCC_OPC_RESET); + if (error) + return error; + + /* Set AVB config mode. */ + error = ravb_set_config_mode(ndev); + if (error) + return error; + + if (priv->info->ccc_gac) + ravb_ptp_init(ndev, priv->pdev); if (info->nc_queues) napi_enable(&priv->napi[RAVB_NC]); @@ -2984,102 +2966,80 @@ static int ravb_wol_restore(struct net_device *ndev) return disable_irq_wake(priv->emac_irq); } -static int __maybe_unused ravb_suspend(struct device *dev) +static int ravb_suspend(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); struct ravb_private *priv = netdev_priv(ndev); int ret; if (!netif_running(ndev)) - return 0; + goto reset_assert; netif_device_detach(ndev); if (priv->wol_enabled) - ret = ravb_wol_setup(ndev); - else - ret = ravb_close(ndev); + return ravb_wol_setup(ndev); - if (priv->info->ccc_gac) - ravb_ptp_stop(ndev); - - return ret; -} - -static int __maybe_unused ravb_resume(struct device *dev) -{ - struct net_device *ndev = dev_get_drvdata(dev); - struct ravb_private *priv = netdev_priv(ndev); - const struct ravb_hw_info *info = priv->info; - int ret = 0; - - /* If WoL is enabled set reset mode to rearm the WoL logic */ - if (priv->wol_enabled) { - ret = ravb_set_opmode(ndev, CCC_OPC_RESET); - if (ret) - return ret; - } - - /* All register have been reset to default values. - * Restore all registers which where setup at probe time and - * reopen device if it was running before system suspended. - */ - - /* Set AVB config mode */ - ret = ravb_set_config_mode(ndev); + ret = ravb_close(ndev); if (ret) return ret; - if (info->gptp || info->ccc_gac) { - /* Set GTI value */ - ret = ravb_set_gti(ndev); +reset_assert: + return reset_control_assert(priv->rstc); +} + +static int ravb_resume(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct ravb_private *priv = netdev_priv(ndev); + int ret; + + ret = reset_control_deassert(priv->rstc); + if (ret) + return ret; + + if (!netif_running(ndev)) + return 0; + + /* If WoL is enabled restore the interface. */ + if (priv->wol_enabled) { + ret = ravb_wol_restore(ndev); if (ret) return ret; - - /* Request GTI loading */ - ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); } - if (info->internal_delay) - ravb_set_delay_mode(ndev); + /* Reopening the interface will restore the device to the working state. */ + ret = ravb_open(ndev); + if (ret < 0) + return ret; - /* Restore descriptor base address table */ - ravb_write(ndev, priv->desc_bat_dma, DBAT); - - if (priv->info->ccc_gac) - ravb_ptp_init(ndev, priv->pdev); - - if (netif_running(ndev)) { - if (priv->wol_enabled) { - ret = ravb_wol_restore(ndev); - if (ret) - return ret; - } - ret = ravb_open(ndev); - if (ret < 0) - return ret; - ravb_set_rx_mode(ndev); - netif_device_attach(ndev); - } + ravb_set_rx_mode(ndev); + netif_device_attach(ndev); return ret; } -static int __maybe_unused ravb_runtime_nop(struct device *dev) +static int ravb_runtime_suspend(struct device *dev) { - /* Runtime PM callback shared between ->runtime_suspend() - * and ->runtime_resume(). Simply returns success. - * - * This driver re-initializes all registers after - * pm_runtime_get_sync() anyway so there is no need - * to save and restore registers here. - */ + struct net_device *ndev = dev_get_drvdata(dev); + struct ravb_private *priv = netdev_priv(ndev); + + clk_disable(priv->refclk); + return 0; } +static int ravb_runtime_resume(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct ravb_private *priv = netdev_priv(ndev); + + return clk_enable(priv->refclk); +} + static const struct dev_pm_ops ravb_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(ravb_suspend, ravb_resume) - SET_RUNTIME_PM_OPS(ravb_runtime_nop, ravb_runtime_nop, NULL) + SYSTEM_SLEEP_PM_OPS(ravb_suspend, ravb_resume) + RUNTIME_PM_OPS(ravb_runtime_suspend, ravb_runtime_resume, NULL) }; static struct platform_driver ravb_driver = { @@ -3087,7 +3047,7 @@ static struct platform_driver ravb_driver = { .remove_new = ravb_remove, .driver = { .name = "ravb", - .pm = &ravb_dev_pm_ops, + .pm = pm_ptr(&ravb_dev_pm_ops), .of_match_table = ravb_match_table, }, };