| .. | .. |
|---|
| 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 | } |
|---|