提交 c2078402 编写于 作者: L Linus Torvalds

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

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

  Not many major things, a number of driver updates and changes, and the
  8250 driver got split up a bit to make it easier to work with by
  moving some functions to a new file.  Full details are in the
  shortlog.

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

* tag 'tty-4.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (90 commits)
  serial: imx: save and restore context in the suspend path
  serial: imx: allow waking up on RTSD
  serial: imx: introduce serial_imx_enable_wakeup()
  serial: imx: remove unbalanced clk_prepare
  serial: 8250: move rx_running out of the bitfield
  tty: serial: 8250_omap: do not use RX DMA if pause is not supported
  serial:8250_dw: do not alter CTS and DCTS since AFE is enabled
  tty: serial: men_z135_uart.c: Don't initialize port->lock
  tty: serial: men_z135_uart.c: Fix race between IRQ and set_termios()
  serial: 8250: bind to ALi Fast Infrared Controller (ALI5123)
  serial: 8250: don't bind to SMSC IrCC IR port
  serial: mxs-auart: fix baud rate range
  serial: mxs-auart: keep the AUART unit in reset state when not in use
  serial: mxs-auart: use a function name to reflect what it really does
  serial: 8250_pci: fix mode after S3/S4 resume for F81504/508/512
  sc16is7xx: constify devtype
  sc16is7xx: support multiple devices
  sc16is7xx: save and use per-chip line number
  uart: pl011: Add support to ZTE ZX296702 uart
  uart: pl011: Improve LCRH register access decision
  ...
...@@ -22,6 +22,8 @@ Optional properties: ...@@ -22,6 +22,8 @@ Optional properties:
memory peripheral interface and USART DMA channel ID, FIFO configuration. memory peripheral interface and USART DMA channel ID, FIFO configuration.
Refer to dma.txt and atmel-dma.txt for details. Refer to dma.txt and atmel-dma.txt for details.
- dma-names: "rx" for RX channel, "tx" for TX channel. - dma-names: "rx" for RX channel, "tx" for TX channel.
- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
capable USARTs.
<chip> compatible description: <chip> compatible description:
- at91rm9200: legacy USART support - at91rm9200: legacy USART support
...@@ -57,4 +59,5 @@ Example: ...@@ -57,4 +59,5 @@ Example:
dmas = <&dma0 2 0x3>, dmas = <&dma0 2 0x3>,
<&dma0 2 0x204>; <&dma0 2 0x204>;
dma-names = "tx", "rx"; dma-names = "tx", "rx";
atmel,fifo-size = <32>;
}; };
...@@ -6,7 +6,7 @@ Required properties: ...@@ -6,7 +6,7 @@ Required properties:
- interrupts: device interrupt - interrupts: device interrupt
Optional properties: Optional properties:
- {dtr,dsr,ri,cd}-gpios: specify a GPIO for DTR/DSR/RI/CD - {dtr,dsr,rng,dcd}-gpios: specify a GPIO for DTR/DSR/RI/DCD
line respectively. line respectively.
Example: Example:
...@@ -16,4 +16,8 @@ serial@b00260000 { ...@@ -16,4 +16,8 @@ serial@b00260000 {
reg = <0xb0026000 0x1000>; reg = <0xb0026000 0x1000>;
interrupts = <68>; interrupts = <68>;
status = "disabled"; status = "disabled";
dtr-gpios = <&sysgpio 0 GPIO_ACTIVE_LOW>;
dsr-gpios = <&sysgpio 1 GPIO_ACTIVE_LOW>;
rng-gpios = <&sysgpio 2 GPIO_ACTIVE_LOW>;
dcd-gpios = <&sysgpio 3 GPIO_ACTIVE_LOW>;
}; };
...@@ -4,6 +4,9 @@ Required properties: ...@@ -4,6 +4,9 @@ Required properties:
- compatible : should be "ti,omap2-uart" for OMAP2 controllers - compatible : should be "ti,omap2-uart" for OMAP2 controllers
- compatible : should be "ti,omap3-uart" for OMAP3 controllers - compatible : should be "ti,omap3-uart" for OMAP3 controllers
- compatible : should be "ti,omap4-uart" for OMAP4 controllers - compatible : should be "ti,omap4-uart" for OMAP4 controllers
- compatible : should be "ti,am4372-uart" for AM437x controllers
- compatible : should be "ti,am3352-uart" for AM335x controllers
- compatible : should be "ti,dra742-uart" for DRA7x controllers
- reg : address and length of the register space - reg : address and length of the register space
- interrupts or interrupts-extended : Should contain the uart interrupt - interrupts or interrupts-extended : Should contain the uart interrupt
specifier or both the interrupt specifier or both the interrupt
......
...@@ -210,7 +210,7 @@ ...@@ -210,7 +210,7 @@
}; };
uart0: serial@44e09000 { uart0: serial@44e09000 {
compatible = "ti,omap3-uart"; compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart1"; ti,hwmods = "uart1";
clock-frequency = <48000000>; clock-frequency = <48000000>;
reg = <0x44e09000 0x2000>; reg = <0x44e09000 0x2000>;
...@@ -221,7 +221,7 @@ ...@@ -221,7 +221,7 @@
}; };
uart1: serial@48022000 { uart1: serial@48022000 {
compatible = "ti,omap3-uart"; compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart2"; ti,hwmods = "uart2";
clock-frequency = <48000000>; clock-frequency = <48000000>;
reg = <0x48022000 0x2000>; reg = <0x48022000 0x2000>;
...@@ -232,7 +232,7 @@ ...@@ -232,7 +232,7 @@
}; };
uart2: serial@48024000 { uart2: serial@48024000 {
compatible = "ti,omap3-uart"; compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart3"; ti,hwmods = "uart3";
clock-frequency = <48000000>; clock-frequency = <48000000>;
reg = <0x48024000 0x2000>; reg = <0x48024000 0x2000>;
...@@ -243,7 +243,7 @@ ...@@ -243,7 +243,7 @@
}; };
uart3: serial@481a6000 { uart3: serial@481a6000 {
compatible = "ti,omap3-uart"; compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart4"; ti,hwmods = "uart4";
clock-frequency = <48000000>; clock-frequency = <48000000>;
reg = <0x481a6000 0x2000>; reg = <0x481a6000 0x2000>;
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
}; };
uart4: serial@481a8000 { uart4: serial@481a8000 {
compatible = "ti,omap3-uart"; compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart5"; ti,hwmods = "uart5";
clock-frequency = <48000000>; clock-frequency = <48000000>;
reg = <0x481a8000 0x2000>; reg = <0x481a8000 0x2000>;
...@@ -261,7 +261,7 @@ ...@@ -261,7 +261,7 @@
}; };
uart5: serial@481aa000 { uart5: serial@481aa000 {
compatible = "ti,omap3-uart"; compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart6"; ti,hwmods = "uart6";
clock-frequency = <48000000>; clock-frequency = <48000000>;
reg = <0x481aa000 0x2000>; reg = <0x481aa000 0x2000>;
......
...@@ -397,7 +397,7 @@ ...@@ -397,7 +397,7 @@
}; };
uart1: serial@4806a000 { uart1: serial@4806a000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806a000 0x100>; reg = <0x4806a000 0x100>;
interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart1"; ti,hwmods = "uart1";
...@@ -408,7 +408,7 @@ ...@@ -408,7 +408,7 @@
}; };
uart2: serial@4806c000 { uart2: serial@4806c000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806c000 0x100>; reg = <0x4806c000 0x100>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart2"; ti,hwmods = "uart2";
...@@ -419,7 +419,7 @@ ...@@ -419,7 +419,7 @@
}; };
uart3: serial@48020000 { uart3: serial@48020000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48020000 0x100>; reg = <0x48020000 0x100>;
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart3"; ti,hwmods = "uart3";
...@@ -430,7 +430,7 @@ ...@@ -430,7 +430,7 @@
}; };
uart4: serial@4806e000 { uart4: serial@4806e000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806e000 0x100>; reg = <0x4806e000 0x100>;
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart4"; ti,hwmods = "uart4";
...@@ -441,7 +441,7 @@ ...@@ -441,7 +441,7 @@
}; };
uart5: serial@48066000 { uart5: serial@48066000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48066000 0x100>; reg = <0x48066000 0x100>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart5"; ti,hwmods = "uart5";
...@@ -452,7 +452,7 @@ ...@@ -452,7 +452,7 @@
}; };
uart6: serial@48068000 { uart6: serial@48068000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48068000 0x100>; reg = <0x48068000 0x100>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart6"; ti,hwmods = "uart6";
...@@ -463,7 +463,7 @@ ...@@ -463,7 +463,7 @@
}; };
uart7: serial@48420000 { uart7: serial@48420000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48420000 0x100>; reg = <0x48420000 0x100>;
interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart7"; ti,hwmods = "uart7";
...@@ -472,7 +472,7 @@ ...@@ -472,7 +472,7 @@
}; };
uart8: serial@48422000 { uart8: serial@48422000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48422000 0x100>; reg = <0x48422000 0x100>;
interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart8"; ti,hwmods = "uart8";
...@@ -481,7 +481,7 @@ ...@@ -481,7 +481,7 @@
}; };
uart9: serial@48424000 { uart9: serial@48424000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48424000 0x100>; reg = <0x48424000 0x100>;
interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart9"; ti,hwmods = "uart9";
...@@ -490,7 +490,7 @@ ...@@ -490,7 +490,7 @@
}; };
uart10: serial@4ae2b000 { uart10: serial@4ae2b000 {
compatible = "ti,omap4-uart"; compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4ae2b000 0x100>; reg = <0x4ae2b000 0x100>;
interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart10"; ti,hwmods = "uart10";
......
...@@ -153,6 +153,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { ...@@ -153,6 +153,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
{"AEI0250"}, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */ {"AEI0250"}, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
{"AEI1240"}, /* Actiontec ISA PNP 56K X2 Fax Modem */ {"AEI1240"}, /* Actiontec ISA PNP 56K X2 Fax Modem */
{"AKY1021"}, /* Rockwell 56K ACF II Fax+Data+Voice Modem */ {"AKY1021"}, /* Rockwell 56K ACF II Fax+Data+Voice Modem */
{"ALI5123"}, /* ALi Fast Infrared Controller */
{"AZT4001"}, /* AZT3005 PnP SOUND DEVICE */ {"AZT4001"}, /* AZT3005 PnP SOUND DEVICE */
{"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */ {"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */
{"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */ {"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */
......
...@@ -2712,7 +2712,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci, ...@@ -2712,7 +2712,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
memcpy(skb_put(skb, size), in_buf, size); memcpy(skb_put(skb, size), in_buf, size);
skb->dev = net; skb->dev = net;
skb->protocol = __constant_htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
/* Ship it off to the kernel */ /* Ship it off to the kernel */
netif_rx(skb); netif_rx(skb);
......
...@@ -2147,6 +2147,8 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *, ...@@ -2147,6 +2147,8 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
static int job_control(struct tty_struct *tty, struct file *file) static int job_control(struct tty_struct *tty, struct file *file)
{ {
struct pid *pgrp;
/* Job control check -- must be done at start and after /* Job control check -- must be done at start and after
every sleep (POSIX.1 7.1.1.4). */ every sleep (POSIX.1 7.1.1.4). */
/* NOTE: not yet done after every sleep pending a thorough /* NOTE: not yet done after every sleep pending a thorough
...@@ -2156,18 +2158,25 @@ static int job_control(struct tty_struct *tty, struct file *file) ...@@ -2156,18 +2158,25 @@ static int job_control(struct tty_struct *tty, struct file *file)
current->signal->tty != tty) current->signal->tty != tty)
return 0; return 0;
rcu_read_lock();
pgrp = task_pgrp(current);
spin_lock_irq(&tty->ctrl_lock); spin_lock_irq(&tty->ctrl_lock);
if (!tty->pgrp) if (!tty->pgrp)
printk(KERN_ERR "n_tty_read: no tty->pgrp!\n"); printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
else if (task_pgrp(current) != tty->pgrp) { else if (pgrp != tty->pgrp) {
spin_unlock_irq(&tty->ctrl_lock); spin_unlock_irq(&tty->ctrl_lock);
if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
rcu_read_unlock();
return -EIO; return -EIO;
kill_pgrp(task_pgrp(current), SIGTTIN, 1); }
kill_pgrp(pgrp, SIGTTIN, 1);
rcu_read_unlock();
set_thread_flag(TIF_SIGPENDING); set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
spin_unlock_irq(&tty->ctrl_lock); spin_unlock_irq(&tty->ctrl_lock);
rcu_read_unlock();
return 0; return 0;
} }
......
...@@ -26,6 +26,12 @@ ...@@ -26,6 +26,12 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/poll.h> #include <linux/poll.h>
#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
# define tty_debug_hangup(tty, f, args...) tty_debug(tty, f, ##args)
#else
# define tty_debug_hangup(tty, f, args...) do {} while (0)
#endif
#ifdef CONFIG_UNIX98_PTYS #ifdef CONFIG_UNIX98_PTYS
static struct tty_driver *ptm_driver; static struct tty_driver *ptm_driver;
...@@ -779,6 +785,8 @@ static int ptmx_open(struct inode *inode, struct file *filp) ...@@ -779,6 +785,8 @@ static int ptmx_open(struct inode *inode, struct file *filp)
if (retval) if (retval)
goto err_release; goto err_release;
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
tty_unlock(tty); tty_unlock(tty);
return 0; return 0;
err_release: err_release:
......
...@@ -42,9 +42,9 @@ struct uart_8250_dma { ...@@ -42,9 +42,9 @@ struct uart_8250_dma {
size_t rx_size; size_t rx_size;
size_t tx_size; size_t tx_size;
unsigned char tx_running:1; unsigned char tx_running;
unsigned char tx_err: 1; unsigned char tx_err;
unsigned char rx_running:1; unsigned char rx_running;
}; };
struct old_serial_port { struct old_serial_port {
...@@ -211,3 +211,14 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) ...@@ -211,3 +211,14 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
} }
return 1; return 1;
} }
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
/* /*
* Driver for 8250/16550-type serial ports * Universal/legacy driver for 8250/16550-type serial ports
* *
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
* *
* Copyright (C) 2001 Russell King. * Copyright (C) 2001 Russell King.
* *
* Supports: ISA-compatible 8250/16550 ports
* PNP 8250/16550 ports
* early_serial_setup() ports
* userspace-configurable "phantom" ports
* "serial8250" platform devices
* serial8250_register_8250_port() ports
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
*
* A note about mapbase / membase
*
* mapbase is the physical address of the IO port.
* membase is an 'ioremapped' cookie.
*/ */
#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/ioport.h> #include <linux/ioport.h>
...@@ -58,33 +56,10 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; ...@@ -58,33 +56,10 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
static struct uart_driver serial8250_reg; static struct uart_driver serial8250_reg;
static int serial_index(struct uart_port *port)
{
return port->minor - 64;
}
static unsigned int skip_txen_test; /* force skip of txen test at init time */ static unsigned int skip_txen_test; /* force skip of txen test at init time */
/*
* Debugging.
*/
#if 0
#define DEBUG_AUTOCONF(fmt...) printk(fmt)
#else
#define DEBUG_AUTOCONF(fmt...) do { } while (0)
#endif
#if 0
#define DEBUG_INTR(fmt...) printk(fmt)
#else
#define DEBUG_INTR(fmt...) do { } while (0)
#endif
#define PASS_LIMIT 512 #define PASS_LIMIT 512
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
#include <asm/serial.h> #include <asm/serial.h>
/* /*
* SERIAL_PORT_DFNS tells us about built-in ports that have no * SERIAL_PORT_DFNS tells us about built-in ports that have no
...@@ -120,2695 +95,268 @@ static struct hlist_head irq_lists[NR_IRQ_HASH]; ...@@ -120,2695 +95,268 @@ static struct hlist_head irq_lists[NR_IRQ_HASH];
static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */ static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */
/* /*
* Here we define the default xmit fifo size used for each type of UART. * This is the serial driver's interrupt routine.
*
* Arjan thinks the old way was overly complex, so it got simplified.
* Alan disagrees, saying that need the complexity to handle the weird
* nature of ISA shared interrupts. (This is a special exception.)
*
* In order to handle ISA shared interrupts properly, we need to check
* that all ports have been serviced, and therefore the ISA interrupt
* line has been de-asserted.
*
* This means we need to loop through all ports. checking that they
* don't have an interrupt pending.
*/ */
static const struct serial8250_config uart_config[] = { static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
[PORT_UNKNOWN] = {
.name = "unknown",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_8250] = {
.name = "8250",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16450] = {
.name = "16450",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16550] = {
.name = "16550",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16550A] = {
.name = "16550A",
.fifo_size = 16,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO,
},
[PORT_CIRRUS] = {
.name = "Cirrus",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16650] = {
.name = "ST16650",
.fifo_size = 1,
.tx_loadsz = 1,
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16650V2] = {
.name = "ST16650V2",
.fifo_size = 32,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_00,
.rxtrig_bytes = {8, 16, 24, 28},
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16750] = {
.name = "TI16750",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
UART_FCR7_64BYTE,
.rxtrig_bytes = {1, 16, 32, 56},
.flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
},
[PORT_STARTECH] = {
.name = "Startech",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16C950] = {
.name = "16C950/954",
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
/* UART_CAP_EFR breaks billionon CF bluetooth card. */
.flags = UART_CAP_FIFO | UART_CAP_SLEEP,
},
[PORT_16654] = {
.name = "ST16654",
.fifo_size = 64,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_10,
.rxtrig_bytes = {8, 16, 56, 60},
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16850] = {
.name = "XR16850",
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_RSA] = {
.name = "RSA",
.fifo_size = 2048,
.tx_loadsz = 2048,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
.flags = UART_CAP_FIFO,
},
[PORT_NS16550A] = {
.name = "NS16550A",
.fifo_size = 16,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_NATSEMI,
},
[PORT_XSCALE] = {
.name = "XScale",
.fifo_size = 32,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
},
[PORT_OCTEON] = {
.name = "OCTEON",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
},
[PORT_AR7] = {
.name = "AR7",
.fifo_size = 16,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_U6_16550A] = {
.name = "U6_16550A",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_TEGRA] = {
.name = "Tegra",
.fifo_size = 32,
.tx_loadsz = 8,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_01,
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO | UART_CAP_RTOIE,
},
[PORT_XR17D15X] = {
.name = "XR17D15X",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP,
},
[PORT_XR17V35X] = {
.name = "XR17V35X",
.fifo_size = 256,
.tx_loadsz = 256,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
UART_FCR_T_TRIG_11,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP,
},
[PORT_LPC3220] = {
.name = "LPC3220",
.fifo_size = 64,
.tx_loadsz = 32,
.fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
.flags = UART_CAP_FIFO,
},
[PORT_BRCM_TRUMANAGE] = {
.name = "TruManage",
.fifo_size = 1,
.tx_loadsz = 1024,
.flags = UART_CAP_HFIFO,
},
[PORT_8250_CIR] = {
.name = "CIR port"
},
[PORT_ALTR_16550_F32] = {
.name = "Altera 16550 FIFO32",
.fifo_size = 32,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_ALTR_16550_F64] = {
.name = "Altera 16550 FIFO64",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_ALTR_16550_F128] = {
.name = "Altera 16550 FIFO128",
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement
workaround of errata A-008006 which states that tx_loadsz should be
configured less than Maximum supported fifo bytes */
[PORT_16550A_FSL64] = {
.name = "16550A_FSL64",
.fifo_size = 64,
.tx_loadsz = 63,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
UART_FCR7_64BYTE,
.flags = UART_CAP_FIFO,
},
};
/* Uart divisor latch read */
static int default_serial_dl_read(struct uart_8250_port *up)
{
return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
}
/* Uart divisor latch write */
static void default_serial_dl_write(struct uart_8250_port *up, int value)
{
serial_out(up, UART_DLL, value & 0xff);
serial_out(up, UART_DLM, value >> 8 & 0xff);
}
#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
/* Au1x00/RT288x UART hardware has a weird register layout */
static const s8 au_io_in_map[8] = {
0, /* UART_RX */
2, /* UART_IER */
3, /* UART_IIR */
5, /* UART_LCR */
6, /* UART_MCR */
7, /* UART_LSR */
8, /* UART_MSR */
-1, /* UART_SCR (unmapped) */
};
static const s8 au_io_out_map[8] = {
1, /* UART_TX */
2, /* UART_IER */
4, /* UART_FCR */
5, /* UART_LCR */
6, /* UART_MCR */
-1, /* UART_LSR (unmapped) */
-1, /* UART_MSR (unmapped) */
-1, /* UART_SCR (unmapped) */
};
static unsigned int au_serial_in(struct uart_port *p, int offset)
{
if (offset >= ARRAY_SIZE(au_io_in_map))
return UINT_MAX;
offset = au_io_in_map[offset];
if (offset < 0)
return UINT_MAX;
return __raw_readl(p->membase + (offset << p->regshift));
}
static void au_serial_out(struct uart_port *p, int offset, int value)
{
if (offset >= ARRAY_SIZE(au_io_out_map))
return;
offset = au_io_out_map[offset];
if (offset < 0)
return;
__raw_writel(value, p->membase + (offset << p->regshift));
}
/* Au1x00 haven't got a standard divisor latch */
static int au_serial_dl_read(struct uart_8250_port *up)
{ {
return __raw_readl(up->port.membase + 0x28); struct irq_info *i = dev_id;
} struct list_head *l, *end = NULL;
int pass_counter = 0, handled = 0;
static void au_serial_dl_write(struct uart_8250_port *up, int value) DEBUG_INTR("serial8250_interrupt(%d)...", irq);
{
__raw_writel(value, up->port.membase + 0x28);
}
#endif spin_lock(&i->lock);
static unsigned int hub6_serial_in(struct uart_port *p, int offset) l = i->head;
{ do {
offset = offset << p->regshift; struct uart_8250_port *up;
outb(p->hub6 - 1 + offset, p->iobase); struct uart_port *port;
return inb(p->iobase + 1);
}
static void hub6_serial_out(struct uart_port *p, int offset, int value) up = list_entry(l, struct uart_8250_port, list);
{ port = &up->port;
offset = offset << p->regshift;
outb(p->hub6 - 1 + offset, p->iobase);
outb(value, p->iobase + 1);
}
static unsigned int mem_serial_in(struct uart_port *p, int offset) if (port->handle_irq(port)) {
{ handled = 1;
offset = offset << p->regshift; end = NULL;
return readb(p->membase + offset); } else if (end == NULL)
} end = l;
static void mem_serial_out(struct uart_port *p, int offset, int value) l = l->next;
{
offset = offset << p->regshift;
writeb(value, p->membase + offset);
}
static void mem32_serial_out(struct uart_port *p, int offset, int value) if (l == i->head && pass_counter++ > PASS_LIMIT) {
{ /* If we hit this, we're dead. */
offset = offset << p->regshift; printk_ratelimited(KERN_ERR
writel(value, p->membase + offset); "serial8250: too much work for irq%d\n", irq);
} break;
}
} while (l != end);
static unsigned int mem32_serial_in(struct uart_port *p, int offset) spin_unlock(&i->lock);
{
offset = offset << p->regshift;
return readl(p->membase + offset);
}
static void mem32be_serial_out(struct uart_port *p, int offset, int value) DEBUG_INTR("end.\n");
{
offset = offset << p->regshift;
iowrite32be(value, p->membase + offset);
}
static unsigned int mem32be_serial_in(struct uart_port *p, int offset) return IRQ_RETVAL(handled);
{
offset = offset << p->regshift;
return ioread32be(p->membase + offset);
} }
static unsigned int io_serial_in(struct uart_port *p, int offset) /*
* To support ISA shared interrupts, we need to have one interrupt
* handler that ensures that the IRQ line has been deasserted
* before returning. Failing to do this will result in the IRQ
* line being stuck active, and, since ISA irqs are edge triggered,
* no more IRQs will be seen.
*/
static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
{ {
offset = offset << p->regshift; spin_lock_irq(&i->lock);
return inb(p->iobase + offset);
}
static void io_serial_out(struct uart_port *p, int offset, int value) if (!list_empty(i->head)) {
{ if (i->head == &up->list)
offset = offset << p->regshift; i->head = i->head->next;
outb(value, p->iobase + offset); list_del(&up->list);
} else {
BUG_ON(i->head != &up->list);
i->head = NULL;
}
spin_unlock_irq(&i->lock);
/* List empty so throw away the hash node */
if (i->head == NULL) {
hlist_del(&i->node);
kfree(i);
}
} }
static int serial8250_default_handle_irq(struct uart_port *port); static int serial_link_irq_chain(struct uart_8250_port *up)
static int exar_handle_irq(struct uart_port *port);
static void set_io_from_upio(struct uart_port *p)
{ {
struct uart_8250_port *up = up_to_u8250p(p); struct hlist_head *h;
struct hlist_node *n;
up->dl_read = default_serial_dl_read; struct irq_info *i;
up->dl_write = default_serial_dl_write; int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
switch (p->iotype) { mutex_lock(&hash_mutex);
case UPIO_HUB6:
p->serial_in = hub6_serial_in;
p->serial_out = hub6_serial_out;
break;
case UPIO_MEM: h = &irq_lists[up->port.irq % NR_IRQ_HASH];
p->serial_in = mem_serial_in;
p->serial_out = mem_serial_out;
break;
case UPIO_MEM32: hlist_for_each(n, h) {
p->serial_in = mem32_serial_in; i = hlist_entry(n, struct irq_info, node);
p->serial_out = mem32_serial_out; if (i->irq == up->port.irq)
break; break;
}
case UPIO_MEM32BE: if (n == NULL) {
p->serial_in = mem32be_serial_in; i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
p->serial_out = mem32be_serial_out; if (i == NULL) {
break; mutex_unlock(&hash_mutex);
return -ENOMEM;
}
spin_lock_init(&i->lock);
i->irq = up->port.irq;
hlist_add_head(&i->node, h);
}
mutex_unlock(&hash_mutex);
#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X) spin_lock_irq(&i->lock);
case UPIO_AU:
p->serial_in = au_serial_in;
p->serial_out = au_serial_out;
up->dl_read = au_serial_dl_read;
up->dl_write = au_serial_dl_write;
break;
#endif
default: if (i->head) {
p->serial_in = io_serial_in; list_add(&up->list, i->head);
p->serial_out = io_serial_out; spin_unlock_irq(&i->lock);
break;
}
/* Remember loaded iotype */
up->cur_iotype = p->iotype;
p->handle_irq = serial8250_default_handle_irq;
}
static void ret = 0;
serial_port_out_sync(struct uart_port *p, int offset, int value) } else {
{ INIT_LIST_HEAD(&up->list);
switch (p->iotype) { i->head = &up->list;
case UPIO_MEM: spin_unlock_irq(&i->lock);
case UPIO_MEM32: irq_flags |= up->port.irqflags;
case UPIO_MEM32BE: ret = request_irq(up->port.irq, serial8250_interrupt,
case UPIO_AU: irq_flags, "serial", i);
p->serial_out(p, offset, value); if (ret < 0)
p->serial_in(p, UART_LCR); /* safe, no side-effects */ serial_do_unlink(i, up);
break;
default:
p->serial_out(p, offset, value);
} }
}
/* return ret;
* For the 16C950
*/
static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
{
serial_out(up, UART_SCR, offset);
serial_out(up, UART_ICR, value);
} }
static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) static void serial_unlink_irq_chain(struct uart_8250_port *up)
{ {
unsigned int value; /*
* yes, some broken gcc emit "warning: 'i' may be used uninitialized"
* but no, we are not going to take a patch that assigns NULL below.
*/
struct irq_info *i;
struct hlist_node *n;
struct hlist_head *h;
serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); mutex_lock(&hash_mutex);
serial_out(up, UART_SCR, offset);
value = serial_in(up, UART_ICR);
serial_icr_write(up, UART_ACR, up->acr);
return value; h = &irq_lists[up->port.irq % NR_IRQ_HASH];
}
/* hlist_for_each(n, h) {
* FIFO support. i = hlist_entry(n, struct irq_info, node);
*/ if (i->irq == up->port.irq)
static void serial8250_clear_fifos(struct uart_8250_port *p) break;
{
if (p->capabilities & UART_CAP_FIFO) {
serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial_out(p, UART_FCR, 0);
} }
}
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p) BUG_ON(n == NULL);
{ BUG_ON(i->head == NULL);
serial8250_clear_fifos(p);
serial_out(p, UART_FCR, p->fcr);
}
EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
void serial8250_rpm_get(struct uart_8250_port *p) if (list_empty(i->head))
{ free_irq(up->port.irq, i);
if (!(p->capabilities & UART_CAP_RPM))
return;
pm_runtime_get_sync(p->port.dev);
}
EXPORT_SYMBOL_GPL(serial8250_rpm_get);
void serial8250_rpm_put(struct uart_8250_port *p) serial_do_unlink(i, up);
{ mutex_unlock(&hash_mutex);
if (!(p->capabilities & UART_CAP_RPM))
return;
pm_runtime_mark_last_busy(p->port.dev);
pm_runtime_put_autosuspend(p->port.dev);
} }
EXPORT_SYMBOL_GPL(serial8250_rpm_put);
/* /*
* These two wrappers ensure that enable_runtime_pm_tx() can be called more than * This function is used to handle ports that do not have an
* once and disable_runtime_pm_tx() will still disable RPM because the fifo is * interrupt. This doesn't work very well for 16450's, but gives
* empty and the HW can idle again. * barely passable results for a 16550A. (Although at the expense
* of much CPU overhead).
*/ */
static void serial8250_rpm_get_tx(struct uart_8250_port *p) static void serial8250_timeout(unsigned long data)
{ {
unsigned char rpm_active; struct uart_8250_port *up = (struct uart_8250_port *)data;
if (!(p->capabilities & UART_CAP_RPM))
return;
rpm_active = xchg(&p->rpm_tx_active, 1); up->port.handle_irq(&up->port);
if (rpm_active) mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
return;
pm_runtime_get_sync(p->port.dev);
} }
static void serial8250_rpm_put_tx(struct uart_8250_port *p) static void serial8250_backup_timeout(unsigned long data)
{ {
unsigned char rpm_active; struct uart_8250_port *up = (struct uart_8250_port *)data;
unsigned int iir, ier = 0, lsr;
unsigned long flags;
if (!(p->capabilities & UART_CAP_RPM)) spin_lock_irqsave(&up->port.lock, flags);
return;
rpm_active = xchg(&p->rpm_tx_active, 0);
if (!rpm_active)
return;
pm_runtime_mark_last_busy(p->port.dev);
pm_runtime_put_autosuspend(p->port.dev);
}
/*
* IER sleep support. UARTs which have EFRs need the "extended
* capability" bit enabled. Note that on XR16C850s, we need to
* reset LCR to write to IER.
*/
static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
unsigned char lcr = 0, efr = 0;
/*
* Exar UARTs have a SLEEP register that enables or disables
* each UART to enter sleep mode separately. On the XR17V35x the
* register is accessible to each UART at the UART_EXAR_SLEEP
* offset but the UART channel may only write to the corresponding
* bit.
*/
serial8250_rpm_get(p);
if ((p->port.type == PORT_XR17V35X) ||
(p->port.type == PORT_XR17D15X)) {
serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
goto out;
}
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
lcr = serial_in(p, UART_LCR);
efr = serial_in(p, UART_EFR);
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(p, UART_EFR, UART_EFR_ECB);
serial_out(p, UART_LCR, 0);
}
serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
if (p->capabilities & UART_CAP_EFR) {
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(p, UART_EFR, efr);
serial_out(p, UART_LCR, lcr);
}
}
out:
serial8250_rpm_put(p);
}
#ifdef CONFIG_SERIAL_8250_RSA
/*
* Attempts to turn on the RSA FIFO. Returns zero on failure.
* We set the port uart clock rate if we succeed.
*/
static int __enable_rsa(struct uart_8250_port *up)
{
unsigned char mode;
int result;
mode = serial_in(up, UART_RSA_MSR);
result = mode & UART_RSA_MSR_FIFO;
if (!result) {
serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
mode = serial_in(up, UART_RSA_MSR);
result = mode & UART_RSA_MSR_FIFO;
}
if (result)
up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
return result;
}
static void enable_rsa(struct uart_8250_port *up)
{
if (up->port.type == PORT_RSA) {
if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
spin_lock_irq(&up->port.lock);
__enable_rsa(up);
spin_unlock_irq(&up->port.lock);
}
if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
serial_out(up, UART_RSA_FRR, 0);
}
}
/*
* Attempts to turn off the RSA FIFO. Returns zero on failure.
* It is unknown why interrupts were disabled in here. However,
* the caller is expected to preserve this behaviour by grabbing
* the spinlock before calling this function.
*/
static void disable_rsa(struct uart_8250_port *up)
{
unsigned char mode;
int result;
if (up->port.type == PORT_RSA &&
up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
spin_lock_irq(&up->port.lock);
mode = serial_in(up, UART_RSA_MSR);
result = !(mode & UART_RSA_MSR_FIFO);
if (!result) {
serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
mode = serial_in(up, UART_RSA_MSR);
result = !(mode & UART_RSA_MSR_FIFO);
}
if (result)
up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
spin_unlock_irq(&up->port.lock);
}
}
#endif /* CONFIG_SERIAL_8250_RSA */
/*
* This is a quickie test to see how big the FIFO is.
* It doesn't work at all the time, more's the pity.
*/
static int size_fifo(struct uart_8250_port *up)
{
unsigned char old_fcr, old_mcr, old_lcr;
unsigned short old_dl;
int count;
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);
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);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
old_dl = serial_dl_read(up);
serial_dl_write(up, 0x0001);
serial_out(up, UART_LCR, 0x03);
for (count = 0; count < 256; count++)
serial_out(up, UART_TX, count);
mdelay(20);/* FIXME - schedule_timeout */
for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) &&
(count < 256); count++)
serial_in(up, UART_RX);
serial_out(up, UART_FCR, old_fcr);
serial_out(up, UART_MCR, 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);
return count;
}
/*
* Read UART ID using the divisor method - set DLL and DLM to zero
* and the revision will be in DLL and device type in DLM. We
* preserve the device state across this.
*/
static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
{
unsigned char old_dll, old_dlm, old_lcr;
unsigned int id;
old_lcr = serial_in(p, UART_LCR);
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
old_dll = serial_in(p, UART_DLL);
old_dlm = serial_in(p, UART_DLM);
serial_out(p, UART_DLL, 0);
serial_out(p, UART_DLM, 0);
id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8;
serial_out(p, UART_DLL, old_dll);
serial_out(p, UART_DLM, old_dlm);
serial_out(p, UART_LCR, old_lcr);
return id;
}
/*
* This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
* When this function is called we know it is at least a StarTech
* 16650 V2, but it might be one of several StarTech UARTs, or one of
* its clones. (We treat the broken original StarTech 16650 V1 as a
* 16550, and why not? Startech doesn't seem to even acknowledge its
* existence.)
*
* What evil have men's minds wrought...
*/
static void autoconfig_has_efr(struct uart_8250_port *up)
{
unsigned int id1, id2, id3, rev;
/*
* Everything with an EFR has SLEEP
*/
up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
/*
* First we check to see if it's an Oxford Semiconductor UART.
*
* If we have to do this here because some non-National
* Semiconductor clone chips lock up if you try writing to the
* LSR register (which serial_icr_read does)
*/
/*
* Check for Oxford Semiconductor 16C950.
*
* EFR [4] must be set else this test fails.
*
* This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
* claims that it's needed for 952 dual UART's (which are not
* recommended for new designs).
*/
up->acr = 0;
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, 0x00);
id1 = serial_icr_read(up, UART_ID1);
id2 = serial_icr_read(up, UART_ID2);
id3 = serial_icr_read(up, UART_ID3);
rev = serial_icr_read(up, UART_REV);
DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
if (id1 == 0x16 && id2 == 0xC9 &&
(id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
up->port.type = PORT_16C950;
/*
* Enable work around for the Oxford Semiconductor 952 rev B
* chip which causes it to seriously miscalculate baud rates
* when DLL is 0.
*/
if (id3 == 0x52 && rev == 0x01)
up->bugs |= UART_BUG_QUOT;
return;
}
/*
* We check for a XR16C850 by setting DLL and DLM to 0, and then
* reading back DLL and DLM. The chip type depends on the DLM
* value read back:
* 0x10 - XR16C850 and the DLL contains the chip revision.
* 0x12 - XR16C2850.
* 0x14 - XR16C854.
*/
id1 = autoconfig_read_divisor_id(up);
DEBUG_AUTOCONF("850id=%04x ", id1);
id2 = id1 >> 8;
if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
up->port.type = PORT_16850;
return;
}
/*
* It wasn't an XR16C850.
*
* We distinguish between the '654 and the '650 by counting
* how many bytes are in the FIFO. I'm using this for now,
* since that's the technique that was sent to me in the
* serial driver update, but I'm not convinced this works.
* I've had problems doing this in the past. -TYT
*/
if (size_fifo(up) == 64)
up->port.type = PORT_16654;
else
up->port.type = PORT_16650V2;
}
/*
* We detected a chip without a FIFO. Only two fall into
* this category - the original 8250 and the 16450. The
* 16450 has a scratch register (accessible with LCR=0)
*/
static void autoconfig_8250(struct uart_8250_port *up)
{
unsigned char scratch, status1, status2;
up->port.type = PORT_8250;
scratch = serial_in(up, UART_SCR);
serial_out(up, UART_SCR, 0xa5);
status1 = serial_in(up, UART_SCR);
serial_out(up, UART_SCR, 0x5a);
status2 = serial_in(up, UART_SCR);
serial_out(up, UART_SCR, scratch);
if (status1 == 0xa5 && status2 == 0x5a)
up->port.type = PORT_16450;
}
static int broken_efr(struct uart_8250_port *up)
{
/*
* Exar ST16C2550 "A2" devices incorrectly detect as
* having an EFR, and report an ID of 0x0201. See
* http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
*/
if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
return 1;
return 0;
}
/*
* We know that the chip has FIFOs. Does it have an EFR? The
* EFR is located in the same register position as the IIR and
* we know the top two bits of the IIR are currently set. The
* EFR should contain zero. Try to read the EFR.
*/
static void autoconfig_16550a(struct uart_8250_port *up)
{
unsigned char status1, status2;
unsigned int iersave;
up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO;
/*
* XR17V35x UARTs have an extra divisor register, DLD
* that gets enabled with when DLAB is set which will
* cause the device to incorrectly match and assign
* port type to PORT_16650. The EFR for this UART is
* found at offset 0x09. Instead check the Deice ID (DVID)
* register for a 2, 4 or 8 port UART.
*/
if (up->port.flags & UPF_EXAR_EFR) {
status1 = serial_in(up, UART_EXAR_DVID);
if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
DEBUG_AUTOCONF("Exar XR17V35x ");
up->port.type = PORT_XR17V35X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
}
}
/*
* Check for presence of the EFR when DLAB is set.
* Only ST16C650V1 UARTs pass this test.
*/
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
if (serial_in(up, UART_EFR) == 0) {
serial_out(up, UART_EFR, 0xA8);
if (serial_in(up, UART_EFR) != 0) {
DEBUG_AUTOCONF("EFRv1 ");
up->port.type = PORT_16650;
up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
} else {
serial_out(up, UART_LCR, 0);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR7_64BYTE);
status1 = serial_in(up, UART_IIR) >> 5;
serial_out(up, UART_FCR, 0);
serial_out(up, UART_LCR, 0);
if (status1 == 7)
up->port.type = PORT_16550A_FSL64;
else
DEBUG_AUTOCONF("Motorola 8xxx DUART ");
}
serial_out(up, UART_EFR, 0);
return;
}
/*
* Maybe it requires 0xbf to be written to the LCR.
* (other ST16C650V2 UARTs, TI16C752A, etc)
*/
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
DEBUG_AUTOCONF("EFRv2 ");
autoconfig_has_efr(up);
return;
}
/*
* Check for a National Semiconductor SuperIO chip.
* Attempt to switch to bank 2, read the value of the LOOP bit
* from EXCR1. Switch back to bank 0, change it in MCR. Then
* switch back to bank 2, read it from EXCR1 again and check
* 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);
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);
serial_out(up, UART_LCR, 0xE0);
status2 = serial_in(up, 0x02); /* EXCR1 */
serial_out(up, UART_LCR, 0);
serial_out(up, UART_MCR, status1);
if ((status2 ^ status1) & UART_MCR_LOOP) {
unsigned short quot;
serial_out(up, UART_LCR, 0xE0);
quot = serial_dl_read(up);
quot <<= 3;
if (ns16550a_goto_highspeed(up))
serial_dl_write(up, quot);
serial_out(up, UART_LCR, 0);
up->port.uartclk = 921600*16;
up->port.type = PORT_NS16550A;
up->capabilities |= UART_NATSEMI;
return;
}
}
/*
* No EFR. Try to detect a TI16750, which only sets bit 5 of
* the IIR when 64 byte FIFO mode is enabled when DLAB is set.
* Try setting it with and without DLAB set. Cheap clones
* set bit 5 without DLAB set.
*/
serial_out(up, UART_LCR, 0);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status1 = serial_in(up, UART_IIR) >> 5;
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status2 = serial_in(up, UART_IIR) >> 5;
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_out(up, UART_LCR, 0);
DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
if (status1 == 6 && status2 == 7) {
up->port.type = PORT_16750;
up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
return;
}
/*
* Try writing and reading the UART_IER_UUE bit (b6).
* If it works, this is probably one of the Xscale platform's
* internal UARTs.
* We're going to explicitly set the UUE bit to 0 before
* trying to write and read a 1 just to make sure it's not
* already a 1 and maybe locked there before we even start start.
*/
iersave = serial_in(up, UART_IER);
serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
/*
* OK it's in a known zero state, try writing and reading
* without disturbing the current state of the other bits.
*/
serial_out(up, UART_IER, iersave | UART_IER_UUE);
if (serial_in(up, UART_IER) & UART_IER_UUE) {
/*
* It's an Xscale.
* We'll leave the UART_IER_UUE bit set to 1 (enabled).
*/
DEBUG_AUTOCONF("Xscale ");
up->port.type = PORT_XSCALE;
up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
return;
}
} else {
/*
* If we got here we couldn't force the IER_UUE bit to 0.
* Log it and continue.
*/
DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
}
serial_out(up, UART_IER, iersave);
/*
* Exar uarts have EFR in a weird location
*/
if (up->port.flags & UPF_EXAR_EFR) {
DEBUG_AUTOCONF("Exar XR17D15x ");
up->port.type = PORT_XR17D15X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
}
/*
* We distinguish between 16550A and U6 16550A by counting
* how many bytes are in the FIFO.
*/
if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
up->port.type = PORT_U6_16550A;
up->capabilities |= UART_CAP_AFE;
}
}
/*
* This routine is called by rs_init() to initialize a specific serial
* port. It determines what type of UART chip this serial port is
* using: 8250, 16450, 16550, 16550A. The important question is
* whether or not this UART is a 16550A or not, since this will
* determine whether or not we can use its FIFO features or not.
*/
static void autoconfig(struct uart_8250_port *up)
{
unsigned char status1, scratch, scratch2, scratch3;
unsigned char save_lcr, save_mcr;
struct uart_port *port = &up->port;
unsigned long flags;
unsigned int old_capabilities;
if (!port->iobase && !port->mapbase && !port->membase)
return;
DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
serial_index(port), port->iobase, port->membase);
/*
* We really do need global IRQs disabled here - we're going to
* be frobbing the chips IRQ enable register to see if it exists.
*/
spin_lock_irqsave(&port->lock, flags);
up->capabilities = 0;
up->bugs = 0;
if (!(port->flags & UPF_BUGGY_UART)) {
/*
* Do a simple existence test first; if we fail this,
* there's no point trying anything else.
*
* 0x80 is used as a nonsense port to prevent against
* false positives due to ISA bus float. The
* assumption is that 0x80 is a non-existent port;
* which should be safe since include/asm/io.h also
* makes this assumption.
*
* Note: this is safe as long as MCR bit 4 is clear
* and the device is in "PC" mode.
*/
scratch = serial_in(up, UART_IER);
serial_out(up, UART_IER, 0);
#ifdef __i386__
outb(0xff, 0x080);
#endif
/*
* Mask out IER[7:4] bits for test as some UARTs (e.g. TL
* 16C754B) allow only to modify them if an EFR bit is set.
*/
scratch2 = serial_in(up, UART_IER) & 0x0f;
serial_out(up, UART_IER, 0x0F);
#ifdef __i386__
outb(0, 0x080);
#endif
scratch3 = serial_in(up, UART_IER) & 0x0f;
serial_out(up, UART_IER, scratch);
if (scratch2 != 0 || scratch3 != 0x0F) {
/*
* We failed; there's nothing here
*/
spin_unlock_irqrestore(&port->lock, flags);
DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
scratch2, scratch3);
goto out;
}
}
save_mcr = serial_in(up, UART_MCR);
save_lcr = serial_in(up, UART_LCR);
/*
* Check to see if a UART is really there. Certain broken
* internal modems based on the Rockwell chipset fail this
* test, because they apparently don't implement the loopback
* test mode. So this test is skipped on the COM 1 through
* COM 4 ports. This *should* be safe, since no board
* manufacturer would be stupid enough to design a board
* that conflicts with COM 1-4 --- we hope!
*/
if (!(port->flags & UPF_SKIP_TEST)) {
serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
status1 = serial_in(up, UART_MSR) & 0xF0;
serial_out(up, UART_MCR, save_mcr);
if (status1 != 0x90) {
spin_unlock_irqrestore(&port->lock, flags);
DEBUG_AUTOCONF("LOOP test failed (%02x) ",
status1);
goto out;
}
}
/*
* We're pretty sure there's a port here. Lets find out what
* type of port it is. The IIR top two bits allows us to find
* out if it's 8250 or 16450, 16550, 16550A or later. This
* determines what we test for next.
*
* We also initialise the EFR (if any) to zero for later. The
* EFR occupies the same register location as the FCR and IIR.
*/
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, 0);
serial_out(up, UART_LCR, 0);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
scratch = serial_in(up, UART_IIR) >> 6;
switch (scratch) {
case 0:
autoconfig_8250(up);
break;
case 1:
port->type = PORT_UNKNOWN;
break;
case 2:
port->type = PORT_16550;
break;
case 3:
autoconfig_16550a(up);
break;
}
#ifdef CONFIG_SERIAL_8250_RSA
/*
* Only probe for RSA ports if we got the region.
*/
if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
__enable_rsa(up))
port->type = PORT_RSA;
#endif
serial_out(up, UART_LCR, save_lcr);
port->fifosize = uart_config[up->port.type].fifo_size;
old_capabilities = up->capabilities;
up->capabilities = uart_config[port->type].flags;
up->tx_loadsz = uart_config[port->type].tx_loadsz;
if (port->type == PORT_UNKNOWN)
goto out_lock;
/*
* Reset the UART.
*/
#ifdef CONFIG_SERIAL_8250_RSA
if (port->type == PORT_RSA)
serial_out(up, UART_RSA_FRR, 0);
#endif
serial_out(up, UART_MCR, save_mcr);
serial8250_clear_fifos(up);
serial_in(up, UART_RX);
if (up->capabilities & UART_CAP_UUE)
serial_out(up, UART_IER, UART_IER_UUE);
else
serial_out(up, UART_IER, 0);
out_lock:
spin_unlock_irqrestore(&port->lock, flags);
if (up->capabilities != old_capabilities) {
printk(KERN_WARNING
"ttyS%d: detected caps %08x should be %08x\n",
serial_index(port), old_capabilities,
up->capabilities);
}
out:
DEBUG_AUTOCONF("iir=%d ", scratch);
DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
}
static void autoconfig_irq(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
unsigned char save_mcr, save_ier;
unsigned char save_ICP = 0;
unsigned int ICP = 0;
unsigned long irqs;
int irq;
if (port->flags & UPF_FOURPORT) {
ICP = (port->iobase & 0xfe0) | 0x1f;
save_ICP = inb_p(ICP);
outb_p(0x80, ICP);
inb_p(ICP);
}
/* forget possible initially masked and pending IRQ */
probe_irq_off(probe_irq_on());
save_mcr = serial_in(up, UART_MCR);
save_ier = serial_in(up, UART_IER);
serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
irqs = probe_irq_on();
serial_out(up, UART_MCR, 0);
udelay(10);
if (port->flags & UPF_FOURPORT) {
serial_out(up, UART_MCR,
UART_MCR_DTR | UART_MCR_RTS);
} else {
serial_out(up, UART_MCR,
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
}
serial_out(up, UART_IER, 0x0f); /* enable all intrs */
serial_in(up, UART_LSR);
serial_in(up, UART_RX);
serial_in(up, UART_IIR);
serial_in(up, UART_MSR);
serial_out(up, UART_TX, 0xFF);
udelay(20);
irq = probe_irq_off(irqs);
serial_out(up, UART_MCR, save_mcr);
serial_out(up, UART_IER, save_ier);
if (port->flags & UPF_FOURPORT)
outb_p(save_ICP, ICP);
port->irq = (irq > 0) ? irq : 0;
}
static inline void __stop_tx(struct uart_8250_port *p)
{
if (p->ier & UART_IER_THRI) {
p->ier &= ~UART_IER_THRI;
serial_out(p, UART_IER, p->ier);
serial8250_rpm_put_tx(p);
}
}
static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get(up);
__stop_tx(up);
/*
* We really want to stop the transmitter from sending.
*/
if (port->type == PORT_16C950) {
up->acr |= UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
serial8250_rpm_put(up);
}
static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get_tx(up);
if (up->dma && !up->dma->tx_dma(up))
return;
if (!(up->ier & UART_IER_THRI)) {
up->ier |= UART_IER_THRI;
serial_port_out(port, UART_IER, up->ier);
if (up->bugs & UART_BUG_TXEN) {
unsigned char lsr;
lsr = serial_in(up, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
if (lsr & UART_LSR_THRE)
serial8250_tx_chars(up);
}
}
/*
* Re-enable the transmitter if we disabled it.
*/
if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
up->acr &= ~UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
}
static void serial8250_throttle(struct uart_port *port)
{
port->throttle(port);
}
static void serial8250_unthrottle(struct uart_port *port)
{
port->unthrottle(port);
}
static void serial8250_stop_rx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get(up);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
up->port.read_status_mask &= ~UART_LSR_DR;
serial_port_out(port, UART_IER, up->ier);
serial8250_rpm_put(up);
}
static void serial8250_disable_ms(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
/* no MSR capabilities */
if (up->bugs & UART_BUG_NOMSR)
return;
up->ier &= ~UART_IER_MSI;
serial_port_out(port, UART_IER, up->ier);
}
static void serial8250_enable_ms(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
/* no MSR capabilities */
if (up->bugs & UART_BUG_NOMSR)
return;
up->ier |= UART_IER_MSI;
serial8250_rpm_get(up);
serial_port_out(port, UART_IER, up->ier);
serial8250_rpm_put(up);
}
/*
* serial8250_rx_chars: processes according to the passed in LSR
* value, and returns the remaining LSR bits not handled
* by this Rx routine.
*/
unsigned char
serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
{
struct uart_port *port = &up->port;
unsigned char ch;
int max_count = 256;
char flag;
do {
if (likely(lsr & UART_LSR_DR))
ch = serial_in(up, UART_RX);
else
/*
* Intel 82571 has a Serial Over Lan device that will
* set UART_LSR_BI without setting UART_LSR_DR when
* it receives a break. To avoid reading from the
* receive buffer without UART_LSR_DR bit set, we
* just force the read character to be 0
*/
ch = 0;
flag = TTY_NORMAL;
port->icount.rx++;
lsr |= up->lsr_saved_flags;
up->lsr_saved_flags = 0;
if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
if (lsr & UART_LSR_BI) {
lsr &= ~(UART_LSR_FE | UART_LSR_PE);
port->icount.brk++;
/*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
* or read_status_mask.
*/
if (uart_handle_break(port))
goto ignore_char;
} else if (lsr & UART_LSR_PE)
port->icount.parity++;
else if (lsr & UART_LSR_FE)
port->icount.frame++;
if (lsr & UART_LSR_OE)
port->icount.overrun++;
/*
* Mask off conditions which should be ignored.
*/
lsr &= port->read_status_mask;
if (lsr & UART_LSR_BI) {
DEBUG_INTR("handling break....");
flag = TTY_BREAK;
} else if (lsr & UART_LSR_PE)
flag = TTY_PARITY;
else if (lsr & UART_LSR_FE)
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(port, ch))
goto ignore_char;
uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
ignore_char:
lsr = serial_in(up, UART_LSR);
} while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
return lsr;
}
EXPORT_SYMBOL_GPL(serial8250_rx_chars);
void serial8250_tx_chars(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
struct circ_buf *xmit = &port->state->xmit;
int count;
if (port->x_char) {
serial_out(up, UART_TX, port->x_char);
port->icount.tx++;
port->x_char = 0;
return;
}
if (uart_tx_stopped(port)) {
serial8250_stop_tx(port);
return;
}
if (uart_circ_empty(xmit)) {
__stop_tx(up);
return;
}
count = up->tx_loadsz;
do {
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
if (uart_circ_empty(xmit))
break;
if (up->capabilities & UART_CAP_HFIFO) {
if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
BOTH_EMPTY)
break;
}
} while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
DEBUG_INTR("THRE...");
/*
* With RPM enabled, we have to wait until the FIFO is empty before the
* HW can go idle. So we get here once again with empty FIFO and disable
* the interrupt and RPM in __stop_tx()
*/
if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
__stop_tx(up);
}
EXPORT_SYMBOL_GPL(serial8250_tx_chars);
/* Caller holds uart port lock */
unsigned int serial8250_modem_status(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
unsigned int status = serial_in(up, UART_MSR);
status |= up->msr_saved_flags;
up->msr_saved_flags = 0;
if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
port->state != NULL) {
if (status & UART_MSR_TERI)
port->icount.rng++;
if (status & UART_MSR_DDSR)
port->icount.dsr++;
if (status & UART_MSR_DDCD)
uart_handle_dcd_change(port, status & UART_MSR_DCD);
if (status & UART_MSR_DCTS)
uart_handle_cts_change(port, status & UART_MSR_CTS);
wake_up_interruptible(&port->state->port.delta_msr_wait);
}
return status;
}
EXPORT_SYMBOL_GPL(serial8250_modem_status);
/*
* This handles the interrupt from one port.
*/
int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
{
unsigned char status;
unsigned long flags;
struct uart_8250_port *up = up_to_u8250p(port);
int dma_err = 0;
if (iir & UART_IIR_NO_INT)
return 0;
spin_lock_irqsave(&port->lock, flags);
status = serial_port_in(port, UART_LSR);
DEBUG_INTR("status = %x...", status);
if (status & (UART_LSR_DR | UART_LSR_BI)) {
if (up->dma)
dma_err = up->dma->rx_dma(up, iir);
if (!up->dma || dma_err)
status = serial8250_rx_chars(up, status);
}
serial8250_modem_status(up);
if ((!up->dma || (up->dma && up->dma->tx_err)) &&
(status & UART_LSR_THRE))
serial8250_tx_chars(up);
spin_unlock_irqrestore(&port->lock, flags);
return 1;
}
EXPORT_SYMBOL_GPL(serial8250_handle_irq);
static int serial8250_default_handle_irq(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int iir;
int ret;
serial8250_rpm_get(up);
iir = serial_port_in(port, UART_IIR);
ret = serial8250_handle_irq(port, iir);
serial8250_rpm_put(up);
return ret;
}
/*
* These Exar UARTs have an extra interrupt indicator that could
* fire for a few unimplemented interrupts. One of which is a
* wakeup event when coming out of sleep. Put this here just
* to be on the safe side that these interrupts don't go unhandled.
*/
static int exar_handle_irq(struct uart_port *port)
{
unsigned char int0, int1, int2, int3;
unsigned int iir = serial_port_in(port, UART_IIR);
int ret;
ret = serial8250_handle_irq(port, iir);
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);
}
return ret;
}
/*
* This is the serial driver's interrupt routine.
*
* Arjan thinks the old way was overly complex, so it got simplified.
* Alan disagrees, saying that need the complexity to handle the weird
* nature of ISA shared interrupts. (This is a special exception.)
*
* In order to handle ISA shared interrupts properly, we need to check
* that all ports have been serviced, and therefore the ISA interrupt
* line has been de-asserted.
*
* This means we need to loop through all ports. checking that they
* don't have an interrupt pending.
*/
static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
{
struct irq_info *i = dev_id;
struct list_head *l, *end = NULL;
int pass_counter = 0, handled = 0;
DEBUG_INTR("serial8250_interrupt(%d)...", irq);
spin_lock(&i->lock);
l = i->head;
do {
struct uart_8250_port *up;
struct uart_port *port;
up = list_entry(l, struct uart_8250_port, list);
port = &up->port;
if (port->handle_irq(port)) {
handled = 1;
end = NULL;
} else if (end == NULL)
end = l;
l = l->next;
if (l == i->head && pass_counter++ > PASS_LIMIT) {
/* If we hit this, we're dead. */
printk_ratelimited(KERN_ERR
"serial8250: too much work for irq%d\n", irq);
break;
}
} while (l != end);
spin_unlock(&i->lock);
DEBUG_INTR("end.\n");
return IRQ_RETVAL(handled);
}
/*
* To support ISA shared interrupts, we need to have one interrupt
* handler that ensures that the IRQ line has been deasserted
* before returning. Failing to do this will result in the IRQ
* line being stuck active, and, since ISA irqs are edge triggered,
* no more IRQs will be seen.
*/
static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
{
spin_lock_irq(&i->lock);
if (!list_empty(i->head)) {
if (i->head == &up->list)
i->head = i->head->next;
list_del(&up->list);
} else {
BUG_ON(i->head != &up->list);
i->head = NULL;
}
spin_unlock_irq(&i->lock);
/* List empty so throw away the hash node */
if (i->head == NULL) {
hlist_del(&i->node);
kfree(i);
}
}
static int serial_link_irq_chain(struct uart_8250_port *up)
{
struct hlist_head *h;
struct hlist_node *n;
struct irq_info *i;
int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
mutex_lock(&hash_mutex);
h = &irq_lists[up->port.irq % NR_IRQ_HASH];
hlist_for_each(n, h) {
i = hlist_entry(n, struct irq_info, node);
if (i->irq == up->port.irq)
break;
}
if (n == NULL) {
i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
if (i == NULL) {
mutex_unlock(&hash_mutex);
return -ENOMEM;
}
spin_lock_init(&i->lock);
i->irq = up->port.irq;
hlist_add_head(&i->node, h);
}
mutex_unlock(&hash_mutex);
spin_lock_irq(&i->lock);
if (i->head) {
list_add(&up->list, i->head);
spin_unlock_irq(&i->lock);
ret = 0;
} else {
INIT_LIST_HEAD(&up->list);
i->head = &up->list;
spin_unlock_irq(&i->lock);
irq_flags |= up->port.irqflags;
ret = request_irq(up->port.irq, serial8250_interrupt,
irq_flags, "serial", i);
if (ret < 0)
serial_do_unlink(i, up);
}
return ret;
}
static void serial_unlink_irq_chain(struct uart_8250_port *up)
{
/*
* yes, some broken gcc emit "warning: 'i' may be used uninitialized"
* but no, we are not going to take a patch that assigns NULL below.
*/
struct irq_info *i;
struct hlist_node *n;
struct hlist_head *h;
mutex_lock(&hash_mutex);
h = &irq_lists[up->port.irq % NR_IRQ_HASH];
hlist_for_each(n, h) {
i = hlist_entry(n, struct irq_info, node);
if (i->irq == up->port.irq)
break;
}
BUG_ON(n == NULL);
BUG_ON(i->head == NULL);
if (list_empty(i->head))
free_irq(up->port.irq, i);
serial_do_unlink(i, up);
mutex_unlock(&hash_mutex);
}
/*
* This function is used to handle ports that do not have an
* interrupt. This doesn't work very well for 16450's, but gives
* barely passable results for a 16550A. (Although at the expense
* of much CPU overhead).
*/
static void serial8250_timeout(unsigned long data)
{
struct uart_8250_port *up = (struct uart_8250_port *)data;
up->port.handle_irq(&up->port);
mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
}
static void serial8250_backup_timeout(unsigned long data)
{
struct uart_8250_port *up = (struct uart_8250_port *)data;
unsigned int iir, ier = 0, lsr;
unsigned long flags;
spin_lock_irqsave(&up->port.lock, flags);
/*
* Must disable interrupts or else we risk racing with the interrupt
* based handler.
*/
if (up->port.irq) {
ier = serial_in(up, UART_IER);
serial_out(up, UART_IER, 0);
}
iir = serial_in(up, UART_IIR);
/*
* This should be a safe test for anyone who doesn't trust the
* IIR bits on their UART, but it's specifically designed for
* the "Diva" UART used on the management processor on many HP
* ia64 and parisc boxes.
*/
lsr = serial_in(up, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
(!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
(lsr & UART_LSR_THRE)) {
iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
iir |= UART_IIR_THRI;
}
if (!(iir & UART_IIR_NO_INT))
serial8250_tx_chars(up);
if (up->port.irq)
serial_out(up, UART_IER, ier);
spin_unlock_irqrestore(&up->port.lock, flags);
/* Standard timer interval plus 0.2s to keep the port running */
mod_timer(&up->timer,
jiffies + uart_poll_timeout(&up->port) + HZ / 5);
}
static int univ8250_setup_irq(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
int retval = 0;
/*
* The above check will only give an accurate result the first time
* the port is opened so this value needs to be preserved.
*/
if (up->bugs & UART_BUG_THRE) {
pr_debug("ttyS%d - using backup timer\n", serial_index(port));
up->timer.function = serial8250_backup_timeout;
up->timer.data = (unsigned long)up;
mod_timer(&up->timer, jiffies +
uart_poll_timeout(port) + HZ / 5);
}
/*
* If the "interrupt" for this port doesn't correspond with any
* hardware interrupt, we use a timer-based system. The original
* driver used to do this with IRQ0.
*/
if (!port->irq) {
up->timer.data = (unsigned long)up;
mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
} else
retval = serial_link_irq_chain(up);
return retval;
}
static void univ8250_release_irq(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
del_timer_sync(&up->timer);
up->timer.function = serial8250_timeout;
if (port->irq)
serial_unlink_irq_chain(up);
}
static unsigned int serial8250_tx_empty(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
unsigned int lsr;
serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
lsr = serial_port_in(port, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
}
static unsigned int serial8250_get_mctrl(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int status;
unsigned int ret;
serial8250_rpm_get(up);
status = serial8250_modem_status(up);
serial8250_rpm_put(up);
ret = 0;
if (status & UART_MSR_DCD)
ret |= TIOCM_CAR;
if (status & UART_MSR_RI)
ret |= TIOCM_RNG;
if (status & UART_MSR_DSR)
ret |= TIOCM_DSR;
if (status & UART_MSR_CTS)
ret |= TIOCM_CTS;
return ret;
}
void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char mcr = 0;
if (mctrl & TIOCM_RTS)
mcr |= UART_MCR_RTS;
if (mctrl & TIOCM_DTR)
mcr |= UART_MCR_DTR;
if (mctrl & TIOCM_OUT1)
mcr |= UART_MCR_OUT1;
if (mctrl & TIOCM_OUT2)
mcr |= UART_MCR_OUT2;
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
serial_port_out(port, UART_MCR, mcr);
}
EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
if (port->set_mctrl)
port->set_mctrl(port, mctrl);
else
serial8250_do_set_mctrl(port, mctrl);
}
static void serial8250_break_ctl(struct uart_port *port, int break_state)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
else
up->lcr &= ~UART_LCR_SBC;
serial_port_out(port, UART_LCR, up->lcr);
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
}
/*
* Wait for transmitter & holding register to empty
*/
static void wait_for_xmitr(struct uart_8250_port *up, int bits)
{
unsigned int status, tmout = 10000;
/* Wait up to 10ms for the character(s) to be sent. */
for (;;) {
status = serial_in(up, UART_LSR);
up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
if ((status & bits) == bits)
break;
if (--tmout == 0)
break;
udelay(1);
}
/* 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;
if (msr & UART_MSR_CTS)
break;
udelay(1);
touch_nmi_watchdog();
}
}
}
#ifdef CONFIG_CONSOLE_POLL
/*
* Console polling routines for writing and reading from the uart while
* in an interrupt or debug context.
*/
static int serial8250_get_poll_char(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char lsr;
int status;
serial8250_rpm_get(up);
lsr = serial_port_in(port, UART_LSR);
if (!(lsr & UART_LSR_DR)) {
status = NO_POLL_CHAR;
goto out;
}
status = serial_port_in(port, UART_RX);
out:
serial8250_rpm_put(up);
return status;
}
static void serial8250_put_poll_char(struct uart_port *port,
unsigned char c)
{
unsigned int ier;
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get(up);
/*
* First save the IER then disable the interrupts
*/
ier = serial_port_in(port, UART_IER);
if (up->capabilities & UART_CAP_UUE)
serial_port_out(port, UART_IER, UART_IER_UUE);
else
serial_port_out(port, UART_IER, 0);
wait_for_xmitr(up, BOTH_EMPTY);
/*
* Send the character out.
*/
serial_port_out(port, UART_TX, c);
/*
* Finally, wait for transmitter to become empty
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
serial_port_out(port, UART_IER, ier);
serial8250_rpm_put(up);
}
#endif /* CONFIG_CONSOLE_POLL */
int serial8250_do_startup(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
unsigned char lsr, iir;
int retval;
if (port->type == PORT_8250_CIR)
return -ENODEV;
if (!port->fifosize)
port->fifosize = uart_config[port->type].fifo_size;
if (!up->tx_loadsz)
up->tx_loadsz = uart_config[port->type].tx_loadsz;
if (!up->capabilities)
up->capabilities = uart_config[port->type].flags;
up->mcr = 0;
if (port->iotype != up->cur_iotype)
set_io_from_upio(port);
serial8250_rpm_get(up);
if (port->type == PORT_16C950) {
/* Wake up and initialize UART */
up->acr = 0;
serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
serial_port_out(port, UART_EFR, UART_EFR_ECB);
serial_port_out(port, UART_IER, 0);
serial_port_out(port, UART_LCR, 0);
serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
serial_port_out(port, UART_EFR, UART_EFR_ECB);
serial_port_out(port, UART_LCR, 0);
}
#ifdef CONFIG_SERIAL_8250_RSA
/*
* If this is an RSA port, see if we can kick it up to the
* higher speed clock.
*/
enable_rsa(up);
#endif
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
*/
serial8250_clear_fifos(up);
/*
* Clear the interrupt registers.
*/
serial_port_in(port, UART_LSR);
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
/*
* At this point, there's no way the LSR could still be 0xff;
* if it is, then bail out, because there's likely no UART
* here.
*/
if (!(port->flags & UPF_BUGGY_UART) &&
(serial_port_in(port, UART_LSR) == 0xff)) {
printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
serial_index(port));
retval = -ENODEV;
goto out;
}
/*
* For a XR16C850, we need to set the trigger levels
*/
if (port->type == PORT_16850) {
unsigned char fctr;
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
serial_port_out(port, UART_FCTR,
fctr | UART_FCTR_TRGD | UART_FCTR_RX);
serial_port_out(port, UART_TRG, UART_TRG_96);
serial_port_out(port, UART_FCTR,
fctr | UART_FCTR_TRGD | UART_FCTR_TX);
serial_port_out(port, UART_TRG, UART_TRG_96);
serial_port_out(port, UART_LCR, 0);
}
if (port->irq) {
unsigned char iir1;
/*
* Test for UARTs that do not reassert THRE when the
* transmitter is idle and the interrupt has already
* been cleared. Real 16550s should always reassert
* this interrupt whenever the transmitter is idle and
* the interrupt is enabled. Delays are necessary to
* allow register changes to become visible.
*/
spin_lock_irqsave(&port->lock, flags);
if (up->port.irqflags & IRQF_SHARED)
disable_irq_nosync(port->irq);
wait_for_xmitr(up, UART_LSR_THRE);
serial_port_out_sync(port, UART_IER, UART_IER_THRI);
udelay(1); /* allow THRE to set */
iir1 = serial_port_in(port, UART_IIR);
serial_port_out(port, UART_IER, 0);
serial_port_out_sync(port, UART_IER, UART_IER_THRI);
udelay(1); /* allow a working UART time to re-assert THRE */
iir = serial_port_in(port, UART_IIR);
serial_port_out(port, UART_IER, 0);
if (port->irqflags & IRQF_SHARED)
enable_irq(port->irq);
spin_unlock_irqrestore(&port->lock, flags);
/*
* If the interrupt is not reasserted, or we otherwise
* don't trust the iir, setup a timer to kick the UART
* on a regular basis.
*/
if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
up->port.flags & UPF_BUG_THRE) {
up->bugs |= UART_BUG_THRE;
}
}
retval = up->ops->setup_irq(up);
if (retval)
goto out;
/*
* Now, initialize the UART
*/
serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
spin_lock_irqsave(&port->lock, flags);
if (up->port.flags & UPF_FOURPORT) {
if (!up->port.irq)
up->port.mctrl |= TIOCM_OUT1;
} else
/*
* Most PC uarts need OUT2 raised to enable interrupts.
*/
if (port->irq)
up->port.mctrl |= TIOCM_OUT2;
serial8250_set_mctrl(port, port->mctrl);
/* Serial over Lan (SoL) hack:
Intel 8257x Gigabit ethernet chips have a
16550 emulation, to be used for Serial Over Lan.
Those chips take a longer time than a normal
serial device to signalize that a transmission
data was queued. Due to that, the above test generally
fails. One solution would be to delay the reading of
iir. However, this is not reliable, since the timeout
is variable. So, let's just don't test if we receive
TX irq. This way, we'll never enable UART_BUG_TXEN.
*/
if (up->port.flags & UPF_NO_TXEN_TEST)
goto dont_test_tx_en;
/*
* Do a quick test to see if we receive an
* interrupt when we enable the TX irq.
*/
serial_port_out(port, UART_IER, UART_IER_THRI);
lsr = serial_port_in(port, UART_LSR);
iir = serial_port_in(port, UART_IIR);
serial_port_out(port, UART_IER, 0);
if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
if (!(up->bugs & UART_BUG_TXEN)) {
up->bugs |= UART_BUG_TXEN;
pr_debug("ttyS%d - enabling bad tx status workarounds\n",
serial_index(port));
}
} else {
up->bugs &= ~UART_BUG_TXEN;
}
dont_test_tx_en:
spin_unlock_irqrestore(&port->lock, flags);
/*
* Clear the interrupt registers again for luck, and clear the
* saved flags to avoid getting false values from polling
* routines or the previous session.
*/
serial_port_in(port, UART_LSR);
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
up->lsr_saved_flags = 0;
up->msr_saved_flags = 0;
/*
* Request DMA channels for both RX and TX.
*/
if (up->dma) {
retval = serial8250_request_dma(up);
if (retval) {
pr_warn_ratelimited("ttyS%d - failed to request DMA\n",
serial_index(port));
up->dma = NULL;
}
}
/*
* Finally, enable interrupts. Note: Modem status interrupts
* are set via set_termios(), which will be occurring imminently
* anyway, so we don't enable them here.
*/
up->ier = UART_IER_RLSI | UART_IER_RDI;
serial_port_out(port, UART_IER, up->ier);
if (port->flags & UPF_FOURPORT) {
unsigned int icp;
/*
* Enable interrupts on the AST Fourport board
*/
icp = (port->iobase & 0xfe0) | 0x01f;
outb_p(0x80, icp);
inb_p(icp);
}
retval = 0;
out:
serial8250_rpm_put(up);
return retval;
}
EXPORT_SYMBOL_GPL(serial8250_do_startup);
static int serial8250_startup(struct uart_port *port)
{
if (port->startup)
return port->startup(port);
return serial8250_do_startup(port);
}
void serial8250_do_shutdown(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
serial8250_rpm_get(up);
/*
* Disable interrupts from this port
*/
up->ier = 0;
serial_port_out(port, UART_IER, 0);
if (up->dma)
serial8250_release_dma(up);
spin_lock_irqsave(&port->lock, flags);
if (port->flags & UPF_FOURPORT) {
/* reset interrupts on the AST Fourport board */
inb((port->iobase & 0xfe0) | 0x1f);
port->mctrl |= TIOCM_OUT1;
} else
port->mctrl &= ~TIOCM_OUT2;
serial8250_set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
/*
* Disable break condition and FIFOs
*/
serial_port_out(port, UART_LCR,
serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
serial8250_clear_fifos(up);
#ifdef CONFIG_SERIAL_8250_RSA
/*
* Reset the RSA board back to 115kbps compat mode.
*/
disable_rsa(up);
#endif
/*
* Read data port to reset things, and then unlink from
* the IRQ chain.
*/
serial_port_in(port, UART_RX);
serial8250_rpm_put(up);
up->ops->release_irq(up);
}
EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
static void serial8250_shutdown(struct uart_port *port)
{
if (port->shutdown)
port->shutdown(port);
else
serial8250_do_shutdown(port);
}
/*
* XR17V35x UARTs have an extra fractional divisor register (DLD)
* Calculate divisor with extra 4-bit fractional portion
*/
static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up,
unsigned int baud,
unsigned int *frac)
{
struct uart_port *port = &up->port;
unsigned int quot_16;
quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud);
*frac = quot_16 & 0x0f;
return quot_16 >> 4;
}
static unsigned int serial8250_get_divisor(struct uart_8250_port *up,
unsigned int baud,
unsigned int *frac)
{
struct uart_port *port = &up->port;
unsigned int quot;
/*
* Handle magic divisors for baud rates above baud_base on
* SMSC SuperIO chips.
*
*/
if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
baud == (port->uartclk/4))
quot = 0x8001;
else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
baud == (port->uartclk/8))
quot = 0x8002;
else if (up->port.type == PORT_XR17V35X)
quot = xr17v35x_get_divisor(up, baud, frac);
else
quot = uart_get_divisor(port, baud);
/*
* Oxford Semi 952 rev B workaround
*/
if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
quot++;
return quot;
}
static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
tcflag_t c_cflag)
{
unsigned char cval;
switch (c_cflag & CSIZE) {
case CS5:
cval = UART_LCR_WLEN5;
break;
case CS6:
cval = UART_LCR_WLEN6;
break;
case CS7:
cval = UART_LCR_WLEN7;
break;
default:
case CS8:
cval = UART_LCR_WLEN8;
break;
}
if (c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
if (c_cflag & PARENB) {
cval |= UART_LCR_PARITY;
if (up->bugs & UART_BUG_PARITY)
up->fifo_bug = true;
}
if (!(c_cflag & PARODD))
cval |= UART_LCR_EPAR;
#ifdef CMSPAR
if (c_cflag & CMSPAR)
cval |= UART_LCR_SPAR;
#endif
return cval;
}
static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
unsigned int quot, unsigned int quot_frac)
{
struct uart_8250_port *up = up_to_u8250p(port);
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
if (is_omap1510_8250(up)) {
if (baud == 115200) {
quot = 1;
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
} else
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
}
/*
* For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
* otherwise just set DLAB
*/
if (up->capabilities & UART_NATSEMI)
serial_port_out(port, UART_LCR, 0xe0);
else
serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
serial_dl_write(up, quot);
/* XR17V35x UARTs have an extra fractional divisor register (DLD) */
if (up->port.type == PORT_XR17V35X)
serial_port_out(port, 0x2, quot_frac);
}
void
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char cval;
unsigned long flags;
unsigned int baud, quot, frac = 0;
cval = serial8250_compute_lcr(up, termios->c_cflag);
/*
* Ask the core to calculate the divisor for us.
*/
baud = uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / 0xffff,
port->uartclk / 16);
quot = serial8250_get_divisor(up, baud, &frac);
/*
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
up->lcr = cval; /* Save computed LCR */
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
/* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
if ((baud < 2400 && !up->dma) || up->fifo_bug) {
up->fcr &= ~UART_FCR_TRIGGER_MASK;
up->fcr |= UART_FCR_TRIGGER_1;
}
}
/*
* MCR-based auto flow control. When AFE is enabled, RTS will be
* deasserted when the receive FIFO contains more characters than
* the trigger, or the MCR RTS bit is cleared. In the case where
* the remote UART is not using CTS auto flow control, we must
* have sufficient FIFO entries for the latency of the remote
* UART to respond. IOW, at least 32 bytes of FIFO.
*/
if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
up->mcr &= ~UART_MCR_AFE;
if (termios->c_cflag & CRTSCTS)
up->mcr |= UART_MCR_AFE;
}
/*
* Update the per-port timeout.
*/
uart_update_timeout(port, termios->c_cflag, baud);
port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
if (termios->c_iflag & INPCK)
port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
port->read_status_mask |= UART_LSR_BI;
/*
* Characteres to ignore
*/
port->ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
if (termios->c_iflag & IGNBRK) {
port->ignore_status_mask |= UART_LSR_BI;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= UART_LSR_OE;
}
/*
* ignore all characters if CREAD is not set
*/
if ((termios->c_cflag & CREAD) == 0)
port->ignore_status_mask |= UART_LSR_DR;
/*
* CTS flow control flag and modem status interrupts
*/
up->ier &= ~UART_IER_MSI;
if (!(up->bugs & UART_BUG_NOMSR) &&
UART_ENABLE_MS(&up->port, termios->c_cflag))
up->ier |= UART_IER_MSI;
if (up->capabilities & UART_CAP_UUE)
up->ier |= UART_IER_UUE;
if (up->capabilities & UART_CAP_RTOIE)
up->ier |= UART_IER_RTOIE;
serial_port_out(port, UART_IER, up->ier);
if (up->capabilities & UART_CAP_EFR) {
unsigned char efr = 0;
/*
* TI16C752/Startech hardware flow control. FIXME:
* - TI16C752 requires control thresholds to be set.
* - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
*/
if (termios->c_cflag & CRTSCTS)
efr |= UART_EFR_CTS;
serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
if (port->flags & UPF_EXAR_EFR)
serial_port_out(port, UART_XR_EFR, efr);
else
serial_port_out(port, UART_EFR, efr);
}
serial8250_set_divisor(port, baud, quot, frac);
/* /*
* LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR * Must disable interrupts or else we risk racing with the interrupt
* is written without DLAB set, this mode will be disabled. * based handler.
*/ */
if (port->type == PORT_16750) if (up->port.irq) {
serial_port_out(port, UART_FCR, up->fcr); ier = serial_in(up, UART_IER);
serial_out(up, UART_IER, 0);
serial_port_out(port, UART_LCR, up->lcr); /* reset DLAB */
if (port->type != PORT_16750) {
/* emulated UARTs (Lucent Venus 167x) need two steps */
if (up->fcr & UART_FCR_ENABLE_FIFO)
serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
}
serial8250_set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
/* Don't rewrite B0 */
if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud);
}
EXPORT_SYMBOL(serial8250_do_set_termios);
static void
serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
if (port->set_termios)
port->set_termios(port, termios, old);
else
serial8250_do_set_termios(port, termios, old);
}
static void
serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
{
if (termios->c_line == N_PPS) {
port->flags |= UPF_HARDPPS_CD;
spin_lock_irq(&port->lock);
serial8250_enable_ms(port);
spin_unlock_irq(&port->lock);
} else {
port->flags &= ~UPF_HARDPPS_CD;
if (!UART_ENABLE_MS(port, termios->c_cflag)) {
spin_lock_irq(&port->lock);
serial8250_disable_ms(port);
spin_unlock_irq(&port->lock);
}
} }
}
iir = serial_in(up, UART_IIR);
void serial8250_do_pm(struct uart_port *port, unsigned int state, /*
unsigned int oldstate) * This should be a safe test for anyone who doesn't trust the
{ * IIR bits on their UART, but it's specifically designed for
struct uart_8250_port *p = up_to_u8250p(port); * the "Diva" UART used on the management processor on many HP
* ia64 and parisc boxes.
*/
lsr = serial_in(up, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
(!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
(lsr & UART_LSR_THRE)) {
iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
iir |= UART_IIR_THRI;
}
serial8250_set_sleep(p, state != 0); if (!(iir & UART_IIR_NO_INT))
} serial8250_tx_chars(up);
EXPORT_SYMBOL(serial8250_do_pm);
static void if (up->port.irq)
serial8250_pm(struct uart_port *port, unsigned int state, serial_out(up, UART_IER, ier);
unsigned int oldstate)
{
if (port->pm)
port->pm(port, state, oldstate);
else
serial8250_do_pm(port, state, oldstate);
}
static unsigned int serial8250_port_size(struct uart_8250_port *pt) spin_unlock_irqrestore(&up->port.lock, flags);
{
if (pt->port.mapsize)
return pt->port.mapsize;
if (pt->port.iotype == UPIO_AU) {
if (pt->port.type == PORT_RT2880)
return 0x100;
return 0x1000;
}
if (is_omap1_8250(pt))
return 0x16 << pt->port.regshift;
return 8 << pt->port.regshift; /* Standard timer interval plus 0.2s to keep the port running */
mod_timer(&up->timer,
jiffies + uart_poll_timeout(&up->port) + HZ / 5);
} }
/* static int univ8250_setup_irq(struct uart_8250_port *up)
* Resource handling.
*/
static int serial8250_request_std_resource(struct uart_8250_port *up)
{ {
unsigned int size = serial8250_port_size(up);
struct uart_port *port = &up->port; struct uart_port *port = &up->port;
int ret = 0; int retval = 0;
switch (port->iotype) { /*
case UPIO_AU: * The above check will only give an accurate result the first time
case UPIO_TSI: * the port is opened so this value needs to be preserved.
case UPIO_MEM32: */
case UPIO_MEM32BE: if (up->bugs & UART_BUG_THRE) {
case UPIO_MEM: pr_debug("ttyS%d - using backup timer\n", serial_index(port));
if (!port->mapbase)
break;
if (!request_mem_region(port->mapbase, size, "serial")) { up->timer.function = serial8250_backup_timeout;
ret = -EBUSY; up->timer.data = (unsigned long)up;
break; mod_timer(&up->timer, jiffies +
} uart_poll_timeout(port) + HZ / 5);
}
if (port->flags & UPF_IOREMAP) { /*
port->membase = ioremap_nocache(port->mapbase, size); * If the "interrupt" for this port doesn't correspond with any
if (!port->membase) { * hardware interrupt, we use a timer-based system. The original
release_mem_region(port->mapbase, size); * driver used to do this with IRQ0.
ret = -ENOMEM; */
} if (!port->irq) {
} up->timer.data = (unsigned long)up;
break; mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
} else
retval = serial_link_irq_chain(up);
case UPIO_HUB6: return retval;
case UPIO_PORT:
if (!request_region(port->iobase, size, "serial"))
ret = -EBUSY;
break;
}
return ret;
} }
static void serial8250_release_std_resource(struct uart_8250_port *up) static void univ8250_release_irq(struct uart_8250_port *up)
{ {
unsigned int size = serial8250_port_size(up);
struct uart_port *port = &up->port; struct uart_port *port = &up->port;
switch (port->iotype) { del_timer_sync(&up->timer);
case UPIO_AU: up->timer.function = serial8250_timeout;
case UPIO_TSI: if (port->irq)
case UPIO_MEM32: serial_unlink_irq_chain(up);
case UPIO_MEM32BE:
case UPIO_MEM:
if (!port->mapbase)
break;
if (port->flags & UPF_IOREMAP) {
iounmap(port->membase);
port->membase = NULL;
}
release_mem_region(port->mapbase, size);
break;
case UPIO_HUB6:
case UPIO_PORT:
release_region(port->iobase, size);
break;
}
} }
#ifdef CONFIG_SERIAL_8250_RSA #ifdef CONFIG_SERIAL_8250_RSA
...@@ -2848,259 +396,6 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up) ...@@ -2848,259 +396,6 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
} }
#endif #endif
static void serial8250_release_port(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_release_std_resource(up);
}
static int serial8250_request_port(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
int ret;
if (port->type == PORT_8250_CIR)
return -ENODEV;
ret = serial8250_request_std_resource(up);
return ret;
}
static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
unsigned char bytes;
bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
return bytes ? bytes : -EOPNOTSUPP;
}
static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
int i;
if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
return -EOPNOTSUPP;
for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
if (bytes < conf_type->rxtrig_bytes[i])
/* Use the nearest lower value */
return (--i) << UART_FCR_R_TRIG_SHIFT;
}
return UART_FCR_R_TRIG_11;
}
static int do_get_rxtrig(struct tty_port *port)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
struct uart_8250_port *up =
container_of(uport, struct uart_8250_port, port);
if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
return -EINVAL;
return fcr_get_rxtrig_bytes(up);
}
static int do_serial8250_get_rxtrig(struct tty_port *port)
{
int rxtrig_bytes;
mutex_lock(&port->mutex);
rxtrig_bytes = do_get_rxtrig(port);
mutex_unlock(&port->mutex);
return rxtrig_bytes;
}
static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tty_port *port = dev_get_drvdata(dev);
int rxtrig_bytes;
rxtrig_bytes = do_serial8250_get_rxtrig(port);
if (rxtrig_bytes < 0)
return rxtrig_bytes;
return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
}
static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
struct uart_8250_port *up =
container_of(uport, struct uart_8250_port, port);
int rxtrig;
if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
up->fifo_bug)
return -EINVAL;
rxtrig = bytes_to_fcr_rxtrig(up, bytes);
if (rxtrig < 0)
return rxtrig;
serial8250_clear_fifos(up);
up->fcr &= ~UART_FCR_TRIGGER_MASK;
up->fcr |= (unsigned char)rxtrig;
serial_out(up, UART_FCR, up->fcr);
return 0;
}
static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
{
int ret;
mutex_lock(&port->mutex);
ret = do_set_rxtrig(port, bytes);
mutex_unlock(&port->mutex);
return ret;
}
static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct tty_port *port = dev_get_drvdata(dev);
unsigned char bytes;
int ret;
if (!count)
return -EINVAL;
ret = kstrtou8(buf, 10, &bytes);
if (ret < 0)
return ret;
ret = do_serial8250_set_rxtrig(port, bytes);
if (ret < 0)
return ret;
return count;
}
static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
serial8250_get_attr_rx_trig_bytes,
serial8250_set_attr_rx_trig_bytes);
static struct attribute *serial8250_dev_attrs[] = {
&dev_attr_rx_trig_bytes.attr,
NULL,
};
static struct attribute_group serial8250_dev_attr_group = {
.attrs = serial8250_dev_attrs,
};
static void register_dev_spec_attr_grp(struct uart_8250_port *up)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
if (conf_type->rxtrig_bytes[0])
up->port.attr_group = &serial8250_dev_attr_group;
}
static void serial8250_config_port(struct uart_port *port, int flags)
{
struct uart_8250_port *up = up_to_u8250p(port);
int ret;
if (port->type == PORT_8250_CIR)
return;
/*
* Find the region that we can probe for. This in turn
* tells us whether we can probe for the type of port.
*/
ret = serial8250_request_std_resource(up);
if (ret < 0)
return;
if (port->iotype != up->cur_iotype)
set_io_from_upio(port);
if (flags & UART_CONFIG_TYPE)
autoconfig(up);
/* if access method is AU, it is a 16550 with a quirk */
if (port->type == PORT_16550A && port->iotype == UPIO_AU)
up->bugs |= UART_BUG_NOMSR;
/* HW bugs may trigger IRQ while IIR == NO_INT */
if (port->type == PORT_TEGRA)
up->bugs |= UART_BUG_NOMSR;
if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
autoconfig_irq(up);
if (port->type == PORT_UNKNOWN)
serial8250_release_std_resource(up);
/* Fixme: probably not the best place for this */
if ((port->type == PORT_XR17V35X) ||
(port->type == PORT_XR17D15X))
port->handle_irq = exar_handle_irq;
register_dev_spec_attr_grp(up);
up->fcr = uart_config[up->port.type].fcr;
}
static int
serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
{
if (ser->irq >= nr_irqs || ser->irq < 0 ||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
ser->type == PORT_STARTECH)
return -EINVAL;
return 0;
}
static const char *
serial8250_type(struct uart_port *port)
{
int type = port->type;
if (type >= ARRAY_SIZE(uart_config))
type = 0;
return uart_config[type].name;
}
static const struct uart_ops serial8250_pops = {
.tx_empty = serial8250_tx_empty,
.set_mctrl = serial8250_set_mctrl,
.get_mctrl = serial8250_get_mctrl,
.stop_tx = serial8250_stop_tx,
.start_tx = serial8250_start_tx,
.throttle = serial8250_throttle,
.unthrottle = serial8250_unthrottle,
.stop_rx = serial8250_stop_rx,
.enable_ms = serial8250_enable_ms,
.break_ctl = serial8250_break_ctl,
.startup = serial8250_startup,
.shutdown = serial8250_shutdown,
.set_termios = serial8250_set_termios,
.set_ldisc = serial8250_set_ldisc,
.pm = serial8250_pm,
.type = serial8250_type,
.release_port = serial8250_release_port,
.request_port = serial8250_request_port,
.config_port = serial8250_config_port,
.verify_port = serial8250_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = serial8250_get_poll_char,
.poll_put_char = serial8250_put_poll_char,
#endif
};
static const struct uart_ops *base_ops; static const struct uart_ops *base_ops;
static struct uart_ops univ8250_port_ops; static struct uart_ops univ8250_port_ops;
...@@ -3139,42 +434,6 @@ void serial8250_set_isa_configurator( ...@@ -3139,42 +434,6 @@ void serial8250_set_isa_configurator(
} }
EXPORT_SYMBOL(serial8250_set_isa_configurator); EXPORT_SYMBOL(serial8250_set_isa_configurator);
static void serial8250_init_port(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
spin_lock_init(&port->lock);
port->ops = &serial8250_pops;
up->cur_iotype = 0xFF;
}
static void serial8250_set_defaults(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
if (up->port.flags & UPF_FIXED_TYPE) {
unsigned int type = up->port.type;
if (!up->port.fifosize)
up->port.fifosize = uart_config[type].fifo_size;
if (!up->tx_loadsz)
up->tx_loadsz = uart_config[type].tx_loadsz;
if (!up->capabilities)
up->capabilities = uart_config[type].flags;
}
set_io_from_upio(port);
/* default dma handlers */
if (up->dma) {
if (!up->dma->tx_dma)
up->dma->tx_dma = serial8250_tx_dma;
if (!up->dma->rx_dma)
up->dma->rx_dma = serial8250_rx_dma;
}
}
#ifdef CONFIG_SERIAL_8250_RSA #ifdef CONFIG_SERIAL_8250_RSA
static void univ8250_config_port(struct uart_port *port, int flags) static void univ8250_config_port(struct uart_port *port, int flags)
...@@ -3324,94 +583,6 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) ...@@ -3324,94 +583,6 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
#ifdef CONFIG_SERIAL_8250_CONSOLE #ifdef CONFIG_SERIAL_8250_CONSOLE
static void serial8250_console_putchar(struct uart_port *port, int ch)
{
struct uart_8250_port *up = up_to_u8250p(port);
wait_for_xmitr(up, UART_LSR_THRE);
serial_port_out(port, UART_TX, ch);
}
/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
*
* The console_lock must be held when we get here.
*/
static void serial8250_console_write(struct uart_8250_port *up, const char *s,
unsigned int count)
{
struct uart_port *port = &up->port;
unsigned long flags;
unsigned int ier;
int locked = 1;
touch_nmi_watchdog();
serial8250_rpm_get(up);
if (port->sysrq)
locked = 0;
else if (oops_in_progress)
locked = spin_trylock_irqsave(&port->lock, flags);
else
spin_lock_irqsave(&port->lock, flags);
/*
* First save the IER then disable the interrupts
*/
ier = serial_port_in(port, UART_IER);
if (up->capabilities & UART_CAP_UUE)
serial_port_out(port, UART_IER, UART_IER_UUE);
else
serial_port_out(port, UART_IER, 0);
/* check scratch reg to see if port powered off during system sleep */
if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
struct ktermios termios;
unsigned int baud, quot, frac = 0;
termios.c_cflag = port->cons->cflag;
if (port->state->port.tty && termios.c_cflag == 0)
termios.c_cflag = port->state->port.tty->termios.c_cflag;
baud = uart_get_baud_rate(port, &termios, NULL,
port->uartclk / 16 / 0xffff,
port->uartclk / 16);
quot = serial8250_get_divisor(up, baud, &frac);
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);
up->canary = 0;
}
uart_console_write(port, s, count, serial8250_console_putchar);
/*
* Finally, wait for transmitter to become empty
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
serial_port_out(port, UART_IER, ier);
/*
* The receive handling will happen properly because the
* receive ready bit will still be set; it is not cleared
* on read. However, modem control will not, we must
* call it if we have saved something in the saved flags
* while processing with interrupts off.
*/
if (up->msr_saved_flags)
serial8250_modem_status(up);
if (locked)
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
}
static void univ8250_console_write(struct console *co, const char *s, static void univ8250_console_write(struct console *co, const char *s,
unsigned int count) unsigned int count)
{ {
...@@ -3420,39 +591,6 @@ static void univ8250_console_write(struct console *co, const char *s, ...@@ -3420,39 +591,6 @@ static void univ8250_console_write(struct console *co, const char *s,
serial8250_console_write(up, s, count); serial8250_console_write(up, s, count);
} }
static unsigned int probe_baud(struct uart_port *port)
{
unsigned char lcr, dll, dlm;
unsigned int quot;
lcr = serial_port_in(port, UART_LCR);
serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
dll = serial_port_in(port, UART_DLL);
dlm = serial_port_in(port, UART_DLM);
serial_port_out(port, UART_LCR, lcr);
quot = (dlm << 8) | dll;
return (port->uartclk / 16) / quot;
}
static int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
{
int baud = 9600;
int bits = 8;
int parity = 'n';
int flow = 'n';
if (!port->iobase && !port->membase)
return -ENODEV;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else if (probe)
baud = probe_baud(port);
return uart_set_options(port, port->cons, baud, parity, bits, flow);
}
static int univ8250_console_setup(struct console *co, char *options) static int univ8250_console_setup(struct console *co, char *options)
{ {
struct uart_port *port; struct uart_port *port;
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
struct dw8250_data { struct dw8250_data {
u8 usr_reg; u8 usr_reg;
int last_mcr;
int line; int line;
int msr_mask_on; int msr_mask_on;
int msr_mask_off; int msr_mask_off;
...@@ -76,12 +75,6 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) ...@@ -76,12 +75,6 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
{ {
struct dw8250_data *d = p->private_data; struct dw8250_data *d = p->private_data;
/* If reading MSR, report CTS asserted when auto-CTS/RTS enabled */
if (offset == UART_MSR && d->last_mcr & UART_MCR_AFE) {
value |= UART_MSR_CTS;
value &= ~UART_MSR_DCTS;
}
/* Override any modem control signals if needed */ /* Override any modem control signals if needed */
if (offset == UART_MSR) { if (offset == UART_MSR) {
value |= d->msr_mask_on; value |= d->msr_mask_on;
...@@ -101,11 +94,6 @@ static void dw8250_force_idle(struct uart_port *p) ...@@ -101,11 +94,6 @@ static void dw8250_force_idle(struct uart_port *p)
static void dw8250_serial_out(struct uart_port *p, int offset, int value) static void dw8250_serial_out(struct uart_port *p, int offset, int value)
{ {
struct dw8250_data *d = p->private_data;
if (offset == UART_MCR)
d->last_mcr = value;
writeb(value, p->membase + (offset << p->regshift)); writeb(value, p->membase + (offset << p->regshift));
/* Make sure LCR write wasn't ignored */ /* Make sure LCR write wasn't ignored */
...@@ -144,11 +132,6 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset) ...@@ -144,11 +132,6 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset)
static void dw8250_serial_outq(struct uart_port *p, int offset, int value) static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
{ {
struct dw8250_data *d = p->private_data;
if (offset == UART_MCR)
d->last_mcr = value;
value &= 0xff; value &= 0xff;
__raw_writeq(value, p->membase + (offset << p->regshift)); __raw_writeq(value, p->membase + (offset << p->regshift));
/* Read back to ensure register write ordering. */ /* Read back to ensure register write ordering. */
...@@ -175,11 +158,6 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value) ...@@ -175,11 +158,6 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
static void dw8250_serial_out32(struct uart_port *p, int offset, int value) static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
{ {
struct dw8250_data *d = p->private_data;
if (offset == UART_MCR)
d->last_mcr = value;
writel(value, p->membase + (offset << p->regshift)); writel(value, p->membase + (offset << p->regshift));
/* Make sure LCR write wasn't ignored */ /* Make sure LCR write wasn't ignored */
...@@ -257,6 +235,11 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, ...@@ -257,6 +235,11 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
if (!ret) if (!ret)
p->uartclk = rate; p->uartclk = rate;
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
out: out:
serial8250_do_set_termios(p, termios, old); serial8250_do_set_termios(p, termios, old);
} }
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/serial.h> #include <asm/serial.h>
unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset) static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
{ {
switch (port->iotype) { switch (port->iotype) {
case UPIO_MEM: case UPIO_MEM:
...@@ -51,7 +51,7 @@ unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offse ...@@ -51,7 +51,7 @@ unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offse
} }
} }
void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value) static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
{ {
switch (port->iotype) { switch (port->iotype) {
case UPIO_MEM: case UPIO_MEM:
......
...@@ -17,18 +17,19 @@ ...@@ -17,18 +17,19 @@
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include "8250.h" #include "8250.h"
#define ADDR_PORT 0x4E #define ADDR_PORT 0
#define DATA_PORT 0x4F #define DATA_PORT 1
#define ENTRY_KEY 0x77
#define EXIT_KEY 0xAA #define EXIT_KEY 0xAA
#define CHIP_ID1 0x20 #define CHIP_ID1 0x20
#define CHIP_ID1_VAL 0x02
#define CHIP_ID2 0x21 #define CHIP_ID2 0x21
#define CHIP_ID2_VAL 0x16 #define CHIP_ID_0 0x1602
#define CHIP_ID_1 0x0501
#define VENDOR_ID1 0x23 #define VENDOR_ID1 0x23
#define VENDOR_ID1_VAL 0x19 #define VENDOR_ID1_VAL 0x19
#define VENDOR_ID2 0x24 #define VENDOR_ID2 0x24
#define VENDOR_ID2_VAL 0x34 #define VENDOR_ID2_VAL 0x34
#define IO_ADDR1 0x61
#define IO_ADDR2 0x60
#define LDN 0x7 #define LDN 0x7
#define RS485 0xF0 #define RS485 0xF0
...@@ -39,51 +40,49 @@ ...@@ -39,51 +40,49 @@
#define DRIVER_NAME "8250_fintek" #define DRIVER_NAME "8250_fintek"
static int fintek_8250_enter_key(void){ struct fintek_8250 {
u16 base_port;
u8 index;
u8 key;
long line;
};
static int fintek_8250_enter_key(u16 base_port, u8 key)
{
if (!request_muxed_region(ADDR_PORT, 2, DRIVER_NAME)) if (!request_muxed_region(base_port, 2, DRIVER_NAME))
return -EBUSY; return -EBUSY;
outb(ENTRY_KEY, ADDR_PORT); outb(key, base_port + ADDR_PORT);
outb(ENTRY_KEY, ADDR_PORT); outb(key, base_port + ADDR_PORT);
return 0; return 0;
} }
static void fintek_8250_exit_key(void){ static void fintek_8250_exit_key(u16 base_port)
outb(EXIT_KEY, ADDR_PORT);
release_region(ADDR_PORT, 2);
}
static int fintek_8250_get_index(resource_size_t base_addr)
{ {
resource_size_t base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
int i;
for (i = 0; i < ARRAY_SIZE(base); i++)
if (base_addr == base[i])
return i;
return -ENODEV; outb(EXIT_KEY, base_port + ADDR_PORT);
release_region(base_port + ADDR_PORT, 2);
} }
static int fintek_8250_check_id(void) static int fintek_8250_check_id(u16 base_port)
{ {
u16 chip;
outb(CHIP_ID1, ADDR_PORT); outb(VENDOR_ID1, base_port + ADDR_PORT);
if (inb(DATA_PORT) != CHIP_ID1_VAL) if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL)
return -ENODEV; return -ENODEV;
outb(CHIP_ID2, ADDR_PORT); outb(VENDOR_ID2, base_port + ADDR_PORT);
if (inb(DATA_PORT) != CHIP_ID2_VAL) if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL)
return -ENODEV; return -ENODEV;
outb(VENDOR_ID1, ADDR_PORT); outb(CHIP_ID1, base_port + ADDR_PORT);
if (inb(DATA_PORT) != VENDOR_ID1_VAL) chip = inb(base_port + DATA_PORT);
return -ENODEV; outb(CHIP_ID2, base_port + ADDR_PORT);
chip |= inb(base_port + DATA_PORT) << 8;
outb(VENDOR_ID2, ADDR_PORT); if (chip != CHIP_ID_0 && chip != CHIP_ID_1)
if (inb(DATA_PORT) != VENDOR_ID2_VAL)
return -ENODEV; return -ENODEV;
return 0; return 0;
...@@ -93,9 +92,9 @@ static int fintek_8250_rs485_config(struct uart_port *port, ...@@ -93,9 +92,9 @@ static int fintek_8250_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485) struct serial_rs485 *rs485)
{ {
uint8_t config = 0; uint8_t config = 0;
int index = fintek_8250_get_index(port->iobase); struct fintek_8250 *pdata = port->private_data;
if (index < 0) if (!pdata)
return -EINVAL; return -EINVAL;
if (rs485->flags & SER_RS485_ENABLED) if (rs485->flags & SER_RS485_ENABLED)
...@@ -125,44 +124,84 @@ static int fintek_8250_rs485_config(struct uart_port *port, ...@@ -125,44 +124,84 @@ static int fintek_8250_rs485_config(struct uart_port *port,
if (rs485->flags & SER_RS485_RTS_ON_SEND) if (rs485->flags & SER_RS485_RTS_ON_SEND)
config |= RTS_INVERT; config |= RTS_INVERT;
if (fintek_8250_enter_key()) if (fintek_8250_enter_key(pdata->base_port, pdata->key))
return -EBUSY; return -EBUSY;
outb(LDN, ADDR_PORT); outb(LDN, pdata->base_port + ADDR_PORT);
outb(index, DATA_PORT); outb(pdata->index, pdata->base_port + DATA_PORT);
outb(RS485, ADDR_PORT); outb(RS485, pdata->base_port + ADDR_PORT);
outb(config, DATA_PORT); outb(config, pdata->base_port + DATA_PORT);
fintek_8250_exit_key(); fintek_8250_exit_key(pdata->base_port);
port->rs485 = *rs485; port->rs485 = *rs485;
return 0; return 0;
} }
static int fintek_8250_base_port(u16 io_address, u8 *key, u8 *index)
{
static const u16 addr[] = {0x4e, 0x2e};
static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67};
int i, j, k;
for (i = 0; i < ARRAY_SIZE(addr); i++) {
for (j = 0; j < ARRAY_SIZE(keys); j++) {
if (fintek_8250_enter_key(addr[i], keys[j]))
continue;
if (fintek_8250_check_id(addr[i])) {
fintek_8250_exit_key(addr[i]);
continue;
}
for (k = 0; k < 4; k++) {
u16 aux;
outb(LDN, addr[i] + ADDR_PORT);
outb(k, addr[i] + DATA_PORT);
outb(IO_ADDR1, addr[i] + ADDR_PORT);
aux = inb(addr[i] + DATA_PORT);
outb(IO_ADDR2, addr[i] + ADDR_PORT);
aux |= inb(addr[i] + DATA_PORT) << 8;
if (aux != io_address)
continue;
fintek_8250_exit_key(addr[i]);
*key = keys[j];
*index = k;
return addr[i];
}
fintek_8250_exit_key(addr[i]);
}
}
return -ENODEV;
}
static int static int
fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{ {
int line;
struct uart_8250_port uart; struct uart_8250_port uart;
int ret; struct fintek_8250 *pdata;
int base_port;
u8 key;
u8 index;
if (!pnp_port_valid(dev, 0)) if (!pnp_port_valid(dev, 0))
return -ENODEV; return -ENODEV;
if (fintek_8250_get_index(pnp_port_start(dev, 0)) < 0) base_port = fintek_8250_base_port(pnp_port_start(dev, 0), &key, &index);
if (base_port < 0)
return -ENODEV; return -ENODEV;
/* Enable configuration registers*/ memset(&uart, 0, sizeof(uart));
if (fintek_8250_enter_key())
return -EBUSY;
/*Check ID*/ pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
ret = fintek_8250_check_id(); if (!pdata)
fintek_8250_exit_key(); return -ENOMEM;
if (ret) uart.port.private_data = pdata;
return ret;
memset(&uart, 0, sizeof(uart));
if (!pnp_irq_valid(dev, 0)) if (!pnp_irq_valid(dev, 0))
return -ENODEV; return -ENODEV;
uart.port.irq = pnp_irq(dev, 0); uart.port.irq = pnp_irq(dev, 0);
...@@ -176,40 +215,43 @@ fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) ...@@ -176,40 +215,43 @@ fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
uart.port.uartclk = 1843200; uart.port.uartclk = 1843200;
uart.port.dev = &dev->dev; uart.port.dev = &dev->dev;
line = serial8250_register_8250_port(&uart); pdata->key = key;
if (line < 0) pdata->base_port = base_port;
pdata->index = index;
pdata->line = serial8250_register_8250_port(&uart);
if (pdata->line < 0)
return -ENODEV; return -ENODEV;
pnp_set_drvdata(dev, (void *)((long)line + 1)); pnp_set_drvdata(dev, pdata);
return 0; return 0;
} }
static void fintek_8250_remove(struct pnp_dev *dev) static void fintek_8250_remove(struct pnp_dev *dev)
{ {
long line = (long)pnp_get_drvdata(dev); struct fintek_8250 *pdata = pnp_get_drvdata(dev);
if (line) if (pdata)
serial8250_unregister_port(line - 1); serial8250_unregister_port(pdata->line);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int fintek_8250_suspend(struct pnp_dev *dev, pm_message_t state) static int fintek_8250_suspend(struct pnp_dev *dev, pm_message_t state)
{ {
long line = (long)pnp_get_drvdata(dev); struct fintek_8250 *pdata = pnp_get_drvdata(dev);
if (!line) if (!pdata)
return -ENODEV; return -ENODEV;
serial8250_suspend_port(line - 1); serial8250_suspend_port(pdata->line);
return 0; return 0;
} }
static int fintek_8250_resume(struct pnp_dev *dev) static int fintek_8250_resume(struct pnp_dev *dev)
{ {
long line = (long)pnp_get_drvdata(dev); struct fintek_8250 *pdata = pnp_get_drvdata(dev);
if (!line) if (!pdata)
return -ENODEV; return -ENODEV;
serial8250_resume_port(line - 1); serial8250_resume_port(pdata->line);
return 0; return 0;
} }
#else #else
......
...@@ -252,7 +252,6 @@ MODULE_DEVICE_TABLE(of, of_match); ...@@ -252,7 +252,6 @@ MODULE_DEVICE_TABLE(of, of_match);
static struct platform_driver ingenic_uart_platform_driver = { static struct platform_driver ingenic_uart_platform_driver = {
.driver = { .driver = {
.name = "ingenic-uart", .name = "ingenic-uart",
.owner = THIS_MODULE,
.of_match_table = of_match, .of_match_table = of_match,
}, },
.probe = ingenic_uart_probe, .probe = ingenic_uart_probe,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -32,6 +33,11 @@ ...@@ -32,6 +33,11 @@
#define UART_ERRATA_i202_MDR1_ACCESS (1 << 0) #define UART_ERRATA_i202_MDR1_ACCESS (1 << 0)
#define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1) #define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1)
#define OMAP_DMA_TX_KICK (1 << 2) #define OMAP_DMA_TX_KICK (1 << 2)
/*
* See Advisory 21 in AM437x errata SPRZ408B, updated April 2015.
* The same errata is applicable to AM335x and DRA7x processors too.
*/
#define UART_ERRATA_CLOCK_DISABLE (1 << 3)
#define OMAP_UART_FCR_RX_TRIG 6 #define OMAP_UART_FCR_RX_TRIG 6
#define OMAP_UART_FCR_TX_TRIG 4 #define OMAP_UART_FCR_TX_TRIG 4
...@@ -53,6 +59,12 @@ ...@@ -53,6 +59,12 @@
#define OMAP_UART_MVR_MAJ_SHIFT 8 #define OMAP_UART_MVR_MAJ_SHIFT 8
#define OMAP_UART_MVR_MIN_MASK 0x3f #define OMAP_UART_MVR_MIN_MASK 0x3f
/* SYSC register bitmasks */
#define OMAP_UART_SYSC_SOFTRESET (1 << 1)
/* SYSS register bitmasks */
#define OMAP_UART_SYSS_RESETDONE (1 << 0)
#define UART_TI752_TLR_TX 0 #define UART_TI752_TLR_TX 0
#define UART_TI752_TLR_RX 4 #define UART_TI752_TLR_RX 4
...@@ -100,6 +112,7 @@ struct omap8250_priv { ...@@ -100,6 +112,7 @@ struct omap8250_priv {
struct work_struct qos_work; struct work_struct qos_work;
struct uart_8250_dma omap8250_dma; struct uart_8250_dma omap8250_dma;
spinlock_t rx_dma_lock; spinlock_t rx_dma_lock;
bool rx_dma_broken;
}; };
static u32 uart_read(struct uart_8250_port *up, u32 reg) static u32 uart_read(struct uart_8250_port *up, u32 reg)
...@@ -232,6 +245,15 @@ static void omap8250_update_scr(struct uart_8250_port *up, ...@@ -232,6 +245,15 @@ static void omap8250_update_scr(struct uart_8250_port *up,
serial_out(up, UART_OMAP_SCR, priv->scr); serial_out(up, UART_OMAP_SCR, priv->scr);
} }
static void omap8250_update_mdr1(struct uart_8250_port *up,
struct omap8250_priv *priv)
{
if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
omap_8250_mdr1_errataset(up, priv);
else
serial_out(up, UART_OMAP_MDR1, priv->mdr1);
}
static void omap8250_restore_regs(struct uart_8250_port *up) static void omap8250_restore_regs(struct uart_8250_port *up)
{ {
struct omap8250_priv *priv = up->port.private_data; struct omap8250_priv *priv = up->port.private_data;
...@@ -282,11 +304,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up) ...@@ -282,11 +304,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
serial_out(up, UART_XOFF1, priv->xoff); serial_out(up, UART_XOFF1, priv->xoff);
serial_out(up, UART_LCR, up->lcr); serial_out(up, UART_LCR, up->lcr);
/* need mode A for FCR */
if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS) omap8250_update_mdr1(up, priv);
omap_8250_mdr1_errataset(up, priv);
else
serial_out(up, UART_OMAP_MDR1, priv->mdr1);
up->port.ops->set_mctrl(&up->port, up->port.mctrl); up->port.ops->set_mctrl(&up->port, up->port.mctrl);
} }
...@@ -428,12 +448,9 @@ static void omap_8250_set_termios(struct uart_port *port, ...@@ -428,12 +448,9 @@ static void omap_8250_set_termios(struct uart_port *port,
priv->efr |= UART_EFR_CTS; priv->efr |= UART_EFR_CTS;
} else if (up->port.flags & UPF_SOFT_FLOW) { } else if (up->port.flags & UPF_SOFT_FLOW) {
/* /*
* IXON Flag: * OMAP rx s/w flow control is borked; the transmitter remains
* Enable XON/XOFF flow control on input. * stuck off even if rx flow control is subsequently disabled
* Receiver compares XON1, XOFF1.
*/ */
if (termios->c_iflag & IXON)
priv->efr |= OMAP_UART_SW_RX;
/* /*
* IXOFF Flag: * IXOFF Flag:
...@@ -444,15 +461,6 @@ static void omap_8250_set_termios(struct uart_port *port, ...@@ -444,15 +461,6 @@ static void omap_8250_set_termios(struct uart_port *port,
up->port.status |= UPSTAT_AUTOXOFF; up->port.status |= UPSTAT_AUTOXOFF;
priv->efr |= OMAP_UART_SW_TX; priv->efr |= OMAP_UART_SW_TX;
} }
/*
* IXANY Flag:
* Enable any character to restart output.
* Operation resumes after receiving any
* character after recognition of the XOFF character
*/
if (termios->c_iflag & IXANY)
up->mcr |= UART_MCR_XONANY;
} }
omap8250_restore_regs(up); omap8250_restore_regs(up);
...@@ -530,14 +538,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up, ...@@ -530,14 +538,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
switch (revision) { switch (revision) {
case OMAP_UART_REV_46: case OMAP_UART_REV_46:
priv->habit = UART_ERRATA_i202_MDR1_ACCESS; priv->habit |= UART_ERRATA_i202_MDR1_ACCESS;
break; break;
case OMAP_UART_REV_52: case OMAP_UART_REV_52:
priv->habit = UART_ERRATA_i202_MDR1_ACCESS | priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
OMAP_UART_WER_HAS_TX_WAKEUP; OMAP_UART_WER_HAS_TX_WAKEUP;
break; break;
case OMAP_UART_REV_63: case OMAP_UART_REV_63:
priv->habit = UART_ERRATA_i202_MDR1_ACCESS | priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
OMAP_UART_WER_HAS_TX_WAKEUP; OMAP_UART_WER_HAS_TX_WAKEUP;
break; break;
default: default:
...@@ -754,6 +762,7 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p) ...@@ -754,6 +762,7 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
struct omap8250_priv *priv = p->port.private_data; struct omap8250_priv *priv = p->port.private_data;
struct uart_8250_dma *dma = p->dma; struct uart_8250_dma *dma = p->dma;
unsigned long flags; unsigned long flags;
int ret;
spin_lock_irqsave(&priv->rx_dma_lock, flags); spin_lock_irqsave(&priv->rx_dma_lock, flags);
...@@ -762,7 +771,9 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p) ...@@ -762,7 +771,9 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
return; return;
} }
dmaengine_pause(dma->rxchan); ret = dmaengine_pause(dma->rxchan);
if (WARN_ON_ONCE(ret))
priv->rx_dma_broken = true;
spin_unlock_irqrestore(&priv->rx_dma_lock, flags); spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
...@@ -806,6 +817,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir) ...@@ -806,6 +817,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
break; break;
} }
if (priv->rx_dma_broken)
return -EINVAL;
spin_lock_irqsave(&priv->rx_dma_lock, flags); spin_lock_irqsave(&priv->rx_dma_lock, flags);
if (dma->rx_running) if (dma->rx_running)
...@@ -1054,6 +1068,20 @@ static int omap8250_no_handle_irq(struct uart_port *port) ...@@ -1054,6 +1068,20 @@ static int omap8250_no_handle_irq(struct uart_port *port)
return 0; return 0;
} }
static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
static const u8 am4372_habit = UART_ERRATA_CLOCK_DISABLE;
static const struct of_device_id omap8250_dt_ids[] = {
{ .compatible = "ti,omap2-uart" },
{ .compatible = "ti,omap3-uart" },
{ .compatible = "ti,omap4-uart" },
{ .compatible = "ti,am3352-uart", .data = &am3352_habit, },
{ .compatible = "ti,am4372-uart", .data = &am4372_habit, },
{ .compatible = "ti,dra742-uart", .data = &am4372_habit, },
{},
};
MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
static int omap8250_probe(struct platform_device *pdev) static int omap8250_probe(struct platform_device *pdev)
{ {
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -1118,11 +1146,17 @@ static int omap8250_probe(struct platform_device *pdev) ...@@ -1118,11 +1146,17 @@ static int omap8250_probe(struct platform_device *pdev)
up.port.unthrottle = omap_8250_unthrottle; up.port.unthrottle = omap_8250_unthrottle;
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
const struct of_device_id *id;
ret = of_alias_get_id(pdev->dev.of_node, "serial"); ret = of_alias_get_id(pdev->dev.of_node, "serial");
of_property_read_u32(pdev->dev.of_node, "clock-frequency", of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&up.port.uartclk); &up.port.uartclk);
priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1); priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
if (id && id->data)
priv->habit |= *(u8 *)id->data;
} else { } else {
ret = pdev->id; ret = pdev->id;
} }
...@@ -1180,6 +1214,11 @@ static int omap8250_probe(struct platform_device *pdev) ...@@ -1180,6 +1214,11 @@ static int omap8250_probe(struct platform_device *pdev)
if (of_machine_is_compatible("ti,am33xx")) if (of_machine_is_compatible("ti,am33xx"))
priv->habit |= OMAP_DMA_TX_KICK; priv->habit |= OMAP_DMA_TX_KICK;
/*
* pause is currently not supported atleast on omap-sdma
* and edma on most earlier kernels.
*/
priv->rx_dma_broken = true;
} }
} }
#endif #endif
...@@ -1257,17 +1296,46 @@ static int omap8250_lost_context(struct uart_8250_port *up) ...@@ -1257,17 +1296,46 @@ static int omap8250_lost_context(struct uart_8250_port *up)
{ {
u32 val; u32 val;
val = serial_in(up, UART_OMAP_MDR1); val = serial_in(up, UART_OMAP_SCR);
/* /*
* If we lose context, then MDR1 is set to its reset value which is * If we lose context, then SCR is set to its reset value of zero.
* UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x * After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1,
* or 16x but never to disable again. * among other bits, to never set the register back to zero again.
*/ */
if (val == UART_OMAP_MDR1_DISABLE) if (!val)
return 1; return 1;
return 0; return 0;
} }
/* TODO: in future, this should happen via API in drivers/reset/ */
static int omap8250_soft_reset(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(priv->line);
int timeout = 100;
int sysc;
int syss;
sysc = serial_in(up, UART_OMAP_SYSC);
/* softreset the UART */
sysc |= OMAP_UART_SYSC_SOFTRESET;
serial_out(up, UART_OMAP_SYSC, sysc);
/* By experiments, 1us enough for reset complete on AM335x */
do {
udelay(1);
syss = serial_in(up, UART_OMAP_SYSS);
} while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE));
if (!timeout) {
dev_err(dev, "timed out waiting for reset done\n");
return -ETIMEDOUT;
}
return 0;
}
static int omap8250_runtime_suspend(struct device *dev) static int omap8250_runtime_suspend(struct device *dev)
{ {
struct omap8250_priv *priv = dev_get_drvdata(dev); struct omap8250_priv *priv = dev_get_drvdata(dev);
...@@ -1285,7 +1353,18 @@ static int omap8250_runtime_suspend(struct device *dev) ...@@ -1285,7 +1353,18 @@ static int omap8250_runtime_suspend(struct device *dev)
return -EBUSY; return -EBUSY;
} }
if (up->dma) if (priv->habit & UART_ERRATA_CLOCK_DISABLE) {
int ret;
ret = omap8250_soft_reset(dev);
if (ret)
return ret;
/* Restore to UART mode after reset (for wakeup) */
omap8250_update_mdr1(up, priv);
}
if (up->dma && up->dma->rxchan)
omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT); omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT);
priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
...@@ -1310,7 +1389,7 @@ static int omap8250_runtime_resume(struct device *dev) ...@@ -1310,7 +1389,7 @@ static int omap8250_runtime_resume(struct device *dev)
if (loss_cntx) if (loss_cntx)
omap8250_restore_regs(up); omap8250_restore_regs(up);
if (up->dma) if (up->dma && up->dma->rxchan)
omap_8250_rx_dma(up, 0); omap_8250_rx_dma(up, 0);
priv->latency = priv->calc_latency; priv->latency = priv->calc_latency;
...@@ -1367,14 +1446,6 @@ static const struct dev_pm_ops omap8250_dev_pm_ops = { ...@@ -1367,14 +1446,6 @@ static const struct dev_pm_ops omap8250_dev_pm_ops = {
.complete = omap8250_complete, .complete = omap8250_complete,
}; };
static const struct of_device_id omap8250_dt_ids[] = {
{ .compatible = "ti,omap2-uart" },
{ .compatible = "ti,omap3-uart" },
{ .compatible = "ti,omap4-uart" },
{},
};
MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
static struct platform_driver omap8250_platform_driver = { static struct platform_driver omap8250_platform_driver = {
.driver = { .driver = {
.name = "omap8250", .name = "omap8250",
......
...@@ -1417,6 +1417,10 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios, ...@@ -1417,6 +1417,10 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE; reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
writel(reg, p->membase + BYT_PRV_CLK); writel(reg, p->membase + BYT_PRV_CLK);
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
serial8250_do_set_termios(p, termios, old); serial8250_do_set_termios(p, termios, old);
} }
...@@ -1685,11 +1689,65 @@ pci_brcm_trumanage_setup(struct serial_private *priv, ...@@ -1685,11 +1689,65 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
return ret; return ret;
} }
/* RTS will control by MCR if this bit is 0 */
#define FINTEK_RTS_CONTROL_BY_HW BIT(4)
/* only worked with FINTEK_RTS_CONTROL_BY_HW on */
#define FINTEK_RTS_INVERT BIT(5)
/* We should do proper H/W transceiver setting before change to RS485 mode */
static int pci_fintek_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
u8 setting;
u8 *index = (u8 *) port->private_data;
struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev,
dev);
pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting);
if (!rs485)
rs485 = &port->rs485;
else if (rs485->flags & SER_RS485_ENABLED)
memset(rs485->padding, 0, sizeof(rs485->padding));
else
memset(rs485, 0, sizeof(*rs485));
/* F81504/508/512 not support RTS delay before or after send */
rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
if (rs485->flags & SER_RS485_ENABLED) {
/* Enable RTS H/W control mode */
setting |= FINTEK_RTS_CONTROL_BY_HW;
if (rs485->flags & SER_RS485_RTS_ON_SEND) {
/* RTS driving high on TX */
setting &= ~FINTEK_RTS_INVERT;
} else {
/* RTS driving low on TX */
setting |= FINTEK_RTS_INVERT;
}
rs485->delay_rts_after_send = 0;
rs485->delay_rts_before_send = 0;
} else {
/* Disable RTS H/W control mode */
setting &= ~(FINTEK_RTS_CONTROL_BY_HW | FINTEK_RTS_INVERT);
}
pci_write_config_byte(pci_dev, 0x40 + 8 * *index + 7, setting);
if (rs485 != &port->rs485)
port->rs485 = *rs485;
return 0;
}
static int pci_fintek_setup(struct serial_private *priv, static int pci_fintek_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
struct uart_8250_port *port, int idx) struct uart_8250_port *port, int idx)
{ {
struct pci_dev *pdev = priv->dev; struct pci_dev *pdev = priv->dev;
u8 *data;
u8 config_base; u8 config_base;
u16 iobase; u16 iobase;
...@@ -1702,6 +1760,15 @@ static int pci_fintek_setup(struct serial_private *priv, ...@@ -1702,6 +1760,15 @@ static int pci_fintek_setup(struct serial_private *priv,
port->port.iotype = UPIO_PORT; port->port.iotype = UPIO_PORT;
port->port.iobase = iobase; port->port.iobase = iobase;
port->port.rs485_config = pci_fintek_rs485_config;
data = devm_kzalloc(&pdev->dev, sizeof(u8), GFP_KERNEL);
if (!data)
return -ENOMEM;
/* preserve index in PCI configuration space */
*data = idx;
port->port.private_data = data;
return 0; return 0;
} }
...@@ -1712,6 +1779,8 @@ static int pci_fintek_init(struct pci_dev *dev) ...@@ -1712,6 +1779,8 @@ static int pci_fintek_init(struct pci_dev *dev)
u32 max_port, i; u32 max_port, i;
u32 bar_data[3]; u32 bar_data[3];
u8 config_base; u8 config_base;
struct serial_private *priv = pci_get_drvdata(dev);
struct uart_8250_port *port;
switch (dev->device) { switch (dev->device) {
case 0x1104: /* 4 ports */ case 0x1104: /* 4 ports */
...@@ -1752,6 +1821,19 @@ static int pci_fintek_init(struct pci_dev *dev) ...@@ -1752,6 +1821,19 @@ static int pci_fintek_init(struct pci_dev *dev)
(u8)((iobase & 0xff00) >> 8)); (u8)((iobase & 0xff00) >> 8));
pci_write_config_byte(dev, config_base + 0x06, dev->irq); pci_write_config_byte(dev, config_base + 0x06, dev->irq);
if (priv) {
/* re-apply RS232/485 mode when
* pciserial_resume_ports()
*/
port = serial8250_get_port(priv->line[i]);
pci_fintek_rs485_config(&port->port, NULL);
} else {
/* First init without port data
* force init to RS232 Mode
*/
pci_write_config_byte(dev, config_base + 0x07, 0x01);
}
} }
return max_port; return max_port;
...@@ -2017,6 +2099,12 @@ pci_wch_ch38x_setup(struct serial_private *priv, ...@@ -2017,6 +2099,12 @@ pci_wch_ch38x_setup(struct serial_private *priv,
#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250 #define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470 #define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
#define PCI_VENDOR_ID_PERICOM 0x12D8
#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954
#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */ /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
...@@ -2331,27 +2419,12 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { ...@@ -2331,27 +2419,12 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
* Pericom * Pericom
*/ */
{ {
.vendor = 0x12d8, .vendor = PCI_VENDOR_ID_PERICOM,
.device = 0x7952, .device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup, .setup = pci_pericom_setup,
},
{
.vendor = 0x12d8,
.device = 0x7954,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup,
},
{
.vendor = 0x12d8,
.device = 0x7958,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup,
}, },
/* /*
* PLX * PLX
*/ */
...@@ -3056,6 +3129,10 @@ enum pci_board_num_t { ...@@ -3056,6 +3129,10 @@ enum pci_board_num_t {
pbn_fintek_8, pbn_fintek_8,
pbn_fintek_12, pbn_fintek_12,
pbn_wch384_4, pbn_wch384_4,
pbn_pericom_PI7C9X7951,
pbn_pericom_PI7C9X7952,
pbn_pericom_PI7C9X7954,
pbn_pericom_PI7C9X7958,
}; };
/* /*
...@@ -3881,7 +3958,6 @@ static struct pciserial_board pci_boards[] = { ...@@ -3881,7 +3958,6 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 115200, .base_baud = 115200,
.first_offset = 0x40, .first_offset = 0x40,
}, },
[pbn_wch384_4] = { [pbn_wch384_4] = {
.flags = FL_BASE0, .flags = FL_BASE0,
.num_ports = 4, .num_ports = 4,
...@@ -3889,6 +3965,33 @@ static struct pciserial_board pci_boards[] = { ...@@ -3889,6 +3965,33 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 8, .uart_offset = 8,
.first_offset = 0xC0, .first_offset = 0xC0,
}, },
/*
* Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
*/
[pbn_pericom_PI7C9X7951] = {
.flags = FL_BASE0,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7952] = {
.flags = FL_BASE0,
.num_ports = 2,
.base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7954] = {
.flags = FL_BASE0,
.num_ports = 4,
.base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7958] = {
.flags = FL_BASE0,
.num_ports = 8,
.base_baud = 921600,
.uart_offset = 0x8,
},
}; };
static const struct pci_device_id blacklist[] = { static const struct pci_device_id blacklist[] = {
...@@ -5153,6 +5256,25 @@ static struct pci_device_id serial_pci_tbl[] = { ...@@ -5153,6 +5256,25 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
0, 0,
0, pbn_exar_XR17V8358 }, 0, pbn_exar_XR17V8358 },
/*
* Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
*/
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7951 },
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7958 },
/* /*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
*/ */
......
...@@ -41,6 +41,12 @@ static const struct pnp_device_id pnp_dev_table[] = { ...@@ -41,6 +41,12 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "AEI1240", 0 }, { "AEI1240", 0 },
/* Rockwell 56K ACF II Fax+Data+Voice Modem */ /* Rockwell 56K ACF II Fax+Data+Voice Modem */
{ "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ }, { "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
/*
* ALi Fast Infrared Controller
* Native driver (ali-ircc) is broken so at least
* it can be used with irtty-sir.
*/
{ "ALI5123", 0 },
/* AZT3005 PnP SOUND DEVICE */ /* AZT3005 PnP SOUND DEVICE */
{ "AZT4001", 0 }, { "AZT4001", 0 },
/* Best Data Products Inc. Smart One 336F PnP Modem */ /* Best Data Products Inc. Smart One 336F PnP Modem */
...@@ -364,6 +370,11 @@ static const struct pnp_device_id pnp_dev_table[] = { ...@@ -364,6 +370,11 @@ static const struct pnp_device_id pnp_dev_table[] = {
/* Winbond CIR port, should not be probed. We should keep track /* Winbond CIR port, should not be probed. We should keep track
of it to prevent the legacy serial driver from probing it */ of it to prevent the legacy serial driver from probing it */
{ "WEC1022", CIR_PORT }, { "WEC1022", CIR_PORT },
/*
* SMSC IrCC SIR/FIR port, should not be probed by serial driver
* as well so its own driver can bind to it.
*/
{ "SMCF010", CIR_PORT },
{ "", 0 } { "", 0 }
}; };
......
/*
* Base port operations for 8250/16550-type serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
* Split from 8250_core.c, Copyright (C) 2001 Russell King.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* A note about mapbase / membase
*
* mapbase is the physical address of the IO port.
* membase is an 'ioremapped' cookie.
*/
#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/ratelimit.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/nmi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/pm_runtime.h>
#include <asm/io.h>
#include <asm/irq.h>
#include "8250.h"
/*
* Debugging.
*/
#if 0
#define DEBUG_AUTOCONF(fmt...) printk(fmt)
#else
#define DEBUG_AUTOCONF(fmt...) do { } while (0)
#endif
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
/*
* Here we define the default xmit fifo size used for each type of UART.
*/
static const struct serial8250_config uart_config[] = {
[PORT_UNKNOWN] = {
.name = "unknown",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_8250] = {
.name = "8250",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16450] = {
.name = "16450",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16550] = {
.name = "16550",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16550A] = {
.name = "16550A",
.fifo_size = 16,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO,
},
[PORT_CIRRUS] = {
.name = "Cirrus",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16650] = {
.name = "ST16650",
.fifo_size = 1,
.tx_loadsz = 1,
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16650V2] = {
.name = "ST16650V2",
.fifo_size = 32,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_00,
.rxtrig_bytes = {8, 16, 24, 28},
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16750] = {
.name = "TI16750",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
UART_FCR7_64BYTE,
.rxtrig_bytes = {1, 16, 32, 56},
.flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
},
[PORT_STARTECH] = {
.name = "Startech",
.fifo_size = 1,
.tx_loadsz = 1,
},
[PORT_16C950] = {
.name = "16C950/954",
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
/* UART_CAP_EFR breaks billionon CF bluetooth card. */
.flags = UART_CAP_FIFO | UART_CAP_SLEEP,
},
[PORT_16654] = {
.name = "ST16654",
.fifo_size = 64,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_10,
.rxtrig_bytes = {8, 16, 56, 60},
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16850] = {
.name = "XR16850",
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_RSA] = {
.name = "RSA",
.fifo_size = 2048,
.tx_loadsz = 2048,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
.flags = UART_CAP_FIFO,
},
[PORT_NS16550A] = {
.name = "NS16550A",
.fifo_size = 16,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_NATSEMI,
},
[PORT_XSCALE] = {
.name = "XScale",
.fifo_size = 32,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
},
[PORT_OCTEON] = {
.name = "OCTEON",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
},
[PORT_AR7] = {
.name = "AR7",
.fifo_size = 16,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_U6_16550A] = {
.name = "U6_16550A",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_TEGRA] = {
.name = "Tegra",
.fifo_size = 32,
.tx_loadsz = 8,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_01,
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO | UART_CAP_RTOIE,
},
[PORT_XR17D15X] = {
.name = "XR17D15X",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP,
},
[PORT_XR17V35X] = {
.name = "XR17V35X",
.fifo_size = 256,
.tx_loadsz = 256,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
UART_FCR_T_TRIG_11,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP,
},
[PORT_LPC3220] = {
.name = "LPC3220",
.fifo_size = 64,
.tx_loadsz = 32,
.fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
.flags = UART_CAP_FIFO,
},
[PORT_BRCM_TRUMANAGE] = {
.name = "TruManage",
.fifo_size = 1,
.tx_loadsz = 1024,
.flags = UART_CAP_HFIFO,
},
[PORT_8250_CIR] = {
.name = "CIR port"
},
[PORT_ALTR_16550_F32] = {
.name = "Altera 16550 FIFO32",
.fifo_size = 32,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_ALTR_16550_F64] = {
.name = "Altera 16550 FIFO64",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_ALTR_16550_F128] = {
.name = "Altera 16550 FIFO128",
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement
workaround of errata A-008006 which states that tx_loadsz should be
configured less than Maximum supported fifo bytes */
[PORT_16550A_FSL64] = {
.name = "16550A_FSL64",
.fifo_size = 64,
.tx_loadsz = 63,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
UART_FCR7_64BYTE,
.flags = UART_CAP_FIFO,
},
};
/* Uart divisor latch read */
static int default_serial_dl_read(struct uart_8250_port *up)
{
return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
}
/* Uart divisor latch write */
static void default_serial_dl_write(struct uart_8250_port *up, int value)
{
serial_out(up, UART_DLL, value & 0xff);
serial_out(up, UART_DLM, value >> 8 & 0xff);
}
#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
/* Au1x00/RT288x UART hardware has a weird register layout */
static const s8 au_io_in_map[8] = {
0, /* UART_RX */
2, /* UART_IER */
3, /* UART_IIR */
5, /* UART_LCR */
6, /* UART_MCR */
7, /* UART_LSR */
8, /* UART_MSR */
-1, /* UART_SCR (unmapped) */
};
static const s8 au_io_out_map[8] = {
1, /* UART_TX */
2, /* UART_IER */
4, /* UART_FCR */
5, /* UART_LCR */
6, /* UART_MCR */
-1, /* UART_LSR (unmapped) */
-1, /* UART_MSR (unmapped) */
-1, /* UART_SCR (unmapped) */
};
static unsigned int au_serial_in(struct uart_port *p, int offset)
{
if (offset >= ARRAY_SIZE(au_io_in_map))
return UINT_MAX;
offset = au_io_in_map[offset];
if (offset < 0)
return UINT_MAX;
return __raw_readl(p->membase + (offset << p->regshift));
}
static void au_serial_out(struct uart_port *p, int offset, int value)
{
if (offset >= ARRAY_SIZE(au_io_out_map))
return;
offset = au_io_out_map[offset];
if (offset < 0)
return;
__raw_writel(value, p->membase + (offset << p->regshift));
}
/* Au1x00 haven't got a standard divisor latch */
static int au_serial_dl_read(struct uart_8250_port *up)
{
return __raw_readl(up->port.membase + 0x28);
}
static void au_serial_dl_write(struct uart_8250_port *up, int value)
{
__raw_writel(value, up->port.membase + 0x28);
}
#endif
static unsigned int hub6_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
outb(p->hub6 - 1 + offset, p->iobase);
return inb(p->iobase + 1);
}
static void hub6_serial_out(struct uart_port *p, int offset, int value)
{
offset = offset << p->regshift;
outb(p->hub6 - 1 + offset, p->iobase);
outb(value, p->iobase + 1);
}
static unsigned int mem_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
return readb(p->membase + offset);
}
static void mem_serial_out(struct uart_port *p, int offset, int value)
{
offset = offset << p->regshift;
writeb(value, p->membase + offset);
}
static void mem32_serial_out(struct uart_port *p, int offset, int value)
{
offset = offset << p->regshift;
writel(value, p->membase + offset);
}
static unsigned int mem32_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
return readl(p->membase + offset);
}
static void mem32be_serial_out(struct uart_port *p, int offset, int value)
{
offset = offset << p->regshift;
iowrite32be(value, p->membase + offset);
}
static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
return ioread32be(p->membase + offset);
}
static unsigned int io_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
return inb(p->iobase + offset);
}
static void io_serial_out(struct uart_port *p, int offset, int value)
{
offset = offset << p->regshift;
outb(value, p->iobase + offset);
}
static int serial8250_default_handle_irq(struct uart_port *port);
static int exar_handle_irq(struct uart_port *port);
static void set_io_from_upio(struct uart_port *p)
{
struct uart_8250_port *up = up_to_u8250p(p);
up->dl_read = default_serial_dl_read;
up->dl_write = default_serial_dl_write;
switch (p->iotype) {
case UPIO_HUB6:
p->serial_in = hub6_serial_in;
p->serial_out = hub6_serial_out;
break;
case UPIO_MEM:
p->serial_in = mem_serial_in;
p->serial_out = mem_serial_out;
break;
case UPIO_MEM32:
p->serial_in = mem32_serial_in;
p->serial_out = mem32_serial_out;
break;
case UPIO_MEM32BE:
p->serial_in = mem32be_serial_in;
p->serial_out = mem32be_serial_out;
break;
#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
case UPIO_AU:
p->serial_in = au_serial_in;
p->serial_out = au_serial_out;
up->dl_read = au_serial_dl_read;
up->dl_write = au_serial_dl_write;
break;
#endif
default:
p->serial_in = io_serial_in;
p->serial_out = io_serial_out;
break;
}
/* Remember loaded iotype */
up->cur_iotype = p->iotype;
p->handle_irq = serial8250_default_handle_irq;
}
static void
serial_port_out_sync(struct uart_port *p, int offset, int value)
{
switch (p->iotype) {
case UPIO_MEM:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_AU:
p->serial_out(p, offset, value);
p->serial_in(p, UART_LCR); /* safe, no side-effects */
break;
default:
p->serial_out(p, offset, value);
}
}
/*
* For the 16C950
*/
static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
{
serial_out(up, UART_SCR, offset);
serial_out(up, UART_ICR, value);
}
static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
{
unsigned int value;
serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
serial_out(up, UART_SCR, offset);
value = serial_in(up, UART_ICR);
serial_icr_write(up, UART_ACR, up->acr);
return value;
}
/*
* FIFO support.
*/
static void serial8250_clear_fifos(struct uart_8250_port *p)
{
if (p->capabilities & UART_CAP_FIFO) {
serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial_out(p, UART_FCR, 0);
}
}
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
{
serial8250_clear_fifos(p);
serial_out(p, UART_FCR, p->fcr);
}
EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
void serial8250_rpm_get(struct uart_8250_port *p)
{
if (!(p->capabilities & UART_CAP_RPM))
return;
pm_runtime_get_sync(p->port.dev);
}
EXPORT_SYMBOL_GPL(serial8250_rpm_get);
void serial8250_rpm_put(struct uart_8250_port *p)
{
if (!(p->capabilities & UART_CAP_RPM))
return;
pm_runtime_mark_last_busy(p->port.dev);
pm_runtime_put_autosuspend(p->port.dev);
}
EXPORT_SYMBOL_GPL(serial8250_rpm_put);
/*
* These two wrappers ensure that enable_runtime_pm_tx() can be called more than
* once and disable_runtime_pm_tx() will still disable RPM because the fifo is
* empty and the HW can idle again.
*/
static void serial8250_rpm_get_tx(struct uart_8250_port *p)
{
unsigned char rpm_active;
if (!(p->capabilities & UART_CAP_RPM))
return;
rpm_active = xchg(&p->rpm_tx_active, 1);
if (rpm_active)
return;
pm_runtime_get_sync(p->port.dev);
}
static void serial8250_rpm_put_tx(struct uart_8250_port *p)
{
unsigned char rpm_active;
if (!(p->capabilities & UART_CAP_RPM))
return;
rpm_active = xchg(&p->rpm_tx_active, 0);
if (!rpm_active)
return;
pm_runtime_mark_last_busy(p->port.dev);
pm_runtime_put_autosuspend(p->port.dev);
}
/*
* IER sleep support. UARTs which have EFRs need the "extended
* capability" bit enabled. Note that on XR16C850s, we need to
* reset LCR to write to IER.
*/
static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
unsigned char lcr = 0, efr = 0;
/*
* Exar UARTs have a SLEEP register that enables or disables
* each UART to enter sleep mode separately. On the XR17V35x the
* register is accessible to each UART at the UART_EXAR_SLEEP
* offset but the UART channel may only write to the corresponding
* bit.
*/
serial8250_rpm_get(p);
if ((p->port.type == PORT_XR17V35X) ||
(p->port.type == PORT_XR17D15X)) {
serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
goto out;
}
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
lcr = serial_in(p, UART_LCR);
efr = serial_in(p, UART_EFR);
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(p, UART_EFR, UART_EFR_ECB);
serial_out(p, UART_LCR, 0);
}
serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
if (p->capabilities & UART_CAP_EFR) {
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(p, UART_EFR, efr);
serial_out(p, UART_LCR, lcr);
}
}
out:
serial8250_rpm_put(p);
}
#ifdef CONFIG_SERIAL_8250_RSA
/*
* Attempts to turn on the RSA FIFO. Returns zero on failure.
* We set the port uart clock rate if we succeed.
*/
static int __enable_rsa(struct uart_8250_port *up)
{
unsigned char mode;
int result;
mode = serial_in(up, UART_RSA_MSR);
result = mode & UART_RSA_MSR_FIFO;
if (!result) {
serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
mode = serial_in(up, UART_RSA_MSR);
result = mode & UART_RSA_MSR_FIFO;
}
if (result)
up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
return result;
}
static void enable_rsa(struct uart_8250_port *up)
{
if (up->port.type == PORT_RSA) {
if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
spin_lock_irq(&up->port.lock);
__enable_rsa(up);
spin_unlock_irq(&up->port.lock);
}
if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
serial_out(up, UART_RSA_FRR, 0);
}
}
/*
* Attempts to turn off the RSA FIFO. Returns zero on failure.
* It is unknown why interrupts were disabled in here. However,
* the caller is expected to preserve this behaviour by grabbing
* the spinlock before calling this function.
*/
static void disable_rsa(struct uart_8250_port *up)
{
unsigned char mode;
int result;
if (up->port.type == PORT_RSA &&
up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
spin_lock_irq(&up->port.lock);
mode = serial_in(up, UART_RSA_MSR);
result = !(mode & UART_RSA_MSR_FIFO);
if (!result) {
serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
mode = serial_in(up, UART_RSA_MSR);
result = !(mode & UART_RSA_MSR_FIFO);
}
if (result)
up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
spin_unlock_irq(&up->port.lock);
}
}
#endif /* CONFIG_SERIAL_8250_RSA */
/*
* This is a quickie test to see how big the FIFO is.
* It doesn't work at all the time, more's the pity.
*/
static int size_fifo(struct uart_8250_port *up)
{
unsigned char old_fcr, old_mcr, old_lcr;
unsigned short old_dl;
int count;
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);
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);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
old_dl = serial_dl_read(up);
serial_dl_write(up, 0x0001);
serial_out(up, UART_LCR, 0x03);
for (count = 0; count < 256; count++)
serial_out(up, UART_TX, count);
mdelay(20);/* FIXME - schedule_timeout */
for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) &&
(count < 256); count++)
serial_in(up, UART_RX);
serial_out(up, UART_FCR, old_fcr);
serial_out(up, UART_MCR, 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);
return count;
}
/*
* Read UART ID using the divisor method - set DLL and DLM to zero
* and the revision will be in DLL and device type in DLM. We
* preserve the device state across this.
*/
static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
{
unsigned char old_dll, old_dlm, old_lcr;
unsigned int id;
old_lcr = serial_in(p, UART_LCR);
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
old_dll = serial_in(p, UART_DLL);
old_dlm = serial_in(p, UART_DLM);
serial_out(p, UART_DLL, 0);
serial_out(p, UART_DLM, 0);
id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8;
serial_out(p, UART_DLL, old_dll);
serial_out(p, UART_DLM, old_dlm);
serial_out(p, UART_LCR, old_lcr);
return id;
}
/*
* This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
* When this function is called we know it is at least a StarTech
* 16650 V2, but it might be one of several StarTech UARTs, or one of
* its clones. (We treat the broken original StarTech 16650 V1 as a
* 16550, and why not? Startech doesn't seem to even acknowledge its
* existence.)
*
* What evil have men's minds wrought...
*/
static void autoconfig_has_efr(struct uart_8250_port *up)
{
unsigned int id1, id2, id3, rev;
/*
* Everything with an EFR has SLEEP
*/
up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
/*
* First we check to see if it's an Oxford Semiconductor UART.
*
* If we have to do this here because some non-National
* Semiconductor clone chips lock up if you try writing to the
* LSR register (which serial_icr_read does)
*/
/*
* Check for Oxford Semiconductor 16C950.
*
* EFR [4] must be set else this test fails.
*
* This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
* claims that it's needed for 952 dual UART's (which are not
* recommended for new designs).
*/
up->acr = 0;
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, 0x00);
id1 = serial_icr_read(up, UART_ID1);
id2 = serial_icr_read(up, UART_ID2);
id3 = serial_icr_read(up, UART_ID3);
rev = serial_icr_read(up, UART_REV);
DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
if (id1 == 0x16 && id2 == 0xC9 &&
(id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
up->port.type = PORT_16C950;
/*
* Enable work around for the Oxford Semiconductor 952 rev B
* chip which causes it to seriously miscalculate baud rates
* when DLL is 0.
*/
if (id3 == 0x52 && rev == 0x01)
up->bugs |= UART_BUG_QUOT;
return;
}
/*
* We check for a XR16C850 by setting DLL and DLM to 0, and then
* reading back DLL and DLM. The chip type depends on the DLM
* value read back:
* 0x10 - XR16C850 and the DLL contains the chip revision.
* 0x12 - XR16C2850.
* 0x14 - XR16C854.
*/
id1 = autoconfig_read_divisor_id(up);
DEBUG_AUTOCONF("850id=%04x ", id1);
id2 = id1 >> 8;
if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
up->port.type = PORT_16850;
return;
}
/*
* It wasn't an XR16C850.
*
* We distinguish between the '654 and the '650 by counting
* how many bytes are in the FIFO. I'm using this for now,
* since that's the technique that was sent to me in the
* serial driver update, but I'm not convinced this works.
* I've had problems doing this in the past. -TYT
*/
if (size_fifo(up) == 64)
up->port.type = PORT_16654;
else
up->port.type = PORT_16650V2;
}
/*
* We detected a chip without a FIFO. Only two fall into
* this category - the original 8250 and the 16450. The
* 16450 has a scratch register (accessible with LCR=0)
*/
static void autoconfig_8250(struct uart_8250_port *up)
{
unsigned char scratch, status1, status2;
up->port.type = PORT_8250;
scratch = serial_in(up, UART_SCR);
serial_out(up, UART_SCR, 0xa5);
status1 = serial_in(up, UART_SCR);
serial_out(up, UART_SCR, 0x5a);
status2 = serial_in(up, UART_SCR);
serial_out(up, UART_SCR, scratch);
if (status1 == 0xa5 && status2 == 0x5a)
up->port.type = PORT_16450;
}
static int broken_efr(struct uart_8250_port *up)
{
/*
* Exar ST16C2550 "A2" devices incorrectly detect as
* having an EFR, and report an ID of 0x0201. See
* http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
*/
if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
return 1;
return 0;
}
/*
* We know that the chip has FIFOs. Does it have an EFR? The
* EFR is located in the same register position as the IIR and
* we know the top two bits of the IIR are currently set. The
* EFR should contain zero. Try to read the EFR.
*/
static void autoconfig_16550a(struct uart_8250_port *up)
{
unsigned char status1, status2;
unsigned int iersave;
up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO;
/*
* XR17V35x UARTs have an extra divisor register, DLD
* that gets enabled with when DLAB is set which will
* cause the device to incorrectly match and assign
* port type to PORT_16650. The EFR for this UART is
* found at offset 0x09. Instead check the Deice ID (DVID)
* register for a 2, 4 or 8 port UART.
*/
if (up->port.flags & UPF_EXAR_EFR) {
status1 = serial_in(up, UART_EXAR_DVID);
if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
DEBUG_AUTOCONF("Exar XR17V35x ");
up->port.type = PORT_XR17V35X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
}
}
/*
* Check for presence of the EFR when DLAB is set.
* Only ST16C650V1 UARTs pass this test.
*/
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
if (serial_in(up, UART_EFR) == 0) {
serial_out(up, UART_EFR, 0xA8);
if (serial_in(up, UART_EFR) != 0) {
DEBUG_AUTOCONF("EFRv1 ");
up->port.type = PORT_16650;
up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
} else {
serial_out(up, UART_LCR, 0);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR7_64BYTE);
status1 = serial_in(up, UART_IIR) >> 5;
serial_out(up, UART_FCR, 0);
serial_out(up, UART_LCR, 0);
if (status1 == 7)
up->port.type = PORT_16550A_FSL64;
else
DEBUG_AUTOCONF("Motorola 8xxx DUART ");
}
serial_out(up, UART_EFR, 0);
return;
}
/*
* Maybe it requires 0xbf to be written to the LCR.
* (other ST16C650V2 UARTs, TI16C752A, etc)
*/
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
DEBUG_AUTOCONF("EFRv2 ");
autoconfig_has_efr(up);
return;
}
/*
* Check for a National Semiconductor SuperIO chip.
* Attempt to switch to bank 2, read the value of the LOOP bit
* from EXCR1. Switch back to bank 0, change it in MCR. Then
* switch back to bank 2, read it from EXCR1 again and check
* 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);
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);
serial_out(up, UART_LCR, 0xE0);
status2 = serial_in(up, 0x02); /* EXCR1 */
serial_out(up, UART_LCR, 0);
serial_out(up, UART_MCR, status1);
if ((status2 ^ status1) & UART_MCR_LOOP) {
unsigned short quot;
serial_out(up, UART_LCR, 0xE0);
quot = serial_dl_read(up);
quot <<= 3;
if (ns16550a_goto_highspeed(up))
serial_dl_write(up, quot);
serial_out(up, UART_LCR, 0);
up->port.uartclk = 921600*16;
up->port.type = PORT_NS16550A;
up->capabilities |= UART_NATSEMI;
return;
}
}
/*
* No EFR. Try to detect a TI16750, which only sets bit 5 of
* the IIR when 64 byte FIFO mode is enabled when DLAB is set.
* Try setting it with and without DLAB set. Cheap clones
* set bit 5 without DLAB set.
*/
serial_out(up, UART_LCR, 0);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status1 = serial_in(up, UART_IIR) >> 5;
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status2 = serial_in(up, UART_IIR) >> 5;
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_out(up, UART_LCR, 0);
DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
if (status1 == 6 && status2 == 7) {
up->port.type = PORT_16750;
up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
return;
}
/*
* Try writing and reading the UART_IER_UUE bit (b6).
* If it works, this is probably one of the Xscale platform's
* internal UARTs.
* We're going to explicitly set the UUE bit to 0 before
* trying to write and read a 1 just to make sure it's not
* already a 1 and maybe locked there before we even start start.
*/
iersave = serial_in(up, UART_IER);
serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
/*
* OK it's in a known zero state, try writing and reading
* without disturbing the current state of the other bits.
*/
serial_out(up, UART_IER, iersave | UART_IER_UUE);
if (serial_in(up, UART_IER) & UART_IER_UUE) {
/*
* It's an Xscale.
* We'll leave the UART_IER_UUE bit set to 1 (enabled).
*/
DEBUG_AUTOCONF("Xscale ");
up->port.type = PORT_XSCALE;
up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
return;
}
} else {
/*
* If we got here we couldn't force the IER_UUE bit to 0.
* Log it and continue.
*/
DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
}
serial_out(up, UART_IER, iersave);
/*
* Exar uarts have EFR in a weird location
*/
if (up->port.flags & UPF_EXAR_EFR) {
DEBUG_AUTOCONF("Exar XR17D15x ");
up->port.type = PORT_XR17D15X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
}
/*
* We distinguish between 16550A and U6 16550A by counting
* how many bytes are in the FIFO.
*/
if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
up->port.type = PORT_U6_16550A;
up->capabilities |= UART_CAP_AFE;
}
}
/*
* This routine is called by rs_init() to initialize a specific serial
* port. It determines what type of UART chip this serial port is
* using: 8250, 16450, 16550, 16550A. The important question is
* whether or not this UART is a 16550A or not, since this will
* determine whether or not we can use its FIFO features or not.
*/
static void autoconfig(struct uart_8250_port *up)
{
unsigned char status1, scratch, scratch2, scratch3;
unsigned char save_lcr, save_mcr;
struct uart_port *port = &up->port;
unsigned long flags;
unsigned int old_capabilities;
if (!port->iobase && !port->mapbase && !port->membase)
return;
DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
serial_index(port), port->iobase, port->membase);
/*
* We really do need global IRQs disabled here - we're going to
* be frobbing the chips IRQ enable register to see if it exists.
*/
spin_lock_irqsave(&port->lock, flags);
up->capabilities = 0;
up->bugs = 0;
if (!(port->flags & UPF_BUGGY_UART)) {
/*
* Do a simple existence test first; if we fail this,
* there's no point trying anything else.
*
* 0x80 is used as a nonsense port to prevent against
* false positives due to ISA bus float. The
* assumption is that 0x80 is a non-existent port;
* which should be safe since include/asm/io.h also
* makes this assumption.
*
* Note: this is safe as long as MCR bit 4 is clear
* and the device is in "PC" mode.
*/
scratch = serial_in(up, UART_IER);
serial_out(up, UART_IER, 0);
#ifdef __i386__
outb(0xff, 0x080);
#endif
/*
* Mask out IER[7:4] bits for test as some UARTs (e.g. TL
* 16C754B) allow only to modify them if an EFR bit is set.
*/
scratch2 = serial_in(up, UART_IER) & 0x0f;
serial_out(up, UART_IER, 0x0F);
#ifdef __i386__
outb(0, 0x080);
#endif
scratch3 = serial_in(up, UART_IER) & 0x0f;
serial_out(up, UART_IER, scratch);
if (scratch2 != 0 || scratch3 != 0x0F) {
/*
* We failed; there's nothing here
*/
spin_unlock_irqrestore(&port->lock, flags);
DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
scratch2, scratch3);
goto out;
}
}
save_mcr = serial_in(up, UART_MCR);
save_lcr = serial_in(up, UART_LCR);
/*
* Check to see if a UART is really there. Certain broken
* internal modems based on the Rockwell chipset fail this
* test, because they apparently don't implement the loopback
* test mode. So this test is skipped on the COM 1 through
* COM 4 ports. This *should* be safe, since no board
* manufacturer would be stupid enough to design a board
* that conflicts with COM 1-4 --- we hope!
*/
if (!(port->flags & UPF_SKIP_TEST)) {
serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
status1 = serial_in(up, UART_MSR) & 0xF0;
serial_out(up, UART_MCR, save_mcr);
if (status1 != 0x90) {
spin_unlock_irqrestore(&port->lock, flags);
DEBUG_AUTOCONF("LOOP test failed (%02x) ",
status1);
goto out;
}
}
/*
* We're pretty sure there's a port here. Lets find out what
* type of port it is. The IIR top two bits allows us to find
* out if it's 8250 or 16450, 16550, 16550A or later. This
* determines what we test for next.
*
* We also initialise the EFR (if any) to zero for later. The
* EFR occupies the same register location as the FCR and IIR.
*/
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, 0);
serial_out(up, UART_LCR, 0);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
scratch = serial_in(up, UART_IIR) >> 6;
switch (scratch) {
case 0:
autoconfig_8250(up);
break;
case 1:
port->type = PORT_UNKNOWN;
break;
case 2:
port->type = PORT_16550;
break;
case 3:
autoconfig_16550a(up);
break;
}
#ifdef CONFIG_SERIAL_8250_RSA
/*
* Only probe for RSA ports if we got the region.
*/
if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
__enable_rsa(up))
port->type = PORT_RSA;
#endif
serial_out(up, UART_LCR, save_lcr);
port->fifosize = uart_config[up->port.type].fifo_size;
old_capabilities = up->capabilities;
up->capabilities = uart_config[port->type].flags;
up->tx_loadsz = uart_config[port->type].tx_loadsz;
if (port->type == PORT_UNKNOWN)
goto out_lock;
/*
* Reset the UART.
*/
#ifdef CONFIG_SERIAL_8250_RSA
if (port->type == PORT_RSA)
serial_out(up, UART_RSA_FRR, 0);
#endif
serial_out(up, UART_MCR, save_mcr);
serial8250_clear_fifos(up);
serial_in(up, UART_RX);
if (up->capabilities & UART_CAP_UUE)
serial_out(up, UART_IER, UART_IER_UUE);
else
serial_out(up, UART_IER, 0);
out_lock:
spin_unlock_irqrestore(&port->lock, flags);
if (up->capabilities != old_capabilities) {
printk(KERN_WARNING
"ttyS%d: detected caps %08x should be %08x\n",
serial_index(port), old_capabilities,
up->capabilities);
}
out:
DEBUG_AUTOCONF("iir=%d ", scratch);
DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
}
static void autoconfig_irq(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
unsigned char save_mcr, save_ier;
unsigned char save_ICP = 0;
unsigned int ICP = 0;
unsigned long irqs;
int irq;
if (port->flags & UPF_FOURPORT) {
ICP = (port->iobase & 0xfe0) | 0x1f;
save_ICP = inb_p(ICP);
outb_p(0x80, ICP);
inb_p(ICP);
}
/* forget possible initially masked and pending IRQ */
probe_irq_off(probe_irq_on());
save_mcr = serial_in(up, UART_MCR);
save_ier = serial_in(up, UART_IER);
serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
irqs = probe_irq_on();
serial_out(up, UART_MCR, 0);
udelay(10);
if (port->flags & UPF_FOURPORT) {
serial_out(up, UART_MCR,
UART_MCR_DTR | UART_MCR_RTS);
} else {
serial_out(up, UART_MCR,
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
}
serial_out(up, UART_IER, 0x0f); /* enable all intrs */
serial_in(up, UART_LSR);
serial_in(up, UART_RX);
serial_in(up, UART_IIR);
serial_in(up, UART_MSR);
serial_out(up, UART_TX, 0xFF);
udelay(20);
irq = probe_irq_off(irqs);
serial_out(up, UART_MCR, save_mcr);
serial_out(up, UART_IER, save_ier);
if (port->flags & UPF_FOURPORT)
outb_p(save_ICP, ICP);
port->irq = (irq > 0) ? irq : 0;
}
static inline void __stop_tx(struct uart_8250_port *p)
{
if (p->ier & UART_IER_THRI) {
p->ier &= ~UART_IER_THRI;
serial_out(p, UART_IER, p->ier);
serial8250_rpm_put_tx(p);
}
}
static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get(up);
__stop_tx(up);
/*
* We really want to stop the transmitter from sending.
*/
if (port->type == PORT_16C950) {
up->acr |= UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
serial8250_rpm_put(up);
}
static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get_tx(up);
if (up->dma && !up->dma->tx_dma(up))
return;
if (!(up->ier & UART_IER_THRI)) {
up->ier |= UART_IER_THRI;
serial_port_out(port, UART_IER, up->ier);
if (up->bugs & UART_BUG_TXEN) {
unsigned char lsr;
lsr = serial_in(up, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
if (lsr & UART_LSR_THRE)
serial8250_tx_chars(up);
}
}
/*
* Re-enable the transmitter if we disabled it.
*/
if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
up->acr &= ~UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
}
static void serial8250_throttle(struct uart_port *port)
{
port->throttle(port);
}
static void serial8250_unthrottle(struct uart_port *port)
{
port->unthrottle(port);
}
static void serial8250_stop_rx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get(up);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
up->port.read_status_mask &= ~UART_LSR_DR;
serial_port_out(port, UART_IER, up->ier);
serial8250_rpm_put(up);
}
static void serial8250_disable_ms(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
/* no MSR capabilities */
if (up->bugs & UART_BUG_NOMSR)
return;
up->ier &= ~UART_IER_MSI;
serial_port_out(port, UART_IER, up->ier);
}
static void serial8250_enable_ms(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
/* no MSR capabilities */
if (up->bugs & UART_BUG_NOMSR)
return;
up->ier |= UART_IER_MSI;
serial8250_rpm_get(up);
serial_port_out(port, UART_IER, up->ier);
serial8250_rpm_put(up);
}
/*
* serial8250_rx_chars: processes according to the passed in LSR
* value, and returns the remaining LSR bits not handled
* by this Rx routine.
*/
unsigned char
serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
{
struct uart_port *port = &up->port;
unsigned char ch;
int max_count = 256;
char flag;
do {
if (likely(lsr & UART_LSR_DR))
ch = serial_in(up, UART_RX);
else
/*
* Intel 82571 has a Serial Over Lan device that will
* set UART_LSR_BI without setting UART_LSR_DR when
* it receives a break. To avoid reading from the
* receive buffer without UART_LSR_DR bit set, we
* just force the read character to be 0
*/
ch = 0;
flag = TTY_NORMAL;
port->icount.rx++;
lsr |= up->lsr_saved_flags;
up->lsr_saved_flags = 0;
if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
if (lsr & UART_LSR_BI) {
lsr &= ~(UART_LSR_FE | UART_LSR_PE);
port->icount.brk++;
/*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
* or read_status_mask.
*/
if (uart_handle_break(port))
goto ignore_char;
} else if (lsr & UART_LSR_PE)
port->icount.parity++;
else if (lsr & UART_LSR_FE)
port->icount.frame++;
if (lsr & UART_LSR_OE)
port->icount.overrun++;
/*
* Mask off conditions which should be ignored.
*/
lsr &= port->read_status_mask;
if (lsr & UART_LSR_BI) {
DEBUG_INTR("handling break....");
flag = TTY_BREAK;
} else if (lsr & UART_LSR_PE)
flag = TTY_PARITY;
else if (lsr & UART_LSR_FE)
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(port, ch))
goto ignore_char;
uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
ignore_char:
lsr = serial_in(up, UART_LSR);
} while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
return lsr;
}
EXPORT_SYMBOL_GPL(serial8250_rx_chars);
void serial8250_tx_chars(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
struct circ_buf *xmit = &port->state->xmit;
int count;
if (port->x_char) {
serial_out(up, UART_TX, port->x_char);
port->icount.tx++;
port->x_char = 0;
return;
}
if (uart_tx_stopped(port)) {
serial8250_stop_tx(port);
return;
}
if (uart_circ_empty(xmit)) {
__stop_tx(up);
return;
}
count = up->tx_loadsz;
do {
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
if (uart_circ_empty(xmit))
break;
if (up->capabilities & UART_CAP_HFIFO) {
if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
BOTH_EMPTY)
break;
}
} while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
DEBUG_INTR("THRE...");
/*
* With RPM enabled, we have to wait until the FIFO is empty before the
* HW can go idle. So we get here once again with empty FIFO and disable
* the interrupt and RPM in __stop_tx()
*/
if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
__stop_tx(up);
}
EXPORT_SYMBOL_GPL(serial8250_tx_chars);
/* Caller holds uart port lock */
unsigned int serial8250_modem_status(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
unsigned int status = serial_in(up, UART_MSR);
status |= up->msr_saved_flags;
up->msr_saved_flags = 0;
if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
port->state != NULL) {
if (status & UART_MSR_TERI)
port->icount.rng++;
if (status & UART_MSR_DDSR)
port->icount.dsr++;
if (status & UART_MSR_DDCD)
uart_handle_dcd_change(port, status & UART_MSR_DCD);
if (status & UART_MSR_DCTS)
uart_handle_cts_change(port, status & UART_MSR_CTS);
wake_up_interruptible(&port->state->port.delta_msr_wait);
}
return status;
}
EXPORT_SYMBOL_GPL(serial8250_modem_status);
/*
* This handles the interrupt from one port.
*/
int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
{
unsigned char status;
unsigned long flags;
struct uart_8250_port *up = up_to_u8250p(port);
int dma_err = 0;
if (iir & UART_IIR_NO_INT)
return 0;
spin_lock_irqsave(&port->lock, flags);
status = serial_port_in(port, UART_LSR);
DEBUG_INTR("status = %x...", status);
if (status & (UART_LSR_DR | UART_LSR_BI)) {
if (up->dma)
dma_err = up->dma->rx_dma(up, iir);
if (!up->dma || dma_err)
status = serial8250_rx_chars(up, status);
}
serial8250_modem_status(up);
if ((!up->dma || (up->dma && up->dma->tx_err)) &&
(status & UART_LSR_THRE))
serial8250_tx_chars(up);
spin_unlock_irqrestore(&port->lock, flags);
return 1;
}
EXPORT_SYMBOL_GPL(serial8250_handle_irq);
static int serial8250_default_handle_irq(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int iir;
int ret;
serial8250_rpm_get(up);
iir = serial_port_in(port, UART_IIR);
ret = serial8250_handle_irq(port, iir);
serial8250_rpm_put(up);
return ret;
}
/*
* These Exar UARTs have an extra interrupt indicator that could
* fire for a few unimplemented interrupts. One of which is a
* wakeup event when coming out of sleep. Put this here just
* to be on the safe side that these interrupts don't go unhandled.
*/
static int exar_handle_irq(struct uart_port *port)
{
unsigned char int0, int1, int2, int3;
unsigned int iir = serial_port_in(port, UART_IIR);
int ret;
ret = serial8250_handle_irq(port, iir);
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);
}
return ret;
}
static unsigned int serial8250_tx_empty(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
unsigned int lsr;
serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
lsr = serial_port_in(port, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
}
static unsigned int serial8250_get_mctrl(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int status;
unsigned int ret;
serial8250_rpm_get(up);
status = serial8250_modem_status(up);
serial8250_rpm_put(up);
ret = 0;
if (status & UART_MSR_DCD)
ret |= TIOCM_CAR;
if (status & UART_MSR_RI)
ret |= TIOCM_RNG;
if (status & UART_MSR_DSR)
ret |= TIOCM_DSR;
if (status & UART_MSR_CTS)
ret |= TIOCM_CTS;
return ret;
}
void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char mcr = 0;
if (mctrl & TIOCM_RTS)
mcr |= UART_MCR_RTS;
if (mctrl & TIOCM_DTR)
mcr |= UART_MCR_DTR;
if (mctrl & TIOCM_OUT1)
mcr |= UART_MCR_OUT1;
if (mctrl & TIOCM_OUT2)
mcr |= UART_MCR_OUT2;
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
serial_port_out(port, UART_MCR, mcr);
}
EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
if (port->set_mctrl)
port->set_mctrl(port, mctrl);
else
serial8250_do_set_mctrl(port, mctrl);
}
static void serial8250_break_ctl(struct uart_port *port, int break_state)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
else
up->lcr &= ~UART_LCR_SBC;
serial_port_out(port, UART_LCR, up->lcr);
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
}
/*
* Wait for transmitter & holding register to empty
*/
static void wait_for_xmitr(struct uart_8250_port *up, int bits)
{
unsigned int status, tmout = 10000;
/* Wait up to 10ms for the character(s) to be sent. */
for (;;) {
status = serial_in(up, UART_LSR);
up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
if ((status & bits) == bits)
break;
if (--tmout == 0)
break;
udelay(1);
}
/* 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;
if (msr & UART_MSR_CTS)
break;
udelay(1);
touch_nmi_watchdog();
}
}
}
#ifdef CONFIG_CONSOLE_POLL
/*
* Console polling routines for writing and reading from the uart while
* in an interrupt or debug context.
*/
static int serial8250_get_poll_char(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char lsr;
int status;
serial8250_rpm_get(up);
lsr = serial_port_in(port, UART_LSR);
if (!(lsr & UART_LSR_DR)) {
status = NO_POLL_CHAR;
goto out;
}
status = serial_port_in(port, UART_RX);
out:
serial8250_rpm_put(up);
return status;
}
static void serial8250_put_poll_char(struct uart_port *port,
unsigned char c)
{
unsigned int ier;
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get(up);
/*
* First save the IER then disable the interrupts
*/
ier = serial_port_in(port, UART_IER);
if (up->capabilities & UART_CAP_UUE)
serial_port_out(port, UART_IER, UART_IER_UUE);
else
serial_port_out(port, UART_IER, 0);
wait_for_xmitr(up, BOTH_EMPTY);
/*
* Send the character out.
*/
serial_port_out(port, UART_TX, c);
/*
* Finally, wait for transmitter to become empty
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
serial_port_out(port, UART_IER, ier);
serial8250_rpm_put(up);
}
#endif /* CONFIG_CONSOLE_POLL */
int serial8250_do_startup(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
unsigned char lsr, iir;
int retval;
if (port->type == PORT_8250_CIR)
return -ENODEV;
if (!port->fifosize)
port->fifosize = uart_config[port->type].fifo_size;
if (!up->tx_loadsz)
up->tx_loadsz = uart_config[port->type].tx_loadsz;
if (!up->capabilities)
up->capabilities = uart_config[port->type].flags;
up->mcr = 0;
if (port->iotype != up->cur_iotype)
set_io_from_upio(port);
serial8250_rpm_get(up);
if (port->type == PORT_16C950) {
/* Wake up and initialize UART */
up->acr = 0;
serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
serial_port_out(port, UART_EFR, UART_EFR_ECB);
serial_port_out(port, UART_IER, 0);
serial_port_out(port, UART_LCR, 0);
serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
serial_port_out(port, UART_EFR, UART_EFR_ECB);
serial_port_out(port, UART_LCR, 0);
}
#ifdef CONFIG_SERIAL_8250_RSA
/*
* If this is an RSA port, see if we can kick it up to the
* higher speed clock.
*/
enable_rsa(up);
#endif
if (port->type == PORT_XR17V35X) {
/*
* First enable access to IER [7:5], ISR [5:4], FCR [5:4],
* MCR [7:5] and MSR [7:0]
*/
serial_port_out(port, UART_XR_EFR, UART_EFR_ECB);
/*
* Make sure all interrups are masked until initialization is
* complete and the FIFOs are cleared
*/
serial_port_out(port, UART_IER, 0);
}
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
*/
serial8250_clear_fifos(up);
/*
* Clear the interrupt registers.
*/
serial_port_in(port, UART_LSR);
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
/*
* At this point, there's no way the LSR could still be 0xff;
* if it is, then bail out, because there's likely no UART
* here.
*/
if (!(port->flags & UPF_BUGGY_UART) &&
(serial_port_in(port, UART_LSR) == 0xff)) {
printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
serial_index(port));
retval = -ENODEV;
goto out;
}
/*
* For a XR16C850, we need to set the trigger levels
*/
if (port->type == PORT_16850) {
unsigned char fctr;
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
serial_port_out(port, UART_FCTR,
fctr | UART_FCTR_TRGD | UART_FCTR_RX);
serial_port_out(port, UART_TRG, UART_TRG_96);
serial_port_out(port, UART_FCTR,
fctr | UART_FCTR_TRGD | UART_FCTR_TX);
serial_port_out(port, UART_TRG, UART_TRG_96);
serial_port_out(port, UART_LCR, 0);
}
if (port->irq) {
unsigned char iir1;
/*
* Test for UARTs that do not reassert THRE when the
* transmitter is idle and the interrupt has already
* been cleared. Real 16550s should always reassert
* this interrupt whenever the transmitter is idle and
* the interrupt is enabled. Delays are necessary to
* allow register changes to become visible.
*/
spin_lock_irqsave(&port->lock, flags);
if (up->port.irqflags & IRQF_SHARED)
disable_irq_nosync(port->irq);
wait_for_xmitr(up, UART_LSR_THRE);
serial_port_out_sync(port, UART_IER, UART_IER_THRI);
udelay(1); /* allow THRE to set */
iir1 = serial_port_in(port, UART_IIR);
serial_port_out(port, UART_IER, 0);
serial_port_out_sync(port, UART_IER, UART_IER_THRI);
udelay(1); /* allow a working UART time to re-assert THRE */
iir = serial_port_in(port, UART_IIR);
serial_port_out(port, UART_IER, 0);
if (port->irqflags & IRQF_SHARED)
enable_irq(port->irq);
spin_unlock_irqrestore(&port->lock, flags);
/*
* If the interrupt is not reasserted, or we otherwise
* don't trust the iir, setup a timer to kick the UART
* on a regular basis.
*/
if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
up->port.flags & UPF_BUG_THRE) {
up->bugs |= UART_BUG_THRE;
}
}
retval = up->ops->setup_irq(up);
if (retval)
goto out;
/*
* Now, initialize the UART
*/
serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
spin_lock_irqsave(&port->lock, flags);
if (up->port.flags & UPF_FOURPORT) {
if (!up->port.irq)
up->port.mctrl |= TIOCM_OUT1;
} else
/*
* Most PC uarts need OUT2 raised to enable interrupts.
*/
if (port->irq)
up->port.mctrl |= TIOCM_OUT2;
serial8250_set_mctrl(port, port->mctrl);
/* Serial over Lan (SoL) hack:
Intel 8257x Gigabit ethernet chips have a
16550 emulation, to be used for Serial Over Lan.
Those chips take a longer time than a normal
serial device to signalize that a transmission
data was queued. Due to that, the above test generally
fails. One solution would be to delay the reading of
iir. However, this is not reliable, since the timeout
is variable. So, let's just don't test if we receive
TX irq. This way, we'll never enable UART_BUG_TXEN.
*/
if (up->port.flags & UPF_NO_TXEN_TEST)
goto dont_test_tx_en;
/*
* Do a quick test to see if we receive an
* interrupt when we enable the TX irq.
*/
serial_port_out(port, UART_IER, UART_IER_THRI);
lsr = serial_port_in(port, UART_LSR);
iir = serial_port_in(port, UART_IIR);
serial_port_out(port, UART_IER, 0);
if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
if (!(up->bugs & UART_BUG_TXEN)) {
up->bugs |= UART_BUG_TXEN;
pr_debug("ttyS%d - enabling bad tx status workarounds\n",
serial_index(port));
}
} else {
up->bugs &= ~UART_BUG_TXEN;
}
dont_test_tx_en:
spin_unlock_irqrestore(&port->lock, flags);
/*
* Clear the interrupt registers again for luck, and clear the
* saved flags to avoid getting false values from polling
* routines or the previous session.
*/
serial_port_in(port, UART_LSR);
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
up->lsr_saved_flags = 0;
up->msr_saved_flags = 0;
/*
* Request DMA channels for both RX and TX.
*/
if (up->dma) {
retval = serial8250_request_dma(up);
if (retval) {
pr_warn_ratelimited("ttyS%d - failed to request DMA\n",
serial_index(port));
up->dma = NULL;
}
}
/*
* Set the IER shadow for rx interrupts but defer actual interrupt
* enable until after the FIFOs are enabled; otherwise, an already-
* active sender can swamp the interrupt handler with "too much work".
*/
up->ier = UART_IER_RLSI | UART_IER_RDI;
if (port->flags & UPF_FOURPORT) {
unsigned int icp;
/*
* Enable interrupts on the AST Fourport board
*/
icp = (port->iobase & 0xfe0) | 0x01f;
outb_p(0x80, icp);
inb_p(icp);
}
retval = 0;
out:
serial8250_rpm_put(up);
return retval;
}
EXPORT_SYMBOL_GPL(serial8250_do_startup);
static int serial8250_startup(struct uart_port *port)
{
if (port->startup)
return port->startup(port);
return serial8250_do_startup(port);
}
void serial8250_do_shutdown(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
serial8250_rpm_get(up);
/*
* Disable interrupts from this port
*/
up->ier = 0;
serial_port_out(port, UART_IER, 0);
if (up->dma)
serial8250_release_dma(up);
spin_lock_irqsave(&port->lock, flags);
if (port->flags & UPF_FOURPORT) {
/* reset interrupts on the AST Fourport board */
inb((port->iobase & 0xfe0) | 0x1f);
port->mctrl |= TIOCM_OUT1;
} else
port->mctrl &= ~TIOCM_OUT2;
serial8250_set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
/*
* Disable break condition and FIFOs
*/
serial_port_out(port, UART_LCR,
serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
serial8250_clear_fifos(up);
#ifdef CONFIG_SERIAL_8250_RSA
/*
* Reset the RSA board back to 115kbps compat mode.
*/
disable_rsa(up);
#endif
/*
* Read data port to reset things, and then unlink from
* the IRQ chain.
*/
serial_port_in(port, UART_RX);
serial8250_rpm_put(up);
up->ops->release_irq(up);
}
EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
static void serial8250_shutdown(struct uart_port *port)
{
if (port->shutdown)
port->shutdown(port);
else
serial8250_do_shutdown(port);
}
/*
* XR17V35x UARTs have an extra fractional divisor register (DLD)
* Calculate divisor with extra 4-bit fractional portion
*/
static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up,
unsigned int baud,
unsigned int *frac)
{
struct uart_port *port = &up->port;
unsigned int quot_16;
quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud);
*frac = quot_16 & 0x0f;
return quot_16 >> 4;
}
static unsigned int serial8250_get_divisor(struct uart_8250_port *up,
unsigned int baud,
unsigned int *frac)
{
struct uart_port *port = &up->port;
unsigned int quot;
/*
* Handle magic divisors for baud rates above baud_base on
* SMSC SuperIO chips.
*
*/
if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
baud == (port->uartclk/4))
quot = 0x8001;
else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
baud == (port->uartclk/8))
quot = 0x8002;
else if (up->port.type == PORT_XR17V35X)
quot = xr17v35x_get_divisor(up, baud, frac);
else
quot = uart_get_divisor(port, baud);
/*
* Oxford Semi 952 rev B workaround
*/
if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
quot++;
return quot;
}
static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
tcflag_t c_cflag)
{
unsigned char cval;
switch (c_cflag & CSIZE) {
case CS5:
cval = UART_LCR_WLEN5;
break;
case CS6:
cval = UART_LCR_WLEN6;
break;
case CS7:
cval = UART_LCR_WLEN7;
break;
default:
case CS8:
cval = UART_LCR_WLEN8;
break;
}
if (c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
if (c_cflag & PARENB) {
cval |= UART_LCR_PARITY;
if (up->bugs & UART_BUG_PARITY)
up->fifo_bug = true;
}
if (!(c_cflag & PARODD))
cval |= UART_LCR_EPAR;
#ifdef CMSPAR
if (c_cflag & CMSPAR)
cval |= UART_LCR_SPAR;
#endif
return cval;
}
static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
unsigned int quot, unsigned int quot_frac)
{
struct uart_8250_port *up = up_to_u8250p(port);
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
if (is_omap1510_8250(up)) {
if (baud == 115200) {
quot = 1;
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
} else
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
}
/*
* For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
* otherwise just set DLAB
*/
if (up->capabilities & UART_NATSEMI)
serial_port_out(port, UART_LCR, 0xe0);
else
serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
serial_dl_write(up, quot);
/* XR17V35x UARTs have an extra fractional divisor register (DLD) */
if (up->port.type == PORT_XR17V35X)
serial_port_out(port, 0x2, quot_frac);
}
void
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char cval;
unsigned long flags;
unsigned int baud, quot, frac = 0;
cval = serial8250_compute_lcr(up, termios->c_cflag);
/*
* Ask the core to calculate the divisor for us.
*/
baud = uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / 0xffff,
port->uartclk / 16);
quot = serial8250_get_divisor(up, baud, &frac);
/*
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
up->lcr = cval; /* Save computed LCR */
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
/* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
if ((baud < 2400 && !up->dma) || up->fifo_bug) {
up->fcr &= ~UART_FCR_TRIGGER_MASK;
up->fcr |= UART_FCR_TRIGGER_1;
}
}
/*
* MCR-based auto flow control. When AFE is enabled, RTS will be
* deasserted when the receive FIFO contains more characters than
* the trigger, or the MCR RTS bit is cleared. In the case where
* the remote UART is not using CTS auto flow control, we must
* have sufficient FIFO entries for the latency of the remote
* UART to respond. IOW, at least 32 bytes of FIFO.
*/
if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
up->mcr &= ~UART_MCR_AFE;
if (termios->c_cflag & CRTSCTS)
up->mcr |= UART_MCR_AFE;
}
/*
* Update the per-port timeout.
*/
uart_update_timeout(port, termios->c_cflag, baud);
port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
if (termios->c_iflag & INPCK)
port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
port->read_status_mask |= UART_LSR_BI;
/*
* Characteres to ignore
*/
port->ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
if (termios->c_iflag & IGNBRK) {
port->ignore_status_mask |= UART_LSR_BI;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= UART_LSR_OE;
}
/*
* ignore all characters if CREAD is not set
*/
if ((termios->c_cflag & CREAD) == 0)
port->ignore_status_mask |= UART_LSR_DR;
/*
* CTS flow control flag and modem status interrupts
*/
up->ier &= ~UART_IER_MSI;
if (!(up->bugs & UART_BUG_NOMSR) &&
UART_ENABLE_MS(&up->port, termios->c_cflag))
up->ier |= UART_IER_MSI;
if (up->capabilities & UART_CAP_UUE)
up->ier |= UART_IER_UUE;
if (up->capabilities & UART_CAP_RTOIE)
up->ier |= UART_IER_RTOIE;
serial_port_out(port, UART_IER, up->ier);
if (up->capabilities & UART_CAP_EFR) {
unsigned char efr = 0;
/*
* TI16C752/Startech hardware flow control. FIXME:
* - TI16C752 requires control thresholds to be set.
* - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
*/
if (termios->c_cflag & CRTSCTS)
efr |= UART_EFR_CTS;
serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
if (port->flags & UPF_EXAR_EFR)
serial_port_out(port, UART_XR_EFR, efr);
else
serial_port_out(port, UART_EFR, efr);
}
serial8250_set_divisor(port, baud, quot, frac);
/*
* LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
* is written without DLAB set, this mode will be disabled.
*/
if (port->type == PORT_16750)
serial_port_out(port, UART_FCR, up->fcr);
serial_port_out(port, UART_LCR, up->lcr); /* reset DLAB */
if (port->type != PORT_16750) {
/* emulated UARTs (Lucent Venus 167x) need two steps */
if (up->fcr & UART_FCR_ENABLE_FIFO)
serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
}
serial8250_set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
/* Don't rewrite B0 */
if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud);
}
EXPORT_SYMBOL(serial8250_do_set_termios);
static void
serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
if (port->set_termios)
port->set_termios(port, termios, old);
else
serial8250_do_set_termios(port, termios, old);
}
static void
serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
{
if (termios->c_line == N_PPS) {
port->flags |= UPF_HARDPPS_CD;
spin_lock_irq(&port->lock);
serial8250_enable_ms(port);
spin_unlock_irq(&port->lock);
} else {
port->flags &= ~UPF_HARDPPS_CD;
if (!UART_ENABLE_MS(port, termios->c_cflag)) {
spin_lock_irq(&port->lock);
serial8250_disable_ms(port);
spin_unlock_irq(&port->lock);
}
}
}
void serial8250_do_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct uart_8250_port *p = up_to_u8250p(port);
serial8250_set_sleep(p, state != 0);
}
EXPORT_SYMBOL(serial8250_do_pm);
static void
serial8250_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
if (port->pm)
port->pm(port, state, oldstate);
else
serial8250_do_pm(port, state, oldstate);
}
static unsigned int serial8250_port_size(struct uart_8250_port *pt)
{
if (pt->port.mapsize)
return pt->port.mapsize;
if (pt->port.iotype == UPIO_AU) {
if (pt->port.type == PORT_RT2880)
return 0x100;
return 0x1000;
}
if (is_omap1_8250(pt))
return 0x16 << pt->port.regshift;
return 8 << pt->port.regshift;
}
/*
* Resource handling.
*/
static int serial8250_request_std_resource(struct uart_8250_port *up)
{
unsigned int size = serial8250_port_size(up);
struct uart_port *port = &up->port;
int ret = 0;
switch (port->iotype) {
case UPIO_AU:
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_MEM:
if (!port->mapbase)
break;
if (!request_mem_region(port->mapbase, size, "serial")) {
ret = -EBUSY;
break;
}
if (port->flags & UPF_IOREMAP) {
port->membase = ioremap_nocache(port->mapbase, size);
if (!port->membase) {
release_mem_region(port->mapbase, size);
ret = -ENOMEM;
}
}
break;
case UPIO_HUB6:
case UPIO_PORT:
if (!request_region(port->iobase, size, "serial"))
ret = -EBUSY;
break;
}
return ret;
}
static void serial8250_release_std_resource(struct uart_8250_port *up)
{
unsigned int size = serial8250_port_size(up);
struct uart_port *port = &up->port;
switch (port->iotype) {
case UPIO_AU:
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_MEM:
if (!port->mapbase)
break;
if (port->flags & UPF_IOREMAP) {
iounmap(port->membase);
port->membase = NULL;
}
release_mem_region(port->mapbase, size);
break;
case UPIO_HUB6:
case UPIO_PORT:
release_region(port->iobase, size);
break;
}
}
static void serial8250_release_port(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_release_std_resource(up);
}
static int serial8250_request_port(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
int ret;
if (port->type == PORT_8250_CIR)
return -ENODEV;
ret = serial8250_request_std_resource(up);
return ret;
}
static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
unsigned char bytes;
bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
return bytes ? bytes : -EOPNOTSUPP;
}
static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
int i;
if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
return -EOPNOTSUPP;
for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
if (bytes < conf_type->rxtrig_bytes[i])
/* Use the nearest lower value */
return (--i) << UART_FCR_R_TRIG_SHIFT;
}
return UART_FCR_R_TRIG_11;
}
static int do_get_rxtrig(struct tty_port *port)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
struct uart_8250_port *up =
container_of(uport, struct uart_8250_port, port);
if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
return -EINVAL;
return fcr_get_rxtrig_bytes(up);
}
static int do_serial8250_get_rxtrig(struct tty_port *port)
{
int rxtrig_bytes;
mutex_lock(&port->mutex);
rxtrig_bytes = do_get_rxtrig(port);
mutex_unlock(&port->mutex);
return rxtrig_bytes;
}
static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tty_port *port = dev_get_drvdata(dev);
int rxtrig_bytes;
rxtrig_bytes = do_serial8250_get_rxtrig(port);
if (rxtrig_bytes < 0)
return rxtrig_bytes;
return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
}
static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
struct uart_8250_port *up =
container_of(uport, struct uart_8250_port, port);
int rxtrig;
if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
up->fifo_bug)
return -EINVAL;
rxtrig = bytes_to_fcr_rxtrig(up, bytes);
if (rxtrig < 0)
return rxtrig;
serial8250_clear_fifos(up);
up->fcr &= ~UART_FCR_TRIGGER_MASK;
up->fcr |= (unsigned char)rxtrig;
serial_out(up, UART_FCR, up->fcr);
return 0;
}
static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
{
int ret;
mutex_lock(&port->mutex);
ret = do_set_rxtrig(port, bytes);
mutex_unlock(&port->mutex);
return ret;
}
static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct tty_port *port = dev_get_drvdata(dev);
unsigned char bytes;
int ret;
if (!count)
return -EINVAL;
ret = kstrtou8(buf, 10, &bytes);
if (ret < 0)
return ret;
ret = do_serial8250_set_rxtrig(port, bytes);
if (ret < 0)
return ret;
return count;
}
static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
serial8250_get_attr_rx_trig_bytes,
serial8250_set_attr_rx_trig_bytes);
static struct attribute *serial8250_dev_attrs[] = {
&dev_attr_rx_trig_bytes.attr,
NULL,
};
static struct attribute_group serial8250_dev_attr_group = {
.attrs = serial8250_dev_attrs,
};
static void register_dev_spec_attr_grp(struct uart_8250_port *up)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
if (conf_type->rxtrig_bytes[0])
up->port.attr_group = &serial8250_dev_attr_group;
}
static void serial8250_config_port(struct uart_port *port, int flags)
{
struct uart_8250_port *up = up_to_u8250p(port);
int ret;
if (port->type == PORT_8250_CIR)
return;
/*
* Find the region that we can probe for. This in turn
* tells us whether we can probe for the type of port.
*/
ret = serial8250_request_std_resource(up);
if (ret < 0)
return;
if (port->iotype != up->cur_iotype)
set_io_from_upio(port);
if (flags & UART_CONFIG_TYPE)
autoconfig(up);
/* if access method is AU, it is a 16550 with a quirk */
if (port->type == PORT_16550A && port->iotype == UPIO_AU)
up->bugs |= UART_BUG_NOMSR;
/* HW bugs may trigger IRQ while IIR == NO_INT */
if (port->type == PORT_TEGRA)
up->bugs |= UART_BUG_NOMSR;
if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
autoconfig_irq(up);
if (port->type == PORT_UNKNOWN)
serial8250_release_std_resource(up);
/* Fixme: probably not the best place for this */
if ((port->type == PORT_XR17V35X) ||
(port->type == PORT_XR17D15X))
port->handle_irq = exar_handle_irq;
register_dev_spec_attr_grp(up);
up->fcr = uart_config[up->port.type].fcr;
}
static int
serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
{
if (ser->irq >= nr_irqs || ser->irq < 0 ||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
ser->type == PORT_STARTECH)
return -EINVAL;
return 0;
}
static const char *
serial8250_type(struct uart_port *port)
{
int type = port->type;
if (type >= ARRAY_SIZE(uart_config))
type = 0;
return uart_config[type].name;
}
static const struct uart_ops serial8250_pops = {
.tx_empty = serial8250_tx_empty,
.set_mctrl = serial8250_set_mctrl,
.get_mctrl = serial8250_get_mctrl,
.stop_tx = serial8250_stop_tx,
.start_tx = serial8250_start_tx,
.throttle = serial8250_throttle,
.unthrottle = serial8250_unthrottle,
.stop_rx = serial8250_stop_rx,
.enable_ms = serial8250_enable_ms,
.break_ctl = serial8250_break_ctl,
.startup = serial8250_startup,
.shutdown = serial8250_shutdown,
.set_termios = serial8250_set_termios,
.set_ldisc = serial8250_set_ldisc,
.pm = serial8250_pm,
.type = serial8250_type,
.release_port = serial8250_release_port,
.request_port = serial8250_request_port,
.config_port = serial8250_config_port,
.verify_port = serial8250_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = serial8250_get_poll_char,
.poll_put_char = serial8250_put_poll_char,
#endif
};
void serial8250_init_port(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
spin_lock_init(&port->lock);
port->ops = &serial8250_pops;
up->cur_iotype = 0xFF;
}
EXPORT_SYMBOL_GPL(serial8250_init_port);
void serial8250_set_defaults(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
if (up->port.flags & UPF_FIXED_TYPE) {
unsigned int type = up->port.type;
if (!up->port.fifosize)
up->port.fifosize = uart_config[type].fifo_size;
if (!up->tx_loadsz)
up->tx_loadsz = uart_config[type].tx_loadsz;
if (!up->capabilities)
up->capabilities = uart_config[type].flags;
}
set_io_from_upio(port);
/* default dma handlers */
if (up->dma) {
if (!up->dma->tx_dma)
up->dma->tx_dma = serial8250_tx_dma;
if (!up->dma->rx_dma)
up->dma->rx_dma = serial8250_rx_dma;
}
}
EXPORT_SYMBOL_GPL(serial8250_set_defaults);
#ifdef CONFIG_SERIAL_8250_CONSOLE
static void serial8250_console_putchar(struct uart_port *port, int ch)
{
struct uart_8250_port *up = up_to_u8250p(port);
wait_for_xmitr(up, UART_LSR_THRE);
serial_port_out(port, UART_TX, ch);
}
/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
*
* The console_lock must be held when we get here.
*/
void serial8250_console_write(struct uart_8250_port *up, const char *s,
unsigned int count)
{
struct uart_port *port = &up->port;
unsigned long flags;
unsigned int ier;
int locked = 1;
touch_nmi_watchdog();
serial8250_rpm_get(up);
if (port->sysrq)
locked = 0;
else if (oops_in_progress)
locked = spin_trylock_irqsave(&port->lock, flags);
else
spin_lock_irqsave(&port->lock, flags);
/*
* First save the IER then disable the interrupts
*/
ier = serial_port_in(port, UART_IER);
if (up->capabilities & UART_CAP_UUE)
serial_port_out(port, UART_IER, UART_IER_UUE);
else
serial_port_out(port, UART_IER, 0);
/* check scratch reg to see if port powered off during system sleep */
if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
struct ktermios termios;
unsigned int baud, quot, frac = 0;
termios.c_cflag = port->cons->cflag;
if (port->state->port.tty && termios.c_cflag == 0)
termios.c_cflag = port->state->port.tty->termios.c_cflag;
baud = uart_get_baud_rate(port, &termios, NULL,
port->uartclk / 16 / 0xffff,
port->uartclk / 16);
quot = serial8250_get_divisor(up, baud, &frac);
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);
up->canary = 0;
}
uart_console_write(port, s, count, serial8250_console_putchar);
/*
* Finally, wait for transmitter to become empty
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
serial_port_out(port, UART_IER, ier);
/*
* The receive handling will happen properly because the
* receive ready bit will still be set; it is not cleared
* on read. However, modem control will not, we must
* call it if we have saved something in the saved flags
* while processing with interrupts off.
*/
if (up->msr_saved_flags)
serial8250_modem_status(up);
if (locked)
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
}
static unsigned int probe_baud(struct uart_port *port)
{
unsigned char lcr, dll, dlm;
unsigned int quot;
lcr = serial_port_in(port, UART_LCR);
serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
dll = serial_port_in(port, UART_DLL);
dlm = serial_port_in(port, UART_DLM);
serial_port_out(port, UART_LCR, lcr);
quot = (dlm << 8) | dll;
return (port->uartclk / 16) / quot;
}
int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
{
int baud = 9600;
int bits = 8;
int parity = 'n';
int flow = 'n';
if (!port->iobase && !port->membase)
return -ENODEV;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else if (probe)
baud = probe_baud(port);
return uart_set_options(port, port->cons, baud, parity, bits, flow);
}
#endif /* CONFIG_SERIAL_8250_CONSOLE */
...@@ -218,6 +218,7 @@ static int uniphier_uart_probe(struct platform_device *pdev) ...@@ -218,6 +218,7 @@ static int uniphier_uart_probe(struct platform_device *pdev)
ret = serial8250_register_8250_port(&up); ret = serial8250_register_8250_port(&up);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to register 8250 port\n"); dev_err(dev, "failed to register 8250 port\n");
clk_disable_unprepare(priv->clk);
return ret; return ret;
} }
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
# Makefile for the 8250 serial device drivers. # Makefile for the 8250 serial device drivers.
# #
obj-$(CONFIG_SERIAL_8250) += 8250.o obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o
8250-y := 8250_core.o 8250-y := 8250_core.o
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
8250-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o 8250_base-y := 8250_port.o
8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
......
...@@ -47,12 +47,12 @@ config SERIAL_AMBA_PL010_CONSOLE ...@@ -47,12 +47,12 @@ config SERIAL_AMBA_PL010_CONSOLE
config SERIAL_AMBA_PL011 config SERIAL_AMBA_PL011
tristate "ARM AMBA PL011 serial port support" tristate "ARM AMBA PL011 serial port support"
depends on ARM_AMBA depends on ARM_AMBA || SOC_ZX296702
select SERIAL_CORE select SERIAL_CORE
help help
This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have
an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M
here. here. Say Y or M if you have SOC_ZX296702.
If unsure, say N. If unsure, say N.
...@@ -594,7 +594,7 @@ config SERIAL_IMX_CONSOLE ...@@ -594,7 +594,7 @@ config SERIAL_IMX_CONSOLE
config SERIAL_UARTLITE config SERIAL_UARTLITE
tristate "Xilinx uartlite serial port support" tristate "Xilinx uartlite serial port support"
depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE || ARCH_ZYNQ depends on HAS_IOMEM
select SERIAL_CORE select SERIAL_CORE
help help
Say Y here if you want to use the Xilinx uartlite serial controller. Say Y here if you want to use the Xilinx uartlite serial controller.
...@@ -1067,6 +1067,7 @@ config SERIAL_ETRAXFS ...@@ -1067,6 +1067,7 @@ config SERIAL_ETRAXFS
bool "ETRAX FS serial port support" bool "ETRAX FS serial port support"
depends on ETRAX_ARCH_V32 && OF depends on ETRAX_ARCH_V32 && OF
select SERIAL_CORE select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
config SERIAL_ETRAXFS_CONSOLE config SERIAL_ETRAXFS_CONSOLE
bool "ETRAX FS serial console support" bool "ETRAX FS serial console support"
...@@ -1376,7 +1377,8 @@ config SERIAL_ALTERA_UART_CONSOLE ...@@ -1376,7 +1377,8 @@ config SERIAL_ALTERA_UART_CONSOLE
config SERIAL_IFX6X60 config SERIAL_IFX6X60
tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)" tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
depends on GPIOLIB && SPI && HAS_DMA depends on GPIOLIB || COMPILE_TEST
depends on SPI && HAS_DMA
help help
Support for the IFX6x60 modem devices on Intel MID platforms. Support for the IFX6x60 modem devices on Intel MID platforms.
......
...@@ -74,8 +74,13 @@ ...@@ -74,8 +74,13 @@
/* There is by now at least one vendor with differing details, so handle it */ /* There is by now at least one vendor with differing details, so handle it */
struct vendor_data { struct vendor_data {
unsigned int ifls; unsigned int ifls;
unsigned int fr_busy;
unsigned int fr_dsr;
unsigned int fr_cts;
unsigned int fr_ri;
unsigned int lcrh_tx; unsigned int lcrh_tx;
unsigned int lcrh_rx; unsigned int lcrh_rx;
u16 *reg_lut;
bool oversampling; bool oversampling;
bool dma_threshold; bool dma_threshold;
bool cts_event_workaround; bool cts_event_workaround;
...@@ -85,6 +90,48 @@ struct vendor_data { ...@@ -85,6 +90,48 @@ struct vendor_data {
unsigned int (*get_fifosize)(struct amba_device *dev); unsigned int (*get_fifosize)(struct amba_device *dev);
}; };
/* Max address offset of register in use is 0x48 */
#define REG_NR (0x48 >> 2)
#define IDX(x) (x >> 2)
enum reg_idx {
REG_DR = IDX(UART01x_DR),
REG_RSR = IDX(UART01x_RSR),
REG_ST_DMAWM = IDX(ST_UART011_DMAWM),
REG_FR = IDX(UART01x_FR),
REG_ST_LCRH_RX = IDX(ST_UART011_LCRH_RX),
REG_ILPR = IDX(UART01x_ILPR),
REG_IBRD = IDX(UART011_IBRD),
REG_FBRD = IDX(UART011_FBRD),
REG_LCRH = IDX(UART011_LCRH),
REG_CR = IDX(UART011_CR),
REG_IFLS = IDX(UART011_IFLS),
REG_IMSC = IDX(UART011_IMSC),
REG_RIS = IDX(UART011_RIS),
REG_MIS = IDX(UART011_MIS),
REG_ICR = IDX(UART011_ICR),
REG_DMACR = IDX(UART011_DMACR),
};
static u16 arm_reg[] = {
[REG_DR] = UART01x_DR,
[REG_RSR] = UART01x_RSR,
[REG_ST_DMAWM] = ~0,
[REG_FR] = UART01x_FR,
[REG_ST_LCRH_RX] = ~0,
[REG_ILPR] = UART01x_ILPR,
[REG_IBRD] = UART011_IBRD,
[REG_FBRD] = UART011_FBRD,
[REG_LCRH] = UART011_LCRH,
[REG_CR] = UART011_CR,
[REG_IFLS] = UART011_IFLS,
[REG_IMSC] = UART011_IMSC,
[REG_RIS] = UART011_RIS,
[REG_MIS] = UART011_MIS,
[REG_ICR] = UART011_ICR,
[REG_DMACR] = UART011_DMACR,
};
#ifdef CONFIG_ARM_AMBA
static unsigned int get_fifosize_arm(struct amba_device *dev) static unsigned int get_fifosize_arm(struct amba_device *dev)
{ {
return amba_rev(dev) < 3 ? 16 : 32; return amba_rev(dev) < 3 ? 16 : 32;
...@@ -92,8 +139,13 @@ static unsigned int get_fifosize_arm(struct amba_device *dev) ...@@ -92,8 +139,13 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
static struct vendor_data vendor_arm = { static struct vendor_data vendor_arm = {
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.lcrh_tx = UART011_LCRH, .fr_busy = UART01x_FR_BUSY,
.lcrh_rx = UART011_LCRH, .fr_dsr = UART01x_FR_DSR,
.fr_cts = UART01x_FR_CTS,
.fr_ri = UART011_FR_RI,
.lcrh_tx = REG_LCRH,
.lcrh_rx = REG_LCRH,
.reg_lut = arm_reg,
.oversampling = false, .oversampling = false,
.dma_threshold = false, .dma_threshold = false,
.cts_event_workaround = false, .cts_event_workaround = false,
...@@ -101,8 +153,14 @@ static struct vendor_data vendor_arm = { ...@@ -101,8 +153,14 @@ static struct vendor_data vendor_arm = {
.fixed_options = false, .fixed_options = false,
.get_fifosize = get_fifosize_arm, .get_fifosize = get_fifosize_arm,
}; };
#endif
static struct vendor_data vendor_sbsa = { static struct vendor_data vendor_sbsa = {
.fr_busy = UART01x_FR_BUSY,
.fr_dsr = UART01x_FR_DSR,
.fr_cts = UART01x_FR_CTS,
.fr_ri = UART011_FR_RI,
.reg_lut = arm_reg,
.oversampling = false, .oversampling = false,
.dma_threshold = false, .dma_threshold = false,
.cts_event_workaround = false, .cts_event_workaround = false,
...@@ -110,6 +168,26 @@ static struct vendor_data vendor_sbsa = { ...@@ -110,6 +168,26 @@ static struct vendor_data vendor_sbsa = {
.fixed_options = true, .fixed_options = true,
}; };
#ifdef CONFIG_ARM_AMBA
static u16 st_reg[] = {
[REG_DR] = UART01x_DR,
[REG_RSR] = UART01x_RSR,
[REG_ST_DMAWM] = ST_UART011_DMAWM,
[REG_FR] = UART01x_FR,
[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
[REG_ILPR] = UART01x_ILPR,
[REG_IBRD] = UART011_IBRD,
[REG_FBRD] = UART011_FBRD,
[REG_LCRH] = UART011_LCRH,
[REG_CR] = UART011_CR,
[REG_IFLS] = UART011_IFLS,
[REG_IMSC] = UART011_IMSC,
[REG_RIS] = UART011_RIS,
[REG_MIS] = UART011_MIS,
[REG_ICR] = UART011_ICR,
[REG_DMACR] = UART011_DMACR,
};
static unsigned int get_fifosize_st(struct amba_device *dev) static unsigned int get_fifosize_st(struct amba_device *dev)
{ {
return 64; return 64;
...@@ -117,8 +195,13 @@ static unsigned int get_fifosize_st(struct amba_device *dev) ...@@ -117,8 +195,13 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
static struct vendor_data vendor_st = { static struct vendor_data vendor_st = {
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
.lcrh_tx = ST_UART011_LCRH_TX, .fr_busy = UART01x_FR_BUSY,
.lcrh_rx = ST_UART011_LCRH_RX, .fr_dsr = UART01x_FR_DSR,
.fr_cts = UART01x_FR_CTS,
.fr_ri = UART011_FR_RI,
.lcrh_tx = REG_LCRH,
.lcrh_rx = REG_ST_LCRH_RX,
.reg_lut = st_reg,
.oversampling = true, .oversampling = true,
.dma_threshold = true, .dma_threshold = true,
.cts_event_workaround = true, .cts_event_workaround = true,
...@@ -126,6 +209,43 @@ static struct vendor_data vendor_st = { ...@@ -126,6 +209,43 @@ static struct vendor_data vendor_st = {
.fixed_options = false, .fixed_options = false,
.get_fifosize = get_fifosize_st, .get_fifosize = get_fifosize_st,
}; };
#endif
#ifdef CONFIG_SOC_ZX296702
static u16 zte_reg[] = {
[REG_DR] = ZX_UART01x_DR,
[REG_RSR] = UART01x_RSR,
[REG_ST_DMAWM] = ST_UART011_DMAWM,
[REG_FR] = ZX_UART01x_FR,
[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
[REG_ILPR] = UART01x_ILPR,
[REG_IBRD] = UART011_IBRD,
[REG_FBRD] = UART011_FBRD,
[REG_LCRH] = ZX_UART011_LCRH_TX,
[REG_CR] = ZX_UART011_CR,
[REG_IFLS] = ZX_UART011_IFLS,
[REG_IMSC] = ZX_UART011_IMSC,
[REG_RIS] = ZX_UART011_RIS,
[REG_MIS] = ZX_UART011_MIS,
[REG_ICR] = ZX_UART011_ICR,
[REG_DMACR] = ZX_UART011_DMACR,
};
static struct vendor_data vendor_zte = {
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.fr_busy = ZX_UART01x_FR_BUSY,
.fr_dsr = ZX_UART01x_FR_DSR,
.fr_cts = ZX_UART01x_FR_CTS,
.fr_ri = ZX_UART011_FR_RI,
.lcrh_tx = REG_LCRH,
.lcrh_rx = REG_ST_LCRH_RX,
.reg_lut = zte_reg,
.oversampling = false,
.dma_threshold = false,
.cts_event_workaround = false,
.fixed_options = false,
};
#endif
/* Deals with DMA transactions */ /* Deals with DMA transactions */
...@@ -164,10 +284,15 @@ struct uart_amba_port { ...@@ -164,10 +284,15 @@ struct uart_amba_port {
struct uart_port port; struct uart_port port;
struct clk *clk; struct clk *clk;
const struct vendor_data *vendor; const struct vendor_data *vendor;
u16 *reg_lut;
unsigned int dmacr; /* dma control reg */ unsigned int dmacr; /* dma control reg */
unsigned int im; /* interrupt mask */ unsigned int im; /* interrupt mask */
unsigned int old_status; unsigned int old_status;
unsigned int fifosize; /* vendor-specific */ unsigned int fifosize; /* vendor-specific */
unsigned int fr_busy; /* vendor-specific */
unsigned int fr_dsr; /* vendor-specific */
unsigned int fr_cts; /* vendor-specific */
unsigned int fr_ri; /* vendor-specific */
unsigned int lcrh_tx; /* vendor-specific */ unsigned int lcrh_tx; /* vendor-specific */
unsigned int lcrh_rx; /* vendor-specific */ unsigned int lcrh_rx; /* vendor-specific */
unsigned int old_cr; /* state during shutdown */ unsigned int old_cr; /* state during shutdown */
...@@ -184,6 +309,29 @@ struct uart_amba_port { ...@@ -184,6 +309,29 @@ struct uart_amba_port {
#endif #endif
}; };
static bool is_implemented(struct uart_amba_port *uap, unsigned int reg)
{
return uap->reg_lut[reg] != (u16)~0;
}
static unsigned int pl011_readw(struct uart_amba_port *uap, int index)
{
WARN_ON(index > REG_NR);
return readw_relaxed(uap->port.membase + uap->reg_lut[index]);
}
static void pl011_writew(struct uart_amba_port *uap, int val, int index)
{
WARN_ON(index > REG_NR);
writew_relaxed(val, uap->port.membase + uap->reg_lut[index]);
}
static void pl011_writeb(struct uart_amba_port *uap, u8 val, int index)
{
WARN_ON(index > REG_NR);
writeb_relaxed(val, uap->port.membase + uap->reg_lut[index]);
}
/* /*
* Reads up to 256 characters from the FIFO or until it's empty and * Reads up to 256 characters from the FIFO or until it's empty and
* inserts them into the TTY layer. Returns the number of characters * inserts them into the TTY layer. Returns the number of characters
...@@ -196,12 +344,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) ...@@ -196,12 +344,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
int fifotaken = 0; int fifotaken = 0;
while (max_count--) { while (max_count--) {
status = readw(uap->port.membase + UART01x_FR); status = pl011_readw(uap, REG_FR);
if (status & UART01x_FR_RXFE) if (status & UART01x_FR_RXFE)
break; break;
/* Take chars from the FIFO and update status */ /* Take chars from the FIFO and update status */
ch = readw(uap->port.membase + UART01x_DR) | ch = pl011_readw(uap, REG_DR) |
UART_DUMMY_DR_RX; UART_DUMMY_DR_RX;
flag = TTY_NORMAL; flag = TTY_NORMAL;
uap->port.icount.rx++; uap->port.icount.rx++;
...@@ -284,7 +432,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap) ...@@ -284,7 +432,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev); struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
struct device *dev = uap->port.dev; struct device *dev = uap->port.dev;
struct dma_slave_config tx_conf = { struct dma_slave_config tx_conf = {
.dst_addr = uap->port.mapbase + UART01x_DR, .dst_addr = uap->port.mapbase + uap->reg_lut[REG_DR],
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_MEM_TO_DEV, .direction = DMA_MEM_TO_DEV,
.dst_maxburst = uap->fifosize >> 1, .dst_maxburst = uap->fifosize >> 1,
...@@ -339,7 +487,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap) ...@@ -339,7 +487,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
if (chan) { if (chan) {
struct dma_slave_config rx_conf = { struct dma_slave_config rx_conf = {
.src_addr = uap->port.mapbase + UART01x_DR, .src_addr = uap->port.mapbase + uap->reg_lut[REG_DR],
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_DEV_TO_MEM, .direction = DMA_DEV_TO_MEM,
.src_maxburst = uap->fifosize >> 2, .src_maxburst = uap->fifosize >> 2,
...@@ -438,7 +586,7 @@ static void pl011_dma_tx_callback(void *data) ...@@ -438,7 +586,7 @@ static void pl011_dma_tx_callback(void *data)
dmacr = uap->dmacr; dmacr = uap->dmacr;
uap->dmacr = dmacr & ~UART011_TXDMAE; uap->dmacr = dmacr & ~UART011_TXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
/* /*
* If TX DMA was disabled, it means that we've stopped the DMA for * If TX DMA was disabled, it means that we've stopped the DMA for
...@@ -552,7 +700,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) ...@@ -552,7 +700,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
dma_dev->device_issue_pending(chan); dma_dev->device_issue_pending(chan);
uap->dmacr |= UART011_TXDMAE; uap->dmacr |= UART011_TXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->dmatx.queued = true; uap->dmatx.queued = true;
/* /*
...@@ -588,9 +736,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) ...@@ -588,9 +736,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
*/ */
if (uap->dmatx.queued) { if (uap->dmatx.queued) {
uap->dmacr |= UART011_TXDMAE; uap->dmacr |= UART011_TXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
return true; return true;
} }
...@@ -600,7 +748,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) ...@@ -600,7 +748,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
*/ */
if (pl011_dma_tx_refill(uap) > 0) { if (pl011_dma_tx_refill(uap) > 0) {
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
return true; return true;
} }
return false; return false;
...@@ -614,7 +762,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap) ...@@ -614,7 +762,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
{ {
if (uap->dmatx.queued) { if (uap->dmatx.queued) {
uap->dmacr &= ~UART011_TXDMAE; uap->dmacr &= ~UART011_TXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
} }
} }
...@@ -640,14 +788,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) ...@@ -640,14 +788,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
if (!uap->dmatx.queued) { if (!uap->dmatx.queued) {
if (pl011_dma_tx_refill(uap) > 0) { if (pl011_dma_tx_refill(uap) > 0) {
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + pl011_writew(uap, uap->im, REG_IMSC);
UART011_IMSC);
} else } else
ret = false; ret = false;
} else if (!(uap->dmacr & UART011_TXDMAE)) { } else if (!(uap->dmacr & UART011_TXDMAE)) {
uap->dmacr |= UART011_TXDMAE; uap->dmacr |= UART011_TXDMAE;
writew(uap->dmacr, pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->port.membase + UART011_DMACR);
} }
return ret; return ret;
} }
...@@ -658,9 +804,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) ...@@ -658,9 +804,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
*/ */
dmacr = uap->dmacr; dmacr = uap->dmacr;
uap->dmacr &= ~UART011_TXDMAE; uap->dmacr &= ~UART011_TXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) { if (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF) {
/* /*
* No space in the FIFO, so enable the transmit interrupt * No space in the FIFO, so enable the transmit interrupt
* so we know when there is space. Note that once we've * so we know when there is space. Note that once we've
...@@ -669,13 +815,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) ...@@ -669,13 +815,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
return false; return false;
} }
writew(uap->port.x_char, uap->port.membase + UART01x_DR); pl011_writew(uap, uap->port.x_char, REG_DR);
uap->port.icount.tx++; uap->port.icount.tx++;
uap->port.x_char = 0; uap->port.x_char = 0;
/* Success - restore the DMA state */ /* Success - restore the DMA state */
uap->dmacr = dmacr; uap->dmacr = dmacr;
writew(dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, dmacr, REG_DMACR);
return true; return true;
} }
...@@ -703,7 +849,7 @@ __acquires(&uap->port.lock) ...@@ -703,7 +849,7 @@ __acquires(&uap->port.lock)
DMA_TO_DEVICE); DMA_TO_DEVICE);
uap->dmatx.queued = false; uap->dmatx.queued = false;
uap->dmacr &= ~UART011_TXDMAE; uap->dmacr &= ~UART011_TXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
} }
} }
...@@ -743,11 +889,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) ...@@ -743,11 +889,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
dma_async_issue_pending(rxchan); dma_async_issue_pending(rxchan);
uap->dmacr |= UART011_RXDMAE; uap->dmacr |= UART011_RXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->dmarx.running = true; uap->dmarx.running = true;
uap->im &= ~UART011_RXIM; uap->im &= ~UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
return 0; return 0;
} }
...@@ -805,8 +951,9 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, ...@@ -805,8 +951,9 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
*/ */
if (dma_count == pending && readfifo) { if (dma_count == pending && readfifo) {
/* Clear any error flags */ /* Clear any error flags */
writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, pl011_writew(uap,
uap->port.membase + UART011_ICR); UART011_OEIS | UART011_BEIS | UART011_PEIS
| UART011_FEIS, REG_ICR);
/* /*
* If we read all the DMA'd characters, and we had an * If we read all the DMA'd characters, and we had an
...@@ -854,7 +1001,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) ...@@ -854,7 +1001,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
/* Disable RX DMA - incoming data will wait in the FIFO */ /* Disable RX DMA - incoming data will wait in the FIFO */
uap->dmacr &= ~UART011_RXDMAE; uap->dmacr &= ~UART011_RXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->dmarx.running = false; uap->dmarx.running = false;
pending = sgbuf->sg.length - state.residue; pending = sgbuf->sg.length - state.residue;
...@@ -874,7 +1021,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) ...@@ -874,7 +1021,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
dev_dbg(uap->port.dev, "could not retrigger RX DMA job " dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
"fall back to interrupt mode\n"); "fall back to interrupt mode\n");
uap->im |= UART011_RXIM; uap->im |= UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
} }
} }
...@@ -922,7 +1069,7 @@ static void pl011_dma_rx_callback(void *data) ...@@ -922,7 +1069,7 @@ static void pl011_dma_rx_callback(void *data)
dev_dbg(uap->port.dev, "could not retrigger RX DMA job " dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
"fall back to interrupt mode\n"); "fall back to interrupt mode\n");
uap->im |= UART011_RXIM; uap->im |= UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
} }
} }
...@@ -935,7 +1082,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) ...@@ -935,7 +1082,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
{ {
/* FIXME. Just disable the DMA enable */ /* FIXME. Just disable the DMA enable */
uap->dmacr &= ~UART011_RXDMAE; uap->dmacr &= ~UART011_RXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
} }
/* /*
...@@ -979,7 +1126,7 @@ static void pl011_dma_rx_poll(unsigned long args) ...@@ -979,7 +1126,7 @@ static void pl011_dma_rx_poll(unsigned long args)
spin_lock_irqsave(&uap->port.lock, flags); spin_lock_irqsave(&uap->port.lock, flags);
pl011_dma_rx_stop(uap); pl011_dma_rx_stop(uap);
uap->im |= UART011_RXIM; uap->im |= UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
spin_unlock_irqrestore(&uap->port.lock, flags); spin_unlock_irqrestore(&uap->port.lock, flags);
uap->dmarx.running = false; uap->dmarx.running = false;
...@@ -1041,7 +1188,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap) ...@@ -1041,7 +1188,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
skip_rx: skip_rx:
/* Turn on DMA error (RX/TX will be enabled on demand) */ /* Turn on DMA error (RX/TX will be enabled on demand) */
uap->dmacr |= UART011_DMAONERR; uap->dmacr |= UART011_DMAONERR;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
/* /*
* ST Micro variants has some specific dma burst threshold * ST Micro variants has some specific dma burst threshold
...@@ -1049,8 +1196,9 @@ static void pl011_dma_startup(struct uart_amba_port *uap) ...@@ -1049,8 +1196,9 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
* be issued above/below 16 bytes. * be issued above/below 16 bytes.
*/ */
if (uap->vendor->dma_threshold) if (uap->vendor->dma_threshold)
writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16, pl011_writew(uap,
uap->port.membase + ST_UART011_DMAWM); ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
REG_ST_DMAWM);
if (uap->using_rx_dma) { if (uap->using_rx_dma) {
if (pl011_dma_rx_trigger_dma(uap)) if (pl011_dma_rx_trigger_dma(uap))
...@@ -1075,12 +1223,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) ...@@ -1075,12 +1223,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
return; return;
/* Disable RX and TX DMA */ /* Disable RX and TX DMA */
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) while (pl011_readw(uap, REG_FR) & uap->fr_busy)
barrier(); barrier();
spin_lock_irq(&uap->port.lock); spin_lock_irq(&uap->port.lock);
uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_writew(uap, uap->dmacr, REG_DMACR);
spin_unlock_irq(&uap->port.lock); spin_unlock_irq(&uap->port.lock);
if (uap->using_tx_dma) { if (uap->using_tx_dma) {
...@@ -1181,7 +1329,7 @@ static void pl011_stop_tx(struct uart_port *port) ...@@ -1181,7 +1329,7 @@ static void pl011_stop_tx(struct uart_port *port)
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
pl011_dma_tx_stop(uap); pl011_dma_tx_stop(uap);
} }
...@@ -1191,7 +1339,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq); ...@@ -1191,7 +1339,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
static void pl011_start_tx_pio(struct uart_amba_port *uap) static void pl011_start_tx_pio(struct uart_amba_port *uap)
{ {
uap->im |= UART011_TXIM; uap->im |= UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
pl011_tx_chars(uap, false); pl011_tx_chars(uap, false);
} }
...@@ -1211,7 +1359,7 @@ static void pl011_stop_rx(struct uart_port *port) ...@@ -1211,7 +1359,7 @@ static void pl011_stop_rx(struct uart_port *port)
uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM| uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
UART011_PEIM|UART011_BEIM|UART011_OEIM); UART011_PEIM|UART011_BEIM|UART011_OEIM);
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
pl011_dma_rx_stop(uap); pl011_dma_rx_stop(uap);
} }
...@@ -1222,7 +1370,7 @@ static void pl011_enable_ms(struct uart_port *port) ...@@ -1222,7 +1370,7 @@ static void pl011_enable_ms(struct uart_port *port)
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM; uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
} }
static void pl011_rx_chars(struct uart_amba_port *uap) static void pl011_rx_chars(struct uart_amba_port *uap)
...@@ -1242,7 +1390,7 @@ __acquires(&uap->port.lock) ...@@ -1242,7 +1390,7 @@ __acquires(&uap->port.lock)
dev_dbg(uap->port.dev, "could not trigger RX DMA job " dev_dbg(uap->port.dev, "could not trigger RX DMA job "
"fall back to interrupt mode again\n"); "fall back to interrupt mode again\n");
uap->im |= UART011_RXIM; uap->im |= UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
} else { } else {
#ifdef CONFIG_DMA_ENGINE #ifdef CONFIG_DMA_ENGINE
/* Start Rx DMA poll */ /* Start Rx DMA poll */
...@@ -1263,10 +1411,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, ...@@ -1263,10 +1411,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
bool from_irq) bool from_irq)
{ {
if (unlikely(!from_irq) && if (unlikely(!from_irq) &&
readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
return false; /* unable to transmit character */ return false; /* unable to transmit character */
writew(c, uap->port.membase + UART01x_DR); pl011_writew(uap, c, REG_DR);
uap->port.icount.tx++; uap->port.icount.tx++;
return true; return true;
...@@ -1313,7 +1461,7 @@ static void pl011_modem_status(struct uart_amba_port *uap) ...@@ -1313,7 +1461,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
{ {
unsigned int status, delta; unsigned int status, delta;
status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; status = pl011_readw(uap, REG_FR) & UART01x_FR_MODEM_ANY;
delta = status ^ uap->old_status; delta = status ^ uap->old_status;
uap->old_status = status; uap->old_status = status;
...@@ -1324,11 +1472,11 @@ static void pl011_modem_status(struct uart_amba_port *uap) ...@@ -1324,11 +1472,11 @@ static void pl011_modem_status(struct uart_amba_port *uap)
if (delta & UART01x_FR_DCD) if (delta & UART01x_FR_DCD)
uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD); uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
if (delta & UART01x_FR_DSR) if (delta & uap->fr_dsr)
uap->port.icount.dsr++; uap->port.icount.dsr++;
if (delta & UART01x_FR_CTS) if (delta & uap->fr_cts)
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS); uart_handle_cts_change(&uap->port, status & uap->fr_cts);
wake_up_interruptible(&uap->port.state->port.delta_msr_wait); wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
} }
...@@ -1341,15 +1489,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap) ...@@ -1341,15 +1489,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
return; return;
/* workaround to make sure that all bits are unlocked.. */ /* workaround to make sure that all bits are unlocked.. */
writew(0x00, uap->port.membase + UART011_ICR); pl011_writew(uap, 0x00, REG_ICR);
/* /*
* WA: introduce 26ns(1 uart clk) delay before W1C; * WA: introduce 26ns(1 uart clk) delay before W1C;
* single apb access will incur 2 pclk(133.12Mhz) delay, * single apb access will incur 2 pclk(133.12Mhz) delay,
* so add 2 dummy reads * so add 2 dummy reads
*/ */
dummy_read = readw(uap->port.membase + UART011_ICR); dummy_read = pl011_readw(uap, REG_ICR);
dummy_read = readw(uap->port.membase + UART011_ICR); dummy_read = pl011_readw(uap, REG_ICR);
} }
static irqreturn_t pl011_int(int irq, void *dev_id) static irqreturn_t pl011_int(int irq, void *dev_id)
...@@ -1361,15 +1509,13 @@ static irqreturn_t pl011_int(int irq, void *dev_id) ...@@ -1361,15 +1509,13 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
int handled = 0; int handled = 0;
spin_lock_irqsave(&uap->port.lock, flags); spin_lock_irqsave(&uap->port.lock, flags);
imsc = readw(uap->port.membase + UART011_IMSC); imsc = pl011_readw(uap, REG_IMSC);
status = readw(uap->port.membase + UART011_RIS) & imsc; status = pl011_readw(uap, REG_RIS) & imsc;
if (status) { if (status) {
do { do {
check_apply_cts_event_workaround(uap); check_apply_cts_event_workaround(uap);
pl011_writew(uap, status & ~(UART011_TXIS|UART011_RTIS|
writew(status & ~(UART011_TXIS|UART011_RTIS| UART011_RXIS), REG_ICR);
UART011_RXIS),
uap->port.membase + UART011_ICR);
if (status & (UART011_RTIS|UART011_RXIS)) { if (status & (UART011_RTIS|UART011_RXIS)) {
if (pl011_dma_rx_running(uap)) if (pl011_dma_rx_running(uap))
...@@ -1386,7 +1532,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) ...@@ -1386,7 +1532,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
if (pass_counter-- == 0) if (pass_counter-- == 0)
break; break;
status = readw(uap->port.membase + UART011_RIS) & imsc; status = pl011_readw(uap, REG_RIS) & imsc;
} while (status != 0); } while (status != 0);
handled = 1; handled = 1;
} }
...@@ -1400,8 +1546,8 @@ static unsigned int pl011_tx_empty(struct uart_port *port) ...@@ -1400,8 +1546,8 @@ static unsigned int pl011_tx_empty(struct uart_port *port)
{ {
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
unsigned int status = readw(uap->port.membase + UART01x_FR); unsigned int status = pl011_readw(uap, REG_FR);
return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; return status & (uap->fr_busy|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
} }
static unsigned int pl011_get_mctrl(struct uart_port *port) static unsigned int pl011_get_mctrl(struct uart_port *port)
...@@ -1409,16 +1555,16 @@ static unsigned int pl011_get_mctrl(struct uart_port *port) ...@@ -1409,16 +1555,16 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
unsigned int result = 0; unsigned int result = 0;
unsigned int status = readw(uap->port.membase + UART01x_FR); unsigned int status = pl011_readw(uap, REG_FR);
#define TIOCMBIT(uartbit, tiocmbit) \ #define TIOCMBIT(uartbit, tiocmbit) \
if (status & uartbit) \ if (status & uartbit) \
result |= tiocmbit result |= tiocmbit
TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR); TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR); TIOCMBIT(uap->fr_dsr, TIOCM_DSR);
TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS); TIOCMBIT(uap->fr_cts, TIOCM_CTS);
TIOCMBIT(UART011_FR_RI, TIOCM_RNG); TIOCMBIT(uap->fr_ri, TIOCM_RNG);
#undef TIOCMBIT #undef TIOCMBIT
return result; return result;
} }
...@@ -1429,7 +1575,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) ...@@ -1429,7 +1575,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
unsigned int cr; unsigned int cr;
cr = readw(uap->port.membase + UART011_CR); cr = pl011_readw(uap, REG_CR);
#define TIOCMBIT(tiocmbit, uartbit) \ #define TIOCMBIT(tiocmbit, uartbit) \
if (mctrl & tiocmbit) \ if (mctrl & tiocmbit) \
...@@ -1449,7 +1595,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) ...@@ -1449,7 +1595,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
} }
#undef TIOCMBIT #undef TIOCMBIT
writew(cr, uap->port.membase + UART011_CR); pl011_writew(uap, cr, REG_CR);
} }
static void pl011_break_ctl(struct uart_port *port, int break_state) static void pl011_break_ctl(struct uart_port *port, int break_state)
...@@ -1460,12 +1606,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) ...@@ -1460,12 +1606,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
unsigned int lcr_h; unsigned int lcr_h;
spin_lock_irqsave(&uap->port.lock, flags); spin_lock_irqsave(&uap->port.lock, flags);
lcr_h = readw(uap->port.membase + uap->lcrh_tx); lcr_h = pl011_readw(uap, uap->lcrh_tx);
if (break_state == -1) if (break_state == -1)
lcr_h |= UART01x_LCRH_BRK; lcr_h |= UART01x_LCRH_BRK;
else else
lcr_h &= ~UART01x_LCRH_BRK; lcr_h &= ~UART01x_LCRH_BRK;
writew(lcr_h, uap->port.membase + uap->lcrh_tx); pl011_writew(uap, lcr_h, uap->lcrh_tx);
spin_unlock_irqrestore(&uap->port.lock, flags); spin_unlock_irqrestore(&uap->port.lock, flags);
} }
...@@ -1475,9 +1621,8 @@ static void pl011_quiesce_irqs(struct uart_port *port) ...@@ -1475,9 +1621,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
{ {
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
unsigned char __iomem *regs = uap->port.membase;
writew(readw(regs + UART011_MIS), regs + UART011_ICR); pl011_writew(uap, pl011_readw(uap, REG_MIS), REG_ICR);
/* /*
* There is no way to clear TXIM as this is "ready to transmit IRQ", so * There is no way to clear TXIM as this is "ready to transmit IRQ", so
* we simply mask it. start_tx() will unmask it. * we simply mask it. start_tx() will unmask it.
...@@ -1491,7 +1636,7 @@ static void pl011_quiesce_irqs(struct uart_port *port) ...@@ -1491,7 +1636,7 @@ static void pl011_quiesce_irqs(struct uart_port *port)
* (including tx queue), so we're also fine with start_tx()'s caller * (including tx queue), so we're also fine with start_tx()'s caller
* side. * side.
*/ */
writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC); pl011_writew(uap, pl011_readw(uap, REG_IMSC) & ~UART011_TXIM, REG_IMSC);
} }
static int pl011_get_poll_char(struct uart_port *port) static int pl011_get_poll_char(struct uart_port *port)
...@@ -1506,11 +1651,11 @@ static int pl011_get_poll_char(struct uart_port *port) ...@@ -1506,11 +1651,11 @@ static int pl011_get_poll_char(struct uart_port *port)
*/ */
pl011_quiesce_irqs(port); pl011_quiesce_irqs(port);
status = readw(uap->port.membase + UART01x_FR); status = pl011_readw(uap, REG_FR);
if (status & UART01x_FR_RXFE) if (status & UART01x_FR_RXFE)
return NO_POLL_CHAR; return NO_POLL_CHAR;
return readw(uap->port.membase + UART01x_DR); return pl011_readw(uap, REG_DR);
} }
static void pl011_put_poll_char(struct uart_port *port, static void pl011_put_poll_char(struct uart_port *port,
...@@ -1519,10 +1664,10 @@ static void pl011_put_poll_char(struct uart_port *port, ...@@ -1519,10 +1664,10 @@ static void pl011_put_poll_char(struct uart_port *port,
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
barrier(); barrier();
writew(ch, uap->port.membase + UART01x_DR); pl011_writew(uap, ch, REG_DR);
} }
#endif /* CONFIG_CONSOLE_POLL */ #endif /* CONFIG_CONSOLE_POLL */
...@@ -1546,15 +1691,15 @@ static int pl011_hwinit(struct uart_port *port) ...@@ -1546,15 +1691,15 @@ static int pl011_hwinit(struct uart_port *port)
uap->port.uartclk = clk_get_rate(uap->clk); uap->port.uartclk = clk_get_rate(uap->clk);
/* Clear pending error and receive interrupts */ /* Clear pending error and receive interrupts */
writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | pl011_writew(uap, UART011_OEIS | UART011_BEIS | UART011_PEIS |
UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); UART011_FEIS | UART011_RTIS | UART011_RXIS, REG_ICR);
/* /*
* Save interrupts enable mask, and enable RX interrupts in case if * Save interrupts enable mask, and enable RX interrupts in case if
* the interrupt is used for NMI entry. * the interrupt is used for NMI entry.
*/ */
uap->im = readw(uap->port.membase + UART011_IMSC); uap->im = pl011_readw(uap, REG_IMSC);
writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); pl011_writew(uap, UART011_RTIM | UART011_RXIM, REG_IMSC);
if (dev_get_platdata(uap->port.dev)) { if (dev_get_platdata(uap->port.dev)) {
struct amba_pl011_data *plat; struct amba_pl011_data *plat;
...@@ -1568,22 +1713,22 @@ static int pl011_hwinit(struct uart_port *port) ...@@ -1568,22 +1713,22 @@ static int pl011_hwinit(struct uart_port *port)
static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
{ {
writew(lcr_h, uap->port.membase + uap->lcrh_rx); pl011_writew(uap, lcr_h, uap->lcrh_rx);
if (uap->lcrh_rx != uap->lcrh_tx) { if (is_implemented(uap, REG_ST_LCRH_RX)) {
int i; int i;
/* /*
* Wait 10 PCLKs before writing LCRH_TX register, * Wait 10 PCLKs before writing LCRH_TX register,
* to get this delay write read only register 10 times * to get this delay write read only register 10 times
*/ */
for (i = 0; i < 10; ++i) for (i = 0; i < 10; ++i)
writew(0xff, uap->port.membase + UART011_MIS); pl011_writew(uap, 0xff, REG_MIS);
writew(lcr_h, uap->port.membase + uap->lcrh_tx); pl011_writew(uap, lcr_h, uap->lcrh_tx);
} }
} }
static int pl011_allocate_irq(struct uart_amba_port *uap) static int pl011_allocate_irq(struct uart_amba_port *uap)
{ {
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
} }
...@@ -1598,12 +1743,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) ...@@ -1598,12 +1743,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
spin_lock_irq(&uap->port.lock); spin_lock_irq(&uap->port.lock);
/* Clear out any spuriously appearing RX interrupts */ /* Clear out any spuriously appearing RX interrupts */
writew(UART011_RTIS | UART011_RXIS, pl011_writew(uap, UART011_RTIS | UART011_RXIS, REG_ICR);
uap->port.membase + UART011_ICR);
uap->im = UART011_RTIM; uap->im = UART011_RTIM;
if (!pl011_dma_rx_running(uap)) if (!pl011_dma_rx_running(uap))
uap->im |= UART011_RXIM; uap->im |= UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
spin_unlock_irq(&uap->port.lock); spin_unlock_irq(&uap->port.lock);
} }
...@@ -1622,21 +1766,21 @@ static int pl011_startup(struct uart_port *port) ...@@ -1622,21 +1766,21 @@ static int pl011_startup(struct uart_port *port)
if (retval) if (retval)
goto clk_dis; goto clk_dis;
writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); pl011_writew(uap, uap->vendor->ifls, REG_IFLS);
spin_lock_irq(&uap->port.lock); spin_lock_irq(&uap->port.lock);
/* restore RTS and DTR */ /* restore RTS and DTR */
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR); pl011_writew(uap, cr, REG_CR);
spin_unlock_irq(&uap->port.lock); spin_unlock_irq(&uap->port.lock);
/* /*
* initialise the old status of the modem signals * initialise the old status of the modem signals
*/ */
uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; uap->old_status = pl011_readw(uap, REG_FR) & UART01x_FR_MODEM_ANY;
/* Startup DMA */ /* Startup DMA */
pl011_dma_startup(uap); pl011_dma_startup(uap);
...@@ -1675,11 +1819,11 @@ static int sbsa_uart_startup(struct uart_port *port) ...@@ -1675,11 +1819,11 @@ static int sbsa_uart_startup(struct uart_port *port)
static void pl011_shutdown_channel(struct uart_amba_port *uap, static void pl011_shutdown_channel(struct uart_amba_port *uap,
unsigned int lcrh) unsigned int lcrh)
{ {
unsigned long val; unsigned long val;
val = readw(uap->port.membase + lcrh); val = pl011_readw(uap, lcrh);
val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
writew(val, uap->port.membase + lcrh); pl011_writew(uap, val, lcrh);
} }
/* /*
...@@ -1693,18 +1837,18 @@ static void pl011_disable_uart(struct uart_amba_port *uap) ...@@ -1693,18 +1837,18 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
uap->autorts = false; uap->autorts = false;
spin_lock_irq(&uap->port.lock); spin_lock_irq(&uap->port.lock);
cr = readw(uap->port.membase + UART011_CR); cr = pl011_readw(uap, REG_CR);
uap->old_cr = cr; uap->old_cr = cr;
cr &= UART011_CR_RTS | UART011_CR_DTR; cr &= UART011_CR_RTS | UART011_CR_DTR;
cr |= UART01x_CR_UARTEN | UART011_CR_TXE; cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR); pl011_writew(uap, cr, REG_CR);
spin_unlock_irq(&uap->port.lock); spin_unlock_irq(&uap->port.lock);
/* /*
* disable break condition and fifos * disable break condition and fifos
*/ */
pl011_shutdown_channel(uap, uap->lcrh_rx); pl011_shutdown_channel(uap, uap->lcrh_rx);
if (uap->lcrh_rx != uap->lcrh_tx) if (is_implemented(uap, REG_ST_LCRH_RX))
pl011_shutdown_channel(uap, uap->lcrh_tx); pl011_shutdown_channel(uap, uap->lcrh_tx);
} }
...@@ -1714,8 +1858,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap) ...@@ -1714,8 +1858,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
/* mask all interrupts and clear all pending ones */ /* mask all interrupts and clear all pending ones */
uap->im = 0; uap->im = 0;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_writew(uap, uap->im, REG_IMSC);
writew(0xffff, uap->port.membase + UART011_ICR); pl011_writew(uap, 0xffff, REG_ICR);
spin_unlock_irq(&uap->port.lock); spin_unlock_irq(&uap->port.lock);
} }
...@@ -1867,8 +2011,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1867,8 +2011,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
pl011_enable_ms(port); pl011_enable_ms(port);
/* first, disable everything */ /* first, disable everything */
old_cr = readw(port->membase + UART011_CR); old_cr = pl011_readw(uap, REG_CR);
writew(0, port->membase + UART011_CR); pl011_writew(uap, 0, REG_CR);
if (termios->c_cflag & CRTSCTS) { if (termios->c_cflag & CRTSCTS) {
if (old_cr & UART011_CR_RTS) if (old_cr & UART011_CR_RTS)
...@@ -1901,17 +2045,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1901,17 +2045,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
quot -= 2; quot -= 2;
} }
/* Set baud rate */ /* Set baud rate */
writew(quot & 0x3f, port->membase + UART011_FBRD); pl011_writew(uap, quot & 0x3f, REG_FBRD);
writew(quot >> 6, port->membase + UART011_IBRD); pl011_writew(uap, quot >> 6, REG_IBRD);
/* /*
* ----------v----------v----------v----------v----- * ----------v----------v----------v----------v-----
* NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
* UART011_FBRD & UART011_IBRD. * REG_FBRD & REG_IBRD.
* ----------^----------^----------^----------^----- * ----------^----------^----------^----------^-----
*/ */
pl011_write_lcr_h(uap, lcr_h); pl011_write_lcr_h(uap, lcr_h);
writew(old_cr, port->membase + UART011_CR); pl011_writew(uap, old_cr, REG_CR);
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
} }
...@@ -2052,9 +2196,9 @@ static void pl011_console_putchar(struct uart_port *port, int ch) ...@@ -2052,9 +2196,9 @@ static void pl011_console_putchar(struct uart_port *port, int ch)
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
barrier(); barrier();
writew(ch, uap->port.membase + UART01x_DR); pl011_writew(uap, ch, REG_DR);
} }
static void static void
...@@ -2079,10 +2223,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) ...@@ -2079,10 +2223,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
* First save the CR then disable the interrupts * First save the CR then disable the interrupts
*/ */
if (!uap->vendor->always_enabled) { if (!uap->vendor->always_enabled) {
old_cr = readw(uap->port.membase + UART011_CR); old_cr = pl011_readw(uap, REG_CR);
new_cr = old_cr & ~UART011_CR_CTSEN; new_cr = old_cr & ~UART011_CR_CTSEN;
new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
writew(new_cr, uap->port.membase + UART011_CR); pl011_writew(uap, new_cr, REG_CR);
} }
uart_console_write(&uap->port, s, count, pl011_console_putchar); uart_console_write(&uap->port, s, count, pl011_console_putchar);
...@@ -2092,10 +2236,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) ...@@ -2092,10 +2236,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
* and restore the TCR * and restore the TCR
*/ */
do { do {
status = readw(uap->port.membase + UART01x_FR); status = pl011_readw(uap, REG_FR);
} while (status & UART01x_FR_BUSY); } while (status & uap->fr_busy);
if (!uap->vendor->always_enabled) if (!uap->vendor->always_enabled)
writew(old_cr, uap->port.membase + UART011_CR); pl011_writew(uap, old_cr, REG_CR);
if (locked) if (locked)
spin_unlock(&uap->port.lock); spin_unlock(&uap->port.lock);
...@@ -2108,10 +2252,10 @@ static void __init ...@@ -2108,10 +2252,10 @@ static void __init
pl011_console_get_options(struct uart_amba_port *uap, int *baud, pl011_console_get_options(struct uart_amba_port *uap, int *baud,
int *parity, int *bits) int *parity, int *bits)
{ {
if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) { if (pl011_readw(uap, REG_CR) & UART01x_CR_UARTEN) {
unsigned int lcr_h, ibrd, fbrd; unsigned int lcr_h, ibrd, fbrd;
lcr_h = readw(uap->port.membase + uap->lcrh_tx); lcr_h = pl011_readw(uap, uap->lcrh_tx);
*parity = 'n'; *parity = 'n';
if (lcr_h & UART01x_LCRH_PEN) { if (lcr_h & UART01x_LCRH_PEN) {
...@@ -2126,13 +2270,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, ...@@ -2126,13 +2270,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
else else
*bits = 8; *bits = 8;
ibrd = readw(uap->port.membase + UART011_IBRD); ibrd = pl011_readw(uap, REG_IBRD);
fbrd = readw(uap->port.membase + UART011_FBRD); fbrd = pl011_readw(uap, REG_FBRD);
*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
if (uap->vendor->oversampling) { if (uap->vendor->oversampling) {
if (readw(uap->port.membase + UART011_CR) if (pl011_readw(uap, REG_CR)
& ST_UART011_CR_OVSFACT) & ST_UART011_CR_OVSFACT)
*baud *= 2; *baud *= 2;
} }
...@@ -2204,10 +2348,13 @@ static struct console amba_console = { ...@@ -2204,10 +2348,13 @@ static struct console amba_console = {
static void pl011_putc(struct uart_port *port, int c) static void pl011_putc(struct uart_port *port, int c)
{ {
while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
; ;
writeb(c, port->membase + UART01x_DR); pl011_writeb(uap, c, REG_DR);
while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) while (pl011_readw(uap, REG_FR) & uap->fr_busy)
; ;
} }
...@@ -2334,8 +2481,8 @@ static int pl011_register_port(struct uart_amba_port *uap) ...@@ -2334,8 +2481,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
int ret; int ret;
/* Ensure interrupts from this UART are masked and cleared */ /* Ensure interrupts from this UART are masked and cleared */
writew(0, uap->port.membase + UART011_IMSC); pl011_writew(uap, 0, REG_IMSC);
writew(0xffff, uap->port.membase + UART011_ICR); pl011_writew(uap, 0xffff, REG_ICR);
if (!amba_reg.state) { if (!amba_reg.state) {
ret = uart_register_driver(&amba_reg); ret = uart_register_driver(&amba_reg);
...@@ -2353,6 +2500,7 @@ static int pl011_register_port(struct uart_amba_port *uap) ...@@ -2353,6 +2500,7 @@ static int pl011_register_port(struct uart_amba_port *uap)
return ret; return ret;
} }
#ifdef CONFIG_ARM_AMBA
static int pl011_probe(struct amba_device *dev, const struct amba_id *id) static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
{ {
struct uart_amba_port *uap; struct uart_amba_port *uap;
...@@ -2373,8 +2521,13 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -2373,8 +2521,13 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
return PTR_ERR(uap->clk); return PTR_ERR(uap->clk);
uap->vendor = vendor; uap->vendor = vendor;
uap->reg_lut = vendor->reg_lut;
uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx; uap->lcrh_tx = vendor->lcrh_tx;
uap->fr_busy = vendor->fr_busy;
uap->fr_dsr = vendor->fr_dsr;
uap->fr_cts = vendor->fr_cts;
uap->fr_ri = vendor->fr_ri;
uap->fifosize = vendor->get_fifosize(dev); uap->fifosize = vendor->get_fifosize(dev);
uap->port.irq = dev->irq[0]; uap->port.irq = dev->irq[0];
uap->port.ops = &amba_pl011_pops; uap->port.ops = &amba_pl011_pops;
...@@ -2398,6 +2551,67 @@ static int pl011_remove(struct amba_device *dev) ...@@ -2398,6 +2551,67 @@ static int pl011_remove(struct amba_device *dev)
pl011_unregister_port(uap); pl011_unregister_port(uap);
return 0; return 0;
} }
#endif
#ifdef CONFIG_SOC_ZX296702
static int zx_uart_probe(struct platform_device *pdev)
{
struct uart_amba_port *uap;
struct vendor_data *vendor = &vendor_zte;
struct resource *res;
int portnr, ret;
portnr = pl011_find_free_port();
if (portnr < 0)
return portnr;
uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port),
GFP_KERNEL);
if (!uap) {
ret = -ENOMEM;
goto out;
}
uap->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk);
goto out;
}
uap->vendor = vendor;
uap->reg_lut = vendor->reg_lut;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
uap->fr_busy = vendor->fr_busy;
uap->fr_dsr = vendor->fr_dsr;
uap->fr_cts = vendor->fr_cts;
uap->fr_ri = vendor->fr_ri;
uap->fifosize = 16;
uap->port.irq = platform_get_irq(pdev, 0);
uap->port.ops = &amba_pl011_pops;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ret = pl011_setup_port(&pdev->dev, uap, res, portnr);
if (ret)
return ret;
platform_set_drvdata(pdev, uap);
return pl011_register_port(uap);
out:
return ret;
}
static int zx_uart_remove(struct platform_device *pdev)
{
struct uart_amba_port *uap = platform_get_drvdata(pdev);
uart_remove_one_port(&amba_reg, &uap->port);
pl011_unregister_port(uap);
return 0;
}
#endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int pl011_suspend(struct device *dev) static int pl011_suspend(struct device *dev)
...@@ -2454,6 +2668,11 @@ static int sbsa_uart_probe(struct platform_device *pdev) ...@@ -2454,6 +2668,11 @@ static int sbsa_uart_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
uap->vendor = &vendor_sbsa; uap->vendor = &vendor_sbsa;
uap->reg_lut = vendor_sbsa.reg_lut;
uap->fr_busy = vendor_sbsa.fr_busy;
uap->fr_dsr = vendor_sbsa.fr_dsr;
uap->fr_cts = vendor_sbsa.fr_cts;
uap->fr_ri = vendor_sbsa.fr_ri;
uap->fifosize = 32; uap->fifosize = 32;
uap->port.irq = platform_get_irq(pdev, 0); uap->port.irq = platform_get_irq(pdev, 0);
uap->port.ops = &sbsa_uart_pops; uap->port.ops = &sbsa_uart_pops;
...@@ -2503,6 +2722,7 @@ static struct platform_driver arm_sbsa_uart_platform_driver = { ...@@ -2503,6 +2722,7 @@ static struct platform_driver arm_sbsa_uart_platform_driver = {
}, },
}; };
#ifdef CONFIG_ARM_AMBA
static struct amba_id pl011_ids[] = { static struct amba_id pl011_ids[] = {
{ {
.id = 0x00041011, .id = 0x00041011,
...@@ -2528,20 +2748,57 @@ static struct amba_driver pl011_driver = { ...@@ -2528,20 +2748,57 @@ static struct amba_driver pl011_driver = {
.probe = pl011_probe, .probe = pl011_probe,
.remove = pl011_remove, .remove = pl011_remove,
}; };
#endif
#ifdef CONFIG_SOC_ZX296702
static const struct of_device_id zx_uart_dt_ids[] = {
{ .compatible = "zte,zx296702-uart", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, zx_uart_dt_ids);
static struct platform_driver zx_uart_driver = {
.driver = {
.name = "zx-uart",
.owner = THIS_MODULE,
.pm = &pl011_dev_pm_ops,
.of_match_table = zx_uart_dt_ids,
},
.probe = zx_uart_probe,
.remove = zx_uart_remove,
};
#endif
static int __init pl011_init(void) static int __init pl011_init(void)
{ {
int ret;
printk(KERN_INFO "Serial: AMBA PL011 UART driver\n"); printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
if (platform_driver_register(&arm_sbsa_uart_platform_driver)) if (platform_driver_register(&arm_sbsa_uart_platform_driver))
pr_warn("could not register SBSA UART platform driver\n"); pr_warn("could not register SBSA UART platform driver\n");
return amba_driver_register(&pl011_driver);
#ifdef CONFIG_SOC_ZX296702
ret = platform_driver_register(&zx_uart_driver);
if (ret)
pr_warn("could not register ZX UART platform driver\n");
#endif
#ifdef CONFIG_ARM_AMBA
ret = amba_driver_register(&pl011_driver);
#endif
return ret;
} }
static void __exit pl011_exit(void) static void __exit pl011_exit(void)
{ {
platform_driver_unregister(&arm_sbsa_uart_platform_driver); platform_driver_unregister(&arm_sbsa_uart_platform_driver);
#ifdef CONFIG_SOC_ZX296702
platform_driver_unregister(&zx_uart_driver);
#endif
#ifdef CONFIG_ARM_AMBA
amba_driver_unregister(&pl011_driver); amba_driver_unregister(&pl011_driver);
#endif
} }
/* /*
......
...@@ -56,6 +56,15 @@ ...@@ -56,6 +56,15 @@
/* Revisit: We should calculate this based on the actual port settings */ /* Revisit: We should calculate this based on the actual port settings */
#define PDC_RX_TIMEOUT (3 * 10) /* 3 bytes */ #define PDC_RX_TIMEOUT (3 * 10) /* 3 bytes */
/* The minium number of data FIFOs should be able to contain */
#define ATMEL_MIN_FIFO_SIZE 8
/*
* These two offsets are substracted from the RX FIFO size to define the RTS
* high and low thresholds
*/
#define ATMEL_RTS_HIGH_OFFSET 16
#define ATMEL_RTS_LOW_OFFSET 20
#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ #define SUPPORT_SYSRQ
#endif #endif
...@@ -88,37 +97,6 @@ static void atmel_stop_rx(struct uart_port *port); ...@@ -88,37 +97,6 @@ static void atmel_stop_rx(struct uart_port *port);
#define ATMEL_ISR_PASS_LIMIT 256 #define ATMEL_ISR_PASS_LIMIT 256
/* UART registers. CR is write-only, hence no GET macro */
#define UART_PUT_CR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_CR)
#define UART_GET_MR(port) __raw_readl((port)->membase + ATMEL_US_MR)
#define UART_PUT_MR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_MR)
#define UART_PUT_IER(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IER)
#define UART_PUT_IDR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IDR)
#define UART_GET_IMR(port) __raw_readl((port)->membase + ATMEL_US_IMR)
#define UART_GET_CSR(port) __raw_readl((port)->membase + ATMEL_US_CSR)
#define UART_GET_CHAR(port) __raw_readl((port)->membase + ATMEL_US_RHR)
#define UART_PUT_CHAR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_THR)
#define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR)
#define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR)
#define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR)
#define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR)
#define UART_GET_IP_NAME(port) __raw_readl((port)->membase + ATMEL_US_NAME)
#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
/* PDC registers */
#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
#define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR)
#define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
#define UART_GET_RPR(port) __raw_readl((port)->membase + ATMEL_PDC_RPR)
#define UART_PUT_RCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
#define UART_PUT_RNPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
#define UART_PUT_RNCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
#define UART_PUT_TPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
#define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
struct atmel_dma_buffer { struct atmel_dma_buffer {
unsigned char *buf; unsigned char *buf;
dma_addr_t dma_addr; dma_addr_t dma_addr;
...@@ -166,12 +144,16 @@ struct atmel_uart_port { ...@@ -166,12 +144,16 @@ struct atmel_uart_port {
unsigned int irq_status; unsigned int irq_status;
unsigned int irq_status_prev; unsigned int irq_status_prev;
unsigned int status_change; unsigned int status_change;
unsigned int tx_len;
struct circ_buf rx_ring; struct circ_buf rx_ring;
struct mctrl_gpios *gpios; struct mctrl_gpios *gpios;
int gpio_irq[UART_GPIO_MAX]; int gpio_irq[UART_GPIO_MAX];
unsigned int tx_done_mask; unsigned int tx_done_mask;
u32 fifo_size;
u32 rts_high;
u32 rts_low;
bool ms_irq_enabled; bool ms_irq_enabled;
bool is_usart; /* usart or uart */ bool is_usart; /* usart or uart */
struct timer_list uart_timer; /* uart timer */ struct timer_list uart_timer; /* uart timer */
...@@ -212,6 +194,43 @@ to_atmel_uart_port(struct uart_port *uart) ...@@ -212,6 +194,43 @@ to_atmel_uart_port(struct uart_port *uart)
return container_of(uart, struct atmel_uart_port, uart); return container_of(uart, struct atmel_uart_port, uart);
} }
static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
{
return __raw_readl(port->membase + reg);
}
static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
{
__raw_writel(value, port->membase + reg);
}
#ifdef CONFIG_AVR32
/* AVR32 cannot handle 8 or 16bit I/O accesses but only 32bit I/O accesses */
static inline u8 atmel_uart_read_char(struct uart_port *port)
{
return __raw_readl(port->membase + ATMEL_US_RHR);
}
static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
{
__raw_writel(value, port->membase + ATMEL_US_THR);
}
#else
static inline u8 atmel_uart_read_char(struct uart_port *port)
{
return __raw_readb(port->membase + ATMEL_US_RHR);
}
static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
{
__raw_writeb(value, port->membase + ATMEL_US_THR);
}
#endif
#ifdef CONFIG_SERIAL_ATMEL_PDC #ifdef CONFIG_SERIAL_ATMEL_PDC
static bool atmel_use_pdc_rx(struct uart_port *port) static bool atmel_use_pdc_rx(struct uart_port *port)
{ {
...@@ -257,7 +276,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port) ...@@ -257,7 +276,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status, ret = 0; unsigned int status, ret = 0;
status = UART_GET_CSR(port); status = atmel_uart_readl(port, ATMEL_US_CSR);
mctrl_gpio_get(atmel_port->gpios, &ret); mctrl_gpio_get(atmel_port->gpios, &ret);
...@@ -304,9 +323,9 @@ static int atmel_config_rs485(struct uart_port *port, ...@@ -304,9 +323,9 @@ static int atmel_config_rs485(struct uart_port *port,
unsigned int mode; unsigned int mode;
/* Disable interrupts */ /* Disable interrupts */
UART_PUT_IDR(port, atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
mode = UART_GET_MR(port); mode = atmel_uart_readl(port, ATMEL_US_MR);
/* Resetting serial mode to RS232 (0x0) */ /* Resetting serial mode to RS232 (0x0) */
mode &= ~ATMEL_US_USMODE; mode &= ~ATMEL_US_USMODE;
...@@ -316,7 +335,8 @@ static int atmel_config_rs485(struct uart_port *port, ...@@ -316,7 +335,8 @@ static int atmel_config_rs485(struct uart_port *port,
if (rs485conf->flags & SER_RS485_ENABLED) { if (rs485conf->flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n"); dev_dbg(port->dev, "Setting UART to RS485\n");
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
UART_PUT_TTGR(port, rs485conf->delay_rts_after_send); atmel_uart_writel(port, ATMEL_US_TTGR,
rs485conf->delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485; mode |= ATMEL_US_USMODE_RS485;
} else { } else {
dev_dbg(port->dev, "Setting UART to RS232\n"); dev_dbg(port->dev, "Setting UART to RS232\n");
...@@ -326,10 +346,10 @@ static int atmel_config_rs485(struct uart_port *port, ...@@ -326,10 +346,10 @@ static int atmel_config_rs485(struct uart_port *port,
else else
atmel_port->tx_done_mask = ATMEL_US_TXRDY; atmel_port->tx_done_mask = ATMEL_US_TXRDY;
} }
UART_PUT_MR(port, mode); atmel_uart_writel(port, ATMEL_US_MR, mode);
/* Enable interrupts */ /* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
return 0; return 0;
} }
...@@ -339,7 +359,9 @@ static int atmel_config_rs485(struct uart_port *port, ...@@ -339,7 +359,9 @@ static int atmel_config_rs485(struct uart_port *port,
*/ */
static u_int atmel_tx_empty(struct uart_port *port) static u_int atmel_tx_empty(struct uart_port *port)
{ {
return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0; return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
TIOCSER_TEMT :
0;
} }
/* /*
...@@ -348,13 +370,14 @@ static u_int atmel_tx_empty(struct uart_port *port) ...@@ -348,13 +370,14 @@ static u_int atmel_tx_empty(struct uart_port *port)
static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
{ {
unsigned int control = 0; unsigned int control = 0;
unsigned int mode = UART_GET_MR(port); unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
unsigned int rts_paused, rts_ready; unsigned int rts_paused, rts_ready;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
/* override mode to RS485 if needed, otherwise keep the current mode */ /* override mode to RS485 if needed, otherwise keep the current mode */
if (port->rs485.flags & SER_RS485_ENABLED) { if (port->rs485.flags & SER_RS485_ENABLED) {
UART_PUT_TTGR(port, port->rs485.delay_rts_after_send); atmel_uart_writel(port, ATMEL_US_TTGR,
port->rs485.delay_rts_after_send);
mode &= ~ATMEL_US_USMODE; mode &= ~ATMEL_US_USMODE;
mode |= ATMEL_US_USMODE_RS485; mode |= ATMEL_US_USMODE_RS485;
} }
...@@ -384,7 +407,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) ...@@ -384,7 +407,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
else else
control |= ATMEL_US_DTRDIS; control |= ATMEL_US_DTRDIS;
UART_PUT_CR(port, control); atmel_uart_writel(port, ATMEL_US_CR, control);
mctrl_gpio_set(atmel_port->gpios, mctrl); mctrl_gpio_set(atmel_port->gpios, mctrl);
...@@ -395,7 +418,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) ...@@ -395,7 +418,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
else else
mode |= ATMEL_US_CHMODE_NORMAL; mode |= ATMEL_US_CHMODE_NORMAL;
UART_PUT_MR(port, mode); atmel_uart_writel(port, ATMEL_US_MR, mode);
} }
/* /*
...@@ -406,7 +429,7 @@ static u_int atmel_get_mctrl(struct uart_port *port) ...@@ -406,7 +429,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int ret = 0, status; unsigned int ret = 0, status;
status = UART_GET_CSR(port); status = atmel_uart_readl(port, ATMEL_US_CSR);
/* /*
* The control signals are active low. * The control signals are active low.
...@@ -432,10 +455,10 @@ static void atmel_stop_tx(struct uart_port *port) ...@@ -432,10 +455,10 @@ static void atmel_stop_tx(struct uart_port *port)
if (atmel_use_pdc_tx(port)) { if (atmel_use_pdc_tx(port)) {
/* disable PDC transmit */ /* disable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
} }
/* Disable interrupts */ /* Disable interrupts */
UART_PUT_IDR(port, atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
if ((port->rs485.flags & SER_RS485_ENABLED) && if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) !(port->rs485.flags & SER_RS485_RX_DURING_TX))
...@@ -450,7 +473,7 @@ static void atmel_start_tx(struct uart_port *port) ...@@ -450,7 +473,7 @@ static void atmel_start_tx(struct uart_port *port)
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_use_pdc_tx(port)) { if (atmel_use_pdc_tx(port)) {
if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN) if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
/* The transmitter is already running. Yes, we /* The transmitter is already running. Yes, we
really need this.*/ really need this.*/
return; return;
...@@ -460,10 +483,10 @@ static void atmel_start_tx(struct uart_port *port) ...@@ -460,10 +483,10 @@ static void atmel_start_tx(struct uart_port *port)
atmel_stop_rx(port); atmel_stop_rx(port);
/* re-enable PDC transmit */ /* re-enable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
} }
/* Enable interrupts */ /* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
} }
/* /*
...@@ -471,17 +494,19 @@ static void atmel_start_tx(struct uart_port *port) ...@@ -471,17 +494,19 @@ static void atmel_start_tx(struct uart_port *port)
*/ */
static void atmel_start_rx(struct uart_port *port) static void atmel_start_rx(struct uart_port *port)
{ {
UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */ /* reset status and receiver */
atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
UART_PUT_CR(port, ATMEL_US_RXEN); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
if (atmel_use_pdc_rx(port)) { if (atmel_use_pdc_rx(port)) {
/* enable PDC controller */ /* enable PDC controller */
UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | atmel_uart_writel(port, ATMEL_US_IER,
port->read_status_mask); ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
UART_PUT_PTCR(port, ATMEL_PDC_RXTEN); port->read_status_mask);
atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
} else { } else {
UART_PUT_IER(port, ATMEL_US_RXRDY); atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
} }
} }
...@@ -490,15 +515,16 @@ static void atmel_start_rx(struct uart_port *port) ...@@ -490,15 +515,16 @@ static void atmel_start_rx(struct uart_port *port)
*/ */
static void atmel_stop_rx(struct uart_port *port) static void atmel_stop_rx(struct uart_port *port)
{ {
UART_PUT_CR(port, ATMEL_US_RXDIS); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
if (atmel_use_pdc_rx(port)) { if (atmel_use_pdc_rx(port)) {
/* disable PDC receive */ /* disable PDC receive */
UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | atmel_uart_writel(port, ATMEL_US_IDR,
port->read_status_mask); ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
port->read_status_mask);
} else { } else {
UART_PUT_IDR(port, ATMEL_US_RXRDY); atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
} }
} }
...@@ -538,7 +564,7 @@ static void atmel_enable_ms(struct uart_port *port) ...@@ -538,7 +564,7 @@ static void atmel_enable_ms(struct uart_port *port)
else else
ier |= ATMEL_US_DCDIC; ier |= ATMEL_US_DCDIC;
UART_PUT_IER(port, ier); atmel_uart_writel(port, ATMEL_US_IER, ier);
} }
/* /*
...@@ -577,7 +603,7 @@ static void atmel_disable_ms(struct uart_port *port) ...@@ -577,7 +603,7 @@ static void atmel_disable_ms(struct uart_port *port)
else else
idr |= ATMEL_US_DCDIC; idr |= ATMEL_US_DCDIC;
UART_PUT_IDR(port, idr); atmel_uart_writel(port, ATMEL_US_IDR, idr);
} }
/* /*
...@@ -586,9 +612,11 @@ static void atmel_disable_ms(struct uart_port *port) ...@@ -586,9 +612,11 @@ static void atmel_disable_ms(struct uart_port *port)
static void atmel_break_ctl(struct uart_port *port, int break_state) static void atmel_break_ctl(struct uart_port *port, int break_state)
{ {
if (break_state != 0) if (break_state != 0)
UART_PUT_CR(port, ATMEL_US_STTBRK); /* start break */ /* start break */
atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
else else
UART_PUT_CR(port, ATMEL_US_STPBRK); /* stop break */ /* stop break */
atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
} }
/* /*
...@@ -622,7 +650,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status, ...@@ -622,7 +650,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status) static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
{ {
/* clear error */ /* clear error */
UART_PUT_CR(port, ATMEL_US_RSTSTA); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
if (status & ATMEL_US_RXBRK) { if (status & ATMEL_US_RXBRK) {
/* ignore side-effect */ /* ignore side-effect */
...@@ -645,9 +673,9 @@ static void atmel_rx_chars(struct uart_port *port) ...@@ -645,9 +673,9 @@ static void atmel_rx_chars(struct uart_port *port)
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status, ch; unsigned int status, ch;
status = UART_GET_CSR(port); status = atmel_uart_readl(port, ATMEL_US_CSR);
while (status & ATMEL_US_RXRDY) { while (status & ATMEL_US_RXRDY) {
ch = UART_GET_CHAR(port); ch = atmel_uart_read_char(port);
/* /*
* note that the error handling code is * note that the error handling code is
...@@ -658,12 +686,13 @@ static void atmel_rx_chars(struct uart_port *port) ...@@ -658,12 +686,13 @@ static void atmel_rx_chars(struct uart_port *port)
|| atmel_port->break_active)) { || atmel_port->break_active)) {
/* clear error */ /* clear error */
UART_PUT_CR(port, ATMEL_US_RSTSTA); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
if (status & ATMEL_US_RXBRK if (status & ATMEL_US_RXBRK
&& !atmel_port->break_active) { && !atmel_port->break_active) {
atmel_port->break_active = 1; atmel_port->break_active = 1;
UART_PUT_IER(port, ATMEL_US_RXBRK); atmel_uart_writel(port, ATMEL_US_IER,
ATMEL_US_RXBRK);
} else { } else {
/* /*
* This is either the end-of-break * This is either the end-of-break
...@@ -672,14 +701,15 @@ static void atmel_rx_chars(struct uart_port *port) ...@@ -672,14 +701,15 @@ static void atmel_rx_chars(struct uart_port *port)
* being set. In both cases, the next * being set. In both cases, the next
* RXBRK will indicate start-of-break. * RXBRK will indicate start-of-break.
*/ */
UART_PUT_IDR(port, ATMEL_US_RXBRK); atmel_uart_writel(port, ATMEL_US_IDR,
ATMEL_US_RXBRK);
status &= ~ATMEL_US_RXBRK; status &= ~ATMEL_US_RXBRK;
atmel_port->break_active = 0; atmel_port->break_active = 0;
} }
} }
atmel_buffer_rx_char(port, status, ch); atmel_buffer_rx_char(port, status, ch);
status = UART_GET_CSR(port); status = atmel_uart_readl(port, ATMEL_US_CSR);
} }
tasklet_schedule(&atmel_port->tasklet); tasklet_schedule(&atmel_port->tasklet);
...@@ -694,16 +724,18 @@ static void atmel_tx_chars(struct uart_port *port) ...@@ -694,16 +724,18 @@ static void atmel_tx_chars(struct uart_port *port)
struct circ_buf *xmit = &port->state->xmit; struct circ_buf *xmit = &port->state->xmit;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) { if (port->x_char &&
UART_PUT_CHAR(port, port->x_char); (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
atmel_uart_write_char(port, port->x_char);
port->icount.tx++; port->icount.tx++;
port->x_char = 0; port->x_char = 0;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) if (uart_circ_empty(xmit) || uart_tx_stopped(port))
return; return;
while (UART_GET_CSR(port) & atmel_port->tx_done_mask) { while (atmel_uart_readl(port, ATMEL_US_CSR) &
UART_PUT_CHAR(port, xmit->buf[xmit->tail]); atmel_port->tx_done_mask) {
atmel_uart_write_char(port, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++; port->icount.tx++;
if (uart_circ_empty(xmit)) if (uart_circ_empty(xmit))
...@@ -715,7 +747,8 @@ static void atmel_tx_chars(struct uart_port *port) ...@@ -715,7 +747,8 @@ static void atmel_tx_chars(struct uart_port *port)
if (!uart_circ_empty(xmit)) if (!uart_circ_empty(xmit))
/* Enable interrupts */ /* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IER,
atmel_port->tx_done_mask);
} }
static void atmel_complete_tx_dma(void *arg) static void atmel_complete_tx_dma(void *arg)
...@@ -730,10 +763,10 @@ static void atmel_complete_tx_dma(void *arg) ...@@ -730,10 +763,10 @@ static void atmel_complete_tx_dma(void *arg)
if (chan) if (chan)
dmaengine_terminate_all(chan); dmaengine_terminate_all(chan);
xmit->tail += sg_dma_len(&atmel_port->sg_tx); xmit->tail += atmel_port->tx_len;
xmit->tail &= UART_XMIT_SIZE - 1; xmit->tail &= UART_XMIT_SIZE - 1;
port->icount.tx += sg_dma_len(&atmel_port->sg_tx); port->icount.tx += atmel_port->tx_len;
spin_lock_irq(&atmel_port->lock_tx); spin_lock_irq(&atmel_port->lock_tx);
async_tx_ack(atmel_port->desc_tx); async_tx_ack(atmel_port->desc_tx);
...@@ -781,7 +814,9 @@ static void atmel_tx_dma(struct uart_port *port) ...@@ -781,7 +814,9 @@ static void atmel_tx_dma(struct uart_port *port)
struct circ_buf *xmit = &port->state->xmit; struct circ_buf *xmit = &port->state->xmit;
struct dma_chan *chan = atmel_port->chan_tx; struct dma_chan *chan = atmel_port->chan_tx;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct scatterlist *sg = &atmel_port->sg_tx; struct scatterlist sgl[2], *sg, *sg_tx = &atmel_port->sg_tx;
unsigned int tx_len, part1_len, part2_len, sg_len;
dma_addr_t phys_addr;
/* Make sure we have an idle channel */ /* Make sure we have an idle channel */
if (atmel_port->desc_tx != NULL) if (atmel_port->desc_tx != NULL)
...@@ -797,18 +832,46 @@ static void atmel_tx_dma(struct uart_port *port) ...@@ -797,18 +832,46 @@ static void atmel_tx_dma(struct uart_port *port)
* Take the port lock to get a * Take the port lock to get a
* consistent xmit buffer state. * consistent xmit buffer state.
*/ */
sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); tx_len = CIRC_CNT_TO_END(xmit->head,
sg_dma_address(sg) = (sg_dma_address(sg) & xmit->tail,
~(UART_XMIT_SIZE - 1)) UART_XMIT_SIZE);
+ sg->offset;
sg_dma_len(sg) = CIRC_CNT_TO_END(xmit->head, if (atmel_port->fifo_size) {
xmit->tail, /* multi data mode */
UART_XMIT_SIZE); part1_len = (tx_len & ~0x3); /* DWORD access */
BUG_ON(!sg_dma_len(sg)); part2_len = (tx_len & 0x3); /* BYTE access */
} else {
/* single data (legacy) mode */
part1_len = 0;
part2_len = tx_len; /* BYTE access only */
}
sg_init_table(sgl, 2);
sg_len = 0;
phys_addr = sg_dma_address(sg_tx) + xmit->tail;
if (part1_len) {
sg = &sgl[sg_len++];
sg_dma_address(sg) = phys_addr;
sg_dma_len(sg) = part1_len;
phys_addr += part1_len;
}
if (part2_len) {
sg = &sgl[sg_len++];
sg_dma_address(sg) = phys_addr;
sg_dma_len(sg) = part2_len;
}
/*
* save tx_len so atmel_complete_tx_dma() will increase
* xmit->tail correctly
*/
atmel_port->tx_len = tx_len;
desc = dmaengine_prep_slave_sg(chan, desc = dmaengine_prep_slave_sg(chan,
sg, sgl,
1, sg_len,
DMA_MEM_TO_DEV, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_PREP_INTERRUPT |
DMA_CTRL_ACK); DMA_CTRL_ACK);
...@@ -817,7 +880,7 @@ static void atmel_tx_dma(struct uart_port *port) ...@@ -817,7 +880,7 @@ static void atmel_tx_dma(struct uart_port *port)
return; return;
} }
dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE); dma_sync_sg_for_device(port->dev, sg_tx, 1, DMA_TO_DEVICE);
atmel_port->desc_tx = desc; atmel_port->desc_tx = desc;
desc->callback = atmel_complete_tx_dma; desc->callback = atmel_complete_tx_dma;
...@@ -877,7 +940,9 @@ static int atmel_prepare_tx_dma(struct uart_port *port) ...@@ -877,7 +940,9 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
/* Configure the slave DMA */ /* Configure the slave DMA */
memset(&config, 0, sizeof(config)); memset(&config, 0, sizeof(config));
config.direction = DMA_MEM_TO_DEV; config.direction = DMA_MEM_TO_DEV;
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; config.dst_addr_width = (atmel_port->fifo_size) ?
DMA_SLAVE_BUSWIDTH_4_BYTES :
DMA_SLAVE_BUSWIDTH_1_BYTE;
config.dst_addr = port->mapbase + ATMEL_US_THR; config.dst_addr = port->mapbase + ATMEL_US_THR;
config.dst_maxburst = 1; config.dst_maxburst = 1;
...@@ -935,14 +1000,14 @@ static void atmel_rx_from_dma(struct uart_port *port) ...@@ -935,14 +1000,14 @@ static void atmel_rx_from_dma(struct uart_port *port)
/* Reset the UART timeout early so that we don't miss one */ /* Reset the UART timeout early so that we don't miss one */
UART_PUT_CR(port, ATMEL_US_STTTO); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
dmastat = dmaengine_tx_status(chan, dmastat = dmaengine_tx_status(chan,
atmel_port->cookie_rx, atmel_port->cookie_rx,
&state); &state);
/* Restart a new tasklet if DMA status is error */ /* Restart a new tasklet if DMA status is error */
if (dmastat == DMA_ERROR) { if (dmastat == DMA_ERROR) {
dev_dbg(port->dev, "Get residue error, restart tasklet\n"); dev_dbg(port->dev, "Get residue error, restart tasklet\n");
UART_PUT_IER(port, ATMEL_US_TIMEOUT); atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
tasklet_schedule(&atmel_port->tasklet); tasklet_schedule(&atmel_port->tasklet);
return; return;
} }
...@@ -1008,7 +1073,7 @@ static void atmel_rx_from_dma(struct uart_port *port) ...@@ -1008,7 +1073,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
tty_flip_buffer_push(tport); tty_flip_buffer_push(tport);
spin_lock(&port->lock); spin_lock(&port->lock);
UART_PUT_IER(port, ATMEL_US_TIMEOUT); atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
} }
static int atmel_prepare_rx_dma(struct uart_port *port) static int atmel_prepare_rx_dma(struct uart_port *port)
...@@ -1118,8 +1183,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending) ...@@ -1118,8 +1183,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
* the moment. * the moment.
*/ */
if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) { if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
UART_PUT_IDR(port, (ATMEL_US_ENDRX atmel_uart_writel(port, ATMEL_US_IDR,
| ATMEL_US_TIMEOUT)); (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
tasklet_schedule(&atmel_port->tasklet); tasklet_schedule(&atmel_port->tasklet);
} }
...@@ -1130,7 +1195,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending) ...@@ -1130,7 +1195,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
if (atmel_use_dma_rx(port)) { if (atmel_use_dma_rx(port)) {
if (pending & ATMEL_US_TIMEOUT) { if (pending & ATMEL_US_TIMEOUT) {
UART_PUT_IDR(port, ATMEL_US_TIMEOUT); atmel_uart_writel(port, ATMEL_US_IDR,
ATMEL_US_TIMEOUT);
tasklet_schedule(&atmel_port->tasklet); tasklet_schedule(&atmel_port->tasklet);
} }
} }
...@@ -1143,8 +1209,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending) ...@@ -1143,8 +1209,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
* End of break detected. If it came along with a * End of break detected. If it came along with a
* character, atmel_rx_chars will handle it. * character, atmel_rx_chars will handle it.
*/ */
UART_PUT_CR(port, ATMEL_US_RSTSTA); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
UART_PUT_IDR(port, ATMEL_US_RXBRK); atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
atmel_port->break_active = 0; atmel_port->break_active = 0;
} }
} }
...@@ -1159,7 +1225,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending) ...@@ -1159,7 +1225,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
if (pending & atmel_port->tx_done_mask) { if (pending & atmel_port->tx_done_mask) {
/* Either PDC or interrupt transmission */ /* Either PDC or interrupt transmission */
UART_PUT_IDR(port, atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IDR,
atmel_port->tx_done_mask);
tasklet_schedule(&atmel_port->tasklet); tasklet_schedule(&atmel_port->tasklet);
} }
} }
...@@ -1197,7 +1264,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) ...@@ -1197,7 +1264,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
do { do {
status = atmel_get_lines_status(port); status = atmel_get_lines_status(port);
mask = UART_GET_IMR(port); mask = atmel_uart_readl(port, ATMEL_US_IMR);
pending = status & mask; pending = status & mask;
if (!gpio_handled) { if (!gpio_handled) {
/* /*
...@@ -1223,7 +1290,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) ...@@ -1223,7 +1290,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
if (atmel_port->suspended) { if (atmel_port->suspended) {
atmel_port->pending |= pending; atmel_port->pending |= pending;
atmel_port->pending_status = status; atmel_port->pending_status = status;
UART_PUT_IDR(port, mask); atmel_uart_writel(port, ATMEL_US_IDR, mask);
pm_system_wakeup(); pm_system_wakeup();
break; break;
} }
...@@ -1260,7 +1327,7 @@ static void atmel_tx_pdc(struct uart_port *port) ...@@ -1260,7 +1327,7 @@ static void atmel_tx_pdc(struct uart_port *port)
int count; int count;
/* nothing left to transmit? */ /* nothing left to transmit? */
if (UART_GET_TCR(port)) if (atmel_uart_readl(port, ATMEL_PDC_TCR))
return; return;
xmit->tail += pdc->ofs; xmit->tail += pdc->ofs;
...@@ -1272,7 +1339,7 @@ static void atmel_tx_pdc(struct uart_port *port) ...@@ -1272,7 +1339,7 @@ static void atmel_tx_pdc(struct uart_port *port)
/* more to transmit - setup next transfer */ /* more to transmit - setup next transfer */
/* disable PDC transmit */ /* disable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
dma_sync_single_for_device(port->dev, dma_sync_single_for_device(port->dev,
...@@ -1283,12 +1350,14 @@ static void atmel_tx_pdc(struct uart_port *port) ...@@ -1283,12 +1350,14 @@ static void atmel_tx_pdc(struct uart_port *port)
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
pdc->ofs = count; pdc->ofs = count;
UART_PUT_TPR(port, pdc->dma_addr + xmit->tail); atmel_uart_writel(port, ATMEL_PDC_TPR,
UART_PUT_TCR(port, count); pdc->dma_addr + xmit->tail);
atmel_uart_writel(port, ATMEL_PDC_TCR, count);
/* re-enable PDC transmit */ /* re-enable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
/* Enable interrupts */ /* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IER,
atmel_port->tx_done_mask);
} else { } else {
if ((port->rs485.flags & SER_RS485_ENABLED) && if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) { !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
...@@ -1414,10 +1483,10 @@ static void atmel_rx_from_pdc(struct uart_port *port) ...@@ -1414,10 +1483,10 @@ static void atmel_rx_from_pdc(struct uart_port *port)
do { do {
/* Reset the UART timeout early so that we don't miss one */ /* Reset the UART timeout early so that we don't miss one */
UART_PUT_CR(port, ATMEL_US_STTTO); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
pdc = &atmel_port->pdc_rx[rx_idx]; pdc = &atmel_port->pdc_rx[rx_idx];
head = UART_GET_RPR(port) - pdc->dma_addr; head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
tail = pdc->ofs; tail = pdc->ofs;
/* If the PDC has switched buffers, RPR won't contain /* If the PDC has switched buffers, RPR won't contain
...@@ -1460,8 +1529,8 @@ static void atmel_rx_from_pdc(struct uart_port *port) ...@@ -1460,8 +1529,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
*/ */
if (head >= pdc->dma_size) { if (head >= pdc->dma_size) {
pdc->ofs = 0; pdc->ofs = 0;
UART_PUT_RNPR(port, pdc->dma_addr); atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
UART_PUT_RNCR(port, pdc->dma_size); atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
rx_idx = !rx_idx; rx_idx = !rx_idx;
atmel_port->pdc_rx_idx = rx_idx; atmel_port->pdc_rx_idx = rx_idx;
...@@ -1476,7 +1545,8 @@ static void atmel_rx_from_pdc(struct uart_port *port) ...@@ -1476,7 +1545,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
tty_flip_buffer_push(tport); tty_flip_buffer_push(tport);
spin_lock(&port->lock); spin_lock(&port->lock);
UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); atmel_uart_writel(port, ATMEL_US_IER,
ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
} }
static int atmel_prepare_rx_pdc(struct uart_port *port) static int atmel_prepare_rx_pdc(struct uart_port *port)
...@@ -1509,11 +1579,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port) ...@@ -1509,11 +1579,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
atmel_port->pdc_rx_idx = 0; atmel_port->pdc_rx_idx = 0;
UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr); atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
UART_PUT_RCR(port, PDC_BUFFER_SIZE); atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr); atmel_uart_writel(port, ATMEL_PDC_RNPR,
UART_PUT_RNCR(port, PDC_BUFFER_SIZE); atmel_port->pdc_rx[1].dma_addr);
atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
return 0; return 0;
} }
...@@ -1667,7 +1738,7 @@ static void atmel_set_ops(struct uart_port *port) ...@@ -1667,7 +1738,7 @@ static void atmel_set_ops(struct uart_port *port)
static void atmel_get_ip_name(struct uart_port *port) static void atmel_get_ip_name(struct uart_port *port)
{ {
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
int name = UART_GET_IP_NAME(port); int name = atmel_uart_readl(port, ATMEL_US_NAME);
u32 version; u32 version;
int usart, uart; int usart, uart;
/* usart and uart ascii */ /* usart and uart ascii */
...@@ -1684,7 +1755,7 @@ static void atmel_get_ip_name(struct uart_port *port) ...@@ -1684,7 +1755,7 @@ static void atmel_get_ip_name(struct uart_port *port)
atmel_port->is_usart = false; atmel_port->is_usart = false;
} else { } else {
/* fallback for older SoCs: use version field */ /* fallback for older SoCs: use version field */
version = UART_GET_IP_VERSION(port); version = atmel_uart_readl(port, ATMEL_US_VERSION);
switch (version) { switch (version) {
case 0x302: case 0x302:
case 0x10213: case 0x10213:
...@@ -1756,7 +1827,7 @@ static int atmel_startup(struct uart_port *port) ...@@ -1756,7 +1827,7 @@ static int atmel_startup(struct uart_port *port)
* request_irq() is called we could get stuck trying to * request_irq() is called we could get stuck trying to
* handle an unexpected interrupt * handle an unexpected interrupt
*/ */
UART_PUT_IDR(port, -1); atmel_uart_writel(port, ATMEL_US_IDR, -1);
atmel_port->ms_irq_enabled = false; atmel_port->ms_irq_enabled = false;
/* /*
...@@ -1797,6 +1868,32 @@ static int atmel_startup(struct uart_port *port) ...@@ -1797,6 +1868,32 @@ static int atmel_startup(struct uart_port *port)
atmel_set_ops(port); atmel_set_ops(port);
} }
/*
* Enable FIFO when available
*/
if (atmel_port->fifo_size) {
unsigned int txrdym = ATMEL_US_ONE_DATA;
unsigned int rxrdym = ATMEL_US_ONE_DATA;
unsigned int fmr;
atmel_uart_writel(port, ATMEL_US_CR,
ATMEL_US_FIFOEN |
ATMEL_US_RXFCLR |
ATMEL_US_TXFLCLR);
if (atmel_use_dma_tx(port))
txrdym = ATMEL_US_FOUR_DATA;
fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
if (atmel_port->rts_high &&
atmel_port->rts_low)
fmr |= ATMEL_US_FRTSC |
ATMEL_US_RXFTHRES(atmel_port->rts_high) |
ATMEL_US_RXFTHRES2(atmel_port->rts_low);
atmel_uart_writel(port, ATMEL_US_FMR, fmr);
}
/* Save current CSR for comparison in atmel_tasklet_func() */ /* Save current CSR for comparison in atmel_tasklet_func() */
atmel_port->irq_status_prev = atmel_get_lines_status(port); atmel_port->irq_status_prev = atmel_get_lines_status(port);
atmel_port->irq_status = atmel_port->irq_status_prev; atmel_port->irq_status = atmel_port->irq_status_prev;
...@@ -1804,9 +1901,9 @@ static int atmel_startup(struct uart_port *port) ...@@ -1804,9 +1901,9 @@ static int atmel_startup(struct uart_port *port)
/* /*
* Finally, enable the serial port * Finally, enable the serial port
*/ */
UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
/* enable xmit & rcvr */ /* enable xmit & rcvr */
UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
setup_timer(&atmel_port->uart_timer, setup_timer(&atmel_port->uart_timer,
atmel_uart_timer_callback, atmel_uart_timer_callback,
...@@ -1819,13 +1916,14 @@ static int atmel_startup(struct uart_port *port) ...@@ -1819,13 +1916,14 @@ static int atmel_startup(struct uart_port *port)
jiffies + uart_poll_timeout(port)); jiffies + uart_poll_timeout(port));
/* set USART timeout */ /* set USART timeout */
} else { } else {
UART_PUT_RTOR(port, PDC_RX_TIMEOUT); atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
UART_PUT_CR(port, ATMEL_US_STTTO); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); atmel_uart_writel(port, ATMEL_US_IER,
ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
} }
/* enable PDC controller */ /* enable PDC controller */
UART_PUT_PTCR(port, ATMEL_PDC_RXTEN); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
} else if (atmel_use_dma_rx(port)) { } else if (atmel_use_dma_rx(port)) {
/* set UART timeout */ /* set UART timeout */
if (!atmel_port->is_usart) { if (!atmel_port->is_usart) {
...@@ -1833,14 +1931,15 @@ static int atmel_startup(struct uart_port *port) ...@@ -1833,14 +1931,15 @@ static int atmel_startup(struct uart_port *port)
jiffies + uart_poll_timeout(port)); jiffies + uart_poll_timeout(port));
/* set USART timeout */ /* set USART timeout */
} else { } else {
UART_PUT_RTOR(port, PDC_RX_TIMEOUT); atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
UART_PUT_CR(port, ATMEL_US_STTTO); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
UART_PUT_IER(port, ATMEL_US_TIMEOUT); atmel_uart_writel(port, ATMEL_US_IER,
ATMEL_US_TIMEOUT);
} }
} else { } else {
/* enable receive only */ /* enable receive only */
UART_PUT_IER(port, ATMEL_US_RXRDY); atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
} }
return 0; return 0;
...@@ -1860,7 +1959,7 @@ static void atmel_flush_buffer(struct uart_port *port) ...@@ -1860,7 +1959,7 @@ static void atmel_flush_buffer(struct uart_port *port)
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_use_pdc_tx(port)) { if (atmel_use_pdc_tx(port)) {
UART_PUT_TCR(port, 0); atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
atmel_port->pdc_tx.ofs = 0; atmel_port->pdc_tx.ofs = 0;
} }
} }
...@@ -1892,8 +1991,8 @@ static void atmel_shutdown(struct uart_port *port) ...@@ -1892,8 +1991,8 @@ static void atmel_shutdown(struct uart_port *port)
atmel_stop_rx(port); atmel_stop_rx(port);
atmel_stop_tx(port); atmel_stop_tx(port);
UART_PUT_CR(port, ATMEL_US_RSTSTA); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
UART_PUT_IDR(port, -1); atmel_uart_writel(port, ATMEL_US_IDR, -1);
/* /*
...@@ -1938,12 +2037,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, ...@@ -1938,12 +2037,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
clk_prepare_enable(atmel_port->clk); clk_prepare_enable(atmel_port->clk);
/* re-enable interrupts if we disabled some on suspend */ /* re-enable interrupts if we disabled some on suspend */
UART_PUT_IER(port, atmel_port->backup_imr); atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
break; break;
case 3: case 3:
/* Back up the interrupt mask and disable all interrupts */ /* Back up the interrupt mask and disable all interrupts */
atmel_port->backup_imr = UART_GET_IMR(port); atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
UART_PUT_IDR(port, -1); atmel_uart_writel(port, ATMEL_US_IDR, -1);
/* /*
* Disable the peripheral clock for this serial port. * Disable the peripheral clock for this serial port.
...@@ -1966,7 +2065,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1966,7 +2065,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned int old_mode, mode, imr, quot, baud; unsigned int old_mode, mode, imr, quot, baud;
/* save the current mode register */ /* save the current mode register */
mode = old_mode = UART_GET_MR(port); mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
/* reset the mode, clock divisor, parity, stop bits and data size */ /* reset the mode, clock divisor, parity, stop bits and data size */
mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP | mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
...@@ -2025,7 +2124,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2025,7 +2124,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
if (atmel_use_pdc_rx(port)) if (atmel_use_pdc_rx(port))
/* need to enable error interrupts */ /* need to enable error interrupts */
UART_PUT_IER(port, port->read_status_mask); atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
/* /*
* Characters to ignore * Characters to ignore
...@@ -2052,15 +2151,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2052,15 +2151,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
* transmitter is empty if requested by the caller, so there's * transmitter is empty if requested by the caller, so there's
* no need to wait for it here. * no need to wait for it here.
*/ */
imr = UART_GET_IMR(port); imr = atmel_uart_readl(port, ATMEL_US_IMR);
UART_PUT_IDR(port, -1); atmel_uart_writel(port, ATMEL_US_IDR, -1);
/* disable receiver and transmitter */ /* disable receiver and transmitter */
UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
/* mode */ /* mode */
if (port->rs485.flags & SER_RS485_ENABLED) { if (port->rs485.flags & SER_RS485_ENABLED) {
UART_PUT_TTGR(port, port->rs485.delay_rts_after_send); atmel_uart_writel(port, ATMEL_US_TTGR,
port->rs485.delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485; mode |= ATMEL_US_USMODE_RS485;
} else if (termios->c_cflag & CRTSCTS) { } else if (termios->c_cflag & CRTSCTS) {
/* RS232 with hardware handshake (RTS/CTS) */ /* RS232 with hardware handshake (RTS/CTS) */
...@@ -2071,7 +2171,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2071,7 +2171,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
} }
/* set the mode, clock divisor, parity, stop bits and data size */ /* set the mode, clock divisor, parity, stop bits and data size */
UART_PUT_MR(port, mode); atmel_uart_writel(port, ATMEL_US_MR, mode);
/* /*
* when switching the mode, set the RTS line state according to the * when switching the mode, set the RTS line state according to the
...@@ -2088,16 +2188,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2088,16 +2188,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
rts_state = ATMEL_US_RTSEN; rts_state = ATMEL_US_RTSEN;
} }
UART_PUT_CR(port, rts_state); atmel_uart_writel(port, ATMEL_US_CR, rts_state);
} }
/* set the baud rate */ /* set the baud rate */
UART_PUT_BRGR(port, quot); atmel_uart_writel(port, ATMEL_US_BRGR, quot);
UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
/* restore interrupts */ /* restore interrupts */
UART_PUT_IER(port, imr); atmel_uart_writel(port, ATMEL_US_IER, imr);
/* CTS flow-control and modem-status interrupts */ /* CTS flow-control and modem-status interrupts */
if (UART_ENABLE_MS(port, termios->c_cflag)) if (UART_ENABLE_MS(port, termios->c_cflag))
...@@ -2208,18 +2308,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser) ...@@ -2208,18 +2308,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
#ifdef CONFIG_CONSOLE_POLL #ifdef CONFIG_CONSOLE_POLL
static int atmel_poll_get_char(struct uart_port *port) static int atmel_poll_get_char(struct uart_port *port)
{ {
while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY)) while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
cpu_relax(); cpu_relax();
return UART_GET_CHAR(port); return atmel_uart_read_char(port);
} }
static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
{ {
while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY)) while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
cpu_relax(); cpu_relax();
UART_PUT_CHAR(port, ch); atmel_uart_write_char(port, ch);
} }
#endif #endif
...@@ -2324,9 +2424,9 @@ struct platform_device *atmel_default_console_device; /* the serial console devi ...@@ -2324,9 +2424,9 @@ struct platform_device *atmel_default_console_device; /* the serial console devi
#ifdef CONFIG_SERIAL_ATMEL_CONSOLE #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
static void atmel_console_putchar(struct uart_port *port, int ch) static void atmel_console_putchar(struct uart_port *port, int ch)
{ {
while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY)) while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
cpu_relax(); cpu_relax();
UART_PUT_CHAR(port, ch); atmel_uart_write_char(port, ch);
} }
/* /*
...@@ -2342,12 +2442,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) ...@@ -2342,12 +2442,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
/* /*
* First, save IMR and then disable interrupts * First, save IMR and then disable interrupts
*/ */
imr = UART_GET_IMR(port); imr = atmel_uart_readl(port, ATMEL_US_IMR);
UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IDR,
ATMEL_US_RXRDY | atmel_port->tx_done_mask);
/* Store PDC transmit status and disable it */ /* Store PDC transmit status and disable it */
pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN; pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
uart_console_write(port, s, count, atmel_console_putchar); uart_console_write(port, s, count, atmel_console_putchar);
...@@ -2356,15 +2457,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) ...@@ -2356,15 +2457,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
* and restore IMR * and restore IMR
*/ */
do { do {
status = UART_GET_CSR(port); status = atmel_uart_readl(port, ATMEL_US_CSR);
} while (!(status & ATMEL_US_TXRDY)); } while (!(status & ATMEL_US_TXRDY));
/* Restore PDC transmit status */ /* Restore PDC transmit status */
if (pdc_tx) if (pdc_tx)
UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
/* set interrupts back the way they were */ /* set interrupts back the way they were */
UART_PUT_IER(port, imr); atmel_uart_writel(port, ATMEL_US_IER, imr);
} }
/* /*
...@@ -2380,17 +2481,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud, ...@@ -2380,17 +2481,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
* If the baud rate generator isn't running, the port wasn't * If the baud rate generator isn't running, the port wasn't
* initialized by the boot loader. * initialized by the boot loader.
*/ */
quot = UART_GET_BRGR(port) & ATMEL_US_CD; quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
if (!quot) if (!quot)
return; return;
mr = UART_GET_MR(port) & ATMEL_US_CHRL; mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
if (mr == ATMEL_US_CHRL_8) if (mr == ATMEL_US_CHRL_8)
*bits = 8; *bits = 8;
else else
*bits = 7; *bits = 7;
mr = UART_GET_MR(port) & ATMEL_US_PAR; mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
if (mr == ATMEL_US_PAR_EVEN) if (mr == ATMEL_US_PAR_EVEN)
*parity = 'e'; *parity = 'e';
else if (mr == ATMEL_US_PAR_ODD) else if (mr == ATMEL_US_PAR_ODD)
...@@ -2423,9 +2524,9 @@ static int __init atmel_console_setup(struct console *co, char *options) ...@@ -2423,9 +2524,9 @@ static int __init atmel_console_setup(struct console *co, char *options)
if (ret) if (ret)
return ret; return ret;
UART_PUT_IDR(port, -1); atmel_uart_writel(port, ATMEL_US_IDR, -1);
UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
if (options) if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow); uart_parse_options(options, &baud, &parity, &bits, &flow);
...@@ -2532,7 +2633,8 @@ static int atmel_serial_suspend(struct platform_device *pdev, ...@@ -2532,7 +2633,8 @@ static int atmel_serial_suspend(struct platform_device *pdev,
if (atmel_is_console_port(port) && console_suspend_enabled) { if (atmel_is_console_port(port) && console_suspend_enabled) {
/* Drain the TX shifter */ /* Drain the TX shifter */
while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY)) while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
ATMEL_US_TXEMPTY))
cpu_relax(); cpu_relax();
} }
...@@ -2599,6 +2701,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev) ...@@ -2599,6 +2701,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
return 0; return 0;
} }
static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
struct platform_device *pdev)
{
port->fifo_size = 0;
port->rts_low = 0;
port->rts_high = 0;
if (of_property_read_u32(pdev->dev.of_node,
"atmel,fifo-size",
&port->fifo_size))
return;
if (!port->fifo_size)
return;
if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
port->fifo_size = 0;
dev_err(&pdev->dev, "Invalid FIFO size\n");
return;
}
/*
* 0 <= rts_low <= rts_high <= fifo_size
* Once their CTS line asserted by the remote peer, some x86 UARTs tend
* to flush their internal TX FIFO, commonly up to 16 data, before
* actually stopping to send new data. So we try to set the RTS High
* Threshold to a reasonably high value respecting this 16 data
* empirical rule when possible.
*/
port->rts_high = max_t(int, port->fifo_size >> 1,
port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
port->rts_low = max_t(int, port->fifo_size >> 2,
port->fifo_size - ATMEL_RTS_LOW_OFFSET);
dev_info(&pdev->dev, "Using FIFO (%u data)\n",
port->fifo_size);
dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
port->rts_high);
dev_dbg(&pdev->dev, "RTS Low Threshold : %2u data\n",
port->rts_low);
}
static int atmel_serial_probe(struct platform_device *pdev) static int atmel_serial_probe(struct platform_device *pdev)
{ {
struct atmel_uart_port *port; struct atmel_uart_port *port;
...@@ -2635,6 +2779,7 @@ static int atmel_serial_probe(struct platform_device *pdev) ...@@ -2635,6 +2779,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
port = &atmel_ports[ret]; port = &atmel_ports[ret];
port->backup_imr = 0; port->backup_imr = 0;
port->uart.line = ret; port->uart.line = ret;
atmel_serial_probe_fifos(port, pdev);
spin_lock_init(&port->lock_suspended); spin_lock_init(&port->lock_suspended);
...@@ -2684,8 +2829,9 @@ static int atmel_serial_probe(struct platform_device *pdev) ...@@ -2684,8 +2829,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
clk_prepare_enable(port->clk); clk_prepare_enable(port->clk);
if (rs485_enabled) { if (rs485_enabled) {
UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL); atmel_uart_writel(&port->uart, ATMEL_US_MR,
UART_PUT_CR(&port->uart, ATMEL_US_RTSEN); ATMEL_US_USMODE_NORMAL);
atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
} }
/* /*
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <hwregs/ser_defs.h> #include <hwregs/ser_defs.h>
#include "serial_mctrl_gpio.h"
#define DRV_NAME "etraxfs-uart" #define DRV_NAME "etraxfs-uart"
#define UART_NR CONFIG_ETRAX_SERIAL_PORTS #define UART_NR CONFIG_ETRAX_SERIAL_PORTS
...@@ -28,10 +30,7 @@ struct uart_cris_port { ...@@ -28,10 +30,7 @@ struct uart_cris_port {
void __iomem *regi_ser; void __iomem *regi_ser;
struct gpio_desc *dtr_pin; struct mctrl_gpios *gpios;
struct gpio_desc *dsr_pin;
struct gpio_desc *ri_pin;
struct gpio_desc *cd_pin;
int write_ongoing; int write_ongoing;
}; };
...@@ -112,17 +111,10 @@ cris_console_setup(struct console *co, char *options) ...@@ -112,17 +111,10 @@ cris_console_setup(struct console *co, char *options)
return 0; return 0;
} }
static struct tty_driver *cris_console_device(struct console *co, int *index)
{
struct uart_driver *p = co->data;
*index = co->index;
return p->tty_driver;
}
static struct console cris_console = { static struct console cris_console = {
.name = "ttyS", .name = "ttyS",
.write = cris_console_write, .write = cris_console_write,
.device = cris_console_device, .device = uart_console_device,
.setup = cris_console_setup, .setup = cris_console_setup,
.flags = CON_PRINTBUFFER, .flags = CON_PRINTBUFFER,
.index = -1, .index = -1,
...@@ -373,14 +365,6 @@ static void etraxfs_uart_stop_rx(struct uart_port *port) ...@@ -373,14 +365,6 @@ static void etraxfs_uart_stop_rx(struct uart_port *port)
REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl); REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
} }
static void etraxfs_uart_enable_ms(struct uart_port *port)
{
}
static void check_modem_status(struct uart_cris_port *up)
{
}
static unsigned int etraxfs_uart_tx_empty(struct uart_port *port) static unsigned int etraxfs_uart_tx_empty(struct uart_port *port)
{ {
struct uart_cris_port *up = (struct uart_cris_port *)port; struct uart_cris_port *up = (struct uart_cris_port *)port;
...@@ -404,21 +388,9 @@ static unsigned int etraxfs_uart_get_mctrl(struct uart_port *port) ...@@ -404,21 +388,9 @@ static unsigned int etraxfs_uart_get_mctrl(struct uart_port *port)
ret = 0; ret = 0;
if (crisv32_serial_get_rts(up)) if (crisv32_serial_get_rts(up))
ret |= TIOCM_RTS; ret |= TIOCM_RTS;
/* DTR is active low */
if (up->dtr_pin && !gpiod_get_raw_value(up->dtr_pin))
ret |= TIOCM_DTR;
/* CD is active low */
if (up->cd_pin && !gpiod_get_raw_value(up->cd_pin))
ret |= TIOCM_CD;
/* RI is active low */
if (up->ri_pin && !gpiod_get_raw_value(up->ri_pin))
ret |= TIOCM_RI;
/* DSR is active low */
if (up->dsr_pin && !gpiod_get_raw_value(up->dsr_pin))
ret |= TIOCM_DSR;
if (crisv32_serial_get_cts(up)) if (crisv32_serial_get_cts(up))
ret |= TIOCM_CTS; ret |= TIOCM_CTS;
return ret; return mctrl_gpio_get(up->gpios, &ret);
} }
static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
...@@ -426,15 +398,7 @@ static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) ...@@ -426,15 +398,7 @@ static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
struct uart_cris_port *up = (struct uart_cris_port *)port; struct uart_cris_port *up = (struct uart_cris_port *)port;
crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0); crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0);
/* DTR is active low */ mctrl_gpio_set(up->gpios, mctrl);
if (up->dtr_pin)
gpiod_set_raw_value(up->dtr_pin, mctrl & TIOCM_DTR ? 0 : 1);
/* RI is active low */
if (up->ri_pin)
gpiod_set_raw_value(up->ri_pin, mctrl & TIOCM_RNG ? 0 : 1);
/* CD is active low */
if (up->cd_pin)
gpiod_set_raw_value(up->cd_pin, mctrl & TIOCM_CD ? 0 : 1);
} }
static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state) static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state)
...@@ -598,7 +562,6 @@ ser_interrupt(int irq, void *dev_id) ...@@ -598,7 +562,6 @@ ser_interrupt(int irq, void *dev_id)
receive_chars_no_dma(up); receive_chars_no_dma(up);
handled = 1; handled = 1;
} }
check_modem_status(up);
if (masked_intr.tr_rdy) { if (masked_intr.tr_rdy) {
transmit_chars_no_dma(up); transmit_chars_no_dma(up);
...@@ -862,7 +825,6 @@ static const struct uart_ops etraxfs_uart_pops = { ...@@ -862,7 +825,6 @@ static const struct uart_ops etraxfs_uart_pops = {
.start_tx = etraxfs_uart_start_tx, .start_tx = etraxfs_uart_start_tx,
.send_xchar = etraxfs_uart_send_xchar, .send_xchar = etraxfs_uart_send_xchar,
.stop_rx = etraxfs_uart_stop_rx, .stop_rx = etraxfs_uart_stop_rx,
.enable_ms = etraxfs_uart_enable_ms,
.break_ctl = etraxfs_uart_break_ctl, .break_ctl = etraxfs_uart_break_ctl,
.startup = etraxfs_uart_startup, .startup = etraxfs_uart_startup,
.shutdown = etraxfs_uart_shutdown, .shutdown = etraxfs_uart_shutdown,
...@@ -930,11 +892,12 @@ static int etraxfs_uart_probe(struct platform_device *pdev) ...@@ -930,11 +892,12 @@ static int etraxfs_uart_probe(struct platform_device *pdev)
up->irq = irq_of_parse_and_map(np, 0); up->irq = irq_of_parse_and_map(np, 0);
up->regi_ser = of_iomap(np, 0); up->regi_ser = of_iomap(np, 0);
up->dtr_pin = devm_gpiod_get_optional(&pdev->dev, "dtr");
up->dsr_pin = devm_gpiod_get_optional(&pdev->dev, "dsr");
up->ri_pin = devm_gpiod_get_optional(&pdev->dev, "ri");
up->cd_pin = devm_gpiod_get_optional(&pdev->dev, "cd");
up->port.dev = &pdev->dev; up->port.dev = &pdev->dev;
up->gpios = mctrl_gpio_init(&pdev->dev, 0);
if (IS_ERR(up->gpios))
return PTR_ERR(up->gpios);
cris_serial_port_init(&up->port, dev_id); cris_serial_port_init(&up->port, dev_id);
etraxfs_uart_ports[dev_id] = up; etraxfs_uart_ports[dev_id] = up;
......
...@@ -216,6 +216,8 @@ struct imx_port { ...@@ -216,6 +216,8 @@ struct imx_port {
unsigned int tx_bytes; unsigned int tx_bytes;
unsigned int dma_tx_nents; unsigned int dma_tx_nents;
wait_queue_head_t dma_wait; wait_queue_head_t dma_wait;
unsigned int saved_reg[10];
bool context_saved;
}; };
struct imx_port_ucrs { struct imx_port_ucrs {
...@@ -700,7 +702,8 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) ...@@ -700,7 +702,8 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
if (sport->port.ignore_status_mask & URXD_DUMMY_READ) if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
goto out; goto out;
tty_insert_flip_char(port, rx, flg); if (tty_insert_flip_char(port, rx, flg) == 0)
sport->port.icount.buf_overrun++;
} }
out: out:
...@@ -766,7 +769,6 @@ static irqreturn_t imx_int(int irq, void *dev_id) ...@@ -766,7 +769,6 @@ static irqreturn_t imx_int(int irq, void *dev_id)
writel(USR1_AWAKE, sport->port.membase + USR1); writel(USR1_AWAKE, sport->port.membase + USR1);
if (sts2 & USR2_ORE) { if (sts2 & USR2_ORE) {
dev_err(sport->port.dev, "Rx FIFO overrun\n");
sport->port.icount.overrun++; sport->port.icount.overrun++;
writel(USR2_ORE, sport->port.membase + USR2); writel(USR2_ORE, sport->port.membase + USR2);
} }
...@@ -921,8 +923,13 @@ static void dma_rx_callback(void *data) ...@@ -921,8 +923,13 @@ static void dma_rx_callback(void *data)
dev_dbg(sport->port.dev, "We get %d bytes.\n", count); dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
if (count) { if (count) {
if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
tty_insert_flip_string(port, sport->rx_buf, count); int bytes = tty_insert_flip_string(port, sport->rx_buf,
count);
if (bytes != count)
sport->port.icount.buf_overrun++;
}
tty_flip_buffer_push(port); tty_flip_buffer_push(port);
start_rx_dma(sport); start_rx_dma(sport);
...@@ -1624,12 +1631,12 @@ imx_console_write(struct console *co, const char *s, unsigned int count) ...@@ -1624,12 +1631,12 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
int locked = 1; int locked = 1;
int retval; int retval;
retval = clk_enable(sport->clk_per); retval = clk_prepare_enable(sport->clk_per);
if (retval) if (retval)
return; return;
retval = clk_enable(sport->clk_ipg); retval = clk_prepare_enable(sport->clk_ipg);
if (retval) { if (retval) {
clk_disable(sport->clk_per); clk_disable_unprepare(sport->clk_per);
return; return;
} }
...@@ -1668,8 +1675,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count) ...@@ -1668,8 +1675,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
if (locked) if (locked)
spin_unlock_irqrestore(&sport->port.lock, flags); spin_unlock_irqrestore(&sport->port.lock, flags);
clk_disable(sport->clk_ipg); clk_disable_unprepare(sport->clk_ipg);
clk_disable(sport->clk_per); clk_disable_unprepare(sport->clk_per);
} }
/* /*
...@@ -1770,15 +1777,7 @@ imx_console_setup(struct console *co, char *options) ...@@ -1770,15 +1777,7 @@ imx_console_setup(struct console *co, char *options)
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow); retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
clk_disable(sport->clk_ipg); clk_disable_unprepare(sport->clk_ipg);
if (retval) {
clk_unprepare(sport->clk_ipg);
goto error_console;
}
retval = clk_prepare(sport->clk_per);
if (retval)
clk_disable_unprepare(sport->clk_ipg);
error_console: error_console:
return retval; return retval;
...@@ -1810,36 +1809,6 @@ static struct uart_driver imx_reg = { ...@@ -1810,36 +1809,6 @@ static struct uart_driver imx_reg = {
.cons = IMX_CONSOLE, .cons = IMX_CONSOLE,
}; };
static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
{
struct imx_port *sport = platform_get_drvdata(dev);
unsigned int val;
/* enable wakeup from i.MX UART */
val = readl(sport->port.membase + UCR3);
val |= UCR3_AWAKEN;
writel(val, sport->port.membase + UCR3);
uart_suspend_port(&imx_reg, &sport->port);
return 0;
}
static int serial_imx_resume(struct platform_device *dev)
{
struct imx_port *sport = platform_get_drvdata(dev);
unsigned int val;
/* disable wakeup from i.MX UART */
val = readl(sport->port.membase + UCR3);
val &= ~UCR3_AWAKEN;
writel(val, sport->port.membase + UCR3);
uart_resume_port(&imx_reg, &sport->port);
return 0;
}
#ifdef CONFIG_OF #ifdef CONFIG_OF
/* /*
* This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
...@@ -1901,7 +1870,7 @@ static int serial_imx_probe(struct platform_device *pdev) ...@@ -1901,7 +1870,7 @@ static int serial_imx_probe(struct platform_device *pdev)
{ {
struct imx_port *sport; struct imx_port *sport;
void __iomem *base; void __iomem *base;
int ret = 0; int ret = 0, reg;
struct resource *res; struct resource *res;
int txirq, rxirq, rtsirq; int txirq, rxirq, rtsirq;
...@@ -1956,6 +1925,19 @@ static int serial_imx_probe(struct platform_device *pdev) ...@@ -1956,6 +1925,19 @@ static int serial_imx_probe(struct platform_device *pdev)
sport->port.uartclk = clk_get_rate(sport->clk_per); sport->port.uartclk = clk_get_rate(sport->clk_per);
/* For register access, we only need to enable the ipg clock. */
ret = clk_prepare_enable(sport->clk_ipg);
if (ret)
return ret;
/* Disable interrupts before requesting them */
reg = readl_relaxed(sport->port.membase + UCR1);
reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
UCR1_TXMPTYEN | UCR1_RTSDEN);
writel_relaxed(reg, sport->port.membase + UCR1);
clk_disable_unprepare(sport->clk_ipg);
/* /*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt. * chips only have one interrupt.
...@@ -1991,16 +1973,135 @@ static int serial_imx_remove(struct platform_device *pdev) ...@@ -1991,16 +1973,135 @@ static int serial_imx_remove(struct platform_device *pdev)
return uart_remove_one_port(&imx_reg, &sport->port); return uart_remove_one_port(&imx_reg, &sport->port);
} }
static void serial_imx_restore_context(struct imx_port *sport)
{
if (!sport->context_saved)
return;
writel(sport->saved_reg[4], sport->port.membase + UFCR);
writel(sport->saved_reg[5], sport->port.membase + UESC);
writel(sport->saved_reg[6], sport->port.membase + UTIM);
writel(sport->saved_reg[7], sport->port.membase + UBIR);
writel(sport->saved_reg[8], sport->port.membase + UBMR);
writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
writel(sport->saved_reg[0], sport->port.membase + UCR1);
writel(sport->saved_reg[1] | UCR2_SRST, sport->port.membase + UCR2);
writel(sport->saved_reg[2], sport->port.membase + UCR3);
writel(sport->saved_reg[3], sport->port.membase + UCR4);
sport->context_saved = false;
}
static void serial_imx_save_context(struct imx_port *sport)
{
/* Save necessary regs */
sport->saved_reg[0] = readl(sport->port.membase + UCR1);
sport->saved_reg[1] = readl(sport->port.membase + UCR2);
sport->saved_reg[2] = readl(sport->port.membase + UCR3);
sport->saved_reg[3] = readl(sport->port.membase + UCR4);
sport->saved_reg[4] = readl(sport->port.membase + UFCR);
sport->saved_reg[5] = readl(sport->port.membase + UESC);
sport->saved_reg[6] = readl(sport->port.membase + UTIM);
sport->saved_reg[7] = readl(sport->port.membase + UBIR);
sport->saved_reg[8] = readl(sport->port.membase + UBMR);
sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
sport->context_saved = true;
}
static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
{
unsigned int val;
val = readl(sport->port.membase + UCR3);
if (on)
val |= UCR3_AWAKEN;
else
val &= ~UCR3_AWAKEN;
writel(val, sport->port.membase + UCR3);
val = readl(sport->port.membase + UCR1);
if (on)
val |= UCR1_RTSDEN;
else
val &= ~UCR1_RTSDEN;
writel(val, sport->port.membase + UCR1);
}
static int imx_serial_port_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
int ret;
ret = clk_enable(sport->clk_ipg);
if (ret)
return ret;
serial_imx_save_context(sport);
clk_disable(sport->clk_ipg);
return 0;
}
static int imx_serial_port_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
int ret;
ret = clk_enable(sport->clk_ipg);
if (ret)
return ret;
serial_imx_restore_context(sport);
clk_disable(sport->clk_ipg);
return 0;
}
static int imx_serial_port_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
/* enable wakeup from i.MX UART */
serial_imx_enable_wakeup(sport, true);
uart_suspend_port(&imx_reg, &sport->port);
return 0;
}
static int imx_serial_port_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
/* disable wakeup from i.MX UART */
serial_imx_enable_wakeup(sport, false);
uart_resume_port(&imx_reg, &sport->port);
return 0;
}
static const struct dev_pm_ops imx_serial_port_pm_ops = {
.suspend_noirq = imx_serial_port_suspend_noirq,
.resume_noirq = imx_serial_port_resume_noirq,
.suspend = imx_serial_port_suspend,
.resume = imx_serial_port_resume,
};
static struct platform_driver serial_imx_driver = { static struct platform_driver serial_imx_driver = {
.probe = serial_imx_probe, .probe = serial_imx_probe,
.remove = serial_imx_remove, .remove = serial_imx_remove,
.suspend = serial_imx_suspend,
.resume = serial_imx_resume,
.id_table = imx_uart_devtype, .id_table = imx_uart_devtype,
.driver = { .driver = {
.name = "imx-uart", .name = "imx-uart",
.of_match_table = imx_uart_dt_ids, .of_match_table = imx_uart_dt_ids,
.pm = &imx_serial_port_pm_ops,
}, },
}; };
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/console.h> #include <linux/console.h>
...@@ -740,7 +739,6 @@ static const struct of_device_id ltq_asc_match[] = { ...@@ -740,7 +739,6 @@ static const struct of_device_id ltq_asc_match[] = {
{ .compatible = DRVNAME }, { .compatible = DRVNAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, ltq_asc_match);
static struct platform_driver lqasc_driver = { static struct platform_driver lqasc_driver = {
.driver = { .driver = {
...@@ -764,8 +762,4 @@ init_lqasc(void) ...@@ -764,8 +762,4 @@ init_lqasc(void)
return ret; return ret;
} }
device_initcall(init_lqasc);
module_init(init_lqasc);
MODULE_DESCRIPTION("Lantiq serial port driver");
MODULE_LICENSE("GPL");
...@@ -392,7 +392,6 @@ static irqreturn_t men_z135_intr(int irq, void *data) ...@@ -392,7 +392,6 @@ static irqreturn_t men_z135_intr(int irq, void *data)
struct men_z135_port *uart = (struct men_z135_port *)data; struct men_z135_port *uart = (struct men_z135_port *)data;
struct uart_port *port = &uart->port; struct uart_port *port = &uart->port;
bool handled = false; bool handled = false;
unsigned long flags;
int irq_id; int irq_id;
uart->stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG); uart->stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
...@@ -401,7 +400,7 @@ static irqreturn_t men_z135_intr(int irq, void *data) ...@@ -401,7 +400,7 @@ static irqreturn_t men_z135_intr(int irq, void *data)
if (!irq_id) if (!irq_id)
goto out; goto out;
spin_lock_irqsave(&port->lock, flags); spin_lock(&port->lock);
/* It's save to write to IIR[7:6] RXC[9:8] */ /* It's save to write to IIR[7:6] RXC[9:8] */
iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG); iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG);
...@@ -427,7 +426,7 @@ static irqreturn_t men_z135_intr(int irq, void *data) ...@@ -427,7 +426,7 @@ static irqreturn_t men_z135_intr(int irq, void *data)
handled = true; handled = true;
} }
spin_unlock_irqrestore(&port->lock, flags); spin_unlock(&port->lock);
out: out:
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
...@@ -717,7 +716,7 @@ static void men_z135_set_termios(struct uart_port *port, ...@@ -717,7 +716,7 @@ static void men_z135_set_termios(struct uart_port *port,
baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16); baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16);
spin_lock(&port->lock); spin_lock_irq(&port->lock);
if (tty_termios_baud_rate(termios)) if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud); tty_termios_encode_baud_rate(termios, baud, baud);
...@@ -725,7 +724,7 @@ static void men_z135_set_termios(struct uart_port *port, ...@@ -725,7 +724,7 @@ static void men_z135_set_termios(struct uart_port *port,
iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG); iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG);
uart_update_timeout(port, termios->c_cflag, baud); uart_update_timeout(port, termios->c_cflag, baud);
spin_unlock(&port->lock); spin_unlock_irq(&port->lock);
} }
static const char *men_z135_type(struct uart_port *port) static const char *men_z135_type(struct uart_port *port)
...@@ -840,7 +839,6 @@ static int men_z135_probe(struct mcb_device *mdev, ...@@ -840,7 +839,6 @@ static int men_z135_probe(struct mcb_device *mdev,
uart->port.membase = NULL; uart->port.membase = NULL;
uart->mdev = mdev; uart->mdev = mdev;
spin_lock_init(&uart->port.lock);
spin_lock_init(&uart->lock); spin_lock_init(&uart->lock);
err = uart_add_one_port(&men_z135_driver, &uart->port); err = uart_add_one_port(&men_z135_driver, &uart->port);
......
...@@ -239,8 +239,9 @@ static int mpc52xx_psc_tx_rdy(struct uart_port *port) ...@@ -239,8 +239,9 @@ static int mpc52xx_psc_tx_rdy(struct uart_port *port)
static int mpc52xx_psc_tx_empty(struct uart_port *port) static int mpc52xx_psc_tx_empty(struct uart_port *port)
{ {
return in_be16(&PSC(port)->mpc52xx_psc_status) u16 sts = in_be16(&PSC(port)->mpc52xx_psc_status);
& MPC52xx_PSC_SR_TXEMP;
return (sts & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
} }
static void mpc52xx_psc_start_tx(struct uart_port *port) static void mpc52xx_psc_start_tx(struct uart_port *port)
......
...@@ -100,6 +100,8 @@ ...@@ -100,6 +100,8 @@
#define AUART_CTRL2_TXE (1 << 8) #define AUART_CTRL2_TXE (1 << 8)
#define AUART_CTRL2_UARTEN (1 << 0) #define AUART_CTRL2_UARTEN (1 << 0)
#define AUART_LINECTRL_BAUD_DIV_MAX 0x003fffc0
#define AUART_LINECTRL_BAUD_DIV_MIN 0x000000ec
#define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16 #define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16
#define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000 #define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000
#define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16) #define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
...@@ -659,7 +661,7 @@ static void mxs_auart_settermios(struct uart_port *u, ...@@ -659,7 +661,7 @@ static void mxs_auart_settermios(struct uart_port *u,
{ {
struct mxs_auart_port *s = to_auart_port(u); struct mxs_auart_port *s = to_auart_port(u);
u32 bm, ctrl, ctrl2, div; u32 bm, ctrl, ctrl2, div;
unsigned int cflag, baud; unsigned int cflag, baud, baud_min, baud_max;
cflag = termios->c_cflag; cflag = termios->c_cflag;
...@@ -752,7 +754,9 @@ static void mxs_auart_settermios(struct uart_port *u, ...@@ -752,7 +754,9 @@ static void mxs_auart_settermios(struct uart_port *u,
} }
/* set baud rate */ /* set baud rate */
baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk); baud_min = DIV_ROUND_UP(u->uartclk * 32, AUART_LINECTRL_BAUD_DIV_MAX);
baud_max = u->uartclk * 32 / AUART_LINECTRL_BAUD_DIV_MIN;
baud = uart_get_baud_rate(u, termios, old, baud_min, baud_max);
div = u->uartclk * 32 / baud; div = u->uartclk * 32 / baud;
ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F); ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6); ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
...@@ -842,7 +846,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context) ...@@ -842,7 +846,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void mxs_auart_reset(struct uart_port *u) static void mxs_auart_reset_deassert(struct uart_port *u)
{ {
int i; int i;
unsigned int reg; unsigned int reg;
...@@ -858,6 +862,30 @@ static void mxs_auart_reset(struct uart_port *u) ...@@ -858,6 +862,30 @@ static void mxs_auart_reset(struct uart_port *u)
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
} }
static void mxs_auart_reset_assert(struct uart_port *u)
{
int i;
u32 reg;
reg = readl(u->membase + AUART_CTRL0);
/* if already in reset state, keep it untouched */
if (reg & AUART_CTRL0_SFTRST)
return;
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_SET);
for (i = 0; i < 1000; i++) {
reg = readl(u->membase + AUART_CTRL0);
/* reset is finished when the clock is gated */
if (reg & AUART_CTRL0_CLKGATE)
return;
udelay(10);
}
dev_err(u->dev, "Failed to reset the unit.");
}
static int mxs_auart_startup(struct uart_port *u) static int mxs_auart_startup(struct uart_port *u)
{ {
int ret; int ret;
...@@ -867,7 +895,13 @@ static int mxs_auart_startup(struct uart_port *u) ...@@ -867,7 +895,13 @@ static int mxs_auart_startup(struct uart_port *u)
if (ret) if (ret)
return ret; return ret;
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); if (uart_console(u)) {
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
} else {
/* reset the unit to a well known state */
mxs_auart_reset_assert(u);
mxs_auart_reset_deassert(u);
}
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET); writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
...@@ -899,12 +933,14 @@ static void mxs_auart_shutdown(struct uart_port *u) ...@@ -899,12 +933,14 @@ static void mxs_auart_shutdown(struct uart_port *u)
if (auart_dma_enabled(s)) if (auart_dma_enabled(s))
mxs_auart_dma_exit(s); mxs_auart_dma_exit(s);
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR); if (uart_console(u)) {
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
u->membase + AUART_INTR_CLR); u->membase + AUART_INTR_CLR);
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET); } else {
mxs_auart_reset_assert(u);
}
clk_disable_unprepare(s->clk); clk_disable_unprepare(s->clk);
} }
...@@ -1291,7 +1327,7 @@ static int mxs_auart_probe(struct platform_device *pdev) ...@@ -1291,7 +1327,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
auart_port[s->port.line] = s; auart_port[s->port.line] = s;
mxs_auart_reset(&s->port); mxs_auart_reset_deassert(&s->port);
ret = uart_add_one_port(&auart_driver, &s->port); ret = uart_add_one_port(&auart_driver, &s->port);
if (ret) if (ret)
......
...@@ -53,7 +53,6 @@ ...@@ -53,7 +53,6 @@
#include "samsung.h" #include "samsung.h"
#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \ #if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
defined(CONFIG_DEBUG_LL) && \
!defined(MODULE) !defined(MODULE)
extern void printascii(const char *); extern void printascii(const char *);
...@@ -295,15 +294,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, ...@@ -295,15 +294,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
if (ourport->tx_mode != S3C24XX_TX_DMA) if (ourport->tx_mode != S3C24XX_TX_DMA)
enable_tx_dma(ourport); enable_tx_dma(ourport);
while (xmit->tail & (dma_get_cache_alignment() - 1)) {
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
return 0;
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
count--;
}
dma->tx_size = count & ~(dma_get_cache_alignment() - 1); dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
dma->tx_transfer_addr = dma->tx_addr + xmit->tail; dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
...@@ -342,7 +332,9 @@ static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport) ...@@ -342,7 +332,9 @@ static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
return; return;
} }
if (!ourport->dma || !ourport->dma->tx_chan || count < port->fifosize) if (!ourport->dma || !ourport->dma->tx_chan ||
count < ourport->min_dma_size ||
xmit->tail & (dma_get_cache_alignment() - 1))
s3c24xx_serial_start_tx_pio(ourport); s3c24xx_serial_start_tx_pio(ourport);
else else
s3c24xx_serial_start_tx_dma(ourport, count); s3c24xx_serial_start_tx_dma(ourport, count);
...@@ -736,15 +728,20 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) ...@@ -736,15 +728,20 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
struct uart_port *port = &ourport->port; struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit; struct circ_buf *xmit = &port->state->xmit;
unsigned long flags; unsigned long flags;
int count; int count, dma_count = 0;
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
if (ourport->dma && ourport->dma->tx_chan && count >= port->fifosize) { if (ourport->dma && ourport->dma->tx_chan &&
s3c24xx_serial_start_tx_dma(ourport, count); count >= ourport->min_dma_size) {
goto out; int align = dma_get_cache_alignment() -
(xmit->tail & (dma_get_cache_alignment() - 1));
if (count-align >= ourport->min_dma_size) {
dma_count = count-align;
count = align;
}
} }
if (port->x_char) { if (port->x_char) {
...@@ -765,14 +762,24 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) ...@@ -765,14 +762,24 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
/* try and drain the buffer... */ /* try and drain the buffer... */
count = port->fifosize; if (count > port->fifosize) {
while (!uart_circ_empty(xmit) && count-- > 0) { count = port->fifosize;
dma_count = 0;
}
while (!uart_circ_empty(xmit) && count > 0) {
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
break; break;
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++; port->icount.tx++;
count--;
}
if (!count && dma_count) {
s3c24xx_serial_start_tx_dma(ourport, dma_count);
goto out;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
...@@ -1838,6 +1845,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) ...@@ -1838,6 +1845,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
else if (ourport->info->fifosize) else if (ourport->info->fifosize)
ourport->port.fifosize = ourport->info->fifosize; ourport->port.fifosize = ourport->info->fifosize;
/*
* DMA transfers must be aligned at least to cache line size,
* so find minimal transfer size suitable for DMA mode
*/
ourport->min_dma_size = max_t(int, ourport->port.fifosize,
dma_get_cache_alignment());
probe_index++; probe_index++;
dbg("%s: initialising port %p...\n", __func__, ourport); dbg("%s: initialising port %p...\n", __func__, ourport);
......
...@@ -82,6 +82,7 @@ struct s3c24xx_uart_port { ...@@ -82,6 +82,7 @@ struct s3c24xx_uart_port {
unsigned char tx_claimed; unsigned char tx_claimed;
unsigned int pm_level; unsigned int pm_level;
unsigned long baudclk_rate; unsigned long baudclk_rate;
unsigned int min_dma_size;
unsigned int rx_irq; unsigned int rx_irq;
unsigned int tx_irq; unsigned int tx_irq;
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* *
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -29,6 +31,7 @@ ...@@ -29,6 +31,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#define SC16IS7XX_NAME "sc16is7xx" #define SC16IS7XX_NAME "sc16is7xx"
#define SC16IS7XX_MAX_DEVS 8
/* SC16IS7XX register definitions */ /* SC16IS7XX register definitions */
#define SC16IS7XX_RHR_REG (0x00) /* RX FIFO */ #define SC16IS7XX_RHR_REG (0x00) /* RX FIFO */
...@@ -312,14 +315,14 @@ struct sc16is7xx_one_config { ...@@ -312,14 +315,14 @@ struct sc16is7xx_one_config {
struct sc16is7xx_one { struct sc16is7xx_one {
struct uart_port port; struct uart_port port;
u8 line;
struct kthread_work tx_work; struct kthread_work tx_work;
struct kthread_work reg_work; struct kthread_work reg_work;
struct sc16is7xx_one_config config; struct sc16is7xx_one_config config;
}; };
struct sc16is7xx_port { struct sc16is7xx_port {
struct uart_driver uart; const struct sc16is7xx_devtype *devtype;
struct sc16is7xx_devtype *devtype;
struct regmap *regmap; struct regmap *regmap;
struct clk *clk; struct clk *clk;
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
...@@ -332,16 +335,31 @@ struct sc16is7xx_port { ...@@ -332,16 +335,31 @@ struct sc16is7xx_port {
struct sc16is7xx_one p[0]; struct sc16is7xx_one p[0];
}; };
static unsigned long sc16is7xx_lines;
static struct uart_driver sc16is7xx_uart = {
.owner = THIS_MODULE,
.dev_name = "ttySC",
.nr = SC16IS7XX_MAX_DEVS,
};
#define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e))) #define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e)))
#define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e))) #define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e)))
static int sc16is7xx_line(struct uart_port *port)
{
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
return one->line;
}
static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg) static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
{ {
struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
unsigned int val = 0; unsigned int val = 0;
const u8 line = sc16is7xx_line(port);
regmap_read(s->regmap, regmap_read(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, &val);
(reg << SC16IS7XX_REG_SHIFT) | port->line, &val);
return val; return val;
} }
...@@ -349,15 +367,16 @@ static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg) ...@@ -349,15 +367,16 @@ static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val) static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
{ {
struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
const u8 line = sc16is7xx_line(port);
regmap_write(s->regmap, regmap_write(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, val);
(reg << SC16IS7XX_REG_SHIFT) | port->line, val);
} }
static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen) static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
{ {
struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | port->line; const u8 line = sc16is7xx_line(port);
u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | line;
regcache_cache_bypass(s->regmap, true); regcache_cache_bypass(s->regmap, true);
regmap_raw_read(s->regmap, addr, s->buf, rxlen); regmap_raw_read(s->regmap, addr, s->buf, rxlen);
...@@ -367,7 +386,8 @@ static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen) ...@@ -367,7 +386,8 @@ static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send) static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
{ {
struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | port->line; const u8 line = sc16is7xx_line(port);
u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line;
regcache_cache_bypass(s->regmap, true); regcache_cache_bypass(s->regmap, true);
regmap_raw_write(s->regmap, addr, s->buf, to_send); regmap_raw_write(s->regmap, addr, s->buf, to_send);
...@@ -378,12 +398,24 @@ static void sc16is7xx_port_update(struct uart_port *port, u8 reg, ...@@ -378,12 +398,24 @@ static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
u8 mask, u8 val) u8 mask, u8 val)
{ {
struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
const u8 line = sc16is7xx_line(port);
regmap_update_bits(s->regmap, regmap_update_bits(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line,
(reg << SC16IS7XX_REG_SHIFT) | port->line,
mask, val); mask, val);
} }
static int sc16is7xx_alloc_line(void)
{
int i;
BUILD_BUG_ON(SC16IS7XX_MAX_DEVS > BITS_PER_LONG);
for (i = 0; i < SC16IS7XX_MAX_DEVS; i++)
if (!test_and_set_bit(i, &sc16is7xx_lines))
break;
return i;
}
static void sc16is7xx_power(struct uart_port *port, int on) static void sc16is7xx_power(struct uart_port *port, int on)
{ {
...@@ -508,7 +540,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, ...@@ -508,7 +540,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
if (unlikely(rxlen >= sizeof(s->buf))) { if (unlikely(rxlen >= sizeof(s->buf))) {
dev_warn_ratelimited(port->dev, dev_warn_ratelimited(port->dev,
"Port %i: Possible RX FIFO overrun: %d\n", "ttySC%i: Possible RX FIFO overrun: %d\n",
port->line, rxlen); port->line, rxlen);
port->icount.buf_overrun++; port->icount.buf_overrun++;
/* Ensure sanity of RX level */ /* Ensure sanity of RX level */
...@@ -649,7 +681,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) ...@@ -649,7 +681,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
break; break;
default: default:
dev_err_ratelimited(port->dev, dev_err_ratelimited(port->dev,
"Port %i: Unexpected interrupt: %x", "ttySC%i: Unexpected interrupt: %x",
port->line, iir); port->line, iir);
break; break;
} }
...@@ -661,7 +693,7 @@ static void sc16is7xx_ist(struct kthread_work *ws) ...@@ -661,7 +693,7 @@ static void sc16is7xx_ist(struct kthread_work *ws)
struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work); struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
int i; int i;
for (i = 0; i < s->uart.nr; ++i) for (i = 0; i < s->devtype->nr_uart; ++i)
sc16is7xx_port_irq(s, i); sc16is7xx_port_irq(s, i);
} }
...@@ -1099,7 +1131,7 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip, ...@@ -1099,7 +1131,7 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
#endif #endif
static int sc16is7xx_probe(struct device *dev, static int sc16is7xx_probe(struct device *dev,
struct sc16is7xx_devtype *devtype, const struct sc16is7xx_devtype *devtype,
struct regmap *regmap, int irq, unsigned long flags) struct regmap *regmap, int irq, unsigned long flags)
{ {
struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 }; struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
...@@ -1134,23 +1166,13 @@ static int sc16is7xx_probe(struct device *dev, ...@@ -1134,23 +1166,13 @@ static int sc16is7xx_probe(struct device *dev,
s->devtype = devtype; s->devtype = devtype;
dev_set_drvdata(dev, s); dev_set_drvdata(dev, s);
/* Register UART driver */
s->uart.owner = THIS_MODULE;
s->uart.dev_name = "ttySC";
s->uart.nr = devtype->nr_uart;
ret = uart_register_driver(&s->uart);
if (ret) {
dev_err(dev, "Registering UART driver failed\n");
goto out_clk;
}
init_kthread_worker(&s->kworker); init_kthread_worker(&s->kworker);
init_kthread_work(&s->irq_work, sc16is7xx_ist); init_kthread_work(&s->irq_work, sc16is7xx_ist);
s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker, s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
"sc16is7xx"); "sc16is7xx");
if (IS_ERR(s->kworker_task)) { if (IS_ERR(s->kworker_task)) {
ret = PTR_ERR(s->kworker_task); ret = PTR_ERR(s->kworker_task);
goto out_uart; goto out_clk;
} }
sched_setscheduler(s->kworker_task, SCHED_FIFO, &sched_param); sched_setscheduler(s->kworker_task, SCHED_FIFO, &sched_param);
...@@ -1174,8 +1196,8 @@ static int sc16is7xx_probe(struct device *dev, ...@@ -1174,8 +1196,8 @@ static int sc16is7xx_probe(struct device *dev,
#endif #endif
for (i = 0; i < devtype->nr_uart; ++i) { for (i = 0; i < devtype->nr_uart; ++i) {
s->p[i].line = i;
/* Initialize port data */ /* Initialize port data */
s->p[i].port.line = i;
s->p[i].port.dev = dev; s->p[i].port.dev = dev;
s->p[i].port.irq = irq; s->p[i].port.irq = irq;
s->p[i].port.type = PORT_SC16IS7XX; s->p[i].port.type = PORT_SC16IS7XX;
...@@ -1185,6 +1207,12 @@ static int sc16is7xx_probe(struct device *dev, ...@@ -1185,6 +1207,12 @@ static int sc16is7xx_probe(struct device *dev,
s->p[i].port.uartclk = freq; s->p[i].port.uartclk = freq;
s->p[i].port.rs485_config = sc16is7xx_config_rs485; s->p[i].port.rs485_config = sc16is7xx_config_rs485;
s->p[i].port.ops = &sc16is7xx_ops; s->p[i].port.ops = &sc16is7xx_ops;
s->p[i].port.line = sc16is7xx_alloc_line();
if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
ret = -ENOMEM;
goto out_ports;
}
/* Disable all interrupts */ /* Disable all interrupts */
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0); sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0);
/* Disable TX/RX */ /* Disable TX/RX */
...@@ -1195,7 +1223,7 @@ static int sc16is7xx_probe(struct device *dev, ...@@ -1195,7 +1223,7 @@ static int sc16is7xx_probe(struct device *dev,
init_kthread_work(&s->p[i].tx_work, sc16is7xx_tx_proc); init_kthread_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc); init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
/* Register port */ /* Register port */
uart_add_one_port(&s->uart, &s->p[i].port); uart_add_one_port(&sc16is7xx_uart, &s->p[i].port);
/* Go to suspend mode */ /* Go to suspend mode */
sc16is7xx_power(&s->p[i].port, 0); sc16is7xx_power(&s->p[i].port, 0);
} }
...@@ -1206,8 +1234,11 @@ static int sc16is7xx_probe(struct device *dev, ...@@ -1206,8 +1234,11 @@ static int sc16is7xx_probe(struct device *dev,
if (!ret) if (!ret)
return 0; return 0;
for (i = 0; i < s->uart.nr; i++) out_ports:
uart_remove_one_port(&s->uart, &s->p[i].port); for (i--; i >= 0; i--) {
uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
clear_bit(s->p[i].port.line, &sc16is7xx_lines);
}
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
if (devtype->nr_gpio) if (devtype->nr_gpio)
...@@ -1217,9 +1248,6 @@ static int sc16is7xx_probe(struct device *dev, ...@@ -1217,9 +1248,6 @@ static int sc16is7xx_probe(struct device *dev,
#endif #endif
kthread_stop(s->kworker_task); kthread_stop(s->kworker_task);
out_uart:
uart_unregister_driver(&s->uart);
out_clk: out_clk:
if (!IS_ERR(s->clk)) if (!IS_ERR(s->clk))
clk_disable_unprepare(s->clk); clk_disable_unprepare(s->clk);
...@@ -1237,15 +1265,15 @@ static int sc16is7xx_remove(struct device *dev) ...@@ -1237,15 +1265,15 @@ static int sc16is7xx_remove(struct device *dev)
gpiochip_remove(&s->gpio); gpiochip_remove(&s->gpio);
#endif #endif
for (i = 0; i < s->uart.nr; i++) { for (i = 0; i < s->devtype->nr_uart; i++) {
uart_remove_one_port(&s->uart, &s->p[i].port); uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
clear_bit(s->p[i].port.line, &sc16is7xx_lines);
sc16is7xx_power(&s->p[i].port, 0); sc16is7xx_power(&s->p[i].port, 0);
} }
flush_kthread_worker(&s->kworker); flush_kthread_worker(&s->kworker);
kthread_stop(s->kworker_task); kthread_stop(s->kworker_task);
uart_unregister_driver(&s->uart);
if (!IS_ERR(s->clk)) if (!IS_ERR(s->clk))
clk_disable_unprepare(s->clk); clk_disable_unprepare(s->clk);
...@@ -1275,7 +1303,7 @@ static struct regmap_config regcfg = { ...@@ -1275,7 +1303,7 @@ static struct regmap_config regcfg = {
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI #ifdef CONFIG_SERIAL_SC16IS7XX_SPI
static int sc16is7xx_spi_probe(struct spi_device *spi) static int sc16is7xx_spi_probe(struct spi_device *spi)
{ {
struct sc16is7xx_devtype *devtype; const struct sc16is7xx_devtype *devtype;
unsigned long flags = 0; unsigned long flags = 0;
struct regmap *regmap; struct regmap *regmap;
int ret; int ret;
...@@ -1344,7 +1372,7 @@ MODULE_ALIAS("spi:sc16is7xx"); ...@@ -1344,7 +1372,7 @@ MODULE_ALIAS("spi:sc16is7xx");
static int sc16is7xx_i2c_probe(struct i2c_client *i2c, static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct sc16is7xx_devtype *devtype; const struct sc16is7xx_devtype *devtype;
unsigned long flags = 0; unsigned long flags = 0;
struct regmap *regmap; struct regmap *regmap;
...@@ -1385,7 +1413,6 @@ MODULE_DEVICE_TABLE(i2c, sc16is7xx_i2c_id_table); ...@@ -1385,7 +1413,6 @@ MODULE_DEVICE_TABLE(i2c, sc16is7xx_i2c_id_table);
static struct i2c_driver sc16is7xx_i2c_uart_driver = { static struct i2c_driver sc16is7xx_i2c_uart_driver = {
.driver = { .driver = {
.name = SC16IS7XX_NAME, .name = SC16IS7XX_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(sc16is7xx_dt_ids), .of_match_table = of_match_ptr(sc16is7xx_dt_ids),
}, },
.probe = sc16is7xx_i2c_probe, .probe = sc16is7xx_i2c_probe,
...@@ -1398,7 +1425,14 @@ MODULE_ALIAS("i2c:sc16is7xx"); ...@@ -1398,7 +1425,14 @@ MODULE_ALIAS("i2c:sc16is7xx");
static int __init sc16is7xx_init(void) static int __init sc16is7xx_init(void)
{ {
int ret = 0; int ret;
ret = uart_register_driver(&sc16is7xx_uart);
if (ret) {
pr_err("Registering UART driver failed\n");
return ret;
}
#ifdef CONFIG_SERIAL_SC16IS7XX_I2C #ifdef CONFIG_SERIAL_SC16IS7XX_I2C
ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver); ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver);
if (ret < 0) { if (ret < 0) {
...@@ -1427,6 +1461,7 @@ static void __exit sc16is7xx_exit(void) ...@@ -1427,6 +1461,7 @@ static void __exit sc16is7xx_exit(void)
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI #ifdef CONFIG_SERIAL_SC16IS7XX_SPI
spi_unregister_driver(&sc16is7xx_spi_uart_driver); spi_unregister_driver(&sc16is7xx_spi_uart_driver);
#endif #endif
uart_unregister_driver(&sc16is7xx_uart);
} }
module_exit(sc16is7xx_exit); module_exit(sc16is7xx_exit);
......
...@@ -1377,7 +1377,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1377,7 +1377,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct tty_port *port; struct tty_port *port;
struct uart_port *uport; struct uart_port *uport;
unsigned long flags;
if (!state) { if (!state) {
struct uart_driver *drv = tty->driver->driver_state; struct uart_driver *drv = tty->driver->driver_state;
...@@ -1403,10 +1402,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1403,10 +1402,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
* disable the receive line status interrupts. * disable the receive line status interrupts.
*/ */
if (port->flags & ASYNC_INITIALIZED) { if (port->flags & ASYNC_INITIALIZED) {
unsigned long flags; spin_lock_irq(&uport->lock);
spin_lock_irqsave(&uport->lock, flags);
uport->ops->stop_rx(uport); uport->ops->stop_rx(uport);
spin_unlock_irqrestore(&uport->lock, flags); spin_unlock_irq(&uport->lock);
/* /*
* Before we drop DTR, make sure the UART transmitter * Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially * has completely drained; this is especially
...@@ -1419,17 +1417,17 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1419,17 +1417,17 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
uart_shutdown(tty, state); uart_shutdown(tty, state);
tty_port_tty_set(port, NULL); tty_port_tty_set(port, NULL);
spin_lock_irqsave(&port->lock, flags); spin_lock_irq(&port->lock);
if (port->blocked_open) { if (port->blocked_open) {
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irq(&port->lock);
if (port->close_delay) if (port->close_delay)
msleep_interruptible(jiffies_to_msecs(port->close_delay)); msleep_interruptible(jiffies_to_msecs(port->close_delay));
spin_lock_irqsave(&port->lock, flags); spin_lock_irq(&port->lock);
} else if (!uart_console(uport)) { } else if (!uart_console(uport)) {
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irq(&port->lock);
uart_change_pm(state, UART_PM_STATE_OFF); uart_change_pm(state, UART_PM_STATE_OFF);
spin_lock_irqsave(&port->lock, flags); spin_lock_irq(&port->lock);
} }
/* /*
...@@ -1437,7 +1435,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1437,7 +1435,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
*/ */
clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
clear_bit(ASYNCB_CLOSING, &port->flags); clear_bit(ASYNCB_CLOSING, &port->flags);
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irq(&port->lock);
wake_up_interruptible(&port->open_wait); wake_up_interruptible(&port->open_wait);
wake_up_interruptible(&port->close_wait); wake_up_interruptible(&port->close_wait);
...@@ -1532,11 +1530,6 @@ static void uart_hangup(struct tty_struct *tty) ...@@ -1532,11 +1530,6 @@ static void uart_hangup(struct tty_struct *tty)
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
} }
static int uart_port_activate(struct tty_port *port, struct tty_struct *tty)
{
return 0;
}
static void uart_port_shutdown(struct tty_port *port) static void uart_port_shutdown(struct tty_port *port)
{ {
struct uart_state *state = container_of(port, struct uart_state, port); struct uart_state *state = container_of(port, struct uart_state, port);
...@@ -2379,8 +2372,6 @@ static const struct tty_operations uart_ops = { ...@@ -2379,8 +2372,6 @@ static const struct tty_operations uart_ops = {
}; };
static const struct tty_port_operations uart_port_ops = { static const struct tty_port_operations uart_port_ops = {
.activate = uart_port_activate,
.shutdown = uart_port_shutdown,
.carrier_raised = uart_carrier_raised, .carrier_raised = uart_carrier_raised,
.dtr_rts = uart_dtr_rts, .dtr_rts = uart_dtr_rts,
}; };
......
...@@ -413,7 +413,6 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count) ...@@ -413,7 +413,6 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count)
break; break;
} }
sirfport->rx_io_count += rx_count;
port->icount.rx += rx_count; port->icount.rx += rx_count;
return rx_count; return rx_count;
...@@ -600,7 +599,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port) ...@@ -600,7 +599,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port)
struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_uart_port *sirfport = to_sirfport(port);
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
sirfport->rx_io_count = 0;
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
~SIRFUART_IO_MODE); ~SIRFUART_IO_MODE);
...@@ -632,31 +630,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port) ...@@ -632,31 +630,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port)
sirfport->uart_reg->uart_type)); sirfport->uart_reg->uart_type));
} }
static void sirfsoc_uart_start_rx(struct uart_port *port)
{
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
sirfport->rx_io_count = 0;
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
if (sirfport->rx_dma_chan)
sirfsoc_uart_start_next_rx_dma(port);
else {
if (!sirfport->is_atlas7)
wr_regl(port, ureg->sirfsoc_int_en_reg,
rd_regl(port, ureg->sirfsoc_int_en_reg) |
SIRFUART_RX_IO_INT_EN(uint_en,
sirfport->uart_reg->uart_type));
else
wr_regl(port, ureg->sirfsoc_int_en_reg,
SIRFUART_RX_IO_INT_EN(uint_en,
sirfport->uart_reg->uart_type));
}
}
static unsigned int static unsigned int
sirfsoc_usp_calc_sample_div(unsigned long set_rate, sirfsoc_usp_calc_sample_div(unsigned long set_rate,
unsigned long ioclk_rate, unsigned long *sample_reg) unsigned long ioclk_rate, unsigned long *sample_reg)
...@@ -850,7 +823,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, ...@@ -850,7 +823,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000); rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000);
rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out); rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out);
txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op); txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op);
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_STOP);
wr_regl(port, ureg->sirfsoc_tx_fifo_op, wr_regl(port, ureg->sirfsoc_tx_fifo_op,
(txfifo_op_reg & ~SIRFUART_FIFO_START)); (txfifo_op_reg & ~SIRFUART_FIFO_START));
if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
...@@ -886,9 +858,13 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, ...@@ -886,9 +858,13 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
else else
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE); wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
if (sirfport->rx_dma_chan) if (sirfport->rx_dma_chan)
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE); wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
~SIRFUART_IO_MODE);
else else
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE); wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
SIRFUART_IO_MODE);
sirfport->rx_period_time = 20000000; sirfport->rx_period_time = 20000000;
/* Reset Rx/Tx FIFO Threshold level for proper baudrate */ /* Reset Rx/Tx FIFO Threshold level for proper baudrate */
if (set_baud < 1000000) if (set_baud < 1000000)
...@@ -902,7 +878,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, ...@@ -902,7 +878,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
txfifo_op_reg |= SIRFUART_FIFO_START; txfifo_op_reg |= SIRFUART_FIFO_START;
wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg); wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg);
uart_update_timeout(port, termios->c_cflag, set_baud); uart_update_timeout(port, termios->c_cflag, set_baud);
sirfsoc_uart_start_rx(port);
wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN); wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN);
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
} }
...@@ -921,6 +896,7 @@ static int sirfsoc_uart_startup(struct uart_port *port) ...@@ -921,6 +896,7 @@ static int sirfsoc_uart_startup(struct uart_port *port)
{ {
struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_uart_port *sirfport = to_sirfport(port);
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
unsigned int index = port->line; unsigned int index = port->line;
int ret; int ret;
irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN); irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN);
...@@ -958,9 +934,9 @@ static int sirfsoc_uart_startup(struct uart_port *port) ...@@ -958,9 +934,9 @@ static int sirfsoc_uart_startup(struct uart_port *port)
wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port)); wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port));
if (sirfport->rx_dma_chan) if (sirfport->rx_dma_chan)
wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk, wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk,
SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) | SIRFUART_RX_FIFO_CHK_SC(port->line, 0x1) |
SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) | SIRFUART_RX_FIFO_CHK_LC(port->line, 0x2) |
SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b)); SIRFUART_RX_FIFO_CHK_HC(port->line, 0x4));
if (sirfport->tx_dma_chan) { if (sirfport->tx_dma_chan) {
sirfport->tx_dma_state = TX_DMA_IDLE; sirfport->tx_dma_state = TX_DMA_IDLE;
wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk, wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk,
...@@ -981,16 +957,41 @@ static int sirfsoc_uart_startup(struct uart_port *port) ...@@ -981,16 +957,41 @@ static int sirfsoc_uart_startup(struct uart_port *port)
goto init_rx_err; goto init_rx_err;
} }
} }
enable_irq(port->irq); if (sirfport->uart_reg->uart_type == SIRF_REAL_UART &&
sirfport->rx_dma_chan)
wr_regl(port, ureg->sirfsoc_swh_dma_io,
SIRFUART_CLEAR_RX_ADDR_EN);
if (sirfport->uart_reg->uart_type == SIRF_USP_UART &&
sirfport->rx_dma_chan)
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
SIRFSOC_USP_FRADDR_CLR_EN);
if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) { if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) {
sirfport->is_hrt_enabled = true; sirfport->is_hrt_enabled = true;
sirfport->rx_period_time = 20000000; sirfport->rx_period_time = 20000000;
sirfport->rx_last_pos = -1;
sirfport->pio_fetch_cnt = 0;
sirfport->rx_dma_items.xmit.tail = sirfport->rx_dma_items.xmit.tail =
sirfport->rx_dma_items.xmit.head = 0; sirfport->rx_dma_items.xmit.head = 0;
hrtimer_start(&sirfport->hrt, hrtimer_start(&sirfport->hrt,
ns_to_ktime(sirfport->rx_period_time), ns_to_ktime(sirfport->rx_period_time),
HRTIMER_MODE_REL); HRTIMER_MODE_REL);
} }
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
if (sirfport->rx_dma_chan)
sirfsoc_uart_start_next_rx_dma(port);
else {
if (!sirfport->is_atlas7)
wr_regl(port, ureg->sirfsoc_int_en_reg,
rd_regl(port, ureg->sirfsoc_int_en_reg) |
SIRFUART_RX_IO_INT_EN(uint_en,
sirfport->uart_reg->uart_type));
else
wr_regl(port, ureg->sirfsoc_int_en_reg,
SIRFUART_RX_IO_INT_EN(uint_en,
sirfport->uart_reg->uart_type));
}
enable_irq(port->irq);
return 0; return 0;
init_rx_err: init_rx_err:
...@@ -1003,6 +1004,9 @@ static void sirfsoc_uart_shutdown(struct uart_port *port) ...@@ -1003,6 +1004,9 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
{ {
struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_uart_port *sirfport = to_sirfport(port);
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
struct circ_buf *xmit;
xmit = &sirfport->rx_dma_items.xmit;
if (!sirfport->is_atlas7) if (!sirfport->is_atlas7)
wr_regl(port, ureg->sirfsoc_int_en_reg, 0); wr_regl(port, ureg->sirfsoc_int_en_reg, 0);
else else
...@@ -1019,8 +1023,10 @@ static void sirfsoc_uart_shutdown(struct uart_port *port) ...@@ -1019,8 +1023,10 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
if (sirfport->tx_dma_chan) if (sirfport->tx_dma_chan)
sirfport->tx_dma_state = TX_DMA_IDLE; sirfport->tx_dma_state = TX_DMA_IDLE;
if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) { if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) {
while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) & while (((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
SIRFUART_RX_FIFO_MASK) > 0) SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt) &&
!CIRC_CNT(xmit->head, xmit->tail,
SIRFSOC_RX_DMA_BUF_SIZE))
; ;
sirfport->is_hrt_enabled = false; sirfport->is_hrt_enabled = false;
hrtimer_cancel(&sirfport->hrt); hrtimer_cancel(&sirfport->hrt);
...@@ -1169,6 +1175,8 @@ static enum hrtimer_restart ...@@ -1169,6 +1175,8 @@ static enum hrtimer_restart
struct tty_struct *tty; struct tty_struct *tty;
struct sirfsoc_register *ureg; struct sirfsoc_register *ureg;
struct circ_buf *xmit; struct circ_buf *xmit;
struct sirfsoc_fifo_status *ufifo_st;
int max_pio_cnt;
sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt); sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt);
port = &sirfport->port; port = &sirfport->port;
...@@ -1176,9 +1184,16 @@ static enum hrtimer_restart ...@@ -1176,9 +1184,16 @@ static enum hrtimer_restart
tty = port->state->port.tty; tty = port->state->port.tty;
ureg = &sirfport->uart_reg->uart_reg; ureg = &sirfport->uart_reg->uart_reg;
xmit = &sirfport->rx_dma_items.xmit; xmit = &sirfport->rx_dma_items.xmit;
ufifo_st = &sirfport->uart_reg->fifo_status;
dmaengine_tx_status(sirfport->rx_dma_chan, dmaengine_tx_status(sirfport->rx_dma_chan,
sirfport->rx_dma_items.cookie, &tx_state); sirfport->rx_dma_items.cookie, &tx_state);
xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue; if (SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue !=
sirfport->rx_last_pos) {
xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
sirfport->rx_last_pos = xmit->head;
sirfport->pio_fetch_cnt = 0;
}
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, count = CIRC_CNT_TO_END(xmit->head, xmit->tail,
SIRFSOC_RX_DMA_BUF_SIZE); SIRFSOC_RX_DMA_BUF_SIZE);
while (count > 0) { while (count > 0) {
...@@ -1200,23 +1215,38 @@ static enum hrtimer_restart ...@@ -1200,23 +1215,38 @@ static enum hrtimer_restart
*/ */
if (!inserted && !count && if (!inserted && !count &&
((rd_regl(port, ureg->sirfsoc_rx_fifo_status) & ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
SIRFUART_RX_FIFO_MASK) > 0)) { SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt)) {
dmaengine_pause(sirfport->rx_dma_chan);
/* switch to pio mode */ /* switch to pio mode */
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
SIRFUART_IO_MODE); SIRFUART_IO_MODE);
while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) & /*
SIRFUART_RX_FIFO_MASK) > 0) { * UART controller SWH_DMA_IO register have CLEAR_RX_ADDR_EN
if (sirfsoc_uart_pio_rx_chars(port, 16) > 0) * When found changing I/O to DMA mode, it clears
tty_flip_buffer_push(tty->port); * two low bits of read point;
* USP have similar FRADDR_CLR_EN bit in USP_RX_DMA_IO_CTRL.
* Fetch data out from rxfifo into DMA buffer in PIO mode,
* while switch back to DMA mode, the data fetched will override
* by DMA, as hardware have a strange behaviour:
* after switch back to DMA mode, check rxfifo status it will
* be the number PIO fetched, so record the fetched data count
* to avoid the repeated fetch
*/
max_pio_cnt = 3;
while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
ufifo_st->ff_empty(port)) && max_pio_cnt--) {
xmit->buf[xmit->head] =
rd_regl(port, ureg->sirfsoc_rx_fifo_data);
xmit->head = (xmit->head + 1) &
(SIRFSOC_RX_DMA_BUF_SIZE - 1);
sirfport->pio_fetch_cnt++;
} }
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
/* switch back to dma mode */ /* switch back to dma mode */
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
~SIRFUART_IO_MODE); ~SIRFUART_IO_MODE);
dmaengine_resume(sirfport->rx_dma_chan);
} }
next_hrt: next_hrt:
hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time)); hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time));
...@@ -1239,7 +1269,7 @@ static int sirfsoc_uart_probe(struct platform_device *pdev) ...@@ -1239,7 +1269,7 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
int ret; int ret;
struct dma_slave_config slv_cfg = { struct dma_slave_config slv_cfg = {
.src_maxburst = 2, .src_maxburst = 1,
}; };
struct dma_slave_config tx_slv_cfg = { struct dma_slave_config tx_slv_cfg = {
.dst_maxburst = 2, .dst_maxburst = 2,
......
...@@ -296,6 +296,7 @@ struct sirfsoc_uart_register sirfsoc_uart = { ...@@ -296,6 +296,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
#define SIRFUART_DMA_MODE 0x0 #define SIRFUART_DMA_MODE 0x0
#define SIRFUART_RX_DMA_FLUSH 0x4 #define SIRFUART_RX_DMA_FLUSH 0x4
#define SIRFUART_CLEAR_RX_ADDR_EN 0x2
/* Baud Rate Calculation */ /* Baud Rate Calculation */
#define SIRF_USP_MIN_SAMPLE_DIV 0x1 #define SIRF_USP_MIN_SAMPLE_DIV 0x1
#define SIRF_MIN_SAMPLE_DIV 0xf #define SIRF_MIN_SAMPLE_DIV 0xf
...@@ -325,6 +326,7 @@ struct sirfsoc_uart_register sirfsoc_uart = { ...@@ -325,6 +326,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
#define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f #define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f
#define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16 #define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16
#define SIRFSOC_USP_LOOP_BACK_CTRL BIT(2) #define SIRFSOC_USP_LOOP_BACK_CTRL BIT(2)
#define SIRFSOC_USP_FRADDR_CLR_EN BIT(1)
/* USP-UART Common */ /* USP-UART Common */
#define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000) #define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000)
#define SIRFUART_RECV_TIMEOUT_VALUE(x) \ #define SIRFUART_RECV_TIMEOUT_VALUE(x) \
...@@ -421,7 +423,6 @@ struct sirfsoc_uart_port { ...@@ -421,7 +423,6 @@ struct sirfsoc_uart_port {
struct dma_chan *tx_dma_chan; struct dma_chan *tx_dma_chan;
dma_addr_t tx_dma_addr; dma_addr_t tx_dma_addr;
struct dma_async_tx_descriptor *tx_dma_desc; struct dma_async_tx_descriptor *tx_dma_desc;
unsigned int rx_io_count;
unsigned long transfer_size; unsigned long transfer_size;
enum sirfsoc_tx_state tx_dma_state; enum sirfsoc_tx_state tx_dma_state;
unsigned int cts_gpio; unsigned int cts_gpio;
...@@ -431,6 +432,8 @@ struct sirfsoc_uart_port { ...@@ -431,6 +432,8 @@ struct sirfsoc_uart_port {
struct hrtimer hrt; struct hrtimer hrt;
bool is_hrt_enabled; bool is_hrt_enabled;
unsigned long rx_period_time; unsigned long rx_period_time;
unsigned long rx_last_pos;
unsigned long pio_fetch_cnt;
}; };
/* Register Access Control */ /* Register Access Control */
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include <linux/tty_flip.h> #include <linux/tty_flip.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/sysrq.h> #include <linux/sysrq.h>
#include <linux/circ_buf.h> #include <linux/circ_buf.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
...@@ -659,7 +659,7 @@ static void sn_sal_timer_poll(unsigned long data) ...@@ -659,7 +659,7 @@ static void sn_sal_timer_poll(unsigned long data)
* @port: Our sn_cons_port (which contains the uart port) * @port: Our sn_cons_port (which contains the uart port)
* *
* So this is used by sn_sal_serial_console_init (early on, before we're * So this is used by sn_sal_serial_console_init (early on, before we're
* registered with serial core). It's also used by sn_sal_module_init * registered with serial core). It's also used by sn_sal_init
* right after we've registered with serial core. The later only happens * right after we've registered with serial core. The later only happens
* if we didn't already come through here via sn_sal_serial_console_init. * if we didn't already come through here via sn_sal_serial_console_init.
* *
...@@ -709,7 +709,7 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port) ...@@ -709,7 +709,7 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port)
* sn_sal_switch_to_interrupts - Switch to interrupt driven mode * sn_sal_switch_to_interrupts - Switch to interrupt driven mode
* @port: Our sn_cons_port (which contains the uart port) * @port: Our sn_cons_port (which contains the uart port)
* *
* In sn_sal_module_init, after we're registered with serial core and * In sn_sal_init, after we're registered with serial core and
* the port is added, this function is called to switch us to interrupt * the port is added, this function is called to switch us to interrupt
* mode. We were previously in asynch/polling mode (using init_timer). * mode. We were previously in asynch/polling mode (using init_timer).
* *
...@@ -773,7 +773,7 @@ static struct uart_driver sal_console_uart = { ...@@ -773,7 +773,7 @@ static struct uart_driver sal_console_uart = {
}; };
/** /**
* sn_sal_module_init - When the kernel loads us, get us rolling w/ serial core * sn_sal_init - When the kernel loads us, get us rolling w/ serial core
* *
* Before this is called, we've been printing kernel messages in a special * Before this is called, we've been printing kernel messages in a special
* early mode not making use of the serial core infrastructure. When our * early mode not making use of the serial core infrastructure. When our
...@@ -781,7 +781,7 @@ static struct uart_driver sal_console_uart = { ...@@ -781,7 +781,7 @@ static struct uart_driver sal_console_uart = {
* core and try to enable interrupt driven mode. * core and try to enable interrupt driven mode.
* *
*/ */
static int __init sn_sal_module_init(void) static int __init sn_sal_init(void)
{ {
int retval; int retval;
...@@ -811,7 +811,7 @@ static int __init sn_sal_module_init(void) ...@@ -811,7 +811,7 @@ static int __init sn_sal_module_init(void)
if (uart_register_driver(&sal_console_uart) < 0) { if (uart_register_driver(&sal_console_uart) < 0) {
printk printk
("ERROR sn_sal_module_init failed uart_register_driver, line %d\n", ("ERROR sn_sal_init failed uart_register_driver, line %d\n",
__LINE__); __LINE__);
return -ENODEV; return -ENODEV;
} }
...@@ -832,33 +832,19 @@ static int __init sn_sal_module_init(void) ...@@ -832,33 +832,19 @@ static int __init sn_sal_module_init(void)
/* when this driver is compiled in, the console initialization /* when this driver is compiled in, the console initialization
* will have already switched us into asynchronous operation * will have already switched us into asynchronous operation
* before we get here through the module initcalls */ * before we get here through the initcalls */
if (!sal_console_port.sc_is_asynch) { if (!sal_console_port.sc_is_asynch) {
sn_sal_switch_to_asynch(&sal_console_port); sn_sal_switch_to_asynch(&sal_console_port);
} }
/* at this point (module_init) we can try to turn on interrupts */ /* at this point (device_init) we can try to turn on interrupts */
if (!IS_RUNNING_ON_SIMULATOR()) { if (!IS_RUNNING_ON_SIMULATOR()) {
sn_sal_switch_to_interrupts(&sal_console_port); sn_sal_switch_to_interrupts(&sal_console_port);
} }
sn_process_input = 1; sn_process_input = 1;
return 0; return 0;
} }
device_initcall(sn_sal_init);
/**
* sn_sal_module_exit - When we're unloaded, remove the driver/port
*
*/
static void __exit sn_sal_module_exit(void)
{
del_timer_sync(&sal_console_port.sc_timer);
uart_remove_one_port(&sal_console_uart, &sal_console_port.sc_port);
uart_unregister_driver(&sal_console_uart);
misc_deregister(&misc);
}
module_init(sn_sal_module_init);
module_exit(sn_sal_module_exit);
/** /**
* puts_raw_fixed - sn_sal_console_write helper for adding \r's as required * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Inspired by st-asc.c from STMicroelectronics (c) * Inspired by st-asc.c from STMicroelectronics (c)
*/ */
#if defined(CONFIG_SERIAL_STM32_USART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #if defined(CONFIG_SERIAL_STM32_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ #define SUPPORT_SYSRQ
#endif #endif
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
* Copyright (C) 2002 David S. Miller (davem@redhat.com) * Copyright (C) 2002 David S. Miller (davem@redhat.com)
*/ */
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/tty.h> #include <linux/tty.h>
...@@ -234,14 +233,10 @@ static int __init suncore_init(void) ...@@ -234,14 +233,10 @@ static int __init suncore_init(void)
{ {
return 0; return 0;
} }
device_initcall(suncore_init);
static void __exit suncore_exit(void) #if 0 /* ..def MODULE ; never supported as such */
{
}
module_init(suncore_init);
module_exit(suncore_exit);
MODULE_AUTHOR("Eddie C. Dost, David S. Miller"); MODULE_AUTHOR("Eddie C. Dost, David S. Miller");
MODULE_DESCRIPTION("Sun serial common layer"); MODULE_DESCRIPTION("Sun serial common layer");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#endif
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
*/ */
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/tty.h> #include <linux/tty.h>
...@@ -621,7 +620,6 @@ static const struct of_device_id hv_match[] = { ...@@ -621,7 +620,6 @@ static const struct of_device_id hv_match[] = {
}, },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, hv_match);
static struct platform_driver hv_driver = { static struct platform_driver hv_driver = {
.driver = { .driver = {
...@@ -639,16 +637,11 @@ static int __init sunhv_init(void) ...@@ -639,16 +637,11 @@ static int __init sunhv_init(void)
return platform_driver_register(&hv_driver); return platform_driver_register(&hv_driver);
} }
device_initcall(sunhv_init);
static void __exit sunhv_exit(void) #if 0 /* ...def MODULE ; never supported as such */
{
platform_driver_unregister(&hv_driver);
}
module_init(sunhv_init);
module_exit(sunhv_exit);
MODULE_AUTHOR("David S. Miller"); MODULE_AUTHOR("David S. Miller");
MODULE_DESCRIPTION("SUN4V Hypervisor console driver"); MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
MODULE_VERSION("2.0"); MODULE_VERSION("2.0");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#endif
...@@ -950,7 +950,7 @@ static void qe_uart_set_termios(struct uart_port *port, ...@@ -950,7 +950,7 @@ static void qe_uart_set_termios(struct uart_port *port,
if ((termios->c_cflag & CREAD) == 0) if ((termios->c_cflag & CREAD) == 0)
port->read_status_mask &= ~BD_SC_EMPTY; port->read_status_mask &= ~BD_SC_EMPTY;
baud = uart_get_baud_rate(port, termios, old, 0, 115200); baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
/* Do we really need a spinlock here? */ /* Do we really need a spinlock here? */
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
......
...@@ -291,12 +291,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size, ...@@ -291,12 +291,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
n->flags = flags; n->flags = flags;
buf->tail = n; buf->tail = n;
b->commit = b->used; b->commit = b->used;
/* paired w/ barrier in flush_to_ldisc(); ensures the /* paired w/ acquire in flush_to_ldisc(); ensures the
* latest commit value can be read before the head is * latest commit value can be read before the head is
* advanced to the next buffer * advanced to the next buffer
*/ */
smp_wmb(); smp_store_release(&b->next, n);
b->next = n;
} else if (change) } else if (change)
size = 0; size = 0;
else else
...@@ -445,7 +444,6 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) ...@@ -445,7 +444,6 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count)
if (count) if (count)
disc->ops->receive_buf(tty, p, f, count); disc->ops->receive_buf(tty, p, f, count);
} }
head->read += count;
return count; return count;
} }
...@@ -488,12 +486,11 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -488,12 +486,11 @@ static void flush_to_ldisc(struct work_struct *work)
if (atomic_read(&buf->priority)) if (atomic_read(&buf->priority))
break; break;
next = head->next; /* paired w/ release in __tty_buffer_request_room();
/* paired w/ barrier in __tty_buffer_request_room();
* ensures commit value read is not stale if the head * ensures commit value read is not stale if the head
* is advancing to the next buffer * is advancing to the next buffer
*/ */
smp_rmb(); next = smp_load_acquire(&head->next);
count = head->commit - head->read; count = head->commit - head->read;
if (!count) { if (!count) {
if (next == NULL) { if (next == NULL) {
...@@ -508,6 +505,7 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -508,6 +505,7 @@ static void flush_to_ldisc(struct work_struct *work)
count = receive_buf(tty, head, count); count = receive_buf(tty, head, count);
if (!count) if (!count)
break; break;
head->read += count;
} }
mutex_unlock(&buf->lock); mutex_unlock(&buf->lock);
......
...@@ -106,6 +106,11 @@ ...@@ -106,6 +106,11 @@
#include <linux/nsproxy.h> #include <linux/nsproxy.h>
#undef TTY_DEBUG_HANGUP #undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
# define tty_debug_hangup(tty, f, args...) tty_debug(tty, f, ##args)
#else
# define tty_debug_hangup(tty, f, args...) do { } while (0)
#endif
#define TTY_PARANOIA_CHECK 1 #define TTY_PARANOIA_CHECK 1
#define CHECK_TTY_COUNT 1 #define CHECK_TTY_COUNT 1
...@@ -388,33 +393,40 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver); ...@@ -388,33 +393,40 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
int tty_check_change(struct tty_struct *tty) int tty_check_change(struct tty_struct *tty)
{ {
unsigned long flags; unsigned long flags;
struct pid *pgrp;
int ret = 0; int ret = 0;
if (current->signal->tty != tty) if (current->signal->tty != tty)
return 0; return 0;
rcu_read_lock();
pgrp = task_pgrp(current);
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl_lock, flags);
if (!tty->pgrp) { if (!tty->pgrp) {
printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n"); printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
goto out_unlock; goto out_unlock;
} }
if (task_pgrp(current) == tty->pgrp) if (pgrp == tty->pgrp)
goto out_unlock; goto out_unlock;
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl_lock, flags);
if (is_ignored(SIGTTOU)) if (is_ignored(SIGTTOU))
goto out; goto out_rcuunlock;
if (is_current_pgrp_orphaned()) { if (is_current_pgrp_orphaned()) {
ret = -EIO; ret = -EIO;
goto out; goto out_rcuunlock;
} }
kill_pgrp(task_pgrp(current), SIGTTOU, 1); kill_pgrp(pgrp, SIGTTOU, 1);
rcu_read_unlock();
set_thread_flag(TIF_SIGPENDING); set_thread_flag(TIF_SIGPENDING);
ret = -ERESTARTSYS; ret = -ERESTARTSYS;
out:
return ret; return ret;
out_unlock: out_unlock:
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl_lock, flags);
out_rcuunlock:
rcu_read_unlock();
return ret; return ret;
} }
...@@ -524,7 +536,8 @@ static void __proc_set_tty(struct tty_struct *tty) ...@@ -524,7 +536,8 @@ static void __proc_set_tty(struct tty_struct *tty)
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl_lock, flags);
tty->session = get_pid(task_session(current)); tty->session = get_pid(task_session(current));
if (current->signal->tty) { if (current->signal->tty) {
printk(KERN_DEBUG "tty not NULL!!\n"); tty_debug(tty, "current tty %s not NULL!!\n",
current->signal->tty->name);
tty_kref_put(current->signal->tty); tty_kref_put(current->signal->tty);
} }
put_pid(current->signal->tty_old_pgrp); put_pid(current->signal->tty_old_pgrp);
...@@ -766,9 +779,7 @@ static void do_tty_hangup(struct work_struct *work) ...@@ -766,9 +779,7 @@ static void do_tty_hangup(struct work_struct *work)
void tty_hangup(struct tty_struct *tty) void tty_hangup(struct tty_struct *tty)
{ {
#ifdef TTY_DEBUG_HANGUP tty_debug_hangup(tty, "\n");
printk(KERN_DEBUG "%s hangup...\n", tty_name(tty));
#endif
schedule_work(&tty->hangup_work); schedule_work(&tty->hangup_work);
} }
...@@ -785,9 +796,7 @@ EXPORT_SYMBOL(tty_hangup); ...@@ -785,9 +796,7 @@ EXPORT_SYMBOL(tty_hangup);
void tty_vhangup(struct tty_struct *tty) void tty_vhangup(struct tty_struct *tty)
{ {
#ifdef TTY_DEBUG_HANGUP tty_debug_hangup(tty, "\n");
printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty));
#endif
__tty_hangup(tty, 0); __tty_hangup(tty, 0);
} }
...@@ -824,9 +833,7 @@ void tty_vhangup_self(void) ...@@ -824,9 +833,7 @@ void tty_vhangup_self(void)
static void tty_vhangup_session(struct tty_struct *tty) static void tty_vhangup_session(struct tty_struct *tty)
{ {
#ifdef TTY_DEBUG_HANGUP tty_debug_hangup(tty, "\n");
printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty));
#endif
__tty_hangup(tty, 1); __tty_hangup(tty, 1);
} }
...@@ -920,12 +927,8 @@ void disassociate_ctty(int on_exit) ...@@ -920,12 +927,8 @@ void disassociate_ctty(int on_exit)
tty->pgrp = NULL; tty->pgrp = NULL;
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl_lock, flags);
tty_kref_put(tty); tty_kref_put(tty);
} else { } else
#ifdef TTY_DEBUG_HANGUP tty_debug_hangup(tty, "no current tty\n");
printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
" = NULL", tty);
#endif
}
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
/* Now clear signal->tty under the lock */ /* Now clear signal->tty under the lock */
...@@ -1705,8 +1708,7 @@ static int tty_release_checks(struct tty_struct *tty, int idx) ...@@ -1705,8 +1708,7 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
{ {
#ifdef TTY_PARANOIA_CHECK #ifdef TTY_PARANOIA_CHECK
if (idx < 0 || idx >= tty->driver->num) { if (idx < 0 || idx >= tty->driver->num) {
printk(KERN_DEBUG "%s: bad idx when trying to free (%s)\n", tty_debug(tty, "bad idx %d\n", idx);
__func__, tty->name);
return -1; return -1;
} }
...@@ -1715,20 +1717,20 @@ static int tty_release_checks(struct tty_struct *tty, int idx) ...@@ -1715,20 +1717,20 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
return 0; return 0;
if (tty != tty->driver->ttys[idx]) { if (tty != tty->driver->ttys[idx]) {
printk(KERN_DEBUG "%s: driver.table[%d] not tty for (%s)\n", tty_debug(tty, "bad driver table[%d] = %p\n",
__func__, idx, tty->name); idx, tty->driver->ttys[idx]);
return -1; return -1;
} }
if (tty->driver->other) { if (tty->driver->other) {
struct tty_struct *o_tty = tty->link; struct tty_struct *o_tty = tty->link;
if (o_tty != tty->driver->other->ttys[idx]) { if (o_tty != tty->driver->other->ttys[idx]) {
printk(KERN_DEBUG "%s: other->table[%d] not o_tty for (%s)\n", tty_debug(tty, "bad other table[%d] = %p\n",
__func__, idx, tty->name); idx, tty->driver->other->ttys[idx]);
return -1; return -1;
} }
if (o_tty->link != tty) { if (o_tty->link != tty) {
printk(KERN_DEBUG "%s: bad pty pointers\n", __func__); tty_debug(tty, "bad link = %p\n", o_tty->link);
return -1; return -1;
} }
} }
...@@ -1782,10 +1784,7 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1782,10 +1784,7 @@ int tty_release(struct inode *inode, struct file *filp)
return 0; return 0;
} }
#ifdef TTY_DEBUG_HANGUP tty_debug_hangup(tty, "(tty count=%d)...\n", tty->count);
printk(KERN_DEBUG "%s: %s (tty count=%d)...\n", __func__,
tty_name(tty), tty->count);
#endif
if (tty->ops->close) if (tty->ops->close)
tty->ops->close(tty, filp); tty->ops->close(tty, filp);
...@@ -1895,9 +1894,7 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1895,9 +1894,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (!final) if (!final)
return 0; return 0;
#ifdef TTY_DEBUG_HANGUP tty_debug_hangup(tty, "final close\n");
printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty));
#endif
/* /*
* Ask the line discipline code to release its structures * Ask the line discipline code to release its structures
*/ */
...@@ -1906,10 +1903,7 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1906,10 +1903,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* Wait for pending work before tty destruction commmences */ /* Wait for pending work before tty destruction commmences */
tty_flush_works(tty); tty_flush_works(tty);
#ifdef TTY_DEBUG_HANGUP tty_debug_hangup(tty, "freeing structure...\n");
printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__,
tty_name(tty));
#endif
/* /*
* The release_tty function takes care of the details of clearing * The release_tty function takes care of the details of clearing
* the slots and preserving the termios structure. The tty_unlock_pair * the slots and preserving the termios structure. The tty_unlock_pair
...@@ -2098,9 +2092,9 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -2098,9 +2092,9 @@ static int tty_open(struct inode *inode, struct file *filp)
if (tty->driver->type == TTY_DRIVER_TYPE_PTY && if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER) tty->driver->subtype == PTY_TYPE_MASTER)
noctty = 1; noctty = 1;
#ifdef TTY_DEBUG_HANGUP
printk(KERN_DEBUG "%s: opening %s...\n", __func__, tty->name); tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
#endif
if (tty->ops->open) if (tty->ops->open)
retval = tty->ops->open(tty, filp); retval = tty->ops->open(tty, filp);
else else
...@@ -2108,10 +2102,8 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -2108,10 +2102,8 @@ static int tty_open(struct inode *inode, struct file *filp)
filp->f_flags = saved_flags; filp->f_flags = saved_flags;
if (retval) { if (retval) {
#ifdef TTY_DEBUG_HANGUP tty_debug_hangup(tty, "error %d, releasing...\n", retval);
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
retval, tty->name);
#endif
tty_unlock(tty); /* need to call tty_release without BTM */ tty_unlock(tty); /* need to call tty_release without BTM */
tty_release(inode, filp); tty_release(inode, filp);
if (retval != -ERESTARTSYS) if (retval != -ERESTARTSYS)
...@@ -3160,9 +3152,12 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev, ...@@ -3160,9 +3152,12 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
unsigned int index, unsigned int count) unsigned int index, unsigned int count)
{ {
/* init here, since reused cdevs cause crashes */ /* init here, since reused cdevs cause crashes */
cdev_init(&driver->cdevs[index], &tty_fops); driver->cdevs[index] = cdev_alloc();
driver->cdevs[index].owner = driver->owner; if (!driver->cdevs[index])
return cdev_add(&driver->cdevs[index], dev, count); return -ENOMEM;
cdev_init(driver->cdevs[index], &tty_fops);
driver->cdevs[index]->owner = driver->owner;
return cdev_add(driver->cdevs[index], dev, count);
} }
/** /**
...@@ -3268,8 +3263,10 @@ struct device *tty_register_device_attr(struct tty_driver *driver, ...@@ -3268,8 +3263,10 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
error: error:
put_device(dev); put_device(dev);
if (cdev) if (cdev) {
cdev_del(&driver->cdevs[index]); cdev_del(driver->cdevs[index]);
driver->cdevs[index] = NULL;
}
return ERR_PTR(retval); return ERR_PTR(retval);
} }
EXPORT_SYMBOL_GPL(tty_register_device_attr); EXPORT_SYMBOL_GPL(tty_register_device_attr);
...@@ -3289,8 +3286,10 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index) ...@@ -3289,8 +3286,10 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
{ {
device_destroy(tty_class, device_destroy(tty_class,
MKDEV(driver->major, driver->minor_start) + index); MKDEV(driver->major, driver->minor_start) + index);
if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
cdev_del(&driver->cdevs[index]); cdev_del(driver->cdevs[index]);
driver->cdevs[index] = NULL;
}
} }
EXPORT_SYMBOL(tty_unregister_device); EXPORT_SYMBOL(tty_unregister_device);
...@@ -3355,6 +3354,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, ...@@ -3355,6 +3354,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
kfree(driver->ports); kfree(driver->ports);
kfree(driver->ttys); kfree(driver->ttys);
kfree(driver->termios); kfree(driver->termios);
kfree(driver->cdevs);
kfree(driver); kfree(driver);
return ERR_PTR(err); return ERR_PTR(err);
} }
...@@ -3383,7 +3383,7 @@ static void destruct_tty_driver(struct kref *kref) ...@@ -3383,7 +3383,7 @@ static void destruct_tty_driver(struct kref *kref)
} }
proc_tty_unregister_driver(driver); proc_tty_unregister_driver(driver);
if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC) if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)
cdev_del(&driver->cdevs[0]); cdev_del(driver->cdevs[0]);
} }
kfree(driver->cdevs); kfree(driver->cdevs);
kfree(driver->ports); kfree(driver->ports);
......
...@@ -26,6 +26,12 @@ ...@@ -26,6 +26,12 @@
#undef TTY_DEBUG_WAIT_UNTIL_SENT #undef TTY_DEBUG_WAIT_UNTIL_SENT
#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
# define tty_debug_wait_until_sent(tty, f, args...) tty_debug(tty, f, ##args)
#else
# define tty_debug_wait_until_sent(tty, f, args...) do {} while (0)
#endif
#undef DEBUG #undef DEBUG
/* /*
...@@ -210,9 +216,8 @@ int tty_unthrottle_safe(struct tty_struct *tty) ...@@ -210,9 +216,8 @@ int tty_unthrottle_safe(struct tty_struct *tty)
void tty_wait_until_sent(struct tty_struct *tty, long timeout) void tty_wait_until_sent(struct tty_struct *tty, long timeout)
{ {
#ifdef TTY_DEBUG_WAIT_UNTIL_SENT tty_debug_wait_until_sent(tty, "\n");
printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty));
#endif
if (!timeout) if (!timeout)
timeout = MAX_SCHEDULE_TIMEOUT; timeout = MAX_SCHEDULE_TIMEOUT;
......
...@@ -22,9 +22,7 @@ ...@@ -22,9 +22,7 @@
#undef LDISC_DEBUG_HANGUP #undef LDISC_DEBUG_HANGUP
#ifdef LDISC_DEBUG_HANGUP #ifdef LDISC_DEBUG_HANGUP
#define tty_ldisc_debug(tty, f, args...) ({ \ #define tty_ldisc_debug(tty, f, args...) tty_debug(tty, f, ##args)
printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty), ##args); \
})
#else #else
#define tty_ldisc_debug(tty, f, args...) #define tty_ldisc_debug(tty, f, args...)
#endif #endif
...@@ -449,6 +447,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) ...@@ -449,6 +447,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
ret = ld->ops->open(tty); ret = ld->ops->open(tty);
if (ret) if (ret)
clear_bit(TTY_LDISC_OPEN, &tty->flags); clear_bit(TTY_LDISC_OPEN, &tty->flags);
tty_ldisc_debug(tty, "%p: opened\n", tty->ldisc);
return ret; return ret;
} }
return 0; return 0;
...@@ -469,6 +469,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) ...@@ -469,6 +469,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
clear_bit(TTY_LDISC_OPEN, &tty->flags); clear_bit(TTY_LDISC_OPEN, &tty->flags);
if (ld->ops->close) if (ld->ops->close)
ld->ops->close(tty); ld->ops->close(tty);
tty_ldisc_debug(tty, "%p: closed\n", tty->ldisc);
} }
/** /**
...@@ -662,7 +663,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) ...@@ -662,7 +663,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
int err = 0; int err = 0;
tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc); tty_ldisc_debug(tty, "%p: closing\n", tty->ldisc);
ld = tty_ldisc_ref(tty); ld = tty_ldisc_ref(tty);
if (ld != NULL) { if (ld != NULL) {
...@@ -712,7 +713,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) ...@@ -712,7 +713,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
if (reset) if (reset)
tty_reset_termios(tty); tty_reset_termios(tty);
tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc); tty_ldisc_debug(tty, "%p: re-opened\n", tty->ldisc);
} }
/** /**
...@@ -776,8 +777,6 @@ void tty_ldisc_release(struct tty_struct *tty) ...@@ -776,8 +777,6 @@ void tty_ldisc_release(struct tty_struct *tty)
* it does not race with the set_ldisc code path. * it does not race with the set_ldisc code path.
*/ */
tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
tty_ldisc_lock_pair(tty, o_tty); tty_ldisc_lock_pair(tty, o_tty);
tty_ldisc_kill(tty); tty_ldisc_kill(tty);
if (o_tty) if (o_tty)
...@@ -787,7 +786,7 @@ void tty_ldisc_release(struct tty_struct *tty) ...@@ -787,7 +786,7 @@ void tty_ldisc_release(struct tty_struct *tty)
/* And the memory resources remaining (buffers, termios) will be /* And the memory resources remaining (buffers, termios) will be
disposed of when the kref hits zero */ disposed of when the kref hits zero */
tty_ldisc_debug(tty, "ldisc closed\n"); tty_ldisc_debug(tty, "released\n");
} }
/** /**
......
...@@ -33,12 +33,14 @@ ...@@ -33,12 +33,14 @@
#define UART01x_DR 0x00 /* Data read or written from the interface. */ #define UART01x_DR 0x00 /* Data read or written from the interface. */
#define UART01x_RSR 0x04 /* Receive status register (Read). */ #define UART01x_RSR 0x04 /* Receive status register (Read). */
#define UART01x_ECR 0x04 /* Error clear register (Write). */ #define UART01x_ECR 0x04 /* Error clear register (Write). */
#define ZX_UART01x_DR 0x04 /* Data read or written from the interface. */
#define UART010_LCRH 0x08 /* Line control register, high byte. */ #define UART010_LCRH 0x08 /* Line control register, high byte. */
#define ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */ #define ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */
#define UART010_LCRM 0x0C /* Line control register, middle byte. */ #define UART010_LCRM 0x0C /* Line control register, middle byte. */
#define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */ #define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */
#define UART010_LCRL 0x10 /* Line control register, low byte. */ #define UART010_LCRL 0x10 /* Line control register, low byte. */
#define UART010_CR 0x14 /* Control register. */ #define UART010_CR 0x14 /* Control register. */
#define ZX_UART01x_FR 0x14 /* Flag register (Read only). */
#define UART01x_FR 0x18 /* Flag register (Read only). */ #define UART01x_FR 0x18 /* Flag register (Read only). */
#define UART010_IIR 0x1C /* Interrupt identification register (Read). */ #define UART010_IIR 0x1C /* Interrupt identification register (Read). */
#define UART010_ICR 0x1C /* Interrupt clear register (Write). */ #define UART010_ICR 0x1C /* Interrupt clear register (Write). */
...@@ -49,13 +51,21 @@ ...@@ -49,13 +51,21 @@
#define UART011_LCRH 0x2c /* Line control register. */ #define UART011_LCRH 0x2c /* Line control register. */
#define ST_UART011_LCRH_TX 0x2c /* Tx Line control register. */ #define ST_UART011_LCRH_TX 0x2c /* Tx Line control register. */
#define UART011_CR 0x30 /* Control register. */ #define UART011_CR 0x30 /* Control register. */
#define ZX_UART011_LCRH_TX 0x30 /* Tx Line control register. */
#define UART011_IFLS 0x34 /* Interrupt fifo level select. */ #define UART011_IFLS 0x34 /* Interrupt fifo level select. */
#define ZX_UART011_CR 0x34 /* Control register. */
#define ZX_UART011_IFLS 0x38 /* Interrupt fifo level select. */
#define UART011_IMSC 0x38 /* Interrupt mask. */ #define UART011_IMSC 0x38 /* Interrupt mask. */
#define UART011_RIS 0x3c /* Raw interrupt status. */ #define UART011_RIS 0x3c /* Raw interrupt status. */
#define UART011_MIS 0x40 /* Masked interrupt status. */ #define UART011_MIS 0x40 /* Masked interrupt status. */
#define ZX_UART011_IMSC 0x40 /* Interrupt mask. */
#define UART011_ICR 0x44 /* Interrupt clear register. */ #define UART011_ICR 0x44 /* Interrupt clear register. */
#define ZX_UART011_RIS 0x44 /* Raw interrupt status. */
#define UART011_DMACR 0x48 /* DMA control register. */ #define UART011_DMACR 0x48 /* DMA control register. */
#define ZX_UART011_MIS 0x48 /* Masked interrupt status. */
#define ZX_UART011_ICR 0x4c /* Interrupt clear register. */
#define ST_UART011_XFCR 0x50 /* XON/XOFF control register. */ #define ST_UART011_XFCR 0x50 /* XON/XOFF control register. */
#define ZX_UART011_DMACR 0x50 /* DMA control register. */
#define ST_UART011_XON1 0x54 /* XON1 register. */ #define ST_UART011_XON1 0x54 /* XON1 register. */
#define ST_UART011_XON2 0x58 /* XON2 register. */ #define ST_UART011_XON2 0x58 /* XON2 register. */
#define ST_UART011_XOFF1 0x5C /* XON1 register. */ #define ST_UART011_XOFF1 0x5C /* XON1 register. */
...@@ -75,15 +85,19 @@ ...@@ -75,15 +85,19 @@
#define UART01x_RSR_PE 0x02 #define UART01x_RSR_PE 0x02
#define UART01x_RSR_FE 0x01 #define UART01x_RSR_FE 0x01
#define ZX_UART01x_FR_BUSY 0x300
#define UART011_FR_RI 0x100 #define UART011_FR_RI 0x100
#define UART011_FR_TXFE 0x080 #define UART011_FR_TXFE 0x080
#define UART011_FR_RXFF 0x040 #define UART011_FR_RXFF 0x040
#define UART01x_FR_TXFF 0x020 #define UART01x_FR_TXFF 0x020
#define UART01x_FR_RXFE 0x010 #define UART01x_FR_RXFE 0x010
#define UART01x_FR_BUSY 0x008 #define UART01x_FR_BUSY 0x008
#define ZX_UART01x_FR_DSR 0x008
#define UART01x_FR_DCD 0x004 #define UART01x_FR_DCD 0x004
#define UART01x_FR_DSR 0x002 #define UART01x_FR_DSR 0x002
#define ZX_UART01x_FR_CTS 0x002
#define UART01x_FR_CTS 0x001 #define UART01x_FR_CTS 0x001
#define ZX_UART011_FR_RI 0x001
#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY) #define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY)
#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */ #define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */
......
...@@ -16,115 +16,151 @@ ...@@ -16,115 +16,151 @@
#ifndef ATMEL_SERIAL_H #ifndef ATMEL_SERIAL_H
#define ATMEL_SERIAL_H #define ATMEL_SERIAL_H
#define ATMEL_US_CR 0x00 /* Control Register */ #define ATMEL_US_CR 0x00 /* Control Register */
#define ATMEL_US_RSTRX (1 << 2) /* Reset Receiver */ #define ATMEL_US_RSTRX BIT(2) /* Reset Receiver */
#define ATMEL_US_RSTTX (1 << 3) /* Reset Transmitter */ #define ATMEL_US_RSTTX BIT(3) /* Reset Transmitter */
#define ATMEL_US_RXEN (1 << 4) /* Receiver Enable */ #define ATMEL_US_RXEN BIT(4) /* Receiver Enable */
#define ATMEL_US_RXDIS (1 << 5) /* Receiver Disable */ #define ATMEL_US_RXDIS BIT(5) /* Receiver Disable */
#define ATMEL_US_TXEN (1 << 6) /* Transmitter Enable */ #define ATMEL_US_TXEN BIT(6) /* Transmitter Enable */
#define ATMEL_US_TXDIS (1 << 7) /* Transmitter Disable */ #define ATMEL_US_TXDIS BIT(7) /* Transmitter Disable */
#define ATMEL_US_RSTSTA (1 << 8) /* Reset Status Bits */ #define ATMEL_US_RSTSTA BIT(8) /* Reset Status Bits */
#define ATMEL_US_STTBRK (1 << 9) /* Start Break */ #define ATMEL_US_STTBRK BIT(9) /* Start Break */
#define ATMEL_US_STPBRK (1 << 10) /* Stop Break */ #define ATMEL_US_STPBRK BIT(10) /* Stop Break */
#define ATMEL_US_STTTO (1 << 11) /* Start Time-out */ #define ATMEL_US_STTTO BIT(11) /* Start Time-out */
#define ATMEL_US_SENDA (1 << 12) /* Send Address */ #define ATMEL_US_SENDA BIT(12) /* Send Address */
#define ATMEL_US_RSTIT (1 << 13) /* Reset Iterations */ #define ATMEL_US_RSTIT BIT(13) /* Reset Iterations */
#define ATMEL_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */ #define ATMEL_US_RSTNACK BIT(14) /* Reset Non Acknowledge */
#define ATMEL_US_RETTO (1 << 15) /* Rearm Time-out */ #define ATMEL_US_RETTO BIT(15) /* Rearm Time-out */
#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable [AT91RM9200 only] */ #define ATMEL_US_DTREN BIT(16) /* Data Terminal Ready Enable */
#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable [AT91RM9200 only] */ #define ATMEL_US_DTRDIS BIT(17) /* Data Terminal Ready Disable */
#define ATMEL_US_RTSEN (1 << 18) /* Request To Send Enable */ #define ATMEL_US_RTSEN BIT(18) /* Request To Send Enable */
#define ATMEL_US_RTSDIS (1 << 19) /* Request To Send Disable */ #define ATMEL_US_RTSDIS BIT(19) /* Request To Send Disable */
#define ATMEL_US_TXFCLR BIT(24) /* Transmit FIFO Clear */
#define ATMEL_US_RXFCLR BIT(25) /* Receive FIFO Clear */
#define ATMEL_US_TXFLCLR BIT(26) /* Transmit FIFO Lock Clear */
#define ATMEL_US_FIFOEN BIT(30) /* FIFO enable */
#define ATMEL_US_FIFODIS BIT(31) /* FIFO disable */
#define ATMEL_US_MR 0x04 /* Mode Register */ #define ATMEL_US_MR 0x04 /* Mode Register */
#define ATMEL_US_USMODE (0xf << 0) /* Mode of the USART */ #define ATMEL_US_USMODE GENMASK(3, 0) /* Mode of the USART */
#define ATMEL_US_USMODE_NORMAL 0 #define ATMEL_US_USMODE_NORMAL 0
#define ATMEL_US_USMODE_RS485 1 #define ATMEL_US_USMODE_RS485 1
#define ATMEL_US_USMODE_HWHS 2 #define ATMEL_US_USMODE_HWHS 2
#define ATMEL_US_USMODE_MODEM 3 #define ATMEL_US_USMODE_MODEM 3
#define ATMEL_US_USMODE_ISO7816_T0 4 #define ATMEL_US_USMODE_ISO7816_T0 4
#define ATMEL_US_USMODE_ISO7816_T1 6 #define ATMEL_US_USMODE_ISO7816_T1 6
#define ATMEL_US_USMODE_IRDA 8 #define ATMEL_US_USMODE_IRDA 8
#define ATMEL_US_USCLKS (3 << 4) /* Clock Selection */ #define ATMEL_US_USCLKS GENMASK(5, 4) /* Clock Selection */
#define ATMEL_US_USCLKS_MCK (0 << 4) #define ATMEL_US_USCLKS_MCK (0 << 4)
#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4) #define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
#define ATMEL_US_USCLKS_SCK (3 << 4) #define ATMEL_US_USCLKS_SCK (3 << 4)
#define ATMEL_US_CHRL (3 << 6) /* Character Length */ #define ATMEL_US_CHRL GENMASK(7, 6) /* Character Length */
#define ATMEL_US_CHRL_5 (0 << 6) #define ATMEL_US_CHRL_5 (0 << 6)
#define ATMEL_US_CHRL_6 (1 << 6) #define ATMEL_US_CHRL_6 (1 << 6)
#define ATMEL_US_CHRL_7 (2 << 6) #define ATMEL_US_CHRL_7 (2 << 6)
#define ATMEL_US_CHRL_8 (3 << 6) #define ATMEL_US_CHRL_8 (3 << 6)
#define ATMEL_US_SYNC (1 << 8) /* Synchronous Mode Select */ #define ATMEL_US_SYNC BIT(8) /* Synchronous Mode Select */
#define ATMEL_US_PAR (7 << 9) /* Parity Type */ #define ATMEL_US_PAR GENMASK(11, 9) /* Parity Type */
#define ATMEL_US_PAR_EVEN (0 << 9) #define ATMEL_US_PAR_EVEN (0 << 9)
#define ATMEL_US_PAR_ODD (1 << 9) #define ATMEL_US_PAR_ODD (1 << 9)
#define ATMEL_US_PAR_SPACE (2 << 9) #define ATMEL_US_PAR_SPACE (2 << 9)
#define ATMEL_US_PAR_MARK (3 << 9) #define ATMEL_US_PAR_MARK (3 << 9)
#define ATMEL_US_PAR_NONE (4 << 9) #define ATMEL_US_PAR_NONE (4 << 9)
#define ATMEL_US_PAR_MULTI_DROP (6 << 9) #define ATMEL_US_PAR_MULTI_DROP (6 << 9)
#define ATMEL_US_NBSTOP (3 << 12) /* Number of Stop Bits */ #define ATMEL_US_NBSTOP GENMASK(13, 12) /* Number of Stop Bits */
#define ATMEL_US_NBSTOP_1 (0 << 12) #define ATMEL_US_NBSTOP_1 (0 << 12)
#define ATMEL_US_NBSTOP_1_5 (1 << 12) #define ATMEL_US_NBSTOP_1_5 (1 << 12)
#define ATMEL_US_NBSTOP_2 (2 << 12) #define ATMEL_US_NBSTOP_2 (2 << 12)
#define ATMEL_US_CHMODE (3 << 14) /* Channel Mode */ #define ATMEL_US_CHMODE GENMASK(15, 14) /* Channel Mode */
#define ATMEL_US_CHMODE_NORMAL (0 << 14) #define ATMEL_US_CHMODE_NORMAL (0 << 14)
#define ATMEL_US_CHMODE_ECHO (1 << 14) #define ATMEL_US_CHMODE_ECHO (1 << 14)
#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14) #define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
#define ATMEL_US_CHMODE_REM_LOOP (3 << 14) #define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
#define ATMEL_US_MSBF (1 << 16) /* Bit Order */ #define ATMEL_US_MSBF BIT(16) /* Bit Order */
#define ATMEL_US_MODE9 (1 << 17) /* 9-bit Character Length */ #define ATMEL_US_MODE9 BIT(17) /* 9-bit Character Length */
#define ATMEL_US_CLKO (1 << 18) /* Clock Output Select */ #define ATMEL_US_CLKO BIT(18) /* Clock Output Select */
#define ATMEL_US_OVER (1 << 19) /* Oversampling Mode */ #define ATMEL_US_OVER BIT(19) /* Oversampling Mode */
#define ATMEL_US_INACK (1 << 20) /* Inhibit Non Acknowledge */ #define ATMEL_US_INACK BIT(20) /* Inhibit Non Acknowledge */
#define ATMEL_US_DSNACK (1 << 21) /* Disable Successive NACK */ #define ATMEL_US_DSNACK BIT(21) /* Disable Successive NACK */
#define ATMEL_US_MAX_ITER (7 << 24) /* Max Iterations */ #define ATMEL_US_MAX_ITER GENMASK(26, 24) /* Max Iterations */
#define ATMEL_US_FILTER (1 << 28) /* Infrared Receive Line Filter */ #define ATMEL_US_FILTER BIT(28) /* Infrared Receive Line Filter */
#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */ #define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
#define ATMEL_US_RXRDY (1 << 0) /* Receiver Ready */ #define ATMEL_US_RXRDY BIT(0) /* Receiver Ready */
#define ATMEL_US_TXRDY (1 << 1) /* Transmitter Ready */ #define ATMEL_US_TXRDY BIT(1) /* Transmitter Ready */
#define ATMEL_US_RXBRK (1 << 2) /* Break Received / End of Break */ #define ATMEL_US_RXBRK BIT(2) /* Break Received / End of Break */
#define ATMEL_US_ENDRX (1 << 3) /* End of Receiver Transfer */ #define ATMEL_US_ENDRX BIT(3) /* End of Receiver Transfer */
#define ATMEL_US_ENDTX (1 << 4) /* End of Transmitter Transfer */ #define ATMEL_US_ENDTX BIT(4) /* End of Transmitter Transfer */
#define ATMEL_US_OVRE (1 << 5) /* Overrun Error */ #define ATMEL_US_OVRE BIT(5) /* Overrun Error */
#define ATMEL_US_FRAME (1 << 6) /* Framing Error */ #define ATMEL_US_FRAME BIT(6) /* Framing Error */
#define ATMEL_US_PARE (1 << 7) /* Parity Error */ #define ATMEL_US_PARE BIT(7) /* Parity Error */
#define ATMEL_US_TIMEOUT (1 << 8) /* Receiver Time-out */ #define ATMEL_US_TIMEOUT BIT(8) /* Receiver Time-out */
#define ATMEL_US_TXEMPTY (1 << 9) /* Transmitter Empty */ #define ATMEL_US_TXEMPTY BIT(9) /* Transmitter Empty */
#define ATMEL_US_ITERATION (1 << 10) /* Max number of Repetitions Reached */ #define ATMEL_US_ITERATION BIT(10) /* Max number of Repetitions Reached */
#define ATMEL_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */ #define ATMEL_US_TXBUFE BIT(11) /* Transmission Buffer Empty */
#define ATMEL_US_RXBUFF (1 << 12) /* Reception Buffer Full */ #define ATMEL_US_RXBUFF BIT(12) /* Reception Buffer Full */
#define ATMEL_US_NACK (1 << 13) /* Non Acknowledge */ #define ATMEL_US_NACK BIT(13) /* Non Acknowledge */
#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change [AT91RM9200 only] */ #define ATMEL_US_RIIC BIT(16) /* Ring Indicator Input Change */
#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change [AT91RM9200 only] */ #define ATMEL_US_DSRIC BIT(17) /* Data Set Ready Input Change */
#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change [AT91RM9200 only] */ #define ATMEL_US_DCDIC BIT(18) /* Data Carrier Detect Input Change */
#define ATMEL_US_CTSIC (1 << 19) /* Clear to Send Input Change */ #define ATMEL_US_CTSIC BIT(19) /* Clear to Send Input Change */
#define ATMEL_US_RI (1 << 20) /* RI */ #define ATMEL_US_RI BIT(20) /* RI */
#define ATMEL_US_DSR (1 << 21) /* DSR */ #define ATMEL_US_DSR BIT(21) /* DSR */
#define ATMEL_US_DCD (1 << 22) /* DCD */ #define ATMEL_US_DCD BIT(22) /* DCD */
#define ATMEL_US_CTS (1 << 23) /* CTS */ #define ATMEL_US_CTS BIT(23) /* CTS */
#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */ #define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */
#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */ #define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */
#define ATMEL_US_CSR 0x14 /* Channel Status Register */ #define ATMEL_US_CSR 0x14 /* Channel Status Register */
#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */ #define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */ #define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
#define ATMEL_US_SYNH (1 << 15) /* Transmit/Receive Sync [AT91SAM9261 only] */ #define ATMEL_US_SYNH BIT(15) /* Transmit/Receive Sync */
#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */ #define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
#define ATMEL_US_CD (0xffff << 0) /* Clock Divider */ #define ATMEL_US_CD GENMASK(15, 0) /* Clock Divider */
#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */ #define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */
#define ATMEL_US_TO (0xffff << 0) /* Time-out Value */ #define ATMEL_US_TO GENMASK(15, 0) /* Time-out Value */
#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */ #define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */
#define ATMEL_US_TG (0xff << 0) /* Timeguard Value */ #define ATMEL_US_TG GENMASK(7, 0) /* Timeguard Value */
#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */ #define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */
#define ATMEL_US_NER 0x44 /* Number of Errors Register */ #define ATMEL_US_NER 0x44 /* Number of Errors Register */
#define ATMEL_US_IF 0x4c /* IrDA Filter Register */ #define ATMEL_US_IF 0x4c /* IrDA Filter Register */
#define ATMEL_US_NAME 0xf0 /* Ip Name */ #define ATMEL_US_CMPR 0x90 /* Comparaison Register */
#define ATMEL_US_VERSION 0xfc /* Ip Version */ #define ATMEL_US_FMR 0xa0 /* FIFO Mode Register */
#define ATMEL_US_TXRDYM(data) (((data) & 0x3) << 0) /* TX Ready Mode */
#define ATMEL_US_RXRDYM(data) (((data) & 0x3) << 4) /* RX Ready Mode */
#define ATMEL_US_ONE_DATA 0x0
#define ATMEL_US_TWO_DATA 0x1
#define ATMEL_US_FOUR_DATA 0x2
#define ATMEL_US_FRTSC BIT(7) /* FIFO RTS pin Control */
#define ATMEL_US_TXFTHRES(thr) (((thr) & 0x3f) << 8) /* TX FIFO Threshold */
#define ATMEL_US_RXFTHRES(thr) (((thr) & 0x3f) << 16) /* RX FIFO Threshold */
#define ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24) /* RX FIFO Threshold2 */
#define ATMEL_US_FLR 0xa4 /* FIFO Level Register */
#define ATMEL_US_TXFL(reg) (((reg) >> 0) & 0x3f) /* TX FIFO Level */
#define ATMEL_US_RXFL(reg) (((reg) >> 16) & 0x3f) /* RX FIFO Level */
#define ATMEL_US_FIER 0xa8 /* FIFO Interrupt Enable Register */
#define ATMEL_US_FIDR 0xac /* FIFO Interrupt Disable Register */
#define ATMEL_US_FIMR 0xb0 /* FIFO Interrupt Mask Register */
#define ATMEL_US_FESR 0xb4 /* FIFO Event Status Register */
#define ATMEL_US_TXFEF BIT(0) /* Transmit FIFO Empty Flag */
#define ATMEL_US_TXFFF BIT(1) /* Transmit FIFO Full Flag */
#define ATMEL_US_TXFTHF BIT(2) /* Transmit FIFO Threshold Flag */
#define ATMEL_US_RXFEF BIT(3) /* Receive FIFO Empty Flag */
#define ATMEL_US_RXFFF BIT(4) /* Receive FIFO Full Flag */
#define ATMEL_US_RXFTHF BIT(5) /* Receive FIFO Threshold Flag */
#define ATMEL_US_TXFPTEF BIT(6) /* Transmit FIFO Pointer Error Flag */
#define ATMEL_US_RXFPTEF BIT(7) /* Receive FIFO Pointer Error Flag */
#define ATMEL_US_TXFLOCK BIT(8) /* Transmit FIFO Lock (FESR only) */
#define ATMEL_US_RXFTHF2 BIT(9) /* Receive FIFO Threshold Flag 2 */
#define ATMEL_US_NAME 0xf0 /* Ip Name */
#define ATMEL_US_VERSION 0xfc /* Ip Version */
#endif #endif
...@@ -136,8 +136,6 @@ void serial8250_resume_port(int line); ...@@ -136,8 +136,6 @@ void serial8250_resume_port(int line);
extern int early_serial_setup(struct uart_port *port); extern int early_serial_setup(struct uart_port *port);
extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
extern void serial8250_early_out(struct uart_port *port, int offset, int value);
extern int early_serial8250_setup(struct earlycon_device *device, extern int early_serial8250_setup(struct earlycon_device *device,
const char *options); const char *options);
extern void serial8250_do_set_termios(struct uart_port *port, extern void serial8250_do_set_termios(struct uart_port *port,
...@@ -152,6 +150,11 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir); ...@@ -152,6 +150,11 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr); unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
void serial8250_tx_chars(struct uart_8250_port *up); void serial8250_tx_chars(struct uart_8250_port *up);
unsigned int serial8250_modem_status(struct uart_8250_port *up); unsigned int serial8250_modem_status(struct uart_8250_port *up);
void serial8250_init_port(struct uart_8250_port *up);
void serial8250_set_defaults(struct uart_8250_port *up);
void serial8250_console_write(struct uart_8250_port *up, const char *s,
unsigned int count);
int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
extern void serial8250_set_isa_configurator(void (*v) extern void serial8250_set_isa_configurator(void (*v)
(int port, struct uart_port *up, (int port, struct uart_port *up,
......
...@@ -709,4 +709,10 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {} ...@@ -709,4 +709,10 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {}
static inline void proc_tty_unregister_driver(struct tty_driver *d) {} static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
#endif #endif
#define tty_debug(tty, f, args...) \
do { \
printk(KERN_DEBUG "%s: %s: " f, __func__, \
tty_name(tty), ##args); \
} while (0)
#endif #endif
...@@ -296,7 +296,7 @@ struct tty_operations { ...@@ -296,7 +296,7 @@ struct tty_operations {
struct tty_driver { struct tty_driver {
int magic; /* magic number for this structure */ int magic; /* magic number for this structure */
struct kref kref; /* Reference management */ struct kref kref; /* Reference management */
struct cdev *cdevs; struct cdev **cdevs;
struct module *owner; struct module *owner;
const char *driver_name; const char *driver_name;
const char *name; const char *name;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/types.h>
struct gsm_config struct gsm_config
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册