From 6b0f5078e3b6de687b3045985d86598d8dd2aecc Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 9 Jul 2013 09:42:22 +0100 Subject: [PATCH] serial/8250: add support for Ingenic jz4780 UARTs The UART block used in Ingenic SoCs is advertised as NS16550 compatible, however it isn't quite. The only difference relevant to basic usage is the presence of a 'UART module enable' bit in the FCR register which must be set at all times in order for the UART block to function. This patch introduces a new UART port type for Ingenic jz4780 UARTs which simply sets that bit & provides appropriate flags. Signed-off-by: Paul Burton --- drivers/tty/serial/8250/8250_core.c | 26 +++++++++++++++++++++++++- drivers/tty/serial/of_serial.c | 1 + include/uapi/linux/serial_core.h | 3 ++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index ca5cfdc1459a61..eed2c82613c564 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -329,6 +329,13 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, + [PORT_INGENIC_JZ4780] = { + .name = "Ingenic jz4780 UART", + .fifo_size = 64, + .tx_loadsz = 32, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_RTOIE, + }, }; /* Uart divisor latch read */ @@ -440,6 +447,20 @@ static void io_serial_out(struct uart_port *p, int offset, int value) outb(value, p->iobase + offset); } +static void jz47xx_serial_out(struct uart_port *p, int offset, int value) +{ + switch (offset) { + case UART_FCR: + value |= 0x10; /* Enable uart module */ + break; + default: + break; + } + + offset = offset << p->regshift; + writeb(value, p->membase + offset); +} + static int serial8250_default_handle_irq(struct uart_port *port); static int exar_handle_irq(struct uart_port *port); @@ -458,7 +479,10 @@ static void set_io_from_upio(struct uart_port *p) case UPIO_MEM: p->serial_in = mem_serial_in; - p->serial_out = mem_serial_out; + if (p->type == PORT_INGENIC_JZ4780) + p->serial_out = jz47xx_serial_out; + else + p->serial_out = mem_serial_out; break; case UPIO_MEM32: diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index bf355050eab695..120729f0eb12bd 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -262,6 +262,7 @@ static struct of_device_id of_platform_serial_table[] = { { .compatible = "ibm,qpace-nwp-serial", .data = (void *)PORT_NWPSERIAL, }, #endif + { .compatible = "ingenic,jz4780-uart", .data = (void *)PORT_INGENIC_JZ4780, }, { .type = "serial", .data = (void *)PORT_UNKNOWN, }, { /* end of list */ }, }; diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 16ad8521af6ad7..f831c9ffc9776a 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -54,7 +54,8 @@ #define PORT_ALTR_16550_F32 26 /* Altera 16550 UART with 32 FIFOs */ #define PORT_ALTR_16550_F64 27 /* Altera 16550 UART with 64 FIFOs */ #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */ -#define PORT_MAX_8250 28 /* max port ID */ +#define PORT_INGENIC_JZ4780 29 +#define PORT_MAX_8250 29 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed