diff options
-rw-r--r-- | target/linux/ar71xx/files/arch/mips/ar71xx/early_printk.c | 98 | ||||
-rw-r--r-- | target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h | 58 |
2 files changed, 112 insertions, 44 deletions
diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/early_printk.c b/target/linux/ar71xx/files/arch/mips/ar71xx/early_printk.c index f84c76d75..c85a04d2c 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/early_printk.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/early_printk.c @@ -15,72 +15,82 @@ #include <asm/addrspace.h> #include <asm/mach-ar71xx/ar71xx.h> +#include <asm/mach-ar71xx/ar933x_uart.h> -static void __iomem *prom_uart_base; -static void (*_putchar)(unsigned char); +static void (*_prom_putchar) (unsigned char); -#define UART_READ(r) \ - __raw_readl(prom_uart_base + 4 * (r)) +static inline void prom_putchar_wait(void __iomem *reg, u32 mask, u32 val) +{ + u32 t; -#define UART_WRITE(r, v) \ - __raw_writel((v), prom_uart_base + 4 * (r)) + do { + t = __raw_readl(reg); + if ((t & mask) == val) + break; + } while (1); +} static void prom_putchar_ar71xx(unsigned char ch) { - while (((UART_READ(UART_LSR)) & UART_LSR_THRE) == 0) - ; - UART_WRITE(UART_TX, ch); - while (((UART_READ(UART_LSR)) & UART_LSR_THRE) == 0) - ; + void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE)); + + prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE); + __raw_writel(ch, base + UART_TX * 4); + prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE); } static void prom_putchar_ar933x(unsigned char ch) { - while (((UART_READ(0)) & 0x200) == 0) - ; - UART_WRITE(0, 0x200 | ch); - while (((UART_READ(0)) & 0x200) == 0) - ; + void __iomem *base = (void __iomem *)(KSEG1ADDR(AR933X_UART_BASE)); + + prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR, + AR933X_UART_DATA_TX_CSR); + __raw_writel(AR933X_UART_DATA_TX_CSR | ch, base + AR933X_UART_DATA_REG); + prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR, + AR933X_UART_DATA_TX_CSR); } -static int prom_putchar_init(void) +static void prom_putchar_dummy(unsigned char ch) { - if (_putchar) - return 0; - - switch(ar71xx_soc) { - case AR71XX_SOC_AR7130: - case AR71XX_SOC_AR7141: - case AR71XX_SOC_AR7161: - case AR71XX_SOC_AR7240: - case AR71XX_SOC_AR7241: - case AR71XX_SOC_AR7242: - case AR71XX_SOC_AR9130: - case AR71XX_SOC_AR9132: - case AR71XX_SOC_AR9341: - case AR71XX_SOC_AR9342: - case AR71XX_SOC_AR9344: - prom_uart_base = (void __iomem *) KSEG1ADDR(AR71XX_UART_BASE); - _putchar = prom_putchar_ar71xx; + /* nothing to do */ +} + +static void prom_putchar_init(void) +{ + void __iomem *base; + u32 id; + + base = (void __iomem *)(KSEG1ADDR(AR71XX_RESET_BASE)); + id = __raw_readl(base + AR71XX_RESET_REG_REV_ID); + id &= REV_ID_MAJOR_MASK; + + switch (id) { + case REV_ID_MAJOR_AR71XX: + case REV_ID_MAJOR_AR7240: + case REV_ID_MAJOR_AR7241: + case REV_ID_MAJOR_AR7242: + case REV_ID_MAJOR_AR913X: + case REV_ID_MAJOR_AR9341: + case REV_ID_MAJOR_AR9342: + case REV_ID_MAJOR_AR9344: + _prom_putchar = prom_putchar_ar71xx; break; - case AR71XX_SOC_AR9330: - case AR71XX_SOC_AR9331: - prom_uart_base = (void __iomem *) KSEG1ADDR(AR933X_UART_BASE); - _putchar = prom_putchar_ar933x; + case REV_ID_MAJOR_AR9330: + case REV_ID_MAJOR_AR9331: + _prom_putchar = prom_putchar_ar933x; break; default: - return -ENODEV; + _prom_putchar = prom_putchar_dummy; + break; } - - return 0; } void prom_putchar(unsigned char ch) { - if (prom_putchar_init()) - return; + if (!_prom_putchar) + prom_putchar_init(); - _putchar(ch); + _prom_putchar(ch); } diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h new file mode 100644 index 000000000..edb13cd01 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h @@ -0,0 +1,58 @@ +/* + * Atheros AR933X UART defines + * + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef __AR933X_UART_H +#define __AR933X_UART_H + +#define AR933X_UART_DATA_REG 0x00 +#define AR933X_UART_CS_REG 0x04 +#define AR933X_UART_CLOCK_REG 0x08 +#define AR933X_UART_INT_REG 0x0c +#define AR933X_UART_INT_EN_REG 0x10 + +#define AR933X_UART_DATA_TX_RX_MASK 0xff +#define AR933X_UART_DATA_RX_CSR BIT(8) +#define AR933X_UART_DATA_TX_CSR BIT(9) + +#define AR933X_UART_CS_PARITY_S 0 +#define AR933X_UART_CS_PARITY_M 0x3 +#define AR933X_UART_CS_PARITY_M 0x3 +#define AR933X_UART_CS_IF_MODE_S 2 +#define AR933X_UART_CS_IF_MODE_M 0x3 +#define AR933X_UART_CS_FLOW_CTRL_S 4 +#define AR933X_UART_CS_FLOW_CTRL_M 0x3 +#define AR933X_UART_CS_DMA_EN BIT(6) +#define AR933X_UART_CS_TX_READY_ORIDE BIT(7) +#define AR933X_UART_CS_RX_READY_ORIDE BIT(8) +#define AR933X_UART_CS_TX_READY BIT(9) +#define AR933X_UART_CS_RX_BREAK BIT(10) +#define AR933X_UART_CS_TX_BREAK BIT(11) +#define AR933X_UART_CS_HOST_INT BIT(12) +#define AR933X_UART_CS_HOST_INT_EN BIT(13) +#define AR933X_UART_CS_TX_BUSY BIT(14) +#define AR933X_UART_CS_RX_BUSY BIT(15) + +#define AR933X_UART_CLOCK_STEP_M 0xffff +#define AR933X_UART_CLOCK_SCALE_M 0xfff +#define AR933X_UART_CLCOK_SCALE_S 16 + +#define AR933X_UART_INT_RX_VALID BIT(0) +#define AR933X_UART_INT_TX_READY BIT(1) +#define AR933X_UART_INT_RX_FRAMING_ERR BIT(2) +#define AR933X_UART_INT_RX_OFLOW_ERR BIT(3) +#define AR933X_UART_INT_TX_OFLOW_ERR BIT(4) +#define AR933X_UART_INT_RX_PARITY_ERR BIT(5) +#define AR933X_UART_INT_RX_BREAK_ON BIT(6) +#define AR933X_UART_INT_RX_BREAK_OFF BIT(7) +#define AR933X_UART_INT_RX_FULL BIT(8) +#define AR933X_UART_INT_TX_EMPTY BIT(9) +#define AR933X_UART_INT_ALLINTS 0x3ff + +#endif /* __AR933X_UART_H */ |