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 early_console_initialized; 25static u32 base_addr; 26 27static void early_printk_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 = 10000; 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_write(struct console *unused, 49 const char *s, unsigned n) 50{ 51 while (*s && n-- > 0) { 52 early_printk_putc(*s); 53 if (*s == '\n') 54 early_printk_putc('\r'); 55 s++; 56 } 57} 58 59static struct console early_serial_console = { 60 .name = "earlyser", 61 .write = early_printk_write, 62 .flags = CON_PRINTBUFFER, 63 .index = -1, 64}; 65 66static struct console *early_console = &early_serial_console; 67 68void early_printk(const char *fmt, ...) 69{ 70 char buf[512]; 71 int n; 72 va_list ap; 73 74 if (early_console_initialized) { 75 va_start(ap, fmt); 76 n = vscnprintf(buf, 512, fmt, ap); 77 early_console->write(early_console, buf, n); 78 va_end(ap); 79 } 80} 81 82int __init setup_early_printk(char *opt) 83{ 84 if (early_console_initialized) 85 return 1; 86 87 base_addr = early_uartlite_console(); 88 if (base_addr) { 89 early_console_initialized = 1; 90#ifdef CONFIG_MMU 91 early_console_reg_tlb_alloc(base_addr); 92#endif 93 early_printk("early_printk_console is enabled at 0x%08x\n", 94 base_addr); 95 96 /* register_console(early_console); */ 97 98 return 0; 99 } else 100 return 1; 101} 102 103void __init disable_early_printk(void) 104{ 105 if (!early_console_initialized || !early_console) 106 return; 107 printk(KERN_WARNING "disabling early console\n"); 108 unregister_console(early_console); 109 early_console_initialized = 0; 110} 111