Merge tag 'tty-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial updates from Greg KH:
 "Here is the big set of TTY / Serial patches for 5.7-rc1

  Lots of console fixups and reworking in here, serial core tweaks
  (doesn't that ever get old, why are we still creating new serial
  devices?), serial driver updates, line-protocol driver updates, and
  some vt cleanups and fixes included in here as well.

  All have been in linux-next with no reported issues"

* tag 'tty-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (161 commits)
  serial: 8250: Optimize irq enable after console write
  serial: 8250: Fix rs485 delay after console write
  vt: vt_ioctl: fix use-after-free in vt_in_use()
  vt: vt_ioctl: fix VT_DISALLOCATE freeing in-use virtual console
  tty: serial: make SERIAL_SPRD depend on COMMON_CLK
  tty: serial: fsl_lpuart: fix return value checking
  tty: serial: fsl_lpuart: move dma_request_chan()
  ARM: dts: tango4: Make /serial compatible with ns16550a
  ARM: dts: mmp*: Make the serial ports compatible with xscale-uart
  ARM: dts: mmp*: Fix serial port names
  ARM: dts: mmp2-brownstone: Don't redeclare phandle references
  ARM: dts: pxa*: Make the serial ports compatible with xscale-uart
  ARM: dts: pxa*: Fix serial port names
  ARM: dts: pxa*: Don't redeclare phandle references
  serial: omap: drop unused dt-bindings header
  serial: 8250: 8250_omap: Add DMA support for UARTs on K3 SoCs
  serial: 8250: 8250_omap: Work around errata causing spurious IRQs with DMA
  serial: 8250: 8250_omap: Extend driver data to pass FIFO trigger info
  serial: 8250: 8250_omap: Move locking out from __dma_rx_do_complete()
  serial: 8250: 8250_omap: Account for data in flight during DMA teardown
  ...
This commit is contained in:
Linus Torvalds
2020-03-31 16:18:55 -07:00
當前提交 1f944f976d
共有 80 個文件被更改,包括 2548 次插入1789 次删除

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Driver for 8250/16550-type serial ports
*
@@ -156,7 +156,9 @@ void serial8250_rpm_put(struct uart_8250_port *p);
void serial8250_rpm_get_tx(struct uart_8250_port *p);
void serial8250_rpm_put_tx(struct uart_8250_port *p);
int serial8250_em485_init(struct uart_8250_port *p);
int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485);
void serial8250_em485_start_tx(struct uart_8250_port *p);
void serial8250_em485_stop_tx(struct uart_8250_port *p);
void serial8250_em485_destroy(struct uart_8250_port *p);
/* MCR <-> TIOCM conversion */

查看文件

@@ -6,6 +6,10 @@
*
* Based on 8250_lpc18xx.c:
* Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
*
* The bcm2835aux is capable of RTS auto flow-control, but this driver doesn't
* take advantage of it yet. When adding support, be sure not to enable it
* simultaneously to rs485.
*/
#include <linux/clk.h>
@@ -16,16 +20,64 @@
#include "8250.h"
#define BCM2835_AUX_UART_CNTL 8
#define BCM2835_AUX_UART_CNTL_RXEN 0x01 /* Receiver enable */
#define BCM2835_AUX_UART_CNTL_TXEN 0x02 /* Transmitter enable */
#define BCM2835_AUX_UART_CNTL_AUTORTS 0x04 /* RTS set by RX fill level */
#define BCM2835_AUX_UART_CNTL_AUTOCTS 0x08 /* CTS stops transmitter */
#define BCM2835_AUX_UART_CNTL_RTS3 0x00 /* RTS set until 3 chars left */
#define BCM2835_AUX_UART_CNTL_RTS2 0x10 /* RTS set until 2 chars left */
#define BCM2835_AUX_UART_CNTL_RTS1 0x20 /* RTS set until 1 chars left */
#define BCM2835_AUX_UART_CNTL_RTS4 0x30 /* RTS set until 4 chars left */
#define BCM2835_AUX_UART_CNTL_RTSINV 0x40 /* Invert auto RTS polarity */
#define BCM2835_AUX_UART_CNTL_CTSINV 0x80 /* Invert auto CTS polarity */
/**
* struct bcm2835aux_data - driver private data of BCM2835 auxiliary UART
* @clk: clock producer of the port's uartclk
* @line: index of the port's serial8250_ports[] entry
* @cntl: cached copy of CNTL register
*/
struct bcm2835aux_data {
struct clk *clk;
int line;
u32 cntl;
};
static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up)
{
if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev);
data->cntl &= ~BCM2835_AUX_UART_CNTL_RXEN;
serial_out(up, BCM2835_AUX_UART_CNTL, data->cntl);
}
/*
* On the bcm2835aux, the MCR register contains no other
* flags besides RTS. So no need for a read-modify-write.
*/
if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
serial8250_out_MCR(up, 0);
else
serial8250_out_MCR(up, UART_MCR_RTS);
}
static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up)
{
if (up->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
serial8250_out_MCR(up, 0);
else
serial8250_out_MCR(up, UART_MCR_RTS);
if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev);
data->cntl |= BCM2835_AUX_UART_CNTL_RXEN;
serial_out(up, BCM2835_AUX_UART_CNTL, data->cntl);
}
}
static int bcm2835aux_serial_probe(struct platform_device *pdev)
{
struct uart_8250_port up = { };
@@ -47,6 +99,14 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
up.port.fifosize = 8;
up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE |
UPF_SKIP_TEST | UPF_IOREMAP;
up.port.rs485_config = serial8250_em485_config;
up.rs485_start_tx = bcm2835aux_rs485_start_tx;
up.rs485_stop_tx = bcm2835aux_rs485_stop_tx;
/* initialize cached copy with power-on reset value */
data->cntl = BCM2835_AUX_UART_CNTL_RXEN | BCM2835_AUX_UART_CNTL_TXEN;
platform_set_drvdata(pdev, data);
/* get the clock - this also enables the HW */
data->clk = devm_clk_get(&pdev->dev, NULL);
@@ -102,8 +162,6 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
}
data->line = ret;
platform_set_drvdata(pdev, data);
return 0;
dis_clk:
@@ -137,6 +195,24 @@ static struct platform_driver bcm2835aux_serial_driver = {
};
module_platform_driver(bcm2835aux_serial_driver);
#ifdef CONFIG_SERIAL_8250_CONSOLE
static int __init early_bcm2835aux_setup(struct earlycon_device *device,
const char *options)
{
if (!device->port.membase)
return -ENODEV;
device->port.iotype = UPIO_MEM32;
device->port.regshift = 2;
return early_serial8250_setup(device, NULL);
}
OF_EARLYCON_DECLARE(bcm2835aux, "brcm,bcm2835-aux-uart",
early_bcm2835aux_setup);
#endif
MODULE_DESCRIPTION("BCM2835 auxiliar UART driver");
MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
MODULE_LICENSE("GPL v2");

查看文件

@@ -608,6 +608,14 @@ static int univ8250_console_setup(struct console *co, char *options)
return retval;
}
static int univ8250_console_exit(struct console *co)
{
struct uart_port *port;
port = &serial8250_ports[co->index].port;
return serial8250_console_exit(port);
}
/**
* univ8250_console_match - non-standard console matching
* @co: registering console
@@ -666,6 +674,7 @@ static struct console univ8250_console = {
.write = univ8250_console_write,
.device = uart_console_device,
.setup = univ8250_console_setup,
.exit = univ8250_console_exit,
.match = univ8250_console_match,
.flags = CON_PRINTBUFFER | CON_ANYTIME,
.index = -1,
@@ -1007,14 +1016,18 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
uart->port.unthrottle = up->port.unthrottle;
uart->port.rs485_config = up->port.rs485_config;
uart->port.rs485 = up->port.rs485;
uart->rs485_start_tx = up->rs485_start_tx;
uart->rs485_stop_tx = up->rs485_stop_tx;
uart->dma = up->dma;
/* Take tx_loadsz from fifosize if it wasn't set separately */
if (uart->port.fifosize && !uart->tx_loadsz)
uart->tx_loadsz = uart->port.fifosize;
if (up->port.dev)
if (up->port.dev) {
uart->port.dev = up->port.dev;
uart_get_rs485_mode(uart->port.dev, &uart->port.rs485);
}
if (up->port.flags & UPF_FIXED_TYPE)
uart->port.type = up->port.type;

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/* SPDX-License-Identifier: GPL-2.0+ */
/* Synopsys DesignWare 8250 library header file. */
#include <linux/types.h>

查看文件

@@ -135,7 +135,7 @@ struct exar8250 {
unsigned int nr;
struct exar8250_board *board;
void __iomem *virt;
int line[0];
int line[];
};
static void exar_pm(struct uart_port *port, unsigned int state, unsigned int old)

查看文件

