1 // SPDX-License-Identifier: GPL-2.0-only
3 * Atheros AR7XXX/AR9XXX SoC early printk support
5 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
6 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
10 #include <linux/errno.h>
11 #include <linux/serial.h>
12 #include <linux/serial_reg.h>
13 #include <asm/addrspace.h>
14 #include <asm/setup.h>
16 #include <asm/mach-ath79/ath79.h>
17 #include <asm/mach-ath79/ar71xx_regs.h>
18 #include <asm/mach-ath79/ar933x_uart.h>
20 static void (*_prom_putchar
)(char);
22 static inline void prom_putchar_wait(void __iomem
*reg
, u32 val
)
33 static void prom_putchar_ar71xx(char ch
)
35 void __iomem
*base
= (void __iomem
*)(KSEG1ADDR(AR71XX_UART_BASE
));
37 prom_putchar_wait(base
+ UART_LSR
* 4, UART_LSR_BOTH_EMPTY
);
38 __raw_writel((unsigned char)ch
, base
+ UART_TX
* 4);
39 prom_putchar_wait(base
+ UART_LSR
* 4, UART_LSR_BOTH_EMPTY
);
42 static void prom_putchar_ar933x(char ch
)
44 void __iomem
*base
= (void __iomem
*)(KSEG1ADDR(AR933X_UART_BASE
));
46 prom_putchar_wait(base
+ AR933X_UART_DATA_REG
, AR933X_UART_DATA_TX_CSR
);
47 __raw_writel(AR933X_UART_DATA_TX_CSR
| (unsigned char)ch
,
48 base
+ AR933X_UART_DATA_REG
);
49 prom_putchar_wait(base
+ AR933X_UART_DATA_REG
, AR933X_UART_DATA_TX_CSR
);
52 static void prom_putchar_dummy(char ch
)
57 static void prom_enable_uart(u32 id
)
59 void __iomem
*gpio_base
;
64 case REV_ID_MAJOR_AR71XX
:
65 uart_en
= AR71XX_GPIO_FUNC_UART_EN
;
68 case REV_ID_MAJOR_AR7240
:
69 case REV_ID_MAJOR_AR7241
:
70 case REV_ID_MAJOR_AR7242
:
71 uart_en
= AR724X_GPIO_FUNC_UART_EN
;
74 case REV_ID_MAJOR_AR913X
:
75 uart_en
= AR913X_GPIO_FUNC_UART_EN
;
78 case REV_ID_MAJOR_AR9330
:
79 case REV_ID_MAJOR_AR9331
:
80 uart_en
= AR933X_GPIO_FUNC_UART_EN
;
83 case REV_ID_MAJOR_AR9341
:
84 case REV_ID_MAJOR_AR9342
:
85 case REV_ID_MAJOR_AR9344
:
91 gpio_base
= (void __iomem
*)KSEG1ADDR(AR71XX_GPIO_BASE
);
92 t
= __raw_readl(gpio_base
+ AR71XX_GPIO_REG_FUNC
);
94 __raw_writel(t
, gpio_base
+ AR71XX_GPIO_REG_FUNC
);
97 static void prom_putchar_init(void)
102 base
= (void __iomem
*)(KSEG1ADDR(AR71XX_RESET_BASE
));
103 id
= __raw_readl(base
+ AR71XX_RESET_REG_REV_ID
);
104 id
&= REV_ID_MAJOR_MASK
;
107 case REV_ID_MAJOR_AR71XX
:
108 case REV_ID_MAJOR_AR7240
:
109 case REV_ID_MAJOR_AR7241
:
110 case REV_ID_MAJOR_AR7242
:
111 case REV_ID_MAJOR_AR913X
:
112 case REV_ID_MAJOR_AR9341
:
113 case REV_ID_MAJOR_AR9342
:
114 case REV_ID_MAJOR_AR9344
:
115 case REV_ID_MAJOR_QCA9533
:
116 case REV_ID_MAJOR_QCA9533_V2
:
117 case REV_ID_MAJOR_QCA9556
:
118 case REV_ID_MAJOR_QCA9558
:
119 case REV_ID_MAJOR_TP9343
:
120 case REV_ID_MAJOR_QCA956X
:
121 case REV_ID_MAJOR_QCN550X
:
122 _prom_putchar
= prom_putchar_ar71xx
;
125 case REV_ID_MAJOR_AR9330
:
126 case REV_ID_MAJOR_AR9331
:
127 _prom_putchar
= prom_putchar_ar933x
;
131 _prom_putchar
= prom_putchar_dummy
;
135 prom_enable_uart(id
);
138 void prom_putchar(char ch
)