1/* 2 * Serial Port driver for Open Firmware platform devices 3 * 4 * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 * 11 */ 12#include <linux/console.h> 13#include <linux/module.h> 14#include <linux/slab.h> 15#include <linux/delay.h> 16#include <linux/serial_core.h> 17#include <linux/serial_reg.h> 18#include <linux/of_address.h> 19#include <linux/of_irq.h> 20#include <linux/of_platform.h> 21#include <linux/nwpserial.h> 22#include <linux/clk.h> 23 24#include "8250/8250.h" 25 26struct of_serial_info { 27 struct clk *clk; 28 int type; 29 int line; 30}; 31 32#ifdef CONFIG_ARCH_TEGRA 33void tegra_serial_handle_break(struct uart_port *p) 34{ 35 unsigned int status, tmout = 10000; 36 37 do { 38 status = p->serial_in(p, UART_LSR); 39 if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) 40 status = p->serial_in(p, UART_RX); 41 else 42 break; 43 if (--tmout == 0) 44 break; 45 udelay(1); 46 } while (1); 47} 48#else 49static inline void tegra_serial_handle_break(struct uart_port *port) 50{ 51} 52#endif 53 54/* 55 * Fill a struct uart_port for a given device node 56 */ 57static int of_platform_serial_setup(struct platform_device *ofdev, 58 int type, struct uart_port *port, 59 struct of_serial_info *info) 60{ 61 struct resource resource; 62 struct device_node *np = ofdev->dev.of_node; 63 u32 clk, spd, prop; 64 int ret; 65 66 memset(port, 0, sizeof *port); 67 if (of_property_read_u32(np, "clock-frequency", &clk)) { 68 69 /* Get clk rate through clk driver if present */ 70 info->clk = clk_get(&ofdev->dev, NULL); 71 if (IS_ERR(info->clk)) { 72 dev_warn(&ofdev->dev, 73 "clk or clock-frequency not defined\n"); 74 return PTR_ERR(info->clk); 75 } 76 77 clk_prepare_enable(info->clk); 78 clk = clk_get_rate(info->clk); 79 } 80 /* If current-speed was set, then try not to change it. */ 81 if (of_property_read_u32(np, "current-speed", &spd) == 0) 82 port->custom_divisor = clk / (16 * spd); 83 84 ret = of_address_to_resource(np, 0, &resource); 85 if (ret) { 86 dev_warn(&ofdev->dev, "invalid address\n"); 87 goto out; 88 } 89 90 spin_lock_init(&port->lock); 91 port->mapbase = resource.start; 92 port->mapsize = resource_size(&resource); 93 94 /* Check for shifted address mapping */ 95 if (of_property_read_u32(np, "reg-offset", &prop) == 0) 96 port->mapbase += prop; 97 98 /* Check for registers offset within the devices address range */ 99 if (of_property_read_u32(np, "reg-shift", &prop) == 0) 100 port->regshift = prop; 101 102 /* Check for fifo size */ 103 if (of_property_read_u32(np, "fifo-size", &prop) == 0) 104 port->fifosize = prop; 105 106 /* Check for a fixed line number */ 107 ret = of_alias_get_id(np, "serial"); 108 if (ret >= 0) 109 port->line = ret; 110 111 port->irq = irq_of_parse_and_map(np, 0); 112 port->iotype = UPIO_MEM; 113 if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { 114 switch (prop) { 115 case 1: 116 port->iotype = UPIO_MEM; 117 break; 118 case 4: 119 port->iotype = of_device_is_big_endian(np) ? 120 UPIO_MEM32BE : UPIO_MEM32; 121 break; 122 default: 123 dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", 124 prop); 125 ret = -EINVAL; 126 goto out; 127 } 128 } 129 130 port->type = type; 131 port->uartclk = clk; 132 port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP 133 | UPF_FIXED_PORT | UPF_FIXED_TYPE; 134 135 if (of_find_property(np, "no-loopback-test", NULL)) 136 port->flags |= UPF_SKIP_TEST; 137 138 port->dev = &ofdev->dev; 139 140 switch (type) { 141 case PORT_TEGRA: 142 port->handle_break = tegra_serial_handle_break; 143 break; 144 145 case PORT_RT2880: 146 port->iotype = UPIO_AU; 147 break; 148 } 149 150 return 0; 151out: 152 if (info->clk) 153 clk_disable_unprepare(info->clk); 154 return ret; 155} 156 157/* 158 * Try to register a serial port 159 */ 160static const struct of_device_id of_platform_serial_table[]; 161static int of_platform_serial_probe(struct platform_device *ofdev) 162{ 163 const struct of_device_id *match; 164 struct of_serial_info *info; 165 struct uart_port port; 166 int port_type; 167 int ret; 168 169 match = of_match_device(of_platform_serial_table, &ofdev->dev); 170 if (!match) 171 return -EINVAL; 172 173 if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) 174 return -EBUSY; 175 176 info = kzalloc(sizeof(*info), GFP_KERNEL); 177 if (info == NULL) 178 return -ENOMEM; 179 180 port_type = (unsigned long)match->data; 181 ret = of_platform_serial_setup(ofdev, port_type, &port, info); 182 if (ret) 183 goto out; 184 185 switch (port_type) { 186#ifdef CONFIG_SERIAL_8250 187 case PORT_8250 ... PORT_MAX_8250: 188 { 189 struct uart_8250_port port8250; 190 memset(&port8250, 0, sizeof(port8250)); 191 port.type = port_type; 192 port8250.port = port; 193 194 if (port.fifosize) 195 port8250.capabilities = UART_CAP_FIFO; 196 197 if (of_property_read_bool(ofdev->dev.of_node, 198 "auto-flow-control")) 199 port8250.capabilities |= UART_CAP_AFE; 200 201 ret = serial8250_register_8250_port(&port8250); 202 break; 203 } 204#endif 205#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL 206 case PORT_NWPSERIAL: 207 ret = nwpserial_register_port(&port); 208 break; 209#endif 210 default: 211 /* need to add code for these */ 212 case PORT_UNKNOWN: 213 dev_info(&ofdev->dev, "Unknown serial port found, ignored\n"); 214 ret = -ENODEV; 215 break; 216 } 217 if (ret < 0) 218 goto out; 219 220 info->type = port_type; 221 info->line = ret; 222 platform_set_drvdata(ofdev, info); 223 return 0; 224out: 225 kfree(info); 226 irq_dispose_mapping(port.irq); 227 return ret; 228} 229 230/* 231 * Release a line 232 */ 233static int of_platform_serial_remove(struct platform_device *ofdev) 234{ 235 struct of_serial_info *info = platform_get_drvdata(ofdev); 236 switch (info->type) { 237#ifdef CONFIG_SERIAL_8250 238 case PORT_8250 ... PORT_MAX_8250: 239 serial8250_unregister_port(info->line); 240 break; 241#endif 242#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL 243 case PORT_NWPSERIAL: 244 nwpserial_unregister_port(info->line); 245 break; 246#endif 247 default: 248 /* need to add code for these */ 249 break; 250 } 251 252 if (info->clk) 253 clk_disable_unprepare(info->clk); 254 kfree(info); 255 return 0; 256} 257 258#ifdef CONFIG_PM_SLEEP 259#ifdef CONFIG_SERIAL_8250 260static void of_serial_suspend_8250(struct of_serial_info *info) 261{ 262 struct uart_8250_port *port8250 = serial8250_get_port(info->line); 263 struct uart_port *port = &port8250->port; 264 265 serial8250_suspend_port(info->line); 266 if (info->clk && (!uart_console(port) || console_suspend_enabled)) 267 clk_disable_unprepare(info->clk); 268} 269 270static void of_serial_resume_8250(struct of_serial_info *info) 271{ 272 struct uart_8250_port *port8250 = serial8250_get_port(info->line); 273 struct uart_port *port = &port8250->port; 274 275 if (info->clk && (!uart_console(port) || console_suspend_enabled)) 276 clk_prepare_enable(info->clk); 277 278 serial8250_resume_port(info->line); 279} 280#else 281static inline void of_serial_suspend_8250(struct of_serial_info *info) 282{ 283} 284 285static inline void of_serial_resume_8250(struct of_serial_info *info) 286{ 287} 288#endif 289 290static int of_serial_suspend(struct device *dev) 291{ 292 struct of_serial_info *info = dev_get_drvdata(dev); 293 294 switch (info->type) { 295 case PORT_8250 ... PORT_MAX_8250: 296 of_serial_suspend_8250(info); 297 break; 298 default: 299 break; 300 } 301 302 return 0; 303} 304 305static int of_serial_resume(struct device *dev) 306{ 307 struct of_serial_info *info = dev_get_drvdata(dev); 308 309 switch (info->type) { 310 case PORT_8250 ... PORT_MAX_8250: 311 of_serial_resume_8250(info); 312 break; 313 default: 314 break; 315 } 316 317 return 0; 318} 319#endif 320static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume); 321 322/* 323 * A few common types, add more as needed. 324 */ 325static const struct of_device_id of_platform_serial_table[] = { 326 { .compatible = "ns8250", .data = (void *)PORT_8250, }, 327 { .compatible = "ns16450", .data = (void *)PORT_16450, }, 328 { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, 329 { .compatible = "ns16550", .data = (void *)PORT_16550, }, 330 { .compatible = "ns16750", .data = (void *)PORT_16750, }, 331 { .compatible = "ns16850", .data = (void *)PORT_16850, }, 332 { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, 333 { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, 334 { .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, }, 335 { .compatible = "altr,16550-FIFO32", 336 .data = (void *)PORT_ALTR_16550_F32, }, 337 { .compatible = "altr,16550-FIFO64", 338 .data = (void *)PORT_ALTR_16550_F64, }, 339 { .compatible = "altr,16550-FIFO128", 340 .data = (void *)PORT_ALTR_16550_F128, }, 341 { .compatible = "mrvl,mmp-uart", 342 .data = (void *)PORT_XSCALE, }, 343 { .compatible = "mrvl,pxa-uart", 344 .data = (void *)PORT_XSCALE, }, 345#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL 346 { .compatible = "ibm,qpace-nwp-serial", 347 .data = (void *)PORT_NWPSERIAL, }, 348#endif 349 { /* end of list */ }, 350}; 351 352static struct platform_driver of_platform_serial_driver = { 353 .driver = { 354 .name = "of_serial", 355 .of_match_table = of_platform_serial_table, 356 }, 357 .probe = of_platform_serial_probe, 358 .remove = of_platform_serial_remove, 359}; 360 361module_platform_driver(of_platform_serial_driver); 362 363MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>"); 364MODULE_LICENSE("GPL"); 365MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices"); 366