diff mbox series

[1/2] net: phy: marvell: Support reg config via "marvell, reg-init" DT property

Message ID 20220330083826.829473-1-sr@denx.de
State Superseded
Delegated to: Ramon Fried
Headers show
Series [1/2] net: phy: marvell: Support reg config via "marvell, reg-init" DT property | expand

Commit Message

Stefan Roese March 30, 2022, 8:38 a.m. UTC
This patch adds support for the "marvell,reg-init" DT property, which
is used to describe board specific Marvell PHY register configurations
in the board dts file. This DT property is supported in the Linux Kernel
since a longer time. Adding it to U-Boot now, enables the boards which
describe the register settings in their DT files here as well.

I've included calling this marvell_of_reg_init() to all foo_config()
functions in this patch as well. If CONFIG_DM_ETH is not set, there is
no ofnode, or no "marvell,reg-init" property, the PHY initialization is
unchanged.

The function marvell_of_reg_init() is a port of the Linux version.
Please note that I explicitly did not add error checking and handling
to the U-Boot version, as this is basically not done for phy_read/write
in this Marvell PHY code.

This will be used by the upcoming ethernet support on the MIPS
Octeon EBB 7304 board.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Ramon Fried <rfried.dev@gmail.com>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Aaron Williams <awilliams@marvell.com>
Cc: Chandrakala Chavva <cchavva@marvell.com>
---
 drivers/net/phy/marvell.c | 100 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)

Comments

Marek Behún March 30, 2022, 12:16 p.m. UTC | #1
On Wed, 30 Mar 2022 10:38:25 +0200
Stefan Roese <sr@denx.de> wrote:

> This patch adds support for the "marvell,reg-init" DT property, which
> is used to describe board specific Marvell PHY register configurations
> in the board dts file. This DT property is supported in the Linux Kernel
> since a longer time. Adding it to U-Boot now, enables the boards which
> describe the register settings in their DT files here as well.
> 
> I've included calling this marvell_of_reg_init() to all foo_config()
> functions in this patch as well. If CONFIG_DM_ETH is not set, there is
> no ofnode, or no "marvell,reg-init" property, the PHY initialization is
> unchanged.
> 
> The function marvell_of_reg_init() is a port of the Linux version.
> Please note that I explicitly did not add error checking and handling
> to the U-Boot version, as this is basically not done for phy_read/write
> in this Marvell PHY code.
> 
> This will be used by the upcoming ethernet support on the MIPS
> Octeon EBB 7304 board.
> 
> Signed-off-by: Stefan Roese <sr@denx.de>
> Cc: Ramon Fried <rfried.dev@gmail.com>
> Cc: Joe Hershberger <joe.hershberger@ni.com>
> Cc: Aaron Williams <awilliams@marvell.com>
> Cc: Chandrakala Chavva <cchavva@marvell.com>

Hi Stefan, I know this property is used also in kernel, but what do you
want to use it for?

Because in kernel the idea is to deprecate it.

It is used for example to confiure INT pin, but that should have it's
own property once someone implements it. It is also used to configure
LEDs, and that is hopefully gonna be obsoleted by supporting the LEDs
via the LED subsystem, so afterwards we will write
   ethernet-phy@1 {
      leds {
          led@0 {
              color = ...;
          };
      };
   };

Marek
Stefan Roese March 30, 2022, 1:33 p.m. UTC | #2
On 3/30/22 14:16, Marek Behún wrote:
> On Wed, 30 Mar 2022 10:38:25 +0200
> Stefan Roese <sr@denx.de> wrote:
> 
>> This patch adds support for the "marvell,reg-init" DT property, which
>> is used to describe board specific Marvell PHY register configurations
>> in the board dts file. This DT property is supported in the Linux Kernel
>> since a longer time. Adding it to U-Boot now, enables the boards which
>> describe the register settings in their DT files here as well.
>>
>> I've included calling this marvell_of_reg_init() to all foo_config()
>> functions in this patch as well. If CONFIG_DM_ETH is not set, there is
>> no ofnode, or no "marvell,reg-init" property, the PHY initialization is
>> unchanged.
>>
>> The function marvell_of_reg_init() is a port of the Linux version.
>> Please note that I explicitly did not add error checking and handling
>> to the U-Boot version, as this is basically not done for phy_read/write
>> in this Marvell PHY code.
>>
>> This will be used by the upcoming ethernet support on the MIPS
>> Octeon EBB 7304 board.
>>
>> Signed-off-by: Stefan Roese <sr@denx.de>
>> Cc: Ramon Fried <rfried.dev@gmail.com>
>> Cc: Joe Hershberger <joe.hershberger@ni.com>
>> Cc: Aaron Williams <awilliams@marvell.com>
>> Cc: Chandrakala Chavva <cchavva@marvell.com>
> 
> Hi Stefan, I know this property is used also in kernel, but what do you
> want to use it for?

