Messages in this thread | | | From | Vladimir Oltean <> | Subject | Re: [PATCH v2 net-next 3/3] net: dsa: ocelot: felix: utilize shared mscc-miim driver for indirect MDIO access | Date | Fri, 26 Nov 2021 00:58:25 +0000 |
| |
On Thu, Nov 25, 2021 at 12:13:01PM -0800, Colin Foster wrote: > Switch to a shared MDIO access implementation by way of the mdio-mscc-miim > driver. > > Signed-off-by: Colin Foster <colin.foster@in-advantage.com> > ---
I'm sorry, I still wasn't able to boot the T1040RDB to test these, it looks like it's bricked or something. I'll try to do more debugging tomorrow.
> drivers/net/dsa/ocelot/Kconfig | 1 + > drivers/net/dsa/ocelot/seville_vsc9953.c | 103 +++-------------------- > drivers/net/mdio/mdio-mscc-miim.c | 40 ++++++--- > include/linux/mdio/mdio-mscc-miim.h | 20 +++++ > include/soc/mscc/ocelot.h | 1 + > 5 files changed, 61 insertions(+), 104 deletions(-) > create mode 100644 include/linux/mdio/mdio-mscc-miim.h > > diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig > index 9948544ba1c4..220b0b027b55 100644 > --- a/drivers/net/dsa/ocelot/Kconfig > +++ b/drivers/net/dsa/ocelot/Kconfig > @@ -21,6 +21,7 @@ config NET_DSA_MSCC_SEVILLE > depends on NET_VENDOR_MICROSEMI > depends on HAS_IOMEM > depends on PTP_1588_CLOCK_OPTIONAL > + select MDIO_MSCC_MIIM > select MSCC_OCELOT_SWITCH_LIB > select NET_DSA_TAG_OCELOT_8021Q > select NET_DSA_TAG_OCELOT > diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c > index db124922c374..41ec60a1fc96 100644 > --- a/drivers/net/dsa/ocelot/seville_vsc9953.c > +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c > @@ -6,19 +6,14 @@ > #include <soc/mscc/ocelot_vcap.h> > #include <soc/mscc/ocelot_sys.h> > #include <soc/mscc/ocelot.h> > +#include <linux/mdio/mdio-mscc-miim.h> > +#include <linux/of_mdio.h> > #include <linux/of_platform.h> > #include <linux/pcs-lynx.h> > #include <linux/dsa/ocelot.h> > #include <linux/iopoll.h> > -#include <linux/of_mdio.h> > #include "felix.h" > > -#define MSCC_MIIM_CMD_OPR_WRITE BIT(1) > -#define MSCC_MIIM_CMD_OPR_READ BIT(2) > -#define MSCC_MIIM_CMD_WRDATA_SHIFT 4 > -#define MSCC_MIIM_CMD_REGAD_SHIFT 20 > -#define MSCC_MIIM_CMD_PHYAD_SHIFT 25 > -#define MSCC_MIIM_CMD_VLD BIT(31) > #define VSC9953_VCAP_POLICER_BASE 11 > #define VSC9953_VCAP_POLICER_MAX 31 > #define VSC9953_VCAP_POLICER_BASE2 120 > @@ -862,7 +857,6 @@ static struct vcap_props vsc9953_vcap_props[] = { > #define VSC9953_INIT_TIMEOUT 50000 > #define VSC9953_GCB_RST_SLEEP 100 > #define VSC9953_SYS_RAMINIT_SLEEP 80 > -#define VCS9953_MII_TIMEOUT 10000 > > static int vsc9953_gcb_soft_rst_status(struct ocelot *ocelot) > { > @@ -882,82 +876,6 @@ static int vsc9953_sys_ram_init_status(struct ocelot *ocelot) > return val; > } > > -static int vsc9953_gcb_miim_pending_status(struct ocelot *ocelot) > -{ > - int val; > - > - ocelot_field_read(ocelot, GCB_MIIM_MII_STATUS_PENDING, &val); > - > - return val; > -} > - > -static int vsc9953_gcb_miim_busy_status(struct ocelot *ocelot) > -{ > - int val; > - > - ocelot_field_read(ocelot, GCB_MIIM_MII_STATUS_BUSY, &val); > - > - return val; > -} > - > -static int vsc9953_mdio_write(struct mii_bus *bus, int phy_id, int regnum, > - u16 value) > -{ > - struct ocelot *ocelot = bus->priv; > - int err, cmd, val; > - > - /* Wait while MIIM controller becomes idle */ > - err = readx_poll_timeout(vsc9953_gcb_miim_pending_status, ocelot, > - val, !val, 10, VCS9953_MII_TIMEOUT); > - if (err) { > - dev_err(ocelot->dev, "MDIO write: pending timeout\n"); > - goto out; > - } > - > - cmd = MSCC_MIIM_CMD_VLD | (phy_id << MSCC_MIIM_CMD_PHYAD_SHIFT) | > - (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | > - (value << MSCC_MIIM_CMD_WRDATA_SHIFT) | > - MSCC_MIIM_CMD_OPR_WRITE; > - > - ocelot_write(ocelot, cmd, GCB_MIIM_MII_CMD); > - > -out: > - return err; > -} > - > -static int vsc9953_mdio_read(struct mii_bus *bus, int phy_id, int regnum) > -{ > - struct ocelot *ocelot = bus->priv; > - int err, cmd, val; > - > - /* Wait until MIIM controller becomes idle */ > - err = readx_poll_timeout(vsc9953_gcb_miim_pending_status, ocelot, > - val, !val, 10, VCS9953_MII_TIMEOUT); > - if (err) { > - dev_err(ocelot->dev, "MDIO read: pending timeout\n"); > - goto out; > - } > - > - /* Write the MIIM COMMAND register */ > - cmd = MSCC_MIIM_CMD_VLD | (phy_id << MSCC_MIIM_CMD_PHYAD_SHIFT) | > - (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | MSCC_MIIM_CMD_OPR_READ; > - > - ocelot_write(ocelot, cmd, GCB_MIIM_MII_CMD); > - > - /* Wait while read operation via the MIIM controller is in progress */ > - err = readx_poll_timeout(vsc9953_gcb_miim_busy_status, ocelot, > - val, !val, 10, VCS9953_MII_TIMEOUT); > - if (err) { > - dev_err(ocelot->dev, "MDIO read: busy timeout\n"); > - goto out; > - } > - > - val = ocelot_read(ocelot, GCB_MIIM_MII_DATA); > - > - err = val & 0xFFFF; > -out: > - return err; > -} > > /* CORE_ENA is in SYS:SYSTEM:RESET_CFG > * MEM_INIT is in SYS:SYSTEM:RESET_CFG > @@ -1101,16 +1019,15 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) > return -ENOMEM; > } > > - bus = devm_mdiobus_alloc(dev); > - if (!bus) > - return -ENOMEM; > + rc = mscc_miim_setup(dev, &bus, "VSC9953 internal MDIO bus", > + ocelot->targets[GCB], > + ocelot->map[GCB][GCB_MIIM_MII_STATUS & REG_MASK], > + NULL, 0); > > - bus->name = "VSC9953 internal MDIO bus"; > - bus->read = vsc9953_mdio_read; > - bus->write = vsc9953_mdio_write; > - bus->parent = dev; > - bus->priv = ocelot; > - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev)); > + if (rc) { > + dev_err(dev, "failed to setup MDIO bus\n"); > + return rc; > + } > > /* Needed in order to initialize the bus mutex lock */ > rc = of_mdiobus_register(bus, NULL); > diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c > index 5a9c0b311bdb..9eed6b597f21 100644 > --- a/drivers/net/mdio/mdio-mscc-miim.c > +++ b/drivers/net/mdio/mdio-mscc-miim.c > @@ -10,6 +10,7 @@ > #include <linux/io.h> > #include <linux/iopoll.h> > #include <linux/kernel.h> > +#include <linux/mdio/mdio-mscc-miim.h> > #include <linux/module.h> > #include <linux/of_mdio.h> > #include <linux/phy.h> > @@ -37,7 +38,9 @@ > > struct mscc_miim_dev { > struct regmap *regs; > + int mii_status_offset; > struct regmap *phy_regs; > + int phy_reset_offset; > }; > > /* When high resolution timers aren't built-in: we can't use usleep_range() as > @@ -56,7 +59,8 @@ static int mscc_miim_status(struct mii_bus *bus) > struct mscc_miim_dev *miim = bus->priv; > int val, ret; > > - ret = regmap_read(miim->regs, MSCC_MIIM_REG_STATUS, &val); > + ret = regmap_read(miim->regs, > + MSCC_MIIM_REG_STATUS + miim->mii_status_offset, &val); > if (ret < 0) { > WARN_ONCE(1, "mscc miim status read error %d\n", ret); > return ret; > @@ -93,7 +97,9 @@ static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum) > if (ret) > goto out; > > - ret = regmap_write(miim->regs, MSCC_MIIM_REG_CMD, MSCC_MIIM_CMD_VLD | > + ret = regmap_write(miim->regs, > + MSCC_MIIM_REG_CMD + miim->mii_status_offset, > + MSCC_MIIM_CMD_VLD | > (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) | > (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | > MSCC_MIIM_CMD_OPR_READ); > @@ -107,8 +113,8 @@ static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum) > if (ret) > goto out; > > - ret = regmap_read(miim->regs, MSCC_MIIM_REG_DATA, &val); > - > + ret = regmap_read(miim->regs, > + MSCC_MIIM_REG_DATA + miim->mii_status_offset, &val);
I'd be tempted to create one separate regmap for DEVCPU_MIIM which starts precisely at 0x8700AC, and therefore does not need adjustment with an offset here. What do you think?
> if (ret < 0) { > WARN_ONCE(1, "mscc miim read data reg error %d\n", ret); > goto out; > @@ -134,7 +140,9 @@ static int mscc_miim_write(struct mii_bus *bus, int mii_id, > if (ret < 0) > goto out; > > - ret = regmap_write(miim->regs, MSCC_MIIM_REG_CMD, MSCC_MIIM_CMD_VLD | > + ret = regmap_write(miim->regs, > + MSCC_MIIM_REG_CMD + miim->mii_status_offset, > + MSCC_MIIM_CMD_VLD | > (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) | > (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | > (value << MSCC_MIIM_CMD_WRDATA_SHIFT) | > @@ -149,16 +157,19 @@ 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 ret; > > if (miim->phy_regs) { > - ret = regmap_write(miim->phy_regs, MSCC_PHY_REG_PHY_CFG, 0); > + ret = regmap_write(miim->phy_regs, > + MSCC_PHY_REG_PHY_CFG + 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, 0x1ff); > + ret = regmap_write(miim->phy_regs, > + MSCC_PHY_REG_PHY_CFG + offset, 0x1ff); > if (ret < 0) { > WARN_ONCE(1, "mscc reset clear error %d\n", ret); > return ret; > @@ -176,8 +187,9 @@ static const struct regmap_config mscc_miim_regmap_config = { > .reg_stride = 4, > }; > > -static int mscc_miim_setup(struct device *dev, struct mii_bus **pbus, > - struct regmap *mii_regmap, struct regmap *phy_regmap) > +int mscc_miim_setup(struct device *dev, struct mii_bus **pbus, const char *name, > + struct regmap *mii_regmap, int status_offset, > + struct regmap *phy_regmap, int reset_offset) > { > struct mscc_miim_dev *miim; > struct mii_bus *bus; > @@ -186,7 +198,7 @@ static int mscc_miim_setup(struct device *dev, struct mii_bus **pbus, > if (!bus) > return -ENOMEM; > > - bus->name = "mscc_miim"; > + bus->name = name; > bus->read = mscc_miim_read; > bus->write = mscc_miim_write; > bus->reset = mscc_miim_reset; > @@ -198,10 +210,15 @@ static int mscc_miim_setup(struct device *dev, struct mii_bus **pbus, > *pbus = bus; > > miim->regs = mii_regmap; > + miim->mii_status_offset = status_offset; > miim->phy_regs = phy_regmap; > + miim->phy_reset_offset = reset_offset;
The reset_offset is unused. Will vsc7514_spi need it?
> + > + *pbus = bus; > > return 0; > } > +EXPORT_SYMBOL(mscc_miim_setup); > > static int mscc_miim_probe(struct platform_device *pdev) > { > @@ -238,7 +255,8 @@ static int mscc_miim_probe(struct platform_device *pdev) > return PTR_ERR(dev->phy_regs); > } > > - ret = mscc_miim_setup(&pdev->dev, &bus, mii_regmap, phy_regmap); > + ret = mscc_miim_setup(&pdev->dev, &bus, "mscc_miim", mii_regmap, 0, > + phy_regmap, 0); > if (ret < 0) { > dev_err(&pdev->dev, "Unable to setup the MDIO bus\n"); > return ret; > diff --git a/include/linux/mdio/mdio-mscc-miim.h b/include/linux/mdio/mdio-mscc-miim.h > new file mode 100644 > index 000000000000..69a023cf8991 > --- /dev/null > +++ b/include/linux/mdio/mdio-mscc-miim.h > @@ -0,0 +1,20 @@ > +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ > +/* > + * Driver for the MDIO interface of Microsemi network switches. > + * > + * Author: Colin Foster <colin.foster@in-advantage.com> > + * Copyright (C) 2021 Innovative Advantage > + */ > +#ifndef MDIO_MSCC_MIIM_H > +#define MDIO_MSCC_MIIM_H > + > +#include <linux/device.h> > +#include <linux/phy.h> > +#include <linux/regmap.h> > + > +int mscc_miim_setup(struct device *device, struct mii_bus **bus, > + const char *name, struct regmap *mii_regmap, > + int status_offset, struct regmap *phy_regmap, > + int reset_offset); > + > +#endif > diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h > index 89d17629efe5..9d6fe8ce9dd1 100644 > --- a/include/soc/mscc/ocelot.h > +++ b/include/soc/mscc/ocelot.h > @@ -398,6 +398,7 @@ enum ocelot_reg { > GCB_MIIM_MII_STATUS, > GCB_MIIM_MII_CMD, > GCB_MIIM_MII_DATA, > + GCB_PHY_PHY_CFG,
This appears extraneous, you are still using MSCC_PHY_REG_PHY_CFG.
> DEV_CLOCK_CFG = DEV_GMII << TARGET_OFFSET, > DEV_PORT_MISC, > DEV_EVENTS, > -- > 2.25.1 >
| |