Changeset 33342


Ignore:
Timestamp:
2012-09-09T16:05:17+02:00 (4 years ago)
Author:
juhosg
Message:

ar71xx: add dynamic MDIO clock calculation

Location:
trunk/target/linux/ar71xx/files
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h

    r31925 r33342  
    5454        u8              is_ar9330:1; 
    5555        u8              is_ar934x:1; 
     56        unsigned long   mdio_clock; 
     57        unsigned long   ref_clock; 
    5658}; 
    5759 
  • trunk/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c

    r32586 r33342  
    106106} 
    107107 
     108static const u32 ar71xx_mdio_div_table[] = { 
     109        4, 4, 6, 8, 10, 14, 20, 28, 
     110}; 
     111 
     112static const u32 ar7240_mdio_div_table[] = { 
     113        2, 2, 4, 6, 8, 12, 18, 26, 32, 40, 48, 56, 62, 70, 78, 96, 
     114}; 
     115 
     116static const u32 ar933x_mdio_div_table[] = { 
     117        4, 4, 6, 8, 10, 14, 20, 28, 34, 42, 50, 58, 66, 74, 82, 98, 
     118}; 
     119 
     120static int ag71xx_mdio_get_divider(struct ag71xx_mdio *am, u32 *div) 
     121{ 
     122        unsigned long ref_clock, mdio_clock; 
     123        const u32 *table; 
     124        int ndivs; 
     125        int i; 
     126 
     127        ref_clock = am->pdata->ref_clock; 
     128        mdio_clock = am->pdata->mdio_clock; 
     129 
     130        if (!ref_clock || !mdio_clock) 
     131                return -EINVAL; 
     132 
     133        if (am->pdata->is_ar9330 || am->pdata->is_ar934x) { 
     134                table = ar933x_mdio_div_table; 
     135                ndivs = ARRAY_SIZE(ar933x_mdio_div_table); 
     136        } else if (am->pdata->is_ar7240) { 
     137                table = ar7240_mdio_div_table; 
     138                ndivs = ARRAY_SIZE(ar7240_mdio_div_table); 
     139        } else { 
     140                table = ar71xx_mdio_div_table; 
     141                ndivs = ARRAY_SIZE(ar71xx_mdio_div_table); 
     142        } 
     143 
     144        for (i = 0; i < ndivs; i++) { 
     145                unsigned long t; 
     146 
     147                t = ref_clock / table[i]; 
     148                if (t <= mdio_clock) { 
     149                        *div = i; 
     150                        return 0; 
     151                } 
     152        } 
     153 
     154        dev_err(&am->mii_bus->dev, "no divider found for %lu/%lu\n", 
     155                ref_clock, mdio_clock); 
     156        return -ENOENT; 
     157} 
     158 
    108159static int ag71xx_mdio_reset(struct mii_bus *bus) 
    109160{ 
    110161        struct ag71xx_mdio *am = bus->priv; 
    111162        u32 t; 
    112  
    113         if (am->pdata->is_ar7240) 
    114                 t = MII_CFG_CLK_DIV_6; 
    115         else if (am->pdata->builtin_switch && !am->pdata->is_ar934x) 
    116                 t = MII_CFG_CLK_DIV_10; 
    117         else if (!am->pdata->builtin_switch && am->pdata->is_ar934x) 
    118                 t = MII_CFG_CLK_DIV_58; 
    119         else 
    120                 t = MII_CFG_CLK_DIV_28; 
     163        int err; 
     164 
     165        err = ag71xx_mdio_get_divider(am, &t); 
     166        if (err) { 
     167                /* fallback */ 
     168                if (am->pdata->is_ar7240) 
     169                        t = MII_CFG_CLK_DIV_6; 
     170                else if (am->pdata->builtin_switch && !am->pdata->is_ar934x) 
     171                        t = MII_CFG_CLK_DIV_10; 
     172                else if (!am->pdata->builtin_switch && am->pdata->is_ar934x) 
     173                        t = MII_CFG_CLK_DIV_58; 
     174                else 
     175                        t = MII_CFG_CLK_DIV_28; 
     176        } 
    121177 
    122178        ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t | MII_CFG_RESET); 
Note: See TracChangeset for help on using the changeset viewer.