1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 25fff610bSJohn Crispin /* 35fff610bSJohn Crispin * 45fff610bSJohn Crispin * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> 55fff610bSJohn Crispin */ 65fff610bSJohn Crispin 75fff610bSJohn Crispin #include <linux/io.h> 85fff610bSJohn Crispin #include <linux/serial_reg.h> 95fff610bSJohn Crispin 105fff610bSJohn Crispin #include <asm/addrspace.h> 115c93316cSAlexander Sverdlin #include <asm/setup.h> 125fff610bSJohn Crispin 135b4500d1SJohn Crispin #ifdef CONFIG_SOC_RT288X 145b4500d1SJohn Crispin #define EARLY_UART_BASE 0x300c00 15a097b13cSJohn Crispin #define CHIPID_BASE 0x300004 16a097b13cSJohn Crispin #elif defined(CONFIG_SOC_MT7621) 17a097b13cSJohn Crispin #define EARLY_UART_BASE 0x1E000c00 18a097b13cSJohn Crispin #define CHIPID_BASE 0x1E000004 195b4500d1SJohn Crispin #else 205fff610bSJohn Crispin #define EARLY_UART_BASE 0x10000c00 21a097b13cSJohn Crispin #define CHIPID_BASE 0x10000004 225b4500d1SJohn Crispin #endif 235fff610bSJohn Crispin 24a097b13cSJohn Crispin #define MT7628_CHIP_NAME1 0x20203832 25a097b13cSJohn Crispin 265fff610bSJohn Crispin #define UART_REG_TX 0x04 2773afa6c4SJohn Crispin #define UART_REG_LCR 0x0c 28a097b13cSJohn Crispin #define UART_REG_LSR 0x14 29a097b13cSJohn Crispin #define UART_REG_LSR_RT2880 0x1c 305fff610bSJohn Crispin 315fff610bSJohn Crispin static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE); 32a097b13cSJohn Crispin static __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE); 3373afa6c4SJohn Crispin static int init_complete; 345fff610bSJohn Crispin uart_w32(u32 val,unsigned reg)355fff610bSJohn Crispinstatic inline void uart_w32(u32 val, unsigned reg) 365fff610bSJohn Crispin { 375fff610bSJohn Crispin __raw_writel(val, uart_membase + reg); 385fff610bSJohn Crispin } 395fff610bSJohn Crispin uart_r32(unsigned reg)405fff610bSJohn Crispinstatic inline u32 uart_r32(unsigned reg) 415fff610bSJohn Crispin { 425fff610bSJohn Crispin return __raw_readl(uart_membase + reg); 435fff610bSJohn Crispin } 445fff610bSJohn Crispin soc_is_mt7628(void)45a097b13cSJohn Crispinstatic inline int soc_is_mt7628(void) 46a097b13cSJohn Crispin { 47a097b13cSJohn Crispin return IS_ENABLED(CONFIG_SOC_MT7620) && 48a097b13cSJohn Crispin (__raw_readl(chipid_membase) == MT7628_CHIP_NAME1); 49a097b13cSJohn Crispin } 50a097b13cSJohn Crispin find_uart_base(void)5173afa6c4SJohn Crispinstatic void find_uart_base(void) 5273afa6c4SJohn Crispin { 5373afa6c4SJohn Crispin int i; 5473afa6c4SJohn Crispin 5573afa6c4SJohn Crispin if (!soc_is_mt7628()) 5673afa6c4SJohn Crispin return; 5773afa6c4SJohn Crispin 5873afa6c4SJohn Crispin for (i = 0; i < 3; i++) { 5973afa6c4SJohn Crispin u32 reg = uart_r32(UART_REG_LCR + (0x100 * i)); 6073afa6c4SJohn Crispin 6173afa6c4SJohn Crispin if (!reg) 6273afa6c4SJohn Crispin continue; 6373afa6c4SJohn Crispin 6473afa6c4SJohn Crispin uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE + 6573afa6c4SJohn Crispin (0x100 * i)); 6673afa6c4SJohn Crispin break; 6773afa6c4SJohn Crispin } 6873afa6c4SJohn Crispin } 6973afa6c4SJohn Crispin prom_putchar(char ch)705c93316cSAlexander Sverdlinvoid prom_putchar(char ch) 715fff610bSJohn Crispin { 7273afa6c4SJohn Crispin if (!init_complete) { 7373afa6c4SJohn Crispin find_uart_base(); 7473afa6c4SJohn Crispin init_complete = 1; 7573afa6c4SJohn Crispin } 7673afa6c4SJohn Crispin 77a097b13cSJohn Crispin if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) { 785c93316cSAlexander Sverdlin uart_w32((unsigned char)ch, UART_TX); 795fff610bSJohn Crispin while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) 805fff610bSJohn Crispin ; 81a097b13cSJohn Crispin } else { 82a097b13cSJohn Crispin while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0) 83a097b13cSJohn Crispin ; 845c93316cSAlexander Sverdlin uart_w32((unsigned char)ch, UART_REG_TX); 85a097b13cSJohn Crispin while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0) 865fff610bSJohn Crispin ; 875fff610bSJohn Crispin } 88a097b13cSJohn Crispin } 89