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ärvinenstatic 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 Sverdlinstatic 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 Sverdlinstatic 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 Sverdlinstatic void prom_putchar_dummy(char ch) 530bd3acdfSGabor Juhos { 540bd3acdfSGabor Juhos /* nothing to do */ 550bd3acdfSGabor Juhos } 560bd3acdfSGabor Juhos prom_enable_uart(u32 id)57ffc20581SGabor Juhosstatic 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 Juhosstatic 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 Sverdlinvoid 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