.. | .. |
---|
7 | 7 | * Copyright (C) 2000 Deep Blue Solutions Ltd. |
---|
8 | 8 | */ |
---|
9 | 9 | |
---|
10 | | -#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
---|
11 | | -#define SUPPORT_SYSRQ |
---|
12 | | -#endif |
---|
13 | | - |
---|
14 | 10 | #include <linux/module.h> |
---|
15 | 11 | #include <linux/ioport.h> |
---|
16 | 12 | #include <linux/init.h> |
---|
.. | .. |
---|
27 | 23 | #include <asm/irq.h> |
---|
28 | 24 | #include <mach/hardware.h> |
---|
29 | 25 | #include <mach/irqs.h> |
---|
| 26 | + |
---|
| 27 | +#include "serial_mctrl_gpio.h" |
---|
30 | 28 | |
---|
31 | 29 | /* We've been assigned a range on the "Low-density serial ports" major */ |
---|
32 | 30 | #define SERIAL_SA1100_MAJOR 204 |
---|
.. | .. |
---|
77 | 75 | struct uart_port port; |
---|
78 | 76 | struct timer_list timer; |
---|
79 | 77 | unsigned int old_status; |
---|
| 78 | + struct mctrl_gpios *gpios; |
---|
80 | 79 | }; |
---|
81 | 80 | |
---|
82 | 81 | /* |
---|
.. | .. |
---|
174 | 173 | container_of(port, struct sa1100_port, port); |
---|
175 | 174 | |
---|
176 | 175 | mod_timer(&sport->timer, jiffies); |
---|
| 176 | + |
---|
| 177 | + mctrl_gpio_enable_ms(sport->gpios); |
---|
177 | 178 | } |
---|
178 | 179 | |
---|
179 | 180 | static void |
---|
.. | .. |
---|
209 | 210 | else if (status & UTSR1_TO_SM(UTSR1_FRE)) |
---|
210 | 211 | flg = TTY_FRAME; |
---|
211 | 212 | |
---|
212 | | -#ifdef SUPPORT_SYSRQ |
---|
213 | 213 | sport->port.sysrq = 0; |
---|
214 | | -#endif |
---|
215 | 214 | } |
---|
216 | 215 | |
---|
217 | 216 | if (uart_handle_sysrq_char(&sport->port, ch)) |
---|
.. | .. |
---|
322 | 321 | |
---|
323 | 322 | static unsigned int sa1100_get_mctrl(struct uart_port *port) |
---|
324 | 323 | { |
---|
325 | | - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; |
---|
| 324 | + struct sa1100_port *sport = |
---|
| 325 | + container_of(port, struct sa1100_port, port); |
---|
| 326 | + int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; |
---|
| 327 | + |
---|
| 328 | + mctrl_gpio_get(sport->gpios, &ret); |
---|
| 329 | + |
---|
| 330 | + return ret; |
---|
326 | 331 | } |
---|
327 | 332 | |
---|
328 | 333 | static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl) |
---|
329 | 334 | { |
---|
| 335 | + struct sa1100_port *sport = |
---|
| 336 | + container_of(port, struct sa1100_port, port); |
---|
| 337 | + |
---|
| 338 | + mctrl_gpio_set(sport->gpios, mctrl); |
---|
330 | 339 | } |
---|
331 | 340 | |
---|
332 | 341 | /* |
---|
.. | .. |
---|
439 | 448 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); |
---|
440 | 449 | quot = uart_get_divisor(port, baud); |
---|
441 | 450 | |
---|
| 451 | + del_timer_sync(&sport->timer); |
---|
| 452 | + |
---|
442 | 453 | spin_lock_irqsave(&sport->port.lock, flags); |
---|
443 | 454 | |
---|
444 | 455 | sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); |
---|
.. | .. |
---|
468 | 479 | sport->port.ignore_status_mask |= |
---|
469 | 480 | UTSR1_TO_SM(UTSR1_ROR); |
---|
470 | 481 | } |
---|
471 | | - |
---|
472 | | - del_timer_sync(&sport->timer); |
---|
473 | 482 | |
---|
474 | 483 | /* |
---|
475 | 484 | * Update the per-port timeout. |
---|
.. | .. |
---|
842 | 851 | return 0; |
---|
843 | 852 | } |
---|
844 | 853 | |
---|
| 854 | +static int sa1100_serial_add_one_port(struct sa1100_port *sport, struct platform_device *dev) |
---|
| 855 | +{ |
---|
| 856 | + sport->port.dev = &dev->dev; |
---|
| 857 | + sport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SA1100_CONSOLE); |
---|
| 858 | + |
---|
| 859 | + // mctrl_gpio_init() requires that the GPIO driver supports interrupts, |
---|
| 860 | + // but we need to support GPIO drivers for hardware that has no such |
---|
| 861 | + // interrupts. Use mctrl_gpio_init_noauto() instead. |
---|
| 862 | + sport->gpios = mctrl_gpio_init_noauto(sport->port.dev, 0); |
---|
| 863 | + if (IS_ERR(sport->gpios)) { |
---|
| 864 | + int err = PTR_ERR(sport->gpios); |
---|
| 865 | + |
---|
| 866 | + dev_err(sport->port.dev, "failed to get mctrl gpios: %d\n", |
---|
| 867 | + err); |
---|
| 868 | + |
---|
| 869 | + if (err == -EPROBE_DEFER) |
---|
| 870 | + return err; |
---|
| 871 | + |
---|
| 872 | + sport->gpios = NULL; |
---|
| 873 | + } |
---|
| 874 | + |
---|
| 875 | + platform_set_drvdata(dev, sport); |
---|
| 876 | + |
---|
| 877 | + return uart_add_one_port(&sa1100_reg, &sport->port); |
---|
| 878 | +} |
---|
| 879 | + |
---|
845 | 880 | static int sa1100_serial_probe(struct platform_device *dev) |
---|
846 | 881 | { |
---|
847 | | - struct resource *res = dev->resource; |
---|
| 882 | + struct resource *res; |
---|
848 | 883 | int i; |
---|
849 | 884 | |
---|
850 | | - for (i = 0; i < dev->num_resources; i++, res++) |
---|
851 | | - if (res->flags & IORESOURCE_MEM) |
---|
852 | | - break; |
---|
| 885 | + res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
---|
| 886 | + if (!res) |
---|
| 887 | + return -EINVAL; |
---|
853 | 888 | |
---|
854 | | - if (i < dev->num_resources) { |
---|
855 | | - for (i = 0; i < NR_PORTS; i++) { |
---|
856 | | - if (sa1100_ports[i].port.mapbase != res->start) |
---|
857 | | - continue; |
---|
858 | | - |
---|
859 | | - sa1100_ports[i].port.dev = &dev->dev; |
---|
860 | | - uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port); |
---|
861 | | - platform_set_drvdata(dev, &sa1100_ports[i]); |
---|
| 889 | + for (i = 0; i < NR_PORTS; i++) |
---|
| 890 | + if (sa1100_ports[i].port.mapbase == res->start) |
---|
862 | 891 | break; |
---|
863 | | - } |
---|
864 | | - } |
---|
| 892 | + if (i == NR_PORTS) |
---|
| 893 | + return -ENODEV; |
---|
| 894 | + |
---|
| 895 | + sa1100_serial_add_one_port(&sa1100_ports[i], dev); |
---|
865 | 896 | |
---|
866 | 897 | return 0; |
---|
867 | 898 | } |
---|