@@ -156,6 +156,11 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return 0;
}
static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
return 0;
}
#ifdef CONFIG_SERIAL_8250_DMA
static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
.nr_channels = 2,
@@ -356,6 +361,7 @@ static const struct lpss8250_board byt_board = {
static const struct lpss8250_board ehl_board = {
.freq = 200000000,
.base_baud = 12500000,
.setup = ehl_serial_setup,
};
static const struct lpss8250_board qrk_board = {

查看文件

@@ -32,6 +32,7 @@
#define MTK_UART_RXTRI_AD 0x14 /* RX Trigger address */
#define MTK_UART_FRACDIV_L 0x15 /* Fractional divider LSB address */
#define MTK_UART_FRACDIV_M 0x16 /* Fractional divider MSB address */
#define MTK_UART_DEBUG0 0x18
#define MTK_UART_IER_XOFFI 0x20 /* Enable XOFF character interrupt */
#define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */
#define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */
@@ -388,9 +389,18 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
static int __maybe_unused mtk8250_runtime_suspend(struct device *dev)
{
struct mtk8250_data *data = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(data->line);
clk_disable_unprepare(data->uart_clk);
clk_disable_unprepare(data->bus_clk);
/* wait until UART in idle status */
while
(serial_in(up, MTK_UART_DEBUG0));
if (data->clk_count == 0U) {
dev_dbg(dev, "%s clock count is 0\n", __func__);
} else {
clk_disable_unprepare(data->bus_clk);
data->clk_count--;
}
return 0;
}
@@ -400,16 +410,16 @@ static int __maybe_unused mtk8250_runtime_resume(struct device *dev)
struct mtk8250_data *data = dev_get_drvdata(dev);
int err;
err = clk_prepare_enable(data->uart_clk);
if (err) {
dev_warn(dev, "Can't enable clock\n");
return err;
}
err = clk_prepare_enable(data->bus_clk);
if (err) {
dev_warn(dev, "Can't enable bus clock\n");
return err;
if (data->clk_count > 0U) {
dev_dbg(dev, "%s clock count is %d\n", __func__,
data->clk_count);
} else {
err = clk_prepare_enable(data->bus_clk);
if (err) {
dev_warn(dev, "Can't enable bus clock\n");
return err;
}
data->clk_count++;
}
return 0;
@@ -419,12 +429,14 @@ static void
mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
{
if (!state)
pm_runtime_get_sync(port->dev);
if (!mtk8250_runtime_resume(port->dev))
pm_runtime_get_sync(port->dev);
serial8250_do_pm(port, state, old);
if (state)
pm_runtime_put_sync_suspend(port->dev);
if (!pm_runtime_put_sync_suspend(port->dev))
mtk8250_runtime_suspend(port->dev);
}
#ifdef CONFIG_SERIAL_8250_DMA
@@ -501,6 +513,8 @@ static int mtk8250_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
data->clk_count = 0;
if (pdev->dev.of_node) {
err = mtk8250_probe_of(pdev, &uart.port, data);
if (err)
@@ -533,6 +547,7 @@ static int mtk8250_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
pm_runtime_enable(&pdev->dev);
err = mtk8250_runtime_resume(&pdev->dev);
if (err)
return err;
@@ -541,9 +556,6 @@ static int mtk8250_probe(struct platform_device *pdev)
if (data->line < 0)
return data->line;
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1);
return 0;
@@ -556,11 +568,13 @@ static int mtk8250_remove(struct platform_device *pdev)
pm_runtime_get_sync(&pdev->dev);
serial8250_unregister_port(data->line);
mtk8250_runtime_suspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
mtk8250_runtime_suspend(&pdev->dev);
return 0;
}

查看文件

@@ -7,7 +7,6 @@
#include <linux/console.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/of_address.h>
@@ -26,67 +25,16 @@ struct of_serial_info {
int line;
};
#ifdef CONFIG_ARCH_TEGRA
static void tegra_serial_handle_break(struct uart_port *p)
{
unsigned int status, tmout = 10000;
do {
status = p->serial_in(p, UART_LSR);
if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
status = p->serial_in(p, UART_RX);
else
break;
if (--tmout == 0)
break;
udelay(1);
} while (1);
}
#else
static inline void tegra_serial_handle_break(struct uart_port *port)
{
}
#endif
static int of_8250_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
struct uart_8250_port *up = up_to_u8250p(port);
/* Clamp the delays to [0, 100ms] */
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
port->rs485 = *rs485;
/*
* Both serial8250_em485_init and serial8250_em485_destroy
* are idempotent
*/
if (rs485->flags & SER_RS485_ENABLED) {
int ret = serial8250_em485_init(up);
if (ret) {
rs485->flags &= ~SER_RS485_ENABLED;
port->rs485.flags &= ~SER_RS485_ENABLED;
}
return ret;
}
serial8250_em485_destroy(up);
return 0;
}
/*
* Fill a struct uart_port for a given device node
*/
static int of_platform_serial_setup(struct platform_device *ofdev,
int type, struct uart_port *port,
int type, struct uart_8250_port *up,
struct of_serial_info *info)
{
struct resource resource;
struct device_node *np = ofdev->dev.of_node;
struct uart_port *port = &up->port;
u32 clk, spd, prop;
int ret, irq;
@@ -207,13 +155,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
port->flags |= UPF_SKIP_TEST;
port->dev = &ofdev->dev;
port->rs485_config = of_8250_rs485_config;
port->rs485_config = serial8250_em485_config;
up->rs485_start_tx = serial8250_em485_start_tx;
up->rs485_stop_tx = serial8250_em485_stop_tx;
switch (type) {
case PORT_TEGRA:
port->handle_break = tegra_serial_handle_break;
break;
case PORT_RT2880:
port->iotype = UPIO_AU;
break;
@@ -258,7 +204,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
return -ENOMEM;
memset(&port8250, 0, sizeof(port8250));
ret = of_platform_serial_setup(ofdev, port_type, &port8250.port, info);
ret = of_platform_serial_setup(ofdev, port_type, &port8250, info);
if (ret)
goto err_free;
@@ -358,7 +304,6 @@ static const struct of_device_id of_platform_serial_table[] = {
{ .compatible = "ns16550", .data = (void *)PORT_16550, },
{ .compatible = "ns16750", .data = (void *)PORT_16750, },
{ .compatible = "ns16850", .data = (void *)PORT_16850, },
{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
{ .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },
{ .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, },
{ .compatible = "intel,xscale-uart", .data = (void *)PORT_XSCALE, },

查看文件

@@ -40,6 +40,7 @@
* The same errata is applicable to AM335x and DRA7x processors too.
*/
#define UART_ERRATA_CLOCK_DISABLE (1 << 3)
#define UART_HAS_EFR2 BIT(4)
#define OMAP_UART_FCR_RX_TRIG 6
#define OMAP_UART_FCR_TX_TRIG 4
@@ -93,6 +94,10 @@
#define OMAP_UART_REV_52 0x0502
#define OMAP_UART_REV_63 0x0603
/* Enhanced features register 2 */
#define UART_OMAP_EFR2 0x23
#define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6)
struct omap8250_priv {
int line;
u8 habit;
@@ -105,6 +110,8 @@ struct omap8250_priv {
u8 delayed_restore;
u16 quot;
u8 tx_trigger;
u8 rx_trigger;
bool is_suspending;
int wakeirq;
int wakeups_enabled;
@@ -118,6 +125,17 @@ struct omap8250_priv {
bool throttled;
};
struct omap8250_dma_params {
u32 rx_size;
u8 rx_trigger;
u8 tx_trigger;
};
struct omap8250_platdata {
struct omap8250_dma_params *dma_params;
u8 habit;
};
#ifdef CONFIG_SERIAL_8250_DMA
static void omap_8250_rx_dma_flush(struct uart_8250_port *p);
#else
@@ -295,8 +313,8 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_RESTORE(16) |
OMAP_UART_TCR_HALT(52));
serial_out(up, UART_TI752_TLR,
TRIGGER_TLR_MASK(TX_TRIGGER) << UART_TI752_TLR_TX |
TRIGGER_TLR_MASK(RX_TRIGGER) << UART_TI752_TLR_RX);
TRIGGER_TLR_MASK(priv->tx_trigger) << UART_TI752_TLR_TX |
TRIGGER_TLR_MASK(priv->rx_trigger) << UART_TI752_TLR_RX);
serial_out(up, UART_LCR, 0);
@@ -435,8 +453,8 @@ static void omap_8250_set_termios(struct uart_port *port,
* This is because threshold and trigger values are the same.
*/
up->fcr = UART_FCR_ENABLE_FIFO;
up->fcr |= TRIGGER_FCR_MASK(TX_TRIGGER) << OMAP_UART_FCR_TX_TRIG;
up->fcr |= TRIGGER_FCR_MASK(RX_TRIGGER) << OMAP_UART_FCR_RX_TRIG;
up->fcr |= TRIGGER_FCR_MASK(priv->tx_trigger) << OMAP_UART_FCR_TX_TRIG;
up->fcr |= TRIGGER_FCR_MASK(priv->rx_trigger) << OMAP_UART_FCR_RX_TRIG;
priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY |
OMAP_UART_SCR_TX_TRIG_GRANU1_MASK;
@@ -651,7 +669,7 @@ static int omap_8250_startup(struct uart_port *port)
priv->wer |= OMAP_UART_TX_WAKEUP_EN;
serial_out(up, UART_OMAP_WER, priv->wer);
if (up->dma)
if (up->dma && !(priv->habit & UART_HAS_EFR2))
up->dma->rx_dma(up);
pm_runtime_mark_last_busy(port->dev);
@@ -676,6 +694,8 @@ static void omap_8250_shutdown(struct uart_port *port)
pm_runtime_get_sync(port->dev);
serial_out(up, UART_OMAP_WER, 0);
if (priv->habit & UART_HAS_EFR2)
serial_out(up, UART_OMAP_EFR2, 0x0);
up->ier = 0;
serial_out(up, UART_IER, 0);
@@ -699,14 +719,12 @@ static void omap_8250_shutdown(struct uart_port *port)
static void omap_8250_throttle(struct uart_port *port)
{
struct omap8250_priv *priv = port->private_data;
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
pm_runtime_get_sync(port->dev);
spin_lock_irqsave(&port->lock, flags);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
serial_out(up, UART_IER, up->ier);
port->ops->stop_rx(port);
priv->throttled = true;
spin_unlock_irqrestore(&port->lock, flags);
@@ -714,36 +732,6 @@ static void omap_8250_throttle(struct uart_port *port)
pm_runtime_put_autosuspend(port->dev);
}
static int omap_8250_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
struct uart_8250_port *up = up_to_u8250p(port);
/* Clamp the delays to [0, 100ms] */
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
port->rs485 = *rs485;
/*
* Both serial8250_em485_init and serial8250_em485_destroy
* are idempotent
*/
if (rs485->flags & SER_RS485_ENABLED) {
int ret = serial8250_em485_init(up);
if (ret) {
rs485->flags &= ~SER_RS485_ENABLED;
port->rs485.flags &= ~SER_RS485_ENABLED;
}
return ret;
}
serial8250_em485_destroy(up);
return 0;
}
static void omap_8250_unthrottle(struct uart_port *port)
{
struct omap8250_priv *priv = port->private_data;
@@ -757,6 +745,7 @@ static void omap_8250_unthrottle(struct uart_port *port)
if (up->dma)
up->dma->rx_dma(up);
up->ier |= UART_IER_RLSI | UART_IER_RDI;
port->read_status_mask |= UART_LSR_DR;
serial_out(up, UART_IER, up->ier);
spin_unlock_irqrestore(&port->lock, flags);
@@ -767,32 +756,50 @@ static void omap_8250_unthrottle(struct uart_port *port)
#ifdef CONFIG_SERIAL_8250_DMA
static int omap_8250_rx_dma(struct uart_8250_port *p);
/* Must be called while priv->rx_dma_lock is held */
static void __dma_rx_do_complete(struct uart_8250_port *p)
{
struct omap8250_priv *priv = p->port.private_data;
struct uart_8250_dma *dma = p->dma;
struct tty_port *tty_port = &p->port.state->port;
struct dma_chan *rxchan = dma->rxchan;
dma_cookie_t cookie;
struct dma_tx_state state;
int count;
unsigned long flags;
int ret;
spin_lock_irqsave(&priv->rx_dma_lock, flags);
if (!dma->rx_running)
goto unlock;
goto out;
cookie = dma->rx_cookie;
dma->rx_running = 0;
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
dmaengine_tx_status(rxchan, cookie, &state);
count = dma->rx_size - state.residue;
count = dma->rx_size - state.residue + state.in_flight_bytes;
if (count < dma->rx_size) {
dmaengine_terminate_async(rxchan);
/*
* Poll for teardown to complete which guarantees in
* flight data is drained.
*/
if (state.in_flight_bytes) {
int poll_count = 25;
while (dmaengine_tx_status(rxchan, cookie, NULL) &&
poll_count--)
cpu_relax();
if (!poll_count)
dev_err(p->port.dev, "teardown incomplete\n");
}
}
if (!count)
goto out;
ret = tty_insert_flip_string(tty_port, dma->rx_buf, count);
p->port.icount.rx += ret;
p->port.icount.buf_overrun += count - ret;
unlock:
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
out:
tty_flip_buffer_push(tty_port);
}
@@ -818,8 +825,12 @@ static void __dma_rx_complete(void *param)
return;
}
__dma_rx_do_complete(p);
if (!priv->throttled)
omap_8250_rx_dma(p);
if (!priv->throttled) {
p->ier |= UART_IER_RLSI | UART_IER_RDI;
serial_out(p, UART_IER, p->ier);
if (!(priv->habit & UART_HAS_EFR2))
omap_8250_rx_dma(p);
}
spin_unlock_irqrestore(&p->port.lock, flags);
}
@@ -845,10 +856,8 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
if (WARN_ON_ONCE(ret))
priv->rx_dma_broken = true;
}
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
__dma_rx_do_complete(p);
dmaengine_terminate_all(dma->rxchan);
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
}
static int omap_8250_rx_dma(struct uart_8250_port *p)
@@ -864,8 +873,20 @@ static int omap_8250_rx_dma(struct uart_8250_port *p)
spin_lock_irqsave(&priv->rx_dma_lock, flags);
if (dma->rx_running)
if (dma->rx_running) {
enum dma_status state;
state = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, NULL);
if (state == DMA_COMPLETE) {
/*
* Disable RX interrupts to allow RX DMA completion
* callback to run.
*/
p->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
serial_out(p, UART_IER, p->ier);
}
goto out;
}
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
dma->rx_size, DMA_DEV_TO_MEM,
@@ -1036,6 +1057,46 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
return omap_8250_rx_dma(up);
}
static unsigned char omap_8250_handle_rx_dma(struct uart_8250_port *up,
u8 iir, unsigned char status)
{
if ((status & (UART_LSR_DR | UART_LSR_BI)) &&
(iir & UART_IIR_RDI)) {
if (handle_rx_dma(up, iir)) {
status = serial8250_rx_chars(up, status);
omap_8250_rx_dma(up);
}
}
return status;
}
static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
unsigned char status)
{
/*
* Queue a new transfer if FIFO has data.
*/
if ((status & (UART_LSR_DR | UART_LSR_BI)) &&
(up->ier & UART_IER_RDI)) {
omap_8250_rx_dma(up);
serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE);
} else if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) {
/*
* Disable RX timeout, read IIR to clear
* current timeout condition, clear EFR2 to
* periodic timeouts, re-enable interrupts.
*/
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
serial_out(up, UART_IER, up->ier);
omap_8250_rx_dma_flush(up);
serial_in(up, UART_IIR);
serial_out(up, UART_OMAP_EFR2, 0x0);
up->ier |= UART_IER_RLSI | UART_IER_RDI;
serial_out(up, UART_IER, up->ier);
}
}
/*
* This is mostly serial8250_handle_irq(). We have a slightly different DMA
* hoook for RX/TX and need different logic for them in the ISR. Therefore we
@@ -1044,6 +1105,7 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
static int omap_8250_dma_handle_irq(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = up->port.private_data;
unsigned char status;
unsigned long flags;
u8 iir;
@@ -1053,19 +1115,18 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
iir = serial_port_in(port, UART_IIR);
if (iir & UART_IIR_NO_INT) {
serial8250_rpm_put(up);
return 0;
return IRQ_HANDLED;
}
spin_lock_irqsave(&port->lock, flags);
status = serial_port_in(port, UART_LSR);
if (status & (UART_LSR_DR | UART_LSR_BI)) {
if (handle_rx_dma(up, iir)) {
status = serial8250_rx_chars(up, status);
omap_8250_rx_dma(up);
}
}
if (priv->habit & UART_HAS_EFR2)
am654_8250_handle_rx_dma(up, iir, status);
else
status = omap_8250_handle_rx_dma(up, iir, status);
serial8250_modem_status(up);
if (status & UART_LSR_THRE && up->dma->tx_err) {
if (uart_tx_stopped(&up->port) ||
@@ -1107,18 +1168,41 @@ static int omap8250_no_handle_irq(struct uart_port *port)
return 0;
}
static const u8 omap4_habit = UART_ERRATA_CLOCK_DISABLE;
static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE;
static struct omap8250_dma_params am654_dma = {
.rx_size = SZ_2K,
.rx_trigger = 1,
.tx_trigger = TX_TRIGGER,
};
static struct omap8250_dma_params am33xx_dma = {
.rx_size = RX_TRIGGER,
.rx_trigger = RX_TRIGGER,
.tx_trigger = TX_TRIGGER,
};
static struct omap8250_platdata am654_platdata = {
.dma_params = &am654_dma,
.habit = UART_HAS_EFR2,
};
static struct omap8250_platdata am33xx_platdata = {
.dma_params = &am33xx_dma,
.habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE,
};
static struct omap8250_platdata omap4_platdata = {
.dma_params = &am33xx_dma,
.habit = UART_ERRATA_CLOCK_DISABLE,
};
static const struct of_device_id omap8250_dt_ids[] = {
{ .compatible = "ti,am654-uart" },
{ .compatible = "ti,am654-uart", .data = &am654_platdata, },
{ .compatible = "ti,omap2-uart" },
{ .compatible = "ti,omap3-uart" },
{ .compatible = "ti,omap4-uart", .data = &omap4_habit, },
{ .compatible = "ti,am3352-uart", .data = &am3352_habit, },
{ .compatible = "ti,am4372-uart", .data = &am3352_habit, },
{ .compatible = "ti,dra742-uart", .data = &dra742_habit, },
{ .compatible = "ti,omap4-uart", .data = &omap4_platdata, },
{ .compatible = "ti,am3352-uart", .data = &am33xx_platdata, },
{ .compatible = "ti,am4372-uart", .data = &am33xx_platdata, },
{ .compatible = "ti,dra742-uart", .data = &omap4_platdata, },
{},
};
MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
@@ -1129,10 +1213,10 @@ static int omap8250_probe(struct platform_device *pdev)
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct device_node *np = pdev->dev.of_node;
struct omap8250_priv *priv;
const struct omap8250_platdata *pdata;
struct uart_8250_port up;
int ret;
void __iomem *membase;
const struct of_device_id *id;
if (!regs || !irq) {
dev_err(&pdev->dev, "missing registers or irq\n");
@@ -1187,7 +1271,9 @@ static int omap8250_probe(struct platform_device *pdev)
up.port.shutdown = omap_8250_shutdown;
up.port.throttle = omap_8250_throttle;
up.port.unthrottle = omap_8250_unthrottle;
up.port.rs485_config = omap_8250_rs485_config;
up.port.rs485_config = serial8250_em485_config;
up.rs485_start_tx = serial8250_em485_start_tx;
up.rs485_stop_tx = serial8250_em485_stop_tx;
up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
ret = of_alias_get_id(np, "serial");
@@ -1211,9 +1297,9 @@ static int omap8250_probe(struct platform_device *pdev)
priv->wakeirq = irq_of_parse_and_map(np, 1);
id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
if (id && id->data)
priv->habit |= *(u8 *)id->data;
pdata = of_device_get_match_data(&pdev->dev);
if (pdata)
priv->habit |= pdata->habit;
if (!up.port.uartclk) {
up.port.uartclk = DEFAULT_CLK_SPEED;
@@ -1230,6 +1316,7 @@ static int omap8250_probe(struct platform_device *pdev)
spin_lock_init(&priv->rx_dma_lock);
device_init_wakeup(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
/*
@@ -1243,12 +1330,13 @@ static int omap8250_probe(struct platform_device *pdev)
pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
pm_runtime_irq_safe(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
omap_serial_fill_features_erratas(&up, priv);
up.port.handle_irq = omap8250_no_handle_irq;
priv->rx_trigger = RX_TRIGGER;
priv->tx_trigger = TX_TRIGGER;
#ifdef CONFIG_SERIAL_8250_DMA
/*
* Oh DMA support. If there are no DMA properties in the DT then
@@ -1260,13 +1348,26 @@ static int omap8250_probe(struct platform_device *pdev)
*/
ret = of_property_count_strings(np, "dma-names");
if (ret == 2) {
struct omap8250_dma_params *dma_params = NULL;
up.dma = &priv->omap8250_dma;
priv->omap8250_dma.fn = the_no_dma_filter_fn;
priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
priv->omap8250_dma.rx_dma = omap_8250_rx_dma;
priv->omap8250_dma.rx_size = RX_TRIGGER;
priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
up.dma->fn = the_no_dma_filter_fn;
up.dma->tx_dma = omap_8250_tx_dma;
up.dma->rx_dma = omap_8250_rx_dma;
if (pdata)
dma_params = pdata->dma_params;
if (dma_params) {
up.dma->rx_size = dma_params->rx_size;
up.dma->rxconf.src_maxburst = dma_params->rx_trigger;
up.dma->txconf.dst_maxburst = dma_params->tx_trigger;
priv->rx_trigger = dma_params->rx_trigger;
priv->tx_trigger = dma_params->tx_trigger;
} else {
up.dma->rx_size = RX_TRIGGER;
up.dma->rxconf.src_maxburst = RX_TRIGGER;
up.dma->txconf.dst_maxburst = TX_TRIGGER;
}
}
#endif
ret = serial8250_register_8250_port(&up);
@@ -1464,7 +1565,7 @@ static int omap8250_runtime_resume(struct device *dev)
if (omap8250_lost_context(up))
omap8250_restore_regs(up);
if (up->dma && up->dma->rxchan)
if (up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2))
omap_8250_rx_dma(up);
priv->latency = priv->calc_latency;

查看文件

