TTY/Serial driver update for 3.15-rc1
Here's the big tty/serial driver update for 3.15-rc1. Nothing major, a number of serial driver updates and a few tty core fixes as well. All have been in linux-next for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iEYEABECAAYFAlM7CWAACgkQMUfUDdst+ylDXACg0vZ+J+5OXbbE3lywVCAebjhB XzkAn1lz7JRIils7IlckAJ2w/m50b174 =M+8c -----END PGP SIGNATURE----- Merge tag 'tty-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial driver update from Greg KH: "Here's the big tty/serial driver update for 3.15-rc1. Nothing major, a number of serial driver updates and a few tty core fixes as well. All have been in linux-next for a while" * tag 'tty-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (71 commits) tty/serial: omap: empty the RX FIFO at the end of half-duplex TX tty/serial: omap: fix RX interrupt enable/disable in half-duplex TX serial: sh-sci: Neaten dev_<level> uses serial: sh-sci: Replace hardcoded 3 by UART_PM_STATE_OFF serial: sh-sci: Add more register documentation serial: sh-sci: Remove useless casts serial: sh-sci: Replace printk() by pr_*() serial_core: Avoid NULL pointer dereference in uart_close() serial_core: Get a reference for port->tty in uart_remove_one_port() serial: clps711x: Give a chance to perform useful tasks during wait loop serial_core: Grammar s/ports/port's/ serial_core: Spelling s/contro/control/ serial: efm32: properly namespace location property serial: max310x: Add missing #include <linux/uaccess.h> synclink: fix info leak in ioctl serial: 8250: Clean up the locking for -rt serial: 8250_pci: change BayTrail default uartclk serial: 8250_pci: more BayTrail error-free bauds serial: sh-sci: Add missing call to uart_remove_one_port() in failure path serial_core: Unregister console in uart_remove_one_port() ...
This commit is contained in:
commit
cb15955638
43 changed files with 1232 additions and 846 deletions
|
@ -6,7 +6,7 @@ Required properties:
|
||||||
- interrupts : Should contain uart interrupt
|
- interrupts : Should contain uart interrupt
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- location : Decides the location of the USART I/O pins.
|
- efm32,location : Decides the location of the USART I/O pins.
|
||||||
Allowed range : [0 .. 5]
|
Allowed range : [0 .. 5]
|
||||||
Default: 0
|
Default: 0
|
||||||
|
|
||||||
|
@ -16,5 +16,5 @@ uart@0x4000c400 {
|
||||||
compatible = "efm32,uart";
|
compatible = "efm32,uart";
|
||||||
reg = <0x4000c400 0x400>;
|
reg = <0x4000c400 0x400>;
|
||||||
interrupts = <15>;
|
interrupts = <15>;
|
||||||
location = <0>;
|
efm32,location = <0>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,14 @@ Required properties:
|
||||||
- compatible : Should be "fsl,<soc>-lpuart"
|
- compatible : Should be "fsl,<soc>-lpuart"
|
||||||
- reg : Address and length of the register set for the device
|
- reg : Address and length of the register set for the device
|
||||||
- interrupts : Should contain uart interrupt
|
- interrupts : Should contain uart interrupt
|
||||||
|
- clocks : phandle + clock specifier pairs, one for each entry in clock-names
|
||||||
|
- clock-names : should contain: "ipg" - the uart clock
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- dmas: A list of two dma specifiers, one for each entry in dma-names.
|
||||||
|
- dma-names: should contain "tx" and "rx".
|
||||||
|
|
||||||
|
Note: Optional properties for DMA support. Write them both or both not.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -11,4 +19,9 @@ uart0: serial@40027000 {
|
||||||
compatible = "fsl,vf610-lpuart";
|
compatible = "fsl,vf610-lpuart";
|
||||||
reg = <0x40027000 0x1000>;
|
reg = <0x40027000 0x1000>;
|
||||||
interrupts = <0 61 0x00>;
|
interrupts = <0 61 0x00>;
|
||||||
|
clocks = <&clks VF610_CLK_UART0>;
|
||||||
|
clock-names = "ipg";
|
||||||
|
dmas = <&edma0 0 2>,
|
||||||
|
<&edma0 0 3>;
|
||||||
|
dma-names = "rx","tx";
|
||||||
};
|
};
|
||||||
|
|
36
Documentation/devicetree/bindings/serial/maxim,max310x.txt
Normal file
36
Documentation/devicetree/bindings/serial/maxim,max310x.txt
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
* Maxim MAX310X advanced Universal Asynchronous Receiver-Transmitter (UART)
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Should be one of the following:
|
||||||
|
- "maxim,max3107" for Maxim MAX3107,
|
||||||
|
- "maxim,max3108" for Maxim MAX3108,
|
||||||
|
- "maxim,max3109" for Maxim MAX3109,
|
||||||
|
- "maxim,max14830" for Maxim MAX14830.
|
||||||
|
- reg: SPI chip select number.
|
||||||
|
- interrupt-parent: The phandle for the interrupt controller that
|
||||||
|
services interrupts for this IC.
|
||||||
|
- interrupts: Specifies the interrupt source of the parent interrupt
|
||||||
|
controller. The format of the interrupt specifier depends on the
|
||||||
|
parent interrupt controller.
|
||||||
|
- clocks: phandle to the IC source clock.
|
||||||
|
- clock-names: Should be "xtal" if clock is an external crystal or
|
||||||
|
"osc" if an external clock source is used.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- gpio-controller: Marks the device node as a GPIO controller.
|
||||||
|
- #gpio-cells: Should be two. The first cell is the GPIO number and
|
||||||
|
the second cell is used to specify the GPIO polarity:
|
||||||
|
0 = active high,
|
||||||
|
1 = active low.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
max14830: max14830@0 {
|
||||||
|
compatible = "maxim,max14830";
|
||||||
|
reg = <0>;
|
||||||
|
clocks = <&clk20m>;
|
||||||
|
clock-names = "osc";
|
||||||
|
interrupt-parent = <&gpio3>;
|
||||||
|
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||||
|
gpio-controller;
|
||||||
|
#gpio-cells = <2>;
|
||||||
|
};
|
|
@ -37,7 +37,7 @@ Example:
|
||||||
};
|
};
|
||||||
|
|
||||||
scifa0: serial@e6c40000 {
|
scifa0: serial@e6c40000 {
|
||||||
compatible = "renesas,scifa-r8a7790", "renesas,scifa-generic";
|
compatible = "renesas,scifa-r8a7790", "renesas,scifa";
|
||||||
reg = <0 0xe6c40000 0 64>;
|
reg = <0 0xe6c40000 0 64>;
|
||||||
interrupt-parent = <&gic>;
|
interrupt-parent = <&gic>;
|
||||||
interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
|
@ -217,8 +217,8 @@
|
||||||
interrupts = <17>;
|
interrupts = <17>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 13>;
|
clocks = <&clks 13>;
|
||||||
sirf,uart-dma-rx-channel = <21>;
|
dmas = <&dmac1 5>, <&dmac0 2>;
|
||||||
sirf,uart-dma-tx-channel = <2>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
uart1: uart@b0060000 {
|
uart1: uart@b0060000 {
|
||||||
|
@ -228,6 +228,7 @@
|
||||||
interrupts = <18>;
|
interrupts = <18>;
|
||||||
fifosize = <32>;
|
fifosize = <32>;
|
||||||
clocks = <&clks 14>;
|
clocks = <&clks 14>;
|
||||||
|
dma-names = "no-rx", "no-tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
uart2: uart@b0070000 {
|
uart2: uart@b0070000 {
|
||||||
|
@ -237,8 +238,8 @@
|
||||||
interrupts = <19>;
|
interrupts = <19>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 15>;
|
clocks = <&clks 15>;
|
||||||
sirf,uart-dma-rx-channel = <6>;
|
dmas = <&dmac0 6>, <&dmac0 7>;
|
||||||
sirf,uart-dma-tx-channel = <7>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
usp0: usp@b0080000 {
|
usp0: usp@b0080000 {
|
||||||
|
@ -248,8 +249,8 @@
|
||||||
interrupts = <20>;
|
interrupts = <20>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 28>;
|
clocks = <&clks 28>;
|
||||||
sirf,usp-dma-rx-channel = <17>;
|
dmas = <&dmac1 1>, <&dmac1 2>;
|
||||||
sirf,usp-dma-tx-channel = <18>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
usp1: usp@b0090000 {
|
usp1: usp@b0090000 {
|
||||||
|
@ -259,8 +260,8 @@
|
||||||
interrupts = <21>;
|
interrupts = <21>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 29>;
|
clocks = <&clks 29>;
|
||||||
sirf,usp-dma-rx-channel = <14>;
|
dmas = <&dmac0 14>, <&dmac0 15>;
|
||||||
sirf,usp-dma-tx-channel = <15>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
dmac0: dma-controller@b00b0000 {
|
dmac0: dma-controller@b00b0000 {
|
||||||
|
|
|
@ -223,8 +223,8 @@
|
||||||
interrupts = <17>;
|
interrupts = <17>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 13>;
|
clocks = <&clks 13>;
|
||||||
sirf,uart-dma-rx-channel = <21>;
|
dmas = <&dmac1 5>, <&dmac0 2>;
|
||||||
sirf,uart-dma-tx-channel = <2>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
uart1: uart@b0060000 {
|
uart1: uart@b0060000 {
|
||||||
|
@ -243,8 +243,8 @@
|
||||||
interrupts = <19>;
|
interrupts = <19>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 15>;
|
clocks = <&clks 15>;
|
||||||
sirf,uart-dma-rx-channel = <6>;
|
dmas = <&dmac0 6>, <&dmac0 7>;
|
||||||
sirf,uart-dma-tx-channel = <7>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
usp0: usp@b0080000 {
|
usp0: usp@b0080000 {
|
||||||
|
@ -254,8 +254,8 @@
|
||||||
interrupts = <20>;
|
interrupts = <20>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 28>;
|
clocks = <&clks 28>;
|
||||||
sirf,usp-dma-rx-channel = <17>;
|
dmas = <&dmac1 1>, <&dmac1 2>;
|
||||||
sirf,usp-dma-tx-channel = <18>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
usp1: usp@b0090000 {
|
usp1: usp@b0090000 {
|
||||||
|
@ -265,8 +265,8 @@
|
||||||
interrupts = <21>;
|
interrupts = <21>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 29>;
|
clocks = <&clks 29>;
|
||||||
sirf,usp-dma-rx-channel = <14>;
|
dmas = <&dmac0 14>, <&dmac0 15>;
|
||||||
sirf,usp-dma-tx-channel = <15>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
usp2: usp@b00a0000 {
|
usp2: usp@b00a0000 {
|
||||||
|
@ -276,8 +276,8 @@
|
||||||
interrupts = <22>;
|
interrupts = <22>;
|
||||||
fifosize = <128>;
|
fifosize = <128>;
|
||||||
clocks = <&clks 30>;
|
clocks = <&clks 30>;
|
||||||
sirf,usp-dma-rx-channel = <10>;
|
dmas = <&dmac0 10>, <&dmac0 11>;
|
||||||
sirf,usp-dma-tx-channel = <11>;
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
|
||||||
dmac0: dma-controller@b00b0000 {
|
dmac0: dma-controller@b00b0000 {
|
||||||
|
|
|
@ -128,27 +128,15 @@ static struct platform_device mx31moboard_flash = {
|
||||||
.num_resources = 1,
|
.num_resources = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int moboard_uart0_init(struct platform_device *pdev)
|
static void __init moboard_uart0_init(void)
|
||||||
{
|
{
|
||||||
int ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CTS1), "uart0-cts-hack");
|
if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_CTS1), "uart0-cts-hack")) {
|
||||||
if (ret)
|
gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CTS1), 0);
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CTS1), 0);
|
|
||||||
if (ret)
|
|
||||||
gpio_free(IOMUX_TO_GPIO(MX31_PIN_CTS1));
|
gpio_free(IOMUX_TO_GPIO(MX31_PIN_CTS1));
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moboard_uart0_exit(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
gpio_free(IOMUX_TO_GPIO(MX31_PIN_CTS1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct imxuart_platform_data uart0_pdata __initconst = {
|
static const struct imxuart_platform_data uart0_pdata __initconst = {
|
||||||
.init = moboard_uart0_init,
|
|
||||||
.exit = moboard_uart0_exit,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct imxuart_platform_data uart4_pdata __initconst = {
|
static const struct imxuart_platform_data uart4_pdata __initconst = {
|
||||||
|
@ -543,6 +531,7 @@ static void __init mx31moboard_init(void)
|
||||||
|
|
||||||
imx31_add_imx2_wdt();
|
imx31_add_imx2_wdt();
|
||||||
|
|
||||||
|
moboard_uart0_init();
|
||||||
imx31_add_imx_uart0(&uart0_pdata);
|
imx31_add_imx_uart0(&uart0_pdata);
|
||||||
imx31_add_imx_uart4(&uart4_pdata);
|
imx31_add_imx_uart4(&uart4_pdata);
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/major.h>
|
#include <linux/major.h>
|
||||||
|
#include <linux/atomic.h>
|
||||||
#include <linux/sysrq.h>
|
#include <linux/sysrq.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
|
@ -70,6 +71,9 @@ static struct task_struct *hvc_task;
|
||||||
/* Picks up late kicks after list walk but before schedule() */
|
/* Picks up late kicks after list walk but before schedule() */
|
||||||
static int hvc_kicked;
|
static int hvc_kicked;
|
||||||
|
|
||||||
|
/* hvc_init is triggered from hvc_alloc, i.e. only when actually used */
|
||||||
|
static atomic_t hvc_needs_init __read_mostly = ATOMIC_INIT(-1);
|
||||||
|
|
||||||
static int hvc_init(void);
|
static int hvc_init(void);
|
||||||
|
|
||||||
#ifdef CONFIG_MAGIC_SYSRQ
|
#ifdef CONFIG_MAGIC_SYSRQ
|
||||||
|
@ -851,7 +855,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* We wait until a driver actually comes along */
|
/* We wait until a driver actually comes along */
|
||||||
if (!hvc_driver) {
|
if (atomic_inc_not_zero(&hvc_needs_init)) {
|
||||||
int err = hvc_init();
|
int err = hvc_init();
|
||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
|
@ -176,9 +176,6 @@ void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
|
||||||
": %d chars not inserted to flip buffer!\n",
|
": %d chars not inserted to flip buffer!\n",
|
||||||
length - work);
|
length - work);
|
||||||
|
|
||||||
/*
|
|
||||||
* This may sleep if ->low_latency is set
|
|
||||||
*/
|
|
||||||
if (work)
|
if (work)
|
||||||
tty_flip_buffer_push(&tty->port);
|
tty_flip_buffer_push(&tty->port);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1900,13 +1900,10 @@ static inline int input_available_p(struct tty_struct *tty, int poll)
|
||||||
struct n_tty_data *ldata = tty->disc_data;
|
struct n_tty_data *ldata = tty->disc_data;
|
||||||
int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1;
|
int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1;
|
||||||
|
|
||||||
if (ldata->icanon && !L_EXTPROC(tty)) {
|
if (ldata->icanon && !L_EXTPROC(tty))
|
||||||
if (ldata->canon_head != ldata->read_tail)
|
return ldata->canon_head != ldata->read_tail;
|
||||||
return 1;
|
else
|
||||||
} else if (read_cnt(ldata) >= amt)
|
return read_cnt(ldata) >= amt;
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1694,6 +1694,10 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
|
||||||
|
|
||||||
static void serial_unlink_irq_chain(struct uart_8250_port *up)
|
static void serial_unlink_irq_chain(struct uart_8250_port *up)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* yes, some broken gcc emit "warning: 'i' may be used uninitialized"
|
||||||
|
* but no, we are not going to take a patch that assigns NULL below.
|
||||||
|
*/
|
||||||
struct irq_info *i;
|
struct irq_info *i;
|
||||||
struct hlist_node *n;
|
struct hlist_node *n;
|
||||||
struct hlist_head *h;
|
struct hlist_head *h;
|
||||||
|
@ -2882,14 +2886,10 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
|
||||||
|
|
||||||
touch_nmi_watchdog();
|
touch_nmi_watchdog();
|
||||||
|
|
||||||
local_irq_save(flags);
|
if (port->sysrq || oops_in_progress)
|
||||||
if (port->sysrq) {
|
locked = spin_trylock_irqsave(&port->lock, flags);
|
||||||
/* serial8250_handle_irq() already took the lock */
|
else
|
||||||
locked = 0;
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
} else if (oops_in_progress) {
|
|
||||||
locked = spin_trylock(&port->lock);
|
|
||||||
} else
|
|
||||||
spin_lock(&port->lock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First save the IER then disable the interrupts
|
* First save the IER then disable the interrupts
|
||||||
|
@ -2921,8 +2921,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
|
||||||
serial8250_modem_status(up);
|
serial8250_modem_status(up);
|
||||||
|
|
||||||
if (locked)
|
if (locked)
|
||||||
spin_unlock(&port->lock);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
local_irq_restore(flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init serial8250_console_setup(struct console *co, char *options)
|
static int __init serial8250_console_setup(struct console *co, char *options)
|
||||||
|
|
|
@ -1366,23 +1366,44 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||||
struct ktermios *old)
|
struct ktermios *old)
|
||||||
{
|
{
|
||||||
unsigned int baud = tty_termios_baud_rate(termios);
|
unsigned int baud = tty_termios_baud_rate(termios);
|
||||||
unsigned int m = 6912;
|
unsigned int m, n;
|
||||||
unsigned int n = 15625;
|
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
/* For baud rates 1M, 2M, 3M and 4M the dividers must be adjusted. */
|
/*
|
||||||
if (baud == 1000000 || baud == 2000000 || baud == 4000000) {
|
* For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
|
||||||
|
* dividers must be adjusted.
|
||||||
|
*
|
||||||
|
* uartclk = (m / n) * 100 MHz, where m <= n
|
||||||
|
*/
|
||||||
|
switch (baud) {
|
||||||
|
case 500000:
|
||||||
|
case 1000000:
|
||||||
|
case 2000000:
|
||||||
|
case 4000000:
|
||||||
m = 64;
|
m = 64;
|
||||||
n = 100;
|
n = 100;
|
||||||
|
|
||||||
p->uartclk = 64000000;
|
p->uartclk = 64000000;
|
||||||
} else if (baud == 3000000) {
|
break;
|
||||||
|
case 3500000:
|
||||||
|
m = 56;
|
||||||
|
n = 100;
|
||||||
|
p->uartclk = 56000000;
|
||||||
|
break;
|
||||||
|
case 1500000:
|
||||||
|
case 3000000:
|
||||||
m = 48;
|
m = 48;
|
||||||
n = 100;
|
n = 100;
|
||||||
|
|
||||||
p->uartclk = 48000000;
|
p->uartclk = 48000000;
|
||||||
} else {
|
break;
|
||||||
p->uartclk = 44236800;
|
case 2500000:
|
||||||
|
m = 40;
|
||||||
|
n = 100;
|
||||||
|
p->uartclk = 40000000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m = 2304;
|
||||||
|
n = 3125;
|
||||||
|
p->uartclk = 73728000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the clock */
|
/* Reset the clock */
|
||||||
|
@ -3449,6 +3470,10 @@ static struct pciserial_board pci_boards[] = {
|
||||||
.base_baud = 921600,
|
.base_baud = 921600,
|
||||||
.reg_shift = 2,
|
.reg_shift = 2,
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
|
* Intel BayTrail HSUART reference clock is 44.2368 MHz at power-on,
|
||||||
|
* but is overridden by byt_set_termios.
|
||||||
|
*/
|
||||||
[pbn_byt] = {
|
[pbn_byt] = {
|
||||||
.flags = FL_BASE0,
|
.flags = FL_BASE0,
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
|
|
|
@ -289,7 +289,7 @@ config SERIAL_MAX3100
|
||||||
MAX3100 chip support
|
MAX3100 chip support
|
||||||
|
|
||||||
config SERIAL_MAX310X
|
config SERIAL_MAX310X
|
||||||
bool "MAX310X support"
|
tristate "MAX310X support"
|
||||||
depends on SPI_MASTER
|
depends on SPI_MASTER
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
select REGMAP_SPI if SPI_MASTER
|
select REGMAP_SPI if SPI_MASTER
|
||||||
|
@ -708,7 +708,7 @@ config SERIAL_IP22_ZILOG_CONSOLE
|
||||||
|
|
||||||
config SERIAL_SH_SCI
|
config SERIAL_SH_SCI
|
||||||
tristate "SuperH SCI(F) serial port support"
|
tristate "SuperH SCI(F) serial port support"
|
||||||
depends on HAVE_CLK && (SUPERH || ARM || COMPILE_TEST)
|
depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
|
|
||||||
config SERIAL_SH_SCI_NR_UARTS
|
config SERIAL_SH_SCI_NR_UARTS
|
||||||
|
|
|
@ -2154,9 +2154,19 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||||
amba_ports[i] = uap;
|
amba_ports[i] = uap;
|
||||||
|
|
||||||
amba_set_drvdata(dev, uap);
|
amba_set_drvdata(dev, uap);
|
||||||
|
|
||||||
|
if (!amba_reg.state) {
|
||||||
|
ret = uart_register_driver(&amba_reg);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("Failed to register AMBA-PL011 driver\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = uart_add_one_port(&amba_reg, &uap->port);
|
ret = uart_add_one_port(&amba_reg, &uap->port);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
amba_ports[i] = NULL;
|
amba_ports[i] = NULL;
|
||||||
|
uart_unregister_driver(&amba_reg);
|
||||||
pl011_dma_remove(uap);
|
pl011_dma_remove(uap);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
@ -2175,6 +2185,7 @@ static int pl011_remove(struct amba_device *dev)
|
||||||
amba_ports[i] = NULL;
|
amba_ports[i] = NULL;
|
||||||
|
|
||||||
pl011_dma_remove(uap);
|
pl011_dma_remove(uap);
|
||||||
|
uart_unregister_driver(&amba_reg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2230,22 +2241,14 @@ static struct amba_driver pl011_driver = {
|
||||||
|
|
||||||
static int __init pl011_init(void)
|
static int __init pl011_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
|
printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
|
||||||
|
|
||||||
ret = uart_register_driver(&amba_reg);
|
return amba_driver_register(&pl011_driver);
|
||||||
if (ret == 0) {
|
|
||||||
ret = amba_driver_register(&pl011_driver);
|
|
||||||
if (ret)
|
|
||||||
uart_unregister_driver(&amba_reg);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit pl011_exit(void)
|
static void __exit pl011_exit(void)
|
||||||
{
|
{
|
||||||
amba_driver_unregister(&pl011_driver);
|
amba_driver_unregister(&pl011_driver);
|
||||||
uart_unregister_driver(&amba_reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -115,9 +115,6 @@ static void atmel_stop_rx(struct uart_port *port);
|
||||||
#define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
|
#define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
|
||||||
#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
|
#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
|
||||||
|
|
||||||
static int (*atmel_open_hook)(struct uart_port *);
|
|
||||||
static void (*atmel_close_hook)(struct uart_port *);
|
|
||||||
|
|
||||||
struct atmel_dma_buffer {
|
struct atmel_dma_buffer {
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
|
@ -1555,7 +1552,7 @@ static int atmel_startup(struct uart_port *port)
|
||||||
retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED,
|
retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED,
|
||||||
tty ? tty->name : "atmel_serial", port);
|
tty ? tty->name : "atmel_serial", port);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
printk("atmel_serial: atmel_startup - Can't get irq\n");
|
dev_err(port->dev, "atmel_startup - Can't get irq\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1575,17 +1572,6 @@ static int atmel_startup(struct uart_port *port)
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
atmel_set_ops(port);
|
atmel_set_ops(port);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* If there is a specific "open" function (to register
|
|
||||||
* control line interrupts)
|
|
||||||
*/
|
|
||||||
if (atmel_open_hook) {
|
|
||||||
retval = atmel_open_hook(port);
|
|
||||||
if (retval) {
|
|
||||||
free_irq(port->irq, port);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save current CSR for comparison in atmel_tasklet_func() */
|
/* Save current CSR for comparison in atmel_tasklet_func() */
|
||||||
atmel_port->irq_status_prev = UART_GET_CSR(port);
|
atmel_port->irq_status_prev = UART_GET_CSR(port);
|
||||||
|
@ -1684,13 +1670,6 @@ static void atmel_shutdown(struct uart_port *port)
|
||||||
* Free the interrupt
|
* Free the interrupt
|
||||||
*/
|
*/
|
||||||
free_irq(port->irq, port);
|
free_irq(port->irq, port);
|
||||||
|
|
||||||
/*
|
|
||||||
* If there is a specific "close" function (to unregister
|
|
||||||
* control line interrupts)
|
|
||||||
*/
|
|
||||||
if (atmel_close_hook)
|
|
||||||
atmel_close_hook(port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1738,7 +1717,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
|
||||||
clk_disable_unprepare(atmel_port->clk);
|
clk_disable_unprepare(atmel_port->clk);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "atmel_serial: unknown pm %d\n", state);
|
dev_err(port->dev, "atmel_serial: unknown pm %d\n", state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1853,13 +1832,10 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
mode &= ~ATMEL_US_USMODE;
|
mode &= ~ATMEL_US_USMODE;
|
||||||
|
|
||||||
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
|
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
|
||||||
dev_dbg(port->dev, "Setting UART to RS485\n");
|
|
||||||
if ((atmel_port->rs485.delay_rts_after_send) > 0)
|
if ((atmel_port->rs485.delay_rts_after_send) > 0)
|
||||||
UART_PUT_TTGR(port,
|
UART_PUT_TTGR(port,
|
||||||
atmel_port->rs485.delay_rts_after_send);
|
atmel_port->rs485.delay_rts_after_send);
|
||||||
mode |= ATMEL_US_USMODE_RS485;
|
mode |= ATMEL_US_USMODE_RS485;
|
||||||
} else {
|
|
||||||
dev_dbg(port->dev, "Setting UART to RS232\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the parity, stop bits and data size */
|
/* set the parity, stop bits and data size */
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/serial_bcm63xx.h>
|
#include <linux/serial_bcm63xx.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
#define BCM63XX_NR_UARTS 2
|
#define BCM63XX_NR_UARTS 2
|
||||||
|
|
||||||
|
@ -588,7 +590,7 @@ static int bcm_uart_request_port(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|
||||||
size = RSET_UART_SIZE;
|
size = UART_REG_SIZE;
|
||||||
if (!request_mem_region(port->mapbase, size, "bcm63xx")) {
|
if (!request_mem_region(port->mapbase, size, "bcm63xx")) {
|
||||||
dev_err(port->dev, "Memory region busy\n");
|
dev_err(port->dev, "Memory region busy\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -608,7 +610,7 @@ static int bcm_uart_request_port(struct uart_port *port)
|
||||||
*/
|
*/
|
||||||
static void bcm_uart_release_port(struct uart_port *port)
|
static void bcm_uart_release_port(struct uart_port *port)
|
||||||
{
|
{
|
||||||
release_mem_region(port->mapbase, RSET_UART_SIZE);
|
release_mem_region(port->mapbase, UART_REG_SIZE);
|
||||||
iounmap(port->membase);
|
iounmap(port->membase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,6 +807,9 @@ static int bcm_uart_probe(struct platform_device *pdev)
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (pdev->dev.of_node)
|
||||||
|
pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
|
||||||
|
|
||||||
if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
|
if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -856,6 +861,12 @@ static int bcm_uart_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id bcm63xx_of_match[] = {
|
||||||
|
{ .compatible = "brcm,bcm6345-uart" },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, bcm63xx_of_match);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* platform driver stuff
|
* platform driver stuff
|
||||||
*/
|
*/
|
||||||
|
@ -865,6 +876,7 @@ static struct platform_driver bcm_uart_platform_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "bcm63xx_uart",
|
.name = "bcm63xx_uart",
|
||||||
|
.of_match_table = bcm63xx_of_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -368,11 +368,16 @@ static const struct uart_ops uart_clps711x_ops = {
|
||||||
static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
|
static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
|
||||||
{
|
{
|
||||||
struct clps711x_port *s = dev_get_drvdata(port->dev);
|
struct clps711x_port *s = dev_get_drvdata(port->dev);
|
||||||
|
|
||||||
|
/* Wait for FIFO is not full */
|
||||||
|
while (1) {
|
||||||
u32 sysflg = 0;
|
u32 sysflg = 0;
|
||||||
|
|
||||||
do {
|
|
||||||
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
|
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
|
||||||
} while (sysflg & SYSFLG_UTXFF);
|
if (!(sysflg & SYSFLG_UTXFF))
|
||||||
|
break;
|
||||||
|
cond_resched();
|
||||||
|
}
|
||||||
|
|
||||||
writew(ch, port->membase + UARTDR_OFFSET);
|
writew(ch, port->membase + UARTDR_OFFSET);
|
||||||
}
|
}
|
||||||
|
@ -382,14 +387,18 @@ static void uart_clps711x_console_write(struct console *co, const char *c,
|
||||||
{
|
{
|
||||||
struct uart_port *port = clps711x_uart.state[co->index].uart_port;
|
struct uart_port *port = clps711x_uart.state[co->index].uart_port;
|
||||||
struct clps711x_port *s = dev_get_drvdata(port->dev);
|
struct clps711x_port *s = dev_get_drvdata(port->dev);
|
||||||
u32 sysflg = 0;
|
|
||||||
|
|
||||||
uart_console_write(port, c, n, uart_clps711x_console_putchar);
|
uart_console_write(port, c, n, uart_clps711x_console_putchar);
|
||||||
|
|
||||||
/* Wait for transmitter to become empty */
|
/* Wait for transmitter to become empty */
|
||||||
do {
|
while (1) {
|
||||||
|
u32 sysflg = 0;
|
||||||
|
|
||||||
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
|
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
|
||||||
} while (sysflg & SYSFLG_UBUSY);
|
if (!(sysflg & SYSFLG_UBUSY))
|
||||||
|
break;
|
||||||
|
cond_resched();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_clps711x_console_setup(struct console *co, char *options)
|
static int uart_clps711x_console_setup(struct console *co, char *options)
|
||||||
|
|
|
@ -286,7 +286,6 @@ static struct e100_serial rs_table[] = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}, /* ttyS0 */
|
}, /* ttyS0 */
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
{ .baud = DEF_BAUD,
|
{ .baud = DEF_BAUD,
|
||||||
.ioport = (unsigned char *)R_SERIAL1_CTRL,
|
.ioport = (unsigned char *)R_SERIAL1_CTRL,
|
||||||
.irq = 1U << 16, /* uses DMA 8 and 9 */
|
.irq = 1U << 16, /* uses DMA 8 and 9 */
|
||||||
|
@ -447,7 +446,6 @@ static struct e100_serial rs_table[] = {
|
||||||
.dma_in_enabled = 0
|
.dma_in_enabled = 0
|
||||||
#endif
|
#endif
|
||||||
} /* ttyS3 */
|
} /* ttyS3 */
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1035,7 +1033,6 @@ cflag_to_etrax_baud(unsigned int cflag)
|
||||||
static inline void
|
static inline void
|
||||||
e100_dtr(struct e100_serial *info, int set)
|
e100_dtr(struct e100_serial *info, int set)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
unsigned char mask = e100_modem_pins[info->line].dtr_mask;
|
unsigned char mask = e100_modem_pins[info->line].dtr_mask;
|
||||||
|
|
||||||
#ifdef SERIAL_DEBUG_IO
|
#ifdef SERIAL_DEBUG_IO
|
||||||
|
@ -1060,7 +1057,6 @@ e100_dtr(struct e100_serial *info, int set)
|
||||||
info->line, *e100_modem_pins[info->line].dtr_shadow,
|
info->line, *e100_modem_pins[info->line].dtr_shadow,
|
||||||
E100_DTR_GET(info));
|
E100_DTR_GET(info));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive
|
/* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive
|
||||||
|
@ -1069,7 +1065,6 @@ e100_dtr(struct e100_serial *info, int set)
|
||||||
static inline void
|
static inline void
|
||||||
e100_rts(struct e100_serial *info, int set)
|
e100_rts(struct e100_serial *info, int set)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
info->rx_ctrl &= ~E100_RTS_MASK;
|
info->rx_ctrl &= ~E100_RTS_MASK;
|
||||||
|
@ -1079,7 +1074,6 @@ e100_rts(struct e100_serial *info, int set)
|
||||||
#ifdef SERIAL_DEBUG_IO
|
#ifdef SERIAL_DEBUG_IO
|
||||||
printk("ser%i rts %i\n", info->line, set);
|
printk("ser%i rts %i\n", info->line, set);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1087,7 +1081,6 @@ e100_rts(struct e100_serial *info, int set)
|
||||||
static inline void
|
static inline void
|
||||||
e100_ri_out(struct e100_serial *info, int set)
|
e100_ri_out(struct e100_serial *info, int set)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
/* RI is active low */
|
/* RI is active low */
|
||||||
{
|
{
|
||||||
unsigned char mask = e100_modem_pins[info->line].ri_mask;
|
unsigned char mask = e100_modem_pins[info->line].ri_mask;
|
||||||
|
@ -1099,12 +1092,10 @@ e100_ri_out(struct e100_serial *info, int set)
|
||||||
*e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
|
*e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static inline void
|
static inline void
|
||||||
e100_cd_out(struct e100_serial *info, int set)
|
e100_cd_out(struct e100_serial *info, int set)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
/* CD is active low */
|
/* CD is active low */
|
||||||
{
|
{
|
||||||
unsigned char mask = e100_modem_pins[info->line].cd_mask;
|
unsigned char mask = e100_modem_pins[info->line].cd_mask;
|
||||||
|
@ -1116,27 +1107,22 @@ e100_cd_out(struct e100_serial *info, int set)
|
||||||
*e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
|
*e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
e100_disable_rx(struct e100_serial *info)
|
e100_disable_rx(struct e100_serial *info)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
/* disable the receiver */
|
/* disable the receiver */
|
||||||
info->ioport[REG_REC_CTRL] =
|
info->ioport[REG_REC_CTRL] =
|
||||||
(info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
|
(info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
e100_enable_rx(struct e100_serial *info)
|
e100_enable_rx(struct e100_serial *info)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
/* enable the receiver */
|
/* enable the receiver */
|
||||||
info->ioport[REG_REC_CTRL] =
|
info->ioport[REG_REC_CTRL] =
|
||||||
(info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
|
(info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the rx DMA uses both the dma_descr and the dma_eop interrupts */
|
/* the rx DMA uses both the dma_descr and the dma_eop interrupts */
|
||||||
|
@ -1554,24 +1540,6 @@ transmit_chars_dma(struct e100_serial *info)
|
||||||
unsigned int c, sentl;
|
unsigned int c, sentl;
|
||||||
struct etrax_dma_descr *descr;
|
struct etrax_dma_descr *descr;
|
||||||
|
|
||||||
#ifdef CONFIG_SVINTO_SIM
|
|
||||||
/* This will output too little if tail is not 0 always since
|
|
||||||
* we don't reloop to send the other part. Anyway this SHOULD be a
|
|
||||||
* no-op - transmit_chars_dma would never really be called during sim
|
|
||||||
* since rs_write does not write into the xmit buffer then.
|
|
||||||
*/
|
|
||||||
if (info->xmit.tail)
|
|
||||||
printk("Error in serial.c:transmit_chars-dma(), tail!=0\n");
|
|
||||||
if (info->xmit.head != info->xmit.tail) {
|
|
||||||
SIMCOUT(info->xmit.buf + info->xmit.tail,
|
|
||||||
CIRC_CNT(info->xmit.head,
|
|
||||||
info->xmit.tail,
|
|
||||||
SERIAL_XMIT_SIZE));
|
|
||||||
info->xmit.head = info->xmit.tail; /* move back head */
|
|
||||||
info->tr_running = 0;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
/* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
|
/* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
|
||||||
*info->oclrintradr =
|
*info->oclrintradr =
|
||||||
IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
|
IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
|
||||||
|
@ -1842,13 +1810,6 @@ static void receive_chars_dma(struct e100_serial *info)
|
||||||
struct tty_struct *tty;
|
struct tty_struct *tty;
|
||||||
unsigned char rstat;
|
unsigned char rstat;
|
||||||
|
|
||||||
#ifdef CONFIG_SVINTO_SIM
|
|
||||||
/* No receive in the simulator. Will probably be when the rest of
|
|
||||||
* the serial interface works, and this piece will just be removed.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
|
/* Acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
|
||||||
*info->iclrintradr =
|
*info->iclrintradr =
|
||||||
IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
|
IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
|
||||||
|
@ -1934,12 +1895,6 @@ static int start_recv_dma(struct e100_serial *info)
|
||||||
static void
|
static void
|
||||||
start_receive(struct e100_serial *info)
|
start_receive(struct e100_serial *info)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SVINTO_SIM
|
|
||||||
/* No receive in the simulator. Will probably be when the rest of
|
|
||||||
* the serial interface works, and this piece will just be removed.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
if (info->uses_dma_in) {
|
if (info->uses_dma_in) {
|
||||||
/* reset the input dma channel to be sure it works */
|
/* reset the input dma channel to be sure it works */
|
||||||
|
|
||||||
|
@ -1972,17 +1927,6 @@ tr_interrupt(int irq, void *dev_id)
|
||||||
int i;
|
int i;
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_SVINTO_SIM
|
|
||||||
/* No receive in the simulator. Will probably be when the rest of
|
|
||||||
* the serial interface works, and this piece will just be removed.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
const char *s = "What? tr_interrupt in simulator??\n";
|
|
||||||
SIMCOUT(s,strlen(s));
|
|
||||||
}
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* find out the line that caused this irq and get it from rs_table */
|
/* find out the line that caused this irq and get it from rs_table */
|
||||||
|
|
||||||
ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
|
ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
|
||||||
|
@ -2021,17 +1965,6 @@ rec_interrupt(int irq, void *dev_id)
|
||||||
int i;
|
int i;
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_SVINTO_SIM
|
|
||||||
/* No receive in the simulator. Will probably be when the rest of
|
|
||||||
* the serial interface works, and this piece will just be removed.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
const char *s = "What? rec_interrupt in simulator??\n";
|
|
||||||
SIMCOUT(s,strlen(s));
|
|
||||||
}
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* find out the line that caused this irq and get it from rs_table */
|
/* find out the line that caused this irq and get it from rs_table */
|
||||||
|
|
||||||
ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
|
ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
|
||||||
|
@ -2173,10 +2106,6 @@ timed_flush_handler(unsigned long ptr)
|
||||||
struct e100_serial *info;
|
struct e100_serial *info;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef CONFIG_SVINTO_SIM
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < NR_PORTS; i++) {
|
for (i = 0; i < NR_PORTS; i++) {
|
||||||
info = rs_table + i;
|
info = rs_table + i;
|
||||||
if (info->uses_dma_in)
|
if (info->uses_dma_in)
|
||||||
|
@ -2729,25 +2658,6 @@ startup(struct e100_serial * info)
|
||||||
printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf);
|
printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SVINTO_SIM
|
|
||||||
/* Bits and pieces collected from below. Better to have them
|
|
||||||
in one ifdef:ed clause than to mix in a lot of ifdefs,
|
|
||||||
right? */
|
|
||||||
if (info->port.tty)
|
|
||||||
clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
|
|
||||||
|
|
||||||
info->xmit.head = info->xmit.tail = 0;
|
|
||||||
info->first_recv_buffer = info->last_recv_buffer = NULL;
|
|
||||||
info->recv_cnt = info->max_recv_cnt = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
|
|
||||||
info->rec_descr[i].buf = NULL;
|
|
||||||
|
|
||||||
/* No real action in the simulator, but may set info important
|
|
||||||
to ioctl. */
|
|
||||||
change_speed(info);
|
|
||||||
#else
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the FIFO buffers and disable them
|
* Clear the FIFO buffers and disable them
|
||||||
* (they will be reenabled in change_speed())
|
* (they will be reenabled in change_speed())
|
||||||
|
@ -2837,8 +2747,6 @@ startup(struct e100_serial * info)
|
||||||
e100_rts(info, 1);
|
e100_rts(info, 1);
|
||||||
e100_dtr(info, 1);
|
e100_dtr(info, 1);
|
||||||
|
|
||||||
#endif /* CONFIG_SVINTO_SIM */
|
|
||||||
|
|
||||||
info->port.flags |= ASYNC_INITIALIZED;
|
info->port.flags |= ASYNC_INITIALIZED;
|
||||||
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
@ -2857,7 +2765,6 @@ shutdown(struct e100_serial * info)
|
||||||
struct etrax_recv_buffer *buffer;
|
struct etrax_recv_buffer *buffer;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
/* shut down the transmitter and receiver */
|
/* shut down the transmitter and receiver */
|
||||||
DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line));
|
DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line));
|
||||||
e100_disable_rx(info);
|
e100_disable_rx(info);
|
||||||
|
@ -2882,8 +2789,6 @@ shutdown(struct e100_serial * info)
|
||||||
info->tr_running = 0;
|
info->tr_running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_SVINTO_SIM */
|
|
||||||
|
|
||||||
if (!(info->port.flags & ASYNC_INITIALIZED))
|
if (!(info->port.flags & ASYNC_INITIALIZED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2995,17 +2900,12 @@ change_speed(struct e100_serial *info)
|
||||||
IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal);
|
IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal);
|
||||||
r_alt_ser_baudrate_shadow &= ~mask;
|
r_alt_ser_baudrate_shadow &= ~mask;
|
||||||
r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8));
|
r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8));
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
*R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow;
|
*R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow;
|
||||||
#endif /* CONFIG_SVINTO_SIM */
|
|
||||||
|
|
||||||
info->baud = cflag_to_baud(cflag);
|
info->baud = cflag_to_baud(cflag);
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag);
|
info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag);
|
||||||
#endif /* CONFIG_SVINTO_SIM */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
/* start with default settings and then fill in changes */
|
/* start with default settings and then fill in changes */
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
/* 8 bit, no/even parity */
|
/* 8 bit, no/even parity */
|
||||||
|
@ -3073,7 +2973,6 @@ change_speed(struct e100_serial *info)
|
||||||
|
|
||||||
*((unsigned long *)&info->ioport[REG_XOFF]) = xoff;
|
*((unsigned long *)&info->ioport[REG_XOFF]) = xoff;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
#endif /* !CONFIG_SVINTO_SIM */
|
|
||||||
|
|
||||||
update_char_time(info);
|
update_char_time(info);
|
||||||
|
|
||||||
|
@ -3122,11 +3021,6 @@ static int rs_raw_write(struct tty_struct *tty,
|
||||||
count, info->ioport[REG_STATUS]);
|
count, info->ioport[REG_STATUS]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SVINTO_SIM
|
|
||||||
/* Really simple. The output is here and now. */
|
|
||||||
SIMCOUT(buf, count);
|
|
||||||
return count;
|
|
||||||
#endif
|
|
||||||
local_save_flags(flags);
|
local_save_flags(flags);
|
||||||
DFLOW(DEBUG_LOG(info->line, "write count %i ", count));
|
DFLOW(DEBUG_LOG(info->line, "write count %i ", count));
|
||||||
DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty)));
|
DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty)));
|
||||||
|
@ -3463,7 +3357,6 @@ static int
|
||||||
get_lsr_info(struct e100_serial * info, unsigned int *value)
|
get_lsr_info(struct e100_serial * info, unsigned int *value)
|
||||||
{
|
{
|
||||||
unsigned int result = TIOCSER_TEMT;
|
unsigned int result = TIOCSER_TEMT;
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
unsigned long curr_time = jiffies;
|
unsigned long curr_time = jiffies;
|
||||||
unsigned long curr_time_usec = GET_JIFFIES_USEC();
|
unsigned long curr_time_usec = GET_JIFFIES_USEC();
|
||||||
unsigned long elapsed_usec =
|
unsigned long elapsed_usec =
|
||||||
|
@ -3474,7 +3367,6 @@ get_lsr_info(struct e100_serial * info, unsigned int *value)
|
||||||
elapsed_usec < 2*info->char_time_usec) {
|
elapsed_usec < 2*info->char_time_usec) {
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (copy_to_user(value, &result, sizeof(int)))
|
if (copy_to_user(value, &result, sizeof(int)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -3804,7 +3696,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
|
||||||
e100_disable_serial_data_irq(info);
|
e100_disable_serial_data_irq(info);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
e100_disable_rx(info);
|
e100_disable_rx(info);
|
||||||
e100_disable_rx_irq(info);
|
e100_disable_rx_irq(info);
|
||||||
|
|
||||||
|
@ -3816,7 +3707,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
|
||||||
*/
|
*/
|
||||||
rs_wait_until_sent(tty, HZ);
|
rs_wait_until_sent(tty, HZ);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
shutdown(info);
|
shutdown(info);
|
||||||
rs_flush_buffer(tty);
|
rs_flush_buffer(tty);
|
||||||
|
@ -4479,7 +4369,6 @@ static int __init rs_init(void)
|
||||||
fast_timer_init();
|
fast_timer_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_SVINTO_SIM
|
|
||||||
#ifndef CONFIG_ETRAX_KGDB
|
#ifndef CONFIG_ETRAX_KGDB
|
||||||
/* Not needed in simulator. May only complicate stuff. */
|
/* Not needed in simulator. May only complicate stuff. */
|
||||||
/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
|
/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
|
||||||
|
@ -4489,7 +4378,6 @@ static int __init rs_init(void)
|
||||||
panic("%s: Failed to request irq8", __func__);
|
panic("%s: Failed to request irq8", __func__);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* CONFIG_SVINTO_SIM */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -671,6 +671,9 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
|
||||||
if (!np)
|
if (!np)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
ret = of_property_read_u32(np, "efm32,location", &location);
|
||||||
|
if (ret)
|
||||||
|
/* fall back to old and (wrongly) generic property "location" */
|
||||||
ret = of_property_read_u32(np, "location", &location);
|
ret = of_property_read_u32(np, "location", &location);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (location > 5) {
|
if (location > 5) {
|
||||||
|
|
|
@ -13,14 +13,19 @@
|
||||||
#define SUPPORT_SYSRQ
|
#define SUPPORT_SYSRQ
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/console.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/dmaengine.h>
|
||||||
|
#include <linux/dmapool.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/console.h>
|
#include <linux/of_dma.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
|
|
||||||
/* All registers are 8-bit width */
|
/* All registers are 8-bit width */
|
||||||
|
@ -112,6 +117,10 @@
|
||||||
#define UARTSFIFO_TXOF 0x02
|
#define UARTSFIFO_TXOF 0x02
|
||||||
#define UARTSFIFO_RXUF 0x01
|
#define UARTSFIFO_RXUF 0x01
|
||||||
|
|
||||||
|
#define DMA_MAXBURST 16
|
||||||
|
#define DMA_MAXBURST_MASK (DMA_MAXBURST - 1)
|
||||||
|
#define FSL_UART_RX_DMA_BUFFER_SIZE 64
|
||||||
|
|
||||||
#define DRIVER_NAME "fsl-lpuart"
|
#define DRIVER_NAME "fsl-lpuart"
|
||||||
#define DEV_NAME "ttyLP"
|
#define DEV_NAME "ttyLP"
|
||||||
#define UART_NR 6
|
#define UART_NR 6
|
||||||
|
@ -121,6 +130,24 @@ struct lpuart_port {
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
unsigned int txfifo_size;
|
unsigned int txfifo_size;
|
||||||
unsigned int rxfifo_size;
|
unsigned int rxfifo_size;
|
||||||
|
|
||||||
|
bool lpuart_dma_use;
|
||||||
|
struct dma_chan *dma_tx_chan;
|
||||||
|
struct dma_chan *dma_rx_chan;
|
||||||
|
struct dma_async_tx_descriptor *dma_tx_desc;
|
||||||
|
struct dma_async_tx_descriptor *dma_rx_desc;
|
||||||
|
dma_addr_t dma_tx_buf_bus;
|
||||||
|
dma_addr_t dma_rx_buf_bus;
|
||||||
|
dma_cookie_t dma_tx_cookie;
|
||||||
|
dma_cookie_t dma_rx_cookie;
|
||||||
|
unsigned char *dma_tx_buf_virt;
|
||||||
|
unsigned char *dma_rx_buf_virt;
|
||||||
|
unsigned int dma_tx_bytes;
|
||||||
|
unsigned int dma_rx_bytes;
|
||||||
|
int dma_tx_in_progress;
|
||||||
|
int dma_rx_in_progress;
|
||||||
|
unsigned int dma_rx_timeout;
|
||||||
|
struct timer_list lpuart_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct of_device_id lpuart_dt_ids[] = {
|
static struct of_device_id lpuart_dt_ids[] = {
|
||||||
|
@ -131,6 +158,10 @@ static struct of_device_id lpuart_dt_ids[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
|
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
|
||||||
|
|
||||||
|
/* Forward declare this for the dma callbacks*/
|
||||||
|
static void lpuart_dma_tx_complete(void *arg);
|
||||||
|
static void lpuart_dma_rx_complete(void *arg);
|
||||||
|
|
||||||
static void lpuart_stop_tx(struct uart_port *port)
|
static void lpuart_stop_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned char temp;
|
unsigned char temp;
|
||||||
|
@ -152,6 +183,210 @@ static void lpuart_enable_ms(struct uart_port *port)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
|
||||||
|
struct tty_port *tty, int count)
|
||||||
|
{
|
||||||
|
int copied;
|
||||||
|
|
||||||
|
sport->port.icount.rx += count;
|
||||||
|
|
||||||
|
if (!tty) {
|
||||||
|
dev_err(sport->port.dev, "No tty port\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_sync_single_for_cpu(sport->port.dev, sport->dma_rx_buf_bus,
|
||||||
|
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
|
||||||
|
copied = tty_insert_flip_string(tty,
|
||||||
|
((unsigned char *)(sport->dma_rx_buf_virt)), count);
|
||||||
|
|
||||||
|
if (copied != count) {
|
||||||
|
WARN_ON(1);
|
||||||
|
dev_err(sport->port.dev, "RxData copy to tty layer failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
|
||||||
|
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpuart_pio_tx(struct lpuart_port *sport)
|
||||||
|
{
|
||||||
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
while (!uart_circ_empty(xmit) &&
|
||||||
|
readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size) {
|
||||||
|
writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR);
|
||||||
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
|
sport->port.icount.tx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
|
uart_write_wakeup(&sport->port);
|
||||||
|
|
||||||
|
if (uart_circ_empty(xmit))
|
||||||
|
writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_TDMAS,
|
||||||
|
sport->port.membase + UARTCR5);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lpuart_dma_tx(struct lpuart_port *sport, unsigned long count)
|
||||||
|
{
|
||||||
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
|
dma_addr_t tx_bus_addr;
|
||||||
|
|
||||||
|
dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
|
||||||
|
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
||||||
|
sport->dma_tx_bytes = count & ~(DMA_MAXBURST_MASK);
|
||||||
|
tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
|
||||||
|
sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
|
||||||
|
tx_bus_addr, sport->dma_tx_bytes,
|
||||||
|
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
|
||||||
|
|
||||||
|
if (!sport->dma_tx_desc) {
|
||||||
|
dev_err(sport->port.dev, "Not able to get desc for tx\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
sport->dma_tx_desc->callback = lpuart_dma_tx_complete;
|
||||||
|
sport->dma_tx_desc->callback_param = sport;
|
||||||
|
sport->dma_tx_in_progress = 1;
|
||||||
|
sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
|
||||||
|
dma_async_issue_pending(sport->dma_tx_chan);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpuart_prepare_tx(struct lpuart_port *sport)
|
||||||
|
{
|
||||||
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
|
unsigned long count = CIRC_CNT_TO_END(xmit->head,
|
||||||
|
xmit->tail, UART_XMIT_SIZE);
|
||||||
|
|
||||||
|
if (!count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (count < DMA_MAXBURST)
|
||||||
|
writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
|
||||||
|
sport->port.membase + UARTCR5);
|
||||||
|
else {
|
||||||
|
writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_TDMAS,
|
||||||
|
sport->port.membase + UARTCR5);
|
||||||
|
lpuart_dma_tx(sport, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpuart_dma_tx_complete(void *arg)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = arg;
|
||||||
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
async_tx_ack(sport->dma_tx_desc);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
xmit->tail = (xmit->tail + sport->dma_tx_bytes) & (UART_XMIT_SIZE - 1);
|
||||||
|
sport->dma_tx_in_progress = 0;
|
||||||
|
|
||||||
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
|
uart_write_wakeup(&sport->port);
|
||||||
|
|
||||||
|
lpuart_prepare_tx(sport);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lpuart_dma_rx(struct lpuart_port *sport)
|
||||||
|
{
|
||||||
|
dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
|
||||||
|
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
|
||||||
|
sport->dma_rx_desc = dmaengine_prep_slave_single(sport->dma_rx_chan,
|
||||||
|
sport->dma_rx_buf_bus, FSL_UART_RX_DMA_BUFFER_SIZE,
|
||||||
|
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
|
||||||
|
|
||||||
|
if (!sport->dma_rx_desc) {
|
||||||
|
dev_err(sport->port.dev, "Not able to get desc for rx\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
|
||||||
|
sport->dma_rx_desc->callback_param = sport;
|
||||||
|
sport->dma_rx_in_progress = 1;
|
||||||
|
sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc);
|
||||||
|
dma_async_issue_pending(sport->dma_rx_chan);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpuart_dma_rx_complete(void *arg)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = arg;
|
||||||
|
struct tty_port *port = &sport->port.state->port;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
async_tx_ack(sport->dma_rx_desc);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
sport->dma_rx_in_progress = 0;
|
||||||
|
lpuart_copy_rx_to_tty(sport, port, FSL_UART_RX_DMA_BUFFER_SIZE);
|
||||||
|
tty_flip_buffer_push(port);
|
||||||
|
lpuart_dma_rx(sport);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpuart_timer_func(unsigned long data)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = (struct lpuart_port *)data;
|
||||||
|
struct tty_port *port = &sport->port.state->port;
|
||||||
|
struct dma_tx_state state;
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned char temp;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
del_timer(&sport->lpuart_timer);
|
||||||
|
dmaengine_pause(sport->dma_rx_chan);
|
||||||
|
dmaengine_tx_status(sport->dma_rx_chan, sport->dma_rx_cookie, &state);
|
||||||
|
dmaengine_terminate_all(sport->dma_rx_chan);
|
||||||
|
count = FSL_UART_RX_DMA_BUFFER_SIZE - state.residue;
|
||||||
|
async_tx_ack(sport->dma_rx_desc);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
sport->dma_rx_in_progress = 0;
|
||||||
|
lpuart_copy_rx_to_tty(sport, port, count);
|
||||||
|
tty_flip_buffer_push(port);
|
||||||
|
temp = readb(sport->port.membase + UARTCR5);
|
||||||
|
writeb(temp & ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void lpuart_prepare_rx(struct lpuart_port *sport)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned char temp;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
init_timer(&sport->lpuart_timer);
|
||||||
|
sport->lpuart_timer.function = lpuart_timer_func;
|
||||||
|
sport->lpuart_timer.data = (unsigned long)sport;
|
||||||
|
sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
|
||||||
|
add_timer(&sport->lpuart_timer);
|
||||||
|
|
||||||
|
lpuart_dma_rx(sport);
|
||||||
|
temp = readb(sport->port.membase + UARTCR5);
|
||||||
|
writeb(temp | UARTCR5_RDMAS, sport->port.membase + UARTCR5);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
|
static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
|
||||||
{
|
{
|
||||||
struct circ_buf *xmit = &sport->port.state->xmit;
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
|
@ -172,15 +407,22 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
|
||||||
|
|
||||||
static void lpuart_start_tx(struct uart_port *port)
|
static void lpuart_start_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
|
struct lpuart_port *sport = container_of(port,
|
||||||
|
struct lpuart_port, port);
|
||||||
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
unsigned char temp;
|
unsigned char temp;
|
||||||
|
|
||||||
temp = readb(port->membase + UARTCR2);
|
temp = readb(port->membase + UARTCR2);
|
||||||
writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
|
writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
|
||||||
|
|
||||||
|
if (sport->lpuart_dma_use) {
|
||||||
|
if (!uart_circ_empty(xmit) && !sport->dma_tx_in_progress)
|
||||||
|
lpuart_prepare_tx(sport);
|
||||||
|
} else {
|
||||||
if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
|
if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
|
||||||
lpuart_transmit_buffer(sport);
|
lpuart_transmit_buffer(sport);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
|
@ -279,12 +521,19 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
|
||||||
|
|
||||||
sts = readb(sport->port.membase + UARTSR1);
|
sts = readb(sport->port.membase + UARTSR1);
|
||||||
|
|
||||||
if (sts & UARTSR1_RDRF)
|
if (sts & UARTSR1_RDRF) {
|
||||||
|
if (sport->lpuart_dma_use)
|
||||||
|
lpuart_prepare_rx(sport);
|
||||||
|
else
|
||||||
lpuart_rxint(irq, dev_id);
|
lpuart_rxint(irq, dev_id);
|
||||||
|
}
|
||||||
if (sts & UARTSR1_TDRE &&
|
if (sts & UARTSR1_TDRE &&
|
||||||
!(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS))
|
!(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS)) {
|
||||||
|
if (sport->lpuart_dma_use)
|
||||||
|
lpuart_pio_tx(sport);
|
||||||
|
else
|
||||||
lpuart_txint(irq, dev_id);
|
lpuart_txint(irq, dev_id);
|
||||||
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -366,13 +615,156 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
|
||||||
writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
|
writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
|
||||||
sport->port.membase + UARTCFIFO);
|
sport->port.membase + UARTCFIFO);
|
||||||
|
|
||||||
writeb(2, sport->port.membase + UARTTWFIFO);
|
writeb(0, sport->port.membase + UARTTWFIFO);
|
||||||
writeb(1, sport->port.membase + UARTRWFIFO);
|
writeb(1, sport->port.membase + UARTRWFIFO);
|
||||||
|
|
||||||
/* Restore cr2 */
|
/* Restore cr2 */
|
||||||
writeb(cr2_saved, sport->port.membase + UARTCR2);
|
writeb(cr2_saved, sport->port.membase + UARTCR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lpuart_dma_tx_request(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port,
|
||||||
|
struct lpuart_port, port);
|
||||||
|
struct dma_chan *tx_chan;
|
||||||
|
struct dma_slave_config dma_tx_sconfig;
|
||||||
|
dma_addr_t dma_bus;
|
||||||
|
unsigned char *dma_buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
|
||||||
|
|
||||||
|
if (!tx_chan) {
|
||||||
|
dev_err(sport->port.dev, "Dma tx channel request failed!\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_bus = dma_map_single(tx_chan->device->dev,
|
||||||
|
sport->port.state->xmit.buf,
|
||||||
|
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
||||||
|
|
||||||
|
if (dma_mapping_error(tx_chan->device->dev, dma_bus)) {
|
||||||
|
dev_err(sport->port.dev, "dma_map_single tx failed\n");
|
||||||
|
dma_release_channel(tx_chan);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_buf = sport->port.state->xmit.buf;
|
||||||
|
dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
|
||||||
|
dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||||
|
dma_tx_sconfig.dst_maxburst = DMA_MAXBURST;
|
||||||
|
dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
|
||||||
|
ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(sport->port.dev,
|
||||||
|
"Dma slave config failed, err = %d\n", ret);
|
||||||
|
dma_release_channel(tx_chan);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sport->dma_tx_chan = tx_chan;
|
||||||
|
sport->dma_tx_buf_virt = dma_buf;
|
||||||
|
sport->dma_tx_buf_bus = dma_bus;
|
||||||
|
sport->dma_tx_in_progress = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lpuart_dma_rx_request(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port,
|
||||||
|
struct lpuart_port, port);
|
||||||
|
struct dma_chan *rx_chan;
|
||||||
|
struct dma_slave_config dma_rx_sconfig;
|
||||||
|
dma_addr_t dma_bus;
|
||||||
|
unsigned char *dma_buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
|
||||||
|
|
||||||
|
if (!rx_chan) {
|
||||||
|
dev_err(sport->port.dev, "Dma rx channel request failed!\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_buf = devm_kzalloc(sport->port.dev,
|
||||||
|
FSL_UART_RX_DMA_BUFFER_SIZE, GFP_KERNEL);
|
||||||
|
|
||||||
|
if (!dma_buf) {
|
||||||
|
dev_err(sport->port.dev, "Dma rx alloc failed\n");
|
||||||
|
dma_release_channel(rx_chan);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_bus = dma_map_single(rx_chan->device->dev, dma_buf,
|
||||||
|
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
|
if (dma_mapping_error(rx_chan->device->dev, dma_bus)) {
|
||||||
|
dev_err(sport->port.dev, "dma_map_single rx failed\n");
|
||||||
|
dma_release_channel(rx_chan);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_rx_sconfig.src_addr = sport->port.mapbase + UARTDR;
|
||||||
|
dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||||
|
dma_rx_sconfig.src_maxburst = 1;
|
||||||
|
dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
|
||||||
|
ret = dmaengine_slave_config(rx_chan, &dma_rx_sconfig);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(sport->port.dev,
|
||||||
|
"Dma slave config failed, err = %d\n", ret);
|
||||||
|
dma_release_channel(rx_chan);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sport->dma_rx_chan = rx_chan;
|
||||||
|
sport->dma_rx_buf_virt = dma_buf;
|
||||||
|
sport->dma_rx_buf_bus = dma_bus;
|
||||||
|
sport->dma_rx_in_progress = 0;
|
||||||
|
|
||||||
|
sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
|
||||||
|
FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
|
||||||
|
sport->rxfifo_size / 2;
|
||||||
|
|
||||||
|
if (sport->dma_rx_timeout < msecs_to_jiffies(20))
|
||||||
|
sport->dma_rx_timeout = msecs_to_jiffies(20);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpuart_dma_tx_free(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port,
|
||||||
|
struct lpuart_port, port);
|
||||||
|
struct dma_chan *dma_chan;
|
||||||
|
|
||||||
|
dma_unmap_single(sport->port.dev, sport->dma_tx_buf_bus,
|
||||||
|
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
||||||
|
dma_chan = sport->dma_tx_chan;
|
||||||
|
sport->dma_tx_chan = NULL;
|
||||||
|
sport->dma_tx_buf_bus = 0;
|
||||||
|
sport->dma_tx_buf_virt = NULL;
|
||||||
|
dma_release_channel(dma_chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpuart_dma_rx_free(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port,
|
||||||
|
struct lpuart_port, port);
|
||||||
|
struct dma_chan *dma_chan;
|
||||||
|
|
||||||
|
dma_unmap_single(sport->port.dev, sport->dma_rx_buf_bus,
|
||||||
|
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
|
dma_chan = sport->dma_rx_chan;
|
||||||
|
sport->dma_rx_chan = NULL;
|
||||||
|
sport->dma_rx_buf_bus = 0;
|
||||||
|
sport->dma_rx_buf_virt = NULL;
|
||||||
|
dma_release_channel(dma_chan);
|
||||||
|
}
|
||||||
|
|
||||||
static int lpuart_startup(struct uart_port *port)
|
static int lpuart_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
|
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
|
||||||
|
@ -380,6 +772,15 @@ static int lpuart_startup(struct uart_port *port)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned char temp;
|
unsigned char temp;
|
||||||
|
|
||||||
|
/*whether use dma support by dma request results*/
|
||||||
|
if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
|
||||||
|
sport->lpuart_dma_use = false;
|
||||||
|
} else {
|
||||||
|
sport->lpuart_dma_use = true;
|
||||||
|
temp = readb(port->membase + UARTCR5);
|
||||||
|
writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
|
||||||
|
}
|
||||||
|
|
||||||
ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0,
|
ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0,
|
||||||
DRIVER_NAME, sport);
|
DRIVER_NAME, sport);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -414,6 +815,11 @@ static void lpuart_shutdown(struct uart_port *port)
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
devm_free_irq(port->dev, port->irq, sport);
|
devm_free_irq(port->dev, port->irq, sport);
|
||||||
|
|
||||||
|
if (sport->lpuart_dma_use) {
|
||||||
|
lpuart_dma_tx_free(port);
|
||||||
|
lpuart_dma_rx_free(port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -496,7 +496,6 @@ static void dma_tx_callback(void *data)
|
||||||
|
|
||||||
dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
|
dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
|
||||||
|
|
||||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
|
||||||
uart_write_wakeup(&sport->port);
|
uart_write_wakeup(&sport->port);
|
||||||
|
|
||||||
if (waitqueue_active(&sport->dma_wait)) {
|
if (waitqueue_active(&sport->dma_wait)) {
|
||||||
|
@ -1117,25 +1116,25 @@ static int imx_startup(struct uart_port *port)
|
||||||
*/
|
*/
|
||||||
if (sport->txirq > 0) {
|
if (sport->txirq > 0) {
|
||||||
retval = request_irq(sport->rxirq, imx_rxint, 0,
|
retval = request_irq(sport->rxirq, imx_rxint, 0,
|
||||||
DRIVER_NAME, sport);
|
dev_name(port->dev), sport);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto error_out1;
|
goto error_out1;
|
||||||
|
|
||||||
retval = request_irq(sport->txirq, imx_txint, 0,
|
retval = request_irq(sport->txirq, imx_txint, 0,
|
||||||
DRIVER_NAME, sport);
|
dev_name(port->dev), sport);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto error_out2;
|
goto error_out2;
|
||||||
|
|
||||||
/* do not use RTS IRQ on IrDA */
|
/* do not use RTS IRQ on IrDA */
|
||||||
if (!USE_IRDA(sport)) {
|
if (!USE_IRDA(sport)) {
|
||||||
retval = request_irq(sport->rtsirq, imx_rtsint, 0,
|
retval = request_irq(sport->rtsirq, imx_rtsint, 0,
|
||||||
DRIVER_NAME, sport);
|
dev_name(port->dev), sport);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto error_out3;
|
goto error_out3;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
retval = request_irq(sport->port.irq, imx_int, 0,
|
retval = request_irq(sport->port.irq, imx_int, 0,
|
||||||
DRIVER_NAME, sport);
|
dev_name(port->dev), sport);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
free_irq(sport->port.irq, sport);
|
free_irq(sport->port.irq, sport);
|
||||||
goto error_out1;
|
goto error_out1;
|
||||||
|
@ -1469,36 +1468,6 @@ static const char *imx_type(struct uart_port *port)
|
||||||
return sport->port.type == PORT_IMX ? "IMX" : NULL;
|
return sport->port.type == PORT_IMX ? "IMX" : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Release the memory region(s) being used by 'port'.
|
|
||||||
*/
|
|
||||||
static void imx_release_port(struct uart_port *port)
|
|
||||||
{
|
|
||||||
struct platform_device *pdev = to_platform_device(port->dev);
|
|
||||||
struct resource *mmres;
|
|
||||||
|
|
||||||
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
release_mem_region(mmres->start, resource_size(mmres));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Request the memory region(s) being used by 'port'.
|
|
||||||
*/
|
|
||||||
static int imx_request_port(struct uart_port *port)
|
|
||||||
{
|
|
||||||
struct platform_device *pdev = to_platform_device(port->dev);
|
|
||||||
struct resource *mmres;
|
|
||||||
void *ret;
|
|
||||||
|
|
||||||
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
if (!mmres)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
ret = request_mem_region(mmres->start, resource_size(mmres), "imx-uart");
|
|
||||||
|
|
||||||
return ret ? 0 : -EBUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure/autoconfigure the port.
|
* Configure/autoconfigure the port.
|
||||||
*/
|
*/
|
||||||
|
@ -1506,8 +1475,7 @@ static void imx_config_port(struct uart_port *port, int flags)
|
||||||
{
|
{
|
||||||
struct imx_port *sport = (struct imx_port *)port;
|
struct imx_port *sport = (struct imx_port *)port;
|
||||||
|
|
||||||
if (flags & UART_CONFIG_TYPE &&
|
if (flags & UART_CONFIG_TYPE)
|
||||||
imx_request_port(&sport->port) == 0)
|
|
||||||
sport->port.type = PORT_IMX;
|
sport->port.type = PORT_IMX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1617,8 +1585,6 @@ static struct uart_ops imx_pops = {
|
||||||
.flush_buffer = imx_flush_buffer,
|
.flush_buffer = imx_flush_buffer,
|
||||||
.set_termios = imx_set_termios,
|
.set_termios = imx_set_termios,
|
||||||
.type = imx_type,
|
.type = imx_type,
|
||||||
.release_port = imx_release_port,
|
|
||||||
.request_port = imx_request_port,
|
|
||||||
.config_port = imx_config_port,
|
.config_port = imx_config_port,
|
||||||
.verify_port = imx_verify_port,
|
.verify_port = imx_verify_port,
|
||||||
#if defined(CONFIG_CONSOLE_POLL)
|
#if defined(CONFIG_CONSOLE_POLL)
|
||||||
|
@ -1935,7 +1901,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
|
||||||
static int serial_imx_probe(struct platform_device *pdev)
|
static int serial_imx_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct imx_port *sport;
|
struct imx_port *sport;
|
||||||
struct imxuart_platform_data *pdata;
|
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
@ -1951,12 +1916,9 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!res)
|
base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
return -ENODEV;
|
if (IS_ERR(base))
|
||||||
|
return PTR_ERR(base);
|
||||||
base = devm_ioremap(&pdev->dev, res->start, PAGE_SIZE);
|
|
||||||
if (!base)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
sport->port.dev = &pdev->dev;
|
sport->port.dev = &pdev->dev;
|
||||||
sport->port.mapbase = res->start;
|
sport->port.mapbase = res->start;
|
||||||
|
@ -1992,38 +1954,16 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
imx_ports[sport->port.line] = sport;
|
imx_ports[sport->port.line] = sport;
|
||||||
|
|
||||||
pdata = dev_get_platdata(&pdev->dev);
|
|
||||||
if (pdata && pdata->init) {
|
|
||||||
ret = pdata->init(pdev);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = uart_add_one_port(&imx_reg, &sport->port);
|
|
||||||
if (ret)
|
|
||||||
goto deinit;
|
|
||||||
platform_set_drvdata(pdev, sport);
|
platform_set_drvdata(pdev, sport);
|
||||||
|
|
||||||
return 0;
|
return uart_add_one_port(&imx_reg, &sport->port);
|
||||||
deinit:
|
|
||||||
if (pdata && pdata->exit)
|
|
||||||
pdata->exit(pdev);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_imx_remove(struct platform_device *pdev)
|
static int serial_imx_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct imxuart_platform_data *pdata;
|
|
||||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
pdata = dev_get_platdata(&pdev->dev);
|
return uart_remove_one_port(&imx_reg, &sport->port);
|
||||||
|
|
||||||
uart_remove_one_port(&imx_reg, &sport->port);
|
|
||||||
|
|
||||||
if (pdata && pdata->exit)
|
|
||||||
pdata->exit(pdev);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver serial_imx_driver = {
|
static struct platform_driver serial_imx_driver = {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
|
* Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012-2013 Alexander Shiyan <shc_work@mail.ru>
|
* Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
|
||||||
*
|
*
|
||||||
* Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
|
* Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
|
||||||
* Based on max3110.c, by Feng Tang <feng.tang@intel.com>
|
* Based on max3110.c, by Feng Tang <feng.tang@intel.com>
|
||||||
|
@ -13,19 +13,21 @@
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/regmap.h>
|
|
||||||
#include <linux/gpio.h>
|
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
#include <linux/platform_data/max310x.h>
|
|
||||||
|
|
||||||
#define MAX310X_NAME "max310x"
|
#define MAX310X_NAME "max310x"
|
||||||
#define MAX310X_MAJOR 204
|
#define MAX310X_MAJOR 204
|
||||||
|
@ -161,10 +163,6 @@
|
||||||
/* IRDA register bits */
|
/* IRDA register bits */
|
||||||
#define MAX310X_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
|
#define MAX310X_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
|
||||||
#define MAX310X_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */
|
#define MAX310X_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */
|
||||||
#define MAX310X_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */
|
|
||||||
#define MAX310X_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */
|
|
||||||
#define MAX310X_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */
|
|
||||||
#define MAX310X_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */
|
|
||||||
|
|
||||||
/* Flow control trigger level register masks */
|
/* Flow control trigger level register masks */
|
||||||
#define MAX310X_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */
|
#define MAX310X_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */
|
||||||
|
@ -220,26 +218,6 @@
|
||||||
* XOFF2
|
* XOFF2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* GPIO configuration register bits */
|
|
||||||
#define MAX310X_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */
|
|
||||||
#define MAX310X_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */
|
|
||||||
#define MAX310X_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */
|
|
||||||
#define MAX310X_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */
|
|
||||||
#define MAX310X_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */
|
|
||||||
#define MAX310X_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */
|
|
||||||
#define MAX310X_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */
|
|
||||||
#define MAX310X_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */
|
|
||||||
|
|
||||||
/* GPIO DATA register bits */
|
|
||||||
#define MAX310X_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */
|
|
||||||
#define MAX310X_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */
|
|
||||||
#define MAX310X_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */
|
|
||||||
#define MAX310X_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */
|
|
||||||
#define MAX310X_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */
|
|
||||||
#define MAX310X_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */
|
|
||||||
#define MAX310X_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */
|
|
||||||
#define MAX310X_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */
|
|
||||||
|
|
||||||
/* PLL configuration register masks */
|
/* PLL configuration register masks */
|
||||||
#define MAX310X_PLLCFG_PREDIV_MASK (0x3f) /* PLL predivision value */
|
#define MAX310X_PLLCFG_PREDIV_MASK (0x3f) /* PLL predivision value */
|
||||||
#define MAX310X_PLLCFG_PLLFACTOR_MASK (0xc0) /* PLL multiplication factor */
|
#define MAX310X_PLLCFG_PLLFACTOR_MASK (0xc0) /* PLL multiplication factor */
|
||||||
|
@ -283,16 +261,15 @@ struct max310x_devtype {
|
||||||
struct max310x_one {
|
struct max310x_one {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
struct work_struct tx_work;
|
struct work_struct tx_work;
|
||||||
|
struct work_struct md_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct max310x_port {
|
struct max310x_port {
|
||||||
struct uart_driver uart;
|
struct uart_driver uart;
|
||||||
struct max310x_devtype *devtype;
|
struct max310x_devtype *devtype;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
struct regmap_config regcfg;
|
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct max310x_pdata *pdata;
|
struct clk *clk;
|
||||||
int gpio_used;
|
|
||||||
#ifdef CONFIG_GPIOLIB
|
#ifdef CONFIG_GPIOLIB
|
||||||
struct gpio_chip gpio;
|
struct gpio_chip gpio;
|
||||||
#endif
|
#endif
|
||||||
|
@ -504,25 +481,33 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void max310x_set_baud(struct uart_port *port, int baud)
|
static int max310x_set_baud(struct uart_port *port, int baud)
|
||||||
{
|
{
|
||||||
unsigned int mode = 0, div = port->uartclk / baud;
|
unsigned int mode = 0, clk = port->uartclk, div = clk / baud;
|
||||||
|
|
||||||
if (!(div / 16)) {
|
/* Check for minimal value for divider */
|
||||||
|
if (div < 16)
|
||||||
|
div = 16;
|
||||||
|
|
||||||
|
if (clk % baud && (div / 16) < 0x8000) {
|
||||||
/* Mode x2 */
|
/* Mode x2 */
|
||||||
mode = MAX310X_BRGCFG_2XMODE_BIT;
|
mode = MAX310X_BRGCFG_2XMODE_BIT;
|
||||||
div = (port->uartclk * 2) / baud;
|
clk = port->uartclk * 2;
|
||||||
}
|
div = clk / baud;
|
||||||
|
|
||||||
if (!(div / 16)) {
|
if (clk % baud && (div / 16) < 0x8000) {
|
||||||
/* Mode x4 */
|
/* Mode x4 */
|
||||||
mode = MAX310X_BRGCFG_4XMODE_BIT;
|
mode = MAX310X_BRGCFG_4XMODE_BIT;
|
||||||
div = (port->uartclk * 4) / baud;
|
clk = port->uartclk * 4;
|
||||||
|
div = clk / baud;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8);
|
max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8);
|
||||||
max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16);
|
max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16);
|
||||||
max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode);
|
max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode);
|
||||||
|
|
||||||
|
return DIV_ROUND_CLOSEST(clk, div);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max310x_update_best_err(unsigned long f, long *besterr)
|
static int max310x_update_best_err(unsigned long f, long *besterr)
|
||||||
|
@ -538,18 +523,19 @@ static int max310x_update_best_err(unsigned long f, long *besterr)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max310x_set_ref_clk(struct max310x_port *s)
|
static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq,
|
||||||
|
bool xtal)
|
||||||
{
|
{
|
||||||
unsigned int div, clksrc, pllcfg = 0;
|
unsigned int div, clksrc, pllcfg = 0;
|
||||||
long besterr = -1;
|
long besterr = -1;
|
||||||
unsigned long fdiv, fmul, bestfreq = s->pdata->frequency;
|
unsigned long fdiv, fmul, bestfreq = freq;
|
||||||
|
|
||||||
/* First, update error without PLL */
|
/* First, update error without PLL */
|
||||||
max310x_update_best_err(s->pdata->frequency, &besterr);
|
max310x_update_best_err(freq, &besterr);
|
||||||
|
|
||||||
/* Try all possible PLL dividers */
|
/* Try all possible PLL dividers */
|
||||||
for (div = 1; (div <= 63) && besterr; div++) {
|
for (div = 1; (div <= 63) && besterr; div++) {
|
||||||
fdiv = DIV_ROUND_CLOSEST(s->pdata->frequency, div);
|
fdiv = DIV_ROUND_CLOSEST(freq, div);
|
||||||
|
|
||||||
/* Try multiplier 6 */
|
/* Try multiplier 6 */
|
||||||
fmul = fdiv * 6;
|
fmul = fdiv * 6;
|
||||||
|
@ -582,10 +568,7 @@ static int max310x_set_ref_clk(struct max310x_port *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure clock source */
|
/* Configure clock source */
|
||||||
if (s->pdata->driver_flags & MAX310X_EXT_CLK)
|
clksrc = xtal ? MAX310X_CLKSRC_CRYST_BIT : MAX310X_CLKSRC_EXTCLK_BIT;
|
||||||
clksrc = MAX310X_CLKSRC_EXTCLK_BIT;
|
|
||||||
else
|
|
||||||
clksrc = MAX310X_CLKSRC_CRYST_BIT;
|
|
||||||
|
|
||||||
/* Configure PLL */
|
/* Configure PLL */
|
||||||
if (pllcfg) {
|
if (pllcfg) {
|
||||||
|
@ -597,7 +580,7 @@ static int max310x_set_ref_clk(struct max310x_port *s)
|
||||||
regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc);
|
regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc);
|
||||||
|
|
||||||
/* Wait for crystal */
|
/* Wait for crystal */
|
||||||
if (pllcfg && !(s->pdata->driver_flags & MAX310X_EXT_CLK))
|
if (pllcfg && xtal)
|
||||||
msleep(10);
|
msleep(10);
|
||||||
|
|
||||||
return (int)bestfreq;
|
return (int)bestfreq;
|
||||||
|
@ -782,11 +765,21 @@ static unsigned int max310x_get_mctrl(struct uart_port *port)
|
||||||
return TIOCM_DSR | TIOCM_CAR;
|
return TIOCM_DSR | TIOCM_CAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void max310x_md_proc(struct work_struct *ws)
|
||||||
|
{
|
||||||
|
struct max310x_one *one = container_of(ws, struct max310x_one, md_work);
|
||||||
|
|
||||||
|
max310x_port_update(&one->port, MAX310X_MODE2_REG,
|
||||||
|
MAX310X_MODE2_LOOPBACK_BIT,
|
||||||
|
(one->port.mctrl & TIOCM_LOOP) ?
|
||||||
|
MAX310X_MODE2_LOOPBACK_BIT : 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
{
|
{
|
||||||
/* DCD and DSR are not wired and CTS/RTS is hadnled automatically
|
struct max310x_one *one = container_of(port, struct max310x_one, port);
|
||||||
* so do nothing
|
|
||||||
*/
|
schedule_work(&one->md_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void max310x_break_ctl(struct uart_port *port, int break_state)
|
static void max310x_break_ctl(struct uart_port *port, int break_state)
|
||||||
|
@ -875,40 +868,76 @@ static void max310x_set_termios(struct uart_port *port,
|
||||||
port->uartclk / 4);
|
port->uartclk / 4);
|
||||||
|
|
||||||
/* Setup baudrate generator */
|
/* Setup baudrate generator */
|
||||||
max310x_set_baud(port, baud);
|
baud = max310x_set_baud(port, baud);
|
||||||
|
|
||||||
/* Update timeout according to new baud rate */
|
/* Update timeout according to new baud rate */
|
||||||
uart_update_timeout(port, termios->c_cflag, baud);
|
uart_update_timeout(port, termios->c_cflag, baud);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int max310x_ioctl(struct uart_port *port, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
#if defined(TIOCSRS485) && defined(TIOCGRS485)
|
||||||
|
struct serial_rs485 rs485;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case TIOCSRS485:
|
||||||
|
if (copy_from_user(&rs485, (void __user *)arg, sizeof(rs485)))
|
||||||
|
return -EFAULT;
|
||||||
|
if (rs485.delay_rts_before_send > 0x0f ||
|
||||||
|
rs485.delay_rts_after_send > 0x0f)
|
||||||
|
return -ERANGE;
|
||||||
|
val = (rs485.delay_rts_before_send << 4) |
|
||||||
|
rs485.delay_rts_after_send;
|
||||||
|
max310x_port_write(port, MAX310X_HDPIXDELAY_REG, val);
|
||||||
|
if (rs485.flags & SER_RS485_ENABLED) {
|
||||||
|
max310x_port_update(port, MAX310X_MODE1_REG,
|
||||||
|
MAX310X_MODE1_TRNSCVCTRL_BIT,
|
||||||
|
MAX310X_MODE1_TRNSCVCTRL_BIT);
|
||||||
|
max310x_port_update(port, MAX310X_MODE2_REG,
|
||||||
|
MAX310X_MODE2_ECHOSUPR_BIT,
|
||||||
|
MAX310X_MODE2_ECHOSUPR_BIT);
|
||||||
|
} else {
|
||||||
|
max310x_port_update(port, MAX310X_MODE1_REG,
|
||||||
|
MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
|
||||||
|
max310x_port_update(port, MAX310X_MODE2_REG,
|
||||||
|
MAX310X_MODE2_ECHOSUPR_BIT, 0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case TIOCGRS485:
|
||||||
|
memset(&rs485, 0, sizeof(rs485));
|
||||||
|
val = max310x_port_read(port, MAX310X_MODE1_REG);
|
||||||
|
rs485.flags = (val & MAX310X_MODE1_TRNSCVCTRL_BIT) ?
|
||||||
|
SER_RS485_ENABLED : 0;
|
||||||
|
rs485.flags |= SER_RS485_RTS_ON_SEND;
|
||||||
|
val = max310x_port_read(port, MAX310X_HDPIXDELAY_REG);
|
||||||
|
rs485.delay_rts_before_send = val >> 4;
|
||||||
|
rs485.delay_rts_after_send = val & 0x0f;
|
||||||
|
if (copy_to_user((void __user *)arg, &rs485, sizeof(rs485)))
|
||||||
|
return -EFAULT;
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
|
||||||
static int max310x_startup(struct uart_port *port)
|
static int max310x_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned int val, line = port->line;
|
|
||||||
struct max310x_port *s = dev_get_drvdata(port->dev);
|
struct max310x_port *s = dev_get_drvdata(port->dev);
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
s->devtype->power(port, 1);
|
s->devtype->power(port, 1);
|
||||||
|
|
||||||
/* Configure baud rate, 9600 as default */
|
|
||||||
max310x_set_baud(port, 9600);
|
|
||||||
|
|
||||||
/* Configure LCR register, 8N1 mode by default */
|
|
||||||
max310x_port_write(port, MAX310X_LCR_REG, MAX310X_LCR_WORD_LEN_8);
|
|
||||||
|
|
||||||
/* Configure MODE1 register */
|
/* Configure MODE1 register */
|
||||||
max310x_port_update(port, MAX310X_MODE1_REG,
|
max310x_port_update(port, MAX310X_MODE1_REG,
|
||||||
MAX310X_MODE1_TRNSCVCTRL_BIT,
|
MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
|
||||||
(s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL)
|
|
||||||
? MAX310X_MODE1_TRNSCVCTRL_BIT : 0);
|
|
||||||
|
|
||||||
/* Configure MODE2 register */
|
/* Configure MODE2 register & Reset FIFOs*/
|
||||||
val = MAX310X_MODE2_RXEMPTINV_BIT;
|
val = MAX310X_MODE2_RXEMPTINV_BIT | MAX310X_MODE2_FIFORST_BIT;
|
||||||
if (s->pdata->uart_flags[line] & MAX310X_LOOPBACK)
|
|
||||||
val |= MAX310X_MODE2_LOOPBACK_BIT;
|
|
||||||
if (s->pdata->uart_flags[line] & MAX310X_ECHO_SUPRESS)
|
|
||||||
val |= MAX310X_MODE2_ECHOSUPR_BIT;
|
|
||||||
|
|
||||||
/* Reset FIFOs */
|
|
||||||
val |= MAX310X_MODE2_FIFORST_BIT;
|
|
||||||
max310x_port_write(port, MAX310X_MODE2_REG, val);
|
max310x_port_write(port, MAX310X_MODE2_REG, val);
|
||||||
max310x_port_update(port, MAX310X_MODE2_REG,
|
max310x_port_update(port, MAX310X_MODE2_REG,
|
||||||
MAX310X_MODE2_FIFORST_BIT, 0);
|
MAX310X_MODE2_FIFORST_BIT, 0);
|
||||||
|
@ -989,6 +1018,7 @@ static const struct uart_ops max310x_ops = {
|
||||||
.release_port = max310x_null_void,
|
.release_port = max310x_null_void,
|
||||||
.config_port = max310x_config_port,
|
.config_port = max310x_config_port,
|
||||||
.verify_port = max310x_verify_port,
|
.verify_port = max310x_verify_port,
|
||||||
|
.ioctl = max310x_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __maybe_unused max310x_suspend(struct device *dev)
|
static int __maybe_unused max310x_suspend(struct device *dev)
|
||||||
|
@ -1017,6 +1047,8 @@ static int __maybe_unused max310x_resume(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
|
||||||
|
|
||||||
#ifdef CONFIG_GPIOLIB
|
#ifdef CONFIG_GPIOLIB
|
||||||
static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
|
static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||||
{
|
{
|
||||||
|
@ -1063,23 +1095,16 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int max310x_probe(struct device *dev, int is_spi,
|
static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||||
struct max310x_devtype *devtype, int irq)
|
struct regmap *regmap, int irq, unsigned long flags)
|
||||||
{
|
{
|
||||||
|
int i, ret, fmin, fmax, freq, uartclk;
|
||||||
|
struct clk *clk_osc, *clk_xtal;
|
||||||
struct max310x_port *s;
|
struct max310x_port *s;
|
||||||
struct max310x_pdata *pdata = dev_get_platdata(dev);
|
bool xtal = false;
|
||||||
int i, ret, uartclk;
|
|
||||||
|
|
||||||
/* Check for IRQ */
|
if (IS_ERR(regmap))
|
||||||
if (irq <= 0) {
|
return PTR_ERR(regmap);
|
||||||
dev_err(dev, "No IRQ specified\n");
|
|
||||||
return -ENOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pdata) {
|
|
||||||
dev_err(dev, "No platform data supplied\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Alloc port structure */
|
/* Alloc port structure */
|
||||||
s = devm_kzalloc(dev, sizeof(*s) +
|
s = devm_kzalloc(dev, sizeof(*s) +
|
||||||
|
@ -1089,52 +1114,44 @@ static int max310x_probe(struct device *dev, int is_spi,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check input frequency */
|
clk_osc = devm_clk_get(dev, "osc");
|
||||||
if ((pdata->driver_flags & MAX310X_EXT_CLK) &&
|
clk_xtal = devm_clk_get(dev, "xtal");
|
||||||
((pdata->frequency < 500000) || (pdata->frequency > 35000000)))
|
if (!IS_ERR(clk_osc)) {
|
||||||
goto err_freq;
|
s->clk = clk_osc;
|
||||||
/* Check frequency for quartz */
|
fmin = 500000;
|
||||||
if (!(pdata->driver_flags & MAX310X_EXT_CLK) &&
|
fmax = 35000000;
|
||||||
((pdata->frequency < 1000000) || (pdata->frequency > 4000000)))
|
} else if (!IS_ERR(clk_xtal)) {
|
||||||
goto err_freq;
|
s->clk = clk_xtal;
|
||||||
|
fmin = 1000000;
|
||||||
s->pdata = pdata;
|
fmax = 4000000;
|
||||||
s->devtype = devtype;
|
xtal = true;
|
||||||
dev_set_drvdata(dev, s);
|
} else if (PTR_ERR(clk_osc) == -EPROBE_DEFER ||
|
||||||
|
PTR_ERR(clk_xtal) == -EPROBE_DEFER) {
|
||||||
mutex_init(&s->mutex);
|
return -EPROBE_DEFER;
|
||||||
|
} else {
|
||||||
/* Setup regmap */
|
dev_err(dev, "Cannot get clock\n");
|
||||||
s->regcfg.reg_bits = 8;
|
return -EINVAL;
|
||||||
s->regcfg.val_bits = 8;
|
|
||||||
s->regcfg.read_flag_mask = 0x00;
|
|
||||||
s->regcfg.write_flag_mask = 0x80;
|
|
||||||
s->regcfg.cache_type = REGCACHE_RBTREE;
|
|
||||||
s->regcfg.writeable_reg = max310x_reg_writeable;
|
|
||||||
s->regcfg.volatile_reg = max310x_reg_volatile;
|
|
||||||
s->regcfg.precious_reg = max310x_reg_precious;
|
|
||||||
s->regcfg.max_register = devtype->nr * 0x20 - 1;
|
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_SPI_MASTER) && is_spi) {
|
|
||||||
struct spi_device *spi = to_spi_device(dev);
|
|
||||||
|
|
||||||
s->regmap = devm_regmap_init_spi(spi, &s->regcfg);
|
|
||||||
} else
|
|
||||||
return -ENOTSUPP;
|
|
||||||
|
|
||||||
if (IS_ERR(s->regmap)) {
|
|
||||||
dev_err(dev, "Failed to initialize register map\n");
|
|
||||||
return PTR_ERR(s->regmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Board specific configure */
|
ret = clk_prepare_enable(s->clk);
|
||||||
if (s->pdata->init)
|
if (ret)
|
||||||
s->pdata->init();
|
return ret;
|
||||||
|
|
||||||
|
freq = clk_get_rate(s->clk);
|
||||||
|
/* Check frequency limits */
|
||||||
|
if (freq < fmin || freq > fmax) {
|
||||||
|
ret = -ERANGE;
|
||||||
|
goto out_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->regmap = regmap;
|
||||||
|
s->devtype = devtype;
|
||||||
|
dev_set_drvdata(dev, s);
|
||||||
|
|
||||||
/* Check device to ensure we are talking to what we expect */
|
/* Check device to ensure we are talking to what we expect */
|
||||||
ret = devtype->detect(dev);
|
ret = devtype->detect(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out_clk;
|
||||||
|
|
||||||
for (i = 0; i < devtype->nr; i++) {
|
for (i = 0; i < devtype->nr; i++) {
|
||||||
unsigned int offs = i << 5;
|
unsigned int offs = i << 5;
|
||||||
|
@ -1156,7 +1173,7 @@ static int max310x_probe(struct device *dev, int is_spi,
|
||||||
MAX310X_MODE1_AUTOSLEEP_BIT);
|
MAX310X_MODE1_AUTOSLEEP_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
uartclk = max310x_set_ref_clk(s);
|
uartclk = max310x_set_ref_clk(s, freq, xtal);
|
||||||
dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
|
dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
|
||||||
|
|
||||||
/* Register UART driver */
|
/* Register UART driver */
|
||||||
|
@ -1168,9 +1185,28 @@ static int max310x_probe(struct device *dev, int is_spi,
|
||||||
ret = uart_register_driver(&s->uart);
|
ret = uart_register_driver(&s->uart);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Registering UART driver failed\n");
|
dev_err(dev, "Registering UART driver failed\n");
|
||||||
return ret;
|
goto out_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_GPIOLIB
|
||||||
|
/* Setup GPIO cotroller */
|
||||||
|
s->gpio.owner = THIS_MODULE;
|
||||||
|
s->gpio.dev = dev;
|
||||||
|
s->gpio.label = dev_name(dev);
|
||||||
|
s->gpio.direction_input = max310x_gpio_direction_input;
|
||||||
|
s->gpio.get = max310x_gpio_get;
|
||||||
|
s->gpio.direction_output= max310x_gpio_direction_output;
|
||||||
|
s->gpio.set = max310x_gpio_set;
|
||||||
|
s->gpio.base = -1;
|
||||||
|
s->gpio.ngpio = devtype->nr * 4;
|
||||||
|
s->gpio.can_sleep = 1;
|
||||||
|
ret = gpiochip_add(&s->gpio);
|
||||||
|
if (ret)
|
||||||
|
goto out_uart;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mutex_init(&s->mutex);
|
||||||
|
|
||||||
for (i = 0; i < devtype->nr; i++) {
|
for (i = 0; i < devtype->nr; i++) {
|
||||||
/* Initialize port data */
|
/* Initialize port data */
|
||||||
s->p[i].port.line = i;
|
s->p[i].port.line = i;
|
||||||
|
@ -1178,8 +1214,7 @@ static int max310x_probe(struct device *dev, int is_spi,
|
||||||
s->p[i].port.irq = irq;
|
s->p[i].port.irq = irq;
|
||||||
s->p[i].port.type = PORT_MAX310X;
|
s->p[i].port.type = PORT_MAX310X;
|
||||||
s->p[i].port.fifosize = MAX310X_FIFO_SIZE;
|
s->p[i].port.fifosize = MAX310X_FIFO_SIZE;
|
||||||
s->p[i].port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE |
|
s->p[i].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
|
||||||
UPF_LOW_LATENCY;
|
|
||||||
s->p[i].port.iotype = UPIO_PORT;
|
s->p[i].port.iotype = UPIO_PORT;
|
||||||
s->p[i].port.iobase = i * 0x20;
|
s->p[i].port.iobase = i * 0x20;
|
||||||
s->p[i].port.membase = (void __iomem *)~0;
|
s->p[i].port.membase = (void __iomem *)~0;
|
||||||
|
@ -1195,48 +1230,35 @@ static int max310x_probe(struct device *dev, int is_spi,
|
||||||
MAX310X_MODE1_IRQSEL_BIT);
|
MAX310X_MODE1_IRQSEL_BIT);
|
||||||
/* Initialize queue for start TX */
|
/* Initialize queue for start TX */
|
||||||
INIT_WORK(&s->p[i].tx_work, max310x_wq_proc);
|
INIT_WORK(&s->p[i].tx_work, max310x_wq_proc);
|
||||||
|
/* Initialize queue for changing mode */
|
||||||
|
INIT_WORK(&s->p[i].md_work, max310x_md_proc);
|
||||||
/* Register port */
|
/* Register port */
|
||||||
uart_add_one_port(&s->uart, &s->p[i].port);
|
uart_add_one_port(&s->uart, &s->p[i].port);
|
||||||
/* Go to suspend mode */
|
/* Go to suspend mode */
|
||||||
devtype->power(&s->p[i].port, 0);
|
devtype->power(&s->p[i].port, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_GPIOLIB
|
|
||||||
/* Setup GPIO cotroller */
|
|
||||||
if (s->pdata->gpio_base) {
|
|
||||||
s->gpio.owner = THIS_MODULE;
|
|
||||||
s->gpio.dev = dev;
|
|
||||||
s->gpio.label = dev_name(dev);
|
|
||||||
s->gpio.direction_input = max310x_gpio_direction_input;
|
|
||||||
s->gpio.get = max310x_gpio_get;
|
|
||||||
s->gpio.direction_output= max310x_gpio_direction_output;
|
|
||||||
s->gpio.set = max310x_gpio_set;
|
|
||||||
s->gpio.base = s->pdata->gpio_base;
|
|
||||||
s->gpio.ngpio = devtype->nr * 4;
|
|
||||||
s->gpio.can_sleep = 1;
|
|
||||||
if (!gpiochip_add(&s->gpio))
|
|
||||||
s->gpio_used = 1;
|
|
||||||
} else
|
|
||||||
dev_info(dev, "GPIO support not enabled\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Setup interrupt */
|
/* Setup interrupt */
|
||||||
ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
|
ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
|
||||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
IRQF_ONESHOT | flags, dev_name(dev), s);
|
||||||
dev_name(dev), s);
|
if (!ret)
|
||||||
if (ret) {
|
return 0;
|
||||||
|
|
||||||
dev_err(dev, "Unable to reguest IRQ %i\n", irq);
|
dev_err(dev, "Unable to reguest IRQ %i\n", irq);
|
||||||
|
|
||||||
|
mutex_destroy(&s->mutex);
|
||||||
|
|
||||||
#ifdef CONFIG_GPIOLIB
|
#ifdef CONFIG_GPIOLIB
|
||||||
if (s->gpio_used)
|
|
||||||
WARN_ON(gpiochip_remove(&s->gpio));
|
WARN_ON(gpiochip_remove(&s->gpio));
|
||||||
|
|
||||||
|
out_uart:
|
||||||
#endif
|
#endif
|
||||||
}
|
uart_unregister_driver(&s->uart);
|
||||||
|
|
||||||
|
out_clk:
|
||||||
|
clk_disable_unprepare(s->clk);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_freq:
|
|
||||||
dev_err(dev, "Frequency parameter incorrect\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max310x_remove(struct device *dev)
|
static int max310x_remove(struct device *dev)
|
||||||
|
@ -1244,30 +1266,51 @@ static int max310x_remove(struct device *dev)
|
||||||
struct max310x_port *s = dev_get_drvdata(dev);
|
struct max310x_port *s = dev_get_drvdata(dev);
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_GPIOLIB
|
||||||
|
ret = gpiochip_remove(&s->gpio);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < s->uart.nr; i++) {
|
for (i = 0; i < s->uart.nr; i++) {
|
||||||
cancel_work_sync(&s->p[i].tx_work);
|
cancel_work_sync(&s->p[i].tx_work);
|
||||||
|
cancel_work_sync(&s->p[i].md_work);
|
||||||
uart_remove_one_port(&s->uart, &s->p[i].port);
|
uart_remove_one_port(&s->uart, &s->p[i].port);
|
||||||
s->devtype->power(&s->p[i].port, 0);
|
s->devtype->power(&s->p[i].port, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_destroy(&s->mutex);
|
||||||
uart_unregister_driver(&s->uart);
|
uart_unregister_driver(&s->uart);
|
||||||
|
clk_disable_unprepare(s->clk);
|
||||||
#ifdef CONFIG_GPIOLIB
|
|
||||||
if (s->gpio_used)
|
|
||||||
ret = gpiochip_remove(&s->gpio);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s->pdata->exit)
|
|
||||||
s->pdata->exit();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id __maybe_unused max310x_dt_ids[] = {
|
||||||
|
{ .compatible = "maxim,max3107", .data = &max3107_devtype, },
|
||||||
|
{ .compatible = "maxim,max3108", .data = &max3108_devtype, },
|
||||||
|
{ .compatible = "maxim,max3109", .data = &max3109_devtype, },
|
||||||
|
{ .compatible = "maxim,max14830", .data = &max14830_devtype },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, max310x_dt_ids);
|
||||||
|
|
||||||
|
static struct regmap_config regcfg = {
|
||||||
|
.reg_bits = 8,
|
||||||
|
.val_bits = 8,
|
||||||
|
.write_flag_mask = 0x80,
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
.writeable_reg = max310x_reg_writeable,
|
||||||
|
.volatile_reg = max310x_reg_volatile,
|
||||||
|
.precious_reg = max310x_reg_precious,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SPI_MASTER
|
#ifdef CONFIG_SPI_MASTER
|
||||||
static int max310x_spi_probe(struct spi_device *spi)
|
static int max310x_spi_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct max310x_devtype *devtype =
|
struct max310x_devtype *devtype;
|
||||||
(struct max310x_devtype *)spi_get_device_id(spi)->driver_data;
|
unsigned long flags = 0;
|
||||||
|
struct regmap *regmap;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Setup SPI bus */
|
/* Setup SPI bus */
|
||||||
|
@ -1275,12 +1318,25 @@ static int max310x_spi_probe(struct spi_device *spi)
|
||||||
spi->mode = spi->mode ? : SPI_MODE_0;
|
spi->mode = spi->mode ? : SPI_MODE_0;
|
||||||
spi->max_speed_hz = spi->max_speed_hz ? : 26000000;
|
spi->max_speed_hz = spi->max_speed_hz ? : 26000000;
|
||||||
ret = spi_setup(spi);
|
ret = spi_setup(spi);
|
||||||
if (ret) {
|
if (ret)
|
||||||
dev_err(&spi->dev, "SPI setup failed\n");
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (spi->dev.of_node) {
|
||||||
|
const struct of_device_id *of_id =
|
||||||
|
of_match_device(max310x_dt_ids, &spi->dev);
|
||||||
|
|
||||||
|
devtype = (struct max310x_devtype *)of_id->data;
|
||||||
|
} else {
|
||||||
|
const struct spi_device_id *id_entry = spi_get_device_id(spi);
|
||||||
|
|
||||||
|
devtype = (struct max310x_devtype *)id_entry->driver_data;
|
||||||
|
flags = IRQF_TRIGGER_FALLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return max310x_probe(&spi->dev, 1, devtype, spi->irq);
|
regcfg.max_register = devtype->nr * 0x20 - 1;
|
||||||
|
regmap = devm_regmap_init_spi(spi, ®cfg);
|
||||||
|
|
||||||
|
return max310x_probe(&spi->dev, devtype, regmap, spi->irq, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max310x_spi_remove(struct spi_device *spi)
|
static int max310x_spi_remove(struct spi_device *spi)
|
||||||
|
@ -1288,8 +1344,6 @@ static int max310x_spi_remove(struct spi_device *spi)
|
||||||
return max310x_remove(&spi->dev);
|
return max310x_remove(&spi->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
|
|
||||||
|
|
||||||
static const struct spi_device_id max310x_id_table[] = {
|
static const struct spi_device_id max310x_id_table[] = {
|
||||||
{ "max3107", (kernel_ulong_t)&max3107_devtype, },
|
{ "max3107", (kernel_ulong_t)&max3107_devtype, },
|
||||||
{ "max3108", (kernel_ulong_t)&max3108_devtype, },
|
{ "max3108", (kernel_ulong_t)&max3108_devtype, },
|
||||||
|
@ -1303,6 +1357,7 @@ static struct spi_driver max310x_uart_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = MAX310X_NAME,
|
.name = MAX310X_NAME,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = of_match_ptr(max310x_dt_ids),
|
||||||
.pm = &max310x_pm_ops,
|
.pm = &max310x_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = max310x_spi_probe,
|
.probe = max310x_spi_probe,
|
||||||
|
|
|
@ -39,6 +39,13 @@
|
||||||
|
|
||||||
#include "msm_serial.h"
|
#include "msm_serial.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UARTDM_1P1 = 1,
|
||||||
|
UARTDM_1P2,
|
||||||
|
UARTDM_1P3,
|
||||||
|
UARTDM_1P4,
|
||||||
|
};
|
||||||
|
|
||||||
struct msm_port {
|
struct msm_port {
|
||||||
struct uart_port uart;
|
struct uart_port uart;
|
||||||
char name[16];
|
char name[16];
|
||||||
|
@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct uart_port *port)
|
||||||
|
|
||||||
static void msm_reset(struct uart_port *port)
|
static void msm_reset(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct msm_port *msm_port = UART_TO_MSM(port);
|
||||||
|
|
||||||
/* reset everything */
|
/* reset everything */
|
||||||
msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
|
||||||
msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
|
||||||
|
@ -316,6 +325,10 @@ static void msm_reset(struct uart_port *port)
|
||||||
msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
|
||||||
msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
|
||||||
msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
|
msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
|
||||||
|
|
||||||
|
/* Disable DM modes */
|
||||||
|
if (msm_port->is_uartdm)
|
||||||
|
msm_write(port, 0, UARTDM_DMEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
|
@ -711,6 +724,117 @@ static void msm_power(struct uart_port *port, unsigned int state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
static int msm_poll_init(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct msm_port *msm_port = UART_TO_MSM(port);
|
||||||
|
|
||||||
|
/* Enable single character mode on RX FIFO */
|
||||||
|
if (msm_port->is_uartdm >= UARTDM_1P4)
|
||||||
|
msm_write(port, UARTDM_DMEN_RX_SC_ENABLE, UARTDM_DMEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_poll_get_char_single(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct msm_port *msm_port = UART_TO_MSM(port);
|
||||||
|
unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF;
|
||||||
|
|
||||||
|
if (!(msm_read(port, UART_SR) & UART_SR_RX_READY))
|
||||||
|
return NO_POLL_CHAR;
|
||||||
|
else
|
||||||
|
return msm_read(port, rf_reg) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_poll_get_char_dm_1p3(struct uart_port *port)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
static u32 slop;
|
||||||
|
static int count;
|
||||||
|
unsigned char *sp = (unsigned char *)&slop;
|
||||||
|
|
||||||
|
/* Check if a previous read had more than one char */
|
||||||
|
if (count) {
|
||||||
|
c = sp[sizeof(slop) - count];
|
||||||
|
count--;
|
||||||
|
/* Or if FIFO is empty */
|
||||||
|
} else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) {
|
||||||
|
/*
|
||||||
|
* If RX packing buffer has less than a word, force stale to
|
||||||
|
* push contents into RX FIFO
|
||||||
|
*/
|
||||||
|
count = msm_read(port, UARTDM_RXFS);
|
||||||
|
count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK;
|
||||||
|
if (count) {
|
||||||
|
msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR);
|
||||||
|
slop = msm_read(port, UARTDM_RF);
|
||||||
|
c = sp[0];
|
||||||
|
count--;
|
||||||
|
} else {
|
||||||
|
c = NO_POLL_CHAR;
|
||||||
|
}
|
||||||
|
/* FIFO has a word */
|
||||||
|
} else {
|
||||||
|
slop = msm_read(port, UARTDM_RF);
|
||||||
|
c = sp[0];
|
||||||
|
count = sizeof(slop) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_poll_get_char(struct uart_port *port)
|
||||||
|
{
|
||||||
|
u32 imr;
|
||||||
|
int c;
|
||||||
|
struct msm_port *msm_port = UART_TO_MSM(port);
|
||||||
|
|
||||||
|
/* Disable all interrupts */
|
||||||
|
imr = msm_read(port, UART_IMR);
|
||||||
|
msm_write(port, 0, UART_IMR);
|
||||||
|
|
||||||
|
if (msm_port->is_uartdm == UARTDM_1P3)
|
||||||
|
c = msm_poll_get_char_dm_1p3(port);
|
||||||
|
else
|
||||||
|
c = msm_poll_get_char_single(port);
|
||||||
|
|
||||||
|
/* Enable interrupts */
|
||||||
|
msm_write(port, imr, UART_IMR);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msm_poll_put_char(struct uart_port *port, unsigned char c)
|
||||||
|
{
|
||||||
|
u32 imr;
|
||||||
|
struct msm_port *msm_port = UART_TO_MSM(port);
|
||||||
|
|
||||||
|
/* Disable all interrupts */
|
||||||
|
imr = msm_read(port, UART_IMR);
|
||||||
|
msm_write(port, 0, UART_IMR);
|
||||||
|
|
||||||
|
if (msm_port->is_uartdm)
|
||||||
|
reset_dm_count(port, 1);
|
||||||
|
|
||||||
|
/* Wait until FIFO is empty */
|
||||||
|
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
/* Write a character */
|
||||||
|
msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
|
||||||
|
|
||||||
|
/* Wait until FIFO is empty */
|
||||||
|
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
/* Enable interrupts */
|
||||||
|
msm_write(port, imr, UART_IMR);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct uart_ops msm_uart_pops = {
|
static struct uart_ops msm_uart_pops = {
|
||||||
.tx_empty = msm_tx_empty,
|
.tx_empty = msm_tx_empty,
|
||||||
.set_mctrl = msm_set_mctrl,
|
.set_mctrl = msm_set_mctrl,
|
||||||
|
@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = {
|
||||||
.config_port = msm_config_port,
|
.config_port = msm_config_port,
|
||||||
.verify_port = msm_verify_port,
|
.verify_port = msm_verify_port,
|
||||||
.pm = msm_power,
|
.pm = msm_power,
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
.poll_init = msm_poll_init,
|
||||||
|
.poll_get_char = msm_poll_get_char,
|
||||||
|
.poll_put_char = msm_poll_put_char,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct msm_port msm_uart_ports[] = {
|
static struct msm_port msm_uart_ports[] = {
|
||||||
|
@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_driver = {
|
||||||
static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
|
static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
|
||||||
|
|
||||||
static const struct of_device_id msm_uartdm_table[] = {
|
static const struct of_device_id msm_uartdm_table[] = {
|
||||||
{ .compatible = "qcom,msm-uartdm" },
|
{ .compatible = "qcom,msm-uartdm-v1.1", .data = (void *)UARTDM_1P1 },
|
||||||
|
{ .compatible = "qcom,msm-uartdm-v1.2", .data = (void *)UARTDM_1P2 },
|
||||||
|
{ .compatible = "qcom,msm-uartdm-v1.3", .data = (void *)UARTDM_1P3 },
|
||||||
|
{ .compatible = "qcom,msm-uartdm-v1.4", .data = (void *)UARTDM_1P4 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
|
||||||
struct msm_port *msm_port;
|
struct msm_port *msm_port;
|
||||||
struct resource *resource;
|
struct resource *resource;
|
||||||
struct uart_port *port;
|
struct uart_port *port;
|
||||||
|
const struct of_device_id *id;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
if (pdev->id == -1)
|
if (pdev->id == -1)
|
||||||
|
@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struct platform_device *pdev)
|
||||||
port->dev = &pdev->dev;
|
port->dev = &pdev->dev;
|
||||||
msm_port = UART_TO_MSM(port);
|
msm_port = UART_TO_MSM(port);
|
||||||
|
|
||||||
if (of_match_device(msm_uartdm_table, &pdev->dev))
|
id = of_match_device(msm_uartdm_table, &pdev->dev);
|
||||||
msm_port->is_uartdm = 1;
|
if (id)
|
||||||
|
msm_port->is_uartdm = (unsigned long)id->data;
|
||||||
else
|
else
|
||||||
msm_port->is_uartdm = 0;
|
msm_port->is_uartdm = 0;
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
#define UART_CR_CMD_RESET_RFR (14 << 4)
|
#define UART_CR_CMD_RESET_RFR (14 << 4)
|
||||||
#define UART_CR_CMD_PROTECTION_EN (16 << 4)
|
#define UART_CR_CMD_PROTECTION_EN (16 << 4)
|
||||||
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
|
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
|
||||||
|
#define UART_CR_CMD_FORCE_STALE (4 << 8)
|
||||||
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
|
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
|
||||||
#define UART_CR_TX_DISABLE (1 << 3)
|
#define UART_CR_TX_DISABLE (1 << 3)
|
||||||
#define UART_CR_TX_ENABLE (1 << 2)
|
#define UART_CR_TX_ENABLE (1 << 2)
|
||||||
|
@ -113,6 +114,14 @@
|
||||||
#define GSBI_PROTOCOL_UART 0x40
|
#define GSBI_PROTOCOL_UART 0x40
|
||||||
#define GSBI_PROTOCOL_IDLE 0x0
|
#define GSBI_PROTOCOL_IDLE 0x0
|
||||||
|
|
||||||
|
#define UARTDM_RXFS 0x50
|
||||||
|
#define UARTDM_RXFS_BUF_SHIFT 0x7
|
||||||
|
#define UARTDM_RXFS_BUF_MASK 0x7
|
||||||
|
|
||||||
|
#define UARTDM_DMEN 0x3C
|
||||||
|
#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
|
||||||
|
#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
|
||||||
|
|
||||||
#define UARTDM_DMRX 0x34
|
#define UARTDM_DMRX 0x34
|
||||||
#define UARTDM_NCF_TX 0x40
|
#define UARTDM_NCF_TX 0x40
|
||||||
#define UARTDM_RX_TOTAL_SNAP 0x38
|
#define UARTDM_RX_TOTAL_SNAP 0x38
|
||||||
|
|
|
@ -342,7 +342,14 @@ static void serial_omap_stop_tx(struct uart_port *port)
|
||||||
|
|
||||||
if ((up->rs485.flags & SER_RS485_ENABLED) &&
|
if ((up->rs485.flags & SER_RS485_ENABLED) &&
|
||||||
!(up->rs485.flags & SER_RS485_RX_DURING_TX)) {
|
!(up->rs485.flags & SER_RS485_RX_DURING_TX)) {
|
||||||
up->ier = UART_IER_RLSI | UART_IER_RDI;
|
/*
|
||||||
|
* Empty the RX FIFO, we are not interested in anything
|
||||||
|
* received during the half-duplex transmission.
|
||||||
|
*/
|
||||||
|
serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_RCVR);
|
||||||
|
/* Re-enable RX interrupts */
|
||||||
|
up->ier |= UART_IER_RLSI | UART_IER_RDI;
|
||||||
|
up->port.read_status_mask |= UART_LSR_DR;
|
||||||
serial_out(up, UART_IER, up->ier);
|
serial_out(up, UART_IER, up->ier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,7 +362,7 @@ static void serial_omap_stop_rx(struct uart_port *port)
|
||||||
struct uart_omap_port *up = to_uart_omap_port(port);
|
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||||
|
|
||||||
pm_runtime_get_sync(up->dev);
|
pm_runtime_get_sync(up->dev);
|
||||||
up->ier &= ~UART_IER_RLSI;
|
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
|
||||||
up->port.read_status_mask &= ~UART_LSR_DR;
|
up->port.read_status_mask &= ~UART_LSR_DR;
|
||||||
serial_out(up, UART_IER, up->ier);
|
serial_out(up, UART_IER, up->ier);
|
||||||
pm_runtime_mark_last_busy(up->dev);
|
pm_runtime_mark_last_busy(up->dev);
|
||||||
|
|
|
@ -1762,7 +1762,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
|
||||||
int fifosize;
|
int fifosize;
|
||||||
int port_type;
|
int port_type;
|
||||||
struct pch_uart_driver_data *board;
|
struct pch_uart_driver_data *board;
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
char name[32]; /* for debugfs file name */
|
char name[32]; /* for debugfs file name */
|
||||||
|
#endif
|
||||||
|
|
||||||
board = &drv_dat[id->driver_data];
|
board = &drv_dat[id->driver_data];
|
||||||
port_type = board->port_type;
|
port_type = board->port_type;
|
||||||
|
|
|
@ -1282,6 +1282,14 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto probe_err;
|
goto probe_err;
|
||||||
|
|
||||||
|
if (!s3c24xx_uart_drv.state) {
|
||||||
|
ret = uart_register_driver(&s3c24xx_uart_drv);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("Failed to register Samsung UART driver\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dbg("%s: adding port\n", __func__);
|
dbg("%s: adding port\n", __func__);
|
||||||
uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
|
uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
|
||||||
platform_set_drvdata(pdev, &ourport->port);
|
platform_set_drvdata(pdev, &ourport->port);
|
||||||
|
@ -1321,6 +1329,8 @@ static int s3c24xx_serial_remove(struct platform_device *dev)
|
||||||
uart_remove_one_port(&s3c24xx_uart_drv, port);
|
uart_remove_one_port(&s3c24xx_uart_drv, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uart_unregister_driver(&s3c24xx_uart_drv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1820,35 +1830,7 @@ static struct platform_driver samsung_serial_driver = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* module initialisation code */
|
module_platform_driver(samsung_serial_driver);
|
||||||
|
|
||||||
static int __init s3c24xx_serial_modinit(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = uart_register_driver(&s3c24xx_uart_drv);
|
|
||||||
if (ret < 0) {
|
|
||||||
pr_err("Failed to register Samsung UART driver\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = platform_driver_register(&samsung_serial_driver);
|
|
||||||
if (ret < 0) {
|
|
||||||
pr_err("Failed to register platform driver\n");
|
|
||||||
uart_unregister_driver(&s3c24xx_uart_drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit s3c24xx_serial_modexit(void)
|
|
||||||
{
|
|
||||||
platform_driver_unregister(&samsung_serial_driver);
|
|
||||||
uart_unregister_driver(&s3c24xx_uart_drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(s3c24xx_serial_modinit);
|
|
||||||
module_exit(s3c24xx_serial_modexit);
|
|
||||||
|
|
||||||
MODULE_ALIAS("platform:samsung-uart");
|
MODULE_ALIAS("platform:samsung-uart");
|
||||||
MODULE_DESCRIPTION("Samsung SoC Serial port driver");
|
MODULE_DESCRIPTION("Samsung SoC Serial port driver");
|
||||||
|
|
|
@ -1319,9 +1319,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
||||||
uport = state->uart_port;
|
uport = state->uart_port;
|
||||||
port = &state->port;
|
port = &state->port;
|
||||||
|
|
||||||
pr_debug("uart_close(%d) called\n", uport->line);
|
pr_debug("uart_close(%d) called\n", uport ? uport->line : -1);
|
||||||
|
|
||||||
if (tty_port_close_start(port, tty, filp) == 0)
|
if (!port->count || tty_port_close_start(port, tty, filp) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1762,7 +1762,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* uart_parse_options - Parse serial port baud/parity/bits/flow contro.
|
* uart_parse_options - Parse serial port baud/parity/bits/flow control.
|
||||||
* @options: pointer to option string
|
* @options: pointer to option string
|
||||||
* @baud: pointer to an 'int' variable for the baud rate.
|
* @baud: pointer to an 'int' variable for the baud rate.
|
||||||
* @parity: pointer to an 'int' variable for the parity.
|
* @parity: pointer to an 'int' variable for the parity.
|
||||||
|
@ -2609,7 +2609,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register the port whether it's detected or not. This allows
|
* Register the port whether it's detected or not. This allows
|
||||||
* setserial to be used to alter this ports parameters.
|
* setserial to be used to alter this port's parameters.
|
||||||
*/
|
*/
|
||||||
tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
|
tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
|
||||||
uport->line, uport->dev, port, tty_dev_attr_groups);
|
uport->line, uport->dev, port, tty_dev_attr_groups);
|
||||||
|
@ -2645,6 +2645,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||||
{
|
{
|
||||||
struct uart_state *state = drv->state + uport->line;
|
struct uart_state *state = drv->state + uport->line;
|
||||||
struct tty_port *port = &state->port;
|
struct tty_port *port = &state->port;
|
||||||
|
struct tty_struct *tty;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
BUG_ON(in_interrupt());
|
BUG_ON(in_interrupt());
|
||||||
|
@ -2673,8 +2674,17 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||||
*/
|
*/
|
||||||
tty_unregister_device(drv->tty_driver, uport->line);
|
tty_unregister_device(drv->tty_driver, uport->line);
|
||||||
|
|
||||||
if (port->tty)
|
tty = tty_port_tty_get(port);
|
||||||
|
if (tty) {
|
||||||
tty_vhangup(port->tty);
|
tty_vhangup(port->tty);
|
||||||
|
tty_kref_put(tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the port is used as a console, unregister it
|
||||||
|
*/
|
||||||
|
if (uart_console(uport))
|
||||||
|
unregister_console(uport->cons);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free the port IO and memory resources, if any.
|
* Free the port IO and memory resources, if any.
|
||||||
|
|
|
@ -428,7 +428,7 @@ static int sci_probe_regmap(struct plat_sci_port *cfg)
|
||||||
cfg->regtype = SCIx_HSCIF_REGTYPE;
|
cfg->regtype = SCIx_HSCIF_REGTYPE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "Can't probe register map for given port\n");
|
pr_err("Can't probe register map for given port\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,7 +788,7 @@ static int sci_handle_errors(struct uart_port *port)
|
||||||
if (tty_insert_flip_char(tport, 0, TTY_OVERRUN))
|
if (tty_insert_flip_char(tport, 0, TTY_OVERRUN))
|
||||||
copied++;
|
copied++;
|
||||||
|
|
||||||
dev_notice(port->dev, "overrun error");
|
dev_notice(port->dev, "overrun error\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & SCxSR_FER(port)) {
|
if (status & SCxSR_FER(port)) {
|
||||||
|
@ -830,7 +830,7 @@ static int sci_handle_errors(struct uart_port *port)
|
||||||
if (tty_insert_flip_char(tport, 0, TTY_PARITY))
|
if (tty_insert_flip_char(tport, 0, TTY_PARITY))
|
||||||
copied++;
|
copied++;
|
||||||
|
|
||||||
dev_notice(port->dev, "parity error");
|
dev_notice(port->dev, "parity error\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copied)
|
if (copied)
|
||||||
|
@ -911,7 +911,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
|
||||||
/* Disable future Rx interrupts */
|
/* Disable future Rx interrupts */
|
||||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||||
disable_irq_nosync(irq);
|
disable_irq_nosync(irq);
|
||||||
scr |= 0x4000;
|
scr |= SCSCR_RDRQE;
|
||||||
} else {
|
} else {
|
||||||
scr &= ~SCSCR_RIE;
|
scr &= ~SCSCR_RIE;
|
||||||
}
|
}
|
||||||
|
@ -1199,7 +1199,9 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
*/
|
*/
|
||||||
reg = sci_getreg(port, SCFCR);
|
reg = sci_getreg(port, SCFCR);
|
||||||
if (reg->size)
|
if (reg->size)
|
||||||
serial_port_out(port, SCFCR, serial_port_in(port, SCFCR) | 1);
|
serial_port_out(port, SCFCR,
|
||||||
|
serial_port_in(port, SCFCR) |
|
||||||
|
SCFCR_LOOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,7 +1291,8 @@ static void sci_dma_rx_complete(void *arg)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx);
|
dev_dbg(port->dev, "%s(%d) active #%d\n",
|
||||||
|
__func__, port->line, s->active_rx);
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
|
@ -1365,8 +1368,8 @@ static void sci_submit_rx(struct sci_port *s)
|
||||||
sci_rx_dma_release(s, true);
|
sci_rx_dma_release(s, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__,
|
dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n",
|
||||||
s->cookie_rx[i], i);
|
__func__, s->cookie_rx[i], i);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->active_rx = s->cookie_rx[0];
|
s->active_rx = s->cookie_rx[0];
|
||||||
|
@ -1425,8 +1428,8 @@ static void work_fn_rx(struct work_struct *work)
|
||||||
|
|
||||||
s->active_rx = s->cookie_rx[!new];
|
s->active_rx = s->cookie_rx[!new];
|
||||||
|
|
||||||
dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__,
|
dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n",
|
||||||
s->cookie_rx[new], new, s->active_rx);
|
__func__, s->cookie_rx[new], new, s->active_rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void work_fn_tx(struct work_struct *work)
|
static void work_fn_tx(struct work_struct *work)
|
||||||
|
@ -1479,8 +1482,8 @@ static void work_fn_tx(struct work_struct *work)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", __func__,
|
dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
|
||||||
xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
|
__func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
|
||||||
|
|
||||||
dma_async_issue_pending(chan);
|
dma_async_issue_pending(chan);
|
||||||
}
|
}
|
||||||
|
@ -1495,9 +1498,9 @@ static void sci_start_tx(struct uart_port *port)
|
||||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||||
u16 new, scr = serial_port_in(port, SCSCR);
|
u16 new, scr = serial_port_in(port, SCSCR);
|
||||||
if (s->chan_tx)
|
if (s->chan_tx)
|
||||||
new = scr | 0x8000;
|
new = scr | SCSCR_TDRQE;
|
||||||
else
|
else
|
||||||
new = scr & ~0x8000;
|
new = scr & ~SCSCR_TDRQE;
|
||||||
if (new != scr)
|
if (new != scr)
|
||||||
serial_port_out(port, SCSCR, new);
|
serial_port_out(port, SCSCR, new);
|
||||||
}
|
}
|
||||||
|
@ -1524,7 +1527,7 @@ static void sci_stop_tx(struct uart_port *port)
|
||||||
ctrl = serial_port_in(port, SCSCR);
|
ctrl = serial_port_in(port, SCSCR);
|
||||||
|
|
||||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||||
ctrl &= ~0x8000;
|
ctrl &= ~SCSCR_TDRQE;
|
||||||
|
|
||||||
ctrl &= ~SCSCR_TIE;
|
ctrl &= ~SCSCR_TIE;
|
||||||
|
|
||||||
|
@ -1538,7 +1541,7 @@ static void sci_start_rx(struct uart_port *port)
|
||||||
ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
|
ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
|
||||||
|
|
||||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||||
ctrl &= ~0x4000;
|
ctrl &= ~SCSCR_RDRQE;
|
||||||
|
|
||||||
serial_port_out(port, SCSCR, ctrl);
|
serial_port_out(port, SCSCR, ctrl);
|
||||||
}
|
}
|
||||||
|
@ -1550,7 +1553,7 @@ static void sci_stop_rx(struct uart_port *port)
|
||||||
ctrl = serial_port_in(port, SCSCR);
|
ctrl = serial_port_in(port, SCSCR);
|
||||||
|
|
||||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||||
ctrl &= ~0x4000;
|
ctrl &= ~SCSCR_RDRQE;
|
||||||
|
|
||||||
ctrl &= ~port_rx_irq_mask(port);
|
ctrl &= ~port_rx_irq_mask(port);
|
||||||
|
|
||||||
|
@ -1599,8 +1602,8 @@ static bool filter(struct dma_chan *chan, void *slave)
|
||||||
{
|
{
|
||||||
struct sh_dmae_slave *param = slave;
|
struct sh_dmae_slave *param = slave;
|
||||||
|
|
||||||
dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__,
|
dev_dbg(chan->device->dev, "%s: slave ID %d\n",
|
||||||
param->shdma_slave.slave_id);
|
__func__, param->shdma_slave.slave_id);
|
||||||
|
|
||||||
chan->private = ¶m->shdma_slave;
|
chan->private = ¶m->shdma_slave;
|
||||||
return true;
|
return true;
|
||||||
|
@ -1613,7 +1616,7 @@ static void rx_timer_fn(unsigned long arg)
|
||||||
u16 scr = serial_port_in(port, SCSCR);
|
u16 scr = serial_port_in(port, SCSCR);
|
||||||
|
|
||||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||||
scr &= ~0x4000;
|
scr &= ~SCSCR_RDRQE;
|
||||||
enable_irq(s->irqs[SCIx_RXI_IRQ]);
|
enable_irq(s->irqs[SCIx_RXI_IRQ]);
|
||||||
}
|
}
|
||||||
serial_port_out(port, SCSCR, scr | SCSCR_RIE);
|
serial_port_out(port, SCSCR, scr | SCSCR_RIE);
|
||||||
|
@ -1629,8 +1632,7 @@ static void sci_request_dma(struct uart_port *port)
|
||||||
dma_cap_mask_t mask;
|
dma_cap_mask_t mask;
|
||||||
int nent;
|
int nent;
|
||||||
|
|
||||||
dev_dbg(port->dev, "%s: port %d\n", __func__,
|
dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
|
||||||
port->line);
|
|
||||||
|
|
||||||
if (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0)
|
if (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0)
|
||||||
return;
|
return;
|
||||||
|
@ -1658,7 +1660,8 @@ static void sci_request_dma(struct uart_port *port)
|
||||||
if (!nent)
|
if (!nent)
|
||||||
sci_tx_dma_release(s, false);
|
sci_tx_dma_release(s, false);
|
||||||
else
|
else
|
||||||
dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__,
|
dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n",
|
||||||
|
__func__,
|
||||||
sg_dma_len(&s->sg_tx), port->state->xmit.buf,
|
sg_dma_len(&s->sg_tx), port->state->xmit.buf,
|
||||||
&sg_dma_address(&s->sg_tx));
|
&sg_dma_address(&s->sg_tx));
|
||||||
|
|
||||||
|
@ -1870,13 +1873,13 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
smr_val = serial_port_in(port, SCSMR) & 3;
|
smr_val = serial_port_in(port, SCSMR) & 3;
|
||||||
|
|
||||||
if ((termios->c_cflag & CSIZE) == CS7)
|
if ((termios->c_cflag & CSIZE) == CS7)
|
||||||
smr_val |= 0x40;
|
smr_val |= SCSMR_CHR;
|
||||||
if (termios->c_cflag & PARENB)
|
if (termios->c_cflag & PARENB)
|
||||||
smr_val |= 0x20;
|
smr_val |= SCSMR_PE;
|
||||||
if (termios->c_cflag & PARODD)
|
if (termios->c_cflag & PARODD)
|
||||||
smr_val |= 0x30;
|
smr_val |= SCSMR_PE | SCSMR_ODD;
|
||||||
if (termios->c_cflag & CSTOPB)
|
if (termios->c_cflag & CSTOPB)
|
||||||
smr_val |= 0x08;
|
smr_val |= SCSMR_STOP;
|
||||||
|
|
||||||
uart_update_timeout(port, termios->c_cflag, baud);
|
uart_update_timeout(port, termios->c_cflag, baud);
|
||||||
|
|
||||||
|
@ -1884,7 +1887,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
__func__, smr_val, cks, t, s->cfg->scscr);
|
__func__, smr_val, cks, t, s->cfg->scscr);
|
||||||
|
|
||||||
if (t >= 0) {
|
if (t >= 0) {
|
||||||
serial_port_out(port, SCSMR, (smr_val & ~3) | cks);
|
serial_port_out(port, SCSMR, (smr_val & ~SCSMR_CKS) | cks);
|
||||||
serial_port_out(port, SCBRR, t);
|
serial_port_out(port, SCBRR, t);
|
||||||
reg = sci_getreg(port, HSSRR);
|
reg = sci_getreg(port, HSSRR);
|
||||||
if (reg->size)
|
if (reg->size)
|
||||||
|
@ -1932,8 +1935,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
if (s->chan_rx) {
|
if (s->chan_rx) {
|
||||||
s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
|
s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
|
||||||
port->fifosize / 2;
|
port->fifosize / 2;
|
||||||
dev_dbg(port->dev,
|
dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
|
||||||
"DMA Rx t-out %ums, tty t-out %u jiffies\n",
|
|
||||||
s->rx_timeout * 1000 / HZ, port->timeout);
|
s->rx_timeout * 1000 / HZ, port->timeout);
|
||||||
if (s->rx_timeout < msecs_to_jiffies(20))
|
if (s->rx_timeout < msecs_to_jiffies(20))
|
||||||
s->rx_timeout = msecs_to_jiffies(20);
|
s->rx_timeout = msecs_to_jiffies(20);
|
||||||
|
@ -1952,7 +1954,7 @@ static void sci_pm(struct uart_port *port, unsigned int state,
|
||||||
struct sci_port *sci_port = to_sci_port(port);
|
struct sci_port *sci_port = to_sci_port(port);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 3:
|
case UART_PM_STATE_OFF:
|
||||||
sci_port_disable(sci_port);
|
sci_port_disable(sci_port);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2017,7 +2019,7 @@ static int sci_remap_port(struct uart_port *port)
|
||||||
* need to do any remapping, just cast the cookie
|
* need to do any remapping, just cast the cookie
|
||||||
* directly.
|
* directly.
|
||||||
*/
|
*/
|
||||||
port->membase = (void __iomem *)port->mapbase;
|
port->membase = (void __iomem *)(uintptr_t)port->mapbase;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2388,8 +2390,7 @@ static inline int sci_probe_earlyprintk(struct platform_device *pdev)
|
||||||
|
|
||||||
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
|
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
|
||||||
|
|
||||||
static char banner[] __initdata =
|
static const char banner[] __initconst = "SuperH (H)SCI(F) driver initialized";
|
||||||
KERN_INFO "SuperH (H)SCI(F) driver initialized\n";
|
|
||||||
|
|
||||||
static struct uart_driver sci_uart_driver = {
|
static struct uart_driver sci_uart_driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
@ -2423,25 +2424,25 @@ struct sci_port_info {
|
||||||
static const struct of_device_id of_sci_match[] = {
|
static const struct of_device_id of_sci_match[] = {
|
||||||
{
|
{
|
||||||
.compatible = "renesas,scif",
|
.compatible = "renesas,scif",
|
||||||
.data = (void *)&(const struct sci_port_info) {
|
.data = &(const struct sci_port_info) {
|
||||||
.type = PORT_SCIF,
|
.type = PORT_SCIF,
|
||||||
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
.compatible = "renesas,scifa",
|
.compatible = "renesas,scifa",
|
||||||
.data = (void *)&(const struct sci_port_info) {
|
.data = &(const struct sci_port_info) {
|
||||||
.type = PORT_SCIFA,
|
.type = PORT_SCIFA,
|
||||||
.regtype = SCIx_SCIFA_REGTYPE,
|
.regtype = SCIx_SCIFA_REGTYPE,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
.compatible = "renesas,scifb",
|
.compatible = "renesas,scifb",
|
||||||
.data = (void *)&(const struct sci_port_info) {
|
.data = &(const struct sci_port_info) {
|
||||||
.type = PORT_SCIFB,
|
.type = PORT_SCIFB,
|
||||||
.regtype = SCIx_SCIFB_REGTYPE,
|
.regtype = SCIx_SCIFB_REGTYPE,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
.compatible = "renesas,hscif",
|
.compatible = "renesas,hscif",
|
||||||
.data = (void *)&(const struct sci_port_info) {
|
.data = &(const struct sci_port_info) {
|
||||||
.type = PORT_HSCIF,
|
.type = PORT_HSCIF,
|
||||||
.regtype = SCIx_HSCIF_REGTYPE,
|
.regtype = SCIx_HSCIF_REGTYPE,
|
||||||
},
|
},
|
||||||
|
@ -2501,11 +2502,9 @@ static int sci_probe_single(struct platform_device *dev,
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if (unlikely(index >= SCI_NPORTS)) {
|
if (unlikely(index >= SCI_NPORTS)) {
|
||||||
dev_notice(&dev->dev, "Attempting to register port "
|
dev_notice(&dev->dev, "Attempting to register port %d when only %d are available\n",
|
||||||
"%d when only %d are available.\n",
|
|
||||||
index+1, SCI_NPORTS);
|
index+1, SCI_NPORTS);
|
||||||
dev_notice(&dev->dev, "Consider bumping "
|
dev_notice(&dev->dev, "Consider bumping CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
|
||||||
"CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2563,6 +2562,7 @@ static int sci_probe(struct platform_device *dev)
|
||||||
ret = cpufreq_register_notifier(&sp->freq_transition,
|
ret = cpufreq_register_notifier(&sp->freq_transition,
|
||||||
CPUFREQ_TRANSITION_NOTIFIER);
|
CPUFREQ_TRANSITION_NOTIFIER);
|
||||||
if (unlikely(ret < 0)) {
|
if (unlikely(ret < 0)) {
|
||||||
|
uart_remove_one_port(&sci_uart_driver, &sp->port);
|
||||||
sci_cleanup_single(sp);
|
sci_cleanup_single(sp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2614,7 +2614,7 @@ static int __init sci_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
printk(banner);
|
pr_info("%s\n", banner);
|
||||||
|
|
||||||
ret = uart_register_driver(&sci_uart_driver);
|
ret = uart_register_driver(&sci_uart_driver);
|
||||||
if (likely(ret == 0)) {
|
if (likely(ret == 0)) {
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include <linux/dmaengine.h>
|
#include <linux/dmaengine.h>
|
||||||
#include <linux/dma-direction.h>
|
#include <linux/dma-direction.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/sirfsoc_dma.h>
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/mach/irq.h>
|
#include <asm/mach/irq.h>
|
||||||
|
|
||||||
|
@ -173,7 +172,7 @@ static void sirfsoc_uart_stop_tx(struct uart_port *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;
|
||||||
|
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) {
|
if (sirfport->tx_dma_chan) {
|
||||||
if (sirfport->tx_dma_state == TX_DMA_RUNNING) {
|
if (sirfport->tx_dma_state == TX_DMA_RUNNING) {
|
||||||
dmaengine_pause(sirfport->tx_dma_chan);
|
dmaengine_pause(sirfport->tx_dma_chan);
|
||||||
sirfport->tx_dma_state = TX_DMA_PAUSE;
|
sirfport->tx_dma_state = TX_DMA_PAUSE;
|
||||||
|
@ -288,7 +287,7 @@ static void sirfsoc_uart_start_tx(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;
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no))
|
if (sirfport->tx_dma_chan)
|
||||||
sirfsoc_uart_tx_with_dma(sirfport);
|
sirfsoc_uart_tx_with_dma(sirfport);
|
||||||
else {
|
else {
|
||||||
sirfsoc_uart_pio_tx_chars(sirfport, 1);
|
sirfsoc_uart_pio_tx_chars(sirfport, 1);
|
||||||
|
@ -310,7 +309,7 @@ static void sirfsoc_uart_stop_rx(struct uart_port *port)
|
||||||
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
|
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
|
||||||
|
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
|
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) {
|
if (sirfport->rx_dma_chan) {
|
||||||
if (!sirfport->is_marco)
|
if (!sirfport->is_marco)
|
||||||
wr_regl(port, ureg->sirfsoc_int_en_reg,
|
wr_regl(port, ureg->sirfsoc_int_en_reg,
|
||||||
rd_regl(port, ureg->sirfsoc_int_en_reg) &
|
rd_regl(port, ureg->sirfsoc_int_en_reg) &
|
||||||
|
@ -675,7 +674,7 @@ recv_char:
|
||||||
uart_handle_cts_change(port, cts_status);
|
uart_handle_cts_change(port, cts_status);
|
||||||
wake_up_interruptible(&state->port.delta_msr_wait);
|
wake_up_interruptible(&state->port.delta_msr_wait);
|
||||||
}
|
}
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) {
|
if (sirfport->rx_dma_chan) {
|
||||||
if (intr_status & uint_st->sirfsoc_rx_timeout)
|
if (intr_status & uint_st->sirfsoc_rx_timeout)
|
||||||
sirfsoc_uart_handle_rx_tmo(sirfport);
|
sirfsoc_uart_handle_rx_tmo(sirfport);
|
||||||
if (intr_status & uint_st->sirfsoc_rx_done)
|
if (intr_status & uint_st->sirfsoc_rx_done)
|
||||||
|
@ -686,7 +685,7 @@ recv_char:
|
||||||
SIRFSOC_UART_IO_RX_MAX_CNT);
|
SIRFSOC_UART_IO_RX_MAX_CNT);
|
||||||
}
|
}
|
||||||
if (intr_status & uint_st->sirfsoc_txfifo_empty) {
|
if (intr_status & uint_st->sirfsoc_txfifo_empty) {
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no))
|
if (sirfport->tx_dma_chan)
|
||||||
sirfsoc_uart_tx_with_dma(sirfport);
|
sirfsoc_uart_tx_with_dma(sirfport);
|
||||||
else {
|
else {
|
||||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||||
|
@ -778,7 +777,7 @@ static void sirfsoc_uart_start_rx(struct uart_port *port)
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
|
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, 0);
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
|
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no))
|
if (sirfport->rx_dma_chan)
|
||||||
sirfsoc_uart_start_next_rx_dma(port);
|
sirfsoc_uart_start_next_rx_dma(port);
|
||||||
else {
|
else {
|
||||||
if (!sirfport->is_marco)
|
if (!sirfport->is_marco)
|
||||||
|
@ -1014,11 +1013,11 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
|
||||||
(sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) <<
|
(sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) <<
|
||||||
SIRFSOC_USP_ASYNC_DIV2_OFFSET);
|
SIRFSOC_USP_ASYNC_DIV2_OFFSET);
|
||||||
}
|
}
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no))
|
if (sirfport->tx_dma_chan)
|
||||||
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE);
|
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE);
|
||||||
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 (IS_DMA_CHAN_VALID(sirfport->rx_dma_no))
|
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, SIRFUART_DMA_MODE);
|
||||||
else
|
else
|
||||||
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
|
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
|
||||||
|
@ -1049,93 +1048,6 @@ static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state,
|
||||||
clk_disable_unprepare(sirfport->clk);
|
clk_disable_unprepare(sirfport->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int sirfsoc_uart_init_tx_dma(struct uart_port *port)
|
|
||||||
{
|
|
||||||
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
|
||||||
dma_cap_mask_t dma_mask;
|
|
||||||
struct dma_slave_config tx_slv_cfg = {
|
|
||||||
.dst_maxburst = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
dma_cap_zero(dma_mask);
|
|
||||||
dma_cap_set(DMA_SLAVE, dma_mask);
|
|
||||||
sirfport->tx_dma_chan = dma_request_channel(dma_mask,
|
|
||||||
(dma_filter_fn)sirfsoc_dma_filter_id,
|
|
||||||
(void *)sirfport->tx_dma_no);
|
|
||||||
if (!sirfport->tx_dma_chan) {
|
|
||||||
dev_err(port->dev, "Uart Request Dma Channel Fail %d\n",
|
|
||||||
sirfport->tx_dma_no);
|
|
||||||
return -EPROBE_DEFER;
|
|
||||||
}
|
|
||||||
dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int sirfsoc_uart_init_rx_dma(struct uart_port *port)
|
|
||||||
{
|
|
||||||
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
|
|
||||||
dma_cap_mask_t dma_mask;
|
|
||||||
int ret;
|
|
||||||
int i, j;
|
|
||||||
struct dma_slave_config slv_cfg = {
|
|
||||||
.src_maxburst = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
dma_cap_zero(dma_mask);
|
|
||||||
dma_cap_set(DMA_SLAVE, dma_mask);
|
|
||||||
sirfport->rx_dma_chan = dma_request_channel(dma_mask,
|
|
||||||
(dma_filter_fn)sirfsoc_dma_filter_id,
|
|
||||||
(void *)sirfport->rx_dma_no);
|
|
||||||
if (!sirfport->rx_dma_chan) {
|
|
||||||
dev_err(port->dev, "Uart Request Dma Channel Fail %d\n",
|
|
||||||
sirfport->rx_dma_no);
|
|
||||||
ret = -EPROBE_DEFER;
|
|
||||||
goto request_err;
|
|
||||||
}
|
|
||||||
for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++) {
|
|
||||||
sirfport->rx_dma_items[i].xmit.buf =
|
|
||||||
dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
|
|
||||||
&sirfport->rx_dma_items[i].dma_addr, GFP_KERNEL);
|
|
||||||
if (!sirfport->rx_dma_items[i].xmit.buf) {
|
|
||||||
dev_err(port->dev, "Uart alloc bufa failed\n");
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto alloc_coherent_err;
|
|
||||||
}
|
|
||||||
sirfport->rx_dma_items[i].xmit.head =
|
|
||||||
sirfport->rx_dma_items[i].xmit.tail = 0;
|
|
||||||
}
|
|
||||||
dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
alloc_coherent_err:
|
|
||||||
for (j = 0; j < i; j++)
|
|
||||||
dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
|
|
||||||
sirfport->rx_dma_items[j].xmit.buf,
|
|
||||||
sirfport->rx_dma_items[j].dma_addr);
|
|
||||||
dma_release_channel(sirfport->rx_dma_chan);
|
|
||||||
request_err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sirfsoc_uart_uninit_tx_dma(struct sirfsoc_uart_port *sirfport)
|
|
||||||
{
|
|
||||||
dmaengine_terminate_all(sirfport->tx_dma_chan);
|
|
||||||
dma_release_channel(sirfport->tx_dma_chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sirfsoc_uart_uninit_rx_dma(struct sirfsoc_uart_port *sirfport)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
struct uart_port *port = &sirfport->port;
|
|
||||||
dmaengine_terminate_all(sirfport->rx_dma_chan);
|
|
||||||
dma_release_channel(sirfport->rx_dma_chan);
|
|
||||||
for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++)
|
|
||||||
dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
|
|
||||||
sirfport->rx_dma_items[i].xmit.buf,
|
|
||||||
sirfport->rx_dma_items[i].dma_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sirfsoc_uart_startup(struct uart_port *port)
|
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);
|
||||||
|
@ -1174,18 +1086,12 @@ static int sirfsoc_uart_startup(struct uart_port *port)
|
||||||
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
|
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
|
||||||
wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port));
|
wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(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 (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) {
|
|
||||||
ret = sirfsoc_uart_init_rx_dma(port);
|
|
||||||
if (ret)
|
|
||||||
goto init_rx_err;
|
|
||||||
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, 0x4) |
|
||||||
SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
|
SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
|
||||||
SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
|
SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
|
||||||
}
|
if (sirfport->tx_dma_chan) {
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) {
|
|
||||||
sirfsoc_uart_init_tx_dma(port);
|
|
||||||
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,
|
||||||
SIRFUART_TX_FIFO_CHK_SC(port->line, 0x1b) |
|
SIRFUART_TX_FIFO_CHK_SC(port->line, 0x1b) |
|
||||||
|
@ -1232,13 +1138,9 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
|
||||||
gpio_set_value(sirfport->rts_gpio, 1);
|
gpio_set_value(sirfport->rts_gpio, 1);
|
||||||
free_irq(gpio_to_irq(sirfport->cts_gpio), sirfport);
|
free_irq(gpio_to_irq(sirfport->cts_gpio), sirfport);
|
||||||
}
|
}
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no))
|
if (sirfport->tx_dma_chan)
|
||||||
sirfsoc_uart_uninit_rx_dma(sirfport);
|
|
||||||
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) {
|
|
||||||
sirfsoc_uart_uninit_tx_dma(sirfport);
|
|
||||||
sirfport->tx_dma_state = TX_DMA_IDLE;
|
sirfport->tx_dma_state = TX_DMA_IDLE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static const char *sirfsoc_uart_type(struct uart_port *port)
|
static const char *sirfsoc_uart_type(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
@ -1313,8 +1215,8 @@ sirfsoc_uart_console_setup(struct console *co, char *options)
|
||||||
port->cons = co;
|
port->cons = co;
|
||||||
|
|
||||||
/* default console tx/rx transfer using io mode */
|
/* default console tx/rx transfer using io mode */
|
||||||
sirfport->rx_dma_no = UNVALID_DMA_CHAN;
|
sirfport->rx_dma_chan = NULL;
|
||||||
sirfport->tx_dma_no = UNVALID_DMA_CHAN;
|
sirfport->tx_dma_chan = NULL;
|
||||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1382,6 +1284,13 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
|
||||||
struct uart_port *port;
|
struct uart_port *port;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int ret;
|
int ret;
|
||||||
|
int i, j;
|
||||||
|
struct dma_slave_config slv_cfg = {
|
||||||
|
.src_maxburst = 2,
|
||||||
|
};
|
||||||
|
struct dma_slave_config tx_slv_cfg = {
|
||||||
|
.dst_maxburst = 2,
|
||||||
|
};
|
||||||
const struct of_device_id *match;
|
const struct of_device_id *match;
|
||||||
|
|
||||||
match = of_match_node(sirfsoc_uart_ids, pdev->dev.of_node);
|
match = of_match_node(sirfsoc_uart_ids, pdev->dev.of_node);
|
||||||
|
@ -1402,27 +1311,10 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
sirfport->hw_flow_ctrl = of_property_read_bool(pdev->dev.of_node,
|
sirfport->hw_flow_ctrl = of_property_read_bool(pdev->dev.of_node,
|
||||||
"sirf,uart-has-rtscts");
|
"sirf,uart-has-rtscts");
|
||||||
if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart")) {
|
if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart"))
|
||||||
sirfport->uart_reg->uart_type = SIRF_REAL_UART;
|
sirfport->uart_reg->uart_type = SIRF_REAL_UART;
|
||||||
if (of_property_read_u32(pdev->dev.of_node,
|
|
||||||
"sirf,uart-dma-rx-channel",
|
|
||||||
&sirfport->rx_dma_no))
|
|
||||||
sirfport->rx_dma_no = UNVALID_DMA_CHAN;
|
|
||||||
if (of_property_read_u32(pdev->dev.of_node,
|
|
||||||
"sirf,uart-dma-tx-channel",
|
|
||||||
&sirfport->tx_dma_no))
|
|
||||||
sirfport->tx_dma_no = UNVALID_DMA_CHAN;
|
|
||||||
}
|
|
||||||
if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-usp-uart")) {
|
if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-usp-uart")) {
|
||||||
sirfport->uart_reg->uart_type = SIRF_USP_UART;
|
sirfport->uart_reg->uart_type = SIRF_USP_UART;
|
||||||
if (of_property_read_u32(pdev->dev.of_node,
|
|
||||||
"sirf,usp-dma-rx-channel",
|
|
||||||
&sirfport->rx_dma_no))
|
|
||||||
sirfport->rx_dma_no = UNVALID_DMA_CHAN;
|
|
||||||
if (of_property_read_u32(pdev->dev.of_node,
|
|
||||||
"sirf,usp-dma-tx-channel",
|
|
||||||
&sirfport->tx_dma_no))
|
|
||||||
sirfport->tx_dma_no = UNVALID_DMA_CHAN;
|
|
||||||
if (!sirfport->hw_flow_ctrl)
|
if (!sirfport->hw_flow_ctrl)
|
||||||
goto usp_no_flow_control;
|
goto usp_no_flow_control;
|
||||||
if (of_find_property(pdev->dev.of_node, "cts-gpios", NULL))
|
if (of_find_property(pdev->dev.of_node, "cts-gpios", NULL))
|
||||||
|
@ -1515,8 +1407,32 @@ usp_no_flow_control:
|
||||||
goto port_err;
|
goto port_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
sirfport->rx_dma_chan = dma_request_slave_channel(port->dev, "rx");
|
||||||
|
for (i = 0; sirfport->rx_dma_chan && i < SIRFSOC_RX_LOOP_BUF_CNT; i++) {
|
||||||
|
sirfport->rx_dma_items[i].xmit.buf =
|
||||||
|
dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
|
||||||
|
&sirfport->rx_dma_items[i].dma_addr, GFP_KERNEL);
|
||||||
|
if (!sirfport->rx_dma_items[i].xmit.buf) {
|
||||||
|
dev_err(port->dev, "Uart alloc bufa failed\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto alloc_coherent_err;
|
||||||
|
}
|
||||||
|
sirfport->rx_dma_items[i].xmit.head =
|
||||||
|
sirfport->rx_dma_items[i].xmit.tail = 0;
|
||||||
|
}
|
||||||
|
if (sirfport->rx_dma_chan)
|
||||||
|
dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg);
|
||||||
|
sirfport->tx_dma_chan = dma_request_slave_channel(port->dev, "tx");
|
||||||
|
if (sirfport->tx_dma_chan)
|
||||||
|
dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
alloc_coherent_err:
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
|
||||||
|
sirfport->rx_dma_items[j].xmit.buf,
|
||||||
|
sirfport->rx_dma_items[j].dma_addr);
|
||||||
|
dma_release_channel(sirfport->rx_dma_chan);
|
||||||
port_err:
|
port_err:
|
||||||
clk_put(sirfport->clk);
|
clk_put(sirfport->clk);
|
||||||
err:
|
err:
|
||||||
|
@ -1529,6 +1445,19 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
|
||||||
struct uart_port *port = &sirfport->port;
|
struct uart_port *port = &sirfport->port;
|
||||||
clk_put(sirfport->clk);
|
clk_put(sirfport->clk);
|
||||||
uart_remove_one_port(&sirfsoc_uart_drv, port);
|
uart_remove_one_port(&sirfsoc_uart_drv, port);
|
||||||
|
if (sirfport->rx_dma_chan) {
|
||||||
|
int i;
|
||||||
|
dmaengine_terminate_all(sirfport->rx_dma_chan);
|
||||||
|
dma_release_channel(sirfport->rx_dma_chan);
|
||||||
|
for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++)
|
||||||
|
dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
|
||||||
|
sirfport->rx_dma_items[i].xmit.buf,
|
||||||
|
sirfport->rx_dma_items[i].dma_addr);
|
||||||
|
}
|
||||||
|
if (sirfport->tx_dma_chan) {
|
||||||
|
dmaengine_terminate_all(sirfport->tx_dma_chan);
|
||||||
|
dma_release_channel(sirfport->tx_dma_chan);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -392,9 +392,6 @@ struct sirfsoc_uart_register sirfsoc_uart = {
|
||||||
/* Indicate how many buffers used */
|
/* Indicate how many buffers used */
|
||||||
#define SIRFSOC_RX_LOOP_BUF_CNT 2
|
#define SIRFSOC_RX_LOOP_BUF_CNT 2
|
||||||
|
|
||||||
/* Indicate if DMA channel valid */
|
|
||||||
#define IS_DMA_CHAN_VALID(x) ((x) != -1)
|
|
||||||
#define UNVALID_DMA_CHAN -1
|
|
||||||
/* For Fast Baud Rate Calculation */
|
/* For Fast Baud Rate Calculation */
|
||||||
struct sirfsoc_baudrate_to_regv {
|
struct sirfsoc_baudrate_to_regv {
|
||||||
unsigned int baud_rate;
|
unsigned int baud_rate;
|
||||||
|
@ -423,8 +420,6 @@ struct sirfsoc_uart_port {
|
||||||
/* for SiRFmarco, there are SET/CLR for UART_INT_EN */
|
/* for SiRFmarco, there are SET/CLR for UART_INT_EN */
|
||||||
bool is_marco;
|
bool is_marco;
|
||||||
struct sirfsoc_uart_register *uart_reg;
|
struct sirfsoc_uart_register *uart_reg;
|
||||||
int rx_dma_no;
|
|
||||||
int tx_dma_no;
|
|
||||||
struct dma_chan *rx_dma_chan;
|
struct dma_chan *rx_dma_chan;
|
||||||
struct dma_chan *tx_dma_chan;
|
struct dma_chan *tx_dma_chan;
|
||||||
dma_addr_t tx_dma_addr;
|
dma_addr_t tx_dma_addr;
|
||||||
|
|
|
@ -7866,6 +7866,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||||
HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
|
HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
|
||||||
HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
|
HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
|
||||||
|
|
||||||
|
memset(&new_line, 0, sizeof(new_line));
|
||||||
switch (flags){
|
switch (flags){
|
||||||
case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
|
case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
|
||||||
case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
|
case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
|
||||||
|
|
|
@ -1766,6 +1766,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||||
HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
|
HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
|
||||||
HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
|
HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
|
||||||
|
|
||||||
|
memset(&new_line, 0, sizeof(new_line));
|
||||||
switch (flags){
|
switch (flags){
|
||||||
case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
|
case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
|
||||||
case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
|
case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
|
||||||
|
|
|
@ -351,14 +351,11 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
|
||||||
* Takes any pending buffers and transfers their ownership to the
|
* Takes any pending buffers and transfers their ownership to the
|
||||||
* ldisc side of the queue. It then schedules those characters for
|
* ldisc side of the queue. It then schedules those characters for
|
||||||
* processing by the line discipline.
|
* processing by the line discipline.
|
||||||
* Note that this function can only be used when the low_latency flag
|
|
||||||
* is unset. Otherwise the workqueue won't be flushed.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void tty_schedule_flip(struct tty_port *port)
|
void tty_schedule_flip(struct tty_port *port)
|
||||||
{
|
{
|
||||||
struct tty_bufhead *buf = &port->buf;
|
struct tty_bufhead *buf = &port->buf;
|
||||||
WARN_ON(port->low_latency);
|
|
||||||
|
|
||||||
buf->tail->commit = buf->tail->used;
|
buf->tail->commit = buf->tail->used;
|
||||||
schedule_work(&buf->work);
|
schedule_work(&buf->work);
|
||||||
|
@ -482,7 +479,6 @@ static void flush_to_ldisc(struct work_struct *work)
|
||||||
*/
|
*/
|
||||||
void tty_flush_to_ldisc(struct tty_struct *tty)
|
void tty_flush_to_ldisc(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
if (!tty->port->low_latency)
|
|
||||||
flush_work(&tty->port->buf.work);
|
flush_work(&tty->port->buf.work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,9 +486,8 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
|
||||||
* tty_flip_buffer_push - terminal
|
* tty_flip_buffer_push - terminal
|
||||||
* @port: tty port to push
|
* @port: tty port to push
|
||||||
*
|
*
|
||||||
* Queue a push of the terminal flip buffers to the line discipline. This
|
* Queue a push of the terminal flip buffers to the line discipline.
|
||||||
* function must not be called from IRQ context if port->low_latency is
|
* Can be called from IRQ/atomic context.
|
||||||
* set.
|
|
||||||
*
|
*
|
||||||
* In the event of the queue being busy for flipping the work will be
|
* In the event of the queue being busy for flipping the work will be
|
||||||
* held off and retried later.
|
* held off and retried later.
|
||||||
|
@ -500,14 +495,7 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
|
||||||
|
|
||||||
void tty_flip_buffer_push(struct tty_port *port)
|
void tty_flip_buffer_push(struct tty_port *port)
|
||||||
{
|
{
|
||||||
struct tty_bufhead *buf = &port->buf;
|
tty_schedule_flip(port);
|
||||||
|
|
||||||
buf->tail->commit = buf->tail->used;
|
|
||||||
|
|
||||||
if (port->low_latency)
|
|
||||||
flush_to_ldisc(&buf->work);
|
|
||||||
else
|
|
||||||
schedule_work(&buf->work);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_flip_buffer_push);
|
EXPORT_SYMBOL(tty_flip_buffer_push);
|
||||||
|
|
||||||
|
|
|
@ -1271,12 +1271,13 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
|
||||||
*
|
*
|
||||||
* Locking: None
|
* Locking: None
|
||||||
*/
|
*/
|
||||||
static void tty_line_name(struct tty_driver *driver, int index, char *p)
|
static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
|
||||||
{
|
{
|
||||||
if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
|
if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
|
||||||
strcpy(p, driver->name);
|
return sprintf(p, "%s", driver->name);
|
||||||
else
|
else
|
||||||
sprintf(p, "%s%d", driver->name, index + driver->name_base);
|
return sprintf(p, "%s%d", driver->name,
|
||||||
|
index + driver->name_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3545,9 +3546,19 @@ static ssize_t show_cons_active(struct device *dev,
|
||||||
if (i >= ARRAY_SIZE(cs))
|
if (i >= ARRAY_SIZE(cs))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (i--)
|
while (i--) {
|
||||||
count += sprintf(buf + count, "%s%d%c",
|
int index = cs[i]->index;
|
||||||
cs[i]->name, cs[i]->index, i ? ' ':'\n');
|
struct tty_driver *drv = cs[i]->device(cs[i], &index);
|
||||||
|
|
||||||
|
/* don't resolve tty0 as some programs depend on it */
|
||||||
|
if (drv && (cs[i]->index > 0 || drv->major != TTY_MAJOR))
|
||||||
|
count += tty_line_name(drv, index, buf + count);
|
||||||
|
else
|
||||||
|
count += sprintf(buf + count, "%s%d",
|
||||||
|
cs[i]->name, cs[i]->index);
|
||||||
|
|
||||||
|
count += sprintf(buf + count, "%c", i ? ' ':'\n');
|
||||||
|
}
|
||||||
console_unlock();
|
console_unlock();
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|
|
@ -1590,9 +1590,9 @@ static void restore_cur(struct vc_data *vc)
|
||||||
vc->vc_need_wrap = 0;
|
vc->vc_need_wrap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
|
enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey,
|
||||||
EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
|
EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
|
||||||
ESpalette };
|
ESpalette, ESosc };
|
||||||
|
|
||||||
/* console_lock is held (except via vc_init()) */
|
/* console_lock is held (except via vc_init()) */
|
||||||
static void reset_terminal(struct vc_data *vc, int do_clear)
|
static void reset_terminal(struct vc_data *vc, int do_clear)
|
||||||
|
@ -1652,11 +1652,15 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
|
||||||
* Control characters can be used in the _middle_
|
* Control characters can be used in the _middle_
|
||||||
* of an escape sequence.
|
* of an escape sequence.
|
||||||
*/
|
*/
|
||||||
|
if (vc->vc_state == ESosc && c>=8 && c<=13) /* ... except for OSC */
|
||||||
|
return;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
return;
|
return;
|
||||||
case 7:
|
case 7:
|
||||||
if (vc->vc_bell_duration)
|
if (vc->vc_state == ESosc)
|
||||||
|
vc->vc_state = ESnormal;
|
||||||
|
else if (vc->vc_bell_duration)
|
||||||
kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
|
kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
|
||||||
return;
|
return;
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -1767,7 +1771,9 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
|
||||||
} else if (c=='R') { /* reset palette */
|
} else if (c=='R') { /* reset palette */
|
||||||
reset_palette(vc);
|
reset_palette(vc);
|
||||||
vc->vc_state = ESnormal;
|
vc->vc_state = ESnormal;
|
||||||
} else
|
} else if (c>='0' && c<='9')
|
||||||
|
vc->vc_state = ESosc;
|
||||||
|
else
|
||||||
vc->vc_state = ESnormal;
|
vc->vc_state = ESnormal;
|
||||||
return;
|
return;
|
||||||
case ESpalette:
|
case ESpalette:
|
||||||
|
@ -1807,9 +1813,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
|
||||||
vc->vc_par[vc->vc_npar] *= 10;
|
vc->vc_par[vc->vc_npar] *= 10;
|
||||||
vc->vc_par[vc->vc_npar] += c - '0';
|
vc->vc_par[vc->vc_npar] += c - '0';
|
||||||
return;
|
return;
|
||||||
} else
|
}
|
||||||
vc->vc_state = ESgotpars;
|
|
||||||
case ESgotpars:
|
|
||||||
vc->vc_state = ESnormal;
|
vc->vc_state = ESnormal;
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
|
@ -2023,6 +2027,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
|
||||||
vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
|
vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
|
||||||
vc->vc_state = ESnormal;
|
vc->vc_state = ESnormal;
|
||||||
return;
|
return;
|
||||||
|
case ESosc:
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
vc->vc_state = ESnormal;
|
vc->vc_state = ESnormal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,8 +549,8 @@ static void gs_rx_push(unsigned long _port)
|
||||||
port->read_started--;
|
port->read_started--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push from tty to ldisc; without low_latency set this is handled by
|
/* Push from tty to ldisc; this is handled by a workqueue,
|
||||||
* a workqueue, so we won't get callbacks and can hold port_lock
|
* so we won't get callbacks and can hold port_lock
|
||||||
*/
|
*/
|
||||||
if (do_push)
|
if (do_push)
|
||||||
tty_flip_buffer_push(&port->port);
|
tty_flip_buffer_push(&port->port);
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
* Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
|
|
||||||
*
|
|
||||||
* Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
|
|
||||||
* Based on max3110.c, by Feng Tang <feng.tang@intel.com>
|
|
||||||
* Based on max3107.c, by Aavamobile
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _MAX310X_H_
|
|
||||||
#define _MAX310X_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Example board initialization data:
|
|
||||||
*
|
|
||||||
* static struct max310x_pdata max3107_pdata = {
|
|
||||||
* .driver_flags = MAX310X_EXT_CLK,
|
|
||||||
* .uart_flags[0] = MAX310X_ECHO_SUPRESS | MAX310X_AUTO_DIR_CTRL,
|
|
||||||
* .frequency = 3686400,
|
|
||||||
* .gpio_base = -1,
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* static struct spi_board_info spi_device_max3107[] = {
|
|
||||||
* {
|
|
||||||
* .modalias = "max3107",
|
|
||||||
* .irq = IRQ_EINT3,
|
|
||||||
* .bus_num = 1,
|
|
||||||
* .chip_select = 1,
|
|
||||||
* .platform_data = &max3107_pdata,
|
|
||||||
* },
|
|
||||||
* };
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAX310X_MAX_UARTS 4
|
|
||||||
|
|
||||||
/* MAX310X platform data structure */
|
|
||||||
struct max310x_pdata {
|
|
||||||
/* Flags global to driver */
|
|
||||||
const u8 driver_flags;
|
|
||||||
#define MAX310X_EXT_CLK (0x00000001) /* External clock enable */
|
|
||||||
/* Flags global to UART port */
|
|
||||||
const u8 uart_flags[MAX310X_MAX_UARTS];
|
|
||||||
#define MAX310X_LOOPBACK (0x00000001) /* Loopback mode enable */
|
|
||||||
#define MAX310X_ECHO_SUPRESS (0x00000002) /* Enable echo supress */
|
|
||||||
#define MAX310X_AUTO_DIR_CTRL (0x00000004) /* Enable Auto direction
|
|
||||||
* control (RS-485)
|
|
||||||
*/
|
|
||||||
/* Frequency (extrenal clock or crystal) */
|
|
||||||
const int frequency;
|
|
||||||
/* GPIO base number (can be negative) */
|
|
||||||
const int gpio_base;
|
|
||||||
/* Called during startup */
|
|
||||||
void (*init)(void);
|
|
||||||
/* Called before finish */
|
|
||||||
void (*exit)(void);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -23,8 +23,6 @@
|
||||||
#define IMXUART_IRDA (1<<1)
|
#define IMXUART_IRDA (1<<1)
|
||||||
|
|
||||||
struct imxuart_platform_data {
|
struct imxuart_platform_data {
|
||||||
int (*init)(struct platform_device *pdev);
|
|
||||||
void (*exit)(struct platform_device *pdev);
|
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
void (*irda_enable)(int enable);
|
void (*irda_enable)(int enable);
|
||||||
unsigned int irda_inv_rx:1;
|
unsigned int irda_inv_rx:1;
|
||||||
|
|
|
@ -116,4 +116,6 @@
|
||||||
UART_FIFO_PARERR_MASK | \
|
UART_FIFO_PARERR_MASK | \
|
||||||
UART_FIFO_BRKDET_MASK)
|
UART_FIFO_BRKDET_MASK)
|
||||||
|
|
||||||
|
#define UART_REG_SIZE 24
|
||||||
|
|
||||||
#endif /* _LINUX_SERIAL_BCM63XX_H */
|
#endif /* _LINUX_SERIAL_BCM63XX_H */
|
||||||
|
|
|
@ -10,45 +10,59 @@
|
||||||
|
|
||||||
#define SCIx_NOT_SUPPORTED (-1)
|
#define SCIx_NOT_SUPPORTED (-1)
|
||||||
|
|
||||||
#define SCSCR_TIE (1 << 7)
|
/* SCSMR (Serial Mode Register) */
|
||||||
#define SCSCR_RIE (1 << 6)
|
#define SCSMR_CHR (1 << 6) /* 7-bit Character Length */
|
||||||
#define SCSCR_TE (1 << 5)
|
#define SCSMR_PE (1 << 5) /* Parity Enable */
|
||||||
#define SCSCR_RE (1 << 4)
|
#define SCSMR_ODD (1 << 4) /* Odd Parity */
|
||||||
#define SCSCR_REIE (1 << 3) /* not supported by all parts */
|
#define SCSMR_STOP (1 << 3) /* Stop Bit Length */
|
||||||
#define SCSCR_TOIE (1 << 2) /* not supported by all parts */
|
#define SCSMR_CKS 0x0003 /* Clock Select */
|
||||||
#define SCSCR_CKE1 (1 << 1)
|
|
||||||
#define SCSCR_CKE0 (1 << 0)
|
|
||||||
|
|
||||||
/* SCxSR SCI */
|
/* Serial Control Register (@ = not supported by all parts) */
|
||||||
#define SCI_TDRE 0x80
|
#define SCSCR_TIE (1 << 7) /* Transmit Interrupt Enable */
|
||||||
#define SCI_RDRF 0x40
|
#define SCSCR_RIE (1 << 6) /* Receive Interrupt Enable */
|
||||||
#define SCI_ORER 0x20
|
#define SCSCR_TE (1 << 5) /* Transmit Enable */
|
||||||
#define SCI_FER 0x10
|
#define SCSCR_RE (1 << 4) /* Receive Enable */
|
||||||
#define SCI_PER 0x08
|
#define SCSCR_REIE (1 << 3) /* Receive Error Interrupt Enable @ */
|
||||||
#define SCI_TEND 0x04
|
#define SCSCR_TOIE (1 << 2) /* Timeout Interrupt Enable @ */
|
||||||
|
#define SCSCR_CKE1 (1 << 1) /* Clock Enable 1 */
|
||||||
|
#define SCSCR_CKE0 (1 << 0) /* Clock Enable 0 */
|
||||||
|
/* SCIFA/SCIFB only */
|
||||||
|
#define SCSCR_TDRQE (1 << 15) /* Tx Data Transfer Request Enable */
|
||||||
|
#define SCSCR_RDRQE (1 << 14) /* Rx Data Transfer Request Enable */
|
||||||
|
|
||||||
|
/* SCxSR (Serial Status Register) on SCI */
|
||||||
|
#define SCI_TDRE 0x80 /* Transmit Data Register Empty */
|
||||||
|
#define SCI_RDRF 0x40 /* Receive Data Register Full */
|
||||||
|
#define SCI_ORER 0x20 /* Overrun Error */
|
||||||
|
#define SCI_FER 0x10 /* Framing Error */
|
||||||
|
#define SCI_PER 0x08 /* Parity Error */
|
||||||
|
#define SCI_TEND 0x04 /* Transmit End */
|
||||||
|
|
||||||
#define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
|
#define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
|
||||||
|
|
||||||
/* SCxSR SCIF, HSCIF */
|
/* SCxSR (Serial Status Register) on SCIF, HSCIF */
|
||||||
#define SCIF_ER 0x0080
|
#define SCIF_ER 0x0080 /* Receive Error */
|
||||||
#define SCIF_TEND 0x0040
|
#define SCIF_TEND 0x0040 /* Transmission End */
|
||||||
#define SCIF_TDFE 0x0020
|
#define SCIF_TDFE 0x0020 /* Transmit FIFO Data Empty */
|
||||||
#define SCIF_BRK 0x0010
|
#define SCIF_BRK 0x0010 /* Break Detect */
|
||||||
#define SCIF_FER 0x0008
|
#define SCIF_FER 0x0008 /* Framing Error */
|
||||||
#define SCIF_PER 0x0004
|
#define SCIF_PER 0x0004 /* Parity Error */
|
||||||
#define SCIF_RDF 0x0002
|
#define SCIF_RDF 0x0002 /* Receive FIFO Data Full */
|
||||||
#define SCIF_DR 0x0001
|
#define SCIF_DR 0x0001 /* Receive Data Ready */
|
||||||
|
|
||||||
#define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
|
#define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
|
||||||
|
|
||||||
/* SCSPTR, optional */
|
/* SCFCR (FIFO Control Register) */
|
||||||
#define SCSPTR_RTSIO (1 << 7)
|
#define SCFCR_LOOP (1 << 0) /* Loopback Test */
|
||||||
#define SCSPTR_CTSIO (1 << 5)
|
|
||||||
#define SCSPTR_SPB2IO (1 << 1)
|
/* SCSPTR (Serial Port Register), optional */
|
||||||
#define SCSPTR_SPB2DT (1 << 0)
|
#define SCSPTR_RTSIO (1 << 7) /* Serial Port RTS Pin Input/Output */
|
||||||
|
#define SCSPTR_CTSIO (1 << 5) /* Serial Port CTS Pin Input/Output */
|
||||||
|
#define SCSPTR_SPB2IO (1 << 1) /* Serial Port Break Input/Output */
|
||||||
|
#define SCSPTR_SPB2DT (1 << 0) /* Serial Port Break Data */
|
||||||
|
|
||||||
/* HSSRR HSCIF */
|
/* HSSRR HSCIF */
|
||||||
#define HSCIF_SRE 0x8000
|
#define HSCIF_SRE 0x8000 /* Sampling Rate Register Enable */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SCIx_PROBE_REGTYPE,
|
SCIx_PROBE_REGTYPE,
|
||||||
|
@ -73,10 +87,19 @@ enum {
|
||||||
* Not all registers will exist on all parts.
|
* Not all registers will exist on all parts.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
SCSMR, SCBRR, SCSCR, SCxSR,
|
SCSMR, /* Serial Mode Register */
|
||||||
SCFCR, SCFDR, SCxTDR, SCxRDR,
|
SCBRR, /* Bit Rate Register */
|
||||||
SCLSR, SCTFDR, SCRFDR, SCSPTR,
|
SCSCR, /* Serial Control Register */
|
||||||
HSSRR,
|
SCxSR, /* Serial Status Register */
|
||||||
|
SCFCR, /* FIFO Control Register */
|
||||||
|
SCFDR, /* FIFO Data Count Register */
|
||||||
|
SCxTDR, /* Transmit (FIFO) Data Register */
|
||||||
|
SCxRDR, /* Receive (FIFO) Data Register */
|
||||||
|
SCLSR, /* Line Status Register */
|
||||||
|
SCTFDR, /* Transmit FIFO Data Count Register */
|
||||||
|
SCRFDR, /* Receive FIFO Data Count Register */
|
||||||
|
SCSPTR, /* Serial Port Register */
|
||||||
|
HSSRR, /* Sampling Rate Register */
|
||||||
|
|
||||||
SCIx_NR_REGS,
|
SCIx_NR_REGS,
|
||||||
};
|
};
|
||||||
|
|
|
@ -208,7 +208,7 @@ struct tty_port {
|
||||||
wait_queue_head_t delta_msr_wait; /* Modem status change */
|
wait_queue_head_t delta_msr_wait; /* Modem status change */
|
||||||
unsigned long flags; /* TTY flags ASY_*/
|
unsigned long flags; /* TTY flags ASY_*/
|
||||||
unsigned char console:1, /* port is a console */
|
unsigned char console:1, /* port is a console */
|
||||||
low_latency:1; /* direct buffer flush */
|
low_latency:1; /* optional: tune for latency */
|
||||||
struct mutex mutex; /* Locking */
|
struct mutex mutex; /* Locking */
|
||||||
struct mutex buf_mutex; /* Buffer alloc lock */
|
struct mutex buf_mutex; /* Buffer alloc lock */
|
||||||
unsigned char *xmit_buf; /* Optional buffer */
|
unsigned char *xmit_buf; /* Optional buffer */
|
||||||
|
|
|
@ -126,7 +126,6 @@
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/wait.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue