linux/arch/sh/kernel/early_printk.c
<<
>>
Prefs
   1/*
   2 * arch/sh/kernel/early_printk.c
   3 *
   4 *  Copyright (C) 1999, 2000  Niibe Yutaka
   5 *  Copyright (C) 2002  M. R. Brown
   6 *  Copyright (C) 2004 - 2007  Paul Mundt
   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#include <linux/console.h>
  13#include <linux/tty.h>
  14#include <linux/init.h>
  15#include <linux/io.h>
  16#include <linux/delay.h>
  17
  18#ifdef CONFIG_SH_STANDARD_BIOS
  19#include <asm/sh_bios.h>
  20
  21/*
  22 *      Print a string through the BIOS
  23 */
  24static void sh_console_write(struct console *co, const char *s,
  25                                 unsigned count)
  26{
  27        sh_bios_console_write(s, count);
  28}
  29
  30/*
  31 *      Setup initial baud/bits/parity. We do two things here:
  32 *      - construct a cflag setting for the first rs_open()
  33 *      - initialize the serial port
  34 *      Return non-zero if we didn't find a serial port.
  35 */
  36static int __init sh_console_setup(struct console *co, char *options)
  37{
  38        int     cflag = CREAD | HUPCL | CLOCAL;
  39
  40        /*
  41         *      Now construct a cflag setting.
  42         *      TODO: this is a totally bogus cflag, as we have
  43         *      no idea what serial settings the BIOS is using, or
  44         *      even if its using the serial port at all.
  45         */
  46        cflag |= B115200 | CS8 | /*no parity*/0;
  47
  48        co->cflag = cflag;
  49
  50        return 0;
  51}
  52
  53static struct console bios_console = {
  54        .name           = "bios",
  55        .write          = sh_console_write,
  56        .setup          = sh_console_setup,
  57        .flags          = CON_PRINTBUFFER,
  58        .index          = -1,
  59};
  60#endif
  61
  62#ifdef CONFIG_EARLY_SCIF_CONSOLE
  63#include <linux/serial_core.h>
  64#include "../../../drivers/serial/sh-sci.h"
  65
  66#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
  67    defined(CONFIG_CPU_SUBTYPE_SH7721)
  68#define EPK_SCSMR_VALUE 0x000
  69#define EPK_SCBRR_VALUE 0x00C
  70#define EPK_FIFO_SIZE 64
  71#define EPK_FIFO_BITS (0x7f00 >> 8)
  72#else
  73#define EPK_FIFO_SIZE 16
  74#define EPK_FIFO_BITS (0x1f00 >> 8)
  75#endif
  76
  77static struct uart_port scif_port = {
  78        .type           = PORT_SCIF,
  79        .mapbase        = CONFIG_EARLY_SCIF_CONSOLE_PORT,
  80        .membase        = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
  81};
  82
  83static void scif_sercon_putc(int c)
  84{
  85        while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE))
  86                ;
  87
  88        sci_in(&scif_port, SCxSR);
  89        sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
  90        sci_out(&scif_port, SCxTDR, c);
  91
  92        while ((sci_in(&scif_port, SCxSR) & 0x40) == 0)
  93                ;
  94
  95        if (c == '\n')
  96                scif_sercon_putc('\r');
  97}
  98
  99static void scif_sercon_write(struct console *con, const char *s,
 100                              unsigned count)
 101{
 102        while (count-- > 0)
 103                scif_sercon_putc(*s++);
 104}
 105
 106static int __init scif_sercon_setup(struct console *con, char *options)
 107{
 108        con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8;
 109
 110        return 0;
 111}
 112
 113static struct console scif_console = {
 114        .name           = "sercon",
 115        .write          = scif_sercon_write,
 116        .setup          = scif_sercon_setup,
 117        .flags          = CON_PRINTBUFFER,
 118        .index          = -1,
 119};
 120
 121#if !defined(CONFIG_SH_STANDARD_BIOS)
 122#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
 123    defined(CONFIG_CPU_SUBTYPE_SH7721)
 124static void scif_sercon_init(char *s)
 125{
 126        sci_out(&scif_port, SCSCR, 0x0000);     /* clear TE and RE */
 127        sci_out(&scif_port, SCFCR, 0x4006);     /* reset */
 128        sci_out(&scif_port, SCSCR, 0x0000);     /* select internal clock */
 129        sci_out(&scif_port, SCSMR, EPK_SCSMR_VALUE);
 130        sci_out(&scif_port, SCBRR, EPK_SCBRR_VALUE);
 131
 132        mdelay(1);      /* wait 1-bit time */
 133
 134        sci_out(&scif_port, SCFCR, 0x0030);     /* TTRG=b'11 */
 135        sci_out(&scif_port, SCSCR, 0x0030);     /* TE, RE */
 136}
 137#elif defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
 138#define DEFAULT_BAUD 115200
 139/*
 140 * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
 141 * devices that aren't using sh-ipl+g.
 142 */
 143static void scif_sercon_init(char *s)
 144{
 145        struct uart_port *port = &scif_port;
 146        unsigned baud = DEFAULT_BAUD;
 147        unsigned int status;
 148        char *e;
 149
 150        if (*s == ',')
 151                ++s;
 152
 153        if (*s) {
 154                /* ignore ioport/device name */
 155                s += strcspn(s, ",");
 156                if (*s == ',')
 157                        s++;
 158        }
 159
 160        if (*s) {
 161                baud = simple_strtoul(s, &e, 0);
 162                if (baud == 0 || s == e)
 163                        baud = DEFAULT_BAUD;
 164        }
 165
 166        do {
 167                status = sci_in(port, SCxSR);
 168        } while (!(status & SCxSR_TEND(port)));
 169
 170        sci_out(port, SCSCR, 0);         /* TE=0, RE=0 */
 171        sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
 172        sci_out(port, SCSMR, 0);
 173
 174        /* Set baud rate */
 175        sci_out(port, SCBRR, (CONFIG_SH_PCLK_FREQ + 16 * baud) /
 176                (32 * baud) - 1);
 177        udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
 178
 179        sci_out(port, SCSPTR, 0);
 180        sci_out(port, SCxSR, 0x60);
 181        sci_out(port, SCLSR, 0);
 182
 183        sci_out(port, SCFCR, 0);
 184        sci_out(port, SCSCR, 0x30);      /* TE=1, RE=1 */
 185}
 186#endif /* defined(CONFIG_CPU_SUBTYPE_SH7720) */
 187#endif /* !defined(CONFIG_SH_STANDARD_BIOS) */
 188#endif /* CONFIG_EARLY_SCIF_CONSOLE */
 189
 190/*
 191 * Setup a default console, if more than one is compiled in, rely on the
 192 * earlyprintk= parsing to give priority.
 193 */
 194static struct console *early_console =
 195#ifdef CONFIG_SH_STANDARD_BIOS
 196        &bios_console
 197#elif defined(CONFIG_EARLY_SCIF_CONSOLE)
 198        &scif_console
 199#else
 200        NULL
 201#endif
 202        ;
 203
 204static int __init setup_early_printk(char *buf)
 205{
 206        int keep_early = 0;
 207
 208        if (!buf)
 209                return 0;
 210
 211        if (strstr(buf, "keep"))
 212                keep_early = 1;
 213
 214#ifdef CONFIG_SH_STANDARD_BIOS
 215        if (!strncmp(buf, "bios", 4))
 216                early_console = &bios_console;
 217#endif
 218#if defined(CONFIG_EARLY_SCIF_CONSOLE)
 219        if (!strncmp(buf, "serial", 6)) {
 220                early_console = &scif_console;
 221
 222#if !defined(CONFIG_SH_STANDARD_BIOS)
 223#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
 224                scif_sercon_init(buf + 6);
 225#endif
 226#endif
 227        }
 228#endif
 229
 230        if (likely(early_console)) {
 231                if (keep_early)
 232                        early_console->flags &= ~CON_BOOT;
 233                else
 234                        early_console->flags |= CON_BOOT;
 235                register_console(early_console);
 236        }
 237
 238        return 0;
 239}
 240early_param("earlyprintk", setup_early_printk);
 241
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.