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

Pull tty/serial driver updates from Greg KH:
 "Here is the big tty and serial driver update for 4.8-rc1.

  Lots of good cleanups from Jiri on a number of vt and other tty
  related things, and the normal driver updates.  Full details are in
  the shortlog.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'tty-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (90 commits)
  tty/serial: atmel: enforce tasklet init and termination sequences
  serial: sh-sci: Stop transfers in sci_shutdown()
  serial: 8250_ingenic: drop #if conditional surrounding earlycon code
  serial: 8250_mtk: drop !defined(MODULE) conditional
  serial: 8250_uniphier: drop !defined(MODULE) conditional
  earlycon: mark earlycon code as __used iif the caller is built-in
  tty/serial/8250: use mctrl_gpio helpers
  serial: mctrl_gpio: enable API usage only for initialized mctrl_gpios struct
  serial: mctrl_gpio: add modem control read routine
  tty/serial/8250: make UART_MCR register access consistent
  serial: 8250_mid: Read RX buffer on RX DMA timeout for DNV
  serial: 8250_dma: Export serial8250_rx_dma_flush()
  dmaengine: hsu: Export hsu_dma_get_status()
  tty: serial: 8250: add CON_CONSDEV to flags
  tty: serial: samsung: add byte-order aware bit functions
  tty: serial: samsung: fixup accessors for endian
  serial: sirf: make fifo functions static
  serial: mps2-uart: make driver explicitly non-modular
  serial: mvebu-uart: free the IRQ in ->shutdown()
  serial/bcm63xx_uart: use correct alias naming
  ...
This commit is contained in:
Linus Torvalds
2016-07-24 17:14:37 -07:00
當前提交 721413aff2
共有 68 個文件被更改,包括 1393 次插入1139 次删除

查看文件

@@ -93,8 +93,6 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096))
#endif
#define STD_COM_FLAGS (0)
/* firmware stuff */
#define ZL_MAX_BLOCKS 16
#define DRIVER_VERSION 0x02010203
@@ -2288,7 +2286,6 @@ static int cy_get_serial_info(struct cyclades_port *info,
.closing_wait = info->port.closing_wait,
.baud_base = info->baud,
.custom_divisor = info->custom_divisor,
.hub6 = 0, /*!!! */
};
return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
}
@@ -3084,7 +3081,6 @@ static int cy_init_card(struct cyclades_card *cinfo)
info->port.closing_wait = CLOSING_WAIT_DELAY;
info->port.close_delay = 5 * HZ / 10;
info->port.flags = STD_COM_FLAGS;
init_completion(&info->shutdown_wait);
if (cy_is_Z(cinfo)) {

查看文件

@@ -252,20 +252,11 @@ static int ipwireless_get_serial_info(struct ipw_tty *tty,
{
struct serial_struct tmp;
if (!retinfo)
return (-EFAULT);
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_UNKNOWN;
tmp.line = tty->index;
tmp.port = 0;
tmp.irq = 0;
tmp.flags = 0;
tmp.baud_base = 115200;
tmp.close_delay = 0;
tmp.closing_wait = 0;
tmp.custom_divisor = 0;
tmp.hub6 = 0;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;

查看文件

@@ -1219,7 +1219,6 @@ static int mxser_get_serial_info(struct tty_struct *tty,
.close_delay = info->port.close_delay,
.closing_wait = info->port.closing_wait,
.custom_divisor = info->custom_divisor,
.hub6 = 0
};
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;

查看文件

@@ -15,6 +15,8 @@
#include <linux/serial_reg.h>
#include <linux/dmaengine.h>
#include "../serial_mctrl_gpio.h"
struct uart_8250_dma {
int (*tx_dma)(struct uart_8250_port *p);
int (*rx_dma)(struct uart_8250_port *p);
@@ -53,11 +55,9 @@ struct old_serial_port {
unsigned int port;
unsigned int irq;
upf_t flags;
unsigned char hub6;
unsigned char io_type;
unsigned char __iomem *iomem_base;
unsigned short iomem_reg_shift;
unsigned long irqflags;
};
struct serial8250_config {
@@ -131,6 +131,47 @@ void serial8250_rpm_put(struct uart_8250_port *p);
int serial8250_em485_init(struct uart_8250_port *p);
void serial8250_em485_destroy(struct uart_8250_port *p);
static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
{
int mctrl_gpio = 0;
serial_out(up, UART_MCR, value);
if (value & UART_MCR_RTS)
mctrl_gpio |= TIOCM_RTS;
if (value & UART_MCR_DTR)
mctrl_gpio |= TIOCM_DTR;
mctrl_gpio_set(up->gpios, mctrl_gpio);
}
static inline int serial8250_in_MCR(struct uart_8250_port *up)
{
int mctrl, mctrl_gpio = 0;
mctrl = serial_in(up, UART_MCR);
/* save current MCR values */
if (mctrl & UART_MCR_RTS)
mctrl_gpio |= TIOCM_RTS;
if (mctrl & UART_MCR_DTR)
mctrl_gpio |= TIOCM_DTR;
mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio);
if (mctrl_gpio & TIOCM_RTS)
mctrl |= UART_MCR_RTS;
else
mctrl &= ~UART_MCR_RTS;
if (mctrl_gpio & TIOCM_DTR)
mctrl |= UART_MCR_DTR;
else
mctrl &= ~UART_MCR_DTR;
return mctrl;
}
#if defined(__alpha__) && !defined(CONFIG_PCI)
/*
* Digital did something really horribly wrong with the OUT1 and OUT2
@@ -237,9 +278,3 @@ static inline int serial_index(struct uart_port *port)
{
return port->minor - 64;
}
#if 0
#define DEBUG_INTR(fmt...) printk(fmt)
#else
#define DEBUG_INTR(fmt...) do { } while (0)
#endif

查看文件

@@ -114,7 +114,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
struct list_head *l, *end = NULL;
int pass_counter = 0, handled = 0;
DEBUG_INTR("serial8250_interrupt(%d)...", irq);
pr_debug("%s(%d): start\n", __func__, irq);
spin_lock(&i->lock);
@@ -144,7 +144,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
spin_unlock(&i->lock);
DEBUG_INTR("end.\n");
pr_debug("%s(%d): end\n", __func__, irq);
return IRQ_RETVAL(handled);
}
@@ -546,10 +546,10 @@ static void __init serial8250_isa_init_ports(void)
port->iobase = old_serial_port[i].port;
port->irq = irq_canonicalize(old_serial_port[i].irq);
port->irqflags = old_serial_port[i].irqflags;
port->irqflags = 0;
port->uartclk = old_serial_port[i].baud_base * 16;
port->flags = old_serial_port[i].flags;
port->hub6 = old_serial_port[i].hub6;
port->hub6 = 0;
port->membase = old_serial_port[i].iomem_base;
port->iotype = old_serial_port[i].io_type;
port->regshift = old_serial_port[i].iomem_reg_shift;
@@ -675,7 +675,7 @@ static struct console univ8250_console = {
.device = uart_console_device,
.setup = univ8250_console_setup,
.match = univ8250_console_match,
.flags = CON_PRINTBUFFER | CON_ANYTIME,
.flags = CON_PRINTBUFFER | CON_ANYTIME | CON_CONSDEV,
.index = -1,
.data = &serial8250_reg,
};
@@ -974,6 +974,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
uart = serial8250_find_match_or_unused(&up->port);
if (uart && uart->port.type != PORT_8250_CIR) {
struct mctrl_gpios *gpios;
if (uart->port.dev)
uart_remove_one_port(&serial8250_reg, &uart->port);
@@ -1011,6 +1013,13 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
if (up->port.flags & UPF_FIXED_TYPE)
uart->port.type = up->port.type;
gpios = mctrl_gpio_init(&uart->port, 0);
if (IS_ERR(gpios)) {
if (PTR_ERR(gpios) != -ENOSYS)
return PTR_ERR(gpios);
} else
uart->gpios = gpios;
serial8250_set_defaults(uart);
/* Possibly override default I/O functions. */

查看文件

@@ -145,6 +145,7 @@ void serial8250_rx_dma_flush(struct uart_8250_port *p)
dmaengine_terminate_all(dma->rxchan);
}
}
EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush);
int serial8250_request_dma(struct uart_8250_port *p)
{

查看文件

@@ -150,6 +150,7 @@ EARLYCON_DECLARE(uart, early_serial8250_setup);
OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup);
OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup);
OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);
#ifdef CONFIG_SERIAL_8250_OMAP

查看文件

@@ -13,6 +13,7 @@
#include <linux/pnp.h>
#include <linux/kernel.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
#include "8250.h"
#define ADDR_PORT 0
@@ -30,6 +31,12 @@
#define IO_ADDR2 0x60
#define LDN 0x7
#define IRQ_MODE 0x70
#define IRQ_SHARE BIT(4)
#define IRQ_MODE_MASK (BIT(6) | BIT(5))
#define IRQ_LEVEL_LOW 0
#define IRQ_EDGE_HIGH BIT(5)
#define RS485 0xF0
#define RTS_INVERT BIT(5)
#define RS485_URA BIT(4)
@@ -176,10 +183,37 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address)
return -ENODEV;
}
static int fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool level_mode)
{
int status;
u8 tmp;
status = fintek_8250_enter_key(pdata->base_port, pdata->key);
if (status)
return status;
outb(LDN, pdata->base_port + ADDR_PORT);
outb(pdata->index, pdata->base_port + DATA_PORT);
outb(IRQ_MODE, pdata->base_port + ADDR_PORT);
tmp = inb(pdata->base_port + DATA_PORT);
tmp &= ~IRQ_MODE_MASK;
tmp |= IRQ_SHARE;
if (!level_mode)
tmp |= IRQ_EDGE_HIGH;
outb(tmp, pdata->base_port + DATA_PORT);
fintek_8250_exit_key(pdata->base_port);
return 0;
}
int fintek_8250_probe(struct uart_8250_port *uart)
{
struct fintek_8250 *pdata;
struct fintek_8250 probe_data;
struct irq_data *irq_data = irq_get_irq_data(uart->port.irq);
bool level_mode = irqd_is_level_type(irq_data);
if (find_base_port(&probe_data, uart->port.iobase))
return -ENODEV;
@@ -192,5 +226,5 @@ int fintek_8250_probe(struct uart_8250_port *uart)
uart->port.rs485_config = fintek_8250_rs485_config;
uart->port.private_data = pdata;
return 0;
return fintek_8250_set_irq_mode(pdata, level_mode);
}

查看文件

