All of lore.kernel.org
 help / color / mirror / Atom feed
* DSA mv88e6xxx_probe
@ 2023-02-02 15:18 Valek, Andrej
  2023-02-02 16:05 ` Andrew Lunn
  0 siblings, 1 reply; 9+ messages in thread
From: Valek, Andrej @ 2023-02-02 15:18 UTC (permalink / raw)
  To: vivien.didelot, andrew; +Cc: netdev

Hello everyone!

I have a switch mv88e6085 which is connected via MDIO bus to iMX.8 SoC.

Switch is not being detected during booting because the address is
different (due to uninitialized PINs from DTB). The problem is, that
switch has to be reset during boot phase, but it isn't.

So I would like to ask you maybe a generic question about
devm_gpiod_get_optional function inside mv88e6xxx_probe.

Is this "chip->reset = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);" line really do the reset? Because from the lines below
looks like, but the reset pulse hasn't been made. Measured with scope.

> chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> if (IS_ERR(chip->reset))
>	goto out;
>
> if (chip->reset)
>	usleep_range(1000, 2000);

So it should wait, but for what?

I see an other lines down bellow
> mv88e6xxx_reg_lock(chip);
> err = mv88e6xxx_switch_reset(chip);
> mv88e6xxx_reg_unlock(chip);

but they are deeper after the "mv88e6xxx_detect" which failed, because
it can't find the switch.
> [3.229659] mv88e6085: probe of 5b040000.ethernet-1:10 failed with
error -110

So I "hard-coded" the real reset there:
> chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> if (IS_ERR(chip->reset))
>	goto out;
>
> if (chip->reset) {
> 	gpiod_set_value_cansleep(chip->reset, 1);
> 	usleep_range(10000, 20000);
> 	gpiod_set_value_cansleep(chip->reset, 0);
> 	usleep_range(10000, 20000);

and switch was correctly founded:
> [    4.022175] mv88e6085 5b040000.ethernet-1:10: switch 0x3100
detected: Marvell 88E6321, revision 2
> [    4.210834] mv88e6085 5b040000.ethernet-1:10: configuring for
fixed/ link mode
> [    4.218587] mv88e6085 5b040000.ethernet-1:10: Link is Up -
1Gbps/Full - flow control off
...

So my question is, how the reset really works, or there is some kind of
potential bug?

Many thanks for your explanation.
Andrej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DSA mv88e6xxx_probe
  2023-02-02 15:18 DSA mv88e6xxx_probe Valek, Andrej
@ 2023-02-02 16:05 ` Andrew Lunn
  2023-02-02 17:57   ` Valek, Andrej
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2023-02-02 16:05 UTC (permalink / raw)
  To: Valek, Andrej; +Cc: vivien.didelot, netdev

On Thu, Feb 02, 2023 at 03:18:37PM +0000, Valek, Andrej wrote:
> Hello everyone!
> 
> I have a switch mv88e6085 which is connected via MDIO bus to iMX.8 SoC.
> 
> Switch is not being detected during booting because the address is
> different (due to uninitialized PINs from DTB). The problem is, that
> switch has to be reset during boot phase, but it isn't.
> 
> So I would like to ask you maybe a generic question about
> devm_gpiod_get_optional function inside mv88e6xxx_probe.
> 
> Is this "chip->reset = devm_gpiod_get_optional(dev, "reset",
> GPIOD_OUT_LOW);" line really do the reset? Because from the lines below
> looks like, but the reset pulse hasn't been made. Measured with scope.
> 
> > chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > if (IS_ERR(chip->reset))
> >	goto out;
> >
> > if (chip->reset)
> >	usleep_range(1000, 2000);
> 
> So it should wait, but for what?

The current code is designed to take a switch held in reset out of
reset. It does not perform an actual reset.

If you need a real reset, you probably need to call
mv88e6xxx_hardware_reset(chip), not usleep().

However, a reset can be a slow operation, specially if the EEPROM is
full of stuff. So we want to avoid two resets if possible.

The MDIO bus itself has DT descriptions for a GPIO reset. See
Documentation/devicetree/bindings/net/mdio.yaml

You might be able to use this to perform the power on reset of the
switch. That advantage of that is it won't slow down the probe of
everybody elses switches which have correct pin strapping.

	Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DSA mv88e6xxx_probe
  2023-02-02 16:05 ` Andrew Lunn
@ 2023-02-02 17:57   ` Valek, Andrej
  2023-02-02 18:10     ` Andrew Lunn
  0 siblings, 1 reply; 9+ messages in thread
From: Valek, Andrej @ 2023-02-02 17:57 UTC (permalink / raw)
  To: andrew; +Cc: vivien.didelot, netdev

Thank you for the explanation, but I have some additional questions...
.

