The MDIO driver has support to release the integrated PHYs from reset.
This was implemented for the SparX-5 for now. Now add support for the
LAN966x, too.
Michael Walle (3):
dt-bindings: net: mscc-miim: add lan966x compatible
net: mdio: mscc-miim: replace magic numbers for the bus reset
net: mdio: mscc-miim: add lan966x internal phy reset support
.../devicetree/bindings/net/mscc-miim.txt | 2 +-
drivers/net/mdio/mdio-mscc-miim.c | 59 +++++++++++++------
2 files changed, 42 insertions(+), 19 deletions(-)
--
2.30.2
The LAN966x has two internal PHYs which are in reset by default. The
driver already supported the internal PHYs of the SparX-5. Now add
support for the LAN966x, too. Add a new compatible to distinguish them.
The LAN966x has additional control bits in this register, thus convert
the regmap_write() to regmap_update_bits() to leave the remaining bits
untouched. This doesn't change anything for the SparX-5 SoC, because
there, the register consists only of reset bits.
Signed-off-by: Michael Walle <[email protected]>
---
drivers/net/mdio/mdio-mscc-miim.c | 59 +++++++++++++++++++++----------
1 file changed, 41 insertions(+), 18 deletions(-)
diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c
index 7773d5019e66..d082a13d9af3 100644
--- a/drivers/net/mdio/mdio-mscc-miim.c
+++ b/drivers/net/mdio/mdio-mscc-miim.c
@@ -15,6 +15,7 @@
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#define MSCC_MIIM_REG_STATUS 0x0
@@ -36,11 +37,19 @@
#define PHY_CFG_PHY_RESET (BIT(5) | BIT(6) | BIT(7) | BIT(8))
#define MSCC_PHY_REG_PHY_STATUS 0x4
+#define LAN966X_CUPHY_COMMON_CFG 0x0
+#define CUPHY_COMMON_CFG_RESET_N BIT(0)
+
+struct mscc_miim_info {
+ unsigned int phy_reset_offset;
+ unsigned int phy_reset_mask;
+};
+
struct mscc_miim_dev {
struct regmap *regs;
int mii_status_offset;
struct regmap *phy_regs;
- int phy_reset_offset;
+ const struct mscc_miim_info *info;
};
/* When high resolution timers aren't built-in: we can't use usleep_range() as
@@ -157,27 +166,29 @@ static int mscc_miim_write(struct mii_bus *bus, int mii_id,
static int mscc_miim_reset(struct mii_bus *bus)
{
struct mscc_miim_dev *miim = bus->priv;
- int offset = miim->phy_reset_offset;
- int mask = PHY_CFG_PHY_ENA | PHY_CFG_PHY_COMMON_RESET |
- PHY_CFG_PHY_RESET;
+ unsigned int offset, mask;
int ret;
- if (miim->phy_regs) {
- ret = regmap_write(miim->phy_regs, offset, 0);
- if (ret < 0) {
- WARN_ONCE(1, "mscc reset set error %d\n", ret);
- return ret;
- }
+ if (!miim->phy_regs || !miim->info)
+ return 0;
- ret = regmap_write(miim->phy_regs, offset, mask);
- if (ret < 0) {
- WARN_ONCE(1, "mscc reset clear error %d\n", ret);
- return ret;
- }
+ offset = miim->info->phy_reset_offset;
+ mask = miim->info->phy_reset_mask;
+
+ ret = regmap_update_bits(miim->phy_regs, offset, mask, 0);
+ if (ret < 0) {
+ WARN_ONCE(1, "mscc reset set error %d\n", ret);
+ return ret;
+ }
- mdelay(500);
+ ret = regmap_update_bits(miim->phy_regs, offset, mask, mask);
+ if (ret < 0) {
+ WARN_ONCE(1, "mscc reset clear error %d\n", ret);
+ return ret;
}
+ mdelay(500);
+
return 0;
}
@@ -272,7 +283,7 @@ static int mscc_miim_probe(struct platform_device *pdev)
miim = bus->priv;
miim->phy_regs = phy_regmap;
- miim->phy_reset_offset = MSCC_PHY_REG_PHY_CFG;
+ miim->info = device_get_match_data(&pdev->dev);
ret = of_mdiobus_register(bus, pdev->dev.of_node);
if (ret < 0) {
@@ -294,8 +305,20 @@ static int mscc_miim_remove(struct platform_device *pdev)
return 0;
}
+static const struct mscc_miim_info mscc_ocelot_miim_info = {
+ .phy_reset_offset = MSCC_PHY_REG_PHY_CFG,
+ .phy_reset_mask = PHY_CFG_PHY_ENA | PHY_CFG_PHY_COMMON_RESET |
+ PHY_CFG_PHY_RESET,
+};
+
+static const struct mscc_miim_info mscc_lan966x_miim_info = {
+ .phy_reset_offset = LAN966X_CUPHY_COMMON_CFG,
+ .phy_reset_mask = CUPHY_COMMON_CFG_RESET_N,
+};
+
static const struct of_device_id mscc_miim_match[] = {
- { .compatible = "mscc,ocelot-miim" },
+ { .compatible = "mscc,ocelot-miim", .data = &mscc_ocelot_miim_info },
+ { .compatible = "mscc,lan966x-miim", .data = &mscc_lan966x_miim_info },
{ }
};
MODULE_DEVICE_TABLE(of, mscc_miim_match);
--
2.30.2
> /* When high resolution timers aren't built-in: we can't use usleep_range() as
> @@ -157,27 +166,29 @@ static int mscc_miim_write(struct mii_bus *bus, int mii_id,
> static int mscc_miim_reset(struct mii_bus *bus)
> {
> struct mscc_miim_dev *miim = bus->priv;
> - int offset = miim->phy_reset_offset;
> - int mask = PHY_CFG_PHY_ENA | PHY_CFG_PHY_COMMON_RESET |
> - PHY_CFG_PHY_RESET;
> + unsigned int offset, mask;
> int ret;
>
> - if (miim->phy_regs) {
> - ret = regmap_write(miim->phy_regs, offset, 0);
> - if (ret < 0) {
> - WARN_ONCE(1, "mscc reset set error %d\n", ret);
> - return ret;
> - }
> + if (!miim->phy_regs || !miim->info)
> + return 0;
I would put the check for miim->info in the probe. Not checking the
return value from *_get_match_data() is one of the things the bots
reports and we receive patches for. You have the check, but it is
hidden away, and i doubt the bot nor the bot handlers are clever
enough to find it.
Andrew
Replace the magic numbers by macros which are already defined. It seems
the original commit missed to use them.
Signed-off-by: Michael Walle <[email protected]>
---
drivers/net/mdio/mdio-mscc-miim.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c
index 64fb76c1e395..7773d5019e66 100644
--- a/drivers/net/mdio/mdio-mscc-miim.c
+++ b/drivers/net/mdio/mdio-mscc-miim.c
@@ -158,18 +158,18 @@ static int mscc_miim_reset(struct mii_bus *bus)
{
struct mscc_miim_dev *miim = bus->priv;
int offset = miim->phy_reset_offset;
+ int mask = PHY_CFG_PHY_ENA | PHY_CFG_PHY_COMMON_RESET |
+ PHY_CFG_PHY_RESET;
int ret;
if (miim->phy_regs) {
- ret = regmap_write(miim->phy_regs,
- MSCC_PHY_REG_PHY_CFG + offset, 0);
+ ret = regmap_write(miim->phy_regs, offset, 0);
if (ret < 0) {
WARN_ONCE(1, "mscc reset set error %d\n", ret);
return ret;
}
- ret = regmap_write(miim->phy_regs,
- MSCC_PHY_REG_PHY_CFG + offset, 0x1ff);
+ ret = regmap_write(miim->phy_regs, offset, mask);
if (ret < 0) {
WARN_ONCE(1, "mscc reset clear error %d\n", ret);
return ret;
@@ -272,7 +272,7 @@ static int mscc_miim_probe(struct platform_device *pdev)
miim = bus->priv;
miim->phy_regs = phy_regmap;
- miim->phy_reset_offset = 0;
+ miim->phy_reset_offset = MSCC_PHY_REG_PHY_CFG;
ret = of_mdiobus_register(bus, pdev->dev.of_node);
if (ret < 0) {
--
2.30.2