18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/io.h> 88c2ecf20Sopenharmony_ci#include <linux/serial_reg.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <asm/addrspace.h> 118c2ecf20Sopenharmony_ci#include <asm/setup.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#ifdef CONFIG_SOC_RT288X 148c2ecf20Sopenharmony_ci#define EARLY_UART_BASE 0x300c00 158c2ecf20Sopenharmony_ci#define CHIPID_BASE 0x300004 168c2ecf20Sopenharmony_ci#elif defined(CONFIG_SOC_MT7621) 178c2ecf20Sopenharmony_ci#define EARLY_UART_BASE 0x1E000c00 188c2ecf20Sopenharmony_ci#define CHIPID_BASE 0x1E000004 198c2ecf20Sopenharmony_ci#else 208c2ecf20Sopenharmony_ci#define EARLY_UART_BASE 0x10000c00 218c2ecf20Sopenharmony_ci#define CHIPID_BASE 0x10000004 228c2ecf20Sopenharmony_ci#endif 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define MT7628_CHIP_NAME1 0x20203832 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define UART_REG_TX 0x04 278c2ecf20Sopenharmony_ci#define UART_REG_LCR 0x0c 288c2ecf20Sopenharmony_ci#define UART_REG_LSR 0x14 298c2ecf20Sopenharmony_ci#define UART_REG_LSR_RT2880 0x1c 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE); 328c2ecf20Sopenharmony_cistatic __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE); 338c2ecf20Sopenharmony_cistatic int init_complete; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic inline void uart_w32(u32 val, unsigned reg) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci __raw_writel(val, uart_membase + reg); 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic inline u32 uart_r32(unsigned reg) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci return __raw_readl(uart_membase + reg); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic inline int soc_is_mt7628(void) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci return IS_ENABLED(CONFIG_SOC_MT7620) && 488c2ecf20Sopenharmony_ci (__raw_readl(chipid_membase) == MT7628_CHIP_NAME1); 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic void find_uart_base(void) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci int i; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (!soc_is_mt7628()) 568c2ecf20Sopenharmony_ci return; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 598c2ecf20Sopenharmony_ci u32 reg = uart_r32(UART_REG_LCR + (0x100 * i)); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (!reg) 628c2ecf20Sopenharmony_ci continue; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE + 658c2ecf20Sopenharmony_ci (0x100 * i)); 668c2ecf20Sopenharmony_ci break; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_civoid prom_putchar(char ch) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci if (!init_complete) { 738c2ecf20Sopenharmony_ci find_uart_base(); 748c2ecf20Sopenharmony_ci init_complete = 1; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) { 788c2ecf20Sopenharmony_ci uart_w32((unsigned char)ch, UART_TX); 798c2ecf20Sopenharmony_ci while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) 808c2ecf20Sopenharmony_ci ; 818c2ecf20Sopenharmony_ci } else { 828c2ecf20Sopenharmony_ci while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0) 838c2ecf20Sopenharmony_ci ; 848c2ecf20Sopenharmony_ci uart_w32((unsigned char)ch, UART_REG_TX); 858c2ecf20Sopenharmony_ci while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0) 868c2ecf20Sopenharmony_ci ; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci} 89