ramips: Power down phy on disabled switch ports
Power down phy on disabled switch ports. Haven't measured this myself yet, but according to this http://www.8devices.com/community/viewtopic.php?f=6&t=156 it can save about 300mW of power. [juhosg: fix checkpatch warning] Signed-off-by: Tobias Diedrich <ranma+openwrt@tdiedrich.de> SVN-Revision: 33304
This commit is contained in:
parent
1617f226a9
commit
bc4763a399
1 changed files with 67 additions and 5 deletions
|
@ -1,5 +1,6 @@
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/switch.h>
|
#include <linux/switch.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
|
||||||
#include <rt305x_regs.h>
|
#include <rt305x_regs.h>
|
||||||
#include <rt305x_esw_platform.h>
|
#include <rt305x_esw_platform.h>
|
||||||
|
@ -326,6 +327,57 @@ rt305x_esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc)
|
||||||
(msc & RT305X_ESW_VMSC_MSC_M) << s);
|
(msc & RT305X_ESW_VMSC_MSC_M) << s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
rt305x_esw_get_port_disable(struct rt305x_esw *esw)
|
||||||
|
{
|
||||||
|
unsigned reg;
|
||||||
|
reg = rt305x_esw_rr(esw, RT305X_ESW_REG_POC0);
|
||||||
|
return (reg >> RT305X_ESW_POC0_DIS_PORT_S) &
|
||||||
|
RT305X_ESW_POC0_DIS_PORT_M;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rt305x_esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask)
|
||||||
|
{
|
||||||
|
unsigned old_mask;
|
||||||
|
unsigned enable_mask;
|
||||||
|
unsigned changed;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
old_mask = rt305x_esw_get_port_disable(esw);
|
||||||
|
changed = old_mask ^ disable_mask;
|
||||||
|
enable_mask = old_mask & disable_mask;
|
||||||
|
|
||||||
|
/* enable before writing to MII */
|
||||||
|
rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0,
|
||||||
|
(RT305X_ESW_POC0_DIS_PORT_M <<
|
||||||
|
RT305X_ESW_POC0_DIS_PORT_S),
|
||||||
|
enable_mask << RT305X_ESW_POC0_DIS_PORT_S);
|
||||||
|
|
||||||
|
for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) {
|
||||||
|
if (!(changed & (1 << i)))
|
||||||
|
continue;
|
||||||
|
if (disable_mask & (1 << i)) {
|
||||||
|
/* disable */
|
||||||
|
rt305x_mii_write(esw, i, MII_BMCR,
|
||||||
|
BMCR_PDOWN);
|
||||||
|
} else {
|
||||||
|
/* enable */
|
||||||
|
rt305x_mii_write(esw, i, MII_BMCR,
|
||||||
|
BMCR_FULLDPLX |
|
||||||
|
BMCR_ANENABLE |
|
||||||
|
BMCR_ANRESTART |
|
||||||
|
BMCR_SPEED100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disable after writing to MII */
|
||||||
|
rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0,
|
||||||
|
(RT305X_ESW_POC0_DIS_PORT_M <<
|
||||||
|
RT305X_ESW_POC0_DIS_PORT_S),
|
||||||
|
disable_mask << RT305X_ESW_POC0_DIS_PORT_S);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rt305x_esw_apply_config(struct switch_dev *dev);
|
rt305x_esw_apply_config(struct switch_dev *dev);
|
||||||
|
|
||||||
|
@ -333,6 +385,7 @@ static void
|
||||||
rt305x_esw_hw_init(struct rt305x_esw *esw)
|
rt305x_esw_hw_init(struct rt305x_esw *esw)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
u8 port_disable = 0;
|
||||||
u8 port_map = RT305X_ESW_PMAP_LLLLLL;
|
u8 port_map = RT305X_ESW_PMAP_LLLLLL;
|
||||||
|
|
||||||
/* vodoo from original driver */
|
/* vodoo from original driver */
|
||||||
|
@ -384,10 +437,21 @@ rt305x_esw_hw_init(struct rt305x_esw *esw)
|
||||||
rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P3LED);
|
rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P3LED);
|
||||||
rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P4LED);
|
rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P4LED);
|
||||||
|
|
||||||
|
/* Copy disabled port configuration from bootloader setup */
|
||||||
|
port_disable = rt305x_esw_get_port_disable(esw);
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
esw->ports[i].disable = (port_disable & (1 << i)) != 0;
|
||||||
|
|
||||||
rt305x_mii_write(esw, 0, 31, 0x8000);
|
rt305x_mii_write(esw, 0, 31, 0x8000);
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
/* TX10 waveform coefficient */
|
if (esw->ports[i].disable) {
|
||||||
rt305x_mii_write(esw, i, 0, 0x3100);
|
rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
|
||||||
|
} else {
|
||||||
|
rt305x_mii_write(esw, i, MII_BMCR,
|
||||||
|
BMCR_FULLDPLX |
|
||||||
|
BMCR_ANENABLE |
|
||||||
|
BMCR_SPEED100);
|
||||||
|
}
|
||||||
/* TX10 waveform coefficient */
|
/* TX10 waveform coefficient */
|
||||||
rt305x_mii_write(esw, i, 26, 0x1601);
|
rt305x_mii_write(esw, i, 26, 0x1601);
|
||||||
/* TX100/TX10 AD/DA current bias */
|
/* TX100/TX10 AD/DA current bias */
|
||||||
|
@ -482,9 +546,7 @@ rt305x_esw_apply_config(struct switch_dev *dev)
|
||||||
RT305X_ESW_REG_P0LED + 4*i);
|
RT305X_ESW_REG_P0LED + 4*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0,
|
rt305x_esw_set_port_disable(esw, disable);
|
||||||
RT305X_ESW_POC0_DIS_PORT_M << RT305X_ESW_POC0_DIS_PORT_S,
|
|
||||||
disable << RT305X_ESW_POC0_DIS_PORT_S);
|
|
||||||
rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2,
|
rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2,
|
||||||
(RT305X_ESW_SGC2_DOUBLE_TAG_M <<
|
(RT305X_ESW_SGC2_DOUBLE_TAG_M <<
|
||||||
RT305X_ESW_SGC2_DOUBLE_TAG_S),
|
RT305X_ESW_SGC2_DOUBLE_TAG_S),
|
||||||
|
|
Loading…
Reference in a new issue