ar71xx: add dynamic MDIO clock calculation
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@33342 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
2ef5213899
commit
773fa9a77f
|
@ -53,6 +53,8 @@ struct ag71xx_mdio_platform_data {
|
|||
u8 is_ar7240:1;
|
||||
u8 is_ar9330:1;
|
||||
u8 is_ar934x:1;
|
||||
unsigned long mdio_clock;
|
||||
unsigned long ref_clock;
|
||||
};
|
||||
|
||||
#endif /* __ASM_MACH_ATH79_PLATFORM_H */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue