TTY/Serial driver patches for 4.3-rc1
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iEYEABECAAYFAlXV9dQACgkQMUfUDdst+ynbVQCgs3TBU7xHE4Yci6/w0+wo27Ru 6h8An2Fm80ia5aqFrKDl67WdRMgJyEzB =6djD -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
c2078402e4
51 changed files with 4740 additions and 3813 deletions
|
@ -22,6 +22,8 @@ Optional properties:
|
|||
memory peripheral interface and USART DMA channel ID, FIFO configuration.
|
||||
Refer to dma.txt and atmel-dma.txt for details.
|
||||
- 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:
|
||||
- at91rm9200: legacy USART support
|
||||
|
@ -57,4 +59,5 @@ Example:
|
|||
dmas = <&dma0 2 0x3>,
|
||||
<&dma0 2 0x204>;
|
||||
dma-names = "tx", "rx";
|
||||
atmel,fifo-size = <32>;
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ Required properties:
|
|||
- interrupts: device interrupt
|
||||
|
||||
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.
|
||||
|
||||
Example:
|
||||
|
@ -16,4 +16,8 @@ serial@b00260000 {
|
|||
reg = <0xb0026000 0x1000>;
|
||||
interrupts = <68>;
|
||||
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:
|
|||
- compatible : should be "ti,omap2-uart" for OMAP2 controllers
|
||||
- compatible : should be "ti,omap3-uart" for OMAP3 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
|
||||
- interrupts or interrupts-extended : Should contain the uart interrupt
|
||||
specifier or both the interrupt
|
||||
|
|
|
@ -210,7 +210,7 @@
|
|||
};
|
||||
|
||||
uart0: serial@44e09000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||
ti,hwmods = "uart1";
|
||||
clock-frequency = <48000000>;
|
||||
reg = <0x44e09000 0x2000>;
|
||||
|
@ -221,7 +221,7 @@
|
|||
};
|
||||
|
||||
uart1: serial@48022000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||
ti,hwmods = "uart2";
|
||||
clock-frequency = <48000000>;
|
||||
reg = <0x48022000 0x2000>;
|
||||
|
@ -232,7 +232,7 @@
|
|||
};
|
||||
|
||||
uart2: serial@48024000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||
ti,hwmods = "uart3";
|
||||
clock-frequency = <48000000>;
|
||||
reg = <0x48024000 0x2000>;
|
||||
|
@ -243,7 +243,7 @@
|
|||
};
|
||||
|
||||
uart3: serial@481a6000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||
ti,hwmods = "uart4";
|
||||
clock-frequency = <48000000>;
|
||||
reg = <0x481a6000 0x2000>;
|
||||
|
@ -252,7 +252,7 @@
|
|||
};
|
||||
|
||||
uart4: serial@481a8000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||
ti,hwmods = "uart5";
|
||||
clock-frequency = <48000000>;
|
||||
reg = <0x481a8000 0x2000>;
|
||||
|
@ -261,7 +261,7 @@
|
|||
};
|
||||
|
||||
uart5: serial@481aa000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||
ti,hwmods = "uart6";
|
||||
clock-frequency = <48000000>;
|
||||
reg = <0x481aa000 0x2000>;
|
||||
|
|
|
@ -397,7 +397,7 @@
|
|||
};
|
||||
|
||||
uart1: serial@4806a000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x4806a000 0x100>;
|
||||
interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart1";
|
||||
|
@ -408,7 +408,7 @@
|
|||
};
|
||||
|
||||
uart2: serial@4806c000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x4806c000 0x100>;
|
||||
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart2";
|
||||
|
@ -419,7 +419,7 @@
|
|||
};
|
||||
|
||||
uart3: serial@48020000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x48020000 0x100>;
|
||||
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart3";
|
||||
|
@ -430,7 +430,7 @@
|
|||
};
|
||||
|
||||
uart4: serial@4806e000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x4806e000 0x100>;
|
||||
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart4";
|
||||
|
@ -441,7 +441,7 @@
|
|||
};
|
||||
|
||||
uart5: serial@48066000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x48066000 0x100>;
|
||||
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart5";
|
||||
|
@ -452,7 +452,7 @@
|
|||
};
|
||||
|
||||
uart6: serial@48068000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x48068000 0x100>;
|
||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart6";
|
||||
|
@ -463,7 +463,7 @@
|
|||
};
|
||||
|
||||
uart7: serial@48420000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x48420000 0x100>;
|
||||
interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart7";
|
||||
|
@ -472,7 +472,7 @@
|
|||
};
|
||||
|
||||
uart8: serial@48422000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x48422000 0x100>;
|
||||
interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart8";
|
||||
|
@ -481,7 +481,7 @@
|
|||
};
|
||||
|
||||
uart9: serial@48424000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x48424000 0x100>;
|
||||
interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart9";
|
||||
|
@ -490,7 +490,7 @@
|
|||
};
|
||||
|
||||
uart10: serial@4ae2b000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||
reg = <0x4ae2b000 0x100>;
|
||||
interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart10";
|
||||
|
|
|
@ -153,6 +153,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
|
|||
{"AEI0250"}, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
|
||||
{"AEI1240"}, /* Actiontec ISA PNP 56K X2 Fax Modem */
|
||||
{"AKY1021"}, /* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
||||
{"ALI5123"}, /* ALi Fast Infrared Controller */
|
||||
{"AZT4001"}, /* AZT3005 PnP SOUND DEVICE */
|
||||
{"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */
|
||||
{"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */
|
||||
|
|
|
@ -2712,7 +2712,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
|
|||
memcpy(skb_put(skb, size), in_buf, size);
|
||||
|
||||
skb->dev = net;
|
||||
skb->protocol = __constant_htons(ETH_P_IP);
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
/* Ship it off to the kernel */
|
||||
netif_rx(skb);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
struct pid *pgrp;
|
||||
|
||||
/* Job control check -- must be done at start and after
|
||||
every sleep (POSIX.1 7.1.1.4). */
|
||||
/* 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)
|
|||
current->signal->tty != tty)
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
pgrp = task_pgrp(current);
|
||||
|
||||
spin_lock_irq(&tty->ctrl_lock);
|
||||
if (!tty->pgrp)
|
||||
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);
|
||||
if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
|
||||
if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
|
||||
rcu_read_unlock();
|
||||
return -EIO;
|
||||
kill_pgrp(task_pgrp(current), SIGTTIN, 1);
|
||||
}
|
||||
kill_pgrp(pgrp, SIGTTIN, 1);
|
||||
rcu_read_unlock();
|
||||
set_thread_flag(TIF_SIGPENDING);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
spin_unlock_irq(&tty->ctrl_lock);
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,12 @@
|
|||
#include <linux/mutex.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
|
||||
static struct tty_driver *ptm_driver;
|
||||
|
@ -779,6 +785,8 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
|||
if (retval)
|
||||
goto err_release;
|
||||
|
||||
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
|
||||
|
||||
tty_unlock(tty);
|
||||
return 0;
|
||||
err_release:
|
||||
|
|
|
@ -42,9 +42,9 @@ struct uart_8250_dma {
|
|||
size_t rx_size;
|
||||
size_t tx_size;
|
||||
|
||||
unsigned char tx_running:1;
|
||||
unsigned char tx_err: 1;
|
||||
unsigned char rx_running:1;
|
||||
unsigned char tx_running;
|
||||
unsigned char tx_err;
|
||||
unsigned char rx_running;
|
||||
};
|
||||
|
||||
struct old_serial_port {
|
||||
|
@ -211,3 +211,14 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
|
|||
}
|
||||
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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -56,7 +56,6 @@
|
|||
|
||||
struct dw8250_data {
|
||||
u8 usr_reg;
|
||||
int last_mcr;
|
||||
int line;
|
||||
int msr_mask_on;
|
||||
int msr_mask_off;
|
||||
|
@ -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;
|
||||
|
||||
/* 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 */
|
||||
if (offset == UART_MSR) {
|
||||
value |= d->msr_mask_on;
|
||||
|
@ -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)
|
||||
{
|
||||
struct dw8250_data *d = p->private_data;
|
||||
|
||||
if (offset == UART_MCR)
|
||||
d->last_mcr = value;
|
||||
|
||||
writeb(value, p->membase + (offset << p->regshift));
|
||||
|
||||
/* Make sure LCR write wasn't ignored */
|
||||
|
@ -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)
|
||||
{
|
||||
struct dw8250_data *d = p->private_data;
|
||||
|
||||
if (offset == UART_MCR)
|
||||
d->last_mcr = value;
|
||||
|
||||
value &= 0xff;
|
||||
__raw_writeq(value, p->membase + (offset << p->regshift));
|
||||
/* Read back to ensure register write ordering. */
|
||||
|
@ -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)
|
||||
{
|
||||
struct dw8250_data *d = p->private_data;
|
||||
|
||||
if (offset == UART_MCR)
|
||||
d->last_mcr = value;
|
||||
|
||||
writel(value, p->membase + (offset << p->regshift));
|
||||
|
||||
/* Make sure LCR write wasn't ignored */
|
||||
|
@ -257,6 +235,11 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
|||
|
||||
if (!ret)
|
||||
p->uartclk = rate;
|
||||
|
||||
p->status &= ~UPSTAT_AUTOCTS;
|
||||
if (termios->c_cflag & CRTSCTS)
|
||||
p->status |= UPSTAT_AUTOCTS;
|
||||
|
||||
out:
|
||||
serial8250_do_set_termios(p, termios, old);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <asm/io.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) {
|
||||
case UPIO_MEM:
|
||||
|
@ -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) {
|
||||
case UPIO_MEM:
|
||||
|
|
|
@ -17,18 +17,19 @@
|
|||
#include <linux/serial_core.h>
|
||||
#include "8250.h"
|
||||
|
||||
#define ADDR_PORT 0x4E
|
||||
#define DATA_PORT 0x4F
|
||||
#define ENTRY_KEY 0x77
|
||||
#define ADDR_PORT 0
|
||||
#define DATA_PORT 1
|
||||
#define EXIT_KEY 0xAA
|
||||
#define CHIP_ID1 0x20
|
||||
#define CHIP_ID1_VAL 0x02
|
||||
#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_VAL 0x19
|
||||
#define VENDOR_ID2 0x24
|
||||
#define VENDOR_ID2_VAL 0x34
|
||||
#define IO_ADDR1 0x61
|
||||
#define IO_ADDR2 0x60
|
||||
#define LDN 0x7
|
||||
|
||||
#define RS485 0xF0
|
||||
|
@ -39,51 +40,49 @@
|
|||
|
||||
#define DRIVER_NAME "8250_fintek"
|
||||
|
||||
static int fintek_8250_enter_key(void){
|
||||
struct fintek_8250 {
|
||||
u16 base_port;
|
||||
u8 index;
|
||||
u8 key;
|
||||
long line;
|
||||
};
|
||||
|
||||
if (!request_muxed_region(ADDR_PORT, 2, DRIVER_NAME))
|
||||
static int fintek_8250_enter_key(u16 base_port, u8 key)
|
||||
{
|
||||
|
||||
if (!request_muxed_region(base_port, 2, DRIVER_NAME))
|
||||
return -EBUSY;
|
||||
|
||||
outb(ENTRY_KEY, ADDR_PORT);
|
||||
outb(ENTRY_KEY, ADDR_PORT);
|
||||
outb(key, base_port + ADDR_PORT);
|
||||
outb(key, base_port + ADDR_PORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fintek_8250_exit_key(void){
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int fintek_8250_check_id(void)
|
||||
static void fintek_8250_exit_key(u16 base_port)
|
||||
{
|
||||
|
||||
outb(CHIP_ID1, ADDR_PORT);
|
||||
if (inb(DATA_PORT) != CHIP_ID1_VAL)
|
||||
outb(EXIT_KEY, base_port + ADDR_PORT);
|
||||
release_region(base_port + ADDR_PORT, 2);
|
||||
}
|
||||
|
||||
static int fintek_8250_check_id(u16 base_port)
|
||||
{
|
||||
u16 chip;
|
||||
|
||||
outb(VENDOR_ID1, base_port + ADDR_PORT);
|
||||
if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL)
|
||||
return -ENODEV;
|
||||
|
||||
outb(CHIP_ID2, ADDR_PORT);
|
||||
if (inb(DATA_PORT) != CHIP_ID2_VAL)
|
||||
outb(VENDOR_ID2, base_port + ADDR_PORT);
|
||||
if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL)
|
||||
return -ENODEV;
|
||||
|
||||
outb(VENDOR_ID1, ADDR_PORT);
|
||||
if (inb(DATA_PORT) != VENDOR_ID1_VAL)
|
||||
return -ENODEV;
|
||||
outb(CHIP_ID1, base_port + ADDR_PORT);
|
||||
chip = inb(base_port + DATA_PORT);
|
||||
outb(CHIP_ID2, base_port + ADDR_PORT);
|
||||
chip |= inb(base_port + DATA_PORT) << 8;
|
||||
|
||||
outb(VENDOR_ID2, ADDR_PORT);
|
||||
if (inb(DATA_PORT) != VENDOR_ID2_VAL)
|
||||
if (chip != CHIP_ID_0 && chip != CHIP_ID_1)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
|
@ -93,9 +92,9 @@ static int fintek_8250_rs485_config(struct uart_port *port,
|
|||
struct serial_rs485 *rs485)
|
||||
{
|
||||
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;
|
||||
|
||||
if (rs485->flags & SER_RS485_ENABLED)
|
||||
|
@ -125,44 +124,84 @@ static int fintek_8250_rs485_config(struct uart_port *port,
|
|||
if (rs485->flags & SER_RS485_RTS_ON_SEND)
|
||||
config |= RTS_INVERT;
|
||||
|
||||
if (fintek_8250_enter_key())
|
||||
if (fintek_8250_enter_key(pdata->base_port, pdata->key))
|
||||
return -EBUSY;
|
||||
|
||||
outb(LDN, ADDR_PORT);
|
||||
outb(index, DATA_PORT);
|
||||
outb(RS485, ADDR_PORT);
|
||||
outb(config, DATA_PORT);
|
||||
fintek_8250_exit_key();
|
||||
outb(LDN, pdata->base_port + ADDR_PORT);
|
||||
outb(pdata->index, pdata->base_port + DATA_PORT);
|
||||
outb(RS485, pdata->base_port + ADDR_PORT);
|
||||
outb(config, pdata->base_port + DATA_PORT);
|
||||
fintek_8250_exit_key(pdata->base_port);
|
||||
|
||||
port->rs485 = *rs485;
|
||||
|
||||
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
|
||||
fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
||||
{
|
||||
int line;
|
||||
struct uart_8250_port uart;
|
||||
int ret;
|
||||
struct fintek_8250 *pdata;
|
||||
int base_port;
|
||||
u8 key;
|
||||
u8 index;
|
||||
|
||||
if (!pnp_port_valid(dev, 0))
|
||||
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;
|
||||
|
||||
/* Enable configuration registers*/
|
||||
if (fintek_8250_enter_key())
|
||||
return -EBUSY;
|
||||
|
||||
/*Check ID*/
|
||||
ret = fintek_8250_check_id();
|
||||
fintek_8250_exit_key();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(&uart, 0, sizeof(uart));
|
||||
|
||||
pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
uart.port.private_data = pdata;
|
||||
|
||||
if (!pnp_irq_valid(dev, 0))
|
||||
return -ENODEV;
|
||||
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)
|
|||
uart.port.uartclk = 1843200;
|
||||
uart.port.dev = &dev->dev;
|
||||
|
||||
line = serial8250_register_8250_port(&uart);
|
||||
if (line < 0)
|
||||
pdata->key = key;
|
||||
pdata->base_port = base_port;
|
||||
pdata->index = index;
|
||||
pdata->line = serial8250_register_8250_port(&uart);
|
||||
if (pdata->line < 0)
|
||||
return -ENODEV;
|
||||
|
||||
pnp_set_drvdata(dev, (void *)((long)line + 1));
|
||||
pnp_set_drvdata(dev, pdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
serial8250_unregister_port(line - 1);
|
||||
if (pdata)
|
||||
serial8250_unregister_port(pdata->line);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
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;
|
||||
serial8250_suspend_port(line - 1);
|
||||
serial8250_suspend_port(pdata->line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
serial8250_resume_port(line - 1);
|
||||
serial8250_resume_port(pdata->line);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -252,7 +252,6 @@ MODULE_DEVICE_TABLE(of, of_match);
|
|||
static struct platform_driver ingenic_uart_platform_driver = {
|
||||
.driver = {
|
||||
.name = "ingenic-uart",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match,
|
||||
},
|
||||
.probe = ingenic_uart_probe,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -32,6 +33,11 @@
|
|||
#define UART_ERRATA_i202_MDR1_ACCESS (1 << 0)
|
||||
#define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1)
|
||||
#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_TX_TRIG 4
|
||||
|
@ -53,6 +59,12 @@
|
|||
#define OMAP_UART_MVR_MAJ_SHIFT 8
|
||||
#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_RX 4
|
||||
|
||||
|
@ -100,6 +112,7 @@ struct omap8250_priv {
|
|||
struct work_struct qos_work;
|
||||
struct uart_8250_dma omap8250_dma;
|
||||
spinlock_t rx_dma_lock;
|
||||
bool rx_dma_broken;
|
||||
};
|
||||
|
||||
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,
|
|||
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)
|
||||
{
|
||||
struct omap8250_priv *priv = up->port.private_data;
|
||||
|
@ -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_LCR, up->lcr);
|
||||
/* need mode A for FCR */
|
||||
if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
|
||||
omap_8250_mdr1_errataset(up, priv);
|
||||
else
|
||||
serial_out(up, UART_OMAP_MDR1, priv->mdr1);
|
||||
|
||||
omap8250_update_mdr1(up, priv);
|
||||
|
||||
up->port.ops->set_mctrl(&up->port, up->port.mctrl);
|
||||
}
|
||||
|
||||
|
@ -428,12 +448,9 @@ static void omap_8250_set_termios(struct uart_port *port,
|
|||
priv->efr |= UART_EFR_CTS;
|
||||
} else if (up->port.flags & UPF_SOFT_FLOW) {
|
||||
/*
|
||||
* IXON Flag:
|
||||
* Enable XON/XOFF flow control on input.
|
||||
* Receiver compares XON1, XOFF1.
|
||||
* OMAP rx s/w flow control is borked; the transmitter remains
|
||||
* stuck off even if rx flow control is subsequently disabled
|
||||
*/
|
||||
if (termios->c_iflag & IXON)
|
||||
priv->efr |= OMAP_UART_SW_RX;
|
||||
|
||||
/*
|
||||
* IXOFF Flag:
|
||||
|
@ -444,15 +461,6 @@ static void omap_8250_set_termios(struct uart_port *port,
|
|||
up->port.status |= UPSTAT_AUTOXOFF;
|
||||
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);
|
||||
|
||||
|
@ -530,14 +538,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
|
|||
|
||||
switch (revision) {
|
||||
case OMAP_UART_REV_46:
|
||||
priv->habit = UART_ERRATA_i202_MDR1_ACCESS;
|
||||
priv->habit |= UART_ERRATA_i202_MDR1_ACCESS;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
|
@ -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 uart_8250_dma *dma = p->dma;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_dma_lock, flags);
|
||||
|
||||
|
@ -762,7 +771,9 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
|
|||
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);
|
||||
|
||||
|
@ -806,6 +817,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
|
|||
break;
|
||||
}
|
||||
|
||||
if (priv->rx_dma_broken)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_dma_lock, flags);
|
||||
|
||||
if (dma->rx_running)
|
||||
|
@ -1054,6 +1068,20 @@ static int omap8250_no_handle_irq(struct uart_port *port)
|
|||
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)
|
||||
{
|
||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
@ -1118,11 +1146,17 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||
up.port.unthrottle = omap_8250_unthrottle;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
const struct of_device_id *id;
|
||||
|
||||
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
|
||||
of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
||||
&up.port.uartclk);
|
||||
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 {
|
||||
ret = pdev->id;
|
||||
}
|
||||
|
@ -1180,6 +1214,11 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||
|
||||
if (of_machine_is_compatible("ti,am33xx"))
|
||||
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
|
||||
|
@ -1257,17 +1296,46 @@ static int omap8250_lost_context(struct uart_8250_port *up)
|
|||
{
|
||||
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
|
||||
* UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x
|
||||
* or 16x but never to disable again.
|
||||
* If we lose context, then SCR is set to its reset value of zero.
|
||||
* After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1,
|
||||
* among other bits, to never set the register back to zero again.
|
||||
*/
|
||||
if (val == UART_OMAP_MDR1_DISABLE)
|
||||
if (!val)
|
||||
return 1;
|
||||
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)
|
||||
{
|
||||
struct omap8250_priv *priv = dev_get_drvdata(dev);
|
||||
|
@ -1285,7 +1353,18 @@ static int omap8250_runtime_suspend(struct device *dev)
|
|||
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);
|
||||
|
||||
priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
|
||||
|
@ -1310,7 +1389,7 @@ static int omap8250_runtime_resume(struct device *dev)
|
|||
if (loss_cntx)
|
||||
omap8250_restore_regs(up);
|
||||
|
||||
if (up->dma)
|
||||
if (up->dma && up->dma->rxchan)
|
||||
omap_8250_rx_dma(up, 0);
|
||||
|
||||
priv->latency = priv->calc_latency;
|
||||
|
@ -1367,14 +1446,6 @@ static const struct dev_pm_ops omap8250_dev_pm_ops = {
|
|||
.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 = {
|
||||
.driver = {
|
||||
.name = "omap8250",
|
||||
|
|
|
@ -1417,6 +1417,10 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
|
|||
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1685,11 +1689,65 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
|
|||
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,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
{
|
||||
struct pci_dev *pdev = priv->dev;
|
||||
u8 *data;
|
||||
u8 config_base;
|
||||
u16 iobase;
|
||||
|
||||
|
@ -1702,6 +1760,15 @@ static int pci_fintek_setup(struct serial_private *priv,
|
|||
|
||||
port->port.iotype = UPIO_PORT;
|
||||
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;
|
||||
}
|
||||
|
@ -1712,6 +1779,8 @@ static int pci_fintek_init(struct pci_dev *dev)
|
|||
u32 max_port, i;
|
||||
u32 bar_data[3];
|
||||
u8 config_base;
|
||||
struct serial_private *priv = pci_get_drvdata(dev);
|
||||
struct uart_8250_port *port;
|
||||
|
||||
switch (dev->device) {
|
||||
case 0x1104: /* 4 ports */
|
||||
|
@ -1752,6 +1821,19 @@ static int pci_fintek_init(struct pci_dev *dev)
|
|||
(u8)((iobase & 0xff00) >> 8));
|
||||
|
||||
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;
|
||||
|
@ -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_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 */
|
||||
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
|
||||
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
|
||||
|
@ -2331,27 +2419,12 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
|||
* Pericom
|
||||
*/
|
||||
{
|
||||
.vendor = 0x12d8,
|
||||
.device = 0x7952,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_pericom_setup,
|
||||
.vendor = PCI_VENDOR_ID_PERICOM,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.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
|
||||
*/
|
||||
|
@ -3056,6 +3129,10 @@ enum pci_board_num_t {
|
|||
pbn_fintek_8,
|
||||
pbn_fintek_12,
|
||||
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[] = {
|
|||
.base_baud = 115200,
|
||||
.first_offset = 0x40,
|
||||
},
|
||||
|
||||
[pbn_wch384_4] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 4,
|
||||
|
@ -3889,6 +3965,33 @@ static struct pciserial_board pci_boards[] = {
|
|||
.uart_offset = 8,
|
||||
.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[] = {
|
||||
|
@ -5153,6 +5256,25 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
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)
|
||||
*/
|
||||
|
|
|
@ -41,6 +41,12 @@ static const struct pnp_device_id pnp_dev_table[] = {
|
|||
{ "AEI1240", 0 },
|
||||
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
||||
{ "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 */
|
||||
{ "AZT4001", 0 },
|
||||
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
||||
|
@ -364,6 +370,11 @@ static const struct pnp_device_id pnp_dev_table[] = {
|
|||
/* Winbond CIR port, should not be probed. We should keep track
|
||||
of it to prevent the legacy serial driver from probing it */
|
||||
{ "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 }
|
||||
};
|
||||
|
||||
|
|
2912
drivers/tty/serial/8250/8250_port.c
Normal file
2912
drivers/tty/serial/8250/8250_port.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -218,6 +218,7 @@ static int uniphier_uart_probe(struct platform_device *pdev)
|
|||
ret = serial8250_register_8250_port(&up);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to register 8250 port\n");
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
# 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-$(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_PCI) += 8250_pci.o
|
||||
obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
|
||||
|
|
|
@ -47,12 +47,12 @@ config SERIAL_AMBA_PL010_CONSOLE
|
|||
|
||||
config SERIAL_AMBA_PL011
|
||||
tristate "ARM AMBA PL011 serial port support"
|
||||
depends on ARM_AMBA
|
||||
depends on ARM_AMBA || SOC_ZX296702
|
||||
select SERIAL_CORE
|
||||
help
|
||||
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
|
||||
here.
|
||||
here. Say Y or M if you have SOC_ZX296702.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
@ -594,7 +594,7 @@ config SERIAL_IMX_CONSOLE
|
|||
|
||||
config SERIAL_UARTLITE
|
||||
tristate "Xilinx uartlite serial port support"
|
||||
depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE || ARCH_ZYNQ
|
||||
depends on HAS_IOMEM
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Say Y here if you want to use the Xilinx uartlite serial controller.
|
||||
|
@ -1067,6 +1067,7 @@ config SERIAL_ETRAXFS
|
|||
bool "ETRAX FS serial port support"
|
||||
depends on ETRAX_ARCH_V32 && OF
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
|
||||
config SERIAL_ETRAXFS_CONSOLE
|
||||
bool "ETRAX FS serial console support"
|
||||
|
@ -1376,7 +1377,8 @@ config SERIAL_ALTERA_UART_CONSOLE
|
|||
|
||||
config SERIAL_IFX6X60
|
||||
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
|
||||
Support for the IFX6x60 modem devices on Intel MID platforms.
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -10,6 +10,8 @@
|
|||
#include <linux/of_address.h>
|
||||
#include <hwregs/ser_defs.h>
|
||||
|
||||
#include "serial_mctrl_gpio.h"
|
||||
|
||||
#define DRV_NAME "etraxfs-uart"
|
||||
#define UART_NR CONFIG_ETRAX_SERIAL_PORTS
|
||||
|
||||
|
@ -28,10 +30,7 @@ struct uart_cris_port {
|
|||
|
||||
void __iomem *regi_ser;
|
||||
|
||||
struct gpio_desc *dtr_pin;
|
||||
struct gpio_desc *dsr_pin;
|
||||
struct gpio_desc *ri_pin;
|
||||
struct gpio_desc *cd_pin;
|
||||
struct mctrl_gpios *gpios;
|
||||
|
||||
int write_ongoing;
|
||||
};
|
||||
|
@ -112,17 +111,10 @@ cris_console_setup(struct console *co, char *options)
|
|||
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 = {
|
||||
.name = "ttyS",
|
||||
.write = cris_console_write,
|
||||
.device = cris_console_device,
|
||||
.device = uart_console_device,
|
||||
.setup = cris_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
|
@ -373,14 +365,6 @@ static void etraxfs_uart_stop_rx(struct uart_port *port)
|
|||
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)
|
||||
{
|
||||
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)
|
|||
ret = 0;
|
||||
if (crisv32_serial_get_rts(up))
|
||||
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))
|
||||
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)
|
||||
|
@ -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;
|
||||
|
||||
crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0);
|
||||
/* DTR is active low */
|
||||
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);
|
||||
mctrl_gpio_set(up->gpios, mctrl);
|
||||
}
|
||||
|
||||
static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state)
|
||||
|
@ -598,7 +562,6 @@ ser_interrupt(int irq, void *dev_id)
|
|||
receive_chars_no_dma(up);
|
||||
handled = 1;
|
||||
}
|
||||
check_modem_status(up);
|
||||
|
||||
if (masked_intr.tr_rdy) {
|
||||
transmit_chars_no_dma(up);
|
||||
|
@ -862,7 +825,6 @@ static const struct uart_ops etraxfs_uart_pops = {
|
|||
.start_tx = etraxfs_uart_start_tx,
|
||||
.send_xchar = etraxfs_uart_send_xchar,
|
||||
.stop_rx = etraxfs_uart_stop_rx,
|
||||
.enable_ms = etraxfs_uart_enable_ms,
|
||||
.break_ctl = etraxfs_uart_break_ctl,
|
||||
.startup = etraxfs_uart_startup,
|
||||
.shutdown = etraxfs_uart_shutdown,
|
||||
|
@ -930,11 +892,12 @@ static int etraxfs_uart_probe(struct platform_device *pdev)
|
|||
|
||||
up->irq = irq_of_parse_and_map(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->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);
|
||||
|
||||
etraxfs_uart_ports[dev_id] = up;
|
||||
|
|
|
@ -216,6 +216,8 @@ struct imx_port {
|
|||
unsigned int tx_bytes;
|
||||
unsigned int dma_tx_nents;
|
||||
wait_queue_head_t dma_wait;
|
||||
unsigned int saved_reg[10];
|
||||
bool context_saved;
|
||||
};
|
||||
|
||||
struct imx_port_ucrs {
|
||||
|
@ -700,7 +702,8 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
|
|||
if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
|
||||
goto out;
|
||||
|
||||
tty_insert_flip_char(port, rx, flg);
|
||||
if (tty_insert_flip_char(port, rx, flg) == 0)
|
||||
sport->port.icount.buf_overrun++;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -766,7 +769,6 @@ static irqreturn_t imx_int(int irq, void *dev_id)
|
|||
writel(USR1_AWAKE, sport->port.membase + USR1);
|
||||
|
||||
if (sts2 & USR2_ORE) {
|
||||
dev_err(sport->port.dev, "Rx FIFO overrun\n");
|
||||
sport->port.icount.overrun++;
|
||||
writel(USR2_ORE, sport->port.membase + USR2);
|
||||
}
|
||||
|
@ -921,8 +923,13 @@ static void dma_rx_callback(void *data)
|
|||
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
|
||||
|
||||
if (count) {
|
||||
if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ))
|
||||
tty_insert_flip_string(port, sport->rx_buf, count);
|
||||
if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
|
||||
int bytes = tty_insert_flip_string(port, sport->rx_buf,
|
||||
count);
|
||||
|
||||
if (bytes != count)
|
||||
sport->port.icount.buf_overrun++;
|
||||
}
|
||||
tty_flip_buffer_push(port);
|
||||
|
||||
start_rx_dma(sport);
|
||||
|
@ -1624,12 +1631,12 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
|
|||
int locked = 1;
|
||||
int retval;
|
||||
|
||||
retval = clk_enable(sport->clk_per);
|
||||
retval = clk_prepare_enable(sport->clk_per);
|
||||
if (retval)
|
||||
return;
|
||||
retval = clk_enable(sport->clk_ipg);
|
||||
retval = clk_prepare_enable(sport->clk_ipg);
|
||||
if (retval) {
|
||||
clk_disable(sport->clk_per);
|
||||
clk_disable_unprepare(sport->clk_per);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1668,8 +1675,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
|
|||
if (locked)
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
|
||||
clk_disable(sport->clk_ipg);
|
||||
clk_disable(sport->clk_per);
|
||||
clk_disable_unprepare(sport->clk_ipg);
|
||||
clk_disable_unprepare(sport->clk_per);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1770,15 +1777,7 @@ imx_console_setup(struct console *co, char *options)
|
|||
|
||||
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
|
||||
|
||||
clk_disable(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);
|
||||
clk_disable_unprepare(sport->clk_ipg);
|
||||
|
||||
error_console:
|
||||
return retval;
|
||||
|
@ -1810,36 +1809,6 @@ static struct uart_driver imx_reg = {
|
|||
.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
|
||||
/*
|
||||
* 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)
|
|||
{
|
||||
struct imx_port *sport;
|
||||
void __iomem *base;
|
||||
int ret = 0;
|
||||
int ret = 0, reg;
|
||||
struct resource *res;
|
||||
int txirq, rxirq, rtsirq;
|
||||
|
||||
|
@ -1956,6 +1925,19 @@ static int serial_imx_probe(struct platform_device *pdev)
|
|||
|
||||
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
|
||||
* chips only have one interrupt.
|
||||
|
@ -1991,16 +1973,135 @@ static int serial_imx_remove(struct platform_device *pdev)
|
|||
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 = {
|
||||
.probe = serial_imx_probe,
|
||||
.remove = serial_imx_remove,
|
||||
|
||||
.suspend = serial_imx_suspend,
|
||||
.resume = serial_imx_resume,
|
||||
.id_table = imx_uart_devtype,
|
||||
.driver = {
|
||||
.name = "imx-uart",
|
||||
.of_match_table = imx_uart_dt_ids,
|
||||
.pm = &imx_serial_port_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
|
@ -740,7 +739,6 @@ static const struct of_device_id ltq_asc_match[] = {
|
|||
{ .compatible = DRVNAME },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ltq_asc_match);
|
||||
|
||||
static struct platform_driver lqasc_driver = {
|
||||
.driver = {
|
||||
|
@ -764,8 +762,4 @@ init_lqasc(void)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
module_init(init_lqasc);
|
||||
|
||||
MODULE_DESCRIPTION("Lantiq serial port driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
device_initcall(init_lqasc);
|
||||
|
|
|
@ -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 uart_port *port = &uart->port;
|
||||
bool handled = false;
|
||||
unsigned long flags;
|
||||
int irq_id;
|
||||
|
||||
uart->stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
|
||||
|
@ -401,7 +400,7 @@ static irqreturn_t men_z135_intr(int irq, void *data)
|
|||
if (!irq_id)
|
||||
goto out;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
spin_lock(&port->lock);
|
||||
/* It's save to write to IIR[7:6] RXC[9:8] */
|
||||
iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG);
|
||||
|
||||
|
@ -427,7 +426,7 @@ static irqreturn_t men_z135_intr(int irq, void *data)
|
|||
handled = true;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
spin_unlock(&port->lock);
|
||||
out:
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
spin_lock(&port->lock);
|
||||
spin_lock_irq(&port->lock);
|
||||
if (tty_termios_baud_rate(termios))
|
||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
|
||||
|
@ -725,7 +724,7 @@ static void men_z135_set_termios(struct uart_port *port,
|
|||
iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG);
|
||||
|
||||
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)
|
||||
|
@ -840,7 +839,6 @@ static int men_z135_probe(struct mcb_device *mdev,
|
|||
uart->port.membase = NULL;
|
||||
uart->mdev = mdev;
|
||||
|
||||
spin_lock_init(&uart->port.lock);
|
||||
spin_lock_init(&uart->lock);
|
||||
|
||||
err = uart_add_one_port(&men_z135_driver, &uart->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)
|
||||
{
|
||||
return in_be16(&PSC(port)->mpc52xx_psc_status)
|
||||
& MPC52xx_PSC_SR_TXEMP;
|
||||
u16 sts = in_be16(&PSC(port)->mpc52xx_psc_status);
|
||||
|
||||
return (sts & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
static void mpc52xx_psc_start_tx(struct uart_port *port)
|
||||
|
|
|
@ -100,6 +100,8 @@
|
|||
#define AUART_CTRL2_TXE (1 << 8)
|
||||
#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_MASK 0xffff0000
|
||||
#define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
|
||||
|
@ -659,7 +661,7 @@ static void mxs_auart_settermios(struct uart_port *u,
|
|||
{
|
||||
struct mxs_auart_port *s = to_auart_port(u);
|
||||
u32 bm, ctrl, ctrl2, div;
|
||||
unsigned int cflag, baud;
|
||||
unsigned int cflag, baud, baud_min, baud_max;
|
||||
|
||||
cflag = termios->c_cflag;
|
||||
|
||||
|
@ -752,7 +754,9 @@ static void mxs_auart_settermios(struct uart_port *u,
|
|||
}
|
||||
|
||||
/* 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;
|
||||
ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
|
||||
ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
|
||||
|
@ -842,7 +846,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mxs_auart_reset(struct uart_port *u)
|
||||
static void mxs_auart_reset_deassert(struct uart_port *u)
|
||||
{
|
||||
int i;
|
||||
unsigned int reg;
|
||||
|
@ -858,6 +862,30 @@ static void mxs_auart_reset(struct uart_port *u)
|
|||
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)
|
||||
{
|
||||
int ret;
|
||||
|
@ -867,7 +895,13 @@ static int mxs_auart_startup(struct uart_port *u)
|
|||
if (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);
|
||||
|
||||
|
@ -899,12 +933,14 @@ static void mxs_auart_shutdown(struct uart_port *u)
|
|||
if (auart_dma_enabled(s))
|
||||
mxs_auart_dma_exit(s);
|
||||
|
||||
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
|
||||
|
||||
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
|
||||
u->membase + AUART_INTR_CLR);
|
||||
|
||||
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
|
||||
if (uart_console(u)) {
|
||||
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
|
||||
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
|
||||
u->membase + AUART_INTR_CLR);
|
||||
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
|
||||
} else {
|
||||
mxs_auart_reset_assert(u);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(s->clk);
|
||||
}
|
||||
|
@ -1291,7 +1327,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
|
|||
|
||||
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);
|
||||
if (ret)
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
#include "samsung.h"
|
||||
|
||||
#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
|
||||
defined(CONFIG_DEBUG_LL) && \
|
||||
!defined(MODULE)
|
||||
|
||||
extern void printascii(const char *);
|
||||
|
@ -295,15 +294,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
|
|||
if (ourport->tx_mode != S3C24XX_TX_DMA)
|
||||
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_transfer_addr = dma->tx_addr + xmit->tail;
|
||||
|
||||
|
@ -342,7 +332,9 @@ static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
|
|||
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);
|
||||
else
|
||||
s3c24xx_serial_start_tx_dma(ourport, count);
|
||||
|
@ -736,15 +728,20 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
|||
struct uart_port *port = &ourport->port;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
unsigned long flags;
|
||||
int count;
|
||||
int count, dma_count = 0;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
|
||||
if (ourport->dma && ourport->dma->tx_chan && count >= port->fifosize) {
|
||||
s3c24xx_serial_start_tx_dma(ourport, count);
|
||||
goto out;
|
||||
if (ourport->dma && ourport->dma->tx_chan &&
|
||||
count >= ourport->min_dma_size) {
|
||||
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) {
|
||||
|
@ -765,14 +762,24 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
|||
|
||||
/* try and drain the buffer... */
|
||||
|
||||
count = port->fifosize;
|
||||
while (!uart_circ_empty(xmit) && count-- > 0) {
|
||||
if (count > port->fifosize) {
|
||||
count = port->fifosize;
|
||||
dma_count = 0;
|
||||
}
|
||||
|
||||
while (!uart_circ_empty(xmit) && count > 0) {
|
||||
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
|
||||
break;
|
||||
|
||||
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
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) {
|
||||
|
@ -1838,6 +1845,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
|||
else if (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++;
|
||||
|
||||
dbg("%s: initialising port %p...\n", __func__, ourport);
|
||||
|
|
|
@ -82,6 +82,7 @@ struct s3c24xx_uart_port {
|
|||
unsigned char tx_claimed;
|
||||
unsigned int pm_level;
|
||||
unsigned long baudclk_rate;
|
||||
unsigned int min_dma_size;
|
||||
|
||||
unsigned int rx_irq;
|
||||
unsigned int tx_irq;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -29,6 +31,7 @@
|
|||
#include <linux/uaccess.h>
|
||||
|
||||
#define SC16IS7XX_NAME "sc16is7xx"
|
||||
#define SC16IS7XX_MAX_DEVS 8
|
||||
|
||||
/* SC16IS7XX register definitions */
|
||||
#define SC16IS7XX_RHR_REG (0x00) /* RX FIFO */
|
||||
|
@ -312,14 +315,14 @@ struct sc16is7xx_one_config {
|
|||
|
||||
struct sc16is7xx_one {
|
||||
struct uart_port port;
|
||||
u8 line;
|
||||
struct kthread_work tx_work;
|
||||
struct kthread_work reg_work;
|
||||
struct sc16is7xx_one_config config;
|
||||
};
|
||||
|
||||
struct sc16is7xx_port {
|
||||
struct uart_driver uart;
|
||||
struct sc16is7xx_devtype *devtype;
|
||||
const struct sc16is7xx_devtype *devtype;
|
||||
struct regmap *regmap;
|
||||
struct clk *clk;
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
|
@ -332,16 +335,31 @@ struct sc16is7xx_port {
|
|||
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_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)
|
||||
{
|
||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||
unsigned int val = 0;
|
||||
const u8 line = sc16is7xx_line(port);
|
||||
|
||||
regmap_read(s->regmap,
|
||||
(reg << SC16IS7XX_REG_SHIFT) | port->line, &val);
|
||||
regmap_read(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||
const u8 line = sc16is7xx_line(port);
|
||||
|
||||
regmap_write(s->regmap,
|
||||
(reg << SC16IS7XX_REG_SHIFT) | port->line, val);
|
||||
regmap_write(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, val);
|
||||
}
|
||||
|
||||
static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
|
||||
{
|
||||
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);
|
||||
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)
|
|||
static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
|
||||
{
|
||||
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);
|
||||
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,
|
|||
u8 mask, u8 val)
|
||||
{
|
||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||
const u8 line = sc16is7xx_line(port);
|
||||
|
||||
regmap_update_bits(s->regmap,
|
||||
(reg << SC16IS7XX_REG_SHIFT) | port->line,
|
||||
regmap_update_bits(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line,
|
||||
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)
|
||||
{
|
||||
|
@ -508,7 +540,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
|
|||
|
||||
if (unlikely(rxlen >= sizeof(s->buf))) {
|
||||
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->icount.buf_overrun++;
|
||||
/* Ensure sanity of RX level */
|
||||
|
@ -649,7 +681,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
|
|||
break;
|
||||
default:
|
||||
dev_err_ratelimited(port->dev,
|
||||
"Port %i: Unexpected interrupt: %x",
|
||||
"ttySC%i: Unexpected interrupt: %x",
|
||||
port->line, iir);
|
||||
break;
|
||||
}
|
||||
|
@ -661,7 +693,7 @@ static void sc16is7xx_ist(struct kthread_work *ws)
|
|||
struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->uart.nr; ++i)
|
||||
for (i = 0; i < s->devtype->nr_uart; ++i)
|
||||
sc16is7xx_port_irq(s, i);
|
||||
}
|
||||
|
||||
|
@ -1099,7 +1131,7 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
|
|||
#endif
|
||||
|
||||
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 sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
|
||||
|
@ -1134,23 +1166,13 @@ static int sc16is7xx_probe(struct device *dev,
|
|||
s->devtype = devtype;
|
||||
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_work(&s->irq_work, sc16is7xx_ist);
|
||||
s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
|
||||
"sc16is7xx");
|
||||
if (IS_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);
|
||||
|
||||
|
@ -1174,8 +1196,8 @@ static int sc16is7xx_probe(struct device *dev,
|
|||
#endif
|
||||
|
||||
for (i = 0; i < devtype->nr_uart; ++i) {
|
||||
s->p[i].line = i;
|
||||
/* Initialize port data */
|
||||
s->p[i].port.line = i;
|
||||
s->p[i].port.dev = dev;
|
||||
s->p[i].port.irq = irq;
|
||||
s->p[i].port.type = PORT_SC16IS7XX;
|
||||
|
@ -1185,6 +1207,12 @@ static int sc16is7xx_probe(struct device *dev,
|
|||
s->p[i].port.uartclk = freq;
|
||||
s->p[i].port.rs485_config = sc16is7xx_config_rs485;
|
||||
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 */
|
||||
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0);
|
||||
/* Disable TX/RX */
|
||||
|
@ -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].reg_work, sc16is7xx_reg_proc);
|
||||
/* 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 */
|
||||
sc16is7xx_power(&s->p[i].port, 0);
|
||||
}
|
||||
|
@ -1206,8 +1234,11 @@ static int sc16is7xx_probe(struct device *dev,
|
|||
if (!ret)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < s->uart.nr; i++)
|
||||
uart_remove_one_port(&s->uart, &s->p[i].port);
|
||||
out_ports:
|
||||
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
|
||||
if (devtype->nr_gpio)
|
||||
|
@ -1217,9 +1248,6 @@ static int sc16is7xx_probe(struct device *dev,
|
|||
#endif
|
||||
kthread_stop(s->kworker_task);
|
||||
|
||||
out_uart:
|
||||
uart_unregister_driver(&s->uart);
|
||||
|
||||
out_clk:
|
||||
if (!IS_ERR(s->clk))
|
||||
clk_disable_unprepare(s->clk);
|
||||
|
@ -1237,15 +1265,15 @@ static int sc16is7xx_remove(struct device *dev)
|
|||
gpiochip_remove(&s->gpio);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < s->uart.nr; i++) {
|
||||
uart_remove_one_port(&s->uart, &s->p[i].port);
|
||||
for (i = 0; i < s->devtype->nr_uart; i++) {
|
||||
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);
|
||||
}
|
||||
|
||||
flush_kthread_worker(&s->kworker);
|
||||
kthread_stop(s->kworker_task);
|
||||
|
||||
uart_unregister_driver(&s->uart);
|
||||
if (!IS_ERR(s->clk))
|
||||
clk_disable_unprepare(s->clk);
|
||||
|
||||
|
@ -1275,7 +1303,7 @@ static struct regmap_config regcfg = {
|
|||
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
|
||||
static int sc16is7xx_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct sc16is7xx_devtype *devtype;
|
||||
const struct sc16is7xx_devtype *devtype;
|
||||
unsigned long flags = 0;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
@ -1344,7 +1372,7 @@ MODULE_ALIAS("spi:sc16is7xx");
|
|||
static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct sc16is7xx_devtype *devtype;
|
||||
const struct sc16is7xx_devtype *devtype;
|
||||
unsigned long flags = 0;
|
||||
struct regmap *regmap;
|
||||
|
||||
|
@ -1385,7 +1413,6 @@ MODULE_DEVICE_TABLE(i2c, sc16is7xx_i2c_id_table);
|
|||
static struct i2c_driver sc16is7xx_i2c_uart_driver = {
|
||||
.driver = {
|
||||
.name = SC16IS7XX_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(sc16is7xx_dt_ids),
|
||||
},
|
||||
.probe = sc16is7xx_i2c_probe,
|
||||
|
@ -1398,7 +1425,14 @@ MODULE_ALIAS("i2c:sc16is7xx");
|
|||
|
||||
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
|
||||
ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver);
|
||||
if (ret < 0) {
|
||||
|
@ -1427,6 +1461,7 @@ static void __exit sc16is7xx_exit(void)
|
|||
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
|
||||
spi_unregister_driver(&sc16is7xx_spi_uart_driver);
|
||||
#endif
|
||||
uart_unregister_driver(&sc16is7xx_uart);
|
||||
}
|
||||
module_exit(sc16is7xx_exit);
|
||||
|
||||
|
|
|
@ -1377,7 +1377,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|||
struct uart_state *state = tty->driver_data;
|
||||
struct tty_port *port;
|
||||
struct uart_port *uport;
|
||||
unsigned long flags;
|
||||
|
||||
if (!state) {
|
||||
struct uart_driver *drv = tty->driver->driver_state;
|
||||
|
@ -1403,10 +1402,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|||
* disable the receive line status interrupts.
|
||||
*/
|
||||
if (port->flags & ASYNC_INITIALIZED) {
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&uport->lock, flags);
|
||||
spin_lock_irq(&uport->lock);
|
||||
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
|
||||
* has completely drained; this is especially
|
||||
|
@ -1419,17 +1417,17 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|||
uart_shutdown(tty, state);
|
||||
tty_port_tty_set(port, NULL);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
spin_lock_irq(&port->lock);
|
||||
|
||||
if (port->blocked_open) {
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
spin_unlock_irq(&port->lock);
|
||||
if (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)) {
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
spin_unlock_irq(&port->lock);
|
||||
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)
|
|||
*/
|
||||
clear_bit(ASYNCB_NORMAL_ACTIVE, &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->close_wait);
|
||||
|
||||
|
@ -1532,11 +1530,6 @@ static void uart_hangup(struct tty_struct *tty)
|
|||
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)
|
||||
{
|
||||
struct uart_state *state = container_of(port, struct uart_state, port);
|
||||
|
@ -2379,8 +2372,6 @@ static const struct tty_operations uart_ops = {
|
|||
};
|
||||
|
||||
static const struct tty_port_operations uart_port_ops = {
|
||||
.activate = uart_port_activate,
|
||||
.shutdown = uart_port_shutdown,
|
||||
.carrier_raised = uart_carrier_raised,
|
||||
.dtr_rts = uart_dtr_rts,
|
||||
};
|
||||
|
|
|
@ -413,7 +413,6 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count)
|
|||
break;
|
||||
}
|
||||
|
||||
sirfport->rx_io_count += rx_count;
|
||||
port->icount.rx += rx_count;
|
||||
|
||||
return rx_count;
|
||||
|
@ -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_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_dma_io_ctrl,
|
||||
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
|
||||
~SIRFUART_IO_MODE);
|
||||
|
@ -632,31 +630,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port)
|
|||
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
|
||||
sirfsoc_usp_calc_sample_div(unsigned long set_rate,
|
||||
unsigned long ioclk_rate, unsigned long *sample_reg)
|
||||
|
@ -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 = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out);
|
||||
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,
|
||||
(txfifo_op_reg & ~SIRFUART_FIFO_START));
|
||||
if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
|
||||
|
@ -886,9 +858,13 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
|
|||
else
|
||||
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
|
||||
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
|
||||
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;
|
||||
/* Reset Rx/Tx FIFO Threshold level for proper baudrate */
|
||||
if (set_baud < 1000000)
|
||||
|
@ -902,7 +878,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
|
|||
txfifo_op_reg |= SIRFUART_FIFO_START;
|
||||
wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg);
|
||||
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);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
@ -921,6 +896,7 @@ static int sirfsoc_uart_startup(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;
|
||||
unsigned int index = port->line;
|
||||
int ret;
|
||||
irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN);
|
||||
|
@ -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));
|
||||
if (sirfport->rx_dma_chan)
|
||||
wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk,
|
||||
SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) |
|
||||
SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
|
||||
SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
|
||||
SIRFUART_RX_FIFO_CHK_SC(port->line, 0x1) |
|
||||
SIRFUART_RX_FIFO_CHK_LC(port->line, 0x2) |
|
||||
SIRFUART_RX_FIFO_CHK_HC(port->line, 0x4));
|
||||
if (sirfport->tx_dma_chan) {
|
||||
sirfport->tx_dma_state = TX_DMA_IDLE;
|
||||
wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk,
|
||||
|
@ -981,16 +957,41 @@ static int sirfsoc_uart_startup(struct uart_port *port)
|
|||
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) {
|
||||
sirfport->is_hrt_enabled = true;
|
||||
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.head = 0;
|
||||
hrtimer_start(&sirfport->hrt,
|
||||
ns_to_ktime(sirfport->rx_period_time),
|
||||
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;
|
||||
init_rx_err:
|
||||
|
@ -1003,6 +1004,9 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
|
|||
{
|
||||
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
||||
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
|
||||
struct circ_buf *xmit;
|
||||
|
||||
xmit = &sirfport->rx_dma_items.xmit;
|
||||
if (!sirfport->is_atlas7)
|
||||
wr_regl(port, ureg->sirfsoc_int_en_reg, 0);
|
||||
else
|
||||
|
@ -1019,8 +1023,10 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
|
|||
if (sirfport->tx_dma_chan)
|
||||
sirfport->tx_dma_state = TX_DMA_IDLE;
|
||||
if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) {
|
||||
while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
||||
SIRFUART_RX_FIFO_MASK) > 0)
|
||||
while (((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
||||
SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt) &&
|
||||
!CIRC_CNT(xmit->head, xmit->tail,
|
||||
SIRFSOC_RX_DMA_BUF_SIZE))
|
||||
;
|
||||
sirfport->is_hrt_enabled = false;
|
||||
hrtimer_cancel(&sirfport->hrt);
|
||||
|
@ -1169,6 +1175,8 @@ static enum hrtimer_restart
|
|||
struct tty_struct *tty;
|
||||
struct sirfsoc_register *ureg;
|
||||
struct circ_buf *xmit;
|
||||
struct sirfsoc_fifo_status *ufifo_st;
|
||||
int max_pio_cnt;
|
||||
|
||||
sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt);
|
||||
port = &sirfport->port;
|
||||
|
@ -1176,9 +1184,16 @@ static enum hrtimer_restart
|
|||
tty = port->state->port.tty;
|
||||
ureg = &sirfport->uart_reg->uart_reg;
|
||||
xmit = &sirfport->rx_dma_items.xmit;
|
||||
ufifo_st = &sirfport->uart_reg->fifo_status;
|
||||
|
||||
dmaengine_tx_status(sirfport->rx_dma_chan,
|
||||
sirfport->rx_dma_items.cookie, &tx_state);
|
||||
xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
|
||||
sirfport->rx_dma_items.cookie, &tx_state);
|
||||
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,
|
||||
SIRFSOC_RX_DMA_BUF_SIZE);
|
||||
while (count > 0) {
|
||||
|
@ -1200,23 +1215,38 @@ static enum hrtimer_restart
|
|||
*/
|
||||
if (!inserted && !count &&
|
||||
((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 */
|
||||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
|
||||
SIRFUART_IO_MODE);
|
||||
while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
||||
SIRFUART_RX_FIFO_MASK) > 0) {
|
||||
if (sirfsoc_uart_pio_rx_chars(port, 16) > 0)
|
||||
tty_flip_buffer_push(tty->port);
|
||||
/*
|
||||
* UART controller SWH_DMA_IO register have CLEAR_RX_ADDR_EN
|
||||
* When found changing I/O to DMA mode, it clears
|
||||
* 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 */
|
||||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
|
||||
~SIRFUART_IO_MODE);
|
||||
dmaengine_resume(sirfport->rx_dma_chan);
|
||||
}
|
||||
next_hrt:
|
||||
hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time));
|
||||
|
@ -1239,7 +1269,7 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
int ret;
|
||||
struct dma_slave_config slv_cfg = {
|
||||
.src_maxburst = 2,
|
||||
.src_maxburst = 1,
|
||||
};
|
||||
struct dma_slave_config tx_slv_cfg = {
|
||||
.dst_maxburst = 2,
|
||||
|
|
|
@ -296,6 +296,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
|
|||
#define SIRFUART_DMA_MODE 0x0
|
||||
#define SIRFUART_RX_DMA_FLUSH 0x4
|
||||
|
||||
#define SIRFUART_CLEAR_RX_ADDR_EN 0x2
|
||||
/* Baud Rate Calculation */
|
||||
#define SIRF_USP_MIN_SAMPLE_DIV 0x1
|
||||
#define SIRF_MIN_SAMPLE_DIV 0xf
|
||||
|
@ -325,6 +326,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
|
|||
#define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f
|
||||
#define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16
|
||||
#define SIRFSOC_USP_LOOP_BACK_CTRL BIT(2)
|
||||
#define SIRFSOC_USP_FRADDR_CLR_EN BIT(1)
|
||||
/* USP-UART Common */
|
||||
#define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000)
|
||||
#define SIRFUART_RECV_TIMEOUT_VALUE(x) \
|
||||
|
@ -421,7 +423,6 @@ struct sirfsoc_uart_port {
|
|||
struct dma_chan *tx_dma_chan;
|
||||
dma_addr_t tx_dma_addr;
|
||||
struct dma_async_tx_descriptor *tx_dma_desc;
|
||||
unsigned int rx_io_count;
|
||||
unsigned long transfer_size;
|
||||
enum sirfsoc_tx_state tx_dma_state;
|
||||
unsigned int cts_gpio;
|
||||
|
@ -431,6 +432,8 @@ struct sirfsoc_uart_port {
|
|||
struct hrtimer hrt;
|
||||
bool is_hrt_enabled;
|
||||
unsigned long rx_period_time;
|
||||
unsigned long rx_last_pos;
|
||||
unsigned long pio_fetch_cnt;
|
||||
};
|
||||
|
||||
/* Register Access Control */
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/serial_reg.h>
|
||||
|
@ -659,7 +659,7 @@ static void sn_sal_timer_poll(unsigned long data)
|
|||
* @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
|
||||
* 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
|
||||
* 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)
|
|||
* sn_sal_switch_to_interrupts - Switch to interrupt driven mode
|
||||
* @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
|
||||
* mode. We were previously in asynch/polling mode (using init_timer).
|
||||
*
|
||||
|
@ -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
|
||||
* early mode not making use of the serial core infrastructure. When our
|
||||
|
@ -781,7 +781,7 @@ static struct uart_driver sal_console_uart = {
|
|||
* 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;
|
||||
|
||||
|
@ -811,7 +811,7 @@ static int __init sn_sal_module_init(void)
|
|||
|
||||
if (uart_register_driver(&sal_console_uart) < 0) {
|
||||
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__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -832,33 +832,19 @@ static int __init sn_sal_module_init(void)
|
|||
|
||||
/* when this driver is compiled in, the console initialization
|
||||
* 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) {
|
||||
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()) {
|
||||
sn_sal_switch_to_interrupts(&sal_console_port);
|
||||
}
|
||||
sn_process_input = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
device_initcall(sn_sal_init);
|
||||
|
||||
/**
|
||||
* puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* 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
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
|
@ -234,14 +233,10 @@ static int __init suncore_init(void)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
device_initcall(suncore_init);
|
||||
|
||||
static void __exit suncore_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(suncore_init);
|
||||
module_exit(suncore_exit);
|
||||
|
||||
#if 0 /* ..def MODULE ; never supported as such */
|
||||
MODULE_AUTHOR("Eddie C. Dost, David S. Miller");
|
||||
MODULE_DESCRIPTION("Sun serial common layer");
|
||||
MODULE_LICENSE("GPL");
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/tty.h>
|
||||
|
@ -621,7 +620,6 @@ static const struct of_device_id hv_match[] = {
|
|||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, hv_match);
|
||||
|
||||
static struct platform_driver hv_driver = {
|
||||
.driver = {
|
||||
|
@ -639,16 +637,11 @@ static int __init sunhv_init(void)
|
|||
|
||||
return platform_driver_register(&hv_driver);
|
||||
}
|
||||
device_initcall(sunhv_init);
|
||||
|
||||
static void __exit sunhv_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&hv_driver);
|
||||
}
|
||||
|
||||
module_init(sunhv_init);
|
||||
module_exit(sunhv_exit);
|
||||
|
||||
#if 0 /* ...def MODULE ; never supported as such */
|
||||
MODULE_AUTHOR("David S. Miller");
|
||||
MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
|
||||
MODULE_VERSION("2.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
#endif
|
||||
|
|
|
@ -950,7 +950,7 @@ static void qe_uart_set_termios(struct uart_port *port,
|
|||
if ((termios->c_cflag & CREAD) == 0)
|
||||
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? */
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
|
|
@ -291,12 +291,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
|
|||
n->flags = flags;
|
||||
buf->tail = n;
|
||||
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
|
||||
* advanced to the next buffer
|
||||
*/
|
||||
smp_wmb();
|
||||
b->next = n;
|
||||
smp_store_release(&b->next, n);
|
||||
} else if (change)
|
||||
size = 0;
|
||||
else
|
||||
|
@ -445,7 +444,6 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count)
|
|||
if (count)
|
||||
disc->ops->receive_buf(tty, p, f, count);
|
||||
}
|
||||
head->read += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -488,12 +486,11 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||
if (atomic_read(&buf->priority))
|
||||
break;
|
||||
|
||||
next = head->next;
|
||||
/* paired w/ barrier in __tty_buffer_request_room();
|
||||
/* paired w/ release in __tty_buffer_request_room();
|
||||
* ensures commit value read is not stale if the head
|
||||
* is advancing to the next buffer
|
||||
*/
|
||||
smp_rmb();
|
||||
next = smp_load_acquire(&head->next);
|
||||
count = head->commit - head->read;
|
||||
if (!count) {
|
||||
if (next == NULL) {
|
||||
|
@ -508,6 +505,7 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||
count = receive_buf(tty, head, count);
|
||||
if (!count)
|
||||
break;
|
||||
head->read += count;
|
||||
}
|
||||
|
||||
mutex_unlock(&buf->lock);
|
||||
|
|
|
@ -106,6 +106,11 @@
|
|||
#include <linux/nsproxy.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
|
||||
|
||||
#define TTY_PARANOIA_CHECK 1
|
||||
#define CHECK_TTY_COUNT 1
|
||||
|
@ -388,33 +393,40 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
|
|||
int tty_check_change(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct pid *pgrp;
|
||||
int ret = 0;
|
||||
|
||||
if (current->signal->tty != tty)
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
pgrp = task_pgrp(current);
|
||||
|
||||
spin_lock_irqsave(&tty->ctrl_lock, flags);
|
||||
|
||||
if (!tty->pgrp) {
|
||||
printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
if (task_pgrp(current) == tty->pgrp)
|
||||
if (pgrp == tty->pgrp)
|
||||
goto out_unlock;
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
|
||||
if (is_ignored(SIGTTOU))
|
||||
goto out;
|
||||
goto out_rcuunlock;
|
||||
if (is_current_pgrp_orphaned()) {
|
||||
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);
|
||||
ret = -ERESTARTSYS;
|
||||
out:
|
||||
return ret;
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
out_rcuunlock:
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -524,7 +536,8 @@ static void __proc_set_tty(struct tty_struct *tty)
|
|||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
tty->session = get_pid(task_session(current));
|
||||
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);
|
||||
}
|
||||
put_pid(current->signal->tty_old_pgrp);
|
||||
|
@ -766,9 +779,7 @@ static void do_tty_hangup(struct work_struct *work)
|
|||
|
||||
void tty_hangup(struct tty_struct *tty)
|
||||
{
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "%s hangup...\n", tty_name(tty));
|
||||
#endif
|
||||
tty_debug_hangup(tty, "\n");
|
||||
schedule_work(&tty->hangup_work);
|
||||
}
|
||||
|
||||
|
@ -785,9 +796,7 @@ EXPORT_SYMBOL(tty_hangup);
|
|||
|
||||
void tty_vhangup(struct tty_struct *tty)
|
||||
{
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty));
|
||||
#endif
|
||||
tty_debug_hangup(tty, "\n");
|
||||
__tty_hangup(tty, 0);
|
||||
}
|
||||
|
||||
|
@ -824,9 +833,7 @@ void tty_vhangup_self(void)
|
|||
|
||||
static void tty_vhangup_session(struct tty_struct *tty)
|
||||
{
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty));
|
||||
#endif
|
||||
tty_debug_hangup(tty, "\n");
|
||||
__tty_hangup(tty, 1);
|
||||
}
|
||||
|
||||
|
@ -920,12 +927,8 @@ void disassociate_ctty(int on_exit)
|
|||
tty->pgrp = NULL;
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
tty_kref_put(tty);
|
||||
} else {
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
|
||||
" = NULL", tty);
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
tty_debug_hangup(tty, "no current tty\n");
|
||||
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
/* Now clear signal->tty under the lock */
|
||||
|
@ -1705,8 +1708,7 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
|
|||
{
|
||||
#ifdef TTY_PARANOIA_CHECK
|
||||
if (idx < 0 || idx >= tty->driver->num) {
|
||||
printk(KERN_DEBUG "%s: bad idx when trying to free (%s)\n",
|
||||
__func__, tty->name);
|
||||
tty_debug(tty, "bad idx %d\n", idx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1715,20 +1717,20 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
|
|||
return 0;
|
||||
|
||||
if (tty != tty->driver->ttys[idx]) {
|
||||
printk(KERN_DEBUG "%s: driver.table[%d] not tty for (%s)\n",
|
||||
__func__, idx, tty->name);
|
||||
tty_debug(tty, "bad driver table[%d] = %p\n",
|
||||
idx, tty->driver->ttys[idx]);
|
||||
return -1;
|
||||
}
|
||||
if (tty->driver->other) {
|
||||
struct tty_struct *o_tty = tty->link;
|
||||
|
||||
if (o_tty != tty->driver->other->ttys[idx]) {
|
||||
printk(KERN_DEBUG "%s: other->table[%d] not o_tty for (%s)\n",
|
||||
__func__, idx, tty->name);
|
||||
tty_debug(tty, "bad other table[%d] = %p\n",
|
||||
idx, tty->driver->other->ttys[idx]);
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1782,10 +1784,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "%s: %s (tty count=%d)...\n", __func__,
|
||||
tty_name(tty), tty->count);
|
||||
#endif
|
||||
tty_debug_hangup(tty, "(tty count=%d)...\n", tty->count);
|
||||
|
||||
if (tty->ops->close)
|
||||
tty->ops->close(tty, filp);
|
||||
|
@ -1895,9 +1894,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
|||
if (!final)
|
||||
return 0;
|
||||
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty));
|
||||
#endif
|
||||
tty_debug_hangup(tty, "final close\n");
|
||||
/*
|
||||
* Ask the line discipline code to release its structures
|
||||
*/
|
||||
|
@ -1906,10 +1903,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
|||
/* Wait for pending work before tty destruction commmences */
|
||||
tty_flush_works(tty);
|
||||
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__,
|
||||
tty_name(tty));
|
||||
#endif
|
||||
tty_debug_hangup(tty, "freeing structure...\n");
|
||||
/*
|
||||
* The release_tty function takes care of the details of clearing
|
||||
* 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)
|
|||
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
||||
tty->driver->subtype == PTY_TYPE_MASTER)
|
||||
noctty = 1;
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "%s: opening %s...\n", __func__, tty->name);
|
||||
#endif
|
||||
|
||||
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
|
||||
|
||||
if (tty->ops->open)
|
||||
retval = tty->ops->open(tty, filp);
|
||||
else
|
||||
|
@ -2108,10 +2102,8 @@ static int tty_open(struct inode *inode, struct file *filp)
|
|||
filp->f_flags = saved_flags;
|
||||
|
||||
if (retval) {
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
|
||||
retval, tty->name);
|
||||
#endif
|
||||
tty_debug_hangup(tty, "error %d, releasing...\n", retval);
|
||||
|
||||
tty_unlock(tty); /* need to call tty_release without BTM */
|
||||
tty_release(inode, filp);
|
||||
if (retval != -ERESTARTSYS)
|
||||
|
@ -3160,9 +3152,12 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
|
|||
unsigned int index, unsigned int count)
|
||||
{
|
||||
/* init here, since reused cdevs cause crashes */
|
||||
cdev_init(&driver->cdevs[index], &tty_fops);
|
||||
driver->cdevs[index].owner = driver->owner;
|
||||
return cdev_add(&driver->cdevs[index], dev, count);
|
||||
driver->cdevs[index] = cdev_alloc();
|
||||
if (!driver->cdevs[index])
|
||||
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,
|
|||
|
||||
error:
|
||||
put_device(dev);
|
||||
if (cdev)
|
||||
cdev_del(&driver->cdevs[index]);
|
||||
if (cdev) {
|
||||
cdev_del(driver->cdevs[index]);
|
||||
driver->cdevs[index] = NULL;
|
||||
}
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_register_device_attr);
|
||||
|
@ -3289,8 +3286,10 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
|
|||
{
|
||||
device_destroy(tty_class,
|
||||
MKDEV(driver->major, driver->minor_start) + index);
|
||||
if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC))
|
||||
cdev_del(&driver->cdevs[index]);
|
||||
if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
|
||||
cdev_del(driver->cdevs[index]);
|
||||
driver->cdevs[index] = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(tty_unregister_device);
|
||||
|
||||
|
@ -3355,6 +3354,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
|
|||
kfree(driver->ports);
|
||||
kfree(driver->ttys);
|
||||
kfree(driver->termios);
|
||||
kfree(driver->cdevs);
|
||||
kfree(driver);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
@ -3383,7 +3383,7 @@ static void destruct_tty_driver(struct kref *kref)
|
|||
}
|
||||
proc_tty_unregister_driver(driver);
|
||||
if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)
|
||||
cdev_del(&driver->cdevs[0]);
|
||||
cdev_del(driver->cdevs[0]);
|
||||
}
|
||||
kfree(driver->cdevs);
|
||||
kfree(driver->ports);
|
||||
|
|
|
@ -26,6 +26,12 @@
|
|||
|
||||
#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
|
||||
|
||||
/*
|
||||
|
@ -210,9 +216,8 @@ int tty_unthrottle_safe(struct tty_struct *tty)
|
|||
|
||||
void tty_wait_until_sent(struct tty_struct *tty, long timeout)
|
||||
{
|
||||
#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
|
||||
printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty));
|
||||
#endif
|
||||
tty_debug_wait_until_sent(tty, "\n");
|
||||
|
||||
if (!timeout)
|
||||
timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
#undef LDISC_DEBUG_HANGUP
|
||||
|
||||
#ifdef LDISC_DEBUG_HANGUP
|
||||
#define tty_ldisc_debug(tty, f, args...) ({ \
|
||||
printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty), ##args); \
|
||||
})
|
||||
#define tty_ldisc_debug(tty, f, args...) tty_debug(tty, f, ##args)
|
||||
#else
|
||||
#define tty_ldisc_debug(tty, f, args...)
|
||||
#endif
|
||||
|
@ -449,6 +447,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
|
|||
ret = ld->ops->open(tty);
|
||||
if (ret)
|
||||
clear_bit(TTY_LDISC_OPEN, &tty->flags);
|
||||
|
||||
tty_ldisc_debug(tty, "%p: opened\n", tty->ldisc);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
|
@ -469,6 +469,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
|
|||
clear_bit(TTY_LDISC_OPEN, &tty->flags);
|
||||
if (ld->ops->close)
|
||||
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)
|
|||
int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
|
||||
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);
|
||||
if (ld != NULL) {
|
||||
|
@ -712,7 +713,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
|||
if (reset)
|
||||
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)
|
|||
* 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_kill(tty);
|
||||
if (o_tty)
|
||||
|
@ -787,7 +786,7 @@ void tty_ldisc_release(struct tty_struct *tty)
|
|||
/* And the memory resources remaining (buffers, termios) will be
|
||||
disposed of when the kref hits zero */
|
||||
|
||||
tty_ldisc_debug(tty, "ldisc closed\n");
|
||||
tty_ldisc_debug(tty, "released\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,12 +33,14 @@
|
|||
#define UART01x_DR 0x00 /* Data read or written from the interface. */
|
||||
#define UART01x_RSR 0x04 /* Receive status register (Read). */
|
||||
#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 ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */
|
||||
#define UART010_LCRM 0x0C /* Line control register, middle byte. */
|
||||
#define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */
|
||||
#define UART010_LCRL 0x10 /* Line control register, low byte. */
|
||||
#define UART010_CR 0x14 /* Control register. */
|
||||
#define ZX_UART01x_FR 0x14 /* Flag register (Read only). */
|
||||
#define UART01x_FR 0x18 /* Flag register (Read only). */
|
||||
#define UART010_IIR 0x1C /* Interrupt identification register (Read). */
|
||||
#define UART010_ICR 0x1C /* Interrupt clear register (Write). */
|
||||
|
@ -49,13 +51,21 @@
|
|||
#define UART011_LCRH 0x2c /* Line control register. */
|
||||
#define ST_UART011_LCRH_TX 0x2c /* Tx Line 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 ZX_UART011_CR 0x34 /* Control register. */
|
||||
#define ZX_UART011_IFLS 0x38 /* Interrupt fifo level select. */
|
||||
#define UART011_IMSC 0x38 /* Interrupt mask. */
|
||||
#define UART011_RIS 0x3c /* Raw interrupt status. */
|
||||
#define UART011_MIS 0x40 /* Masked interrupt status. */
|
||||
#define ZX_UART011_IMSC 0x40 /* Interrupt mask. */
|
||||
#define UART011_ICR 0x44 /* Interrupt clear register. */
|
||||
#define ZX_UART011_RIS 0x44 /* Raw interrupt status. */
|
||||
#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 ZX_UART011_DMACR 0x50 /* DMA control register. */
|
||||
#define ST_UART011_XON1 0x54 /* XON1 register. */
|
||||
#define ST_UART011_XON2 0x58 /* XON2 register. */
|
||||
#define ST_UART011_XOFF1 0x5C /* XON1 register. */
|
||||
|
@ -75,15 +85,19 @@
|
|||
#define UART01x_RSR_PE 0x02
|
||||
#define UART01x_RSR_FE 0x01
|
||||
|
||||
#define ZX_UART01x_FR_BUSY 0x300
|
||||
#define UART011_FR_RI 0x100
|
||||
#define UART011_FR_TXFE 0x080
|
||||
#define UART011_FR_RXFF 0x040
|
||||
#define UART01x_FR_TXFF 0x020
|
||||
#define UART01x_FR_RXFE 0x010
|
||||
#define UART01x_FR_BUSY 0x008
|
||||
#define ZX_UART01x_FR_DSR 0x008
|
||||
#define UART01x_FR_DCD 0x004
|
||||
#define UART01x_FR_DSR 0x002
|
||||
#define ZX_UART01x_FR_CTS 0x002
|
||||
#define UART01x_FR_CTS 0x001
|
||||
#define ZX_UART011_FR_RI 0x001
|
||||
#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY)
|
||||
|
||||
#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */
|
||||
|
|
|
@ -16,115 +16,151 @@
|
|||
#ifndef ATMEL_SERIAL_H
|
||||
#define ATMEL_SERIAL_H
|
||||
|
||||
#define ATMEL_US_CR 0x00 /* Control Register */
|
||||
#define ATMEL_US_RSTRX (1 << 2) /* Reset Receiver */
|
||||
#define ATMEL_US_RSTTX (1 << 3) /* Reset Transmitter */
|
||||
#define ATMEL_US_RXEN (1 << 4) /* Receiver Enable */
|
||||
#define ATMEL_US_RXDIS (1 << 5) /* Receiver Disable */
|
||||
#define ATMEL_US_TXEN (1 << 6) /* Transmitter Enable */
|
||||
#define ATMEL_US_TXDIS (1 << 7) /* Transmitter Disable */
|
||||
#define ATMEL_US_RSTSTA (1 << 8) /* Reset Status Bits */
|
||||
#define ATMEL_US_STTBRK (1 << 9) /* Start Break */
|
||||
#define ATMEL_US_STPBRK (1 << 10) /* Stop Break */
|
||||
#define ATMEL_US_STTTO (1 << 11) /* Start Time-out */
|
||||
#define ATMEL_US_SENDA (1 << 12) /* Send Address */
|
||||
#define ATMEL_US_RSTIT (1 << 13) /* Reset Iterations */
|
||||
#define ATMEL_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */
|
||||
#define ATMEL_US_RETTO (1 << 15) /* Rearm Time-out */
|
||||
#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable [AT91RM9200 only] */
|
||||
#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable [AT91RM9200 only] */
|
||||
#define ATMEL_US_RTSEN (1 << 18) /* Request To Send Enable */
|
||||
#define ATMEL_US_RTSDIS (1 << 19) /* Request To Send Disable */
|
||||
#define ATMEL_US_CR 0x00 /* Control Register */
|
||||
#define ATMEL_US_RSTRX BIT(2) /* Reset Receiver */
|
||||
#define ATMEL_US_RSTTX BIT(3) /* Reset Transmitter */
|
||||
#define ATMEL_US_RXEN BIT(4) /* Receiver Enable */
|
||||
#define ATMEL_US_RXDIS BIT(5) /* Receiver Disable */
|
||||
#define ATMEL_US_TXEN BIT(6) /* Transmitter Enable */
|
||||
#define ATMEL_US_TXDIS BIT(7) /* Transmitter Disable */
|
||||
#define ATMEL_US_RSTSTA BIT(8) /* Reset Status Bits */
|
||||
#define ATMEL_US_STTBRK BIT(9) /* Start Break */
|
||||
#define ATMEL_US_STPBRK BIT(10) /* Stop Break */
|
||||
#define ATMEL_US_STTTO BIT(11) /* Start Time-out */
|
||||
#define ATMEL_US_SENDA BIT(12) /* Send Address */
|
||||
#define ATMEL_US_RSTIT BIT(13) /* Reset Iterations */
|
||||
#define ATMEL_US_RSTNACK BIT(14) /* Reset Non Acknowledge */
|
||||
#define ATMEL_US_RETTO BIT(15) /* Rearm Time-out */
|
||||
#define ATMEL_US_DTREN BIT(16) /* Data Terminal Ready Enable */
|
||||
#define ATMEL_US_DTRDIS BIT(17) /* Data Terminal Ready Disable */
|
||||
#define ATMEL_US_RTSEN BIT(18) /* Request To Send Enable */
|
||||
#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_USMODE (0xf << 0) /* Mode of the USART */
|
||||
#define ATMEL_US_USMODE_NORMAL 0
|
||||
#define ATMEL_US_USMODE_RS485 1
|
||||
#define ATMEL_US_USMODE_HWHS 2
|
||||
#define ATMEL_US_USMODE_MODEM 3
|
||||
#define ATMEL_US_USMODE_ISO7816_T0 4
|
||||
#define ATMEL_US_USMODE_ISO7816_T1 6
|
||||
#define ATMEL_US_USMODE_IRDA 8
|
||||
#define ATMEL_US_USCLKS (3 << 4) /* Clock Selection */
|
||||
#define ATMEL_US_USCLKS_MCK (0 << 4)
|
||||
#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
|
||||
#define ATMEL_US_USCLKS_SCK (3 << 4)
|
||||
#define ATMEL_US_CHRL (3 << 6) /* Character Length */
|
||||
#define ATMEL_US_CHRL_5 (0 << 6)
|
||||
#define ATMEL_US_CHRL_6 (1 << 6)
|
||||
#define ATMEL_US_CHRL_7 (2 << 6)
|
||||
#define ATMEL_US_CHRL_8 (3 << 6)
|
||||
#define ATMEL_US_SYNC (1 << 8) /* Synchronous Mode Select */
|
||||
#define ATMEL_US_PAR (7 << 9) /* Parity Type */
|
||||
#define ATMEL_US_PAR_EVEN (0 << 9)
|
||||
#define ATMEL_US_PAR_ODD (1 << 9)
|
||||
#define ATMEL_US_PAR_SPACE (2 << 9)
|
||||
#define ATMEL_US_PAR_MARK (3 << 9)
|
||||
#define ATMEL_US_PAR_NONE (4 << 9)
|
||||
#define ATMEL_US_PAR_MULTI_DROP (6 << 9)
|
||||
#define ATMEL_US_NBSTOP (3 << 12) /* Number of Stop Bits */
|
||||
#define ATMEL_US_NBSTOP_1 (0 << 12)
|
||||
#define ATMEL_US_NBSTOP_1_5 (1 << 12)
|
||||
#define ATMEL_US_NBSTOP_2 (2 << 12)
|
||||
#define ATMEL_US_CHMODE (3 << 14) /* Channel Mode */
|
||||
#define ATMEL_US_CHMODE_NORMAL (0 << 14)
|
||||
#define ATMEL_US_CHMODE_ECHO (1 << 14)
|
||||
#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
|
||||
#define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
|
||||
#define ATMEL_US_MSBF (1 << 16) /* Bit Order */
|
||||
#define ATMEL_US_MODE9 (1 << 17) /* 9-bit Character Length */
|
||||
#define ATMEL_US_CLKO (1 << 18) /* Clock Output Select */
|
||||
#define ATMEL_US_OVER (1 << 19) /* Oversampling Mode */
|
||||
#define ATMEL_US_INACK (1 << 20) /* Inhibit Non Acknowledge */
|
||||
#define ATMEL_US_DSNACK (1 << 21) /* Disable Successive NACK */
|
||||
#define ATMEL_US_MAX_ITER (7 << 24) /* Max Iterations */
|
||||
#define ATMEL_US_FILTER (1 << 28) /* Infrared Receive Line Filter */
|
||||
#define ATMEL_US_MR 0x04 /* Mode Register */
|
||||
#define ATMEL_US_USMODE GENMASK(3, 0) /* Mode of the USART */
|
||||
#define ATMEL_US_USMODE_NORMAL 0
|
||||
#define ATMEL_US_USMODE_RS485 1
|
||||
#define ATMEL_US_USMODE_HWHS 2
|
||||
#define ATMEL_US_USMODE_MODEM 3
|
||||
#define ATMEL_US_USMODE_ISO7816_T0 4
|
||||
#define ATMEL_US_USMODE_ISO7816_T1 6
|
||||
#define ATMEL_US_USMODE_IRDA 8
|
||||
#define ATMEL_US_USCLKS GENMASK(5, 4) /* Clock Selection */
|
||||
#define ATMEL_US_USCLKS_MCK (0 << 4)
|
||||
#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
|
||||
#define ATMEL_US_USCLKS_SCK (3 << 4)
|
||||
#define ATMEL_US_CHRL GENMASK(7, 6) /* Character Length */
|
||||
#define ATMEL_US_CHRL_5 (0 << 6)
|
||||
#define ATMEL_US_CHRL_6 (1 << 6)
|
||||
#define ATMEL_US_CHRL_7 (2 << 6)
|
||||
#define ATMEL_US_CHRL_8 (3 << 6)
|
||||
#define ATMEL_US_SYNC BIT(8) /* Synchronous Mode Select */
|
||||
#define ATMEL_US_PAR GENMASK(11, 9) /* Parity Type */
|
||||
#define ATMEL_US_PAR_EVEN (0 << 9)
|
||||
#define ATMEL_US_PAR_ODD (1 << 9)
|
||||
#define ATMEL_US_PAR_SPACE (2 << 9)
|
||||
#define ATMEL_US_PAR_MARK (3 << 9)
|
||||
#define ATMEL_US_PAR_NONE (4 << 9)
|
||||
#define ATMEL_US_PAR_MULTI_DROP (6 << 9)
|
||||
#define ATMEL_US_NBSTOP GENMASK(13, 12) /* Number of Stop Bits */
|
||||
#define ATMEL_US_NBSTOP_1 (0 << 12)
|
||||
#define ATMEL_US_NBSTOP_1_5 (1 << 12)
|
||||
#define ATMEL_US_NBSTOP_2 (2 << 12)
|
||||
#define ATMEL_US_CHMODE GENMASK(15, 14) /* Channel Mode */
|
||||
#define ATMEL_US_CHMODE_NORMAL (0 << 14)
|
||||
#define ATMEL_US_CHMODE_ECHO (1 << 14)
|
||||
#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
|
||||
#define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
|
||||
#define ATMEL_US_MSBF BIT(16) /* Bit Order */
|
||||
#define ATMEL_US_MODE9 BIT(17) /* 9-bit Character Length */
|
||||
#define ATMEL_US_CLKO BIT(18) /* Clock Output Select */
|
||||
#define ATMEL_US_OVER BIT(19) /* Oversampling Mode */
|
||||
#define ATMEL_US_INACK BIT(20) /* Inhibit Non Acknowledge */
|
||||
#define ATMEL_US_DSNACK BIT(21) /* Disable Successive NACK */
|
||||
#define ATMEL_US_MAX_ITER GENMASK(26, 24) /* Max Iterations */
|
||||
#define ATMEL_US_FILTER BIT(28) /* Infrared Receive Line Filter */
|
||||
|
||||
#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
|
||||
#define ATMEL_US_RXRDY (1 << 0) /* Receiver Ready */
|
||||
#define ATMEL_US_TXRDY (1 << 1) /* Transmitter Ready */
|
||||
#define ATMEL_US_RXBRK (1 << 2) /* Break Received / End of Break */
|
||||
#define ATMEL_US_ENDRX (1 << 3) /* End of Receiver Transfer */
|
||||
#define ATMEL_US_ENDTX (1 << 4) /* End of Transmitter Transfer */
|
||||
#define ATMEL_US_OVRE (1 << 5) /* Overrun Error */
|
||||
#define ATMEL_US_FRAME (1 << 6) /* Framing Error */
|
||||
#define ATMEL_US_PARE (1 << 7) /* Parity Error */
|
||||
#define ATMEL_US_TIMEOUT (1 << 8) /* Receiver Time-out */
|
||||
#define ATMEL_US_TXEMPTY (1 << 9) /* Transmitter Empty */
|
||||
#define ATMEL_US_ITERATION (1 << 10) /* Max number of Repetitions Reached */
|
||||
#define ATMEL_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */
|
||||
#define ATMEL_US_RXBUFF (1 << 12) /* Reception Buffer Full */
|
||||
#define ATMEL_US_NACK (1 << 13) /* Non Acknowledge */
|
||||
#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change [AT91RM9200 only] */
|
||||
#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change [AT91RM9200 only] */
|
||||
#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change [AT91RM9200 only] */
|
||||
#define ATMEL_US_CTSIC (1 << 19) /* Clear to Send Input Change */
|
||||
#define ATMEL_US_RI (1 << 20) /* RI */
|
||||
#define ATMEL_US_DSR (1 << 21) /* DSR */
|
||||
#define ATMEL_US_DCD (1 << 22) /* DCD */
|
||||
#define ATMEL_US_CTS (1 << 23) /* CTS */
|
||||
#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
|
||||
#define ATMEL_US_RXRDY BIT(0) /* Receiver Ready */
|
||||
#define ATMEL_US_TXRDY BIT(1) /* Transmitter Ready */
|
||||
#define ATMEL_US_RXBRK BIT(2) /* Break Received / End of Break */
|
||||
#define ATMEL_US_ENDRX BIT(3) /* End of Receiver Transfer */
|
||||
#define ATMEL_US_ENDTX BIT(4) /* End of Transmitter Transfer */
|
||||
#define ATMEL_US_OVRE BIT(5) /* Overrun Error */
|
||||
#define ATMEL_US_FRAME BIT(6) /* Framing Error */
|
||||
#define ATMEL_US_PARE BIT(7) /* Parity Error */
|
||||
#define ATMEL_US_TIMEOUT BIT(8) /* Receiver Time-out */
|
||||
#define ATMEL_US_TXEMPTY BIT(9) /* Transmitter Empty */
|
||||
#define ATMEL_US_ITERATION BIT(10) /* Max number of Repetitions Reached */
|
||||
#define ATMEL_US_TXBUFE BIT(11) /* Transmission Buffer Empty */
|
||||
#define ATMEL_US_RXBUFF BIT(12) /* Reception Buffer Full */
|
||||
#define ATMEL_US_NACK BIT(13) /* Non Acknowledge */
|
||||
#define ATMEL_US_RIIC BIT(16) /* Ring Indicator Input Change */
|
||||
#define ATMEL_US_DSRIC BIT(17) /* Data Set Ready Input Change */
|
||||
#define ATMEL_US_DCDIC BIT(18) /* Data Carrier Detect Input Change */
|
||||
#define ATMEL_US_CTSIC BIT(19) /* Clear to Send Input Change */
|
||||
#define ATMEL_US_RI BIT(20) /* RI */
|
||||
#define ATMEL_US_DSR BIT(21) /* DSR */
|
||||
#define ATMEL_US_DCD BIT(22) /* DCD */
|
||||
#define ATMEL_US_CTS BIT(23) /* CTS */
|
||||
|
||||
#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */
|
||||
#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */
|
||||
#define ATMEL_US_CSR 0x14 /* Channel Status Register */
|
||||
#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
|
||||
#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
|
||||
#define ATMEL_US_SYNH (1 << 15) /* Transmit/Receive Sync [AT91SAM9261 only] */
|
||||
#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */
|
||||
#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */
|
||||
#define ATMEL_US_CSR 0x14 /* Channel Status Register */
|
||||
#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
|
||||
#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
|
||||
#define ATMEL_US_SYNH BIT(15) /* Transmit/Receive Sync */
|
||||
|
||||
#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
|
||||
#define ATMEL_US_CD (0xffff << 0) /* Clock Divider */
|
||||
#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
|
||||
#define ATMEL_US_CD GENMASK(15, 0) /* Clock Divider */
|
||||
|
||||
#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */
|
||||
#define ATMEL_US_TO (0xffff << 0) /* Time-out Value */
|
||||
#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */
|
||||
#define ATMEL_US_TO GENMASK(15, 0) /* Time-out Value */
|
||||
|
||||
#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */
|
||||
#define ATMEL_US_TG (0xff << 0) /* Timeguard Value */
|
||||
#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */
|
||||
#define ATMEL_US_TG GENMASK(7, 0) /* Timeguard Value */
|
||||
|
||||
#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */
|
||||
#define ATMEL_US_NER 0x44 /* Number of Errors Register */
|
||||
#define ATMEL_US_IF 0x4c /* IrDA Filter Register */
|
||||
#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */
|
||||
#define ATMEL_US_NER 0x44 /* Number of Errors Register */
|
||||
#define ATMEL_US_IF 0x4c /* IrDA Filter Register */
|
||||
|
||||
#define ATMEL_US_NAME 0xf0 /* Ip Name */
|
||||
#define ATMEL_US_VERSION 0xfc /* Ip Version */
|
||||
#define ATMEL_US_CMPR 0x90 /* Comparaison Register */
|
||||
#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
|
||||
|
|
|
@ -136,8 +136,6 @@ void serial8250_resume_port(int line);
|
|||
|
||||
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,
|
||||
const char *options);
|
||||
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);
|
|||
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
|
||||
void serial8250_tx_chars(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)
|
||||
(int port, struct uart_port *up,
|
||||
|
|
|
@ -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) {}
|
||||
#endif
|
||||
|
||||
#define tty_debug(tty, f, args...) \
|
||||
do { \
|
||||
printk(KERN_DEBUG "%s: %s: " f, __func__, \
|
||||
tty_name(tty), ##args); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -296,7 +296,7 @@ struct tty_operations {
|
|||
struct tty_driver {
|
||||
int magic; /* magic number for this structure */
|
||||
struct kref kref; /* Reference management */
|
||||
struct cdev *cdevs;
|
||||
struct cdev **cdevs;
|
||||
struct module *owner;
|
||||
const char *driver_name;
|
||||
const char *name;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <linux/if.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct gsm_config
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue