mirror of
https://github.com/t2linux/kernel.git
synced 2026-04-30 13:48:59 -07:00
Merge tag 'tty-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty / serial driver updates from Greg KH:
"Here is the "large" TTY and Serial driver update for 5.3-rc1.
It's in the negative number of lines overall as we removed an obsolete
serial driver that was causing problems for some people who were
trying to clean up some apis (the mpsc.c driver, which only worked for
some pre-production hardware that no one has anymore.)
Other than that, lots of tiny changes, cleaning up small things along
with some platform-specific serial driver updates.
All of these have been in linux-next for a while now with no reported
issues"
* tag 'tty-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (68 commits)
tty: serial: fsl_lpuart: add imx8qxp support
serial: imx: set_termios(): preserve RTS state
serial: imx: set_termios(): clarify RTS/CTS bits calculation
serial: imx: set_termios(): factor-out 'ucr2' initial value
serial: sh-sci: Terminate TX DMA during buffer flushing
serial: sh-sci: Fix TX DMA buffer flushing and workqueue races
serial: mpsc: Remove obsolete MPSC driver
serial: 8250: 8250_core: Fix missing unlock on error in serial8250_register_8250_port()
serial: stm32: add RX and TX FIFO flush
serial: stm32: add support of RX FIFO threshold
serial: stm32: add support of TX FIFO threshold
serial: stm32: update PIO transmission
serial: stm32: add support of timeout interrupt for RX
Revert "serial: 8250: Don't service RX FIFO if interrupts are disabled"
tty/serial/8250: use mctrl_gpio helpers
serial: mctrl_gpio: Check if GPIO property exisits before requesting it
serial: 8250: pericom_do_set_divisor can be static
tty: serial_core: Set port active bit in uart_port_activate
serial: 8250: Add MSR/MCR TIOCM conversion wrapper functions
serial: 8250: factor out serial8250_{set,clear}_THRI() helpers
...
This commit is contained in:
@@ -2693,8 +2693,8 @@
|
||||
41 = /dev/ttySMX0 Motorola i.MX - port 0
|
||||
42 = /dev/ttySMX1 Motorola i.MX - port 1
|
||||
43 = /dev/ttySMX2 Motorola i.MX - port 2
|
||||
44 = /dev/ttyMM0 Marvell MPSC - port 0
|
||||
45 = /dev/ttyMM1 Marvell MPSC - port 1
|
||||
44 = /dev/ttyMM0 Marvell MPSC - port 0 (obsolete unused)
|
||||
45 = /dev/ttyMM1 Marvell MPSC - port 1 (obsolete unused)
|
||||
46 = /dev/ttyCPM0 PPC CPM (SCC or SMC) - port 0
|
||||
...
|
||||
47 = /dev/ttyCPM5 PPC CPM (SCC or SMC) - port 5
|
||||
|
||||
@@ -53,6 +53,9 @@ Optional properties:
|
||||
programmable TX FIFO thresholds.
|
||||
- resets : phandle + reset specifier pairs
|
||||
- overrun-throttle-ms : how long to pause uart rx when input overrun is encountered.
|
||||
- {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD
|
||||
line respectively. It will use specified GPIO instead of the peripheral
|
||||
function pin for the UART feature. If unsure, don't specify this property.
|
||||
|
||||
Note:
|
||||
* fsl,ns16550:
|
||||
@@ -74,3 +77,19 @@ Example:
|
||||
interrupts = <10>;
|
||||
reg-shift = <2>;
|
||||
};
|
||||
|
||||
Example for OMAP UART using GPIO-based modem control signals:
|
||||
|
||||
uart4: serial@49042000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
reg = <0x49042000 0x400>;
|
||||
interrupts = <80>;
|
||||
ti,hwmods = "uart4";
|
||||
clock-frequency = <48000000>;
|
||||
cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>;
|
||||
rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
|
||||
dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
|
||||
dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
|
||||
dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
|
||||
rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
@@ -324,8 +324,6 @@ static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
|
||||
|
||||
/*
|
||||
* This routine will shutdown a serial port; interrupts are disabled, and
|
||||
* DTR is dropped if the hangup on close termio flag is on.
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#define NR_CHANNELS 8
|
||||
#define IPOCTAL_MAX_BOARDS 16
|
||||
#define MAX_DEVICES (NR_CHANNELS * IPOCTAL_MAX_BOARDS)
|
||||
#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
|
||||
|
||||
/**
|
||||
* struct ipoctal_stats -- Stats since last reset
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#include "../serial_mctrl_gpio.h"
|
||||
|
||||
struct uart_8250_dma {
|
||||
int (*tx_dma)(struct uart_8250_port *p);
|
||||
int (*rx_dma)(struct uart_8250_port *p);
|
||||
@@ -128,6 +130,24 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
|
||||
up->dl_write(up, value);
|
||||
}
|
||||
|
||||
static inline bool serial8250_set_THRI(struct uart_8250_port *up)
|
||||
{
|
||||
if (up->ier & UART_IER_THRI)
|
||||
return false;
|
||||
up->ier |= UART_IER_THRI;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool serial8250_clear_THRI(struct uart_8250_port *up)
|
||||
{
|
||||
if (!(up->ier & UART_IER_THRI))
|
||||
return false;
|
||||
up->ier &= ~UART_IER_THRI;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct uart_8250_port *serial8250_get_port(int line);
|
||||
|
||||
void serial8250_rpm_get(struct uart_8250_port *p);
|
||||
@@ -139,14 +159,82 @@ void serial8250_rpm_put_tx(struct uart_8250_port *p);
|
||||
int serial8250_em485_init(struct uart_8250_port *p);
|
||||
void serial8250_em485_destroy(struct uart_8250_port *p);
|
||||
|
||||
/* MCR <-> TIOCM conversion */
|
||||
static inline int serial8250_TIOCM_to_MCR(int tiocm)
|
||||
{
|
||||
int mcr = 0;
|
||||
|
||||
if (tiocm & TIOCM_RTS)
|
||||
mcr |= UART_MCR_RTS;
|
||||
if (tiocm & TIOCM_DTR)
|
||||
mcr |= UART_MCR_DTR;
|
||||
if (tiocm & TIOCM_OUT1)
|
||||
mcr |= UART_MCR_OUT1;
|
||||
if (tiocm & TIOCM_OUT2)
|
||||
mcr |= UART_MCR_OUT2;
|
||||
if (tiocm & TIOCM_LOOP)
|
||||
mcr |= UART_MCR_LOOP;
|
||||
|
||||
return mcr;
|
||||
}
|
||||
|
||||
static inline int serial8250_MCR_to_TIOCM(int mcr)
|
||||
{
|
||||
int tiocm = 0;
|
||||
|
||||
if (mcr & UART_MCR_RTS)
|
||||
tiocm |= TIOCM_RTS;
|
||||
if (mcr & UART_MCR_DTR)
|
||||
tiocm |= TIOCM_DTR;
|
||||
if (mcr & UART_MCR_OUT1)
|
||||
tiocm |= TIOCM_OUT1;
|
||||
if (mcr & UART_MCR_OUT2)
|
||||
tiocm |= TIOCM_OUT2;
|
||||
if (mcr & UART_MCR_LOOP)
|
||||
tiocm |= TIOCM_LOOP;
|
||||
|
||||
return tiocm;
|
||||
}
|
||||
|
||||
/* MSR <-> TIOCM conversion */
|
||||
static inline int serial8250_MSR_to_TIOCM(int msr)
|
||||
{
|
||||
int tiocm = 0;
|
||||
|
||||
if (msr & UART_MSR_DCD)
|
||||
tiocm |= TIOCM_CAR;
|
||||
if (msr & UART_MSR_RI)
|
||||
tiocm |= TIOCM_RNG;
|
||||
if (msr & UART_MSR_DSR)
|
||||
tiocm |= TIOCM_DSR;
|
||||
if (msr & UART_MSR_CTS)
|
||||
tiocm |= TIOCM_CTS;
|
||||
|
||||
return tiocm;
|
||||
}
|
||||
|
||||
static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
|
||||
{
|
||||
serial_out(up, UART_MCR, value);
|
||||
|
||||
if (up->gpios)
|
||||
mctrl_gpio_set(up->gpios, serial8250_MCR_to_TIOCM(value));
|
||||
}
|
||||
|
||||
static inline int serial8250_in_MCR(struct uart_8250_port *up)
|
||||
{
|
||||
return serial_in(up, UART_MCR);
|
||||
int mctrl;
|
||||
|
||||
mctrl = serial_in(up, UART_MCR);
|
||||
|
||||
if (up->gpios) {
|
||||
unsigned int mctrl_gpio = 0;
|
||||
|
||||
mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio);
|
||||
mctrl |= serial8250_TIOCM_to_MCR(mctrl_gpio);
|
||||
}
|
||||
|
||||
return mctrl;
|
||||
}
|
||||
|
||||
#if defined(__alpha__) && !defined(CONFIG_PCI)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* serial8250_register_8250_port() ports
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ioport.h>
|
||||
@@ -982,6 +983,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
||||
|
||||
uart = serial8250_find_match_or_unused(&up->port);
|
||||
if (uart && uart->port.type != PORT_8250_CIR) {
|
||||
struct mctrl_gpios *gpios;
|
||||
|
||||
if (uart->port.dev)
|
||||
uart_remove_one_port(&serial8250_reg, &uart->port);
|
||||
|
||||
@@ -1016,6 +1019,22 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
||||
if (up->port.flags & UPF_FIXED_TYPE)
|
||||
uart->port.type = up->port.type;
|
||||
|
||||
/*
|
||||
* Only call mctrl_gpio_init(), if the device has no ACPI
|
||||
* companion device
|
||||
*/
|
||||
if (!has_acpi_companion(uart->port.dev)) {
|
||||
gpios = mctrl_gpio_init(&uart->port, 0);
|
||||
if (IS_ERR(gpios)) {
|
||||
if (PTR_ERR(gpios) != -ENOSYS) {
|
||||
ret = PTR_ERR(gpios);
|
||||
goto out_unlock;
|
||||
}
|
||||
} else {
|
||||
uart->gpios = gpios;
|
||||
}
|
||||
}
|
||||
|
||||
serial8250_set_defaults(uart);
|
||||
|
||||
/* Possibly override default I/O functions. */
|
||||
@@ -1082,6 +1101,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
||||
}
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&serial_mutex);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -34,10 +34,8 @@ static void __dma_tx_complete(void *param)
|
||||
uart_write_wakeup(&p->port);
|
||||
|
||||
ret = serial8250_tx_dma(p);
|
||||
if (ret) {
|
||||
p->ier |= UART_IER_THRI;
|
||||
serial_port_out(&p->port, UART_IER, p->ier);
|
||||
}
|
||||
if (ret)
|
||||
serial8250_set_THRI(p);
|
||||
|
||||
spin_unlock_irqrestore(&p->port.lock, flags);
|
||||
}
|
||||
@@ -100,10 +98,7 @@ int serial8250_tx_dma(struct uart_8250_port *p)
|
||||
dma_async_issue_pending(dma->txchan);
|
||||
if (dma->tx_err) {
|
||||
dma->tx_err = 0;
|
||||
if (p->ier & UART_IER_THRI) {
|
||||
p->ier &= ~UART_IER_THRI;
|
||||
serial_out(p, UART_IER, p->ier);
|
||||
}
|
||||
serial8250_clear_THRI(p);
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/serial_8250.h>
|
||||
@@ -47,7 +48,6 @@
|
||||
#define MTK_UART_DMA_EN_RX 0x5
|
||||
|
||||
#define MTK_UART_ESCAPE_CHAR 0x77 /* Escape char added under sw fc */
|
||||
#define MTK_UART_TX_SIZE UART_XMIT_SIZE
|
||||
#define MTK_UART_RX_SIZE 0x8000
|
||||
#define MTK_UART_TX_TRIGGER 1
|
||||
#define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
|
||||
@@ -70,6 +70,7 @@ struct mtk8250_data {
|
||||
#ifdef CONFIG_SERIAL_8250_DMA
|
||||
enum dma_rx_status rx_status;
|
||||
#endif
|
||||
int rx_wakeup_irq;
|
||||
};
|
||||
|
||||
/* flow control mode */
|
||||
@@ -89,28 +90,30 @@ static void mtk8250_dma_rx_complete(void *param)
|
||||
struct mtk8250_data *data = up->port.private_data;
|
||||
struct tty_port *tty_port = &up->port.state->port;
|
||||
struct dma_tx_state state;
|
||||
int copied, total, cnt;
|
||||
unsigned char *ptr;
|
||||
int copied;
|
||||
|
||||
dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
|
||||
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
|
||||
|
||||
if (data->rx_status == DMA_RX_SHUTDOWN)
|
||||
return;
|
||||
|
||||
if ((data->rx_pos + state.residue) <= dma->rx_size) {
|
||||
ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
|
||||
copied = tty_insert_flip_string(tty_port, ptr, state.residue);
|
||||
} else {
|
||||
ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
|
||||
copied = tty_insert_flip_string(tty_port, ptr,
|
||||
dma->rx_size - data->rx_pos);
|
||||
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
|
||||
total = dma->rx_size - state.residue;
|
||||
cnt = total;
|
||||
|
||||
if ((data->rx_pos + cnt) > dma->rx_size)
|
||||
cnt = dma->rx_size - data->rx_pos;
|
||||
|
||||
ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
|
||||
copied = tty_insert_flip_string(tty_port, ptr, cnt);
|
||||
data->rx_pos += cnt;
|
||||
|
||||
if (total > cnt) {
|
||||
ptr = (unsigned char *)(dma->rx_buf);
|
||||
copied += tty_insert_flip_string(tty_port, ptr,
|
||||
data->rx_pos + state.residue - dma->rx_size);
|
||||
cnt = total - cnt;
|
||||
copied += tty_insert_flip_string(tty_port, ptr, cnt);
|
||||
data->rx_pos = cnt;
|
||||
}
|
||||
|
||||
up->port.icount.rx += copied;
|
||||
|
||||
tty_flip_buffer_push(tty_port);
|
||||
@@ -121,9 +124,7 @@ static void mtk8250_dma_rx_complete(void *param)
|
||||
static void mtk8250_rx_dma(struct uart_8250_port *up)
|
||||
{
|
||||
struct uart_8250_dma *dma = up->dma;
|
||||
struct mtk8250_data *data = up->port.private_data;
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct dma_tx_state state;
|
||||
|
||||
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
|
||||
dma->rx_size, DMA_DEV_TO_MEM,
|
||||
@@ -138,12 +139,6 @@ static void mtk8250_rx_dma(struct uart_8250_port *up)
|
||||
|
||||
dma->rx_cookie = dmaengine_submit(desc);
|
||||
|
||||
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
|
||||
data->rx_pos = state.residue;
|
||||
|
||||
dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
|
||||
dma_async_issue_pending(dma->rxchan);
|
||||
}
|
||||
|
||||
@@ -156,13 +151,11 @@ static void mtk8250_dma_enable(struct uart_8250_port *up)
|
||||
if (data->rx_status != DMA_RX_START)
|
||||
return;
|
||||
|
||||
dma->rxconf.direction = DMA_DEV_TO_MEM;
|
||||
dma->rxconf.src_addr_width = dma->rx_size / 1024;
|
||||
dma->rxconf.src_addr = dma->rx_addr;
|
||||
dma->rxconf.src_port_window_size = dma->rx_size;
|
||||
dma->rxconf.src_addr = dma->rx_addr;
|
||||
|
||||
dma->txconf.direction = DMA_MEM_TO_DEV;
|
||||
dma->txconf.dst_addr_width = MTK_UART_TX_SIZE / 1024;
|
||||
dma->txconf.dst_addr = dma->tx_addr;
|
||||
dma->txconf.dst_port_window_size = UART_XMIT_SIZE;
|
||||
dma->txconf.dst_addr = dma->tx_addr;
|
||||
|
||||
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
|
||||
UART_FCR_CLEAR_XMIT);
|
||||
@@ -551,6 +544,8 @@ static int mtk8250_probe(struct platform_device *pdev)
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
data->rx_wakeup_irq = platform_get_irq(pdev, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -572,15 +567,35 @@ static int mtk8250_remove(struct platform_device *pdev)
|
||||
static int __maybe_unused mtk8250_suspend(struct device *dev)
|
||||
{
|
||||
struct mtk8250_data *data = dev_get_drvdata(dev);
|
||||
int irq = data->rx_wakeup_irq;
|
||||
int err;
|
||||
|
||||
serial8250_suspend_port(data->line);
|
||||
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
if (irq >= 0) {
|
||||
err = enable_irq_wake(irq);
|
||||
if (err) {
|
||||
dev_err(dev,
|
||||
"failed to enable irq wake on IRQ %d: %d\n",
|
||||
irq, err);
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
serial8250_resume_port(data->line);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused mtk8250_resume(struct device *dev)
|
||||
{
|
||||
struct mtk8250_data *data = dev_get_drvdata(dev);
|
||||
int irq = data->rx_wakeup_irq;
|
||||
|
||||
if (irq >= 0)
|
||||
disable_irq_wake(irq);
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
|
||||
serial8250_resume_port(data->line);
|
||||
|
||||
|
||||
@@ -70,9 +70,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
||||
/* Get clk rate through clk driver if present */
|
||||
info->clk = devm_clk_get(&ofdev->dev, NULL);
|
||||
if (IS_ERR(info->clk)) {
|
||||
dev_warn(&ofdev->dev,
|
||||
"clk or clock-frequency not defined\n");
|
||||
ret = PTR_ERR(info->clk);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_warn(&ofdev->dev,
|
||||
"failed to get clock: %d\n", ret);
|
||||
goto err_pmruntime;
|
||||
}
|
||||
|
||||
@@ -205,18 +206,16 @@ err_pmruntime:
|
||||
/*
|
||||
* Try to register a serial port
|
||||
*/
|
||||
static const struct of_device_id of_platform_serial_table[];
|
||||
static int of_platform_serial_probe(struct platform_device *ofdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct of_serial_info *info;
|
||||
struct uart_8250_port port8250;
|
||||
unsigned int port_type;
|
||||
u32 tx_threshold;
|
||||
int port_type;
|
||||
int ret;
|
||||
|
||||
match = of_match_device(of_platform_serial_table, &ofdev->dev);
|
||||
if (!match)
|
||||
port_type = (unsigned long)of_device_get_match_data(&ofdev->dev);
|
||||
if (port_type == PORT_UNKNOWN)
|
||||
return -EINVAL;
|
||||
|
||||
if (of_property_read_bool(ofdev->dev.of_node, "used-by-rtas"))
|
||||
@@ -226,7 +225,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
|
||||
if (info == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
port_type = (unsigned long)match->data;
|
||||
memset(&port8250, 0, sizeof(port8250));
|
||||
ret = of_platform_serial_setup(ofdev, port_type, &port8250.port, info);
|
||||
if (ret)
|
||||
|
||||
@@ -141,18 +141,20 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
|
||||
serial8250_do_set_mctrl(port, mctrl);
|
||||
|
||||
/*
|
||||
* Turn off autoRTS if RTS is lowered and restore autoRTS setting
|
||||
* if RTS is raised
|
||||
*/
|
||||
lcr = serial_in(up, UART_LCR);
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
|
||||
priv->efr |= UART_EFR_RTS;
|
||||
else
|
||||
priv->efr &= ~UART_EFR_RTS;
|
||||
serial_out(up, UART_EFR, priv->efr);
|
||||
serial_out(up, UART_LCR, lcr);
|
||||
if (!up->gpios) {
|
||||
/*
|
||||
* Turn off autoRTS if RTS is lowered and restore autoRTS
|
||||
* setting if RTS is raised
|
||||
*/
|
||||
lcr = serial_in(up, UART_LCR);
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
|
||||
priv->efr |= UART_EFR_RTS;
|
||||
else
|
||||
priv->efr &= ~UART_EFR_RTS;
|
||||
serial_out(up, UART_EFR, priv->efr);
|
||||
serial_out(up, UART_LCR, lcr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -453,7 +455,8 @@ static void omap_8250_set_termios(struct uart_port *port,
|
||||
priv->efr = 0;
|
||||
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
|
||||
|
||||
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
|
||||
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW &&
|
||||
!up->gpios) {
|
||||
/* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */
|
||||
up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
|
||||
priv->efr |= UART_EFR_CTS;
|
||||
@@ -923,15 +926,13 @@ static void omap_8250_dma_tx_complete(void *param)
|
||||
ret = omap_8250_tx_dma(p);
|
||||
if (ret)
|
||||
en_thri = true;
|
||||
|
||||
} else if (p->capabilities & UART_CAP_RPM) {
|
||||
en_thri = true;
|
||||
}
|
||||
|
||||
if (en_thri) {
|
||||
dma->tx_err = 1;
|
||||
p->ier |= UART_IER_THRI;
|
||||
serial_port_out(&p->port, UART_IER, p->ier);
|
||||
serial8250_set_THRI(p);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&p->port.lock, flags);
|
||||
@@ -959,10 +960,7 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
if (p->ier & UART_IER_THRI) {
|
||||
p->ier &= ~UART_IER_THRI;
|
||||
serial_out(p, UART_IER, p->ier);
|
||||
}
|
||||
serial8250_clear_THRI(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1020,10 +1018,7 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
|
||||
if (dma->tx_err)
|
||||
dma->tx_err = 0;
|
||||
|
||||
if (p->ier & UART_IER_THRI) {
|
||||
p->ier &= ~UART_IER_THRI;
|
||||
serial_out(p, UART_IER, p->ier);
|
||||
}
|
||||
serial8250_clear_THRI(p);
|
||||
if (skip_byte)
|
||||
serial_out(p, UART_TX, xmit->buf[xmit->tail]);
|
||||
return 0;
|
||||
|
||||
@@ -1326,13 +1326,66 @@ static int pci_default_setup(struct serial_private *priv,
|
||||
|
||||
return setup_port(priv, port, bar, offset, board->reg_shift);
|
||||
}
|
||||
static void
|
||||
pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
|
||||
unsigned int quot, unsigned int quot_frac)
|
||||
{
|
||||
int scr;
|
||||
int lcr;
|
||||
int actual_baud;
|
||||
int tolerance;
|
||||
|
||||
for (scr = 5 ; scr <= 15 ; scr++) {
|
||||
actual_baud = 921600 * 16 / scr;
|
||||
tolerance = actual_baud / 50;
|
||||
|
||||
if ((baud < actual_baud + tolerance) &&
|
||||
(baud > actual_baud - tolerance)) {
|
||||
|
||||
lcr = serial_port_in(port, UART_LCR);
|
||||
serial_port_out(port, UART_LCR, lcr | 0x80);
|
||||
|
||||
serial_port_out(port, UART_DLL, 1);
|
||||
serial_port_out(port, UART_DLM, 0);
|
||||
serial_port_out(port, 2, 16 - scr);
|
||||
serial_port_out(port, UART_LCR, lcr);
|
||||
return;
|
||||
} else if (baud > actual_baud) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
serial8250_do_set_divisor(port, baud, quot, quot_frac);
|
||||
}
|
||||
static int pci_pericom_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
{
|
||||
unsigned int bar, offset = board->first_offset, maxnr;
|
||||
|
||||
bar = FL_GET_BASE(board->flags);
|
||||
if (board->flags & FL_BASE_BARS)
|
||||
bar += idx;
|
||||
else
|
||||
offset += idx * board->uart_offset;
|
||||
|
||||
|
||||
maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
|
||||
(board->reg_shift + 3);
|
||||
|
||||
if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
|
||||
return 1;
|
||||
|
||||
port->port.set_divisor = pericom_do_set_divisor;
|
||||
|
||||
return setup_port(priv, port, bar, offset, board->reg_shift);
|
||||
}
|
||||
|
||||
static int pci_pericom_setup_four_at_eight(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
{
|
||||
unsigned int bar, offset = board->first_offset, maxnr;
|
||||
|
||||
bar = FL_GET_BASE(board->flags);
|
||||
if (board->flags & FL_BASE_BARS)
|
||||
bar += idx;
|
||||
@@ -1348,6 +1401,8 @@ static int pci_pericom_setup(struct serial_private *priv,
|
||||
if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
|
||||
return 1;
|
||||
|
||||
port->port.set_divisor = pericom_do_set_divisor;
|
||||
|
||||
return setup_port(priv, port, bar, offset, board->reg_shift);
|
||||
}
|
||||
|
||||
@@ -1995,7 +2050,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.device = PCI_DEVICE_ID_PERICOM_PI7C9X7954,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
/*
|
||||
* PLX
|
||||
@@ -2032,107 +2087,113 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.setup = pci_pericom_setup_four_at_eight,
|
||||
},
|
||||
/*
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_ACCESIO,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
}, /*
|
||||
* SBS Technologies, Inc., PMC-OCTALPRO 232
|
||||
*/
|
||||
{
|
||||
|
||||
@@ -462,8 +462,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&dev->dev,
|
||||
"Setup PNP port: port %lx, mem %pa, irq %d, type %d\n",
|
||||
uart.port.iobase, &uart.port.mapbase,
|
||||
"Setup PNP port: port %#lx, mem %#llx, irq %u, type %u\n",
|
||||
uart.port.iobase, (unsigned long long)uart.port.mapbase,
|
||||
uart.port.irq, uart.port.iotype);
|
||||
|
||||
if (flags & CIR_PORT) {
|
||||
|
||||
@@ -1502,11 +1502,8 @@ static void __stop_tx_rs485(struct uart_8250_port *p)
|
||||
|
||||
static inline void __do_stop_tx(struct uart_8250_port *p)
|
||||
{
|
||||
if (p->ier & UART_IER_THRI) {
|
||||
p->ier &= ~UART_IER_THRI;
|
||||
serial_out(p, UART_IER, p->ier);
|
||||
if (serial8250_clear_THRI(p))
|
||||
serial8250_rpm_put_tx(p);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __stop_tx(struct uart_8250_port *p)
|
||||
@@ -1555,10 +1552,7 @@ static inline void __start_tx(struct uart_port *port)
|
||||
if (up->dma && !up->dma->tx_dma(up))
|
||||
return;
|
||||
|
||||
if (!(up->ier & UART_IER_THRI)) {
|
||||
up->ier |= UART_IER_THRI;
|
||||
serial_port_out(port, UART_IER, up->ier);
|
||||
|
||||
if (serial8250_set_THRI(up)) {
|
||||
if (up->bugs & UART_BUG_TXEN) {
|
||||
unsigned char lsr;
|
||||
|
||||
@@ -1662,6 +1656,8 @@ static void serial8250_disable_ms(struct uart_port *port)
|
||||
if (up->bugs & UART_BUG_NOMSR)
|
||||
return;
|
||||
|
||||
mctrl_gpio_disable_ms(up->gpios);
|
||||
|
||||
up->ier &= ~UART_IER_MSI;
|
||||
serial_port_out(port, UART_IER, up->ier);
|
||||
}
|
||||
@@ -1674,6 +1670,8 @@ static void serial8250_enable_ms(struct uart_port *port)
|
||||
if (up->bugs & UART_BUG_NOMSR)
|
||||
return;
|
||||
|
||||
mctrl_gpio_enable_ms(up->gpios);
|
||||
|
||||
up->ier |= UART_IER_MSI;
|
||||
|
||||
serial8250_rpm_get(up);
|
||||
@@ -1869,13 +1867,13 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
|
||||
|
||||
status = serial_port_in(port, UART_LSR);
|
||||
|
||||
if (status & (UART_LSR_DR | UART_LSR_BI) &&
|
||||
iir & UART_IIR_RDI) {
|
||||
if (status & (UART_LSR_DR | UART_LSR_BI)) {
|
||||
if (!up->dma || handle_rx_dma(up, iir))
|
||||
status = serial8250_rx_chars(up, status);
|
||||
}
|
||||
serial8250_modem_status(up);
|
||||
if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE))
|
||||
if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) &&
|
||||
(up->ier & UART_IER_THRI))
|
||||
serial8250_tx_chars(up);
|
||||
|
||||
uart_unlock_and_check_sysrq(port, flags);
|
||||
@@ -1944,22 +1942,17 @@ unsigned int serial8250_do_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
unsigned int status;
|
||||
unsigned int ret;
|
||||
unsigned int val;
|
||||
|
||||
serial8250_rpm_get(up);
|
||||
status = serial8250_modem_status(up);
|
||||
serial8250_rpm_put(up);
|
||||
|
||||
ret = 0;
|
||||
if (status & UART_MSR_DCD)
|
||||
ret |= TIOCM_CAR;
|
||||
if (status & UART_MSR_RI)
|
||||
ret |= TIOCM_RNG;
|
||||
if (status & UART_MSR_DSR)
|
||||
ret |= TIOCM_DSR;
|
||||
if (status & UART_MSR_CTS)
|
||||
ret |= TIOCM_CTS;
|
||||
return ret;
|
||||
val = serial8250_MSR_to_TIOCM(status);
|
||||
if (up->gpios)
|
||||
return mctrl_gpio_get(up->gpios, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl);
|
||||
|
||||
@@ -1973,18 +1966,9 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
|
||||
void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
unsigned char mcr = 0;
|
||||
unsigned char mcr;
|
||||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
mcr |= UART_MCR_RTS;
|
||||
if (mctrl & TIOCM_DTR)
|
||||
mcr |= UART_MCR_DTR;
|
||||
if (mctrl & TIOCM_OUT1)
|
||||
mcr |= UART_MCR_OUT1;
|
||||
if (mctrl & TIOCM_OUT2)
|
||||
mcr |= UART_MCR_OUT2;
|
||||
if (mctrl & TIOCM_LOOP)
|
||||
mcr |= UART_MCR_LOOP;
|
||||
mcr = serial8250_TIOCM_to_MCR(mctrl);
|
||||
|
||||
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ config SERIAL_8250
|
||||
tristate "8250/16550 and compatible serial support"
|
||||
depends on !S390
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
---help---
|
||||
This selects whether you want to include the driver for the standard
|
||||
serial ports. The standard answer is Y. People who might say N
|
||||
|
||||
@@ -457,20 +457,6 @@ config SERIAL_21285_CONSOLE
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_MPSC
|
||||
bool "Marvell MPSC serial port support"
|
||||
depends on MV64X60
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Say Y here if you want to use the Marvell MPSC serial controller.
|
||||
|
||||
config SERIAL_MPSC_CONSOLE
|
||||
bool "Support for console on Marvell MPSC serial port"
|
||||
depends on SERIAL_MPSC
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Say Y here if you want to support a serial console on a Marvell MPSC.
|
||||
|
||||
config SERIAL_PXA
|
||||
bool "PXA serial port support (DEPRECATED)"
|
||||
depends on ARCH_PXA || ARCH_MMP
|
||||
|
||||
@@ -46,7 +46,6 @@ obj-$(CONFIG_SERIAL_CPM) += cpm_uart/
|
||||
obj-$(CONFIG_SERIAL_IMX) += imx.o
|
||||
obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
|
||||
obj-$(CONFIG_SERIAL_ICOM) += icom.o
|
||||
obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
|
||||
obj-$(CONFIG_SERIAL_MESON) += meson_uart.o
|
||||
obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
|
||||
obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
|
||||
|
||||
@@ -1717,7 +1717,7 @@ static int pl011_allocate_irq(struct uart_amba_port *uap)
|
||||
{
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
|
||||
return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
|
||||
return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -407,7 +407,16 @@ static int cpm_uart_startup(struct uart_port *port)
|
||||
clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX);
|
||||
}
|
||||
cpm_uart_initbd(pinfo);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
|
||||
if (IS_SMC(pinfo)) {
|
||||
out_be32(&pinfo->smcup->smc_rstate, 0);
|
||||
out_be32(&pinfo->smcup->smc_tstate, 0);
|
||||
out_be16(&pinfo->smcup->smc_rbptr,
|
||||
in_be16(&pinfo->smcup->smc_rbase));
|
||||
out_be16(&pinfo->smcup->smc_tbptr,
|
||||
in_be16(&pinfo->smcup->smc_tbase));
|
||||
} else {
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
|
||||
}
|
||||
}
|
||||
/* Install interrupt handler. */
|
||||
retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port);
|
||||
@@ -567,8 +576,6 @@ static void cpm_uart_set_termios(struct uart_port *port,
|
||||
/*
|
||||
* Set up parity check flag
|
||||
*/
|
||||
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
|
||||
|
||||
port->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= BD_SC_FR | BD_SC_PR;
|
||||
@@ -861,16 +868,14 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
|
||||
(u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);
|
||||
|
||||
/*
|
||||
* In case SMC1 is being relocated...
|
||||
* In case SMC is being relocated...
|
||||
*/
|
||||
#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
|
||||
out_be16(&up->smc_rbptr, in_be16(&pinfo->smcup->smc_rbase));
|
||||
out_be16(&up->smc_tbptr, in_be16(&pinfo->smcup->smc_tbase));
|
||||
out_be32(&up->smc_rstate, 0);
|
||||
out_be32(&up->smc_tstate, 0);
|
||||
out_be16(&up->smc_brkcr, 1); /* number of break chars */
|
||||
out_be16(&up->smc_brkec, 0);
|
||||
#endif
|
||||
|
||||
/* Set up the uart parameters in the
|
||||
* parameter ram.
|
||||
@@ -884,8 +889,6 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
|
||||
out_be16(&up->smc_brkec, 0);
|
||||
out_be16(&up->smc_brkcr, 1);
|
||||
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
|
||||
|
||||
/* Set UART mode, 8 bit, no parity, one stop.
|
||||
* Enable receive and transmit.
|
||||
*/
|
||||
|
||||
@@ -541,7 +541,11 @@ static int __init digicolor_uart_init(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return platform_driver_register(&digicolor_uart_platform);
|
||||
ret = platform_driver_register(&digicolor_uart_platform);
|
||||
if (ret)
|
||||
uart_unregister_driver(&digicolor_uart);
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(digicolor_uart_init);
|
||||
|
||||
|
||||
@@ -234,9 +234,18 @@
|
||||
|
||||
static DEFINE_IDA(fsl_lpuart_ida);
|
||||
|
||||
enum lpuart_type {
|
||||
VF610_LPUART,
|
||||
LS1021A_LPUART,
|
||||
IMX7ULP_LPUART,
|
||||
IMX8QXP_LPUART,
|
||||
};
|
||||
|
||||
struct lpuart_port {
|
||||
struct uart_port port;
|
||||
struct clk *clk;
|
||||
enum lpuart_type devtype;
|
||||
struct clk *ipg_clk;
|
||||
struct clk *baud_clk;
|
||||
unsigned int txfifo_size;
|
||||
unsigned int rxfifo_size;
|
||||
|
||||
@@ -261,19 +270,29 @@ struct lpuart_port {
|
||||
};
|
||||
|
||||
struct lpuart_soc_data {
|
||||
char iotype;
|
||||
u8 reg_off;
|
||||
enum lpuart_type devtype;
|
||||
char iotype;
|
||||
u8 reg_off;
|
||||
};
|
||||
|
||||
static const struct lpuart_soc_data vf_data = {
|
||||
.devtype = VF610_LPUART,
|
||||
.iotype = UPIO_MEM,
|
||||
};
|
||||
|
||||
static const struct lpuart_soc_data ls_data = {
|
||||
.devtype = LS1021A_LPUART,
|
||||
.iotype = UPIO_MEM32BE,
|
||||
};
|
||||
|
||||
static struct lpuart_soc_data imx_data = {
|
||||
static struct lpuart_soc_data imx7ulp_data = {
|
||||
.devtype = IMX7ULP_LPUART,
|
||||
.iotype = UPIO_MEM32,
|
||||
.reg_off = IMX_REG_OFF,
|
||||
};
|
||||
|
||||
static struct lpuart_soc_data imx8qxp_data = {
|
||||
.devtype = IMX8QXP_LPUART,
|
||||
.iotype = UPIO_MEM32,
|
||||
.reg_off = IMX_REG_OFF,
|
||||
};
|
||||
@@ -281,7 +300,8 @@ static struct lpuart_soc_data imx_data = {
|
||||
static const struct of_device_id lpuart_dt_ids[] = {
|
||||
{ .compatible = "fsl,vf610-lpuart", .data = &vf_data, },
|
||||
{ .compatible = "fsl,ls1021a-lpuart", .data = &ls_data, },
|
||||
{ .compatible = "fsl,imx7ulp-lpuart", .data = &imx_data, },
|
||||
{ .compatible = "fsl,imx7ulp-lpuart", .data = &imx7ulp_data, },
|
||||
{ .compatible = "fsl,imx8qxp-lpuart", .data = &imx8qxp_data, },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
|
||||
@@ -289,6 +309,11 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
|
||||
/* Forward declare this for the dma callbacks*/
|
||||
static void lpuart_dma_tx_complete(void *arg);
|
||||
|
||||
static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
|
||||
{
|
||||
return sport->devtype == IMX8QXP_LPUART;
|
||||
}
|
||||
|
||||
static inline u32 lpuart32_read(struct uart_port *port, u32 off)
|
||||
{
|
||||
switch (port->iotype) {
|
||||
@@ -314,6 +339,39 @@ static inline void lpuart32_write(struct uart_port *port, u32 val,
|
||||
}
|
||||
}
|
||||
|
||||
static int __lpuart_enable_clks(struct lpuart_port *sport, bool is_en)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (is_en) {
|
||||
ret = clk_prepare_enable(sport->ipg_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(sport->baud_clk);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(sport->ipg_clk);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
clk_disable_unprepare(sport->baud_clk);
|
||||
clk_disable_unprepare(sport->ipg_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport)
|
||||
{
|
||||
if (is_imx8qxp_lpuart(sport))
|
||||
return clk_get_rate(sport->baud_clk);
|
||||
|
||||
return clk_get_rate(sport->ipg_clk);
|
||||
}
|
||||
|
||||
#define lpuart_enable_clks(x) __lpuart_enable_clks(x, true)
|
||||
#define lpuart_disable_clks(x) __lpuart_enable_clks(x, false)
|
||||
|
||||
static void lpuart_stop_tx(struct uart_port *port)
|
||||
{
|
||||
unsigned char temp;
|
||||
@@ -1040,10 +1098,8 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
|
||||
sport->rx_dma_rng_buf_len = 16;
|
||||
|
||||
ring->buf = kmalloc(sport->rx_dma_rng_buf_len, GFP_ATOMIC);
|
||||
if (!ring->buf) {
|
||||
dev_err(sport->port.dev, "Ring buf alloc failed\n");
|
||||
if (!ring->buf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sg_init_one(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len);
|
||||
sg_set_buf(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len);
|
||||
@@ -2071,14 +2127,14 @@ lpuart_console_get_options(struct lpuart_port *sport, int *baud,
|
||||
brfa = readb(sport->port.membase + UARTCR4);
|
||||
brfa &= UARTCR4_BRFA_MASK;
|
||||
|
||||
uartclk = clk_get_rate(sport->clk);
|
||||
uartclk = lpuart_get_baud_clk_rate(sport);
|
||||
/*
|
||||
* baud = mod_clk/(16*(sbr[13]+(brfa)/32)
|
||||
*/
|
||||
baud_raw = uartclk / (16 * (sbr + brfa / 32));
|
||||
|
||||
if (*baud != baud_raw)
|
||||
printk(KERN_INFO "Serial: Console lpuart rounded baud rate"
|
||||
dev_info(sport->port.dev, "Serial: Console lpuart rounded baud rate"
|
||||
"from %d to %d\n", baud_raw, *baud);
|
||||
}
|
||||
|
||||
@@ -2114,14 +2170,14 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
|
||||
bd = lpuart32_read(&sport->port, UARTBAUD);
|
||||
bd &= UARTBAUD_SBR_MASK;
|
||||
sbr = bd;
|
||||
uartclk = clk_get_rate(sport->clk);
|
||||
uartclk = lpuart_get_baud_clk_rate(sport);
|
||||
/*
|
||||
* baud = mod_clk/(16*(sbr[13]+(brfa)/32)
|
||||
*/
|
||||
baud_raw = uartclk / (16 * sbr);
|
||||
|
||||
if (*baud != baud_raw)
|
||||
printk(KERN_INFO "Serial: Console lpuart rounded baud rate"
|
||||
dev_info(sport->port.dev, "Serial: Console lpuart rounded baud rate"
|
||||
"from %d to %d\n", baud_raw, *baud);
|
||||
}
|
||||
|
||||
@@ -2288,6 +2344,7 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||
sport->port.mapbase = res->start;
|
||||
sport->port.dev = &pdev->dev;
|
||||
sport->port.type = PORT_LPUART;
|
||||
sport->devtype = sdata->devtype;
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "cannot obtain irq\n");
|
||||
@@ -2303,20 +2360,27 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||
|
||||
sport->port.rs485_config = lpuart_config_rs485;
|
||||
|
||||
sport->clk = devm_clk_get(&pdev->dev, "ipg");
|
||||
if (IS_ERR(sport->clk)) {
|
||||
ret = PTR_ERR(sport->clk);
|
||||
dev_err(&pdev->dev, "failed to get uart clk: %d\n", ret);
|
||||
sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
|
||||
if (IS_ERR(sport->ipg_clk)) {
|
||||
ret = PTR_ERR(sport->ipg_clk);
|
||||
dev_err(&pdev->dev, "failed to get uart ipg clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(sport->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable uart clk: %d\n", ret);
|
||||
return ret;
|
||||
sport->baud_clk = NULL;
|
||||
if (is_imx8qxp_lpuart(sport)) {
|
||||
sport->baud_clk = devm_clk_get(&pdev->dev, "baud");
|
||||
if (IS_ERR(sport->baud_clk)) {
|
||||
ret = PTR_ERR(sport->baud_clk);
|
||||
dev_err(&pdev->dev, "failed to get uart baud clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
sport->port.uartclk = clk_get_rate(sport->clk);
|
||||
ret = lpuart_enable_clks(sport);
|
||||
if (ret)
|
||||
return ret;
|
||||
sport->port.uartclk = lpuart_get_baud_clk_rate(sport);
|
||||
|
||||
lpuart_ports[sport->port.line] = sport;
|
||||
|
||||
@@ -2364,7 +2428,7 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||
|
||||
failed_attach_port:
|
||||
failed_irq_request:
|
||||
clk_disable_unprepare(sport->clk);
|
||||
lpuart_disable_clks(sport);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2376,7 +2440,7 @@ static int lpuart_remove(struct platform_device *pdev)
|
||||
|
||||
ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
|
||||
|
||||
clk_disable_unprepare(sport->clk);
|
||||
lpuart_disable_clks(sport);
|
||||
|
||||
if (sport->dma_tx_chan)
|
||||
dma_release_channel(sport->dma_tx_chan);
|
||||
@@ -2441,7 +2505,7 @@ static int lpuart_suspend(struct device *dev)
|
||||
}
|
||||
|
||||
if (sport->port.suspended && !irq_wake)
|
||||
clk_disable_unprepare(sport->clk);
|
||||
lpuart_disable_clks(sport);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2453,7 +2517,7 @@ static int lpuart_resume(struct device *dev)
|
||||
unsigned long temp;
|
||||
|
||||
if (sport->port.suspended && !irq_wake)
|
||||
clk_prepare_enable(sport->clk);
|
||||
lpuart_enable_clks(sport);
|
||||
|
||||
if (lpuart_is_32(sport)) {
|
||||
lpuart32_setup_watermark(sport);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user