serial: max310x: Add support for RS-485 mode
authorAlexander Shiyan <shc_work@mail.ru>
Mon, 10 Feb 2014 18:18:34 +0000 (22:18 +0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Feb 2014 17:34:48 +0000 (09:34 -0800)
This patch adds support for RS-485 (TIOCSRS485/TIOCGRS485) IOCTLs.
As a result this patch eliminate private driver header.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/max310x.c
include/linux/platform_data/max310x.h [deleted file]

index c180576546ed5055bc021ed1f7703040dbc593c7..090f25d4a0196260b60eaf3ff22161b97b02f1b0 100644 (file)
@@ -26,8 +26,6 @@
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 
-#include <linux/platform_data/max310x.h>
-
 #define MAX310X_NAME                   "max310x"
 #define MAX310X_MAJOR                  204
 #define MAX310X_MINOR                  209
@@ -293,7 +291,6 @@ struct max310x_port {
        struct regmap           *regmap;
        struct mutex            mutex;
        struct clk              *clk;
-       struct max310x_pdata    *pdata;
 #ifdef CONFIG_GPIOLIB
        struct gpio_chip        gpio;
 #endif
@@ -898,26 +895,70 @@ static void max310x_set_termios(struct uart_port *port,
        uart_update_timeout(port, termios->c_cflag, baud);
 }
 
+static int max310x_ioctl(struct uart_port *port, unsigned int cmd,
+                        unsigned long arg)
+{
+       struct serial_rs485 rs485;
+       unsigned int val;
+
+       switch (cmd) {
+       case TIOCSRS485:
+               if (copy_from_user(&rs485, (struct serial_rs485 *)arg,
+                                  sizeof(rs485)))
+                       return -EFAULT;
+               if (rs485.delay_rts_before_send > 0x0f ||
+                   rs485.delay_rts_after_send > 0x0f)
+                       return -ERANGE;
+               val = (rs485.delay_rts_before_send << 4) |
+                     rs485.delay_rts_after_send;
+               max310x_port_write(port, MAX310X_HDPIXDELAY_REG, val);
+               if (rs485.flags & SER_RS485_ENABLED) {
+                       max310x_port_update(port, MAX310X_MODE1_REG,
+                                           MAX310X_MODE1_TRNSCVCTRL_BIT,
+                                           MAX310X_MODE1_TRNSCVCTRL_BIT);
+                       max310x_port_update(port, MAX310X_MODE2_REG,
+                                           MAX310X_MODE2_ECHOSUPR_BIT,
+                                           MAX310X_MODE2_ECHOSUPR_BIT);
+               } else {
+                       max310x_port_update(port, MAX310X_MODE1_REG,
+                                           MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
+                       max310x_port_update(port, MAX310X_MODE2_REG,
+                                           MAX310X_MODE2_ECHOSUPR_BIT, 0);
+               }
+               break;
+       case TIOCGRS485:
+               memset(&rs485, 0, sizeof(rs485));
+               val = max310x_port_read(port, MAX310X_MODE1_REG);
+               rs485.flags = (val & MAX310X_MODE1_TRNSCVCTRL_BIT) ?
+                             SER_RS485_ENABLED : 0;
+               rs485.flags |= SER_RS485_RTS_ON_SEND;
+               val = max310x_port_read(port, MAX310X_HDPIXDELAY_REG);
+               rs485.delay_rts_before_send = val >> 4;
+               rs485.delay_rts_after_send = val & 0x0f;
+               if (copy_to_user((struct serial_rs485 *)arg, &rs485,
+                                sizeof(rs485)))
+                       return -EFAULT;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return 0;
+}
+
 static int max310x_startup(struct uart_port *port)
 {
-       unsigned int val, line = port->line;
        struct max310x_port *s = dev_get_drvdata(port->dev);
+       unsigned int val;
 
        s->devtype->power(port, 1);
 
        /* Configure MODE1 register */
        max310x_port_update(port, MAX310X_MODE1_REG,
-                           MAX310X_MODE1_TRNSCVCTRL_BIT,
-                           (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL)
-                           ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0);
+                           MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
 
-       /* Configure MODE2 register */
-       val = MAX310X_MODE2_RXEMPTINV_BIT;
-       if (s->pdata->uart_flags[line] & MAX310X_ECHO_SUPRESS)
-               val |= MAX310X_MODE2_ECHOSUPR_BIT;
-
-       /* Reset FIFOs */
-       val |= MAX310X_MODE2_FIFORST_BIT;
+       /* Configure MODE2 register & Reset FIFOs*/
+       val = MAX310X_MODE2_RXEMPTINV_BIT | MAX310X_MODE2_FIFORST_BIT;
        max310x_port_write(port, MAX310X_MODE2_REG, val);
        max310x_port_update(port, MAX310X_MODE2_REG,
                            MAX310X_MODE2_FIFORST_BIT, 0);
@@ -998,6 +1039,7 @@ static const struct uart_ops max310x_ops = {
        .release_port   = max310x_null_void,
        .config_port    = max310x_config_port,
        .verify_port    = max310x_verify_port,
+       .ioctl          = max310x_ioctl,
 };
 
 static int __maybe_unused max310x_suspend(struct device *dev)
@@ -1077,7 +1119,6 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,
 static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
                         struct regmap *regmap, int irq)
 {
-       struct max310x_pdata *pdata = dev_get_platdata(dev);
        int i, ret, fmin, fmax, freq, uartclk;
        struct clk *clk_osc, *clk_xtal;
        struct max310x_port *s;
@@ -1086,11 +1127,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
        if (IS_ERR(regmap))
                return PTR_ERR(regmap);
 
-       if (!pdata) {
-               dev_err(dev, "No platform data supplied\n");
-               return -EINVAL;
-       }
-
        /* Alloc port structure */
        s = devm_kzalloc(dev, sizeof(*s) +
                         sizeof(struct max310x_one) * devtype->nr, GFP_KERNEL);
@@ -1129,7 +1165,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
                goto out_clk;
        }
 
-       s->pdata = pdata;
        s->regmap = regmap;
        s->devtype = devtype;
        dev_set_drvdata(dev, s);
diff --git a/include/linux/platform_data/max310x.h b/include/linux/platform_data/max310x.h
deleted file mode 100644 (file)
index 1140a57..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
- *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
- *
- *  Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
- *  Based on max3110.c, by Feng Tang <feng.tang@intel.com>
- *  Based on max3107.c, by Aavamobile
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- */
-
-#ifndef _MAX310X_H_
-#define _MAX310X_H_
-
-/*
- * Example board initialization data:
- *
- * static struct max310x_pdata max3107_pdata = {
- *     .uart_flags[0]  = MAX310X_ECHO_SUPRESS | MAX310X_AUTO_DIR_CTRL,
- * };
- *
- * static struct spi_board_info spi_device_max3107[] = {
- *     {
- *             .modalias       = "max3107",
- *             .irq            = IRQ_EINT3,
- *             .bus_num        = 1,
- *             .chip_select    = 1,
- *             .platform_data  = &max3107_pdata,
- *     },
- * };
- */
-
-#define MAX310X_MAX_UARTS      4
-
-/* MAX310X platform data structure */
-struct max310x_pdata {
-       /* Flags global to UART port */
-       const u8                uart_flags[MAX310X_MAX_UARTS];
-#define MAX310X_ECHO_SUPRESS   (0x00000002)    /* Enable echo supress */
-#define MAX310X_AUTO_DIR_CTRL  (0x00000004)    /* Enable Auto direction
-                                                * control (RS-485)
-                                                */
-};
-
-#endif