Browse Source

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>
Matt Redfearn 10 years ago
parent
commit
c74997bdfe
1 changed files with 43 additions and 4 deletions
  1. 43 4
      drivers/tty/serial/8250/8250_ingenic.c

+ 43 - 4
drivers/tty/serial/8250/8250_ingenic.c

@@ -21,17 +21,28 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/of_fdt.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_reg.h>
 
 
+#include "8250.h"
+
+/** ingenic_uart_config: SOC specific config data. */
+struct ingenic_uart_config {
+	int tx_loadsz;
+	int fifosize;
+};
+
 struct ingenic_uart_data {
 struct ingenic_uart_data {
 	struct clk	*clk_module;
 	struct clk	*clk_module;
 	struct clk	*clk_baud;
 	struct clk	*clk_baud;
 	int		line;
 	int		line;
 };
 };
 
 
+static const struct of_device_id of_match[];
+
 #define UART_FCR_UME	BIT(4)
 #define UART_FCR_UME	BIT(4)
 
 
 #define UART_MCR_MDCE	BIT(7)
 #define UART_MCR_MDCE	BIT(7)
@@ -192,8 +203,17 @@ static int ingenic_uart_probe(struct platform_device *pdev)
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	struct ingenic_uart_data *data;
 	struct ingenic_uart_data *data;
+	const struct ingenic_uart_config *cdata;
+	const struct of_device_id *match;
 	int err, line;
 	int err, line;
 
 
+	match = of_match_device(of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "Error: No device match found\n");
+		return -ENODEV;
+	}
+	cdata = match->data;
+
 	if (!regs || !irq) {
 	if (!regs || !irq) {
 		dev_err(&pdev->dev, "no registers/irq defined\n");
 		dev_err(&pdev->dev, "no registers/irq defined\n");
 		return -EINVAL;
 		return -EINVAL;
@@ -204,7 +224,7 @@ static int ingenic_uart_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	spin_lock_init(&uart.port.lock);
 	spin_lock_init(&uart.port.lock);
-	uart.port.type = PORT_16550;
+	uart.port.type = PORT_16550A;
 	uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
 	uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
 	uart.port.iotype = UPIO_MEM;
 	uart.port.iotype = UPIO_MEM;
 	uart.port.mapbase = regs->start;
 	uart.port.mapbase = regs->start;
@@ -213,6 +233,9 @@ static int ingenic_uart_probe(struct platform_device *pdev)
 	uart.port.serial_in = ingenic_uart_serial_in;
 	uart.port.serial_in = ingenic_uart_serial_in;
 	uart.port.irq = irq->start;
 	uart.port.irq = irq->start;
 	uart.port.dev = &pdev->dev;
 	uart.port.dev = &pdev->dev;
+	uart.port.fifosize = cdata->fifosize;
+	uart.tx_loadsz = cdata->tx_loadsz;
+	uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE;
 
 
 	/* Check for a fixed line number */
 	/* Check for a fixed line number */
 	line = of_alias_get_id(pdev->dev.of_node, "serial");
 	line = of_alias_get_id(pdev->dev.of_node, "serial");
@@ -282,10 +305,26 @@ static int ingenic_uart_remove(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
+static const struct ingenic_uart_config jz4740_uart_config = {
+	.tx_loadsz = 8,
+	.fifosize = 16,
+};
+
+static const struct ingenic_uart_config jz4760_uart_config = {
+	.tx_loadsz = 16,
+	.fifosize = 32,
+};
+
+static const struct ingenic_uart_config jz4780_uart_config = {
+	.tx_loadsz = 32,
+	.fifosize = 64,
+};
+
 static const struct of_device_id of_match[] = {
 static const struct of_device_id of_match[] = {
-	{ .compatible = "ingenic,jz4740-uart" },
-	{ .compatible = "ingenic,jz4775-uart" },
-	{ .compatible = "ingenic,jz4780-uart" },
+	{ .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config },
+	{ .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config },
+	{ .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config },
+	{ .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config },
 	{ /* sentinel */ }
 	{ /* sentinel */ }
 };
 };
 MODULE_DEVICE_TABLE(of, of_match);
 MODULE_DEVICE_TABLE(of, of_match);