On Thu, 2023-02-02 at 17:05 +0100, Andrew Lunn wrote:
> On Thu, Feb 02, 2023 at 03:18:37PM +0000, Valek, Andrej wrote:
> > Hello everyone!
> > 
> > I have a switch mv88e6085 which is connected via MDIO bus to iMX.8
> > SoC.
> > 
> > Switch is not being detected during booting because the address is
> > different (due to uninitialized PINs from DTB). The problem is,
> > that
> > switch has to be reset during boot phase, but it isn't.
> > 
> > So I would like to ask you maybe a generic question about
> > devm_gpiod_get_optional function inside mv88e6xxx_probe.
> > 
> > Is this "chip->reset = devm_gpiod_get_optional(dev, "reset",
> > GPIOD_OUT_LOW);" line really do the reset? Because from the lines
> > below
> > looks like, but the reset pulse hasn't been made. Measured with
> > scope.
> > 
> > > chip->reset = devm_gpiod_get_optional(dev, "reset",
> > > GPIOD_OUT_LOW);
> > > if (IS_ERR(chip->reset))
> > >         goto out;
> > > 
> > > if (chip->reset)
> > >         usleep_range(1000, 2000);
> > 
> > So it should wait, but for what?
> 
> The current code is designed to take a switch held in reset out of
> reset. It does not perform an actual reset.
> 
How does it then work? I see just a "devm_gpiod_get_optional" which
just assign an pointer to "chip->reset" and then
" if (chip->reset) usleep_range(1000, 2000);" which just waits for
"something" ? Where is the "reset" took out? I don't see any gpio set
to 0.
> If you need a real reset, you probably need to call
> mv88e6xxx_hardware_reset(chip), not usleep().
> 
> However, a reset can be a slow operation, specially if the EEPROM is
> full of stuff. So we want to avoid two resets if possible.
> 
> The MDIO bus itself has DT descriptions for a GPIO reset. See
> Documentation/devicetree/bindings/net/mdio.yaml
This looks promising. So I have to just move the "reset-gpios" DTB
entry from switch to mdio section. But which driver handles it,
drivers/net/phy/mdio_bus.c,  or?
> mdio {
> 	#address-cells = <1>;
> 	#size-cells = 0>;
while here is no compatible part... .
> 
> You might be able to use this to perform the power on reset of the
> switch. That advantage of that is it won't slow down the probe of
> everybody elses switches which have correct pin strapping.
> 
>         Andrew

Regards,
Andrej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DSA mv88e6xxx_probe
  2023-02-02 17:57   ` Valek, Andrej
@ 2023-02-02 18:10     ` Andrew Lunn
  2023-02-03  8:07       ` Valek, Andrej
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2023-02-02 18:10 UTC (permalink / raw)
  To: Valek, Andrej; +Cc: vivien.didelot, netdev

> > > > chip->reset = devm_gpiod_get_optional(dev, "reset",
> > > > GPIOD_OUT_LOW);
> > > > if (IS_ERR(chip->reset))
> > > >         goto out;
> > > > 
> > > > if (chip->reset)
> > > >         usleep_range(1000, 2000);
> > > 
> > > So it should wait, but for what?
> > 
> > The current code is designed to take a switch held in reset out of
> > reset. It does not perform an actual reset.
> > 
> How does it then work? I see just a "devm_gpiod_get_optional" which
> just assign an pointer to "chip->reset" and then
> " if (chip->reset) usleep_range(1000, 2000);" which just waits for
> "something" ? Where is the "reset" took out? I don't see any gpio set
> to 0.

https://elixir.bootlin.com/linux/latest/source/include/linux/gpio/consumer.h#L49

	GPIOD_OUT_LOW	= GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,

https://elixir.bootlin.com/linux/latest/source/drivers/gpio/gpiolib.c#L4051

	/* Process flags */
	if (dflags & GPIOD_FLAGS_BIT_DIR_OUT)
		ret = gpiod_direction_output(desc,
				!!(dflags & GPIOD_FLAGS_BIT_DIR_VAL));
	else
		ret = gpiod_direction_input(desc);

> > If you need a real reset, you probably need to call
> > mv88e6xxx_hardware_reset(chip), not usleep().
> > 
> > However, a reset can be a slow operation, specially if the EEPROM is
> > full of stuff. So we want to avoid two resets if possible.
> > 
> > The MDIO bus itself has DT descriptions for a GPIO reset. See
> > Documentation/devicetree/bindings/net/mdio.yaml
> This looks promising. So I have to just move the "reset-gpios" DTB
> entry from switch to mdio section. But which driver handles it,
> drivers/net/phy/mdio_bus.c,

Yes.

> > mdio {
> > 	#address-cells = <1>;
> > 	#size-cells = 0>;
> while here is no compatible part... .

It does not need a compatible, because it is part of the FEC, and the
FEC has a compatible. Remember this is device tree, sometimes you need
to go up the tree towards the root to find the actual device with a
compatible.

    Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DSA mv88e6xxx_probe
  2023-02-02 18:10     ` Andrew Lunn
@ 2023-02-03  8:07       ` Valek, Andrej
  2023-02-03 13:54         ` Andrew Lunn
  0 siblings, 1 reply; 9+ messages in thread
From: Valek, Andrej @ 2023-02-03  8:07 UTC (permalink / raw)
  To: andrew; +Cc: vivien.didelot, netdev

Hello again,

On Thu, 2023-02-02 at 19:10 +0100, Andrew Lunn wrote:
> > > > > chip->reset = devm_gpiod_get_optional(dev, "reset",
> > > > > GPIOD_OUT_LOW);
> > > > > if (IS_ERR(chip->reset))
> > > > >         goto out;
> > > > > 
> > > > > if (chip->reset)
> > > > >         usleep_range(1000, 2000);
> > > > 
> > > > So it should wait, but for what?
> > > 
> > > The current code is designed to take a switch held in reset out of
> > > reset. It does not perform an actual reset.
> > > 
> > How does it then work? I see just a "devm_gpiod_get_optional" which
> > just assign an pointer to "chip->reset" and then
> > " if (chip->reset) usleep_range(1000, 2000);" which just waits for
> > "something" ? Where is the "reset" took out? I don't see any gpio set
> > to 0.
> 
> https://elixir.bootlin.com/linux/latest/source/include/linux/gpio/consumer.h#L49
> 
>         GPIOD_OUT_LOW   = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,
> 
> https://elixir.bootlin.com/linux/latest/source/drivers/gpio/gpiolib.c#L4051
> 
>         /* Process flags */
>         if (dflags & GPIOD_FLAGS_BIT_DIR_OUT)
>                 ret = gpiod_direction_output(desc,
>                                 !!(dflags & GPIOD_FLAGS_BIT_DIR_VAL));
>         else
>                 ret = gpiod_direction_input(desc);
> 
Ok, not it makes much more sense. So it's automatically set output to OFF. In my case to HIGH.
> > > If you need a real reset, you probably need to call
> > > mv88e6xxx_hardware_reset(chip), not usleep().
> > > 
> > > However, a reset can be a slow operation, specially if the EEPROM is
> > > full of stuff. So we want to avoid two resets if possible.
> > > 
> > > The MDIO bus itself has DT descriptions for a GPIO reset. See
> > > Documentation/devicetree/bindings/net/mdio.yaml
> > This looks promising. So I have to just move the "reset-gpios" DTB
> > entry from switch to mdio section. But which driver handles it,
> > drivers/net/phy/mdio_bus.c,
> 
> Yes.
> 
> > > mdio {
> > >         #address-cells = <1>;
> > >         #size-cells = 0>;
> > while here is no compatible part... .
> 
> It does not need a compatible, because it is part of the FEC, and the
> FEC has a compatible. Remember this is device tree, sometimes you need
> to go up the tree towards the root to find the actual device with a
> compatible.
> 
>     Andrew
I tried put the "reset-gpios" and "reset-delay-us" into multiple mdio locations, but nothing has been working. DTB looks like that:

> &fec1 {
> 	pinctrl-names = "default";
> 	pinctrl-0 = <&pinctrl_fec1>;
> 	phy-mode = "rgmii-id";
> 	tx-internal-delay-ps = <2000>;
> 	rx-internal-delay-ps = <2000>;
> 	slaves = <1>;			// use only one emac if
> 	status = "okay";
> 	mac-address = [ 00 00 00 00 00 00 ]; // Filled in by U-Boot
>
> 	// #### 3. try ####
> 	//phy-reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> 	//reset-delay-us = <10000>;
>
> 	fixed-link {
> 		speed = <1000>;
> 		full-duplex;
> 	};
>
> 	mdio {
> 		#address-cells = <1>;
> 		#size-cells = <0>;
>
> 		// 1. try
> 		reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> 		reset-delay-us = <10000>;
>
> 		// MV88E6321 Switch
> 		switch: switch@10 {
> 			compatible = "marvell,mv88e6321","marvell,mv88e6085";
>
> 			#address-cells = <1>;
> 			#size-cells = <0>;
> 			dsa,member = <0 0>;
>
> 			reg = <0x10>;
> 			interrupt-controller;
> 			#interrupt-cells = <2>;
>
> 			// this is the location, where driver is handling the reset
> 			//reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
>
> 			ports {
> 				#address-cells = <1>;
> 				#size-cells = <0>;
>
> 				port0: ports@0 {
> 					reg = <0>;
> 					label = "wan0";
> 					phy-handle = <&switch1phy0>;
> 				// other ports part...
> 			};
>
> 			mdio {
> 				#address-cells = <1>;
> 				#size-cells = <0>;
>
> 				// #### 2. try ####
> 				//reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> 				//reset-delay-us = <10000>;
>
>
> 				switch1phy0: switch1phy0@0 {
> 					reg = <0>;
> 					select-class-a;
> 				};
> 				// ...
> 			};
> 		};
> 	};
>};

And if I look at the decompiled DTB, there is no physical address for MDIO bus.
> mdio {
> 		#address-cells = <0x01>;
> 		#size-cells = <0x00>;
> 		reset-gpios = <0x8c 0x0d 0x01>;
> 		reset-delay-us = <0x2710>;
>
>		switch@10 {
> 			compatible = "marvell,mv88e6321\0marvell,mv88e6085";
> 			#address-cells = <0x01>;
> 			#size-cells = <0x00>;
> 			dsa,member = <0x00 0x00>;

So how to verify it?

Thank you,
Andrej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DSA mv88e6xxx_probe
  2023-02-03  8:07       ` Valek, Andrej
@ 2023-02-03 13:54         ` Andrew Lunn
  2023-02-03 14:47           ` Valek, Andrej
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2023-02-03 13:54 UTC (permalink / raw)
  To: Valek, Andrej; +Cc: vivien.didelot, netdev

> > > This looks promising. So I have to just move the "reset-gpios" DTB
> > > entry from switch to mdio section. But which driver handles it,
> > > drivers/net/phy/mdio_bus.c,
> > 
> > Yes.
> > 
> > > > mdio {
> > > >         #address-cells = <1>;
> > > >         #size-cells = 0>;
> > > while here is no compatible part... .
> > 
> > It does not need a compatible, because it is part of the FEC, and the
> > FEC has a compatible. Remember this is device tree, sometimes you need
> > to go up the tree towards the root to find the actual device with a
> > compatible.
> > 
> >     Andrew
> I tried put the "reset-gpios" and "reset-delay-us" into multiple mdio locations, but nothing has been working. DTB looks like that:
> 
> > &fec1 {
> > 	pinctrl-names = "default";
> > 	pinctrl-0 = <&pinctrl_fec1>;
> > 	phy-mode = "rgmii-id";
> > 	tx-internal-delay-ps = <2000>;
> > 	rx-internal-delay-ps = <2000>;
> > 	slaves = <1>;			// use only one emac if
> > 	status = "okay";
> > 	mac-address = [ 00 00 00 00 00 00 ]; // Filled in by U-Boot
> >
> > 	// #### 3. try ####
> > 	//phy-reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> > 	//reset-delay-us = <10000>;
> >
> > 	fixed-link {
> > 		speed = <1000>;
> > 		full-duplex;
> > 	};
> >
> > 	mdio {
> > 		#address-cells = <1>;
> > 		#size-cells = <0>;
> >
> > 		// 1. try
> > 		reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> > 		reset-delay-us = <10000>;

This looks like the correct location. Have you put a printk() after
https://elixir.bootlin.com/linux/latest/source/drivers/net/phy/mdio_bus.c#L569
to make sure it has found it?

You might also need a post reset delay. I'm not sure the device will
answer if it is still busy reading the EEPROM. Which is why the
mv88e6xxx hardware reset does some polling before continuing.

	  Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DSA mv88e6xxx_probe
  2023-02-03 13:54         ` Andrew Lunn
@ 2023-02-03 14:47           ` Valek, Andrej
  2023-02-06 14:50             ` Valek, Andrej
  0 siblings, 1 reply; 9+ messages in thread
From: Valek, Andrej @ 2023-02-03 14:47 UTC (permalink / raw)
  To: andrew; +Cc: vivien.didelot, netdev

On Fri, 2023-02-03 at 14:54 +0100, Andrew Lunn wrote:
> > > > This looks promising. So I have to just move the "reset-gpios" DTB
> > > > entry from switch to mdio section. But which driver handles it,
> > > > drivers/net/phy/mdio_bus.c,
> > > 
> > > Yes.
> > > 
> > > > > mdio {
> > > > >         #address-cells = <1>;
> > > > >         #size-cells = 0>;
> > > > while here is no compatible part... .
> > > 
> > > It does not need a compatible, because it is part of the FEC, and the
> > > FEC has a compatible. Remember this is device tree, sometimes you need
> > > to go up the tree towards the root to find the actual device with a
> > > compatible.
> > > 
> > >     Andrew
> > I tried put the "reset-gpios" and "reset-delay-us" into multiple mdio locations, but nothing has been working. DTB looks like that:
> > 
> > > &fec1 {
> > >         pinctrl-names = "default";
> > >         pinctrl-0 = <&pinctrl_fec1>;
> > >         phy-mode = "rgmii-id";
> > >         tx-internal-delay-ps = <2000>;
> > >         rx-internal-delay-ps = <2000>;
> > >         slaves = <1>;                   // use only one emac if
> > >         status = "okay";
> > >         mac-address = [ 00 00 00 00 00 00 ]; // Filled in by U-Boot
> > > 
> > >         // #### 3. try ####
> > >         //phy-reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> > >         //reset-delay-us = <10000>;
> > > 
> > >         fixed-link {
> > >                 speed = <1000>;
> > >                 full-duplex;
> > >         };
> > > 
> > >         mdio {
> > >                 #address-cells = <1>;
> > >                 #size-cells = <0>;
> > > 
> > >                 // 1. try
> > >                 reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> > >                 reset-delay-us = <10000>;
> 
> This looks like the correct location. Have you put a printk() after
> https://elixir.bootlin.com/linux/latest/source/drivers/net/phy/mdio_bus.c#L569
> to make sure it has found it?
> 
Yes, I put there multiple printk-s... .
> 	dev_info(&bus->dev, "device registered\n");
>
> 	mutex_init(&bus->mdio_lock);
> 	mutex_init(&bus->shared_lock);
>
> 	/* assert bus level PHY GPIO reset */
> 	gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_HIGH);
> 	dev_info(&bus->dev, "getting gpiod\n");
>
> 	if (IS_ERR(gpiod)) {
> 		err = dev_err_probe(&bus->dev, PTR_ERR(gpiod),
> 				    "mii_bus %s couldn't get reset GPIO\n",
> 				    bus->id);
> 		device_del(&bus->dev);
> 		return err;
> 	} else	if (gpiod) {
> 		dev_info(&bus->dev, "gpiod found\n");
> 		bus->reset_gpiod = gpiod;
> 		fsleep(bus->reset_delay_us);
> 		gpiod_set_value_cansleep(gpiod, 0);
> 		if (bus->reset_post_delay_us > 0)
> 			fsleep(bus->reset_post_delay_us);
> 	}
>
> 	if (bus->reset) {
> 		dev_info(&bus->dev, "reset found\n");
> 		err = bus->reset(bus);

And the output log looks:
> [    1.446095] mdio_bus fixed-0: device registered
> [    1.450698] mdio_bus fixed-0: getting gpiod
> [    1.494870] pps pps0: new PPS source ptp0
> [    1.505888] mdio_bus 5b040000.ethernet-1: device registered
> [    1.511552] mdio_bus 5b040000.ethernet-1: getting gpiod
> [    1.550705] pps pps0: new PPS source ptp0
> [    1.561203] mdio_bus 5b050000.ethernet-1: device registered
> [    1.566791] mdio_bus 5b050000.ethernet-1: getting gpiod
> ...
> [    2.568174] fec 5b050000.ethernet eth0: registered PHC device 0

Sp there are only a "device registered" and "getting gpiod" messages and nor "gpiod found" and "resed found".
So now the question is why it didn't find the reset in dtb, or where to place it.

Andrej

> You might also need a post reset delay. I'm not sure the device will
> answer if it is still busy reading the EEPROM. Which is why the
> mv88e6xxx hardware reset does some polling before continuing.
> 
>           Andrew


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DSA mv88e6xxx_probe
  2023-02-03 14:47           ` Valek, Andrej
@ 2023-02-06 14:50             ` Valek, Andrej
  2023-02-08  8:20               ` Valek, Andrej
  0 siblings, 1 reply; 9+ messages in thread
From: Valek, Andrej @ 2023-02-06 14:50 UTC (permalink / raw)
  To: andrew; +Cc: vivien.didelot, netdev

Hello again,

I put some more "debugs" there.

> 	/* assert bus level PHY GPIO reset */
> 	dev_info(&bus->dev, "getting gpiod\n");
> 	gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_HIGH);
> 	if(gpiod) dev_info(&bus->dev, "gpio found1\n");
> 	else dev_info(&bus->dev, "gpio NOT found1\n");
>
> 	/*if (IS_ERR(gpiod)) {
> 		dev_info(&bus->dev, "gpiod error\n");
> 		err = dev_err_probe(&bus->dev, PTR_ERR(gpiod),
> 				    "mii_bus %s couldn't get reset GPIO\n",
> 				    bus->id);
> 		device_del(&bus->dev);
> 		return err;
> 	}*/
>
> 	if (gpiod) {
> 		dev_info(&bus->dev, "%p:gpiod found\n", gpiod);
> 		bus->reset_gpiod = gpiod;
> 		fsleep(bus->reset_delay_us);
> 		gpiod_set_value_cansleep(gpiod, 0);
> 		if (bus->reset_post_delay_us > 0)
> 			fsleep(bus->reset_post_delay_us);
> 	}

After that I see messages like:
> [    1.530251] mdio_bus 5b040000.ethernet-1: device registered
> [    1.535840] mdio_bus 5b040000.ethernet-1: getting gpiod
> [    1.541150] mdio_bus 5b040000.ethernet-1: gpio found1
> [    1.546210] mdio_bus 5b040000.ethernet-1: fffffffffffffdfb:gpiod found
> [    1.567900] gpiod_set_value_cansleep: invalid GPIO (errorpointer)

So there is a problem, that function "devm_gpiod_get_optional" is not returning the correct pointer.

Regards,
Andrej

On Fri, 2023-02-03 at 14:47 +0000, Valek, Andrej wrote:
> On Fri, 2023-02-03 at 14:54 +0100, Andrew Lunn wrote:
> > > > > This looks promising. So I have to just move the "reset-
> > > > > gpios" DTB
> > > > > entry from switch to mdio section. But which driver handles
> > > > > it,
> > > > > drivers/net/phy/mdio_bus.c,
> > > > 
> > > > Yes.
> > > > 
> > > > > > mdio {
> > > > > >         #address-cells = <1>;
> > > > > >         #size-cells = 0>;
> > > > > while here is no compatible part... .
> > > > 
> > > > It does not need a compatible, because it is part of the FEC,
> > > > and the
> > > > FEC has a compatible. Remember this is device tree, sometimes
> > > > you need
> > > > to go up the tree towards the root to find the actual device
> > > > with a
> > > > compatible.
> > > > 
> > > >     Andrew
> > > I tried put the "reset-gpios" and "reset-delay-us" into multiple
> > > mdio locations, but nothing has been working. DTB looks like
> > > that:
> > > 
> > > > &fec1 {
> > > >         pinctrl-names = "default";
> > > >         pinctrl-0 = <&pinctrl_fec1>;
> > > >         phy-mode = "rgmii-id";
> > > >         tx-internal-delay-ps = <2000>;
> > > >         rx-internal-delay-ps = <2000>;
> > > >         slaves = <1>;                   // use only one emac if
> > > >         status = "okay";
> > > >         mac-address = [ 00 00 00 00 00 00 ]; // Filled in by U-
> > > > Boot
> > > > 
> > > >         // #### 3. try ####
> > > >         //phy-reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> > > >         //reset-delay-us = <10000>;
> > > > 
> > > >         fixed-link {
> > > >                 speed = <1000>;
> > > >                 full-duplex;
> > > >         };
> > > > 
> > > >         mdio {
> > > >                 #address-cells = <1>;
> > > >                 #size-cells = <0>;
> > > > 
> > > >                 // 1. try
> > > >                 reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> > > >                 reset-delay-us = <10000>;
> > 
> > This looks like the correct location. Have you put a printk() after
> > https://elixir.bootlin.com/linux/latest/source/drivers/net/phy/mdio_bus.c#L569
> > to make sure it has found it?
> > 
> Yes, I put there multiple printk-s... .
> >         dev_info(&bus->dev, "device registered\n");
> > 
> >         mutex_init(&bus->mdio_lock);
> >         mutex_init(&bus->shared_lock);
> > 
> >         /* assert bus level PHY GPIO reset */
> >         gpiod = devm_gpiod_get_optional(&bus->dev, "reset",
> > GPIOD_OUT_HIGH);
> >         dev_info(&bus->dev, "getting gpiod\n");
> > 
> >         if (IS_ERR(gpiod)) {
> >                 err = dev_err_probe(&bus->dev, PTR_ERR(gpiod),
> >                                     "mii_bus %s couldn't get reset
> > GPIO\n",
> >                                     bus->id);
> >                 device_del(&bus->dev);
> >                 return err;
> >         } else  if (gpiod) {
> >                 dev_info(&bus->dev, "gpiod found\n");
> >                 bus->reset_gpiod = gpiod;
> >                 fsleep(bus->reset_delay_us);
> >                 gpiod_set_value_cansleep(gpiod, 0);
> >                 if (bus->reset_post_delay_us > 0)
> >                         fsleep(bus->reset_post_delay_us);
> >         }
> > 
> >         if (bus->reset) {
> >                 dev_info(&bus->dev, "reset found\n");
> >                 err = bus->reset(bus);
> 
> And the output log looks:
> > [    1.446095] mdio_bus fixed-0: device registered
> > [    1.450698] mdio_bus fixed-0: getting gpiod
> > [    1.494870] pps pps0: new PPS source ptp0
> > [    1.505888] mdio_bus 5b040000.ethernet-1: device registered
> > [    1.511552] mdio_bus 5b040000.ethernet-1: getting gpiod
> > [    1.550705] pps pps0: new PPS source ptp0
> > [    1.561203] mdio_bus 5b050000.ethernet-1: device registered
> > [    1.566791] mdio_bus 5b050000.ethernet-1: getting gpiod
> > ...
> > [    2.568174] fec 5b050000.ethernet eth0: registered PHC device 0
> 
> Sp there are only a "device registered" and "getting gpiod" messages
> and nor "gpiod found" and "resed found".
> So now the question is why it didn't find the reset in dtb, or where
> to place it.
> 
> Andrej
> 
> > You might also need a post reset delay. I'm not sure the device
> > will
> > answer if it is still busy reading the EEPROM. Which is why the
> > mv88e6xxx hardware reset does some polling before continuing.
> > 
> >           Andrew
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DSA mv88e6xxx_probe
  2023-02-06 14:50             ` Valek, Andrej
@ 2023-02-08  8:20               ` Valek, Andrej
  0 siblings, 0 replies; 9+ messages in thread
From: Valek, Andrej @ 2023-02-08  8:20 UTC (permalink / raw)
  To: andrew; +Cc: vivien.didelot, netdev

Hello Andrew,

I found a problem.
There is a bug in FEC driver which is not handling the MDIO bus
properly. Once this is fixed, then it works exactly like you described.

Many thanks for your support,
Andrej

On Mon, 2023-02-06 at 14:50 +0000, Valek, Andrej wrote:
> Hello again,
> 
> I put some more "debugs" there.
> 
> >         /* assert bus level PHY GPIO reset */
> >         dev_info(&bus->dev, "getting gpiod\n");
> >         gpiod = devm_gpiod_get_optional(&bus->dev, "reset",
> > GPIOD_OUT_HIGH);
> >         if(gpiod) dev_info(&bus->dev, "gpio found1\n");
> >         else dev_info(&bus->dev, "gpio NOT found1\n");
> > 
> >         /*if (IS_ERR(gpiod)) {
> >                 dev_info(&bus->dev, "gpiod error\n");
> >                 err = dev_err_probe(&bus->dev, PTR_ERR(gpiod),
> >                                     "mii_bus %s couldn't get reset
> > GPIO\n",
> >                                     bus->id);
> >                 device_del(&bus->dev);
> >                 return err;
> >         }*/
> > 
> >         if (gpiod) {
> >                 dev_info(&bus->dev, "%p:gpiod found\n", gpiod);
> >                 bus->reset_gpiod = gpiod;
> >                 fsleep(bus->reset_delay_us);
> >                 gpiod_set_value_cansleep(gpiod, 0);
> >                 if (bus->reset_post_delay_us > 0)
> >                         fsleep(bus->reset_post_delay_us);
> >         }
> 
> After that I see messages like:
> > [    1.530251] mdio_bus 5b040000.ethernet-1: device registered
> > [    1.535840] mdio_bus 5b040000.ethernet-1: getting gpiod
> > [    1.541150] mdio_bus 5b040000.ethernet-1: gpio found1
> > [    1.546210] mdio_bus 5b040000.ethernet-1: fffffffffffffdfb:gpiod
> > found
> > [    1.567900] gpiod_set_value_cansleep: invalid GPIO
> > (errorpointer)
> 
> So there is a problem, that function "devm_gpiod_get_optional" is not
> returning the correct pointer.
> 
> Regards,
> Andrej
> 
> On Fri, 2023-02-03 at 14:47 +0000, Valek, Andrej wrote:
> > On Fri, 2023-02-03 at 14:54 +0100, Andrew Lunn wrote:
> > > > > > This looks promising. So I have to just move the "reset-
> > > > > > gpios" DTB
> > > > > > entry from switch to mdio section. But which driver handles
> > > > > > it,
> > > > > > drivers/net/phy/mdio_bus.c,
> > > > > 
> > > > > Yes.
> > > > > 
> > > > > > > mdio {
> > > > > > >         #address-cells = <1>;
> > > > > > >         #size-cells = 0>;
> > > > > > while here is no compatible part... .
> > > > > 
> > > > > It does not need a compatible, because it is part of the FEC,
> > > > > and the
> > > > > FEC has a compatible. Remember this is device tree, sometimes
> > > > > you need
> > > > > to go up the tree towards the root to find the actual device
> > > > > with a
> > > > > compatible.
> > > > > 
> > > > >     Andrew
> > > > I tried put the "reset-gpios" and "reset-delay-us" into
> > > > multiple
> > > > mdio locations, but nothing has been working. DTB looks like
> > > > that:
> > > > 
> > > > > &fec1 {
> > > > >         pinctrl-names = "default";
> > > > >         pinctrl-0 = <&pinctrl_fec1>;
> > > > >         phy-mode = "rgmii-id";
> > > > >         tx-internal-delay-ps = <2000>;
> > > > >         rx-internal-delay-ps = <2000>;
> > > > >         slaves = <1>;                   // use only one emac
> > > > > if
> > > > >         status = "okay";
> > > > >         mac-address = [ 00 00 00 00 00 00 ]; // Filled in by
> > > > > U-
> > > > > Boot
> > > > > 
> > > > >         // #### 3. try ####
> > > > >         //phy-reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> > > > >         //reset-delay-us = <10000>;
> > > > > 
> > > > >         fixed-link {
> > > > >                 speed = <1000>;
> > > > >                 full-duplex;
> > > > >         };
> > > > > 
> > > > >         mdio {
> > > > >                 #address-cells = <1>;
> > > > >                 #size-cells = <0>;
> > > > > 
> > > > >                 // 1. try
> > > > >                 reset-gpios = <&lsio_gpio0 13
> > > > > GPIO_ACTIVE_LOW>;
> > > > >                 reset-delay-us = <10000>;
> > > 
> > > This looks like the correct location. Have you put a printk()
> > > after
> > > https://elixir.bootlin.com/linux/latest/source/drivers/net/phy/mdio_bus.c#L569
> > > to make sure it has found it?
> > > 
> > Yes, I put there multiple printk-s... .
> > >         dev_info(&bus->dev, "device registered\n");
> > > 
> > >         mutex_init(&bus->mdio_lock);
> > >         mutex_init(&bus->shared_lock);
> > > 
> > >         /* assert bus level PHY GPIO reset */
> > >         gpiod = devm_gpiod_get_optional(&bus->dev, "reset",
> > > GPIOD_OUT_HIGH);
> > >         dev_info(&bus->dev, "getting gpiod\n");
> > > 
> > >         if (IS_ERR(gpiod)) {
> > >                 err = dev_err_probe(&bus->dev, PTR_ERR(gpiod),
> > >                                     "mii_bus %s couldn't get
> > > reset
> > > GPIO\n",
> > >                                     bus->id);
> > >                 device_del(&bus->dev);
> > >                 return err;
> > >         } else  if (gpiod) {
> > >                 dev_info(&bus->dev, "gpiod found\n");
> > >                 bus->reset_gpiod = gpiod;
> > >                 fsleep(bus->reset_delay_us);
> > >                 gpiod_set_value_cansleep(gpiod, 0);
> > >                 if (bus->reset_post_delay_us > 0)
> > >                         fsleep(bus->reset_post_delay_us);
> > >         }
> > > 
> > >         if (bus->reset) {
> > >                 dev_info(&bus->dev, "reset found\n");
> > >                 err = bus->reset(bus);
> > 
> > And the output log looks:
> > > [    1.446095] mdio_bus fixed-0: device registered
> > > [    1.450698] mdio_bus fixed-0: getting gpiod
> > > [    1.494870] pps pps0: new PPS source ptp0
> > > [    1.505888] mdio_bus 5b040000.ethernet-1: device registered
> > > [    1.511552] mdio_bus 5b040000.ethernet-1: getting gpiod
> > > [    1.550705] pps pps0: new PPS source ptp0
> > > [    1.561203] mdio_bus 5b050000.ethernet-1: device registered
> > > [    1.566791] mdio_bus 5b050000.ethernet-1: getting gpiod
> > > ...
> > > [    2.568174] fec 5b050000.ethernet eth0: registered PHC device
> > > 0
> > 
> > Sp there are only a "device registered" and "getting gpiod"
> > messages
> > and nor "gpiod found" and "resed found".
> > So now the question is why it didn't find the reset in dtb, or
> > where
> > to place it.
> > 
> > Andrej
> > 
> > > You might also need a post reset delay. I'm not sure the device
> > > will
> > > answer if it is still busy reading the EEPROM. Which is why the
> > > mv88e6xxx hardware reset does some polling before continuing.
> > > 
> > >           Andrew
> > 
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-02-08  8:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-02 15:18 DSA mv88e6xxx_probe Valek, Andrej
2023-02-02 16:05 ` Andrew Lunn
2023-02-02 17:57   ` Valek, Andrej
2023-02-02 18:10     ` Andrew Lunn
2023-02-03  8:07       ` Valek, Andrej
2023-02-03 13:54         ` Andrew Lunn
2023-02-03 14:47           ` Valek, Andrej
2023-02-06 14:50             ` Valek, Andrej
2023-02-08  8:20               ` Valek, Andrej

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.