diff options
Diffstat (limited to 'arch/mips/alchemy/common/platform.c')
-rw-r--r-- | arch/mips/alchemy/common/platform.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index f9e5622ebc95..3691630931d6 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -12,6 +12,7 @@ */ #include <linux/dma-mapping.h> +#include <linux/etherdevice.h> #include <linux/platform_device.h> #include <linux/serial_8250.h> #include <linux/init.h> @@ -21,6 +22,35 @@ #include <asm/mach-au1x00/au1100_mmc.h> #include <asm/mach-au1x00/au1xxx_eth.h> +#include <prom.h> + +static void alchemy_8250_pm(struct uart_port *port, unsigned int state, + unsigned int old_state) +{ + switch (state) { + case 0: + if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) { + /* power-on sequence as suggested in the databooks */ + __raw_writel(0, port->membase + UART_MOD_CNTRL); + wmb(); + __raw_writel(1, port->membase + UART_MOD_CNTRL); + wmb(); + } + __raw_writel(3, port->membase + UART_MOD_CNTRL); /* full on */ + wmb(); + serial8250_do_pm(port, state, old_state); + break; + case 3: /* power off */ + serial8250_do_pm(port, state, old_state); + __raw_writel(0, port->membase + UART_MOD_CNTRL); + wmb(); + break; + default: + serial8250_do_pm(port, state, old_state); + break; + } +} + #define PORT(_base, _irq) \ { \ .mapbase = _base, \ @@ -30,10 +60,10 @@ .flags = UPF_SKIP_TEST | UPF_IOREMAP | \ UPF_FIXED_TYPE, \ .type = PORT_16550A, \ + .pm = alchemy_8250_pm, \ } static struct plat_serial8250_port au1x00_uart_data[] = { -#if defined(CONFIG_SERIAL_8250_AU1X00) #if defined(CONFIG_SOC_AU1000) PORT(UART0_PHYS_ADDR, AU1000_UART0_INT), PORT(UART1_PHYS_ADDR, AU1000_UART1_INT), @@ -54,7 +84,6 @@ static struct plat_serial8250_port au1x00_uart_data[] = { PORT(UART0_PHYS_ADDR, AU1200_UART0_INT), PORT(UART1_PHYS_ADDR, AU1200_UART1_INT), #endif -#endif /* CONFIG_SERIAL_8250_AU1X00 */ { }, }; @@ -436,17 +465,27 @@ static int __init au1xxx_platform_init(void) { unsigned int uartclk = get_au1x00_uart_baud_base() * 16; int err, i; + unsigned char ethaddr[6]; /* Fill up uartclk. */ for (i = 0; au1x00_uart_data[i].flags; i++) au1x00_uart_data[i].uartclk = uartclk; + /* use firmware-provided mac addr if available and necessary */ + i = prom_get_ethernet_addr(ethaddr); + if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac)) + memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6); + err = platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices)); #ifndef CONFIG_SOC_AU1100 + ethaddr[5] += 1; /* next addr for 2nd MAC */ + if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac)) + memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6); + /* Register second MAC if enabled in pinfunc */ if (!err && !(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) - platform_device_register(&au1xxx_eth1_device); + err = platform_device_register(&au1xxx_eth1_device); #endif return err; |