serial: max310x: Add support for RS-485 mode
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>
This commit is contained in:
parent
0fbae8874e
commit
55367c620a
|
@ -26,8 +26,6 @@
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
#include <linux/platform_data/max310x.h>
|
|
||||||
|
|
||||||
#define MAX310X_NAME "max310x"
|
#define MAX310X_NAME "max310x"
|
||||||
#define MAX310X_MAJOR 204
|
#define MAX310X_MAJOR 204
|
||||||
#define MAX310X_MINOR 209
|
#define MAX310X_MINOR 209
|
||||||
|
@ -293,7 +291,6 @@ struct max310x_port {
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct max310x_pdata *pdata;
|
|
||||||
#ifdef CONFIG_GPIOLIB
|
#ifdef CONFIG_GPIOLIB
|
||||||
struct gpio_chip gpio;
|
struct gpio_chip gpio;
|
||||||
#endif
|
#endif
|
||||||
|
@ -898,26 +895,70 @@ static void max310x_set_termios(struct uart_port *port,
|
||||||
uart_update_timeout(port, termios->c_cflag, baud);
|
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)
|
static int max310x_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned int val, line = port->line;
|
|
||||||
struct max310x_port *s = dev_get_drvdata(port->dev);
|
struct max310x_port *s = dev_get_drvdata(port->dev);
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
s->devtype->power(port, 1);
|
s->devtype->power(port, 1);
|
||||||
|
|
||||||
/* Configure MODE1 register */
|
/* Configure MODE1 register */
|
||||||
max310x_port_update(port, MAX310X_MODE1_REG,
|
max310x_port_update(port, MAX310X_MODE1_REG,
|
||||||
MAX310X_MODE1_TRNSCVCTRL_BIT,
|
MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
|
||||||
(s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL)
|
|
||||||
? MAX310X_MODE1_TRNSCVCTRL_BIT : 0);
|
|
||||||
|
|
||||||
/* Configure MODE2 register */
|
/* Configure MODE2 register & Reset FIFOs*/
|
||||||
val = MAX310X_MODE2_RXEMPTINV_BIT;
|
val = MAX310X_MODE2_RXEMPTINV_BIT | MAX310X_MODE2_FIFORST_BIT;
|
||||||
if (s->pdata->uart_flags[line] & MAX310X_ECHO_SUPRESS)
|
|
||||||
val |= MAX310X_MODE2_ECHOSUPR_BIT;
|
|
||||||
|
|
||||||
/* Reset FIFOs */
|
|
||||||
val |= MAX310X_MODE2_FIFORST_BIT;
|
|
||||||
max310x_port_write(port, MAX310X_MODE2_REG, val);
|
max310x_port_write(port, MAX310X_MODE2_REG, val);
|
||||||
max310x_port_update(port, MAX310X_MODE2_REG,
|
max310x_port_update(port, MAX310X_MODE2_REG,
|
||||||
MAX310X_MODE2_FIFORST_BIT, 0);
|
MAX310X_MODE2_FIFORST_BIT, 0);
|
||||||
|
@ -998,6 +1039,7 @@ static const struct uart_ops max310x_ops = {
|
||||||
.release_port = max310x_null_void,
|
.release_port = max310x_null_void,
|
||||||
.config_port = max310x_config_port,
|
.config_port = max310x_config_port,
|
||||||
.verify_port = max310x_verify_port,
|
.verify_port = max310x_verify_port,
|
||||||
|
.ioctl = max310x_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __maybe_unused max310x_suspend(struct device *dev)
|
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,
|
static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||||
struct regmap *regmap, int irq)
|
struct regmap *regmap, int irq)
|
||||||
{
|
{
|
||||||
struct max310x_pdata *pdata = dev_get_platdata(dev);
|
|
||||||
int i, ret, fmin, fmax, freq, uartclk;
|
int i, ret, fmin, fmax, freq, uartclk;
|
||||||
struct clk *clk_osc, *clk_xtal;
|
struct clk *clk_osc, *clk_xtal;
|
||||||
struct max310x_port *s;
|
struct max310x_port *s;
|
||||||
|
@ -1086,11 +1127,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||||
if (IS_ERR(regmap))
|
if (IS_ERR(regmap))
|
||||||
return PTR_ERR(regmap);
|
return PTR_ERR(regmap);
|
||||||
|
|
||||||
if (!pdata) {
|
|
||||||
dev_err(dev, "No platform data supplied\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Alloc port structure */
|
/* Alloc port structure */
|
||||||
s = devm_kzalloc(dev, sizeof(*s) +
|
s = devm_kzalloc(dev, sizeof(*s) +
|
||||||
sizeof(struct max310x_one) * devtype->nr, GFP_KERNEL);
|
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;
|
goto out_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->pdata = pdata;
|
|
||||||
s->regmap = regmap;
|
s->regmap = regmap;
|
||||||
s->devtype = devtype;
|
s->devtype = devtype;
|
||||||
dev_set_drvdata(dev, s);
|
dev_set_drvdata(dev, s);
|
||||||
|
|
|
@ -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
|
|
Loading…
Reference in New Issue