Message ID | 20191218162919.5293-1-m.grzeschik@pengutronix.de |
---|---|
State | Changes Requested |
Delegated to: | David Miller |
Headers | show |
Series | mdio-bitbang: add support for lowlevel mdio read/write | expand |
On Wed, Dec 18, 2019 at 05:29:19PM +0100, Michael Grzeschik wrote: > Some phys support special opcode handling when communicating via mdio. > This patch introduces mdio_ll_read/write which makes it possible to set > the opcode. It implements these functions in the gpio-bitbang driver, > which is capable of setting the opcode on read and write. > > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Hi Michael It is normal to post the user of a new API at the same time as a new API. I'm having trouble working out how this is supposed to be used. Andrew
On Thu, Dec 19, 2019 at 09:39:31PM +0100, Andrew Lunn wrote: > On Wed, Dec 18, 2019 at 05:29:19PM +0100, Michael Grzeschik wrote: > > Some phys support special opcode handling when communicating via mdio. > > This patch introduces mdio_ll_read/write which makes it possible to set > > the opcode. It implements these functions in the gpio-bitbang driver, > > which is capable of setting the opcode on read and write. > > > > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> > > Hi Michael > > It is normal to post the user of a new API at the same time as a new > API. I'm having trouble working out how this is supposed to be used. Hi Andrew, so this patch should have been in the series with the ksz8863 driver, which is using the API. I will send the series again as v3 including this patch, so it will be clear how this is ment. Thanks, Michael
On 12/18/19 8:29 AM, Michael Grzeschik wrote: > Some phys support special opcode handling when communicating via mdio. > This patch introduces mdio_ll_read/write which makes it possible to set > the opcode. It implements these functions in the gpio-bitbang driver, > which is capable of setting the opcode on read and write. > > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> > --- > Hi Andrew, > > I worked on your suggestion moving the proprietary call to > mdio-ksz88x3.c which does not seem to work out very well. > I still end up having an MII_ADDR_SMI???? define in linux/phy.h. > > Instead of having to support this special case in one extra file > what do you think of adding mdiobus_lowlevel_write/read to mdio_bus. > This way it would be possible to add the opcode directly as user. > > Other controllers which have the possibility to set the op code in hardware > will also profit from that and can implement these functions. I am not sure it makes sense for the entire struct mii_bus to gain two new pointers, when you could just exported the mdiobb_ll_read() and mdiobb_ll_write() to the kernel modules that needs those, and wrap them however you need them to implement the mdiobus->read() and mdiobus->write() operations?
Hi Michael In your V1 patch, you had this diagram. +/* Serial Management Interface (SMI) uses the following frame format: + * + * preamble|start|Read/Write| PHY | REG |TA| Data bits | Idle + * |frame| OP code |address |address| | | + * read | 32x1´s | 01 | 00 | 1xRRR | RRRRR |Z0| 00000000DDDDDDDD | Z + * write| 32x1´s | 01 | 00 | 0xRRR | RRRRR |10| xxxxxxxxDDDDDDDD | Z + * + */ I just compared this to plain MDIO: + * preamble|start|Read/Write| PHY | REG |TA| Data bits | Idle + * |frame| OP code |address |address| | | + * read | 32x1´s | 01 | 10 | AAAA | RRRRR |Z0| DDDDDDDDDDDDDDDD | Z + * write| 32x1´s | 01 | 01 | AAAA | RRRRR |10| DDDDDDDDDDDDDDDD | Z So the only real issue here is the OP code? The rest you can do with a layer on top of the standard API. How about something like this. Totally untested, probably does not even compile..... Andrew From 6051479b218fd19942d702e3e051c6355fe2a11f Mon Sep 17 00:00:00 2001 From: Andrew Lunn <andrew@lunn.ch> Date: Sat, 21 Dec 2019 10:31:19 -0600 Subject: [PATCH] net: phy: Add support for microchip SMI0 MDIO bus. SMI0 is a mangled version of MDIO. The main low level difference is the MDIO C22 OP code is always 0, not 0x2 or 0x1 for Read/Write. The read/write information is instead encoded in the PHY address. Extend the bit-bang code to allow the op code to be overridden, but default to normal C22 values. Add an extra compatible to the mdio-gpio driver, and when this compatible is present, set the op codes to 0. A higher level driver, sitting on top of the basic MDIO bus driver can then implement the rest of the microchip SMI0 odderties. Signed-off-by: Andrew Lunn <andrew@lunn.ch> --- drivers/net/phy/mdio-bitbang.c | 7 +++++-- drivers/net/phy/mdio-gpio.c | 7 +++++++ include/linux/mdio-bitbang.h | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index 5136275c8e73..01f620889c78 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c @@ -158,7 +158,7 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg) reg = mdiobb_cmd_addr(ctrl, phy, reg); mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); } else - mdiobb_cmd(ctrl, MDIO_READ, phy, reg); + mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg); ctrl->ops->set_mdio_dir(ctrl, 0); @@ -189,7 +189,7 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) reg = mdiobb_cmd_addr(ctrl, phy, reg); mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); } else - mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg); + mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg); /* send the turnaround (10) */ mdiobb_send_bit(ctrl, 1); @@ -216,6 +216,9 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl) bus->write = mdiobb_write; bus->priv = ctrl; + ctrl->op_c22_read = MDIO_READ; + ctrl->op_c22_write = MDIO_WRITE; + return bus; } EXPORT_SYMBOL(alloc_mdio_bitbang); diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 1b00235d7dc5..282bc38331d7 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -132,6 +132,12 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, new_bus->phy_ignore_ta_mask = pdata->phy_ignore_ta_mask; } + if (dev->of_node && + of_device_is_compatible(dev->of_node, "microchip,mdio-smi0")) { + bitbang->ctrl->op_c22_read = 0; + bitbang->ctrl->op_c22_write = 0; + } + dev_set_drvdata(dev, new_bus); return new_bus; @@ -196,6 +202,7 @@ static int mdio_gpio_remove(struct platform_device *pdev) static const struct of_device_id mdio_gpio_of_match[] = { { .compatible = "virtual,mdio-gpio", }, + { .compatible = "microchip,mdio-smi0" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mdio_gpio_of_match); diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h index 5d71e8a8500f..8ae0b3835233 100644 --- a/include/linux/mdio-bitbang.h +++ b/include/linux/mdio-bitbang.h @@ -33,6 +33,8 @@ struct mdiobb_ops { struct mdiobb_ctrl { const struct mdiobb_ops *ops; + u8 op_c22_read; + u8 op_c22_write; }; /* The returned bus is not yet registered with the phy layer. */
Hi Andrew! I tested your patch. But it works only partially. For the case that the upper driver is directly communicating in SMI mode with the phy, this works fine. But the regular MDIO connection does not work anymore afterwards. The normals MDIO communication still needs to work, as mdio-gpio is calling of_mdiobus_register that on the other end calls get_phy_device and tries to communicate via regular MDIO to the device. Fixing the whole bus to the SMI opcode breaks the regular commands. Do you have any ideas how to fix that? Regards, Michael On Sat, Dec 21, 2019 at 05:41:10PM +0100, Andrew Lunn wrote: > Hi Michael > > In your V1 patch, you had this diagram. > > +/* Serial Management Interface (SMI) uses the following frame format: > + * > + * preamble|start|Read/Write| PHY | REG |TA| Data bits | Idle > + * |frame| OP code |address |address| | | > + * read | 32x1´s | 01 | 00 | 1xRRR | RRRRR |Z0| 00000000DDDDDDDD | Z > + * write| 32x1´s | 01 | 00 | 0xRRR | RRRRR |10| xxxxxxxxDDDDDDDD | Z > + * > + */ > > I just compared this to plain MDIO: > > + * preamble|start|Read/Write| PHY | REG |TA| Data bits | Idle > + * |frame| OP code |address |address| | | > + * read | 32x1´s | 01 | 10 | AAAA | RRRRR |Z0| DDDDDDDDDDDDDDDD | Z > + * write| 32x1´s | 01 | 01 | AAAA | RRRRR |10| DDDDDDDDDDDDDDDD | Z > > So the only real issue here is the OP code? The rest you can do with a > layer on top of the standard API. > > How about something like this. Totally untested, probably does not > even compile..... > > Andrew > > From 6051479b218fd19942d702e3e051c6355fe2a11f Mon Sep 17 00:00:00 2001 > From: Andrew Lunn <andrew@lunn.ch> > Date: Sat, 21 Dec 2019 10:31:19 -0600 > Subject: [PATCH] net: phy: Add support for microchip SMI0 MDIO bus. > > SMI0 is a mangled version of MDIO. The main low level difference is > the MDIO C22 OP code is always 0, not 0x2 or 0x1 for Read/Write. The > read/write information is instead encoded in the PHY address. > > Extend the bit-bang code to allow the op code to be overridden, but > default to normal C22 values. Add an extra compatible to the mdio-gpio > driver, and when this compatible is present, set the op codes to 0. > > A higher level driver, sitting on top of the basic MDIO bus driver can > then implement the rest of the microchip SMI0 odderties. > > Signed-off-by: Andrew Lunn <andrew@lunn.ch> > --- > drivers/net/phy/mdio-bitbang.c | 7 +++++-- > drivers/net/phy/mdio-gpio.c | 7 +++++++ > include/linux/mdio-bitbang.h | 2 ++ > 3 files changed, 14 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c > index 5136275c8e73..01f620889c78 100644 > --- a/drivers/net/phy/mdio-bitbang.c > +++ b/drivers/net/phy/mdio-bitbang.c > @@ -158,7 +158,7 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg) > reg = mdiobb_cmd_addr(ctrl, phy, reg); > mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); > } else > - mdiobb_cmd(ctrl, MDIO_READ, phy, reg); > + mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg); > > ctrl->ops->set_mdio_dir(ctrl, 0); > > @@ -189,7 +189,7 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) > reg = mdiobb_cmd_addr(ctrl, phy, reg); > mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); > } else > - mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg); > + mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg); > > /* send the turnaround (10) */ > mdiobb_send_bit(ctrl, 1); > @@ -216,6 +216,9 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl) > bus->write = mdiobb_write; > bus->priv = ctrl; > > + ctrl->op_c22_read = MDIO_READ; > + ctrl->op_c22_write = MDIO_WRITE; > + > return bus; > } > EXPORT_SYMBOL(alloc_mdio_bitbang); > diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c > index 1b00235d7dc5..282bc38331d7 100644 > --- a/drivers/net/phy/mdio-gpio.c > +++ b/drivers/net/phy/mdio-gpio.c > @@ -132,6 +132,12 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, > new_bus->phy_ignore_ta_mask = pdata->phy_ignore_ta_mask; > } > > + if (dev->of_node && > + of_device_is_compatible(dev->of_node, "microchip,mdio-smi0")) { > + bitbang->ctrl->op_c22_read = 0; > + bitbang->ctrl->op_c22_write = 0; > + } > + > dev_set_drvdata(dev, new_bus); > > return new_bus; > @@ -196,6 +202,7 @@ static int mdio_gpio_remove(struct platform_device *pdev) > > static const struct of_device_id mdio_gpio_of_match[] = { > { .compatible = "virtual,mdio-gpio", }, > + { .compatible = "microchip,mdio-smi0" }, > { /* sentinel */ } > }; > MODULE_DEVICE_TABLE(of, mdio_gpio_of_match); > diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h > index 5d71e8a8500f..8ae0b3835233 100644 > --- a/include/linux/mdio-bitbang.h > +++ b/include/linux/mdio-bitbang.h > @@ -33,6 +33,8 @@ struct mdiobb_ops { > > struct mdiobb_ctrl { > const struct mdiobb_ops *ops; > + u8 op_c22_read; > + u8 op_c22_write; > }; > > /* The returned bus is not yet registered with the phy layer. */ > -- > 2.24.0 > >
On Wed, Jan 29, 2020 at 04:42:01PM +0100, Michael Grzeschik wrote: > Hi Andrew! > > I tested your patch. But it works only partially. For the case that > the upper driver is directly communicating in SMI mode with the phy, > this works fine. But the regular MDIO connection does not work anymore > afterwards. > > The normals MDIO communication still needs to work, as mdio-gpio is > calling of_mdiobus_register that on the other end calls get_phy_device > and tries to communicate via regular MDIO to the device. Do you mean you have a mix of devices on the bus, some standards comformant, and others using this hacked up SMI0 mode? You need to specify per device if SMI0 should be used? Andrew
On Wed, Jan 29, 2020 at 04:53:46PM +0100, Andrew Lunn wrote: > On Wed, Jan 29, 2020 at 04:42:01PM +0100, Michael Grzeschik wrote: > > Hi Andrew! > > > > I tested your patch. But it works only partially. For the case that > > the upper driver is directly communicating in SMI mode with the phy, > > this works fine. But the regular MDIO connection does not work anymore > > afterwards. > > > > The normals MDIO communication still needs to work, as mdio-gpio is > > calling of_mdiobus_register that on the other end calls get_phy_device > > and tries to communicate via regular MDIO to the device. > > Do you mean you have a mix of devices on the bus, some standards > comformant, and others using this hacked up SMI0 mode? Actually it is the same device used in both modes. The SMI0 mode is used by the switch driver to address the extended switch functions. But on the same bus we have the fec connected to the cpu bound fixed-phy (microchip,ks8863) via MDIO. > You need to specify per device if SMI0 should be used? Yes, we have to use the same bus fot both modes SMI0 and MDIO. Michael
Hi Andrew, I want to refresh this thread. On Wed, Jan 29, 2020 at 10:48:05PM +0100, Michael Grzeschik wrote: >On Wed, Jan 29, 2020 at 04:53:46PM +0100, Andrew Lunn wrote: >> On Wed, Jan 29, 2020 at 04:42:01PM +0100, Michael Grzeschik wrote: >> > Hi Andrew! >> > >> > I tested your patch. But it works only partially. For the case that >> > the upper driver is directly communicating in SMI mode with the phy, >> > this works fine. But the regular MDIO connection does not work anymore >> > afterwards. >> > >> > The normals MDIO communication still needs to work, as mdio-gpio is >> > calling of_mdiobus_register that on the other end calls get_phy_device >> > and tries to communicate via regular MDIO to the device. >> >> Do you mean you have a mix of devices on the bus, some standards >> comformant, and others using this hacked up SMI0 mode? > >Actually it is the same device used in both modes. The SMI0 >mode is used by the switch driver to address the extended switch >functions. But on the same bus we have the fec connected to >the cpu bound fixed-phy (microchip,ks8863) via MDIO. > >> You need to specify per device if SMI0 should be used? > >Yes, we have to use the same bus fot both modes SMI0 and MDIO. In fact I for now used the cpu bound port with phy-handle to the fec. This way it still used mdio for the initial probe. But it should also work to use fixed-phy for it don't run into mdio communication on the same bus. This way your patch should work. In case you did not think of anything else, I will send the series including your patch after I tested it with master. Regards, Michael
diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index 5136275c8e739..77fbc7eaadf51 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c @@ -149,16 +149,12 @@ static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr) return dev_addr; } -static int mdiobb_read(struct mii_bus *bus, int phy, int reg) +static int mdiobb_ll_read(struct mii_bus *bus, int op, int phy, int reg) { struct mdiobb_ctrl *ctrl = bus->priv; int ret, i; - if (reg & MII_ADDR_C45) { - reg = mdiobb_cmd_addr(ctrl, phy, reg); - mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); - } else - mdiobb_cmd(ctrl, MDIO_READ, phy, reg); + mdiobb_cmd(ctrl, op, phy, reg); ctrl->ops->set_mdio_dir(ctrl, 0); @@ -181,15 +177,25 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg) return ret; } -static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) +static int mdiobb_read(struct mii_bus *bus, int phy, int reg) { struct mdiobb_ctrl *ctrl = bus->priv; + int op = MDIO_READ; if (reg & MII_ADDR_C45) { reg = mdiobb_cmd_addr(ctrl, phy, reg); - mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); - } else - mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg); + op = MDIO_C45_READ; + } + + return mdiobb_ll_read(bus, op, phy, reg); +} + +static int mdiobb_ll_write(struct mii_bus *bus, int op, int phy, + int reg, u16 val) +{ + struct mdiobb_ctrl *ctrl = bus->priv; + + mdiobb_cmd(ctrl, op, phy, reg); /* send the turnaround (10) */ mdiobb_send_bit(ctrl, 1); @@ -202,6 +208,19 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) return 0; } +static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) +{ + struct mdiobb_ctrl *ctrl = bus->priv; + int op = MDIO_WRITE; + + if (reg & MII_ADDR_C45) { + reg = mdiobb_cmd_addr(ctrl, phy, reg); + op = MDIO_C45_WRITE; + } + + return mdiobb_ll_write(bus, op, phy, reg, val); +} + struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl) { struct mii_bus *bus; @@ -213,7 +232,9 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl) __module_get(ctrl->ops->owner); bus->read = mdiobb_read; + bus->ll_read = mdiobb_ll_read; bus->write = mdiobb_write; + bus->ll_write = mdiobb_ll_write; bus->priv = ctrl; return bus; diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 229e480179ff1..57f4b7b9ce39a 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -560,6 +560,34 @@ int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) } EXPORT_SYMBOL(__mdiobus_read); +/** + * __mdiobus_ll_read - Unlocked version of the mdiobus_read function + * @bus: the mii_bus struct + * @op: opcode to use on transfer + * @addr: the phy address + * @regnum: register number to read + * + * Read a MDIO bus register. Caller must hold the mdio bus lock. + * + * NOTE: MUST NOT be called from interrupt context. + */ +int __mdiobus_ll_read(struct mii_bus *bus, int op, int addr, u32 regnum) +{ + int retval; + + if (!bus->ll_write) + return -ENODEV; + + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); + + retval = bus->ll_read(bus, op, addr, regnum); + + trace_mdio_access(bus, 1, addr, regnum, retval, retval); + + return retval; +} +EXPORT_SYMBOL(__mdiobus_ll_read); + /** * __mdiobus_write - Unlocked version of the mdiobus_write function * @bus: the mii_bus struct @@ -585,6 +613,36 @@ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) } EXPORT_SYMBOL(__mdiobus_write); +/** + * __mdiobus_ll_write - Unlocked version of the mdiobus_write function + * @bus: the mii_bus struct + * @op: opcode to use on transfer + * @addr: the phy address + * @regnum: register number to write + * @val: value to write to @regnum + * + * Write a MDIO bus register. Caller must hold the mdio bus lock. + * + * NOTE: MUST NOT be called from interrupt context. + */ +int __mdiobus_ll_write(struct mii_bus *bus, int op, int addr, + u32 regnum, u16 val) +{ + int err; + + if (!bus->ll_write) + return -ENODEV; + + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); + + err = bus->ll_write(bus, op, addr, regnum, val); + + trace_mdio_access(bus, 0, addr, regnum, val, err); + + return err; +} +EXPORT_SYMBOL(__mdiobus_ll_write); + /** * mdiobus_read_nested - Nested version of the mdiobus_read function * @bus: the mii_bus struct @@ -636,6 +694,31 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) } EXPORT_SYMBOL(mdiobus_read); +/** + * mdiobus_ll_read - Convenience function for reading a given MII mgmt register + * @bus: the mii_bus struct + * @op: opcode to use on transfer + * @addr: the phy address + * @regnum: register number to read + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int mdiobus_ll_read(struct mii_bus *bus, int op, int addr, u32 regnum) +{ + int retval; + + BUG_ON(in_interrupt()); + + mutex_lock(&bus->mdio_lock); + retval = __mdiobus_ll_read(bus, op, addr, regnum); + mutex_unlock(&bus->mdio_lock); + + return retval; +} +EXPORT_SYMBOL(mdiobus_ll_read); + /** * mdiobus_write_nested - Nested version of the mdiobus_write function * @bus: the mii_bus struct @@ -689,6 +772,33 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) } EXPORT_SYMBOL(mdiobus_write); +/** + * mdiobus_ll_write - Convenience function for writing a given MII mgmt register + * @bus: the mii_bus struct + * @op: opcode to use on transfer + * @addr: the phy address + * @regnum: register number to write + * @val: value to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int mdiobus_ll_write(struct mii_bus *bus, int op, int addr, + u32 regnum, u16 val) +{ + int err; + + BUG_ON(in_interrupt()); + + mutex_lock(&bus->mdio_lock); + err = __mdiobus_ll_write(bus, op, addr, regnum, val); + mutex_unlock(&bus->mdio_lock); + + return err; +} +EXPORT_SYMBOL(mdiobus_ll_write); + /** * mdio_bus_match - determine if given MDIO driver supports the given * MDIO device diff --git a/include/linux/mdio.h b/include/linux/mdio.h index a7604248777b7..aafd24eb6d393 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -315,11 +315,17 @@ static inline void mii_10gbt_stat_mod_linkmode_lpa_t(unsigned long *advertising, } int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); +int __mdiobus_ll_read(struct mii_bus *bus, int op, int addr, u32 regnum); int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); +int __mdiobus_ll_write(struct mii_bus *bus, int op, int addr, + u32 regnum, u16 val); int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); +int mdiobus_ll_read(struct mii_bus *bus, int op, int addr, u32 regnum); int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum); int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); +int mdiobus_ll_write(struct mii_bus *bus, int op, int addr, + u32 regnum, u16 val); int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val); int mdiobus_register_device(struct mdio_device *mdiodev); diff --git a/include/linux/phy.h b/include/linux/phy.h index 5032d453ac66a..3bb802cb03a8a 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -218,6 +218,9 @@ struct mii_bus { void *priv; int (*read)(struct mii_bus *bus, int addr, int regnum); int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val); + int (*ll_read)(struct mii_bus *bus, int op, int addr, int regnum); + int (*ll_write)(struct mii_bus *bus, int op, int addr, + int regnum, u16 val); int (*reset)(struct mii_bus *bus); /*
Some phys support special opcode handling when communicating via mdio. This patch introduces mdio_ll_read/write which makes it possible to set the opcode. It implements these functions in the gpio-bitbang driver, which is capable of setting the opcode on read and write. Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> --- Hi Andrew, I worked on your suggestion moving the proprietary call to mdio-ksz88x3.c which does not seem to work out very well. I still end up having an MII_ADDR_SMI???? define in linux/phy.h. Instead of having to support this special case in one extra file what do you think of adding mdiobus_lowlevel_write/read to mdio_bus. This way it would be possible to add the opcode directly as user. Other controllers which have the possibility to set the op code in hardware will also profit from that and can implement these functions. Regards, Michael drivers/net/phy/mdio-bitbang.c | 41 +++++++++--- drivers/net/phy/mdio_bus.c | 110 +++++++++++++++++++++++++++++++++ include/linux/mdio.h | 6 ++ include/linux/phy.h | 3 + 4 files changed, 150 insertions(+), 10 deletions(-)