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:
@@ -22,6 +22,8 @@ Optional properties:
|
|||||||
memory peripheral interface and USART DMA channel ID, FIFO configuration.
|
memory peripheral interface and USART DMA channel ID, FIFO configuration.
|
||||||
Refer to dma.txt and atmel-dma.txt for details.
|
Refer to dma.txt and atmel-dma.txt for details.
|
||||||
- dma-names: "rx" for RX channel, "tx" for TX channel.
|
- dma-names: "rx" for RX channel, "tx" for TX channel.
|
||||||
|
- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
|
||||||
|
capable USARTs.
|
||||||
|
|
||||||
<chip> compatible description:
|
<chip> compatible description:
|
||||||
- at91rm9200: legacy USART support
|
- at91rm9200: legacy USART support
|
||||||
@@ -57,4 +59,5 @@ Example:
|
|||||||
dmas = <&dma0 2 0x3>,
|
dmas = <&dma0 2 0x3>,
|
||||||
<&dma0 2 0x204>;
|
<&dma0 2 0x204>;
|
||||||
dma-names = "tx", "rx";
|
dma-names = "tx", "rx";
|
||||||
|
atmel,fifo-size = <32>;
|
||||||
};
|
};
|
||||||
|
@@ -6,7 +6,7 @@ Required properties:
|
|||||||
- interrupts: device interrupt
|
- interrupts: device interrupt
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- {dtr,dsr,ri,cd}-gpios: specify a GPIO for DTR/DSR/RI/CD
|
- {dtr,dsr,rng,dcd}-gpios: specify a GPIO for DTR/DSR/RI/DCD
|
||||||
line respectively.
|
line respectively.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -16,4 +16,8 @@ serial@b00260000 {
|
|||||||
reg = <0xb0026000 0x1000>;
|
reg = <0xb0026000 0x1000>;
|
||||||
interrupts = <68>;
|
interrupts = <68>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
dtr-gpios = <&sysgpio 0 GPIO_ACTIVE_LOW>;
|
||||||
|
dsr-gpios = <&sysgpio 1 GPIO_ACTIVE_LOW>;
|
||||||
|
rng-gpios = <&sysgpio 2 GPIO_ACTIVE_LOW>;
|
||||||
|
dcd-gpios = <&sysgpio 3 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
|
@@ -4,6 +4,9 @@ Required properties:
|
|||||||
- compatible : should be "ti,omap2-uart" for OMAP2 controllers
|
- compatible : should be "ti,omap2-uart" for OMAP2 controllers
|
||||||
- compatible : should be "ti,omap3-uart" for OMAP3 controllers
|
- compatible : should be "ti,omap3-uart" for OMAP3 controllers
|
||||||
- compatible : should be "ti,omap4-uart" for OMAP4 controllers
|
- compatible : should be "ti,omap4-uart" for OMAP4 controllers
|
||||||
|
- compatible : should be "ti,am4372-uart" for AM437x controllers
|
||||||
|
- compatible : should be "ti,am3352-uart" for AM335x controllers
|
||||||
|
- compatible : should be "ti,dra742-uart" for DRA7x controllers
|
||||||
- reg : address and length of the register space
|
- reg : address and length of the register space
|
||||||
- interrupts or interrupts-extended : Should contain the uart interrupt
|
- interrupts or interrupts-extended : Should contain the uart interrupt
|
||||||
specifier or both the interrupt
|
specifier or both the interrupt
|
||||||
|
@@ -210,7 +210,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart0: serial@44e09000 {
|
uart0: serial@44e09000 {
|
||||||
compatible = "ti,omap3-uart";
|
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||||
ti,hwmods = "uart1";
|
ti,hwmods = "uart1";
|
||||||
clock-frequency = <48000000>;
|
clock-frequency = <48000000>;
|
||||||
reg = <0x44e09000 0x2000>;
|
reg = <0x44e09000 0x2000>;
|
||||||
@@ -221,7 +221,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart1: serial@48022000 {
|
uart1: serial@48022000 {
|
||||||
compatible = "ti,omap3-uart";
|
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||||
ti,hwmods = "uart2";
|
ti,hwmods = "uart2";
|
||||||
clock-frequency = <48000000>;
|
clock-frequency = <48000000>;
|
||||||
reg = <0x48022000 0x2000>;
|
reg = <0x48022000 0x2000>;
|
||||||
@@ -232,7 +232,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart2: serial@48024000 {
|
uart2: serial@48024000 {
|
||||||
compatible = "ti,omap3-uart";
|
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||||
ti,hwmods = "uart3";
|
ti,hwmods = "uart3";
|
||||||
clock-frequency = <48000000>;
|
clock-frequency = <48000000>;
|
||||||
reg = <0x48024000 0x2000>;
|
reg = <0x48024000 0x2000>;
|
||||||
@@ -243,7 +243,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart3: serial@481a6000 {
|
uart3: serial@481a6000 {
|
||||||
compatible = "ti,omap3-uart";
|
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||||
ti,hwmods = "uart4";
|
ti,hwmods = "uart4";
|
||||||
clock-frequency = <48000000>;
|
clock-frequency = <48000000>;
|
||||||
reg = <0x481a6000 0x2000>;
|
reg = <0x481a6000 0x2000>;
|
||||||
@@ -252,7 +252,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart4: serial@481a8000 {
|
uart4: serial@481a8000 {
|
||||||
compatible = "ti,omap3-uart";
|
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||||
ti,hwmods = "uart5";
|
ti,hwmods = "uart5";
|
||||||
clock-frequency = <48000000>;
|
clock-frequency = <48000000>;
|
||||||
reg = <0x481a8000 0x2000>;
|
reg = <0x481a8000 0x2000>;
|
||||||
@@ -261,7 +261,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart5: serial@481aa000 {
|
uart5: serial@481aa000 {
|
||||||
compatible = "ti,omap3-uart";
|
compatible = "ti,am3352-uart", "ti,omap3-uart";
|
||||||
ti,hwmods = "uart6";
|
ti,hwmods = "uart6";
|
||||||
clock-frequency = <48000000>;
|
clock-frequency = <48000000>;
|
||||||
reg = <0x481aa000 0x2000>;
|
reg = <0x481aa000 0x2000>;
|
||||||
|
@@ -397,7 +397,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart1: serial@4806a000 {
|
uart1: serial@4806a000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x4806a000 0x100>;
|
reg = <0x4806a000 0x100>;
|
||||||
interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart1";
|
ti,hwmods = "uart1";
|
||||||
@@ -408,7 +408,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart2: serial@4806c000 {
|
uart2: serial@4806c000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x4806c000 0x100>;
|
reg = <0x4806c000 0x100>;
|
||||||
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart2";
|
ti,hwmods = "uart2";
|
||||||
@@ -419,7 +419,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart3: serial@48020000 {
|
uart3: serial@48020000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x48020000 0x100>;
|
reg = <0x48020000 0x100>;
|
||||||
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart3";
|
ti,hwmods = "uart3";
|
||||||
@@ -430,7 +430,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart4: serial@4806e000 {
|
uart4: serial@4806e000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x4806e000 0x100>;
|
reg = <0x4806e000 0x100>;
|
||||||
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart4";
|
ti,hwmods = "uart4";
|
||||||
@@ -441,7 +441,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart5: serial@48066000 {
|
uart5: serial@48066000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x48066000 0x100>;
|
reg = <0x48066000 0x100>;
|
||||||
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart5";
|
ti,hwmods = "uart5";
|
||||||
@@ -452,7 +452,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart6: serial@48068000 {
|
uart6: serial@48068000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x48068000 0x100>;
|
reg = <0x48068000 0x100>;
|
||||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart6";
|
ti,hwmods = "uart6";
|
||||||
@@ -463,7 +463,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart7: serial@48420000 {
|
uart7: serial@48420000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x48420000 0x100>;
|
reg = <0x48420000 0x100>;
|
||||||
interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart7";
|
ti,hwmods = "uart7";
|
||||||
@@ -472,7 +472,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart8: serial@48422000 {
|
uart8: serial@48422000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x48422000 0x100>;
|
reg = <0x48422000 0x100>;
|
||||||
interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart8";
|
ti,hwmods = "uart8";
|
||||||
@@ -481,7 +481,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart9: serial@48424000 {
|
uart9: serial@48424000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x48424000 0x100>;
|
reg = <0x48424000 0x100>;
|
||||||
interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart9";
|
ti,hwmods = "uart9";
|
||||||
@@ -490,7 +490,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
uart10: serial@4ae2b000 {
|
uart10: serial@4ae2b000 {
|
||||||
compatible = "ti,omap4-uart";
|
compatible = "ti,dra742-uart", "ti,omap4-uart";
|
||||||
reg = <0x4ae2b000 0x100>;
|
reg = <0x4ae2b000 0x100>;
|
||||||
interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
ti,hwmods = "uart10";
|
ti,hwmods = "uart10";
|
||||||
|
@@ -153,6 +153,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
|
|||||||
{"AEI0250"}, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
|
{"AEI0250"}, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
|
||||||
{"AEI1240"}, /* Actiontec ISA PNP 56K X2 Fax Modem */
|
{"AEI1240"}, /* Actiontec ISA PNP 56K X2 Fax Modem */
|
||||||
{"AKY1021"}, /* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
{"AKY1021"}, /* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
||||||
|
{"ALI5123"}, /* ALi Fast Infrared Controller */
|
||||||
{"AZT4001"}, /* AZT3005 PnP SOUND DEVICE */
|
{"AZT4001"}, /* AZT3005 PnP SOUND DEVICE */
|
||||||
{"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */
|
{"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */
|
||||||
{"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */
|
{"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */
|
||||||
|
@@ -2712,7 +2712,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
|
|||||||
memcpy(skb_put(skb, size), in_buf, size);
|
memcpy(skb_put(skb, size), in_buf, size);
|
||||||
|
|
||||||
skb->dev = net;
|
skb->dev = net;
|
||||||
skb->protocol = __constant_htons(ETH_P_IP);
|
skb->protocol = htons(ETH_P_IP);
|
||||||
|
|
||||||
/* Ship it off to the kernel */
|
/* Ship it off to the kernel */
|
||||||
netif_rx(skb);
|
netif_rx(skb);
|
||||||
|
@@ -2147,6 +2147,8 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
|
|||||||
|
|
||||||
static int job_control(struct tty_struct *tty, struct file *file)
|
static int job_control(struct tty_struct *tty, struct file *file)
|
||||||
{
|
{
|
||||||
|
struct pid *pgrp;
|
||||||
|
|
||||||
/* Job control check -- must be done at start and after
|
/* Job control check -- must be done at start and after
|
||||||
every sleep (POSIX.1 7.1.1.4). */
|
every sleep (POSIX.1 7.1.1.4). */
|
||||||
/* NOTE: not yet done after every sleep pending a thorough
|
/* NOTE: not yet done after every sleep pending a thorough
|
||||||
@@ -2156,18 +2158,25 @@ static int job_control(struct tty_struct *tty, struct file *file)
|
|||||||
current->signal->tty != tty)
|
current->signal->tty != tty)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
pgrp = task_pgrp(current);
|
||||||
|
|
||||||
spin_lock_irq(&tty->ctrl_lock);
|
spin_lock_irq(&tty->ctrl_lock);
|
||||||
if (!tty->pgrp)
|
if (!tty->pgrp)
|
||||||
printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
|
printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
|
||||||
else if (task_pgrp(current) != tty->pgrp) {
|
else if (pgrp != tty->pgrp) {
|
||||||
spin_unlock_irq(&tty->ctrl_lock);
|
spin_unlock_irq(&tty->ctrl_lock);
|
||||||
if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
|
if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
|
||||||
|
rcu_read_unlock();
|
||||||
return -EIO;
|
return -EIO;
|
||||||
kill_pgrp(task_pgrp(current), SIGTTIN, 1);
|
}
|
||||||
|
kill_pgrp(pgrp, SIGTTIN, 1);
|
||||||
|
rcu_read_unlock();
|
||||||
set_thread_flag(TIF_SIGPENDING);
|
set_thread_flag(TIF_SIGPENDING);
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&tty->ctrl_lock);
|
spin_unlock_irq(&tty->ctrl_lock);
|
||||||
|
rcu_read_unlock();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,6 +26,12 @@
|
|||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
|
|
||||||
|
#undef TTY_DEBUG_HANGUP
|
||||||
|
#ifdef TTY_DEBUG_HANGUP
|
||||||
|
# define tty_debug_hangup(tty, f, args...) tty_debug(tty, f, ##args)
|
||||||
|
#else
|
||||||
|
# define tty_debug_hangup(tty, f, args...) do {} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_UNIX98_PTYS
|
#ifdef CONFIG_UNIX98_PTYS
|
||||||
static struct tty_driver *ptm_driver;
|
static struct tty_driver *ptm_driver;
|
||||||
@@ -779,6 +785,8 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
|||||||
if (retval)
|
if (retval)
|
||||||
goto err_release;
|
goto err_release;
|
||||||
|
|
||||||
|
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
|
||||||
|
|
||||||
tty_unlock(tty);
|
tty_unlock(tty);
|
||||||
return 0;
|
return 0;
|
||||||
err_release:
|
err_release:
|
||||||
|
@@ -42,9 +42,9 @@ struct uart_8250_dma {
|
|||||||
size_t rx_size;
|
size_t rx_size;
|
||||||
size_t tx_size;
|
size_t tx_size;
|
||||||
|
|
||||||
unsigned char tx_running:1;
|
unsigned char tx_running;
|
||||||
unsigned char tx_err: 1;
|
unsigned char tx_err;
|
||||||
unsigned char rx_running:1;
|
unsigned char rx_running;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct old_serial_port {
|
struct old_serial_port {
|
||||||
@@ -211,3 +211,14 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int serial_index(struct uart_port *port)
|
||||||
|
{
|
||||||
|
return port->minor - 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define DEBUG_INTR(fmt...) printk(fmt)
|
||||||
|
#else
|
||||||
|
#define DEBUG_INTR(fmt...) do { } while (0)
|
||||||
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,6 @@
|
|||||||
|
|
||||||
struct dw8250_data {
|
struct dw8250_data {
|
||||||
u8 usr_reg;
|
u8 usr_reg;
|
||||||
int last_mcr;
|
|
||||||
int line;
|
int line;
|
||||||
int msr_mask_on;
|
int msr_mask_on;
|
||||||
int msr_mask_off;
|
int msr_mask_off;
|
||||||
@@ -76,12 +75,6 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
|
|||||||
{
|
{
|
||||||
struct dw8250_data *d = p->private_data;
|
struct dw8250_data *d = p->private_data;
|
||||||
|
|
||||||
/* If reading MSR, report CTS asserted when auto-CTS/RTS enabled */
|
|
||||||
if (offset == UART_MSR && d->last_mcr & UART_MCR_AFE) {
|
|
||||||
value |= UART_MSR_CTS;
|
|
||||||
value &= ~UART_MSR_DCTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Override any modem control signals if needed */
|
/* Override any modem control signals if needed */
|
||||||
if (offset == UART_MSR) {
|
if (offset == UART_MSR) {
|
||||||
value |= d->msr_mask_on;
|
value |= d->msr_mask_on;
|
||||||
@@ -101,11 +94,6 @@ static void dw8250_force_idle(struct uart_port *p)
|
|||||||
|
|
||||||
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
|
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
|
||||||
{
|
{
|
||||||
struct dw8250_data *d = p->private_data;
|
|
||||||
|
|
||||||
if (offset == UART_MCR)
|
|
||||||
d->last_mcr = value;
|
|
||||||
|
|
||||||
writeb(value, p->membase + (offset << p->regshift));
|
writeb(value, p->membase + (offset << p->regshift));
|
||||||
|
|
||||||
/* Make sure LCR write wasn't ignored */
|
/* Make sure LCR write wasn't ignored */
|
||||||
@@ -144,11 +132,6 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset)
|
|||||||
|
|
||||||
static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
|
static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
|
||||||
{
|
{
|
||||||
struct dw8250_data *d = p->private_data;
|
|
||||||
|
|
||||||
if (offset == UART_MCR)
|
|
||||||
d->last_mcr = value;
|
|
||||||
|
|
||||||
value &= 0xff;
|
value &= 0xff;
|
||||||
__raw_writeq(value, p->membase + (offset << p->regshift));
|
__raw_writeq(value, p->membase + (offset << p->regshift));
|
||||||
/* Read back to ensure register write ordering. */
|
/* Read back to ensure register write ordering. */
|
||||||
@@ -175,11 +158,6 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
|
|||||||
|
|
||||||
static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
|
static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
|
||||||
{
|
{
|
||||||
struct dw8250_data *d = p->private_data;
|
|
||||||
|
|
||||||
if (offset == UART_MCR)
|
|
||||||
d->last_mcr = value;
|
|
||||||
|
|
||||||
writel(value, p->membase + (offset << p->regshift));
|
writel(value, p->membase + (offset << p->regshift));
|
||||||
|
|
||||||
/* Make sure LCR write wasn't ignored */
|
/* Make sure LCR write wasn't ignored */
|
||||||
@@ -257,6 +235,11 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
|||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
p->uartclk = rate;
|
p->uartclk = rate;
|
||||||
|
|
||||||
|
p->status &= ~UPSTAT_AUTOCTS;
|
||||||
|
if (termios->c_cflag & CRTSCTS)
|
||||||
|
p->status |= UPSTAT_AUTOCTS;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
serial8250_do_set_termios(p, termios, old);
|
serial8250_do_set_termios(p, termios, old);
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/serial.h>
|
#include <asm/serial.h>
|
||||||
|
|
||||||
unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
|
static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
|
||||||
{
|
{
|
||||||
switch (port->iotype) {
|
switch (port->iotype) {
|
||||||
case UPIO_MEM:
|
case UPIO_MEM:
|
||||||
@@ -51,7 +51,7 @@ unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value)
|
static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
|
||||||
{
|
{
|
||||||
switch (port->iotype) {
|
switch (port->iotype) {
|
||||||
case UPIO_MEM:
|
case UPIO_MEM:
|
||||||
|
@@ -17,18 +17,19 @@
|
|||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include "8250.h"
|
#include "8250.h"
|
||||||
|
|
||||||
#define ADDR_PORT 0x4E
|
#define ADDR_PORT 0
|
||||||
#define DATA_PORT 0x4F
|
#define DATA_PORT 1
|
||||||
#define ENTRY_KEY 0x77
|
|
||||||
#define EXIT_KEY 0xAA
|
#define EXIT_KEY 0xAA
|
||||||
#define CHIP_ID1 0x20
|
#define CHIP_ID1 0x20
|
||||||
#define CHIP_ID1_VAL 0x02
|
|
||||||
#define CHIP_ID2 0x21
|
#define CHIP_ID2 0x21
|
||||||
#define CHIP_ID2_VAL 0x16
|
#define CHIP_ID_0 0x1602
|
||||||
|
#define CHIP_ID_1 0x0501
|
||||||
#define VENDOR_ID1 0x23
|
#define VENDOR_ID1 0x23
|
||||||
#define VENDOR_ID1_VAL 0x19
|
#define VENDOR_ID1_VAL 0x19
|
||||||
#define VENDOR_ID2 0x24
|
#define VENDOR_ID2 0x24
|
||||||
#define VENDOR_ID2_VAL 0x34
|
#define VENDOR_ID2_VAL 0x34
|
||||||
|
#define IO_ADDR1 0x61
|
||||||
|
#define IO_ADDR2 0x60
|
||||||
#define LDN 0x7
|
#define LDN 0x7
|
||||||
|
|
||||||
#define RS485 0xF0
|
#define RS485 0xF0
|
||||||
@@ -39,51 +40,49 @@
|
|||||||
|
|
||||||
#define DRIVER_NAME "8250_fintek"
|
#define DRIVER_NAME "8250_fintek"
|
||||||
|
|
||||||
static int fintek_8250_enter_key(void){
|
struct fintek_8250 {
|
||||||
|
u16 base_port;
|
||||||
|
u8 index;
|
||||||
|
u8 key;
|
||||||
|
long line;
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
return -EBUSY;
|
||||||
|
|
||||||
outb(ENTRY_KEY, ADDR_PORT);
|
outb(key, base_port + ADDR_PORT);
|
||||||
outb(ENTRY_KEY, ADDR_PORT);
|
outb(key, base_port + ADDR_PORT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fintek_8250_exit_key(void){
|
static void fintek_8250_exit_key(u16 base_port)
|
||||||
|
|
||||||
outb(EXIT_KEY, ADDR_PORT);
|
|
||||||
release_region(ADDR_PORT, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fintek_8250_get_index(resource_size_t base_addr)
|
|
||||||
{
|
|
||||||
resource_size_t base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(base); i++)
|
|
||||||
if (base_addr == base[i])
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fintek_8250_check_id(void)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
outb(CHIP_ID1, ADDR_PORT);
|
outb(EXIT_KEY, base_port + ADDR_PORT);
|
||||||
if (inb(DATA_PORT) != CHIP_ID1_VAL)
|
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;
|
return -ENODEV;
|
||||||
|
|
||||||
outb(CHIP_ID2, ADDR_PORT);
|
outb(VENDOR_ID2, base_port + ADDR_PORT);
|
||||||
if (inb(DATA_PORT) != CHIP_ID2_VAL)
|
if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
outb(VENDOR_ID1, ADDR_PORT);
|
outb(CHIP_ID1, base_port + ADDR_PORT);
|
||||||
if (inb(DATA_PORT) != VENDOR_ID1_VAL)
|
chip = inb(base_port + DATA_PORT);
|
||||||
return -ENODEV;
|
outb(CHIP_ID2, base_port + ADDR_PORT);
|
||||||
|
chip |= inb(base_port + DATA_PORT) << 8;
|
||||||
|
|
||||||
outb(VENDOR_ID2, ADDR_PORT);
|
if (chip != CHIP_ID_0 && chip != CHIP_ID_1)
|
||||||
if (inb(DATA_PORT) != VENDOR_ID2_VAL)
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -93,9 +92,9 @@ static int fintek_8250_rs485_config(struct uart_port *port,
|
|||||||
struct serial_rs485 *rs485)
|
struct serial_rs485 *rs485)
|
||||||
{
|
{
|
||||||
uint8_t config = 0;
|
uint8_t config = 0;
|
||||||
int index = fintek_8250_get_index(port->iobase);
|
struct fintek_8250 *pdata = port->private_data;
|
||||||
|
|
||||||
if (index < 0)
|
if (!pdata)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (rs485->flags & SER_RS485_ENABLED)
|
if (rs485->flags & SER_RS485_ENABLED)
|
||||||
@@ -125,44 +124,84 @@ static int fintek_8250_rs485_config(struct uart_port *port,
|
|||||||
if (rs485->flags & SER_RS485_RTS_ON_SEND)
|
if (rs485->flags & SER_RS485_RTS_ON_SEND)
|
||||||
config |= RTS_INVERT;
|
config |= RTS_INVERT;
|
||||||
|
|
||||||
if (fintek_8250_enter_key())
|
if (fintek_8250_enter_key(pdata->base_port, pdata->key))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
outb(LDN, ADDR_PORT);
|
outb(LDN, pdata->base_port + ADDR_PORT);
|
||||||
outb(index, DATA_PORT);
|
outb(pdata->index, pdata->base_port + DATA_PORT);
|
||||||
outb(RS485, ADDR_PORT);
|
outb(RS485, pdata->base_port + ADDR_PORT);
|
||||||
outb(config, DATA_PORT);
|
outb(config, pdata->base_port + DATA_PORT);
|
||||||
fintek_8250_exit_key();
|
fintek_8250_exit_key(pdata->base_port);
|
||||||
|
|
||||||
port->rs485 = *rs485;
|
port->rs485 = *rs485;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fintek_8250_base_port(u16 io_address, u8 *key, u8 *index)
|
||||||
|
{
|
||||||
|
static const u16 addr[] = {0x4e, 0x2e};
|
||||||
|
static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67};
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(addr); i++) {
|
||||||
|
for (j = 0; j < ARRAY_SIZE(keys); j++) {
|
||||||
|
|
||||||
|
if (fintek_8250_enter_key(addr[i], keys[j]))
|
||||||
|
continue;
|
||||||
|
if (fintek_8250_check_id(addr[i])) {
|
||||||
|
fintek_8250_exit_key(addr[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 0; k < 4; k++) {
|
||||||
|
u16 aux;
|
||||||
|
|
||||||
|
outb(LDN, addr[i] + ADDR_PORT);
|
||||||
|
outb(k, addr[i] + DATA_PORT);
|
||||||
|
|
||||||
|
outb(IO_ADDR1, addr[i] + ADDR_PORT);
|
||||||
|
aux = inb(addr[i] + DATA_PORT);
|
||||||
|
outb(IO_ADDR2, addr[i] + ADDR_PORT);
|
||||||
|
aux |= inb(addr[i] + DATA_PORT) << 8;
|
||||||
|
if (aux != io_address)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fintek_8250_exit_key(addr[i]);
|
||||||
|
*key = keys[j];
|
||||||
|
*index = k;
|
||||||
|
return addr[i];
|
||||||
|
}
|
||||||
|
fintek_8250_exit_key(addr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
||||||
{
|
{
|
||||||
int line;
|
|
||||||
struct uart_8250_port uart;
|
struct uart_8250_port uart;
|
||||||
int ret;
|
struct fintek_8250 *pdata;
|
||||||
|
int base_port;
|
||||||
|
u8 key;
|
||||||
|
u8 index;
|
||||||
|
|
||||||
if (!pnp_port_valid(dev, 0))
|
if (!pnp_port_valid(dev, 0))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (fintek_8250_get_index(pnp_port_start(dev, 0)) < 0)
|
base_port = fintek_8250_base_port(pnp_port_start(dev, 0), &key, &index);
|
||||||
|
if (base_port < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Enable configuration registers*/
|
|
||||||
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));
|
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))
|
if (!pnp_irq_valid(dev, 0))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
uart.port.irq = pnp_irq(dev, 0);
|
uart.port.irq = pnp_irq(dev, 0);
|
||||||
@@ -176,40 +215,43 @@ fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
|||||||
uart.port.uartclk = 1843200;
|
uart.port.uartclk = 1843200;
|
||||||
uart.port.dev = &dev->dev;
|
uart.port.dev = &dev->dev;
|
||||||
|
|
||||||
line = serial8250_register_8250_port(&uart);
|
pdata->key = key;
|
||||||
if (line < 0)
|
pdata->base_port = base_port;
|
||||||
|
pdata->index = index;
|
||||||
|
pdata->line = serial8250_register_8250_port(&uart);
|
||||||
|
if (pdata->line < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
pnp_set_drvdata(dev, (void *)((long)line + 1));
|
pnp_set_drvdata(dev, pdata);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fintek_8250_remove(struct pnp_dev *dev)
|
static void fintek_8250_remove(struct pnp_dev *dev)
|
||||||
{
|
{
|
||||||
long line = (long)pnp_get_drvdata(dev);
|
struct fintek_8250 *pdata = pnp_get_drvdata(dev);
|
||||||
|
|
||||||
if (line)
|
if (pdata)
|
||||||
serial8250_unregister_port(line - 1);
|
serial8250_unregister_port(pdata->line);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int fintek_8250_suspend(struct pnp_dev *dev, pm_message_t state)
|
static int fintek_8250_suspend(struct pnp_dev *dev, pm_message_t state)
|
||||||
{
|
{
|
||||||
long line = (long)pnp_get_drvdata(dev);
|
struct fintek_8250 *pdata = pnp_get_drvdata(dev);
|
||||||
|
|
||||||
if (!line)
|
if (!pdata)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
serial8250_suspend_port(line - 1);
|
serial8250_suspend_port(pdata->line);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fintek_8250_resume(struct pnp_dev *dev)
|
static int fintek_8250_resume(struct pnp_dev *dev)
|
||||||
{
|
{
|
||||||
long line = (long)pnp_get_drvdata(dev);
|
struct fintek_8250 *pdata = pnp_get_drvdata(dev);
|
||||||
|
|
||||||
if (!line)
|
if (!pdata)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
serial8250_resume_port(line - 1);
|
serial8250_resume_port(pdata->line);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@@ -252,7 +252,6 @@ MODULE_DEVICE_TABLE(of, of_match);
|
|||||||
static struct platform_driver ingenic_uart_platform_driver = {
|
static struct platform_driver ingenic_uart_platform_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "ingenic-uart",
|
.name = "ingenic-uart",
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.of_match_table = of_match,
|
.of_match_table = of_match,
|
||||||
},
|
},
|
||||||
.probe = ingenic_uart_probe,
|
.probe = ingenic_uart_probe,
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@@ -32,6 +33,11 @@
|
|||||||
#define UART_ERRATA_i202_MDR1_ACCESS (1 << 0)
|
#define UART_ERRATA_i202_MDR1_ACCESS (1 << 0)
|
||||||
#define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1)
|
#define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1)
|
||||||
#define OMAP_DMA_TX_KICK (1 << 2)
|
#define OMAP_DMA_TX_KICK (1 << 2)
|
||||||
|
/*
|
||||||
|
* See Advisory 21 in AM437x errata SPRZ408B, updated April 2015.
|
||||||
|
* The same errata is applicable to AM335x and DRA7x processors too.
|
||||||
|
*/
|
||||||
|
#define UART_ERRATA_CLOCK_DISABLE (1 << 3)
|
||||||
|
|
||||||
#define OMAP_UART_FCR_RX_TRIG 6
|
#define OMAP_UART_FCR_RX_TRIG 6
|
||||||
#define OMAP_UART_FCR_TX_TRIG 4
|
#define OMAP_UART_FCR_TX_TRIG 4
|
||||||
@@ -53,6 +59,12 @@
|
|||||||
#define OMAP_UART_MVR_MAJ_SHIFT 8
|
#define OMAP_UART_MVR_MAJ_SHIFT 8
|
||||||
#define OMAP_UART_MVR_MIN_MASK 0x3f
|
#define OMAP_UART_MVR_MIN_MASK 0x3f
|
||||||
|
|
||||||
|
/* SYSC register bitmasks */
|
||||||
|
#define OMAP_UART_SYSC_SOFTRESET (1 << 1)
|
||||||
|
|
||||||
|
/* SYSS register bitmasks */
|
||||||
|
#define OMAP_UART_SYSS_RESETDONE (1 << 0)
|
||||||
|
|
||||||
#define UART_TI752_TLR_TX 0
|
#define UART_TI752_TLR_TX 0
|
||||||
#define UART_TI752_TLR_RX 4
|
#define UART_TI752_TLR_RX 4
|
||||||
|
|
||||||
@@ -100,6 +112,7 @@ struct omap8250_priv {
|
|||||||
struct work_struct qos_work;
|
struct work_struct qos_work;
|
||||||
struct uart_8250_dma omap8250_dma;
|
struct uart_8250_dma omap8250_dma;
|
||||||
spinlock_t rx_dma_lock;
|
spinlock_t rx_dma_lock;
|
||||||
|
bool rx_dma_broken;
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 uart_read(struct uart_8250_port *up, u32 reg)
|
static u32 uart_read(struct uart_8250_port *up, u32 reg)
|
||||||
@@ -232,6 +245,15 @@ static void omap8250_update_scr(struct uart_8250_port *up,
|
|||||||
serial_out(up, UART_OMAP_SCR, priv->scr);
|
serial_out(up, UART_OMAP_SCR, priv->scr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void omap8250_update_mdr1(struct uart_8250_port *up,
|
||||||
|
struct omap8250_priv *priv)
|
||||||
|
{
|
||||||
|
if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
|
||||||
|
omap_8250_mdr1_errataset(up, priv);
|
||||||
|
else
|
||||||
|
serial_out(up, UART_OMAP_MDR1, priv->mdr1);
|
||||||
|
}
|
||||||
|
|
||||||
static void omap8250_restore_regs(struct uart_8250_port *up)
|
static void omap8250_restore_regs(struct uart_8250_port *up)
|
||||||
{
|
{
|
||||||
struct omap8250_priv *priv = up->port.private_data;
|
struct omap8250_priv *priv = up->port.private_data;
|
||||||
@@ -282,11 +304,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
|
|||||||
serial_out(up, UART_XOFF1, priv->xoff);
|
serial_out(up, UART_XOFF1, priv->xoff);
|
||||||
|
|
||||||
serial_out(up, UART_LCR, up->lcr);
|
serial_out(up, UART_LCR, up->lcr);
|
||||||
/* need mode A for FCR */
|
|
||||||
if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
|
omap8250_update_mdr1(up, priv);
|
||||||
omap_8250_mdr1_errataset(up, priv);
|
|
||||||
else
|
|
||||||
serial_out(up, UART_OMAP_MDR1, priv->mdr1);
|
|
||||||
up->port.ops->set_mctrl(&up->port, up->port.mctrl);
|
up->port.ops->set_mctrl(&up->port, up->port.mctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,12 +448,9 @@ static void omap_8250_set_termios(struct uart_port *port,
|
|||||||
priv->efr |= UART_EFR_CTS;
|
priv->efr |= UART_EFR_CTS;
|
||||||
} else if (up->port.flags & UPF_SOFT_FLOW) {
|
} else if (up->port.flags & UPF_SOFT_FLOW) {
|
||||||
/*
|
/*
|
||||||
* IXON Flag:
|
* OMAP rx s/w flow control is borked; the transmitter remains
|
||||||
* Enable XON/XOFF flow control on input.
|
* stuck off even if rx flow control is subsequently disabled
|
||||||
* Receiver compares XON1, XOFF1.
|
|
||||||
*/
|
*/
|
||||||
if (termios->c_iflag & IXON)
|
|
||||||
priv->efr |= OMAP_UART_SW_RX;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IXOFF Flag:
|
* IXOFF Flag:
|
||||||
@@ -444,15 +461,6 @@ static void omap_8250_set_termios(struct uart_port *port,
|
|||||||
up->port.status |= UPSTAT_AUTOXOFF;
|
up->port.status |= UPSTAT_AUTOXOFF;
|
||||||
priv->efr |= OMAP_UART_SW_TX;
|
priv->efr |= OMAP_UART_SW_TX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* IXANY Flag:
|
|
||||||
* Enable any character to restart output.
|
|
||||||
* Operation resumes after receiving any
|
|
||||||
* character after recognition of the XOFF character
|
|
||||||
*/
|
|
||||||
if (termios->c_iflag & IXANY)
|
|
||||||
up->mcr |= UART_MCR_XONANY;
|
|
||||||
}
|
}
|
||||||
omap8250_restore_regs(up);
|
omap8250_restore_regs(up);
|
||||||
|
|
||||||
@@ -530,14 +538,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
|
|||||||
|
|
||||||
switch (revision) {
|
switch (revision) {
|
||||||
case OMAP_UART_REV_46:
|
case OMAP_UART_REV_46:
|
||||||
priv->habit = UART_ERRATA_i202_MDR1_ACCESS;
|
priv->habit |= UART_ERRATA_i202_MDR1_ACCESS;
|
||||||
break;
|
break;
|
||||||
case OMAP_UART_REV_52:
|
case OMAP_UART_REV_52:
|
||||||
priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
|
priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
|
||||||
OMAP_UART_WER_HAS_TX_WAKEUP;
|
OMAP_UART_WER_HAS_TX_WAKEUP;
|
||||||
break;
|
break;
|
||||||
case OMAP_UART_REV_63:
|
case OMAP_UART_REV_63:
|
||||||
priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
|
priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
|
||||||
OMAP_UART_WER_HAS_TX_WAKEUP;
|
OMAP_UART_WER_HAS_TX_WAKEUP;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -754,6 +762,7 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
|
|||||||
struct omap8250_priv *priv = p->port.private_data;
|
struct omap8250_priv *priv = p->port.private_data;
|
||||||
struct uart_8250_dma *dma = p->dma;
|
struct uart_8250_dma *dma = p->dma;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->rx_dma_lock, flags);
|
spin_lock_irqsave(&priv->rx_dma_lock, flags);
|
||||||
|
|
||||||
@@ -762,7 +771,9 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dmaengine_pause(dma->rxchan);
|
ret = dmaengine_pause(dma->rxchan);
|
||||||
|
if (WARN_ON_ONCE(ret))
|
||||||
|
priv->rx_dma_broken = true;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
|
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
|
||||||
|
|
||||||
@@ -806,6 +817,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->rx_dma_broken)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->rx_dma_lock, flags);
|
spin_lock_irqsave(&priv->rx_dma_lock, flags);
|
||||||
|
|
||||||
if (dma->rx_running)
|
if (dma->rx_running)
|
||||||
@@ -1054,6 +1068,20 @@ static int omap8250_no_handle_irq(struct uart_port *port)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
|
||||||
|
static const u8 am4372_habit = UART_ERRATA_CLOCK_DISABLE;
|
||||||
|
|
||||||
|
static const struct of_device_id omap8250_dt_ids[] = {
|
||||||
|
{ .compatible = "ti,omap2-uart" },
|
||||||
|
{ .compatible = "ti,omap3-uart" },
|
||||||
|
{ .compatible = "ti,omap4-uart" },
|
||||||
|
{ .compatible = "ti,am3352-uart", .data = &am3352_habit, },
|
||||||
|
{ .compatible = "ti,am4372-uart", .data = &am4372_habit, },
|
||||||
|
{ .compatible = "ti,dra742-uart", .data = &am4372_habit, },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
|
||||||
|
|
||||||
static int omap8250_probe(struct platform_device *pdev)
|
static int omap8250_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
@@ -1118,11 +1146,17 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||||||
up.port.unthrottle = omap_8250_unthrottle;
|
up.port.unthrottle = omap_8250_unthrottle;
|
||||||
|
|
||||||
if (pdev->dev.of_node) {
|
if (pdev->dev.of_node) {
|
||||||
|
const struct of_device_id *id;
|
||||||
|
|
||||||
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||||
|
|
||||||
of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
||||||
&up.port.uartclk);
|
&up.port.uartclk);
|
||||||
priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
|
priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
|
||||||
|
|
||||||
|
id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
|
||||||
|
if (id && id->data)
|
||||||
|
priv->habit |= *(u8 *)id->data;
|
||||||
} else {
|
} else {
|
||||||
ret = pdev->id;
|
ret = pdev->id;
|
||||||
}
|
}
|
||||||
@@ -1180,6 +1214,11 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
if (of_machine_is_compatible("ti,am33xx"))
|
if (of_machine_is_compatible("ti,am33xx"))
|
||||||
priv->habit |= OMAP_DMA_TX_KICK;
|
priv->habit |= OMAP_DMA_TX_KICK;
|
||||||
|
/*
|
||||||
|
* pause is currently not supported atleast on omap-sdma
|
||||||
|
* and edma on most earlier kernels.
|
||||||
|
*/
|
||||||
|
priv->rx_dma_broken = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1257,17 +1296,46 @@ static int omap8250_lost_context(struct uart_8250_port *up)
|
|||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
val = serial_in(up, UART_OMAP_MDR1);
|
val = serial_in(up, UART_OMAP_SCR);
|
||||||
/*
|
/*
|
||||||
* If we lose context, then MDR1 is set to its reset value which is
|
* If we lose context, then SCR is set to its reset value of zero.
|
||||||
* UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x
|
* After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1,
|
||||||
* or 16x but never to disable again.
|
* among other bits, to never set the register back to zero again.
|
||||||
*/
|
*/
|
||||||
if (val == UART_OMAP_MDR1_DISABLE)
|
if (!val)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: in future, this should happen via API in drivers/reset/ */
|
||||||
|
static int omap8250_soft_reset(struct device *dev)
|
||||||
|
{
|
||||||
|
struct omap8250_priv *priv = dev_get_drvdata(dev);
|
||||||
|
struct uart_8250_port *up = serial8250_get_port(priv->line);
|
||||||
|
int timeout = 100;
|
||||||
|
int sysc;
|
||||||
|
int syss;
|
||||||
|
|
||||||
|
sysc = serial_in(up, UART_OMAP_SYSC);
|
||||||
|
|
||||||
|
/* softreset the UART */
|
||||||
|
sysc |= OMAP_UART_SYSC_SOFTRESET;
|
||||||
|
serial_out(up, UART_OMAP_SYSC, sysc);
|
||||||
|
|
||||||
|
/* By experiments, 1us enough for reset complete on AM335x */
|
||||||
|
do {
|
||||||
|
udelay(1);
|
||||||
|
syss = serial_in(up, UART_OMAP_SYSS);
|
||||||
|
} while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE));
|
||||||
|
|
||||||
|
if (!timeout) {
|
||||||
|
dev_err(dev, "timed out waiting for reset done\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int omap8250_runtime_suspend(struct device *dev)
|
static int omap8250_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct omap8250_priv *priv = dev_get_drvdata(dev);
|
struct omap8250_priv *priv = dev_get_drvdata(dev);
|
||||||
@@ -1285,7 +1353,18 @@ static int omap8250_runtime_suspend(struct device *dev)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (up->dma)
|
if (priv->habit & UART_ERRATA_CLOCK_DISABLE) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = omap8250_soft_reset(dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Restore to UART mode after reset (for wakeup) */
|
||||||
|
omap8250_update_mdr1(up, priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (up->dma && up->dma->rxchan)
|
||||||
omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT);
|
omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT);
|
||||||
|
|
||||||
priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
|
priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
|
||||||
@@ -1310,7 +1389,7 @@ static int omap8250_runtime_resume(struct device *dev)
|
|||||||
if (loss_cntx)
|
if (loss_cntx)
|
||||||
omap8250_restore_regs(up);
|
omap8250_restore_regs(up);
|
||||||
|
|
||||||
if (up->dma)
|
if (up->dma && up->dma->rxchan)
|
||||||
omap_8250_rx_dma(up, 0);
|
omap_8250_rx_dma(up, 0);
|
||||||
|
|
||||||
priv->latency = priv->calc_latency;
|
priv->latency = priv->calc_latency;
|
||||||
@@ -1367,14 +1446,6 @@ static const struct dev_pm_ops omap8250_dev_pm_ops = {
|
|||||||
.complete = omap8250_complete,
|
.complete = omap8250_complete,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id omap8250_dt_ids[] = {
|
|
||||||
{ .compatible = "ti,omap2-uart" },
|
|
||||||
{ .compatible = "ti,omap3-uart" },
|
|
||||||
{ .compatible = "ti,omap4-uart" },
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
|
|
||||||
|
|
||||||
static struct platform_driver omap8250_platform_driver = {
|
static struct platform_driver omap8250_platform_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "omap8250",
|
.name = "omap8250",
|
||||||
|
@@ -1417,6 +1417,10 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
|
|||||||
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
|
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
|
||||||
writel(reg, p->membase + BYT_PRV_CLK);
|
writel(reg, p->membase + BYT_PRV_CLK);
|
||||||
|
|
||||||
|
p->status &= ~UPSTAT_AUTOCTS;
|
||||||
|
if (termios->c_cflag & CRTSCTS)
|
||||||
|
p->status |= UPSTAT_AUTOCTS;
|
||||||
|
|
||||||
serial8250_do_set_termios(p, termios, old);
|
serial8250_do_set_termios(p, termios, old);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1685,11 +1689,65 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* RTS will control by MCR if this bit is 0 */
|
||||||
|
#define FINTEK_RTS_CONTROL_BY_HW BIT(4)
|
||||||
|
/* only worked with FINTEK_RTS_CONTROL_BY_HW on */
|
||||||
|
#define FINTEK_RTS_INVERT BIT(5)
|
||||||
|
|
||||||
|
/* We should do proper H/W transceiver setting before change to RS485 mode */
|
||||||
|
static int pci_fintek_rs485_config(struct uart_port *port,
|
||||||
|
struct serial_rs485 *rs485)
|
||||||
|
{
|
||||||
|
u8 setting;
|
||||||
|
u8 *index = (u8 *) port->private_data;
|
||||||
|
struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev,
|
||||||
|
dev);
|
||||||
|
|
||||||
|
pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting);
|
||||||
|
|
||||||
|
if (!rs485)
|
||||||
|
rs485 = &port->rs485;
|
||||||
|
else if (rs485->flags & SER_RS485_ENABLED)
|
||||||
|
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||||
|
else
|
||||||
|
memset(rs485, 0, sizeof(*rs485));
|
||||||
|
|
||||||
|
/* F81504/508/512 not support RTS delay before or after send */
|
||||||
|
rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
|
||||||
|
|
||||||
|
if (rs485->flags & SER_RS485_ENABLED) {
|
||||||
|
/* Enable RTS H/W control mode */
|
||||||
|
setting |= FINTEK_RTS_CONTROL_BY_HW;
|
||||||
|
|
||||||
|
if (rs485->flags & SER_RS485_RTS_ON_SEND) {
|
||||||
|
/* RTS driving high on TX */
|
||||||
|
setting &= ~FINTEK_RTS_INVERT;
|
||||||
|
} else {
|
||||||
|
/* RTS driving low on TX */
|
||||||
|
setting |= FINTEK_RTS_INVERT;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs485->delay_rts_after_send = 0;
|
||||||
|
rs485->delay_rts_before_send = 0;
|
||||||
|
} else {
|
||||||
|
/* Disable RTS H/W control mode */
|
||||||
|
setting &= ~(FINTEK_RTS_CONTROL_BY_HW | FINTEK_RTS_INVERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_write_config_byte(pci_dev, 0x40 + 8 * *index + 7, setting);
|
||||||
|
|
||||||
|
if (rs485 != &port->rs485)
|
||||||
|
port->rs485 = *rs485;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int pci_fintek_setup(struct serial_private *priv,
|
static int pci_fintek_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_8250_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = priv->dev;
|
struct pci_dev *pdev = priv->dev;
|
||||||
|
u8 *data;
|
||||||
u8 config_base;
|
u8 config_base;
|
||||||
u16 iobase;
|
u16 iobase;
|
||||||
|
|
||||||
@@ -1702,6 +1760,15 @@ static int pci_fintek_setup(struct serial_private *priv,
|
|||||||
|
|
||||||
port->port.iotype = UPIO_PORT;
|
port->port.iotype = UPIO_PORT;
|
||||||
port->port.iobase = iobase;
|
port->port.iobase = iobase;
|
||||||
|
port->port.rs485_config = pci_fintek_rs485_config;
|
||||||
|
|
||||||
|
data = devm_kzalloc(&pdev->dev, sizeof(u8), GFP_KERNEL);
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* preserve index in PCI configuration space */
|
||||||
|
*data = idx;
|
||||||
|
port->port.private_data = data;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1712,6 +1779,8 @@ static int pci_fintek_init(struct pci_dev *dev)
|
|||||||
u32 max_port, i;
|
u32 max_port, i;
|
||||||
u32 bar_data[3];
|
u32 bar_data[3];
|
||||||
u8 config_base;
|
u8 config_base;
|
||||||
|
struct serial_private *priv = pci_get_drvdata(dev);
|
||||||
|
struct uart_8250_port *port;
|
||||||
|
|
||||||
switch (dev->device) {
|
switch (dev->device) {
|
||||||
case 0x1104: /* 4 ports */
|
case 0x1104: /* 4 ports */
|
||||||
@@ -1752,6 +1821,19 @@ static int pci_fintek_init(struct pci_dev *dev)
|
|||||||
(u8)((iobase & 0xff00) >> 8));
|
(u8)((iobase & 0xff00) >> 8));
|
||||||
|
|
||||||
pci_write_config_byte(dev, config_base + 0x06, dev->irq);
|
pci_write_config_byte(dev, config_base + 0x06, dev->irq);
|
||||||
|
|
||||||
|
if (priv) {
|
||||||
|
/* re-apply RS232/485 mode when
|
||||||
|
* pciserial_resume_ports()
|
||||||
|
*/
|
||||||
|
port = serial8250_get_port(priv->line[i]);
|
||||||
|
pci_fintek_rs485_config(&port->port, NULL);
|
||||||
|
} else {
|
||||||
|
/* First init without port data
|
||||||
|
* force init to RS232 Mode
|
||||||
|
*/
|
||||||
|
pci_write_config_byte(dev, config_base + 0x07, 0x01);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return max_port;
|
return max_port;
|
||||||
@@ -2017,6 +2099,12 @@ pci_wch_ch38x_setup(struct serial_private *priv,
|
|||||||
#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
|
#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
|
||||||
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
|
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
|
||||||
|
|
||||||
|
#define PCI_VENDOR_ID_PERICOM 0x12D8
|
||||||
|
#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
|
||||||
|
#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
|
||||||
|
#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954
|
||||||
|
#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958
|
||||||
|
|
||||||
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
|
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
|
||||||
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
|
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
|
||||||
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
|
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
|
||||||
@@ -2331,27 +2419,12 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
|||||||
* Pericom
|
* Pericom
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
.vendor = 0x12d8,
|
.vendor = PCI_VENDOR_ID_PERICOM,
|
||||||
.device = 0x7952,
|
.device = PCI_ANY_ID,
|
||||||
.subvendor = PCI_ANY_ID,
|
.subvendor = PCI_ANY_ID,
|
||||||
.subdevice = PCI_ANY_ID,
|
.subdevice = PCI_ANY_ID,
|
||||||
.setup = pci_pericom_setup,
|
.setup = pci_pericom_setup,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.vendor = 0x12d8,
|
|
||||||
.device = 0x7954,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.setup = pci_pericom_setup,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = 0x12d8,
|
|
||||||
.device = 0x7958,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.setup = pci_pericom_setup,
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PLX
|
* PLX
|
||||||
*/
|
*/
|
||||||
@@ -3056,6 +3129,10 @@ enum pci_board_num_t {
|
|||||||
pbn_fintek_8,
|
pbn_fintek_8,
|
||||||
pbn_fintek_12,
|
pbn_fintek_12,
|
||||||
pbn_wch384_4,
|
pbn_wch384_4,
|
||||||
|
pbn_pericom_PI7C9X7951,
|
||||||
|
pbn_pericom_PI7C9X7952,
|
||||||
|
pbn_pericom_PI7C9X7954,
|
||||||
|
pbn_pericom_PI7C9X7958,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3881,7 +3958,6 @@ static struct pciserial_board pci_boards[] = {
|
|||||||
.base_baud = 115200,
|
.base_baud = 115200,
|
||||||
.first_offset = 0x40,
|
.first_offset = 0x40,
|
||||||
},
|
},
|
||||||
|
|
||||||
[pbn_wch384_4] = {
|
[pbn_wch384_4] = {
|
||||||
.flags = FL_BASE0,
|
.flags = FL_BASE0,
|
||||||
.num_ports = 4,
|
.num_ports = 4,
|
||||||
@@ -3889,6 +3965,33 @@ static struct pciserial_board pci_boards[] = {
|
|||||||
.uart_offset = 8,
|
.uart_offset = 8,
|
||||||
.first_offset = 0xC0,
|
.first_offset = 0xC0,
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
|
* Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
|
||||||
|
*/
|
||||||
|
[pbn_pericom_PI7C9X7951] = {
|
||||||
|
.flags = FL_BASE0,
|
||||||
|
.num_ports = 1,
|
||||||
|
.base_baud = 921600,
|
||||||
|
.uart_offset = 0x8,
|
||||||
|
},
|
||||||
|
[pbn_pericom_PI7C9X7952] = {
|
||||||
|
.flags = FL_BASE0,
|
||||||
|
.num_ports = 2,
|
||||||
|
.base_baud = 921600,
|
||||||
|
.uart_offset = 0x8,
|
||||||
|
},
|
||||||
|
[pbn_pericom_PI7C9X7954] = {
|
||||||
|
.flags = FL_BASE0,
|
||||||
|
.num_ports = 4,
|
||||||
|
.base_baud = 921600,
|
||||||
|
.uart_offset = 0x8,
|
||||||
|
},
|
||||||
|
[pbn_pericom_PI7C9X7958] = {
|
||||||
|
.flags = FL_BASE0,
|
||||||
|
.num_ports = 8,
|
||||||
|
.base_baud = 921600,
|
||||||
|
.uart_offset = 0x8,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pci_device_id blacklist[] = {
|
static const struct pci_device_id blacklist[] = {
|
||||||
@@ -5153,6 +5256,25 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|||||||
PCI_ANY_ID, PCI_ANY_ID,
|
PCI_ANY_ID, PCI_ANY_ID,
|
||||||
0,
|
0,
|
||||||
0, pbn_exar_XR17V8358 },
|
0, pbn_exar_XR17V8358 },
|
||||||
|
/*
|
||||||
|
* Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
|
||||||
|
*/
|
||||||
|
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID,
|
||||||
|
0,
|
||||||
|
0, pbn_pericom_PI7C9X7951 },
|
||||||
|
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID,
|
||||||
|
0,
|
||||||
|
0, pbn_pericom_PI7C9X7952 },
|
||||||
|
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID,
|
||||||
|
0,
|
||||||
|
0, pbn_pericom_PI7C9X7954 },
|
||||||
|
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID,
|
||||||
|
0,
|
||||||
|
0, pbn_pericom_PI7C9X7958 },
|
||||||
/*
|
/*
|
||||||
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
|
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
|
||||||
*/
|
*/
|
||||||
|
@@ -41,6 +41,12 @@ static const struct pnp_device_id pnp_dev_table[] = {
|
|||||||
{ "AEI1240", 0 },
|
{ "AEI1240", 0 },
|
||||||
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
||||||
{ "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
|
{ "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
|
||||||
|
/*
|
||||||
|
* ALi Fast Infrared Controller
|
||||||
|
* Native driver (ali-ircc) is broken so at least
|
||||||
|
* it can be used with irtty-sir.
|
||||||
|
*/
|
||||||
|
{ "ALI5123", 0 },
|
||||||
/* AZT3005 PnP SOUND DEVICE */
|
/* AZT3005 PnP SOUND DEVICE */
|
||||||
{ "AZT4001", 0 },
|
{ "AZT4001", 0 },
|
||||||
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
||||||
@@ -364,6 +370,11 @@ static const struct pnp_device_id pnp_dev_table[] = {
|
|||||||
/* Winbond CIR port, should not be probed. We should keep track
|
/* Winbond CIR port, should not be probed. We should keep track
|
||||||
of it to prevent the legacy serial driver from probing it */
|
of it to prevent the legacy serial driver from probing it */
|
||||||
{ "WEC1022", CIR_PORT },
|
{ "WEC1022", CIR_PORT },
|
||||||
|
/*
|
||||||
|
* SMSC IrCC SIR/FIR port, should not be probed by serial driver
|
||||||
|
* as well so its own driver can bind to it.
|
||||||
|
*/
|
||||||
|
{ "SMCF010", CIR_PORT },
|
||||||
{ "", 0 }
|
{ "", 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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);
|
ret = serial8250_register_8250_port(&up);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "failed to register 8250 port\n");
|
dev_err(dev, "failed to register 8250 port\n");
|
||||||
|
clk_disable_unprepare(priv->clk);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,10 +2,11 @@
|
|||||||
# Makefile for the 8250 serial device drivers.
|
# Makefile for the 8250 serial device drivers.
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-$(CONFIG_SERIAL_8250) += 8250.o
|
obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o
|
||||||
8250-y := 8250_core.o
|
8250-y := 8250_core.o
|
||||||
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
|
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
|
||||||
8250-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
|
8250_base-y := 8250_port.o
|
||||||
|
8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
|
||||||
obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
|
obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
|
||||||
obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
|
obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
|
||||||
obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
|
obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
|
||||||
|
@@ -47,12 +47,12 @@ config SERIAL_AMBA_PL010_CONSOLE
|
|||||||
|
|
||||||
config SERIAL_AMBA_PL011
|
config SERIAL_AMBA_PL011
|
||||||
tristate "ARM AMBA PL011 serial port support"
|
tristate "ARM AMBA PL011 serial port support"
|
||||||
depends on ARM_AMBA
|
depends on ARM_AMBA || SOC_ZX296702
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
help
|
help
|
||||||
This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have
|
This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have
|
||||||
an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M
|
an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M
|
||||||
here.
|
here. Say Y or M if you have SOC_ZX296702.
|
||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
@@ -594,7 +594,7 @@ config SERIAL_IMX_CONSOLE
|
|||||||
|
|
||||||
config SERIAL_UARTLITE
|
config SERIAL_UARTLITE
|
||||||
tristate "Xilinx uartlite serial port support"
|
tristate "Xilinx uartlite serial port support"
|
||||||
depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE || ARCH_ZYNQ
|
depends on HAS_IOMEM
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
help
|
help
|
||||||
Say Y here if you want to use the Xilinx uartlite serial controller.
|
Say Y here if you want to use the Xilinx uartlite serial controller.
|
||||||
@@ -1067,6 +1067,7 @@ config SERIAL_ETRAXFS
|
|||||||
bool "ETRAX FS serial port support"
|
bool "ETRAX FS serial port support"
|
||||||
depends on ETRAX_ARCH_V32 && OF
|
depends on ETRAX_ARCH_V32 && OF
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
|
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||||
|
|
||||||
config SERIAL_ETRAXFS_CONSOLE
|
config SERIAL_ETRAXFS_CONSOLE
|
||||||
bool "ETRAX FS serial console support"
|
bool "ETRAX FS serial console support"
|
||||||
@@ -1376,7 +1377,8 @@ config SERIAL_ALTERA_UART_CONSOLE
|
|||||||
|
|
||||||
config SERIAL_IFX6X60
|
config SERIAL_IFX6X60
|
||||||
tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
|
tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
|
||||||
depends on GPIOLIB && SPI && HAS_DMA
|
depends on GPIOLIB || COMPILE_TEST
|
||||||
|
depends on SPI && HAS_DMA
|
||||||
help
|
help
|
||||||
Support for the IFX6x60 modem devices on Intel MID platforms.
|
Support for the IFX6x60 modem devices on Intel MID platforms.
|
||||||
|
|
||||||
|
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 <linux/of_address.h>
|
||||||
#include <hwregs/ser_defs.h>
|
#include <hwregs/ser_defs.h>
|
||||||
|
|
||||||
|
#include "serial_mctrl_gpio.h"
|
||||||
|
|
||||||
#define DRV_NAME "etraxfs-uart"
|
#define DRV_NAME "etraxfs-uart"
|
||||||
#define UART_NR CONFIG_ETRAX_SERIAL_PORTS
|
#define UART_NR CONFIG_ETRAX_SERIAL_PORTS
|
||||||
|
|
||||||
@@ -28,10 +30,7 @@ struct uart_cris_port {
|
|||||||
|
|
||||||
void __iomem *regi_ser;
|
void __iomem *regi_ser;
|
||||||
|
|
||||||
struct gpio_desc *dtr_pin;
|
struct mctrl_gpios *gpios;
|
||||||
struct gpio_desc *dsr_pin;
|
|
||||||
struct gpio_desc *ri_pin;
|
|
||||||
struct gpio_desc *cd_pin;
|
|
||||||
|
|
||||||
int write_ongoing;
|
int write_ongoing;
|
||||||
};
|
};
|
||||||
@@ -112,17 +111,10 @@ cris_console_setup(struct console *co, char *options)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tty_driver *cris_console_device(struct console *co, int *index)
|
|
||||||
{
|
|
||||||
struct uart_driver *p = co->data;
|
|
||||||
*index = co->index;
|
|
||||||
return p->tty_driver;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct console cris_console = {
|
static struct console cris_console = {
|
||||||
.name = "ttyS",
|
.name = "ttyS",
|
||||||
.write = cris_console_write,
|
.write = cris_console_write,
|
||||||
.device = cris_console_device,
|
.device = uart_console_device,
|
||||||
.setup = cris_console_setup,
|
.setup = cris_console_setup,
|
||||||
.flags = CON_PRINTBUFFER,
|
.flags = CON_PRINTBUFFER,
|
||||||
.index = -1,
|
.index = -1,
|
||||||
@@ -373,14 +365,6 @@ static void etraxfs_uart_stop_rx(struct uart_port *port)
|
|||||||
REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
|
REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void etraxfs_uart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_modem_status(struct uart_cris_port *up)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int etraxfs_uart_tx_empty(struct uart_port *port)
|
static unsigned int etraxfs_uart_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_cris_port *up = (struct uart_cris_port *)port;
|
struct uart_cris_port *up = (struct uart_cris_port *)port;
|
||||||
@@ -404,21 +388,9 @@ static unsigned int etraxfs_uart_get_mctrl(struct uart_port *port)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
if (crisv32_serial_get_rts(up))
|
if (crisv32_serial_get_rts(up))
|
||||||
ret |= TIOCM_RTS;
|
ret |= TIOCM_RTS;
|
||||||
/* DTR is active low */
|
|
||||||
if (up->dtr_pin && !gpiod_get_raw_value(up->dtr_pin))
|
|
||||||
ret |= TIOCM_DTR;
|
|
||||||
/* CD is active low */
|
|
||||||
if (up->cd_pin && !gpiod_get_raw_value(up->cd_pin))
|
|
||||||
ret |= TIOCM_CD;
|
|
||||||
/* RI is active low */
|
|
||||||
if (up->ri_pin && !gpiod_get_raw_value(up->ri_pin))
|
|
||||||
ret |= TIOCM_RI;
|
|
||||||
/* DSR is active low */
|
|
||||||
if (up->dsr_pin && !gpiod_get_raw_value(up->dsr_pin))
|
|
||||||
ret |= TIOCM_DSR;
|
|
||||||
if (crisv32_serial_get_cts(up))
|
if (crisv32_serial_get_cts(up))
|
||||||
ret |= TIOCM_CTS;
|
ret |= TIOCM_CTS;
|
||||||
return ret;
|
return mctrl_gpio_get(up->gpios, &ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
@@ -426,15 +398,7 @@ static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||||||
struct uart_cris_port *up = (struct uart_cris_port *)port;
|
struct uart_cris_port *up = (struct uart_cris_port *)port;
|
||||||
|
|
||||||
crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0);
|
crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0);
|
||||||
/* DTR is active low */
|
mctrl_gpio_set(up->gpios, mctrl);
|
||||||
if (up->dtr_pin)
|
|
||||||
gpiod_set_raw_value(up->dtr_pin, mctrl & TIOCM_DTR ? 0 : 1);
|
|
||||||
/* RI is active low */
|
|
||||||
if (up->ri_pin)
|
|
||||||
gpiod_set_raw_value(up->ri_pin, mctrl & TIOCM_RNG ? 0 : 1);
|
|
||||||
/* CD is active low */
|
|
||||||
if (up->cd_pin)
|
|
||||||
gpiod_set_raw_value(up->cd_pin, mctrl & TIOCM_CD ? 0 : 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state)
|
static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state)
|
||||||
@@ -598,7 +562,6 @@ ser_interrupt(int irq, void *dev_id)
|
|||||||
receive_chars_no_dma(up);
|
receive_chars_no_dma(up);
|
||||||
handled = 1;
|
handled = 1;
|
||||||
}
|
}
|
||||||
check_modem_status(up);
|
|
||||||
|
|
||||||
if (masked_intr.tr_rdy) {
|
if (masked_intr.tr_rdy) {
|
||||||
transmit_chars_no_dma(up);
|
transmit_chars_no_dma(up);
|
||||||
@@ -862,7 +825,6 @@ static const struct uart_ops etraxfs_uart_pops = {
|
|||||||
.start_tx = etraxfs_uart_start_tx,
|
.start_tx = etraxfs_uart_start_tx,
|
||||||
.send_xchar = etraxfs_uart_send_xchar,
|
.send_xchar = etraxfs_uart_send_xchar,
|
||||||
.stop_rx = etraxfs_uart_stop_rx,
|
.stop_rx = etraxfs_uart_stop_rx,
|
||||||
.enable_ms = etraxfs_uart_enable_ms,
|
|
||||||
.break_ctl = etraxfs_uart_break_ctl,
|
.break_ctl = etraxfs_uart_break_ctl,
|
||||||
.startup = etraxfs_uart_startup,
|
.startup = etraxfs_uart_startup,
|
||||||
.shutdown = etraxfs_uart_shutdown,
|
.shutdown = etraxfs_uart_shutdown,
|
||||||
@@ -930,11 +892,12 @@ static int etraxfs_uart_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
up->irq = irq_of_parse_and_map(np, 0);
|
up->irq = irq_of_parse_and_map(np, 0);
|
||||||
up->regi_ser = of_iomap(np, 0);
|
up->regi_ser = of_iomap(np, 0);
|
||||||
up->dtr_pin = devm_gpiod_get_optional(&pdev->dev, "dtr");
|
|
||||||
up->dsr_pin = devm_gpiod_get_optional(&pdev->dev, "dsr");
|
|
||||||
up->ri_pin = devm_gpiod_get_optional(&pdev->dev, "ri");
|
|
||||||
up->cd_pin = devm_gpiod_get_optional(&pdev->dev, "cd");
|
|
||||||
up->port.dev = &pdev->dev;
|
up->port.dev = &pdev->dev;
|
||||||
|
|
||||||
|
up->gpios = mctrl_gpio_init(&pdev->dev, 0);
|
||||||
|
if (IS_ERR(up->gpios))
|
||||||
|
return PTR_ERR(up->gpios);
|
||||||
|
|
||||||
cris_serial_port_init(&up->port, dev_id);
|
cris_serial_port_init(&up->port, dev_id);
|
||||||
|
|
||||||
etraxfs_uart_ports[dev_id] = up;
|
etraxfs_uart_ports[dev_id] = up;
|
||||||
|
@@ -216,6 +216,8 @@ struct imx_port {
|
|||||||
unsigned int tx_bytes;
|
unsigned int tx_bytes;
|
||||||
unsigned int dma_tx_nents;
|
unsigned int dma_tx_nents;
|
||||||
wait_queue_head_t dma_wait;
|
wait_queue_head_t dma_wait;
|
||||||
|
unsigned int saved_reg[10];
|
||||||
|
bool context_saved;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct imx_port_ucrs {
|
struct imx_port_ucrs {
|
||||||
@@ -700,7 +702,8 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
|
|||||||
if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
|
if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
tty_insert_flip_char(port, rx, flg);
|
if (tty_insert_flip_char(port, rx, flg) == 0)
|
||||||
|
sport->port.icount.buf_overrun++;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -766,7 +769,6 @@ static irqreturn_t imx_int(int irq, void *dev_id)
|
|||||||
writel(USR1_AWAKE, sport->port.membase + USR1);
|
writel(USR1_AWAKE, sport->port.membase + USR1);
|
||||||
|
|
||||||
if (sts2 & USR2_ORE) {
|
if (sts2 & USR2_ORE) {
|
||||||
dev_err(sport->port.dev, "Rx FIFO overrun\n");
|
|
||||||
sport->port.icount.overrun++;
|
sport->port.icount.overrun++;
|
||||||
writel(USR2_ORE, sport->port.membase + USR2);
|
writel(USR2_ORE, sport->port.membase + USR2);
|
||||||
}
|
}
|
||||||
@@ -921,8 +923,13 @@ static void dma_rx_callback(void *data)
|
|||||||
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
|
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
|
||||||
|
|
||||||
if (count) {
|
if (count) {
|
||||||
if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ))
|
if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
|
||||||
tty_insert_flip_string(port, sport->rx_buf, count);
|
int bytes = tty_insert_flip_string(port, sport->rx_buf,
|
||||||
|
count);
|
||||||
|
|
||||||
|
if (bytes != count)
|
||||||
|
sport->port.icount.buf_overrun++;
|
||||||
|
}
|
||||||
tty_flip_buffer_push(port);
|
tty_flip_buffer_push(port);
|
||||||
|
|
||||||
start_rx_dma(sport);
|
start_rx_dma(sport);
|
||||||
@@ -1624,12 +1631,12 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
|
|||||||
int locked = 1;
|
int locked = 1;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = clk_enable(sport->clk_per);
|
retval = clk_prepare_enable(sport->clk_per);
|
||||||
if (retval)
|
if (retval)
|
||||||
return;
|
return;
|
||||||
retval = clk_enable(sport->clk_ipg);
|
retval = clk_prepare_enable(sport->clk_ipg);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
clk_disable(sport->clk_per);
|
clk_disable_unprepare(sport->clk_per);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1668,8 +1675,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
|
|||||||
if (locked)
|
if (locked)
|
||||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
|
||||||
clk_disable(sport->clk_ipg);
|
clk_disable_unprepare(sport->clk_ipg);
|
||||||
clk_disable(sport->clk_per);
|
clk_disable_unprepare(sport->clk_per);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1770,15 +1777,7 @@ imx_console_setup(struct console *co, char *options)
|
|||||||
|
|
||||||
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
|
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
|
||||||
|
|
||||||
clk_disable(sport->clk_ipg);
|
clk_disable_unprepare(sport->clk_ipg);
|
||||||
if (retval) {
|
|
||||||
clk_unprepare(sport->clk_ipg);
|
|
||||||
goto error_console;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = clk_prepare(sport->clk_per);
|
|
||||||
if (retval)
|
|
||||||
clk_disable_unprepare(sport->clk_ipg);
|
|
||||||
|
|
||||||
error_console:
|
error_console:
|
||||||
return retval;
|
return retval;
|
||||||
@@ -1810,36 +1809,6 @@ static struct uart_driver imx_reg = {
|
|||||||
.cons = IMX_CONSOLE,
|
.cons = IMX_CONSOLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
|
|
||||||
{
|
|
||||||
struct imx_port *sport = platform_get_drvdata(dev);
|
|
||||||
unsigned int val;
|
|
||||||
|
|
||||||
/* enable wakeup from i.MX UART */
|
|
||||||
val = readl(sport->port.membase + UCR3);
|
|
||||||
val |= UCR3_AWAKEN;
|
|
||||||
writel(val, sport->port.membase + UCR3);
|
|
||||||
|
|
||||||
uart_suspend_port(&imx_reg, &sport->port);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int serial_imx_resume(struct platform_device *dev)
|
|
||||||
{
|
|
||||||
struct imx_port *sport = platform_get_drvdata(dev);
|
|
||||||
unsigned int val;
|
|
||||||
|
|
||||||
/* disable wakeup from i.MX UART */
|
|
||||||
val = readl(sport->port.membase + UCR3);
|
|
||||||
val &= ~UCR3_AWAKEN;
|
|
||||||
writel(val, sport->port.membase + UCR3);
|
|
||||||
|
|
||||||
uart_resume_port(&imx_reg, &sport->port);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
/*
|
/*
|
||||||
* This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
|
* This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
|
||||||
@@ -1901,7 +1870,7 @@ static int serial_imx_probe(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct imx_port *sport;
|
struct imx_port *sport;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int ret = 0;
|
int ret = 0, reg;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int txirq, rxirq, rtsirq;
|
int txirq, rxirq, rtsirq;
|
||||||
|
|
||||||
@@ -1956,6 +1925,19 @@ static int serial_imx_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
sport->port.uartclk = clk_get_rate(sport->clk_per);
|
sport->port.uartclk = clk_get_rate(sport->clk_per);
|
||||||
|
|
||||||
|
/* For register access, we only need to enable the ipg clock. */
|
||||||
|
ret = clk_prepare_enable(sport->clk_ipg);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Disable interrupts before requesting them */
|
||||||
|
reg = readl_relaxed(sport->port.membase + UCR1);
|
||||||
|
reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
|
||||||
|
UCR1_TXMPTYEN | UCR1_RTSDEN);
|
||||||
|
writel_relaxed(reg, sport->port.membase + UCR1);
|
||||||
|
|
||||||
|
clk_disable_unprepare(sport->clk_ipg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
|
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
|
||||||
* chips only have one interrupt.
|
* chips only have one interrupt.
|
||||||
@@ -1991,16 +1973,135 @@ static int serial_imx_remove(struct platform_device *pdev)
|
|||||||
return uart_remove_one_port(&imx_reg, &sport->port);
|
return uart_remove_one_port(&imx_reg, &sport->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void serial_imx_restore_context(struct imx_port *sport)
|
||||||
|
{
|
||||||
|
if (!sport->context_saved)
|
||||||
|
return;
|
||||||
|
|
||||||
|
writel(sport->saved_reg[4], sport->port.membase + UFCR);
|
||||||
|
writel(sport->saved_reg[5], sport->port.membase + UESC);
|
||||||
|
writel(sport->saved_reg[6], sport->port.membase + UTIM);
|
||||||
|
writel(sport->saved_reg[7], sport->port.membase + UBIR);
|
||||||
|
writel(sport->saved_reg[8], sport->port.membase + UBMR);
|
||||||
|
writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
|
||||||
|
writel(sport->saved_reg[0], sport->port.membase + UCR1);
|
||||||
|
writel(sport->saved_reg[1] | UCR2_SRST, sport->port.membase + UCR2);
|
||||||
|
writel(sport->saved_reg[2], sport->port.membase + UCR3);
|
||||||
|
writel(sport->saved_reg[3], sport->port.membase + UCR4);
|
||||||
|
sport->context_saved = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void serial_imx_save_context(struct imx_port *sport)
|
||||||
|
{
|
||||||
|
/* Save necessary regs */
|
||||||
|
sport->saved_reg[0] = readl(sport->port.membase + UCR1);
|
||||||
|
sport->saved_reg[1] = readl(sport->port.membase + UCR2);
|
||||||
|
sport->saved_reg[2] = readl(sport->port.membase + UCR3);
|
||||||
|
sport->saved_reg[3] = readl(sport->port.membase + UCR4);
|
||||||
|
sport->saved_reg[4] = readl(sport->port.membase + UFCR);
|
||||||
|
sport->saved_reg[5] = readl(sport->port.membase + UESC);
|
||||||
|
sport->saved_reg[6] = readl(sport->port.membase + UTIM);
|
||||||
|
sport->saved_reg[7] = readl(sport->port.membase + UBIR);
|
||||||
|
sport->saved_reg[8] = readl(sport->port.membase + UBMR);
|
||||||
|
sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
|
||||||
|
sport->context_saved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
|
||||||
|
{
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
val = readl(sport->port.membase + UCR3);
|
||||||
|
if (on)
|
||||||
|
val |= UCR3_AWAKEN;
|
||||||
|
else
|
||||||
|
val &= ~UCR3_AWAKEN;
|
||||||
|
writel(val, sport->port.membase + UCR3);
|
||||||
|
|
||||||
|
val = readl(sport->port.membase + UCR1);
|
||||||
|
if (on)
|
||||||
|
val |= UCR1_RTSDEN;
|
||||||
|
else
|
||||||
|
val &= ~UCR1_RTSDEN;
|
||||||
|
writel(val, sport->port.membase + UCR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx_serial_port_suspend_noirq(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clk_enable(sport->clk_ipg);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
serial_imx_save_context(sport);
|
||||||
|
|
||||||
|
clk_disable(sport->clk_ipg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx_serial_port_resume_noirq(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clk_enable(sport->clk_ipg);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
serial_imx_restore_context(sport);
|
||||||
|
|
||||||
|
clk_disable(sport->clk_ipg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx_serial_port_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
/* enable wakeup from i.MX UART */
|
||||||
|
serial_imx_enable_wakeup(sport, true);
|
||||||
|
|
||||||
|
uart_suspend_port(&imx_reg, &sport->port);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx_serial_port_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
/* disable wakeup from i.MX UART */
|
||||||
|
serial_imx_enable_wakeup(sport, false);
|
||||||
|
|
||||||
|
uart_resume_port(&imx_reg, &sport->port);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops imx_serial_port_pm_ops = {
|
||||||
|
.suspend_noirq = imx_serial_port_suspend_noirq,
|
||||||
|
.resume_noirq = imx_serial_port_resume_noirq,
|
||||||
|
.suspend = imx_serial_port_suspend,
|
||||||
|
.resume = imx_serial_port_resume,
|
||||||
|
};
|
||||||
|
|
||||||
static struct platform_driver serial_imx_driver = {
|
static struct platform_driver serial_imx_driver = {
|
||||||
.probe = serial_imx_probe,
|
.probe = serial_imx_probe,
|
||||||
.remove = serial_imx_remove,
|
.remove = serial_imx_remove,
|
||||||
|
|
||||||
.suspend = serial_imx_suspend,
|
|
||||||
.resume = serial_imx_resume,
|
|
||||||
.id_table = imx_uart_devtype,
|
.id_table = imx_uart_devtype,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "imx-uart",
|
.name = "imx-uart",
|
||||||
.of_match_table = imx_uart_dt_ids,
|
.of_match_table = imx_uart_dt_ids,
|
||||||
|
.pm = &imx_serial_port_pm_ops,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
@@ -740,7 +739,6 @@ static const struct of_device_id ltq_asc_match[] = {
|
|||||||
{ .compatible = DRVNAME },
|
{ .compatible = DRVNAME },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, ltq_asc_match);
|
|
||||||
|
|
||||||
static struct platform_driver lqasc_driver = {
|
static struct platform_driver lqasc_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
@@ -764,8 +762,4 @@ init_lqasc(void)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
device_initcall(init_lqasc);
|
||||||
module_init(init_lqasc);
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Lantiq serial port driver");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
@@ -392,7 +392,6 @@ static irqreturn_t men_z135_intr(int irq, void *data)
|
|||||||
struct men_z135_port *uart = (struct men_z135_port *)data;
|
struct men_z135_port *uart = (struct men_z135_port *)data;
|
||||||
struct uart_port *port = &uart->port;
|
struct uart_port *port = &uart->port;
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
unsigned long flags;
|
|
||||||
int irq_id;
|
int irq_id;
|
||||||
|
|
||||||
uart->stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
|
uart->stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
|
||||||
@@ -401,7 +400,7 @@ static irqreturn_t men_z135_intr(int irq, void *data)
|
|||||||
if (!irq_id)
|
if (!irq_id)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock(&port->lock);
|
||||||
/* It's save to write to IIR[7:6] RXC[9:8] */
|
/* It's save to write to IIR[7:6] RXC[9:8] */
|
||||||
iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG);
|
iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG);
|
||||||
|
|
||||||
@@ -427,7 +426,7 @@ static irqreturn_t men_z135_intr(int irq, void *data)
|
|||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock(&port->lock);
|
||||||
out:
|
out:
|
||||||
return IRQ_RETVAL(handled);
|
return IRQ_RETVAL(handled);
|
||||||
}
|
}
|
||||||
@@ -717,7 +716,7 @@ static void men_z135_set_termios(struct uart_port *port,
|
|||||||
|
|
||||||
baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16);
|
baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16);
|
||||||
|
|
||||||
spin_lock(&port->lock);
|
spin_lock_irq(&port->lock);
|
||||||
if (tty_termios_baud_rate(termios))
|
if (tty_termios_baud_rate(termios))
|
||||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||||
|
|
||||||
@@ -725,7 +724,7 @@ static void men_z135_set_termios(struct uart_port *port,
|
|||||||
iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG);
|
iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG);
|
||||||
|
|
||||||
uart_update_timeout(port, termios->c_cflag, baud);
|
uart_update_timeout(port, termios->c_cflag, baud);
|
||||||
spin_unlock(&port->lock);
|
spin_unlock_irq(&port->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *men_z135_type(struct uart_port *port)
|
static const char *men_z135_type(struct uart_port *port)
|
||||||
@@ -840,7 +839,6 @@ static int men_z135_probe(struct mcb_device *mdev,
|
|||||||
uart->port.membase = NULL;
|
uart->port.membase = NULL;
|
||||||
uart->mdev = mdev;
|
uart->mdev = mdev;
|
||||||
|
|
||||||
spin_lock_init(&uart->port.lock);
|
|
||||||
spin_lock_init(&uart->lock);
|
spin_lock_init(&uart->lock);
|
||||||
|
|
||||||
err = uart_add_one_port(&men_z135_driver, &uart->port);
|
err = uart_add_one_port(&men_z135_driver, &uart->port);
|
||||||
|
@@ -239,8 +239,9 @@ static int mpc52xx_psc_tx_rdy(struct uart_port *port)
|
|||||||
|
|
||||||
static int mpc52xx_psc_tx_empty(struct uart_port *port)
|
static int mpc52xx_psc_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
return in_be16(&PSC(port)->mpc52xx_psc_status)
|
u16 sts = in_be16(&PSC(port)->mpc52xx_psc_status);
|
||||||
& MPC52xx_PSC_SR_TXEMP;
|
|
||||||
|
return (sts & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mpc52xx_psc_start_tx(struct uart_port *port)
|
static void mpc52xx_psc_start_tx(struct uart_port *port)
|
||||||
|
@@ -100,6 +100,8 @@
|
|||||||
#define AUART_CTRL2_TXE (1 << 8)
|
#define AUART_CTRL2_TXE (1 << 8)
|
||||||
#define AUART_CTRL2_UARTEN (1 << 0)
|
#define AUART_CTRL2_UARTEN (1 << 0)
|
||||||
|
|
||||||
|
#define AUART_LINECTRL_BAUD_DIV_MAX 0x003fffc0
|
||||||
|
#define AUART_LINECTRL_BAUD_DIV_MIN 0x000000ec
|
||||||
#define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16
|
#define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16
|
||||||
#define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000
|
#define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000
|
||||||
#define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
|
#define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
|
||||||
@@ -659,7 +661,7 @@ static void mxs_auart_settermios(struct uart_port *u,
|
|||||||
{
|
{
|
||||||
struct mxs_auart_port *s = to_auart_port(u);
|
struct mxs_auart_port *s = to_auart_port(u);
|
||||||
u32 bm, ctrl, ctrl2, div;
|
u32 bm, ctrl, ctrl2, div;
|
||||||
unsigned int cflag, baud;
|
unsigned int cflag, baud, baud_min, baud_max;
|
||||||
|
|
||||||
cflag = termios->c_cflag;
|
cflag = termios->c_cflag;
|
||||||
|
|
||||||
@@ -752,7 +754,9 @@ static void mxs_auart_settermios(struct uart_port *u,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set baud rate */
|
/* set baud rate */
|
||||||
baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
|
baud_min = DIV_ROUND_UP(u->uartclk * 32, AUART_LINECTRL_BAUD_DIV_MAX);
|
||||||
|
baud_max = u->uartclk * 32 / AUART_LINECTRL_BAUD_DIV_MIN;
|
||||||
|
baud = uart_get_baud_rate(u, termios, old, baud_min, baud_max);
|
||||||
div = u->uartclk * 32 / baud;
|
div = u->uartclk * 32 / baud;
|
||||||
ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
|
ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
|
||||||
ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
|
ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
|
||||||
@@ -842,7 +846,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mxs_auart_reset(struct uart_port *u)
|
static void mxs_auart_reset_deassert(struct uart_port *u)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
@@ -858,6 +862,30 @@ static void mxs_auart_reset(struct uart_port *u)
|
|||||||
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
|
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mxs_auart_reset_assert(struct uart_port *u)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
reg = readl(u->membase + AUART_CTRL0);
|
||||||
|
/* if already in reset state, keep it untouched */
|
||||||
|
if (reg & AUART_CTRL0_SFTRST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
|
||||||
|
writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_SET);
|
||||||
|
|
||||||
|
for (i = 0; i < 1000; i++) {
|
||||||
|
reg = readl(u->membase + AUART_CTRL0);
|
||||||
|
/* reset is finished when the clock is gated */
|
||||||
|
if (reg & AUART_CTRL0_CLKGATE)
|
||||||
|
return;
|
||||||
|
udelay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_err(u->dev, "Failed to reset the unit.");
|
||||||
|
}
|
||||||
|
|
||||||
static int mxs_auart_startup(struct uart_port *u)
|
static int mxs_auart_startup(struct uart_port *u)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -867,7 +895,13 @@ static int mxs_auart_startup(struct uart_port *u)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
|
if (uart_console(u)) {
|
||||||
|
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
|
||||||
|
} else {
|
||||||
|
/* reset the unit to a well known state */
|
||||||
|
mxs_auart_reset_assert(u);
|
||||||
|
mxs_auart_reset_deassert(u);
|
||||||
|
}
|
||||||
|
|
||||||
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
|
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
|
||||||
|
|
||||||
@@ -899,12 +933,14 @@ static void mxs_auart_shutdown(struct uart_port *u)
|
|||||||
if (auart_dma_enabled(s))
|
if (auart_dma_enabled(s))
|
||||||
mxs_auart_dma_exit(s);
|
mxs_auart_dma_exit(s);
|
||||||
|
|
||||||
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
|
if (uart_console(u)) {
|
||||||
|
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
|
||||||
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
|
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
|
||||||
u->membase + AUART_INTR_CLR);
|
u->membase + AUART_INTR_CLR);
|
||||||
|
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
|
||||||
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
|
} else {
|
||||||
|
mxs_auart_reset_assert(u);
|
||||||
|
}
|
||||||
|
|
||||||
clk_disable_unprepare(s->clk);
|
clk_disable_unprepare(s->clk);
|
||||||
}
|
}
|
||||||
@@ -1291,7 +1327,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
auart_port[s->port.line] = s;
|
auart_port[s->port.line] = s;
|
||||||
|
|
||||||
mxs_auart_reset(&s->port);
|
mxs_auart_reset_deassert(&s->port);
|
||||||
|
|
||||||
ret = uart_add_one_port(&auart_driver, &s->port);
|
ret = uart_add_one_port(&auart_driver, &s->port);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@@ -53,7 +53,6 @@
|
|||||||
#include "samsung.h"
|
#include "samsung.h"
|
||||||
|
|
||||||
#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
|
#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
|
||||||
defined(CONFIG_DEBUG_LL) && \
|
|
||||||
!defined(MODULE)
|
!defined(MODULE)
|
||||||
|
|
||||||
extern void printascii(const char *);
|
extern void printascii(const char *);
|
||||||
@@ -295,15 +294,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
|
|||||||
if (ourport->tx_mode != S3C24XX_TX_DMA)
|
if (ourport->tx_mode != S3C24XX_TX_DMA)
|
||||||
enable_tx_dma(ourport);
|
enable_tx_dma(ourport);
|
||||||
|
|
||||||
while (xmit->tail & (dma_get_cache_alignment() - 1)) {
|
|
||||||
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
|
|
||||||
return 0;
|
|
||||||
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
|
|
||||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
|
||||||
port->icount.tx++;
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
|
dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
|
||||||
dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
|
dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
|
||||||
|
|
||||||
@@ -342,7 +332,9 @@ static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ourport->dma || !ourport->dma->tx_chan || count < port->fifosize)
|
if (!ourport->dma || !ourport->dma->tx_chan ||
|
||||||
|
count < ourport->min_dma_size ||
|
||||||
|
xmit->tail & (dma_get_cache_alignment() - 1))
|
||||||
s3c24xx_serial_start_tx_pio(ourport);
|
s3c24xx_serial_start_tx_pio(ourport);
|
||||||
else
|
else
|
||||||
s3c24xx_serial_start_tx_dma(ourport, count);
|
s3c24xx_serial_start_tx_dma(ourport, count);
|
||||||
@@ -736,15 +728,20 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
|||||||
struct uart_port *port = &ourport->port;
|
struct uart_port *port = &ourport->port;
|
||||||
struct circ_buf *xmit = &port->state->xmit;
|
struct circ_buf *xmit = &port->state->xmit;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int count;
|
int count, dma_count = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||||
|
|
||||||
if (ourport->dma && ourport->dma->tx_chan && count >= port->fifosize) {
|
if (ourport->dma && ourport->dma->tx_chan &&
|
||||||
s3c24xx_serial_start_tx_dma(ourport, count);
|
count >= ourport->min_dma_size) {
|
||||||
goto out;
|
int align = dma_get_cache_alignment() -
|
||||||
|
(xmit->tail & (dma_get_cache_alignment() - 1));
|
||||||
|
if (count-align >= ourport->min_dma_size) {
|
||||||
|
dma_count = count-align;
|
||||||
|
count = align;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->x_char) {
|
if (port->x_char) {
|
||||||
@@ -765,14 +762,24 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
|||||||
|
|
||||||
/* try and drain the buffer... */
|
/* try and drain the buffer... */
|
||||||
|
|
||||||
count = port->fifosize;
|
if (count > port->fifosize) {
|
||||||
while (!uart_circ_empty(xmit) && count-- > 0) {
|
count = port->fifosize;
|
||||||
|
dma_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!uart_circ_empty(xmit) && count > 0) {
|
||||||
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
|
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
|
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
|
||||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count && dma_count) {
|
||||||
|
s3c24xx_serial_start_tx_dma(ourport, dma_count);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
|
||||||
@@ -1838,6 +1845,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
|||||||
else if (ourport->info->fifosize)
|
else if (ourport->info->fifosize)
|
||||||
ourport->port.fifosize = ourport->info->fifosize;
|
ourport->port.fifosize = ourport->info->fifosize;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DMA transfers must be aligned at least to cache line size,
|
||||||
|
* so find minimal transfer size suitable for DMA mode
|
||||||
|
*/
|
||||||
|
ourport->min_dma_size = max_t(int, ourport->port.fifosize,
|
||||||
|
dma_get_cache_alignment());
|
||||||
|
|
||||||
probe_index++;
|
probe_index++;
|
||||||
|
|
||||||
dbg("%s: initialising port %p...\n", __func__, ourport);
|
dbg("%s: initialising port %p...\n", __func__, ourport);
|
||||||
|
@@ -82,6 +82,7 @@ struct s3c24xx_uart_port {
|
|||||||
unsigned char tx_claimed;
|
unsigned char tx_claimed;
|
||||||
unsigned int pm_level;
|
unsigned int pm_level;
|
||||||
unsigned long baudclk_rate;
|
unsigned long baudclk_rate;
|
||||||
|
unsigned int min_dma_size;
|
||||||
|
|
||||||
unsigned int rx_irq;
|
unsigned int rx_irq;
|
||||||
unsigned int tx_irq;
|
unsigned int tx_irq;
|
||||||
|
@@ -11,6 +11,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@@ -29,6 +31,7 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
#define SC16IS7XX_NAME "sc16is7xx"
|
#define SC16IS7XX_NAME "sc16is7xx"
|
||||||
|
#define SC16IS7XX_MAX_DEVS 8
|
||||||
|
|
||||||
/* SC16IS7XX register definitions */
|
/* SC16IS7XX register definitions */
|
||||||
#define SC16IS7XX_RHR_REG (0x00) /* RX FIFO */
|
#define SC16IS7XX_RHR_REG (0x00) /* RX FIFO */
|
||||||
@@ -312,14 +315,14 @@ struct sc16is7xx_one_config {
|
|||||||
|
|
||||||
struct sc16is7xx_one {
|
struct sc16is7xx_one {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
|
u8 line;
|
||||||
struct kthread_work tx_work;
|
struct kthread_work tx_work;
|
||||||
struct kthread_work reg_work;
|
struct kthread_work reg_work;
|
||||||
struct sc16is7xx_one_config config;
|
struct sc16is7xx_one_config config;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc16is7xx_port {
|
struct sc16is7xx_port {
|
||||||
struct uart_driver uart;
|
const struct sc16is7xx_devtype *devtype;
|
||||||
struct sc16is7xx_devtype *devtype;
|
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
#ifdef CONFIG_GPIOLIB
|
#ifdef CONFIG_GPIOLIB
|
||||||
@@ -332,16 +335,31 @@ struct sc16is7xx_port {
|
|||||||
struct sc16is7xx_one p[0];
|
struct sc16is7xx_one p[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned long sc16is7xx_lines;
|
||||||
|
|
||||||
|
static struct uart_driver sc16is7xx_uart = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.dev_name = "ttySC",
|
||||||
|
.nr = SC16IS7XX_MAX_DEVS,
|
||||||
|
};
|
||||||
|
|
||||||
#define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e)))
|
#define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e)))
|
||||||
#define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e)))
|
#define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e)))
|
||||||
|
|
||||||
|
static int sc16is7xx_line(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
|
||||||
|
|
||||||
|
return one->line;
|
||||||
|
}
|
||||||
|
|
||||||
static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
|
static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
|
||||||
{
|
{
|
||||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||||
unsigned int val = 0;
|
unsigned int val = 0;
|
||||||
|
const u8 line = sc16is7xx_line(port);
|
||||||
|
|
||||||
regmap_read(s->regmap,
|
regmap_read(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, &val);
|
||||||
(reg << SC16IS7XX_REG_SHIFT) | port->line, &val);
|
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@@ -349,15 +367,16 @@ static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
|
|||||||
static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
|
static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
|
||||||
{
|
{
|
||||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||||
|
const u8 line = sc16is7xx_line(port);
|
||||||
|
|
||||||
regmap_write(s->regmap,
|
regmap_write(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, val);
|
||||||
(reg << SC16IS7XX_REG_SHIFT) | port->line, val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
|
static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
|
||||||
{
|
{
|
||||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||||
u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | port->line;
|
const u8 line = sc16is7xx_line(port);
|
||||||
|
u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | line;
|
||||||
|
|
||||||
regcache_cache_bypass(s->regmap, true);
|
regcache_cache_bypass(s->regmap, true);
|
||||||
regmap_raw_read(s->regmap, addr, s->buf, rxlen);
|
regmap_raw_read(s->regmap, addr, s->buf, rxlen);
|
||||||
@@ -367,7 +386,8 @@ static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
|
|||||||
static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
|
static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
|
||||||
{
|
{
|
||||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||||
u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | port->line;
|
const u8 line = sc16is7xx_line(port);
|
||||||
|
u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line;
|
||||||
|
|
||||||
regcache_cache_bypass(s->regmap, true);
|
regcache_cache_bypass(s->regmap, true);
|
||||||
regmap_raw_write(s->regmap, addr, s->buf, to_send);
|
regmap_raw_write(s->regmap, addr, s->buf, to_send);
|
||||||
@@ -378,12 +398,24 @@ static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
|
|||||||
u8 mask, u8 val)
|
u8 mask, u8 val)
|
||||||
{
|
{
|
||||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||||
|
const u8 line = sc16is7xx_line(port);
|
||||||
|
|
||||||
regmap_update_bits(s->regmap,
|
regmap_update_bits(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line,
|
||||||
(reg << SC16IS7XX_REG_SHIFT) | port->line,
|
|
||||||
mask, val);
|
mask, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sc16is7xx_alloc_line(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(SC16IS7XX_MAX_DEVS > BITS_PER_LONG);
|
||||||
|
|
||||||
|
for (i = 0; i < SC16IS7XX_MAX_DEVS; i++)
|
||||||
|
if (!test_and_set_bit(i, &sc16is7xx_lines))
|
||||||
|
break;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
static void sc16is7xx_power(struct uart_port *port, int on)
|
static void sc16is7xx_power(struct uart_port *port, int on)
|
||||||
{
|
{
|
||||||
@@ -508,7 +540,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
|
|||||||
|
|
||||||
if (unlikely(rxlen >= sizeof(s->buf))) {
|
if (unlikely(rxlen >= sizeof(s->buf))) {
|
||||||
dev_warn_ratelimited(port->dev,
|
dev_warn_ratelimited(port->dev,
|
||||||
"Port %i: Possible RX FIFO overrun: %d\n",
|
"ttySC%i: Possible RX FIFO overrun: %d\n",
|
||||||
port->line, rxlen);
|
port->line, rxlen);
|
||||||
port->icount.buf_overrun++;
|
port->icount.buf_overrun++;
|
||||||
/* Ensure sanity of RX level */
|
/* Ensure sanity of RX level */
|
||||||
@@ -649,7 +681,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err_ratelimited(port->dev,
|
dev_err_ratelimited(port->dev,
|
||||||
"Port %i: Unexpected interrupt: %x",
|
"ttySC%i: Unexpected interrupt: %x",
|
||||||
port->line, iir);
|
port->line, iir);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -661,7 +693,7 @@ static void sc16is7xx_ist(struct kthread_work *ws)
|
|||||||
struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
|
struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < s->uart.nr; ++i)
|
for (i = 0; i < s->devtype->nr_uart; ++i)
|
||||||
sc16is7xx_port_irq(s, i);
|
sc16is7xx_port_irq(s, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,7 +1131,7 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int sc16is7xx_probe(struct device *dev,
|
static int sc16is7xx_probe(struct device *dev,
|
||||||
struct sc16is7xx_devtype *devtype,
|
const struct sc16is7xx_devtype *devtype,
|
||||||
struct regmap *regmap, int irq, unsigned long flags)
|
struct regmap *regmap, int irq, unsigned long flags)
|
||||||
{
|
{
|
||||||
struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
|
struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
|
||||||
@@ -1134,23 +1166,13 @@ static int sc16is7xx_probe(struct device *dev,
|
|||||||
s->devtype = devtype;
|
s->devtype = devtype;
|
||||||
dev_set_drvdata(dev, s);
|
dev_set_drvdata(dev, s);
|
||||||
|
|
||||||
/* Register UART driver */
|
|
||||||
s->uart.owner = THIS_MODULE;
|
|
||||||
s->uart.dev_name = "ttySC";
|
|
||||||
s->uart.nr = devtype->nr_uart;
|
|
||||||
ret = uart_register_driver(&s->uart);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Registering UART driver failed\n");
|
|
||||||
goto out_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_kthread_worker(&s->kworker);
|
init_kthread_worker(&s->kworker);
|
||||||
init_kthread_work(&s->irq_work, sc16is7xx_ist);
|
init_kthread_work(&s->irq_work, sc16is7xx_ist);
|
||||||
s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
|
s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
|
||||||
"sc16is7xx");
|
"sc16is7xx");
|
||||||
if (IS_ERR(s->kworker_task)) {
|
if (IS_ERR(s->kworker_task)) {
|
||||||
ret = PTR_ERR(s->kworker_task);
|
ret = PTR_ERR(s->kworker_task);
|
||||||
goto out_uart;
|
goto out_clk;
|
||||||
}
|
}
|
||||||
sched_setscheduler(s->kworker_task, SCHED_FIFO, &sched_param);
|
sched_setscheduler(s->kworker_task, SCHED_FIFO, &sched_param);
|
||||||
|
|
||||||
@@ -1174,8 +1196,8 @@ static int sc16is7xx_probe(struct device *dev,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < devtype->nr_uart; ++i) {
|
for (i = 0; i < devtype->nr_uart; ++i) {
|
||||||
|
s->p[i].line = i;
|
||||||
/* Initialize port data */
|
/* Initialize port data */
|
||||||
s->p[i].port.line = i;
|
|
||||||
s->p[i].port.dev = dev;
|
s->p[i].port.dev = dev;
|
||||||
s->p[i].port.irq = irq;
|
s->p[i].port.irq = irq;
|
||||||
s->p[i].port.type = PORT_SC16IS7XX;
|
s->p[i].port.type = PORT_SC16IS7XX;
|
||||||
@@ -1185,6 +1207,12 @@ static int sc16is7xx_probe(struct device *dev,
|
|||||||
s->p[i].port.uartclk = freq;
|
s->p[i].port.uartclk = freq;
|
||||||
s->p[i].port.rs485_config = sc16is7xx_config_rs485;
|
s->p[i].port.rs485_config = sc16is7xx_config_rs485;
|
||||||
s->p[i].port.ops = &sc16is7xx_ops;
|
s->p[i].port.ops = &sc16is7xx_ops;
|
||||||
|
s->p[i].port.line = sc16is7xx_alloc_line();
|
||||||
|
if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out_ports;
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0);
|
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0);
|
||||||
/* Disable TX/RX */
|
/* Disable TX/RX */
|
||||||
@@ -1195,7 +1223,7 @@ static int sc16is7xx_probe(struct device *dev,
|
|||||||
init_kthread_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
|
init_kthread_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
|
||||||
init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
|
init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
|
||||||
/* Register port */
|
/* Register port */
|
||||||
uart_add_one_port(&s->uart, &s->p[i].port);
|
uart_add_one_port(&sc16is7xx_uart, &s->p[i].port);
|
||||||
/* Go to suspend mode */
|
/* Go to suspend mode */
|
||||||
sc16is7xx_power(&s->p[i].port, 0);
|
sc16is7xx_power(&s->p[i].port, 0);
|
||||||
}
|
}
|
||||||
@@ -1206,8 +1234,11 @@ static int sc16is7xx_probe(struct device *dev,
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = 0; i < s->uart.nr; i++)
|
out_ports:
|
||||||
uart_remove_one_port(&s->uart, &s->p[i].port);
|
for (i--; i >= 0; i--) {
|
||||||
|
uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
|
||||||
|
clear_bit(s->p[i].port.line, &sc16is7xx_lines);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_GPIOLIB
|
#ifdef CONFIG_GPIOLIB
|
||||||
if (devtype->nr_gpio)
|
if (devtype->nr_gpio)
|
||||||
@@ -1217,9 +1248,6 @@ out_thread:
|
|||||||
#endif
|
#endif
|
||||||
kthread_stop(s->kworker_task);
|
kthread_stop(s->kworker_task);
|
||||||
|
|
||||||
out_uart:
|
|
||||||
uart_unregister_driver(&s->uart);
|
|
||||||
|
|
||||||
out_clk:
|
out_clk:
|
||||||
if (!IS_ERR(s->clk))
|
if (!IS_ERR(s->clk))
|
||||||
clk_disable_unprepare(s->clk);
|
clk_disable_unprepare(s->clk);
|
||||||
@@ -1237,15 +1265,15 @@ static int sc16is7xx_remove(struct device *dev)
|
|||||||
gpiochip_remove(&s->gpio);
|
gpiochip_remove(&s->gpio);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < s->uart.nr; i++) {
|
for (i = 0; i < s->devtype->nr_uart; i++) {
|
||||||
uart_remove_one_port(&s->uart, &s->p[i].port);
|
uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
|
||||||
|
clear_bit(s->p[i].port.line, &sc16is7xx_lines);
|
||||||
sc16is7xx_power(&s->p[i].port, 0);
|
sc16is7xx_power(&s->p[i].port, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_kthread_worker(&s->kworker);
|
flush_kthread_worker(&s->kworker);
|
||||||
kthread_stop(s->kworker_task);
|
kthread_stop(s->kworker_task);
|
||||||
|
|
||||||
uart_unregister_driver(&s->uart);
|
|
||||||
if (!IS_ERR(s->clk))
|
if (!IS_ERR(s->clk))
|
||||||
clk_disable_unprepare(s->clk);
|
clk_disable_unprepare(s->clk);
|
||||||
|
|
||||||
@@ -1275,7 +1303,7 @@ static struct regmap_config regcfg = {
|
|||||||
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
|
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
|
||||||
static int sc16is7xx_spi_probe(struct spi_device *spi)
|
static int sc16is7xx_spi_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct sc16is7xx_devtype *devtype;
|
const struct sc16is7xx_devtype *devtype;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1344,7 +1372,7 @@ MODULE_ALIAS("spi:sc16is7xx");
|
|||||||
static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
|
static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct sc16is7xx_devtype *devtype;
|
const struct sc16is7xx_devtype *devtype;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
|
||||||
@@ -1385,7 +1413,6 @@ MODULE_DEVICE_TABLE(i2c, sc16is7xx_i2c_id_table);
|
|||||||
static struct i2c_driver sc16is7xx_i2c_uart_driver = {
|
static struct i2c_driver sc16is7xx_i2c_uart_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = SC16IS7XX_NAME,
|
.name = SC16IS7XX_NAME,
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.of_match_table = of_match_ptr(sc16is7xx_dt_ids),
|
.of_match_table = of_match_ptr(sc16is7xx_dt_ids),
|
||||||
},
|
},
|
||||||
.probe = sc16is7xx_i2c_probe,
|
.probe = sc16is7xx_i2c_probe,
|
||||||
@@ -1398,7 +1425,14 @@ MODULE_ALIAS("i2c:sc16is7xx");
|
|||||||
|
|
||||||
static int __init sc16is7xx_init(void)
|
static int __init sc16is7xx_init(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
|
ret = uart_register_driver(&sc16is7xx_uart);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("Registering UART driver failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_SC16IS7XX_I2C
|
#ifdef CONFIG_SERIAL_SC16IS7XX_I2C
|
||||||
ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver);
|
ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -1427,6 +1461,7 @@ static void __exit sc16is7xx_exit(void)
|
|||||||
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
|
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
|
||||||
spi_unregister_driver(&sc16is7xx_spi_uart_driver);
|
spi_unregister_driver(&sc16is7xx_spi_uart_driver);
|
||||||
#endif
|
#endif
|
||||||
|
uart_unregister_driver(&sc16is7xx_uart);
|
||||||
}
|
}
|
||||||
module_exit(sc16is7xx_exit);
|
module_exit(sc16is7xx_exit);
|
||||||
|
|
||||||
|
@@ -1377,7 +1377,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|||||||
struct uart_state *state = tty->driver_data;
|
struct uart_state *state = tty->driver_data;
|
||||||
struct tty_port *port;
|
struct tty_port *port;
|
||||||
struct uart_port *uport;
|
struct uart_port *uport;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
struct uart_driver *drv = tty->driver->driver_state;
|
struct uart_driver *drv = tty->driver->driver_state;
|
||||||
@@ -1403,10 +1402,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|||||||
* disable the receive line status interrupts.
|
* disable the receive line status interrupts.
|
||||||
*/
|
*/
|
||||||
if (port->flags & ASYNC_INITIALIZED) {
|
if (port->flags & ASYNC_INITIALIZED) {
|
||||||
unsigned long flags;
|
spin_lock_irq(&uport->lock);
|
||||||
spin_lock_irqsave(&uport->lock, flags);
|
|
||||||
uport->ops->stop_rx(uport);
|
uport->ops->stop_rx(uport);
|
||||||
spin_unlock_irqrestore(&uport->lock, flags);
|
spin_unlock_irq(&uport->lock);
|
||||||
/*
|
/*
|
||||||
* Before we drop DTR, make sure the UART transmitter
|
* Before we drop DTR, make sure the UART transmitter
|
||||||
* has completely drained; this is especially
|
* has completely drained; this is especially
|
||||||
@@ -1419,17 +1417,17 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|||||||
uart_shutdown(tty, state);
|
uart_shutdown(tty, state);
|
||||||
tty_port_tty_set(port, NULL);
|
tty_port_tty_set(port, NULL);
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irq(&port->lock);
|
||||||
|
|
||||||
if (port->blocked_open) {
|
if (port->blocked_open) {
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irq(&port->lock);
|
||||||
if (port->close_delay)
|
if (port->close_delay)
|
||||||
msleep_interruptible(jiffies_to_msecs(port->close_delay));
|
msleep_interruptible(jiffies_to_msecs(port->close_delay));
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irq(&port->lock);
|
||||||
} else if (!uart_console(uport)) {
|
} else if (!uart_console(uport)) {
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irq(&port->lock);
|
||||||
uart_change_pm(state, UART_PM_STATE_OFF);
|
uart_change_pm(state, UART_PM_STATE_OFF);
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irq(&port->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1437,7 +1435,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|||||||
*/
|
*/
|
||||||
clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
|
clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
|
||||||
clear_bit(ASYNCB_CLOSING, &port->flags);
|
clear_bit(ASYNCB_CLOSING, &port->flags);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irq(&port->lock);
|
||||||
wake_up_interruptible(&port->open_wait);
|
wake_up_interruptible(&port->open_wait);
|
||||||
wake_up_interruptible(&port->close_wait);
|
wake_up_interruptible(&port->close_wait);
|
||||||
|
|
||||||
@@ -1532,11 +1530,6 @@ static void uart_hangup(struct tty_struct *tty)
|
|||||||
mutex_unlock(&port->mutex);
|
mutex_unlock(&port->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_port_activate(struct tty_port *port, struct tty_struct *tty)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void uart_port_shutdown(struct tty_port *port)
|
static void uart_port_shutdown(struct tty_port *port)
|
||||||
{
|
{
|
||||||
struct uart_state *state = container_of(port, struct uart_state, port);
|
struct uart_state *state = container_of(port, struct uart_state, port);
|
||||||
@@ -2379,8 +2372,6 @@ static const struct tty_operations uart_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct tty_port_operations uart_port_ops = {
|
static const struct tty_port_operations uart_port_ops = {
|
||||||
.activate = uart_port_activate,
|
|
||||||
.shutdown = uart_port_shutdown,
|
|
||||||
.carrier_raised = uart_carrier_raised,
|
.carrier_raised = uart_carrier_raised,
|
||||||
.dtr_rts = uart_dtr_rts,
|
.dtr_rts = uart_dtr_rts,
|
||||||
};
|
};
|
||||||
|
@@ -413,7 +413,6 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sirfport->rx_io_count += rx_count;
|
|
||||||
port->icount.rx += rx_count;
|
port->icount.rx += rx_count;
|
||||||
|
|
||||||
return rx_count;
|
return rx_count;
|
||||||
@@ -600,7 +599,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port)
|
|||||||
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
||||||
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
|
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
|
||||||
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
|
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
|
||||||
sirfport->rx_io_count = 0;
|
|
||||||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||||
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
|
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
|
||||||
~SIRFUART_IO_MODE);
|
~SIRFUART_IO_MODE);
|
||||||
@@ -632,31 +630,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port)
|
|||||||
sirfport->uart_reg->uart_type));
|
sirfport->uart_reg->uart_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sirfsoc_uart_start_rx(struct uart_port *port)
|
|
||||||
{
|
|
||||||
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
|
||||||
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
|
|
||||||
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
|
|
||||||
|
|
||||||
sirfport->rx_io_count = 0;
|
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
|
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
|
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
|
|
||||||
if (sirfport->rx_dma_chan)
|
|
||||||
sirfsoc_uart_start_next_rx_dma(port);
|
|
||||||
else {
|
|
||||||
if (!sirfport->is_atlas7)
|
|
||||||
wr_regl(port, ureg->sirfsoc_int_en_reg,
|
|
||||||
rd_regl(port, ureg->sirfsoc_int_en_reg) |
|
|
||||||
SIRFUART_RX_IO_INT_EN(uint_en,
|
|
||||||
sirfport->uart_reg->uart_type));
|
|
||||||
else
|
|
||||||
wr_regl(port, ureg->sirfsoc_int_en_reg,
|
|
||||||
SIRFUART_RX_IO_INT_EN(uint_en,
|
|
||||||
sirfport->uart_reg->uart_type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
sirfsoc_usp_calc_sample_div(unsigned long set_rate,
|
sirfsoc_usp_calc_sample_div(unsigned long set_rate,
|
||||||
unsigned long ioclk_rate, unsigned long *sample_reg)
|
unsigned long ioclk_rate, unsigned long *sample_reg)
|
||||||
@@ -850,7 +823,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
|
|||||||
rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000);
|
rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000);
|
||||||
rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out);
|
rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out);
|
||||||
txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op);
|
txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op);
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_STOP);
|
|
||||||
wr_regl(port, ureg->sirfsoc_tx_fifo_op,
|
wr_regl(port, ureg->sirfsoc_tx_fifo_op,
|
||||||
(txfifo_op_reg & ~SIRFUART_FIFO_START));
|
(txfifo_op_reg & ~SIRFUART_FIFO_START));
|
||||||
if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
|
if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
|
||||||
@@ -886,9 +858,13 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
|
|||||||
else
|
else
|
||||||
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
|
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
|
||||||
if (sirfport->rx_dma_chan)
|
if (sirfport->rx_dma_chan)
|
||||||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE);
|
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||||
|
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
|
||||||
|
~SIRFUART_IO_MODE);
|
||||||
else
|
else
|
||||||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
|
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||||
|
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
|
||||||
|
SIRFUART_IO_MODE);
|
||||||
sirfport->rx_period_time = 20000000;
|
sirfport->rx_period_time = 20000000;
|
||||||
/* Reset Rx/Tx FIFO Threshold level for proper baudrate */
|
/* Reset Rx/Tx FIFO Threshold level for proper baudrate */
|
||||||
if (set_baud < 1000000)
|
if (set_baud < 1000000)
|
||||||
@@ -902,7 +878,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
|
|||||||
txfifo_op_reg |= SIRFUART_FIFO_START;
|
txfifo_op_reg |= SIRFUART_FIFO_START;
|
||||||
wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg);
|
wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg);
|
||||||
uart_update_timeout(port, termios->c_cflag, set_baud);
|
uart_update_timeout(port, termios->c_cflag, set_baud);
|
||||||
sirfsoc_uart_start_rx(port);
|
|
||||||
wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN);
|
wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
@@ -921,6 +896,7 @@ static int sirfsoc_uart_startup(struct uart_port *port)
|
|||||||
{
|
{
|
||||||
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
||||||
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
|
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
|
||||||
|
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
|
||||||
unsigned int index = port->line;
|
unsigned int index = port->line;
|
||||||
int ret;
|
int ret;
|
||||||
irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN);
|
irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN);
|
||||||
@@ -958,9 +934,9 @@ static int sirfsoc_uart_startup(struct uart_port *port)
|
|||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port));
|
wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port));
|
||||||
if (sirfport->rx_dma_chan)
|
if (sirfport->rx_dma_chan)
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk,
|
wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk,
|
||||||
SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) |
|
SIRFUART_RX_FIFO_CHK_SC(port->line, 0x1) |
|
||||||
SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
|
SIRFUART_RX_FIFO_CHK_LC(port->line, 0x2) |
|
||||||
SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
|
SIRFUART_RX_FIFO_CHK_HC(port->line, 0x4));
|
||||||
if (sirfport->tx_dma_chan) {
|
if (sirfport->tx_dma_chan) {
|
||||||
sirfport->tx_dma_state = TX_DMA_IDLE;
|
sirfport->tx_dma_state = TX_DMA_IDLE;
|
||||||
wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk,
|
wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk,
|
||||||
@@ -981,16 +957,41 @@ static int sirfsoc_uart_startup(struct uart_port *port)
|
|||||||
goto init_rx_err;
|
goto init_rx_err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enable_irq(port->irq);
|
if (sirfport->uart_reg->uart_type == SIRF_REAL_UART &&
|
||||||
|
sirfport->rx_dma_chan)
|
||||||
|
wr_regl(port, ureg->sirfsoc_swh_dma_io,
|
||||||
|
SIRFUART_CLEAR_RX_ADDR_EN);
|
||||||
|
if (sirfport->uart_reg->uart_type == SIRF_USP_UART &&
|
||||||
|
sirfport->rx_dma_chan)
|
||||||
|
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||||
|
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
|
||||||
|
SIRFSOC_USP_FRADDR_CLR_EN);
|
||||||
if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) {
|
if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) {
|
||||||
sirfport->is_hrt_enabled = true;
|
sirfport->is_hrt_enabled = true;
|
||||||
sirfport->rx_period_time = 20000000;
|
sirfport->rx_period_time = 20000000;
|
||||||
|
sirfport->rx_last_pos = -1;
|
||||||
|
sirfport->pio_fetch_cnt = 0;
|
||||||
sirfport->rx_dma_items.xmit.tail =
|
sirfport->rx_dma_items.xmit.tail =
|
||||||
sirfport->rx_dma_items.xmit.head = 0;
|
sirfport->rx_dma_items.xmit.head = 0;
|
||||||
hrtimer_start(&sirfport->hrt,
|
hrtimer_start(&sirfport->hrt,
|
||||||
ns_to_ktime(sirfport->rx_period_time),
|
ns_to_ktime(sirfport->rx_period_time),
|
||||||
HRTIMER_MODE_REL);
|
HRTIMER_MODE_REL);
|
||||||
}
|
}
|
||||||
|
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
|
||||||
|
if (sirfport->rx_dma_chan)
|
||||||
|
sirfsoc_uart_start_next_rx_dma(port);
|
||||||
|
else {
|
||||||
|
if (!sirfport->is_atlas7)
|
||||||
|
wr_regl(port, ureg->sirfsoc_int_en_reg,
|
||||||
|
rd_regl(port, ureg->sirfsoc_int_en_reg) |
|
||||||
|
SIRFUART_RX_IO_INT_EN(uint_en,
|
||||||
|
sirfport->uart_reg->uart_type));
|
||||||
|
else
|
||||||
|
wr_regl(port, ureg->sirfsoc_int_en_reg,
|
||||||
|
SIRFUART_RX_IO_INT_EN(uint_en,
|
||||||
|
sirfport->uart_reg->uart_type));
|
||||||
|
}
|
||||||
|
enable_irq(port->irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
init_rx_err:
|
init_rx_err:
|
||||||
@@ -1003,6 +1004,9 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
|
|||||||
{
|
{
|
||||||
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
||||||
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
|
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
|
||||||
|
struct circ_buf *xmit;
|
||||||
|
|
||||||
|
xmit = &sirfport->rx_dma_items.xmit;
|
||||||
if (!sirfport->is_atlas7)
|
if (!sirfport->is_atlas7)
|
||||||
wr_regl(port, ureg->sirfsoc_int_en_reg, 0);
|
wr_regl(port, ureg->sirfsoc_int_en_reg, 0);
|
||||||
else
|
else
|
||||||
@@ -1019,8 +1023,10 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
|
|||||||
if (sirfport->tx_dma_chan)
|
if (sirfport->tx_dma_chan)
|
||||||
sirfport->tx_dma_state = TX_DMA_IDLE;
|
sirfport->tx_dma_state = TX_DMA_IDLE;
|
||||||
if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) {
|
if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) {
|
||||||
while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
while (((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
||||||
SIRFUART_RX_FIFO_MASK) > 0)
|
SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt) &&
|
||||||
|
!CIRC_CNT(xmit->head, xmit->tail,
|
||||||
|
SIRFSOC_RX_DMA_BUF_SIZE))
|
||||||
;
|
;
|
||||||
sirfport->is_hrt_enabled = false;
|
sirfport->is_hrt_enabled = false;
|
||||||
hrtimer_cancel(&sirfport->hrt);
|
hrtimer_cancel(&sirfport->hrt);
|
||||||
@@ -1169,6 +1175,8 @@ static enum hrtimer_restart
|
|||||||
struct tty_struct *tty;
|
struct tty_struct *tty;
|
||||||
struct sirfsoc_register *ureg;
|
struct sirfsoc_register *ureg;
|
||||||
struct circ_buf *xmit;
|
struct circ_buf *xmit;
|
||||||
|
struct sirfsoc_fifo_status *ufifo_st;
|
||||||
|
int max_pio_cnt;
|
||||||
|
|
||||||
sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt);
|
sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt);
|
||||||
port = &sirfport->port;
|
port = &sirfport->port;
|
||||||
@@ -1176,9 +1184,16 @@ static enum hrtimer_restart
|
|||||||
tty = port->state->port.tty;
|
tty = port->state->port.tty;
|
||||||
ureg = &sirfport->uart_reg->uart_reg;
|
ureg = &sirfport->uart_reg->uart_reg;
|
||||||
xmit = &sirfport->rx_dma_items.xmit;
|
xmit = &sirfport->rx_dma_items.xmit;
|
||||||
|
ufifo_st = &sirfport->uart_reg->fifo_status;
|
||||||
|
|
||||||
dmaengine_tx_status(sirfport->rx_dma_chan,
|
dmaengine_tx_status(sirfport->rx_dma_chan,
|
||||||
sirfport->rx_dma_items.cookie, &tx_state);
|
sirfport->rx_dma_items.cookie, &tx_state);
|
||||||
xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
|
if (SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue !=
|
||||||
|
sirfport->rx_last_pos) {
|
||||||
|
xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
|
||||||
|
sirfport->rx_last_pos = xmit->head;
|
||||||
|
sirfport->pio_fetch_cnt = 0;
|
||||||
|
}
|
||||||
count = CIRC_CNT_TO_END(xmit->head, xmit->tail,
|
count = CIRC_CNT_TO_END(xmit->head, xmit->tail,
|
||||||
SIRFSOC_RX_DMA_BUF_SIZE);
|
SIRFSOC_RX_DMA_BUF_SIZE);
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@@ -1200,23 +1215,38 @@ static enum hrtimer_restart
|
|||||||
*/
|
*/
|
||||||
if (!inserted && !count &&
|
if (!inserted && !count &&
|
||||||
((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
||||||
SIRFUART_RX_FIFO_MASK) > 0)) {
|
SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt)) {
|
||||||
|
dmaengine_pause(sirfport->rx_dma_chan);
|
||||||
/* switch to pio mode */
|
/* switch to pio mode */
|
||||||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||||
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
|
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
|
||||||
SIRFUART_IO_MODE);
|
SIRFUART_IO_MODE);
|
||||||
while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
/*
|
||||||
SIRFUART_RX_FIFO_MASK) > 0) {
|
* UART controller SWH_DMA_IO register have CLEAR_RX_ADDR_EN
|
||||||
if (sirfsoc_uart_pio_rx_chars(port, 16) > 0)
|
* When found changing I/O to DMA mode, it clears
|
||||||
tty_flip_buffer_push(tty->port);
|
* two low bits of read point;
|
||||||
|
* USP have similar FRADDR_CLR_EN bit in USP_RX_DMA_IO_CTRL.
|
||||||
|
* Fetch data out from rxfifo into DMA buffer in PIO mode,
|
||||||
|
* while switch back to DMA mode, the data fetched will override
|
||||||
|
* by DMA, as hardware have a strange behaviour:
|
||||||
|
* after switch back to DMA mode, check rxfifo status it will
|
||||||
|
* be the number PIO fetched, so record the fetched data count
|
||||||
|
* to avoid the repeated fetch
|
||||||
|
*/
|
||||||
|
max_pio_cnt = 3;
|
||||||
|
while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
|
||||||
|
ufifo_st->ff_empty(port)) && max_pio_cnt--) {
|
||||||
|
xmit->buf[xmit->head] =
|
||||||
|
rd_regl(port, ureg->sirfsoc_rx_fifo_data);
|
||||||
|
xmit->head = (xmit->head + 1) &
|
||||||
|
(SIRFSOC_RX_DMA_BUF_SIZE - 1);
|
||||||
|
sirfport->pio_fetch_cnt++;
|
||||||
}
|
}
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
|
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
|
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
|
|
||||||
/* switch back to dma mode */
|
/* switch back to dma mode */
|
||||||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
|
||||||
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
|
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
|
||||||
~SIRFUART_IO_MODE);
|
~SIRFUART_IO_MODE);
|
||||||
|
dmaengine_resume(sirfport->rx_dma_chan);
|
||||||
}
|
}
|
||||||
next_hrt:
|
next_hrt:
|
||||||
hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time));
|
hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time));
|
||||||
@@ -1239,7 +1269,7 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
|
|||||||
struct resource *res;
|
struct resource *res;
|
||||||
int ret;
|
int ret;
|
||||||
struct dma_slave_config slv_cfg = {
|
struct dma_slave_config slv_cfg = {
|
||||||
.src_maxburst = 2,
|
.src_maxburst = 1,
|
||||||
};
|
};
|
||||||
struct dma_slave_config tx_slv_cfg = {
|
struct dma_slave_config tx_slv_cfg = {
|
||||||
.dst_maxburst = 2,
|
.dst_maxburst = 2,
|
||||||
|
@@ -296,6 +296,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
|
|||||||
#define SIRFUART_DMA_MODE 0x0
|
#define SIRFUART_DMA_MODE 0x0
|
||||||
#define SIRFUART_RX_DMA_FLUSH 0x4
|
#define SIRFUART_RX_DMA_FLUSH 0x4
|
||||||
|
|
||||||
|
#define SIRFUART_CLEAR_RX_ADDR_EN 0x2
|
||||||
/* Baud Rate Calculation */
|
/* Baud Rate Calculation */
|
||||||
#define SIRF_USP_MIN_SAMPLE_DIV 0x1
|
#define SIRF_USP_MIN_SAMPLE_DIV 0x1
|
||||||
#define SIRF_MIN_SAMPLE_DIV 0xf
|
#define SIRF_MIN_SAMPLE_DIV 0xf
|
||||||
@@ -325,6 +326,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
|
|||||||
#define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f
|
#define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f
|
||||||
#define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16
|
#define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16
|
||||||
#define SIRFSOC_USP_LOOP_BACK_CTRL BIT(2)
|
#define SIRFSOC_USP_LOOP_BACK_CTRL BIT(2)
|
||||||
|
#define SIRFSOC_USP_FRADDR_CLR_EN BIT(1)
|
||||||
/* USP-UART Common */
|
/* USP-UART Common */
|
||||||
#define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000)
|
#define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000)
|
||||||
#define SIRFUART_RECV_TIMEOUT_VALUE(x) \
|
#define SIRFUART_RECV_TIMEOUT_VALUE(x) \
|
||||||
@@ -421,7 +423,6 @@ struct sirfsoc_uart_port {
|
|||||||
struct dma_chan *tx_dma_chan;
|
struct dma_chan *tx_dma_chan;
|
||||||
dma_addr_t tx_dma_addr;
|
dma_addr_t tx_dma_addr;
|
||||||
struct dma_async_tx_descriptor *tx_dma_desc;
|
struct dma_async_tx_descriptor *tx_dma_desc;
|
||||||
unsigned int rx_io_count;
|
|
||||||
unsigned long transfer_size;
|
unsigned long transfer_size;
|
||||||
enum sirfsoc_tx_state tx_dma_state;
|
enum sirfsoc_tx_state tx_dma_state;
|
||||||
unsigned int cts_gpio;
|
unsigned int cts_gpio;
|
||||||
@@ -431,6 +432,8 @@ struct sirfsoc_uart_port {
|
|||||||
struct hrtimer hrt;
|
struct hrtimer hrt;
|
||||||
bool is_hrt_enabled;
|
bool is_hrt_enabled;
|
||||||
unsigned long rx_period_time;
|
unsigned long rx_period_time;
|
||||||
|
unsigned long rx_last_pos;
|
||||||
|
unsigned long pio_fetch_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Register Access Control */
|
/* Register Access Control */
|
||||||
|
@@ -42,7 +42,7 @@
|
|||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/sysrq.h>
|
#include <linux/sysrq.h>
|
||||||
#include <linux/circ_buf.h>
|
#include <linux/circ_buf.h>
|
||||||
#include <linux/serial_reg.h>
|
#include <linux/serial_reg.h>
|
||||||
@@ -659,7 +659,7 @@ static void sn_sal_timer_poll(unsigned long data)
|
|||||||
* @port: Our sn_cons_port (which contains the uart port)
|
* @port: Our sn_cons_port (which contains the uart port)
|
||||||
*
|
*
|
||||||
* So this is used by sn_sal_serial_console_init (early on, before we're
|
* So this is used by sn_sal_serial_console_init (early on, before we're
|
||||||
* registered with serial core). It's also used by sn_sal_module_init
|
* registered with serial core). It's also used by sn_sal_init
|
||||||
* right after we've registered with serial core. The later only happens
|
* right after we've registered with serial core. The later only happens
|
||||||
* if we didn't already come through here via sn_sal_serial_console_init.
|
* if we didn't already come through here via sn_sal_serial_console_init.
|
||||||
*
|
*
|
||||||
@@ -709,7 +709,7 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port)
|
|||||||
* sn_sal_switch_to_interrupts - Switch to interrupt driven mode
|
* sn_sal_switch_to_interrupts - Switch to interrupt driven mode
|
||||||
* @port: Our sn_cons_port (which contains the uart port)
|
* @port: Our sn_cons_port (which contains the uart port)
|
||||||
*
|
*
|
||||||
* In sn_sal_module_init, after we're registered with serial core and
|
* In sn_sal_init, after we're registered with serial core and
|
||||||
* the port is added, this function is called to switch us to interrupt
|
* the port is added, this function is called to switch us to interrupt
|
||||||
* mode. We were previously in asynch/polling mode (using init_timer).
|
* mode. We were previously in asynch/polling mode (using init_timer).
|
||||||
*
|
*
|
||||||
@@ -773,7 +773,7 @@ static struct uart_driver sal_console_uart = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sn_sal_module_init - When the kernel loads us, get us rolling w/ serial core
|
* sn_sal_init - When the kernel loads us, get us rolling w/ serial core
|
||||||
*
|
*
|
||||||
* Before this is called, we've been printing kernel messages in a special
|
* Before this is called, we've been printing kernel messages in a special
|
||||||
* early mode not making use of the serial core infrastructure. When our
|
* early mode not making use of the serial core infrastructure. When our
|
||||||
@@ -781,7 +781,7 @@ static struct uart_driver sal_console_uart = {
|
|||||||
* core and try to enable interrupt driven mode.
|
* core and try to enable interrupt driven mode.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int __init sn_sal_module_init(void)
|
static int __init sn_sal_init(void)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
@@ -811,7 +811,7 @@ static int __init sn_sal_module_init(void)
|
|||||||
|
|
||||||
if (uart_register_driver(&sal_console_uart) < 0) {
|
if (uart_register_driver(&sal_console_uart) < 0) {
|
||||||
printk
|
printk
|
||||||
("ERROR sn_sal_module_init failed uart_register_driver, line %d\n",
|
("ERROR sn_sal_init failed uart_register_driver, line %d\n",
|
||||||
__LINE__);
|
__LINE__);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@@ -832,33 +832,19 @@ static int __init sn_sal_module_init(void)
|
|||||||
|
|
||||||
/* when this driver is compiled in, the console initialization
|
/* when this driver is compiled in, the console initialization
|
||||||
* will have already switched us into asynchronous operation
|
* will have already switched us into asynchronous operation
|
||||||
* before we get here through the module initcalls */
|
* before we get here through the initcalls */
|
||||||
if (!sal_console_port.sc_is_asynch) {
|
if (!sal_console_port.sc_is_asynch) {
|
||||||
sn_sal_switch_to_asynch(&sal_console_port);
|
sn_sal_switch_to_asynch(&sal_console_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* at this point (module_init) we can try to turn on interrupts */
|
/* at this point (device_init) we can try to turn on interrupts */
|
||||||
if (!IS_RUNNING_ON_SIMULATOR()) {
|
if (!IS_RUNNING_ON_SIMULATOR()) {
|
||||||
sn_sal_switch_to_interrupts(&sal_console_port);
|
sn_sal_switch_to_interrupts(&sal_console_port);
|
||||||
}
|
}
|
||||||
sn_process_input = 1;
|
sn_process_input = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
device_initcall(sn_sal_init);
|
||||||
/**
|
|
||||||
* sn_sal_module_exit - When we're unloaded, remove the driver/port
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void __exit sn_sal_module_exit(void)
|
|
||||||
{
|
|
||||||
del_timer_sync(&sal_console_port.sc_timer);
|
|
||||||
uart_remove_one_port(&sal_console_uart, &sal_console_port.sc_port);
|
|
||||||
uart_unregister_driver(&sal_console_uart);
|
|
||||||
misc_deregister(&misc);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(sn_sal_module_init);
|
|
||||||
module_exit(sn_sal_module_exit);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
|
* puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
* Inspired by st-asc.c from STMicroelectronics (c)
|
* Inspired by st-asc.c from STMicroelectronics (c)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(CONFIG_SERIAL_STM32_USART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
#if defined(CONFIG_SERIAL_STM32_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||||
#define SUPPORT_SYSRQ
|
#define SUPPORT_SYSRQ
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
@@ -234,14 +233,10 @@ static int __init suncore_init(void)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
device_initcall(suncore_init);
|
||||||
|
|
||||||
static void __exit suncore_exit(void)
|
#if 0 /* ..def MODULE ; never supported as such */
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(suncore_init);
|
|
||||||
module_exit(suncore_exit);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Eddie C. Dost, David S. Miller");
|
MODULE_AUTHOR("Eddie C. Dost, David S. Miller");
|
||||||
MODULE_DESCRIPTION("Sun serial common layer");
|
MODULE_DESCRIPTION("Sun serial common layer");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
#endif
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
* Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
|
* Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
@@ -621,7 +620,6 @@ static const struct of_device_id hv_match[] = {
|
|||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, hv_match);
|
|
||||||
|
|
||||||
static struct platform_driver hv_driver = {
|
static struct platform_driver hv_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
@@ -639,16 +637,11 @@ static int __init sunhv_init(void)
|
|||||||
|
|
||||||
return platform_driver_register(&hv_driver);
|
return platform_driver_register(&hv_driver);
|
||||||
}
|
}
|
||||||
|
device_initcall(sunhv_init);
|
||||||
|
|
||||||
static void __exit sunhv_exit(void)
|
#if 0 /* ...def MODULE ; never supported as such */
|
||||||
{
|
|
||||||
platform_driver_unregister(&hv_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(sunhv_init);
|
|
||||||
module_exit(sunhv_exit);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("David S. Miller");
|
MODULE_AUTHOR("David S. Miller");
|
||||||
MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
|
MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
|
||||||
MODULE_VERSION("2.0");
|
MODULE_VERSION("2.0");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
#endif
|
||||||
|
@@ -950,7 +950,7 @@ static void qe_uart_set_termios(struct uart_port *port,
|
|||||||
if ((termios->c_cflag & CREAD) == 0)
|
if ((termios->c_cflag & CREAD) == 0)
|
||||||
port->read_status_mask &= ~BD_SC_EMPTY;
|
port->read_status_mask &= ~BD_SC_EMPTY;
|
||||||
|
|
||||||
baud = uart_get_baud_rate(port, termios, old, 0, 115200);
|
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
|
||||||
|
|
||||||
/* Do we really need a spinlock here? */
|
/* Do we really need a spinlock here? */
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
@@ -291,12 +291,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
|
|||||||
n->flags = flags;
|
n->flags = flags;
|
||||||
buf->tail = n;
|
buf->tail = n;
|
||||||
b->commit = b->used;
|
b->commit = b->used;
|
||||||
/* paired w/ barrier in flush_to_ldisc(); ensures the
|
/* paired w/ acquire in flush_to_ldisc(); ensures the
|
||||||
* latest commit value can be read before the head is
|
* latest commit value can be read before the head is
|
||||||
* advanced to the next buffer
|
* advanced to the next buffer
|
||||||
*/
|
*/
|
||||||
smp_wmb();
|
smp_store_release(&b->next, n);
|
||||||
b->next = n;
|
|
||||||
} else if (change)
|
} else if (change)
|
||||||
size = 0;
|
size = 0;
|
||||||
else
|
else
|
||||||
@@ -445,7 +444,6 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count)
|
|||||||
if (count)
|
if (count)
|
||||||
disc->ops->receive_buf(tty, p, f, count);
|
disc->ops->receive_buf(tty, p, f, count);
|
||||||
}
|
}
|
||||||
head->read += count;
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,12 +486,11 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||||||
if (atomic_read(&buf->priority))
|
if (atomic_read(&buf->priority))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
next = head->next;
|
/* paired w/ release in __tty_buffer_request_room();
|
||||||
/* paired w/ barrier in __tty_buffer_request_room();
|
|
||||||
* ensures commit value read is not stale if the head
|
* ensures commit value read is not stale if the head
|
||||||
* is advancing to the next buffer
|
* is advancing to the next buffer
|
||||||
*/
|
*/
|
||||||
smp_rmb();
|
next = smp_load_acquire(&head->next);
|
||||||
count = head->commit - head->read;
|
count = head->commit - head->read;
|
||||||
if (!count) {
|
if (!count) {
|
||||||
if (next == NULL) {
|
if (next == NULL) {
|
||||||
@@ -508,6 +505,7 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||||||
count = receive_buf(tty, head, count);
|
count = receive_buf(tty, head, count);
|
||||||
if (!count)
|
if (!count)
|
||||||
break;
|
break;
|
||||||
|
head->read += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&buf->lock);
|
mutex_unlock(&buf->lock);
|
||||||
|
@@ -106,6 +106,11 @@
|
|||||||
#include <linux/nsproxy.h>
|
#include <linux/nsproxy.h>
|
||||||
|
|
||||||
#undef TTY_DEBUG_HANGUP
|
#undef TTY_DEBUG_HANGUP
|
||||||
|
#ifdef TTY_DEBUG_HANGUP
|
||||||
|
# define tty_debug_hangup(tty, f, args...) tty_debug(tty, f, ##args)
|
||||||
|
#else
|
||||||
|
# define tty_debug_hangup(tty, f, args...) do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TTY_PARANOIA_CHECK 1
|
#define TTY_PARANOIA_CHECK 1
|
||||||
#define CHECK_TTY_COUNT 1
|
#define CHECK_TTY_COUNT 1
|
||||||
@@ -388,33 +393,40 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
|
|||||||
int tty_check_change(struct tty_struct *tty)
|
int tty_check_change(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct pid *pgrp;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (current->signal->tty != tty)
|
if (current->signal->tty != tty)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
pgrp = task_pgrp(current);
|
||||||
|
|
||||||
spin_lock_irqsave(&tty->ctrl_lock, flags);
|
spin_lock_irqsave(&tty->ctrl_lock, flags);
|
||||||
|
|
||||||
if (!tty->pgrp) {
|
if (!tty->pgrp) {
|
||||||
printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
|
printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
if (task_pgrp(current) == tty->pgrp)
|
if (pgrp == tty->pgrp)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||||
|
|
||||||
if (is_ignored(SIGTTOU))
|
if (is_ignored(SIGTTOU))
|
||||||
goto out;
|
goto out_rcuunlock;
|
||||||
if (is_current_pgrp_orphaned()) {
|
if (is_current_pgrp_orphaned()) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out_rcuunlock;
|
||||||
}
|
}
|
||||||
kill_pgrp(task_pgrp(current), SIGTTOU, 1);
|
kill_pgrp(pgrp, SIGTTOU, 1);
|
||||||
|
rcu_read_unlock();
|
||||||
set_thread_flag(TIF_SIGPENDING);
|
set_thread_flag(TIF_SIGPENDING);
|
||||||
ret = -ERESTARTSYS;
|
ret = -ERESTARTSYS;
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
out_unlock:
|
out_unlock:
|
||||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||||
|
out_rcuunlock:
|
||||||
|
rcu_read_unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,7 +536,8 @@ static void __proc_set_tty(struct tty_struct *tty)
|
|||||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||||
tty->session = get_pid(task_session(current));
|
tty->session = get_pid(task_session(current));
|
||||||
if (current->signal->tty) {
|
if (current->signal->tty) {
|
||||||
printk(KERN_DEBUG "tty not NULL!!\n");
|
tty_debug(tty, "current tty %s not NULL!!\n",
|
||||||
|
current->signal->tty->name);
|
||||||
tty_kref_put(current->signal->tty);
|
tty_kref_put(current->signal->tty);
|
||||||
}
|
}
|
||||||
put_pid(current->signal->tty_old_pgrp);
|
put_pid(current->signal->tty_old_pgrp);
|
||||||
@@ -766,9 +779,7 @@ static void do_tty_hangup(struct work_struct *work)
|
|||||||
|
|
||||||
void tty_hangup(struct tty_struct *tty)
|
void tty_hangup(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
tty_debug_hangup(tty, "\n");
|
||||||
printk(KERN_DEBUG "%s hangup...\n", tty_name(tty));
|
|
||||||
#endif
|
|
||||||
schedule_work(&tty->hangup_work);
|
schedule_work(&tty->hangup_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,9 +796,7 @@ EXPORT_SYMBOL(tty_hangup);
|
|||||||
|
|
||||||
void tty_vhangup(struct tty_struct *tty)
|
void tty_vhangup(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
tty_debug_hangup(tty, "\n");
|
||||||
printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty));
|
|
||||||
#endif
|
|
||||||
__tty_hangup(tty, 0);
|
__tty_hangup(tty, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -824,9 +833,7 @@ void tty_vhangup_self(void)
|
|||||||
|
|
||||||
static void tty_vhangup_session(struct tty_struct *tty)
|
static void tty_vhangup_session(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
tty_debug_hangup(tty, "\n");
|
||||||
printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty));
|
|
||||||
#endif
|
|
||||||
__tty_hangup(tty, 1);
|
__tty_hangup(tty, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,12 +927,8 @@ void disassociate_ctty(int on_exit)
|
|||||||
tty->pgrp = NULL;
|
tty->pgrp = NULL;
|
||||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||||
tty_kref_put(tty);
|
tty_kref_put(tty);
|
||||||
} else {
|
} else
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
tty_debug_hangup(tty, "no current tty\n");
|
||||||
printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
|
|
||||||
" = NULL", tty);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
/* Now clear signal->tty under the lock */
|
/* Now clear signal->tty under the lock */
|
||||||
@@ -1705,8 +1708,7 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
|
|||||||
{
|
{
|
||||||
#ifdef TTY_PARANOIA_CHECK
|
#ifdef TTY_PARANOIA_CHECK
|
||||||
if (idx < 0 || idx >= tty->driver->num) {
|
if (idx < 0 || idx >= tty->driver->num) {
|
||||||
printk(KERN_DEBUG "%s: bad idx when trying to free (%s)\n",
|
tty_debug(tty, "bad idx %d\n", idx);
|
||||||
__func__, tty->name);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1715,20 +1717,20 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (tty != tty->driver->ttys[idx]) {
|
if (tty != tty->driver->ttys[idx]) {
|
||||||
printk(KERN_DEBUG "%s: driver.table[%d] not tty for (%s)\n",
|
tty_debug(tty, "bad driver table[%d] = %p\n",
|
||||||
__func__, idx, tty->name);
|
idx, tty->driver->ttys[idx]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (tty->driver->other) {
|
if (tty->driver->other) {
|
||||||
struct tty_struct *o_tty = tty->link;
|
struct tty_struct *o_tty = tty->link;
|
||||||
|
|
||||||
if (o_tty != tty->driver->other->ttys[idx]) {
|
if (o_tty != tty->driver->other->ttys[idx]) {
|
||||||
printk(KERN_DEBUG "%s: other->table[%d] not o_tty for (%s)\n",
|
tty_debug(tty, "bad other table[%d] = %p\n",
|
||||||
__func__, idx, tty->name);
|
idx, tty->driver->other->ttys[idx]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (o_tty->link != tty) {
|
if (o_tty->link != tty) {
|
||||||
printk(KERN_DEBUG "%s: bad pty pointers\n", __func__);
|
tty_debug(tty, "bad link = %p\n", o_tty->link);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1782,10 +1784,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
tty_debug_hangup(tty, "(tty count=%d)...\n", tty->count);
|
||||||
printk(KERN_DEBUG "%s: %s (tty count=%d)...\n", __func__,
|
|
||||||
tty_name(tty), tty->count);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (tty->ops->close)
|
if (tty->ops->close)
|
||||||
tty->ops->close(tty, filp);
|
tty->ops->close(tty, filp);
|
||||||
@@ -1895,9 +1894,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
|||||||
if (!final)
|
if (!final)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
tty_debug_hangup(tty, "final close\n");
|
||||||
printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty));
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Ask the line discipline code to release its structures
|
* Ask the line discipline code to release its structures
|
||||||
*/
|
*/
|
||||||
@@ -1906,10 +1903,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
|||||||
/* Wait for pending work before tty destruction commmences */
|
/* Wait for pending work before tty destruction commmences */
|
||||||
tty_flush_works(tty);
|
tty_flush_works(tty);
|
||||||
|
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
tty_debug_hangup(tty, "freeing structure...\n");
|
||||||
printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__,
|
|
||||||
tty_name(tty));
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* The release_tty function takes care of the details of clearing
|
* The release_tty function takes care of the details of clearing
|
||||||
* the slots and preserving the termios structure. The tty_unlock_pair
|
* the slots and preserving the termios structure. The tty_unlock_pair
|
||||||
@@ -2098,9 +2092,9 @@ retry_open:
|
|||||||
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
||||||
tty->driver->subtype == PTY_TYPE_MASTER)
|
tty->driver->subtype == PTY_TYPE_MASTER)
|
||||||
noctty = 1;
|
noctty = 1;
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
|
||||||
printk(KERN_DEBUG "%s: opening %s...\n", __func__, tty->name);
|
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
|
||||||
#endif
|
|
||||||
if (tty->ops->open)
|
if (tty->ops->open)
|
||||||
retval = tty->ops->open(tty, filp);
|
retval = tty->ops->open(tty, filp);
|
||||||
else
|
else
|
||||||
@@ -2108,10 +2102,8 @@ retry_open:
|
|||||||
filp->f_flags = saved_flags;
|
filp->f_flags = saved_flags;
|
||||||
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
#ifdef TTY_DEBUG_HANGUP
|
tty_debug_hangup(tty, "error %d, releasing...\n", retval);
|
||||||
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
|
|
||||||
retval, tty->name);
|
|
||||||
#endif
|
|
||||||
tty_unlock(tty); /* need to call tty_release without BTM */
|
tty_unlock(tty); /* need to call tty_release without BTM */
|
||||||
tty_release(inode, filp);
|
tty_release(inode, filp);
|
||||||
if (retval != -ERESTARTSYS)
|
if (retval != -ERESTARTSYS)
|
||||||
@@ -3160,9 +3152,12 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
|
|||||||
unsigned int index, unsigned int count)
|
unsigned int index, unsigned int count)
|
||||||
{
|
{
|
||||||
/* init here, since reused cdevs cause crashes */
|
/* init here, since reused cdevs cause crashes */
|
||||||
cdev_init(&driver->cdevs[index], &tty_fops);
|
driver->cdevs[index] = cdev_alloc();
|
||||||
driver->cdevs[index].owner = driver->owner;
|
if (!driver->cdevs[index])
|
||||||
return cdev_add(&driver->cdevs[index], dev, count);
|
return -ENOMEM;
|
||||||
|
cdev_init(driver->cdevs[index], &tty_fops);
|
||||||
|
driver->cdevs[index]->owner = driver->owner;
|
||||||
|
return cdev_add(driver->cdevs[index], dev, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3268,8 +3263,10 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
if (cdev)
|
if (cdev) {
|
||||||
cdev_del(&driver->cdevs[index]);
|
cdev_del(driver->cdevs[index]);
|
||||||
|
driver->cdevs[index] = NULL;
|
||||||
|
}
|
||||||
return ERR_PTR(retval);
|
return ERR_PTR(retval);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tty_register_device_attr);
|
EXPORT_SYMBOL_GPL(tty_register_device_attr);
|
||||||
@@ -3289,8 +3286,10 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
|
|||||||
{
|
{
|
||||||
device_destroy(tty_class,
|
device_destroy(tty_class,
|
||||||
MKDEV(driver->major, driver->minor_start) + index);
|
MKDEV(driver->major, driver->minor_start) + index);
|
||||||
if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC))
|
if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
|
||||||
cdev_del(&driver->cdevs[index]);
|
cdev_del(driver->cdevs[index]);
|
||||||
|
driver->cdevs[index] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_unregister_device);
|
EXPORT_SYMBOL(tty_unregister_device);
|
||||||
|
|
||||||
@@ -3355,6 +3354,7 @@ err_free_all:
|
|||||||
kfree(driver->ports);
|
kfree(driver->ports);
|
||||||
kfree(driver->ttys);
|
kfree(driver->ttys);
|
||||||
kfree(driver->termios);
|
kfree(driver->termios);
|
||||||
|
kfree(driver->cdevs);
|
||||||
kfree(driver);
|
kfree(driver);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
@@ -3383,7 +3383,7 @@ static void destruct_tty_driver(struct kref *kref)
|
|||||||
}
|
}
|
||||||
proc_tty_unregister_driver(driver);
|
proc_tty_unregister_driver(driver);
|
||||||
if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)
|
if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)
|
||||||
cdev_del(&driver->cdevs[0]);
|
cdev_del(driver->cdevs[0]);
|
||||||
}
|
}
|
||||||
kfree(driver->cdevs);
|
kfree(driver->cdevs);
|
||||||
kfree(driver->ports);
|
kfree(driver->ports);
|
||||||
|
@@ -26,6 +26,12 @@
|
|||||||
|
|
||||||
#undef TTY_DEBUG_WAIT_UNTIL_SENT
|
#undef TTY_DEBUG_WAIT_UNTIL_SENT
|
||||||
|
|
||||||
|
#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
|
||||||
|
# define tty_debug_wait_until_sent(tty, f, args...) tty_debug(tty, f, ##args)
|
||||||
|
#else
|
||||||
|
# define tty_debug_wait_until_sent(tty, f, args...) do {} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -210,9 +216,8 @@ int tty_unthrottle_safe(struct tty_struct *tty)
|
|||||||
|
|
||||||
void tty_wait_until_sent(struct tty_struct *tty, long timeout)
|
void tty_wait_until_sent(struct tty_struct *tty, long timeout)
|
||||||
{
|
{
|
||||||
#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
|
tty_debug_wait_until_sent(tty, "\n");
|
||||||
printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty));
|
|
||||||
#endif
|
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
timeout = MAX_SCHEDULE_TIMEOUT;
|
timeout = MAX_SCHEDULE_TIMEOUT;
|
||||||
|
|
||||||
|
@@ -22,9 +22,7 @@
|
|||||||
#undef LDISC_DEBUG_HANGUP
|
#undef LDISC_DEBUG_HANGUP
|
||||||
|
|
||||||
#ifdef LDISC_DEBUG_HANGUP
|
#ifdef LDISC_DEBUG_HANGUP
|
||||||
#define tty_ldisc_debug(tty, f, args...) ({ \
|
#define tty_ldisc_debug(tty, f, args...) tty_debug(tty, f, ##args)
|
||||||
printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty), ##args); \
|
|
||||||
})
|
|
||||||
#else
|
#else
|
||||||
#define tty_ldisc_debug(tty, f, args...)
|
#define tty_ldisc_debug(tty, f, args...)
|
||||||
#endif
|
#endif
|
||||||
@@ -449,6 +447,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
|
|||||||
ret = ld->ops->open(tty);
|
ret = ld->ops->open(tty);
|
||||||
if (ret)
|
if (ret)
|
||||||
clear_bit(TTY_LDISC_OPEN, &tty->flags);
|
clear_bit(TTY_LDISC_OPEN, &tty->flags);
|
||||||
|
|
||||||
|
tty_ldisc_debug(tty, "%p: opened\n", tty->ldisc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -469,6 +469,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
|
|||||||
clear_bit(TTY_LDISC_OPEN, &tty->flags);
|
clear_bit(TTY_LDISC_OPEN, &tty->flags);
|
||||||
if (ld->ops->close)
|
if (ld->ops->close)
|
||||||
ld->ops->close(tty);
|
ld->ops->close(tty);
|
||||||
|
tty_ldisc_debug(tty, "%p: closed\n", tty->ldisc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -662,7 +663,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
|||||||
int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
|
int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
|
tty_ldisc_debug(tty, "%p: closing\n", tty->ldisc);
|
||||||
|
|
||||||
ld = tty_ldisc_ref(tty);
|
ld = tty_ldisc_ref(tty);
|
||||||
if (ld != NULL) {
|
if (ld != NULL) {
|
||||||
@@ -712,7 +713,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
|||||||
if (reset)
|
if (reset)
|
||||||
tty_reset_termios(tty);
|
tty_reset_termios(tty);
|
||||||
|
|
||||||
tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc);
|
tty_ldisc_debug(tty, "%p: re-opened\n", tty->ldisc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -776,8 +777,6 @@ void tty_ldisc_release(struct tty_struct *tty)
|
|||||||
* it does not race with the set_ldisc code path.
|
* it does not race with the set_ldisc code path.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
|
|
||||||
|
|
||||||
tty_ldisc_lock_pair(tty, o_tty);
|
tty_ldisc_lock_pair(tty, o_tty);
|
||||||
tty_ldisc_kill(tty);
|
tty_ldisc_kill(tty);
|
||||||
if (o_tty)
|
if (o_tty)
|
||||||
@@ -787,7 +786,7 @@ void tty_ldisc_release(struct tty_struct *tty)
|
|||||||
/* And the memory resources remaining (buffers, termios) will be
|
/* And the memory resources remaining (buffers, termios) will be
|
||||||
disposed of when the kref hits zero */
|
disposed of when the kref hits zero */
|
||||||
|
|
||||||
tty_ldisc_debug(tty, "ldisc closed\n");
|
tty_ldisc_debug(tty, "released\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -33,12 +33,14 @@
|
|||||||
#define UART01x_DR 0x00 /* Data read or written from the interface. */
|
#define UART01x_DR 0x00 /* Data read or written from the interface. */
|
||||||
#define UART01x_RSR 0x04 /* Receive status register (Read). */
|
#define UART01x_RSR 0x04 /* Receive status register (Read). */
|
||||||
#define UART01x_ECR 0x04 /* Error clear register (Write). */
|
#define UART01x_ECR 0x04 /* Error clear register (Write). */
|
||||||
|
#define ZX_UART01x_DR 0x04 /* Data read or written from the interface. */
|
||||||
#define UART010_LCRH 0x08 /* Line control register, high byte. */
|
#define UART010_LCRH 0x08 /* Line control register, high byte. */
|
||||||
#define ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */
|
#define ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */
|
||||||
#define UART010_LCRM 0x0C /* Line control register, middle byte. */
|
#define UART010_LCRM 0x0C /* Line control register, middle byte. */
|
||||||
#define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */
|
#define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */
|
||||||
#define UART010_LCRL 0x10 /* Line control register, low byte. */
|
#define UART010_LCRL 0x10 /* Line control register, low byte. */
|
||||||
#define UART010_CR 0x14 /* Control register. */
|
#define UART010_CR 0x14 /* Control register. */
|
||||||
|
#define ZX_UART01x_FR 0x14 /* Flag register (Read only). */
|
||||||
#define UART01x_FR 0x18 /* Flag register (Read only). */
|
#define UART01x_FR 0x18 /* Flag register (Read only). */
|
||||||
#define UART010_IIR 0x1C /* Interrupt identification register (Read). */
|
#define UART010_IIR 0x1C /* Interrupt identification register (Read). */
|
||||||
#define UART010_ICR 0x1C /* Interrupt clear register (Write). */
|
#define UART010_ICR 0x1C /* Interrupt clear register (Write). */
|
||||||
@@ -49,13 +51,21 @@
|
|||||||
#define UART011_LCRH 0x2c /* Line control register. */
|
#define UART011_LCRH 0x2c /* Line control register. */
|
||||||
#define ST_UART011_LCRH_TX 0x2c /* Tx Line control register. */
|
#define ST_UART011_LCRH_TX 0x2c /* Tx Line control register. */
|
||||||
#define UART011_CR 0x30 /* Control register. */
|
#define UART011_CR 0x30 /* Control register. */
|
||||||
|
#define ZX_UART011_LCRH_TX 0x30 /* Tx Line control register. */
|
||||||
#define UART011_IFLS 0x34 /* Interrupt fifo level select. */
|
#define UART011_IFLS 0x34 /* Interrupt fifo level select. */
|
||||||
|
#define ZX_UART011_CR 0x34 /* Control register. */
|
||||||
|
#define ZX_UART011_IFLS 0x38 /* Interrupt fifo level select. */
|
||||||
#define UART011_IMSC 0x38 /* Interrupt mask. */
|
#define UART011_IMSC 0x38 /* Interrupt mask. */
|
||||||
#define UART011_RIS 0x3c /* Raw interrupt status. */
|
#define UART011_RIS 0x3c /* Raw interrupt status. */
|
||||||
#define UART011_MIS 0x40 /* Masked interrupt status. */
|
#define UART011_MIS 0x40 /* Masked interrupt status. */
|
||||||
|
#define ZX_UART011_IMSC 0x40 /* Interrupt mask. */
|
||||||
#define UART011_ICR 0x44 /* Interrupt clear register. */
|
#define UART011_ICR 0x44 /* Interrupt clear register. */
|
||||||
|
#define ZX_UART011_RIS 0x44 /* Raw interrupt status. */
|
||||||
#define UART011_DMACR 0x48 /* DMA control register. */
|
#define UART011_DMACR 0x48 /* DMA control register. */
|
||||||
|
#define ZX_UART011_MIS 0x48 /* Masked interrupt status. */
|
||||||
|
#define ZX_UART011_ICR 0x4c /* Interrupt clear register. */
|
||||||
#define ST_UART011_XFCR 0x50 /* XON/XOFF control register. */
|
#define ST_UART011_XFCR 0x50 /* XON/XOFF control register. */
|
||||||
|
#define ZX_UART011_DMACR 0x50 /* DMA control register. */
|
||||||
#define ST_UART011_XON1 0x54 /* XON1 register. */
|
#define ST_UART011_XON1 0x54 /* XON1 register. */
|
||||||
#define ST_UART011_XON2 0x58 /* XON2 register. */
|
#define ST_UART011_XON2 0x58 /* XON2 register. */
|
||||||
#define ST_UART011_XOFF1 0x5C /* XON1 register. */
|
#define ST_UART011_XOFF1 0x5C /* XON1 register. */
|
||||||
@@ -75,15 +85,19 @@
|
|||||||
#define UART01x_RSR_PE 0x02
|
#define UART01x_RSR_PE 0x02
|
||||||
#define UART01x_RSR_FE 0x01
|
#define UART01x_RSR_FE 0x01
|
||||||
|
|
||||||
|
#define ZX_UART01x_FR_BUSY 0x300
|
||||||
#define UART011_FR_RI 0x100
|
#define UART011_FR_RI 0x100
|
||||||
#define UART011_FR_TXFE 0x080
|
#define UART011_FR_TXFE 0x080
|
||||||
#define UART011_FR_RXFF 0x040
|
#define UART011_FR_RXFF 0x040
|
||||||
#define UART01x_FR_TXFF 0x020
|
#define UART01x_FR_TXFF 0x020
|
||||||
#define UART01x_FR_RXFE 0x010
|
#define UART01x_FR_RXFE 0x010
|
||||||
#define UART01x_FR_BUSY 0x008
|
#define UART01x_FR_BUSY 0x008
|
||||||
|
#define ZX_UART01x_FR_DSR 0x008
|
||||||
#define UART01x_FR_DCD 0x004
|
#define UART01x_FR_DCD 0x004
|
||||||
#define UART01x_FR_DSR 0x002
|
#define UART01x_FR_DSR 0x002
|
||||||
|
#define ZX_UART01x_FR_CTS 0x002
|
||||||
#define UART01x_FR_CTS 0x001
|
#define UART01x_FR_CTS 0x001
|
||||||
|
#define ZX_UART011_FR_RI 0x001
|
||||||
#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY)
|
#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY)
|
||||||
|
|
||||||
#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */
|
#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */
|
||||||
|
@@ -16,115 +16,151 @@
|
|||||||
#ifndef ATMEL_SERIAL_H
|
#ifndef ATMEL_SERIAL_H
|
||||||
#define ATMEL_SERIAL_H
|
#define ATMEL_SERIAL_H
|
||||||
|
|
||||||
#define ATMEL_US_CR 0x00 /* Control Register */
|
#define ATMEL_US_CR 0x00 /* Control Register */
|
||||||
#define ATMEL_US_RSTRX (1 << 2) /* Reset Receiver */
|
#define ATMEL_US_RSTRX BIT(2) /* Reset Receiver */
|
||||||
#define ATMEL_US_RSTTX (1 << 3) /* Reset Transmitter */
|
#define ATMEL_US_RSTTX BIT(3) /* Reset Transmitter */
|
||||||
#define ATMEL_US_RXEN (1 << 4) /* Receiver Enable */
|
#define ATMEL_US_RXEN BIT(4) /* Receiver Enable */
|
||||||
#define ATMEL_US_RXDIS (1 << 5) /* Receiver Disable */
|
#define ATMEL_US_RXDIS BIT(5) /* Receiver Disable */
|
||||||
#define ATMEL_US_TXEN (1 << 6) /* Transmitter Enable */
|
#define ATMEL_US_TXEN BIT(6) /* Transmitter Enable */
|
||||||
#define ATMEL_US_TXDIS (1 << 7) /* Transmitter Disable */
|
#define ATMEL_US_TXDIS BIT(7) /* Transmitter Disable */
|
||||||
#define ATMEL_US_RSTSTA (1 << 8) /* Reset Status Bits */
|
#define ATMEL_US_RSTSTA BIT(8) /* Reset Status Bits */
|
||||||
#define ATMEL_US_STTBRK (1 << 9) /* Start Break */
|
#define ATMEL_US_STTBRK BIT(9) /* Start Break */
|
||||||
#define ATMEL_US_STPBRK (1 << 10) /* Stop Break */
|
#define ATMEL_US_STPBRK BIT(10) /* Stop Break */
|
||||||
#define ATMEL_US_STTTO (1 << 11) /* Start Time-out */
|
#define ATMEL_US_STTTO BIT(11) /* Start Time-out */
|
||||||
#define ATMEL_US_SENDA (1 << 12) /* Send Address */
|
#define ATMEL_US_SENDA BIT(12) /* Send Address */
|
||||||
#define ATMEL_US_RSTIT (1 << 13) /* Reset Iterations */
|
#define ATMEL_US_RSTIT BIT(13) /* Reset Iterations */
|
||||||
#define ATMEL_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */
|
#define ATMEL_US_RSTNACK BIT(14) /* Reset Non Acknowledge */
|
||||||
#define ATMEL_US_RETTO (1 << 15) /* Rearm Time-out */
|
#define ATMEL_US_RETTO BIT(15) /* Rearm Time-out */
|
||||||
#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable [AT91RM9200 only] */
|
#define ATMEL_US_DTREN BIT(16) /* Data Terminal Ready Enable */
|
||||||
#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable [AT91RM9200 only] */
|
#define ATMEL_US_DTRDIS BIT(17) /* Data Terminal Ready Disable */
|
||||||
#define ATMEL_US_RTSEN (1 << 18) /* Request To Send Enable */
|
#define ATMEL_US_RTSEN BIT(18) /* Request To Send Enable */
|
||||||
#define ATMEL_US_RTSDIS (1 << 19) /* Request To Send Disable */
|
#define ATMEL_US_RTSDIS BIT(19) /* Request To Send Disable */
|
||||||
|
#define ATMEL_US_TXFCLR BIT(24) /* Transmit FIFO Clear */
|
||||||
|
#define ATMEL_US_RXFCLR BIT(25) /* Receive FIFO Clear */
|
||||||
|
#define ATMEL_US_TXFLCLR BIT(26) /* Transmit FIFO Lock Clear */
|
||||||
|
#define ATMEL_US_FIFOEN BIT(30) /* FIFO enable */
|
||||||
|
#define ATMEL_US_FIFODIS BIT(31) /* FIFO disable */
|
||||||
|
|
||||||
#define ATMEL_US_MR 0x04 /* Mode Register */
|
#define ATMEL_US_MR 0x04 /* Mode Register */
|
||||||
#define ATMEL_US_USMODE (0xf << 0) /* Mode of the USART */
|
#define ATMEL_US_USMODE GENMASK(3, 0) /* Mode of the USART */
|
||||||
#define ATMEL_US_USMODE_NORMAL 0
|
#define ATMEL_US_USMODE_NORMAL 0
|
||||||
#define ATMEL_US_USMODE_RS485 1
|
#define ATMEL_US_USMODE_RS485 1
|
||||||
#define ATMEL_US_USMODE_HWHS 2
|
#define ATMEL_US_USMODE_HWHS 2
|
||||||
#define ATMEL_US_USMODE_MODEM 3
|
#define ATMEL_US_USMODE_MODEM 3
|
||||||
#define ATMEL_US_USMODE_ISO7816_T0 4
|
#define ATMEL_US_USMODE_ISO7816_T0 4
|
||||||
#define ATMEL_US_USMODE_ISO7816_T1 6
|
#define ATMEL_US_USMODE_ISO7816_T1 6
|
||||||
#define ATMEL_US_USMODE_IRDA 8
|
#define ATMEL_US_USMODE_IRDA 8
|
||||||
#define ATMEL_US_USCLKS (3 << 4) /* Clock Selection */
|
#define ATMEL_US_USCLKS GENMASK(5, 4) /* Clock Selection */
|
||||||
#define ATMEL_US_USCLKS_MCK (0 << 4)
|
#define ATMEL_US_USCLKS_MCK (0 << 4)
|
||||||
#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
|
#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
|
||||||
#define ATMEL_US_USCLKS_SCK (3 << 4)
|
#define ATMEL_US_USCLKS_SCK (3 << 4)
|
||||||
#define ATMEL_US_CHRL (3 << 6) /* Character Length */
|
#define ATMEL_US_CHRL GENMASK(7, 6) /* Character Length */
|
||||||
#define ATMEL_US_CHRL_5 (0 << 6)
|
#define ATMEL_US_CHRL_5 (0 << 6)
|
||||||
#define ATMEL_US_CHRL_6 (1 << 6)
|
#define ATMEL_US_CHRL_6 (1 << 6)
|
||||||
#define ATMEL_US_CHRL_7 (2 << 6)
|
#define ATMEL_US_CHRL_7 (2 << 6)
|
||||||
#define ATMEL_US_CHRL_8 (3 << 6)
|
#define ATMEL_US_CHRL_8 (3 << 6)
|
||||||
#define ATMEL_US_SYNC (1 << 8) /* Synchronous Mode Select */
|
#define ATMEL_US_SYNC BIT(8) /* Synchronous Mode Select */
|
||||||
#define ATMEL_US_PAR (7 << 9) /* Parity Type */
|
#define ATMEL_US_PAR GENMASK(11, 9) /* Parity Type */
|
||||||
#define ATMEL_US_PAR_EVEN (0 << 9)
|
#define ATMEL_US_PAR_EVEN (0 << 9)
|
||||||
#define ATMEL_US_PAR_ODD (1 << 9)
|
#define ATMEL_US_PAR_ODD (1 << 9)
|
||||||
#define ATMEL_US_PAR_SPACE (2 << 9)
|
#define ATMEL_US_PAR_SPACE (2 << 9)
|
||||||
#define ATMEL_US_PAR_MARK (3 << 9)
|
#define ATMEL_US_PAR_MARK (3 << 9)
|
||||||
#define ATMEL_US_PAR_NONE (4 << 9)
|
#define ATMEL_US_PAR_NONE (4 << 9)
|
||||||
#define ATMEL_US_PAR_MULTI_DROP (6 << 9)
|
#define ATMEL_US_PAR_MULTI_DROP (6 << 9)
|
||||||
#define ATMEL_US_NBSTOP (3 << 12) /* Number of Stop Bits */
|
#define ATMEL_US_NBSTOP GENMASK(13, 12) /* Number of Stop Bits */
|
||||||
#define ATMEL_US_NBSTOP_1 (0 << 12)
|
#define ATMEL_US_NBSTOP_1 (0 << 12)
|
||||||
#define ATMEL_US_NBSTOP_1_5 (1 << 12)
|
#define ATMEL_US_NBSTOP_1_5 (1 << 12)
|
||||||
#define ATMEL_US_NBSTOP_2 (2 << 12)
|
#define ATMEL_US_NBSTOP_2 (2 << 12)
|
||||||
#define ATMEL_US_CHMODE (3 << 14) /* Channel Mode */
|
#define ATMEL_US_CHMODE GENMASK(15, 14) /* Channel Mode */
|
||||||
#define ATMEL_US_CHMODE_NORMAL (0 << 14)
|
#define ATMEL_US_CHMODE_NORMAL (0 << 14)
|
||||||
#define ATMEL_US_CHMODE_ECHO (1 << 14)
|
#define ATMEL_US_CHMODE_ECHO (1 << 14)
|
||||||
#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
|
#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
|
||||||
#define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
|
#define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
|
||||||
#define ATMEL_US_MSBF (1 << 16) /* Bit Order */
|
#define ATMEL_US_MSBF BIT(16) /* Bit Order */
|
||||||
#define ATMEL_US_MODE9 (1 << 17) /* 9-bit Character Length */
|
#define ATMEL_US_MODE9 BIT(17) /* 9-bit Character Length */
|
||||||
#define ATMEL_US_CLKO (1 << 18) /* Clock Output Select */
|
#define ATMEL_US_CLKO BIT(18) /* Clock Output Select */
|
||||||
#define ATMEL_US_OVER (1 << 19) /* Oversampling Mode */
|
#define ATMEL_US_OVER BIT(19) /* Oversampling Mode */
|
||||||
#define ATMEL_US_INACK (1 << 20) /* Inhibit Non Acknowledge */
|
#define ATMEL_US_INACK BIT(20) /* Inhibit Non Acknowledge */
|
||||||
#define ATMEL_US_DSNACK (1 << 21) /* Disable Successive NACK */
|
#define ATMEL_US_DSNACK BIT(21) /* Disable Successive NACK */
|
||||||
#define ATMEL_US_MAX_ITER (7 << 24) /* Max Iterations */
|
#define ATMEL_US_MAX_ITER GENMASK(26, 24) /* Max Iterations */
|
||||||
#define ATMEL_US_FILTER (1 << 28) /* Infrared Receive Line Filter */
|
#define ATMEL_US_FILTER BIT(28) /* Infrared Receive Line Filter */
|
||||||
|
|
||||||
#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
|
#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
|
||||||
#define ATMEL_US_RXRDY (1 << 0) /* Receiver Ready */
|
#define ATMEL_US_RXRDY BIT(0) /* Receiver Ready */
|
||||||
#define ATMEL_US_TXRDY (1 << 1) /* Transmitter Ready */
|
#define ATMEL_US_TXRDY BIT(1) /* Transmitter Ready */
|
||||||
#define ATMEL_US_RXBRK (1 << 2) /* Break Received / End of Break */
|
#define ATMEL_US_RXBRK BIT(2) /* Break Received / End of Break */
|
||||||
#define ATMEL_US_ENDRX (1 << 3) /* End of Receiver Transfer */
|
#define ATMEL_US_ENDRX BIT(3) /* End of Receiver Transfer */
|
||||||
#define ATMEL_US_ENDTX (1 << 4) /* End of Transmitter Transfer */
|
#define ATMEL_US_ENDTX BIT(4) /* End of Transmitter Transfer */
|
||||||
#define ATMEL_US_OVRE (1 << 5) /* Overrun Error */
|
#define ATMEL_US_OVRE BIT(5) /* Overrun Error */
|
||||||
#define ATMEL_US_FRAME (1 << 6) /* Framing Error */
|
#define ATMEL_US_FRAME BIT(6) /* Framing Error */
|
||||||
#define ATMEL_US_PARE (1 << 7) /* Parity Error */
|
#define ATMEL_US_PARE BIT(7) /* Parity Error */
|
||||||
#define ATMEL_US_TIMEOUT (1 << 8) /* Receiver Time-out */
|
#define ATMEL_US_TIMEOUT BIT(8) /* Receiver Time-out */
|
||||||
#define ATMEL_US_TXEMPTY (1 << 9) /* Transmitter Empty */
|
#define ATMEL_US_TXEMPTY BIT(9) /* Transmitter Empty */
|
||||||
#define ATMEL_US_ITERATION (1 << 10) /* Max number of Repetitions Reached */
|
#define ATMEL_US_ITERATION BIT(10) /* Max number of Repetitions Reached */
|
||||||
#define ATMEL_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */
|
#define ATMEL_US_TXBUFE BIT(11) /* Transmission Buffer Empty */
|
||||||
#define ATMEL_US_RXBUFF (1 << 12) /* Reception Buffer Full */
|
#define ATMEL_US_RXBUFF BIT(12) /* Reception Buffer Full */
|
||||||
#define ATMEL_US_NACK (1 << 13) /* Non Acknowledge */
|
#define ATMEL_US_NACK BIT(13) /* Non Acknowledge */
|
||||||
#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change [AT91RM9200 only] */
|
#define ATMEL_US_RIIC BIT(16) /* Ring Indicator Input Change */
|
||||||
#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change [AT91RM9200 only] */
|
#define ATMEL_US_DSRIC BIT(17) /* Data Set Ready Input Change */
|
||||||
#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change [AT91RM9200 only] */
|
#define ATMEL_US_DCDIC BIT(18) /* Data Carrier Detect Input Change */
|
||||||
#define ATMEL_US_CTSIC (1 << 19) /* Clear to Send Input Change */
|
#define ATMEL_US_CTSIC BIT(19) /* Clear to Send Input Change */
|
||||||
#define ATMEL_US_RI (1 << 20) /* RI */
|
#define ATMEL_US_RI BIT(20) /* RI */
|
||||||
#define ATMEL_US_DSR (1 << 21) /* DSR */
|
#define ATMEL_US_DSR BIT(21) /* DSR */
|
||||||
#define ATMEL_US_DCD (1 << 22) /* DCD */
|
#define ATMEL_US_DCD BIT(22) /* DCD */
|
||||||
#define ATMEL_US_CTS (1 << 23) /* CTS */
|
#define ATMEL_US_CTS BIT(23) /* CTS */
|
||||||
|
|
||||||
#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */
|
#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */
|
||||||
#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */
|
#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */
|
||||||
#define ATMEL_US_CSR 0x14 /* Channel Status Register */
|
#define ATMEL_US_CSR 0x14 /* Channel Status Register */
|
||||||
#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
|
#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
|
||||||
#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
|
#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
|
||||||
#define ATMEL_US_SYNH (1 << 15) /* Transmit/Receive Sync [AT91SAM9261 only] */
|
#define ATMEL_US_SYNH BIT(15) /* Transmit/Receive Sync */
|
||||||
|
|
||||||
#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
|
#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
|
||||||
#define ATMEL_US_CD (0xffff << 0) /* Clock Divider */
|
#define ATMEL_US_CD GENMASK(15, 0) /* Clock Divider */
|
||||||
|
|
||||||
#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */
|
#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */
|
||||||
#define ATMEL_US_TO (0xffff << 0) /* Time-out Value */
|
#define ATMEL_US_TO GENMASK(15, 0) /* Time-out Value */
|
||||||
|
|
||||||
#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */
|
#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */
|
||||||
#define ATMEL_US_TG (0xff << 0) /* Timeguard Value */
|
#define ATMEL_US_TG GENMASK(7, 0) /* Timeguard Value */
|
||||||
|
|
||||||
#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */
|
#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */
|
||||||
#define ATMEL_US_NER 0x44 /* Number of Errors Register */
|
#define ATMEL_US_NER 0x44 /* Number of Errors Register */
|
||||||
#define ATMEL_US_IF 0x4c /* IrDA Filter Register */
|
#define ATMEL_US_IF 0x4c /* IrDA Filter Register */
|
||||||
|
|
||||||
#define ATMEL_US_NAME 0xf0 /* Ip Name */
|
#define ATMEL_US_CMPR 0x90 /* Comparaison Register */
|
||||||
#define ATMEL_US_VERSION 0xfc /* Ip Version */
|
#define ATMEL_US_FMR 0xa0 /* FIFO Mode Register */
|
||||||
|
#define ATMEL_US_TXRDYM(data) (((data) & 0x3) << 0) /* TX Ready Mode */
|
||||||
|
#define ATMEL_US_RXRDYM(data) (((data) & 0x3) << 4) /* RX Ready Mode */
|
||||||
|
#define ATMEL_US_ONE_DATA 0x0
|
||||||
|
#define ATMEL_US_TWO_DATA 0x1
|
||||||
|
#define ATMEL_US_FOUR_DATA 0x2
|
||||||
|
#define ATMEL_US_FRTSC BIT(7) /* FIFO RTS pin Control */
|
||||||
|
#define ATMEL_US_TXFTHRES(thr) (((thr) & 0x3f) << 8) /* TX FIFO Threshold */
|
||||||
|
#define ATMEL_US_RXFTHRES(thr) (((thr) & 0x3f) << 16) /* RX FIFO Threshold */
|
||||||
|
#define ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24) /* RX FIFO Threshold2 */
|
||||||
|
|
||||||
|
#define ATMEL_US_FLR 0xa4 /* FIFO Level Register */
|
||||||
|
#define ATMEL_US_TXFL(reg) (((reg) >> 0) & 0x3f) /* TX FIFO Level */
|
||||||
|
#define ATMEL_US_RXFL(reg) (((reg) >> 16) & 0x3f) /* RX FIFO Level */
|
||||||
|
|
||||||
|
#define ATMEL_US_FIER 0xa8 /* FIFO Interrupt Enable Register */
|
||||||
|
#define ATMEL_US_FIDR 0xac /* FIFO Interrupt Disable Register */
|
||||||
|
#define ATMEL_US_FIMR 0xb0 /* FIFO Interrupt Mask Register */
|
||||||
|
#define ATMEL_US_FESR 0xb4 /* FIFO Event Status Register */
|
||||||
|
#define ATMEL_US_TXFEF BIT(0) /* Transmit FIFO Empty Flag */
|
||||||
|
#define ATMEL_US_TXFFF BIT(1) /* Transmit FIFO Full Flag */
|
||||||
|
#define ATMEL_US_TXFTHF BIT(2) /* Transmit FIFO Threshold Flag */
|
||||||
|
#define ATMEL_US_RXFEF BIT(3) /* Receive FIFO Empty Flag */
|
||||||
|
#define ATMEL_US_RXFFF BIT(4) /* Receive FIFO Full Flag */
|
||||||
|
#define ATMEL_US_RXFTHF BIT(5) /* Receive FIFO Threshold Flag */
|
||||||
|
#define ATMEL_US_TXFPTEF BIT(6) /* Transmit FIFO Pointer Error Flag */
|
||||||
|
#define ATMEL_US_RXFPTEF BIT(7) /* Receive FIFO Pointer Error Flag */
|
||||||
|
#define ATMEL_US_TXFLOCK BIT(8) /* Transmit FIFO Lock (FESR only) */
|
||||||
|
#define ATMEL_US_RXFTHF2 BIT(9) /* Receive FIFO Threshold Flag 2 */
|
||||||
|
|
||||||
|
#define ATMEL_US_NAME 0xf0 /* Ip Name */
|
||||||
|
#define ATMEL_US_VERSION 0xfc /* Ip Version */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -136,8 +136,6 @@ void serial8250_resume_port(int line);
|
|||||||
|
|
||||||
extern int early_serial_setup(struct uart_port *port);
|
extern int early_serial_setup(struct uart_port *port);
|
||||||
|
|
||||||
extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
|
|
||||||
extern void serial8250_early_out(struct uart_port *port, int offset, int value);
|
|
||||||
extern int early_serial8250_setup(struct earlycon_device *device,
|
extern int early_serial8250_setup(struct earlycon_device *device,
|
||||||
const char *options);
|
const char *options);
|
||||||
extern void serial8250_do_set_termios(struct uart_port *port,
|
extern void serial8250_do_set_termios(struct uart_port *port,
|
||||||
@@ -152,6 +150,11 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
|
|||||||
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
|
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
|
||||||
void serial8250_tx_chars(struct uart_8250_port *up);
|
void serial8250_tx_chars(struct uart_8250_port *up);
|
||||||
unsigned int serial8250_modem_status(struct uart_8250_port *up);
|
unsigned int serial8250_modem_status(struct uart_8250_port *up);
|
||||||
|
void serial8250_init_port(struct uart_8250_port *up);
|
||||||
|
void serial8250_set_defaults(struct uart_8250_port *up);
|
||||||
|
void serial8250_console_write(struct uart_8250_port *up, const char *s,
|
||||||
|
unsigned int count);
|
||||||
|
int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
|
||||||
|
|
||||||
extern void serial8250_set_isa_configurator(void (*v)
|
extern void serial8250_set_isa_configurator(void (*v)
|
||||||
(int port, struct uart_port *up,
|
(int port, struct uart_port *up,
|
||||||
|
@@ -709,4 +709,10 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {}
|
|||||||
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
|
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define tty_debug(tty, f, args...) \
|
||||||
|
do { \
|
||||||
|
printk(KERN_DEBUG "%s: %s: " f, __func__, \
|
||||||
|
tty_name(tty), ##args); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -296,7 +296,7 @@ struct tty_operations {
|
|||||||
struct tty_driver {
|
struct tty_driver {
|
||||||
int magic; /* magic number for this structure */
|
int magic; /* magic number for this structure */
|
||||||
struct kref kref; /* Reference management */
|
struct kref kref; /* Reference management */
|
||||||
struct cdev *cdevs;
|
struct cdev **cdevs;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
const char *driver_name;
|
const char *driver_name;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <linux/ioctl.h>
|
#include <linux/ioctl.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
struct gsm_config
|
struct gsm_config
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user