2013.12.17. 1:12 keltezéssel, Felix Kaechele írta:
> The bootloader on the WD My Net N750 disables the ports on it's internal
> AR8327N switch by powering them down. The stock firmware then brings the
> ports back up again by starting the auto negotiation process on each
> port.
> 
> There is one big disadvantage of this approach: In tests I noticed that
> PHYs on this platform that are powered down can be written but not read.
> As a result the scan on the mdio bus fails to detect the ports on the
> switch.
> 
> This workaround adds an option to the mdio bus platform data that
> enables toggling of an early reset of all available PHYs before the mdio
> bus scan is performed. On the test platform this brings the PHYs back to
> life in time to be detected by the mdio bus scan.
> 
> Signed-off-by: Felix Kaechele <hef...@fedoraproject.org>
> ---
>  .../linux/ar71xx/files/arch/mips/ath79/dev-eth.c   |  4 +--
>  .../linux/ar71xx/files/arch/mips/ath79/dev-eth.h   |  2 ++
>  .../mips/include/asm/mach-ath79/ag71xx_platform.h  |  1 +
>  .../net/ethernet/atheros/ag71xx/ag71xx_mdio.c      | 30 
> ++++++++++++++--------
>  4 files changed, 24 insertions(+), 13 deletions(-)
> 
> diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c 
> b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c
> index 4a2b1db..742218b 100644
> --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c
> +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c
> @@ -39,7 +39,7 @@ static struct resource ath79_mdio0_resources[] = {
>       }
>  };
>  
> -static struct ag71xx_mdio_platform_data ath79_mdio0_data;
> +struct ag71xx_mdio_platform_data ath79_mdio0_data;
>  
>  struct platform_device ath79_mdio0_device = {
>       .name           = "ag71xx-mdio",
> @@ -60,7 +60,7 @@ static struct resource ath79_mdio1_resources[] = {
>       }
>  };
>  
> -static struct ag71xx_mdio_platform_data ath79_mdio1_data;
> +struct ag71xx_mdio_platform_data ath79_mdio1_data;

Making the ath79_mdio[01]_data visible is not strictly related to the patch. I
would do it in a separate change ...

>  
>  struct platform_device ath79_mdio1_device = {
>       .name           = "ag71xx-mdio",
> diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h 
> b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h
> index bc608da..08a59ef 100644
> --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h
> +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h
> @@ -39,6 +39,8 @@ void ath79_register_eth(unsigned int id);
>  
>  extern struct ag71xx_switch_platform_data ath79_switch_data;
>  
> +extern struct ag71xx_mdio_platform_data ath79_mdio0_data;
> +extern struct ag71xx_mdio_platform_data ath79_mdio0_data;

... and the second line should refer to ath79_mdio*1*_data.

>  extern struct platform_device ath79_mdio0_device;
>  extern struct platform_device ath79_mdio1_device;
>  void ath79_register_mdio(unsigned int id, u32 phy_mask);
> diff --git 
> a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h
>  
> b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h
> index 656a6ef..333daa9 100644
> --- 
> a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h
> +++ 
> b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h
> @@ -53,6 +53,7 @@ struct ag71xx_mdio_platform_data {
>       u8              is_ar7240:1;
>       u8              is_ar9330:1;
>       u8              is_ar934x:1;
> +     u8              wake_phys:1;

To be honest, I would like to avoid any board specific workaround in the
ag71xx/mdio driver. Even if there is no other alternative to make it working on
the My Net N750 , this should be done in a more generic way.

It would be better to add a 'void (*reset)(struct mii_bus *bus);' callback to
the ag71xx_mdio_platform_data and call that from the ag71xx_mdio_reset function.
In that way, the extra functionality can be implemented within the board
specific code.

>       unsigned long   mdio_clock;
>       unsigned long   ref_clock;
>  };
> diff --git 
> a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c 
> b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
> index ec88233..0f3ed63 100644
> --- 
> a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
> +++ 
> b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
> @@ -156,10 +156,22 @@ static int ag71xx_mdio_get_divider(struct ag71xx_mdio 
> *am, u32 *div)
>       return -ENOENT;
>  }
>  
> +static int ag71xx_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
> +{
> +     struct ag71xx_mdio *am = bus->priv;
> +
> +     if (am->pdata->builtin_switch)
> +             ar7240sw_phy_write(bus, addr, reg, val);
> +     else
> +             ag71xx_mdio_mii_write(am, addr, reg, val);
> +     return 0;
> +}
> +
>  static int ag71xx_mdio_reset(struct mii_bus *bus)
>  {
>       struct ag71xx_mdio *am = bus->priv;
>       u32 t;
> +     int i;
>       int err;
>  
>       err = ag71xx_mdio_get_divider(am, &t);
> @@ -181,6 +193,13 @@ static int ag71xx_mdio_reset(struct mii_bus *bus)
>       ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t);
>       udelay(100);
>  
> +     if(am->pdata->wake_phys) {
> +             for (i = 0; i < PHY_MAX_ADDR; i++)

Another advantage of a separate callback is that you can optimize the loop. It
makes no sense to write to the non existing PHYs.

> +                     ag71xx_mdio_write(bus, i, MII_BMCR, (BMCR_RESET |
> +                                     BMCR_ANENABLE | BMCR_SPEED1000));
> +             msleep(1000);
> +     }
> +
>       return 0;
>  }
>  
> @@ -194,17 +213,6 @@ static int ag71xx_mdio_read(struct mii_bus *bus, int 
> addr, int reg)
>               return ag71xx_mdio_mii_read(am, addr, reg);
>  }
>  
> -static int ag71xx_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
> -{
> -     struct ag71xx_mdio *am = bus->priv;
> -
> -     if (am->pdata->builtin_switch)
> -             ar7240sw_phy_write(bus, addr, reg, val);
> -     else
> -             ag71xx_mdio_mii_write(am, addr, reg, val);
> -     return 0;
> -}
> -

Additionally, you would not have to move the 'ag71xx_mdio_write' function at
all. From the board specific callback, you can use the mdiobus_write() function
instead.

>  static int ag71xx_mdio_probe(struct platform_device *pdev)
>  {
>       struct ag71xx_mdio_platform_data *pdata;
> 

-Gabor
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to