@@ -48,7 +48,6 @@ static const struct of_device_id of_match[];
#define UART_MCR_MDCE BIT(7)
#define UART_MCR_FCM BIT(6)
#if defined(CONFIG_SERIAL_EARLYCON) && !defined(MODULE)
static struct earlycon_device *early_device;
static uint8_t __init early_in(struct uart_port *port, int offset)
@@ -141,7 +140,6 @@ OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",
EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup);
OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
ingenic_early_console_setup);
#endif /* CONFIG_SERIAL_EARLYCON */
static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
{

查看文件

@@ -96,13 +96,27 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p)
static int dnv_handle_irq(struct uart_port *p)
{
struct mid8250 *mid = p->private_data;
struct uart_8250_port *up = up_to_u8250p(p);
unsigned int fisr = serial_port_in(p, INTEL_MID_UART_DNV_FISR);
u32 status;
int ret = IRQ_NONE;
int err;
if (fisr & BIT(2))
ret |= hsu_dma_irq(&mid->dma_chip, 1);
if (fisr & BIT(1))
ret |= hsu_dma_irq(&mid->dma_chip, 0);
if (fisr & BIT(2)) {
err = hsu_dma_get_status(&mid->dma_chip, 1, &status);
if (err > 0) {
serial8250_rx_dma_flush(up);
ret |= IRQ_HANDLED;
} else if (err == 0)
ret |= hsu_dma_do_irq(&mid->dma_chip, 1, status);
}
if (fisr & BIT(1)) {
err = hsu_dma_get_status(&mid->dma_chip, 0, &status);
if (err > 0)
ret |= IRQ_HANDLED;
else if (err == 0)
ret |= hsu_dma_do_irq(&mid->dma_chip, 0, status);
}
if (fisr & BIT(0))
ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
return ret;

查看文件

@@ -301,7 +301,7 @@ static struct platform_driver mtk8250_platform_driver = {
};
module_platform_driver(mtk8250_platform_driver);
#if defined(CONFIG_SERIAL_8250_CONSOLE) && !defined(MODULE)
#ifdef CONFIG_SERIAL_8250_CONSOLE
static int __init early_mtk8250_setup(struct earlycon_device *device,
const char *options)
{

查看文件

@@ -134,18 +134,21 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
serial8250_do_set_mctrl(port, mctrl);
/*
* Turn off autoRTS if RTS is lowered and restore autoRTS setting
* if RTS is raised
*/
lcr = serial_in(up, UART_LCR);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
priv->efr |= UART_EFR_RTS;
else
priv->efr &= ~UART_EFR_RTS;
serial_out(up, UART_EFR, priv->efr);
serial_out(up, UART_LCR, lcr);
if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(up->gpios,
UART_GPIO_RTS))) {
/*
* Turn off autoRTS if RTS is lowered and restore autoRTS
* setting if RTS is raised
*/
lcr = serial_in(up, UART_LCR);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
priv->efr |= UART_EFR_RTS;
else
priv->efr &= ~UART_EFR_RTS;
serial_out(up, UART_EFR, priv->efr);
serial_out(up, UART_LCR, lcr);
}
}
/*
@@ -280,7 +283,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
serial_out(up, UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_MCR, UART_MCR_TCRTLR);
serial8250_out_MCR(up, UART_MCR_TCRTLR);
serial_out(up, UART_FCR, up->fcr);
omap8250_update_scr(up, priv);
@@ -296,7 +299,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
serial_out(up, UART_LCR, 0);
/* drop TCR + TLR access, we setup XON/XOFF later */
serial_out(up, UART_MCR, up->mcr);
serial8250_out_MCR(up, up->mcr);
serial_out(up, UART_IER, up->ier);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
@@ -446,7 +449,9 @@ static void omap_8250_set_termios(struct uart_port *port,
priv->efr = 0;
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW
&& IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(up->gpios,
UART_GPIO_RTS))) {
/* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */
up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
priv->efr |= UART_EFR_CTS;

查看文件

@@ -1136,11 +1136,11 @@ static int pci_quatech_rqopr(struct uart_8250_port *port)
static void pci_quatech_wqopr(struct uart_8250_port *port, u8 qopr)
{
unsigned long base = port->port.iobase;
u8 LCR, val;
u8 LCR;
LCR = inb(base + UART_LCR);
outb(0xBF, base + UART_LCR);
val = inb(base + UART_SCR);
inb(base + UART_SCR);
outb(qopr, base + UART_SCR);
outb(LCR, base + UART_LCR);
}
@@ -1864,6 +1864,16 @@ pci_wch_ch353_setup(struct serial_private *priv,
return pci_default_setup(priv, board, port, idx);
}
static int
pci_wch_ch355_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16550A;
return pci_default_setup(priv, board, port, idx);
}
static int
pci_wch_ch38x_setup(struct serial_private *priv,
const struct pciserial_board *board,
@@ -1915,6 +1925,7 @@ pci_wch_ch38x_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046
#define PCI_DEVICE_ID_WCH_CH353_1S1P 0x5053
#define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053
#define PCI_DEVICE_ID_WCH_CH355_4S 0x7173
#define PCI_VENDOR_ID_AGESTAR 0x5372
#define PCI_DEVICE_ID_AGESTAR_9375 0x6872
#define PCI_VENDOR_ID_ASIX 0x9710
@@ -2618,6 +2629,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.setup = pci_wch_ch353_setup,
},
/* WCH CH355 4S card (16550 clone) */
{
.vendor = PCI_VENDOR_ID_WCH,
.device = PCI_DEVICE_ID_WCH_CH355_4S,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_wch_ch355_setup,
},
/* WCH CH382 2S card (16850 clone) */
{
.vendor = PCIE_VENDOR_ID_WCH,
@@ -3812,6 +3831,7 @@ static const struct pci_device_id blacklist[] = {
/* multi-io cards handled by parport_serial */
{ PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
{ PCI_DEVICE(0x4348, 0x7173), }, /* WCH CH355 4S */
{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
{ PCI_DEVICE(0x1c00, 0x3470), }, /* WCH CH384 4S */
@@ -5567,6 +5587,10 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID,
0, 0, pbn_b0_bt_2_115200 },
{ PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH355_4S,
PCI_ANY_ID, PCI_ANY_ID,
0, 0, pbn_b0_bt_4_115200 },
{ PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S,
PCI_ANY_ID, PCI_ANY_ID,
0, 0, pbn_wch382_2 },

查看文件

@@ -527,13 +527,13 @@ 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 = serial_in(p, UART_MCR);
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;
serial_out(p, UART_MCR, mcr);
serial8250_out_MCR(p, mcr);
}
static void serial8250_em485_handle_start_tx(unsigned long arg);
@@ -785,10 +785,10 @@ static int size_fifo(struct uart_8250_port *up)
old_lcr = serial_in(up, UART_LCR);
serial_out(up, UART_LCR, 0);
old_fcr = serial_in(up, UART_FCR);
old_mcr = serial_in(up, UART_MCR);
old_mcr = serial8250_in_MCR(up);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial_out(up, UART_MCR, UART_MCR_LOOP);
serial8250_out_MCR(up, UART_MCR_LOOP);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
old_dl = serial_dl_read(up);
serial_dl_write(up, 0x0001);
@@ -800,7 +800,7 @@ static int size_fifo(struct uart_8250_port *up)
(count < 256); count++)
serial_in(up, UART_RX);
serial_out(up, UART_FCR, old_fcr);
serial_out(up, UART_MCR, old_mcr);
serial8250_out_MCR(up, old_mcr);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_dl_write(up, old_dl);
serial_out(up, UART_LCR, old_lcr);
@@ -1040,17 +1040,17 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
*/
serial_out(up, UART_LCR, 0);
status1 = serial_in(up, UART_MCR);
status1 = serial8250_in_MCR(up);
serial_out(up, UART_LCR, 0xE0);
status2 = serial_in(up, 0x02); /* EXCR1 */
if (!((status2 ^ status1) & UART_MCR_LOOP)) {
serial_out(up, UART_LCR, 0);
serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP);
serial8250_out_MCR(up, status1 ^ UART_MCR_LOOP);
serial_out(up, UART_LCR, 0xE0);
status2 = serial_in(up, 0x02); /* EXCR1 */
serial_out(up, UART_LCR, 0);
serial_out(up, UART_MCR, status1);
serial8250_out_MCR(up, status1);
if ((status2 ^ status1) & UART_MCR_LOOP) {
unsigned short quot;
@@ -1224,7 +1224,7 @@ static void autoconfig(struct uart_8250_port *up)
}
}
save_mcr = serial_in(up, UART_MCR);
save_mcr = serial8250_in_MCR(up);
save_lcr = serial_in(up, UART_LCR);
/*
@@ -1237,9 +1237,9 @@ static void autoconfig(struct uart_8250_port *up)
* that conflicts with COM 1-4 --- we hope!
*/
if (!(port->flags & UPF_SKIP_TEST)) {
serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
serial8250_out_MCR(up, UART_MCR_LOOP | 0x0A);
status1 = serial_in(up, UART_MSR) & 0xF0;
serial_out(up, UART_MCR, save_mcr);
serial8250_out_MCR(up, save_mcr);
if (status1 != 0x90) {
spin_unlock_irqrestore(&port->lock, flags);
DEBUG_AUTOCONF("LOOP test failed (%02x) ",
@@ -1305,7 +1305,7 @@ static void autoconfig(struct uart_8250_port *up)
if (port->type == PORT_RSA)
serial_out(up, UART_RSA_FRR, 0);
#endif
serial_out(up, UART_MCR, save_mcr);
serial8250_out_MCR(up, save_mcr);
serial8250_clear_fifos(up);
serial_in(up, UART_RX);
if (up->capabilities & UART_CAP_UUE)
@@ -1353,19 +1353,18 @@ static void autoconfig_irq(struct uart_8250_port *up)
/* forget possible initially masked and pending IRQ */
probe_irq_off(probe_irq_on());
save_mcr = serial_in(up, UART_MCR);
save_mcr = serial8250_in_MCR(up);
save_ier = serial_in(up, UART_IER);
serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2);
irqs = probe_irq_on();
serial_out(up, UART_MCR, 0);
serial8250_out_MCR(up, 0);
udelay(10);
if (port->flags & UPF_FOURPORT) {
serial_out(up, UART_MCR,
UART_MCR_DTR | UART_MCR_RTS);
serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
} else {
serial_out(up, UART_MCR,
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
serial8250_out_MCR(up,
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
}
serial_out(up, UART_IER, 0x0f); /* enable all intrs */
serial_in(up, UART_LSR);
@@ -1376,7 +1375,7 @@ static void autoconfig_irq(struct uart_8250_port *up)
udelay(20);
irq = probe_irq_off(irqs);
serial_out(up, UART_MCR, save_mcr);
serial8250_out_MCR(up, save_mcr);
serial_out(up, UART_IER, save_ier);
if (port->flags & UPF_FOURPORT)
@@ -1549,14 +1548,14 @@ static inline void start_tx_rs485(struct uart_port *port)
del_timer(&em485->stop_tx_timer);
em485->active_timer = NULL;
mcr = serial_in(up, UART_MCR);
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;
serial_out(up, UART_MCR, mcr);
serial8250_out_MCR(up, mcr);
if (up->port.rs485.delay_rts_before_send > 0) {
em485->active_timer = &em485->start_tx_timer;
@@ -1619,6 +1618,8 @@ static void serial8250_disable_ms(struct uart_port *port)
if (up->bugs & UART_BUG_NOMSR)
return;
mctrl_gpio_disable_ms(up->gpios);
up->ier &= ~UART_IER_MSI;
serial_port_out(port, UART_IER, up->ier);
}
@@ -1631,6 +1632,8 @@ static void serial8250_enable_ms(struct uart_port *port)
if (up->bugs & UART_BUG_NOMSR)
return;
mctrl_gpio_enable_ms(up->gpios);
up->ier |= UART_IER_MSI;
serial8250_rpm_get(up);
@@ -1686,7 +1689,7 @@ static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)
lsr &= port->read_status_mask;
if (lsr & UART_LSR_BI) {
DEBUG_INTR("handling break....");
pr_debug("%s: handling break\n", __func__);
flag = TTY_BREAK;
} else if (lsr & UART_LSR_PE)
flag = TTY_PARITY;
@@ -1757,7 +1760,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
DEBUG_INTR("THRE...");
pr_debug("%s: THRE\n", __func__);
/*
* With RPM enabled, we have to wait until the FIFO is empty before the
@@ -1823,7 +1826,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
status = serial_port_in(port, UART_LSR);
DEBUG_INTR("status = %x...", status);
pr_debug("%s: status = %x\n", __func__, status);
if (status & (UART_LSR_DR | UART_LSR_BI)) {
if (!up->dma || handle_rx_dma(up, iir))
@@ -1861,7 +1864,6 @@ static int serial8250_default_handle_irq(struct uart_port *port)
*/
static int exar_handle_irq(struct uart_port *port)
{
unsigned char int0, int1, int2, int3;
unsigned int iir = serial_port_in(port, UART_IIR);
int ret;
@@ -1869,10 +1871,10 @@ static int exar_handle_irq(struct uart_port *port)
if ((port->type == PORT_XR17V35X) ||
(port->type == PORT_XR17D15X)) {
int0 = serial_port_in(port, 0x80);
int1 = serial_port_in(port, 0x81);
int2 = serial_port_in(port, 0x82);
int3 = serial_port_in(port, 0x83);
serial_port_in(port, 0x80);
serial_port_in(port, 0x81);
serial_port_in(port, 0x82);
serial_port_in(port, 0x83);
}
return ret;
@@ -1915,7 +1917,8 @@ unsigned int serial8250_do_get_mctrl(struct uart_port *port)
ret |= TIOCM_DSR;
if (status & UART_MSR_CTS)
ret |= TIOCM_CTS;
return ret;
return mctrl_gpio_get(up->gpios, &ret);
}
EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl);
@@ -1944,7 +1947,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
serial_port_out(port, UART_MCR, mcr);
serial8250_out_MCR(up, mcr);
}
EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
@@ -1994,8 +1997,6 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
/* Wait up to 1s for flow control if necessary */
if (up->port.flags & UPF_CONS_FLOW) {
unsigned int tmout;
for (tmout = 1000000; tmout; tmout--) {
unsigned int msr = serial_in(up, UART_MSR);
up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
@@ -3093,7 +3094,7 @@ static void serial8250_console_restore(struct uart_8250_port *up)
serial8250_set_divisor(port, baud, quot, frac);
serial_port_out(port, UART_LCR, up->lcr);
serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
}
/*

查看文件

@@ -35,7 +35,7 @@ struct uniphier8250_priv {
spinlock_t atomic_write_lock;
};
#if defined(CONFIG_SERIAL_8250_CONSOLE) && !defined(MODULE)
#ifdef CONFIG_SERIAL_8250_CONSOLE
static int __init uniphier_early_console_setup(struct earlycon_device *device,
const char *options)
{

查看文件

@@ -6,6 +6,7 @@
config SERIAL_8250
tristate "8250/16550 and compatible serial support"
select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
---help---
This selects whether you want to include the driver for the standard
serial ports. The standard answer is Y. People who might say N
@@ -387,7 +388,8 @@ config SERIAL_8250_MT6577
config SERIAL_8250_UNIPHIER
tristate "Support for UniPhier on-chip UART"
depends on SERIAL_8250 && ARCH_UNIPHIER
depends on SERIAL_8250
depends on ARCH_UNIPHIER || COMPILE_TEST
help
If you have a UniPhier based board and want to use the on-chip
serial ports, say Y to this option. If unsure, say N.
@@ -395,7 +397,7 @@ config SERIAL_8250_UNIPHIER
config SERIAL_8250_INGENIC
tristate "Support for Ingenic SoC serial ports"
depends on SERIAL_8250
depends on (OF_FLATTREE && SERIAL_8250_CONSOLE) || !SERIAL_EARLYCON
depends on OF_FLATTREE
depends on MIPS || COMPILE_TEST
help
If you have a system using an Ingenic SoC and wish to make use of

查看文件

@@ -736,6 +736,7 @@ config SERIAL_SH_SCI
tristate "SuperH SCI(F) serial port support"
depends on SUPERH || ARCH_RENESAS || H8300 || COMPILE_TEST
select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
config SERIAL_SH_SCI_NR_UARTS
int "Maximum number of SCI(F) serial ports"
@@ -1477,7 +1478,7 @@ config SERIAL_MPS2_UART_CONSOLE
config SERIAL_MPS2_UART
bool "MPS2 UART port"
depends on ARM || COMPILE_TEST
depends on ARCH_MPS2 || COMPILE_TEST
select SERIAL_CORE
help
This driver support the UART ports on ARM MPS2.

查看文件

@@ -2553,11 +2553,17 @@ static int sbsa_uart_probe(struct platform_device *pdev)
if (!uap)
return -ENOMEM;
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(&pdev->dev, "cannot obtain irq\n");
return ret;
}
uap->port.irq = ret;
uap->reg_offset = vendor_sbsa.reg_offset;
uap->vendor = &vendor_sbsa;
uap->fifosize = 32;
uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM;
uap->port.irq = platform_get_irq(pdev, 0);
uap->port.ops = &sbsa_uart_pops;
uap->fixed_baud = baudrate;

查看文件

@@ -108,6 +108,12 @@ struct atmel_uart_char {
u16 ch;
};
/*
* Be careful, the real size of the ring buffer is
* sizeof(atmel_uart_char) * ATMEL_SERIAL_RINGSIZE. It means that ring buffer
* can contain up to 1024 characters in PIO mode and up to 4096 characters in
* DMA mode.
*/
#define ATMEL_SERIAL_RINGSIZE 1024
/*
@@ -145,10 +151,10 @@ struct atmel_uart_port {
dma_cookie_t cookie_rx;
struct scatterlist sg_tx;
struct scatterlist sg_rx;
struct tasklet_struct tasklet;
unsigned int irq_status;
struct tasklet_struct tasklet_rx;
struct tasklet_struct tasklet_tx;
atomic_t tasklet_shutdown;
unsigned int irq_status_prev;
unsigned int status_change;
unsigned int tx_len;
struct circ_buf rx_ring;
@@ -281,6 +287,13 @@ static bool atmel_use_fifo(struct uart_port *port)
return atmel_port->fifo_size;
}
static void atmel_tasklet_schedule(struct atmel_uart_port *atmel_port,
struct tasklet_struct *t)
{
if (!atomic_read(&atmel_port->tasklet_shutdown))
tasklet_schedule(t);
}
static unsigned int atmel_get_lines_status(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
@@ -482,19 +495,21 @@ static void atmel_start_tx(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_use_pdc_tx(port)) {
if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
/* The transmitter is already running. Yes, we
really need this.*/
return;
if (atmel_use_pdc_tx(port) && (atmel_uart_readl(port, ATMEL_PDC_PTSR)
& ATMEL_PDC_TXTEN))
/* The transmitter is already running. Yes, we
really need this.*/
return;
if (atmel_use_pdc_tx(port) || atmel_use_dma_tx(port))
if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX))
atmel_stop_rx(port);
if (atmel_use_pdc_tx(port))
/* re-enable PDC transmit */
atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
}
/* Enable interrupts */
atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
}
@@ -710,7 +725,7 @@ static void atmel_rx_chars(struct uart_port *port)
status = atmel_uart_readl(port, ATMEL_US_CSR);
}
tasklet_schedule(&atmel_port->tasklet);
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
}
/*
@@ -781,7 +796,7 @@ static void atmel_complete_tx_dma(void *arg)
* remaining data from the beginning of xmit->buf to xmit->head.
*/
if (!uart_circ_empty(xmit))
tasklet_schedule(&atmel_port->tasklet);
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -966,7 +981,7 @@ static void atmel_complete_rx_dma(void *arg)
struct uart_port *port = arg;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
tasklet_schedule(&atmel_port->tasklet);
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
}
static void atmel_release_rx_dma(struct uart_port *port)
@@ -1006,7 +1021,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
if (dmastat == DMA_ERROR) {
dev_dbg(port->dev, "Get residue error, restart tasklet\n");
atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
tasklet_schedule(&atmel_port->tasklet);
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
return;
}
@@ -1160,8 +1175,11 @@ static void atmel_uart_timer_callback(unsigned long data)
struct uart_port *port = (void *)data;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
tasklet_schedule(&atmel_port->tasklet);
mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port));
if (!atomic_read(&atmel_port->tasklet_shutdown)) {
tasklet_schedule(&atmel_port->tasklet_rx);
mod_timer(&atmel_port->uart_timer,
jiffies + uart_poll_timeout(port));
}
}
/*
@@ -1183,7 +1201,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
atmel_uart_writel(port, ATMEL_US_IDR,
(ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
tasklet_schedule(&atmel_port->tasklet);
atmel_tasklet_schedule(atmel_port,
&atmel_port->tasklet_rx);
}
if (pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE |
@@ -1195,7 +1214,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
if (pending & ATMEL_US_TIMEOUT) {
atmel_uart_writel(port, ATMEL_US_IDR,
ATMEL_US_TIMEOUT);
tasklet_schedule(&atmel_port->tasklet);
atmel_tasklet_schedule(atmel_port,
&atmel_port->tasklet_rx);
}
}
@@ -1225,7 +1245,7 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
/* Either PDC or interrupt transmission */
atmel_uart_writel(port, ATMEL_US_IDR,
atmel_port->tx_done_mask);
tasklet_schedule(&atmel_port->tasklet);
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
}
}
@@ -1237,14 +1257,27 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
unsigned int status)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status_change;
if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
| ATMEL_US_CTSIC)) {
atmel_port->irq_status = status;
atmel_port->status_change = atmel_port->irq_status ^
atmel_port->irq_status_prev;
status_change = status ^ atmel_port->irq_status_prev;
atmel_port->irq_status_prev = status;
tasklet_schedule(&atmel_port->tasklet);
if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
| ATMEL_US_DCD | ATMEL_US_CTS)) {
/* TODO: All reads to CSR will clear these interrupts! */
if (status_change & ATMEL_US_RI)
port->icount.rng++;
if (status_change & ATMEL_US_DSR)
port->icount.dsr++;
if (status_change & ATMEL_US_DCD)
uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
if (status_change & ATMEL_US_CTS)
uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
wake_up_interruptible(&port->state->port.delta_msr_wait);
}
}
}
@@ -1571,37 +1604,25 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
/*
* tasklet handling tty stuff outside the interrupt handler.
*/
static void atmel_tasklet_func(unsigned long data)
static void atmel_tasklet_rx_func(unsigned long data)
{
struct uart_port *port = (struct uart_port *)data;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status = atmel_port->irq_status;
unsigned int status_change = atmel_port->status_change;
/* The interrupt handler does not take the lock */
spin_lock(&port->lock);
atmel_port->schedule_tx(port);
if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
| ATMEL_US_DCD | ATMEL_US_CTS)) {
/* TODO: All reads to CSR will clear these interrupts! */
if (status_change & ATMEL_US_RI)
port->icount.rng++;
if (status_change & ATMEL_US_DSR)
port->icount.dsr++;
if (status_change & ATMEL_US_DCD)
uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
if (status_change & ATMEL_US_CTS)
uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
wake_up_interruptible(&port->state->port.delta_msr_wait);
atmel_port->status_change = 0;
}
atmel_port->schedule_rx(port);
spin_unlock(&port->lock);
}
static void atmel_tasklet_tx_func(unsigned long data)
{
struct uart_port *port = (struct uart_port *)data;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
/* The interrupt handler does not take the lock */
spin_lock(&port->lock);
atmel_port->schedule_tx(port);
spin_unlock(&port->lock);
}
@@ -1785,7 +1806,11 @@ static int atmel_startup(struct uart_port *port)
return retval;
}
tasklet_enable(&atmel_port->tasklet);
atomic_set(&atmel_port->tasklet_shutdown, 0);
tasklet_init(&atmel_port->tasklet_rx, atmel_tasklet_rx_func,
(unsigned long)port);
tasklet_init(&atmel_port->tasklet_tx, atmel_tasklet_tx_func,
(unsigned long)port);
/*
* Initialize DMA (if necessary)
@@ -1833,7 +1858,6 @@ static int atmel_startup(struct uart_port *port)
/* Save current CSR for comparison in atmel_tasklet_func() */
atmel_port->irq_status_prev = atmel_get_lines_status(port);
atmel_port->irq_status = atmel_port->irq_status_prev;
/*
* Finally, enable the serial port
@@ -1905,29 +1929,36 @@ static void atmel_shutdown(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
/* Disable interrupts at device level */
atmel_uart_writel(port, ATMEL_US_IDR, -1);
/* Prevent spurious interrupts from scheduling the tasklet */
atomic_inc(&atmel_port->tasklet_shutdown);
/*
* Prevent any tasklets being scheduled during
* cleanup
*/
del_timer_sync(&atmel_port->uart_timer);
/* Make sure that no interrupt is on the fly */
synchronize_irq(port->irq);
/*
* Clear out any scheduled tasklets before
* we destroy the buffers
*/
tasklet_disable(&atmel_port->tasklet);
tasklet_kill(&atmel_port->tasklet);
tasklet_kill(&atmel_port->tasklet_rx);
tasklet_kill(&atmel_port->tasklet_tx);
/*
* Ensure everything is stopped and
* disable all interrupts, port and break condition.
* disable port and break condition.
*/
atmel_stop_rx(port);
atmel_stop_tx(port);
atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
atmel_uart_writel(port, ATMEL_US_IDR, -1);
/*
* Shut-down the DMA.
@@ -2311,10 +2342,6 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
port->irq = pdev->resource[1].start;
port->rs485_config = atmel_config_rs485;
tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
(unsigned long)port);
tasklet_disable(&atmel_port->tasklet);
memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
if (pdata && pdata->regs) {
@@ -2699,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
atmel_port->uart.line = ret;
atmel_serial_probe_fifos(atmel_port, pdev);
atomic_set(&atmel_port->tasklet_shutdown, 0);
spin_lock_init(&atmel_port->lock_suspended);
ret = atmel_init_port(atmel_port, pdev);
@@ -2795,7 +2823,8 @@ static int atmel_serial_remove(struct platform_device *pdev)
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
int ret = 0;
tasklet_kill(&atmel_port->tasklet);
tasklet_kill(&atmel_port->tasklet_rx);
tasklet_kill(&atmel_port->tasklet_tx);
device_init_wakeup(&pdev->dev, 0);

查看文件

@@ -813,8 +813,12 @@ static int bcm_uart_probe(struct platform_device *pdev)
struct clk *clk;
int ret;
if (pdev->dev.of_node)
pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
if (pdev->dev.of_node) {
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
if (pdev->id < 0)
pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
}
if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
return -EINVAL;

查看文件

@@ -1830,7 +1830,13 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.dev = &pdev->dev;
sport->port.type = PORT_LPUART;
sport->port.iotype = UPIO_MEM;
sport->port.irq = platform_get_irq(pdev, 0);
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(&pdev->dev, "cannot obtain irq\n");
return ret;
}
sport->port.irq = ret;
if (sport->lpuart32)
sport->port.ops = &lpuart32_pops;
else

查看文件

@@ -30,7 +30,6 @@
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/ioport.h>
@@ -51,9 +50,6 @@
#define PASS_LIMIT 256
/* Standard COM flags */
#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
static const struct {
unsigned int port;
unsigned int irq;
@@ -892,7 +888,7 @@ static void __init m32r_sio_init_ports(void)
up->port.iobase = old_serial_port[i].port;
up->port.irq = irq_canonicalize(old_serial_port[i].irq);
up->port.uartclk = BAUD_RATE * 16;
up->port.flags = STD_COM_FLAGS;
up->port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
up->port.membase = 0;
up->port.iotype = 0;
up->port.regshift = 0;
@@ -1060,19 +1056,4 @@ static int __init m32r_sio_init(void)
return ret;
}
static void __exit m32r_sio_exit(void)
{
int i;
for (i = 0; i < UART_NR; i++)
uart_remove_one_port(&m32r_sio_reg, &m32r_sio_ports[i].port);
uart_unregister_driver(&m32r_sio_reg);
}
module_init(m32r_sio_init);
module_exit(m32r_sio_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic M32R SIO serial driver");
device_initcall(m32r_sio_init);

查看文件

@@ -1,7 +1,7 @@
/*
* Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
*
* Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
* Copyright (C) 2012-2016 Alexander Shiyan <shc_work@mail.ru>
*
* Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
* Based on max3110.c, by Feng Tang <feng.tang@intel.com>
@@ -32,6 +32,7 @@
#define MAX310X_NAME "max310x"
#define MAX310X_MAJOR 204
#define MAX310X_MINOR 209
#define MAX310X_UART_NRMAX 16
/* MAX310X register definitions */
#define MAX310X_RHR_REG (0x00) /* RX FIFO */
@@ -155,10 +156,6 @@
#define MAX310X_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
#define MAX310X_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
#define MAX310X_LCR_RTS_BIT (1 << 7) /* RTS pin control */
#define MAX310X_LCR_WORD_LEN_5 (0x00)
#define MAX310X_LCR_WORD_LEN_6 (0x01)
#define MAX310X_LCR_WORD_LEN_7 (0x02)
#define MAX310X_LCR_WORD_LEN_8 (0x03)
/* IRDA register bits */
#define MAX310X_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
@@ -262,10 +259,10 @@ struct max310x_one {
struct uart_port port;
struct work_struct tx_work;
struct work_struct md_work;
struct work_struct rs_work;
};
struct max310x_port {
struct uart_driver uart;
struct max310x_devtype *devtype;
struct regmap *regmap;
struct mutex mutex;
@@ -276,6 +273,17 @@ struct max310x_port {
struct max310x_one p[0];
};
static struct uart_driver max310x_uart = {
.owner = THIS_MODULE,
.driver_name = MAX310X_NAME,
.dev_name = "ttyMAX",
.major = MAX310X_MAJOR,
.minor = MAX310X_MINOR,
.nr = MAX310X_UART_NRMAX,
};
static DECLARE_BITMAP(max310x_lines, MAX310X_UART_NRMAX);
static u8 max310x_port_read(struct uart_port *port, u8 reg)
{
struct max310x_port *s = dev_get_drvdata(port->dev);
@@ -594,9 +602,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
unsigned int sts, ch, flag;
if (unlikely(rxlen >= port->fifosize)) {
dev_warn_ratelimited(port->dev,
"Port %i: Possible RX FIFO overrun\n",
port->line);
dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n");
port->icount.buf_overrun++;
/* Ensure sanity of RX level */
rxlen = port->fifosize;
@@ -715,13 +721,13 @@ static irqreturn_t max310x_ist(int irq, void *dev_id)
{
struct max310x_port *s = (struct max310x_port *)dev_id;
if (s->uart.nr > 1) {
if (s->devtype->nr > 1) {
do {
unsigned int val = ~0;
WARN_ON_ONCE(regmap_read(s->regmap,
MAX310X_GLOBALIRQ_REG, &val));
val = ((1 << s->uart.nr) - 1) & ~val;
val = ((1 << s->devtype->nr) - 1) & ~val;
if (!val)
break;
max310x_port_irq(s, fls(val) - 1);
@@ -796,7 +802,7 @@ static void max310x_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
{
unsigned int lcr, flow = 0;
unsigned int lcr = 0, flow = 0;
int baud;
/* Mask termios capabilities we don't support */
@@ -805,17 +811,16 @@ static void max310x_set_termios(struct uart_port *port,
/* Word size */
switch (termios->c_cflag & CSIZE) {
case CS5:
lcr = MAX310X_LCR_WORD_LEN_5;
break;
case CS6:
lcr = MAX310X_LCR_WORD_LEN_6;
lcr = MAX310X_LCR_LENGTH0_BIT;
break;
case CS7:
lcr = MAX310X_LCR_WORD_LEN_7;
lcr = MAX310X_LCR_LENGTH1_BIT;
break;
case CS8:
default:
lcr = MAX310X_LCR_WORD_LEN_8;
lcr = MAX310X_LCR_LENGTH1_BIT | MAX310X_LCR_LENGTH0_BIT;
break;
}
@@ -877,36 +882,45 @@ static void max310x_set_termios(struct uart_port *port,
uart_update_timeout(port, termios->c_cflag, baud);
}
static int max310x_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
static void max310x_rs_proc(struct work_struct *ws)
{
struct max310x_one *one = container_of(ws, struct max310x_one, rs_work);
unsigned int val;
if (rs485->delay_rts_before_send > 0x0f ||
rs485->delay_rts_after_send > 0x0f)
return -ERANGE;
val = (one->port.rs485.delay_rts_before_send << 4) |
one->port.rs485.delay_rts_after_send;
max310x_port_write(&one->port, MAX310X_HDPIXDELAY_REG, val);
val = (rs485->delay_rts_before_send << 4) |
rs485->delay_rts_after_send;
max310x_port_write(port, MAX310X_HDPIXDELAY_REG, val);
if (rs485->flags & SER_RS485_ENABLED) {
max310x_port_update(port, MAX310X_MODE1_REG,
if (one->port.rs485.flags & SER_RS485_ENABLED) {
max310x_port_update(&one->port, MAX310X_MODE1_REG,
MAX310X_MODE1_TRNSCVCTRL_BIT,
MAX310X_MODE1_TRNSCVCTRL_BIT);
max310x_port_update(port, MAX310X_MODE2_REG,
max310x_port_update(&one->port, MAX310X_MODE2_REG,
MAX310X_MODE2_ECHOSUPR_BIT,
MAX310X_MODE2_ECHOSUPR_BIT);
} else {
max310x_port_update(port, MAX310X_MODE1_REG,
max310x_port_update(&one->port, MAX310X_MODE1_REG,
MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
max310x_port_update(port, MAX310X_MODE2_REG,
max310x_port_update(&one->port, MAX310X_MODE2_REG,
MAX310X_MODE2_ECHOSUPR_BIT, 0);
}
}
static int max310x_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
struct max310x_one *one = container_of(port, struct max310x_one, port);
if ((rs485->delay_rts_before_send > 0x0f) ||
(rs485->delay_rts_after_send > 0x0f))
return -ERANGE;
rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_ENABLED;
memset(rs485->padding, 0, sizeof(rs485->padding));
port->rs485 = *rs485;
schedule_work(&one->rs_work);
return 0;
}
@@ -1009,8 +1023,8 @@ static int __maybe_unused max310x_suspend(struct device *dev)
struct max310x_port *s = dev_get_drvdata(dev);
int i;
for (i = 0; i < s->uart.nr; i++) {
uart_suspend_port(&s->uart, &s->p[i].port);
for (i = 0; i < s->devtype->nr; i++) {
uart_suspend_port(&max310x_uart, &s->p[i].port);
s->devtype->power(&s->p[i].port, 0);
}
@@ -1022,9 +1036,9 @@ static int __maybe_unused max310x_resume(struct device *dev)
struct max310x_port *s = dev_get_drvdata(dev);
int i;
for (i = 0; i < s->uart.nr; i++) {
for (i = 0; i < s->devtype->nr; i++) {
s->devtype->power(&s->p[i].port, 1);
uart_resume_port(&s->uart, &s->p[i].port);
uart_resume_port(&max310x_uart, &s->p[i].port);
}
return 0;
@@ -1159,18 +1173,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
uartclk = max310x_set_ref_clk(s, freq, xtal);
dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
/* Register UART driver */
s->uart.owner = THIS_MODULE;
s->uart.dev_name = "ttyMAX";
s->uart.major = MAX310X_MAJOR;
s->uart.minor = MAX310X_MINOR;
s->uart.nr = devtype->nr;
ret = uart_register_driver(&s->uart);
if (ret) {
dev_err(dev, "Registering UART driver failed\n");
goto out_clk;
}
#ifdef CONFIG_GPIOLIB
/* Setup GPIO cotroller */
s->gpio.owner = THIS_MODULE;
@@ -1183,16 +1185,24 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
s->gpio.base = -1;
s->gpio.ngpio = devtype->nr * 4;
s->gpio.can_sleep = 1;
ret = gpiochip_add_data(&s->gpio, s);
ret = devm_gpiochip_add_data(dev, &s->gpio, s);
if (ret)
goto out_uart;
goto out_clk;
#endif
mutex_init(&s->mutex);
for (i = 0; i < devtype->nr; i++) {
unsigned int line;
line = find_first_zero_bit(max310x_lines, MAX310X_UART_NRMAX);
if (line == MAX310X_UART_NRMAX) {
ret = -ERANGE;
goto out_uart;
}
/* Initialize port data */
s->p[i].port.line = i;
s->p[i].port.line = line;
s->p[i].port.dev = dev;
s->p[i].port.irq = irq;
s->p[i].port.type = PORT_MAX310X;
@@ -1214,10 +1224,19 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
MAX310X_MODE1_IRQSEL_BIT);
/* Initialize queue for start TX */
INIT_WORK(&s->p[i].tx_work, max310x_wq_proc);
/* Initialize queue for changing mode */
/* Initialize queue for changing LOOPBACK mode */
INIT_WORK(&s->p[i].md_work, max310x_md_proc);
/* Initialize queue for changing RS485 mode */
INIT_WORK(&s->p[i].rs_work, max310x_rs_proc);
/* Register port */
uart_add_one_port(&s->uart, &s->p[i].port);
ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
if (ret) {
s->p[i].port.dev = NULL;
goto out_uart;
}
set_bit(line, max310x_lines);
/* Go to suspend mode */
devtype->power(&s->p[i].port, 0);
}
@@ -1230,14 +1249,15 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
dev_err(dev, "Unable to reguest IRQ %i\n", irq);
mutex_destroy(&s->mutex);
#ifdef CONFIG_GPIOLIB
gpiochip_remove(&s->gpio);
out_uart:
#endif
uart_unregister_driver(&s->uart);
for (i = 0; i < devtype->nr; i++) {
if (s->p[i].port.dev) {
uart_remove_one_port(&max310x_uart, &s->p[i].port);
clear_bit(s->p[i].port.line, max310x_lines);
}
}
mutex_destroy(&s->mutex);
out_clk:
clk_disable_unprepare(s->clk);
@@ -1250,19 +1270,16 @@ static int max310x_remove(struct device *dev)
struct max310x_port *s = dev_get_drvdata(dev);
int i;
#ifdef CONFIG_GPIOLIB
gpiochip_remove(&s->gpio);
#endif
for (i = 0; i < s->uart.nr; i++) {
for (i = 0; i < s->devtype->nr; i++) {
cancel_work_sync(&s->p[i].tx_work);
cancel_work_sync(&s->p[i].md_work);
uart_remove_one_port(&s->uart, &s->p[i].port);
cancel_work_sync(&s->p[i].rs_work);
uart_remove_one_port(&max310x_uart, &s->p[i].port);
clear_bit(s->p[i].port.line, max310x_lines);
s->devtype->power(&s->p[i].port, 0);
}
mutex_destroy(&s->mutex);
uart_unregister_driver(&s->uart);
clk_disable_unprepare(s->clk);
return 0;
@@ -1335,7 +1352,7 @@ static const struct spi_device_id max310x_id_table[] = {
};
MODULE_DEVICE_TABLE(spi, max310x_id_table);
static struct spi_driver max310x_uart_driver = {
static struct spi_driver max310x_spi_driver = {
.driver = {
.name = MAX310X_NAME,
.of_match_table = of_match_ptr(max310x_dt_ids),
@@ -1345,9 +1362,36 @@ static struct spi_driver max310x_uart_driver = {
.remove = max310x_spi_remove,
.id_table = max310x_id_table,
};
module_spi_driver(max310x_uart_driver);
#endif
static int __init max310x_uart_init(void)
{
int ret;
bitmap_zero(max310x_lines, MAX310X_UART_NRMAX);
ret = uart_register_driver(&max310x_uart);
if (ret)
return ret;
#ifdef CONFIG_SPI_MASTER
spi_register_driver(&max310x_spi_driver);
#endif
return 0;
}
module_init(max310x_uart_init);
static void __exit max310x_uart_exit(void)
{
#ifdef CONFIG_SPI_MASTER
spi_unregister_driver(&max310x_spi_driver);
#endif
uart_unregister_driver(&max310x_uart);
}
module_exit(max310x_uart_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
MODULE_DESCRIPTION("MAX310X serial driver");

查看文件

@@ -1,4 +1,6 @@
/*
* MPS2 UART driver
*
* Copyright (C) 2015 ARM Limited
*
* Author: Vladimir Murzin <vladimir.murzin@arm.com>
@@ -17,7 +19,6 @@
#include <linux/console.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -569,30 +570,20 @@ static int mps2_serial_probe(struct platform_device *pdev)
return 0;
}
static int mps2_serial_remove(struct platform_device *pdev)
{
struct mps2_uart_port *mps_port = platform_get_drvdata(pdev);
uart_remove_one_port(&mps2_uart_driver, &mps_port->port);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id mps2_match[] = {
{ .compatible = "arm,mps2-uart", },
{},
};
MODULE_DEVICE_TABLE(of, mps2_match);
#endif
static struct platform_driver mps2_serial_driver = {
.probe = mps2_serial_probe,
.remove = mps2_serial_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(mps2_match),
.suppress_bind_attrs = true,
},
};
@@ -610,16 +601,4 @@ static int __init mps2_uart_init(void)
return ret;
}
module_init(mps2_uart_init);
static void __exit mps2_uart_exit(void)
{
platform_driver_unregister(&mps2_serial_driver);
uart_unregister_driver(&mps2_uart_driver);
}
module_exit(mps2_uart_exit);
MODULE_AUTHOR("Vladimir Murzin <vladimir.murzin@arm.com>");
MODULE_DESCRIPTION("MPS2 UART driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRIVER_NAME);
arch_initcall(mps2_uart_init);

查看文件

@@ -19,33 +19,147 @@
# define SUPPORT_SYSRQ
#endif
#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/wait.h>
#include "msm_serial.h"
#define UART_MR1 0x0000
#define UARTDM_BURST_SIZE 16 /* in bytes */
#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
#define UART_MR1_RX_RDY_CTL BIT(7)
#define UART_MR1_CTS_CTL BIT(6)
#define UART_MR2 0x0004
#define UART_MR2_ERROR_MODE BIT(6)
#define UART_MR2_BITS_PER_CHAR 0x30
#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
#define UART_MR2_PARITY_MODE_NONE 0x0
#define UART_MR2_PARITY_MODE_ODD 0x1
#define UART_MR2_PARITY_MODE_EVEN 0x2
#define UART_MR2_PARITY_MODE_SPACE 0x3
#define UART_MR2_PARITY_MODE 0x3
#define UART_CSR 0x0008
#define UART_TF 0x000C
#define UARTDM_TF 0x0070
#define UART_CR 0x0010
#define UART_CR_CMD_NULL (0 << 4)
#define UART_CR_CMD_RESET_RX (1 << 4)
#define UART_CR_CMD_RESET_TX (2 << 4)
#define UART_CR_CMD_RESET_ERR (3 << 4)
#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
#define UART_CR_CMD_START_BREAK (5 << 4)
#define UART_CR_CMD_STOP_BREAK (6 << 4)
#define UART_CR_CMD_RESET_CTS (7 << 4)
#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
#define UART_CR_CMD_PACKET_MODE (9 << 4)
#define UART_CR_CMD_MODE_RESET (12 << 4)
#define UART_CR_CMD_SET_RFR (13 << 4)
#define UART_CR_CMD_RESET_RFR (14 << 4)
#define UART_CR_CMD_PROTECTION_EN (16 << 4)
#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
#define UART_CR_CMD_FORCE_STALE (4 << 8)
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
#define UART_CR_TX_DISABLE BIT(3)
#define UART_CR_TX_ENABLE BIT(2)
#define UART_CR_RX_DISABLE BIT(1)
#define UART_CR_RX_ENABLE BIT(0)
#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
#define UART_IMR 0x0014
#define UART_IMR_TXLEV BIT(0)
#define UART_IMR_RXSTALE BIT(3)
#define UART_IMR_RXLEV BIT(4)
#define UART_IMR_DELTA_CTS BIT(5)
#define UART_IMR_CURRENT_CTS BIT(6)
#define UART_IMR_RXBREAK_START BIT(10)
#define UART_IPR_RXSTALE_LAST 0x20
#define UART_IPR_STALE_LSB 0x1F
#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
#define UART_IPR 0x0018
#define UART_TFWR 0x001C
#define UART_RFWR 0x0020
#define UART_HCR 0x0024
#define UART_MREG 0x0028
#define UART_NREG 0x002C
#define UART_DREG 0x0030
#define UART_MNDREG 0x0034
#define UART_IRDA 0x0038
#define UART_MISR_MODE 0x0040
#define UART_MISR_RESET 0x0044
#define UART_MISR_EXPORT 0x0048
#define UART_MISR_VAL 0x004C
#define UART_TEST_CTRL 0x0050
#define UART_SR 0x0008
#define UART_SR_HUNT_CHAR BIT(7)
#define UART_SR_RX_BREAK BIT(6)
#define UART_SR_PAR_FRAME_ERR BIT(5)
#define UART_SR_OVERRUN BIT(4)
#define UART_SR_TX_EMPTY BIT(3)
#define UART_SR_TX_READY BIT(2)
#define UART_SR_RX_FULL BIT(1)
#define UART_SR_RX_READY BIT(0)
#define UART_RF 0x000C
#define UARTDM_RF 0x0070
#define UART_MISR 0x0010
#define UART_ISR 0x0014
#define UART_ISR_TX_READY BIT(7)
#define UARTDM_RXFS 0x50
#define UARTDM_RXFS_BUF_SHIFT 0x7
#define UARTDM_RXFS_BUF_MASK 0x7
#define UARTDM_DMEN 0x3C
#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
#define UARTDM_DMRX 0x34
#define UARTDM_NCF_TX 0x40
#define UARTDM_RX_TOTAL_SNAP 0x38
#define UARTDM_BURST_SIZE 16 /* in bytes */
#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
enum {
UARTDM_1P1 = 1,
@@ -78,10 +192,65 @@ struct msm_port {
struct msm_dma rx_dma;
};
#define UART_TO_MSM(uart_port) container_of(uart_port, struct msm_port, uart)
static
void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
{
writel_relaxed(val, port->membase + off);
}
static
unsigned int msm_read(struct uart_port *port, unsigned int off)
{
return readl_relaxed(port->membase + off);
}
/*
* Setup the MND registers to use the TCXO clock.
*/
static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
{
msm_write(port, 0x06, UART_MREG);
msm_write(port, 0xF1, UART_NREG);
msm_write(port, 0x0F, UART_DREG);
msm_write(port, 0x1A, UART_MNDREG);
port->uartclk = 1843200;
}
/*
* Setup the MND registers to use the TCXO clock divided by 4.
*/
static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
{
msm_write(port, 0x18, UART_MREG);
msm_write(port, 0xF6, UART_NREG);
msm_write(port, 0x0F, UART_DREG);
msm_write(port, 0x0A, UART_MNDREG);
port->uartclk = 1843200;
}
static void msm_serial_set_mnd_regs(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
/*
* These registers don't exist so we change the clk input rate
* on uartdm hardware instead
*/
if (msm_port->is_uartdm)
return;
if (port->uartclk == 19200000)
msm_serial_set_mnd_regs_tcxo(port);
else if (port->uartclk == 4800000)
msm_serial_set_mnd_regs_tcxoby4(port);
}
static void msm_handle_tx(struct uart_port *port);
static void msm_start_rx_dma(struct msm_port *msm_port);
void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
static void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
{
struct device *dev = port->dev;
unsigned int mapped;
@@ -388,10 +557,6 @@ static void msm_complete_rx_dma(void *args)
val &= ~dma->enable_bit;
msm_write(port, val, UARTDM_DMEN);
/* Restore interrupts */
msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE;
msm_write(port, msm_port->imr, UART_IMR);
if (msm_read(port, UART_SR) & UART_SR_OVERRUN) {
port->icount.overrun++;
tty_insert_flip_char(tport, 0, TTY_OVERRUN);
@@ -726,7 +891,7 @@ static void msm_handle_tx(struct uart_port *port)
return;
}
pio_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
pio_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
dma_min = 1; /* Always DMA */

查看文件

@@ -1,184 +0,0 @@
/*
* Copyright (C) 2007 Google, Inc.
* Author: Robert Love <rlove@google.com>
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DRIVERS_SERIAL_MSM_SERIAL_H
#define __DRIVERS_SERIAL_MSM_SERIAL_H
#define UART_MR1 0x0000
#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
#define UART_MR1_RX_RDY_CTL BIT(7)
#define UART_MR1_CTS_CTL BIT(6)
#define UART_MR2 0x0004
#define UART_MR2_ERROR_MODE BIT(6)
#define UART_MR2_BITS_PER_CHAR 0x30
#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
#define UART_MR2_PARITY_MODE_NONE 0x0
#define UART_MR2_PARITY_MODE_ODD 0x1
#define UART_MR2_PARITY_MODE_EVEN 0x2
#define UART_MR2_PARITY_MODE_SPACE 0x3
#define UART_MR2_PARITY_MODE 0x3
#define UART_CSR 0x0008
#define UART_TF 0x000C
#define UARTDM_TF 0x0070
#define UART_CR 0x0010
#define UART_CR_CMD_NULL (0 << 4)
#define UART_CR_CMD_RESET_RX (1 << 4)
#define UART_CR_CMD_RESET_TX (2 << 4)
#define UART_CR_CMD_RESET_ERR (3 << 4)
#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
#define UART_CR_CMD_START_BREAK (5 << 4)
#define UART_CR_CMD_STOP_BREAK (6 << 4)
#define UART_CR_CMD_RESET_CTS (7 << 4)
#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
#define UART_CR_CMD_PACKET_MODE (9 << 4)
#define UART_CR_CMD_MODE_RESET (12 << 4)
#define UART_CR_CMD_SET_RFR (13 << 4)
#define UART_CR_CMD_RESET_RFR (14 << 4)
#define UART_CR_CMD_PROTECTION_EN (16 << 4)
#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
#define UART_CR_CMD_FORCE_STALE (4 << 8)
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
#define UART_CR_TX_DISABLE BIT(3)
#define UART_CR_TX_ENABLE BIT(2)
#define UART_CR_RX_DISABLE BIT(1)
#define UART_CR_RX_ENABLE BIT(0)
#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
#define UART_IMR 0x0014
#define UART_IMR_TXLEV BIT(0)
#define UART_IMR_RXSTALE BIT(3)
#define UART_IMR_RXLEV BIT(4)
#define UART_IMR_DELTA_CTS BIT(5)
#define UART_IMR_CURRENT_CTS BIT(6)
#define UART_IMR_RXBREAK_START BIT(10)
#define UART_IPR_RXSTALE_LAST 0x20
#define UART_IPR_STALE_LSB 0x1F
#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
#define UART_IPR 0x0018
#define UART_TFWR 0x001C
#define UART_RFWR 0x0020
#define UART_HCR 0x0024
#define UART_MREG 0x0028
#define UART_NREG 0x002C
#define UART_DREG 0x0030
#define UART_MNDREG 0x0034
#define UART_IRDA 0x0038
#define UART_MISR_MODE 0x0040
#define UART_MISR_RESET 0x0044
#define UART_MISR_EXPORT 0x0048
#define UART_MISR_VAL 0x004C
#define UART_TEST_CTRL 0x0050
#define UART_SR 0x0008
#define UART_SR_HUNT_CHAR BIT(7)
#define UART_SR_RX_BREAK BIT(6)
#define UART_SR_PAR_FRAME_ERR BIT(5)
#define UART_SR_OVERRUN BIT(4)
#define UART_SR_TX_EMPTY BIT(3)
#define UART_SR_TX_READY BIT(2)
#define UART_SR_RX_FULL BIT(1)
#define UART_SR_RX_READY BIT(0)
#define UART_RF 0x000C
#define UARTDM_RF 0x0070
#define UART_MISR 0x0010
#define UART_ISR 0x0014
#define UART_ISR_TX_READY BIT(7)
#define UARTDM_RXFS 0x50
#define UARTDM_RXFS_BUF_SHIFT 0x7
#define UARTDM_RXFS_BUF_MASK 0x7
#define UARTDM_DMEN 0x3C
#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
#define UARTDM_DMRX 0x34
#define UARTDM_NCF_TX 0x40
#define UARTDM_RX_TOTAL_SNAP 0x38
#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
static inline
void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
{
writel_relaxed(val, port->membase + off);
}
static inline
unsigned int msm_read(struct uart_port *port, unsigned int off)
{
return readl_relaxed(port->membase + off);
}
/*
* Setup the MND registers to use the TCXO clock.
*/
static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
{
msm_write(port, 0x06, UART_MREG);
msm_write(port, 0xF1, UART_NREG);
msm_write(port, 0x0F, UART_DREG);
msm_write(port, 0x1A, UART_MNDREG);
port->uartclk = 1843200;
}
/*
* Setup the MND registers to use the TCXO clock divided by 4.
*/
static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
{
msm_write(port, 0x18, UART_MREG);
msm_write(port, 0xF6, UART_NREG);
msm_write(port, 0x0F, UART_DREG);
msm_write(port, 0x0A, UART_MNDREG);
port->uartclk = 1843200;
}
static inline
void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
{
if (port->uartclk == 19200000)
msm_serial_set_mnd_regs_tcxo(port);
else if (port->uartclk == 4800000)
msm_serial_set_mnd_regs_tcxoby4(port);
}
#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */

查看文件

@@ -300,6 +300,8 @@ static int mvebu_uart_startup(struct uart_port *port)
static void mvebu_uart_shutdown(struct uart_port *port)
{
writel(0, port->membase + UART_CTRL);
free_irq(port->irq, port);
}
static void mvebu_uart_set_termios(struct uart_port *port,

查看文件

@@ -445,7 +445,6 @@ static int pic32_uart_startup(struct uart_port *port)
sport->idx);
if (!sport->irq_rx_name) {
dev_err(port->dev, "%s: kasprintf err!", __func__);
kfree(sport->irq_fault_name);
ret = -ENOMEM;
goto out_f;
}

查看文件

@@ -1720,7 +1720,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
r_ports = platform_get_resource(uap->pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(uap->pdev, 0);
if (!r_ports || !irq)
if (!r_ports || irq <= 0)
return -ENODEV;
uap->port.mapbase = r_ports->start;

查看文件

@@ -27,7 +27,6 @@
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
@@ -829,7 +828,6 @@ static const struct of_device_id serial_pxa_dt_ids[] = {
{ .compatible = "mrvl,mmp-uart", },
{}
};
MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
static int serial_pxa_probe_dt(struct platform_device *pdev,
struct uart_pxa_port *sport)
@@ -914,28 +912,15 @@ static int serial_pxa_probe(struct platform_device *dev)
return ret;
}
static int serial_pxa_remove(struct platform_device *dev)
{
struct uart_pxa_port *sport = platform_get_drvdata(dev);
uart_remove_one_port(&serial_pxa_reg, &sport->port);
clk_unprepare(sport->clk);
clk_put(sport->clk);
kfree(sport);
return 0;
}
static struct platform_driver serial_pxa_driver = {
.probe = serial_pxa_probe,
.remove = serial_pxa_remove,
.driver = {
.name = "pxa2xx-uart",
#ifdef CONFIG_PM
.pm = &serial_pxa_pm_ops,
#endif
.suppress_bind_attrs = true,
.of_match_table = serial_pxa_dt_ids,
},
};
@@ -954,15 +939,4 @@ static int __init serial_pxa_init(void)
return ret;
}
static void __exit serial_pxa_exit(void)
{
platform_driver_unregister(&serial_pxa_driver);
uart_unregister_driver(&serial_pxa_reg);
}
module_init(serial_pxa_init);
module_exit(serial_pxa_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pxa2xx-uart");
device_initcall(serial_pxa_init);

查看文件

@@ -169,8 +169,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
return;
if (s3c24xx_serial_has_interrupt_mask(port))
__set_bit(S3C64XX_UINTM_TXD,
portaddrl(port, S3C64XX_UINTM));
s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
else
disable_irq_nosync(ourport->tx_irq);
@@ -235,8 +234,7 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
/* Mask Tx interrupt */
if (s3c24xx_serial_has_interrupt_mask(port))
__set_bit(S3C64XX_UINTM_TXD,
portaddrl(port, S3C64XX_UINTM));
s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
else
disable_irq_nosync(ourport->tx_irq);
@@ -269,8 +267,8 @@ static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
/* Unmask Tx interrupt */
if (s3c24xx_serial_has_interrupt_mask(port))
__clear_bit(S3C64XX_UINTM_TXD,
portaddrl(port, S3C64XX_UINTM));
s3c24xx_clear_bit(port, S3C64XX_UINTM_TXD,
S3C64XX_UINTM);
else
enable_irq(ourport->tx_irq);
@@ -397,8 +395,8 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
if (rx_enabled(port)) {
dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
if (s3c24xx_serial_has_interrupt_mask(port))
__set_bit(S3C64XX_UINTM_RXD,
portaddrl(port, S3C64XX_UINTM));
s3c24xx_set_bit(port, S3C64XX_UINTM_RXD,
S3C64XX_UINTM);
else
disable_irq_nosync(ourport->rx_irq);
rx_enabled(port) = 0;
@@ -1069,7 +1067,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
spin_unlock_irqrestore(&port->lock, flags);
/* Enable Rx Interrupt */
__clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM);
dbg("s3c64xx_serial_startup ok\n");
return ret;
@@ -1684,7 +1682,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
return -ENODEV;
if (port->mapbase != 0)
return 0;
return -EINVAL;
/* setup info for port */
port->dev = &platdev->dev;
@@ -1738,22 +1736,25 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->dma = devm_kzalloc(port->dev,
sizeof(*ourport->dma),
GFP_KERNEL);
if (!ourport->dma)
return -ENOMEM;
if (!ourport->dma) {
ret = -ENOMEM;
goto err;
}
}
ourport->clk = clk_get(&platdev->dev, "uart");
if (IS_ERR(ourport->clk)) {
pr_err("%s: Controller clock not found\n",
dev_name(&platdev->dev));
return PTR_ERR(ourport->clk);
ret = PTR_ERR(ourport->clk);
goto err;
}
ret = clk_prepare_enable(ourport->clk);
if (ret) {
pr_err("uart: clock failed to prepare+enable: %d\n", ret);
clk_put(ourport->clk);
return ret;
goto err;
}
/* Keep all interrupts masked and cleared */
@@ -1769,7 +1770,12 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
/* reset the fifos (and setup the uart) */
s3c24xx_serial_resetport(port, cfg);
return 0;
err:
port->mapbase = 0;
return ret;
}
/* Device driver serial port probe */
@@ -1836,8 +1842,6 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
ourport->min_dma_size = max_t(int, ourport->port.fifosize,
dma_get_cache_alignment());
probe_index++;
dbg("%s: initialising port %p...\n", __func__, ourport);
ret = s3c24xx_serial_init_port(ourport, pdev);
@@ -1867,6 +1871,8 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
if (ret < 0)
dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
probe_index++;
return 0;
}

查看文件

@@ -117,10 +117,38 @@ struct s3c24xx_uart_port {
#define portaddrl(port, reg) \
((unsigned long *)(unsigned long)((port)->membase + (reg)))
#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
#define rd_regb(port, reg) (readb_relaxed(portaddr(port, reg)))
#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))
#define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
#define wr_regb(port, reg, val) writeb_relaxed(val, portaddr(port, reg))
#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
/* Byte-order aware bit setting/clearing functions. */
static inline void s3c24xx_set_bit(struct uart_port *port, int idx,
unsigned int reg)
{
unsigned long flags;
u32 val;
local_irq_save(flags);
val = rd_regl(port, reg);
val |= (1 << idx);
wr_regl(port, reg, val);
local_irq_restore(flags);
}
static inline void s3c24xx_clear_bit(struct uart_port *port, int idx,
unsigned int reg)
{
unsigned long flags;
u32 val;
local_irq_save(flags);
val = rd_regl(port, reg);
val &= ~(1 << idx);
wr_regl(port, reg, val);
local_irq_restore(flags);
}
#endif

查看文件

@@ -1317,7 +1317,12 @@ static int tegra_uart_probe(struct platform_device *pdev)
}
u->iotype = UPIO_MEM32;
u->irq = platform_get_irq(pdev, 0);
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't get IRQ\n");
return ret;
}
u->irq = ret;
u->regshift = 2;
ret = uart_add_one_port(&tegra_uart_driver, u);
if (ret < 0) {

查看文件

@@ -887,7 +887,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
/*
* Free and release old regions
*/
if (old_type != PORT_UNKNOWN)
if (old_type != PORT_UNKNOWN && uport->ops->release_port)
uport->ops->release_port(uport);
uport->iobase = new_port;
@@ -900,7 +900,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
/*
* Claim and map the new regions
*/
if (uport->type != PORT_UNKNOWN) {
if (uport->type != PORT_UNKNOWN && uport->ops->request_port) {
retval = uport->ops->request_port(uport);
} else {
/* Always success - Jean II */
@@ -1125,7 +1125,7 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
* If we already have a port type configured,
* we must release its resources.
*/
if (uport->type != PORT_UNKNOWN)
if (uport->type != PORT_UNKNOWN && uport->ops->release_port)
uport->ops->release_port(uport);
flags = UART_CONFIG_TYPE;
@@ -2897,7 +2897,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
/*
* Free the port IO and memory resources, if any.
*/
if (uport->type != PORT_UNKNOWN)
if (uport->type != PORT_UNKNOWN && uport->ops->release_port)
uport->ops->release_port(uport);
kfree(uport->tty_groups);

查看文件

@@ -52,6 +52,9 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
int value_array[UART_GPIO_MAX];
unsigned int count = 0;
if (gpios == NULL)
return;
for (i = 0; i < UART_GPIO_MAX; i++)
if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) {
desc_array[count] = gpios->gpio[i];
@@ -73,6 +76,9 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
{
enum mctrl_gpio_idx i;
if (gpios == NULL)
return *mctrl;
for (i = 0; i < UART_GPIO_MAX; i++) {
if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) {
if (gpiod_get_value(gpios->gpio[i]))
@@ -86,6 +92,27 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
}
EXPORT_SYMBOL_GPL(mctrl_gpio_get);
unsigned int
mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl)
{
enum mctrl_gpio_idx i;
if (gpios == NULL)
return *mctrl;
for (i = 0; i < UART_GPIO_MAX; i++) {
if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) {
if (gpiod_get_value(gpios->gpio[i]))
*mctrl |= mctrl_gpios_desc[i].mctrl;
else
*mctrl &= ~mctrl_gpios_desc[i].mctrl;
}
}
return *mctrl;
}
EXPORT_SYMBOL_GPL(mctrl_gpio_get_outputs);
struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
{
struct mctrl_gpios *gpios;
@@ -203,6 +230,9 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
{
enum mctrl_gpio_idx i;
if (gpios == NULL)
return;
for (i = 0; i < UART_GPIO_MAX; i++) {
if (gpios->irq[i])
devm_free_irq(gpios->port->dev, gpios->irq[i], gpios);
@@ -218,6 +248,9 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
{
enum mctrl_gpio_idx i;
if (gpios == NULL)
return;
/* .enable_ms may be called multiple times */
if (gpios->mctrl_on)
return;
@@ -240,6 +273,9 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
{
enum mctrl_gpio_idx i;
if (gpios == NULL)
return;
if (!gpios->mctrl_on)
return;

查看文件

@@ -48,11 +48,18 @@ struct mctrl_gpios;
void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl);
/*
* Get state of the modem control output lines from GPIOs.
* Get state of the modem control input lines from GPIOs.
* The mctrl flags are updated and returned.
*/
unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl);
/*
* Get state of the modem control output lines from GPIOs.
* The mctrl flags are updated and returned.
*/
unsigned int
mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl);
/*
* Returns the associated struct gpio_desc to the modem line gidx
*/
@@ -107,6 +114,12 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
return *mctrl;
}
static inline unsigned int
mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl)
{
return *mctrl;
}
static inline
struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
enum mctrl_gpio_idx gidx)

查看文件

@@ -57,6 +57,7 @@
#include <asm/sh_bios.h>
#endif
#include "serial_mctrl_gpio.h"
#include "sh-sci.h"
/* Offsets into the sci_port->irqs array */
@@ -111,6 +112,7 @@ struct sci_port {
unsigned int error_clear;
unsigned int sampling_rate_mask;
resource_size_t reg_size;
struct mctrl_gpios *gpios;
/* Break timer */
struct timer_list break_timer;
@@ -139,6 +141,8 @@ struct sci_port {
struct timer_list rx_timer;
unsigned int rx_timeout;
#endif
bool autorts;
};
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
@@ -701,7 +705,6 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
static void sci_init_pins(struct uart_port *port, unsigned int cflag)
{
struct sci_port *s = to_sci_port(port);
const struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
/*
* Use port-specific handler if provided.
@@ -711,21 +714,28 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
return;
}
/*
* For the generic path SCSPTR is necessary. Bail out if that's
* unavailable, too.
*/
if (!reg->size)
return;
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
u16 ctrl = serial_port_in(port, SCPCR);
if ((s->cfg->capabilities & SCIx_HAVE_RTSCTS) &&
((!(cflag & CRTSCTS)))) {
unsigned short status;
/* Enable RXD and TXD pin functions */
ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
if (to_sci_port(port)->cfg->capabilities & SCIx_HAVE_RTSCTS) {
/* RTS# is output, driven 1 */
ctrl |= SCPCR_RTSC;
serial_port_out(port, SCPDR,
serial_port_in(port, SCPDR) | SCPDR_RTSD);
/* Enable CTS# pin function */
ctrl &= ~SCPCR_CTSC;
}
serial_port_out(port, SCPCR, ctrl);
} else if (sci_getreg(port, SCSPTR)->size) {
u16 status = serial_port_in(port, SCSPTR);
status = serial_port_in(port, SCSPTR);
status &= ~SCSPTR_CTSIO;
status |= SCSPTR_RTSIO;
serial_port_out(port, SCSPTR, status); /* Set RTS = 1 */
/* RTS# is output, driven 1 */
status |= SCSPTR_RTSIO | SCSPTR_RTSDT;
/* CTS# and SCK are inputs */
status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO);
serial_port_out(port, SCSPTR, status);
}
}
@@ -1803,6 +1813,46 @@ static unsigned int sci_tx_empty(struct uart_port *port)
return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
}
static void sci_set_rts(struct uart_port *port, bool state)
{
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
u16 data = serial_port_in(port, SCPDR);
/* Active low */
if (state)
data &= ~SCPDR_RTSD;
else
data |= SCPDR_RTSD;
serial_port_out(port, SCPDR, data);
/* RTS# is output */
serial_port_out(port, SCPCR,
serial_port_in(port, SCPCR) | SCPCR_RTSC);
} else if (sci_getreg(port, SCSPTR)->size) {
u16 ctrl = serial_port_in(port, SCSPTR);
/* Active low */
if (state)
ctrl &= ~SCSPTR_RTSDT;
else
ctrl |= SCSPTR_RTSDT;
serial_port_out(port, SCSPTR, ctrl);
}
}
static bool sci_get_cts(struct uart_port *port)
{
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
/* Active low */
return !(serial_port_in(port, SCPDR) & SCPDR_CTSD);
} else if (sci_getreg(port, SCSPTR)->size) {
/* Active low */
return !(serial_port_in(port, SCSPTR) & SCSPTR_CTSDT);
}
return true;
}
/*
* Modem control is a bit of a mixed bag for SCI(F) ports. Generally
* CTS/RTS is supported in hardware by at least one port and controlled
@@ -1817,6 +1867,8 @@ static unsigned int sci_tx_empty(struct uart_port *port)
*/
static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct sci_port *s = to_sci_port(port);
if (mctrl & TIOCM_LOOP) {
const struct plat_sci_reg *reg;
@@ -1829,25 +1881,72 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
serial_port_in(port, SCFCR) |
SCFCR_LOOP);
}
mctrl_gpio_set(s->gpios, mctrl);
if (!(s->cfg->capabilities & SCIx_HAVE_RTSCTS))
return;
if (!(mctrl & TIOCM_RTS)) {
/* Disable Auto RTS */
serial_port_out(port, SCFCR,
serial_port_in(port, SCFCR) & ~SCFCR_MCE);
/* Clear RTS */
sci_set_rts(port, 0);
} else if (s->autorts) {
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
/* Enable RTS# pin function */
serial_port_out(port, SCPCR,
serial_port_in(port, SCPCR) & ~SCPCR_RTSC);
}
/* Enable Auto RTS */
serial_port_out(port, SCFCR,
serial_port_in(port, SCFCR) | SCFCR_MCE);
} else {
/* Set RTS */
sci_set_rts(port, 1);
}
}
static unsigned int sci_get_mctrl(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
struct mctrl_gpios *gpios = s->gpios;
unsigned int mctrl = 0;
mctrl_gpio_get(gpios, &mctrl);
/*
* CTS/RTS is handled in hardware when supported, while nothing
* else is wired up. Keep it simple and simply assert DSR/CAR.
* else is wired up.
*/
return TIOCM_DSR | TIOCM_CAR;
if (s->autorts) {
if (sci_get_cts(port))
mctrl |= TIOCM_CTS;
} else if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_CTS))) {
mctrl |= TIOCM_CTS;
}
if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_DSR)))
mctrl |= TIOCM_DSR;
if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_DCD)))
mctrl |= TIOCM_CAR;
return mctrl;
}
static void sci_enable_ms(struct uart_port *port)
{
mctrl_gpio_enable_ms(to_sci_port(port)->gpios);
}
static void sci_break_ctl(struct uart_port *port, int break_state)
{
struct sci_port *s = to_sci_port(port);
const struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
unsigned short scscr, scsptr;
/* check wheter the port has SCSPTR */
if (!reg->size) {
if (!sci_getreg(port, SCSPTR)->size) {
/*
* Not supported by hardware. Most parts couple break and rx
* interrupts together, with break detection always enabled.
@@ -1873,7 +1972,6 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
static int sci_startup(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
unsigned long flags;
int ret;
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
@@ -1884,11 +1982,6 @@ static int sci_startup(struct uart_port *port)
sci_request_dma(port);
spin_lock_irqsave(&port->lock, flags);
sci_start_tx(port);
sci_start_rx(port);
spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
@@ -1896,12 +1989,19 @@ static void sci_shutdown(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
unsigned long flags;
u16 scr;
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
s->autorts = false;
mctrl_gpio_disable_ms(to_sci_port(port)->gpios);
spin_lock_irqsave(&port->lock, flags);
sci_stop_rx(port);
sci_stop_tx(port);
/* Stop RX and TX, disable related interrupts, keep clock source */
scr = serial_port_in(port, SCSCR);
serial_port_out(port, SCSCR, scr & (SCSCR_CKE1 | SCSCR_CKE0));
spin_unlock_irqrestore(&port->lock, flags);
#ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -2056,6 +2156,15 @@ static void sci_reset(struct uart_port *port)
reg = sci_getreg(port, SCFCR);
if (reg->size)
serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
sci_clear_SCxSR(port,
SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) &
SCxSR_BREAK_CLEAR(port));
if (sci_getreg(port, SCLSR)->size) {
status = serial_port_in(port, SCLSR);
status &= ~(SCLSR_TO | SCLSR_ORER);
serial_port_out(port, SCLSR, status);
}
}
static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
@@ -2218,15 +2327,18 @@ done:
sci_init_pins(port, termios->c_cflag);
port->status &= ~UPSTAT_AUTOCTS;
s->autorts = false;
reg = sci_getreg(port, SCFCR);
if (reg->size) {
unsigned short ctrl = serial_port_in(port, SCFCR);
if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) {
if (termios->c_cflag & CRTSCTS)
ctrl |= SCFCR_MCE;
else
ctrl &= ~SCFCR_MCE;
if ((port->flags & UPF_HARD_FLOW) &&
(termios->c_cflag & CRTSCTS)) {
/* There is no CTS interrupt to restart the hardware */
port->status |= UPSTAT_AUTOCTS;
/* MCE is enabled when RTS is raised */
s->autorts = true;
}
/*
@@ -2300,6 +2412,9 @@ done:
sci_start_rx(port);
sci_port_disable(s);
if (UART_ENABLE_MS(port, termios->c_cflag))
sci_enable_ms(port);
}
static void sci_pm(struct uart_port *port, unsigned int state,
@@ -2425,6 +2540,7 @@ static struct uart_ops sci_uart_ops = {
.start_tx = sci_start_tx,
.stop_tx = sci_stop_tx,
.stop_rx = sci_stop_rx,
.enable_ms = sci_enable_ms,
.break_ctl = sci_break_ctl,
.startup = sci_startup,
.shutdown = sci_shutdown,
@@ -2890,6 +3006,9 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
p->regtype = SCI_OF_REGTYPE(match->data);
p->scscr = SCSCR_RE | SCSCR_TE;
if (of_find_property(np, "uart-has-rtscts", NULL))
p->capabilities |= SCIx_HAVE_RTSCTS;
return p;
}
@@ -2912,6 +3031,21 @@ static int sci_probe_single(struct platform_device *dev,
if (ret)
return ret;
sciport->gpios = mctrl_gpio_init(&sciport->port, 0);
if (IS_ERR(sciport->gpios) && PTR_ERR(sciport->gpios) != -ENOSYS)
return PTR_ERR(sciport->gpios);
if (p->capabilities & SCIx_HAVE_RTSCTS) {
if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios,
UART_GPIO_CTS)) ||
!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios,
UART_GPIO_RTS))) {
dev_err(&dev->dev, "Conflicting RTS/CTS config\n");
return -EINVAL;
}
sciport->port.flags |= UPF_HARD_FLOW;
}
ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
if (ret) {
sci_cleanup_single(sciport);

查看文件

@@ -105,13 +105,16 @@ enum {
#define SCFCR_LOOP BIT(0) /* Loopback Test */
/* SCLSR (Line Status Register) on (H)SCIF */
#define SCLSR_TO BIT(2) /* Timeout */
#define SCLSR_ORER BIT(0) /* Overrun Error */
/* SCSPTR (Serial Port Register), optional */
#define SCSPTR_RTSIO BIT(7) /* Serial Port RTS Pin Input/Output */
#define SCSPTR_RTSDT BIT(6) /* Serial Port RTS Pin Data */
#define SCSPTR_CTSIO BIT(5) /* Serial Port CTS Pin Input/Output */
#define SCSPTR_CTSDT BIT(4) /* Serial Port CTS Pin Data */
#define SCSPTR_RTSIO BIT(7) /* Serial Port RTS# Pin Input/Output */
#define SCSPTR_RTSDT BIT(6) /* Serial Port RTS# Pin Data */
#define SCSPTR_CTSIO BIT(5) /* Serial Port CTS# Pin Input/Output */
#define SCSPTR_CTSDT BIT(4) /* Serial Port CTS# Pin Data */
#define SCSPTR_SCKIO BIT(3) /* Serial Port Clock Pin Input/Output */
#define SCSPTR_SCKDT BIT(2) /* Serial Port Clock Pin Data */
#define SCSPTR_SPB2IO BIT(1) /* Serial Port Break Input/Output */
#define SCSPTR_SPB2DT BIT(0) /* Serial Port Break Data */
@@ -119,12 +122,18 @@ enum {
#define HSCIF_SRE BIT(15) /* Sampling Rate Register Enable */
/* SCPCR (Serial Port Control Register), SCIFA/SCIFB only */
#define SCPCR_RTSC BIT(4) /* Serial Port RTS Pin / Output Pin */
#define SCPCR_CTSC BIT(3) /* Serial Port CTS Pin / Input Pin */
#define SCPCR_RTSC BIT(4) /* Serial Port RTS# Pin / Output Pin */
#define SCPCR_CTSC BIT(3) /* Serial Port CTS# Pin / Input Pin */
#define SCPCR_SCKC BIT(2) /* Serial Port SCK Pin / Output Pin */
#define SCPCR_RXDC BIT(1) /* Serial Port RXD Pin / Input Pin */
#define SCPCR_TXDC BIT(0) /* Serial Port TXD Pin / Output Pin */
/* SCPDR (Serial Port Data Register), SCIFA/SCIFB only */
#define SCPDR_RTSD BIT(4) /* Serial Port RTS Output Pin Data */
#define SCPDR_CTSD BIT(3) /* Serial Port CTS Input Pin Data */
#define SCPDR_RTSD BIT(4) /* Serial Port RTS# Output Pin Data */
#define SCPDR_CTSD BIT(3) /* Serial Port CTS# Input Pin Data */
#define SCPDR_SCKD BIT(2) /* Serial Port SCK Output Pin Data */
#define SCPDR_RXDD BIT(1) /* Serial Port RXD Input Pin Data */
#define SCPDR_TXDD BIT(0) /* Serial Port TXD Output Pin Data */
/*
* BRG Clock Select Register (Some SCIF and HSCIF)

查看文件

@@ -106,7 +106,7 @@ struct sirfsoc_uart_register {
enum sirfsoc_uart_type uart_type;
};
u32 uart_usp_ff_full_mask(struct uart_port *port)
static u32 uart_usp_ff_full_mask(struct uart_port *port)
{
u32 full_bit;
@@ -114,7 +114,7 @@ u32 uart_usp_ff_full_mask(struct uart_port *port)
return (1 << full_bit);
}
u32 uart_usp_ff_empty_mask(struct uart_port *port)
static u32 uart_usp_ff_empty_mask(struct uart_port *port)
{
u32 empty_bit;

查看文件

@@ -21,7 +21,6 @@
#include <linux/hrtimer.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
@@ -730,22 +729,12 @@ static int vt8500_serial_probe(struct platform_device *pdev)
return 0;
}
static int vt8500_serial_remove(struct platform_device *pdev)
{
struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
clk_disable_unprepare(vt8500_port->clk);
uart_remove_one_port(&vt8500_uart_driver, &vt8500_port->uart);
return 0;
}
static struct platform_driver vt8500_platform_driver = {
.probe = vt8500_serial_probe,
.remove = vt8500_serial_remove,
.driver = {
.name = "vt8500_serial",
.of_match_table = wmt_dt_ids,
.suppress_bind_attrs = true,
},
};
@@ -764,19 +753,4 @@ static int __init vt8500_serial_init(void)
return ret;
}
static void __exit vt8500_serial_exit(void)
{
#ifdef CONFIG_SERIAL_VT8500_CONSOLE
unregister_console(&vt8500_console);
#endif
platform_driver_unregister(&vt8500_platform_driver);
uart_unregister_driver(&vt8500_uart_driver);
}
module_init(vt8500_serial_init);
module_exit(vt8500_serial_exit);
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
MODULE_DESCRIPTION("Driver for vt8500 serial device");
MODULE_LICENSE("GPL v2");
device_initcall(vt8500_serial_init);

查看文件

@@ -976,6 +976,23 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c)
}
#endif
static void cdns_uart_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct cdns_uart *cdns_uart = port->private_data;
switch (state) {
case UART_PM_STATE_OFF:
clk_disable(cdns_uart->uartclk);
clk_disable(cdns_uart->pclk);
break;
default:
clk_enable(cdns_uart->pclk);
clk_enable(cdns_uart->uartclk);
break;
}
}
static struct uart_ops cdns_uart_ops = {
.set_mctrl = cdns_uart_set_mctrl,
.get_mctrl = cdns_uart_get_mctrl,
@@ -987,6 +1004,7 @@ static struct uart_ops cdns_uart_ops = {
.set_termios = cdns_uart_set_termios,
.startup = cdns_uart_startup,
.shutdown = cdns_uart_shutdown,
.pm = cdns_uart_pm,
.type = cdns_uart_type,
.verify_port = cdns_uart_verify_port,
.request_port = cdns_uart_request_port,
@@ -1350,12 +1368,12 @@ static int cdns_uart_probe(struct platform_device *pdev)
return PTR_ERR(cdns_uart_data->uartclk);
}
rc = clk_prepare_enable(cdns_uart_data->pclk);
rc = clk_prepare(cdns_uart_data->pclk);
if (rc) {
dev_err(&pdev->dev, "Unable to enable pclk clock.\n");
return rc;
}
rc = clk_prepare_enable(cdns_uart_data->uartclk);
rc = clk_prepare(cdns_uart_data->uartclk);
if (rc) {
dev_err(&pdev->dev, "Unable to enable device clock.\n");
goto err_out_clk_dis_pclk;
@@ -1422,9 +1440,9 @@ err_out_notif_unreg:
&cdns_uart_data->clk_rate_change_nb);
#endif
err_out_clk_disable:
clk_disable_unprepare(cdns_uart_data->uartclk);
clk_unprepare(cdns_uart_data->uartclk);
err_out_clk_dis_pclk:
clk_disable_unprepare(cdns_uart_data->pclk);
clk_unprepare(cdns_uart_data->pclk);
return rc;
}
@@ -1448,8 +1466,8 @@ static int cdns_uart_remove(struct platform_device *pdev)
#endif
rc = uart_remove_one_port(&cdns_uart_uart_driver, port);
port->mapbase = 0;
clk_disable_unprepare(cdns_uart_data->uartclk);
clk_disable_unprepare(cdns_uart_data->pclk);
clk_unprepare(cdns_uart_data->uartclk);
clk_unprepare(cdns_uart_data->pclk);
return rc;
}

查看文件

@@ -499,9 +499,8 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
return 0;
}
/* ui is a leftover from using a hashtable, but might be used again
Caller must hold the lock */
static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
/* Caller must hold the lock */
static int con_do_clear_unimap(struct vc_data *vc)
{
struct uni_pagedir *p, *q;
@@ -524,11 +523,11 @@ static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
return 0;
}
int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
int con_clear_unimap(struct vc_data *vc)
{
int ret;
console_lock();
ret = con_do_clear_unimap(vc, ui);
ret = con_do_clear_unimap(vc);
console_unlock();
return ret;
}
@@ -556,7 +555,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
int j, k;
u16 **p1, *p2, l;
err1 = con_do_clear_unimap(vc, NULL);
err1 = con_do_clear_unimap(vc);
if (err1) {
console_unlock();
return err1;
@@ -677,7 +676,7 @@ int con_set_default_unimap(struct vc_data *vc)
/* The default font is always 256 characters */
err = con_do_clear_unimap(vc, NULL);
err = con_do_clear_unimap(vc);
if (err)
return err;

查看文件

@@ -567,7 +567,7 @@ static void fn_scroll_forw(struct vc_data *vc)
static void fn_scroll_back(struct vc_data *vc)
{
scrollback(vc, 0);
scrollback(vc);
}
static void fn_show_mem(struct vc_data *vc)
@@ -1733,16 +1733,10 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
return -EINVAL;
if (ct) {
buf = kmalloc(ct * sizeof(struct kbdiacruc),
GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
if (copy_from_user(buf, a->kbdiacruc,
ct * sizeof(struct kbdiacruc))) {
kfree(buf);
return -EFAULT;
}
buf = memdup_user(a->kbdiacruc,
ct * sizeof(struct kbdiacruc));
if (IS_ERR(buf))
return PTR_ERR(buf);
}
spin_lock_irqsave(&kbd_event_lock, flags);
if (ct)

查看文件

@@ -277,13 +277,15 @@ static void notify_update(struct vc_data *vc)
* Low-Level Functions
*/
#define IS_FG(vc) ((vc)->vc_num == fg_console)
static inline bool con_is_fg(const struct vc_data *vc)
{
return vc->vc_num == fg_console;
}
#ifdef VT_BUF_VRAM_ONLY
#define DO_UPDATE(vc) 0
#else
#define DO_UPDATE(vc) (CON_IS_VISIBLE(vc) && !console_blanked)
#endif
static inline bool con_should_update(const struct vc_data *vc)
{
return con_is_visible(vc) && !console_blanked;
}
static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
{
@@ -321,7 +323,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
nr = b - t - 1;
if (b > vc->vc_rows || t >= b || nr < 1)
return;
if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
return;
d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
@@ -339,7 +341,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
nr = b - t - 1;
if (b > vc->vc_rows || t >= b || nr < 1)
return;
if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
return;
s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
step = vc->vc_cols * nr;
@@ -349,7 +351,6 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
static void do_update_region(struct vc_data *vc, unsigned long start, int count)
{
#ifndef VT_BUF_VRAM_ONLY
unsigned int xx, yy, offset;
u16 *p;
@@ -390,14 +391,13 @@ static void do_update_region(struct vc_data *vc, unsigned long start, int count)
start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
}
}
#endif
}
void update_region(struct vc_data *vc, unsigned long start, int count)
{
WARN_CONSOLE_UNLOCKED();
if (DO_UPDATE(vc)) {
if (con_should_update(vc)) {
hide_cursor(vc);
do_update_region(vc, start, count);
set_cursor(vc);
@@ -413,7 +413,6 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
return vc->vc_sw->con_build_attr(vc, _color, _intensity,
_blink, _underline, _reverse, _italic);
#ifndef VT_BUF_VRAM_ONLY
/*
* ++roman: I completely changed the attribute format for monochrome
* mode (!can_do_color). The formerly used MDA (monochrome display
@@ -448,9 +447,6 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
a <<= 1;
return a;
}
#else
return 0;
#endif
}
static void update_attr(struct vc_data *vc)
@@ -470,10 +466,9 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
count /= 2;
p = screenpos(vc, offset, viewed);
if (vc->vc_sw->con_invert_region)
if (vc->vc_sw->con_invert_region) {
vc->vc_sw->con_invert_region(vc, p, count);
#ifndef VT_BUF_VRAM_ONLY
else {
} else {
u16 *q = p;
int cnt = count;
u16 a;
@@ -501,8 +496,8 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
}
}
}
#endif
if (DO_UPDATE(vc))
if (con_should_update(vc))
do_update_region(vc, (unsigned long) p, count);
notify_update(vc);
}
@@ -519,7 +514,7 @@ void complement_pos(struct vc_data *vc, int offset)
if (old_offset != -1 && old_offset >= 0 &&
old_offset < vc->vc_screenbuf_size) {
scr_writew(old, screenpos(vc, old_offset, 1));
if (DO_UPDATE(vc))
if (con_should_update(vc))
vc->vc_sw->con_putc(vc, old, oldy, oldx);
notify_update(vc);
}
@@ -534,7 +529,7 @@ void complement_pos(struct vc_data *vc, int offset)
old = scr_readw(p);
new = old ^ vc->vc_complement_mask;
scr_writew(new, p);
if (DO_UPDATE(vc)) {
if (con_should_update(vc)) {
oldx = (offset >> 1) % vc->vc_cols;
oldy = (offset >> 1) / vc->vc_cols;
vc->vc_sw->con_putc(vc, new, oldy, oldx);
@@ -550,7 +545,7 @@ static void insert_char(struct vc_data *vc, unsigned int nr)
scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2);
scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
vc->vc_need_wrap = 0;
if (DO_UPDATE(vc))
if (con_should_update(vc))
do_update_region(vc, (unsigned long) p,
vc->vc_cols - vc->vc_x);
}
@@ -563,7 +558,7 @@ static void delete_char(struct vc_data *vc, unsigned int nr)
scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
nr * 2);
vc->vc_need_wrap = 0;
if (DO_UPDATE(vc))
if (con_should_update(vc))
do_update_region(vc, (unsigned long) p,
vc->vc_cols - vc->vc_x);
}
@@ -583,7 +578,7 @@ static void add_softcursor(struct vc_data *vc)
if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
scr_writew(i, (u16 *) vc->vc_pos);
if (DO_UPDATE(vc))
if (con_should_update(vc))
vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
}
@@ -591,7 +586,7 @@ static void hide_softcursor(struct vc_data *vc)
{
if (softcursor_original != -1) {
scr_writew(softcursor_original, (u16 *)vc->vc_pos);
if (DO_UPDATE(vc))
if (con_should_update(vc))
vc->vc_sw->con_putc(vc, softcursor_original,
vc->vc_y, vc->vc_x);
softcursor_original = -1;
@@ -608,8 +603,7 @@ static void hide_cursor(struct vc_data *vc)
static void set_cursor(struct vc_data *vc)
{
if (!IS_FG(vc) || console_blanked ||
vc->vc_mode == KD_GRAPHICS)
if (!con_is_fg(vc) || console_blanked || vc->vc_mode == KD_GRAPHICS)
return;
if (vc->vc_deccm) {
if (vc == sel_cons)
@@ -625,7 +619,7 @@ static void set_origin(struct vc_data *vc)
{
WARN_CONSOLE_UNLOCKED();
if (!CON_IS_VISIBLE(vc) ||
if (!con_is_visible(vc) ||
!vc->vc_sw->con_set_origin ||
!vc->vc_sw->con_set_origin(vc))
vc->vc_origin = (unsigned long)vc->vc_screenbuf;
@@ -673,12 +667,12 @@ void redraw_screen(struct vc_data *vc, int is_switch)
struct vc_data *old_vc = vc_cons[fg_console].d;
if (old_vc == vc)
return;
if (!CON_IS_VISIBLE(vc))
if (!con_is_visible(vc))
redraw = 1;
*vc->vc_display_fg = vc;
fg_console = vc->vc_num;
hide_cursor(old_vc);
if (!CON_IS_VISIBLE(old_vc)) {
if (!con_is_visible(old_vc)) {
save_screen(old_vc);
set_origin(old_vc);
}
@@ -954,7 +948,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
tty_do_resize(tty, &ws);
}
if (CON_IS_VISIBLE(vc))
if (con_is_visible(vc))
update_screen(vc);
vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
return err;
@@ -1103,11 +1097,9 @@ static void gotoxay(struct vc_data *vc, int new_x, int new_y)
gotoxy(vc, new_x, vc->vc_decom ? (vc->vc_top + new_y) : new_y);
}
void scrollback(struct vc_data *vc, int lines)
void scrollback(struct vc_data *vc)
{
if (!lines)
lines = vc->vc_rows / 2;
scrolldelta(-lines);
scrolldelta(-(vc->vc_rows / 2));
}
void scrollfront(struct vc_data *vc, int lines)
@@ -1186,7 +1178,7 @@ static void csi_J(struct vc_data *vc, int vpar)
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size >> 1);
set_origin(vc);
if (CON_IS_VISIBLE(vc))
if (con_is_visible(vc))
update_screen(vc);
/* fall through */
case 2: /* erase whole display */
@@ -1197,7 +1189,7 @@ static void csi_J(struct vc_data *vc, int vpar)
return;
}
scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
if (DO_UPDATE(vc))
if (con_should_update(vc))
do_update_region(vc, (unsigned long) start, count);
vc->vc_need_wrap = 0;
}
@@ -1225,7 +1217,7 @@ static void csi_K(struct vc_data *vc, int vpar)
}
scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
vc->vc_need_wrap = 0;
if (DO_UPDATE(vc))
if (con_should_update(vc))
do_update_region(vc, (unsigned long) start, count);
}
@@ -1238,7 +1230,7 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi
count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;
scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
if (DO_UPDATE(vc))
if (con_should_update(vc))
vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);
vc->vc_need_wrap = 0;
}
@@ -1255,48 +1247,87 @@ static void default_attr(struct vc_data *vc)
struct rgb { u8 r; u8 g; u8 b; };
static struct rgb rgb_from_256(int i)
static void rgb_from_256(int i, struct rgb *c)
{
struct rgb c;
if (i < 8) { /* Standard colours. */
c.r = i&1 ? 0xaa : 0x00;
c.g = i&2 ? 0xaa : 0x00;
c.b = i&4 ? 0xaa : 0x00;
c->r = i&1 ? 0xaa : 0x00;
c->g = i&2 ? 0xaa : 0x00;
c->b = i&4 ? 0xaa : 0x00;
} else if (i < 16) {
c.r = i&1 ? 0xff : 0x55;
c.g = i&2 ? 0xff : 0x55;
c.b = i&4 ? 0xff : 0x55;
c->r = i&1 ? 0xff : 0x55;
c->g = i&2 ? 0xff : 0x55;
c->b = i&4 ? 0xff : 0x55;
} else if (i < 232) { /* 6x6x6 colour cube. */
c.r = (i - 16) / 36 * 85 / 2;
c.g = (i - 16) / 6 % 6 * 85 / 2;
c.b = (i - 16) % 6 * 85 / 2;
c->r = (i - 16) / 36 * 85 / 2;
c->g = (i - 16) / 6 % 6 * 85 / 2;
c->b = (i - 16) % 6 * 85 / 2;
} else /* Grayscale ramp. */
c.r = c.g = c.b = i * 10 - 2312;
return c;
c->r = c->g = c->b = i * 10 - 2312;
}
static void rgb_foreground(struct vc_data *vc, struct rgb c)
static void rgb_foreground(struct vc_data *vc, const struct rgb *c)
{
u8 hue, max = c.r;
if (c.g > max)
max = c.g;
if (c.b > max)
max = c.b;
hue = (c.r > max/2 ? 4 : 0)
| (c.g > max/2 ? 2 : 0)
| (c.b > max/2 ? 1 : 0);
if (hue == 7 && max <= 0x55)
hue = 0, vc->vc_intensity = 2;
u8 hue = 0, max = max3(c->r, c->g, c->b);
if (c->r > max / 2)
hue |= 4;
if (c->g > max / 2)
hue |= 2;
if (c->b > max / 2)
hue |= 1;
if (hue == 7 && max <= 0x55) {
hue = 0;
vc->vc_intensity = 2;
} else if (max > 0xaa)
vc->vc_intensity = 2;
else
vc->vc_intensity = (max > 0xaa) + 1;
vc->vc_intensity = 1;
vc->vc_color = (vc->vc_color & 0xf0) | hue;
}
static void rgb_background(struct vc_data *vc, struct rgb c)
static void rgb_background(struct vc_data *vc, const struct rgb *c)
{
/* For backgrounds, err on the dark side. */
vc->vc_color = (vc->vc_color & 0x0f)
| (c.r&0x80) >> 1 | (c.g&0x80) >> 2 | (c.b&0x80) >> 3;
| (c->r&0x80) >> 1 | (c->g&0x80) >> 2 | (c->b&0x80) >> 3;
}
/*
* ITU T.416 Higher colour modes. They break the usual properties of SGR codes
* and thus need to be detected and ignored by hand. Strictly speaking, that
* standard also wants : rather than ; as separators, contrary to ECMA-48, but
* no one produces such codes and almost no one accepts them.
*
* Subcommands 3 (CMY) and 4 (CMYK) are so insane there's no point in
* supporting them.
*/
static int vc_t416_color(struct vc_data *vc, int i,
void(*set_color)(struct vc_data *vc, const struct rgb *c))
{
struct rgb c;
i++;
if (i > vc->vc_npar)
return i;
if (vc->vc_par[i] == 5 && i < vc->vc_npar) {
/* 256 colours -- ubiquitous */
i++;
rgb_from_256(vc->vc_par[i], &c);
} else if (vc->vc_par[i] == 2 && i <= vc->vc_npar + 3) {
/* 24 bit -- extremely rare */
c.r = vc->vc_par[i + 1];
c.g = vc->vc_par[i + 2];
c.b = vc->vc_par[i + 3];
i += 3;
} else
return i;
set_color(vc, &c);
return i;
}
/* console_lock is held */
@@ -1306,135 +1337,91 @@ static void csi_m(struct vc_data *vc)
for (i = 0; i <= vc->vc_npar; i++)
switch (vc->vc_par[i]) {
case 0: /* all attributes off */
default_attr(vc);
break;
case 1:
vc->vc_intensity = 2;
break;
case 2:
vc->vc_intensity = 0;
break;
case 3:
vc->vc_italic = 1;
break;
case 4:
vc->vc_underline = 1;
break;
case 5:
vc->vc_blink = 1;
break;
case 7:
vc->vc_reverse = 1;
break;
case 10: /* ANSI X3.64-1979 (SCO-ish?)
* Select primary font, don't display
* control chars if defined, don't set
* bit 8 on output.
*/
vc->vc_translate = set_translate(vc->vc_charset == 0
? vc->vc_G0_charset
: vc->vc_G1_charset, vc);
vc->vc_disp_ctrl = 0;
vc->vc_toggle_meta = 0;
break;
case 11: /* ANSI X3.64-1979 (SCO-ish?)
* Select first alternate font, lets
* chars < 32 be displayed as ROM chars.
*/
vc->vc_translate = set_translate(IBMPC_MAP, vc);
vc->vc_disp_ctrl = 1;
vc->vc_toggle_meta = 0;
break;
case 12: /* ANSI X3.64-1979 (SCO-ish?)
* Select second alternate font, toggle
* high bit before displaying as ROM char.
*/
vc->vc_translate = set_translate(IBMPC_MAP, vc);
vc->vc_disp_ctrl = 1;
vc->vc_toggle_meta = 1;
break;
case 21:
case 22:
vc->vc_intensity = 1;
break;
case 23:
vc->vc_italic = 0;
break;
case 24:
vc->vc_underline = 0;
break;
case 25:
vc->vc_blink = 0;
break;
case 27:
vc->vc_reverse = 0;
break;
case 38: /* ITU T.416
* Higher colour modes.
* They break the usual properties of SGR codes
* and thus need to be detected and ignored by
* hand. Strictly speaking, that standard also
* wants : rather than ; as separators, contrary
* to ECMA-48, but no one produces such codes
* and almost no one accepts them.
*/
i++;
if (i > vc->vc_npar)
break;
if (vc->vc_par[i] == 5 && /* 256 colours */
i < vc->vc_npar) { /* ubiquitous */
i++;
rgb_foreground(vc,
rgb_from_256(vc->vc_par[i]));
} else if (vc->vc_par[i] == 2 && /* 24 bit */
i <= vc->vc_npar + 3) {/* extremely rare */
struct rgb c = {
.r = vc->vc_par[i + 1],
.g = vc->vc_par[i + 2],
.b = vc->vc_par[i + 3],
};
rgb_foreground(vc, c);
i += 3;
}
/* Subcommands 3 (CMY) and 4 (CMYK) are so insane
* there's no point in supporting them.
*/
break;
case 48:
i++;
if (i > vc->vc_npar)
break;
if (vc->vc_par[i] == 5 && /* 256 colours */
i < vc->vc_npar) {
i++;
rgb_background(vc,
rgb_from_256(vc->vc_par[i]));
} else if (vc->vc_par[i] == 2 && /* 24 bit */
i <= vc->vc_npar + 3) {
struct rgb c = {
.r = vc->vc_par[i + 1],
.g = vc->vc_par[i + 2],
.b = vc->vc_par[i + 3],
};
rgb_background(vc, c);
i += 3;
}
break;
case 39:
vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
break;
case 49:
vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
break;
default:
if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
vc->vc_color = color_table[vc->vc_par[i] - 30]
| (vc->vc_color & 0xf0);
else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
| (vc->vc_color & 0x0f);
break;
case 0: /* all attributes off */
default_attr(vc);
break;
case 1:
vc->vc_intensity = 2;
break;
case 2:
vc->vc_intensity = 0;
break;
case 3:
vc->vc_italic = 1;
break;
case 4:
vc->vc_underline = 1;
break;
case 5:
vc->vc_blink = 1;
break;
case 7:
vc->vc_reverse = 1;
break;
case 10: /* ANSI X3.64-1979 (SCO-ish?)
* Select primary font, don't display control chars if
* defined, don't set bit 8 on output.
*/
vc->vc_translate = set_translate(vc->vc_charset == 0
? vc->vc_G0_charset
: vc->vc_G1_charset, vc);
vc->vc_disp_ctrl = 0;
vc->vc_toggle_meta = 0;
break;
case 11: /* ANSI X3.64-1979 (SCO-ish?)
* Select first alternate font, lets chars < 32 be
* displayed as ROM chars.
*/
vc->vc_translate = set_translate(IBMPC_MAP, vc);
vc->vc_disp_ctrl = 1;
vc->vc_toggle_meta = 0;
break;
case 12: /* ANSI X3.64-1979 (SCO-ish?)
* Select second alternate font, toggle high bit
* before displaying as ROM char.
*/
vc->vc_translate = set_translate(IBMPC_MAP, vc);
vc->vc_disp_ctrl = 1;
vc->vc_toggle_meta = 1;
break;
case 21:
case 22:
vc->vc_intensity = 1;
break;
case 23:
vc->vc_italic = 0;
break;
case 24:
vc->vc_underline = 0;
break;
case 25:
vc->vc_blink = 0;
break;
case 27:
vc->vc_reverse = 0;
break;
case 38:
i = vc_t416_color(vc, i, rgb_foreground);
break;
case 48:
i = vc_t416_color(vc, i, rgb_background);
break;
case 39:
vc->vc_color = (vc->vc_def_color & 0x0f) |
(vc->vc_color & 0xf0);
break;
case 49:
vc->vc_color = (vc->vc_def_color & 0xf0) |
(vc->vc_color & 0x0f);
break;
default:
if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
vc->vc_color = color_table[vc->vc_par[i] - 30]
| (vc->vc_color & 0xf0);
else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
| (vc->vc_color & 0x0f);
break;
}
update_attr(vc);
}
@@ -1496,7 +1483,6 @@ static void set_mode(struct vc_data *vc, int on_off)
clr_kbd(vc, decckm);
break;
case 3: /* 80/132 mode switch unimplemented */
vc->vc_deccolm = on_off;
#if 0
vc_resize(deccolm ? 132 : 80, vc->vc_rows);
/* this alone does not suffice; some user mode
@@ -2178,18 +2164,20 @@ static int is_double_width(uint32_t ucs)
return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1);
}
static void con_flush(struct vc_data *vc, unsigned long draw_from,
unsigned long draw_to, int *draw_x)
{
if (*draw_x < 0)
return;
vc->vc_sw->con_putcs(vc, (u16 *)draw_from,
(u16 *)draw_to - (u16 *)draw_from, vc->vc_y, *draw_x);
*draw_x = -1;
}
/* acquires console_lock */
static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
#ifdef VT_BUF_VRAM_ONLY
#define FLUSH do { } while(0);
#else
#define FLUSH if (draw_x >= 0) { \
vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, draw_x); \
draw_x = -1; \
}
#endif
int c, tc, ok, n = 0, draw_x = -1;
unsigned int currcons;
unsigned long draw_from = 0, draw_to = 0;
@@ -2226,7 +2214,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
charmask = himask ? 0x1ff : 0xff;
/* undraw cursor first */
if (IS_FG(vc))
if (con_is_fg(vc))
hide_cursor(vc);
param.vc = vc;
@@ -2381,12 +2369,13 @@ rescan_last_byte:
} else {
vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
}
FLUSH
con_flush(vc, draw_from, draw_to, &draw_x);
}
while (1) {
if (vc->vc_need_wrap || vc->vc_decim)
FLUSH
con_flush(vc, draw_from, draw_to,
&draw_x);
if (vc->vc_need_wrap) {
cr(vc);
lf(vc);
@@ -2397,7 +2386,7 @@ rescan_last_byte:
((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
(vc_attr << 8) + tc,
(u16 *) vc->vc_pos);
if (DO_UPDATE(vc) && draw_x < 0) {
if (con_should_update(vc) && draw_x < 0) {
draw_x = vc->vc_x;
draw_from = vc->vc_pos;
}
@@ -2416,9 +2405,8 @@ rescan_last_byte:
}
notify_write(vc, c);
if (inverse) {
FLUSH
}
if (inverse)
con_flush(vc, draw_from, draw_to, &draw_x);
if (rescan) {
rescan = 0;
@@ -2429,15 +2417,14 @@ rescan_last_byte:
}
continue;
}
FLUSH
con_flush(vc, draw_from, draw_to, &draw_x);
do_con_trol(tty, vc, orig);
}
FLUSH
con_flush(vc, draw_from, draw_to, &draw_x);
console_conditional_schedule();
console_unlock();
notify_update(vc);
return n;
#undef FLUSH
}
/*
@@ -2471,7 +2458,7 @@ static void console_callback(struct work_struct *ignored)
if (scrollback_delta) {
struct vc_data *vc = vc_cons[fg_console].d;
clear_selection();
if (vc->vc_mode == KD_TEXT)
if (vc->vc_mode == KD_TEXT && vc->vc_sw->con_scrolldelta)
vc->vc_sw->con_scrolldelta(vc, scrollback_delta);
scrollback_delta = 0;
}
@@ -2583,7 +2570,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
goto quit;
/* undraw cursor first */
if (IS_FG(vc))
if (con_is_fg(vc))
hide_cursor(vc);
start = (ushort *)vc->vc_pos;
@@ -2594,7 +2581,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
c = *b++;
if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
if (cnt > 0) {
if (CON_IS_VISIBLE(vc))
if (con_is_visible(vc))
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
vc->vc_x += cnt;
if (vc->vc_need_wrap)
@@ -2626,7 +2613,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
myx++;
}
if (cnt > 0) {
if (CON_IS_VISIBLE(vc))
if (con_is_visible(vc))
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
vc->vc_x += cnt;
if (vc->vc_x == vc->vc_cols) {
@@ -3173,7 +3160,7 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last,
j = i;
if (CON_IS_VISIBLE(vc)) {
if (con_is_visible(vc)) {
k = i;
save_screen(vc);
}
@@ -3981,7 +3968,7 @@ static void set_palette(struct vc_data *vc)
{
WARN_CONSOLE_UNLOCKED();
if (vc->vc_mode != KD_GRAPHICS)
if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_set_palette)
vc->vc_sw->con_set_palette(vc, color_table);
}

查看文件

@@ -1006,16 +1006,10 @@ int vt_ioctl(struct tty_struct *tty,
break;
case PIO_UNIMAPCLR:
{ struct unimapinit ui;
if (!perm)
return -EPERM;
ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
if (ret)
ret = -EFAULT;
else
con_clear_unimap(vc, &ui);
con_clear_unimap(vc);
break;
}
case PIO_UNIMAP:
case GIO_UNIMAP: