1 /* 2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #include <linux/clk.h> 16 #include <linux/console.h> 17 #include <linux/io.h> 18 #include <linux/module.h> 19 #include <linux/of.h> 20 #include <linux/platform_device.h> 21 22 #include "8250.h" 23 24 /* Most (but not all) of UniPhier UART devices have 64-depth FIFO. */ 25 #define UNIPHIER_UART_DEFAULT_FIFO_SIZE 64 26 27 /* 28 * This hardware is similar to 8250, but its register map is a bit different: 29 * - MMIO32 (regshift = 2) 30 * - FCR is not at 2, but 3 31 * - LCR and MCR are not at 3 and 4, they share 4 32 * - Divisor latch at 9, no divisor latch access bit 33 */ 34 35 #define UNIPHIER_UART_REGSHIFT 2 36 37 /* bit[15:8] = CHAR (not used), bit[7:0] = FCR */ 38 #define UNIPHIER_UART_CHAR_FCR (3 << (UNIPHIER_UART_REGSHIFT)) 39 /* bit[15:8] = LCR, bit[7:0] = MCR */ 40 #define UNIPHIER_UART_LCR_MCR (4 << (UNIPHIER_UART_REGSHIFT)) 41 /* Divisor Latch Register */ 42 #define UNIPHIER_UART_DLR (9 << (UNIPHIER_UART_REGSHIFT)) 43 44 struct uniphier8250_priv { 45 int line; 46 struct clk *clk; 47 spinlock_t atomic_write_lock; 48 }; 49 50 #ifdef CONFIG_SERIAL_8250_CONSOLE 51 static int __init uniphier_early_console_setup(struct earlycon_device *device, 52 const char *options) 53 { 54 if (!device->port.membase) 55 return -ENODEV; 56 57 /* This hardware always expects MMIO32 register interface. */ 58 device->port.iotype = UPIO_MEM32; 59 device->port.regshift = UNIPHIER_UART_REGSHIFT; 60 61 /* 62 * Do not touch the divisor register in early_serial8250_setup(); 63 * we assume it has been initialized by a boot loader. 64 */ 65 device->baud = 0; 66 67 return early_serial8250_setup(device, options); 68 } 69 OF_EARLYCON_DECLARE(uniphier, "socionext,uniphier-uart", 70 uniphier_early_console_setup); 71 #endif 72 73 /* 74 * The register map is slightly different from that of 8250. 75 * IO callbacks must be overridden for correct access to FCR, LCR, and MCR. 76 */ 77 static unsigned int uniphier_serial_in(struct uart_port *p, int offset) 78 { 79 unsigned int valshift = 0; 80 81 switch (offset) { 82 case UART_LCR: 83 valshift = 8; 84 /* fall through */ 85 case UART_MCR: 86 offset = UNIPHIER_UART_LCR_MCR; 87 break; 88 default: 89 offset <<= UNIPHIER_UART_REGSHIFT; 90 break; 91 } 92 93 /* 94 * The return value must be masked with 0xff because LCR and MCR reside 95 * in the same register that must be accessed by 32-bit write/read. 96 * 8 or 16 bit access to this hardware result in unexpected behavior. 97 */ 98 return (readl(p->membase + offset) >> valshift) & 0xff; 99 } 100 101 static void uniphier_serial_out(struct uart_port *p, int offset, int value) 102 { 103 unsigned int valshift = 0; 104 bool normal = true; 105 106 switch (offset) { 107 case UART_FCR: 108 offset = UNIPHIER_UART_CHAR_FCR; 109 break; 110 case UART_LCR: 111 valshift = 8; 112 /* Divisor latch access bit does not exist. */ 113 value &= ~UART_LCR_DLAB; 114 /* fall through */ 115 case UART_MCR: 116 offset = UNIPHIER_UART_LCR_MCR; 117 normal = false; 118 break; 119 default: 120 offset <<= UNIPHIER_UART_REGSHIFT; 121 break; 122 } 123 124 if (normal) { 125 writel(value, p->membase + offset); 126 } else { 127 /* 128 * Special case: two registers share the same address that 129 * must be 32-bit accessed. As this is not longer atomic safe, 130 * take a lock just in case. 131 */ 132 struct uniphier8250_priv *priv = p->private_data; 133 unsigned long flags; 134 u32 tmp; 135 136 spin_lock_irqsave(&priv->atomic_write_lock, flags); 137 tmp = readl(p->membase + offset); 138 tmp &= ~(0xff << valshift); 139 tmp |= value << valshift; 140 writel(tmp, p->membase + offset); 141 spin_unlock_irqrestore(&priv->atomic_write_lock, flags); 142 } 143 } 144 145 /* 146 * This hardware does not have the divisor latch access bit. 147 * The divisor latch register exists at different address. 148 * Override dl_read/write callbacks. 149 */ 150 static int uniphier_serial_dl_read(struct uart_8250_port *up) 151 { 152 return readl(up->port.membase + UNIPHIER_UART_DLR); 153 } 154 155 static void uniphier_serial_dl_write(struct uart_8250_port *up, int value) 156 { 157 writel(value, up->port.membase + UNIPHIER_UART_DLR); 158 } 159 160 static int uniphier_of_serial_setup(struct device *dev, struct uart_port *port, 161 struct uniphier8250_priv *priv) 162 { 163 int ret; 164 u32 prop; 165 struct device_node *np = dev->of_node; 166 167 ret = of_alias_get_id(np, "serial"); 168 if (ret < 0) { 169 dev_err(dev, "failed to get alias id\n"); 170 return ret; 171 } 172 port->line = priv->line = ret; 173 174 /* Get clk rate through clk driver */ 175 priv->clk = devm_clk_get(dev, NULL); 176 if (IS_ERR(priv->clk)) { 177 dev_err(dev, "failed to get clock\n"); 178 return PTR_ERR(priv->clk); 179 } 180 181 ret = clk_prepare_enable(priv->clk); 182 if (ret < 0) 183 return ret; 184 185 port->uartclk = clk_get_rate(priv->clk); 186 187 /* Check for fifo size */ 188 if (of_property_read_u32(np, "fifo-size", &prop) == 0) 189 port->fifosize = prop; 190 else 191 port->fifosize = UNIPHIER_UART_DEFAULT_FIFO_SIZE; 192 193 return 0; 194 } 195 196 static int uniphier_uart_probe(struct platform_device *pdev) 197 { 198 struct device *dev = &pdev->dev; 199 struct uart_8250_port up; 200 struct uniphier8250_priv *priv; 201 struct resource *regs; 202 void __iomem *membase; 203 int irq; 204 int ret; 205 206 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 207 if (!regs) { 208 dev_err(dev, "failed to get memory resource\n"); 209 return -EINVAL; 210 } 211 212 membase = devm_ioremap(dev, regs->start, resource_size(regs)); 213 if (!membase) 214 return -ENOMEM; 215 216 irq = platform_get_irq(pdev, 0); 217 if (irq < 0) { 218 dev_err(dev, "failed to get IRQ number\n"); 219 return irq; 220 } 221 222 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 223 if (!priv) 224 return -ENOMEM; 225 226 memset(&up, 0, sizeof(up)); 227 228 ret = uniphier_of_serial_setup(dev, &up.port, priv); 229 if (ret < 0) 230 return ret; 231 232 spin_lock_init(&priv->atomic_write_lock); 233 234 up.port.dev = dev; 235 up.port.private_data = priv; 236 up.port.mapbase = regs->start; 237 up.port.mapsize = resource_size(regs); 238 up.port.membase = membase; 239 up.port.irq = irq; 240 241 up.port.type = PORT_16550A; 242 up.port.iotype = UPIO_MEM32; 243 up.port.regshift = UNIPHIER_UART_REGSHIFT; 244 up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE; 245 up.capabilities = UART_CAP_FIFO; 246 247 up.port.serial_in = uniphier_serial_in; 248 up.port.serial_out = uniphier_serial_out; 249 up.dl_read = uniphier_serial_dl_read; 250 up.dl_write = uniphier_serial_dl_write; 251 252 ret = serial8250_register_8250_port(&up); 253 if (ret < 0) { 254 dev_err(dev, "failed to register 8250 port\n"); 255 clk_disable_unprepare(priv->clk); 256 return ret; 257 } 258 259 platform_set_drvdata(pdev, priv); 260 261 return 0; 262 } 263 264 static int uniphier_uart_remove(struct platform_device *pdev) 265 { 266 struct uniphier8250_priv *priv = platform_get_drvdata(pdev); 267 268 serial8250_unregister_port(priv->line); 269 clk_disable_unprepare(priv->clk); 270 271 return 0; 272 } 273 274 static const struct of_device_id uniphier_uart_match[] = { 275 { .compatible = "socionext,uniphier-uart" }, 276 { /* sentinel */ } 277 }; 278 MODULE_DEVICE_TABLE(of, uniphier_uart_match); 279 280 static struct platform_driver uniphier_uart_platform_driver = { 281 .probe = uniphier_uart_probe, 282 .remove = uniphier_uart_remove, 283 .driver = { 284 .name = "uniphier-uart", 285 .of_match_table = uniphier_uart_match, 286 }, 287 }; 288 module_platform_driver(uniphier_uart_platform_driver); 289 290 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>"); 291 MODULE_DESCRIPTION("UniPhier UART driver"); 292 MODULE_LICENSE("GPL"); 293