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_reg.h>
12 #include <asm/addrspace.h>
13 #include <asm/setup.h>
15 #include <asm/mach-ath79/ath79.h>
16 #include <asm/mach-ath79/ar71xx_regs.h>
17 #include <asm/mach-ath79/ar933x_uart.h>
19 static void (*_prom_putchar
)(char);
21 static inline void prom_putchar_wait(void __iomem
*reg
, u32 mask
, u32 val
)
27 if ((t
& mask
) == val
)
32 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
34 static void prom_putchar_ar71xx(char ch
)
36 void __iomem
*base
= (void __iomem
*)(KSEG1ADDR(AR71XX_UART_BASE
));
38 prom_putchar_wait(base
+ UART_LSR
* 4, BOTH_EMPTY
, BOTH_EMPTY
);
39 __raw_writel((unsigned char)ch
, base
+ UART_TX
* 4);
40 prom_putchar_wait(base
+ UART_LSR
* 4, BOTH_EMPTY
, BOTH_EMPTY
);
43 static void prom_putchar_ar933x(char ch
)
45 void __iomem
*base
= (void __iomem
*)(KSEG1ADDR(AR933X_UART_BASE
));
47 prom_putchar_wait(base
+ AR933X_UART_DATA_REG
, AR933X_UART_DATA_TX_CSR
,
48 AR933X_UART_DATA_TX_CSR
);
49 __raw_writel(AR933X_UART_DATA_TX_CSR
| (unsigned char)ch
,
50 base
+ AR933X_UART_DATA_REG
);
51 prom_putchar_wait(base
+ AR933X_UART_DATA_REG
, AR933X_UART_DATA_TX_CSR
,
52 AR933X_UART_DATA_TX_CSR
);
55 static void prom_putchar_dummy(char ch
)
60 static void prom_enable_uart(u32 id
)
62 void __iomem
*gpio_base
;
67 case REV_ID_MAJOR_AR71XX
:
68 uart_en
= AR71XX_GPIO_FUNC_UART_EN
;
71 case REV_ID_MAJOR_AR7240
:
72 case REV_ID_MAJOR_AR7241
:
73 case REV_ID_MAJOR_AR7242
:
74 uart_en
= AR724X_GPIO_FUNC_UART_EN
;
77 case REV_ID_MAJOR_AR913X
:
78 uart_en
= AR913X_GPIO_FUNC_UART_EN
;
81 case REV_ID_MAJOR_AR9330
:
82 case REV_ID_MAJOR_AR9331
:
83 uart_en
= AR933X_GPIO_FUNC_UART_EN
;
86 case REV_ID_MAJOR_AR9341
:
87 case REV_ID_MAJOR_AR9342
:
88 case REV_ID_MAJOR_AR9344
:
94 gpio_base
= (void __iomem
*)KSEG1ADDR(AR71XX_GPIO_BASE
);
95 t
= __raw_readl(gpio_base
+ AR71XX_GPIO_REG_FUNC
);
97 __raw_writel(t
, gpio_base
+ AR71XX_GPIO_REG_FUNC
);
100 static void prom_putchar_init(void)
105 base
= (void __iomem
*)(KSEG1ADDR(AR71XX_RESET_BASE
));
106 id
= __raw_readl(base
+ AR71XX_RESET_REG_REV_ID
);
107 id
&= REV_ID_MAJOR_MASK
;
110 case REV_ID_MAJOR_AR71XX
:
111 case REV_ID_MAJOR_AR7240
:
112 case REV_ID_MAJOR_AR7241
:
113 case REV_ID_MAJOR_AR7242
:
114 case REV_ID_MAJOR_AR913X
:
115 case REV_ID_MAJOR_AR9341
:
116 case REV_ID_MAJOR_AR9342
:
117 case REV_ID_MAJOR_AR9344
:
118 case REV_ID_MAJOR_QCA9533
:
119 case REV_ID_MAJOR_QCA9533_V2
:
120 case REV_ID_MAJOR_QCA9556
:
121 case REV_ID_MAJOR_QCA9558
:
122 case REV_ID_MAJOR_TP9343
:
123 case REV_ID_MAJOR_QCA956X
:
124 _prom_putchar
= prom_putchar_ar71xx
;
127 case REV_ID_MAJOR_AR9330
:
128 case REV_ID_MAJOR_AR9331
:
129 _prom_putchar
= prom_putchar_ar933x
;
133 _prom_putchar
= prom_putchar_dummy
;
137 prom_enable_uart(id
);
140 void prom_putchar(char ch
)