TTY/Serial driver update for 4.8-rc1

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.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iFYEABECABYFAleVPbQPHGdyZWdAa3JvYWguY29tAAoJEDFH1A3bLfspWXgAn046
 QCMeFya4J1zjYjcGXJzNfGMUAKCHxha8Xe65cc0LDz8mNB0MgzjHEg==
 =ED8v
 -----END PGP SIGNATURE-----

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
commit 721413aff2
68 changed files with 1393 additions and 1139 deletions

View file

@ -42,6 +42,9 @@ Optional properties:
- auto-flow-control: one way to enable automatic flow control support. The
driver is allowed to detect support for the capability even without this
property.
- {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD
line respectively. It will use specified GPIO instead of the peripheral
function pin for the UART feature. If unsure, don't specify this property.
Note:
* fsl,ns16550:
@ -63,3 +66,19 @@ Example:
interrupts = <10>;
reg-shift = <2>;
};
Example for OMAP UART using GPIO-based modem control signals:
uart4: serial@49042000 {
compatible = "ti,omap3-uart";
reg = <0x49042000 0x400>;
interrupts = <80>;
ti,hwmods = "uart4";
clock-frequency = <48000000>;
cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>;
rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};

View file

@ -31,6 +31,8 @@ Required properties:
- "renesas,hscif-r8a7794" for R8A7794 (R-Car E2) HSCIF compatible UART.
- "renesas,scif-r8a7795" for R8A7795 (R-Car H3) SCIF compatible UART.
- "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
- "renesas,scif-r8a7796" for R8A7796 (R-Car M3-W) SCIF compatible UART.
- "renesas,hscif-r8a7796" for R8A7796 (R-Car M3-W) HSCIF compatible UART.
- "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART.
- "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART.
- "renesas,rcar-gen1-scif" for R-Car Gen1 SCIF compatible UART,
@ -76,6 +78,10 @@ Optional properties:
- dmas: Must contain a list of two references to DMA specifiers, one for
transmission, and one for reception.
- dma-names: Must contain a list of two DMA names, "tx" and "rx".
- {cts,dsr,dcd,rng,rts,dtr}-gpios: Specify GPIOs for modem lines, cfr. the
generic serial DT bindings in serial.txt.
- uart-has-rtscts: Indicates dedicated lines for RTS/CTS hardware flow
control, cfr. the generic serial DT bindings in serial.txt.
Example:
aliases {

View file

@ -10003,6 +10003,7 @@ SERIAL DRIVERS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-serial@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/serial/
F: drivers/tty/serial/
SYNOPSYS DESIGNWARE DMAC DRIVER

View file

@ -12,7 +12,3 @@
* the base baud is derived from the clock speed and so is variable
*/
#define BASE_BAUD 0
#define STD_COM_FLAGS UPF_BOOT_AUTOCONF
#define SERIAL_PORT_DFNS

View file

@ -113,7 +113,6 @@ void platform_heartbeat(void)
}
//#define RS_TABLE_SIZE 2
//#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF|UPF_SKIP_TEST)
#define _SERIAL_PORT(_base,_irq) \
{ \

View file

@ -126,28 +126,33 @@ static void hsu_dma_start_transfer(struct hsu_dma_chan *hsuc)
hsu_dma_start_channel(hsuc);
}
static u32 hsu_dma_chan_get_sr(struct hsu_dma_chan *hsuc)
{
unsigned long flags;
u32 sr;
spin_lock_irqsave(&hsuc->vchan.lock, flags);
sr = hsu_chan_readl(hsuc, HSU_CH_SR);
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
return sr & ~(HSU_CH_SR_DESCE_ANY | HSU_CH_SR_CDESC_ANY);
}
irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
/*
* hsu_dma_get_status() - get DMA channel status
* @chip: HSUART DMA chip
* @nr: DMA channel number
* @status: pointer for DMA Channel Status Register value
*
* Description:
* The function reads and clears the DMA Channel Status Register, checks
* if it was a timeout interrupt and returns a corresponding value.
*
* Caller should provide a valid pointer for the DMA Channel Status
* Register value that will be returned in @status.
*
* Return:
* 1 for DMA timeout status, 0 for other DMA status, or error code for
* invalid parameters or no interrupt pending.
*/
int hsu_dma_get_status(struct hsu_dma_chip *chip, unsigned short nr,
u32 *status)
{
struct hsu_dma_chan *hsuc;
struct hsu_dma_desc *desc;
unsigned long flags;
u32 sr;
/* Sanity check */
if (nr >= chip->hsu->nr_channels)
return IRQ_NONE;
return -EINVAL;
hsuc = &chip->hsu->chan[nr];
@ -155,22 +160,65 @@ irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
* No matter what situation, need read clear the IRQ status
* There is a bug, see Errata 5, HSD 2900918
*/
sr = hsu_dma_chan_get_sr(hsuc);
spin_lock_irqsave(&hsuc->vchan.lock, flags);
sr = hsu_chan_readl(hsuc, HSU_CH_SR);
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
/* Check if any interrupt is pending */
sr &= ~(HSU_CH_SR_DESCE_ANY | HSU_CH_SR_CDESC_ANY);
if (!sr)
return IRQ_NONE;
return -EIO;
/* Timeout IRQ, need wait some time, see Errata 2 */
if (sr & HSU_CH_SR_DESCTO_ANY)
udelay(2);
/*
* At this point, at least one of Descriptor Time Out, Channel Error
* or Descriptor Done bits must be set. Clear the Descriptor Time Out
* bits and if sr is still non-zero, it must be channel error or
* descriptor done which are higher priority than timeout and handled
* in hsu_dma_do_irq(). Else, it must be a timeout.
*/
sr &= ~HSU_CH_SR_DESCTO_ANY;
if (!sr)
return IRQ_HANDLED;
*status = sr;
return sr ? 0 : 1;
}
EXPORT_SYMBOL_GPL(hsu_dma_get_status);
/*
* hsu_dma_do_irq() - DMA interrupt handler
* @chip: HSUART DMA chip
* @nr: DMA channel number
* @status: Channel Status Register value
*
* Description:
* This function handles Channel Error and Descriptor Done interrupts.
* This function should be called after determining that the DMA interrupt
* is not a normal timeout interrupt, ie. hsu_dma_get_status() returned 0.
*
* Return:
* IRQ_NONE for invalid channel number, IRQ_HANDLED otherwise.
*/
irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr,
u32 status)
{
struct hsu_dma_chan *hsuc;
struct hsu_dma_desc *desc;
unsigned long flags;
/* Sanity check */
if (nr >= chip->hsu->nr_channels)
return IRQ_NONE;
hsuc = &chip->hsu->chan[nr];
spin_lock_irqsave(&hsuc->vchan.lock, flags);
desc = hsuc->desc;
if (desc) {
if (sr & HSU_CH_SR_CHE) {
if (status & HSU_CH_SR_CHE) {
desc->status = DMA_ERROR;
} else if (desc->active < desc->nents) {
hsu_dma_start_channel(hsuc);
@ -184,7 +232,7 @@ irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
return IRQ_HANDLED;
}
EXPORT_SYMBOL_GPL(hsu_dma_irq);
EXPORT_SYMBOL_GPL(hsu_dma_do_irq);
static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents)
{

View file

@ -27,13 +27,20 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev)
{
struct hsu_dma_chip *chip = dev;
u32 dmaisr;
u32 status;
unsigned short i;
irqreturn_t ret = IRQ_NONE;
int err;
dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
for (i = 0; i < chip->hsu->nr_channels; i++) {
if (dmaisr & 0x1)
ret |= hsu_dma_irq(chip, i);
if (dmaisr & 0x1) {
err = hsu_dma_get_status(chip, i, &status);
if (err > 0)
ret |= IRQ_HANDLED;
else if (err == 0)
ret |= hsu_dma_do_irq(chip, i, status);
}
dmaisr >>= 1;
}

View file

@ -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)) {

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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. */

View file

@ -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)
{

View file

@ -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

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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;

View file

@ -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)
{

View file

@ -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;

View file

@ -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 },

View file

@ -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);
}
/*

View file

@ -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)
{

View file

@ -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

View file

@ -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.

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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");

View file

@ -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);

View file

@ -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 */

