0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/device.h>
0009 #include <linux/io.h>
0010 #include <linux/module.h>
0011 #include <linux/mod_devicetable.h>
0012 #include <linux/serial_8250.h>
0013 #include <linux/serial_reg.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/clk.h>
0016 #include <linux/slab.h>
0017
0018 #include "8250.h"
0019
0020 #define UART_DLL_EM 9
0021 #define UART_DLM_EM 10
0022
0023 struct serial8250_em_priv {
0024 struct clk *sclk;
0025 int line;
0026 };
0027
0028 static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
0029 {
0030 switch (offset) {
0031 case UART_TX:
0032 writeb(value, p->membase);
0033 break;
0034 case UART_FCR:
0035 case UART_LCR:
0036 case UART_MCR:
0037 case UART_SCR:
0038 writel(value, p->membase + ((offset + 1) << 2));
0039 break;
0040 case UART_IER:
0041 value &= 0x0f;
0042 fallthrough;
0043 case UART_DLL_EM:
0044 case UART_DLM_EM:
0045 writel(value, p->membase + (offset << 2));
0046 }
0047 }
0048
0049 static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset)
0050 {
0051 switch (offset) {
0052 case UART_RX:
0053 return readb(p->membase);
0054 case UART_MCR:
0055 case UART_LSR:
0056 case UART_MSR:
0057 case UART_SCR:
0058 return readl(p->membase + ((offset + 1) << 2));
0059 case UART_IER:
0060 case UART_IIR:
0061 case UART_DLL_EM:
0062 case UART_DLM_EM:
0063 return readl(p->membase + (offset << 2));
0064 }
0065 return 0;
0066 }
0067
0068 static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
0069 {
0070 return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8;
0071 }
0072
0073 static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
0074 {
0075 serial_out(up, UART_DLL_EM, value & 0xff);
0076 serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
0077 }
0078
0079 static int serial8250_em_probe(struct platform_device *pdev)
0080 {
0081 struct serial8250_em_priv *priv;
0082 struct uart_8250_port up;
0083 struct resource *regs;
0084 int irq, ret;
0085
0086 irq = platform_get_irq(pdev, 0);
0087 if (irq < 0)
0088 return irq;
0089
0090 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0091 if (!regs) {
0092 dev_err(&pdev->dev, "missing registers\n");
0093 return -EINVAL;
0094 }
0095
0096 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0097 if (!priv)
0098 return -ENOMEM;
0099
0100 priv->sclk = devm_clk_get(&pdev->dev, "sclk");
0101 if (IS_ERR(priv->sclk)) {
0102 dev_err(&pdev->dev, "unable to get clock\n");
0103 return PTR_ERR(priv->sclk);
0104 }
0105
0106 memset(&up, 0, sizeof(up));
0107 up.port.mapbase = regs->start;
0108 up.port.irq = irq;
0109 up.port.type = PORT_UNKNOWN;
0110 up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
0111 up.port.dev = &pdev->dev;
0112 up.port.private_data = priv;
0113
0114 clk_prepare_enable(priv->sclk);
0115 up.port.uartclk = clk_get_rate(priv->sclk);
0116
0117 up.port.iotype = UPIO_MEM32;
0118 up.port.serial_in = serial8250_em_serial_in;
0119 up.port.serial_out = serial8250_em_serial_out;
0120 up.dl_read = serial8250_em_serial_dl_read;
0121 up.dl_write = serial8250_em_serial_dl_write;
0122
0123 ret = serial8250_register_8250_port(&up);
0124 if (ret < 0) {
0125 dev_err(&pdev->dev, "unable to register 8250 port\n");
0126 clk_disable_unprepare(priv->sclk);
0127 return ret;
0128 }
0129
0130 priv->line = ret;
0131 platform_set_drvdata(pdev, priv);
0132 return 0;
0133 }
0134
0135 static int serial8250_em_remove(struct platform_device *pdev)
0136 {
0137 struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
0138
0139 serial8250_unregister_port(priv->line);
0140 clk_disable_unprepare(priv->sclk);
0141 return 0;
0142 }
0143
0144 static const struct of_device_id serial8250_em_dt_ids[] = {
0145 { .compatible = "renesas,em-uart", },
0146 {},
0147 };
0148 MODULE_DEVICE_TABLE(of, serial8250_em_dt_ids);
0149
0150 static struct platform_driver serial8250_em_platform_driver = {
0151 .driver = {
0152 .name = "serial8250-em",
0153 .of_match_table = serial8250_em_dt_ids,
0154 },
0155 .probe = serial8250_em_probe,
0156 .remove = serial8250_em_remove,
0157 };
0158
0159 module_platform_driver(serial8250_em_platform_driver);
0160
0161 MODULE_AUTHOR("Magnus Damm");
0162 MODULE_DESCRIPTION("Renesas Emma Mobile 8250 Driver");
0163 MODULE_LICENSE("GPL v2");