X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?p=linux-2.6-omap-h63xx.git;a=blobdiff_plain;f=drivers%2Fmisc%2Fsti%2Fsti-console.c;fp=drivers%2Fmisc%2Fsti%2Fsti-console.c;h=2062d23dca010344505edb01b001b307d8510276;hp=0000000000000000000000000000000000000000;hb=0d5f2216edfeb9904e0d6512f803b0f93871baaf;hpb=14fc69723d3442ef46f8f82b3f481e82f06a346d diff --git a/drivers/misc/sti/sti-console.c b/drivers/misc/sti/sti-console.c new file mode 100644 index 00000000000..2062d23dca0 --- /dev/null +++ b/drivers/misc/sti/sti-console.c @@ -0,0 +1,189 @@ +/* + * Console support for OMAP STI/XTI + * + * Copyright (C) 2004, 2005, 2006 Nokia Corporation + * Written by: Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "sticon" + +static struct tty_driver *tty_driver; +static DEFINE_SPINLOCK(sti_console_lock); +static unsigned int sti_console_channel = -1; +static int sti_line_done = -1; + +/* + * Write a string to any channel (including terminating NULL) + * Returns number of characters written. + */ +static int sti_channel_puts(const char *string, unsigned int channel, int len) +{ + int count = 0; + + /* + * sti_line_done is needed to determine when we have reached the + * end of the line. write() has a tendency to hand us small + * strings which otherwise end up creating newlines.. we need to + * keep the channel open and in append mode until the line has + * been terminated. + */ + if (sti_line_done != 0) { +#ifdef __LITTLE_ENDIAN + sti_channel_writeb(0xc3, channel); +#else + sti_channel_writeb(0xc0, channel); +#endif + xchg(&sti_line_done, 0); + } + + while (*string && count != len) { + char c = *string++; + + count++; + + if (c == '\n') { + xchg(&sti_line_done, 1); + sti_channel_writeb(0, channel); + break; + } else + sti_channel_writeb(c, channel); + } + + if (sti_line_done) + sti_channel_flush(channel); + + return count; +} + +static int sti_tty_open(struct tty_struct *tty, struct file *filp) +{ + return 0; +} + +static int sti_tty_write(struct tty_struct *tty, + const unsigned char *buf, int len) +{ + unsigned long flags; + int bytes; + + spin_lock_irqsave(&sti_console_lock, flags); + bytes = sti_channel_puts(buf, sti_console_channel, len); + spin_unlock_irqrestore(&sti_console_lock, flags); + + return bytes; +} + +static int sti_tty_write_room(struct tty_struct *tty) +{ + return 0x100000; +} + +static int sti_tty_chars_in_buffer(struct tty_struct *tty) +{ + return 0; +} + +static struct tty_operations sti_tty_ops = { + .open = sti_tty_open, + .write = sti_tty_write, + .write_room = sti_tty_write_room, + .chars_in_buffer = sti_tty_chars_in_buffer, +}; + +static void sti_console_write(struct console *c, const char *s, unsigned n) +{ + unsigned long flags; + + spin_lock_irqsave(&sti_console_lock, flags); + sti_channel_puts(s, sti_console_channel, n); + spin_unlock_irqrestore(&sti_console_lock, flags); +} + +static struct tty_driver *sti_console_device(struct console *c, int *index) +{ + *index = c->index; + return tty_driver; +} + +static int sti_console_setup(struct console *c, char *opts) +{ + return 0; +} + +static struct console sti_console = { + .name = DRV_NAME, + .write = sti_console_write, + .device = sti_console_device, + .setup = sti_console_setup, + .flags = CON_PRINTBUFFER | CON_ENABLED, + .index = -1, +}; + +static int __init sti_console_init(void) +{ + const struct omap_sti_console_config *info; + + info = omap_get_config(OMAP_TAG_STI_CONSOLE, + struct omap_sti_console_config); + if (info && info->enable) { + add_preferred_console(DRV_NAME, 0, NULL); + + sti_console_channel = info->channel; + } + + if (unlikely(sti_console_channel == -1)) + return -EINVAL; + + register_console(&sti_console); + + return 0; +} +__initcall(sti_console_init); + +static int __init sti_tty_init(void) +{ + struct tty_driver *tty; + int ret; + + tty = alloc_tty_driver(1); + if (!tty) + return -ENOMEM; + + tty->name = DRV_NAME; + tty->driver_name = DRV_NAME; + tty->major = 0; /* dynamic major */ + tty->minor_start = 0; + tty->type = TTY_DRIVER_TYPE_SYSTEM; + tty->subtype = SYSTEM_TYPE_SYSCONS; + tty->init_termios = tty_std_termios; + + tty_set_operations(tty, &sti_tty_ops); + + ret = tty_register_driver(tty); + if (ret) { + put_tty_driver(tty); + return ret; + } + + tty_driver = tty; + return 0; +} +late_initcall(sti_tty_init); + +module_param(sti_console_channel, uint, 0); +MODULE_PARM_DESC(sti_console_channel, "STI console channel"); +MODULE_AUTHOR("Paul Mundt"); +MODULE_DESCRIPTION("OMAP STI console support"); +MODULE_LICENSE("GPL");