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_ar7240:1;
|
||||||
u8 is_ar9330:1;
|
u8 is_ar9330:1;
|
||||||
u8 is_ar934x:1;
|
u8 is_ar934x:1;
|
||||||
|
unsigned long mdio_clock;
|
||||||
|
unsigned long ref_clock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ASM_MACH_ATH79_PLATFORM_H */
|
#endif /* __ASM_MACH_ATH79_PLATFORM_H */
|
||||||
|
|
|
@ -105,11 +105,66 @@ void ag71xx_mdio_mii_write(struct ag71xx_mdio *am, int addr, int reg, u16 val)
|
||||||
ag71xx_mdio_wait_busy(am);
|
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)
|
static int ag71xx_mdio_reset(struct mii_bus *bus)
|
||||||
{
|
{
|
||||||
struct ag71xx_mdio *am = bus->priv;
|
struct ag71xx_mdio *am = bus->priv;
|
||||||
u32 t;
|
u32 t;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = ag71xx_mdio_get_divider(am, &t);
|
||||||
|
if (err) {
|
||||||
|
/* fallback */
|
||||||
if (am->pdata->is_ar7240)
|
if (am->pdata->is_ar7240)
|
||||||
t = MII_CFG_CLK_DIV_6;
|
t = MII_CFG_CLK_DIV_6;
|
||||||
else if (am->pdata->builtin_switch && !am->pdata->is_ar934x)
|
else if (am->pdata->builtin_switch && !am->pdata->is_ar934x)
|
||||||
|
@ -118,6 +173,7 @@ static int ag71xx_mdio_reset(struct mii_bus *bus)
|
||||||
t = MII_CFG_CLK_DIV_58;
|
t = MII_CFG_CLK_DIV_58;
|
||||||
else
|
else
|
||||||
t = MII_CFG_CLK_DIV_28;
|
t = MII_CFG_CLK_DIV_28;
|
||||||
|
}
|
||||||
|
|
||||||
ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t | MII_CFG_RESET);
|
ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t | MII_CFG_RESET);
|
||||||
udelay(100);
|
udelay(100);
|
||||||
|
|
Loading…
Reference in New Issue