@@ -53,7 +53,7 @@ struct serial_private {
unsigned int nr;
struct pci_serial_quirk *quirk;
const struct pciserial_board *board;
int line[0];
int line[];
};
static const struct pci_device_id pci_use_msi[] = {

查看文件

@@ -557,17 +557,6 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
}
}
static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p)
{
unsigned char mcr = serial8250_in_MCR(p);
if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
mcr |= UART_MCR_RTS;
else
mcr &= ~UART_MCR_RTS;
serial8250_out_MCR(p, mcr);
}
static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);
static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);
@@ -615,7 +604,7 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put);
*
* Return 0 - success, -errno - otherwise
*/
int serial8250_em485_init(struct uart_8250_port *p)
static int serial8250_em485_init(struct uart_8250_port *p)
{
if (p->em485)
return 0;
@@ -632,11 +621,12 @@ int serial8250_em485_init(struct uart_8250_port *p)
p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;
p->em485->port = p;
p->em485->active_timer = NULL;
serial8250_em485_rts_after_send(p);
p->em485->tx_stopped = true;
p->rs485_stop_tx(p);
return 0;
}
EXPORT_SYMBOL_GPL(serial8250_em485_init);
/**
* serial8250_em485_destroy() - put uart_8250_port into normal state
@@ -664,6 +654,52 @@ void serial8250_em485_destroy(struct uart_8250_port *p)
}
EXPORT_SYMBOL_GPL(serial8250_em485_destroy);
/**
* serial8250_em485_config() - generic ->rs485_config() callback
* @port: uart port
* @rs485: rs485 settings
*
* Generic callback usable by 8250 uart drivers to activate rs485 settings
* if the uart is incapable of driving RTS as a Transmit Enable signal in
* hardware, relying on software emulation instead.
*/
int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485)
{
struct uart_8250_port *up = up_to_u8250p(port);
/* pick sane settings if the user hasn't */
if (!!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
!!(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
rs485->flags |= SER_RS485_RTS_ON_SEND;
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
}
/* clamp the delays to [0, 100ms] */
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
memset(rs485->padding, 0, sizeof(rs485->padding));
port->rs485 = *rs485;
/*
* Both serial8250_em485_init() and serial8250_em485_destroy()
* are idempotent.
*/
if (rs485->flags & SER_RS485_ENABLED) {
int ret = serial8250_em485_init(up);
if (ret) {
rs485->flags &= ~SER_RS485_ENABLED;
port->rs485.flags &= ~SER_RS485_ENABLED;
}
return ret;
}
serial8250_em485_destroy(up);
return 0;
}
EXPORT_SYMBOL_GPL(serial8250_em485_config);
/*
* These two wrappers ensure that enable_runtime_pm_tx() can be called more than
* once and disable_runtime_pm_tx() will still disable RPM because the fifo is
@@ -1318,8 +1354,8 @@ out_lock:
fintek_8250_probe(up);
if (up->capabilities != old_capabilities) {
pr_warn("%s: detected caps %08x should be %08x\n",
port->name, old_capabilities, up->capabilities);
dev_warn(port->dev, "detected caps %08x should be %08x\n",
old_capabilities, up->capabilities);
}
out:
DEBUG_AUTOCONF("iir=%d ", scratch);
@@ -1394,9 +1430,21 @@ static void serial8250_stop_rx(struct uart_port *port)
serial8250_rpm_put(up);
}
static void __do_stop_tx_rs485(struct uart_8250_port *p)
/**
* serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback
* @up: uart 8250 port
*
* Generic callback usable by 8250 uart drivers to stop rs485 transmission.
*/
void serial8250_em485_stop_tx(struct uart_8250_port *p)
{
serial8250_em485_rts_after_send(p);
unsigned char mcr = serial8250_in_MCR(p);
if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
mcr |= UART_MCR_RTS;
else
mcr &= ~UART_MCR_RTS;
serial8250_out_MCR(p, mcr);
/*
* Empty the RX FIFO, we are not interested in anything
@@ -1410,6 +1458,8 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p)
serial_port_out(&p->port, UART_IER, p->ier);
}
}
EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
{
struct uart_8250_em485 *em485;
@@ -1422,8 +1472,9 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
serial8250_rpm_get(p);
spin_lock_irqsave(&p->port.lock, flags);
if (em485->active_timer == &em485->stop_tx_timer) {
__do_stop_tx_rs485(p);
p->rs485_stop_tx(p);
em485->active_timer = NULL;
em485->tx_stopped = true;
}
spin_unlock_irqrestore(&p->port.lock, flags);
serial8250_rpm_put(p);
@@ -1444,7 +1495,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p)
struct uart_8250_em485 *em485 = p->em485;
/*
* __do_stop_tx_rs485 is going to set RTS according to config
* rs485_stop_tx() is going to set RTS according to config
* AND flush RX FIFO if required.
*/
if (p->port.rs485.delay_rts_after_send > 0) {
@@ -1452,7 +1503,9 @@ static void __stop_tx_rs485(struct uart_8250_port *p)
start_hrtimer_ms(&em485->stop_tx_timer,
p->port.rs485.delay_rts_after_send);
} else {
__do_stop_tx_rs485(p);
p->rs485_stop_tx(p);
em485->active_timer = NULL;
em485->tx_stopped = true;
}
}
@@ -1477,8 +1530,6 @@ static inline void __stop_tx(struct uart_8250_port *p)
if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
return;
em485->active_timer = NULL;
__stop_tx_rs485(p);
}
__do_stop_tx(p);
@@ -1528,25 +1579,42 @@ static inline void __start_tx(struct uart_port *port)
}
}
static inline void start_tx_rs485(struct uart_port *port)
/**
* serial8250_em485_start_tx() - generic ->rs485_start_tx() callback
* @up: uart 8250 port
*
* Generic callback usable by 8250 uart drivers to start rs485 transmission.
* Assumes that setting the RTS bit in the MCR register means RTS is high.
* (Some chips use inverse semantics.) Further assumes that reception is
* stoppable by disabling the UART_IER_RDI interrupt. (Some chips set the
* UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.)
*/
void serial8250_em485_start_tx(struct uart_8250_port *up)
{
struct uart_8250_port *up = up_to_u8250p(port);
struct uart_8250_em485 *em485 = up->em485;
unsigned char mcr;
unsigned char mcr = serial8250_in_MCR(up);
if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
serial8250_stop_rx(&up->port);
if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
mcr |= UART_MCR_RTS;
else
mcr &= ~UART_MCR_RTS;
serial8250_out_MCR(up, mcr);
}
EXPORT_SYMBOL_GPL(serial8250_em485_start_tx);
static inline void start_tx_rs485(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
struct uart_8250_em485 *em485 = up->em485;
em485->active_timer = NULL;
mcr = serial8250_in_MCR(up);
if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) !=
!!(mcr & UART_MCR_RTS)) {
if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
mcr |= UART_MCR_RTS;
else
mcr &= ~UART_MCR_RTS;
serial8250_out_MCR(up, mcr);
if (em485->tx_stopped) {
em485->tx_stopped = false;
up->rs485_start_tx(up);
if (up->port.rs485.delay_rts_before_send > 0) {
em485->active_timer = &em485->start_tx_timer;
@@ -1683,7 +1751,7 @@ void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)
lsr &= port->read_status_mask;
if (lsr & UART_LSR_BI) {
pr_debug("%s: handling break\n", __func__);
dev_dbg(port->dev, "handling break\n");
flag = TTY_BREAK;
} else if (lsr & UART_LSR_PE)
flag = TTY_PARITY;
@@ -1815,6 +1883,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
unsigned char status;
unsigned long flags;
struct uart_8250_port *up = up_to_u8250p(port);
bool skip_rx = false;
if (iir & UART_IIR_NO_INT)
return 0;
@@ -1823,7 +1892,20 @@ 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)) {
/*
* If port is stopped and there are no error conditions in the
* FIFO, then don't drain the FIFO, as this may lead to TTY buffer
* overflow. Not servicing, RX FIFO would trigger auto HW flow
* control when FIFO occupancy reaches preset threshold, thus
* halting RX. This only works when auto HW flow control is
* available.
*/
if (!(status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) &&
(port->status & (UPSTAT_AUTOCTS | UPSTAT_AUTORTS)) &&
!(port->read_status_mask & UART_LSR_DR))
skip_rx = true;
if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) {
if (!up->dma || handle_rx_dma(up, iir))
status = serial8250_rx_chars(up, status);
}
@@ -1924,6 +2006,13 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char mcr;
if (port->rs485.flags & SER_RS485_ENABLED) {
if (serial8250_in_MCR(up) & UART_MCR_RTS)
mctrl |= TIOCM_RTS;
else
mctrl &= ~TIOCM_RTS;
}
mcr = serial8250_TIOCM_to_MCR(mctrl);
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
@@ -2134,7 +2223,7 @@ int serial8250_do_startup(struct uart_port *port)
*/
if (!(port->flags & UPF_BUGGY_UART) &&
(serial_port_in(port, UART_LSR) == 0xff)) {
pr_info_ratelimited("%s: LSR safety check engaged!\n", port->name);
dev_info_ratelimited(port->dev, "LSR safety check engaged!\n");
retval = -ENODEV;
goto out;
}
@@ -2166,8 +2255,7 @@ int serial8250_do_startup(struct uart_port *port)
(port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) {
/* Bounds checking of TX threshold (valid 0 to fifosize-2) */
if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) {
pr_err("%s TX FIFO Threshold errors, skipping\n",
port->name);
dev_err(port->dev, "TX FIFO Threshold errors, skipping\n");
} else {
serial_port_out(port, UART_ALTR_AFR,
UART_ALTR_EN_TXFIFO_LW);
@@ -2268,8 +2356,7 @@ int serial8250_do_startup(struct uart_port *port)
if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
if (!(up->bugs & UART_BUG_TXEN)) {
up->bugs |= UART_BUG_TXEN;
pr_debug("%s - enabling bad tx status workarounds\n",
port->name);
dev_dbg(port->dev, "enabling bad tx status workarounds\n");
}
} else {
up->bugs &= ~UART_BUG_TXEN;
@@ -2294,10 +2381,14 @@ dont_test_tx_en:
* Request DMA channels for both RX and TX.
*/
if (up->dma) {
retval = serial8250_request_dma(up);
if (retval) {
pr_warn_ratelimited("%s - failed to request DMA\n",
port->name);
const char *msg = NULL;
if (uart_console(port))
msg = "forbid DMA for kernel console";
else if (serial8250_request_dma(up))
msg = "failed to request DMA";
if (msg) {
dev_warn_ratelimited(port->dev, "%s\n", msg);
up->dma = NULL;
}
}
@@ -2880,7 +2971,7 @@ static int do_serial8250_get_rxtrig(struct tty_port *port)
return rxtrig_bytes;
}
static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
static ssize_t rx_trig_bytes_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tty_port *port = dev_get_drvdata(dev);
@@ -2926,7 +3017,7 @@ static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
return ret;
}
static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
static ssize_t rx_trig_bytes_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct tty_port *port = dev_get_drvdata(dev);
@@ -2947,18 +3038,16 @@ static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
return count;
}
static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
serial8250_get_attr_rx_trig_bytes,
serial8250_set_attr_rx_trig_bytes);
static DEVICE_ATTR_RW(rx_trig_bytes);
static struct attribute *serial8250_dev_attrs[] = {
&dev_attr_rx_trig_bytes.attr,
NULL,
};
NULL
};
static struct attribute_group serial8250_dev_attr_group = {
.attrs = serial8250_dev_attrs,
};
};
static void register_dev_spec_attr_grp(struct uart_8250_port *up)
{
@@ -2987,6 +3076,9 @@ static void serial8250_config_port(struct uart_port *port, int flags)
if (flags & UART_CONFIG_TYPE)
autoconfig(up);
if (port->rs485.flags & SER_RS485_ENABLED)
port->rs485_config(port, &port->rs485);
/* if access method is AU, it is a 16550 with a quirk */
if (port->type == PORT_16550A && port->iotype == UPIO_AU)
up->bugs |= UART_BUG_NOMSR;
@@ -3127,10 +3219,14 @@ static void serial8250_console_restore(struct uart_8250_port *up)
* any possible real use of the port...
*
* The console_lock must be held when we get here.
*
* Doing runtime PM is really a bad idea for the kernel console.
* Thus, we assume the function is called when device is powered up.
*/
void serial8250_console_write(struct uart_8250_port *up, const char *s,
unsigned int count)
{
struct uart_8250_em485 *em485 = up->em485;
struct uart_port *port = &up->port;
unsigned long flags;
unsigned int ier;
@@ -3138,8 +3234,6 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
touch_nmi_watchdog();
serial8250_rpm_get(up);
if (oops_in_progress)
locked = spin_trylock_irqsave(&port->lock, flags);
else
@@ -3161,6 +3255,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
up->canary = 0;
}
if (em485) {
if (em485->tx_stopped)
up->rs485_start_tx(up);
mdelay(port->rs485.delay_rts_before_send);
}
uart_console_write(port, s, count, serial8250_console_putchar);
/*
@@ -3168,6 +3268,13 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
if (em485) {
mdelay(port->rs485.delay_rts_after_send);
if (em485->tx_stopped)
up->rs485_stop_tx(up);
}
serial_port_out(port, UART_IER, ier);
/*
@@ -3182,7 +3289,6 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
if (locked)
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
}
static unsigned int probe_baud(struct uart_port *port)
@@ -3206,6 +3312,7 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
int bits = 8;
int parity = 'n';
int flow = 'n';
int ret;
if (!port->iobase && !port->membase)
return -ENODEV;
@@ -3215,7 +3322,22 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
else if (probe)
baud = probe_baud(port);
return uart_set_options(port, port->cons, baud, parity, bits, flow);
ret = uart_set_options(port, port->cons, baud, parity, bits, flow);
if (ret)
return ret;
if (port->dev)
pm_runtime_get_sync(port->dev);
return 0;
}
int serial8250_console_exit(struct uart_port *port)
{
if (port->dev)
pm_runtime_put_sync(port->dev);
return 0;
}
#endif /* CONFIG_SERIAL_8250_CONSOLE */

查看文件

@@ -123,7 +123,7 @@ static int serial_pxa_probe(struct platform_device *pdev)
uart.port.regshift = 2;
uart.port.irq = irqres->start;
uart.port.fifosize = 64;
uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE;
uart.port.dev = &pdev->dev;
uart.port.uartclk = clk_get_rate(data->clk);
uart.port.pm = serial_pxa_pm;

查看文件

@@ -0,0 +1,198 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Serial Port driver for Tegra devices
*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include "8250.h"
struct tegra_uart {
struct clk *clk;
struct reset_control *rst;
int line;
};
static void tegra_uart_handle_break(struct uart_port *p)
{
unsigned int status, tmout = 10000;
do {
status = p->serial_in(p, UART_LSR);
if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
status = p->serial_in(p, UART_RX);
else
break;
if (--tmout == 0)
break;
udelay(1);
} while (1);
}
static int tegra_uart_probe(struct platform_device *pdev)
{
struct uart_8250_port port8250;
struct tegra_uart *uart;
struct uart_port *port;
struct resource *res;
int ret;
uart = devm_kzalloc(&pdev->dev, sizeof(*uart), GFP_KERNEL);
if (!uart)
return -ENOMEM;
memset(&port8250, 0, sizeof(port8250));
port = &port8250.port;
spin_lock_init(&port->lock);
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT |
UPF_FIXED_TYPE;
port->iotype = UPIO_MEM32;
port->regshift = 2;
port->type = PORT_TEGRA;
port->irqflags |= IRQF_SHARED;
port->dev = &pdev->dev;
port->handle_break = tegra_uart_handle_break;
ret = of_alias_get_id(pdev->dev.of_node, "serial");
if (ret >= 0)
port->line = ret;
ret = platform_get_irq(pdev, 0);
if (ret < 0)
return ret;
port->irq = ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
port->membase = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!port->membase)
return -ENOMEM;
port->mapbase = res->start;
port->mapsize = resource_size(res);
uart->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
if (IS_ERR(uart->rst))
return PTR_ERR(uart->rst);
if (device_property_read_u32(&pdev->dev, "clock-frequency",
&port->uartclk)) {
uart->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(uart->clk)) {
dev_err(&pdev->dev, "failed to get clock!\n");
return -ENODEV;
}
ret = clk_prepare_enable(uart->clk);
if (ret < 0)
return ret;
port->uartclk = clk_get_rate(uart->clk);
}
ret = reset_control_deassert(uart->rst);
if (ret)
goto err_clkdisable;
ret = serial8250_register_8250_port(&port8250);
if (ret < 0)
goto err_clkdisable;
platform_set_drvdata(pdev, uart);
uart->line = ret;
return 0;
err_clkdisable:
clk_disable_unprepare(uart->clk);
return ret;
}
static int tegra_uart_remove(struct platform_device *pdev)
{
struct tegra_uart *uart = platform_get_drvdata(pdev);
serial8250_unregister_port(uart->line);
reset_control_assert(uart->rst);
clk_disable_unprepare(uart->clk);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int tegra_uart_suspend(struct device *dev)
{
struct tegra_uart *uart = dev_get_drvdata(dev);
struct uart_8250_port *port8250 = serial8250_get_port(uart->line);
struct uart_port *port = &port8250->port;
serial8250_suspend_port(uart->line);
if (!uart_console(port) || console_suspend_enabled)
clk_disable_unprepare(uart->clk);
return 0;
}
static int tegra_uart_resume(struct device *dev)
{
struct tegra_uart *uart = dev_get_drvdata(dev);
struct uart_8250_port *port8250 = serial8250_get_port(uart->line);
struct uart_port *port = &port8250->port;
if (!uart_console(port) || console_suspend_enabled)
clk_prepare_enable(uart->clk);
serial8250_resume_port(uart->line);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(tegra_uart_pm_ops, tegra_uart_suspend,
tegra_uart_resume);
static const struct of_device_id tegra_uart_of_match[] = {
{ .compatible = "nvidia,tegra20-uart", },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_uart_of_match);
static const struct acpi_device_id tegra_uart_acpi_match[] = {
{ "NVDA0100", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, tegra_uart_acpi_match);
static struct platform_driver tegra_uart_driver = {
.driver = {
.name = "tegra-uart",
.pm = &tegra_uart_pm_ops,
.of_match_table = tegra_uart_of_match,
.acpi_match_table = ACPI_PTR(tegra_uart_acpi_match),
},
.probe = tegra_uart_probe,
.remove = tegra_uart_remove,
};
module_platform_driver(tegra_uart_driver);
MODULE_AUTHOR("Jeff Brasen <jbrasen@nvidia.com>");
MODULE_DESCRIPTION("NVIDIA Tegra 8250 Driver");
MODULE_LICENSE("GPL v2");

查看文件

@@ -500,6 +500,15 @@ config SERIAL_8250_PXA
applicable to both devicetree and legacy boards, and early console is
part of its support.
config SERIAL_8250_TEGRA
tristate "8250 support for Tegra serial ports"
default SERIAL_8250
depends on SERIAL_8250
depends on ARCH_TEGRA || COMPILE_TEST
help
Select this option if you have machine with an NVIDIA Tegra SoC and
wish to enable 8250 serial driver for the Tegra serial interfaces.
config SERIAL_OF_PLATFORM
tristate "Devicetree based probing for 8250 ports"
depends on SERIAL_8250 && OF

查看文件

@@ -37,6 +37,7 @@ obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o
obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt

查看文件

@@ -260,15 +260,6 @@ config SERIAL_SAMSUNG_UARTS
help
Select the number of available UART ports for the Samsung S3C
serial driver
config SERIAL_SAMSUNG_DEBUG
bool "Samsung SoC serial debug"
depends on SERIAL_SAMSUNG && DEBUG_LL
help
Add support for debugging the serial driver. Since this is
generally being used as a console, we use our own output
routines that go via the low-level debug printascii()
function.
config SERIAL_SAMSUNG_CONSOLE
bool "Support for console on Samsung SoC serial port"
@@ -1111,7 +1102,7 @@ config SERIAL_SC16IS7XX_SPI
help
Enable SC16IS7xx driver on SPI bus,
If required say y, and say n to spi if not required,
This is additional support to exsisting driver.
This is additional support to existing driver.
You must select at least one bus for the driver to be built.
config SERIAL_TIMBERDALE
@@ -1279,6 +1270,7 @@ config SERIAL_AR933X
tristate "AR933X serial port support"
depends on HAVE_CLK && ATH79
select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
help
If you have an Atheros AR933X SOC based board and want to use the
built-in UART of the SoC, say Y to this option.
@@ -1452,8 +1444,8 @@ config SERIAL_MEN_Z135
config SERIAL_SPRD
tristate "Support for Spreadtrum serial"
depends on ARCH_SPRD
select SERIAL_CORE
depends on COMMON_CLK
help
This enables the driver for the Spreadtrum's serial.

查看文件

@@ -13,6 +13,7 @@
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@@ -29,6 +30,8 @@
#include <asm/mach-ath79/ar933x_uart.h>
#include "serial_mctrl_gpio.h"
#define DRIVER_NAME "ar933x-uart"
#define AR933X_UART_MAX_SCALE 0xff
@@ -47,6 +50,8 @@ struct ar933x_uart_port {
unsigned int min_baud;
unsigned int max_baud;
struct clk *clk;
struct mctrl_gpios *gpios;
struct gpio_desc *rts_gpiod;
};
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
@@ -100,6 +105,18 @@ static inline void ar933x_uart_stop_tx_interrupt(struct ar933x_uart_port *up)
ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
}
static inline void ar933x_uart_start_rx_interrupt(struct ar933x_uart_port *up)
{
up->ier |= AR933X_UART_INT_RX_VALID;
ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
}
static inline void ar933x_uart_stop_rx_interrupt(struct ar933x_uart_port *up)
{
up->ier &= ~AR933X_UART_INT_RX_VALID;
ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
}
static inline void ar933x_uart_putc(struct ar933x_uart_port *up, int ch)
{
unsigned int rdata;
@@ -125,11 +142,21 @@ static unsigned int ar933x_uart_tx_empty(struct uart_port *port)
static unsigned int ar933x_uart_get_mctrl(struct uart_port *port)
{
return TIOCM_CAR;
struct ar933x_uart_port *up =
container_of(port, struct ar933x_uart_port, port);
int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
mctrl_gpio_get(up->gpios, &ret);
return ret;
}
static void ar933x_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct ar933x_uart_port *up =
container_of(port, struct ar933x_uart_port, port);
mctrl_gpio_set(up->gpios, mctrl);
}
static void ar933x_uart_start_tx(struct uart_port *port)
@@ -140,6 +167,37 @@ static void ar933x_uart_start_tx(struct uart_port *port)
ar933x_uart_start_tx_interrupt(up);
}
static void ar933x_uart_wait_tx_complete(struct ar933x_uart_port *up)
{
unsigned int status;
unsigned int timeout = 60000;
/* Wait up to 60ms for the character(s) to be sent. */
do {
status = ar933x_uart_read(up, AR933X_UART_CS_REG);
if (--timeout == 0)
break;
udelay(1);
} while (status & AR933X_UART_CS_TX_BUSY);
if (timeout == 0)
dev_err(up->port.dev, "waiting for TX timed out\n");
}
static void ar933x_uart_rx_flush(struct ar933x_uart_port *up)
{
unsigned int status;
/* clear RX_VALID interrupt */
ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_RX_VALID);
/* remove characters from the RX FIFO */
do {
ar933x_uart_write(up, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);
status = ar933x_uart_read(up, AR933X_UART_DATA_REG);
} while (status & AR933X_UART_DATA_RX_CSR);
}
static void ar933x_uart_stop_tx(struct uart_port *port)
{
struct ar933x_uart_port *up =
@@ -153,8 +211,7 @@ static void ar933x_uart_stop_rx(struct uart_port *port)
struct ar933x_uart_port *up =
container_of(port, struct ar933x_uart_port, port);
up->ier &= ~AR933X_UART_INT_RX_VALID;
ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
ar933x_uart_stop_rx_interrupt(up);
}
static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)
@@ -336,11 +393,20 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)
static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
{
struct circ_buf *xmit = &up->port.state->xmit;
struct serial_rs485 *rs485conf = &up->port.rs485;
int count;
bool half_duplex_send = false;
if (uart_tx_stopped(&up->port))
return;
if ((rs485conf->flags & SER_RS485_ENABLED) &&
(up->port.x_char || !uart_circ_empty(xmit))) {
ar933x_uart_stop_rx_interrupt(up);
gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SEND));
half_duplex_send = true;
}
count = up->port.fifosize;
do {
unsigned int rdata;
@@ -368,8 +434,14 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port);
if (!uart_circ_empty(xmit))
if (!uart_circ_empty(xmit)) {
ar933x_uart_start_tx_interrupt(up);
} else if (half_duplex_send) {
ar933x_uart_wait_tx_complete(up);
ar933x_uart_rx_flush(up);
ar933x_uart_start_rx_interrupt(up);
gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_AFTER_SEND));
}
}
static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id)
@@ -427,8 +499,7 @@ static int ar933x_uart_startup(struct uart_port *port)
AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
/* Enable RX interrupts */
up->ier = AR933X_UART_INT_RX_VALID;
ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
ar933x_uart_start_rx_interrupt(up);
spin_unlock_irqrestore(&up->port.lock, flags);
@@ -511,6 +582,21 @@ static const struct uart_ops ar933x_uart_ops = {
.verify_port = ar933x_uart_verify_port,
};
static int ar933x_config_rs485(struct uart_port *port,
struct serial_rs485 *rs485conf)
{
struct ar933x_uart_port *up =
container_of(port, struct ar933x_uart_port, port);
if ((rs485conf->flags & SER_RS485_ENABLED) &&
!up->rts_gpiod) {
dev_err(port->dev, "RS485 needs rts-gpio\n");
return 1;
}
port->rs485 = *rs485conf;
return 0;
}
#ifdef CONFIG_SERIAL_AR933X_CONSOLE
static struct ar933x_uart_port *
ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS];
@@ -680,6 +766,8 @@ static int ar933x_uart_probe(struct platform_device *pdev)
goto err_disable_clk;
}
uart_get_rs485_mode(&pdev->dev, &port->rs485);
port->mapbase = mem_res->start;
port->line = id;
port->irq = irq_res->start;
@@ -690,6 +778,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
port->regshift = 2;
port->fifosize = AR933X_UART_FIFO_SIZE;
port->ops = &ar933x_uart_ops;
port->rs485_config = ar933x_config_rs485;
baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);
up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD);
@@ -697,6 +786,18 @@ static int ar933x_uart_probe(struct platform_device *pdev)
baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
up->gpios = mctrl_gpio_init(port, 0);
if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS)
return PTR_ERR(up->gpios);
up->rts_gpiod = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS);
if ((port->rs485.flags & SER_RS485_ENABLED) &&
!up->rts_gpiod) {
dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n");
port->rs485.flags &= ~SER_RS485_ENABLED;
}
#ifdef CONFIG_SERIAL_AR933X_CONSOLE
ar933x_console_ports[up->port.line] = up;
#endif

