Merge branch 'net-systemport-Clock-support'

Florian Fainelli says:

====================
net: systemport: Clock support

This patch series makes the SYSTEMPORT driver request and manage its
main and Wake-on-LAN clocks appropriately.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-09-03 15:06:03 -07:00
commit e8f259651f
3 changed files with 45 additions and 2 deletions

View File

@ -20,6 +20,11 @@ Optional properties:
- systemport,num-tier1-arb: number of tier 1 arbiters, an integer - systemport,num-tier1-arb: number of tier 1 arbiters, an integer
- systemport,num-txq: number of HW transmit queues, an integer - systemport,num-txq: number of HW transmit queues, an integer
- systemport,num-rxq: number of HW receive queues, an integer - systemport,num-rxq: number of HW receive queues, an integer
- clocks: When provided, must be two phandles to the functional clocks nodes of
the SYSTEMPORT block. The first phandle is the main SYSTEMPORT clock used
during normal operation, while the second phandle is the Wake-on-LAN clock.
- clock-names: When provided, names of the functional clock phandles, first
name should be "sw_sysport" and second should be "sw_sysportwol".
Example: Example:
ethernet@f04a0000 { ethernet@f04a0000 {

View File

@ -20,6 +20,7 @@
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/phy_fixed.h> #include <linux/phy_fixed.h>
#include <net/dsa.h> #include <net/dsa.h>
#include <linux/clk.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/ipv6.h> #include <net/ipv6.h>
@ -186,6 +187,11 @@ static int bcm_sysport_set_features(struct net_device *dev,
netdev_features_t features) netdev_features_t features)
{ {
struct bcm_sysport_priv *priv = netdev_priv(dev); struct bcm_sysport_priv *priv = netdev_priv(dev);
int ret;
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
/* Read CRC forward */ /* Read CRC forward */
if (!priv->is_lite) if (!priv->is_lite)
@ -197,6 +203,8 @@ static int bcm_sysport_set_features(struct net_device *dev,
bcm_sysport_set_rx_csum(dev, features); bcm_sysport_set_rx_csum(dev, features);
bcm_sysport_set_tx_csum(dev, features); bcm_sysport_set_tx_csum(dev, features);
clk_disable_unprepare(priv->clk);
return 0; return 0;
} }
@ -1940,6 +1948,8 @@ static int bcm_sysport_open(struct net_device *dev)
unsigned int i; unsigned int i;
int ret; int ret;
clk_prepare_enable(priv->clk);
/* Reset UniMAC */ /* Reset UniMAC */
umac_reset(priv); umac_reset(priv);
@ -1970,7 +1980,8 @@ static int bcm_sysport_open(struct net_device *dev)
0, priv->phy_interface); 0, priv->phy_interface);
if (!phydev) { if (!phydev) {
netdev_err(dev, "could not attach to PHY\n"); netdev_err(dev, "could not attach to PHY\n");
return -ENODEV; ret = -ENODEV;
goto out_clk_disable;
} }
/* Reset house keeping link status */ /* Reset house keeping link status */
@ -2048,6 +2059,8 @@ out_free_irq0:
free_irq(priv->irq0, dev); free_irq(priv->irq0, dev);
out_phy_disconnect: out_phy_disconnect:
phy_disconnect(phydev); phy_disconnect(phydev);
out_clk_disable:
clk_disable_unprepare(priv->clk);
return ret; return ret;
} }
@ -2106,6 +2119,8 @@ static int bcm_sysport_stop(struct net_device *dev)
/* Disconnect from PHY */ /* Disconnect from PHY */
phy_disconnect(dev->phydev); phy_disconnect(dev->phydev);
clk_disable_unprepare(priv->clk);
return 0; return 0;
} }
@ -2487,6 +2502,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
/* Initialize private members */ /* Initialize private members */
priv = netdev_priv(dev); priv = netdev_priv(dev);
priv->clk = devm_clk_get_optional(&pdev->dev, "sw_sysport");
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
/* Allocate number of TX rings */ /* Allocate number of TX rings */
priv->tx_rings = devm_kcalloc(&pdev->dev, txq, priv->tx_rings = devm_kcalloc(&pdev->dev, txq,
sizeof(struct bcm_sysport_tx_ring), sizeof(struct bcm_sysport_tx_ring),
@ -2564,6 +2583,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
if (!ret) if (!ret)
device_set_wakeup_capable(&pdev->dev, 1); device_set_wakeup_capable(&pdev->dev, 1);
priv->wol_clk = devm_clk_get_optional(&pdev->dev, "sw_sysportwol");
if (IS_ERR(priv->wol_clk))
return PTR_ERR(priv->wol_clk);
/* Set the needed headroom once and for all */ /* Set the needed headroom once and for all */
BUILD_BUG_ON(sizeof(struct bcm_tsb) != 8); BUILD_BUG_ON(sizeof(struct bcm_tsb) != 8);
dev->needed_headroom += sizeof(struct bcm_tsb); dev->needed_headroom += sizeof(struct bcm_tsb);
@ -2588,6 +2611,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
goto err_deregister_notifier; goto err_deregister_notifier;
} }
clk_prepare_enable(priv->clk);
priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK; priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK;
dev_info(&pdev->dev, dev_info(&pdev->dev,
"Broadcom SYSTEMPORT%s " REV_FMT "Broadcom SYSTEMPORT%s " REV_FMT
@ -2596,6 +2621,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
(priv->rev >> 8) & 0xff, priv->rev & 0xff, (priv->rev >> 8) & 0xff, priv->rev & 0xff,
priv->irq0, priv->irq1, txq, rxq); priv->irq0, priv->irq1, txq, rxq);
clk_disable_unprepare(priv->clk);
return 0; return 0;
err_deregister_notifier: err_deregister_notifier:
@ -2749,8 +2776,12 @@ static int __maybe_unused bcm_sysport_suspend(struct device *d)
bcm_sysport_fini_rx_ring(priv); bcm_sysport_fini_rx_ring(priv);
/* Get prepared for Wake-on-LAN */ /* Get prepared for Wake-on-LAN */
if (device_may_wakeup(d) && priv->wolopts) if (device_may_wakeup(d) && priv->wolopts) {
clk_prepare_enable(priv->wol_clk);
ret = bcm_sysport_suspend_to_wol(priv); ret = bcm_sysport_suspend_to_wol(priv);
}
clk_disable_unprepare(priv->clk);
return ret; return ret;
} }
@ -2765,6 +2796,10 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)
if (!netif_running(dev)) if (!netif_running(dev))
return 0; return 0;
clk_prepare_enable(priv->clk);
if (priv->wolopts)
clk_disable_unprepare(priv->wol_clk);
umac_reset(priv); umac_reset(priv);
/* Disable the UniMAC RX/TX */ /* Disable the UniMAC RX/TX */
@ -2844,6 +2879,7 @@ out_free_rx_ring:
out_free_tx_rings: out_free_tx_rings:
for (i = 0; i < dev->num_tx_queues; i++) for (i = 0; i < dev->num_tx_queues; i++)
bcm_sysport_fini_tx_ring(priv, i); bcm_sysport_fini_tx_ring(priv, i);
clk_disable_unprepare(priv->clk);
return ret; return ret;
} }

View File

@ -770,6 +770,8 @@ struct bcm_sysport_priv {
u32 wolopts; u32 wolopts;
u8 sopass[SOPASS_MAX]; u8 sopass[SOPASS_MAX];
unsigned int wol_irq_disabled:1; unsigned int wol_irq_disabled:1;
struct clk *clk;
struct clk *wol_clk;
/* MIB related fields */ /* MIB related fields */
struct bcm_sysport_mib mib; struct bcm_sysport_mib mib;