Frankly, I do not know exactly. It's part of the MIPS Octeon ethernet
support in mainline U-Boot, which also uses this DT property on the
EBB7304 board. I've not analyzed the register settings in detail to
check which register is being configured to which value to see, why this
might be the case. Dropping these register settings might have resulted
in problems not directly spotted on the board. So my plan was to
integrate these as well.

For reference, I've added the current DT reg-init setting below [1].
This is for the 88e1240 PHY, and taking a quick look in the manual,
this seems to be LED related (see below).


> Because in kernel the idea is to deprecate it.

This is new to me.

> It is used for example to confiure INT pin, but that should have it's
> own property once someone implements it. It is also used to configure
> LEDs, and that is hopefully gonna be obsoleted by supporting the LEDs
> via the LED subsystem, so afterwards we will write
>     ethernet-phy@1 {
>        leds {
>            led@0 {
>                color = ...;
>            };
>        };
>     };

That would be very cool indeed. Even though it's not possible "right
now".

So how to continue? Add this "reg-init" "feature" for now? And perhaps
drop it once this LED configuration is possible via the way you describe
above? Or drop it once it's also dropped in the Kernel? My personal
feeling is, that supporting "reg-init" does not "hurt" and might even be
handy for some testing / debugging of network PHY setups.

Perhaps Ramon and/or Joe also have some comments on this.

Thanks,
Stefan

[1]		marvell,reg-init = <3 0x10 0 0x8665>,
				   <3 0x11 0 0x00aa>,
				   <3 0x12 0 0x4105>,
				   <3 0x13 0 0x8a08>;
Marek Behún March 30, 2022, 1:48 p.m. UTC | #3
On Wed, 30 Mar 2022 15:33:34 +0200
Stefan Roese <sr@denx.de> wrote:

> So how to continue? Add this "reg-init" "feature" for now? And perhaps
> drop it once this LED configuration is possible via the way you describe
> above? Or drop it once it's also dropped in the Kernel? My personal
> feeling is, that supporting "reg-init" does not "hurt" and might even be
> handy for some testing / debugging of network PHY setups.

Add it now, maybe we will drop it sometime in future if no dts uses it
anymore.

Kernel will need to support it forever because of backwards
compatibility with older DTBs.

Marek
diff mbox series

Patch

diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index a62c695c5c84..41520c6d392a 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -104,6 +104,88 @@ 
 #define MIIM_88E151x_MODE_SGMII		1
 #define MIIM_88E151x_RESET_OFFS		15
 