查看文件

@@ -20,15 +20,12 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/atmel_pdc.h>
#include <linux/uaccess.h>
#include <linux/platform_data/atmel.h>
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/suspend.h>
@@ -2679,18 +2676,8 @@ static struct console atmel_console = {
#define ATMEL_CONSOLE_DEVICE (&atmel_console)
static inline bool atmel_is_console_port(struct uart_port *port)
{
return port->cons && port->cons->index == port->line;
}
#else
#define ATMEL_CONSOLE_DEVICE NULL
static inline bool atmel_is_console_port(struct uart_port *port)
{
return false;
}
#endif
static struct uart_driver atmel_uart = {
@@ -2719,14 +2706,14 @@ static int atmel_serial_suspend(struct platform_device *pdev,
struct uart_port *port = platform_get_drvdata(pdev);
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_is_console_port(port) && console_suspend_enabled) {
if (uart_console(port) && console_suspend_enabled) {
/* Drain the TX shifter */
while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
ATMEL_US_TXEMPTY))
cpu_relax();
}
if (atmel_is_console_port(port) && !console_suspend_enabled) {
if (uart_console(port) && !console_suspend_enabled) {
/* Cache register values as we won't get a full shutdown/startup
* cycle
*/
@@ -2762,7 +2749,7 @@ static int atmel_serial_resume(struct platform_device *pdev)
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned long flags;
if (atmel_is_console_port(port) && !console_suspend_enabled) {
if (uart_console(port) && !console_suspend_enabled) {
atmel_uart_writel(port, ATMEL_US_MR, atmel_port->cache.mr);
atmel_uart_writel(port, ATMEL_US_IER, atmel_port->cache.imr);
atmel_uart_writel(port, ATMEL_US_BRGR, atmel_port->cache.brgr);
@@ -2916,7 +2903,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
goto err_add_port;
#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
if (atmel_is_console_port(&atmel_port->uart)
if (uart_console(&atmel_port->uart)
&& ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {
/*
* The serial core enabled the clock for us, so undo
@@ -2959,7 +2946,7 @@ err_add_port:
kfree(atmel_port->rx_ring.buf);
atmel_port->rx_ring.buf = NULL;
err_alloc_ring:
if (!atmel_is_console_port(&atmel_port->uart)) {
if (!uart_console(&atmel_port->uart)) {
clk_put(atmel_port->clk);
atmel_port->clk = NULL;
}

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* include/linux/atmel_serial.h
*

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Driver for CPM (SCC/SMC) serial ports
*
@@ -13,6 +13,8 @@
#include <linux/platform_device.h>
#include <linux/fs_uart_pd.h>
struct gpio_desc;
#if defined(CONFIG_CPM2)
#include "cpm_uart_cpm2.h"
#elif defined(CONFIG_CPM1)
@@ -80,7 +82,7 @@ struct uart_cpm_port {
int wait_closing;
/* value to combine with opcode to form cpm command */
u32 command;
int gpios[NUM_GPIOS];
struct gpio_desc *gpios[NUM_GPIOS];
};
extern int cpm_uart_nr;

查看文件

@@ -30,8 +30,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/clk.h>
#include <asm/io.h>
@@ -88,11 +87,11 @@ static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
struct uart_cpm_port *pinfo =
container_of(port, struct uart_cpm_port, port);
if (pinfo->gpios[GPIO_RTS] >= 0)
gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS));
if (pinfo->gpios[GPIO_RTS])
gpiod_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS));
if (pinfo->gpios[GPIO_DTR] >= 0)
gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR));
if (pinfo->gpios[GPIO_DTR])
gpiod_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR));
}
static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
@@ -101,23 +100,23 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
container_of(port, struct uart_cpm_port, port);
unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
if (pinfo->gpios[GPIO_CTS] >= 0) {
if (gpio_get_value(pinfo->gpios[GPIO_CTS]))
if (pinfo->gpios[GPIO_CTS]) {
if (gpiod_get_value(pinfo->gpios[GPIO_CTS]))
mctrl &= ~TIOCM_CTS;
}
if (pinfo->gpios[GPIO_DSR] >= 0) {
if (gpio_get_value(pinfo->gpios[GPIO_DSR]))
if (pinfo->gpios[GPIO_DSR]) {
if (gpiod_get_value(pinfo->gpios[GPIO_DSR]))
mctrl &= ~TIOCM_DSR;
}
if (pinfo->gpios[GPIO_DCD] >= 0) {
if (gpio_get_value(pinfo->gpios[GPIO_DCD]))
if (pinfo->gpios[GPIO_DCD]) {
if (gpiod_get_value(pinfo->gpios[GPIO_DCD]))
mctrl &= ~TIOCM_CAR;
}
if (pinfo->gpios[GPIO_RI] >= 0) {
if (!gpio_get_value(pinfo->gpios[GPIO_RI]))
if (pinfo->gpios[GPIO_RI]) {
if (!gpiod_get_value(pinfo->gpios[GPIO_RI]))
mctrl |= TIOCM_RNG;
}
@@ -1139,6 +1138,7 @@ static int cpm_uart_init_port(struct device_node *np,
{
const u32 *data;
void __iomem *mem, *pram;
struct device *dev = pinfo->port.dev;
int len;
int ret;
int i;
@@ -1211,29 +1211,23 @@ static int cpm_uart_init_port(struct device_node *np,
}
for (i = 0; i < NUM_GPIOS; i++) {
int gpio;
struct gpio_desc *gpiod;
pinfo->gpios[i] = -1;
pinfo->gpios[i] = NULL;
gpio = of_get_gpio(np, i);
gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS);
if (gpio_is_valid(gpio)) {
ret = gpio_request(gpio, "cpm_uart");
if (ret) {
pr_err("can't request gpio #%d: %d\n", i, ret);
continue;
}
if (gpiod) {
if (i == GPIO_RTS || i == GPIO_DTR)
ret = gpio_direction_output(gpio, 0);
ret = gpiod_direction_output(gpiod, 0);
else
ret = gpio_direction_input(gpio);
ret = gpiod_direction_input(gpiod);
if (ret) {
pr_err("can't set direction for gpio #%d: %d\n",
i, ret);
gpio_free(gpio);
continue;
}
pinfo->gpios[i] = gpio;
pinfo->gpios[i] = gpiod;
}
}

查看文件

@@ -170,6 +170,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match)
int __init setup_earlycon(char *buf)
{
const struct earlycon_id **p_match;
bool empty_compatible = true;
if (!buf || !buf[0])
return -EINVAL;
@@ -177,6 +178,7 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
again:
for (p_match = __earlycon_table; p_match < __earlycon_table_end;
p_match++) {
const struct earlycon_id *match = *p_match;
@@ -185,6 +187,10 @@ int __init setup_earlycon(char *buf)
if (strncmp(buf, match->name, len))
continue;
/* prefer entries with empty compatible */
if (empty_compatible && *match->compatible)
continue;
if (buf[len]) {
if (buf[len] != ',')
continue;
@@ -195,6 +201,11 @@ int __init setup_earlycon(char *buf)
return register_earlycon(buf, match);
}
if (empty_compatible) {
empty_compatible = false;
goto again;
}
return -ENOENT;
}

查看文件

@@ -200,7 +200,7 @@ static void efm32_uart_rx_chars(struct efm32_uart_port *efm_port)
/*
* This is a reserved bit and I only saw it read as 0. But to be
* sure not to be confused too much by new devices adhere to the
* warning in the reference manual that reserverd bits might
* warning in the reference manual that reserved bits might
* read as 1 in the future.
*/
rxdata &= ~SW_UARTn_RXDATAX_BERR;

查看文件

@@ -234,6 +234,7 @@ static DEFINE_IDA(fsl_lpuart_ida);
enum lpuart_type {
VF610_LPUART,
LS1021A_LPUART,
LS1028A_LPUART,
IMX7ULP_LPUART,
IMX8QXP_LPUART,
};
@@ -278,11 +279,16 @@ static const struct lpuart_soc_data vf_data = {
.iotype = UPIO_MEM,
};
static const struct lpuart_soc_data ls_data = {
static const struct lpuart_soc_data ls1021a_data = {
.devtype = LS1021A_LPUART,
.iotype = UPIO_MEM32BE,
};
static const struct lpuart_soc_data ls1028a_data = {
.devtype = LS1028A_LPUART,
.iotype = UPIO_MEM32,
};
static struct lpuart_soc_data imx7ulp_data = {
.devtype = IMX7ULP_LPUART,
.iotype = UPIO_MEM32,
@@ -297,7 +303,8 @@ static struct lpuart_soc_data imx8qxp_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,ls1021a-lpuart", .data = &ls1021a_data, },
{ .compatible = "fsl,ls1028a-lpuart", .data = &ls1028a_data, },
{ .compatible = "fsl,imx7ulp-lpuart", .data = &imx7ulp_data, },
{ .compatible = "fsl,imx8qxp-lpuart", .data = &imx8qxp_data, },
{ /* sentinel */ }
@@ -307,6 +314,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_ls1028a_lpuart(struct lpuart_port *sport)
{
return sport->devtype == LS1028A_LPUART;
}
static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
{
return sport->devtype == IMX8QXP_LPUART;
@@ -409,6 +421,7 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
struct circ_buf *xmit = &sport->port.state->xmit;
struct scatterlist *sgl = sport->tx_sgl;
struct device *dev = sport->port.dev;
struct dma_chan *chan = sport->dma_tx_chan;
int ret;
if (sport->dma_tx_in_progress)
@@ -427,17 +440,19 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
sg_set_buf(sgl + 1, xmit->buf, xmit->head);
}
ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
ret = dma_map_sg(chan->device->dev, sgl, sport->dma_tx_nents,
DMA_TO_DEVICE);
if (!ret) {
dev_err(dev, "DMA mapping error for TX.\n");
return;
}
sport->dma_tx_desc = dmaengine_prep_slave_sg(sport->dma_tx_chan, sgl,
sport->dma_tx_desc = dmaengine_prep_slave_sg(chan, sgl,
ret, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT);
if (!sport->dma_tx_desc) {
dma_unmap_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents,
DMA_TO_DEVICE);
dev_err(dev, "Cannot prepare TX slave DMA!\n");
return;
}
@@ -446,7 +461,7 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
sport->dma_tx_desc->callback_param = sport;
sport->dma_tx_in_progress = true;
sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
dma_async_issue_pending(sport->dma_tx_chan);
dma_async_issue_pending(chan);
}
static bool lpuart_stopped_or_empty(struct uart_port *port)
@@ -459,11 +474,13 @@ static void lpuart_dma_tx_complete(void *arg)
struct lpuart_port *sport = arg;
struct scatterlist *sgl = &sport->tx_sgl[0];
struct circ_buf *xmit = &sport->port.state->xmit;
struct dma_chan *chan = sport->dma_tx_chan;
unsigned long flags;
spin_lock_irqsave(&sport->port.lock, flags);
dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents,
DMA_TO_DEVICE);
xmit->tail = (xmit->tail + sport->dma_tx_bytes) & (UART_XMIT_SIZE - 1);
@@ -529,15 +546,16 @@ static bool lpuart_is_32(struct lpuart_port *sport)
static void lpuart_flush_buffer(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
struct dma_chan *chan = sport->dma_tx_chan;
u32 val;
if (sport->lpuart_dma_tx_use) {
if (sport->dma_tx_in_progress) {
dma_unmap_sg(sport->port.dev, &sport->tx_sgl[0],
dma_unmap_sg(chan->device->dev, &sport->tx_sgl[0],
sport->dma_tx_nents, DMA_TO_DEVICE);
sport->dma_tx_in_progress = false;
}
dmaengine_terminate_all(sport->dma_tx_chan);
dmaengine_terminate_all(chan);
}
if (lpuart_is_32(sport)) {
@@ -993,6 +1011,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
struct tty_port *port = &sport->port.state->port;
struct dma_tx_state state;
enum dma_status dmastat;
struct dma_chan *chan = sport->dma_rx_chan;
struct circ_buf *ring = &sport->rx_ring;
unsigned long flags;
int count = 0;
@@ -1053,10 +1072,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
spin_lock_irqsave(&sport->port.lock, flags);
dmastat = dmaengine_tx_status(sport->dma_rx_chan,
sport->dma_rx_cookie,
&state);
dmastat = dmaengine_tx_status(chan, sport->dma_rx_cookie, &state);
if (dmastat == DMA_ERROR) {
dev_err(sport->port.dev, "Rx DMA transfer failed!\n");
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1064,7 +1080,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
}
/* CPU claims ownership of RX DMA buffer */
dma_sync_sg_for_cpu(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
dma_sync_sg_for_cpu(chan->device->dev, &sport->rx_sgl, 1,
DMA_FROM_DEVICE);
/*
* ring->head points to the end of data already written by the DMA.
@@ -1106,7 +1123,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
sport->port.icount.rx += count;
}
dma_sync_sg_for_device(sport->port.dev, &sport->rx_sgl, 1,
dma_sync_sg_for_device(chan->device->dev, &sport->rx_sgl, 1,
DMA_FROM_DEVICE);
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1138,6 +1155,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
struct tty_port *port = &sport->port.state->port;
struct tty_struct *tty = port->tty;
struct ktermios *termios = &tty->termios;
struct dma_chan *chan = sport->dma_rx_chan;
baud = tty_get_baud_rate(tty);
@@ -1159,7 +1177,8 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
return -ENOMEM;
sg_init_one(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len);
nent = dma_map_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
nent = dma_map_sg(chan->device->dev, &sport->rx_sgl, 1,
DMA_FROM_DEVICE);
if (!nent) {
dev_err(sport->port.dev, "DMA Rx mapping error\n");
@@ -1170,7 +1189,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_rx_sconfig.src_maxburst = 1;
dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
ret = dmaengine_slave_config(sport->dma_rx_chan, &dma_rx_sconfig);
ret = dmaengine_slave_config(chan, &dma_rx_sconfig);
if (ret < 0) {
dev_err(sport->port.dev,
@@ -1178,7 +1197,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
return ret;
}
sport->dma_rx_desc = dmaengine_prep_dma_cyclic(sport->dma_rx_chan,
sport->dma_rx_desc = dmaengine_prep_dma_cyclic(chan,
sg_dma_address(&sport->rx_sgl),
sport->rx_sgl.length,
sport->rx_sgl.length / 2,
@@ -1192,7 +1211,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
sport->dma_rx_desc->callback_param = sport;
sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc);
dma_async_issue_pending(sport->dma_rx_chan);
dma_async_issue_pending(chan);
if (lpuart_is_32(sport)) {
unsigned long temp = lpuart32_read(&sport->port, UARTBAUD);
@@ -1210,11 +1229,12 @@ static void lpuart_dma_rx_free(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
struct dma_chan *chan = sport->dma_rx_chan;
if (sport->dma_rx_chan)
dmaengine_terminate_all(sport->dma_rx_chan);
if (chan)
dmaengine_terminate_all(chan);
dma_unmap_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
kfree(sport->rx_ring.buf);
sport->rx_ring.tail = 0;
sport->rx_ring.head = 0;
@@ -1490,39 +1510,77 @@ static void rx_dma_timer_init(struct lpuart_port *sport)
add_timer(&sport->lpuart_timer);
}
static void lpuart_request_dma(struct lpuart_port *sport)
{
sport->dma_tx_chan = dma_request_chan(sport->port.dev, "tx");
if (IS_ERR(sport->dma_tx_chan)) {
dev_info_once(sport->port.dev,
"DMA tx channel request failed, operating without tx DMA (%ld)\n",
PTR_ERR(sport->dma_tx_chan));
sport->dma_tx_chan = NULL;
}
sport->dma_rx_chan = dma_request_chan(sport->port.dev, "rx");
if (IS_ERR(sport->dma_rx_chan)) {
dev_info_once(sport->port.dev,
"DMA rx channel request failed, operating without rx DMA (%ld)\n",
PTR_ERR(sport->dma_rx_chan));
sport->dma_rx_chan = NULL;
}
}
static void lpuart_tx_dma_startup(struct lpuart_port *sport)
{
u32 uartbaud;
int ret;
if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) {
init_waitqueue_head(&sport->dma_wait);
sport->lpuart_dma_tx_use = true;
if (lpuart_is_32(sport)) {
uartbaud = lpuart32_read(&sport->port, UARTBAUD);
lpuart32_write(&sport->port,
uartbaud | UARTBAUD_TDMAE, UARTBAUD);
} else {
writeb(readb(sport->port.membase + UARTCR5) |
UARTCR5_TDMAS, sport->port.membase + UARTCR5);
}
if (!sport->dma_tx_chan)
goto err;
ret = lpuart_dma_tx_request(&sport->port);
if (ret)
goto err;
init_waitqueue_head(&sport->dma_wait);
sport->lpuart_dma_tx_use = true;
if (lpuart_is_32(sport)) {
uartbaud = lpuart32_read(&sport->port, UARTBAUD);
lpuart32_write(&sport->port,
uartbaud | UARTBAUD_TDMAE, UARTBAUD);
} else {
sport->lpuart_dma_tx_use = false;
writeb(readb(sport->port.membase + UARTCR5) |
UARTCR5_TDMAS, sport->port.membase + UARTCR5);
}
return;
err:
sport->lpuart_dma_tx_use = false;
}
static void lpuart_rx_dma_startup(struct lpuart_port *sport)
{
if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
/* set Rx DMA timeout */
sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
if (!sport->dma_rx_timeout)
sport->dma_rx_timeout = 1;
int ret;
sport->lpuart_dma_rx_use = true;
rx_dma_timer_init(sport);
} else {
sport->lpuart_dma_rx_use = false;
}
if (!sport->dma_rx_chan)
goto err;
ret = lpuart_start_rx_dma(sport);
if (ret)
goto err;
/* set Rx DMA timeout */
sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
if (!sport->dma_rx_timeout)
sport->dma_rx_timeout = 1;
sport->lpuart_dma_rx_use = true;
rx_dma_timer_init(sport);
return;
err:
sport->lpuart_dma_rx_use = false;
}
static int lpuart_startup(struct uart_port *port)
@@ -1541,6 +1599,8 @@ static int lpuart_startup(struct uart_port *port)
sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_RXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK);
lpuart_request_dma(sport);
spin_lock_irqsave(&sport->port.lock, flags);
lpuart_setup_watermark_enable(sport);
@@ -1587,11 +1647,23 @@ static int lpuart32_startup(struct uart_port *port)
sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_RXSIZE_OFF) &
UARTFIFO_FIFOSIZE_MASK);
/*
* The LS1028A has a fixed length of 16 words. Although it supports the
* RX/TXSIZE fields their encoding is different. Eg the reference manual
* states 0b101 is 16 words.
*/
if (is_ls1028a_lpuart(sport)) {
sport->rxfifo_size = 16;
sport->txfifo_size = 16;
sport->port.fifosize = sport->txfifo_size;
}
lpuart_request_dma(sport);
spin_lock_irqsave(&sport->port.lock, flags);
lpuart32_setup_watermark_enable(sport);
lpuart_rx_dma_startup(sport);
lpuart_tx_dma_startup(sport);
@@ -1615,6 +1687,11 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport)
dmaengine_terminate_all(sport->dma_tx_chan);
}
}
if (sport->dma_tx_chan)
dma_release_channel(sport->dma_tx_chan);
if (sport->dma_rx_chan)
dma_release_channel(sport->dma_rx_chan);
}
static void lpuart_shutdown(struct uart_port *port)
@@ -1811,11 +1888,12 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
spin_unlock_irqrestore(&sport->port.lock, flags);
}
static void
lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
static void __lpuart32_serial_setbrg(struct uart_port *port,
unsigned int baudrate, bool use_rx_dma,
bool use_tx_dma)
{
u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
u32 clk = sport->port.uartclk;
u32 clk = port->uartclk;
/*
* The idea is to use the best OSR (over-sampling rate) possible.
@@ -1861,10 +1939,10 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
/* handle buadrate outside acceptable rate */
if (baud_diff > ((baudrate / 100) * 3))
dev_warn(sport->port.dev,
dev_warn(port->dev,
"unacceptable baud rate difference of more than 3%%\n");
tmp = lpuart32_read(&sport->port, UARTBAUD);
tmp = lpuart32_read(port, UARTBAUD);
if ((osr > 3) && (osr < 8))
tmp |= UARTBAUD_BOTHEDGE;
@@ -1875,14 +1953,23 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
tmp &= ~UARTBAUD_SBR_MASK;
tmp |= sbr & UARTBAUD_SBR_MASK;
if (!sport->lpuart_dma_rx_use)
if (!use_rx_dma)
tmp &= ~UARTBAUD_RDMAE;
if (!sport->lpuart_dma_tx_use)
if (!use_tx_dma)
tmp &= ~UARTBAUD_TDMAE;
lpuart32_write(&sport->port, tmp, UARTBAUD);
lpuart32_write(port, tmp, UARTBAUD);
}
static void lpuart32_serial_setbrg(struct lpuart_port *sport,
unsigned int baudrate)
{
__lpuart32_serial_setbrg(&sport->port, baudrate,
sport->lpuart_dma_rx_use,
sport->lpuart_dma_tx_use);
}
static void
lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
@@ -2376,6 +2463,30 @@ static int __init lpuart32_early_console_setup(struct earlycon_device *device,
return 0;
}
static int __init ls1028a_early_console_setup(struct earlycon_device *device,
const char *opt)
{
u32 cr;
if (!device->port.membase)
return -ENODEV;
device->port.iotype = UPIO_MEM32;
device->con->write = lpuart32_early_write;
/* set the baudrate */
if (device->port.uartclk && device->baud)
__lpuart32_serial_setbrg(&device->port, device->baud,
false, false);
/* enable transmitter */
cr = lpuart32_read(&device->port, UARTCTRL);
cr |= UARTCTRL_TE;
lpuart32_write(&device->port, cr, UARTCTRL);
return 0;
}
static int __init lpuart32_imx_early_console_setup(struct earlycon_device *device,
const char *opt)
{
@@ -2390,6 +2501,7 @@ static int __init lpuart32_imx_early_console_setup(struct earlycon_device *devic
}
OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
@@ -2520,16 +2632,6 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.rs485_config(&sport->port, &sport->port.rs485);
sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
if (!sport->dma_tx_chan)
dev_info(sport->port.dev, "DMA tx channel request failed, "
"operating without tx DMA\n");
sport->dma_rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
if (!sport->dma_rx_chan)
dev_info(sport->port.dev, "DMA rx channel request failed, "
"operating without rx DMA\n");
return 0;
failed_attach_port:

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* icom.h
*

查看文件

@@ -39,7 +39,7 @@
#include <linux/fs.h>
#include <linux/ip.h>
#include <linux/dmapool.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/wait.h>
@@ -61,7 +61,6 @@
#define IFX_SPI_HEADER_F (-2)
#define PO_POST_DELAY 200
#define IFX_MDM_RST_PMU 4
/* forward reference */
static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
@@ -81,7 +80,7 @@ static struct notifier_block ifx_modem_reboot_notifier_block = {
static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev)
{
gpio_set_value(IFX_MDM_RST_PMU, 1);
gpiod_set_value(ifx_dev->gpio.pmu_reset, 1);
msleep(PO_POST_DELAY);
return 0;
@@ -107,7 +106,7 @@ static int ifx_modem_reboot_callback(struct notifier_block *nfb,
*/
static inline void mrdy_set_high(struct ifx_spi_device *ifx)
{
gpio_set_value(ifx->gpio.mrdy, 1);
gpiod_set_value(ifx->gpio.mrdy, 1);
}
/**
@@ -117,7 +116,7 @@ static inline void mrdy_set_high(struct ifx_spi_device *ifx)
*/
static inline void mrdy_set_low(struct ifx_spi_device *ifx)
{
gpio_set_value(ifx->gpio.mrdy, 0);
gpiod_set_value(ifx->gpio.mrdy, 0);
}
/**
@@ -244,7 +243,7 @@ static inline void swap_buf_32(unsigned char *buf, int len, void *end)
*/
static void mrdy_assert(struct ifx_spi_device *ifx_dev)
{
int val = gpio_get_value(ifx_dev->gpio.srdy);
int val = gpiod_get_value(ifx_dev->gpio.srdy);
if (!val) {
if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,
&ifx_dev->flags)) {
@@ -691,7 +690,7 @@ complete_exit:
clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &(ifx_dev->flags));
queue_length = kfifo_len(&ifx_dev->tx_fifo);
srdy = gpio_get_value(ifx_dev->gpio.srdy);
srdy = gpiod_get_value(ifx_dev->gpio.srdy);
if (!srdy)
ifx_spi_power_state_clear(ifx_dev, IFX_SPI_POWER_SRDY);
@@ -898,7 +897,7 @@ static irqreturn_t ifx_spi_srdy_interrupt(int irq, void *dev)
static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
{
struct ifx_spi_device *ifx_dev = dev;
int val = gpio_get_value(ifx_dev->gpio.reset_out);
int val = gpiod_get_value(ifx_dev->gpio.reset_out);
int solreset = test_bit(MR_START, &ifx_dev->mdm_reset_state);
if (val == 0) {
@@ -954,14 +953,14 @@ static int ifx_spi_reset(struct ifx_spi_device *ifx_dev)
* to reset properly
*/
set_bit(MR_START, &ifx_dev->mdm_reset_state);
gpio_set_value(ifx_dev->gpio.po, 0);
gpio_set_value(ifx_dev->gpio.reset, 0);
gpiod_set_value(ifx_dev->gpio.po, 0);
gpiod_set_value(ifx_dev->gpio.reset, 0);
msleep(25);
gpio_set_value(ifx_dev->gpio.reset, 1);
gpiod_set_value(ifx_dev->gpio.reset, 1);
msleep(1);
gpio_set_value(ifx_dev->gpio.po, 1);
gpiod_set_value(ifx_dev->gpio.po, 1);
msleep(1);
gpio_set_value(ifx_dev->gpio.po, 0);
gpiod_set_value(ifx_dev->gpio.po, 0);
ret = wait_event_timeout(ifx_dev->mdm_reset_wait,
test_bit(MR_COMPLETE,
&ifx_dev->mdm_reset_state),
@@ -992,22 +991,23 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
int srdy;
struct ifx_modem_platform_data *pl_data;
struct ifx_spi_device *ifx_dev;
struct device *dev = &spi->dev;
if (saved_ifx_dev) {
dev_dbg(&spi->dev, "ignoring subsequent detection");
dev_dbg(dev, "ignoring subsequent detection");
return -ENODEV;
}
pl_data = dev_get_platdata(&spi->dev);
pl_data = dev_get_platdata(dev);
if (!pl_data) {
dev_err(&spi->dev, "missing platform data!");
dev_err(dev, "missing platform data!");
return -ENODEV;
}
/* initialize structure to hold our device variables */
ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL);
if (!ifx_dev) {
dev_err(&spi->dev, "spi device allocation failed");
dev_err(dev, "spi device allocation failed");
return -ENOMEM;
}
saved_ifx_dev = ifx_dev;
@@ -1026,7 +1026,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
spi->bits_per_word = spi_bpw;
ret = spi_setup(spi);
if (ret) {
dev_err(&spi->dev, "SPI setup wasn't successful %d", ret);
dev_err(dev, "SPI setup wasn't successful %d", ret);
kfree(ifx_dev);
return -ENODEV;
}
@@ -1049,7 +1049,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
&ifx_dev->tx_bus,
GFP_KERNEL);
if (!ifx_dev->tx_buffer) {
dev_err(&spi->dev, "DMA-TX buffer allocation failed");
dev_err(dev, "DMA-TX buffer allocation failed");
ret = -ENOMEM;
goto error_ret;
}
@@ -1058,7 +1058,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
&ifx_dev->rx_bus,
GFP_KERNEL);
if (!ifx_dev->rx_buffer) {
dev_err(&spi->dev, "DMA-RX buffer allocation failed");
dev_err(dev, "DMA-RX buffer allocation failed");
ret = -ENOMEM;
goto error_ret;
}
@@ -1075,122 +1075,83 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
/* create our tty port */
ret = ifx_spi_create_port(ifx_dev);
if (ret != 0) {
dev_err(&spi->dev, "create default tty port failed");
dev_err(dev, "create default tty port failed");
goto error_ret;
}
ifx_dev->gpio.reset = pl_data->rst_pmu;
ifx_dev->gpio.po = pl_data->pwr_on;
ifx_dev->gpio.mrdy = pl_data->mrdy;
ifx_dev->gpio.srdy = pl_data->srdy;
ifx_dev->gpio.reset_out = pl_data->rst_out;
dev_info(&spi->dev, "gpios %d, %d, %d, %d, %d",
ifx_dev->gpio.reset, ifx_dev->gpio.po, ifx_dev->gpio.mrdy,
ifx_dev->gpio.srdy, ifx_dev->gpio.reset_out);
/* Configure gpios */
ret = gpio_request(ifx_dev->gpio.reset, "ifxModem");
if (ret < 0) {
dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET)",
ifx_dev->gpio.reset);
ifx_dev->gpio.reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(ifx_dev->gpio.reset)) {
dev_err(dev, "could not obtain reset GPIO\n");
ret = PTR_ERR(ifx_dev->gpio.reset);
goto error_ret;
}
ret += gpio_direction_output(ifx_dev->gpio.reset, 0);
ret += gpio_export(ifx_dev->gpio.reset, 1);
if (ret) {
dev_err(&spi->dev, "Unable to configure GPIO%d (RESET)",
ifx_dev->gpio.reset);
ret = -EBUSY;
goto error_ret2;
gpiod_set_consumer_name(ifx_dev->gpio.reset, "ifxModem reset");
ifx_dev->gpio.po = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW);
if (IS_ERR(ifx_dev->gpio.po)) {
dev_err(dev, "could not obtain power GPIO\n");
ret = PTR_ERR(ifx_dev->gpio.po);
goto error_ret;
}
gpiod_set_consumer_name(ifx_dev->gpio.po, "ifxModem power");
ifx_dev->gpio.mrdy = devm_gpiod_get(dev, "mrdy", GPIOD_OUT_LOW);
if (IS_ERR(ifx_dev->gpio.mrdy)) {
dev_err(dev, "could not obtain mrdy GPIO\n");
ret = PTR_ERR(ifx_dev->gpio.mrdy);
goto error_ret;
}
gpiod_set_consumer_name(ifx_dev->gpio.mrdy, "ifxModem mrdy");
ifx_dev->gpio.srdy = devm_gpiod_get(dev, "srdy", GPIOD_IN);
if (IS_ERR(ifx_dev->gpio.srdy)) {
dev_err(dev, "could not obtain srdy GPIO\n");
ret = PTR_ERR(ifx_dev->gpio.srdy);
goto error_ret;
}
gpiod_set_consumer_name(ifx_dev->gpio.srdy, "ifxModem srdy");
ifx_dev->gpio.reset_out = devm_gpiod_get(dev, "rst_out", GPIOD_IN);
if (IS_ERR(ifx_dev->gpio.reset_out)) {
dev_err(dev, "could not obtain rst_out GPIO\n");
ret = PTR_ERR(ifx_dev->gpio.reset_out);
goto error_ret;
}
gpiod_set_consumer_name(ifx_dev->gpio.reset_out, "ifxModem reset out");
ifx_dev->gpio.pmu_reset = devm_gpiod_get(dev, "pmu_reset", GPIOD_ASIS);
if (IS_ERR(ifx_dev->gpio.pmu_reset)) {
dev_err(dev, "could not obtain pmu_reset GPIO\n");
ret = PTR_ERR(ifx_dev->gpio.pmu_reset);
goto error_ret;
}
gpiod_set_consumer_name(ifx_dev->gpio.pmu_reset, "ifxModem PMU reset");
ret = gpio_request(ifx_dev->gpio.po, "ifxModem");
ret += gpio_direction_output(ifx_dev->gpio.po, 0);
ret += gpio_export(ifx_dev->gpio.po, 1);
if (ret) {
dev_err(&spi->dev, "Unable to configure GPIO%d (ON)",
ifx_dev->gpio.po);
ret = -EBUSY;
goto error_ret3;
}
ret = gpio_request(ifx_dev->gpio.mrdy, "ifxModem");
if (ret < 0) {
dev_err(&spi->dev, "Unable to allocate GPIO%d (MRDY)",
ifx_dev->gpio.mrdy);
goto error_ret3;
}
ret += gpio_export(ifx_dev->gpio.mrdy, 1);
ret += gpio_direction_output(ifx_dev->gpio.mrdy, 0);
if (ret) {
dev_err(&spi->dev, "Unable to configure GPIO%d (MRDY)",
ifx_dev->gpio.mrdy);
ret = -EBUSY;
goto error_ret4;
}
ret = gpio_request(ifx_dev->gpio.srdy, "ifxModem");
if (ret < 0) {
dev_err(&spi->dev, "Unable to allocate GPIO%d (SRDY)",
ifx_dev->gpio.srdy);
ret = -EBUSY;
goto error_ret4;
}
ret += gpio_export(ifx_dev->gpio.srdy, 1);
ret += gpio_direction_input(ifx_dev->gpio.srdy);
if (ret) {
dev_err(&spi->dev, "Unable to configure GPIO%d (SRDY)",
ifx_dev->gpio.srdy);
ret = -EBUSY;
goto error_ret5;
}
ret = gpio_request(ifx_dev->gpio.reset_out, "ifxModem");
if (ret < 0) {
dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET_OUT)",
ifx_dev->gpio.reset_out);
goto error_ret5;
}
ret += gpio_export(ifx_dev->gpio.reset_out, 1);
ret += gpio_direction_input(ifx_dev->gpio.reset_out);
if (ret) {
dev_err(&spi->dev, "Unable to configure GPIO%d (RESET_OUT)",
ifx_dev->gpio.reset_out);
ret = -EBUSY;
goto error_ret6;
}
ret = request_irq(gpio_to_irq(ifx_dev->gpio.reset_out),
ret = request_irq(gpiod_to_irq(ifx_dev->gpio.reset_out),
ifx_spi_reset_interrupt,
IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME,
ifx_dev);
if (ret) {
dev_err(&spi->dev, "Unable to get irq %x\n",
gpio_to_irq(ifx_dev->gpio.reset_out));
goto error_ret6;
dev_err(dev, "Unable to get irq %x\n",
gpiod_to_irq(ifx_dev->gpio.reset_out));
goto error_ret;
}
ret = ifx_spi_reset(ifx_dev);
ret = request_irq(gpio_to_irq(ifx_dev->gpio.srdy),
ret = request_irq(gpiod_to_irq(ifx_dev->gpio.srdy),
ifx_spi_srdy_interrupt, IRQF_TRIGGER_RISING, DRVNAME,
ifx_dev);
if (ret) {
dev_err(&spi->dev, "Unable to get irq %x",
gpio_to_irq(ifx_dev->gpio.srdy));
goto error_ret7;
dev_err(dev, "Unable to get irq %x",
gpiod_to_irq(ifx_dev->gpio.srdy));
goto error_ret2;
}
/* set pm runtime power state and register with power system */
pm_runtime_set_active(&spi->dev);
pm_runtime_enable(&spi->dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
/* handle case that modem is already signaling SRDY */
/* no outgoing tty open at this point, this just satisfies the
* modem's read and should reset communication properly
*/
srdy = gpio_get_value(ifx_dev->gpio.srdy);
srdy = gpiod_get_value(ifx_dev->gpio.srdy);
if (srdy) {
mrdy_assert(ifx_dev);
@@ -1199,18 +1160,8 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
mrdy_set_low(ifx_dev);
return 0;
error_ret7:
free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev);
error_ret6:
gpio_free(ifx_dev->gpio.srdy);
error_ret5:
gpio_free(ifx_dev->gpio.mrdy);
error_ret4:
gpio_free(ifx_dev->gpio.reset);
error_ret3:
gpio_free(ifx_dev->gpio.po);
error_ret2:
gpio_free(ifx_dev->gpio.reset_out);
free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev);
error_ret:
ifx_spi_free_device(ifx_dev);
saved_ifx_dev = NULL;
@@ -1234,14 +1185,8 @@ static int ifx_spi_spi_remove(struct spi_device *spi)
pm_runtime_disable(&spi->dev);
/* free irq */
free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev);
free_irq(gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev);
gpio_free(ifx_dev->gpio.srdy);
gpio_free(ifx_dev->gpio.mrdy);
gpio_free(ifx_dev->gpio.reset);
gpio_free(ifx_dev->gpio.po);
gpio_free(ifx_dev->gpio.reset_out);
free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev);
free_irq(gpiod_to_irq(ifx_dev->gpio.srdy), ifx_dev);
/* free allocations */
ifx_spi_free_device(ifx_dev);

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
/****************************************************************************
*
* Driver for the IFX spi modem.
@@ -10,6 +10,8 @@
#ifndef _IFX6X60_H
#define _IFX6X60_H
struct gpio_desc;
#define DRVNAME "ifx6x60"
#define TTYNAME "ttyIFX"
@@ -94,11 +96,12 @@ struct ifx_spi_device {
struct {
/* gpio lines */
unsigned short srdy; /* slave-ready gpio */
unsigned short mrdy; /* master-ready gpio */
unsigned short reset; /* modem-reset gpio */
unsigned short po; /* modem-on gpio */
unsigned short reset_out; /* modem-in-reset gpio */
struct gpio_desc *srdy; /* slave-ready gpio */
struct gpio_desc *mrdy; /* master-ready gpio */
struct gpio_desc *reset; /* modem-reset gpio */
struct gpio_desc *po; /* modem-on gpio */
struct gpio_desc *reset_out; /* modem-in-reset gpio */
struct gpio_desc *pmu_reset; /* PMU reset gpio */
/* state/stats */
int unack_srdy_int_nb;
} gpio;