View file

@ -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 */

View file

@ -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,

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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) {

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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);

View file

@ -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)

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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)

View file

@ -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);
}

View file

@ -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:

View file

@ -1285,18 +1285,22 @@ int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
}
int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
u32 dest, int length, size_t *bytes_written)
u32 dest, int length)
{
size_t dummy;
return sisusb_write_mem_bulk(sisusb, dest, src, length,
NULL, 0, bytes_written);
NULL, 0, &dummy);
}
#ifdef SISUSBENDIANTEST
int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
u32 src, int length, size_t *bytes_written)
static int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
u32 src, int length)
{
size_t dummy;
return sisusb_read_mem_bulk(sisusb, src, dest, length,
NULL, bytes_written);
NULL, &dummy);
}
#endif
#endif
@ -1306,16 +1310,14 @@ static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
{
static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
char destbuffer[10];
size_t dummy;
int i, j;
sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7);
for (i = 1; i <= 7; i++) {
dev_dbg(&sisusb->sisusb_dev->dev,
"sisusb: rwtest %d bytes\n", i);
sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase,
i, &dummy);
sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i);
for (j = 0; j < i; j++) {
dev_dbg(&sisusb->sisusb_dev->dev,
"rwtest read[%d] = %x\n",
@ -2276,7 +2278,6 @@ int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
const struct font_desc *myfont;
u8 *tempbuf;
u16 *tempbufb;
size_t written;
static const char bootstring[] =
"SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
static const char bootlogo[] = "(o_ //\\ V_/_";
@ -2343,18 +2344,15 @@ int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
*(tempbufb++) = 0x0700 | bootstring[i++];
ret |= sisusb_copy_memory(sisusb, tempbuf,
sisusb->vrambase, 8192, &written);
sisusb->vrambase, 8192);
vfree(tempbuf);
}
} else if (sisusb->scrbuf) {
ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
sisusb->vrambase, sisusb->scrbuf_size,
&written);
sisusb->vrambase, sisusb->scrbuf_size);
}
if (sisusb->sisusb_cursor_size_from >= 0 &&

View file

@ -370,7 +370,6 @@ static void
sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
{
struct sisusb_usb_data *sisusb;
ssize_t written;
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
if (!sisusb)
@ -384,7 +383,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
(long)SISUSB_HADDR(x, y), 2, &written);
(long)SISUSB_HADDR(x, y), 2);
mutex_unlock(&sisusb->lock);
}
@ -395,7 +394,6 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
int count, int y, int x)
{
struct sisusb_usb_data *sisusb;
ssize_t written;
u16 *dest;
int i;
@ -420,7 +418,7 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
}
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
(long)SISUSB_HADDR(x, y), count * 2, &written);
(long)SISUSB_HADDR(x, y), count * 2);
mutex_unlock(&sisusb->lock);
}
@ -431,7 +429,6 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
{
struct sisusb_usb_data *sisusb;
u16 eattr = c->vc_video_erase_char;
ssize_t written;
int i, length, cols;
u16 *dest;
@ -475,41 +472,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
(long)SISUSB_HADDR(x, y), length, &written);
mutex_unlock(&sisusb->lock);
}
/* Interface routine */
static void
sisusbcon_bmove(struct vc_data *c, int sy, int sx,
int dy, int dx, int height, int width)
{
struct sisusb_usb_data *sisusb;
ssize_t written;
int cols, length;
if (width <= 0 || height <= 0)
return;
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
if (!sisusb)
return;
/* sisusb->lock is down */
cols = sisusb->sisusb_num_columns;
if (sisusb_is_inactive(c, sisusb)) {
mutex_unlock(&sisusb->lock);
return;
}
length = ((height * cols) - dx - (cols - width - dx)) * 2;
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
(long)SISUSB_HADDR(dx, dy), length, &written);
(long)SISUSB_HADDR(x, y), length);
mutex_unlock(&sisusb->lock);
}
@ -519,7 +482,6 @@ static int
sisusbcon_switch(struct vc_data *c)
{
struct sisusb_usb_data *sisusb;
ssize_t written;
int length;
/* Returnvalue 0 means we have fully restored screen,
@ -559,7 +521,7 @@ sisusbcon_switch(struct vc_data *c)
sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
(long)SISUSB_HADDR(0, 0),
length, &written);
length);
mutex_unlock(&sisusb->lock);
@ -600,7 +562,7 @@ sisusbcon_save_screen(struct vc_data *c)
}
/* interface routine */
static int
static void
sisusbcon_set_palette(struct vc_data *c, const unsigned char *table)
{
struct sisusb_usb_data *sisusb;
@ -608,18 +570,18 @@ sisusbcon_set_palette(struct vc_data *c, const unsigned char *table)
/* Return value not used by vt */
if (!CON_IS_VISIBLE(c))
return -EINVAL;
if (!con_is_visible(c))
return;
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
if (!sisusb)
return -EINVAL;
return;
/* sisusb->lock is down */
if (sisusb_is_inactive(c, sisusb)) {
mutex_unlock(&sisusb->lock);
return -EINVAL;
return;
}
for (i = j = 0; i < 16; i++) {
@ -634,8 +596,6 @@ sisusbcon_set_palette(struct vc_data *c, const unsigned char *table)
}
mutex_unlock(&sisusb->lock);
return 0;
}
/* interface routine */
@ -644,7 +604,6 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
{
struct sisusb_usb_data *sisusb;
u8 sr1, cr17, pmreg, cr63;
ssize_t written;
int ret = 0;
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
@ -672,7 +631,7 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
(unsigned char *)c->vc_origin,
(u32)(sisusb->vrambase +
(c->vc_origin - sisusb->scrbuf)),
c->vc_screenbuf_size, &written);
c->vc_screenbuf_size);
sisusb->con_blanked = 1;
ret = 1;
break;
@ -723,24 +682,22 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
}
/* interface routine */
static int
static void
sisusbcon_scrolldelta(struct vc_data *c, int lines)
{
struct sisusb_usb_data *sisusb;
int margin = c->vc_size_row * 4;
int ul, we, p, st;
/* The return value does not seem to be used */
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
if (!sisusb)
return 0;
return;
/* sisusb->lock is down */
if (sisusb_is_inactive(c, sisusb)) {
mutex_unlock(&sisusb->lock);
return 0;
return;
}
if (!lines) /* Turn scrollback off */
@ -780,8 +737,6 @@ sisusbcon_scrolldelta(struct vc_data *c, int lines)
sisusbcon_set_start_address(sisusb, c);
mutex_unlock(&sisusb->lock);
return 1;
}
/* Interface routine */
@ -860,7 +815,6 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
int cols = sisusb->sisusb_num_columns;
int length = ((b - t) * cols) * 2;
u16 eattr = c->vc_video_erase_char;
ssize_t written;
/* sisusb->lock is down */
@ -890,7 +844,7 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
}
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
(long)SISUSB_HADDR(0, t), length, &written);
(long)SISUSB_HADDR(0, t), length);
mutex_unlock(&sisusb->lock);
@ -903,7 +857,6 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
{
struct sisusb_usb_data *sisusb;
u16 eattr = c->vc_video_erase_char;
ssize_t written;
int copyall = 0;
unsigned long oldorigin;
unsigned int delta = lines * c->vc_size_row;
@ -996,18 +949,18 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
sisusb_copy_memory(sisusb,
(char *)c->vc_origin,
(u32)(sisusb->vrambase + originoffset),
c->vc_screenbuf_size, &written);
c->vc_screenbuf_size);
else if (dir == SM_UP)
sisusb_copy_memory(sisusb,
(char *)c->vc_origin + c->vc_screenbuf_size - delta,
(u32)sisusb->vrambase + originoffset +
c->vc_screenbuf_size - delta,
delta, &written);
delta);
else
sisusb_copy_memory(sisusb,
(char *)c->vc_origin,
(u32)(sisusb->vrambase + originoffset),
delta, &written);
delta);
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
c->vc_visible_origin = c->vc_origin;
@ -1273,7 +1226,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
struct vc_data *vc = vc_cons[i].d;
if (vc && vc->vc_sw == &sisusb_con) {
if (CON_IS_VISIBLE(vc)) {
if (con_is_visible(vc)) {
vc->vc_sw->con_cursor(vc, CM_DRAW);
}
vc->vc_font.height = fh;
@ -1385,7 +1338,6 @@ static const struct consw sisusb_con = {
.con_putcs = sisusbcon_putcs,
.con_cursor = sisusbcon_cursor,
.con_scroll = sisusbcon_scroll,
.con_bmove = sisusbcon_bmove,
.con_switch = sisusbcon_switch,
.con_blank = sisusbcon_blank,
.con_font_set = sisusbcon_font_set,
@ -1433,15 +1385,12 @@ static const struct consw sisusb_dummy_con = {
.con_putcs = SISUSBCONDUMMY,
.con_cursor = SISUSBCONDUMMY,
.con_scroll = SISUSBCONDUMMY,
.con_bmove = SISUSBCONDUMMY,
.con_switch = SISUSBCONDUMMY,
.con_blank = SISUSBCONDUMMY,
.con_font_set = SISUSBCONDUMMY,
.con_font_get = SISUSBCONDUMMY,
.con_font_default = SISUSBCONDUMMY,
.con_font_copy = SISUSBCONDUMMY,
.con_set_palette = SISUSBCONDUMMY,
.con_scrolldelta = SISUSBCONDUMMY,
};
int

View file

@ -828,7 +828,7 @@ void sisusb_delete(struct kref *kref);
int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 * data);
int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
u32 dest, int length, size_t * bytes_written);
u32 dest, int length);
int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
u8 * arg, int cmapsz, int ch512, int dorecalc,