+static int marvell_read_page(struct phy_device *phydev)
+{
+	return phy_read(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE);
+}
+
+static int marvell_write_page(struct phy_device *phydev, int page)
+{
+	return phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, page);
+}
+
+#if IS_ENABLED(CONFIG_DM_ETH)
+/* Set and/or override some configuration registers based on the
+ * marvell,reg-init property stored in the of_node for the phydev.
+ *
+ * marvell,reg-init = <reg-page reg mask value>,...;
+ *
+ * There may be one or more sets of <reg-page reg mask value>:
+ *
+ * reg-page: which register bank to use.
+ * reg: the register.
+ * mask: if non-zero, ANDed with existing register value.
+ * value: ORed with the masked value and written to the regiser.
+ *
+ */
+static int marvell_of_reg_init(struct phy_device *phydev)
+{
+	const __be32 *prop;
+	int len, i, saved_page, current_page, ret = 0;
+
+	if (!ofnode_valid(phydev->node))
+		return 0;
+
+	prop = ofnode_get_property(phydev->node, "marvell,reg-init", &len);
+	if (!prop)
+		return 0;
+
+	saved_page = marvell_read_page(phydev);
+	if (saved_page < 0)
+		goto err;
+	current_page = saved_page;
+
+	len /= sizeof(*prop);
+	for (i = 0; i < len - 3; i += 4) {
+		u16 page = be32_to_cpup(prop + i);
+		u16 reg = be32_to_cpup(prop + i + 1);
+		u16 mask = be32_to_cpup(prop + i + 2);
+		u16 val_bits = be32_to_cpup(prop + i + 3);
+		int val;
+
+		if (page != current_page) {
+			current_page = page;
+			ret = marvell_write_page(phydev, page);
+			if (ret < 0)
+				goto err;
+		}
+
+		val = 0;
+		if (mask) {
+			val = phy_read(phydev, MDIO_DEVAD_NONE, reg);
+			if (val < 0) {
+				ret = val;
+				goto err;
+			}
+			val &= mask;
+		}
+		val |= val_bits;
+
+		ret = phy_write(phydev, MDIO_DEVAD_NONE, reg, val);
+		if (ret < 0)
+			goto err;
+	}
+
+err:
+	return marvell_write_page(phydev, saved_page);
+}
+#else
+static int marvell_of_reg_init(struct phy_device *phydev)
+{
+	return 0;
+}
+#endif /* CONFIG_DM_ETH */
+
 static int m88e1xxx_phy_extread(struct phy_device *phydev, int addr,
 				int devaddr, int regnum)
 {
@@ -143,6 +225,8 @@  static int m88e1011s_config(struct phy_device *phydev)
 
 	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
 
+	marvell_of_reg_init(phydev);
+
 	genphy_config_aneg(phydev);
 
 	return 0;
@@ -298,6 +382,8 @@  static int m88e1111s_config(struct phy_device *phydev)
 	/* soft reset */
 	phy_reset(phydev);
 
+	marvell_of_reg_init(phydev);
+
 	genphy_config_aneg(phydev);
 	genphy_restart_aneg(phydev);
 
@@ -397,6 +483,8 @@  static int m88e151x_config(struct phy_device *phydev)
 	/* soft reset */
 	phy_reset(phydev);
 
+	marvell_of_reg_init(phydev);
+
 	genphy_config_aneg(phydev);
 	genphy_restart_aneg(phydev);
 
@@ -417,6 +505,8 @@  static int m88e1118_config(struct phy_device *phydev)
 	/* Change Page Number */
 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 
+	marvell_of_reg_init(phydev);
+
 	return genphy_config_aneg(phydev);
 }
 
@@ -439,6 +529,8 @@  static int m88e1121_config(struct phy_device *phydev)
 {
 	int pg;
 
+	marvell_of_reg_init(phydev);
+
 	/* Configure the PHY */
 	genphy_config_aneg(phydev);
 
@@ -479,6 +571,8 @@  static int m88e1145_config(struct phy_device *phydev)
 			MIIM_M88E1145_RGMII_TX_DELAY;
 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg);
 
+	marvell_of_reg_init(phydev);
+
 	genphy_config_aneg(phydev);
 
 	/* soft reset */
@@ -511,6 +605,8 @@  static int m88e1149_config(struct phy_device *phydev)
 	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0);
 	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
 
+	marvell_of_reg_init(phydev);
+
 	genphy_config_aneg(phydev);
 
 	phy_reset(phydev);
@@ -544,6 +640,8 @@  static int m88e1310_config(struct phy_device *phydev)
 	/* Ensure to return to page 0 */
 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000);
 
+	marvell_of_reg_init(phydev);
+
 	return genphy_config_aneg(phydev);
 }
 
@@ -578,6 +676,8 @@  static int m88e1680_config(struct phy_device *phydev)
 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 	phy_write(phydev, MDIO_DEVAD_NONE,  0, 0x9140);
 
+	marvell_of_reg_init(phydev);
+
 	res = genphy_config_aneg(phydev);
 	if (res < 0)
 		return res;