|
|
|
@ -105,19 +105,75 @@ void ag71xx_mdio_mii_write(struct ag71xx_mdio *am, int addr, int reg, u16 val) |
|
|
|
|
ag71xx_mdio_wait_busy(am); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const u32 ar71xx_mdio_div_table[] = { |
|
|
|
|
4, 4, 6, 8, 10, 14, 20, 28, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const u32 ar7240_mdio_div_table[] = { |
|
|
|
|
2, 2, 4, 6, 8, 12, 18, 26, 32, 40, 48, 56, 62, 70, 78, 96, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const u32 ar933x_mdio_div_table[] = { |
|
|
|
|
4, 4, 6, 8, 10, 14, 20, 28, 34, 42, 50, 58, 66, 74, 82, 98, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int ag71xx_mdio_get_divider(struct ag71xx_mdio *am, u32 *div) |
|
|
|
|
{ |
|
|
|
|
unsigned long ref_clock, mdio_clock; |
|
|
|
|
const u32 *table; |
|
|
|
|
int ndivs; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
ref_clock = am->pdata->ref_clock; |
|
|
|
|
mdio_clock = am->pdata->mdio_clock; |
|
|
|
|
|
|
|
|
|
if (!ref_clock || !mdio_clock) |
|
|
|
|
return -EINVAL; |
|
|
|
|
|
|
|
|
|
if (am->pdata->is_ar9330 || am->pdata->is_ar934x) { |
|
|
|
|
table = ar933x_mdio_div_table; |
|
|
|
|
ndivs = ARRAY_SIZE(ar933x_mdio_div_table); |
|
|
|
|
} else if (am->pdata->is_ar7240) { |
|
|
|
|
table = ar7240_mdio_div_table; |
|
|
|
|
ndivs = ARRAY_SIZE(ar7240_mdio_div_table); |
|
|
|
|
} else { |
|
|
|
|
table = ar71xx_mdio_div_table; |
|
|
|
|
ndivs = ARRAY_SIZE(ar71xx_mdio_div_table); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ndivs; i++) { |
|
|
|
|
unsigned long t; |
|
|
|
|
|
|
|
|
|
t = ref_clock / table[i]; |
|
|
|
|
if (t <= mdio_clock) { |
|
|
|
|
*div = i; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dev_err(&am->mii_bus->dev, "no divider found for %lu/%lu\n", |
|
|
|
|
ref_clock, mdio_clock); |
|
|
|
|
return -ENOENT; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ag71xx_mdio_reset(struct mii_bus *bus) |
|
|
|
|
{ |
|
|
|
|
struct ag71xx_mdio *am = bus->priv; |
|
|
|
|
u32 t; |
|
|
|
|
int err; |
|
|
|
|
|
|
|
|
|
if (am->pdata->is_ar7240) |
|
|
|
|
t = MII_CFG_CLK_DIV_6; |
|
|
|
|
else if (am->pdata->builtin_switch && !am->pdata->is_ar934x) |
|
|
|
|
t = MII_CFG_CLK_DIV_10; |
|
|
|
|
else if (!am->pdata->builtin_switch && am->pdata->is_ar934x) |
|
|
|
|
t = MII_CFG_CLK_DIV_58; |
|
|
|
|
else |
|
|
|
|
t = MII_CFG_CLK_DIV_28; |
|
|
|
|
err = ag71xx_mdio_get_divider(am, &t); |
|
|
|
|
if (err) { |
|
|
|
|
/* fallback */ |
|
|
|
|
if (am->pdata->is_ar7240) |
|
|
|
|
t = MII_CFG_CLK_DIV_6; |
|
|
|
|
else if (am->pdata->builtin_switch && !am->pdata->is_ar934x) |
|
|
|
|
t = MII_CFG_CLK_DIV_10; |
|
|
|
|
else if (!am->pdata->builtin_switch && am->pdata->is_ar934x) |
|
|
|
|
t = MII_CFG_CLK_DIV_58; |
|
|
|
|
else |
|
|
|
|
t = MII_CFG_CLK_DIV_28; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t | MII_CFG_RESET); |
|
|
|
|
udelay(100); |
|
|
|
|