1d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos/* 20bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos * Atheros AR7XXX/AR9XXX SoC early printk support 3d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos * 40bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 5d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos * 7d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos * This program is free software; you can redistribute it and/or modify it 8d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos * under the terms of the GNU General Public License version 2 as published 9d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos * by the Free Software Foundation. 10d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos */ 11d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos 12d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos#include <linux/io.h> 130bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos#include <linux/errno.h> 14d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos#include <linux/serial_reg.h> 15d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos#include <asm/addrspace.h> 16d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos 170bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos#include <asm/mach-ath79/ath79.h> 18d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos#include <asm/mach-ath79/ar71xx_regs.h> 190bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos#include <asm/mach-ath79/ar933x_uart.h> 20d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos 210bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhosstatic void (*_prom_putchar) (unsigned char); 220bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 230bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhosstatic inline void prom_putchar_wait(void __iomem *reg, u32 mask, u32 val) 24d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos{ 250bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos u32 t; 26d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos 27d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos do { 280bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos t = __raw_readl(reg); 290bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos if ((t & mask) == val) 30d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos break; 31d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos } while (1); 32d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos} 33d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos 340bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhosstatic void prom_putchar_ar71xx(unsigned char ch) 35d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos{ 36d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE)); 37d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos 380bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE); 39d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos __raw_writel(ch, base + UART_TX * 4); 400bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE); 410bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos} 420bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 430bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhosstatic void prom_putchar_ar933x(unsigned char ch) 440bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos{ 450bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos void __iomem *base = (void __iomem *)(KSEG1ADDR(AR933X_UART_BASE)); 460bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 470bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR, 480bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos AR933X_UART_DATA_TX_CSR); 490bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos __raw_writel(AR933X_UART_DATA_TX_CSR | ch, base + AR933X_UART_DATA_REG); 500bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR, 510bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos AR933X_UART_DATA_TX_CSR); 520bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos} 530bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 540bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhosstatic void prom_putchar_dummy(unsigned char ch) 550bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos{ 560bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos /* nothing to do */ 570bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos} 580bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 590bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhosstatic void prom_putchar_init(void) 600bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos{ 610bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos void __iomem *base; 620bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos u32 id; 630bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 640bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos base = (void __iomem *)(KSEG1ADDR(AR71XX_RESET_BASE)); 650bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos id = __raw_readl(base + AR71XX_RESET_REG_REV_ID); 660bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos id &= REV_ID_MAJOR_MASK; 670bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 680bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos switch (id) { 690bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos case REV_ID_MAJOR_AR71XX: 700bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos case REV_ID_MAJOR_AR7240: 710bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos case REV_ID_MAJOR_AR7241: 720bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos case REV_ID_MAJOR_AR7242: 730bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos case REV_ID_MAJOR_AR913X: 74703327ddcc736a054f4e2c132235a8370d2f7870Gabor Juhos case REV_ID_MAJOR_AR9341: 75703327ddcc736a054f4e2c132235a8370d2f7870Gabor Juhos case REV_ID_MAJOR_AR9342: 76703327ddcc736a054f4e2c132235a8370d2f7870Gabor Juhos case REV_ID_MAJOR_AR9344: 77908987797076b848f01b32c21d61d0e152efc236Gabor Juhos case REV_ID_MAJOR_QCA9556: 78908987797076b848f01b32c21d61d0e152efc236Gabor Juhos case REV_ID_MAJOR_QCA9558: 790bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos _prom_putchar = prom_putchar_ar71xx; 800bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos break; 810bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 820bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos case REV_ID_MAJOR_AR9330: 830bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos case REV_ID_MAJOR_AR9331: 840bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos _prom_putchar = prom_putchar_ar933x; 850bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos break; 860bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 870bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos default: 880bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos _prom_putchar = prom_putchar_dummy; 890bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos break; 900bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos } 910bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos} 920bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 930bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhosvoid prom_putchar(unsigned char ch) 940bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos{ 950bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos if (!_prom_putchar) 960bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos prom_putchar_init(); 970bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos 980bd3acdf7d559c8289de73c4c711fd2381e6c7adGabor Juhos _prom_putchar(ch); 99d4a67d9dc8a5a80c4ec1814791af8c0252c158b8Gabor Juhos} 100