xref: /linux/arch/mips/ath79/early_printk.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d4a67d9dSGabor Juhos /*
30bd3acdfSGabor Juhos  *  Atheros AR7XXX/AR9XXX SoC early printk support
4d4a67d9dSGabor Juhos  *
50bd3acdfSGabor Juhos  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
6d4a67d9dSGabor Juhos  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7d4a67d9dSGabor Juhos  */
8d4a67d9dSGabor Juhos 
9d4a67d9dSGabor Juhos #include <linux/io.h>
100bd3acdfSGabor Juhos #include <linux/errno.h>
1134619de1SIlpo Järvinen #include <linux/serial.h>
12d4a67d9dSGabor Juhos #include <linux/serial_reg.h>
13d4a67d9dSGabor Juhos #include <asm/addrspace.h>
145c93316cSAlexander Sverdlin #include <asm/setup.h>
15d4a67d9dSGabor Juhos 
160bd3acdfSGabor Juhos #include <asm/mach-ath79/ath79.h>
17d4a67d9dSGabor Juhos #include <asm/mach-ath79/ar71xx_regs.h>
180bd3acdfSGabor Juhos #include <asm/mach-ath79/ar933x_uart.h>
19d4a67d9dSGabor Juhos 
205c93316cSAlexander Sverdlin static void (*_prom_putchar)(char);
210bd3acdfSGabor Juhos 
prom_putchar_wait(void __iomem * reg,u32 val)22*60b21490SIlpo Järvinen static inline void prom_putchar_wait(void __iomem *reg, u32 val)
23d4a67d9dSGabor Juhos {
240bd3acdfSGabor Juhos 	u32 t;
25d4a67d9dSGabor Juhos 
26d4a67d9dSGabor Juhos 	do {
270bd3acdfSGabor Juhos 		t = __raw_readl(reg);
28*60b21490SIlpo Järvinen 		if ((t & val) == val)
29d4a67d9dSGabor Juhos 			break;
30d4a67d9dSGabor Juhos 	} while (1);
31d4a67d9dSGabor Juhos }
32d4a67d9dSGabor Juhos 
prom_putchar_ar71xx(char ch)335c93316cSAlexander Sverdlin static void prom_putchar_ar71xx(char ch)
34d4a67d9dSGabor Juhos {
35d4a67d9dSGabor Juhos 	void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
36d4a67d9dSGabor Juhos 
37*60b21490SIlpo Järvinen 	prom_putchar_wait(base + UART_LSR * 4, UART_LSR_BOTH_EMPTY);
385c93316cSAlexander Sverdlin 	__raw_writel((unsigned char)ch, base + UART_TX * 4);
39*60b21490SIlpo Järvinen 	prom_putchar_wait(base + UART_LSR * 4, UART_LSR_BOTH_EMPTY);
400bd3acdfSGabor Juhos }
410bd3acdfSGabor Juhos 
prom_putchar_ar933x(char ch)425c93316cSAlexander Sverdlin static void prom_putchar_ar933x(char ch)
430bd3acdfSGabor Juhos {
440bd3acdfSGabor Juhos 	void __iomem *base = (void __iomem *)(KSEG1ADDR(AR933X_UART_BASE));
450bd3acdfSGabor Juhos 
46*60b21490SIlpo Järvinen 	prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR);
475c93316cSAlexander Sverdlin 	__raw_writel(AR933X_UART_DATA_TX_CSR | (unsigned char)ch,
485c93316cSAlexander Sverdlin 		     base + AR933X_UART_DATA_REG);
49*60b21490SIlpo Järvinen 	prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR);
500bd3acdfSGabor Juhos }
510bd3acdfSGabor Juhos 
prom_putchar_dummy(char ch)525c93316cSAlexander Sverdlin static void prom_putchar_dummy(char ch)
530bd3acdfSGabor Juhos {
540bd3acdfSGabor Juhos 	/* nothing to do */
550bd3acdfSGabor Juhos }
560bd3acdfSGabor Juhos 
prom_enable_uart(u32 id)57ffc20581SGabor Juhos static void prom_enable_uart(u32 id)
58ffc20581SGabor Juhos {
59ffc20581SGabor Juhos 	void __iomem *gpio_base;
60ffc20581SGabor Juhos 	u32 uart_en;
61ffc20581SGabor Juhos 	u32 t;
62ffc20581SGabor Juhos 
63ffc20581SGabor Juhos 	switch (id) {
64ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR71XX:
65ffc20581SGabor Juhos 		uart_en = AR71XX_GPIO_FUNC_UART_EN;
66ffc20581SGabor Juhos 		break;
67ffc20581SGabor Juhos 
68ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR7240:
69ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR7241:
70ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR7242:
71ffc20581SGabor Juhos 		uart_en = AR724X_GPIO_FUNC_UART_EN;
72ffc20581SGabor Juhos 		break;
73ffc20581SGabor Juhos 
74ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR913X:
75ffc20581SGabor Juhos 		uart_en = AR913X_GPIO_FUNC_UART_EN;
76ffc20581SGabor Juhos 		break;
77ffc20581SGabor Juhos 
78ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR9330:
79ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR9331:
80ffc20581SGabor Juhos 		uart_en = AR933X_GPIO_FUNC_UART_EN;
81ffc20581SGabor Juhos 		break;
82ffc20581SGabor Juhos 
83ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR9341:
84ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR9342:
85ffc20581SGabor Juhos 	case REV_ID_MAJOR_AR9344:
86ffc20581SGabor Juhos 		/* TODO */
87ffc20581SGabor Juhos 	default:
88ffc20581SGabor Juhos 		return;
89ffc20581SGabor Juhos 	}
90ffc20581SGabor Juhos 
91ffc20581SGabor Juhos 	gpio_base = (void __iomem *)KSEG1ADDR(AR71XX_GPIO_BASE);
92ffc20581SGabor Juhos 	t = __raw_readl(gpio_base + AR71XX_GPIO_REG_FUNC);
93ffc20581SGabor Juhos 	t |= uart_en;
94ffc20581SGabor Juhos 	__raw_writel(t, gpio_base + AR71XX_GPIO_REG_FUNC);
95ffc20581SGabor Juhos }
96ffc20581SGabor Juhos 
prom_putchar_init(void)970bd3acdfSGabor Juhos static void prom_putchar_init(void)
980bd3acdfSGabor Juhos {
990bd3acdfSGabor Juhos 	void __iomem *base;
1000bd3acdfSGabor Juhos 	u32 id;
1010bd3acdfSGabor Juhos 
1020bd3acdfSGabor Juhos 	base = (void __iomem *)(KSEG1ADDR(AR71XX_RESET_BASE));
1030bd3acdfSGabor Juhos 	id = __raw_readl(base + AR71XX_RESET_REG_REV_ID);
1040bd3acdfSGabor Juhos 	id &= REV_ID_MAJOR_MASK;
1050bd3acdfSGabor Juhos 
1060bd3acdfSGabor Juhos 	switch (id) {
1070bd3acdfSGabor Juhos 	case REV_ID_MAJOR_AR71XX:
1080bd3acdfSGabor Juhos 	case REV_ID_MAJOR_AR7240:
1090bd3acdfSGabor Juhos 	case REV_ID_MAJOR_AR7241:
1100bd3acdfSGabor Juhos 	case REV_ID_MAJOR_AR7242:
1110bd3acdfSGabor Juhos 	case REV_ID_MAJOR_AR913X:
112703327ddSGabor Juhos 	case REV_ID_MAJOR_AR9341:
113703327ddSGabor Juhos 	case REV_ID_MAJOR_AR9342:
114703327ddSGabor Juhos 	case REV_ID_MAJOR_AR9344:
115af2d1b52SMatthias Schiffer 	case REV_ID_MAJOR_QCA9533:
116af2d1b52SMatthias Schiffer 	case REV_ID_MAJOR_QCA9533_V2:
11790898779SGabor Juhos 	case REV_ID_MAJOR_QCA9556:
11890898779SGabor Juhos 	case REV_ID_MAJOR_QCA9558:
119af2d1b52SMatthias Schiffer 	case REV_ID_MAJOR_TP9343:
120af2d1b52SMatthias Schiffer 	case REV_ID_MAJOR_QCA956X:
121a0b8cd5cSWenli Looi 	case REV_ID_MAJOR_QCN550X:
1220bd3acdfSGabor Juhos 		_prom_putchar = prom_putchar_ar71xx;
1230bd3acdfSGabor Juhos 		break;
1240bd3acdfSGabor Juhos 
1250bd3acdfSGabor Juhos 	case REV_ID_MAJOR_AR9330:
1260bd3acdfSGabor Juhos 	case REV_ID_MAJOR_AR9331:
1270bd3acdfSGabor Juhos 		_prom_putchar = prom_putchar_ar933x;
1280bd3acdfSGabor Juhos 		break;
1290bd3acdfSGabor Juhos 
1300bd3acdfSGabor Juhos 	default:
1310bd3acdfSGabor Juhos 		_prom_putchar = prom_putchar_dummy;
132ffc20581SGabor Juhos 		return;
1330bd3acdfSGabor Juhos 	}
134ffc20581SGabor Juhos 
135ffc20581SGabor Juhos 	prom_enable_uart(id);
1360bd3acdfSGabor Juhos }
1370bd3acdfSGabor Juhos 
prom_putchar(char ch)1385c93316cSAlexander Sverdlin void prom_putchar(char ch)
1390bd3acdfSGabor Juhos {
1400bd3acdfSGabor Juhos 	if (!_prom_putchar)
1410bd3acdfSGabor Juhos 		prom_putchar_init();
1420bd3acdfSGabor Juhos 
1430bd3acdfSGabor Juhos 	_prom_putchar(ch);
144d4a67d9dSGabor Juhos }
145