查看文件

@@ -195,6 +195,8 @@ struct imx_port {
unsigned int have_rtscts:1;
unsigned int have_rtsgpio:1;
unsigned int dte_mode:1;
unsigned int inverted_tx:1;
unsigned int inverted_rx:1;
struct clk *clk_ipg;
struct clk *clk_per;
const struct imx_uart_data *devdata;
@@ -1335,7 +1337,7 @@ static int imx_uart_startup(struct uart_port *port)
int retval, i;
unsigned long flags;
int dma_is_inited = 0;
u32 ucr1, ucr2, ucr4;
u32 ucr1, ucr2, ucr3, ucr4;
retval = clk_prepare_enable(sport->clk_per);
if (retval)
@@ -1387,11 +1389,29 @@ static int imx_uart_startup(struct uart_port *port)
imx_uart_writel(sport, ucr1, UCR1);
ucr4 = imx_uart_readl(sport, UCR4) & ~UCR4_OREN;
ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR);
if (!sport->dma_is_enabled)
ucr4 |= UCR4_OREN;
if (sport->inverted_rx)
ucr4 |= UCR4_INVR;
imx_uart_writel(sport, ucr4, UCR4);
ucr3 = imx_uart_readl(sport, UCR3) & ~UCR3_INVT;
/*
* configure tx polarity before enabling tx
*/
if (sport->inverted_tx)
ucr3 |= UCR3_INVT;
if (!imx_uart_is_imx1(sport)) {
ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
if (sport->dte_mode)
/* disable broken interrupts */
ucr3 &= ~(UCR3_RI | UCR3_DCD);
}
imx_uart_writel(sport, ucr3, UCR3);
ucr2 = imx_uart_readl(sport, UCR2) & ~UCR2_ATEN;
ucr2 |= (UCR2_RXEN | UCR2_TXEN);
if (!sport->have_rtscts)
@@ -1404,20 +1424,6 @@ static int imx_uart_startup(struct uart_port *port)
ucr2 &= ~UCR2_RTSEN;
imx_uart_writel(sport, ucr2, UCR2);
if (!imx_uart_is_imx1(sport)) {
u32 ucr3;
ucr3 = imx_uart_readl(sport, UCR3);
ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
if (sport->dte_mode)
/* disable broken interrupts */
ucr3 &= ~(UCR3_RI | UCR3_DCD);
imx_uart_writel(sport, ucr3, UCR3);
}
/*
* Enable modem status interrupts
*/
@@ -2184,6 +2190,12 @@ static int imx_uart_probe_dt(struct imx_port *sport,
if (of_get_property(np, "rts-gpios", NULL))
sport->have_rtsgpio = 1;
if (of_get_property(np, "fsl,inverted-tx", NULL))
sport->inverted_tx = 1;
if (of_get_property(np, "fsl,inverted-rx", NULL))
sport->inverted_rx = 1;
return 0;
}
#else

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/* SPDX-License-Identifier: GPL-2.0+ */
/************************************************************************
* Copyright 2003 Digi International (www.digi.com)
*

查看文件

@@ -169,15 +169,13 @@ static int configure_kgdboc(void)
if (!p)
goto noconfig;
cons = console_drivers;
while (cons) {
for_each_console(cons) {
int idx;
if (cons->device && cons->device(cons, &idx) == p &&
idx == tty_line) {
kgdboc_io_ops.is_console = 1;
break;
}
cons = cons->next;
}
kgdb_tty_driver = p;

查看文件

@@ -11,7 +11,6 @@
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>

查看文件

@@ -37,8 +37,6 @@
#include <linux/of_gpio.h>
#include <linux/platform_data/serial-omap.h>
#include <dt-bindings/gpio/gpio.h>
#define OMAP_MAX_HSUART_PORTS 10
#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y))

查看文件

@@ -310,32 +310,32 @@ static ssize_t port_show_regs(struct file *file, char __user *user_buf,
if (!buf)
return 0;
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"PCH EG20T port[%d] regs:\n", priv->port.line);
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"=================================\n");
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"IER: \t0x%02x\n", ioread8(priv->membase + UART_IER));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"BRCSR: \t0x%02x\n",
ioread8(priv->membase + PCH_UART_BRCSR));
lcr = ioread8(priv->membase + UART_LCR);
iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL));
len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,
"DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM));
iowrite8(lcr, priv->membase + UART_LCR);

查看文件

@@ -768,11 +768,6 @@ static int __init pic32_console_init(void)
}
console_initcall(pic32_console_init);
static inline bool is_pic32_console_port(struct uart_port *port)
{
return port->cons && port->cons->index == port->line;
}
/*
* Late console initialization.
*/
@@ -873,8 +868,7 @@ static int pic32_uart_probe(struct platform_device *pdev)
}
#ifdef CONFIG_SERIAL_PIC32_CONSOLE
if (is_pic32_console_port(port) &&
(pic32_console.flags & CON_ENABLED)) {
if (uart_console(port) && (pic32_console.flags & CON_ENABLED)) {
/* The peripheral clock has been enabled by console_setup,
* so disable it till the port is used.
*/

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* PIC32 Integrated Serial Driver.
*

查看文件

@@ -21,6 +21,7 @@
/* UART specific GENI registers */
#define SE_UART_LOOPBACK_CFG 0x22c
#define SE_UART_IO_MACRO_CTRL 0x240
#define SE_UART_TX_TRANS_CFG 0x25c
#define SE_UART_TX_WORD_LEN 0x268
#define SE_UART_TX_STOP_BIT_LEN 0x26c
@@ -95,6 +96,12 @@
#define CTS_RTS_SORTED BIT(1)
#define RX_TX_CTS_RTS_SORTED (RX_TX_SORTED | CTS_RTS_SORTED)
/* UART pin swap value */
#define DEFAULT_IO_MACRO_IO0_IO1_MASK GENMASK(3, 0)
#define IO_MACRO_IO0_SEL 0x3
#define DEFAULT_IO_MACRO_IO2_IO3_MASK GENMASK(15, 4)
#define IO_MACRO_IO2_IO3_SWAP 0x4640
#ifdef CONFIG_CONSOLE_POLL
#define CONSOLE_RX_BYTES_PW 1
#else
@@ -113,12 +120,14 @@ struct qcom_geni_serial_port {
unsigned int baud;
unsigned int tx_bytes_pw;
unsigned int rx_bytes_pw;
u32 *rx_fifo;
void *rx_fifo;
u32 loopback;
bool brk;
unsigned int tx_remaining;
int wakeup_irq;
bool rx_tx_swap;
bool cts_rts_swap;
};
static const struct uart_ops qcom_geni_console_pops;
@@ -505,7 +514,6 @@ static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop)
{
unsigned char *buf;
struct tty_port *tport;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
u32 num_bytes_pw = port->tx_fifo_width / BITS_PER_BYTE;
@@ -517,8 +525,7 @@ static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop)
if (drop)
return 0;
buf = (unsigned char *)port->rx_fifo;
ret = tty_insert_flip_string(tport, buf, bytes);
ret = tty_insert_flip_string(tport, port->rx_fifo, bytes);
if (ret != bytes) {
dev_err(uport->dev, "%s:Unable to push data ret %d_bytes %d\n",
__func__, ret, bytes);
@@ -818,17 +825,7 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port)
static void qcom_geni_serial_shutdown(struct uart_port *uport)
{
unsigned long flags;
/* Stop the console before stopping the current tx */
if (uart_console(uport))
console_stop(uport->cons);
disable_irq(uport->irq);
spin_lock_irqsave(&uport->lock, flags);
qcom_geni_serial_stop_tx(uport);
qcom_geni_serial_stop_rx(uport);
spin_unlock_irqrestore(&uport->lock, flags);
}
static int qcom_geni_serial_port_setup(struct uart_port *uport)
@@ -836,6 +833,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
u32 proto;
u32 pin_swap;
if (uart_console(uport)) {
port->tx_bytes_pw = 1;
@@ -856,6 +854,20 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
get_tx_fifo_size(port);
writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT);
pin_swap = readl(uport->membase + SE_UART_IO_MACRO_CTRL);
if (port->rx_tx_swap) {
pin_swap &= ~DEFAULT_IO_MACRO_IO2_IO3_MASK;
pin_swap |= IO_MACRO_IO2_IO3_SWAP;
}
if (port->cts_rts_swap) {
pin_swap &= ~DEFAULT_IO_MACRO_IO0_IO1_MASK;
pin_swap |= IO_MACRO_IO0_SEL;
}
/* Configure this register if RX-TX, CTS-RTS pins are swapped */
if (port->rx_tx_swap || port->cts_rts_swap)
writel(pin_swap, uport->membase + SE_UART_IO_MACRO_CTRL);
/*
* Make an unconditional cancel on the main sequencer to reset
* it else we could end up in data loss scenarios.
@@ -868,12 +880,6 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
false, false, true);
geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2);
geni_se_select_mode(&port->se, GENI_SE_FIFO);
if (!uart_console(uport)) {
port->rx_fifo = devm_kcalloc(uport->dev,
port->rx_fifo_depth, sizeof(u32), GFP_KERNEL);
if (!port->rx_fifo)
return -ENOMEM;
}
port->setup = true;
return 0;
@@ -1284,6 +1290,13 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
if (!console) {
port->rx_fifo = devm_kcalloc(uport->dev,
port->rx_fifo_depth, sizeof(u32), GFP_KERNEL);
if (!port->rx_fifo)
return -ENOMEM;
}
port->name = devm_kasprintf(uport->dev, GFP_KERNEL,
"qcom_geni_serial_%s%d",
uart_console(uport) ? "console" : "uart", uport->line);
@@ -1299,6 +1312,12 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
if (!console)
port->wakeup_irq = platform_get_irq_optional(pdev, 1);
if (of_property_read_bool(pdev->dev.of_node, "rx-tx-swap"))
port->rx_tx_swap = true;
if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap"))
port->cts_rts_swap = true;
uport->private_data = drv;
platform_set_drvdata(pdev, port);
port->handle_rx = console ? handle_rx_console : handle_rx_uart;

查看文件

@@ -329,7 +329,7 @@ struct sc16is7xx_port {
struct task_struct *kworker_task;
struct kthread_work irq_work;
struct mutex efr_lock;
struct sc16is7xx_one p[0];
struct sc16is7xx_one p[];
};
static unsigned long sc16is7xx_lines;

查看文件

@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/serial.h> /* for serial_state and serial_icounter_struct */
#include <linux/serial_core.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/security.h>
@@ -40,6 +41,8 @@ static struct lock_class_key port_lock_key;
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
#define SYSRQ_TIMEOUT (HZ * 5)
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
struct ktermios *old_termios);
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
@@ -1908,6 +1911,24 @@ static int uart_proc_show(struct seq_file *m, void *v)
}
#endif
static inline bool uart_console_enabled(struct uart_port *port)
{
return uart_console(port) && (port->cons->flags & CON_ENABLED);
}
/*
* Ensure that the serial console lock is initialised early.
* If this port is a console, then the spinlock is already initialised.
*/
static inline void uart_port_spin_lock_init(struct uart_port *port)
{
if (uart_console(port))
return;
spin_lock_init(&port->lock);
lockdep_set_class(&port->lock, &port_lock_key);
}
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
/**
* uart_console_write - write a console message to a serial port
@@ -2060,16 +2081,7 @@ uart_set_options(struct uart_port *port, struct console *co,
struct ktermios termios;
static struct ktermios dummy;
/*
* Ensure that the serial console lock is initialised
* early.
* If this port is a console, then the spinlock is already
* initialised.
*/
if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) {
spin_lock_init(&port->lock);
lockdep_set_class(&port->lock, &port_lock_key);
}
uart_port_spin_lock_init(port);
memset(&termios, 0, sizeof(struct ktermios));
@@ -2605,7 +2617,7 @@ struct tty_driver *uart_console_device(struct console *co, int *index)
}
EXPORT_SYMBOL_GPL(uart_console_device);
static ssize_t uart_get_attr_uartclk(struct device *dev,
static ssize_t uartclk_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2615,7 +2627,7 @@ static ssize_t uart_get_attr_uartclk(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.baud_base * 16);
}
static ssize_t uart_get_attr_type(struct device *dev,
static ssize_t type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2624,7 +2636,8 @@ static ssize_t uart_get_attr_type(struct device *dev,
uart_get_info(port, &tmp);
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.type);
}
static ssize_t uart_get_attr_line(struct device *dev,
static ssize_t line_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2634,7 +2647,7 @@ static ssize_t uart_get_attr_line(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.line);
}
static ssize_t uart_get_attr_port(struct device *dev,
static ssize_t port_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2648,7 +2661,7 @@ static ssize_t uart_get_attr_port(struct device *dev,
return snprintf(buf, PAGE_SIZE, "0x%lX\n", ioaddr);
}
static ssize_t uart_get_attr_irq(struct device *dev,
static ssize_t irq_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2658,7 +2671,7 @@ static ssize_t uart_get_attr_irq(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.irq);
}
static ssize_t uart_get_attr_flags(struct device *dev,
static ssize_t flags_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2668,7 +2681,7 @@ static ssize_t uart_get_attr_flags(struct device *dev,
return snprintf(buf, PAGE_SIZE, "0x%X\n", tmp.flags);
}
static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev,
static ssize_t xmit_fifo_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2678,8 +2691,7 @@ static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.xmit_fifo_size);
}
static ssize_t uart_get_attr_close_delay(struct device *dev,
static ssize_t close_delay_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2689,8 +2701,7 @@ static ssize_t uart_get_attr_close_delay(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.close_delay);
}
static ssize_t uart_get_attr_closing_wait(struct device *dev,
static ssize_t closing_wait_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2700,7 +2711,7 @@ static ssize_t uart_get_attr_closing_wait(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.closing_wait);
}
static ssize_t uart_get_attr_custom_divisor(struct device *dev,
static ssize_t custom_divisor_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2710,7 +2721,7 @@ static ssize_t uart_get_attr_custom_divisor(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.custom_divisor);
}
static ssize_t uart_get_attr_io_type(struct device *dev,
static ssize_t io_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2720,7 +2731,7 @@ static ssize_t uart_get_attr_io_type(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.io_type);
}
static ssize_t uart_get_attr_iomem_base(struct device *dev,
static ssize_t iomem_base_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2730,7 +2741,7 @@ static ssize_t uart_get_attr_iomem_base(struct device *dev,
return snprintf(buf, PAGE_SIZE, "0x%lX\n", (unsigned long)tmp.iomem_base);
}
static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev,
static ssize_t iomem_reg_shift_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct serial_struct tmp;
@@ -2740,40 +2751,92 @@ static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);
}
static DEVICE_ATTR(type, S_IRUSR | S_IRGRP, uart_get_attr_type, NULL);
static DEVICE_ATTR(line, S_IRUSR | S_IRGRP, uart_get_attr_line, NULL);
static DEVICE_ATTR(port, S_IRUSR | S_IRGRP, uart_get_attr_port, NULL);
static DEVICE_ATTR(irq, S_IRUSR | S_IRGRP, uart_get_attr_irq, NULL);
static DEVICE_ATTR(flags, S_IRUSR | S_IRGRP, uart_get_attr_flags, NULL);
static DEVICE_ATTR(xmit_fifo_size, S_IRUSR | S_IRGRP, uart_get_attr_xmit_fifo_size, NULL);
static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL);
static DEVICE_ATTR(close_delay, S_IRUSR | S_IRGRP, uart_get_attr_close_delay, NULL);
static DEVICE_ATTR(closing_wait, S_IRUSR | S_IRGRP, uart_get_attr_closing_wait, NULL);
static DEVICE_ATTR(custom_divisor, S_IRUSR | S_IRGRP, uart_get_attr_custom_divisor, NULL);
static DEVICE_ATTR(io_type, S_IRUSR | S_IRGRP, uart_get_attr_io_type, NULL);
static DEVICE_ATTR(iomem_base, S_IRUSR | S_IRGRP, uart_get_attr_iomem_base, NULL);
static DEVICE_ATTR(iomem_reg_shift, S_IRUSR | S_IRGRP, uart_get_attr_iomem_reg_shift, NULL);
static ssize_t console_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tty_port *port = dev_get_drvdata(dev);
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport;
bool console = false;
mutex_lock(&port->mutex);
uport = uart_port_check(state);
if (uport)
console = uart_console_enabled(uport);
mutex_unlock(&port->mutex);
return sprintf(buf, "%c\n", console ? 'Y' : 'N');
}
static ssize_t console_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct tty_port *port = dev_get_drvdata(dev);
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport;
bool oldconsole, newconsole;
int ret;
ret = kstrtobool(buf, &newconsole);
if (ret)
return ret;
mutex_lock(&port->mutex);
uport = uart_port_check(state);
if (uport) {
oldconsole = uart_console_enabled(uport);
if (oldconsole && !newconsole) {
ret = unregister_console(uport->cons);
} else if (!oldconsole && newconsole) {
if (uart_console(uport))
register_console(uport->cons);
else
ret = -ENOENT;
}
} else {
ret = -ENXIO;
}
mutex_unlock(&port->mutex);
return ret < 0 ? ret : count;
}
static DEVICE_ATTR_RO(uartclk);
static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RO(line);
static DEVICE_ATTR_RO(port);
static DEVICE_ATTR_RO(irq);
static DEVICE_ATTR_RO(flags);
static DEVICE_ATTR_RO(xmit_fifo_size);
static DEVICE_ATTR_RO(close_delay);
static DEVICE_ATTR_RO(closing_wait);
static DEVICE_ATTR_RO(custom_divisor);
static DEVICE_ATTR_RO(io_type);
static DEVICE_ATTR_RO(iomem_base);
static DEVICE_ATTR_RO(iomem_reg_shift);
static DEVICE_ATTR_RW(console);
static struct attribute *tty_dev_attrs[] = {
&dev_attr_uartclk.attr,
&dev_attr_type.attr,
&dev_attr_line.attr,
&dev_attr_port.attr,
&dev_attr_irq.attr,
&dev_attr_flags.attr,
&dev_attr_xmit_fifo_size.attr,
&dev_attr_uartclk.attr,
&dev_attr_close_delay.attr,
&dev_attr_closing_wait.attr,
&dev_attr_custom_divisor.attr,
&dev_attr_io_type.attr,
&dev_attr_iomem_base.attr,
&dev_attr_iomem_reg_shift.attr,
NULL,
};
&dev_attr_console.attr,
NULL
};
static const struct attribute_group tty_dev_attr_group = {
.attrs = tty_dev_attrs,
};
};
/**
* uart_add_one_port - attach a driver-defined port structure
@@ -2824,14 +2887,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
goto out;
}
/*
* If this port is a console, then the spinlock is already
* initialised.
*/
if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {
spin_lock_init(&uport->lock);
lockdep_set_class(&uport->lock, &port_lock_key);
}
uart_port_spin_lock_init(uport);
if (uport->cons && uport->dev)
of_console_check(uport->dev->of_node, uport->cons->name, uport->line);
@@ -3082,6 +3139,60 @@ void uart_insert_char(struct uart_port *port, unsigned int status,
}
EXPORT_SYMBOL_GPL(uart_insert_char);
#ifdef CONFIG_MAGIC_SYSRQ_SERIAL
static const char sysrq_toggle_seq[] = CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE;
static void uart_sysrq_on(struct work_struct *w)
{
int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq);
sysrq_toggle_support(1);
pr_info("SysRq is enabled by magic sequence '%*pE' on serial\n",
sysrq_toggle_seq_len, sysrq_toggle_seq);
}
static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on);
/**
* uart_try_toggle_sysrq - Enables SysRq from serial line
* @port: uart_port structure where char(s) after BREAK met
* @ch: new character in the sequence after received BREAK
*
* Enables magic SysRq when the required sequence is met on port
* (see CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE).
*
* Returns false if @ch is out of enabling sequence and should be
* handled some other way, true if @ch was consumed.
*/
static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
{
int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq);
if (!sysrq_toggle_seq_len)
return false;
BUILD_BUG_ON(ARRAY_SIZE(sysrq_toggle_seq) >= U8_MAX);
if (sysrq_toggle_seq[port->sysrq_seq] != ch) {
port->sysrq_seq = 0;
return false;
}
if (++port->sysrq_seq < sysrq_toggle_seq_len) {
port->sysrq = jiffies + SYSRQ_TIMEOUT;
return true;
}
schedule_work(&sysrq_enable_work);
port->sysrq = 0;
return true;
}
#else
static inline bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
{
return false;
}
#endif
int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
{
if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL))
@@ -3091,9 +3202,13 @@ int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
return 0;
if (ch && time_before(jiffies, port->sysrq)) {
handle_sysrq(ch);
port->sysrq = 0;
return 1;
if (sysrq_mask()) {
handle_sysrq(ch);
port->sysrq = 0;
return 1;
}
if (uart_try_toggle_sysrq(port, ch))
return 1;
}
port->sysrq = 0;
@@ -3110,9 +3225,13 @@ int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
return 0;
if (ch && time_before(jiffies, port->sysrq)) {
port->sysrq_ch = ch;
port->sysrq = 0;
return 1;
if (sysrq_mask()) {
port->sysrq_ch = ch;
port->sysrq = 0;
return 1;
}
if (uart_try_toggle_sysrq(port, ch))
return 1;
}
port->sysrq = 0;
@@ -3120,22 +3239,19 @@ int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
}
EXPORT_SYMBOL_GPL(uart_prepare_sysrq_char);
void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags)
void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long flags)
__releases(&port->lock)
{
int sysrq_ch;
if (port->has_sysrq) {
int sysrq_ch = port->sysrq_ch;
if (!port->has_sysrq) {
spin_unlock_irqrestore(&port->lock, irqflags);
return;
port->sysrq_ch = 0;
spin_unlock_irqrestore(&port->lock, flags);
if (sysrq_ch)
handle_sysrq(sysrq_ch);
} else {
spin_unlock_irqrestore(&port->lock, flags);
}
sysrq_ch = port->sysrq_ch;
port->sysrq_ch = 0;
spin_unlock_irqrestore(&port->lock, irqflags);
if (sysrq_ch)
handle_sysrq(sysrq_ch);
}
EXPORT_SYMBOL_GPL(uart_unlock_and_check_sysrq);
@@ -3149,14 +3265,12 @@ int uart_handle_break(struct uart_port *port)
if (port->handle_break)
port->handle_break(port);
if (port->has_sysrq) {
if (port->cons && port->cons->index == port->line) {
if (!port->sysrq) {
port->sysrq = jiffies + HZ*5;
return 1;
}
port->sysrq = 0;
if (port->has_sysrq && uart_console(port)) {
if (!port->sysrq) {
port->sysrq = jiffies + SYSRQ_TIMEOUT;
return 1;
}
port->sysrq = 0;
}
if (port->flags & UPF_SAK)

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Helpers for controlling modem lines via GPIO
*

查看文件

@@ -618,10 +618,10 @@ static void sifive_serial_shutdown(struct uart_port *port)
*
* On the V0 SoC, the UART IP block is derived from the CPU clock source
* after a synchronous divide-by-two divider, so any CPU clock rate change
* requires the UART baud rate to be updated. This presumably could corrupt any
* serial word currently being transmitted or received. It would probably
* be better to stop receives and transmits, then complete the baud rate
* change, then re-enable them.
* requires the UART baud rate to be updated. This presumably corrupts any
* serial word currently being transmitted or received. In order to avoid
* corrupting the output data stream, we drain the transmit queue before
* allowing the clock's rate to be changed.
*/
static int sifive_serial_clk_notifier(struct notifier_block *nb,
unsigned long event, void *data)
@@ -629,6 +629,26 @@ static int sifive_serial_clk_notifier(struct notifier_block *nb,
struct clk_notifier_data *cnd = data;
struct sifive_serial_port *ssp = notifier_to_sifive_serial_port(nb);
if (event == PRE_RATE_CHANGE) {
/*
* The TX watermark is always set to 1 by this driver, which
* means that the TX busy bit will lower when there are 0 bytes
* left in the TX queue -- in other words, when the TX FIFO is
* empty.
*/
__ssp_wait_for_xmitr(ssp);
/*
* On the cycle the TX FIFO goes empty there is still a full
* UART frame left to be transmitted in the shift register.
* The UART provides no way for software to directly determine
* when that last frame has been transmitted, so we just sleep
* here instead. As we're not tracking the number of stop bits
* they're just worst cased here. The rest of the serial
* framing parameters aren't configurable by software.
*/
udelay(DIV_ROUND_UP(12 * 1000 * 1000, ssp->baud_rate));
}
if (event == POST_RATE_CHANGE && ssp->clkin_rate != cnd->new_rate) {
ssp->clkin_rate = cnd->new_rate;
__ssp_update_div(ssp);
@@ -709,6 +729,29 @@ static const char *sifive_serial_type(struct uart_port *port)
return port->type == PORT_SIFIVE_V0 ? "SiFive UART v0" : NULL;
}
#ifdef CONFIG_CONSOLE_POLL
static int sifive_serial_poll_get_char(struct uart_port *port)
{
struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
char is_empty, ch;
ch = __ssp_receive_char(ssp, &is_empty);
if (is_empty)
return NO_POLL_CHAR;
return ch;
}
static void sifive_serial_poll_put_char(struct uart_port *port,
unsigned char c)
{
struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
__ssp_wait_for_xmitr(ssp);
__ssp_transmit_char(ssp, c);
}
#endif /* CONFIG_CONSOLE_POLL */
/*
* Early console support
*/
@@ -877,6 +920,10 @@ static const struct uart_ops sifive_serial_uops = {
.request_port = sifive_serial_request_port,
.config_port = sifive_serial_config_port,
.verify_port = sifive_serial_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = sifive_serial_poll_get_char,
.poll_put_char = sifive_serial_poll_put_char,
#endif
};
static struct uart_driver sifive_serial_uart_driver = {

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Drivers for CSR SiRFprimaII onboard UARTs.
*

查看文件

@@ -1013,7 +1013,7 @@ static void sprd_console_write(struct console *co, const char *s,
spin_unlock_irqrestore(&port->lock, flags);
}
static int __init sprd_console_setup(struct console *co, char *options)
static int sprd_console_setup(struct console *co, char *options)
{
struct sprd_uart_port *sprd_uart_port;
int baud = 115200;
@@ -1102,29 +1102,6 @@ static struct uart_driver sprd_uart_driver = {
.cons = SPRD_CONSOLE,
};
static int sprd_probe_dt_alias(int index, struct device *dev)
{
struct device_node *np;
int ret = index;
if (!IS_ENABLED(CONFIG_OF))
return ret;
np = dev->of_node;
if (!np)
return ret;
ret = of_alias_get_id(np, "serial");
if (ret < 0)
ret = index;
else if (ret >= ARRAY_SIZE(sprd_port) || sprd_port[ret] != NULL) {
dev_warn(dev, "requested serial port %d not available.\n", ret);
ret = index;
}
return ret;
}
static int sprd_remove(struct platform_device *dev)
{
struct sprd_uart_port *sup = platform_get_drvdata(dev);
@@ -1132,14 +1109,13 @@ static int sprd_remove(struct platform_device *dev)
if (sup) {
uart_remove_one_port(&sprd_uart_driver, &sup->port);
sprd_port[sup->port.line] = NULL;
sprd_rx_free_buf(sup);
sprd_ports_num--;
}
if (!sprd_ports_num)
uart_unregister_driver(&sprd_uart_driver);
sprd_rx_free_buf(sup);
return 0;
}
@@ -1147,7 +1123,8 @@ static bool sprd_uart_is_console(struct uart_port *uport)
{
struct console *cons = sprd_uart_driver.cons;
if (cons && cons->index >= 0 && cons->index == uport->line)
if ((cons && cons->index >= 0 && cons->index == uport->line) ||
of_console_check(uport->dev->of_node, SPRD_TTY_NAME, uport->line))
return true;
return false;
@@ -1203,14 +1180,11 @@ static int sprd_probe(struct platform_device *pdev)
int index;
int ret;
for (index = 0; index < ARRAY_SIZE(sprd_port); index++)
if (sprd_port[index] == NULL)
break;
if (index == ARRAY_SIZE(sprd_port))
return -EBUSY;
index = sprd_probe_dt_alias(index, &pdev->dev);
index = of_alias_get_id(pdev->dev.of_node, "serial");
if (index < 0 || index >= ARRAY_SIZE(sprd_port)) {
dev_err(&pdev->dev, "got a wrong serial alias id %d\n", index);
return -EINVAL;
}
sprd_port[index] = devm_kzalloc(&pdev->dev, sizeof(*sprd_port[index]),
GFP_KERNEL);
@@ -1262,10 +1236,8 @@ static int sprd_probe(struct platform_device *pdev)
sprd_ports_num++;
ret = uart_add_one_port(&sprd_uart_driver, up);
if (ret) {
sprd_port[index] = NULL;
if (ret)
sprd_remove(pdev);
}
platform_set_drvdata(pdev, up);

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Maxime Coquelin 2015
* Copyright (C) STMicroelectronics SA 2017

查看文件

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
/*
* timbuart.c timberdale FPGA GPIO driver
* Copyright (c) 2009 Intel Corporation

查看文件

@@ -650,8 +650,8 @@ static unsigned int cdns_uart_tx_empty(struct uart_port *port)
unsigned int status;
status = readl(port->membase + CDNS_UART_SR) &
CDNS_UART_SR_TXEMPTY;
return status ? TIOCSER_TEMT : 0;
(CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE);
return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0;
}
/**
@@ -693,20 +693,8 @@ static void cdns_uart_set_termios(struct uart_port *port,
u32 cval = 0;
unsigned int baud, minbaud, maxbaud;
unsigned long flags;
unsigned int ctrl_reg, mode_reg, val;
int err;
unsigned int ctrl_reg, mode_reg;
/* Wait for the transmit FIFO to empty before making changes */
if (!(readl(port->membase + CDNS_UART_CR) &
CDNS_UART_CR_TX_DIS)) {
err = readl_poll_timeout(port->membase + CDNS_UART_SR,
val, (val & CDNS_UART_SR_TXEMPTY),
1000, TX_TIMEOUT);
if (err) {
dev_err(port->dev, "timed out waiting for tx empty");
return;
}
}
spin_lock_irqsave(&port->lock, flags);
/* Disable the TX and RX to set baud rate */