Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: 8250_ingenic: Enable FIFO for Ingenic UARTs

Enable the TX/RX FIFOs present on UARTs in Ingenic SoCs.
FIFO sizes vary per device so match these based on
the OF compatible string

Enabling the FIFOs permits much faster transfer with
lower CPU overhead.

Tested on Ingenic JZ4780 on the MIPS Ci20 Creator board

Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Matt Redfearn and committed by
Greg Kroah-Hartman
c74997bd 129a45b1

+43 -4
+43 -4
drivers/tty/serial/8250/8250_ingenic.c
··· 21 21 #include <linux/module.h> 22 22 #include <linux/of.h> 23 23 #include <linux/of_fdt.h> 24 + #include <linux/of_device.h> 24 25 #include <linux/platform_device.h> 25 26 #include <linux/serial_8250.h> 26 27 #include <linux/serial_core.h> 27 28 #include <linux/serial_reg.h> 29 + 30 + #include "8250.h" 31 + 32 + /** ingenic_uart_config: SOC specific config data. */ 33 + struct ingenic_uart_config { 34 + int tx_loadsz; 35 + int fifosize; 36 + }; 28 37 29 38 struct ingenic_uart_data { 30 39 struct clk *clk_module; 31 40 struct clk *clk_baud; 32 41 int line; 33 42 }; 43 + 44 + static const struct of_device_id of_match[]; 34 45 35 46 #define UART_FCR_UME BIT(4) 36 47 ··· 203 192 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 204 193 struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 205 194 struct ingenic_uart_data *data; 195 + const struct ingenic_uart_config *cdata; 196 + const struct of_device_id *match; 206 197 int err, line; 198 + 199 + match = of_match_device(of_match, &pdev->dev); 200 + if (!match) { 201 + dev_err(&pdev->dev, "Error: No device match found\n"); 202 + return -ENODEV; 203 + } 204 + cdata = match->data; 207 205 208 206 if (!regs || !irq) { 209 207 dev_err(&pdev->dev, "no registers/irq defined\n"); ··· 224 204 return -ENOMEM; 225 205 226 206 spin_lock_init(&uart.port.lock); 227 - uart.port.type = PORT_16550; 207 + uart.port.type = PORT_16550A; 228 208 uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE; 229 209 uart.port.iotype = UPIO_MEM; 230 210 uart.port.mapbase = regs->start; ··· 233 213 uart.port.serial_in = ingenic_uart_serial_in; 234 214 uart.port.irq = irq->start; 235 215 uart.port.dev = &pdev->dev; 216 + uart.port.fifosize = cdata->fifosize; 217 + uart.tx_loadsz = cdata->tx_loadsz; 218 + uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE; 236 219 237 220 /* Check for a fixed line number */ 238 221 line = of_alias_get_id(pdev->dev.of_node, "serial"); ··· 305 282 return 0; 306 283 } 307 284 285 + static const struct ingenic_uart_config jz4740_uart_config = { 286 + .tx_loadsz = 8, 287 + .fifosize = 16, 288 + }; 289 + 290 + static const struct ingenic_uart_config jz4760_uart_config = { 291 + .tx_loadsz = 16, 292 + .fifosize = 32, 293 + }; 294 + 295 + static const struct ingenic_uart_config jz4780_uart_config = { 296 + .tx_loadsz = 32, 297 + .fifosize = 64, 298 + }; 299 + 308 300 static const struct of_device_id of_match[] = { 309 - { .compatible = "ingenic,jz4740-uart" }, 310 - { .compatible = "ingenic,jz4775-uart" }, 311 - { .compatible = "ingenic,jz4780-uart" }, 301 + { .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config }, 302 + { .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config }, 303 + { .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config }, 304 + { .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config }, 312 305 { /* sentinel */ } 313 306 }; 314 307 MODULE_DEVICE_TABLE(of, of_match);