diff options
Diffstat (limited to 'drivers/serial')
52 files changed, 1552 insertions, 460 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 6a1a568ca64..facb6785561 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -214,8 +214,8 @@ static void serial21285_shutdown(struct uart_port *port) } static void -serial21285_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial21285_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned long flags; unsigned int baud, quot, h_lcr; diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 9b8b585513e..cad426c9711 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -1061,7 +1061,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 634ecca36a7..68817a7d8c0 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1523,7 +1523,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file, /* FIX UP modem control here someday...... */ -static void rs_360_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { ser_info_t *info = (ser_info_t *)tty->driver_data; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index e34bd03cfce..51f3c739f7e 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1763,8 +1763,8 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int } static void -serial8250_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char cval, fcr = 0; diff --git a/drivers/serial/8250_exar_st16c554.c b/drivers/serial/8250_exar_st16c554.c new file mode 100644 index 00000000000..567143ace15 --- /dev/null +++ b/drivers/serial/8250_exar_st16c554.c @@ -0,0 +1,52 @@ +/* + * linux/drivers/serial/8250_exar.c + * + * Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com > + * Based on 8250_boca. + * + * Copyright (C) 2005 Russell King. + * Data taken from include/asm-i386/serial.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/serial_8250.h> + +#define PORT(_base,_irq) \ + { \ + .iobase = _base, \ + .irq = _irq, \ + .uartclk = 1843200, \ + .iotype = UPIO_PORT, \ + .flags = UPF_BOOT_AUTOCONF, \ + } + +static struct plat_serial8250_port exar_data[] = { + PORT(0x100, 5), + PORT(0x108, 5), + PORT(0x110, 5), + PORT(0x118, 5), + { }, +}; + +static struct platform_device exar_device = { + .name = "serial8250", + .id = PLAT8250_DEV_EXAR_ST16C554, + .dev = { + .platform_data = exar_data, + }, +}; + +static int __init exar_init(void) +{ + return platform_device_register(&exar_device); +} + +module_init(exar_init); + +MODULE_AUTHOR("Paul B Schroeder"); +MODULE_DESCRIPTION("8250 serial probe module for Exar cards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 71d907c8288..d3d6b82706b 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -464,11 +464,38 @@ static void __devexit serial_pnp_remove(struct pnp_dev *dev) serial8250_unregister_port(line - 1); } +#ifdef CONFIG_PM +static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state) +{ + long line = (long)pnp_get_drvdata(dev); + + if (!line) + return -ENODEV; + serial8250_suspend_port(line - 1); + return 0; +} + +static int serial_pnp_resume(struct pnp_dev *dev) +{ + long line = (long)pnp_get_drvdata(dev); + + if (!line) + return -ENODEV; + serial8250_resume_port(line - 1); + return 0; +} +#else +#define serial_pnp_suspend NULL +#define serial_pnp_resume NULL +#endif /* CONFIG_PM */ + static struct pnp_driver serial_pnp_driver = { .name = "serial", - .id_table = pnp_dev_table, .probe = serial_pnp_probe, .remove = __devexit_p(serial_pnp_remove), + .suspend = serial_pnp_suspend, + .resume = serial_pnp_resume, + .id_table = pnp_dev_table, }; static int __init serial8250_pnp_init(void) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b0d502622d9..0b36dd5cdac 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -151,32 +151,6 @@ config SERIAL_8250_MANY_PORTS say N here to save some memory. You can also say Y if you have an "intelligent" multiport card such as Cyclades, Digiboards, etc. -config SERIAL_8250_SHARE_IRQ - bool "Support for sharing serial interrupts" - depends on SERIAL_8250_EXTENDED - help - Some serial boards have hardware support which allows multiple dumb - serial ports on the same board to share a single IRQ. To enable - support for this in the serial driver, say Y here. - -config SERIAL_8250_DETECT_IRQ - bool "Autodetect IRQ on standard ports (unsafe)" - depends on SERIAL_8250_EXTENDED - help - Say Y here if you want the kernel to try to guess which IRQ - to use for your serial port. - - This is considered unsafe; it is far better to configure the IRQ in - a boot script using the setserial command. - - If unsure, say N. - -config SERIAL_8250_RSA - bool "Support RSA serial ports" - depends on SERIAL_8250_EXTENDED - help - ::: To be written ::: - # # Multi-port serial cards # @@ -199,7 +173,6 @@ config SERIAL_8250_ACCENT To compile this driver as a module, choose M here: the module will be called 8250_accent. - config SERIAL_8250_BOCA tristate "Support Boca cards" depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS @@ -210,6 +183,17 @@ config SERIAL_8250_BOCA To compile this driver as a module, choose M here: the module will be called 8250_boca. +config SERIAL_8250_EXAR_ST16C554 + tristate "Support Exar ST16C554/554D Quad UART" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + The Uplogix Envoy TU301 uses this Exar Quad UART. If you are + tinkering with your Envoy TU301, or have a machine with this UART, + say Y here. + + To compile this driver as a module, choose M here: the module + will be called 8250_exar_st16c554. + config SERIAL_8250_HUB6 tristate "Support Hub6 cards" depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS @@ -219,6 +203,32 @@ config SERIAL_8250_HUB6 To compile this driver as a module, choose M here: the module will be called 8250_hub6. +config SERIAL_8250_SHARE_IRQ + bool "Support for sharing serial interrupts" + depends on SERIAL_8250_EXTENDED + help + Some serial boards have hardware support which allows multiple dumb + serial ports on the same board to share a single IRQ. To enable + support for this in the serial driver, say Y here. + +config SERIAL_8250_DETECT_IRQ + bool "Autodetect IRQ on standard ports (unsafe)" + depends on SERIAL_8250_EXTENDED + help + Say Y here if you want the kernel to try to guess which IRQ + to use for your serial port. + + This is considered unsafe; it is far better to configure the IRQ in + a boot script using the setserial command. + + If unsure, say N. + +config SERIAL_8250_RSA + bool "Support RSA serial ports" + depends on SERIAL_8250_EXTENDED + help + ::: To be written ::: + config SERIAL_8250_MCA tristate "Support 8250-type ports on MCA buses" depends on SERIAL_8250 != n && MCA @@ -511,6 +521,25 @@ config SERIAL_IMX_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_UARTLITE + tristate "Xilinx uartlite serial port support" + depends on PPC32 + select SERIAL_CORE + help + Say Y here if you want to use the Xilinx uartlite serial controller. + + To compile this driver as a module, choose M here: the + module will be called uartlite.ko. + +config SERIAL_UARTLITE_CONSOLE + bool "Support for console on Xilinx uartlite serial port" + depends on SERIAL_UARTLITE=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you wish to use a Xilinx uartlite as the system + console (the system console is the device which receives all kernel + messages and warnings and which allows logins in single user mode). + config SERIAL_SUNCORE bool depends on SPARC @@ -767,37 +796,37 @@ config SERIAL_CPM_SCC1 bool "Support for SCC1 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC1 as a serial port + Select this option to use SCC1 as a serial port config SERIAL_CPM_SCC2 bool "Support for SCC2 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC2 as a serial port + Select this option to use SCC2 as a serial port config SERIAL_CPM_SCC3 bool "Support for SCC3 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC3 as a serial port + Select this option to use SCC3 as a serial port config SERIAL_CPM_SCC4 bool "Support for SCC4 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC4 as a serial port + Select this option to use SCC4 as a serial port config SERIAL_CPM_SMC1 bool "Support for SMC1 serial port" depends on SERIAL_CPM=y help - Select the is option to use SMC1 as a serial port + Select this option to use SMC1 as a serial port config SERIAL_CPM_SMC2 bool "Support for SMC2 serial port" depends on SERIAL_CPM=y help - Select the is option to use SMC2 as a serial port + Select this option to use SMC2 as a serial port config SERIAL_SGI_L1_CONSOLE bool "SGI Altix L1 serial console support" diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index b4d8a7c182e..df3632cd7df 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o +obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o @@ -55,4 +56,5 @@ obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o +obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 4213fabc62b..61db6973755 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -129,6 +129,8 @@ static void pl010_rx_chars(struct uart_port *port) */ rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX; if (unlikely(rsr & UART01x_RSR_ANY)) { + writel(0, port->membase + UART01x_ECR); + if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); port->icount.brk++; @@ -343,8 +345,8 @@ static void pl010_shutdown(struct uart_port *port) } static void -pl010_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +pl010_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int lcr_h, old_cr; unsigned long flags; diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index d503625730d..9a3b374b2a0 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -412,8 +412,8 @@ static void pl011_shutdown(struct uart_port *port) } static void -pl011_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +pl011_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int lcr_h, old_cr; unsigned long flags; diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 391a1f4167a..ed7f7209ea5 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -1,5 +1,5 @@ /* - * linux/drivers/char/at91_serial.c + * linux/drivers/char/atmel_serial.c * * Driver for Atmel AT91 / AT32 Serial ports * Copyright (C) 2003 Rick Bronson @@ -36,11 +36,11 @@ #include <asm/io.h> -#include <asm/arch/at91rm9200_pdc.h> #include <asm/mach/serial_at91.h> #include <asm/arch/board.h> +#include <asm/arch/at91_pdc.h> #ifdef CONFIG_ARM -#include <asm/arch/system.h> +#include <asm/arch/cpu.h> #include <asm/arch/gpio.h> #endif @@ -137,8 +137,8 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) unsigned int control = 0; unsigned int mode; -#ifdef CONFIG_ARM - if (arch_identify() == ARCH_ID_AT91RM9200) { +#ifdef CONFIG_ARCH_AT91RM9200 + if (cpu_is_at91rm9200()) { /* * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. * We need to drive the pin manually. @@ -478,7 +478,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, unsigned /* * Change the port parameters */ -static void atmel_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) +static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old) { unsigned long flags; unsigned int mode, imr, quot, baud; diff --git a/drivers/serial/atmel_serial.h b/drivers/serial/atmel_serial.h index eced2ad1a8d..fe1763b2a6d 100644 --- a/drivers/serial/atmel_serial.h +++ b/drivers/serial/atmel_serial.h @@ -31,8 +31,8 @@ #define ATMEL_US_RSTIT (1 << 13) /* Reset Iterations */ #define ATMEL_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */ #define ATMEL_US_RETTO (1 << 15) /* Rearm Time-out */ -#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable */ -#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable */ +#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable [AT91RM9200 only] */ +#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable [AT91RM9200 only] */ #define ATMEL_US_RTSEN (1 << 18) /* Request To Send Enable */ #define ATMEL_US_RTSDIS (1 << 19) /* Request To Send Disable */ @@ -92,9 +92,9 @@ #define ATMEL_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */ #define ATMEL_US_RXBUFF (1 << 12) /* Reception Buffer Full */ #define ATMEL_US_NACK (1 << 13) /* Non Acknowledge */ -#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change */ -#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change */ -#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change */ +#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change [AT91RM9200 only] */ +#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change [AT91RM9200 only] */ +#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change [AT91RM9200 only] */ #define ATMEL_US_CTSIC (1 << 19) /* Clear to Send Input Change */ #define ATMEL_US_RI (1 << 20) /* RI */ #define ATMEL_US_DSR (1 << 21) /* DSR */ @@ -106,6 +106,7 @@ #define ATMEL_US_CSR 0x14 /* Channel Status Register */ #define ATMEL_US_RHR 0x18 /* Receiver Holding Register */ #define ATMEL_US_THR 0x1c /* Transmitter Holding Register */ +#define ATMEL_US_SYNH (1 << 15) /* Transmit/Receive Sync [SAM9 only] */ #define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */ #define ATMEL_US_CD (0xffff << 0) /* Clock Divider */ diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 59801271488..23827189ec0 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -286,8 +286,8 @@ static void clps711xuart_shutdown(struct uart_port *port) } static void -clps711xuart_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int ubrlcr, baud, quot; unsigned long flags; diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index a8f894c7819..69715e55650 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h @@ -88,7 +88,7 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR]; /* these are located in their respective files */ void cpm_line_cr_cmd(int line, int cmd); -int cpm_uart_init_portdesc(void); +int __init cpm_uart_init_portdesc(void); int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); void cpm_uart_freebuf(struct uart_cpm_port *pinfo); diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 0abb544ae63..7a3b97fdf8d 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -195,10 +195,8 @@ static void cpm_uart_start_tx(struct uart_port *port) if (cpm_uart_tx_pump(port) != 0) { if (IS_SMC(pinfo)) { smcp->smc_smcm |= SMCM_TX; - smcp->smc_smcmr |= SMCMR_TEN; } else { sccp->scc_sccm |= UART_SCCM_TX; - pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT; } } } @@ -421,9 +419,10 @@ static int cpm_uart_startup(struct uart_port *port) /* Startup rx-int */ if (IS_SMC(pinfo)) { pinfo->smcp->smc_smcm |= SMCM_RX; - pinfo->smcp->smc_smcmr |= SMCMR_REN; + pinfo->smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN); } else { pinfo->sccp->scc_sccm |= UART_SCCM_RX; + pinfo->sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); } if (!(pinfo->flags & FLAG_CONSOLE)) @@ -1350,11 +1349,10 @@ static int cpm_uart_init(void) { pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n"); pr_info( "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n"); -#ifndef CONFIG_SERIAL_CPM_CONSOLE - ret = cpm_uart_init_portdesc(); - if (ret) - return ret; -#endif + + /* Don't run this again, if the console driver did it already */ + if (cpm_uart_nr == 0) + cpm_uart_init_portdesc(); cpm_reg.nr = cpm_uart_nr; ret = uart_register_driver(&cpm_reg); @@ -1366,6 +1364,8 @@ static int cpm_uart_init(void) { int con = cpm_uart_port_map[i]; cpm_uart_ports[con].port.line = i; cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF; + if (cpm_uart_ports[con].set_lineif) + cpm_uart_ports[con].set_lineif(&cpm_uart_ports[con]); uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port); } diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 95afc37297a..08e55fdc882 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c @@ -184,7 +184,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo) } /* Setup any dynamic params in the uart desc */ -int cpm_uart_init_portdesc(void) +int __init cpm_uart_init_portdesc(void) { pr_debug("CPM uart[-]:init portdesc\n"); diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index b691d3e1475..787a8f13467 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c @@ -282,7 +282,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo) } /* Setup any dynamic params in the uart desc */ -int cpm_uart_init_portdesc(void) +int __init cpm_uart_init_portdesc(void) { #if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2) u32 addr; diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 7a24e53546c..42b050c46ab 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -804,8 +804,8 @@ static struct e100_serial rs_table[] = { #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) -static struct termios *serial_termios[NR_PORTS]; -static struct termios *serial_termios_locked[NR_PORTS]; +static struct ktermios *serial_termios[NR_PORTS]; +static struct ktermios *serial_termios_locked[NR_PORTS]; #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER static struct fast_timer fast_timers[NR_PORTS]; #endif @@ -4223,7 +4223,7 @@ rs_ioctl(struct tty_struct *tty, struct file * file, } static void -rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; @@ -4877,6 +4877,8 @@ rs_init(void) driver->init_termios = tty_std_termios; driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ + driver->init_termios.c_ispeed = 115200; + driver->init_termios.c_ospeed = 115200; driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; driver->termios = serial_termios; driver->termios_locked = serial_termios_locked; diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h index f30b93d6ef7..4a23340663a 100644 --- a/drivers/serial/crisv10.h +++ b/drivers/serial/crisv10.h @@ -93,8 +93,8 @@ struct e100_serial { struct work_struct work; struct async_icount icount; /* error-statistics etc.*/ - struct termios normal_termios; - struct termios callout_termios; + struct ktermios normal_termios; + struct ktermios callout_termios; #ifdef DECLARE_WAITQUEUE wait_queue_head_t open_wait; wait_queue_head_t close_wait; diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 53662b33b84..587d87b9eb3 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -1,11 +1,13 @@ /* - * dz.c: Serial port driver for DECStations equiped + * dz.c: Serial port driver for DECstations equipped * with the DZ chipset. * * Copyright (C) 1998 Olivier A. D. Lebaillif * * Email: olivier.lebaillif@ifrsys.com * + * Copyright (C) 2004, 2006 Maciej W. Rozycki + * * [31-AUG-98] triemer * Changed IRQ to use Harald's dec internals interrupts.h * removed base_addr code - moving address assignment to setup.c @@ -26,10 +28,16 @@ #undef DEBUG_DZ +#if defined(CONFIG_SERIAL_DZ_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include <linux/delay.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/init.h> #include <linux/console.h> +#include <linux/sysrq.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/serial_core.h> @@ -45,14 +53,10 @@ #include <asm/system.h> #include <asm/uaccess.h> -#define CONSOLE_LINE (3) /* for definition of struct console */ - #include "dz.h" -#define DZ_INTR_DEBUG 1 - static char *dz_name = "DECstation DZ serial driver version "; -static char *dz_version = "1.02"; +static char *dz_version = "1.03"; struct dz_port { struct uart_port port; @@ -61,22 +65,6 @@ struct dz_port { static struct dz_port dz_ports[DZ_NB_PORT]; -#ifdef DEBUG_DZ -/* - * debugging code to send out chars via prom - */ -static void debug_console(const char *s, int count) -{ - unsigned i; - - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); - } -} -#endif - /* * ------------------------------------------------------------ * dz_in () and dz_out () @@ -90,6 +78,7 @@ static inline unsigned short dz_in(struct dz_port *dport, unsigned offset) { volatile unsigned short *addr = (volatile unsigned short *) (dport->port.membase + offset); + return *addr; } @@ -98,6 +87,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, { volatile unsigned short *addr = (volatile unsigned short *) (dport->port.membase + offset); + *addr = value; } @@ -144,7 +134,7 @@ static void dz_stop_rx(struct uart_port *uport) spin_lock_irqsave(&dport->port.lock, flags); dport->cflag &= ~DZ_CREAD; - dz_out(dport, DZ_LPR, dport->cflag); + dz_out(dport, DZ_LPR, dport->cflag | dport->port.line); spin_unlock_irqrestore(&dport->port.lock, flags); } @@ -155,14 +145,14 @@ static void dz_enable_ms(struct uart_port *port) /* * ------------------------------------------------------------ - * Here starts the interrupt handling routines. All of the - * following subroutines are declared as inline and are folded - * into dz_interrupt. They were separated out for readability's - * sake. * - * Note: rs_interrupt() is a "fast" interrupt, which means that it + * Here start the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * dz_interrupt. They were separated out for readability's sake. + * + * Note: dz_interrupt() is a "fast" interrupt, which means that it * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as + * dz_interrupt() should try to keep the interrupt handler as fast as * possible. After you are done making modifications, it is not a bad * idea to do: * @@ -180,92 +170,74 @@ static void dz_enable_ms(struct uart_port *port) * This routine deals with inputs from any lines. * ------------------------------------------------------------ */ -static inline void dz_receive_chars(struct dz_port *dport) +static inline void dz_receive_chars(struct dz_port *dport_in, + struct pt_regs *regs) { + struct dz_port *dport; struct tty_struct *tty = NULL; struct uart_icount *icount; - int ignore = 0; - unsigned short status, tmp; + int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 }; + unsigned short status; unsigned char ch, flag; + int i; - /* this code is going to be a problem... - the call to tty_flip_buffer is going to need - to be rethought... - */ - do { - status = dz_in(dport, DZ_RBUF); - - /* punt so we don't get duplicate characters */ - if (!(status & DZ_DVAL)) - goto ignore_char; - - - ch = UCHAR(status); /* grab the char */ - flag = TTY_NORMAL; + while ((status = dz_in(dport_in, DZ_RBUF)) & DZ_DVAL) { + dport = &dz_ports[LINE(status)]; + tty = dport->port.info->tty; /* point to the proper dev */ -#if 0 - if (info->is_console) { - if (ch == 0) - return; /* it's a break ... */ - } -#endif + ch = UCHAR(status); /* grab the char */ - tty = dport->port.info->tty;/* now tty points to the proper dev */ icount = &dport->port.icount; - - if (!tty) - break; - icount->rx++; - /* keep track of the statistics */ - if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) { - if (status & DZ_PERR) /* parity error */ - icount->parity++; - else if (status & DZ_FERR) /* frame error */ - icount->frame++; - if (status & DZ_OERR) /* overrun error */ - icount->overrun++; - - /* check to see if we should ignore the character - and mask off conditions that should be ignored + flag = TTY_NORMAL; + if (status & DZ_FERR) { /* frame error */ + /* + * There is no separate BREAK status bit, so + * treat framing errors as BREAKs for Magic SysRq + * and SAK; normally, otherwise. */ - - if (status & dport->port.ignore_status_mask) { - if (++ignore > 100) - break; - goto ignore_char; - } - /* mask off the error conditions we want to ignore */ - tmp = status & dport->port.read_status_mask; - - if (tmp & DZ_PERR) { - flag = TTY_PARITY; -#ifdef DEBUG_DZ - debug_console("PERR\n", 5); -#endif - } else if (tmp & DZ_FERR) { + if (uart_handle_break(&dport->port)) + continue; + if (dport->port.flags & UPF_SAK) + flag = TTY_BREAK; + else flag = TTY_FRAME; -#ifdef DEBUG_DZ - debug_console("FERR\n", 5); -#endif - } - if (tmp & DZ_OERR) { -#ifdef DEBUG_DZ - debug_console("OERR\n", 5); -#endif - tty_insert_flip_char(tty, ch, flag); - ch = 0; - flag = TTY_OVERRUN; - } + } else if (status & DZ_OERR) /* overrun error */ + flag = TTY_OVERRUN; + else if (status & DZ_PERR) /* parity error */ + flag = TTY_PARITY; + + /* keep track of the statistics */ + switch (flag) { + case TTY_FRAME: + icount->frame++; + break; + case TTY_PARITY: + icount->parity++; + break; + case TTY_OVERRUN: + icount->overrun++; + break; + case TTY_BREAK: + icount->brk++; + break; + default: + break; } - tty_insert_flip_char(tty, ch, flag); - ignore_char: - ; - } while (status & DZ_DVAL); - if (tty) - tty_flip_buffer_push(tty); + if (uart_handle_sysrq_char(&dport->port, ch, regs)) + continue; + + if ((status & dport->port.ignore_status_mask) == 0) { + uart_insert_char(&dport->port, + status, DZ_OERR, ch, flag); + lines_rx[LINE(status)] = 1; + } + } + for (i = 0; i < DZ_NB_PORT; i++) + if (lines_rx[i]) + tty_flip_buffer_push(dz_ports[i].port.info->tty); } /* @@ -275,26 +247,32 @@ static inline void dz_receive_chars(struct dz_port *dport) * This routine deals with outputs to any lines. * ------------------------------------------------------------ */ -static inline void dz_transmit_chars(struct dz_port *dport) +static inline void dz_transmit_chars(struct dz_port *dport_in) { - struct circ_buf *xmit = &dport->port.info->xmit; + struct dz_port *dport; + struct circ_buf *xmit; + unsigned short status; unsigned char tmp; - if (dport->port.x_char) { /* XON/XOFF chars */ + status = dz_in(dport_in, DZ_CSR); + dport = &dz_ports[LINE(status)]; + xmit = &dport->port.info->xmit; + + if (dport->port.x_char) { /* XON/XOFF chars */ dz_out(dport, DZ_TDR, dport->port.x_char); dport->port.icount.tx++; dport->port.x_char = 0; return; } - /* if nothing to do or stopped or hardware stopped */ + /* If nothing to do or stopped or hardware stopped. */ if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { dz_stop_tx(&dport->port); return; } /* - * if something to do ... (rember the dz has no output fifo so we go - * one char at a time :-< + * If something to do... (remember the dz has no output fifo, + * so we go one char at a time) :-< */ tmp = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1); @@ -304,23 +282,29 @@ static inline void dz_transmit_chars(struct dz_port *dport) if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS) uart_write_wakeup(&dport->port); - /* Are we done */ + /* Are we are done. */ if (uart_circ_empty(xmit)) dz_stop_tx(&dport->port); } /* * ------------------------------------------------------------ - * check_modem_status () + * check_modem_status() * - * Only valid for the MODEM line duh ! + * DS 3100 & 5100: Only valid for the MODEM line, duh! + * DS 5000/200: Valid for the MODEM and PRINTER line. * ------------------------------------------------------------ */ static inline void check_modem_status(struct dz_port *dport) { + /* + * FIXME: + * 1. No status change interrupt; use a timer. + * 2. Handle the 3100/5000 as appropriate. --macro + */ unsigned short status; - /* if not ne modem line just return */ + /* If not the modem line just return. */ if (dport->port.line != DZ_MODEM) return; @@ -341,21 +325,18 @@ static inline void check_modem_status(struct dz_port *dport) */ static irqreturn_t dz_interrupt(int irq, void *dev) { - struct dz_port *dport; + struct dz_port *dport = (struct dz_port *)dev; unsigned short status; /* get the reason why we just got an irq */ - status = dz_in((struct dz_port *)dev, DZ_CSR); - dport = &dz_ports[LINE(status)]; + status = dz_in(dport, DZ_CSR); - if (status & DZ_RDONE) - dz_receive_chars(dport); + if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) + dz_receive_chars(dport, regs); - if (status & DZ_TRDY) + if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) dz_transmit_chars(dport); - /* FIXME: what about check modem status??? --rmk */ - return IRQ_HANDLED; } @@ -367,13 +348,13 @@ static irqreturn_t dz_interrupt(int irq, void *dev) static unsigned int dz_get_mctrl(struct uart_port *uport) { + /* + * FIXME: Handle the 3100/5000 as appropriate. --macro + */ struct dz_port *dport = (struct dz_port *)uport; unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; if (dport->port.line == DZ_MODEM) { - /* - * CHECKME: This is a guess from the other code... --rmk - */ if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR) mctrl &= ~TIOCM_DSR; } @@ -383,6 +364,9 @@ static unsigned int dz_get_mctrl(struct uart_port *uport) static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) { + /* + * FIXME: Handle the 3100/5000 as appropriate. --macro + */ struct dz_port *dport = (struct dz_port *)uport; unsigned short tmp; @@ -409,13 +393,6 @@ static int dz_startup(struct uart_port *uport) unsigned long flags; unsigned short tmp; - /* The dz lines for the mouse/keyboard must be - * opened using their respective drivers. - */ - if ((dport->port.line == DZ_KEYBOARD) || - (dport->port.line == DZ_MOUSE)) - return -ENODEV; - spin_lock_irqsave(&dport->port.lock, flags); /* enable the interrupt and the scanning */ @@ -442,7 +419,8 @@ static void dz_shutdown(struct uart_port *uport) } /* - * get_lsr_info - get line status register info + * ------------------------------------------------------------------- + * dz_tx_empty() -- get the transmitter empty status * * Purpose: Let user call ioctl() to get info when the UART physically * is emptied. On bus types like RS485, the transmitter must @@ -450,21 +428,28 @@ static void dz_shutdown(struct uart_port *uport) * the transmit shift register is empty, not be done when the * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. + * ------------------------------------------------------------------- */ static unsigned int dz_tx_empty(struct uart_port *uport) { struct dz_port *dport = (struct dz_port *)uport; - unsigned short status = dz_in(dport, DZ_LPR); + unsigned short tmp, mask = 1 << dport->port.line; - /* FIXME: this appears to be obviously broken --rmk. */ - return status ? TIOCSER_TEMT : 0; + tmp = dz_in(dport, DZ_TCR); + tmp &= mask; + + return tmp ? 0 : TIOCSER_TEMT; } static void dz_break_ctl(struct uart_port *uport, int break_state) { + /* + * FIXME: Can't access BREAK bits in TDR easily; + * reuse the code for polled TX. --macro + */ struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; - unsigned short tmp, mask = 1 << uport->line; + unsigned short tmp, mask = 1 << dport->port.line; spin_lock_irqsave(&uport->lock, flags); tmp = dz_in(dport, DZ_TCR); @@ -476,8 +461,8 @@ static void dz_break_ctl(struct uart_port *uport, int break_state) spin_unlock_irqrestore(&uport->lock, flags); } -static void dz_set_termios(struct uart_port *uport, struct termios *termios, - struct termios *old_termios) +static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, + struct ktermios *old_termios) { struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; @@ -561,7 +546,7 @@ static void dz_set_termios(struct uart_port *uport, struct termios *termios, spin_lock_irqsave(&dport->port.lock, flags); - dz_out(dport, DZ_LPR, cflag); + dz_out(dport, DZ_LPR, cflag | dport->port.line); dport->cflag = cflag; /* setup accept flag */ @@ -650,7 +635,7 @@ static void __init dz_init_ports(void) for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { spin_lock_init(&dport->port.lock); dport->port.membase = (char *) base; - dport->port.iotype = UPIO_PORT; + dport->port.iotype = UPIO_MEM; dport->port.irq = dec_interrupt[DEC_IRQ_DZ11]; dport->port.line = i; dport->port.fifosize = 1; @@ -662,10 +647,7 @@ static void __init dz_init_ports(void) static void dz_reset(struct dz_port *dport) { dz_out(dport, DZ_CSR, DZ_CLR); - while (dz_in(dport, DZ_CSR) & DZ_CLR); - /* FIXME: cpu_relax? */ - iob(); /* enable scanning */ @@ -673,26 +655,55 @@ static void dz_reset(struct dz_port *dport) } #ifdef CONFIG_SERIAL_DZ_CONSOLE +/* + * ------------------------------------------------------------------- + * dz_console_putchar() -- transmit a character + * + * Polled transmission. This is tricky. We need to mask transmit + * interrupts so that they do not interfere, enable the transmitter + * for the line requested and then wait till the transmit scanner + * requests data for this line. But it may request data for another + * line first, in which case we have to disable its transmitter and + * repeat waiting till our line pops up. Only then the character may + * be transmitted. Finally, the state of the transmitter mask is + * restored. Welcome to the world of PDP-11! + * ------------------------------------------------------------------- + */ static void dz_console_putchar(struct uart_port *uport, int ch) { struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; - int loops = 2500; - unsigned short tmp = (unsigned char)ch; - /* this code sends stuff out to serial device - spinning its - wheels and waiting. */ + unsigned short csr, tcr, trdy, mask; + int loops = 10000; spin_lock_irqsave(&dport->port.lock, flags); + csr = dz_in(dport, DZ_CSR); + dz_out(dport, DZ_CSR, csr & ~DZ_TIE); + tcr = dz_in(dport, DZ_TCR); + tcr |= 1 << dport->port.line; + mask = tcr; + dz_out(dport, DZ_TCR, mask); + iob(); + spin_unlock_irqrestore(&dport->port.lock, flags); - /* spin our wheels */ - while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--) - /* FIXME: cpu_relax, udelay? --rmk */ - ; + while (loops--) { + trdy = dz_in(dport, DZ_CSR); + if (!(trdy & DZ_TRDY)) + continue; + trdy = (trdy & DZ_TLINE) >> 8; + if (trdy == dport->port.line) + break; + mask &= ~(1 << trdy); + dz_out(dport, DZ_TCR, mask); + iob(); + udelay(2); + } - /* Actually transmit the character. */ - dz_out(dport, DZ_TDR, tmp); + if (loops) /* Cannot send otherwise. */ + dz_out(dport, DZ_TDR, ch); - spin_unlock_irqrestore(&dport->port.lock, flags); + dz_out(dport, DZ_TCR, tcr); + dz_out(dport, DZ_CSR, csr); } /* @@ -703,11 +714,11 @@ static void dz_console_putchar(struct uart_port *uport, int ch) * The console must be locked when we get here. * ------------------------------------------------------------------- */ -static void dz_console_print(struct console *cons, +static void dz_console_print(struct console *co, const char *str, unsigned int count) { - struct dz_port *dport = &dz_ports[CONSOLE_LINE]; + struct dz_port *dport = &dz_ports[co->index]; #ifdef DEBUG_DZ prom_printf((char *) str); #endif @@ -716,49 +727,43 @@ static void dz_console_print(struct console *cons, static int __init dz_console_setup(struct console *co, char *options) { - struct dz_port *dport = &dz_ports[CONSOLE_LINE]; + struct dz_port *dport = &dz_ports[co->index]; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; - int ret; - unsigned short mask, tmp; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); dz_reset(dport); - ret = uart_set_options(&dport->port, co, baud, parity, bits, flow); - if (ret == 0) { - mask = 1 << dport->port.line; - tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ - if (!(tmp & mask)) { - tmp |= mask; /* set the TX flag */ - dz_out(dport, DZ_TCR, tmp); - } - } - - return ret; + return uart_set_options(&dport->port, co, baud, parity, bits, flow); } -static struct console dz_sercons = -{ +static struct uart_driver dz_reg; +static struct console dz_sercons = { .name = "ttyS", .write = dz_console_print, .device = uart_console_device, .setup = dz_console_setup, - .flags = CON_CONSDEV | CON_PRINTBUFFER, - .index = CONSOLE_LINE, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &dz_reg, }; -void __init dz_serial_console_init(void) +static int __init dz_serial_console_init(void) { - dz_init_ports(); - - register_console(&dz_sercons); + if (!IOASIC) { + dz_init_ports(); + register_console(&dz_sercons); + return 0; + } else + return -ENXIO; } +console_initcall(dz_serial_console_init); + #define SERIAL_DZ_CONSOLE &dz_sercons #else #define SERIAL_DZ_CONSOLE NULL @@ -767,35 +772,29 @@ void __init dz_serial_console_init(void) static struct uart_driver dz_reg = { .owner = THIS_MODULE, .driver_name = "serial", - .dev_name = "ttyS%d", + .dev_name = "ttyS", .major = TTY_MAJOR, .minor = 64, .nr = DZ_NB_PORT, .cons = SERIAL_DZ_CONSOLE, }; -int __init dz_init(void) +static int __init dz_init(void) { - unsigned long flags; int ret, i; + if (IOASIC) + return -ENXIO; + printk("%s%s\n", dz_name, dz_version); dz_init_ports(); - save_flags(flags); - cli(); - #ifndef CONFIG_SERIAL_DZ_CONSOLE /* reset the chip */ dz_reset(&dz_ports[0]); #endif - /* order matters here... the trick is that flags - is updated... in request_irq - to immediatedly obliterate - it is unwise. */ - restore_flags(flags); - if (request_irq(dz_ports[0].port.irq, dz_interrupt, IRQF_DISABLED, "DZ", &dz_ports[0])) panic("Unable to register DZ interrupt"); @@ -810,5 +809,7 @@ int __init dz_init(void) return ret; } +module_init(dz_init); + MODULE_DESCRIPTION("DECstation DZ serial driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/serial/dz.h b/drivers/serial/dz.h index 86ef417382b..9674d4e4987 100644 --- a/drivers/serial/dz.h +++ b/drivers/serial/dz.h @@ -1,20 +1,22 @@ /* - * dz.h: Serial port driver for DECStations equiped + * dz.h: Serial port driver for DECstations equipped * with the DZ chipset. * * Copyright (C) 1998 Olivier A. D. Lebaillif * * Email: olivier.lebaillif@ifrsys.com * + * Copyright (C) 2004, 2006 Maciej W. Rozycki */ #ifndef DZ_SERIAL_H #define DZ_SERIAL_H /* - * Definitions for the Control and Status Received. + * Definitions for the Control and Status Register. */ #define DZ_TRDY 0x8000 /* Transmitter empty */ -#define DZ_TIE 0x4000 /* Transmitter Interrupt Enable */ +#define DZ_TIE 0x4000 /* Transmitter Interrupt Enbl */ +#define DZ_TLINE 0x0300 /* Transmitter Line Number */ #define DZ_RDONE 0x0080 /* Receiver data ready */ #define DZ_RIE 0x0040 /* Receive Interrupt Enable */ #define DZ_MSE 0x0020 /* Master Scan Enable */ @@ -22,32 +24,44 @@ #define DZ_MAINT 0x0008 /* Loop Back Mode */ /* - * Definitions for the Received buffer. + * Definitions for the Receiver Buffer Register. */ -#define DZ_RBUF_MASK 0x00FF /* Data Mask in the Receive Buffer */ -#define DZ_LINE_MASK 0x0300 /* Line Mask in the Receive Buffer */ +#define DZ_RBUF_MASK 0x00FF /* Data Mask */ +#define DZ_LINE_MASK 0x0300 /* Line Mask */ #define DZ_DVAL 0x8000 /* Valid Data indicator */ #define DZ_OERR 0x4000 /* Overrun error indicator */ #define DZ_FERR 0x2000 /* Frame error indicator */ #define DZ_PERR 0x1000 /* Parity error indicator */ -#define LINE(x) (x & DZ_LINE_MASK) >> 8 /* Get the line number from the input buffer */ -#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK) +#define LINE(x) ((x & DZ_LINE_MASK) >> 8) /* Get the line number + from the input buffer */ +#define UCHAR(x) ((unsigned char)(x & DZ_RBUF_MASK)) /* - * Definitions for the Transmit Register. + * Definitions for the Transmit Control Register. */ #define DZ_LINE_KEYBOARD 0x0001 #define DZ_LINE_MOUSE 0x0002 #define DZ_LINE_MODEM 0x0004 #define DZ_LINE_PRINTER 0x0008 +#define DZ_MODEM_RTS 0x0800 /* RTS for the modem line (2) */ #define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */ +#define DZ_PRINT_RTS 0x0200 /* RTS for the prntr line (3) */ +#define DZ_PRINT_DTR 0x0100 /* DTR for the prntr line (3) */ +#define DZ_LNENB 0x000f /* Transmitter Line Enable */ /* * Definitions for the Modem Status Register. */ +#define DZ_MODEM_RI 0x0800 /* RI for the modem line (2) */ +#define DZ_MODEM_CD 0x0400 /* CD for the modem line (2) */ #define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */ +#define DZ_MODEM_CTS 0x0100 /* CTS for the modem line (2) */ +#define DZ_PRINT_RI 0x0008 /* RI for the printer line (3) */ +#define DZ_PRINT_CD 0x0004 /* CD for the printer line (3) */ +#define DZ_PRINT_DSR 0x0002 /* DSR for the prntr line (3) */ +#define DZ_PRINT_CTS 0x0001 /* CTS for the prntr line (3) */ /* * Definitions for the Transmit Data Register. diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 8aa0f641866..7d623003e65 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -1087,8 +1087,8 @@ static void icom_close(struct uart_port *port) } static void icom_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old_termios) + struct ktermios *termios, + struct ktermios *old_termios) { int baud; unsigned cflag, iflag; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index ee5c782597d..e216dcf2937 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -459,8 +459,8 @@ static void imx_shutdown(struct uart_port *port) } static void -imx_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +imx_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct imx_port *sport = (struct imx_port *)port; unsigned long flags; diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 2308d26c862..9cc0be93231 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c @@ -950,7 +950,7 @@ static void transmit_chars(struct uart_port *the_port) */ static void ioc3_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) + struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc3_port *port = get_ioc3_port(the_port); unsigned int cflag; @@ -1853,7 +1853,7 @@ static int ic3_startup(struct uart_port *the_port) */ static void ic3_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) + struct ktermios *termios, struct ktermios *old_termios) { unsigned long port_flags; diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 98ce88d8020..c862f67c985 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -921,7 +921,7 @@ static void handle_dma_error_intr(void *arg, uint32_t other_ir) { struct ioc4_port *port = (struct ioc4_port *)arg; struct hooks *hooks = port->ip_hooks; - unsigned int flags; + unsigned long flags; spin_lock_irqsave(&port->ip_lock, flags); @@ -1681,7 +1681,7 @@ static void transmit_chars(struct uart_port *the_port) */ static void ioc4_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) + struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc4_port *port = get_ioc4_port(the_port, 0); int baud, bits; @@ -1802,7 +1802,7 @@ static inline int ic4_startup_local(struct uart_port *the_port) ioc4_set_proto(port, the_port->mapbase); /* set the speed of the serial port */ - ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); + ioc4_change_speed(the_port, info->tty->termios, (struct ktermios *)0); return 0; } @@ -1834,7 +1834,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) struct ioc4_port *port = (struct ioc4_port *)arg; struct hooks *hooks = port->ip_hooks; unsigned int rx_high_rd_aborted = 0; - unsigned int flags; + unsigned long flags; struct uart_port *the_port; int loop_counter; @@ -2570,7 +2570,7 @@ static int ic4_startup(struct uart_port *the_port) */ static void ic4_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) + struct ktermios *termios, struct ktermios *old_termios) { unsigned long port_flags; @@ -2935,7 +2935,7 @@ static void __devexit ioc4_serial_exit(void) uart_unregister_driver(&ioc4_uart_rs422); } -module_init(ioc4_serial_init); +late_initcall(ioc4_serial_init); /* Call only after tty init is done */ module_exit(ioc4_serial_exit); MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index dca6c1bde8f..0746c9446ae 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -840,8 +840,8 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag, /* The port lock is not held. */ static void -ip22zilog_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; unsigned long flags; diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index f8262e6ad8d..7cf1c60027f 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -142,7 +142,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch) { unsigned long lock_flags; struct jsm_channel *channel = (struct jsm_channel *)port; - struct termios *termios; + struct ktermios *termios; spin_lock_irqsave(&port->lock, lock_flags); termios = port->info->tty->termios; @@ -180,7 +180,7 @@ static int jsm_tty_open(struct uart_port *port) struct jsm_board *brd; int rc = 0; struct jsm_channel *channel = (struct jsm_channel *)port; - struct termios *termios; + struct ktermios *termios; /* Get board pointer from our array of majors we have allocated */ brd = channel->ch_bd; @@ -269,7 +269,7 @@ static int jsm_tty_open(struct uart_port *port) static void jsm_tty_close(struct uart_port *port) { struct jsm_board *bd; - struct termios *ts; + struct ktermios *ts; struct jsm_channel *channel = (struct jsm_channel *)port; jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); @@ -302,8 +302,8 @@ static void jsm_tty_close(struct uart_port *port) } static void jsm_tty_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old_termios) + struct ktermios *termios, + struct ktermios *old_termios) { unsigned long lock_flags; struct jsm_channel *channel = (struct jsm_channel *)port; diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 7656a35f5e2..6e09c8b395e 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -699,7 +699,7 @@ static unsigned int m32r_sio_get_divisor(struct uart_port *port, } static void m32r_sio_set_termios(struct uart_port *port, - struct termios *termios, struct termios *old) + struct ktermios *termios, struct ktermios *old) { struct uart_sio_port *up = (struct uart_sio_port *)port; unsigned char cval = 0; diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index aee1b31f1a1..08430961a89 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -60,7 +60,8 @@ struct timer_list mcfrs_timer_struct; #if defined(CONFIG_HW_FEITH) #define CONSOLE_BAUD_RATE 38400 #define DEFAULT_CBAUD B38400 -#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || defined(CONFIG_M5329EVB) +#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \ + defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO) #define CONSOLE_BAUD_RATE 115200 #define DEFAULT_CBAUD B115200 #elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ @@ -109,12 +110,30 @@ static struct mcf_serial mcfrs_table[] = { .irq = IRQBASE, .flags = ASYNC_BOOT_AUTOCONF, }, +#ifdef MCFUART_BASE2 { /* ttyS1 */ .magic = 0, .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2), .irq = IRQBASE+1, .flags = ASYNC_BOOT_AUTOCONF, }, +#endif +#ifdef MCFUART_BASE3 + { /* ttyS2 */ + .magic = 0, + .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3), + .irq = IRQBASE+2, + .flags = ASYNC_BOOT_AUTOCONF, + }, +#endif +#ifdef MCFUART_BASE4 + { /* ttyS3 */ + .magic = 0, + .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4), + .irq = IRQBASE+3, + .flags = ASYNC_BOOT_AUTOCONF, + }, +#endif }; @@ -1113,7 +1132,7 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; @@ -1516,6 +1535,22 @@ static void mcfrs_irqinit(struct mcf_serial *info) imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + MCFINTC_IMRL); *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); +#if defined(CONFIG_M527x) + { + /* + * External Pin Mask Setting & Enable External Pin for Interface + * mrcbis@aliceposta.it + */ + unsigned short *serpin_enable_mask; + serpin_enable_mask = (MCF_IPSBAR + MCF_GPIO_PAR_UART); + if (info->line == 0) + *serpin_enable_mask |= UART0_ENABLE_MASK; + else if (info->line == 1) + *serpin_enable_mask |= UART1_ENABLE_MASK; + else if (info->line == 2) + *serpin_enable_mask |= UART2_ENABLE_MASK; + } +#endif #elif defined(CONFIG_M520x) volatile unsigned char *icrp, *uartp; volatile unsigned long *imrp; @@ -1713,7 +1748,7 @@ mcfrs_init(void) /* Initialize the tty_driver structure */ mcfrs_serial_driver->owner = THIS_MODULE; mcfrs_serial_driver->name = "ttyS"; - mcfrs_serial_driver->driver_name = "serial"; + mcfrs_serial_driver->driver_name = "mcfserial"; mcfrs_serial_driver->major = TTY_MAJOR; mcfrs_serial_driver->minor_start = 64; mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; @@ -1797,10 +1832,23 @@ void mcfrs_init_console(void) uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8; uartp[MCFUART_UMR] = MCFUART_MR2_STOP1; +#ifdef CONFIG_M5272 +{ + /* + * For the MCF5272, also compute the baudrate fraction. + */ + int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud); + fraction *= 16; + fraction /= (32 * mcfrs_console_baud); + uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */ + clk = (MCF_BUSCLK / mcfrs_console_baud) / 32; +} +#else clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */ +#endif + uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8; /* set msb baud */ uartp[MCFUART_UBG2] = (clk & 0xff); /* set lsb baud */ - uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 4f80c5b4a75..9d11a75663e 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -1,6 +1,4 @@ /* - * drivers/serial/mpc52xx_uart.c - * * Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs. * * FIXME According to the usermanual the status bits in the status register @@ -14,18 +12,20 @@ * * * Maintainer : Sylvain Munaut <tnt@246tNt.com> - * + * * Some of the code has been inspired/copied from the 2.4 code written * by Dale Farnsworth <dfarnsworth@mvista.com>. - * - * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com> + * + * Copyright (C) 2006 Secret Lab Technologies Ltd. + * Grant Likely <grant.likely@secretlab.ca> + * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> * Copyright (C) 2003 MontaVista, Software, Inc. - * + * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. */ - + /* Platform device Usage : * * Since PSCs can have multiple function, the correct driver for each one @@ -44,7 +44,24 @@ * will be mapped to. */ -#include <linux/platform_device.h> +/* OF Platform device Usage : + * + * This driver is only used for PSCs configured in uart mode. The device + * tree will have a node for each PSC in uart mode w/ device_type = "serial" + * and "mpc52xx-psc-uart" in the compatible string + * + * By default, PSC devices are enumerated in the order they are found. However + * a particular PSC number can be forces by adding 'device_no = <port#>' + * to the device node. + * + * The driver init all necessary registers to place the PSC in uart mode without + * DCD. However, the pin multiplexing aren't changed and should be set either + * by the bootloader or in the platform init code. + */ + +#undef DEBUG + +#include <linux/device.h> #include <linux/module.h> #include <linux/tty.h> #include <linux/serial.h> @@ -54,6 +71,12 @@ #include <asm/delay.h> #include <asm/io.h> +#if defined(CONFIG_PPC_MERGE) +#include <asm/of_platform.h> +#else +#include <linux/platform_device.h> +#endif + #include <asm/mpc52xx.h> #include <asm/mpc52xx_psc.h> @@ -80,6 +103,12 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM]; * it's cleared, then a memset(...,0,...) should be added to * the console_init */ +#if defined(CONFIG_PPC_MERGE) +/* lookup table for matching device nodes to index numbers */ +static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM]; + +static void mpc52xx_uart_of_enumerate(void); +#endif #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) @@ -96,32 +125,40 @@ static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id); #define uart_console(port) (0) #endif +#if defined(CONFIG_PPC_MERGE) +static struct of_device_id mpc52xx_uart_of_match[] = { + { .type = "serial", .compatible = "mpc52xx-psc-uart", }, + { .type = "serial", .compatible = "mpc5200-psc", }, /* Efika only! */ + {}, +}; +#endif + /* ======================================================================== */ /* UART operations */ /* ======================================================================== */ -static unsigned int +static unsigned int mpc52xx_uart_tx_empty(struct uart_port *port) { int status = in_be16(&PSC(port)->mpc52xx_psc_status); return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0; } -static void +static void mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) { /* Not implemented */ } -static unsigned int +static unsigned int mpc52xx_uart_get_mctrl(struct uart_port *port) { /* Not implemented */ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; } -static void +static void mpc52xx_uart_stop_tx(struct uart_port *port) { /* port->lock taken by caller */ @@ -129,7 +166,7 @@ mpc52xx_uart_stop_tx(struct uart_port *port) out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); } -static void +static void mpc52xx_uart_start_tx(struct uart_port *port) { /* port->lock taken by caller */ @@ -137,12 +174,12 @@ mpc52xx_uart_start_tx(struct uart_port *port) out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); } -static void +static void mpc52xx_uart_send_xchar(struct uart_port *port, char ch) { unsigned long flags; spin_lock_irqsave(&port->lock, flags); - + port->x_char = ch; if (ch) { /* Make sure tx interrupts are on */ @@ -150,7 +187,7 @@ mpc52xx_uart_send_xchar(struct uart_port *port, char ch) port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); } - + spin_unlock_irqrestore(&port->lock, flags); } @@ -178,7 +215,7 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) out_8(&PSC(port)->command,MPC52xx_PSC_START_BRK); else out_8(&PSC(port)->command,MPC52xx_PSC_STOP_BRK); - + spin_unlock_irqrestore(&port->lock, flags); } @@ -197,11 +234,11 @@ mpc52xx_uart_startup(struct uart_port *port) /* Reset/activate the port, clear and enable interrupts */ out_8(&psc->command,MPC52xx_PSC_RST_RX); out_8(&psc->command,MPC52xx_PSC_RST_TX); - + out_be32(&psc->sicr,0); /* UART mode DCD ignored */ out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */ - + out_8(&psc->rfcntl, 0x00); out_be16(&psc->rfalarm, 0x1ff); out_8(&psc->tfcntl, 0x07); @@ -209,10 +246,10 @@ mpc52xx_uart_startup(struct uart_port *port) port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask); - + out_8(&psc->command,MPC52xx_PSC_TX_ENABLE); out_8(&psc->command,MPC52xx_PSC_RX_ENABLE); - + return 0; } @@ -220,31 +257,31 @@ static void mpc52xx_uart_shutdown(struct uart_port *port) { struct mpc52xx_psc __iomem *psc = PSC(port); - + /* Shut down the port, interrupt and all */ out_8(&psc->command,MPC52xx_PSC_RST_RX); out_8(&psc->command,MPC52xx_PSC_RST_TX); - - port->read_status_mask = 0; + + port->read_status_mask = 0; out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask); /* Release interrupt */ free_irq(port->irq, port); } -static void -mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, - struct termios *old) +static void +mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) { struct mpc52xx_psc __iomem *psc = PSC(port); unsigned long flags; unsigned char mr1, mr2; unsigned short ctr; unsigned int j, baud, quot; - + /* Prepare what we're gonna write */ mr1 = 0; - + switch (new->c_cflag & CSIZE) { case CS5: mr1 |= MPC52xx_PSC_MODE_5_BITS; break; @@ -261,8 +298,8 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN; } else mr1 |= MPC52xx_PSC_MODE_PARNONE; - - + + mr2 = 0; if (new->c_cflag & CSTOPB) @@ -276,7 +313,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); ctr = quot & 0xffff; - + /* Get the lock */ spin_lock_irqsave(&port->lock, flags); @@ -290,14 +327,14 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, * boot for the console, all stuff is not yet ready to receive at that * time and that just makes the kernel oops */ /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ - while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && + while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && --j) udelay(1); if (!j) printk( KERN_ERR "mpc52xx_uart.c: " "Unable to flush RX & TX fifos in-time in set_termios." - "Some chars may have been lost.\n" ); + "Some chars may have been lost.\n" ); /* Reset the TX & RX */ out_8(&psc->command,MPC52xx_PSC_RST_RX); @@ -309,7 +346,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, out_8(&psc->mode,mr2); out_8(&psc->ctur,ctr >> 8); out_8(&psc->ctlr,ctr & 0xff); - + /* Reenable TX & RX */ out_8(&psc->command,MPC52xx_PSC_TX_ENABLE); out_8(&psc->command,MPC52xx_PSC_RX_ENABLE); @@ -332,7 +369,7 @@ mpc52xx_uart_release_port(struct uart_port *port) port->membase = NULL; } - release_mem_region(port->mapbase, MPC52xx_PSC_SIZE); + release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); } static int @@ -341,12 +378,13 @@ mpc52xx_uart_request_port(struct uart_port *port) int err; if (port->flags & UPF_IOREMAP) /* Need to remap ? */ - port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE); + port->membase = ioremap(port->mapbase, + sizeof(struct mpc52xx_psc)); if (!port->membase) return -EINVAL; - err = request_mem_region(port->mapbase, MPC52xx_PSC_SIZE, + err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc), "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; if (err && (port->flags & UPF_IOREMAP)) { @@ -373,7 +411,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser) if ( (ser->irq != port->irq) || (ser->io_type != SERIAL_IO_MEM) || - (ser->baud_base != port->uartclk) || + (ser->baud_base != port->uartclk) || (ser->iomem_base != (void*)port->mapbase) || (ser->hub6 != 0 ) ) return -EINVAL; @@ -404,11 +442,11 @@ static struct uart_ops mpc52xx_uart_ops = { .verify_port = mpc52xx_uart_verify_port }; - + /* ======================================================================== */ /* Interrupt handling */ /* ======================================================================== */ - + static inline int mpc52xx_uart_int_rx_chars(struct uart_port *port) { @@ -435,11 +473,11 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) flag = TTY_NORMAL; port->icount.rx++; - + if ( status & (MPC52xx_PSC_SR_PE | MPC52xx_PSC_SR_FE | MPC52xx_PSC_SR_RB) ) { - + if (status & MPC52xx_PSC_SR_RB) { flag = TTY_BREAK; uart_handle_break(port); @@ -464,7 +502,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) } tty_flip_buffer_push(tty); - + return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY; } @@ -509,25 +547,25 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) return 1; } -static irqreturn_t +static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id) { struct uart_port *port = dev_id; unsigned long pass = ISR_PASS_LIMIT; unsigned int keepgoing; unsigned short status; - + spin_lock(&port->lock); - + /* While we have stuff to do, we continue */ do { /* If we don't find anything to do, we stop */ - keepgoing = 0; - + keepgoing = 0; + /* Read status */ status = in_be16(&PSC(port)->mpc52xx_psc_isr); status &= port->read_status_mask; - + /* Do we need to receive chars ? */ /* For this RX interrupts must be on and some chars waiting */ if ( status & MPC52xx_PSC_IMR_RXRDY ) @@ -537,15 +575,15 @@ mpc52xx_uart_int(int irq, void *dev_id) /* For this, TX must be ready and TX interrupt enabled */ if ( status & MPC52xx_PSC_IMR_TXRDY ) keepgoing |= mpc52xx_uart_int_tx_chars(port); - + /* Limit number of iteration */ if ( !(--pass) ) keepgoing = 0; } while (keepgoing); - + spin_unlock(&port->lock); - + return IRQ_HANDLED; } @@ -563,13 +601,18 @@ mpc52xx_console_get_options(struct uart_port *port, struct mpc52xx_psc __iomem *psc = PSC(port); unsigned char mr1; + pr_debug("mpc52xx_console_get_options(port=%p)\n", port); + /* Read the mode registers */ out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1); mr1 = in_8(&psc->mode); - + /* CT{U,L}R are write-only ! */ - *baud = __res.bi_baudrate ? - __res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; + *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; +#if !defined(CONFIG_PPC_MERGE) + if (__res.bi_baudrate) + *baud = __res.bi_baudrate; +#endif /* Parse them */ switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) { @@ -579,26 +622,26 @@ mpc52xx_console_get_options(struct uart_port *port, case MPC52xx_PSC_MODE_8_BITS: default: *bits = 8; } - + if (mr1 & MPC52xx_PSC_MODE_PARNONE) *parity = 'n'; else *parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e'; } -static void +static void mpc52xx_console_write(struct console *co, const char *s, unsigned int count) { struct uart_port *port = &mpc52xx_uart_ports[co->index]; struct mpc52xx_psc __iomem *psc = PSC(port); unsigned int i, j; - + /* Disable interrupts */ out_be16(&psc->mpc52xx_psc_imr, 0); /* Wait the TX buffer to be empty */ - j = 5000000; /* Maximum wait */ - while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && + j = 5000000; /* Maximum wait */ + while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && --j) udelay(1); @@ -607,13 +650,13 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count) /* Line return handling */ if (*s == '\n') out_8(&psc->mpc52xx_psc_buffer_8, '\r'); - + /* Send the char */ out_8(&psc->mpc52xx_psc_buffer_8, *s); /* Wait the TX buffer to be empty */ - j = 20000; /* Maximum wait */ - while (!(in_be16(&psc->mpc52xx_psc_status) & + j = 20000; /* Maximum wait */ + while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && --j) udelay(1); } @@ -622,6 +665,7 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count) out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); } +#if !defined(CONFIG_PPC_MERGE) static int __init mpc52xx_console_setup(struct console *co, char *options) { @@ -634,7 +678,7 @@ mpc52xx_console_setup(struct console *co, char *options) if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM) return -EINVAL; - + /* Basic port init. Needed since we use some uart_??? func before * real init for early access */ spin_lock_init(&port->lock); @@ -656,6 +700,78 @@ mpc52xx_console_setup(struct console *co, char *options) return uart_set_options(port, co, baud, parity, bits, flow); } +#else + +static int __init +mpc52xx_console_setup(struct console *co, char *options) +{ + struct uart_port *port = &mpc52xx_uart_ports[co->index]; + struct device_node *np = mpc52xx_uart_nodes[co->index]; + unsigned int ipb_freq; + struct resource res; + int ret; + + int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n", + co, co->index, options); + + if ((co->index < 0) || (co->index > MPC52xx_PSC_MAXNUM)) { + pr_debug("PSC%x out of range\n", co->index); + return -EINVAL; + } + + if (!np) { + pr_debug("PSC%x not found in device tree\n", co->index); + return -EINVAL; + } + + pr_debug("Console on ttyPSC%x is %s\n", + co->index, mpc52xx_uart_nodes[co->index]->full_name); + + /* Fetch register locations */ + if ((ret = of_address_to_resource(np, 0, &res)) != 0) { + pr_debug("Could not get resources for PSC%x\n", co->index); + return ret; + } + + /* Search for bus-frequency property in this node or a parent */ + if ((ipb_freq = mpc52xx_find_ipb_freq(np)) == 0) { + pr_debug("Could not find IPB bus frequency!\n"); + return -EINVAL; + } + + /* Basic port init. Needed since we use some uart_??? func before + * real init for early access */ + spin_lock_init(&port->lock); + port->uartclk = ipb_freq / 2; + port->ops = &mpc52xx_uart_ops; + port->mapbase = res.start; + port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); + port->irq = irq_of_parse_and_map(np, 0); + + if (port->membase == NULL) + return -EINVAL; + + pr_debug("mpc52xx-psc uart at %lx, mapped to %p, irq=%x, freq=%i\n", + port->mapbase, port->membase, port->irq, port->uartclk); + + /* Setup the port parameters accoding to options */ + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow); + + pr_debug("Setting console parameters: %i %i%c1 flow=%c\n", + baud, bits, parity, flow); + + return uart_set_options(port, co, baud, parity, bits, flow); +} +#endif /* defined(CONFIG_PPC_MERGE) */ + static struct uart_driver mpc52xx_uart_driver; @@ -669,10 +785,11 @@ static struct console mpc52xx_console = { .data = &mpc52xx_uart_driver, }; - -static int __init + +static int __init mpc52xx_console_init(void) { + mpc52xx_uart_of_enumerate(); register_console(&mpc52xx_console); return 0; } @@ -700,6 +817,7 @@ static struct uart_driver mpc52xx_uart_driver = { }; +#if !defined(CONFIG_PPC_MERGE) /* ======================================================================== */ /* Platform Driver */ /* ======================================================================== */ @@ -723,8 +841,6 @@ mpc52xx_uart_probe(struct platform_device *dev) /* Init the port structure */ port = &mpc52xx_uart_ports[idx]; - memset(port, 0x00, sizeof(struct uart_port)); - spin_lock_init(&port->lock); port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ port->fifosize = 512; @@ -733,6 +849,7 @@ mpc52xx_uart_probe(struct platform_device *dev) ( uart_console(port) ? 0 : UPF_IOREMAP ); port->line = idx; port->ops = &mpc52xx_uart_ops; + port->dev = &dev->dev; /* Search for IRQ and mapbase */ for (i=0 ; i<dev->num_resources ; i++, res++) { @@ -771,7 +888,7 @@ mpc52xx_uart_suspend(struct platform_device *dev, pm_message_t state) { struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev); - if (sport) + if (port) uart_suspend_port(&mpc52xx_uart_driver, port); return 0; @@ -789,6 +906,7 @@ mpc52xx_uart_resume(struct platform_device *dev) } #endif + static struct platform_driver mpc52xx_uart_platform_driver = { .probe = mpc52xx_uart_probe, .remove = mpc52xx_uart_remove, @@ -800,6 +918,184 @@ static struct platform_driver mpc52xx_uart_platform_driver = { .name = "mpc52xx-psc", }, }; +#endif /* !defined(CONFIG_PPC_MERGE) */ + + +#if defined(CONFIG_PPC_MERGE) +/* ======================================================================== */ +/* OF Platform Driver */ +/* ======================================================================== */ + +static int __devinit +mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) +{ + int idx = -1; + unsigned int ipb_freq; + struct uart_port *port = NULL; + struct resource res; + int ret; + + dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match); + + /* Check validity & presence */ + for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++) + if (mpc52xx_uart_nodes[idx] == op->node) + break; + if (idx >= MPC52xx_PSC_MAXNUM) + return -EINVAL; + pr_debug("Found %s assigned to ttyPSC%x\n", + mpc52xx_uart_nodes[idx]->full_name, idx); + + /* Search for bus-frequency property in this node or a parent */ + if ((ipb_freq = mpc52xx_find_ipb_freq(op->node)) == 0) { + dev_dbg(&op->dev, "Could not find IPB bus frequency!\n"); + return -EINVAL; + } + + /* Init the port structure */ + port = &mpc52xx_uart_ports[idx]; + + spin_lock_init(&port->lock); + port->uartclk = ipb_freq / 2; + port->fifosize = 512; + port->iotype = UPIO_MEM; + port->flags = UPF_BOOT_AUTOCONF | + ( uart_console(port) ? 0 : UPF_IOREMAP ); + port->line = idx; + port->ops = &mpc52xx_uart_ops; + port->dev = &op->dev; + + /* Search for IRQ and mapbase */ + if ((ret = of_address_to_resource(op->node, 0, &res)) != 0) + return ret; + + port->mapbase = res.start; + port->irq = irq_of_parse_and_map(op->node, 0); + + dev_dbg(&op->dev, "mpc52xx-psc uart at %lx, irq=%x, freq=%i\n", + port->mapbase, port->irq, port->uartclk); + + if ((port->irq==NO_IRQ) || !port->mapbase) { + printk(KERN_ERR "Could not allocate resources for PSC\n"); + return -EINVAL; + } + + /* Add the port to the uart sub-system */ + ret = uart_add_one_port(&mpc52xx_uart_driver, port); + if (!ret) + dev_set_drvdata(&op->dev, (void*)port); + + return ret; +} + +static int +mpc52xx_uart_of_remove(struct of_device *op) +{ + struct uart_port *port = dev_get_drvdata(&op->dev); + dev_set_drvdata(&op->dev, NULL); + + if (port) + uart_remove_one_port(&mpc52xx_uart_driver, port); + + return 0; +} + +#ifdef CONFIG_PM +static int +mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) +{ + struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); + + if (port) + uart_suspend_port(&mpc52xx_uart_driver, port); + + return 0; +} + +static int +mpc52xx_uart_of_resume(struct of_device *op) +{ + struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); + + if (port) + uart_resume_port(&mpc52xx_uart_driver, port); + + return 0; +} +#endif + +static void +mpc52xx_uart_of_assign(struct device_node *np, int idx) +{ + int free_idx = -1; + int i; + + /* Find the first free node */ + for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { + if (mpc52xx_uart_nodes[i] == NULL) { + free_idx = i; + break; + } + } + + if ((idx < 0) || (idx >= MPC52xx_PSC_MAXNUM)) + idx = free_idx; + + if (idx < 0) + return; /* No free slot; abort */ + + /* If the slot is already occupied, then swap slots */ + if (mpc52xx_uart_nodes[idx] && (free_idx != -1)) + mpc52xx_uart_nodes[free_idx] = mpc52xx_uart_nodes[idx]; + mpc52xx_uart_nodes[i] = np; +} + +static void +mpc52xx_uart_of_enumerate(void) +{ + static int enum_done = 0; + struct device_node *np; + const unsigned int *devno; + int i; + + if (enum_done) + return; + + for_each_node_by_type(np, "serial") { + if (!of_match_node(mpc52xx_uart_of_match, np)) + continue; + + /* Is a particular device number requested? */ + devno = get_property(np, "device_no", NULL); + mpc52xx_uart_of_assign(of_node_get(np), devno ? *devno : -1); + } + + enum_done = 1; + + for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { + if (mpc52xx_uart_nodes[i]) + pr_debug("%s assigned to ttyPSC%x\n", + mpc52xx_uart_nodes[i]->full_name, i); + } +} + +MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match); + +static struct of_platform_driver mpc52xx_uart_of_driver = { + .owner = THIS_MODULE, + .name = "mpc52xx-psc-uart", + .match_table = mpc52xx_uart_of_match, + .probe = mpc52xx_uart_of_probe, + .remove = mpc52xx_uart_of_remove, +#ifdef CONFIG_PM + .suspend = mpc52xx_uart_of_suspend, + .resume = mpc52xx_uart_of_resume, +#endif + .driver = { + .name = "mpc52xx-psc-uart", + }, +}; +#endif /* defined(CONFIG_PPC_MERGE) */ /* ======================================================================== */ @@ -811,22 +1107,45 @@ mpc52xx_uart_init(void) { int ret; - printk(KERN_INFO "Serial: MPC52xx PSC driver\n"); + printk(KERN_INFO "Serial: MPC52xx PSC UART driver\n"); - ret = uart_register_driver(&mpc52xx_uart_driver); - if (ret == 0) { - ret = platform_driver_register(&mpc52xx_uart_platform_driver); - if (ret) - uart_unregister_driver(&mpc52xx_uart_driver); + if ((ret = uart_register_driver(&mpc52xx_uart_driver)) != 0) { + printk(KERN_ERR "%s: uart_register_driver failed (%i)\n", + __FILE__, ret); + return ret; } - return ret; +#if defined(CONFIG_PPC_MERGE) + mpc52xx_uart_of_enumerate(); + + ret = of_register_platform_driver(&mpc52xx_uart_of_driver); + if (ret) { + printk(KERN_ERR "%s: of_register_platform_driver failed (%i)\n", + __FILE__, ret); + uart_unregister_driver(&mpc52xx_uart_driver); + return ret; + } +#else + ret = platform_driver_register(&mpc52xx_uart_platform_driver); + if (ret) { + printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", + __FILE__, ret); + uart_unregister_driver(&mpc52xx_uart_driver); + return ret; + } +#endif + + return 0; } static void __exit mpc52xx_uart_exit(void) { +#if defined(CONFIG_PPC_MERGE) + of_unregister_platform_driver(&mpc52xx_uart_of_driver); +#else platform_driver_unregister(&mpc52xx_uart_platform_driver); +#endif uart_unregister_driver(&mpc52xx_uart_driver); } diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 8eea69f2998..3d2fcc57b1c 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -555,7 +555,7 @@ mpsc_sdma_start_tx(struct mpsc_port_info *pi) if (!mpsc_sdma_tx_active(pi)) { txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, @@ -931,7 +931,7 @@ mpsc_init_rings(struct mpsc_port_info *pi) } txre->link = cpu_to_be32(pi->txr_p); /* Wrap last back to first */ - dma_cache_sync((void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE, + dma_cache_sync(pi->port.dev, (void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ @@ -1005,7 +1005,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi) rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE)); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)rxre, @@ -1029,7 +1029,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi) } bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); - dma_cache_sync((void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)bp, @@ -1098,7 +1098,7 @@ next_frame: SDMA_DESC_CMDSTAT_F | SDMA_DESC_CMDSTAT_L); wmb(); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)rxre, @@ -1109,7 +1109,7 @@ next_frame: pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1); rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn * MPSC_RXRE_SIZE)); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)rxre, @@ -1143,7 +1143,7 @@ mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr) SDMA_DESC_CMDSTAT_EI : 0)); wmb(); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)txre, @@ -1192,7 +1192,7 @@ mpsc_copy_tx_data(struct mpsc_port_info *pi) else /* All tx data copied into ring bufs */ return; - dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)bp, @@ -1217,7 +1217,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, @@ -1235,7 +1235,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ @@ -1440,8 +1440,8 @@ mpsc_shutdown(struct uart_port *port) } static void -mpsc_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +mpsc_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; u32 baud; @@ -1652,7 +1652,7 @@ mpsc_console_write(struct console *co, const char *s, uint count) count--; } - dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)bp, diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 8ad1b8c5ec5..ccb8fa1800a 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -273,8 +273,8 @@ static void mux_shutdown(struct uart_port *port) * The Serial Mux does not support this function. */ static void -mux_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +mux_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { } diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c index 062bad457b1..b56f7db4503 100644 --- a/drivers/serial/netx-serial.c +++ b/drivers/serial/netx-serial.c @@ -337,8 +337,8 @@ static void netx_shutdown(struct uart_port *port) } static void -netx_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +netx_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud, quot; unsigned char old_cr; diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index bf9809ed9c0..752ef07516b 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1262,8 +1262,8 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) } -static void __pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long baud; @@ -1273,7 +1273,7 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, if (ZS_IS_ASLEEP(uap)) return; - memcpy(&uap->termios_cache, termios, sizeof(struct termios)); + memcpy(&uap->termios_cache, termios, sizeof(struct ktermios)); /* XXX Check which revs of machines actually allow 1 and 4Mb speeds * on the IR dongle. Note that the IRTTY driver currently doesn't know @@ -1313,8 +1313,8 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, } /* The port lock is not held. */ -static void pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; diff --git a/drivers/serial/pmac_zilog.h b/drivers/serial/pmac_zilog.h index c03f9bfacdd..570b0d925e8 100644 --- a/drivers/serial/pmac_zilog.h +++ b/drivers/serial/pmac_zilog.h @@ -60,7 +60,7 @@ struct uart_pmac_port { volatile struct dbdma_regs __iomem *tx_dma_regs; volatile struct dbdma_regs __iomem *rx_dma_regs; - struct termios termios_cache; + struct ktermios termios_cache; }; #define to_pmz(p) ((struct uart_pmac_port *)(p)) diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 415fe9633a9..d403aaa5509 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -433,8 +433,8 @@ static void serial_pxa_shutdown(struct uart_port *port) } static void -serial_pxa_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; unsigned char cval, fcr = 0; diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 8dfc2dd058c..3ba9208ebd0 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -738,8 +738,8 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port, } static void s3c24xx_serial_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old) + struct ktermios *termios, + struct ktermios *old) { struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index d4065266b6f..58a83c27e14 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -408,8 +408,8 @@ static void sa1100_shutdown(struct uart_port *port) } static void -sa1100_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sa1100_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index c67b05e9a45..f84982e508c 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -65,7 +65,7 @@ static struct lock_class_key port_lock_key; #define uart_console(port) (0) #endif -static void uart_change_speed(struct uart_state *state, struct termios *old_termios); +static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); static void uart_change_pm(struct uart_state *state, int pm_state); @@ -338,8 +338,8 @@ EXPORT_SYMBOL(uart_update_timeout); * we're actually going to be using. */ unsigned int -uart_get_baud_rate(struct uart_port *port, struct termios *termios, - struct termios *old, unsigned int min, unsigned int max) +uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, + struct ktermios *old, unsigned int min, unsigned int max) { unsigned int try, baud, altbaud = 38400; upf_t flags = port->flags & UPF_SPD_MASK; @@ -421,11 +421,11 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) EXPORT_SYMBOL(uart_get_divisor); static void -uart_change_speed(struct uart_state *state, struct termios *old_termios) +uart_change_speed(struct uart_state *state, struct ktermios *old_termios) { struct tty_struct *tty = state->info->tty; struct uart_port *port = state->port; - struct termios *termios; + struct ktermios *termios; /* * If we have no tty, termios, or the port does not exist, @@ -1139,7 +1139,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, return ret; } -static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct uart_state *state = tty->driver_data; unsigned long flags; @@ -1866,7 +1866,7 @@ int __init uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow) { - struct termios termios; + struct ktermios termios; int i; /* @@ -1876,7 +1876,7 @@ uart_set_options(struct uart_port *port, struct console *co, spin_lock_init(&port->lock); lockdep_set_class(&port->lock, &port_lock_key); - memset(&termios, 0, sizeof(struct termios)); + memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = CREAD | HUPCL | CLOCAL; @@ -1991,12 +1991,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) * Re-enable the console device after suspending. */ if (uart_console(port)) { - struct termios termios; + struct ktermios termios; /* * First try to use the console cflag setting. */ - memset(&termios, 0, sizeof(struct termios)); + memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = port->cons->cflag; /* @@ -2189,6 +2189,7 @@ int uart_register_driver(struct uart_driver *drv) normal->subtype = SERIAL_TYPE_NORMAL; normal->init_termios = tty_std_termios; normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600; normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; normal->driver_state = drv; tty_set_operations(normal, &uart_ops); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 00f9ffd6948..431433f4dd6 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -723,7 +723,7 @@ static int serial_config(struct pcmcia_device * link) u_char *buf; cisparse_t *parse; cistpl_cftable_entry_t *cf; - int i, last_ret, last_fn; + int i; DEBUG(0, "serial_config(0x%p)\n", link); @@ -740,15 +740,6 @@ static int serial_config(struct pcmcia_device * link) tuple->TupleOffset = 0; tuple->TupleDataMax = 255; tuple->Attributes = 0; - /* Get configuration register information */ - tuple->DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(link, tuple, parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse->config.base; - link->conf.Present = parse->config.rmask[0]; /* Is this a compliant multifunction card? */ tuple->DesiredTuple = CISTPL_LONGLINK_MFC; @@ -757,27 +748,25 @@ static int serial_config(struct pcmcia_device * link) /* Is this a multiport card? */ tuple->DesiredTuple = CISTPL_MANFID; - if (first_tuple(link, tuple, parse) == CS_SUCCESS) { - info->manfid = parse->manfid.manf; - info->prodid = parse->manfid.card; - - for (i = 0; i < ARRAY_SIZE(quirks); i++) - if ((quirks[i].manfid == ~0 || - quirks[i].manfid == info->manfid) && - (quirks[i].prodid == ~0 || - quirks[i].prodid == info->prodid)) { - info->quirk = &quirks[i]; - break; - } - } + info->manfid = link->manf_id; + info->prodid = link->card_id; + + for (i = 0; i < ARRAY_SIZE(quirks); i++) + if ((quirks[i].manfid == ~0 || + quirks[i].manfid == info->manfid) && + (quirks[i].prodid == ~0 || + quirks[i].prodid == info->prodid)) { + info->quirk = &quirks[i]; + break; + } /* Another check for dual-serial cards: look for either serial or multifunction cards that ask for appropriate IO port ranges */ tuple->DesiredTuple = CISTPL_FUNCID; if ((info->multi == 0) && - ((first_tuple(link, tuple, parse) != CS_SUCCESS) || - (parse->funcid.func == CISTPL_FUNCID_MULTI) || - (parse->funcid.func == CISTPL_FUNCID_SERIAL))) { + (link->has_func_id) && + ((link->func_id == CISTPL_FUNCID_MULTI) || + (link->func_id == CISTPL_FUNCID_SERIAL))) { tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; if (first_tuple(link, tuple, parse) == CS_SUCCESS) { if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) @@ -814,8 +803,6 @@ static int serial_config(struct pcmcia_device * link) kfree(cfg_mem); return 0; - cs_failed: - cs_error(link, last_fn, last_ret); failed: serial_remove(link); kfree(cfg_mem); @@ -925,6 +912,30 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"), PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), /* too generic */ /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 5e1ac356bbb..eb18d429752 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -348,8 +348,8 @@ static void lh7a40xuart_shutdown (struct uart_port* port) } static void lh7a40xuart_set_termios (struct uart_port* port, - struct termios* termios, - struct termios* old) + struct ktermios* termios, + struct ktermios* old) { unsigned int con; unsigned int inten; diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 2a48289ac72..7186a82c475 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -556,8 +556,8 @@ static void serial_txx9_shutdown(struct uart_port *port) } static void -serial_txx9_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; unsigned int cval, fcr = 0; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index cfcc3caf49d..c53b69610a5 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -319,6 +319,28 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) sci_out(port, SCFCR, fcr_val); } +#elif defined(CONFIG_CPU_SUBTYPE_SH7722) +static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) +{ + unsigned int fcr_val = 0; + + if (cflag & CRTSCTS) { + fcr_val |= SCFCR_MCE; + + ctrl_outw(0x0000, PORT_PSCR); + } else { + unsigned short data; + + data = ctrl_inw(PORT_PSCR); + data &= 0x033f; + data |= 0x0400; + ctrl_outw(data, PORT_PSCR); + + ctrl_outw(ctrl_inw(SCSPTR0) & 0x17, SCSPTR0); + } + + sci_out(port, SCFCR, fcr_val); +} #else /* For SH7750 */ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) @@ -775,7 +797,7 @@ static int sci_notifier(struct notifier_block *self, * * Clean this up later.. */ - clk = clk_get("module_clk"); + clk = clk_get(NULL, "module_clk"); port->uartclk = clk_get_rate(clk) * 16; clk_put(clk); } @@ -943,8 +965,8 @@ static void sci_shutdown(struct uart_port *port) s->disable(port); } -static void sci_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sci_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct sci_port *s = &sci_ports[port->line]; unsigned int status, baud, smr_val; @@ -960,7 +982,7 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios, default: { #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) - struct clk *clk = clk_get("module_clk"); + struct clk *clk = clk_get(NULL, "module_clk"); t = SCBRR_VALUE(baud, clk_get_rate(clk)); clk_put(clk); #else @@ -1128,7 +1150,7 @@ static void __init sci_init_ports(void) * XXX: We should use a proper SCI/SCIF clock */ { - struct clk *clk = clk_get("module_clk"); + struct clk *clk = clk_get(NULL, "module_clk"); sci_ports[i].port.uartclk = clk_get_rate(clk) * 16; clk_put(clk); } diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 7ee992146ae..77f7d6351ab 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -90,6 +90,13 @@ # define SCSPTR3 0xffe30010 /* 16 bit SCIF */ # define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */ # define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7722) +# define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ +# define SCSPTR0 SCPDR0 +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY +# define PORT_PSCR 0xA405011E #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ @@ -133,6 +140,20 @@ # define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ +# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */ +# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */ +# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +# define SCSPTR0 0xf8400020 /* 16 bit SCIF */ +# define SCSPTR1 0xf8410020 /* 16 bit SCIF */ +# define SCSPTR2 0xf8420020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #else # error CPU subtype not defined #endif @@ -365,6 +386,7 @@ SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8) SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8) SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) #if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780) +SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) @@ -480,6 +502,7 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfe620000) return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7300) static inline int sci_rxd_in(struct uart_port *port) @@ -506,6 +529,13 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } +#elif defined(CONFIG_CPU_SUBTYPE_SH7722) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xffe00000) + return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ + return 1; +} #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) static inline int sci_rxd_in(struct uart_port *port) { @@ -535,6 +565,7 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xff925000) return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7780) static inline int sci_rxd_in(struct uart_port *port) @@ -543,6 +574,31 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe10000) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return 1; +} +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xfffe8000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe8800) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe9000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe9800) + return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return 1; +} +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xf8400000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xf8410000) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xf8420000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return 1; } #endif diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 956b2cf08e1..253ceb895ca 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -361,8 +361,8 @@ static int snp_startup(struct uart_port *port) * */ static void -snp_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +snp_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { } diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 03941d27d15..40d48566215 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -281,8 +281,8 @@ static void sunhv_shutdown(struct uart_port *port) } /* port->lock is not held. */ -static void sunhv_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); unsigned int quot = uart_get_divisor(port, baud); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 08a7cd6a3a0..493d5bbb661 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -786,8 +786,8 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla } /* port->lock is not held. */ -static void sunsab_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index c577faea60e..564592b2b2b 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -893,8 +893,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, } static void -sunsu_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sunsu_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud, quot; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index b2cc703b2b9..75de919a947 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -922,8 +922,8 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, /* The port lock is not held. */ static void -sunzilog_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; unsigned long flags; diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c new file mode 100644 index 00000000000..92eba893559 --- /dev/null +++ b/drivers/serial/uartlite.c @@ -0,0 +1,505 @@ +/* + * uartlite.c: Serial driver for Xilinx uartlite serial controller + * + * Peter Korsgaard <jacmet@sunsite.dk> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/console.h> +#include <linux/serial.h> +#include <linux/serial_core.h> +#include <linux/tty.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <asm/io.h> + +#define ULITE_MAJOR 204 +#define ULITE_MINOR 187 +#define ULITE_NR_UARTS 4 + +/* For register details see datasheet: + http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf +*/ +#define ULITE_RX 0x00 +#define ULITE_TX 0x04 +#define ULITE_STATUS 0x08 +#define ULITE_CONTROL 0x0c + +#define ULITE_REGION 16 + +#define ULITE_STATUS_RXVALID 0x01 +#define ULITE_STATUS_RXFULL 0x02 +#define ULITE_STATUS_TXEMPTY 0x04 +#define ULITE_STATUS_TXFULL 0x08 +#define ULITE_STATUS_IE 0x10 +#define ULITE_STATUS_OVERRUN 0x20 +#define ULITE_STATUS_FRAME 0x40 +#define ULITE_STATUS_PARITY 0x80 + +#define ULITE_CONTROL_RST_TX 0x01 +#define ULITE_CONTROL_RST_RX 0x02 +#define ULITE_CONTROL_IE 0x10 + + +static struct uart_port ports[ULITE_NR_UARTS]; + +static int ulite_receive(struct uart_port *port, int stat) +{ + struct tty_struct *tty = port->info->tty; + unsigned char ch = 0; + char flag = TTY_NORMAL; + + if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN + | ULITE_STATUS_FRAME)) == 0) + return 0; + + /* stats */ + if (stat & ULITE_STATUS_RXVALID) { + port->icount.rx++; + ch = readb(port->membase + ULITE_RX); + + if (stat & ULITE_STATUS_PARITY) + port->icount.parity++; + } + + if (stat & ULITE_STATUS_OVERRUN) + port->icount.overrun++; + + if (stat & ULITE_STATUS_FRAME) + port->icount.frame++; + + + /* drop byte with parity error if IGNPAR specificed */ + if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY) + stat &= ~ULITE_STATUS_RXVALID; + + stat &= port->read_status_mask; + + if (stat & ULITE_STATUS_PARITY) + flag = TTY_PARITY; + + + stat &= ~port->ignore_status_mask; + + if (stat & ULITE_STATUS_RXVALID) + tty_insert_flip_char(tty, ch, flag); + + if (stat & ULITE_STATUS_FRAME) + tty_insert_flip_char(tty, 0, TTY_FRAME); + + if (stat & ULITE_STATUS_OVERRUN) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + return 1; +} + +static int ulite_transmit(struct uart_port *port, int stat) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (stat & ULITE_STATUS_TXFULL) + return 0; + + if (port->x_char) { + writeb(port->x_char, port->membase + ULITE_TX); + port->x_char = 0; + port->icount.tx++; + return 1; + } + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + return 0; + + writeb(xmit->buf[xmit->tail], port->membase + ULITE_TX); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); + port->icount.tx++; + + /* wake up */ + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + return 1; +} + +static irqreturn_t ulite_isr(int irq, void *dev_id) +{ + struct uart_port *port = (struct uart_port *)dev_id; + int busy; + + do { + int stat = readb(port->membase + ULITE_STATUS); + busy = ulite_receive(port, stat); + busy |= ulite_transmit(port, stat); + } while (busy); + + tty_flip_buffer_push(port->info->tty); + + return IRQ_HANDLED; +} + +static unsigned int ulite_tx_empty(struct uart_port *port) +{ + unsigned long flags; + unsigned int ret; + + spin_lock_irqsave(&port->lock, flags); + ret = readb(port->membase + ULITE_STATUS); + spin_unlock_irqrestore(&port->lock, flags); + + return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0; +} + +static unsigned int ulite_get_mctrl(struct uart_port *port) +{ + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; +} + +static void ulite_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* N/A */ +} + +static void ulite_stop_tx(struct uart_port *port) +{ + /* N/A */ +} + +static void ulite_start_tx(struct uart_port *port) +{ + ulite_transmit(port, readb(port->membase + ULITE_STATUS)); +} + +static void ulite_stop_rx(struct uart_port *port) +{ + /* don't forward any more data (like !CREAD) */ + port->ignore_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN; +} + +static void ulite_enable_ms(struct uart_port *port) +{ + /* N/A */ +} + +static void ulite_break_ctl(struct uart_port *port, int ctl) +{ + /* N/A */ +} + +static int ulite_startup(struct uart_port *port) +{ + int ret; + + ret = request_irq(port->irq, ulite_isr, + IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "uartlite", port); + if (ret) + return ret; + + writeb(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX, + port->membase + ULITE_CONTROL); + writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); + + return 0; +} + +static void ulite_shutdown(struct uart_port *port) +{ + writeb(0, port->membase + ULITE_CONTROL); + readb(port->membase + ULITE_CONTROL); /* dummy */ + free_irq(port->irq, port); +} + +static void ulite_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + unsigned long flags; + unsigned int baud; + + spin_lock_irqsave(&port->lock, flags); + + port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN + | ULITE_STATUS_TXFULL; + + if (termios->c_iflag & INPCK) + port->read_status_mask |= + ULITE_STATUS_PARITY | ULITE_STATUS_FRAME; + + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= ULITE_STATUS_PARITY + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN; + + /* ignore all characters if CREAD is not set */ + if ((termios->c_cflag & CREAD) == 0) + port->ignore_status_mask |= + ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN; + + /* update timeout */ + baud = uart_get_baud_rate(port, termios, old, 0, 460800); + uart_update_timeout(port, termios->c_cflag, baud); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *ulite_type(struct uart_port *port) +{ + return port->type == PORT_UARTLITE ? "uartlite" : NULL; +} + +static void ulite_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, ULITE_REGION); + iounmap(port->membase); + port->membase = 0; +} + +static int ulite_request_port(struct uart_port *port) +{ + if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) { + dev_err(port->dev, "Memory region busy\n"); + return -EBUSY; + } + + port->membase = ioremap(port->mapbase, ULITE_REGION); + if (!port->membase) { + dev_err(port->dev, "Unable to map registers\n"); + release_mem_region(port->mapbase, ULITE_REGION); + return -EBUSY; + } + + return 0; +} + +static void ulite_config_port(struct uart_port *port, int flags) +{ + ulite_request_port(port); + port->type = PORT_UARTLITE; +} + +static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + /* we don't want the core code to modify any port params */ + return -EINVAL; +} + +static struct uart_ops ulite_ops = { + .tx_empty = ulite_tx_empty, + .set_mctrl = ulite_set_mctrl, + .get_mctrl = ulite_get_mctrl, + .stop_tx = ulite_stop_tx, + .start_tx = ulite_start_tx, + .stop_rx = ulite_stop_rx, + .enable_ms = ulite_enable_ms, + .break_ctl = ulite_break_ctl, + .startup = ulite_startup, + .shutdown = ulite_shutdown, + .set_termios = ulite_set_termios, + .type = ulite_type, + .release_port = ulite_release_port, + .request_port = ulite_request_port, + .config_port = ulite_config_port, + .verify_port = ulite_verify_port +}; + +#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE +static void ulite_console_wait_tx(struct uart_port *port) +{ + int i; + + /* wait up to 10ms for the character(s) to be sent */ + for (i = 0; i < 10000; i++) { + if (readb(port->membase + ULITE_STATUS) & ULITE_STATUS_TXEMPTY) + break; + udelay(1); + } +} + +static void ulite_console_putchar(struct uart_port *port, int ch) +{ + ulite_console_wait_tx(port); + writeb(ch, port->membase + ULITE_TX); +} + +static void ulite_console_write(struct console *co, const char *s, + unsigned int count) +{ + struct uart_port *port = &ports[co->index]; + unsigned long flags; + unsigned int ier; + int locked = 1; + + if (oops_in_progress) { + locked = spin_trylock_irqsave(&port->lock, flags); + } else + spin_lock_irqsave(&port->lock, flags); + + /* save and disable interrupt */ + ier = readb(port->membase + ULITE_STATUS) & ULITE_STATUS_IE; + writeb(0, port->membase + ULITE_CONTROL); + + uart_console_write(port, s, count, ulite_console_putchar); + + ulite_console_wait_tx(port); + + /* restore interrupt state */ + if (ier) + writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); + + if (locked) + spin_unlock_irqrestore(&port->lock, flags); +} + +static int __init ulite_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (co->index < 0 || co->index >= ULITE_NR_UARTS) + return -EINVAL; + + port = &ports[co->index]; + + /* not initialized yet? */ + if (!port->membase) + return -ENODEV; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct uart_driver ulite_uart_driver; + +static struct console ulite_console = { + .name = "ttyUL", + .write = ulite_console_write, + .device = uart_console_device, + .setup = ulite_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */ + .data = &ulite_uart_driver, +}; + +static int __init ulite_console_init(void) +{ + register_console(&ulite_console); + return 0; +} + +console_initcall(ulite_console_init); + +#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */ + +static struct uart_driver ulite_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "uartlite", + .dev_name = "ttyUL", + .major = ULITE_MAJOR, + .minor = ULITE_MINOR, + .nr = ULITE_NR_UARTS, +#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE + .cons = &ulite_console, +#endif +}; + +static int __devinit ulite_probe(struct platform_device *pdev) +{ + struct resource *res, *res2; + struct uart_port *port; + + if (pdev->id < 0 || pdev->id >= ULITE_NR_UARTS) + return -EINVAL; + + if (ports[pdev->id].membase) + return -EBUSY; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res2) + return -ENODEV; + + port = &ports[pdev->id]; + + port->fifosize = 16; + port->regshift = 2; + port->iotype = UPIO_MEM; + port->iobase = 1; /* mark port in use */ + port->mapbase = res->start; + port->membase = 0; + port->ops = &ulite_ops; + port->irq = res2->start; + port->flags = UPF_BOOT_AUTOCONF; + port->dev = &pdev->dev; + port->type = PORT_UNKNOWN; + port->line = pdev->id; + + uart_add_one_port(&ulite_uart_driver, port); + platform_set_drvdata(pdev, port); + + return 0; +} + +static int ulite_remove(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (port) + uart_remove_one_port(&ulite_uart_driver, port); + + /* mark port as free */ + port->membase = 0; + + return 0; +} + +static struct platform_driver ulite_platform_driver = { + .probe = ulite_probe, + .remove = ulite_remove, + .driver = { + .owner = THIS_MODULE, + .name = "uartlite", + }, +}; + +int __init ulite_init(void) +{ + int ret; + + ret = uart_register_driver(&ulite_uart_driver); + if (ret) + return ret; + + ret = platform_driver_register(&ulite_platform_driver); + if (ret) + uart_unregister_driver(&ulite_uart_driver); + + return ret; +} + +void __exit ulite_exit(void) +{ + platform_driver_unregister(&ulite_platform_driver); + uart_unregister_driver(&ulite_uart_driver); +} + +module_init(ulite_init); +module_exit(ulite_exit); + +MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>"); +MODULE_DESCRIPTION("Xilinx uartlite serial driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c index 28f3bbff87b..dd98aca6ed0 100644 --- a/drivers/serial/v850e_uart.c +++ b/drivers/serial/v850e_uart.c @@ -404,8 +404,8 @@ static void v850e_uart_shutdown (struct uart_port *port) } static void -v850e_uart_set_termios (struct uart_port *port, struct termios *termios, - struct termios *old) +v850e_uart_set_termios (struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned cflags = termios->c_cflag; diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index fd51f8182de..cf0e663b42e 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -562,8 +562,8 @@ static void siu_shutdown(struct uart_port *port) free_irq(port->irq, port); } -static void siu_set_termios(struct uart_port *port, struct termios *new, - struct termios *old) +static void siu_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) { tcflag_t c_cflag, c_iflag; uint8_t lcr, fcr, ier; |