View file

@ -64,14 +64,11 @@ const struct consw dummy_con = {
.con_putcs = DUMMY,
.con_cursor = DUMMY,
.con_scroll = DUMMY,
.con_bmove = DUMMY,
.con_switch = DUMMY,
.con_blank = DUMMY,
.con_font_set = DUMMY,
.con_font_get = DUMMY,
.con_font_default = DUMMY,
.con_font_copy = DUMMY,
.con_set_palette = DUMMY,
.con_scrolldelta = DUMMY,
};
EXPORT_SYMBOL_GPL(dummy_con);

View file

@ -170,8 +170,7 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
int height, int width);
static int fbcon_switch(struct vc_data *vc);
static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch);
static int fbcon_set_palette(struct vc_data *vc, const unsigned char *table);
static int fbcon_scrolldelta(struct vc_data *vc, int lines);
static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table);
/*
* Internal routines
@ -381,7 +380,7 @@ static void fb_flashcursor(struct work_struct *work)
if (ops && ops->currcon != -1)
vc = vc_cons[ops->currcon].d;
if (!vc || !CON_IS_VISIBLE(vc) ||
if (!vc || !con_is_visible(vc) ||
registered_fb[con2fb_map[vc->vc_num]] != info ||
vc->vc_deccm != 1) {
console_unlock();
@ -619,7 +618,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
erase,
vc->vc_size_row * logo_lines);
if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) {
fbcon_clear_margins(vc, 0);
update_screen(vc);
}
@ -1113,7 +1112,7 @@ static void fbcon_init(struct vc_data *vc, int init)
*
* We need to do it in fbcon_init() to prevent screen corruption.
*/
if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) {
if (info->fbops->fb_set_par &&
!(ops->flags & FBCON_FLAGS_INIT)) {
ret = info->fbops->fb_set_par(info);
@ -1193,7 +1192,7 @@ static void fbcon_deinit(struct vc_data *vc)
if (!ops)
goto finished;
if (CON_IS_VISIBLE(vc))
if (con_is_visible(vc))
fbcon_del_cursor_timer(info);
ops->flags &= ~FBCON_FLAGS_INIT;
@ -1398,7 +1397,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
rows /= vc->vc_font.height;
vc_resize(vc, cols, rows);
if (CON_IS_VISIBLE(vc)) {
if (con_is_visible(vc)) {
update_screen(vc);
if (softback_buf)
fbcon_update_softback(vc);
@ -2146,7 +2145,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
return -EINVAL;
DPRINTK("resize now %ix%i\n", var.xres, var.yres);
if (CON_IS_VISIBLE(vc)) {
if (con_is_visible(vc)) {
var.activate = FB_ACTIVATE_NOW |
FB_ACTIVATE_FORCE;
fb_set_var(info, &var);
@ -2449,7 +2448,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
int cnt;
char *old_data = NULL;
if (CON_IS_VISIBLE(vc) && softback_lines)
if (con_is_visible(vc) && softback_lines)
fbcon_set_origin(vc);
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
@ -2530,9 +2529,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
cols /= w;
rows /= h;
vc_resize(vc, cols, rows);
if (CON_IS_VISIBLE(vc) && softback_buf)
if (con_is_visible(vc) && softback_buf)
fbcon_update_softback(vc);
} else if (CON_IS_VISIBLE(vc)
} else if (con_is_visible(vc)
&& vc->vc_mode == KD_TEXT) {
fbcon_clear_margins(vc, 0);
update_screen(vc);
@ -2652,17 +2651,17 @@ static struct fb_cmap palette_cmap = {
0, 16, palette_red, palette_green, palette_blue, NULL
};
static int fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
int i, j, k, depth;
u8 val;
if (fbcon_is_inactive(vc, info))
return -EINVAL;
return;
if (!CON_IS_VISIBLE(vc))
return 0;
if (!con_is_visible(vc))
return;
depth = fb_get_color_depth(&info->var, &info->fix);
if (depth > 3) {
@ -2684,7 +2683,7 @@ static int fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
} else
fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
return fb_set_cmap(&palette_cmap, info);
fb_set_cmap(&palette_cmap, info);
}
static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
@ -2765,7 +2764,7 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
}
}
static int fbcon_scrolldelta(struct vc_data *vc, int lines)
static void fbcon_scrolldelta(struct vc_data *vc, int lines)
{
struct fb_info *info = registered_fb[con2fb_map[fg_console]];
struct fbcon_ops *ops = info->fbcon_par;
@ -2774,9 +2773,9 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
if (softback_top) {
if (vc->vc_num != fg_console)
return 0;
return;
if (vc->vc_mode != KD_TEXT || !lines)
return 0;
return;
if (logo_shown >= 0) {
struct vc_data *conp2 = vc_cons[logo_shown].d;
@ -2809,11 +2808,11 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
fbcon_redraw_softback(vc, disp, lines);
fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
return 0;
return;
}
if (!scrollback_phys_max)
return -ENOSYS;
return;
scrollback_old = scrollback_current;
scrollback_current -= lines;
@ -2822,10 +2821,10 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
else if (scrollback_current > scrollback_max)
scrollback_current = scrollback_max;
if (scrollback_current == scrollback_old)
return 0;
return;
if (fbcon_is_inactive(vc, info))
return 0;
return;
fbcon_cursor(vc, CM_ERASE);
@ -2852,7 +2851,6 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
if (!scrollback_current)
fbcon_cursor(vc, CM_DRAW);
return 0;
}
static int fbcon_set_origin(struct vc_data *vc)
@ -2904,7 +2902,7 @@ static void fbcon_modechanged(struct fb_info *info)
p = &fb_display[vc->vc_num];
set_blitting_type(vc, info);
if (CON_IS_VISIBLE(vc)) {
if (con_is_visible(vc)) {
var_to_display(p, &info->var, info);
cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
@ -2943,7 +2941,7 @@ static void fbcon_set_all_vcs(struct fb_info *info)
registered_fb[con2fb_map[i]] != info)
continue;
if (CON_IS_VISIBLE(vc)) {
if (con_is_visible(vc)) {
fg = i;
continue;
}
@ -3182,7 +3180,7 @@ static void fbcon_fb_blanked(struct fb_info *info, int blank)
registered_fb[con2fb_map[ops->currcon]] != info)
return;
if (CON_IS_VISIBLE(vc)) {
if (con_is_visible(vc)) {
if (blank)
do_blank_screen(0);
else
@ -3336,7 +3334,6 @@ static const struct consw fb_con = {
.con_putcs = fbcon_putcs,
.con_cursor = fbcon_cursor,
.con_scroll = fbcon_scroll,
.con_bmove = fbcon_bmove,
.con_switch = fbcon_switch,
.con_blank = fbcon_blank,
.con_font_set = fbcon_set_font,

View file

@ -444,48 +444,11 @@ static void mdacon_clear(struct vc_data *c, int y, int x,
}
}
static void mdacon_bmove(struct vc_data *c, int sy, int sx,
int dy, int dx, int height, int width)
{
u16 *src, *dest;
if (width <= 0 || height <= 0)
return;
if (sx==0 && dx==0 && width==mda_num_columns) {
scr_memmovew(MDA_ADDR(0,dy), MDA_ADDR(0,sy), height*width*2);
} else if (dy < sy || (dy == sy && dx < sx)) {
src = MDA_ADDR(sx, sy);
dest = MDA_ADDR(dx, dy);
for (; height > 0; height--) {
scr_memmovew(dest, src, width*2);
src += mda_num_columns;
dest += mda_num_columns;
}
} else {
src = MDA_ADDR(sx, sy+height-1);
dest = MDA_ADDR(dx, dy+height-1);
for (; height > 0; height--) {
scr_memmovew(dest, src, width*2);
src -= mda_num_columns;
dest -= mda_num_columns;
}
}
}
static int mdacon_switch(struct vc_data *c)
{
return 1; /* redrawing needed */
}
static int mdacon_set_palette(struct vc_data *c, const unsigned char *table)
{
return -EINVAL;
}
static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
{
if (mda_type == TYPE_MDA) {
@ -505,11 +468,6 @@ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
}
}
static int mdacon_scrolldelta(struct vc_data *c, int lines)
{
return 0;
}
static void mdacon_cursor(struct vc_data *c, int mode)
{
if (mode == CM_ERASE) {
@ -574,11 +532,8 @@ static const struct consw mda_con = {
.con_putcs = mdacon_putcs,
.con_cursor = mdacon_cursor,
.con_scroll = mdacon_scroll,
.con_bmove = mdacon_bmove,
.con_switch = mdacon_switch,
.con_blank = mdacon_blank,
.con_set_palette = mdacon_set_palette,
.con_scrolldelta = mdacon_scrolldelta,
.con_build_attr = mdacon_build_attr,
.con_invert_region = mdacon_invert_region,
};

View file

@ -574,17 +574,6 @@ static int newport_font_set(struct vc_data *vc, struct console_font *font, unsig
return newport_set_font(vc->vc_num, font);
}
static int newport_set_palette(struct vc_data *vc, const unsigned char *table)
{
return -EINVAL;
}
static int newport_scrolldelta(struct vc_data *vc, int lines)
{
/* there is (nearly) no off-screen memory, so we can't scroll back */
return 0;
}
static int newport_scroll(struct vc_data *vc, int t, int b, int dir,
int lines)
{
@ -684,34 +673,6 @@ static int newport_scroll(struct vc_data *vc, int t, int b, int dir,
return 1;
}
static void newport_bmove(struct vc_data *vc, int sy, int sx, int dy,
int dx, int h, int w)
{
short xs, ys, xe, ye, xoffs, yoffs;
xs = sx << 3;
xe = ((sx + w) << 3) - 1;
/*
* as bmove is only used to move stuff around in the same line
* (h == 1), we don't care about wrap arounds caused by topscan != 0
*/
ys = ((sy << 4) + topscan) & 0x3ff;
ye = (((sy + h) << 4) - 1 + topscan) & 0x3ff;
xoffs = (dx - sx) << 3;
yoffs = (dy - sy) << 4;
if (xoffs > 0) {
/* move to the right, exchange starting points */
swap(xe, xs);
}
newport_wait(npregs);
npregs->set.drawmode0 = (NPORT_DMODE0_S2S | NPORT_DMODE0_BLOCK |
NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX
| NPORT_DMODE0_STOPY);
npregs->set.xystarti = (xs << 16) | ys;
npregs->set.xyendi = (xe << 16) | ye;
npregs->go.xymove = (xoffs << 16) | yoffs;
}
static int newport_dummy(struct vc_data *c)
{
return 0;
@ -729,13 +690,10 @@ const struct consw newport_con = {
.con_putcs = newport_putcs,
.con_cursor = newport_cursor,
.con_scroll = newport_scroll,
.con_bmove = newport_bmove,
.con_switch = newport_switch,
.con_blank = newport_blank,
.con_font_set = newport_font_set,
.con_font_default = newport_font_default,
.con_set_palette = newport_set_palette,
.con_scrolldelta = newport_scrolldelta,
.con_set_origin = DUMMY,
.con_save_screen = DUMMY
};

View file

@ -79,11 +79,6 @@ static const char *sticon_startup(void)
return "STI console";
}
static int sticon_set_palette(struct vc_data *c, const unsigned char *table)
{
return -EINVAL;
}
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
{
int redraw_cursor = 0;
@ -182,22 +177,6 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
return 0;
}
static void sticon_bmove(struct vc_data *conp, int sy, int sx,
int dy, int dx, int height, int width)
{
if (!width || !height)
return;
#if 0
if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
(sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
(dx <= p->cursor_x) && (p->cursor_x < dx+width)))
sticon_cursor(p, CM_ERASE /*|CM_SOFTBACK*/);
#endif
sti_bmove(sticon_sti, sy, sx, dy, dx, height, width);
}
static void sticon_init(struct vc_data *c, int init)
{
struct sti_struct *sti = sticon_sti;
@ -256,11 +235,6 @@ static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
return 1;
}
static int sticon_scrolldelta(struct vc_data *conp, int lines)
{
return 0;
}
static u16 *sticon_screen_pos(struct vc_data *conp, int offset)
{
int line;
@ -355,11 +329,8 @@ static const struct consw sti_con = {
.con_putcs = sticon_putcs,
.con_cursor = sticon_cursor,
.con_scroll = sticon_scroll,
.con_bmove = sticon_bmove,
.con_switch = sticon_switch,
.con_blank = sticon_blank,
.con_set_palette = sticon_set_palette,
.con_scrolldelta = sticon_scrolldelta,
.con_set_origin = sticon_set_origin,
.con_save_screen = sticon_save_screen,
.con_build_attr = sticon_build_attr,

View file

@ -80,7 +80,7 @@ static void vgacon_deinit(struct vc_data *c);
static void vgacon_cursor(struct vc_data *c, int mode);
static int vgacon_switch(struct vc_data *c);
static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
static int vgacon_scrolldelta(struct vc_data *c, int lines);
static void vgacon_scrolldelta(struct vc_data *c, int lines);
static int vgacon_set_origin(struct vc_data *c);
static void vgacon_save_screen(struct vc_data *c);
static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
@ -248,18 +248,18 @@ static void vgacon_restore_screen(struct vc_data *c)
}
}
static int vgacon_scrolldelta(struct vc_data *c, int lines)
static void vgacon_scrolldelta(struct vc_data *c, int lines)
{
int start, end, count, soff;
if (!lines) {
c->vc_visible_origin = c->vc_origin;
vga_set_mem_top(c);
return 1;
return;
}
if (!vgacon_scrollback)
return 1;
return;
if (!vgacon_scrollback_save) {
vgacon_cursor(c, CM_ERASE);
@ -320,8 +320,6 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
scr_memcpyw(d, s, diff * c->vc_size_row);
} else
vgacon_cursor(c, CM_MOVE);
return 1;
}
#else
#define vgacon_scrollback_startup(...) do { } while (0)
@ -334,7 +332,7 @@ static void vgacon_restore_screen(struct vc_data *c)
vgacon_scrolldelta(c, 0);
}
static int vgacon_scrolldelta(struct vc_data *c, int lines)
static void vgacon_scrolldelta(struct vc_data *c, int lines)
{
if (!lines) /* Turn scrollback off */
c->vc_visible_origin = c->vc_origin;
@ -362,7 +360,6 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
c->vc_visible_origin = vga_vram_base + (p + ul) % we;
}
vga_set_mem_top(c);
return 1;
}
#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
@ -592,7 +589,7 @@ static void vgacon_init(struct vc_data *c, int init)
static void vgacon_deinit(struct vc_data *c)
{
/* When closing the active console, reset video origin */
if (CON_IS_VISIBLE(c)) {
if (con_is_visible(c)) {
c->vc_visible_origin = vga_vram_base;
vga_set_mem_top(c);
}
@ -859,16 +856,13 @@ static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
}
}
static int vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
{
#ifdef CAN_LOAD_PALETTE
if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
|| !CON_IS_VISIBLE(vc))
return -EINVAL;
|| !con_is_visible(vc))
return;
vga_set_palette(vc, table);
return 0;
#else
return -EINVAL;
#endif
}
@ -1254,7 +1248,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
struct vc_data *c = vc_cons[i].d;
if (c && c->vc_sw == &vga_con) {
if (CON_IS_VISIBLE(c)) {
if (con_is_visible(c)) {
/* void size to cause regs to be rewritten */
cursor_size_lastfrom = 0;
cursor_size_lastto = 0;
@ -1318,7 +1312,7 @@ static int vgacon_resize(struct vc_data *c, unsigned int width,
return success */
return (user) ? 0 : -EINVAL;
if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
if (con_is_visible(c) && !vga_is_gfx) /* who knows */
vgacon_doresize(c, width, height);
return 0;
}
@ -1427,7 +1421,6 @@ const struct consw vga_con = {
.con_putcs = DUMMY,
.con_cursor = vgacon_cursor,
.con_scroll = vgacon_scroll,
.con_bmove = DUMMY,
.con_switch = vgacon_switch,
.con_blank = vgacon_blank,
.con_font_set = vgacon_font_set,

View file

@ -28,6 +28,13 @@ struct tty_struct;
#define VT100ID "\033[?1;2c"
#define VT102ID "\033[?6c"
/**
* struct consw - callbacks for consoles
*
* @con_set_palette: sets the palette of the console to @table (optional)
* @con_scrolldelta: the contents of the console should be scrolled by @lines.
* Invoked by user. (optional)
*/
struct consw {
struct module *owner;
const char *(*con_startup)(void);
@ -38,7 +45,6 @@ struct consw {
void (*con_putcs)(struct vc_data *, const unsigned short *, int, int, int);
void (*con_cursor)(struct vc_data *, int);
int (*con_scroll)(struct vc_data *, int, int, int, int);
void (*con_bmove)(struct vc_data *, int, int, int, int, int, int);
int (*con_switch)(struct vc_data *);
int (*con_blank)(struct vc_data *, int, int);
int (*con_font_set)(struct vc_data *, struct console_font *, unsigned);
@ -47,8 +53,9 @@ struct consw {
int (*con_font_copy)(struct vc_data *, int);
int (*con_resize)(struct vc_data *, unsigned int, unsigned int,
unsigned int);
int (*con_set_palette)(struct vc_data *, const unsigned char *);
int (*con_scrolldelta)(struct vc_data *, int);
void (*con_set_palette)(struct vc_data *,
const unsigned char *table);
void (*con_scrolldelta)(struct vc_data *, int lines);
int (*con_set_origin)(struct vc_data *);
void (*con_save_screen)(struct vc_data *);
u8 (*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8, u8);

View file

@ -21,6 +21,38 @@ struct uni_pagedir;
#define NPAR 16
/*
* Example: vc_data of a console that was scrolled 3 lines down.
*
* Console buffer
* vc_screenbuf ---------> +----------------------+-.
* | initializing W | \
* | initializing X | |
* | initializing Y | > scroll-back area
* | initializing Z | |
* | | /
* vc_visible_origin ---> ^+----------------------+-:
* (changes by scroll) || Welcome to linux | \
* || | |
* vc_rows --->< | login: root | | visible on console
* || password: | > (vc_screenbuf_size is
* vc_origin -----------> || | | vc_size_row * vc_rows)
* (start when no scroll) || Last login: 12:28 | /
* v+----------------------+-:
* | Have a lot of fun... | \
* vc_pos -----------------|--------v | > scroll-front area
* | ~ # cat_ | /
* vc_scr_end -----------> +----------------------+-:
* (vc_origin + | | \ EMPTY, to be filled by
* vc_screenbuf_size) | | / vc_video_erase_char
* +----------------------+-'
* <---- 2 * vc_cols ----->
* <---- vc_size_row ----->
*
* Note that every character in the console buffer is accompanied with an
* attribute in the buffer right after the character. This is not depicted
* in the figure.
*/
struct vc_data {
struct tty_port port; /* Upper level data */
@ -74,7 +106,6 @@ struct vc_data {
unsigned int vc_decawm : 1; /* Autowrap Mode */
unsigned int vc_deccm : 1; /* Cursor Visible */
unsigned int vc_decim : 1; /* Insert Mode */
unsigned int vc_deccolm : 1; /* 80/132 Column Mode */
/* attribute flags */
unsigned int vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */
unsigned int vc_italic:1;
@ -136,6 +167,9 @@ extern void vc_SAK(struct work_struct *work);
#define CUR_DEFAULT CUR_UNDERLINE
#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
static inline bool con_is_visible(const struct vc_data *vc)
{
return *vc->vc_display_fg == vc;
}
#endif /* _LINUX_CONSOLE_STRUCT_H */

View file

@ -39,14 +39,22 @@ struct hsu_dma_chip {
#if IS_ENABLED(CONFIG_HSU_DMA)
/* Export to the internal users */
irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr);
int hsu_dma_get_status(struct hsu_dma_chip *chip, unsigned short nr,
u32 *status);
irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr,
u32 status);
/* Export to the platform drivers */
int hsu_dma_probe(struct hsu_dma_chip *chip);
int hsu_dma_remove(struct hsu_dma_chip *chip);
#else
static inline irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip,
unsigned short nr)
static inline int hsu_dma_get_status(struct hsu_dma_chip *chip,
unsigned short nr, u32 *status)
{
return 0;
}
static inline irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip,
unsigned short nr, u32 status)
{
return IRQ_NONE;
}

View file

@ -111,6 +111,7 @@ struct uart_8250_port {
* if no_console_suspend
*/
unsigned char probe;
struct mctrl_gpios *gpios;
#define UART_PROBE_RSA (1 << 0)
/*

View file

@ -352,9 +352,15 @@ struct earlycon_id {
extern const struct earlycon_id __earlycon_table[];
extern const struct earlycon_id __earlycon_table_end[];
#if defined(CONFIG_SERIAL_EARLYCON) && !defined(MODULE)
#define EARLYCON_USED_OR_UNUSED __used
#else
#define EARLYCON_USED_OR_UNUSED __maybe_unused
#endif
#define OF_EARLYCON_DECLARE(_name, compat, fn) \
static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \
__used __section(__earlycon_table) \
EARLYCON_USED_OR_UNUSED __section(__earlycon_table) \
= { .name = __stringify(_name), \
.compatible = compat, \
.setup = fn }

View file

@ -45,7 +45,7 @@ void poke_blanked_console(void);
int con_font_op(struct vc_data *vc, struct console_font_op *op);
int con_set_cmap(unsigned char __user *cmap);
int con_get_cmap(unsigned char __user *cmap);
void scrollback(struct vc_data *vc, int lines);
void scrollback(struct vc_data *vc);
void scrollfront(struct vc_data *vc, int lines);
void clear_buffer_attributes(struct vc_data *vc);
void update_region(struct vc_data *vc, unsigned long start, int count);
@ -59,14 +59,13 @@ int tioclinux(struct tty_struct *tty, unsigned long arg);
#ifdef CONFIG_CONSOLE_TRANSLATIONS
/* consolemap.c */
struct unimapinit;
struct unipair;
int con_set_trans_old(unsigned char __user * table);
int con_get_trans_old(unsigned char __user * table);
int con_set_trans_new(unsigned short __user * table);
int con_get_trans_new(unsigned short __user * table);
int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui);
int con_clear_unimap(struct vc_data *vc);
int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list);
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list);
int con_set_default_unimap(struct vc_data *vc);
@ -92,7 +91,7 @@ static inline int con_get_trans_new(unsigned short __user *table)
{
return -EINVAL;
}
static inline int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
static inline int con_clear_unimap(struct vc_data *vc)
{
return 0;
}

View file

@ -246,9 +246,6 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
{
struct serial_struct info;
if (!retinfo)
return -EFAULT;
memset(&info, 0, sizeof(info));
info.line = self->line;
info.flags = self->port.flags;
@ -258,11 +255,6 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
/* For compatibility */
info.type = PORT_16550A;
info.port = 0;
info.irq = 0;
info.xmit_fifo_size = 0;
info.hub6 = 0;
info.custom_divisor = 0;
if (copy_to_user(retinfo, &info, sizeof(*retinfo)))
return -EFAULT;