forked from Minki/linux
TTY/Staging driver updates for 4.16-rc1
Here is the big tty/serial driver update for 4.16-rc1. The usual number of various serial driver fixes and updates to try to get them to work with crazy hardware configurations (seriously, how many different ways are hardware engineers going to come up with to hook up a simple UART?) There is also some serdev bugfixes and updates, as well as a smattering of other small fixes in here. All have been in the linux-next tree for a while, with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWnLyuw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylItQCgncAzYeOJ9IXY/wEnmIJS7sPzeMkAnimmYddW Z5d3SAbe9drdGs6BOr5e =h8ad -----END PGP SIGNATURE----- Merge tag 'tty-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/staging driver updates from Greg KH: "Here is the big tty/serial driver update for 4.16-rc1. The usual number of various serial driver fixes and updates to try to get them to work with crazy hardware configurations (seriously, how many different ways are hardware engineers going to come up with to hook up a simple UART?) There is also some serdev bugfixes and updates, as well as a smattering of other small fixes in here. All have been in the linux-next tree for a while, with no reported issues" * tag 'tty-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (65 commits) tty: serial: exar: Relocate sleep wake-up handling tty: fix data race between tty_init_dev and flush of buf serial: imx: fix endless loop during suspend serial: core: mark port as initialized after successful IRQ change serdev: only match serdev devices serdev: do not generate modaliases for controllers serial: mxs-auart: don't use GPIOF_* with gpiod_get_direction serial: 8250_dw: Revert "Improve clock rate setting" MAINTAINERS: Add myself as designated reviewer for 8250_dw gpio: serial: max310x: Support open-drain configuration for GPIOs serdev: Fix serdev_uevent failure on ACPI enumerated serdev-controllers serial: 8250_ingenic: Parse earlycon options serial: 8250_ingenic: Add support for the JZ4770 SoC serial: core: Make uart_parse_options take const char* argument serial: 8250_of: fix return code when probe function fails to get reset serial: imx: Only wakeup via RTSDEN bit if the system has RTS/CTS serial: 8250_uniphier: fix error return code in uniphier_uart_probe() tty: n_gsm: Allow ADM response in addition to UA for control dlci tty: omap-serial: Fix initial on-boot RTS GPIO level tty: serial: jsm: Add one check against NULL pointer dereference ...
This commit is contained in:
commit
db5933225f
@ -6,10 +6,10 @@ Required properties:
|
||||
- interrupts : Should contain uart interrupt
|
||||
|
||||
Optional properties:
|
||||
- fsl,irda-mode : Indicate the uart supports irda mode
|
||||
- fsl,dte-mode : Indicate the uart works in DTE mode. The uart works
|
||||
in DCE mode by default.
|
||||
- rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt
|
||||
- rs485-rts-delay, rs485-rts-active-low, rs485-rx-during-tx,
|
||||
linux,rs485-enabled-at-boot-time: see rs485.txt
|
||||
|
||||
Please check Documentation/devicetree/bindings/serial/serial.txt
|
||||
for the complete list of generic properties.
|
||||
|
@ -16,7 +16,8 @@ Required properties:
|
||||
Optional properties:
|
||||
- dmas: A list of two dma specifiers, one for each entry in dma-names.
|
||||
- dma-names: should contain "tx" and "rx".
|
||||
- rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt
|
||||
- rs485-rts-delay, rs485-rts-active-low, rs485-rx-during-tx,
|
||||
linux,rs485-enabled-at-boot-time: see rs485.txt
|
||||
|
||||
Note: Optional properties for DMA support. Write them both or both not.
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
* Ingenic SoC UART
|
||||
|
||||
Required properties:
|
||||
- compatible : "ingenic,jz4740-uart", "ingenic,jz4760-uart",
|
||||
"ingenic,jz4775-uart" or "ingenic,jz4780-uart"
|
||||
- compatible : One of:
|
||||
- "ingenic,jz4740-uart",
|
||||
- "ingenic,jz4760-uart",
|
||||
- "ingenic,jz4770-uart",
|
||||
- "ingenic,jz4775-uart",
|
||||
- "ingenic,jz4780-uart".
|
||||
- reg : offset and length of the register set for the device.
|
||||
- interrupts : should contain uart interrupt.
|
||||
- clocks : phandles to the module & baud clocks.
|
||||
|
@ -24,13 +24,27 @@ Optional properties:
|
||||
1 = active low.
|
||||
|
||||
Example:
|
||||
|
||||
/ {
|
||||
clocks {
|
||||
spi_uart_clk: osc_max14830 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <3686400>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
max14830: max14830@0 {
|
||||
compatible = "maxim,max14830";
|
||||
reg = <0>;
|
||||
clocks = <&clk20m>;
|
||||
clocks = <&spi_uart_clk>;
|
||||
clock-names = "osc";
|
||||
interrupt-parent = <&gpio3>;
|
||||
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
@ -1,13 +1,53 @@
|
||||
* Marvell UART : Non standard UART used in some of Marvell EBU SoCs (e.g., Armada-3700)
|
||||
* Marvell UART : Non standard UART used in some of Marvell EBU SoCs
|
||||
e.g., Armada-3700.
|
||||
|
||||
Required properties:
|
||||
- compatible: "marvell,armada-3700-uart"
|
||||
- compatible:
|
||||
- "marvell,armada-3700-uart" for the standard variant of the UART
|
||||
(32 bytes FIFO, no DMA, level interrupts, 8-bit access to the
|
||||
FIFO, baudrate limited to 230400).
|
||||
- "marvell,armada-3700-uart-ext" for the extended variant of the
|
||||
UART (128 bytes FIFO, DMA, front interrupts, 8-bit or 32-bit
|
||||
accesses to the FIFO, baudrate unlimited by the dividers).
|
||||
- reg: offset and length of the register set for the device.
|
||||
- interrupts: device interrupt
|
||||
- clocks: UART reference clock used to derive the baudrate. If no clock
|
||||
is provided (possible only with the "marvell,armada-3700-uart"
|
||||
compatible string for backward compatibility), it will only work
|
||||
if the baudrate was initialized by the bootloader and no baudrate
|
||||
change will then be possible.
|
||||
- interrupts:
|
||||
- Must contain three elements for the standard variant of the IP
|
||||
(marvell,armada-3700-uart): "uart-sum", "uart-tx" and "uart-rx",
|
||||
respectively the UART sum interrupt, the UART TX interrupt and
|
||||
UART RX interrupt. A corresponding interrupt-names property must
|
||||
be defined.
|
||||
- Must contain two elements for the extended variant of the IP
|
||||
(marvell,armada-3700-uart-ext): "uart-tx" and "uart-rx",
|
||||
respectively the UART TX interrupt and the UART RX interrupt. A
|
||||
corresponding interrupts-names property must be defined.
|
||||
- For backward compatibility reasons, a single element interrupts
|
||||
property is also supported for the standard variant of the IP,
|
||||
containing only the UART sum interrupt. This form is deprecated
|
||||
and should no longer be used.
|
||||
|
||||
Example:
|
||||
serial@12000 {
|
||||
uart0: serial@12000 {
|
||||
compatible = "marvell,armada-3700-uart";
|
||||
reg = <0x12000 0x200>;
|
||||
interrupts = <43>;
|
||||
clocks = <&xtalclk>;
|
||||
interrupts =
|
||||
<GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "uart-sum", "uart-tx", "uart-rx";
|
||||
};
|
||||
|
||||
uart1: serial@12200 {
|
||||
compatible = "marvell,armada-3700-uart-ext";
|
||||
reg = <0x12200 0x30>;
|
||||
clocks = <&xtalclk>;
|
||||
interrupts =
|
||||
<GIC_SPI 30 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 31 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "uart-tx", "uart-rx";
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ Optional properties:
|
||||
node and a DMA channel number.
|
||||
- dma-names : "rx" for receive channel, "tx" for transmit channel.
|
||||
- rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt
|
||||
- rs485-rts-active-high: drive RTS high when sending (default is low).
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -12,6 +12,7 @@ Optional properties:
|
||||
* b is the delay between end of data sent and rts signal in milliseconds
|
||||
it corresponds to the delay after sending data and actual release of the line.
|
||||
If this property is not specified, <0 0> is assumed.
|
||||
- rs485-rts-active-low: drive RTS low when sending (default is high).
|
||||
- linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485
|
||||
feature at boot time. It can be disabled later with proper ioctl.
|
||||
- rs485-rx-during-tx: empty property that enables the receiving of data even
|
||||
|
@ -13181,6 +13181,11 @@ S: Supported
|
||||
F: drivers/reset/reset-axs10x.c
|
||||
F: Documentation/devicetree/bindings/reset/snps,axs10x-reset.txt
|
||||
|
||||
SYNOPSYS DESIGNWARE 8250 UART DRIVER
|
||||
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
S: Maintained
|
||||
F: drivers/tty/serial/8250/8250_dw.c
|
||||
|
||||
SYNOPSYS DESIGNWARE APB GPIO DRIVER
|
||||
M: Hoan Tran <hotran@apm.com>
|
||||
L: linux-gpio@vger.kernel.org
|
||||
|
@ -394,10 +394,14 @@ config GOLDFISH_TTY
|
||||
depends on GOLDFISH
|
||||
select SERIAL_CORE
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_EARLYCON
|
||||
help
|
||||
Console and system TTY driver for the Goldfish virtual platform.
|
||||
|
||||
config GOLDFISH_TTY_EARLY_CONSOLE
|
||||
bool
|
||||
default y if GOLDFISH_TTY=y
|
||||
select SERIAL_EARLYCON
|
||||
|
||||
config DA_TTY
|
||||
bool "DA TTY"
|
||||
depends on METAG_DA
|
||||
|
@ -433,6 +433,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE
|
||||
static void gf_early_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
__raw_writel(ch, port->membase);
|
||||
@ -456,6 +457,7 @@ static int __init gf_earlycon_setup(struct earlycon_device *device,
|
||||
}
|
||||
|
||||
OF_EARLYCON_DECLARE(early_gf_tty, "google,goldfish-tty", gf_earlycon_setup);
|
||||
#endif
|
||||
|
||||
static const struct of_device_id goldfish_tty_of_match[] = {
|
||||
{ .compatible = "google,goldfish-tty", },
|
||||
|
@ -219,13 +219,9 @@ static struct isi_port isi_ports[PORT_COUNT];
|
||||
static int WaitTillCardIsFree(unsigned long base)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
unsigned int a = in_atomic(); /* do we run under spinlock? */
|
||||
|
||||
while (!(inw(base + 0xe) & 0x1) && count++ < 100)
|
||||
if (a)
|
||||
mdelay(1);
|
||||
else
|
||||
msleep(1);
|
||||
mdelay(1);
|
||||
|
||||
return !(inw(base + 0xe) & 0x1);
|
||||
}
|
||||
|
@ -1487,8 +1487,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term
|
||||
if (ts->c_iflag & IXANY)
|
||||
xany = 1;
|
||||
|
||||
/* Clear the features we don't support */
|
||||
ts->c_cflag &= ~CMSPAR;
|
||||
MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);
|
||||
baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));
|
||||
if (baud == -1)
|
||||
@ -1781,10 +1779,17 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
|
||||
mode |= MX_STOP1;
|
||||
|
||||
if (termio->c_cflag & PARENB) {
|
||||
if (termio->c_cflag & PARODD)
|
||||
mode |= MX_PARODD;
|
||||
else
|
||||
mode |= MX_PAREVEN;
|
||||
if (termio->c_cflag & PARODD) {
|
||||
if (termio->c_cflag & CMSPAR)
|
||||
mode |= MX_PARMARK;
|
||||
else
|
||||
mode |= MX_PARODD;
|
||||
} else {
|
||||
if (termio->c_cflag & CMSPAR)
|
||||
mode |= MX_PARSPACE;
|
||||
else
|
||||
mode |= MX_PAREVEN;
|
||||
}
|
||||
} else
|
||||
mode |= MX_PARNONE;
|
||||
|
||||
|
@ -301,5 +301,7 @@
|
||||
#define MX_PARNONE 0x00
|
||||
#define MX_PAREVEN 0x40
|
||||
#define MX_PARODD 0xC0
|
||||
#define MX_PARMARK 0xA0
|
||||
#define MX_PARSPACE 0x20
|
||||
|
||||
#endif
|
||||
|
@ -1451,6 +1451,10 @@ static void gsm_dlci_open(struct gsm_dlci *dlci)
|
||||
* in which case an opening port goes back to closed and a closing port
|
||||
* is simply put into closed state (any further frames from the other
|
||||
* end will get a DM response)
|
||||
*
|
||||
* Some control dlci can stay in ADM mode with other dlci working just
|
||||
* fine. In that case we can just keep the control dlci open after the
|
||||
* DLCI_OPENING retries time out.
|
||||
*/
|
||||
|
||||
static void gsm_dlci_t1(struct timer_list *t)
|
||||
@ -1464,8 +1468,15 @@ static void gsm_dlci_t1(struct timer_list *t)
|
||||
if (dlci->retries) {
|
||||
gsm_command(dlci->gsm, dlci->addr, SABM|PF);
|
||||
mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100);
|
||||
} else
|
||||
} else if (!dlci->addr && gsm->control == (DM | PF)) {
|
||||
if (debug & 8)
|
||||
pr_info("DLCI %d opening in ADM mode.\n",
|
||||
dlci->addr);
|
||||
gsm_dlci_open(dlci);
|
||||
} else {
|
||||
gsm_dlci_close(dlci);
|
||||
}
|
||||
|
||||
break;
|
||||
case DLCI_CLOSING:
|
||||
dlci->retries--;
|
||||
@ -1483,8 +1494,8 @@ static void gsm_dlci_t1(struct timer_list *t)
|
||||
* @dlci: DLCI to open
|
||||
*
|
||||
* Commence opening a DLCI from the Linux side. We issue SABM messages
|
||||
* to the modem which should then reply with a UA, at which point we
|
||||
* will move into open state. Opening is done asynchronously with retry
|
||||
* to the modem which should then reply with a UA or ADM, at which point
|
||||
* we will move into open state. Opening is done asynchronously with retry
|
||||
* running off timers and the responses.
|
||||
*/
|
||||
|
||||
@ -2955,7 +2966,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
|
||||
static void gsmtty_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
struct gsm_dlci *dlci = tty->driver_data;
|
||||
struct gsm_mux *gsm;
|
||||
|
||||
if (dlci == NULL)
|
||||
return;
|
||||
@ -2964,7 +2974,6 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
|
||||
mutex_lock(&dlci->mutex);
|
||||
gsm_destroy_network(dlci);
|
||||
mutex_unlock(&dlci->mutex);
|
||||
gsm = dlci->gsm;
|
||||
if (tty_port_close_start(&dlci->port, tty, filp) == 0)
|
||||
return;
|
||||
gsm_dlci_begin_close(dlci);
|
||||
|
@ -19,6 +19,38 @@
|
||||
static bool is_registered;
|
||||
static DEFINE_IDA(ctrl_ida);
|
||||
|
||||
static ssize_t modalias_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
|
||||
if (len != -ENODEV)
|
||||
return len;
|
||||
|
||||
return of_device_modalias(dev, buf, PAGE_SIZE);
|
||||
}
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
static struct attribute *serdev_device_attrs[] = {
|
||||
&dev_attr_modalias.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(serdev_device);
|
||||
|
||||
static int serdev_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* TODO: platform modalias */
|
||||
|
||||
rc = acpi_device_uevent_modalias(dev, env);
|
||||
if (rc != -ENODEV)
|
||||
return rc;
|
||||
|
||||
return of_device_uevent_modalias(dev, env);
|
||||
}
|
||||
|
||||
static void serdev_device_release(struct device *dev)
|
||||
{
|
||||
struct serdev_device *serdev = to_serdev_device(dev);
|
||||
@ -26,9 +58,16 @@ static void serdev_device_release(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct device_type serdev_device_type = {
|
||||
.groups = serdev_device_groups,
|
||||
.uevent = serdev_device_uevent,
|
||||
.release = serdev_device_release,
|
||||
};
|
||||
|
||||
static bool is_serdev_device(const struct device *dev)
|
||||
{
|
||||
return dev->type == &serdev_device_type;
|
||||
}
|
||||
|
||||
static void serdev_ctrl_release(struct device *dev)
|
||||
{
|
||||
struct serdev_controller *ctrl = to_serdev_controller(dev);
|
||||
@ -42,6 +81,9 @@ static const struct device_type serdev_ctrl_type = {
|
||||
|
||||
static int serdev_device_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
if (!is_serdev_device(dev))
|
||||
return 0;
|
||||
|
||||
/* TODO: platform matching */
|
||||
if (acpi_driver_match_device(dev, drv))
|
||||
return 1;
|
||||
@ -49,18 +91,6 @@ static int serdev_device_match(struct device *dev, struct device_driver *drv)
|
||||
return of_driver_match_device(dev, drv);
|
||||
}
|
||||
|
||||
static int serdev_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* TODO: platform modalias */
|
||||
rc = acpi_device_uevent_modalias(dev, env);
|
||||
if (rc != -ENODEV)
|
||||
return rc;
|
||||
|
||||
return of_device_uevent_modalias(dev, env);
|
||||
}
|
||||
|
||||
/**
|
||||
* serdev_device_add() - add a device previously constructed via serdev_device_alloc()
|
||||
* @serdev: serdev_device to be added
|
||||
@ -312,32 +342,11 @@ static int serdev_drv_remove(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t modalias_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
|
||||
if (len != -ENODEV)
|
||||
return len;
|
||||
|
||||
return of_device_modalias(dev, buf, PAGE_SIZE);
|
||||
}
|
||||
DEVICE_ATTR_RO(modalias);
|
||||
|
||||
static struct attribute *serdev_device_attrs[] = {
|
||||
&dev_attr_modalias.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(serdev_device);
|
||||
|
||||
static struct bus_type serdev_bus_type = {
|
||||
.name = "serial",
|
||||
.match = serdev_device_match,
|
||||
.probe = serdev_drv_probe,
|
||||
.remove = serdev_drv_remove,
|
||||
.uevent = serdev_uevent,
|
||||
.dev_groups = serdev_device_groups,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -59,7 +59,8 @@ static void ttyport_write_wakeup(struct tty_port *port)
|
||||
test_bit(SERPORT_ACTIVE, &serport->flags))
|
||||
serdev_controller_write_wakeup(ctrl);
|
||||
|
||||
wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
|
||||
/* Wake up any tty_wait_until_sent() */
|
||||
wake_up_interruptible(&tty->write_wait);
|
||||
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
@ -122,6 +123,8 @@ static int ttyport_open(struct serdev_controller *ctrl)
|
||||
if (ret)
|
||||
goto err_close;
|
||||
|
||||
tty_unlock(serport->tty);
|
||||
|
||||
/* Bring the UART into a known 8 bits no parity hw fc state */
|
||||
ktermios = tty->termios;
|
||||
ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
|
||||
@ -131,11 +134,12 @@ static int ttyport_open(struct serdev_controller *ctrl)
|
||||
ktermios.c_cflag &= ~(CSIZE | PARENB);
|
||||
ktermios.c_cflag |= CS8;
|
||||
ktermios.c_cflag |= CRTSCTS;
|
||||
/* Hangups are not supported so make sure to ignore carrier detect. */
|
||||
ktermios.c_cflag |= CLOCAL;
|
||||
tty_set_termios(tty, &ktermios);
|
||||
|
||||
set_bit(SERPORT_ACTIVE, &serport->flags);
|
||||
|
||||
tty_unlock(serport->tty);
|
||||
return 0;
|
||||
|
||||
err_close:
|
||||
|
@ -252,31 +252,25 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned int baud = tty_termios_baud_rate(termios);
|
||||
unsigned int target_rate, min_rate, max_rate;
|
||||
struct dw8250_data *d = p->private_data;
|
||||
long rate;
|
||||
int i, ret;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(d->clk) || !old)
|
||||
goto out;
|
||||
|
||||
/* Find a clk rate within +/-1.6% of an integer multiple of baudx16 */
|
||||
target_rate = baud * 16;
|
||||
min_rate = target_rate - (target_rate >> 6);
|
||||
max_rate = target_rate + (target_rate >> 6);
|
||||
|
||||
for (i = 1; i <= UART_DIV_MAX; i++) {
|
||||
rate = clk_round_rate(d->clk, i * target_rate);
|
||||
if (rate >= i * min_rate && rate <= i * max_rate)
|
||||
break;
|
||||
}
|
||||
if (i <= UART_DIV_MAX) {
|
||||
clk_disable_unprepare(d->clk);
|
||||
clk_disable_unprepare(d->clk);
|
||||
rate = clk_round_rate(d->clk, baud * 16);
|
||||
if (rate < 0)
|
||||
ret = rate;
|
||||
else if (rate == 0)
|
||||
ret = -ENOENT;
|
||||
else
|
||||
ret = clk_set_rate(d->clk, rate);
|
||||
clk_prepare_enable(d->clk);
|
||||
if (!ret)
|
||||
p->uartclk = rate;
|
||||
}
|
||||
clk_prepare_enable(d->clk);
|
||||
|
||||
if (!ret)
|
||||
p->uartclk = rate;
|
||||
|
||||
out:
|
||||
p->status &= ~UPSTAT_AUTOCTS;
|
||||
@ -515,7 +509,8 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
/* If no clock rate is defined, fail. */
|
||||
if (!p->uartclk) {
|
||||
dev_err(dev, "clock rate not defined\n");
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
data->pclk = devm_clk_get(dev, "apb_pclk");
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358
|
||||
#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358
|
||||
|
||||
#define UART_EXAR_INT0 0x80
|
||||
#define UART_EXAR_8XMODE 0x88 /* 8X sampling rate select */
|
||||
|
||||
#define UART_EXAR_FCTR 0x08 /* Feature Control Register */
|
||||
@ -121,6 +122,7 @@ struct exar8250_board {
|
||||
struct exar8250 {
|
||||
unsigned int nr;
|
||||
struct exar8250_board *board;
|
||||
void __iomem *virt;
|
||||
int line[0];
|
||||
};
|
||||
|
||||
@ -131,12 +133,9 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,
|
||||
const struct exar8250_board *board = priv->board;
|
||||
unsigned int bar = 0;
|
||||
|
||||
if (!pcim_iomap_table(pcidev)[bar] && !pcim_iomap(pcidev, bar, 0))
|
||||
return -ENOMEM;
|
||||
|
||||
port->port.iotype = UPIO_MEM;
|
||||
port->port.mapbase = pci_resource_start(pcidev, bar) + offset;
|
||||
port->port.membase = pcim_iomap_table(pcidev)[bar] + offset;
|
||||
port->port.membase = priv->virt + offset;
|
||||
port->port.regshift = board->reg_shift;
|
||||
|
||||
return 0;
|
||||
@ -420,6 +419,25 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev)
|
||||
port->port.private_data = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* These Exar UARTs have an extra interrupt indicator that could fire for a
|
||||
* few interrupts that are not presented/cleared through IIR. One of which is
|
||||
* a wakeup interrupt when coming out of sleep. These interrupts are only
|
||||
* cleared by reading global INT0 or INT1 registers as interrupts are
|
||||
* associated with channel 0. The INT[3:0] registers _are_ accessible from each
|
||||
* channel's address space, but for the sake of bus efficiency we register a
|
||||
* dedicated handler at the PCI device level to handle them.
|
||||
*/
|
||||
static irqreturn_t exar_misc_handler(int irq, void *data)
|
||||
{
|
||||
struct exar8250 *priv = data;
|
||||
|
||||
/* Clear all PCI interrupts by reading INT0. No effect on IIR */
|
||||
ioread8(priv->virt + UART_EXAR_INT0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int
|
||||
exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
|
||||
{
|
||||
@ -448,6 +466,9 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->board = board;
|
||||
priv->virt = pcim_iomap(pcidev, bar, 0);
|
||||
if (!priv->virt)
|
||||
return -ENOMEM;
|
||||
|
||||
pci_set_master(pcidev);
|
||||
|
||||
@ -461,6 +482,11 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
|
||||
uart.port.irq = pci_irq_vector(pcidev, 0);
|
||||
uart.port.dev = &pcidev->dev;
|
||||
|
||||
rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler,
|
||||
IRQF_SHARED, "exar_uart", priv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < nr_ports && i < maxnr; i++) {
|
||||
rc = board->setup(priv, pcidev, &uart, i);
|
||||
if (rc) {
|
||||
|
@ -91,14 +91,22 @@ static int __init ingenic_early_console_setup(struct earlycon_device *dev,
|
||||
const char *opt)
|
||||
{
|
||||
struct uart_port *port = &dev->port;
|
||||
unsigned int baud, divisor;
|
||||
unsigned int divisor;
|
||||
int baud = 115200;
|
||||
|
||||
if (!dev->port.membase)
|
||||
return -ENODEV;
|
||||
|
||||
if (opt) {
|
||||
unsigned int parity, bits, flow; /* unused for now */
|
||||
|
||||
uart_parse_options(opt, &baud, &parity, &bits, &flow);
|
||||
}
|
||||
|
||||
ingenic_early_console_setup_clock(dev);
|
||||
|
||||
baud = dev->baud ?: 115200;
|
||||
if (dev->baud)
|
||||
baud = dev->baud;
|
||||
divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
|
||||
|
||||
early_out(port, UART_IER, 0);
|
||||
@ -125,6 +133,10 @@ EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart",
|
||||
ingenic_early_console_setup);
|
||||
|
||||
EARLYCON_DECLARE(jz4770_uart, ingenic_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(jz4770_uart, "ingenic,jz4770-uart",
|
||||
ingenic_early_console_setup);
|
||||
|
||||
EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",
|
||||
ingenic_early_console_setup);
|
||||
@ -319,6 +331,7 @@ static const struct ingenic_uart_config jz4780_uart_config = {
|
||||
static const struct of_device_id of_match[] = {
|
||||
{ .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config },
|
||||
{ .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config },
|
||||
{ .compatible = "ingenic,jz4770-uart", .data = &jz4760_uart_config },
|
||||
{ .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config },
|
||||
{ .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config },
|
||||
{ /* sentinel */ }
|
||||
|
@ -136,8 +136,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
||||
}
|
||||
|
||||
info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL);
|
||||
if (IS_ERR(info->rst))
|
||||
if (IS_ERR(info->rst)) {
|
||||
ret = PTR_ERR(info->rst);
|
||||
goto err_dispose;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(info->rst);
|
||||
if (ret)
|
||||
goto err_dispose;
|
||||
|
@ -414,7 +414,7 @@ static void omap_8250_set_termios(struct uart_port *port,
|
||||
/* Up to here it was mostly serial8250_do_set_termios() */
|
||||
|
||||
/*
|
||||
* We enable TRIG_GRANU for RX and TX and additionaly we set
|
||||
* We enable TRIG_GRANU for RX and TX and additionally we set
|
||||
* SCR_TX_EMPTY bit. The result is the following:
|
||||
* - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt.
|
||||
* - less than RX_TRIGGER number of bytes will also cause an interrupt
|
||||
|
@ -441,7 +441,6 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
|
||||
}
|
||||
|
||||
static int serial8250_default_handle_irq(struct uart_port *port);
|
||||
static int exar_handle_irq(struct uart_port *port);
|
||||
|
||||
static void set_io_from_upio(struct uart_port *p)
|
||||
{
|
||||
@ -1883,26 +1882,6 @@ static int serial8250_default_handle_irq(struct uart_port *port)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* These Exar UARTs have an extra interrupt indicator that could
|
||||
* fire for a few unimplemented interrupts. One of which is a
|
||||
* wakeup event when coming out of sleep. Put this here just
|
||||
* to be on the safe side that these interrupts don't go unhandled.
|
||||
*/
|
||||
static int exar_handle_irq(struct uart_port *port)
|
||||
{
|
||||
unsigned int iir = serial_port_in(port, UART_IIR);
|
||||
int ret = 0;
|
||||
|
||||
if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) &&
|
||||
serial_port_in(port, UART_EXAR_INT0) != 0)
|
||||
ret = 1;
|
||||
|
||||
ret |= serial8250_handle_irq(port, iir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Newer 16550 compatible parts such as the SC16C650 & Altera 16550 Soft IP
|
||||
* have a programmable TX threshold that triggers the THRE interrupt in
|
||||
@ -3067,11 +3046,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
|
||||
if (port->type == PORT_UNKNOWN)
|
||||
serial8250_release_std_resource(up);
|
||||
|
||||
/* Fixme: probably not the best place for this */
|
||||
if ((port->type == PORT_XR17V35X) ||
|
||||
(port->type == PORT_XR17D15X))
|
||||
port->handle_irq = exar_handle_irq;
|
||||
|
||||
register_dev_spec_attr_grp(up);
|
||||
up->fcr = uart_config[up->port.type].fcr;
|
||||
}
|
||||
|
@ -250,12 +250,13 @@ static int uniphier_uart_probe(struct platform_device *pdev)
|
||||
up.dl_read = uniphier_serial_dl_read;
|
||||
up.dl_write = uniphier_serial_dl_write;
|
||||
|
||||
priv->line = serial8250_register_8250_port(&up);
|
||||
if (priv->line < 0) {
|
||||
ret = serial8250_register_8250_port(&up);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to register 8250 port\n");
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return ret;
|
||||
}
|
||||
priv->line = ret;
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
config SERIAL_8250
|
||||
tristate "8250/16550 and compatible serial support"
|
||||
depends on !S390
|
||||
select SERIAL_CORE
|
||||
---help---
|
||||
This selects whether you want to include the driver for the standard
|
||||
|
@ -761,24 +761,30 @@ config SERIAL_SH_SCI
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
|
||||
config SERIAL_SH_SCI_NR_UARTS
|
||||
int "Maximum number of SCI(F) serial ports"
|
||||
int "Maximum number of SCI(F) serial ports" if EXPERT
|
||||
depends on SERIAL_SH_SCI
|
||||
default "3" if H8300
|
||||
default "10" if SUPERH
|
||||
default "18" if ARCH_RENESAS
|
||||
default "2"
|
||||
|
||||
config SERIAL_SH_SCI_CONSOLE
|
||||
bool "Support for console on SuperH SCI(F)"
|
||||
bool "Support for console on SuperH SCI(F)" if EXPERT
|
||||
depends on SERIAL_SH_SCI=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
default y
|
||||
|
||||
config SERIAL_SH_SCI_EARLYCON
|
||||
bool "Support for early console on SuperH SCI(F)"
|
||||
bool "Support for early console on SuperH SCI(F)" if EXPERT
|
||||
depends on SERIAL_SH_SCI=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_EARLYCON
|
||||
default ARCH_RENESAS || H8300
|
||||
|
||||
config SERIAL_SH_SCI_DMA
|
||||
bool "DMA support"
|
||||
bool "DMA support" if EXPERT
|
||||
depends on SERIAL_SH_SCI && DMA_ENGINE
|
||||
default ARCH_RENESAS
|
||||
|
||||
config SERIAL_PNX8XXX
|
||||
bool "Enable PNX8XXX SoCs' UART Support"
|
||||
|
@ -314,10 +314,9 @@ static void pl011_write(unsigned int val, const struct uart_amba_port *uap,
|
||||
static int pl011_fifo_to_tty(struct uart_amba_port *uap)
|
||||
{
|
||||
u16 status;
|
||||
unsigned int ch, flag, max_count = 256;
|
||||
int fifotaken = 0;
|
||||
unsigned int ch, flag, fifotaken;
|
||||
|
||||
while (max_count--) {
|
||||
for (fifotaken = 0; fifotaken != 256; fifotaken++) {
|
||||
status = pl011_read(uap, REG_FR);
|
||||
if (status & UART01x_FR_RXFE)
|
||||
break;
|
||||
@ -326,7 +325,6 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
|
||||
ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX;
|
||||
flag = TTY_NORMAL;
|
||||
uap->port.icount.rx++;
|
||||
fifotaken++;
|
||||
|
||||
if (unlikely(ch & UART_DR_ERROR)) {
|
||||
if (ch & UART011_DR_BE) {
|
||||
@ -1482,12 +1480,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
|
||||
struct uart_amba_port *uap = dev_id;
|
||||
unsigned long flags;
|
||||
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
|
||||
u16 imsc;
|
||||
int handled = 0;
|
||||
|
||||
spin_lock_irqsave(&uap->port.lock, flags);
|
||||
imsc = pl011_read(uap, REG_IMSC);
|
||||
status = pl011_read(uap, REG_RIS) & imsc;
|
||||
status = pl011_read(uap, REG_RIS) & uap->im;
|
||||
if (status) {
|
||||
do {
|
||||
check_apply_cts_event_workaround(uap);
|
||||
@ -1511,7 +1507,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
|
||||
if (pass_counter-- == 0)
|
||||
break;
|
||||
|
||||
status = pl011_read(uap, REG_RIS) & imsc;
|
||||
status = pl011_read(uap, REG_RIS) & uap->im;
|
||||
} while (status != 0);
|
||||
handled = 1;
|
||||
}
|
||||
|
@ -2345,7 +2345,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
|
||||
atmel_init_property(atmel_port, pdev);
|
||||
atmel_set_ops(port);
|
||||
|
||||
of_get_rs485_mode(pdev->dev.of_node, &port->rs485);
|
||||
uart_get_rs485_mode(&pdev->dev, &port->rs485);
|
||||
|
||||
port->iotype = UPIO_MEM;
|
||||
port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
|
||||
|
@ -2206,23 +2206,16 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto failed_attach_port;
|
||||
|
||||
of_get_rs485_mode(np, &sport->port.rs485);
|
||||
uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
|
||||
|
||||
if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) {
|
||||
if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX)
|
||||
dev_err(&pdev->dev, "driver doesn't support RX during TX\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
if (sport->port.rs485.delay_rts_before_send ||
|
||||
sport->port.rs485.delay_rts_after_send) {
|
||||
sport->port.rs485.delay_rts_after_send)
|
||||
dev_err(&pdev->dev, "driver doesn't support RTS delays\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
if (sport->port.rs485.flags & SER_RS485_ENABLED) {
|
||||
sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND;
|
||||
writeb(UARTMODEM_TXRTSE, sport->port.membase + UARTMODEM);
|
||||
}
|
||||
lpuart_config_rs485(&sport->port, &sport->port.rs485);
|
||||
|
||||
sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
|
||||
if (!sport->dma_tx_chan)
|
||||
|
@ -703,25 +703,6 @@ out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void imx_disable_rx_int(struct imx_port *sport)
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
/* disable the receiver ready and aging timer interrupts */
|
||||
temp = readl(sport->port.membase + UCR1);
|
||||
temp &= ~(UCR1_RRDYEN);
|
||||
writel(temp, sport->port.membase + UCR1);
|
||||
|
||||
temp = readl(sport->port.membase + UCR2);
|
||||
temp &= ~(UCR2_ATEN);
|
||||
writel(temp, sport->port.membase + UCR2);
|
||||
|
||||
/* disable the rx errors interrupts */
|
||||
temp = readl(sport->port.membase + UCR4);
|
||||
temp &= ~UCR4_OREN;
|
||||
writel(temp, sport->port.membase + UCR4);
|
||||
}
|
||||
|
||||
static void clear_rx_errors(struct imx_port *sport);
|
||||
|
||||
/*
|
||||
@ -1252,18 +1233,21 @@ static int imx_startup(struct uart_port *port)
|
||||
if (sport->dma_is_inited && !sport->dma_is_enabled)
|
||||
imx_enable_dma(sport);
|
||||
|
||||
temp = readl(sport->port.membase + UCR1);
|
||||
temp |= UCR1_RRDYEN | UCR1_UARTEN;
|
||||
temp = readl(sport->port.membase + UCR1) & ~UCR1_RRDYEN;
|
||||
if (!sport->dma_is_enabled)
|
||||
temp |= UCR1_RRDYEN;
|
||||
temp |= UCR1_UARTEN;
|
||||
if (sport->have_rtscts)
|
||||
temp |= UCR1_RTSDEN;
|
||||
|
||||
writel(temp, sport->port.membase + UCR1);
|
||||
|
||||
temp = readl(sport->port.membase + UCR4);
|
||||
temp |= UCR4_OREN;
|
||||
temp = readl(sport->port.membase + UCR4) & ~UCR4_OREN;
|
||||
if (!sport->dma_is_enabled)
|
||||
temp |= UCR4_OREN;
|
||||
writel(temp, sport->port.membase + UCR4);
|
||||
|
||||
temp = readl(sport->port.membase + UCR2);
|
||||
temp = readl(sport->port.membase + UCR2) & ~UCR2_ATEN;
|
||||
temp |= (UCR2_RXEN | UCR2_TXEN);
|
||||
if (!sport->have_rtscts)
|
||||
temp |= UCR2_IRTS;
|
||||
@ -1297,10 +1281,8 @@ static int imx_startup(struct uart_port *port)
|
||||
* In our iMX53 the average delay for the first reception dropped from
|
||||
* approximately 35000 microseconds to 1000 microseconds.
|
||||
*/
|
||||
if (sport->dma_is_enabled) {
|
||||
imx_disable_rx_int(sport);
|
||||
if (sport->dma_is_enabled)
|
||||
start_rx_dma(sport);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
|
||||
@ -2017,8 +1999,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
|
||||
if (of_get_property(np, "rts-gpios", NULL))
|
||||
sport->have_rtsgpio = 1;
|
||||
|
||||
of_get_rs485_mode(np, &sport->port.rs485);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
@ -2080,7 +2060,6 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||
sport->port.fifosize = 32;
|
||||
sport->port.ops = &imx_pops;
|
||||
sport->port.rs485_config = imx_rs485_config;
|
||||
sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND;
|
||||
sport->port.flags = UPF_BOOT_AUTOCONF;
|
||||
timer_setup(&sport->timer, imx_timeout, 0);
|
||||
|
||||
@ -2111,6 +2090,14 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
|
||||
|
||||
if (sport->port.rs485.flags & SER_RS485_ENABLED &&
|
||||
(!sport->have_rtscts || !sport->have_rtsgpio))
|
||||
dev_err(&pdev->dev, "no RTS control, disabling rs485\n");
|
||||
|
||||
imx_rs485_config(&sport->port, &sport->port.rs485);
|
||||
|
||||
/* Disable interrupts before requesting them */
|
||||
reg = readl_relaxed(sport->port.membase + UCR1);
|
||||
reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
|
||||
@ -2232,29 +2219,28 @@ static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
|
||||
unsigned int val;
|
||||
|
||||
val = readl(sport->port.membase + UCR3);
|
||||
if (on)
|
||||
if (on) {
|
||||
writel(USR1_AWAKE, sport->port.membase + USR1);
|
||||
val |= UCR3_AWAKEN;
|
||||
}
|
||||
else
|
||||
val &= ~UCR3_AWAKEN;
|
||||
writel(val, sport->port.membase + UCR3);
|
||||
|
||||
val = readl(sport->port.membase + UCR1);
|
||||
if (on)
|
||||
val |= UCR1_RTSDEN;
|
||||
else
|
||||
val &= ~UCR1_RTSDEN;
|
||||
writel(val, sport->port.membase + UCR1);
|
||||
if (sport->have_rtscts) {
|
||||
val = readl(sport->port.membase + UCR1);
|
||||
if (on)
|
||||
val |= UCR1_RTSDEN;
|
||||
else
|
||||
val &= ~UCR1_RTSDEN;
|
||||
writel(val, sport->port.membase + UCR1);
|
||||
}
|
||||
}
|
||||
|
||||
static int imx_serial_port_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
ret = clk_enable(sport->clk_ipg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
serial_imx_save_context(sport);
|
||||
|
||||
@ -2275,8 +2261,6 @@ static int imx_serial_port_resume_noirq(struct device *dev)
|
||||
|
||||
serial_imx_restore_context(sport);
|
||||
|
||||
clk_disable(sport->clk_ipg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2284,15 +2268,19 @@ static int imx_serial_port_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||
|
||||
/* enable wakeup from i.MX UART */
|
||||
serial_imx_enable_wakeup(sport, true);
|
||||
int ret;
|
||||
|
||||
uart_suspend_port(&imx_reg, &sport->port);
|
||||
disable_irq(sport->port.irq);
|
||||
|
||||
/* Needed to enable clock in suspend_noirq */
|
||||
return clk_prepare(sport->clk_ipg);
|
||||
ret = clk_prepare_enable(sport->clk_ipg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* enable wakeup from i.MX UART */
|
||||
serial_imx_enable_wakeup(sport, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_serial_port_resume(struct device *dev)
|
||||
@ -2306,7 +2294,7 @@ static int imx_serial_port_resume(struct device *dev)
|
||||
uart_resume_port(&imx_reg, &sport->port);
|
||||
enable_irq(sport->port.irq);
|
||||
|
||||
clk_unprepare(sport->clk_ipg);
|
||||
clk_disable_unprepare(sport->clk_ipg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2318,8 +2306,7 @@ static int imx_serial_port_freeze(struct device *dev)
|
||||
|
||||
uart_suspend_port(&imx_reg, &sport->port);
|
||||
|
||||
/* Needed to enable clock in suspend_noirq */
|
||||
return clk_prepare(sport->clk_ipg);
|
||||
return clk_prepare_enable(sport->clk_ipg);
|
||||
}
|
||||
|
||||
static int imx_serial_port_thaw(struct device *dev)
|
||||
@ -2329,7 +2316,7 @@ static int imx_serial_port_thaw(struct device *dev)
|
||||
|
||||
uart_resume_port(&imx_reg, &sport->port);
|
||||
|
||||
clk_unprepare(sport->clk_ipg);
|
||||
clk_disable_unprepare(sport->clk_ipg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -282,9 +282,6 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
|
||||
u16 head;
|
||||
u16 tail;
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
/* cache head and tail of queue */
|
||||
head = ch->ch_r_head & RQUEUEMASK;
|
||||
tail = ch->ch_r_tail & RQUEUEMASK;
|
||||
@ -1175,6 +1172,9 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
|
||||
continue;
|
||||
|
||||
ch = brd->channels[port];
|
||||
if (!ch)
|
||||
continue;
|
||||
|
||||
neo_copy_data_from_uart_to_queue(ch);
|
||||
|
||||
/* Call our tty layer to enforce queue flow control if needed. */
|
||||
|
@ -523,9 +523,6 @@ void jsm_input(struct jsm_channel *ch)
|
||||
|
||||
jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n");
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
port = &ch->uart_port.state->port;
|
||||
tp = port->tty;
|
||||
|
||||
@ -648,11 +645,8 @@ static void jsm_carrier(struct jsm_channel *ch)
|
||||
int phys_carrier = 0;
|
||||
|
||||
jsm_dbg(CARR, &ch->ch_bd->pci_dev, "start\n");
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
bd = ch->ch_bd;
|
||||
|
||||
if (!bd)
|
||||
return;
|
||||
|
||||
|
@ -233,6 +233,7 @@
|
||||
/* Misc definitions */
|
||||
#define MAX310X_FIFO_SIZE (128)
|
||||
#define MAX310x_REV_MASK (0xf8)
|
||||
#define MAX310X_WRITE_BIT 0x80
|
||||
|
||||
/* MAX3107 specific */
|
||||
#define MAX3107_REV_ID (0xa0)
|
||||
@ -593,57 +594,118 @@ static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq,
|
||||
return (int)bestfreq;
|
||||
}
|
||||
|
||||
static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len)
|
||||
{
|
||||
u8 header[] = { (port->iobase + MAX310X_THR_REG) | MAX310X_WRITE_BIT };
|
||||
struct spi_transfer xfer[] = {
|
||||
{
|
||||
.tx_buf = &header,
|
||||
.len = sizeof(header),
|
||||
}, {
|
||||
.tx_buf = txbuf,
|
||||
.len = len,
|
||||
}
|
||||
};
|
||||
spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
|
||||
}
|
||||
|
||||
static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len)
|
||||
{
|
||||
u8 header[] = { port->iobase + MAX310X_RHR_REG };
|
||||
struct spi_transfer xfer[] = {
|
||||
{
|
||||
.tx_buf = &header,
|
||||
.len = sizeof(header),
|
||||
}, {
|
||||
.rx_buf = rxbuf,
|
||||
.len = len,
|
||||
}
|
||||
};
|
||||
spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
|
||||
}
|
||||
|
||||
static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
||||
{
|
||||
unsigned int sts, ch, flag;
|
||||
unsigned int sts, ch, flag, i;
|
||||
u8 buf[MAX310X_FIFO_SIZE];
|
||||
|
||||
if (unlikely(rxlen >= port->fifosize)) {
|
||||
dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n");
|
||||
port->icount.buf_overrun++;
|
||||
/* Ensure sanity of RX level */
|
||||
rxlen = port->fifosize;
|
||||
}
|
||||
if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) {
|
||||
/* We are just reading, happily ignoring any error conditions.
|
||||
* Break condition, parity checking, framing errors -- they
|
||||
* are all ignored. That means that we can do a batch-read.
|
||||
*
|
||||
* There is a small opportunity for race if the RX FIFO
|
||||
* overruns while we're reading the buffer; the datasheets says
|
||||
* that the LSR register applies to the "current" character.
|
||||
* That's also the reason why we cannot do batched reads when
|
||||
* asked to check the individual statuses.
|
||||
* */
|
||||
|
||||
while (rxlen--) {
|
||||
ch = max310x_port_read(port, MAX310X_RHR_REG);
|
||||
sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
||||
max310x_batch_read(port, buf, rxlen);
|
||||
|
||||
sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT |
|
||||
MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT;
|
||||
|
||||
port->icount.rx++;
|
||||
port->icount.rx += rxlen;
|
||||
flag = TTY_NORMAL;
|
||||
sts &= port->read_status_mask;
|
||||
|
||||
if (unlikely(sts)) {
|
||||
if (sts & MAX310X_LSR_RXBRK_BIT) {
|
||||
port->icount.brk++;
|
||||
if (uart_handle_break(port))
|
||||
continue;
|
||||
} else if (sts & MAX310X_LSR_RXPAR_BIT)
|
||||
port->icount.parity++;
|
||||
else if (sts & MAX310X_LSR_FRERR_BIT)
|
||||
port->icount.frame++;
|
||||
else if (sts & MAX310X_LSR_RXOVR_BIT)
|
||||
port->icount.overrun++;
|
||||
|
||||
sts &= port->read_status_mask;
|
||||
if (sts & MAX310X_LSR_RXBRK_BIT)
|
||||
flag = TTY_BREAK;
|
||||
else if (sts & MAX310X_LSR_RXPAR_BIT)
|
||||
flag = TTY_PARITY;
|
||||
else if (sts & MAX310X_LSR_FRERR_BIT)
|
||||
flag = TTY_FRAME;
|
||||
else if (sts & MAX310X_LSR_RXOVR_BIT)
|
||||
flag = TTY_OVERRUN;
|
||||
if (sts & MAX310X_LSR_RXOVR_BIT) {
|
||||
dev_warn_ratelimited(port->dev, "Hardware RX FIFO overrun\n");
|
||||
port->icount.overrun++;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(port, ch))
|
||||
continue;
|
||||
for (i = 0; i < rxlen; ++i) {
|
||||
uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, buf[i], flag);
|
||||
}
|
||||
|
||||
if (sts & port->ignore_status_mask)
|
||||
continue;
|
||||
} else {
|
||||
if (unlikely(rxlen >= port->fifosize)) {
|
||||
dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n");
|
||||
port->icount.buf_overrun++;
|
||||
/* Ensure sanity of RX level */
|
||||
rxlen = port->fifosize;
|
||||
}
|
||||
|
||||
uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag);
|
||||
while (rxlen--) {
|
||||
ch = max310x_port_read(port, MAX310X_RHR_REG);
|
||||
sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
||||
|
||||
sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT |
|
||||
MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT;
|
||||
|
||||
port->icount.rx++;
|
||||
flag = TTY_NORMAL;
|
||||
|
||||
if (unlikely(sts)) {
|
||||
if (sts & MAX310X_LSR_RXBRK_BIT) {
|
||||
port->icount.brk++;
|
||||
if (uart_handle_break(port))
|
||||
continue;
|
||||
} else if (sts & MAX310X_LSR_RXPAR_BIT)
|
||||
port->icount.parity++;
|
||||
else if (sts & MAX310X_LSR_FRERR_BIT)
|
||||
port->icount.frame++;
|
||||
else if (sts & MAX310X_LSR_RXOVR_BIT)
|
||||
port->icount.overrun++;
|
||||
|
||||
sts &= port->read_status_mask;
|
||||
if (sts & MAX310X_LSR_RXBRK_BIT)
|
||||
flag = TTY_BREAK;
|
||||
else if (sts & MAX310X_LSR_RXPAR_BIT)
|
||||
flag = TTY_PARITY;
|
||||
else if (sts & MAX310X_LSR_FRERR_BIT)
|
||||
flag = TTY_FRAME;
|
||||
else if (sts & MAX310X_LSR_RXOVR_BIT)
|
||||
flag = TTY_OVERRUN;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(port, ch))
|
||||
continue;
|
||||
|
||||
if (sts & port->ignore_status_mask)
|
||||
continue;
|
||||
|
||||
uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag);
|
||||
}
|
||||
}
|
||||
|
||||
tty_flip_buffer_push(&port->state->port);
|
||||
@ -652,7 +714,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
||||
static void max310x_handle_tx(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
unsigned int txlen, to_send;
|
||||
unsigned int txlen, to_send, until_end;
|
||||
|
||||
if (unlikely(port->x_char)) {
|
||||
max310x_port_write(port, MAX310X_THR_REG, port->x_char);
|
||||
@ -666,28 +728,43 @@ static void max310x_handle_tx(struct uart_port *port)
|
||||
|
||||
/* Get length of data pending in circular buffer */
|
||||
to_send = uart_circ_chars_pending(xmit);
|
||||
until_end = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
if (likely(to_send)) {
|
||||
/* Limit to size of TX FIFO */
|
||||
txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG);
|
||||
txlen = port->fifosize - txlen;
|
||||
to_send = (to_send > txlen) ? txlen : to_send;
|
||||
|
||||
if (until_end < to_send) {
|
||||
/* It's a circ buffer -- wrap around.
|
||||
* We could do that in one SPI transaction, but meh. */
|
||||
max310x_batch_write(port, xmit->buf + xmit->tail, until_end);
|
||||
max310x_batch_write(port, xmit->buf, to_send - until_end);
|
||||
} else {
|
||||
max310x_batch_write(port, xmit->buf + xmit->tail, to_send);
|
||||
}
|
||||
|
||||
/* Add data to send */
|
||||
port->icount.tx += to_send;
|
||||
while (to_send--) {
|
||||
max310x_port_write(port, MAX310X_THR_REG,
|
||||
xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
}
|
||||
xmit->tail = (xmit->tail + to_send) & (UART_XMIT_SIZE - 1);
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
}
|
||||
|
||||
static void max310x_port_irq(struct max310x_port *s, int portno)
|
||||
static void max310x_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct max310x_one *one = container_of(port, struct max310x_one, port);
|
||||
|
||||
if (!work_pending(&one->tx_work))
|
||||
schedule_work(&one->tx_work);
|
||||
}
|
||||
|
||||
static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno)
|
||||
{
|
||||
struct uart_port *port = &s->p[portno].port;
|
||||
irqreturn_t res = IRQ_NONE;
|
||||
|
||||
do {
|
||||
unsigned int ists, lsr, rxlen;
|
||||
@ -698,6 +775,8 @@ static void max310x_port_irq(struct max310x_port *s, int portno)
|
||||
if (!ists && !rxlen)
|
||||
break;
|
||||
|
||||
res = IRQ_HANDLED;
|
||||
|
||||
if (ists & MAX310X_IRQ_CTS_BIT) {
|
||||
lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
||||
uart_handle_cts_change(port,
|
||||
@ -705,17 +784,16 @@ static void max310x_port_irq(struct max310x_port *s, int portno)
|
||||
}
|
||||
if (rxlen)
|
||||
max310x_handle_rx(port, rxlen);
|
||||
if (ists & MAX310X_IRQ_TXEMPTY_BIT) {
|
||||
mutex_lock(&s->mutex);
|
||||
max310x_handle_tx(port);
|
||||
mutex_unlock(&s->mutex);
|
||||
}
|
||||
if (ists & MAX310X_IRQ_TXEMPTY_BIT)
|
||||
max310x_start_tx(port);
|
||||
} while (1);
|
||||
return res;
|
||||
}
|
||||
|
||||
static irqreturn_t max310x_ist(int irq, void *dev_id)
|
||||
{
|
||||
struct max310x_port *s = (struct max310x_port *)dev_id;
|
||||
bool handled = false;
|
||||
|
||||
if (s->devtype->nr > 1) {
|
||||
do {
|
||||
@ -726,12 +804,15 @@ static irqreturn_t max310x_ist(int irq, void *dev_id)
|
||||
val = ((1 << s->devtype->nr) - 1) & ~val;
|
||||
if (!val)
|
||||
break;
|
||||
max310x_port_irq(s, fls(val) - 1);
|
||||
if (max310x_port_irq(s, fls(val) - 1) == IRQ_HANDLED)
|
||||
handled = true;
|
||||
} while (1);
|
||||
} else
|
||||
max310x_port_irq(s, 0);
|
||||
} else {
|
||||
if (max310x_port_irq(s, 0) == IRQ_HANDLED)
|
||||
handled = true;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static void max310x_wq_proc(struct work_struct *ws)
|
||||
@ -744,14 +825,6 @@ static void max310x_wq_proc(struct work_struct *ws)
|
||||
mutex_unlock(&s->mutex);
|
||||
}
|
||||
|
||||
static void max310x_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct max310x_one *one = container_of(port, struct max310x_one, port);
|
||||
|
||||
if (!work_pending(&one->tx_work))
|
||||
schedule_work(&one->tx_work);
|
||||
}
|
||||
|
||||
static unsigned int max310x_tx_empty(struct uart_port *port)
|
||||
{
|
||||
unsigned int lvl, sts;
|
||||
@ -1086,10 +1159,31 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned long config)
|
||||
{
|
||||
struct max310x_port *s = gpiochip_get_data(chip);
|
||||
struct uart_port *port = &s->p[offset / 4].port;
|
||||
|
||||
switch (pinconf_to_config_param(config)) {
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
max310x_port_update(port, MAX310X_GPIOCFG_REG,
|
||||
1 << ((offset % 4) + 4),
|
||||
1 << ((offset % 4) + 4));
|
||||
return 0;
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
max310x_port_update(port, MAX310X_GPIOCFG_REG,
|
||||
1 << ((offset % 4) + 4), 0);
|
||||
return 0;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||
struct regmap *regmap, int irq, unsigned long flags)
|
||||
struct regmap *regmap, int irq)
|
||||
{
|
||||
int i, ret, fmin, fmax, freq, uartclk;
|
||||
struct clk *clk_osc, *clk_xtal;
|
||||
@ -1169,23 +1263,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||
uartclk = max310x_set_ref_clk(s, freq, xtal);
|
||||
dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
/* Setup GPIO cotroller */
|
||||
s->gpio.owner = THIS_MODULE;
|
||||
s->gpio.parent = dev;
|
||||
s->gpio.label = dev_name(dev);
|
||||
s->gpio.direction_input = max310x_gpio_direction_input;
|
||||
s->gpio.get = max310x_gpio_get;
|
||||
s->gpio.direction_output= max310x_gpio_direction_output;
|
||||
s->gpio.set = max310x_gpio_set;
|
||||
s->gpio.base = -1;
|
||||
s->gpio.ngpio = devtype->nr * 4;
|
||||
s->gpio.can_sleep = 1;
|
||||
ret = devm_gpiochip_add_data(dev, &s->gpio, s);
|
||||
if (ret)
|
||||
goto out_clk;
|
||||
#endif
|
||||
|
||||
mutex_init(&s->mutex);
|
||||
|
||||
for (i = 0; i < devtype->nr; i++) {
|
||||
@ -1237,9 +1314,27 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||
devtype->power(&s->p[i].port, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
/* Setup GPIO cotroller */
|
||||
s->gpio.owner = THIS_MODULE;
|
||||
s->gpio.parent = dev;
|
||||
s->gpio.label = dev_name(dev);
|
||||
s->gpio.direction_input = max310x_gpio_direction_input;
|
||||
s->gpio.get = max310x_gpio_get;
|
||||
s->gpio.direction_output= max310x_gpio_direction_output;
|
||||
s->gpio.set = max310x_gpio_set;
|
||||
s->gpio.set_config = max310x_gpio_set_config;
|
||||
s->gpio.base = -1;
|
||||
s->gpio.ngpio = devtype->nr * 4;
|
||||
s->gpio.can_sleep = 1;
|
||||
ret = devm_gpiochip_add_data(dev, &s->gpio, s);
|
||||
if (ret)
|
||||
goto out_uart;
|
||||
#endif
|
||||
|
||||
/* Setup interrupt */
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
|
||||
IRQF_ONESHOT | flags, dev_name(dev), s);
|
||||
IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), s);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
@ -1293,7 +1388,7 @@ MODULE_DEVICE_TABLE(of, max310x_dt_ids);
|
||||
static struct regmap_config regcfg = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.write_flag_mask = 0x80,
|
||||
.write_flag_mask = MAX310X_WRITE_BIT,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.writeable_reg = max310x_reg_writeable,
|
||||
.volatile_reg = max310x_reg_volatile,
|
||||
@ -1304,7 +1399,6 @@ static struct regmap_config regcfg = {
|
||||
static int max310x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct max310x_devtype *devtype;
|
||||
unsigned long flags = 0;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
@ -1327,11 +1421,10 @@ static int max310x_spi_probe(struct spi_device *spi)
|
||||
devtype = (struct max310x_devtype *)id_entry->driver_data;
|
||||
}
|
||||
|
||||
flags = IRQF_TRIGGER_FALLING;
|
||||
regcfg.max_register = devtype->nr * 0x20 - 1;
|
||||
regmap = devm_regmap_init_spi(spi, ®cfg);
|
||||
|
||||
return max310x_probe(&spi->dev, devtype, regmap, spi->irq, flags);
|
||||
return max310x_probe(&spi->dev, devtype, regmap, spi->irq);
|
||||
}
|
||||
|
||||
static int max310x_spi_remove(struct spi_device *spi)
|
||||
|
@ -34,9 +34,15 @@
|
||||
/* AML_UART_CONTROL bits */
|
||||
#define AML_UART_TX_EN BIT(12)
|
||||
#define AML_UART_RX_EN BIT(13)
|
||||
#define AML_UART_TWO_WIRE_EN BIT(15)
|
||||
#define AML_UART_STOP_BIT_LEN_MASK (0x03 << 16)
|
||||
#define AML_UART_STOP_BIT_1SB (0x00 << 16)
|
||||
#define AML_UART_STOP_BIT_2SB (0x01 << 16)
|
||||
#define AML_UART_PARITY_TYPE BIT(18)
|
||||
#define AML_UART_PARITY_EN BIT(19)
|
||||
#define AML_UART_TX_RST BIT(22)
|
||||
#define AML_UART_RX_RST BIT(23)
|
||||
#define AML_UART_CLR_ERR BIT(24)
|
||||
#define AML_UART_CLEAR_ERR BIT(24)
|
||||
#define AML_UART_RX_INT_EN BIT(27)
|
||||
#define AML_UART_TX_INT_EN BIT(28)
|
||||
#define AML_UART_DATA_LEN_MASK (0x03 << 20)
|
||||
@ -57,15 +63,6 @@
|
||||
AML_UART_FRAME_ERR | \
|
||||
AML_UART_TX_FIFO_WERR)
|
||||
|
||||
/* AML_UART_CONTROL bits */
|
||||
#define AML_UART_TWO_WIRE_EN BIT(15)
|
||||
#define AML_UART_PARITY_TYPE BIT(18)
|
||||
#define AML_UART_PARITY_EN BIT(19)
|
||||
#define AML_UART_CLEAR_ERR BIT(24)
|
||||
#define AML_UART_STOP_BIN_LEN_MASK (0x03 << 16)
|
||||
#define AML_UART_STOP_BIN_1SB (0x00 << 16)
|
||||
#define AML_UART_STOP_BIN_2SB (0x01 << 16)
|
||||
|
||||
/* AML_UART_MISC bits */
|
||||
#define AML_UART_XMIT_IRQ(c) (((c) & 0xff) << 8)
|
||||
#define AML_UART_RECV_IRQ(c) ((c) & 0xff)
|
||||
@ -263,10 +260,10 @@ static void meson_uart_reset(struct uart_port *port)
|
||||
u32 val;
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
|
||||
val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR);
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
|
||||
val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
|
||||
val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR);
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
}
|
||||
|
||||
@ -276,9 +273,9 @@ static int meson_uart_startup(struct uart_port *port)
|
||||
int ret = 0;
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val |= AML_UART_CLR_ERR;
|
||||
val |= AML_UART_CLEAR_ERR;
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
val &= ~AML_UART_CLR_ERR;
|
||||
val &= ~AML_UART_CLEAR_ERR;
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
|
||||
val |= (AML_UART_RX_EN | AML_UART_TX_EN);
|
||||
@ -354,11 +351,11 @@ static void meson_uart_set_termios(struct uart_port *port,
|
||||
else
|
||||
val &= ~AML_UART_PARITY_TYPE;
|
||||
|
||||
val &= ~AML_UART_STOP_BIN_LEN_MASK;
|
||||
val &= ~AML_UART_STOP_BIT_LEN_MASK;
|
||||
if (cflags & CSTOPB)
|
||||
val |= AML_UART_STOP_BIN_2SB;
|
||||
val |= AML_UART_STOP_BIT_2SB;
|
||||
else
|
||||
val |= AML_UART_STOP_BIN_1SB;
|
||||
val |= AML_UART_STOP_BIT_1SB;
|
||||
|
||||
if (cflags & CRTSCTS)
|
||||
val &= ~AML_UART_TWO_WIRE_EN;
|
||||
|
@ -40,7 +40,6 @@
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/irq.h>
|
||||
@ -1597,7 +1596,7 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
|
||||
|
||||
for (i = 0; i < UART_GPIO_MAX; i++) {
|
||||
gpiod = mctrl_gpio_to_gpiod(s->gpios, i);
|
||||
if (gpiod && (gpiod_get_direction(gpiod) == GPIOF_DIR_IN))
|
||||
if (gpiod && (gpiod_get_direction(gpiod) == 1))
|
||||
s->gpio_irq[i] = gpiod_to_irq(gpiod);
|
||||
else
|
||||
s->gpio_irq[i] = -EINVAL;
|
||||
@ -1721,7 +1720,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
|
||||
|
||||
ret = uart_add_one_port(&auart_driver, &s->port);
|
||||
if (ret)
|
||||
goto out_free_gpio_irq;
|
||||
goto out_disable_clks_free_qpio_irq;
|
||||
|
||||
/* ASM9260 don't have version reg */
|
||||
if (is_asm9260_auart(s)) {
|
||||
@ -1735,7 +1734,11 @@ static int mxs_auart_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_gpio_irq:
|
||||
out_disable_clks_free_qpio_irq:
|
||||
if (s->clk)
|
||||
clk_disable_unprepare(s->clk_ahb);
|
||||
if (s->clk_ahb)
|
||||
clk_disable_unprepare(s->clk_ahb);
|
||||
mxs_auart_free_gpio_irq(s);
|
||||
auart_port[pdev->id] = NULL;
|
||||
return ret;
|
||||
|
@ -1602,7 +1602,6 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct serial_rs485 *rs485conf = &up->port.rs485;
|
||||
enum of_gpio_flags flags;
|
||||
int ret;
|
||||
|
||||
rs485conf->flags = 0;
|
||||
@ -1611,19 +1610,24 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
|
||||
if (!np)
|
||||
return 0;
|
||||
|
||||
if (of_property_read_bool(np, "rs485-rts-active-high"))
|
||||
uart_get_rs485_mode(up->dev, rs485conf);
|
||||
|
||||
if (of_property_read_bool(np, "rs485-rts-active-high")) {
|
||||
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
|
||||
else
|
||||
rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
} else {
|
||||
rs485conf->flags &= ~SER_RS485_RTS_ON_SEND;
|
||||
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
|
||||
/* check for tx enable gpio */
|
||||
up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags);
|
||||
up->rts_gpio = of_get_named_gpio(np, "rts-gpio", 0);
|
||||
if (gpio_is_valid(up->rts_gpio)) {
|
||||
ret = devm_gpio_request(up->dev, up->rts_gpio, "omap-serial");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = gpio_direction_output(up->rts_gpio,
|
||||
flags & SER_RS485_RTS_AFTER_SEND);
|
||||
ret = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ? 1 : 0;
|
||||
ret = gpio_direction_output(up->rts_gpio, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (up->rts_gpio == -EPROBE_DEFER) {
|
||||
@ -1632,8 +1636,6 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
|
||||
up->rts_gpio = -EINVAL;
|
||||
}
|
||||
|
||||
of_get_rs485_mode(np, rs485conf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -974,6 +974,8 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
|
||||
}
|
||||
} else {
|
||||
retval = uart_startup(tty, state, 1);
|
||||
if (retval == 0)
|
||||
tty_port_set_initialized(port, true);
|
||||
if (retval > 0)
|
||||
retval = 0;
|
||||
}
|
||||
@ -1955,9 +1957,10 @@ EXPORT_SYMBOL_GPL(uart_parse_earlycon);
|
||||
* eg: 115200n8r
|
||||
*/
|
||||
void
|
||||
uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
|
||||
uart_parse_options(const char *options, int *baud, int *parity,
|
||||
int *bits, int *flow)
|
||||
{
|
||||
char *s = options;
|
||||
const char *s = options;
|
||||
|
||||
*baud = simple_strtoul(s, NULL, 10);
|
||||
while (*s >= '0' && *s <= '9')
|
||||
@ -3013,19 +3016,20 @@ EXPORT_SYMBOL(uart_add_one_port);
|
||||
EXPORT_SYMBOL(uart_remove_one_port);
|
||||
|
||||
/**
|
||||
* of_get_rs485_mode() - Implement parsing rs485 properties
|
||||
* @np: uart node
|
||||
* uart_get_rs485_mode() - retrieve rs485 properties for given uart
|
||||
* @dev: uart device
|
||||
* @rs485conf: output parameter
|
||||
*
|
||||
* This function implements the device tree binding described in
|
||||
* Documentation/devicetree/bindings/serial/rs485.txt.
|
||||
*/
|
||||
void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf)
|
||||
void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf)
|
||||
{
|
||||
u32 rs485_delay[2];
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_u32_array(np, "rs485-rts-delay", rs485_delay, 2);
|
||||
ret = device_property_read_u32_array(dev, "rs485-rts-delay",
|
||||
rs485_delay, 2);
|
||||
if (!ret) {
|
||||
rs485conf->delay_rts_before_send = rs485_delay[0];
|
||||
rs485conf->delay_rts_after_send = rs485_delay[1];
|
||||
@ -3035,18 +3039,25 @@ void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf)
|
||||
}
|
||||
|
||||
/*
|
||||
* clear full-duplex and enabled flags to get to a defined state with
|
||||
* the two following properties.
|
||||
* Clear full-duplex and enabled flags, set RTS polarity to active high
|
||||
* to get to a defined state with the following properties:
|
||||
*/
|
||||
rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED);
|
||||
rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED |
|
||||
SER_RS485_RTS_AFTER_SEND);
|
||||
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
|
||||
|
||||
if (of_property_read_bool(np, "rs485-rx-during-tx"))
|
||||
if (device_property_read_bool(dev, "rs485-rx-during-tx"))
|
||||
rs485conf->flags |= SER_RS485_RX_DURING_TX;
|
||||
|
||||
if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time"))
|
||||
if (device_property_read_bool(dev, "linux,rs485-enabled-at-boot-time"))
|
||||
rs485conf->flags |= SER_RS485_ENABLED;
|
||||
|
||||
if (device_property_read_bool(dev, "rs485-rts-active-low")) {
|
||||
rs485conf->flags &= ~SER_RS485_RTS_ON_SEND;
|
||||
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_get_rs485_mode);
|
||||
EXPORT_SYMBOL_GPL(uart_get_rs485_mode);
|
||||
|
||||
MODULE_DESCRIPTION("Serial driver core");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -236,7 +236,7 @@ struct stm32_usart_info stm32h7_info = {
|
||||
#define USART_ICR_CMCF BIT(17) /* F7 */
|
||||
#define USART_ICR_WUCF BIT(20) /* H7 */
|
||||
|
||||
#define STM32_SERIAL_NAME "ttyS"
|
||||
#define STM32_SERIAL_NAME "ttySTM"
|
||||
#define STM32_MAX_PORTS 8
|
||||
|
||||
#define RX_BUF_L 200 /* dma rx buffer length */
|
||||
|
@ -1323,6 +1323,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
|
||||
"%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",
|
||||
__func__, tty->driver->name);
|
||||
|
||||
retval = tty_ldisc_lock(tty, 5 * HZ);
|
||||
if (retval)
|
||||
goto err_release_lock;
|
||||
tty->port->itty = tty;
|
||||
|
||||
/*
|
||||
@ -1333,6 +1336,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
|
||||
retval = tty_ldisc_setup(tty, tty->link);
|
||||
if (retval)
|
||||
goto err_release_tty;
|
||||
tty_ldisc_unlock(tty);
|
||||
/* Return the tty locked so that it cannot vanish under the caller */
|
||||
return tty;
|
||||
|
||||
@ -1345,9 +1349,11 @@ err_module_put:
|
||||
|
||||
/* call the tty release_tty routine to clean out this slot */
|
||||
err_release_tty:
|
||||
tty_unlock(tty);
|
||||
tty_ldisc_unlock(tty);
|
||||
tty_info_ratelimited(tty, "ldisc open failed (%d), clearing slot %d\n",
|
||||
retval, idx);
|
||||
err_release_lock:
|
||||
tty_unlock(tty);
|
||||
release_tty(tty, idx);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
@ -1476,6 +1482,8 @@ static void release_tty(struct tty_struct *tty, int idx)
|
||||
if (tty->link)
|
||||
tty->link->port->itty = NULL;
|
||||
tty_buffer_cancel_work(tty->port);
|
||||
if (tty->link)
|
||||
tty_buffer_cancel_work(tty->link->port);
|
||||
|
||||
tty_kref_put(tty->link);
|
||||
tty_kref_put(tty);
|
||||
|
@ -337,7 +337,7 @@ static inline void __tty_ldisc_unlock(struct tty_struct *tty)
|
||||
ldsem_up_write(&tty->ldisc_sem);
|
||||
}
|
||||
|
||||
static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)
|
||||
int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -348,7 +348,7 @@ static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tty_ldisc_unlock(struct tty_struct *tty)
|
||||
void tty_ldisc_unlock(struct tty_struct *tty)
|
||||
{
|
||||
clear_bit(TTY_LDISC_HALTED, &tty->flags);
|
||||
__tty_ldisc_unlock(tty);
|
||||
|
@ -186,11 +186,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
|
||||
}
|
||||
|
||||
if (ps > pe) /* make sel_start <= sel_end */
|
||||
{
|
||||
int tmp = ps;
|
||||
ps = pe;
|
||||
pe = tmp;
|
||||
}
|
||||
swap(ps, pe);
|
||||
|
||||
if (sel_cons != vc_cons[fg_console].d) {
|
||||
clear_selection();
|
||||
|
@ -27,8 +27,10 @@ struct serdev_device;
|
||||
|
||||
/**
|
||||
* struct serdev_device_ops - Callback operations for a serdev device
|
||||
* @receive_buf: Function called with data received from device.
|
||||
* @write_wakeup: Function called when ready to transmit more data.
|
||||
* @receive_buf: Function called with data received from device;
|
||||
* returns number of bytes accepted; may sleep.
|
||||
* @write_wakeup: Function called when ready to transmit more data; must
|
||||
* not sleep.
|
||||
*/
|
||||
struct serdev_device_ops {
|
||||
int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t);
|
||||
|
@ -387,7 +387,7 @@ struct uart_port *uart_get_console(struct uart_port *ports, int nr,
|
||||
struct console *c);
|
||||
int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr,
|
||||
char **options);
|
||||
void uart_parse_options(char *options, int *baud, int *parity, int *bits,
|
||||
void uart_parse_options(const char *options, int *baud, int *parity, int *bits,
|
||||
int *flow);
|
||||
int uart_set_options(struct uart_port *port, struct console *co, int baud,
|
||||
int parity, int bits, int flow);
|
||||
@ -501,9 +501,5 @@ static inline int uart_handle_break(struct uart_port *port)
|
||||
(cflag) & CRTSCTS || \
|
||||
!((cflag) & CLOCAL))
|
||||
|
||||
/*
|
||||
* Common device tree parsing helpers
|
||||
*/
|
||||
void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf);
|
||||
|
||||
void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf);
|
||||
#endif /* LINUX_SERIAL_CORE_H */
|
||||
|
@ -405,6 +405,8 @@ extern const char *tty_name(const struct tty_struct *tty);
|
||||
extern struct tty_struct *tty_kopen(dev_t device);
|
||||
extern void tty_kclose(struct tty_struct *tty);
|
||||
extern int tty_dev_name_to_number(const char *name, dev_t *number);
|
||||
extern int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
|
||||
extern void tty_ldisc_unlock(struct tty_struct *tty);
|
||||
#else
|
||||
static inline void tty_kref_put(struct tty_struct *tty)
|
||||
{ }
|
||||
|
Loading…
Reference in New Issue
Block a user