diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2021-06-18 14:52:54 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-06-18 12:26:17 -0700 |
commit | cb5a82d2b9aaca66ed74c424c9d79f0a5bfdbac4 (patch) | |
tree | d19cba85e6665fabb4c7ee8d51c0c11c5082388b /drivers/net/dsa/sja1105/sja1105_main.c | |
parent | qlcnic: remove redundant continue statement (diff) | |
download | linux-dev-cb5a82d2b9aaca66ed74c424c9d79f0a5bfdbac4.tar.xz linux-dev-cb5a82d2b9aaca66ed74c424c9d79f0a5bfdbac4.zip |
net: dsa: sja1105: properly power down the microcontroller clock for SJA1110
It turns out that powering down the BASE_TIMER_CLK does not turn off the
microcontroller, just its timers, including the one for the watchdog.
So the embedded microcontroller is still running, and potentially still
doing things.
To prevent unwanted interference, we should power down the BASE_MCSS_CLK
as well (MCSS = microcontroller subsystem).
The trouble is that currently we turn off the BASE_TIMER_CLK for SJA1110
from the .clocking_setup() method, mostly because this is a Clock
Generation Unit (CGU) setting which was traditionally configured in that
method for SJA1105. But in SJA1105, the CGU was used for bringing up the
port clocks at the proper speeds, and in SJA1110 it's not (but rather
for initial configuration), so it's best that we rebrand the
sja1110_clocking_setup() method into what it really is - an implementation
of the .disable_microcontroller() method.
Since disabling the microcontroller only needs to be done once, at probe
time, we can choose the best place to do that as being in sja1105_setup(),
before we upload the static config to the device. This guarantees that
the static config being used by the switch afterwards is really ours.
Note that the procedure to upload a static config necessarily resets the
switch. This already did not reset the microcontroller, only the switch
core, so since the .disable_microcontroller() method is guaranteed to be
called by that point, if it's disabled, it remains disabled. Add a
comment to make that clear.
With the code movement for SJA1110 from .clocking_setup() to
.disable_microcontroller(), both methods are optional and are guarded by
"if" conditions.
Tested by enabling in the device tree the rev-mii switch port 0 that
goes towards the microcontroller, and flashing a firmware that would
have networking. Without this patch, the microcontroller can be pinged,
with this patch it cannot.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/sja1105/sja1105_main.c')
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_main.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 8e5cdf93c23b..57ccd4548911 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1922,9 +1922,11 @@ out_unlock_ptp: * For these interfaces there is no dynamic configuration * needed, since PLLs have same settings at all speeds. */ - rc = priv->info->clocking_setup(priv); - if (rc < 0) - goto out; + if (priv->info->clocking_setup) { + rc = priv->info->clocking_setup(priv); + if (rc < 0) + goto out; + } for (i = 0; i < ds->num_ports; i++) { struct dw_xpcs *xpcs = priv->xpcs[i]; @@ -3032,18 +3034,34 @@ static int sja1105_setup(struct dsa_switch *ds) goto out_ptp_clock_unregister; } + if (priv->info->disable_microcontroller) { + rc = priv->info->disable_microcontroller(priv); + if (rc < 0) { + dev_err(ds->dev, + "Failed to disable microcontroller: %pe\n", + ERR_PTR(rc)); + goto out_mdiobus_unregister; + } + } + /* Create and send configuration down to device */ rc = sja1105_static_config_load(priv); if (rc < 0) { dev_err(ds->dev, "Failed to load static config: %d\n", rc); goto out_mdiobus_unregister; } + /* Configure the CGU (PHY link modes and speeds) */ - rc = priv->info->clocking_setup(priv); - if (rc < 0) { - dev_err(ds->dev, "Failed to configure MII clocking: %d\n", rc); - goto out_static_config_free; + if (priv->info->clocking_setup) { + rc = priv->info->clocking_setup(priv); + if (rc < 0) { + dev_err(ds->dev, + "Failed to configure MII clocking: %pe\n", + ERR_PTR(rc)); + goto out_static_config_free; + } } + /* On SJA1105, VLAN filtering per se is always enabled in hardware. * The only thing we can do to disable it is lie about what the 802.1Q * EtherType is. |