Atheros 8035 PHY only works when at803x_config_init() is commented out
Subsystems (3)
Hello everyone,
I have a weird problem, that I've only started investigating, and I'd be grateful if anyone can help me along.
I have an ARM-based SoC that provides (AFAIU) an Atheros 8035 PHY.
If I enable the driver in my kernel (CONFIG_AT803X_PHY) then something goes wrong, and the system cannot load the nfsroot. Bizarrely, DHCP seems to work (so there is limited connectivity) but then the NFS server just times out.
However, if I just comment this line:
//.config_init = at803x_config_init,
in at803x_driver[0]
then everything seems to work. (At least, the system sets the PHY to Gbit, and manages to download the nfsroot.)
If I'm reading the code right (big "if"), when config_init is NULL, then phy_init_hw() turns into a NOP?
So either at803x_config_init() or something called from phy_init_hw() seems to be hosing this system's networking?
Sprinkling printk over phy_init_hw shows no errors (no premature exit) and phydev->drv->config_init(phydev) returns 0.
Maybe I didn't set something up correctly, and phy_write() is scribbling over the wrong register?
Does anyone see something I missed?
Regards.
Quoted 24 lines · Mason
Hello everyone,
I have a weird problem, that I've only started investigating, and I'd be grateful if anyone can help me along.
I have an ARM-based SoC that provides (AFAIU) an Atheros 8035 PHY.
If I enable the driver in my kernel (
CONFIG_AT803X_PHY) then something goes wrong, and the system cannot load the nfsroot. Bizarrely, DHCP seems to work (so there is limited connectivity) but then the NFS server just times out.However, if I just comment this line:
//.config_init = at803x_config_init,in at803x_driver[0]
then everything seems to work. (At least, the system sets the PHY to Gbit, and manages to download the nfsroot.)If I'm reading the code right (big "if"), when
config_initis NULL, thenphy_init_hw()turns into a NOP?So either
at803x_config_init()or something called fromphy_init_hw()seems to be hosing this system's networking?
Quoted 7 lines
Sprinkling printk over
phy_init_hwshows no errors (no premature exit) andphydev->drv->config_init(phydev)returns 0.Maybe I didn't set something up correctly, and
phy_write()is scribbling over the wrong register?Does anyone see something I missed?
So one possibility could be that the bootloader initializes the PHY in a certain way, typically by applying workarounds, and your config_init() callback is not restoring any of theses, which is why, after phy_init_hw(), which does a software reset of the PHY, all of these workarounds are wiped out, and your PHY behaves funky.
The reason why config_init() needs to put the PHY back into a fully functional state is because the PHY library should be able to software reset the PHY when it needs to, but also be able to deal with deep sleep modes etc.. where the PHY could loose its settings, yet the kernel should be able to bring you back in a good state.
An easy way to bypass that is to provide a soft_reset calback which does nothing, and see if calling either at803x_config_init(), or genphy_config_init() is sufficient to preserve the PHY settings. Although the real solution is to look at what the bootloader does on that front and replicate it in the config_init() callback.
Hope this helps.
Signature · 1 line
Florian
Quoted 45 lines · Florian Fainelli
Quoted 24 lines · Mason
Hello everyone,
I have a weird problem, that I've only started investigating, and I'd be grateful if anyone can help me along.
I have an ARM-based SoC that provides (AFAIU) an Atheros 8035 PHY.
If I enable the driver in my kernel (
CONFIG_AT803X_PHY) then something goes wrong, and the system cannot load the nfsroot. Bizarrely, DHCP seems to work (so there is limited connectivity) but then the NFS server just times out.However, if I just comment this line:
//.config_init = at803x_config_init,in at803x_driver[0]
then everything seems to work. (At least, the system sets the PHY to Gbit, and manages to download the nfsroot.)If I'm reading the code right (big "if"), when
config_initis NULL, thenphy_init_hw()turns into a NOP?So either
at803x_config_init()or something called fromphy_init_hw()seems to be hosing this system's networking?Quoted 7 lines
Sprinkling printk over
phy_init_hwshows no errors (no premature exit) andphydev->drv->config_init(phydev)returns 0.Maybe I didn't set something up correctly, and
phy_write()is scribbling over the wrong register?Does anyone see something I missed?
So one possibility could be that the bootloader initializes the PHY in a certain way, typically by applying workarounds, and your
config_init()callback is not restoring any of theses, which is why, afterphy_init_hw(), which does a software reset of the PHY, all of these workarounds are wiped out, and your PHY behaves funky.The reason why
config_init()needs to put the PHY back into a fully functional state is because the PHY library should be able to software reset the PHY when it needs to, but also be able to deal with deep sleep modes etc.. where the PHY could loose its settings, yet the kernel should be able to bring you back in a good state.
Quoted 7 lines
An easy way to bypass that is to provide a
soft_resetcalback which does nothing, and see if calling eitherat803x_config_init(), orgenphy_config_init()is sufficient to preserve the PHY settings. Although the real solution is to look at what the bootloader does on that front and replicate it in theconfig_init()callback.Hope this helps.
Thanks for the insight. I hadn't considered the bootloader's role.
One thing I forgot to mention is that I'm using an old kernel 3.14 and it doesn't seem to have the soft_reset function pointer.
http://lxr.free-electrons.com/source/drivers/net/phy/phy_device.c?v=3.14#L535
phy_init_hw() just calls phy_write(phydev, MII_BMCR, BMCR_RESET) and then phy_poll_reset(phydev) -- the equivalent of today's genphy_soft_reset().
Anyway, I will look more closely at the points you mentioned.
Thanks again.
Regards.
[ Problem with Atheros AR8035 PHY reset ]
Quoted 44 lines · Florian Fainelli
Quoted 22 lines · Mason
I have a weird problem, that I've only started investigating, and I'd be grateful if anyone can help me along.
I have an ARM-based SoC that provides (AFAIU) an Atheros 8035 PHY.
If I enable the driver in my kernel (
CONFIG_AT803X_PHY) then something goes wrong, and the system cannot load the nfsroot. Bizarrely, DHCP seems to work (so there is limited connectivity) but then the NFS server just times out.However, if I just comment this line:
//.config_init = at803x_config_init,in at803x_driver[0]
then everything seems to work. (At least, the system sets the PHY to Gbit, and manages to download the nfsroot.)If I'm reading the code right (big "if"), when
config_initis NULL, thenphy_init_hw()turns into a NOP?So either
at803x_config_init()or something called fromphy_init_hw()seems to be hosing this system's networking?Quoted 7 lines
Sprinkling printk over
phy_init_hwshows no errors (no premature exit) andphydev->drv->config_init(phydev)returns 0.Maybe I didn't set something up correctly, and
phy_write()is scribbling over the wrong register?Does anyone see something I missed?
So one possibility could be that the bootloader initializes the PHY in a certain way, typically by applying workarounds, and your
config_init()callback is not restoring any of theses, which is why, afterphy_init_hw(), which does a software reset of the PHY, all of these workarounds are wiped out, and your PHY behaves funky.The reason why
config_init()needs to put the PHY back into a fully functional state is because the PHY library should be able to software reset the PHY when it needs to, but also be able to deal with deep sleep modes etc.. where the PHY could loose its settings, yet the kernel should be able to bring you back in a good state.
Quoted 5 lines
An easy way to bypass that is to provide a
soft_resetcallback which does nothing, and see if calling eitherat803x_config_init(), orgenphy_config_init()is sufficient to preserve the PHY settings. Although the real solution is to look at what the bootloader does on that front and replicate it in theconfig_init()callback.
Here is the data sheet for the AR8035:
http://www.redeszone.net/app/uploads/2014/04/AR8035.pdf
It seems the problem comes from the fact that the PHY treats HW reset and SW reset differently:
HW reset: registers are set to specific values SW reset: some bits are retained across reset
Case in point: the control register (BMCR)
HW reset: BMCR = 0x3100
SW reset: retain bits[6,8,12,13] / other bits = 0
(0x3100 means bit_6=0, bit_8=bit_12=bit_13=1)
When we execute this line from genphy_soft_reset()
phy_write(phydev, MII_BMCR, BMCR_RESET);
we reset the bits in BMCR, and SW reset does not restore them.
It seems to me (please tell me if I am wrong) that it should be safe for all PHYs to write old_val | BMCR_RESET, instead of just BMCR_RESET. Thus...
On chips that REALLY reset, the old_val bits will be discarded; while on chips that retain some bits, we do want to keep them.
So the patch would go something like below. What do you think?
Regards
drivers/net/phy/phy_device.c +3 -2
@@ -1087,9 +1087,10 @@ static int gen10g_read_status(struct phy_device *phydev)*/ int genphy_soft_reset (struct phy_device *phydev) { -int ret; +int ret, val; - ret =phy_write (phydev,MII_BMCR ,BMCR_RESET ); + val =phy_read (phydev,MII_BMCR ); + ret =phy_write (phydev,MII_BMCR , val |BMCR_RESET );if (ret <0 )return ret;
Quoted 73 lines · Mason
[ Problem with Atheros AR8035 PHY reset ]
Quoted 44 lines · Florian Fainelli
Quoted 22 lines · Mason
I have a weird problem, that I've only started investigating, and I'd be grateful if anyone can help me along.
I have an ARM-based SoC that provides (AFAIU) an Atheros 8035 PHY.
If I enable the driver in my kernel (
CONFIG_AT803X_PHY) then something goes wrong, and the system cannot load the nfsroot. Bizarrely, DHCP seems to work (so there is limited connectivity) but then the NFS server just times out.However, if I just comment this line:
//.config_init = at803x_config_init,in at803x_driver[0]
then everything seems to work. (At least, the system sets the PHY to Gbit, and manages to download the nfsroot.)If I'm reading the code right (big "if"), when
config_initis NULL, thenphy_init_hw()turns into a NOP?So either
at803x_config_init()or something called fromphy_init_hw()seems to be hosing this system's networking?Quoted 7 lines
Sprinkling printk over
phy_init_hwshows no errors (no premature exit) andphydev->drv->config_init(phydev)returns 0.Maybe I didn't set something up correctly, and
phy_write()is scribbling over the wrong register?Does anyone see something I missed?
So one possibility could be that the bootloader initializes the PHY in a certain way, typically by applying workarounds, and your
config_init()callback is not restoring any of theses, which is why, afterphy_init_hw(), which does a software reset of the PHY, all of these workarounds are wiped out, and your PHY behaves funky.The reason why
config_init()needs to put the PHY back into a fully functional state is because the PHY library should be able to software reset the PHY when it needs to, but also be able to deal with deep sleep modes etc.. where the PHY could loose its settings, yet the kernel should be able to bring you back in a good state.Quoted 5 lines
An easy way to bypass that is to provide a
soft_resetcallback which does nothing, and see if calling eitherat803x_config_init(), orgenphy_config_init()is sufficient to preserve the PHY settings. Although the real solution is to look at what the bootloader does on that front and replicate it in theconfig_init()callback.Here is the data sheet for the AR8035:
http://www.redeszone.net/app/uploads/2014/04/AR8035.pdfIt seems the problem comes from the fact that the PHY treats HW reset and SW reset differently:
HW reset: registers are set to specific values SW reset: some bits are retained across reset
Case in point: the control register (BMCR)
HW reset: BMCR =0x3100
SW reset: retain bits[6,8,12,13] / other bits = 0(
0x3100means bit_6=0, bit_8=bit_12=bit_13=1)When we execute this line from
genphy_soft_reset()phy_write(phydev, MII_BMCR, BMCR_RESET);
Quoted 8 lines
we reset the bits in BMCR, and SW reset does not restore them.
It seems to me (please tell me if I am wrong) that it should be safe for all PHYs to write
old_val|BMCR_RESET, instead of justBMCR_RESET. Thus...On chips that REALLY reset, the
old_valbits will be discarded; while on chips that retain some bits, we do want to keep them.
I should add that all is not well, however.
If I set .config_init to NULL, it takes the system 4.5 seconds to boot. But if I leave .config_init set to at803x_config_init, then it takes 8.2 seconds to boot :-(
In 1) the link comes up at 1.66, we get an IP address at 4.2 In 2) the link comes up at 4.72, we get an IP address at 7.9
Looks like there are still mysteries to solve...
Regards.
Hi,
Quoted 40 lines · Mason
Quoted 12 lines · Florian Fainelli
So one possibility could be that the bootloader initializes the PHY in a certain way, typically by applying workarounds, and your
config_init()callback is not restoring any of theses, which is why, afterphy_init_hw(), which does a software reset of the PHY, all of these workarounds are wiped out, and your PHY behaves funky.The reason why
config_init()needs to put the PHY back into a fully functional state is because the PHY library should be able to software reset the PHY when it needs to, but also be able to deal with deep sleep modes etc.. where the PHY could loose its settings, yet the kernel should be able to bring you back in a good state.Quoted 5 lines
An easy way to bypass that is to provide a
soft_resetcallback which does nothing, and see if calling eitherat803x_config_init(), orgenphy_config_init()is sufficient to preserve the PHY settings. Although the real solution is to look at what the bootloader does on that front and replicate it in theconfig_init()callback.Here is the data sheet for the AR8035:
http://www.redeszone.net/app/uploads/2014/04/AR8035.pdfIt seems the problem comes from the fact that the PHY treats HW reset and SW reset differently:
HW reset: registers are set to specific values SW reset: some bits are retained across reset
Case in point: the control register (BMCR)
HW reset: BMCR =0x3100
SW reset: retain bits[6,8,12,13] / other bits = 0(
0x3100means bit_6=0, bit_8=bit_12=bit_13=1)When we execute this line from
genphy_soft_reset()phy_write(phydev, MII_BMCR, BMCR_RESET);we reset the bits in BMCR, and SW reset does not restore them.
Quoted 8 lines
It seems to me (please tell me if I am wrong) that it should be safe for all PHYs to write
old_val|BMCR_RESET, instead of justBMCR_RESET. Thus...On chips that REALLY reset, the
old_valbits will be discarded; while on chips that retain some bits, we do want to keep them.So the patch would go something like below. What do you think?
I don't think that'll work, because writing a 1 into the RESET bit of the register causes the PHY to enter its software reset routine immediately. The other bits should hence be reset to their defaults, regardless of what you set them to at the same time.
My suggestion is to dump the entire register set when at803x_config_init() is entered and again when it's left. Then try to find the differences and see if you can bring the PHY into the needed mode through the exisiting configuration hooks in the kernel.
Note that it really should be possible for the kernel to bring the PHY into the mode needed for your board. Relying on the bootloader to do the magic is fragile, and as Florian said, this will break once a suspend mode switches off the power domain that feeds the PHY.
Thanks,
Daniel
Hello,
Quoted 48 lines · Daniel Mack
Quoted 47 lines · Mason
Quoted 12 lines · Florian Fainelli
So one possibility could be that the bootloader initializes the PHY in a certain way, typically by applying workarounds, and your
config_init()callback is not restoring any of theses, which is why, afterphy_init_hw(), which does a software reset of the PHY, all of these workarounds are wiped out, and your PHY behaves funky.The reason why
config_init()needs to put the PHY back into a fully functional state is because the PHY library should be able to software reset the PHY when it needs to, but also be able to deal with deep sleep modes etc.. where the PHY could loose its settings, yet the kernel should be able to bring you back in a good state.Quoted 5 lines
An easy way to bypass that is to provide a
soft_resetcallback which does nothing, and see if calling eitherat803x_config_init(), orgenphy_config_init()is sufficient to preserve the PHY settings. Although the real solution is to look at what the bootloader does on that front and replicate it in theconfig_init()callback.Here is the data sheet for the AR8035:
http://www.redeszone.net/app/uploads/2014/04/AR8035.pdfIt seems the problem comes from the fact that the PHY treats HW reset and SW reset differently:
HW reset: registers are set to specific values SW reset: some bits are retained across reset
Case in point: the control register (BMCR)
HW reset: BMCR =0x3100
SW reset: retain bits[6,8,12,13] / other bits = 0(
0x3100means bit_6=0, bit_8=bit_12=bit_13=1)When we execute this line from
genphy_soft_reset()phy_write(phydev, MII_BMCR, BMCR_RESET);we reset the bits in BMCR, and SW reset does not restore them.
It seems to me (please tell me if I am wrong) that it should be safe for all PHYs to write
old_val|BMCR_RESET, instead of justBMCR_RESET. Thus...On chips that REALLY reset, the
old_valbits will be discarded; while on chips that retain some bits, we do want to keep them.
Quoted 6 lines
Quoted 1 line
So the patch would go something like below. What do you think?
I don't think that'll work, because writing a 1 into the RESET bit of the register causes the PHY to enter its software reset routine immediately. The other bits should hence be reset to their defaults, regardless of what you set them to at the same time.
I'm confused by your answer, because it seems to be ignoring the whole "some bits retain their value across SW reset" issue?
This can be settled quickly by an execution trace. (Note, I'm using kernel 3.14)
I have instrumented phy_init_hw thus:
(I've also added a printk after phy_poll_reset)
printk("BMCR = 0x%x\n", (unsigned)phy_read (phydev, MII_BMCR));
#if 0
val = phy_read (phydev, MII_BMCR);
ret = phy_write(phydev, MII_BMCR, val | BMCR_RESET);
#else
ret = phy_write(phydev, MII_BMCR, BMCR_RESET);
#endif
printk("BMCR = 0x%x\n", (unsigned)phy_read (phydev, MII_BMCR));Running the #else branch outputs:
[ 0.623188] BMCR = 0x3100 [ 0.625957] BMCR = 0x0 [ 0.686817] BMCR = 0x0
Running the #if branch outputs:
[ 0.623151] BMCR = 0x3100 [ 0.625979] BMCR = 0x3100 [ 0.686817] BMCR = 0x3100
As you can see, writing val | BMCR_RESET is required on this PHY.
Quoted 4 lines
My suggestion is to dump the entire register set when
at803x_config_init()is entered and again when it's left. Then try to find the differences and see if you can bring the PHY into the needed mode through the existing configuration hooks in the kernel.
Good idea.
[ 0.685330] IDX= 1 796d != 7949 [ 0.688490] IDX= 5 c1e1 != 0000 [ 0.691647] IDX= 6 000f != 0004 [ 0.694803] IDX=10 3800 != 0000 [ 0.697960] IDX=17 bc10 != 0012 [ 0.701115] IDX=19 7400 != 0000 [ 0.704271] IDX=27 060e != 0600
Hmmm, didn't expect so many differences. I'll have to take a closer look.
Quoted 4 lines
Note that it really should be possible for the kernel to bring the PHY into the mode needed for your board. Relying on the bootloader to do the magic is fragile, and as Florian said, this will break once a suspend mode switches off the power domain that feeds the PHY.
Uboot dev boards, uboot runs (and uboot speaks Ethernet). I don't know if uboot tweaks the PHY. But on production boards, there is no uboot, and the early bootloaders don't touch the PHY.
Regards.
Quoted 15 lines · Mason
Quoted 4 lines · Daniel Mack
My suggestion is to dump the entire register set when
at803x_config_init()is entered and again when it's left. Then try to find the differences and see if you can bring the PHY into the needed mode through the existing configuration hooks in the kernel.[ 0.685330] IDX= 1 796d != 7949 [ 0.688490] IDX= 5 c1e1 != 0000 [ 0.691647] IDX= 6 000f != 0004 [ 0.694803] IDX=10 3800 != 0000 [ 0.697960] IDX=17 bc10 != 0012 [ 0.701115] IDX=19 7400 != 0000 [ 0.704271] IDX=27 060e != 0600
Quoted 1 line
Hmmm, didn't expect so many differences. I'll have to take a closer look.
For the record, I dumped the PHY registers
A) upon entering phy_init_hw
B) before leaving phy_init_hw (thus right after at803x_config_init)
IDX 1: b2 LINK STATUS, b5 AUTO-NEGOTIATION COMPLETE => Difference in status bits, seems reasonable
IDX 5: Link partner ability (base page)
=> seems reasonable (no partner yet?)
IDX 6: Auto-Negotiation Expansion
=> seems reasonable (no partner yet?)
IDX 10: 1000 BASE-T Status (HW reset = SW reset = 0)
(ALSO: Contents of this register clear after a read operation has occurred.) => Looks like my own read cleared it
IDX 17: PHY-Specific Status
b1 = "POLARITY (real time)"?
=> Difference in status bits, seems reasonable? (
IDX 19: Interrupt Status
=> Looks like some interrupt requests might have been discarded?
IDX 27: This register is undocumented
Nothing looks suspicious, except maybe the Interrupt Status?
Is speed auto-negotiation supposed to be complete when phy_init_hw exits?
Regards.
Quoted 21 lines · Mason
For the record, I dumped the PHY registers
A) upon enteringphy_init_hw
B) before leavingphy_init_hw(thus right afterat803x_config_init)IDX 1: b2 LINK STATUS, b5 AUTO-NEGOTIATION COMPLETE => Difference in status bits, seems reasonable
IDX 5: Link partner ability (base page)
=> seems reasonable (no partner yet?)IDX 6: Auto-Negotiation Expansion
=> seems reasonable (no partner yet?)IDX 10: 1000 BASE-T Status (HW reset = SW reset = 0)
(ALSO: Contents of this register clear after a read operation has occurred.) => Looks like my own read cleared itIDX 17: PHY-Specific Status
b1 = "POLARITY (real time)"?
=> Difference in status bits, seems reasonable? (
Quoted 6 lines
IDX 19: Interrupt Status
=> Looks like some interrupt requests might have been discarded?IDX 27: This register is undocumented
Nothing looks suspicious, except maybe the Interrupt Status?
What about the debug registers, such as the one that configures the RGMII TX/RX clock delay (4.2.25, 4.2.26). These are indirectly addressed, see at803x_config_init().
Daniel
Quoted 3 lines · Daniel Mack
What about the debug registers, such as the one that configures the RGMII TX/RX clock delay (4.2.25, 4.2.26). These are indirectly addressed, see
at803x_config_init().
My dump code:
void mydump(struct phy_device *phydev, int *foo, int *bar)
{
int i;
for (i = 0; i < 32; ++i) foo[i] = phy_read(phydev, i);
for (i = 0; i < 20; ++i) {
phy_write(phydev, 0x1d, i);
mdelay(1);
bar[i] = phy_read(phydev, 0x1e);
}
}[ 0.738528] IDX=0x01 796d != 7949 [ 0.741860] IDX=0x05 c1e1 != 0000 [ 0.745191] IDX=0x06 000f != 0004 [ 0.748521] IDX=0x0a 3800 != 0000 [ 0.751851] IDX=0x11 bc10 != 0012 [ 0.755182] IDX=0x13 7400 != 0000 [ 0.758513] IDX=0x1b 060e != 0600 [ 0.761842] DEBUG REGS [ 0.764211] IDX=0x01 ffd0 != 0032 [ 0.767542] IDX=0x02 3f0f != 3110 [ 0.770872] IDX=0x03 3fff != 3f00 [ 0.774203] IDX=0x0c 0800 != 1801 [ 0.777533] IDX=0x0d 0100 != 0000 [ 0.780863] IDX=0x0e 0023 != 0040
Differences in debug registers only occur in undocumented registers. (Only 0x00, 0x05, 0x10, 0x11, 0x12 are documented.)
Regards.
Quoted 41 lines · Mason
Quoted 15 lines · Mason
Quoted 4 lines · Daniel Mack
My suggestion is to dump the entire register set when
at803x_config_init()is entered and again when it's left. Then try to find the differences and see if you can bring the PHY into the needed mode through the existing configuration hooks in the kernel.[ 0.685330] IDX= 1 796d != 7949 [ 0.688490] IDX= 5 c1e1 != 0000 [ 0.691647] IDX= 6 000f != 0004 [ 0.694803] IDX=10 3800 != 0000 [ 0.697960] IDX=17 bc10 != 0012 [ 0.701115] IDX=19 7400 != 0000 [ 0.704271] IDX=27 060e != 0600Quoted 1 line
Hmmm, didn't expect so many differences. I'll have to take a closer look.
For the record, I dumped the PHY registers
A) upon enteringphy_init_hw
B) before leavingphy_init_hw(thus right afterat803x_config_init)IDX 1: b2 LINK STATUS, b5 AUTO-NEGOTIATION COMPLETE => Difference in status bits, seems reasonable
IDX 5: Link partner ability (base page)
=> seems reasonable (no partner yet?)IDX 6: Auto-Negotiation Expansion
=> seems reasonable (no partner yet?)IDX 10: 1000 BASE-T Status (HW reset = SW reset = 0) (ALSO: Contents of this register clear after a read operation has occurred.)
=> Looks like my own read cleared itIDX 17: PHY-Specific Status
b1 = "POLARITY (real time)"?
=> Difference in status bits, seems reasonable? (
Quoted 8 lines
IDX 19: Interrupt Status
=> Looks like some interrupt requests might have been discarded?IDX 27: This register is undocumented
Nothing looks suspicious, except maybe the Interrupt Status?
Is speed auto-negotiation supposed to be complete when
phy_init_hwexits?
There is no such guarantee, and the PHY state machine is started later, which will take care of auto-neg and other things.
Signature · 1 line
Florian
Quoted 6 lines · Florian Fainelli
Quoted 1 line · Mason
Is speed auto-negotiation supposed to be complete when
phy_init_hwexits?There is no such guarantee, and the PHY state machine is started later, which will take care of auto-neg and other things.
That's what I thought.
So it's expected that many status bits will only change later.
You didn't comment on my patch. What's your take on it?
Regards.
Quoted 6 lines · Mason
Quoted 4 lines · Florian Fainelli
Quoted 1 line · Mason
Is speed auto-negotiation supposed to be complete when
phy_init_hwexits?
Quoted 8 lines
Quoted 2 lines
There is no such guarantee, and the PHY state machine is started later, which will take care of auto-neg and other things.
That's what I thought.
So it's expected that many status bits will only change later.
You didn't comment on my patch. What's your take on it?
Quoting IEEE 802.3 section 2, paragprah 22.2.4.1:
"Resetting a PHY is accomplished by setting bit 0.15 to a logic one. This action shall set the status and con-trol registers to their default states. As a consequence this action may change the internal state of the PHY
and the state of the physical link associated with the PHY. This bit is self-clearing, and a PHY shall return a
value of one in bit 0.15 until the reset process is completed. A PHY is not required to accept a write transac-
tion to the control register until the reset process is completed, and writes to bits of the control register other
than 0.15 may have no effect until the reset process is completed. The reset process shall be completed
within 0.5 s from the setting of bit 0.15.
"
So even though this is not extremely specific about whether or not doing a RMW instead of W is accepted, considering that this resets the PHY internal state, and the fact that there is a lack of clarify on whether setting any bits other than 15 is going to fall under the "A PHY is not required to accept a write transaction to the control register until the reset process is completed" statement, setting only this bit at least guarantees that you are back into your reset defaults.
As Daniel suggested, I would be looking for undocumented/proprietary registers for reasons as to why your PHY is not working, in particular (RG)MII tuning.
Signature · 1 line
Florian
Quoted 38 lines · Florian Fainelli
Quoted 6 lines · Mason
Quoted 4 lines · Florian Fainelli
Quoted 1 line · Mason
Is speed auto-negotiation supposed to be complete when
phy_init_hwexits?Quoted 8 lines
Quoted 2 lines
There is no such guarantee, and the PHY state machine is started later, which will take care of auto-neg and other things.
That's what I thought.
So it's expected that many status bits will only change later.
You didn't comment on my patch. What's your take on it?
Quoting IEEE 802.3 section 2, paragraph 22.2.4.1:
"Resetting a PHY is accomplished by setting bit 0.15 to a logic one. This action shall set the status and control registers to their default states. As a consequence this action may change the internal state of the PHY and the state of the physical link associated with the PHY. This bit is self-clearing, and a PHY shall return a value of one in bit 0.15 until the reset process is completed. A PHY is not required to accept a write transaction to the control register until the reset process is completed, and writes to bits of the control register other than 0.15 may have no effect until the reset process is completed. The reset process shall be completed within 0.5 s from the setting of bit 0.15"
So even though this is not extremely specific about whether or not doing a RMW instead of W is accepted, considering that this resets the PHY internal state, and the fact that there is a lack of clarify on whether setting any bits other than 15 is going to fall under the "A PHY is not required to accept a write transaction to the control register until the reset process is completed" statement, setting only this bit at least guarantees that you are back into your reset defaults.
Quoted 3 lines
As Daniel suggested, I would be looking for undocumented/proprietary registers for reasons as to why your PHY is not working, in particular (RG)MII tuning.
Am I the only having problems with the AR8035? :-(
The standard driver works for everyone but me?
Did you take a look at the data sheet? Do you understand the difference between "Hardware Reset" and "Software Reset"?
Maybe on my PHY, writing BMCR_RESET to BMCR triggers a SW reset, while it triggers a HW reset on other boards?
Would that be possible?
Also, why do you say the PHY is not working? When I apply the patch I proposed, it doesn't malfunction.
Regards.
Quoted 43 lines · Mason
Quoted 38 lines · Florian Fainelli
Quoted 6 lines · Mason
Quoted 4 lines · Florian Fainelli
Quoted 1 line · Mason
Is speed auto-negotiation supposed to be complete when
phy_init_hwexits?Quoted 8 lines
Quoted 2 lines
There is no such guarantee, and the PHY state machine is started later, which will take care of auto-neg and other things.
That's what I thought.
So it's expected that many status bits will only change later.
You didn't comment on my patch. What's your take on it?
Quoting IEEE 802.3 section 2, paragraph 22.2.4.1:
"Resetting a PHY is accomplished by setting bit 0.15 to a logic one. This action shall set the status and control registers to their default states. As a consequence this action may change the internal state of the PHY and the state of the physical link associated with the PHY. This bit is self-clearing, and a PHY shall return a value of one in bit 0.15 until the reset process is completed. A PHY is not required to accept a write transaction to the control register until the reset process is completed, and writes to bits of the control register other than 0.15 may have no effect until the reset process is completed. The reset process shall be completed within 0.5 s from the setting of bit 0.15"
So even though this is not extremely specific about whether or not doing a RMW instead of W is accepted, considering that this resets the PHY internal state, and the fact that there is a lack of clarify on whether setting any bits other than 15 is going to fall under the "A PHY is not required to accept a write transaction to the control register until the reset process is completed" statement, setting only this bit at least guarantees that you are back into your reset defaults.
Quoted 3 lines
As Daniel suggested, I would be looking for undocumented/proprietary registers for reasons as to why your PHY is not working, in particular (RG)MII tuning.
Quoted 6 lines
Am I the only having problems with the AR8035? :-(
The standard driver works for everyone but me?
Did you take a look at the data sheet? Do you understand the difference between "Hardware Reset" and "Software Reset"?
I did not.
Quoted 5 lines
Maybe on my PHY, writing
BMCR_RESETto BMCR triggers a SW reset, while it triggers a HW reset on other boards?Would that be possible?
Possible, but certainly non-compliant behavior, in which case you would want to override the soft_reset() callback.
Quoted 3 lines
Also, why do you say the PHY is not working? When I apply the patch I proposed, it doesn't malfunction.
There are no BMCR registers that would affect directly the passing of unicast or broadcast traffic with distinction, which is how you originally reported the problem, or maybe that was a bad description of the issue?
Have you checked the Ethernet MAC MIB counters to see if there are any errors reported differently from the working case to the non-working case? What about your link partner, what does it looks like on its end when it does not work?
Signature · 1 line
Florian
Quoted 28 lines · Florian Fainelli
Quoted 27 lines · Mason
Quoted 25 lines · Florian Fainelli
Quoting IEEE 802.3 section 2, paragraph 22.2.4.1:
"Resetting a PHY is accomplished by setting bit 0.15 to a logic one. This action shall set the status and control registers to their default states. As a consequence this action may change the internal state of the PHY and the state of the physical link associated with the PHY. This bit is self-clearing, and a PHY shall return a value of one in bit 0.15 until the reset process is completed. A PHY is not required to accept a write transaction to the control register until the reset process is completed, and writes to bits of the control register other than 0.15 may have no effect until the reset process is completed. The reset process shall be completed within 0.5 s from the setting of bit 0.15"
So even though this is not extremely specific about whether or not doing a RMW instead of W is accepted, considering that this resets the PHY internal state, and the fact that there is a lack of clarify on whether setting any bits other than 15 is going to fall under the "A PHY is not required to accept a write transaction to the control register until the reset process is completed" statement, setting only this bit at least guarantees that you are back into your reset defaults.
As Daniel suggested, I would be looking for undocumented/proprietary registers for reasons as to why your PHY is not working, in particular (RG)MII tuning.
Quoted 8 lines
Quoted 6 lines
Am I the only having problems with the AR8035? :-(
The standard driver works for everyone but me?
Did you take a look at the data sheet? Do you understand the difference between "Hardware Reset" and "Software Reset"?
I did not.
If I understand your quote from the standard correctly, then the behavior documented in the data sheet looks very non-compliant to my untrained eye.
Quoted 7 lines
Quoted 2 lines
Also, why do you say the PHY is not working? When I apply the patch I proposed, it doesn't malfunction.
There are no BMCR registers that would affect directly the passing of unicast or broadcast traffic with distinction, which is how you originally reported the problem, or maybe that was a bad description of the issue?
I didn't say anything about unicast vs broadcast.
When I run the unpatched code, it looks like the PHY negotiates only 10 Mbps Half-duplex, then DHCP appears to succeed (IIUC only the very first packets are broadcast), and then the system hangs trying to mount the root filesystem over NFS.
I actually left it running over lunch break, and according to the kernel's time stamps, the system seems to have managed to mount the root file system after 2000+ seconds.
Quoted 4 lines
Have you checked the Ethernet MAC MIB counters to see if there are any errors reported differently from the working case to the non-working case? What about your link partner, what does it looks like on its end when it does not work?
Should I use ethtool for this?
Or do it directly with kernel code? (If so which API?)
The catch is that I need the network to get a running system. No network, no root file system.
Maybe I need to write the kernel to non-volatile storage.
Going on a wild goose hunt...
Somewhat related discussion
https://community.freescale.com/thread/289362
Let me check how u-boot handles the AR8035.
http://git.denx.de/?p=u-boot.git;a=blob;f=drivers/net/phy/atheros.c
static int ar8035_config(struct phy_device *phydev)
{
int regval;
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018));
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100));
phydev->supported = phydev->drv->features;
return 0;
}Data sheet states:
Register 0xd = "MMD Access Control".
Register 0xe = "MMD Access Control Data".
MMD register access:
See detail in register description
example: Write 0x8000 to Register 0 of MMD3
1. Write 0x3 to register 0xD:
0xD=0x0003;(function= address; set the device address)
2. Write 0x0 to register 0xE: 0xE=0x0; (set the register offset address)
3. Write 0x4003 to register
0xD:0xD=0x4003;(function=data; keep the device address)
4. Read register 0xE:0xE==(data from register 0x0 of MMD3)
5. Write 0x8000 to register 0xE
:0xE=0x8000(write 0x8000 to register 0x0 of MMD3)
Please Note:Read operation please refers to process 1 ~ 4
Important note:CLK_25M default outputs 25MHz, can be configured to 50MHz, 62.5MHz, or 125MHz by register MMD7 8016[4:3].
Ah yes, there it is on page 58:
Device address = 7, address offset = 0x8016 (Hex)
4:3 Select_clk125mCLK_25M output clock select
00=25M
01=50M
10=62.5M
11=125M
So...
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007); phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018));
R[0xd] = 0x0007 ; select MMD7 R[0xe] = 0x8016 ; offset 0x8016, so R[0xd] = 0x4007 ; select "data, no post increment" for MMD7
then we read the current value of MMD7/offset=0x8016 and set bits 3 and 4 on top of that => 125 MHz clock
HW reset val = 0
SW reset val = retain previous value
so the reset in Linux shouldn't affect this...
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100));
set debug port offset to 5 (DR5)
read current value
set bit 8 (rgmii_tx_clk_dly)
Rgmii tx clock delay control bit:
1 = rgmii tx clock delay enable
0 = rgmii tx clock delay disable.
AFAICT, the Linux code doesn't RMW, it just blindly writes AT803X_DEBUG_RGMII_TX_CLK_DLY. Dunno if it makes any difference...
Meh, I'm still grasping at straws...
Regards.
Quoted 50 lines · Mason
Quoted 28 lines · Florian Fainelli
Quoted 27 lines · Mason
Quoted 25 lines · Florian Fainelli
Quoting IEEE 802.3 section 2, paragraph 22.2.4.1:
"Resetting a PHY is accomplished by setting bit 0.15 to a logic one. This action shall set the status and control registers to their default states. As a consequence this action may change the internal state of the PHY and the state of the physical link associated with the PHY. This bit is self-clearing, and a PHY shall return a value of one in bit 0.15 until the reset process is completed. A PHY is not required to accept a write transaction to the control register until the reset process is completed, and writes to bits of the control register other than 0.15 may have no effect until the reset process is completed. The reset process shall be completed within 0.5 s from the setting of bit 0.15"
So even though this is not extremely specific about whether or not doing a RMW instead of W is accepted, considering that this resets the PHY internal state, and the fact that there is a lack of clarify on whether setting any bits other than 15 is going to fall under the "A PHY is not required to accept a write transaction to the control register until the reset process is completed" statement, setting only this bit at least guarantees that you are back into your reset defaults.
As Daniel suggested, I would be looking for undocumented/proprietary registers for reasons as to why your PHY is not working, in particular (RG)MII tuning.
Quoted 8 lines
Quoted 6 lines
Am I the only having problems with the AR8035? :-(
The standard driver works for everyone but me?
Did you take a look at the data sheet? Do you understand the difference between "Hardware Reset" and "Software Reset"?
I did not.
If I understand your quote from the standard correctly, then the behavior documented in the data sheet looks very non-compliant to my untrained eye.
Quoted 7 lines
Quoted 2 lines
Also, why do you say the PHY is not working? When I apply the patch I proposed, it doesn't malfunction.
There are no BMCR registers that would affect directly the passing of unicast or broadcast traffic with distinction, which is how you originally reported the problem, or maybe that was a bad description of the issue?
Quoted 6 lines
I didn't say anything about unicast vs broadcast.
When I run the unpatched code, it looks like the PHY negotiates only 10 Mbps Half-duplex, then DHCP appears to succeed (IIUC only the very first packets are broadcast), and then the system hangs trying to mount the root filesystem over NFS.
So maybe you can make sure that your driver properly advertises all the supported modes by your PHY, for instance, drivers/net/phy/bcm7xxx.c calls genphy_config_aneg() to make sure that all modes are advertised (the PHY does not advertise half-duplex modes by default).
Quoted 4 lines
I actually left it running over lunch break, and according to the kernel's time stamps, the system seems to have managed to mount the root file system after 2000+ seconds.
Ah, so it's doing something after all.
Quoted 7 lines
Quoted 5 lines
Have you checked the Ethernet MAC MIB counters to see if there are any errors reported differently from the working case to the non-working case? What about your link partner, what does it looks like on its end when it does not work?
Should I use ethtool for this?
Yes. Which might be difficult since you depend on networking to mount your rootfs, you should probably use an initramfs so you need NFS root to work.
Quoted 105 lines
Or do it directly with kernel code? (If so which API?)
The catch is that I need the network to get a running system. No network, no root file system.
Maybe I need to write the kernel to non-volatile storage.
Going on a wild goose hunt...
Somewhat related discussion
https://community.freescale.com/thread/289362Let me check how u-boot handles the AR8035.
http://git.denx.de/?p=u-boot.git;a=blob;f=drivers/net/phy/atheros.cstatic int
ar8035_config(struct phy_device *phydev){ int regval; phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007); phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018)); phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100)); phydev->supported = phydev->drv->features; return 0; }Data sheet states:
Register0xd= "MMD Access Control".
Register0xe= "MMD Access Control Data".MMD register access:
See detail in register description
example: Write0x8000to Register 0 of MMD3
1. Write0x3to register0xD:
0xD=0x0003;(function= address; set the device address)
2. Write0x0to register0xE: 0xE=0x0; (set the register offset address)
3. Write0x4003to register
0xD:0xD=0x4003;(function=data; keep the device address)
4. Read register 0xE:0xE==(data from register0x0of MMD3)
5. Write0x8000to register0xE
:0xE=0x8000(write0x8000to register0x0of MMD3)
Please Note:Read operation please refers to process 1 ~ 4Important note:
CLK_25Mdefault outputs 25MHz, can be configured to 50MHz, 62.5MHz, or 125MHz by register MMD7 8016[4:3].Ah yes, there it is on page 58:
Device address = 7, address offset =0x8016(Hex)
4:3Select_clk125mCLK_25Moutput clock select
00=25M
01=50M
10=62.5M
11=125MSo...
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007); phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018));R[0xd] = 0x0007 ; select MMD7 R[0xe] = 0x8016 ; offset 0x8016, so R[0xd] = 0x4007 ; select "data, no post increment" for MMD7then we read the current value of MMD7/offset=0x8016 and set bits 3 and 4 on top of that => 125 MHz clock
HW reset val = 0
SW reset val = retain previous value
so the reset in Linux shouldn't affect this...phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100));set debug port offset to 5 (DR5)
read current value
set bit 8 (rgmii_tx_clk_dly)Rgmii tx clock delay control bit:
1 = rgmii tx clock delay enable
0 = rgmii tx clock delay disable.AFAICT, the Linux code doesn't RMW, it just blindly writes
AT803X_DEBUG_RGMII_TX_CLK_DLY. Dunno if it makes any difference...Meh, I'm still grasping at straws...
Regards.
Signature · 1 line
Florian
Quoted 3 lines · Mason
Am I the only having problems with the AR8035? :-(
The standard driver works for everyone but me?
Works well on a imx6q-hummingboard:
fec 2188000.ethernet eth0: Freescale FEC PHY driver [Atheros 8035 ethernet] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
Regards,
Fabio Estevam
Quoted 10 lines · Fabio Estevam
Quoted 3 lines · Mason
Am I the only having problems with the AR8035? :-(
The standard driver works for everyone but me?
Works well on a imx6q-hummingboard:
fec 2188000.ethernet eth0: Freescale FEC PHY driver [Atheros 8035 ethernet] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
Forgot to point out that we also have a 8035 fixup in arch/arm/mach-imx/mach-imx6q.c. Search for ar8035_phy_fixup().
Regards,
Fabio Estevam
Quoted 11 lines · Fabio Estevam
Quoted 10 lines · Fabio Estevam
Quoted 3 lines · Mason
Am I the only having problems with the AR8035? :-(
The standard driver works for everyone but me?
Works well on a imx6q-hummingboard:
fec 2188000.ethernet eth0: Freescale FEC PHY driver [Atheros 8035 ethernet] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
Could you tell me the value of BMCR on entry and exit of phy_init_hw?
Quoted 2 lines
Forgot to point out that we also have a 8035 fixup in
arch/arm/mach-imx/mach-imx6q.c. Search forar8035_phy_fixup().
Thanks for the pointer.
Freescale's ar8031_phy_fixup() is almost the same as U-boot's ar8035_config() The only difference is one extra sanitizing instruction: val &= 0xffe3;
What's the point of masking bits 3 and 4, when they are set by the next instruction:
val &= 0xffe3; val |= 0x18;
The result of these two operations is
bit2=0 bit3=1 bit4=1 other=unchanged
Bit 2 is undocumented, why does Freescale set it to 0?
The tx clock delay is already done in the generic driver. Do you know why it is necessary? Why not rx clock delay also?
I'll give the "disable SmartEEE" fixup a try.
Not sure why they reset the POWER_DOWN bit? It's cleared by both HW and SW resets.
Regards.
On 04/09/2015 09:30 PM, Mason wrote:> Am I the only having problems with the AR8035? :-(
Quoted 2 lines
The standard driver works for everyone but me?
A company I used to work with ships various hardware models in quantities which features this chip, and they're using the unpatched mainline kernel version of the driver.
Quoted 2 lines
Did you take a look at the data sheet? Do you understand the difference between "Hardware Reset" and "Software Reset"?
I did, most notably because I was desperately trying to find a sane way to conduct a full reset of the PHY to work around a confirmed bug in the DIE of the chip which causes the internal state machine to lock up on link loss under certain conditions.
Unfortunately, I failed to find a way to really put the chip into complete reset state through the registers. Instead, I added a possibility to let the driver pull the hardware reset (see 13a56b4493).
Other than that, however, I didn't encounter any problems.
Quoted 2 lines
Maybe on my PHY, writing
BMCR_RESETto BMCR triggers a SW reset, while it triggers a HW reset on other boards?
AFAIK, the chip does not do this, no. But even if it did,
Quoted 2 lines
Also, why do you say the PHY is not working? When I apply the patch I proposed, it doesn't malfunction.
You're referring to the one that removes the phy init routine?
I'd still go and check if there's anything in one of the chained bootloaders that does some magic. One other thing that might give you a hint is to manually pull the RESET line low for a short time right when the kernel decompressor is started. That way, the kernel has to deal with a device that has just seen a hardware reset. Just see if that makes any difference.
Also, some delays in between the register writes during initialization might also be worth a try. But that's all just random guessing right now, sorry.
Daniel
Quoted 8 lines · Daniel Mack
Quoted 2 lines · Mason
Am I the only having problems with the AR8035? :-( The standard driver works for everyone but me?
A company I used to work with ships various hardware models in quantities which features this chip, and they're using the unpatched mainline kernel version of the driver.
It seems something was done differently on my SoC. I'll keep looking.
Quoted 8 lines
Quoted 2 lines
Did you take a look at the data sheet? Do you understand the difference between "Hardware Reset" and "Software Reset"?
I did, most notably because I was desperately trying to find a sane way to conduct a full reset of the PHY to work around a confirmed bug in the DIE of the chip which causes the internal state machine to lock up on link loss under certain conditions.
Quoted 5 lines
Unfortunately, I failed to find a way to really put the chip into complete reset state through the registers. Instead, I added a possibility to let the driver pull the hardware reset (see
13a56b4493).Other than that, however, I didn't encounter any problems.
I wonder what value the CONTROL register was set to on your SoC after a SW reset. Maybe the "retain value" jiggery-pokery is just a red herring.
Quoted 4 lines
Quoted 2 lines
Maybe on my PHY, writing
BMCR_RESETto BMCR triggers a SW reset, while it triggers a HW reset on other boards?AFAIK, the chip does not do this, no. But even if it did,
Did you forget to finish that sentence? :-)
Quoted 4 lines
Quoted 2 lines
Also, why do you say the PHY is not working? When I apply the patch I proposed, it doesn't malfunction.
You're referring to the one that removes the phy init routine?
No, the RMW of the CONTROL register for when triggering reset.
Quoted 6 lines
I'd still go and check if there's anything in one of the chained bootloaders that does some magic. One other thing that might give you a hint is to manually pull the RESET line low for a short time right when the kernel decompressor is started. That way, the kernel has to deal with a device that has just seen a hardware reset. Just see if that makes any difference.
I'd force a HW reset by jiggling the appropriate GPIO pin? Like you did in the at803x.c driver?
Quoted 3 lines
Also, some delays in between the register writes during initialization might also be worth a try. But that's all just random guessing right now, sorry.
Thanks for your help, by the way (and Fabio too).
Regards.
Quoted 5 lines · Mason
Quoted 3 lines · Daniel Mack
A company I used to work with ships various hardware models in quantities which features this chip, and they're using the unpatched mainline kernel version of the driver.
Meh. I just double-checked the references again and figured the final verions of the hardware design featured a 8030 model, not 8035. Sorry for that.
So there might be a difference, and maybe the 8035 needs special treatment. Then again, Fabio said he has a 8035 working.
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
Maybe on my PHY, writing
BMCR_RESETto BMCR triggers a SW reset, while it triggers a HW reset on other boards?AFAIK, the chip does not do this, no. But even if it did,
Did you forget to finish that sentence? :-)
Even if it did, the kernel driver should still be able to set up the device just fine.
Quoted 9 lines
Quoted 6 lines
I'd still go and check if there's anything in one of the chained bootloaders that does some magic. One other thing that might give you a hint is to manually pull the RESET line low for a short time right when the kernel decompressor is started. That way, the kernel has to deal with a device that has just seen a hardware reset. Just see if that makes any difference.
I'd force a HW reset by jiggling the appropriate GPIO pin? Like you did in the
at803x.cdriver?
Yes. But that's just to gain more ideas where to look for, and possibly find a pattern.
Daniel
Quoted 30 lines · Daniel Mack
Quoted 28 lines · Mason
Here is the data sheet for the AR8035:
http://www.redeszone.net/app/uploads/2014/04/AR8035.pdfIt seems the problem comes from the fact that the PHY treats HW reset and SW reset differently:
HW reset: registers are set to specific values SW reset: some bits are retained across reset
Case in point: the control register (BMCR)
HW reset: BMCR =0x3100
SW reset: retain bits[6,8,12,13] / other bits = 0(
0x3100means bit_6=0, bit_8=bit_12=bit_13=1)When we execute this line from
genphy_soft_reset()phy_write(phydev, MII_BMCR, BMCR_RESET);we reset the bits in BMCR, and SW reset does not restore them.
It seems to me (please tell me if I am wrong) that it should be safe for all PHYs to write
old_val|BMCR_RESET, instead of justBMCR_RESET. Thus...On chips that REALLY reset, the
old_valbits will be discarded; while on chips that retain some bits, we do want to keep them.
Quoted 6 lines
Quoted 1 line
So the patch would go something like below. What do you think?
I don't think that'll work, because writing a 1 into the RESET bit of the register causes the PHY to enter its software reset routine immediately. The other bits should hence be reset to their defaults, regardless of what you set them to at the same time.
I forgot to ask:
(I presume you have a system with an AR8035.)
When the PHY is reset, you don't see the odd behavior I get?
Can you print the value of BMCR, before and after
phy_write(phydev, MII_BMCR, BMCR_RESET);
Regards.