phy: add phy_connect_by_mask
Subsystems (2)
PATCH 1/3 phy: add phy_connect_by_mask
It is useful to be able to try a range of
possible phy addresses to connect.
--- drivers/net/phy/phy.c | 108 +++++++++++++++++++++++++++++++------------------ include/phy.h | 2 + 2 files changed, 71 insertions(+), 39 deletions(-)
drivers/net/phy/phy.c +69 -39
@@ -31,6 +31,7 @@#include <miiphy.h> #include <phy.h> #include <errno.h> +#include <linux/err.h> /* Generic PHY support and helper functions */
@@ -573,6 +574,61 @@ int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)return 0 ; } +static struct phy_device *create_phy_by_mask (struct mii_dev *bus, +unsigned phy_mask,int devad,phy_interface_t interface) +{ +u32 phy_id =0xffffffff ; +while (phy_mask) { +int addr =ffs (phy_mask) -1 ; +int r =get_phy_id (bus, addr, devad, &phy_id); +if (r <0 ) +return ERR_PTR (r); +/* If the PHY ID is mostly f's, we didn't find anything */ +if ((phy_id &0x1fffffff ) !=0x1fffffff ) +return phy_device_create (bus, addr, phy_id, interface); + phy_mask &= ~(1 << addr); + } +return NULL ; +} + +static struct phy_device *search_for_existing_phy (struct mii_dev *bus, +unsigned phy_mask,phy_interface_t interface) +{ +/* If we have one, return the existing device, with new interface */ +while (phy_mask) { +int addr =ffs (phy_mask) -1 ; +if (bus->phymap[addr]) { + bus->phymap[addr]->interface = interface; +return bus->phymap[addr]; + } + phy_mask &= ~(1 << addr); + } +return NULL ; +} + +static struct phy_device *get_phy_device_by_mask (struct mii_dev *bus, +unsigned phy_mask,phy_interface_t interface) +{ +int i; +struct phy_device *phydev; + + phydev =search_for_existing_phy (bus, phy_mask, interface); +if (phydev) +return phydev; +/* Try Standard (ie Clause 22) access */ +/* Otherwise we have to try Clause 45 */ +for (i =0 ; i <5 ; i++) { + phydev =create_phy_by_mask (bus, phy_mask, + i ? i :MDIO_DEVAD_NONE , interface); +if (IS_ERR (phydev)) +return NULL ; +if (phydev) +return phydev; + } +printf ("Phy not found\n" ); +return phy_device_create (bus,ffs (phy_mask) -1 ,0xffffffff , interface); +} +/** * get_phy_device - reads the specified PHY device and returns its @phy_device struct * @bus: the target MII bus
@@ -584,38 +640,7 @@ int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)struct phy_device *get_phy_device (struct mii_dev *bus,int addr,phy_interface_t interface) { -u32 phy_id =0x1fffffff ; -int i; -int r; - -/* If we have one, return the existing device, with new interface */ -if (bus->phymap[addr]) { - bus->phymap[addr]->interface = interface; - -return bus->phymap[addr]; - } - -/* Try Standard (ie Clause 22) access */ - r =get_phy_id (bus, addr,MDIO_DEVAD_NONE , &phy_id); -if (r) -return NULL ; - -/* If the PHY ID is mostly f's, we didn't find anything */ -if ((phy_id &0x1fffffff ) !=0x1fffffff ) -return phy_device_create (bus, addr, phy_id, interface); - -/* Otherwise we have to try Clause 45 */ -for (i =1 ; i <5 ; i++) { - r =get_phy_id (bus, addr, i, &phy_id); -if (r) -return NULL ; - -/* If the phy_id is mostly Fs, there is no device there */ -if ((phy_id &0x1fffffff ) !=0x1fffffff ) -break ; - } - -return phy_device_create (bus, addr, phy_id, interface); +return get_phy_device_by_mask (bus,1 << addr, interface); }int phy_reset (struct phy_device *phydev)
@@ -688,9 +713,8 @@ int miiphy_reset(const char *devname, unsigned char addr)return phy_reset (phydev); } -struct phy_device *phy_connect (struct mii_dev *bus,int addr, -struct eth_device *dev, -phy_interface_t interface) +struct phy_device *phy_connect_by_mask (struct mii_dev *bus,unsigned phy_mask, +struct eth_device *dev,phy_interface_t interface) {struct phy_device *phydev;
@@ -701,11 +725,11 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,/* Wait 15ms to make sure the PHY has come out of hard reset */ udelay (15000 ); - phydev =get_phy_device (bus, addr, interface); + phydev =get_phy_device_by_mask (bus, phy_mask, interface);if (!phydev) { -printf ("Could not get PHY for %s:%d\n" , bus->name, addr); - +printf ("Could not get PHY for %s: phy mask %x\n" , + bus->name, phy_mask);return NULL ; }
@@ -714,7 +738,7 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,if (phydev->dev)printf ("%s:%d is connected to %s. Reconnecting to %s\n" , - bus->name, addr, phydev->dev->name, dev->name); + bus->name, phydev->addr, phydev->dev->name, dev->name); phydev->dev = dev;
@@ -723,6 +747,12 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,return phydev; } +struct phy_device *phy_connect (struct mii_dev *bus,int addr, +struct eth_device *dev,phy_interface_t interface) +{ +return phy_connect_by_mask (bus,1 << addr, dev, interface); +} +/* * Start the PHY. Returns 0 on success, or a negative error code. */
include/phy.h +2 -0
@@ -202,6 +202,8 @@ int phy_reset(struct phy_device *phydev);struct phy_device *phy_connect (struct mii_dev *bus,int addr,struct eth_device *dev,phy_interface_t interface); +struct phy_device *phy_connect_by_mask (struct mii_dev *bus,unsigned phy_mask, +struct eth_device *dev,phy_interface_t interface);int phy_startup (struct phy_device *phydev);int phy_config (struct phy_device *phydev);int phy_shutdown (struct phy_device *phydev);
Signature · 1 line
1.7.9.5
PATCH 2/3 fec_mxc: use phy_connect_by_mask
Allow board config files to list a range
of possible phy addresses, in case the
exact phy address is not certain.
--- drivers/net/fec_mxc.c | 21 +++++++++++++++------ drivers/net/fec_mxc.h | 3 ++- 2 files changed, 17 insertions(+), 7 deletions(-)
drivers/net/fec_mxc.c +15 -6
@@ -391,7 +391,7 @@ static void fec_eth_phy_config(struct eth_device *dev)struct fec_priv *fec = (struct fec_priv *)dev->priv;struct phy_device *phydev; - phydev =phy_connect (fec->bus, fec->phy_id, dev, + phydev =phy_connect_by_mask (fec->bus, fec->phy_mask, dev,PHY_INTERFACE_MODE_RGMII );if (phydev) { fec->phydev = phydev;
@@ -898,7 +898,8 @@ static int fec_recv(struct eth_device *dev)return len; } -static int fec_probe (bd_t *bd,int dev_id,int phy_id,uint32_t base_addr) +static int fec_probe (bd_t *bd,int dev_id,unsigned phy_mask, +uint32_t base_addr) {struct eth_device *edev;struct fec_priv *fec;
@@ -958,8 +959,11 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)sprintf (edev->name,"FEC%i" , dev_id); fec->dev_id = dev_id; } - fec->phy_id = phy_id; - +#ifdef CONFIG_PHYLIB + fec->phy_mask = phy_mask; +#else + fec->phy_id =ffs (phy_mask) -1 ; +#endif bus =mdio_alloc ();if (!bus) {printf ("mdio_alloc failed\n" );
@@ -1008,9 +1012,14 @@ err1:int fecmxc_initialize (bd_t *bd) {int lout =1 ; +#ifdef CONFIG_FEC_MXC_PHYMASK +unsigned phy_mask =CONFIG_FEC_MXC_PHYMASK ; +#else +unsigned phy_mask =1 <<CONFIG_FEC_MXC_PHYADDR ; +#endif debug ("eth_init: fec_probe(bd)\n" ); - lout =fec_probe (bd,-1 ,CONFIG_FEC_MXC_PHYADDR ,IMX_FEC_BASE ); + lout =fec_probe (bd,-1 , phy_mask,IMX_FEC_BASE );return lout; }
@@ -1021,7 +1030,7 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)int lout =1 ;debug ("eth_init: fec_probe(bd, %i, %i) @ %08x\n" , dev_id, phy_id, addr); - lout =fec_probe (bd, dev_id, phy_id, addr); + lout =fec_probe (bd, dev_id,1 << phy_id, addr);return lout; }
drivers/net/fec_mxc.h +2 -1
@@ -268,11 +268,12 @@ struct fec_priv {bd_t *bd;uint8_t *tdb_ptr;int dev_id; -int phy_id;struct mii_dev *bus;#ifdef CONFIG_PHYLIB +int phy_mask;struct phy_device *phydev;#else +int phy_id;int (*mii_postcall)(int );#endif };
Signature · 1 line
1.7.9.5
PATCH 2/3 fec_mxc: use phy_connect_by_mask
Quoted 6 lines · Troy Kisky
Allow board config files to list a range
of possible phy addresses, in case the
exact phy address is not certain.Signed-off-by Troy Kisky <[email protected]>---
Hi Troy,
Quoted 75 lines
drivers/net/fec_mxc.c | 21 +++++++++++++++------ drivers/net/fec_mxc.h | 3 ++- 2 files changed, 17 insertions(+), 7 deletions(-)drivers/net/fec_mxc.c +15
-6@@ -391,7 +391,7 @@ static void fec_eth_phy_config(struct eth_device *dev)struct fec_priv *fec = (struct fec_priv *)dev->priv;struct phy_device *phydev; - phydev =phy_connect (fec->bus, fec->phy_id, dev, + phydev =phy_connect_by_mask (fec->bus, fec->phy_mask, dev,PHY_INTERFACE_MODE_RGMII );if (phydev) { fec->phydev = phydev;@@ -898,7 +898,8 @@ static int fec_recv(struct eth_device *dev)return len; } -static int fec_probe (bd_t *bd,int dev_id,int phy_id,uint32_t base_addr) +static int fec_probe (bd_t *bd,int dev_id,unsigned phy_mask, +uint32_t base_addr) {struct eth_device *edev;struct fec_priv *fec;@@ -958,8 +959,11 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)sprintf (edev->name,"FEC%i" , dev_id); fec->dev_id = dev_id; } - fec->phy_id = phy_id; - +#ifdef CONFIG_PHYLIB + fec->phy_mask = phy_mask; +#else + fec->phy_id =ffs (phy_mask) -1 ; +#endif bus =mdio_alloc ();if (!bus) {printf ("mdio_alloc failed\n" );@@ -1008,9 +1012,14 @@ err1:int fecmxc_initialize (bd_t *bd) {int lout =1 ; +#ifdef CONFIG_FEC_MXC_PHYMASK +unsigned phy_mask =CONFIG_FEC_MXC_PHYMASK ; +#else +unsigned phy_mask =1 <<CONFIG_FEC_MXC_PHYADDR ; +#endif debug ("eth_init: fec_probe(bd)\n" ); - lout =fec_probe (bd,-1 ,CONFIG_FEC_MXC_PHYADDR ,IMX_FEC_BASE ); + lout =fec_probe (bd,-1 , phy_mask,IMX_FEC_BASE );return lout; }@@ -1021,7 +1030,7 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)int lout =1 ;debug ("eth_init: fec_probe(bd, %i, %i) @ %08x\n" , dev_id, phy_id, addr); - lout =fec_probe (bd, dev_id, phy_id, addr); + lout =fec_probe (bd, dev_id,1 << phy_id, addr);return lout; }drivers/net/fec_mxc.h +0
-0@@ -268,11 +268,12 @@ struct fec_priv {bd_t *bd;uint8_t *tdb_ptr;int dev_id;
drivers/net/fec_mxc.h struct fec_priv { · line 279
Quoted 10 lines
drivers/net/fec_mxc.h +2
-1-int phy_id;struct mii_dev *bus;#ifdef CONFIG_PHYLIB +int phy_mask;struct phy_device *phydev;#else +int phy_id;int (*mii_postcall)(int );#endif };
I generally agree with this patchset. My only concern is that we add a new CONFIG_ option without documentation. Can you add an entry into the README file (I know, a lot of CONFIG_ are missing, but we can at least avoid to add hidden features..).
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de =====================================================================
PATCH 2/3 fec_mxc: use phy_connect_by_mask
Quoted 4 lines · Stefano Babic
I generally agree with this patchset. My only concern is that we add a new
CONFIG_option without documentation. Can you add an entry into the README file (I know, a lot ofCONFIG_are missing, but we can at least avoid to add hidden features..). Best regards, Stefano Babic
Will do
Thanks
Troy
PATCH 3/3 mx6qsabrelite: set CONFIG_FEC_MXC_PHYMASK
In reply to Troy KiskyDifferent ethernet jacks parts can result in the Micrel KSZ9021 getting a different phy address. Let's support all parts.
--- include/configs/mx6qsabrelite.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/configs/mx6qsabrelite.h +1 -1
@@ -99,7 +99,7 @@#define IMX_FEC_BASE ENET_BASE_ADDR#define CONFIG_FEC_XCV_TYPE RGMII#define CONFIG_ETHPRIME "FEC" -#define CONFIG_FEC_MXC_PHYADDR 6 +#define CONFIG_FEC_MXC_PHYMASK (0xf << 4)/* scan phy 4,5,6,7 */ #define CONFIG_PHYLIB #define CONFIG_PHY_MICREL #define CONFIG_PHY_MICREL_KSZ9021
Signature · 1 line
1.7.9.5