MIPS: ath79: Add early printk support for the AR933X SoCs
authorGabor Juhos <juhosg@openwrt.org>
Mon, 20 Jun 2011 19:26:03 +0000 (21:26 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 7 Dec 2011 22:02:45 +0000 (22:02 +0000)
The AR933X SoCs are using a different UART, thus require
different code for early printk support.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: Kathy Giori <kgiori@qca.qualcomm.com>
Cc: "Luis R. Rodriguez" <rodrigue@qca.qualcomm.com>
Patchwork: https://patchwork.linux-mips.org/patch/2521/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/ath79/early_printk.c
arch/mips/include/asm/mach-ath79/ar71xx_regs.h
arch/mips/include/asm/mach-ath79/ar933x_uart.h [new file with mode: 0644]

index 7499b0e9df263e38b00181323da58debd0ae00b6..6a51ced7a293fe840351d1e7b0ff5f467784a334 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  Atheros AR71XX/AR724X/AR913X SoC early printk support
+ *  Atheros AR7XXX/AR9XXX SoC early printk support
  *
- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  */
 
 #include <linux/io.h>
+#include <linux/errno.h>
 #include <linux/serial_reg.h>
 #include <asm/addrspace.h>
 
+#include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ar933x_uart.h>
 
-static inline void prom_wait_thre(void __iomem *base)
+static void (*_prom_putchar) (unsigned char);
+
+static inline void prom_putchar_wait(void __iomem *reg, u32 mask, u32 val)
 {
-       u32 lsr;
+       u32 t;
 
        do {
-               lsr = __raw_readl(base + UART_LSR * 4);
-               if (lsr & UART_LSR_THRE)
+               t = __raw_readl(reg);
+               if ((t & mask) == val)
                        break;
        } while (1);
 }
 
-void prom_putchar(unsigned char ch)
+static void prom_putchar_ar71xx(unsigned char ch)
 {
        void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
 
-       prom_wait_thre(base);
+       prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
        __raw_writel(ch, base + UART_TX * 4);
-       prom_wait_thre(base);
+       prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+}
+
+static void prom_putchar_ar933x(unsigned char ch)
+{
+       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 void prom_putchar_dummy(unsigned char ch)
+{
+       /* 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:
+               _prom_putchar = prom_putchar_ar71xx;
+               break;
+
+       case REV_ID_MAJOR_AR9330:
+       case REV_ID_MAJOR_AR9331:
+               _prom_putchar = prom_putchar_ar933x;
+               break;
+
+       default:
+               _prom_putchar = prom_putchar_dummy;
+               break;
+       }
+}
+
+void prom_putchar(unsigned char ch)
+{
+       if (!_prom_putchar)
+               prom_putchar_init();
+
+       _prom_putchar(ch);
 }
index 929be06e1475466cf01810915a9bfefb615bae46..90223f206610ab7eacefbf798748910ed6ab287f 100644 (file)
@@ -53,6 +53,9 @@
 #define AR913X_WMAC_BASE       (AR71XX_APB_BASE + 0x000C0000)
 #define AR913X_WMAC_SIZE       0x30000
 
+#define AR933X_UART_BASE       (AR71XX_APB_BASE + 0x00020000)
+#define AR933X_UART_SIZE       0x14
+
 /*
  * DDR_CTRL block
  */
diff --git a/arch/mips/include/asm/mach-ath79/ar933x_uart.h b/arch/mips/include/asm/mach-ath79/ar933x_uart.h
new file mode 100644 (file)
index 0000000..5273055
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  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_REGS_SIZE          20
+#define AR933X_UART_FIFO_SIZE          16
+
+#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_NONE   0
+#define   AR933X_UART_CS_PARITY_ODD    1
+#define   AR933X_UART_CS_PARITY_EVEN   2
+#define AR933X_UART_CS_IF_MODE_S       2
+#define AR933X_UART_CS_IF_MODE_M       0x3
+#define   AR933X_UART_CS_IF_MODE_NONE  0
+#define   AR933X_UART_CS_IF_MODE_DTE   1
+#define   AR933X_UART_CS_IF_MODE_DCE   2
+#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_CLOCK_SCALE_S      16
+#define AR933X_UART_CLOCK_STEP_M       0xffff
+
+#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 */