1/* 2 * Early printk support for Microblaze. 3 * 4 * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> 5 * Copyright (C) 2007-2009 PetaLogix 6 * Copyright (C) 2003-2006 Yasushi SHOJI <yashi@atmark-techno.com> 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12 13#include <linux/console.h> 14#include <linux/kernel.h> 15#include <linux/init.h> 16#include <linux/string.h> 17#include <linux/tty.h> 18#include <linux/io.h> 19#include <asm/processor.h> 20#include <linux/fcntl.h> 21#include <asm/setup.h> 22#include <asm/prom.h> 23 24static u32 base_addr; 25 26#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE 27static void early_printk_uartlite_putc(char c) 28{ 29 /* 30 * Limit how many times we'll spin waiting for TX FIFO status. 31 * This will prevent lockups if the base address is incorrectly 32 * set, or any other issue on the UARTLITE. 33 * This limit is pretty arbitrary, unless we are at about 10 baud 34 * we'll never timeout on a working UART. 35 */ 36 37 unsigned retries = 1000000; 38 /* read status bit - 0x8 offset */ 39 while (--retries && (in_be32(base_addr + 8) & (1 << 3))) 40 ; 41 42 /* Only attempt the iowrite if we didn't timeout */ 43 /* write to TX_FIFO - 0x4 offset */ 44 if (retries) 45 out_be32(base_addr + 4, c & 0xff); 46} 47 48static void early_printk_uartlite_write(struct console *unused, 49 const char *s, unsigned n) 50{ 51 while (*s && n-- > 0) { 52 if (*s == '\n') 53 early_printk_uartlite_putc('\r'); 54 early_printk_uartlite_putc(*s); 55 s++; 56 } 57} 58 59static struct console early_serial_uartlite_console = { 60 .name = "earlyser", 61 .write = early_printk_uartlite_write, 62 .flags = CON_PRINTBUFFER | CON_BOOT, 63 .index = -1, 64}; 65#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */ 66 67#ifdef CONFIG_SERIAL_8250_CONSOLE 68static void early_printk_uart16550_putc(char c) 69{ 70 /* 71 * Limit how many times we'll spin waiting for TX FIFO status. 72 * This will prevent lockups if the base address is incorrectly 73 * set, or any other issue on the UARTLITE. 74 * This limit is pretty arbitrary, unless we are at about 10 baud 75 * we'll never timeout on a working UART. 76 */ 77 78 #define UART_LSR_TEMT 0x40 /* Transmitter empty */ 79 #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ 80 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) 81 82 unsigned retries = 10000; 83 84 while (--retries && 85 !((in_be32(base_addr + 0x14) & BOTH_EMPTY) == BOTH_EMPTY)) 86 ; 87 88 if (retries) 89 out_be32(base_addr, c & 0xff); 90} 91 92static void early_printk_uart16550_write(struct console *unused, 93 const char *s, unsigned n) 94{ 95 while (*s && n-- > 0) { 96 if (*s == '\n') 97 early_printk_uart16550_putc('\r'); 98 early_printk_uart16550_putc(*s); 99 s++; 100 } 101} 102 103static struct console early_serial_uart16550_console = { 104 .name = "earlyser", 105 .write = early_printk_uart16550_write, 106 .flags = CON_PRINTBUFFER | CON_BOOT, 107 .index = -1, 108}; 109#endif /* CONFIG_SERIAL_8250_CONSOLE */ 110 111int __init setup_early_printk(char *opt) 112{ 113 int version = 0; 114 115 if (early_console) 116 return 1; 117 118 base_addr = of_early_console(&version); 119 if (base_addr) { 120#ifdef CONFIG_MMU 121 early_console_reg_tlb_alloc(base_addr); 122#endif 123 switch (version) { 124#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE 125 case UARTLITE: 126 pr_info("Early console on uartlite at 0x%08x\n", 127 base_addr); 128 early_console = &early_serial_uartlite_console; 129 break; 130#endif 131#ifdef CONFIG_SERIAL_8250_CONSOLE 132 case UART16550: 133 pr_info("Early console on uart16650 at 0x%08x\n", 134 base_addr); 135 early_console = &early_serial_uart16550_console; 136 break; 137#endif 138 default: 139 pr_info("Unsupported early console %d\n", 140 version); 141 return 1; 142 } 143 144 register_console(early_console); 145 return 0; 146 } 147 return 1; 148} 149 150/* Remap early console to virtual address and do not allocate one TLB 151 * only for early console because of performance degression */ 152void __init remap_early_printk(void) 153{ 154 if (!early_console) 155 return; 156 pr_info("early_printk_console remapping from 0x%x to ", base_addr); 157 base_addr = (u32) ioremap(base_addr, PAGE_SIZE); 158 pr_cont("0x%x\n", base_addr); 159 160#ifdef CONFIG_MMU 161 /* 162 * Early console is on the top of skipped TLB entries 163 * decrease tlb_skip size ensure that hardcoded TLB entry will be 164 * used by generic algorithm 165 * FIXME check if early console mapping is on the top by rereading 166 * TLB entry and compare baseaddr 167 * mts rtlbx, (tlb_skip - 1) 168 * nop 169 * mfs rX, rtlblo 170 * nop 171 * cmp rX, orig_base_addr 172 */ 173 tlb_skip -= 1; 174#endif 175} 176 177void __init disable_early_printk(void) 178{ 179 if (!early_console) 180 return; 181 pr_warn("disabling early console\n"); 182 unregister_console(early_console); 183 early_console = NULL; 184} 185