From: Michael Walle <hidden> Date: 2021-02-10 21:09:29
Cleanup the PHY drivers for IPplus devices and add PHY counters and MDIX
support for the IP101A/G.
Patch 5 adds a model detection based on the behavior of the PHY.
Unfortunately, the IP101A shares the PHY ID with the IP101G. But the latter
provides more features. Try to detect the newer model by accessing the page
selection register. If it is writeable, it is assumed, that it is a IP101G.
With this detection in place, we can now access registers >= 16 in a
correct way on the IP101G; that is by first selecting the correct page.
This might previouly worked, because no one ever set another active page
before booting linux.
The last two patches add the new features.
Michael Walle (9):
net: phy: icplus: use PHY_ID_MATCH_MODEL() macro
net: phy: icplus: use PHY_ID_MATCH_EXACT() for IP101A/G
net: phy: icplus: drop address operator for functions
net: phy: icplus: use the .soft_reset() of the phy-core
net: phy: icplus: split IP101A/G driver
net: phy: icplus: don't set APS_EN bit on IP101G
net: phy: icplus: fix paged register access
net: phy: icplus: add PHY counter for IP101G
net: phy: icplus: add MDI/MDIX support for IP101A/G
drivers/net/phy/icplus.c | 378 ++++++++++++++++++++++++++++++++-------
1 file changed, 317 insertions(+), 61 deletions(-)
--
2.20.1
From: Michael Walle <hidden> Date: 2021-02-10 21:09:46
Simpify the initializations of the structures. There is no functional
change.
Signed-off-by: Michael Walle <redacted>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Changes since v2:
- none
Changes since v1:
- none
drivers/net/phy/icplus.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
From: Michael Walle <hidden> Date: 2021-02-10 21:10:26
According to the datasheet of the IP101A/G there is no revision field
and MII_PHYSID2 always reads as 0x0c54. Use PHY_ID_MATCH_EXACT() then.
Signed-off-by: Michael Walle <redacted>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Changes since v2:
- none
Changes since v1:
- none
drivers/net/phy/icplus.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Michael Walle <hidden> Date: 2021-02-10 21:11:16
Don't sometimes use the address operator and sometimes not. Drop it and
make the code look uniform.
Signed-off-by: Michael Walle <redacted>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Changes since v2:
- none
Changes since v1:
- none
drivers/net/phy/icplus.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
From: Michael Walle <hidden> Date: 2021-02-10 21:11:46
The PHY core already resets the PHY before .config_init() if a
.soft_reset() op is registered. Drop the open-coded ip1xx_reset().
Signed-off-by: Michael Walle <redacted>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Changes since v2:
- none
Changes since v1:
- none
drivers/net/phy/icplus.c | 32 ++------------------------------
1 file changed, 2 insertions(+), 30 deletions(-)
@@ -120,36 +120,10 @@ static int ip175c_config_init(struct phy_device *phydev)return0;}-staticintip1xx_reset(structphy_device*phydev)-{-intbmcr;--/* Software Reset PHY */-bmcr=phy_read(phydev,MII_BMCR);-if(bmcr<0)-returnbmcr;-bmcr|=BMCR_RESET;-bmcr=phy_write(phydev,MII_BMCR,bmcr);-if(bmcr<0)-returnbmcr;--do{-bmcr=phy_read(phydev,MII_BMCR);-if(bmcr<0)-returnbmcr;-}while(bmcr&BMCR_RESET);--return0;-}-staticintip1001_config_init(structphy_device*phydev){intc;-c=ip1xx_reset(phydev);-if(c<0)-returnc;-/* Enable Auto Power Saving mode */c=phy_read(phydev,IP1001_SPEC_CTRL_STATUS_2);if(c<0)
@@ -237,10 +211,6 @@ static int ip101a_g_config_init(struct phy_device *phydev)structip101a_g_phy_priv*priv=phydev->priv;interr,c;-c=ip1xx_reset(phydev);-if(c<0)-returnc;-/* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */switch(priv->sel_intr32){caseIP101GR_SEL_INTR32_RXER:
From: Michael Walle <hidden> Date: 2021-02-10 21:12:12
This bit is reserved as 'always-write-1'. While this is not a particular
error, because we are only setting it, guard it by checking the model to
prevent errors in the future.
Signed-off-by: Michael Walle <redacted>
---
Changes since v2:
- none
Changes since v1:
- dropped the model check. Instead use two different functions.
Andrew, I've dropped your Reviewed-by because of this.
drivers/net/phy/icplus.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
@@ -208,10 +208,10 @@ static int ip101a_g_probe(struct phy_device *phydev)return0;}-staticintip101a_g_config_init(structphy_device*phydev)+staticintip101a_g_config_intr_pin(structphy_device*phydev){structip101a_g_phy_priv*priv=phydev->priv;-interr,c;+interr;/* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */switch(priv->sel_intr32){
@@ -241,11 +241,24 @@ static int ip101a_g_config_init(struct phy_device *phydev)break;}+return0;+}++staticintip101a_config_init(structphy_device*phydev)+{+intret;+/* Enable Auto Power Saving mode */-c=phy_read(phydev,IP10XX_SPEC_CTRL_STATUS);-c|=IP101A_G_APS_ON;+ret=phy_set_bits(phydev,IP10XX_SPEC_CTRL_STATUS,IP101A_G_APS_ON);+if(ret)+returnret;-returnphy_write(phydev,IP10XX_SPEC_CTRL_STATUS,c);+returnip101a_g_config_intr_pin(phydev);+}++staticintip101g_config_init(structphy_device*phydev)+{+returnip101a_g_config_intr_pin(phydev);}staticintip101a_g_ack_interrupt(structphy_device*phydev)
From: Michael Walle <hidden> Date: 2021-02-10 21:13:18
The IP101G provides three counters: RX packets, CRC errors and symbol
errors. The error counters can be configured to clear automatically on
read. Unfortunately, this isn't true for the RX packet counter. Because
of this and because the RX packet counter is more likely to overflow,
than the error counters implement only support for the error counters.
Signed-off-by: Michael Walle <redacted>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Changes since v2:
- none
Changes since v1:
- renamed the functions to represend a IP101G-only function
- enable the counters in IP101G's config_init()
drivers/net/phy/icplus.c | 75 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
From: Michael Walle <hidden> Date: 2021-02-10 21:13:18
Registers >= 16 are paged. Be sure to set the page. It seems this was
working for now, because the default is correct for the registers used
in the driver at the moment. But this will also assume, nobody will
change the page select register before linux is started. The page select
register is _not_ reset with a soft reset of the PHY.
To ease the function reuse between the non-paged register space of the
IP101A and the IP101G, add noop read_page()/write_page() callbacks so
the IP101G functions can also be used for the IP101A.
Signed-off-by: Michael Walle <redacted>
---
Changes since v2:
- none
Changes since v1:
- introduce a noop read/write_page() for the IP101A
- also use phy_*_paged() for the interrupt status register
Andrew, I've dropped your Reviewed-by because of this.
drivers/net/phy/icplus.c | 65 ++++++++++++++++++++++++++++++++--------
1 file changed, 52 insertions(+), 13 deletions(-)
@@ -211,23 +213,25 @@ static int ip101a_g_probe(struct phy_device *phydev)staticintip101a_g_config_intr_pin(structphy_device*phydev){structip101a_g_phy_priv*priv=phydev->priv;-interr;+intoldpage,err;++oldpage=phy_select_page(phydev,IP101G_DEFAULT_PAGE);/* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */switch(priv->sel_intr32){caseIP101GR_SEL_INTR32_RXER:-err=phy_modify(phydev,IP101G_DIGITAL_IO_SPEC_CTRL,-IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,0);+err=__phy_modify(phydev,IP101G_DIGITAL_IO_SPEC_CTRL,+IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,0);if(err<0)-returnerr;+gotoout;break;caseIP101GR_SEL_INTR32_INTR:-err=phy_modify(phydev,IP101G_DIGITAL_IO_SPEC_CTRL,-IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,-IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);+err=__phy_modify(phydev,IP101G_DIGITAL_IO_SPEC_CTRL,+IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,+IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);if(err<0)-returnerr;+gotoout;break;default:
@@ -241,7 +245,8 @@ static int ip101a_g_config_intr_pin(struct phy_device *phydev)break;}-return0;+out:+returnphy_restore_page(phydev,oldpage,err);}staticintip101a_config_init(structphy_device*phydev)
@@ -263,8 +268,10 @@ static int ip101g_config_init(struct phy_device *phydev)staticintip101a_g_ack_interrupt(structphy_device*phydev){-interr=phy_read(phydev,IP101A_G_IRQ_CONF_STATUS);+interr;+err=phy_read_paged(phydev,IP101G_DEFAULT_PAGE,+IP101A_G_IRQ_CONF_STATUS);if(err<0)returnerr;
@@ -283,10 +290,12 @@ static int ip101a_g_config_intr(struct phy_device *phydev)/* INTR pin used: Speed/link/duplex will cause an interrupt */val=IP101A_G_IRQ_PIN_USED;-err=phy_write(phydev,IP101A_G_IRQ_CONF_STATUS,val);+err=phy_write_paged(phydev,IP101G_DEFAULT_PAGE,+IP101A_G_IRQ_CONF_STATUS,val);}else{val=IP101A_G_IRQ_ALL_MASK;-err=phy_write(phydev,IP101A_G_IRQ_CONF_STATUS,val);+err=phy_write_paged(phydev,IP101G_DEFAULT_PAGE,+IP101A_G_IRQ_CONF_STATUS,val);if(err)returnerr;
@@ -316,6 +326,31 @@ static irqreturn_t ip101a_g_handle_interrupt(struct phy_device *phydev)returnIRQ_HANDLED;}+/* The IP101A doesn't really have a page register. We just pretend to have one+*sowecanusethepagedversionsofthecallbacksoftheIP101G.+*/+staticintip101a_read_page(structphy_device*phydev)+{+returnIP101G_DEFAULT_PAGE;+}++staticintip101a_write_page(structphy_device*phydev,intpage)+{+WARN_ONCE(page!=IP101G_DEFAULT_PAGE,"wrong page selected\n");++return0;+}++staticintip101g_read_page(structphy_device*phydev)+{+return__phy_read(phydev,IP101G_PAGE_CONTROL);+}++staticintip101g_write_page(structphy_device*phydev,intpage)+{+return__phy_write(phydev,IP101G_PAGE_CONTROL,page);+}+staticintip101a_g_has_page_register(structphy_device*phydev){intoldval,val,ret;
From: Michael Walle <hidden> Date: 2021-02-10 21:13:18
Unfortunately, the IP101A and IP101G share the same PHY identifier.
While most of the functions are somewhat backwards compatible, there is
for example the APS_EN bit on the IP101A but on the IP101G this bit
reserved. Also, the IP101G has many more functionalities.
Deduce the model by accessing the page select register which - according
to the datasheet - is not available on the IP101A. If this register is
writable, assume we have an IP101G.
Split the combined IP101A/G driver into two separate drivers.
Signed-off-by: Michael Walle <redacted>
---
Changes since v2:
- dropped the PHY_BASIC_FEATURES comments as suggested by Heiner
- converted the ternary operator to a simple comparison as suggested by
Heiner
Changes since v1:
- use match_phy_device() as suggested by Heiner
Andrew, I've dropped your Reviewed-by because of this.
drivers/net/phy/icplus.c | 69 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 66 insertions(+), 3 deletions(-)
@@ -301,6 +303,58 @@ static irqreturn_t ip101a_g_handle_interrupt(struct phy_device *phydev)returnIRQ_HANDLED;}+staticintip101a_g_has_page_register(structphy_device*phydev)+{+intoldval,val,ret;++oldval=phy_read(phydev,IP101G_PAGE_CONTROL);+if(oldval<0)+returnoldval;++ret=phy_write(phydev,IP101G_PAGE_CONTROL,0xffff);+if(ret)+returnret;++val=phy_read(phydev,IP101G_PAGE_CONTROL);+if(val<0)+returnval;++ret=phy_write(phydev,IP101G_PAGE_CONTROL,oldval);+if(ret)+returnret;++returnval==IP101G_PAGE_CONTROL_MASK;+}++staticintip101a_g_match_phy_device(structphy_device*phydev,boolip101a)+{+intret;++if(phydev->phy_id!=IP101A_PHY_ID)+return0;++/* The IP101A and the IP101G share the same PHY identifier.The IP101G+*seemstobeasuccessoroftheIP101Aandimplementsmorefunctions.+*Amongstotherthingsthereisapageselectregister,whichisnot+*availableontheIP101A.Usethistodistinguishthesetwo.+*/+ret=ip101a_g_has_page_register(phydev);+if(ret<0)+returnret;++returnip101a==!ret;+}++staticintip101a_match_phy_device(structphy_device*phydev)+{+returnip101a_g_match_phy_device(phydev,true);+}++staticintip101g_match_phy_device(structphy_device*phydev)+{+returnip101a_g_match_phy_device(phydev,false);+}+staticstructphy_drivericplus_driver[]={{PHY_ID_MATCH_MODEL(IP175C_PHY_ID),
From: Michael Walle <hidden> Date: 2021-02-10 21:13:19
Implement the operations to set desired mode and retrieve the current
mode.
This feature was tested with an IP101G.
Signed-off-by: Michael Walle <redacted>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Changes since v2:
- none
Changes since v1:
- none, except that the callbacks are register for both IP101A and IP101G
PHY drivers
drivers/net/phy/icplus.c | 93 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
From: kernel test robot <hidden> Date: 2021-02-10 23:23:44
Hi Michael,
I love your patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Michael-Walle/net-phy-icplus-cleanups-and-new-features/20210211-051702
base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git de1db4a6ed6241e34cab0e5059d4b56f6bae39b9
config: powerpc64-randconfig-r004-20210211 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project c9439ca36342fb6013187d0a69aef92736951476)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install powerpc64 cross compiling tool for clang build
# apt-get install binutils-powerpc64-linux-gnu
# https://github.com/0day-ci/linux/commit/07b7c444040f9baff7b28415b4f26be7e7a71e2e
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Michael-Walle/net-phy-icplus-cleanups-and-new-features/20210211-051702
git checkout 07b7c444040f9baff7b28415b4f26be7e7a71e2e
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=powerpc64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <redacted>
All warnings (new ones prefixed by >>):
__do_insb
^
arch/powerpc/include/asm/io.h:556:56: note: expanded from macro '__do_insb'
#define __do_insb(p, b, n) readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/net/phy/icplus.c:11:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:10:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:619:
arch/powerpc/include/asm/io-defs.h:45:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:616:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:139:1: note: expanded from here
__do_insw
^
arch/powerpc/include/asm/io.h:557:56: note: expanded from macro '__do_insw'
#define __do_insw(p, b, n) readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/net/phy/icplus.c:11:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:10:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:619:
arch/powerpc/include/asm/io-defs.h:47:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:616:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:141:1: note: expanded from here
__do_insl
^
arch/powerpc/include/asm/io.h:558:56: note: expanded from macro '__do_insl'
#define __do_insl(p, b, n) readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/net/phy/icplus.c:11:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:10:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:619:
arch/powerpc/include/asm/io-defs.h:49:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:616:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:143:1: note: expanded from here
__do_outsb
^
arch/powerpc/include/asm/io.h:559:58: note: expanded from macro '__do_outsb'
#define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/net/phy/icplus.c:11:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:10:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:619:
arch/powerpc/include/asm/io-defs.h:51:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:616:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:145:1: note: expanded from here
__do_outsw
^
arch/powerpc/include/asm/io.h:560:58: note: expanded from macro '__do_outsw'
#define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/net/phy/icplus.c:11:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:10:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:619:
arch/powerpc/include/asm/io-defs.h:53:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:616:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:147:1: note: expanded from here
__do_outsl
^
arch/powerpc/include/asm/io.h:561:58: note: expanded from macro '__do_outsl'
#define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
~~~~~~~~~~~~~~~~~~~~~^
quoted
drivers/net/phy/icplus.c:237:2: warning: variable 'err' is used uninitialized whenever switch default is taken [-Wsometimes-uninitialized]
default:
^~~~~~~
drivers/net/phy/icplus.c:249:43: note: uninitialized use occurs here
return phy_restore_page(phydev, oldpage, err);
^~~
drivers/net/phy/icplus.c:216:18: note: initialize the variable 'err' to silence this warning
int oldpage, err;
^
= 0
7 warnings generated.
vim +/err +237 drivers/net/phy/icplus.c
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 212
56ff94ca1f47d1 Michael Walle 2021-02-10 213 static int ip101a_g_config_intr_pin(struct phy_device *phydev)
034289b2d7cf29 Martin Blumenstingl 2018-11-18 214 {
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 215 struct ip101a_g_phy_priv *priv = phydev->priv;
07b7c444040f9b Michael Walle 2021-02-10 216 int oldpage, err;
07b7c444040f9b Michael Walle 2021-02-10 217
07b7c444040f9b Michael Walle 2021-02-10 218 oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
034289b2d7cf29 Martin Blumenstingl 2018-11-18 219
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 220 /* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 221 switch (priv->sel_intr32) {
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 222 case IP101GR_SEL_INTR32_RXER:
07b7c444040f9b Michael Walle 2021-02-10 223 err = __phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 224 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0);
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 225 if (err < 0)
07b7c444040f9b Michael Walle 2021-02-10 226 goto out;
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 227 break;
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 228
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 229 case IP101GR_SEL_INTR32_INTR:
07b7c444040f9b Michael Walle 2021-02-10 230 err = __phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 231 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 232 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 233 if (err < 0)
07b7c444040f9b Michael Walle 2021-02-10 234 goto out;
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 235 break;
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 236
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 @237 default:
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 238 /* Don't touch IP101G_DIGITAL_IO_SPEC_CTRL because it's not
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 239 * documented on IP101A and it's not clear whether this would
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 240 * cause problems.
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 241 * For the 32-pin IP101GR we simply keep the SEL_INTR32
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 242 * configuration as set by the bootloader when not configured
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 243 * to one of the special functions.
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 244 */
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 245 break;
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 246 }
f2f1a847e74f61 Martin Blumenstingl 2018-11-18 247
07b7c444040f9b Michael Walle 2021-02-10 248 out:
07b7c444040f9b Michael Walle 2021-02-10 249 return phy_restore_page(phydev, oldpage, err);
56ff94ca1f47d1 Michael Walle 2021-02-10 250 }
56ff94ca1f47d1 Michael Walle 2021-02-10 251
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
From: Andrew Lunn <andrew@lunn.ch> Date: 2021-02-10 23:50:34
On Wed, Feb 10, 2021 at 10:08:06PM +0100, Michael Walle wrote:
This bit is reserved as 'always-write-1'. While this is not a particular
error, because we are only setting it, guard it by checking the model to
prevent errors in the future.
Signed-off-by: Michael Walle <redacted>
From: Michael Walle <hidden> Date: 2021-02-10 23:56:54
Am 2021-02-10 22:08, schrieb Michael Walle:
quoted hunk
Registers >= 16 are paged. Be sure to set the page. It seems this was
working for now, because the default is correct for the registers used
in the driver at the moment. But this will also assume, nobody will
change the page select register before linux is started. The page
select
register is _not_ reset with a soft reset of the PHY.
To ease the function reuse between the non-paged register space of the
IP101A and the IP101G, add noop read_page()/write_page() callbacks so
the IP101G functions can also be used for the IP101A.
Signed-off-by: Michael Walle <redacted>
---
Changes since v2:
- none
Changes since v1:
- introduce a noop read/write_page() for the IP101A
- also use phy_*_paged() for the interrupt status register
Andrew, I've dropped your Reviewed-by because of this.
drivers/net/phy/icplus.c | 65 ++++++++++++++++++++++++++++++++--------
1 file changed, 52 insertions(+), 13 deletions(-)
ip101a_g_handle_interrupt(struct phy_device *phydev)
return IRQ_HANDLED;
}
+/* The IP101A doesn't really have a page register. We just pretend to
have one
+ * so we can use the paged versions of the callbacks of the IP101G.
+ */
+static int ip101a_read_page(struct phy_device *phydev)
+{
+ return IP101G_DEFAULT_PAGE;
+}
+
+static int ip101a_write_page(struct phy_device *phydev, int page)
+{
+ WARN_ONCE(page != IP101G_DEFAULT_PAGE, "wrong page selected\n");
+
+ return 0;
+}
+
+static int ip101g_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, IP101G_PAGE_CONTROL);
+}
+
+static int ip101g_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, IP101G_PAGE_CONTROL, page);
+}
+
static int ip101a_g_has_page_register(struct phy_device *phydev)
{
int oldval, val, ret;
From: Michael Walle <hidden> Date: 2021-02-11 00:14:14
Am 2021-02-10 22:08, schrieb Michael Walle:
quoted hunk
Implement the operations to set desired mode and retrieve the current
mode.
This feature was tested with an IP101G.
Signed-off-by: Michael Walle <redacted>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Changes since v2:
- none
Changes since v1:
- none, except that the callbacks are register for both IP101A and
IP101G
PHY drivers
drivers/net/phy/icplus.c | 93 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)