* [RFC PATCH] net: phy: Added device tree binding for dev-addr and dev-addr code check-up and usage
@ 2018-03-20 13:46 Vicentiu Galanopulo
2018-03-20 14:30 ` Andrew Lunn
0 siblings, 1 reply; 3+ messages in thread
From: Vicentiu Galanopulo @ 2018-03-20 13:46 UTC (permalink / raw)
To: andrew, f.fainelli, netdev, linux-kernel, robh+dt, mark.rutland,
davem, marcel, devicetree
Cc: madalin.bucur, alexandru.marginean
Reason for this patch is that the Inphi PHY
has a vendor specific address space for accessing
the C45 MDIO registers - starting from 0x1e.
A new function has been added, get_phy_c45_dev_addr,
which loops through all the PHY device nodes under
a MDIO bus node and looks for the <dev-addr> property. If
it's not set/found, the get_phy_c45_devs_in_pkg,
will be called with the value 0 as dev_addr parameter,
else it will be called with the dev-addr property
value from the device tree.
As a plus to this patch, num_ids in get_phy_c45_ids,
has the value 8 (ARRAY_SIZE(c45_ids->device_ids)), but
the u32 *devs can store 32 devices in the bitfield. If
a device is stored in *devs, in bits 32 to 9, it
will not be found. This is the reason for changing in phy.h,
the size of device_ids array.
Signed-off-by: Vicentiu Galanopulo <vicentiu.galanopulo@nxp.com>
---
Documentation/devicetree/bindings/net/phy.txt | 6 ++
drivers/net/phy/phy_device.c | 80 ++++++++++++++++++++++++++-
include/linux/phy.h | 2 +-
3 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt
index d2169a5..82692e2 100644
--- a/Documentation/devicetree/bindings/net/phy.txt
+++ b/Documentation/devicetree/bindings/net/phy.txt
@@ -61,6 +61,11 @@ Optional Properties:
- reset-deassert-us: Delay after the reset was deasserted in microseconds.
If this property is missing the delay will be skipped.
+- dev-addr: If set, it indicates the device address of the PHY to be used
+ when accessing the C45 PHY registers over MDIO. It is used for vendor specific
+ register space addresses that do no conform to standard address for the MDIO
+ registers (e.g. MMD30)
+
Example:
ethernet-phy@0 {
@@ -72,4 +77,5 @@ ethernet-phy@0 {
reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
reset-assert-us = <1000>;
reset-deassert-us = <2000>;
+ dev-addr = <0x1e>;
};
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index b285323..35b9a2b 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -442,6 +442,52 @@ static int get_phy_c45_devs_in_pkg(struct mii_bus *bus, int addr, int dev_addr,
}
/**
+ * get_phy_c45_dev_addr - reads the C45 PHY device register address
+ * from the PHY device tree node
+ * @bus: the target MII bus
+ * @addr: PHY address on the MII bus
+ * @dev_addr: where to store the device address of the C45 PHY.
+ *
+ * Description: reads the PHY device address in @dev_addr
+ * from PHY at @addr on @bus.
+ *
+ * Returns: 0 on success, -EIO and -ENODEV on failure.
+ */
+static int get_phy_c45_dev_addr(struct mii_bus *bus,
+ int addr, int *dev_addr)
+{
+ struct device_node *child;
+ u32 reg_addr;
+ int ret;
+
+ if (!bus->dev.of_node)
+ return -ENODEV;
+
+ for_each_available_child_of_node(bus->dev.of_node, child) {
+ ret = of_property_read_u32(child, "reg", ®_addr);
+ if (ret < 0) {
+ dev_err(&bus->dev, "%s has invalid PHY address\n",
+ child->full_name);
+ *dev_addr = 0;
+ return -EINVAL;
+ }
+
+ /* match the device address with the device tree address */
+ if (reg_addr == addr) {
+ ret = of_property_read_u32(child, "dev-addr", dev_addr);
+ if (ret < 0) {
+ dev_warn(&bus->dev, "No PHY device address defined for %s\n",
+ child->full_name);
+ *dev_addr = 0;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
* get_phy_c45_ids - reads the specified addr for its 802.3-c45 IDs.
* @bus: the target MII bus
* @addr: PHY address on the MII bus
@@ -458,6 +504,9 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id,
struct phy_c45_device_ids *c45_ids) {
int phy_reg;
int i, reg_addr;
+ int dev_addr = 0;
+ int ret;
+ int dev_reg_addr;
const int num_ids = ARRAY_SIZE(c45_ids->device_ids);
u32 *devs = &c45_ids->devices_in_package;
@@ -475,9 +524,27 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id,
* 10G PHYs have zero Devices In package,
* e.g. Cortina CS4315/CS4340 PHY.
*/
- phy_reg = get_phy_c45_devs_in_pkg(bus, addr, 0, devs);
+
+ /* Check if the device address
+ * is set in the device tree
+ */
+ ret = get_phy_c45_dev_addr(bus, addr, &dev_addr);
+ /* Exit only when MDIO querying fails
+ * or <reg> property is not set in the
+ * PHY device tree node.
+ */
+ if (ret < 0)
+ return -EIO;
+
+ /* If the device tree property (dev-addr)
+ * is not set, the default value for
+ * dev_addr is 0.
+ */
+ phy_reg = get_phy_c45_devs_in_pkg(bus, addr,
+ dev_addr, devs);
if (phy_reg < 0)
return -EIO;
+
/* no device there, let's get out of here */
if ((*devs & 0x1fffffff) == 0x1fffffff) {
*phy_id = 0xffffffff;
@@ -493,13 +560,20 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id,
if (!(c45_ids->devices_in_package & (1 << i)))
continue;
- reg_addr = MII_ADDR_C45 | i << 16 | MII_PHYSID1;
+ /* If dev-addr is set in the device tree,
+ * use that property value for querying
+ * the PHY device ID.
+ */
+
+ dev_reg_addr = (!!dev_addr ? dev_addr : i) << 16;
+ reg_addr = MII_ADDR_C45 | dev_reg_addr | MII_PHYSID1;
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
c45_ids->device_ids[i] = (phy_reg & 0xffff) << 16;
- reg_addr = MII_ADDR_C45 | i << 16 | MII_PHYSID2;
+ dev_reg_addr = (!!dev_addr ? dev_addr : i) << 16;
+ reg_addr = MII_ADDR_C45 | dev_reg_addr | MII_PHYSID2;
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 5a9b175..c3b3633 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -360,7 +360,7 @@ enum phy_state {
*/
struct phy_c45_device_ids {
u32 devices_in_package;
- u32 device_ids[8];
+ u32 device_ids[32];
};
/* phy_device: An instance of a PHY
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [RFC PATCH] net: phy: Added device tree binding for dev-addr and dev-addr code check-up and usage
2018-03-20 13:46 [RFC PATCH] net: phy: Added device tree binding for dev-addr and dev-addr code check-up and usage Vicentiu Galanopulo
@ 2018-03-20 14:30 ` Andrew Lunn
[not found] ` <HE1PR0402MB3578B23A4DEB394DECB68876EEAA0@HE1PR0402MB3578.eurprd04.prod.outlook.com>
0 siblings, 1 reply; 3+ messages in thread
From: Andrew Lunn @ 2018-03-20 14:30 UTC (permalink / raw)
To: Vicentiu Galanopulo
Cc: f.fainelli, netdev, linux-kernel, robh+dt, mark.rutland, davem,
marcel, devicetree, madalin.bucur, alexandru.marginean
On Tue, Mar 20, 2018 at 08:46:15AM -0500, Vicentiu Galanopulo wrote:
> Reason for this patch is that the Inphi PHY
> has a vendor specific address space for accessing
> the C45 MDIO registers - starting from 0x1e.
>
> A new function has been added, get_phy_c45_dev_addr,
> which loops through all the PHY device nodes under
> a MDIO bus node and looks for the <dev-addr> property. If
> it's not set/found, the get_phy_c45_devs_in_pkg,
> will be called with the value 0 as dev_addr parameter,
> else it will be called with the dev-addr property
> value from the device tree.
This seems like the wrong way to implement this. How about:
of_mdiobus_register(), when it loops over the children, looks for the
new property. If found, it passed dev-id to of_mdiobus_register_phy().
That passes it to get_phy_device(). I think get_phy_device() can then
set the ID in c45_ids, before passing it to
get_phy_id(). get_phy_c45_ids() will first look at devices in package
and can add further devices to c45_ids. It will then probe both those
found, and the static one you added.
Andrew
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC PATCH] net: phy: Added device tree binding for dev-addr and dev-addr code check-up and usage
[not found] ` <HE1PR0402MB3578B23A4DEB394DECB68876EEAA0@HE1PR0402MB3578.eurprd04.prod.outlook.com>
@ 2018-03-22 15:43 ` Andrew Lunn
0 siblings, 0 replies; 3+ messages in thread
From: Andrew Lunn @ 2018-03-22 15:43 UTC (permalink / raw)
To: Vicen?iu Galanopulo; +Cc: netdev
> Just to make sure I understand. Do you want me to change the
> signature of all of_mdiobus_register_phy(), get_phy_device(),
> get_phy_id() and get_phy_c45_ids() and include the dev_addr
> parameter obtained from the device tree? (a propagation of this
> parameter across all functions all the way to
> get_phy_c45_devs_in_pkg?)
Humm, i thought about this some more...
When calling mdio_read/mdio_write with C45 addresses, we pack both
parts in addr, and mask in MII_ADDR_C45. Try playing with that idea.
It might be less messy.
Andrew
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-03-22 15:43 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-20 13:46 [RFC PATCH] net: phy: Added device tree binding for dev-addr and dev-addr code check-up and usage Vicentiu Galanopulo
2018-03-20 14:30 ` Andrew Lunn
[not found] ` <HE1PR0402MB3578B23A4DEB394DECB68876EEAA0@HE1PR0402MB3578.eurprd04.prod.outlook.com>
2018-03-22 15:43 ` Andrew Lunn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).