MII related infrastructure changes.

* Add a new method to set the MII mode - GMII, RGMII, RMII, MII.
  + arge0 supports all four (two for non-Gige interfaces.)
  + arge1 only supports two (one for non-gige interfaces.)
* Set the MII clock speed when changing the MAC PLL speed.
  + Needed for AR91xx and AR71xx; not needed for AR724x.

Tested:

* AR71xx only, I'll do AR913x testing tonight and fix whichever issues
  creep up.

TODO:

* Implement the missing AR7242 arge0 PLL configuration, but don't
  adjust the MII speed accordingly.
* .. the AR7240/AR7241 don't require this, so make sure it's not set
  accidentally.

Bugs (not fixed here):

* Statically configured arge speeds are still broken - investigate why
  that is on the AP96 board.  Autonegotiate is working fine, but there
  still seems to be an occasionally heavy packet loss issue.

Obtained from: Linux/Atheros/OpenWRT
This commit is contained in:
Adrian Chadd 2012-05-02 01:21:57 +00:00
parent 784bcea8a9
commit da88453012
5 changed files with 70 additions and 0 deletions

View File

@ -176,6 +176,50 @@ ar71xx_chip_set_mii_speed(uint32_t unit, uint32_t speed)
ATH_WRITE_REG(reg, val);
}
void
ar71xx_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
{
uint32_t val, reg, mii_if;
switch (unit) {
case 0:
reg = AR71XX_MII0_CTRL;
if (mii_mode == AR71XX_MII_MODE_GMII)
mii_if = MII0_CTRL_IF_GMII;
else if (mii_mode == AR71XX_MII_MODE_MII)
mii_if = MII0_CTRL_IF_MII;
else if (mii_mode == AR71XX_MII_MODE_RGMII)
mii_if = MII0_CTRL_IF_RGMII;
else if (mii_mode == AR71XX_MII_MODE_RMII)
mii_if = MII0_CTRL_IF_RMII;
else
printf("%s: invalid MII mode (%d) for unit %d\n",
__func__, mii_mode, unit);
return;
break;
case 1:
reg = AR71XX_MII1_CTRL;
if (mii_mode == AR71XX_MII_MODE_RGMII)
mii_if = MII1_CTRL_IF_RGMII;
if (mii_mode == AR71XX_MII_MODE_RMII)
mii_if = MII1_CTRL_IF_RMII;
else
printf("%s: invalid MII mode (%d) for unit %d\n",
__func__, mii_mode, unit);
return;
break;
default:
printf("%s: invalid MII unit set for arge unit: %d\n",
__func__, unit);
return;
}
val = ATH_READ_REG(reg);
val &= ~(MII_CTRL_IF_MASK << MII_CTRL_IF_SHIFT);
val |= (mii_if & MII_CTRL_IF_MASK) << MII_CTRL_IF_SHIFT;
ATH_WRITE_REG(reg, val);
}
/* Speed is either 10, 100 or 1000 */
static void
ar71xx_chip_set_pll_ge(int unit, int speed)
@ -197,6 +241,7 @@ ar71xx_chip_set_pll_ge(int unit, int speed)
__func__, unit, speed);
return;
}
switch (unit) {
case 0:
ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
@ -213,6 +258,12 @@ ar71xx_chip_set_pll_ge(int unit, int speed)
__func__, unit);
return;
}
/*
* AR71xx and AR913x require this; AR724x doesn't require
* an MII clock change at all.
*/
ar71xx_chip_set_mii_speed(unit, speed);
}
static void
@ -278,6 +329,7 @@ struct ar71xx_cpu_def ar71xx_chip_def = {
&ar71xx_chip_device_stopped,
&ar71xx_chip_set_pll_ge,
&ar71xx_chip_set_mii_speed,
&ar71xx_chip_set_mii_if,
&ar71xx_chip_ddr_flush_ge,
&ar71xx_chip_get_eth_pll,
&ar71xx_chip_ddr_flush_ip2,

View File

@ -31,5 +31,6 @@
extern struct ar71xx_cpu_def ar71xx_chip_def;
extern void ar71xx_chip_set_mii_speed(uint32_t unit, uint32_t speed);
extern void ar71xx_chip_set_mii_if(uint32_t unit, uint32_t mii_if);
#endif

View File

@ -37,6 +37,7 @@ struct ar71xx_cpu_def {
int (* ar71xx_chip_device_stopped) (uint32_t);
void (* ar71xx_chip_set_pll_ge) (int, int);
void (* ar71xx_chip_set_mii_speed) (uint32_t, uint32_t);
void (* ar71xx_chip_set_mii_if) (uint32_t, ar71xx_mii_mode);
void (* ar71xx_chip_ddr_flush_ge) (int);
uint32_t (* ar71xx_chip_get_eth_pll) (unsigned int, int);
@ -90,6 +91,11 @@ static inline void ar71xx_device_set_mii_speed(int unit, int speed)
ar71xx_cpu_ops->ar71xx_chip_set_mii_speed(unit, speed);
}
static inline void ar71xx_device_set_mii_if(int unit, ar71xx_mii_mode mii_cfg)
{
ar71xx_cpu_ops->ar71xx_chip_set_mii_if(unit, mii_cfg);
}
static inline void ar71xx_device_flush_ddr_ge(int unit)
{
ar71xx_cpu_ops->ar71xx_chip_ddr_flush_ge(unit);

View File

@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <mips/atheros/ar71xx_cpudef.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_chip.h>
#include <mips/atheros/ar724x_chip.h>
#include <mips/sentry5/s5reg.h>
@ -130,6 +131,13 @@ ar724x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
return;
}
/*
* XXX TODO: set the PLL for arge0 only on AR7242.
* The PLL/clock requirements are different.
*
* Otherwise, it's a NULL function for AR7240, AR7241 and
* AR7242 arge1.
*/
static void
ar724x_chip_set_pll_ge(int unit, int speed)
{
@ -229,6 +237,7 @@ struct ar71xx_cpu_def ar724x_chip_def = {
&ar724x_chip_device_stopped,
&ar724x_chip_set_pll_ge,
&ar724x_chip_set_mii_speed,
&ar71xx_chip_set_mii_if,
&ar724x_chip_ddr_flush_ge,
&ar724x_chip_get_eth_pll,
&ar724x_chip_ddr_flush_ip2,

View File

@ -147,6 +147,7 @@ ar91xx_chip_set_pll_ge(int unit, int speed)
__func__, unit);
return;
}
ar71xx_chip_set_mii_speed(unit, speed);
}
static void
@ -211,6 +212,7 @@ struct ar71xx_cpu_def ar91xx_chip_def = {
&ar91xx_chip_device_stopped,
&ar91xx_chip_set_pll_ge,
&ar71xx_chip_set_mii_speed,
&ar71xx_chip_set_mii_if,
&ar91xx_chip_ddr_flush_ge,
&ar91xx_chip_get_eth_pll,
&ar91xx_chip_ddr_flush_ip2,