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

Configure Feed

Select the types of activity you want to include in your feed.

at v4.3-rc5 367 lines 8.9 kB view raw
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 = devm_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 ret = clk_prepare_enable(info->clk); 78 if (ret < 0) 79 return ret; 80 81 clk = clk_get_rate(info->clk); 82 } 83 /* If current-speed was set, then try not to change it. */ 84 if (of_property_read_u32(np, "current-speed", &spd) == 0) 85 port->custom_divisor = clk / (16 * spd); 86 87 ret = of_address_to_resource(np, 0, &resource); 88 if (ret) { 89 dev_warn(&ofdev->dev, "invalid address\n"); 90 goto out; 91 } 92 93 spin_lock_init(&port->lock); 94 port->mapbase = resource.start; 95 port->mapsize = resource_size(&resource); 96 97 /* Check for shifted address mapping */ 98 if (of_property_read_u32(np, "reg-offset", &prop) == 0) 99 port->mapbase += prop; 100 101 /* Check for registers offset within the devices address range */ 102 if (of_property_read_u32(np, "reg-shift", &prop) == 0) 103 port->regshift = prop; 104 105 /* Check for fifo size */ 106 if (of_property_read_u32(np, "fifo-size", &prop) == 0) 107 port->fifosize = prop; 108 109 /* Check for a fixed line number */ 110 ret = of_alias_get_id(np, "serial"); 111 if (ret >= 0) 112 port->line = ret; 113 114 port->irq = irq_of_parse_and_map(np, 0); 115 port->iotype = UPIO_MEM; 116 if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { 117 switch (prop) { 118 case 1: 119 port->iotype = UPIO_MEM; 120 break; 121 case 4: 122 port->iotype = of_device_is_big_endian(np) ? 123 UPIO_MEM32BE : UPIO_MEM32; 124 break; 125 default: 126 dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", 127 prop); 128 ret = -EINVAL; 129 goto out; 130 } 131 } 132 133 port->type = type; 134 port->uartclk = clk; 135 port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP 136 | UPF_FIXED_PORT | UPF_FIXED_TYPE; 137 138 if (of_find_property(np, "no-loopback-test", NULL)) 139 port->flags |= UPF_SKIP_TEST; 140 141 port->dev = &ofdev->dev; 142 143 switch (type) { 144 case PORT_TEGRA: 145 port->handle_break = tegra_serial_handle_break; 146 break; 147 148 case PORT_RT2880: 149 port->iotype = UPIO_AU; 150 break; 151 } 152 153 return 0; 154out: 155 if (info->clk) 156 clk_disable_unprepare(info->clk); 157 return ret; 158} 159 160/* 161 * Try to register a serial port 162 */ 163static const struct of_device_id of_platform_serial_table[]; 164static int of_platform_serial_probe(struct platform_device *ofdev) 165{ 166 const struct of_device_id *match; 167 struct of_serial_info *info; 168 struct uart_port port; 169 int port_type; 170 int ret; 171 172 match = of_match_device(of_platform_serial_table, &ofdev->dev); 173 if (!match) 174 return -EINVAL; 175 176 if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) 177 return -EBUSY; 178 179 info = kzalloc(sizeof(*info), GFP_KERNEL); 180 if (info == NULL) 181 return -ENOMEM; 182 183 port_type = (unsigned long)match->data; 184 ret = of_platform_serial_setup(ofdev, port_type, &port, info); 185 if (ret) 186 goto out; 187 188 switch (port_type) { 189#ifdef CONFIG_SERIAL_8250 190 case PORT_8250 ... PORT_MAX_8250: 191 { 192 struct uart_8250_port port8250; 193 memset(&port8250, 0, sizeof(port8250)); 194 port8250.port = port; 195 196 if (port.fifosize) 197 port8250.capabilities = UART_CAP_FIFO; 198 199 if (of_property_read_bool(ofdev->dev.of_node, 200 "auto-flow-control")) 201 port8250.capabilities |= UART_CAP_AFE; 202 203 ret = serial8250_register_8250_port(&port8250); 204 break; 205 } 206#endif 207#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL 208 case PORT_NWPSERIAL: 209 ret = nwpserial_register_port(&port); 210 break; 211#endif 212 default: 213 /* need to add code for these */ 214 case PORT_UNKNOWN: 215 dev_info(&ofdev->dev, "Unknown serial port found, ignored\n"); 216 ret = -ENODEV; 217 break; 218 } 219 if (ret < 0) 220 goto out; 221 222 info->type = port_type; 223 info->line = ret; 224 platform_set_drvdata(ofdev, info); 225 return 0; 226out: 227 kfree(info); 228 irq_dispose_mapping(port.irq); 229 return ret; 230} 231 232/* 233 * Release a line 234 */ 235static int of_platform_serial_remove(struct platform_device *ofdev) 236{ 237 struct of_serial_info *info = platform_get_drvdata(ofdev); 238 switch (info->type) { 239#ifdef CONFIG_SERIAL_8250 240 case PORT_8250 ... PORT_MAX_8250: 241 serial8250_unregister_port(info->line); 242 break; 243#endif 244#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL 245 case PORT_NWPSERIAL: 246 nwpserial_unregister_port(info->line); 247 break; 248#endif 249 default: 250 /* need to add code for these */ 251 break; 252 } 253 254 if (info->clk) 255 clk_disable_unprepare(info->clk); 256 kfree(info); 257 return 0; 258} 259 260#ifdef CONFIG_PM_SLEEP 261#ifdef CONFIG_SERIAL_8250 262static void of_serial_suspend_8250(struct of_serial_info *info) 263{ 264 struct uart_8250_port *port8250 = serial8250_get_port(info->line); 265 struct uart_port *port = &port8250->port; 266 267 serial8250_suspend_port(info->line); 268 if (info->clk && (!uart_console(port) || console_suspend_enabled)) 269 clk_disable_unprepare(info->clk); 270} 271 272static void of_serial_resume_8250(struct of_serial_info *info) 273{ 274 struct uart_8250_port *port8250 = serial8250_get_port(info->line); 275 struct uart_port *port = &port8250->port; 276 277 if (info->clk && (!uart_console(port) || console_suspend_enabled)) 278 clk_prepare_enable(info->clk); 279 280 serial8250_resume_port(info->line); 281} 282#else 283static inline void of_serial_suspend_8250(struct of_serial_info *info) 284{ 285} 286 287static inline void of_serial_resume_8250(struct of_serial_info *info) 288{ 289} 290#endif 291 292static int of_serial_suspend(struct device *dev) 293{ 294 struct of_serial_info *info = dev_get_drvdata(dev); 295 296 switch (info->type) { 297 case PORT_8250 ... PORT_MAX_8250: 298 of_serial_suspend_8250(info); 299 break; 300 default: 301 break; 302 } 303 304 return 0; 305} 306 307static int of_serial_resume(struct device *dev) 308{ 309 struct of_serial_info *info = dev_get_drvdata(dev); 310 311 switch (info->type) { 312 case PORT_8250 ... PORT_MAX_8250: 313 of_serial_resume_8250(info); 314 break; 315 default: 316 break; 317 } 318 319 return 0; 320} 321#endif 322static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume); 323 324/* 325 * A few common types, add more as needed. 326 */ 327static const struct of_device_id of_platform_serial_table[] = { 328 { .compatible = "ns8250", .data = (void *)PORT_8250, }, 329 { .compatible = "ns16450", .data = (void *)PORT_16450, }, 330 { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, 331 { .compatible = "ns16550", .data = (void *)PORT_16550, }, 332 { .compatible = "ns16750", .data = (void *)PORT_16750, }, 333 { .compatible = "ns16850", .data = (void *)PORT_16850, }, 334 { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, 335 { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, 336 { .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, }, 337 { .compatible = "altr,16550-FIFO32", 338 .data = (void *)PORT_ALTR_16550_F32, }, 339 { .compatible = "altr,16550-FIFO64", 340 .data = (void *)PORT_ALTR_16550_F64, }, 341 { .compatible = "altr,16550-FIFO128", 342 .data = (void *)PORT_ALTR_16550_F128, }, 343 { .compatible = "mrvl,mmp-uart", 344 .data = (void *)PORT_XSCALE, }, 345 { .compatible = "mrvl,pxa-uart", 346 .data = (void *)PORT_XSCALE, }, 347#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL 348 { .compatible = "ibm,qpace-nwp-serial", 349 .data = (void *)PORT_NWPSERIAL, }, 350#endif 351 { /* end of list */ }, 352}; 353 354static struct platform_driver of_platform_serial_driver = { 355 .driver = { 356 .name = "of_serial", 357 .of_match_table = of_platform_serial_table, 358 }, 359 .probe = of_platform_serial_probe, 360 .remove = of_platform_serial_remove, 361}; 362 363module_platform_driver(of_platform_serial_driver); 364 365MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>"); 366MODULE_LICENSE("GPL"); 367MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices");