TTY / Serial driver update for 3.17-rc1
Here's the big tty / serial driver update for 3.17-rc1. Nothing major, just a number of fixes and new features for different serial drivers, and some more tty core fixes and documentation of the tty locks. All of these have been in linux-next for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iEYEABECAAYFAlPf2C4ACgkQMUfUDdst+yllVgCgtZl/Mcr/LlxPgjsg2C1AE7nX YJ4An3o4N112bkdGqhZ7RjAE6K/8YILx =rPhE -----END PGP SIGNATURE----- Merge tag 'tty-3.17-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.17-rc1. Nothing major, just a number of fixes and new features for different serial drivers, and some more tty core fixes and documentation of the tty locks. All of these have been in linux-next for a while" * tag 'tty-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (82 commits) tty/n_gsm.c: fix a memory leak in gsmld_open pch_uart: don't hardcode PCI slot to get DMA device tty: n_gsm, use setup_timer Revert "ARC: [arcfpga] stdout-path now suffices for earlycon/console" serial: sc16is7xx: Correct initialization of s->clk serial: 8250_dw: Add support for deferred probing serial: 8250_dw: Add optional reset control support serial: st-asc: Fix overflow in baudrate calculation serial: st-asc: Don't call BUG in asc_console_setup() tty: serial: msm: Make of_device_id array const tty/n_gsm.c: get gsm->num after gsm_activate_mux serial/core: Fix too big allocation for attribute member drivers/tty/serial: use correct type for dma_map/unmap serial: altera_jtaguart: Fix putchar function passed to uart_console_write() serial/uart/8250: Add tunable RX interrupt trigger I/F of FIFO buffers Serial: allow port drivers to have a default attribute group tty: kgdb_nmi: Automatically manage tty enable serial: altera_jtaguart: Adpot uart_console_write() serial: samsung: improve code clarity by defining a variable serial: samsung: correct the case and default order in switch ...
This commit is contained in:
commit
79eb238c76
|
@ -138,3 +138,19 @@ Description:
|
||||||
|
|
||||||
These sysfs values expose the TIOCGSERIAL interface via
|
These sysfs values expose the TIOCGSERIAL interface via
|
||||||
sysfs rather than via ioctls.
|
sysfs rather than via ioctls.
|
||||||
|
|
||||||
|
What: /sys/class/tty/ttyS0/rx_trig_bytes
|
||||||
|
Date: May 2014
|
||||||
|
Contact: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>
|
||||||
|
Description:
|
||||||
|
Shows current RX interrupt trigger bytes or sets the
|
||||||
|
user specified value to change it for the FIFO buffer.
|
||||||
|
Users can show or set this value regardless of opening the
|
||||||
|
serial device file or not.
|
||||||
|
|
||||||
|
The RX trigger can be set one of four kinds of values for UART
|
||||||
|
serials. When users input a meaning less value to this I/F,
|
||||||
|
the RX trigger is changed to the nearest lower value for the
|
||||||
|
device specification. For example, when user sets 7bytes on
|
||||||
|
16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
|
||||||
|
automatically changed to 4 bytes.
|
||||||
|
|
|
@ -6,7 +6,7 @@ Required properties:
|
||||||
- interrupts : Should contain uart interrupt
|
- interrupts : Should contain uart interrupt
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- efm32,location : Decides the location of the USART I/O pins.
|
- energymicro,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 = "energymicro,efm32-uart";
|
compatible = "energymicro,efm32-uart";
|
||||||
reg = <0x4000c400 0x400>;
|
reg = <0x4000c400 0x400>;
|
||||||
interrupts = <15>;
|
interrupts = <15>;
|
||||||
efm32,location = <0>;
|
energymicro,location = <0>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
* Freescale low power universal asynchronous receiver/transmitter (lpuart)
|
* Freescale low power universal asynchronous receiver/transmitter (lpuart)
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : Should be "fsl,<soc>-lpuart"
|
- compatible :
|
||||||
|
- "fsl,vf610-lpuart" for lpuart compatible with the one integrated
|
||||||
|
on Vybrid vf610 SoC with 8-bit register organization
|
||||||
|
- "fsl,ls1021a-lpuart" for lpuart compatible with the one integrated
|
||||||
|
on LS1021A SoC with 32-bit big-endian register organization
|
||||||
- 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
|
- clocks : phandle + clock specifier pairs, one for each entry in clock-names
|
||||||
|
|
|
@ -1,14 +1,58 @@
|
||||||
* Samsung's UART Controller
|
* Samsung's UART Controller
|
||||||
|
|
||||||
The Samsung's UART controller is used for interfacing SoC with serial communicaion
|
The Samsung's UART controller is used for interfacing SoC with serial
|
||||||
devices.
|
communicaion devices.
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: should be
|
- compatible: should be one of following:
|
||||||
- "samsung,exynos4210-uart", for UART's compatible with Exynos4210 uart ports.
|
- "samsung,exynos4210-uart" - Exynos4210 SoC,
|
||||||
|
- "samsung,s3c2410-uart" - compatible with ports present on S3C2410 SoC,
|
||||||
|
- "samsung,s3c2412-uart" - compatible with ports present on S3C2412 SoC,
|
||||||
|
- "samsung,s3c2440-uart" - compatible with ports present on S3C2440 SoC,
|
||||||
|
- "samsung,s3c6400-uart" - compatible with ports present on S3C6400 SoC,
|
||||||
|
- "samsung,s5pv210-uart" - compatible with ports present on S5PV210 SoC.
|
||||||
|
|
||||||
- reg: base physical address of the controller and length of memory mapped
|
- reg: base physical address of the controller and length of memory mapped
|
||||||
region.
|
region.
|
||||||
|
|
||||||
- interrupts: interrupt number to the cpu. The interrupt specifier format depends
|
- interrupts: a single interrupt signal to SoC interrupt controller,
|
||||||
on the interrupt controller parent.
|
according to interrupt bindings documentation [1].
|
||||||
|
|
||||||
|
- clock-names: input names of clocks used by the controller:
|
||||||
|
- "uart" - controller bus clock,
|
||||||
|
- "clk_uart_baudN" - Nth baud base clock input (N = 0, 1, ...),
|
||||||
|
according to SoC User's Manual (only N = 0 is allowedfor SoCs without
|
||||||
|
internal baud clock mux).
|
||||||
|
- clocks: phandles and specifiers for all clocks specified in "clock-names"
|
||||||
|
property, in the same order, according to clock bindings documentation [2].
|
||||||
|
|
||||||
|
[1] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
|
||||||
|
[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- samsung,uart-fifosize: The fifo size supported by the UART channel
|
||||||
|
|
||||||
|
Note: Each Samsung UART should have an alias correctly numbered in the
|
||||||
|
"aliases" node, according to serialN format, where N is the port number
|
||||||
|
(non-negative decimal integer) as specified by User's Manual of respective
|
||||||
|
SoC.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
aliases {
|
||||||
|
serial0 = &uart0;
|
||||||
|
serial1 = &uart1;
|
||||||
|
serial2 = &uart2;
|
||||||
|
};
|
||||||
|
|
||||||
|
Example:
|
||||||
|
uart1: serial@7f005400 {
|
||||||
|
compatible = "samsung,s3c6400-uart";
|
||||||
|
reg = <0x7f005400 0x100>;
|
||||||
|
interrupt-parent = <&vic1>;
|
||||||
|
interrupts = <6>;
|
||||||
|
clock-names = "uart", "clk_uart_baud2",
|
||||||
|
"clk_uart_baud3";
|
||||||
|
clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
|
||||||
|
<&clocks SCLK_UART>;
|
||||||
|
samsung,uart-fifosize = <16>;
|
||||||
|
};
|
||||||
|
|
|
@ -4,9 +4,18 @@ Required properties:
|
||||||
- compatible : "snps,dw-apb-uart"
|
- compatible : "snps,dw-apb-uart"
|
||||||
- reg : offset and length of the register set for the device.
|
- reg : offset and length of the register set for the device.
|
||||||
- interrupts : should contain uart interrupt.
|
- interrupts : should contain uart interrupt.
|
||||||
|
|
||||||
|
Clock handling:
|
||||||
|
The clock rate of the input clock needs to be supplied by one of
|
||||||
- clock-frequency : the input clock frequency for the UART.
|
- clock-frequency : the input clock frequency for the UART.
|
||||||
|
- clocks : phandle to the input clock
|
||||||
|
|
||||||
|
The supplying peripheral clock can also be handled, needing a second property
|
||||||
|
- clock-names: tuple listing input clock names.
|
||||||
|
Required elements: "baudclk", "apb_pclk"
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
|
- resets : phandle to the parent reset controller.
|
||||||
- reg-shift : quantity to shift the register offsets by. If this property is
|
- reg-shift : quantity to shift the register offsets by. If this property is
|
||||||
not present then the register offsets are not shifted.
|
not present then the register offsets are not shifted.
|
||||||
- reg-io-width : the size (in bytes) of the IO accesses that should be
|
- reg-io-width : the size (in bytes) of the IO accesses that should be
|
||||||
|
@ -23,3 +32,26 @@ Example:
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Example with one clock:
|
||||||
|
|
||||||
|
uart@80230000 {
|
||||||
|
compatible = "snps,dw-apb-uart";
|
||||||
|
reg = <0x80230000 0x100>;
|
||||||
|
clocks = <&baudclk>;
|
||||||
|
interrupts = <10>;
|
||||||
|
reg-shift = <2>;
|
||||||
|
reg-io-width = <4>;
|
||||||
|
};
|
||||||
|
|
||||||
|
Example with two clocks:
|
||||||
|
|
||||||
|
uart@80230000 {
|
||||||
|
compatible = "snps,dw-apb-uart";
|
||||||
|
reg = <0x80230000 0x100>;
|
||||||
|
clocks = <&baudclk>, <&apb_pclk>;
|
||||||
|
clock-names = "baudclk", "apb_pclk";
|
||||||
|
interrupts = <10>;
|
||||||
|
reg-shift = <2>;
|
||||||
|
reg-io-width = <4>;
|
||||||
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
bootargs = "console=ttyARC0,115200n8 earlyprintk=ttyARC0";
|
bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
|
||||||
};
|
};
|
||||||
|
|
||||||
aliases {
|
aliases {
|
||||||
|
|
|
@ -41,11 +41,4 @@ config ISS_SMP_EXTN
|
||||||
-XTL (To enable CPU start/stop/set-PC for another CPU)
|
-XTL (To enable CPU start/stop/set-PC for another CPU)
|
||||||
It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
|
It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
|
||||||
|
|
||||||
config ARC_SERIAL_BAUD
|
|
||||||
int "UART Baud rate"
|
|
||||||
default "115200"
|
|
||||||
depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
|
|
||||||
help
|
|
||||||
Baud rate for the ARC UART
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -22,115 +22,22 @@
|
||||||
#include <plat/smp.h>
|
#include <plat/smp.h>
|
||||||
#include <plat/irq.h>
|
#include <plat/irq.h>
|
||||||
|
|
||||||
/*----------------------- Platform Devices -----------------------------*/
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SERIAL_ARC)
|
|
||||||
static unsigned long arc_uart_info[] = {
|
|
||||||
0, /* uart->is_emulated (runtime @running_on_hw) */
|
|
||||||
0, /* uart->port.uartclk */
|
|
||||||
0, /* uart->baud */
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
|
|
||||||
/*
|
|
||||||
* static platform data - but only for early serial
|
|
||||||
* TBD: derive this from a special DT node
|
|
||||||
*/
|
|
||||||
static struct resource arc_uart0_res[] = {
|
|
||||||
{
|
|
||||||
.start = UART0_BASE,
|
|
||||||
.end = UART0_BASE + 0xFF,
|
|
||||||
.flags = IORESOURCE_MEM,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.start = UART0_IRQ,
|
|
||||||
.end = UART0_IRQ,
|
|
||||||
.flags = IORESOURCE_IRQ,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct platform_device arc_uart0_dev = {
|
|
||||||
.name = "arc-uart",
|
|
||||||
.id = 0,
|
|
||||||
.num_resources = ARRAY_SIZE(arc_uart0_res),
|
|
||||||
.resource = arc_uart0_res,
|
|
||||||
.dev = {
|
|
||||||
.platform_data = &arc_uart_info,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct platform_device *fpga_early_devs[] __initdata = {
|
|
||||||
&arc_uart0_dev,
|
|
||||||
};
|
|
||||||
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
|
|
||||||
|
|
||||||
static void arc_fpga_serial_init(void)
|
|
||||||
{
|
|
||||||
/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
|
|
||||||
arc_uart_info[0] = !running_on_hw;
|
|
||||||
|
|
||||||
arc_uart_info[1] = arc_get_core_freq();
|
|
||||||
|
|
||||||
arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
|
|
||||||
|
|
||||||
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
|
|
||||||
early_platform_add_devices(fpga_early_devs,
|
|
||||||
ARRAY_SIZE(fpga_early_devs));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ARC console driver registers (build time) as an early platform driver
|
|
||||||
* of class "earlyprintk". However it needs explicit cmdline toggle
|
|
||||||
* "earlyprintk=ttyARC0" to be successfuly runtime registered.
|
|
||||||
* Otherwise the early probe below fails to find the driver
|
|
||||||
*/
|
|
||||||
early_platform_driver_probe("earlyprintk", 1, 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is to make sure that arc uart would be preferred console
|
|
||||||
* despite one/more of following:
|
|
||||||
* -command line lacked "console=ttyARC0" or
|
|
||||||
* -CONFIG_VT_CONSOLE was enabled (for no reason whatsoever)
|
|
||||||
* Note that this needs to be done after above early console is reg,
|
|
||||||
* otherwise the early console never gets a chance to run.
|
|
||||||
*/
|
|
||||||
add_preferred_console("ttyARC", 0, "115200");
|
|
||||||
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
|
|
||||||
}
|
|
||||||
#else /* !IS_ENABLED(CONFIG_SERIAL_ARC) */
|
|
||||||
static void arc_fpga_serial_init(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void __init plat_fpga_early_init(void)
|
static void __init plat_fpga_early_init(void)
|
||||||
{
|
{
|
||||||
pr_info("[plat-arcfpga]: registering early dev resources\n");
|
pr_info("[plat-arcfpga]: registering early dev resources\n");
|
||||||
|
|
||||||
arc_fpga_serial_init();
|
|
||||||
|
|
||||||
#ifdef CONFIG_ISS_SMP_EXTN
|
#ifdef CONFIG_ISS_SMP_EXTN
|
||||||
iss_model_init_early_smp();
|
iss_model_init_early_smp();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
|
|
||||||
#if IS_ENABLED(CONFIG_SERIAL_ARC)
|
|
||||||
OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
|
|
||||||
#endif
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __init plat_fpga_populate_dev(void)
|
static void __init plat_fpga_populate_dev(void)
|
||||||
{
|
{
|
||||||
pr_info("[plat-arcfpga]: registering device resources\n");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Traverses flattened DeviceTree - registering platform devices
|
* Traverses flattened DeviceTree - registering platform devices
|
||||||
* complete with their resources
|
* (if any) complete with their resources
|
||||||
*/
|
*/
|
||||||
of_platform_populate(NULL, of_default_bus_match_table,
|
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||||
plat_auxdata_lookup, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------- Machine Descriptions ------------------------------
|
/*----------------------- Machine Descriptions ------------------------------
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
i2c5 = &i2c_5;
|
i2c5 = &i2c_5;
|
||||||
i2c6 = &i2c_6;
|
i2c6 = &i2c_6;
|
||||||
i2c7 = &i2c_7;
|
i2c7 = &i2c_7;
|
||||||
|
serial0 = &serial_0;
|
||||||
|
serial1 = &serial_1;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
|
|
|
@ -44,6 +44,10 @@
|
||||||
fimc1 = &fimc_1;
|
fimc1 = &fimc_1;
|
||||||
fimc2 = &fimc_2;
|
fimc2 = &fimc_2;
|
||||||
fimc3 = &fimc_3;
|
fimc3 = &fimc_3;
|
||||||
|
serial0 = &serial_0;
|
||||||
|
serial1 = &serial_1;
|
||||||
|
serial2 = &serial_2;
|
||||||
|
serial3 = &serial_3;
|
||||||
};
|
};
|
||||||
|
|
||||||
clock_audss: clock-controller@03810000 {
|
clock_audss: clock-controller@03810000 {
|
||||||
|
@ -363,7 +367,7 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@13800000 {
|
serial_0: serial@13800000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0x13800000 0x100>;
|
reg = <0x13800000 0x100>;
|
||||||
interrupts = <0 52 0>;
|
interrupts = <0 52 0>;
|
||||||
|
@ -372,7 +376,7 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@13810000 {
|
serial_1: serial@13810000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0x13810000 0x100>;
|
reg = <0x13810000 0x100>;
|
||||||
interrupts = <0 53 0>;
|
interrupts = <0 53 0>;
|
||||||
|
@ -381,7 +385,7 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@13820000 {
|
serial_2: serial@13820000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0x13820000 0x100>;
|
reg = <0x13820000 0x100>;
|
||||||
interrupts = <0 54 0>;
|
interrupts = <0 54 0>;
|
||||||
|
@ -390,7 +394,7 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@13830000 {
|
serial_3: serial@13830000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0x13830000 0x100>;
|
reg = <0x13830000 0x100>;
|
||||||
interrupts = <0 55 0>;
|
interrupts = <0 55 0>;
|
||||||
|
|
|
@ -18,6 +18,13 @@
|
||||||
/ {
|
/ {
|
||||||
interrupt-parent = <&gic>;
|
interrupt-parent = <&gic>;
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
serial0 = &serial_0;
|
||||||
|
serial1 = &serial_1;
|
||||||
|
serial2 = &serial_2;
|
||||||
|
serial3 = &serial_3;
|
||||||
|
};
|
||||||
|
|
||||||
chipid@10000000 {
|
chipid@10000000 {
|
||||||
compatible = "samsung,exynos4210-chipid";
|
compatible = "samsung,exynos4210-chipid";
|
||||||
reg = <0x10000000 0x100>;
|
reg = <0x10000000 0x100>;
|
||||||
|
@ -50,25 +57,25 @@
|
||||||
interrupts = <1 9 0xf04>;
|
interrupts = <1 9 0xf04>;
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@12C00000 {
|
serial_0: serial@12C00000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0x12C00000 0x100>;
|
reg = <0x12C00000 0x100>;
|
||||||
interrupts = <0 51 0>;
|
interrupts = <0 51 0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@12C10000 {
|
serial_1: serial@12C10000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0x12C10000 0x100>;
|
reg = <0x12C10000 0x100>;
|
||||||
interrupts = <0 52 0>;
|
interrupts = <0 52 0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@12C20000 {
|
serial_2: serial@12C20000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0x12C20000 0x100>;
|
reg = <0x12C20000 0x100>;
|
||||||
interrupts = <0 53 0>;
|
interrupts = <0 53 0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@12C30000 {
|
serial_3: serial@12C30000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0x12C30000 0x100>;
|
reg = <0x12C30000 0x100>;
|
||||||
interrupts = <0 54 0>;
|
interrupts = <0 54 0>;
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
pinctrl0 = &pinctrl_0;
|
pinctrl0 = &pinctrl_0;
|
||||||
pinctrl1 = &pinctrl_1;
|
pinctrl1 = &pinctrl_1;
|
||||||
pinctrl2 = &pinctrl_2;
|
pinctrl2 = &pinctrl_2;
|
||||||
|
serial0 = &uart0;
|
||||||
|
serial1 = &uart1;
|
||||||
|
serial2 = &uart2;
|
||||||
|
serial3 = &uart3;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
|
|
|
@ -20,6 +20,12 @@
|
||||||
compatible = "samsung,exynos5410", "samsung,exynos5";
|
compatible = "samsung,exynos5410", "samsung,exynos5";
|
||||||
interrupt-parent = <&gic>;
|
interrupt-parent = <&gic>;
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
serial0 = &uart0;
|
||||||
|
serial1 = &uart1;
|
||||||
|
serial2 = &uart2;
|
||||||
|
};
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
interrupt-parent = <&gic>;
|
interrupt-parent = <&gic>;
|
||||||
|
|
||||||
aliases {
|
aliases {
|
||||||
|
serial0 = &serial_0;
|
||||||
|
serial1 = &serial_1;
|
||||||
spi0 = &spi_0;
|
spi0 = &spi_0;
|
||||||
tmuctrl0 = &tmuctrl_0;
|
tmuctrl0 = &tmuctrl_0;
|
||||||
tmuctrl1 = &tmuctrl_1;
|
tmuctrl1 = &tmuctrl_1;
|
||||||
|
@ -102,7 +104,7 @@
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@B0000 {
|
serial_0: serial@B0000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0xB0000 0x1000>;
|
reg = <0xB0000 0x1000>;
|
||||||
interrupts = <0 2 0>;
|
interrupts = <0 2 0>;
|
||||||
|
@ -110,7 +112,7 @@
|
||||||
clock-names = "uart", "clk_uart_baud0";
|
clock-names = "uart", "clk_uart_baud0";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@C0000 {
|
serial_1: serial@C0000 {
|
||||||
compatible = "samsung,exynos4210-uart";
|
compatible = "samsung,exynos4210-uart";
|
||||||
reg = <0xC0000 0x1000>;
|
reg = <0xC0000 0x1000>;
|
||||||
interrupts = <0 3 0>;
|
interrupts = <0 3 0>;
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
model = "Samsung S3C2416 SoC";
|
model = "Samsung S3C2416 SoC";
|
||||||
compatible = "samsung,s3c2416";
|
compatible = "samsung,s3c2416";
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
serial3 = &uart3;
|
||||||
|
};
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
@ -68,7 +72,7 @@
|
||||||
<&clocks SCLK_UART>;
|
<&clocks SCLK_UART>;
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@5000C000 {
|
uart3: serial@5000C000 {
|
||||||
compatible = "samsung,s3c2440-uart";
|
compatible = "samsung,s3c2440-uart";
|
||||||
reg = <0x5000C000 0x4000>;
|
reg = <0x5000C000 0x4000>;
|
||||||
interrupts = <1 18 24 4>, <1 18 25 4>;
|
interrupts = <1 18 24 4>, <1 18 25 4>;
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
|
|
||||||
aliases {
|
aliases {
|
||||||
pinctrl0 = &pinctrl_0;
|
pinctrl0 = &pinctrl_0;
|
||||||
|
serial0 = &uart0;
|
||||||
|
serial1 = &uart1;
|
||||||
|
serial2 = &uart2;
|
||||||
};
|
};
|
||||||
|
|
||||||
intc:interrupt-controller@4a000000 {
|
intc:interrupt-controller@4a000000 {
|
||||||
|
@ -46,21 +49,21 @@
|
||||||
#pwm-cells = <4>;
|
#pwm-cells = <4>;
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@50000000 {
|
uart0: serial@50000000 {
|
||||||
compatible = "samsung,s3c2410-uart";
|
compatible = "samsung,s3c2410-uart";
|
||||||
reg = <0x50000000 0x4000>;
|
reg = <0x50000000 0x4000>;
|
||||||
interrupts = <1 28 0 4>, <1 28 1 4>;
|
interrupts = <1 28 0 4>, <1 28 1 4>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@50004000 {
|
uart1: serial@50004000 {
|
||||||
compatible = "samsung,s3c2410-uart";
|
compatible = "samsung,s3c2410-uart";
|
||||||
reg = <0x50004000 0x4000>;
|
reg = <0x50004000 0x4000>;
|
||||||
interrupts = <1 23 3 4>, <1 23 4 4>;
|
interrupts = <1 23 3 4>, <1 23 4 4>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@50008000 {
|
uart2: serial@50008000 {
|
||||||
compatible = "samsung,s3c2410-uart";
|
compatible = "samsung,s3c2410-uart";
|
||||||
reg = <0x50008000 0x4000>;
|
reg = <0x50008000 0x4000>;
|
||||||
interrupts = <1 15 6 4>, <1 15 7 4>;
|
interrupts = <1 15 6 4>, <1 15 7 4>;
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
aliases {
|
aliases {
|
||||||
i2c0 = &i2c0;
|
i2c0 = &i2c0;
|
||||||
pinctrl0 = &pinctrl0;
|
pinctrl0 = &pinctrl0;
|
||||||
|
serial0 = &uart0;
|
||||||
|
serial1 = &uart1;
|
||||||
|
serial2 = &uart2;
|
||||||
|
serial3 = &uart3;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
|
|
|
@ -2347,8 +2347,6 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
|
||||||
printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
|
printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
|
||||||
__FILE__, __LINE__, info->device_name, port->count);
|
__FILE__, __LINE__, info->device_name, port->count);
|
||||||
|
|
||||||
WARN_ON(!port->count);
|
|
||||||
|
|
||||||
if (tty_port_close_start(port, tty, filp) == 0)
|
if (tty_port_close_start(port, tty, filp) == 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -2510,7 +2508,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
|
||||||
__FILE__, __LINE__, tty->driver->name, port->count);
|
__FILE__, __LINE__, tty->driver->name, port->count);
|
||||||
|
|
||||||
/* If port is closing, signal caller to try again */
|
/* If port is closing, signal caller to try again */
|
||||||
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
|
if (port->flags & ASYNC_CLOSING){
|
||||||
wait_event_interruptible_tty(tty, port->close_wait,
|
wait_event_interruptible_tty(tty, port->close_wait,
|
||||||
!(port->flags & ASYNC_CLOSING));
|
!(port->flags & ASYNC_CLOSING));
|
||||||
retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
|
retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
|
||||||
|
|
|
@ -1579,7 +1579,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
|
||||||
/*
|
/*
|
||||||
* If the port is the middle of closing, bail out now
|
* If the port is the middle of closing, bail out now
|
||||||
*/
|
*/
|
||||||
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
|
if (info->port.flags & ASYNC_CLOSING) {
|
||||||
wait_event_interruptible_tty(tty, info->port.close_wait,
|
wait_event_interruptible_tty(tty, info->port.close_wait,
|
||||||
!(info->port.flags & ASYNC_CLOSING));
|
!(info->port.flags & ASYNC_CLOSING));
|
||||||
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
|
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
|
||||||
|
|
|
@ -93,11 +93,6 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
mutex_lock(&tty->ipw_tty_mutex);
|
mutex_lock(&tty->ipw_tty_mutex);
|
||||||
|
|
||||||
if (tty->closing) {
|
|
||||||
mutex_unlock(&tty->ipw_tty_mutex);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
if (tty->port.count == 0)
|
if (tty->port.count == 0)
|
||||||
tty->tx_bytes_queued = 0;
|
tty->tx_bytes_queued = 0;
|
||||||
|
|
||||||
|
|
|
@ -2088,9 +2088,7 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
|
||||||
struct gsm_dlci *dlci;
|
struct gsm_dlci *dlci;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
init_timer(&gsm->t2_timer);
|
setup_timer(&gsm->t2_timer, gsm_control_retransmit, (unsigned long)gsm);
|
||||||
gsm->t2_timer.function = gsm_control_retransmit;
|
|
||||||
gsm->t2_timer.data = (unsigned long)gsm;
|
|
||||||
init_waitqueue_head(&gsm->event);
|
init_waitqueue_head(&gsm->event);
|
||||||
spin_lock_init(&gsm->control_lock);
|
spin_lock_init(&gsm->control_lock);
|
||||||
spin_lock_init(&gsm->tx_lock);
|
spin_lock_init(&gsm->tx_lock);
|
||||||
|
@ -2230,8 +2228,7 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
|
||||||
|
|
||||||
static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
|
static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i, base;
|
||||||
int base = gsm->num << 6; /* Base for this MUX */
|
|
||||||
|
|
||||||
gsm->tty = tty_kref_get(tty);
|
gsm->tty = tty_kref_get(tty);
|
||||||
gsm->output = gsmld_output;
|
gsm->output = gsmld_output;
|
||||||
|
@ -2241,6 +2238,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
|
||||||
else {
|
else {
|
||||||
/* Don't register device 0 - this is the control channel and not
|
/* Don't register device 0 - this is the control channel and not
|
||||||
a usable tty interface */
|
a usable tty interface */
|
||||||
|
base = gsm->num << 6; /* Base for this MUX */
|
||||||
for (i = 1; i < NUM_DLCI; i++)
|
for (i = 1; i < NUM_DLCI; i++)
|
||||||
tty_register_device(gsm_tty_driver, base + i, NULL);
|
tty_register_device(gsm_tty_driver, base + i, NULL);
|
||||||
}
|
}
|
||||||
|
@ -2368,6 +2366,7 @@ static void gsmld_close(struct tty_struct *tty)
|
||||||
static int gsmld_open(struct tty_struct *tty)
|
static int gsmld_open(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct gsm_mux *gsm;
|
struct gsm_mux *gsm;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (tty->ops->write == NULL)
|
if (tty->ops->write == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -2382,7 +2381,13 @@ static int gsmld_open(struct tty_struct *tty)
|
||||||
|
|
||||||
/* Attach the initial passive connection */
|
/* Attach the initial passive connection */
|
||||||
gsm->encoding = 1;
|
gsm->encoding = 1;
|
||||||
return gsmld_attach_gsm(tty, gsm);
|
|
||||||
|
ret = gsmld_attach_gsm(tty, gsm);
|
||||||
|
if (ret != 0) {
|
||||||
|
gsm_cleanup_mux(gsm);
|
||||||
|
mux_put(gsm);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -316,7 +316,7 @@ done:
|
||||||
* pty_common_install - set up the pty pair
|
* pty_common_install - set up the pty pair
|
||||||
* @driver: the pty driver
|
* @driver: the pty driver
|
||||||
* @tty: the tty being instantiated
|
* @tty: the tty being instantiated
|
||||||
* @bool: legacy, true if this is BSD style
|
* @legacy: true if this is BSD style
|
||||||
*
|
*
|
||||||
* Perform the initial set up for the tty/pty pair. Called from the
|
* Perform the initial set up for the tty/pty pair. Called from the
|
||||||
* tty layer when the port is first opened.
|
* tty layer when the port is first opened.
|
||||||
|
@ -331,18 +331,17 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
|
||||||
int idx = tty->index;
|
int idx = tty->index;
|
||||||
int retval = -ENOMEM;
|
int retval = -ENOMEM;
|
||||||
|
|
||||||
o_tty = alloc_tty_struct();
|
|
||||||
if (!o_tty)
|
|
||||||
goto err;
|
|
||||||
ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
|
ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
|
||||||
ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
|
ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
|
||||||
if (!ports[0] || !ports[1])
|
if (!ports[0] || !ports[1])
|
||||||
goto err_free_tty;
|
goto err;
|
||||||
if (!try_module_get(driver->other->owner)) {
|
if (!try_module_get(driver->other->owner)) {
|
||||||
/* This cannot in fact currently happen */
|
/* This cannot in fact currently happen */
|
||||||
goto err_free_tty;
|
goto err;
|
||||||
}
|
}
|
||||||
initialize_tty_struct(o_tty, driver->other, idx);
|
o_tty = alloc_tty_struct(driver->other, idx);
|
||||||
|
if (!o_tty)
|
||||||
|
goto err_put_module;
|
||||||
|
|
||||||
if (legacy) {
|
if (legacy) {
|
||||||
/* We always use new tty termios data so we can do this
|
/* We always use new tty termios data so we can do this
|
||||||
|
@ -387,12 +386,12 @@ err_free_termios:
|
||||||
tty_free_termios(tty);
|
tty_free_termios(tty);
|
||||||
err_deinit_tty:
|
err_deinit_tty:
|
||||||
deinitialize_tty_struct(o_tty);
|
deinitialize_tty_struct(o_tty);
|
||||||
module_put(o_tty->driver->owner);
|
free_tty_struct(o_tty);
|
||||||
err_free_tty:
|
err_put_module:
|
||||||
|
module_put(driver->other->owner);
|
||||||
|
err:
|
||||||
kfree(ports[0]);
|
kfree(ports[0]);
|
||||||
kfree(ports[1]);
|
kfree(ports[1]);
|
||||||
free_tty_struct(o_tty);
|
|
||||||
err:
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,10 +78,6 @@ static void serial21285_stop_rx(struct uart_port *port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial21285_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
|
static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct uart_port *port = dev_id;
|
struct uart_port *port = dev_id;
|
||||||
|
@ -345,7 +341,6 @@ static struct uart_ops serial21285_ops = {
|
||||||
.stop_tx = serial21285_stop_tx,
|
.stop_tx = serial21285_stop_tx,
|
||||||
.start_tx = serial21285_start_tx,
|
.start_tx = serial21285_start_tx,
|
||||||
.stop_rx = serial21285_stop_rx,
|
.stop_rx = serial21285_stop_rx,
|
||||||
.enable_ms = serial21285_enable_ms,
|
|
||||||
.break_ctl = serial21285_break_ctl,
|
.break_ctl = serial21285_break_ctl,
|
||||||
.startup = serial21285_startup,
|
.startup = serial21285_startup,
|
||||||
.shutdown = serial21285_shutdown,
|
.shutdown = serial21285_shutdown,
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/serial_8250.h>
|
#include <linux/serial_8250.h>
|
||||||
|
#include <linux/serial_reg.h>
|
||||||
#include <linux/dmaengine.h>
|
#include <linux/dmaengine.h>
|
||||||
|
|
||||||
struct uart_8250_dma {
|
struct uart_8250_dma {
|
||||||
|
@ -60,6 +61,7 @@ struct serial8250_config {
|
||||||
unsigned short fifo_size;
|
unsigned short fifo_size;
|
||||||
unsigned short tx_loadsz;
|
unsigned short tx_loadsz;
|
||||||
unsigned char fcr;
|
unsigned char fcr;
|
||||||
|
unsigned char rxtrig_bytes[UART_FCR_R_TRIG_MAX_STATE];
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/serial_reg.h>
|
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/serial_8250.h>
|
#include <linux/serial_8250.h>
|
||||||
|
@ -161,6 +160,7 @@ static const struct serial8250_config uart_config[] = {
|
||||||
.fifo_size = 16,
|
.fifo_size = 16,
|
||||||
.tx_loadsz = 16,
|
.tx_loadsz = 16,
|
||||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
||||||
|
.rxtrig_bytes = {1, 4, 8, 14},
|
||||||
.flags = UART_CAP_FIFO,
|
.flags = UART_CAP_FIFO,
|
||||||
},
|
},
|
||||||
[PORT_CIRRUS] = {
|
[PORT_CIRRUS] = {
|
||||||
|
@ -180,6 +180,7 @@ static const struct serial8250_config uart_config[] = {
|
||||||
.tx_loadsz = 16,
|
.tx_loadsz = 16,
|
||||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
|
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
|
||||||
UART_FCR_T_TRIG_00,
|
UART_FCR_T_TRIG_00,
|
||||||
|
.rxtrig_bytes = {8, 16, 24, 28},
|
||||||
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
|
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
|
||||||
},
|
},
|
||||||
[PORT_16750] = {
|
[PORT_16750] = {
|
||||||
|
@ -188,6 +189,7 @@ static const struct serial8250_config uart_config[] = {
|
||||||
.tx_loadsz = 64,
|
.tx_loadsz = 64,
|
||||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
|
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
|
||||||
UART_FCR7_64BYTE,
|
UART_FCR7_64BYTE,
|
||||||
|
.rxtrig_bytes = {1, 16, 32, 56},
|
||||||
.flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
|
.flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
|
||||||
},
|
},
|
||||||
[PORT_STARTECH] = {
|
[PORT_STARTECH] = {
|
||||||
|
@ -209,6 +211,7 @@ static const struct serial8250_config uart_config[] = {
|
||||||
.tx_loadsz = 32,
|
.tx_loadsz = 32,
|
||||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
|
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
|
||||||
UART_FCR_T_TRIG_10,
|
UART_FCR_T_TRIG_10,
|
||||||
|
.rxtrig_bytes = {8, 16, 56, 60},
|
||||||
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
|
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
|
||||||
},
|
},
|
||||||
[PORT_16850] = {
|
[PORT_16850] = {
|
||||||
|
@ -266,6 +269,7 @@ static const struct serial8250_config uart_config[] = {
|
||||||
.tx_loadsz = 8,
|
.tx_loadsz = 8,
|
||||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
|
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
|
||||||
UART_FCR_T_TRIG_01,
|
UART_FCR_T_TRIG_01,
|
||||||
|
.rxtrig_bytes = {1, 4, 8, 14},
|
||||||
.flags = UART_CAP_FIFO | UART_CAP_RTOIE,
|
.flags = UART_CAP_FIFO | UART_CAP_RTOIE,
|
||||||
},
|
},
|
||||||
[PORT_XR17D15X] = {
|
[PORT_XR17D15X] = {
|
||||||
|
@ -439,8 +443,7 @@ static int exar_handle_irq(struct uart_port *port);
|
||||||
|
|
||||||
static void set_io_from_upio(struct uart_port *p)
|
static void set_io_from_upio(struct uart_port *p)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(p);
|
||||||
container_of(p, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
up->dl_read = default_serial_dl_read;
|
up->dl_read = default_serial_dl_read;
|
||||||
up->dl_write = default_serial_dl_write;
|
up->dl_write = default_serial_dl_write;
|
||||||
|
@ -531,11 +534,8 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
|
||||||
|
|
||||||
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
|
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
|
||||||
{
|
{
|
||||||
unsigned char fcr;
|
|
||||||
|
|
||||||
serial8250_clear_fifos(p);
|
serial8250_clear_fifos(p);
|
||||||
fcr = uart_config[p->port.type].fcr;
|
serial_out(p, UART_FCR, p->fcr);
|
||||||
serial_out(p, UART_FCR, fcr);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
|
EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
|
||||||
|
|
||||||
|
@ -1277,8 +1277,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
|
||||||
|
|
||||||
static void serial8250_stop_tx(struct uart_port *port)
|
static void serial8250_stop_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
__stop_tx(up);
|
__stop_tx(up);
|
||||||
|
|
||||||
|
@ -1293,8 +1292,7 @@ static void serial8250_stop_tx(struct uart_port *port)
|
||||||
|
|
||||||
static void serial8250_start_tx(struct uart_port *port)
|
static void serial8250_start_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
if (up->dma && !serial8250_tx_dma(up)) {
|
if (up->dma && !serial8250_tx_dma(up)) {
|
||||||
return;
|
return;
|
||||||
|
@ -1322,8 +1320,7 @@ static void serial8250_start_tx(struct uart_port *port)
|
||||||
|
|
||||||
static void serial8250_stop_rx(struct uart_port *port)
|
static void serial8250_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
up->ier &= ~UART_IER_RLSI;
|
up->ier &= ~UART_IER_RLSI;
|
||||||
up->port.read_status_mask &= ~UART_LSR_DR;
|
up->port.read_status_mask &= ~UART_LSR_DR;
|
||||||
|
@ -1332,8 +1329,7 @@ static void serial8250_stop_rx(struct uart_port *port)
|
||||||
|
|
||||||
static void serial8250_enable_ms(struct uart_port *port)
|
static void serial8250_enable_ms(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
/* no MSR capabilities */
|
/* no MSR capabilities */
|
||||||
if (up->bugs & UART_BUG_NOMSR)
|
if (up->bugs & UART_BUG_NOMSR)
|
||||||
|
@ -1499,8 +1495,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
|
||||||
{
|
{
|
||||||
unsigned char status;
|
unsigned char status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
int dma_err = 0;
|
int dma_err = 0;
|
||||||
|
|
||||||
if (iir & UART_IIR_NO_INT)
|
if (iir & UART_IIR_NO_INT)
|
||||||
|
@ -1785,8 +1780,7 @@ static void serial8250_backup_timeout(unsigned long data)
|
||||||
|
|
||||||
static unsigned int serial8250_tx_empty(struct uart_port *port)
|
static unsigned int serial8250_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int lsr;
|
unsigned int lsr;
|
||||||
|
|
||||||
|
@ -1800,8 +1794,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
|
||||||
|
|
||||||
static unsigned int serial8250_get_mctrl(struct uart_port *port)
|
static unsigned int serial8250_get_mctrl(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
unsigned int ret;
|
unsigned int ret;
|
||||||
|
|
||||||
|
@ -1821,8 +1814,7 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
|
||||||
|
|
||||||
static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
unsigned char mcr = 0;
|
unsigned char mcr = 0;
|
||||||
|
|
||||||
if (mctrl & TIOCM_RTS)
|
if (mctrl & TIOCM_RTS)
|
||||||
|
@ -1843,8 +1835,7 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
|
|
||||||
static void serial8250_break_ctl(struct uart_port *port, int break_state)
|
static void serial8250_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
@ -1911,8 +1902,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
|
||||||
unsigned char c)
|
unsigned char c)
|
||||||
{
|
{
|
||||||
unsigned int ier;
|
unsigned int ier;
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First save the IER then disable the interrupts
|
* First save the IER then disable the interrupts
|
||||||
|
@ -1941,8 +1931,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
|
||||||
|
|
||||||
static int serial8250_startup(struct uart_port *port)
|
static int serial8250_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned char lsr, iir;
|
unsigned char lsr, iir;
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -2194,8 +2183,7 @@ dont_test_tx_en:
|
||||||
|
|
||||||
static void serial8250_shutdown(struct uart_port *port)
|
static void serial8250_shutdown(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2268,12 +2256,10 @@ void
|
||||||
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
struct ktermios *old)
|
struct ktermios *old)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
unsigned char cval;
|
||||||
unsigned char cval, fcr = 0;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int baud, quot;
|
unsigned int baud, quot;
|
||||||
int fifo_bug = 0;
|
|
||||||
|
|
||||||
switch (termios->c_cflag & CSIZE) {
|
switch (termios->c_cflag & CSIZE) {
|
||||||
case CS5:
|
case CS5:
|
||||||
|
@ -2296,7 +2282,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
if (termios->c_cflag & PARENB) {
|
if (termios->c_cflag & PARENB) {
|
||||||
cval |= UART_LCR_PARITY;
|
cval |= UART_LCR_PARITY;
|
||||||
if (up->bugs & UART_BUG_PARITY)
|
if (up->bugs & UART_BUG_PARITY)
|
||||||
fifo_bug = 1;
|
up->fifo_bug = true;
|
||||||
}
|
}
|
||||||
if (!(termios->c_cflag & PARODD))
|
if (!(termios->c_cflag & PARODD))
|
||||||
cval |= UART_LCR_EPAR;
|
cval |= UART_LCR_EPAR;
|
||||||
|
@ -2320,10 +2306,10 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
quot++;
|
quot++;
|
||||||
|
|
||||||
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
|
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
|
||||||
fcr = uart_config[port->type].fcr;
|
/* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
|
||||||
if ((baud < 2400 && !up->dma) || fifo_bug) {
|
if ((baud < 2400 && !up->dma) || up->fifo_bug) {
|
||||||
fcr &= ~UART_FCR_TRIGGER_MASK;
|
up->fcr &= ~UART_FCR_TRIGGER_MASK;
|
||||||
fcr |= UART_FCR_TRIGGER_1;
|
up->fcr |= UART_FCR_TRIGGER_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2456,15 +2442,15 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
* is written without DLAB set, this mode will be disabled.
|
* is written without DLAB set, this mode will be disabled.
|
||||||
*/
|
*/
|
||||||
if (port->type == PORT_16750)
|
if (port->type == PORT_16750)
|
||||||
serial_port_out(port, UART_FCR, fcr);
|
serial_port_out(port, UART_FCR, up->fcr);
|
||||||
|
|
||||||
serial_port_out(port, UART_LCR, cval); /* reset DLAB */
|
serial_port_out(port, UART_LCR, cval); /* reset DLAB */
|
||||||
up->lcr = cval; /* Save LCR */
|
up->lcr = cval; /* Save LCR */
|
||||||
if (port->type != PORT_16750) {
|
if (port->type != PORT_16750) {
|
||||||
/* emulated UARTs (Lucent Venus 167x) need two steps */
|
/* emulated UARTs (Lucent Venus 167x) need two steps */
|
||||||
if (fcr & UART_FCR_ENABLE_FIFO)
|
if (up->fcr & UART_FCR_ENABLE_FIFO)
|
||||||
serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
|
serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
|
||||||
serial_port_out(port, UART_FCR, fcr); /* set fcr */
|
serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
|
||||||
}
|
}
|
||||||
serial8250_set_mctrl(port, port->mctrl);
|
serial8250_set_mctrl(port, port->mctrl);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
@ -2498,8 +2484,7 @@ serial8250_set_ldisc(struct uart_port *port, int new)
|
||||||
void serial8250_do_pm(struct uart_port *port, unsigned int state,
|
void serial8250_do_pm(struct uart_port *port, unsigned int state,
|
||||||
unsigned int oldstate)
|
unsigned int oldstate)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *p =
|
struct uart_8250_port *p = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
serial8250_set_sleep(p, state != 0);
|
serial8250_set_sleep(p, state != 0);
|
||||||
}
|
}
|
||||||
|
@ -2630,8 +2615,7 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
|
||||||
|
|
||||||
static void serial8250_release_port(struct uart_port *port)
|
static void serial8250_release_port(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
serial8250_release_std_resource(up);
|
serial8250_release_std_resource(up);
|
||||||
if (port->type == PORT_RSA)
|
if (port->type == PORT_RSA)
|
||||||
|
@ -2640,8 +2624,7 @@ static void serial8250_release_port(struct uart_port *port)
|
||||||
|
|
||||||
static int serial8250_request_port(struct uart_port *port)
|
static int serial8250_request_port(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (port->type == PORT_8250_CIR)
|
if (port->type == PORT_8250_CIR)
|
||||||
|
@ -2657,10 +2640,149 @@ static int serial8250_request_port(struct uart_port *port)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
|
||||||
|
{
|
||||||
|
const struct serial8250_config *conf_type = &uart_config[up->port.type];
|
||||||
|
unsigned char bytes;
|
||||||
|
|
||||||
|
bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
|
||||||
|
|
||||||
|
return bytes ? bytes : -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
|
||||||
|
{
|
||||||
|
const struct serial8250_config *conf_type = &uart_config[up->port.type];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
|
||||||
|
if (bytes < conf_type->rxtrig_bytes[i])
|
||||||
|
/* Use the nearest lower value */
|
||||||
|
return (--i) << UART_FCR_R_TRIG_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UART_FCR_R_TRIG_11;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_get_rxtrig(struct tty_port *port)
|
||||||
|
{
|
||||||
|
struct uart_state *state = container_of(port, struct uart_state, port);
|
||||||
|
struct uart_port *uport = state->uart_port;
|
||||||
|
struct uart_8250_port *up =
|
||||||
|
container_of(uport, struct uart_8250_port, port);
|
||||||
|
|
||||||
|
if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return fcr_get_rxtrig_bytes(up);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_serial8250_get_rxtrig(struct tty_port *port)
|
||||||
|
{
|
||||||
|
int rxtrig_bytes;
|
||||||
|
|
||||||
|
mutex_lock(&port->mutex);
|
||||||
|
rxtrig_bytes = do_get_rxtrig(port);
|
||||||
|
mutex_unlock(&port->mutex);
|
||||||
|
|
||||||
|
return rxtrig_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct tty_port *port = dev_get_drvdata(dev);
|
||||||
|
int rxtrig_bytes;
|
||||||
|
|
||||||
|
rxtrig_bytes = do_serial8250_get_rxtrig(port);
|
||||||
|
if (rxtrig_bytes < 0)
|
||||||
|
return rxtrig_bytes;
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
|
||||||
|
{
|
||||||
|
struct uart_state *state = container_of(port, struct uart_state, port);
|
||||||
|
struct uart_port *uport = state->uart_port;
|
||||||
|
struct uart_8250_port *up =
|
||||||
|
container_of(uport, struct uart_8250_port, port);
|
||||||
|
int rxtrig;
|
||||||
|
|
||||||
|
if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
|
||||||
|
up->fifo_bug)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
rxtrig = bytes_to_fcr_rxtrig(up, bytes);
|
||||||
|
if (rxtrig < 0)
|
||||||
|
return rxtrig;
|
||||||
|
|
||||||
|
serial8250_clear_fifos(up);
|
||||||
|
up->fcr &= ~UART_FCR_TRIGGER_MASK;
|
||||||
|
up->fcr |= (unsigned char)rxtrig;
|
||||||
|
serial_out(up, UART_FCR, up->fcr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&port->mutex);
|
||||||
|
ret = do_set_rxtrig(port, bytes);
|
||||||
|
mutex_unlock(&port->mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
|
||||||
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct tty_port *port = dev_get_drvdata(dev);
|
||||||
|
unsigned char bytes;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!count)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = kstrtou8(buf, 10, &bytes);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = do_serial8250_set_rxtrig(port, bytes);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
|
||||||
|
serial8250_get_attr_rx_trig_bytes,
|
||||||
|
serial8250_set_attr_rx_trig_bytes);
|
||||||
|
|
||||||
|
static struct attribute *serial8250_dev_attrs[] = {
|
||||||
|
&dev_attr_rx_trig_bytes.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group serial8250_dev_attr_group = {
|
||||||
|
.attrs = serial8250_dev_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void register_dev_spec_attr_grp(struct uart_8250_port *up)
|
||||||
|
{
|
||||||
|
const struct serial8250_config *conf_type = &uart_config[up->port.type];
|
||||||
|
|
||||||
|
if (conf_type->rxtrig_bytes[0])
|
||||||
|
up->port.attr_group = &serial8250_dev_attr_group;
|
||||||
|
}
|
||||||
|
|
||||||
static void serial8250_config_port(struct uart_port *port, int flags)
|
static void serial8250_config_port(struct uart_port *port, int flags)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
int probeflags = PROBE_ANY;
|
int probeflags = PROBE_ANY;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -2705,6 +2827,9 @@ static void serial8250_config_port(struct uart_port *port, int flags)
|
||||||
if ((port->type == PORT_XR17V35X) ||
|
if ((port->type == PORT_XR17V35X) ||
|
||||||
(port->type == PORT_XR17D15X))
|
(port->type == PORT_XR17D15X))
|
||||||
port->handle_irq = exar_handle_irq;
|
port->handle_irq = exar_handle_irq;
|
||||||
|
|
||||||
|
register_dev_spec_attr_grp(up);
|
||||||
|
up->fcr = uart_config[up->port.type].fcr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -2859,8 +2984,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
|
||||||
|
|
||||||
static void serial8250_console_putchar(struct uart_port *port, int ch)
|
static void serial8250_console_putchar(struct uart_port *port, int ch)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
wait_for_xmitr(up, UART_LSR_THRE);
|
wait_for_xmitr(up, UART_LSR_THRE);
|
||||||
serial_port_out(port, UART_TX, ch);
|
serial_port_out(port, UART_TX, ch);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
@ -59,73 +60,17 @@ struct dw8250_data {
|
||||||
int last_mcr;
|
int last_mcr;
|
||||||
int line;
|
int line;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
struct clk *pclk;
|
||||||
|
struct reset_control *rst;
|
||||||
struct uart_8250_dma dma;
|
struct uart_8250_dma dma;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dw8250_acpi_desc {
|
|
||||||
void (*set_termios)(struct uart_port *p, struct ktermios *termios,
|
|
||||||
struct ktermios *old);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BYT_PRV_CLK 0x800
|
#define BYT_PRV_CLK 0x800
|
||||||
#define BYT_PRV_CLK_EN (1 << 0)
|
#define BYT_PRV_CLK_EN (1 << 0)
|
||||||
#define BYT_PRV_CLK_M_VAL_SHIFT 1
|
#define BYT_PRV_CLK_M_VAL_SHIFT 1
|
||||||
#define BYT_PRV_CLK_N_VAL_SHIFT 16
|
#define BYT_PRV_CLK_N_VAL_SHIFT 16
|
||||||
#define BYT_PRV_CLK_UPDATE (1 << 31)
|
#define BYT_PRV_CLK_UPDATE (1 << 31)
|
||||||
|
|
||||||
static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
|
|
||||||
struct ktermios *old)
|
|
||||||
{
|
|
||||||
unsigned int baud = tty_termios_baud_rate(termios);
|
|
||||||
unsigned int m, n;
|
|
||||||
u32 reg;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
n = 100;
|
|
||||||
p->uartclk = 64000000;
|
|
||||||
break;
|
|
||||||
case 3500000:
|
|
||||||
m = 56;
|
|
||||||
n = 100;
|
|
||||||
p->uartclk = 56000000;
|
|
||||||
break;
|
|
||||||
case 1500000:
|
|
||||||
case 3000000:
|
|
||||||
m = 48;
|
|
||||||
n = 100;
|
|
||||||
p->uartclk = 48000000;
|
|
||||||
break;
|
|
||||||
case 2500000:
|
|
||||||
m = 40;
|
|
||||||
n = 100;
|
|
||||||
p->uartclk = 40000000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
m = 2304;
|
|
||||||
n = 3125;
|
|
||||||
p->uartclk = 73728000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset the clock */
|
|
||||||
reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
|
|
||||||
writel(reg, p->membase + BYT_PRV_CLK);
|
|
||||||
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
|
|
||||||
writel(reg, p->membase + BYT_PRV_CLK);
|
|
||||||
|
|
||||||
serial8250_do_set_termios(p, termios, old);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
|
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
|
||||||
{
|
{
|
||||||
struct dw8250_data *d = p->private_data;
|
struct dw8250_data *d = p->private_data;
|
||||||
|
@ -141,8 +86,9 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
|
||||||
|
|
||||||
static void dw8250_force_idle(struct uart_port *p)
|
static void dw8250_force_idle(struct uart_port *p)
|
||||||
{
|
{
|
||||||
serial8250_clear_and_reinit_fifos(container_of
|
struct uart_8250_port *up = up_to_u8250p(p);
|
||||||
(p, struct uart_8250_port, port));
|
|
||||||
|
serial8250_clear_and_reinit_fifos(up);
|
||||||
(void)p->serial_in(p, UART_RX);
|
(void)p->serial_in(p, UART_RX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,6 +188,32 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
|
||||||
pm_runtime_put_sync_suspend(port->dev);
|
pm_runtime_put_sync_suspend(port->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||||
|
struct ktermios *old)
|
||||||
|
{
|
||||||
|
unsigned int baud = tty_termios_baud_rate(termios);
|
||||||
|
struct dw8250_data *d = p->private_data;
|
||||||
|
unsigned int rate;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (IS_ERR(d->clk) || !old)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Not requesting clock rates below 1.8432Mhz */
|
||||||
|
if (baud < 115200)
|
||||||
|
baud = 115200;
|
||||||
|
|
||||||
|
clk_disable_unprepare(d->clk);
|
||||||
|
rate = clk_round_rate(d->clk, baud * 16);
|
||||||
|
ret = clk_set_rate(d->clk, rate);
|
||||||
|
clk_prepare_enable(d->clk);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
p->uartclk = rate;
|
||||||
|
out:
|
||||||
|
serial8250_do_set_termios(p, termios, old);
|
||||||
|
}
|
||||||
|
|
||||||
static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
|
static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
|
||||||
{
|
{
|
||||||
struct dw8250_data *data = param;
|
struct dw8250_data *data = param;
|
||||||
|
@ -286,6 +258,7 @@ static int dw8250_probe_of(struct uart_port *p,
|
||||||
struct dw8250_data *data)
|
struct dw8250_data *data)
|
||||||
{
|
{
|
||||||
struct device_node *np = p->dev->of_node;
|
struct device_node *np = p->dev->of_node;
|
||||||
|
struct uart_8250_port *up = up_to_u8250p(p);
|
||||||
u32 val;
|
u32 val;
|
||||||
bool has_ucv = true;
|
bool has_ucv = true;
|
||||||
|
|
||||||
|
@ -299,7 +272,7 @@ static int dw8250_probe_of(struct uart_port *p,
|
||||||
p->membase += 7;
|
p->membase += 7;
|
||||||
#endif
|
#endif
|
||||||
p->serial_out = dw8250_serial_out_rb;
|
p->serial_out = dw8250_serial_out_rb;
|
||||||
p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
||||||
p->type = PORT_OCTEON;
|
p->type = PORT_OCTEON;
|
||||||
data->usr_reg = 0x27;
|
data->usr_reg = 0x27;
|
||||||
has_ucv = false;
|
has_ucv = false;
|
||||||
|
@ -318,7 +291,7 @@ static int dw8250_probe_of(struct uart_port *p,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (has_ucv)
|
if (has_ucv)
|
||||||
dw8250_setup_port(container_of(p, struct uart_8250_port, port));
|
dw8250_setup_port(up);
|
||||||
|
|
||||||
if (!of_property_read_u32(np, "reg-shift", &val))
|
if (!of_property_read_u32(np, "reg-shift", &val))
|
||||||
p->regshift = val;
|
p->regshift = val;
|
||||||
|
@ -340,16 +313,10 @@ static int dw8250_probe_of(struct uart_port *p,
|
||||||
static int dw8250_probe_acpi(struct uart_8250_port *up,
|
static int dw8250_probe_acpi(struct uart_8250_port *up,
|
||||||
struct dw8250_data *data)
|
struct dw8250_data *data)
|
||||||
{
|
{
|
||||||
const struct acpi_device_id *id;
|
|
||||||
struct uart_port *p = &up->port;
|
struct uart_port *p = &up->port;
|
||||||
struct dw8250_acpi_desc *acpi_desc;
|
|
||||||
|
|
||||||
dw8250_setup_port(up);
|
dw8250_setup_port(up);
|
||||||
|
|
||||||
id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
|
|
||||||
if (!id)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
p->iotype = UPIO_MEM32;
|
p->iotype = UPIO_MEM32;
|
||||||
p->serial_in = dw8250_serial_in32;
|
p->serial_in = dw8250_serial_in32;
|
||||||
p->serial_out = dw8250_serial_out32;
|
p->serial_out = dw8250_serial_out32;
|
||||||
|
@ -360,12 +327,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
|
||||||
up->dma->rxconf.src_maxburst = p->fifosize / 4;
|
up->dma->rxconf.src_maxburst = p->fifosize / 4;
|
||||||
up->dma->txconf.dst_maxburst = p->fifosize / 4;
|
up->dma->txconf.dst_maxburst = p->fifosize / 4;
|
||||||
|
|
||||||
acpi_desc = (struct dw8250_acpi_desc *)id->driver_data;
|
up->port.set_termios = dw8250_set_termios;
|
||||||
if (!acpi_desc)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (acpi_desc->set_termios)
|
|
||||||
p->set_termios = acpi_desc->set_termios;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -402,12 +364,41 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
data->usr_reg = DW_UART_USR;
|
data->usr_reg = DW_UART_USR;
|
||||||
data->clk = devm_clk_get(&pdev->dev, NULL);
|
data->clk = devm_clk_get(&pdev->dev, "baudclk");
|
||||||
|
if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER)
|
||||||
|
data->clk = devm_clk_get(&pdev->dev, NULL);
|
||||||
|
if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER)
|
||||||
|
return -EPROBE_DEFER;
|
||||||
if (!IS_ERR(data->clk)) {
|
if (!IS_ERR(data->clk)) {
|
||||||
clk_prepare_enable(data->clk);
|
err = clk_prepare_enable(data->clk);
|
||||||
uart.port.uartclk = clk_get_rate(data->clk);
|
if (err)
|
||||||
|
dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
|
||||||
|
err);
|
||||||
|
else
|
||||||
|
uart.port.uartclk = clk_get_rate(data->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
|
||||||
|
if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) {
|
||||||
|
err = -EPROBE_DEFER;
|
||||||
|
goto err_clk;
|
||||||
|
}
|
||||||
|
if (!IS_ERR(data->pclk)) {
|
||||||
|
err = clk_prepare_enable(data->pclk);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&pdev->dev, "could not enable apb_pclk\n");
|
||||||
|
goto err_clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->rst = devm_reset_control_get_optional(&pdev->dev, NULL);
|
||||||
|
if (IS_ERR(data->rst) && PTR_ERR(data->rst) == -EPROBE_DEFER) {
|
||||||
|
err = -EPROBE_DEFER;
|
||||||
|
goto err_pclk;
|
||||||
|
}
|
||||||
|
if (!IS_ERR(data->rst))
|
||||||
|
reset_control_deassert(data->rst);
|
||||||
|
|
||||||
data->dma.rx_chan_id = -1;
|
data->dma.rx_chan_id = -1;
|
||||||
data->dma.tx_chan_id = -1;
|
data->dma.tx_chan_id = -1;
|
||||||
data->dma.rx_param = data;
|
data->dma.rx_param = data;
|
||||||
|
@ -422,18 +413,21 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||||
if (pdev->dev.of_node) {
|
if (pdev->dev.of_node) {
|
||||||
err = dw8250_probe_of(&uart.port, data);
|
err = dw8250_probe_of(&uart.port, data);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto err_reset;
|
||||||
} else if (ACPI_HANDLE(&pdev->dev)) {
|
} else if (ACPI_HANDLE(&pdev->dev)) {
|
||||||
err = dw8250_probe_acpi(&uart, data);
|
err = dw8250_probe_acpi(&uart, data);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto err_reset;
|
||||||
} else {
|
} else {
|
||||||
return -ENODEV;
|
err = -ENODEV;
|
||||||
|
goto err_reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->line = serial8250_register_8250_port(&uart);
|
data->line = serial8250_register_8250_port(&uart);
|
||||||
if (data->line < 0)
|
if (data->line < 0) {
|
||||||
return data->line;
|
err = data->line;
|
||||||
|
goto err_reset;
|
||||||
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, data);
|
platform_set_drvdata(pdev, data);
|
||||||
|
|
||||||
|
@ -441,6 +435,20 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||||
pm_runtime_enable(&pdev->dev);
|
pm_runtime_enable(&pdev->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_reset:
|
||||||
|
if (!IS_ERR(data->rst))
|
||||||
|
reset_control_assert(data->rst);
|
||||||
|
|
||||||
|
err_pclk:
|
||||||
|
if (!IS_ERR(data->pclk))
|
||||||
|
clk_disable_unprepare(data->pclk);
|
||||||
|
|
||||||
|
err_clk:
|
||||||
|
if (!IS_ERR(data->clk))
|
||||||
|
clk_disable_unprepare(data->clk);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dw8250_remove(struct platform_device *pdev)
|
static int dw8250_remove(struct platform_device *pdev)
|
||||||
|
@ -451,6 +459,12 @@ static int dw8250_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
serial8250_unregister_port(data->line);
|
serial8250_unregister_port(data->line);
|
||||||
|
|
||||||
|
if (!IS_ERR(data->rst))
|
||||||
|
reset_control_assert(data->rst);
|
||||||
|
|
||||||
|
if (!IS_ERR(data->pclk))
|
||||||
|
clk_disable_unprepare(data->pclk);
|
||||||
|
|
||||||
if (!IS_ERR(data->clk))
|
if (!IS_ERR(data->clk))
|
||||||
clk_disable_unprepare(data->clk);
|
clk_disable_unprepare(data->clk);
|
||||||
|
|
||||||
|
@ -488,6 +502,9 @@ static int dw8250_runtime_suspend(struct device *dev)
|
||||||
if (!IS_ERR(data->clk))
|
if (!IS_ERR(data->clk))
|
||||||
clk_disable_unprepare(data->clk);
|
clk_disable_unprepare(data->clk);
|
||||||
|
|
||||||
|
if (!IS_ERR(data->pclk))
|
||||||
|
clk_disable_unprepare(data->pclk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,6 +512,9 @@ static int dw8250_runtime_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct dw8250_data *data = dev_get_drvdata(dev);
|
struct dw8250_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (!IS_ERR(data->pclk))
|
||||||
|
clk_prepare_enable(data->pclk);
|
||||||
|
|
||||||
if (!IS_ERR(data->clk))
|
if (!IS_ERR(data->clk))
|
||||||
clk_prepare_enable(data->clk);
|
clk_prepare_enable(data->clk);
|
||||||
|
|
||||||
|
@ -514,16 +534,12 @@ static const struct of_device_id dw8250_of_match[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
||||||
|
|
||||||
static struct dw8250_acpi_desc byt_8250_desc = {
|
|
||||||
.set_termios = byt_set_termios,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct acpi_device_id dw8250_acpi_match[] = {
|
static const struct acpi_device_id dw8250_acpi_match[] = {
|
||||||
{ "INT33C4", 0 },
|
{ "INT33C4", 0 },
|
||||||
{ "INT33C5", 0 },
|
{ "INT33C5", 0 },
|
||||||
{ "INT3434", 0 },
|
{ "INT3434", 0 },
|
||||||
{ "INT3435", 0 },
|
{ "INT3435", 0 },
|
||||||
{ "80860F0A", (kernel_ulong_t)&byt_8250_desc},
|
{ "80860F0A", 0 },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
|
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
|
||||||
|
|
|
@ -28,8 +28,7 @@ int fsl8250_handle_irq(struct uart_port *port)
|
||||||
unsigned char lsr, orig_lsr;
|
unsigned char lsr, orig_lsr;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int iir;
|
unsigned int iir;
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
container_of(port, struct uart_8250_port, port);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&up->port.lock, flags);
|
spin_lock_irqsave(&up->port.lock, flags);
|
||||||
|
|
||||||
|
|
|
@ -1581,8 +1581,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
|
||||||
|
|
||||||
static void kt_handle_break(struct uart_port *p)
|
static void kt_handle_break(struct uart_port *p)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(p);
|
||||||
container_of(p, struct uart_8250_port, port);
|
|
||||||
/*
|
/*
|
||||||
* On receipt of a BI, serial device in Intel ME (Intel
|
* On receipt of a BI, serial device in Intel ME (Intel
|
||||||
* management engine) needs to have its fifos cleared for sane
|
* management engine) needs to have its fifos cleared for sane
|
||||||
|
@ -1593,8 +1592,7 @@ static void kt_handle_break(struct uart_port *p)
|
||||||
|
|
||||||
static unsigned int kt_serial_in(struct uart_port *p, int offset)
|
static unsigned int kt_serial_in(struct uart_port *p, int offset)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up =
|
struct uart_8250_port *up = up_to_u8250p(p);
|
||||||
container_of(p, struct uart_8250_port, port);
|
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -238,7 +238,6 @@ config SERIAL_SAMSUNG_UARTS_4
|
||||||
config SERIAL_SAMSUNG_UARTS
|
config SERIAL_SAMSUNG_UARTS
|
||||||
int
|
int
|
||||||
depends on PLAT_SAMSUNG
|
depends on PLAT_SAMSUNG
|
||||||
default 6 if CPU_S5P6450
|
|
||||||
default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
|
default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
|
||||||
default 3
|
default 3
|
||||||
help
|
help
|
||||||
|
@ -774,7 +773,7 @@ config SERIAL_HS_LPC32XX
|
||||||
|
|
||||||
config SERIAL_HS_LPC32XX_CONSOLE
|
config SERIAL_HS_LPC32XX_CONSOLE
|
||||||
bool "Enable LPC32XX high speed UART serial console"
|
bool "Enable LPC32XX high speed UART serial console"
|
||||||
depends on SERIAL_HS_LPC32XX
|
depends on SERIAL_HS_LPC32XX=y
|
||||||
select SERIAL_CORE_CONSOLE
|
select SERIAL_CORE_CONSOLE
|
||||||
help
|
help
|
||||||
If you would like to be able to use one of the high speed serial
|
If you would like to be able to use one of the high speed serial
|
||||||
|
@ -1473,6 +1472,7 @@ config SERIAL_ARC_CONSOLE
|
||||||
bool "Console on ARC UART"
|
bool "Console on ARC UART"
|
||||||
depends on SERIAL_ARC=y
|
depends on SERIAL_ARC=y
|
||||||
select SERIAL_CORE_CONSOLE
|
select SERIAL_CORE_CONSOLE
|
||||||
|
select SERIAL_EARLYCON
|
||||||
help
|
help
|
||||||
Enable system Console on ARC UART
|
Enable system Console on ARC UART
|
||||||
|
|
||||||
|
|
|
@ -109,10 +109,6 @@ static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void altera_jtaguart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void altera_jtaguart_set_termios(struct uart_port *port,
|
static void altera_jtaguart_set_termios(struct uart_port *port,
|
||||||
struct ktermios *termios,
|
struct ktermios *termios,
|
||||||
struct ktermios *old)
|
struct ktermios *old)
|
||||||
|
@ -291,7 +287,6 @@ static struct uart_ops altera_jtaguart_ops = {
|
||||||
.start_tx = altera_jtaguart_start_tx,
|
.start_tx = altera_jtaguart_start_tx,
|
||||||
.stop_tx = altera_jtaguart_stop_tx,
|
.stop_tx = altera_jtaguart_stop_tx,
|
||||||
.stop_rx = altera_jtaguart_stop_rx,
|
.stop_rx = altera_jtaguart_stop_rx,
|
||||||
.enable_ms = altera_jtaguart_enable_ms,
|
|
||||||
.break_ctl = altera_jtaguart_break_ctl,
|
.break_ctl = altera_jtaguart_break_ctl,
|
||||||
.startup = altera_jtaguart_startup,
|
.startup = altera_jtaguart_startup,
|
||||||
.shutdown = altera_jtaguart_shutdown,
|
.shutdown = altera_jtaguart_shutdown,
|
||||||
|
@ -309,9 +304,8 @@ static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
|
||||||
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
|
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
|
||||||
|
|
||||||
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
|
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
|
||||||
static void altera_jtaguart_console_putc(struct console *co, const char c)
|
static void altera_jtaguart_console_putc(struct uart_port *port, int c)
|
||||||
{
|
{
|
||||||
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
|
|
||||||
unsigned long status;
|
unsigned long status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
@ -330,9 +324,8 @@ static void altera_jtaguart_console_putc(struct console *co, const char c)
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void altera_jtaguart_console_putc(struct console *co, const char c)
|
static void altera_jtaguart_console_putc(struct uart_port *port, int c)
|
||||||
{
|
{
|
||||||
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
@ -350,11 +343,9 @@ static void altera_jtaguart_console_putc(struct console *co, const char c)
|
||||||
static void altera_jtaguart_console_write(struct console *co, const char *s,
|
static void altera_jtaguart_console_write(struct console *co, const char *s,
|
||||||
unsigned int count)
|
unsigned int count)
|
||||||
{
|
{
|
||||||
for (; count; count--, s++) {
|
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
|
||||||
altera_jtaguart_console_putc(co, *s);
|
|
||||||
if (*s == '\n')
|
uart_console_write(port, s, count, altera_jtaguart_console_putc);
|
||||||
altera_jtaguart_console_putc(co, '\r');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init altera_jtaguart_console_setup(struct console *co,
|
static int __init altera_jtaguart_console_setup(struct console *co,
|
||||||
|
|
|
@ -163,10 +163,6 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state)
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void altera_uart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void altera_uart_set_termios(struct uart_port *port,
|
static void altera_uart_set_termios(struct uart_port *port,
|
||||||
struct ktermios *termios,
|
struct ktermios *termios,
|
||||||
struct ktermios *old)
|
struct ktermios *old)
|
||||||
|
@ -415,7 +411,6 @@ static struct uart_ops altera_uart_ops = {
|
||||||
.start_tx = altera_uart_start_tx,
|
.start_tx = altera_uart_start_tx,
|
||||||
.stop_tx = altera_uart_stop_tx,
|
.stop_tx = altera_uart_stop_tx,
|
||||||
.stop_rx = altera_uart_stop_rx,
|
.stop_rx = altera_uart_stop_rx,
|
||||||
.enable_ms = altera_uart_enable_ms,
|
|
||||||
.break_ctl = altera_uart_break_ctl,
|
.break_ctl = altera_uart_break_ctl,
|
||||||
.startup = altera_uart_startup,
|
.startup = altera_uart_startup,
|
||||||
.shutdown = altera_uart_shutdown,
|
.shutdown = altera_uart_shutdown,
|
||||||
|
@ -435,7 +430,7 @@ static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
|
||||||
|
|
||||||
#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
|
#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
|
||||||
|
|
||||||
static void altera_uart_console_putc(struct uart_port *port, const char c)
|
static void altera_uart_console_putc(struct uart_port *port, int c)
|
||||||
{
|
{
|
||||||
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
||||||
ALTERA_UART_STATUS_TRDY_MSK))
|
ALTERA_UART_STATUS_TRDY_MSK))
|
||||||
|
@ -449,11 +444,7 @@ static void altera_uart_console_write(struct console *co, const char *s,
|
||||||
{
|
{
|
||||||
struct uart_port *port = &(altera_uart_ports + co->index)->port;
|
struct uart_port *port = &(altera_uart_ports + co->index)->port;
|
||||||
|
|
||||||
for (; count; count--, s++) {
|
uart_console_write(port, s, count, altera_uart_console_putc);
|
||||||
altera_uart_console_putc(port, *s);
|
|
||||||
if (*s == '\n')
|
|
||||||
altera_uart_console_putc(port, '\r');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init altera_uart_console_setup(struct console *co, char *options)
|
static int __init altera_uart_console_setup(struct console *co, char *options)
|
||||||
|
|
|
@ -46,8 +46,7 @@
|
||||||
#include <linux/amba/serial.h>
|
#include <linux/amba/serial.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/io.h>
|
||||||
#include <asm/io.h>
|
|
||||||
|
|
||||||
#define UART_NR 8
|
#define UART_NR 8
|
||||||
|
|
||||||
|
@ -688,28 +687,22 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
|
||||||
if (amba_ports[i] == NULL)
|
if (amba_ports[i] == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == ARRAY_SIZE(amba_ports)) {
|
if (i == ARRAY_SIZE(amba_ports))
|
||||||
ret = -EBUSY;
|
return -EBUSY;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
|
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
|
||||||
if (!uap) {
|
GFP_KERNEL);
|
||||||
ret = -ENOMEM;
|
if (!uap)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
base = ioremap(dev->res.start, resource_size(&dev->res));
|
base = devm_ioremap(&dev->dev, dev->res.start,
|
||||||
if (!base) {
|
resource_size(&dev->res));
|
||||||
ret = -ENOMEM;
|
if (!base)
|
||||||
goto free;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
uap->clk = clk_get(&dev->dev, NULL);
|
uap->clk = devm_clk_get(&dev->dev, NULL);
|
||||||
if (IS_ERR(uap->clk)) {
|
if (IS_ERR(uap->clk))
|
||||||
ret = PTR_ERR(uap->clk);
|
return PTR_ERR(uap->clk);
|
||||||
goto unmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
uap->port.dev = &dev->dev;
|
uap->port.dev = &dev->dev;
|
||||||
uap->port.mapbase = dev->res.start;
|
uap->port.mapbase = dev->res.start;
|
||||||
|
@ -727,15 +720,9 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
|
||||||
|
|
||||||
amba_set_drvdata(dev, uap);
|
amba_set_drvdata(dev, uap);
|
||||||
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;
|
||||||
clk_put(uap->clk);
|
|
||||||
unmap:
|
|
||||||
iounmap(base);
|
|
||||||
free:
|
|
||||||
kfree(uap);
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,9 +737,6 @@ static int pl010_remove(struct amba_device *dev)
|
||||||
if (amba_ports[i] == uap)
|
if (amba_ports[i] == uap)
|
||||||
amba_ports[i] = NULL;
|
amba_ports[i] = NULL;
|
||||||
|
|
||||||
iounmap(uap->port.membase);
|
|
||||||
clk_put(uap->clk);
|
|
||||||
kfree(uap);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1484,7 +1484,7 @@ static int pl011_hwinit(struct uart_port *port)
|
||||||
*/
|
*/
|
||||||
retval = clk_prepare_enable(uap->clk);
|
retval = clk_prepare_enable(uap->clk);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
return retval;
|
||||||
|
|
||||||
uap->port.uartclk = clk_get_rate(uap->clk);
|
uap->port.uartclk = clk_get_rate(uap->clk);
|
||||||
|
|
||||||
|
@ -1507,8 +1507,6 @@ static int pl011_hwinit(struct uart_port *port)
|
||||||
plat->init();
|
plat->init();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
out:
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
|
static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
|
||||||
|
@ -2131,32 +2129,24 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||||
if (amba_ports[i] == NULL)
|
if (amba_ports[i] == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == ARRAY_SIZE(amba_ports)) {
|
if (i == ARRAY_SIZE(amba_ports))
|
||||||
ret = -EBUSY;
|
return -EBUSY;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
|
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (uap == NULL) {
|
if (uap == NULL)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = pl011_probe_dt_alias(i, &dev->dev);
|
i = pl011_probe_dt_alias(i, &dev->dev);
|
||||||
|
|
||||||
base = devm_ioremap(&dev->dev, dev->res.start,
|
base = devm_ioremap(&dev->dev, dev->res.start,
|
||||||
resource_size(&dev->res));
|
resource_size(&dev->res));
|
||||||
if (!base) {
|
if (!base)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
uap->clk = devm_clk_get(&dev->dev, NULL);
|
uap->clk = devm_clk_get(&dev->dev, NULL);
|
||||||
if (IS_ERR(uap->clk)) {
|
if (IS_ERR(uap->clk))
|
||||||
ret = PTR_ERR(uap->clk);
|
return PTR_ERR(uap->clk);
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
uap->vendor = vendor;
|
uap->vendor = vendor;
|
||||||
uap->lcrh_rx = vendor->lcrh_rx;
|
uap->lcrh_rx = vendor->lcrh_rx;
|
||||||
|
@ -2198,7 +2188,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||||
uart_unregister_driver(&amba_reg);
|
uart_unregister_driver(&amba_reg);
|
||||||
pl011_dma_remove(uap);
|
pl011_dma_remove(uap);
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,11 +71,6 @@ static void apbuart_stop_rx(struct uart_port *port)
|
||||||
UART_PUT_CTRL(port, cr);
|
UART_PUT_CTRL(port, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apbuart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* No modem status change interrupts for APBUART */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void apbuart_rx_chars(struct uart_port *port)
|
static void apbuart_rx_chars(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned int status, ch, rsr, flag;
|
unsigned int status, ch, rsr, flag;
|
||||||
|
@ -337,7 +332,6 @@ static struct uart_ops grlib_apbuart_ops = {
|
||||||
.stop_tx = apbuart_stop_tx,
|
.stop_tx = apbuart_stop_tx,
|
||||||
.start_tx = apbuart_start_tx,
|
.start_tx = apbuart_start_tx,
|
||||||
.stop_rx = apbuart_stop_rx,
|
.stop_rx = apbuart_stop_rx,
|
||||||
.enable_ms = apbuart_enable_ms,
|
|
||||||
.break_ctl = apbuart_break_ctl,
|
.break_ctl = apbuart_break_ctl,
|
||||||
.startup = apbuart_startup,
|
.startup = apbuart_startup,
|
||||||
.shutdown = apbuart_shutdown,
|
.shutdown = apbuart_shutdown,
|
||||||
|
|
|
@ -176,10 +176,6 @@ static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)
|
||||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ar933x_uart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
|
* baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
|
||||||
*/
|
*/
|
||||||
|
@ -495,7 +491,6 @@ static struct uart_ops ar933x_uart_ops = {
|
||||||
.stop_tx = ar933x_uart_stop_tx,
|
.stop_tx = ar933x_uart_stop_tx,
|
||||||
.start_tx = ar933x_uart_start_tx,
|
.start_tx = ar933x_uart_start_tx,
|
||||||
.stop_rx = ar933x_uart_stop_rx,
|
.stop_rx = ar933x_uart_stop_rx,
|
||||||
.enable_ms = ar933x_uart_enable_ms,
|
|
||||||
.break_ctl = ar933x_uart_break_ctl,
|
.break_ctl = ar933x_uart_break_ctl,
|
||||||
.startup = ar933x_uart_startup,
|
.startup = ar933x_uart_startup,
|
||||||
.shutdown = ar933x_uart_shutdown,
|
.shutdown = ar933x_uart_shutdown,
|
||||||
|
|
|
@ -37,8 +37,8 @@
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
* ARC UART Hardware Specs
|
* ARC UART Hardware Specs
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
#define RXOERR 0x02 /* OverFlow Err: Char recv but RXFULL still set */
|
#define RXOERR 0x02 /* OverFlow Err: Char recv but RXFULL still set */
|
||||||
|
|
||||||
/* Uart bit fiddling helpers: lowest level */
|
/* Uart bit fiddling helpers: lowest level */
|
||||||
#define RBASE(uart, reg) (uart->port.membase + reg)
|
#define RBASE(port, reg) (port->membase + reg)
|
||||||
#define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
|
#define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
|
||||||
#define UART_REG_GET(u, r) readb(RBASE(u, r))
|
#define UART_REG_GET(u, r) readb(RBASE(u, r))
|
||||||
|
|
||||||
|
@ -102,7 +102,6 @@
|
||||||
struct arc_uart_port {
|
struct arc_uart_port {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
unsigned long baud;
|
unsigned long baud;
|
||||||
int is_emulated; /* H/w vs. Instruction Set Simulator */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_arc_port(uport) container_of(uport, struct arc_uart_port, port)
|
#define to_arc_port(uport) container_of(uport, struct arc_uart_port, port)
|
||||||
|
@ -129,19 +128,15 @@ static struct uart_driver arc_uart_driver = {
|
||||||
|
|
||||||
static void arc_serial_stop_rx(struct uart_port *port)
|
static void arc_serial_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
UART_RX_IRQ_DISABLE(port);
|
||||||
|
|
||||||
UART_RX_IRQ_DISABLE(uart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arc_serial_stop_tx(struct uart_port *port)
|
static void arc_serial_stop_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
while (!(UART_GET_STATUS(port) & TXEMPTY))
|
||||||
|
|
||||||
while (!(UART_GET_STATUS(uart) & TXEMPTY))
|
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
UART_TX_IRQ_DISABLE(uart);
|
UART_TX_IRQ_DISABLE(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -149,10 +144,9 @@ static void arc_serial_stop_tx(struct uart_port *port)
|
||||||
*/
|
*/
|
||||||
static unsigned int arc_serial_tx_empty(struct uart_port *port)
|
static unsigned int arc_serial_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
|
||||||
unsigned int stat;
|
unsigned int stat;
|
||||||
|
|
||||||
stat = UART_GET_STATUS(uart);
|
stat = UART_GET_STATUS(port);
|
||||||
if (stat & TXEMPTY)
|
if (stat & TXEMPTY)
|
||||||
return TIOCSER_TEMT;
|
return TIOCSER_TEMT;
|
||||||
|
|
||||||
|
@ -166,24 +160,24 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
|
||||||
* = by uart_start( ) before calling us
|
* = by uart_start( ) before calling us
|
||||||
* = tx_ist checks that too before calling
|
* = tx_ist checks that too before calling
|
||||||
*/
|
*/
|
||||||
static void arc_serial_tx_chars(struct arc_uart_port *uart)
|
static void arc_serial_tx_chars(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct circ_buf *xmit = &uart->port.state->xmit;
|
struct circ_buf *xmit = &port->state->xmit;
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
|
|
||||||
if (unlikely(uart->port.x_char)) {
|
if (unlikely(port->x_char)) {
|
||||||
UART_SET_DATA(uart, uart->port.x_char);
|
UART_SET_DATA(port, port->x_char);
|
||||||
uart->port.icount.tx++;
|
port->icount.tx++;
|
||||||
uart->port.x_char = 0;
|
port->x_char = 0;
|
||||||
sent = 1;
|
sent = 1;
|
||||||
} else if (!uart_circ_empty(xmit)) {
|
} else if (!uart_circ_empty(xmit)) {
|
||||||
ch = xmit->buf[xmit->tail];
|
ch = xmit->buf[xmit->tail];
|
||||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
uart->port.icount.tx++;
|
port->icount.tx++;
|
||||||
while (!(UART_GET_STATUS(uart) & TXEMPTY))
|
while (!(UART_GET_STATUS(port) & TXEMPTY))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
UART_SET_DATA(uart, ch);
|
UART_SET_DATA(port, ch);
|
||||||
sent = 1;
|
sent = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,10 +186,10 @@ static void arc_serial_tx_chars(struct arc_uart_port *uart)
|
||||||
* By Hard ISR to schedule processing in software interrupt part
|
* By Hard ISR to schedule processing in software interrupt part
|
||||||
*/
|
*/
|
||||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
uart_write_wakeup(&uart->port);
|
uart_write_wakeup(port);
|
||||||
|
|
||||||
if (sent)
|
if (sent)
|
||||||
UART_TX_IRQ_ENABLE(uart);
|
UART_TX_IRQ_ENABLE(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -204,12 +198,10 @@ static void arc_serial_tx_chars(struct arc_uart_port *uart)
|
||||||
*/
|
*/
|
||||||
static void arc_serial_start_tx(struct uart_port *port)
|
static void arc_serial_start_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
arc_serial_tx_chars(port);
|
||||||
|
|
||||||
arc_serial_tx_chars(uart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
|
static void arc_serial_rx_chars(struct uart_port *port, unsigned int status)
|
||||||
{
|
{
|
||||||
unsigned int ch, flg = 0;
|
unsigned int ch, flg = 0;
|
||||||
|
|
||||||
|
@ -229,15 +221,15 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
|
||||||
*/
|
*/
|
||||||
if (unlikely(status & (RXOERR | RXFERR))) {
|
if (unlikely(status & (RXOERR | RXFERR))) {
|
||||||
if (status & RXOERR) {
|
if (status & RXOERR) {
|
||||||
uart->port.icount.overrun++;
|
port->icount.overrun++;
|
||||||
flg = TTY_OVERRUN;
|
flg = TTY_OVERRUN;
|
||||||
UART_CLR_STATUS(uart, RXOERR);
|
UART_CLR_STATUS(port, RXOERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & RXFERR) {
|
if (status & RXFERR) {
|
||||||
uart->port.icount.frame++;
|
port->icount.frame++;
|
||||||
flg = TTY_FRAME;
|
flg = TTY_FRAME;
|
||||||
UART_CLR_STATUS(uart, RXFERR);
|
UART_CLR_STATUS(port, RXFERR);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
flg = TTY_NORMAL;
|
flg = TTY_NORMAL;
|
||||||
|
@ -245,16 +237,16 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
|
||||||
if (status & RXEMPTY)
|
if (status & RXEMPTY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ch = UART_GET_DATA(uart);
|
ch = UART_GET_DATA(port);
|
||||||
uart->port.icount.rx++;
|
port->icount.rx++;
|
||||||
|
|
||||||
if (!(uart_handle_sysrq_char(&uart->port, ch)))
|
if (!(uart_handle_sysrq_char(port, ch)))
|
||||||
uart_insert_char(&uart->port, status, RXOERR, ch, flg);
|
uart_insert_char(port, status, RXOERR, ch, flg);
|
||||||
|
|
||||||
spin_unlock(&uart->port.lock);
|
spin_unlock(&port->lock);
|
||||||
tty_flip_buffer_push(&uart->port.state->port);
|
tty_flip_buffer_push(&port->state->port);
|
||||||
spin_lock(&uart->port.lock);
|
spin_lock(&port->lock);
|
||||||
} while (!((status = UART_GET_STATUS(uart)) & RXEMPTY));
|
} while (!((status = UART_GET_STATUS(port)) & RXEMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -287,10 +279,10 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
|
||||||
|
|
||||||
static irqreturn_t arc_serial_isr(int irq, void *dev_id)
|
static irqreturn_t arc_serial_isr(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = dev_id;
|
struct uart_port *port = dev_id;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
status = UART_GET_STATUS(uart);
|
status = UART_GET_STATUS(port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Single IRQ for both Rx (data available) Tx (room available) Interrupt
|
* Single IRQ for both Rx (data available) Tx (room available) Interrupt
|
||||||
|
@ -300,9 +292,9 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
|
||||||
if (status & RXIENB) {
|
if (status & RXIENB) {
|
||||||
|
|
||||||
/* already in ISR, no need of xx_irqsave */
|
/* already in ISR, no need of xx_irqsave */
|
||||||
spin_lock(&uart->port.lock);
|
spin_lock(&port->lock);
|
||||||
arc_serial_rx_chars(uart, status);
|
arc_serial_rx_chars(port, status);
|
||||||
spin_unlock(&uart->port.lock);
|
spin_unlock(&port->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & TXIENB) && (status & TXEMPTY)) {
|
if ((status & TXIENB) && (status & TXEMPTY)) {
|
||||||
|
@ -310,14 +302,14 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
|
||||||
/* Unconditionally disable further Tx-Interrupts.
|
/* Unconditionally disable further Tx-Interrupts.
|
||||||
* will be enabled by tx_chars() if needed.
|
* will be enabled by tx_chars() if needed.
|
||||||
*/
|
*/
|
||||||
UART_TX_IRQ_DISABLE(uart);
|
UART_TX_IRQ_DISABLE(port);
|
||||||
|
|
||||||
spin_lock(&uart->port.lock);
|
spin_lock(&port->lock);
|
||||||
|
|
||||||
if (!uart_tx_stopped(&uart->port))
|
if (!uart_tx_stopped(port))
|
||||||
arc_serial_tx_chars(uart);
|
arc_serial_tx_chars(port);
|
||||||
|
|
||||||
spin_unlock(&uart->port.lock);
|
spin_unlock(&port->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
@ -340,13 +332,6 @@ static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
/* MCR not present */
|
/* MCR not present */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable Modem Status Interrupts */
|
|
||||||
|
|
||||||
static void arc_serial_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* MSR not present */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void arc_serial_break_ctl(struct uart_port *port, int break_state)
|
static void arc_serial_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
/* ARC UART doesn't support sending Break signal */
|
/* ARC UART doesn't support sending Break signal */
|
||||||
|
@ -354,18 +339,15 @@ static void arc_serial_break_ctl(struct uart_port *port, int break_state)
|
||||||
|
|
||||||
static int arc_serial_startup(struct uart_port *port)
|
static int arc_serial_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
|
||||||
|
|
||||||
/* Before we hook up the ISR, Disable all UART Interrupts */
|
/* Before we hook up the ISR, Disable all UART Interrupts */
|
||||||
UART_ALL_IRQ_DISABLE(uart);
|
UART_ALL_IRQ_DISABLE(port);
|
||||||
|
|
||||||
if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx",
|
if (request_irq(port->irq, arc_serial_isr, 0, "arc uart rx-tx", port)) {
|
||||||
uart)) {
|
dev_warn(port->dev, "Unable to attach ARC UART intr\n");
|
||||||
dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n");
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */
|
UART_RX_IRQ_ENABLE(port); /* Only Rx IRQ enabled to begin with */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -373,8 +355,7 @@ static int arc_serial_startup(struct uart_port *port)
|
||||||
/* This is not really needed */
|
/* This is not really needed */
|
||||||
static void arc_serial_shutdown(struct uart_port *port)
|
static void arc_serial_shutdown(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
free_irq(port->irq, port);
|
||||||
free_irq(uart->port.irq, uart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -398,25 +379,14 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
|
||||||
uartl = hw_val & 0xFF;
|
uartl = hw_val & 0xFF;
|
||||||
uarth = (hw_val >> 8) & 0xFF;
|
uarth = (hw_val >> 8) & 0xFF;
|
||||||
|
|
||||||
/*
|
|
||||||
* UART ISS(Instruction Set simulator) emulation has a subtle bug:
|
|
||||||
* A existing value of Baudh = 0 is used as a indication to startup
|
|
||||||
* it's internal state machine.
|
|
||||||
* Thus if baudh is set to 0, 2 times, it chokes.
|
|
||||||
* This happens with BAUD=115200 and the formaula above
|
|
||||||
* Until that is fixed, when running on ISS, we will set baudh to !0
|
|
||||||
*/
|
|
||||||
if (uart->is_emulated)
|
|
||||||
uarth = 1;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
UART_ALL_IRQ_DISABLE(uart);
|
UART_ALL_IRQ_DISABLE(port);
|
||||||
|
|
||||||
UART_SET_BAUDL(uart, uartl);
|
UART_SET_BAUDL(port, uartl);
|
||||||
UART_SET_BAUDH(uart, uarth);
|
UART_SET_BAUDH(port, uarth);
|
||||||
|
|
||||||
UART_RX_IRQ_ENABLE(uart);
|
UART_RX_IRQ_ENABLE(port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UART doesn't support Parity/Hardware Flow Control;
|
* UART doesn't support Parity/Hardware Flow Control;
|
||||||
|
@ -439,9 +409,7 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
|
||||||
|
|
||||||
static const char *arc_serial_type(struct uart_port *port)
|
static const char *arc_serial_type(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
return port->type == PORT_ARC ? DRIVER_NAME : NULL;
|
||||||
|
|
||||||
return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arc_serial_release_port(struct uart_port *port)
|
static void arc_serial_release_port(struct uart_port *port)
|
||||||
|
@ -470,35 +438,28 @@ arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||||
*/
|
*/
|
||||||
static void arc_serial_config_port(struct uart_port *port, int flags)
|
static void arc_serial_config_port(struct uart_port *port, int flags)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
|
||||||
|
|
||||||
if (flags & UART_CONFIG_TYPE)
|
if (flags & UART_CONFIG_TYPE)
|
||||||
uart->port.type = PORT_ARC;
|
port->type = PORT_ARC;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
|
||||||
static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
|
static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
while (!(UART_GET_STATUS(port) & TXEMPTY))
|
||||||
|
|
||||||
while (!(UART_GET_STATUS(uart) & TXEMPTY))
|
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
UART_SET_DATA(uart, chr);
|
UART_SET_DATA(port, chr);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
|
||||||
static int arc_serial_poll_getchar(struct uart_port *port)
|
static int arc_serial_poll_getchar(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct arc_uart_port *uart = to_arc_port(port);
|
|
||||||
unsigned char chr;
|
unsigned char chr;
|
||||||
|
|
||||||
while (!(UART_GET_STATUS(uart) & RXEMPTY))
|
while (!(UART_GET_STATUS(port) & RXEMPTY))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
chr = UART_GET_DATA(uart);
|
chr = UART_GET_DATA(port);
|
||||||
return chr;
|
return chr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -510,7 +471,6 @@ static struct uart_ops arc_serial_pops = {
|
||||||
.stop_tx = arc_serial_stop_tx,
|
.stop_tx = arc_serial_stop_tx,
|
||||||
.start_tx = arc_serial_start_tx,
|
.start_tx = arc_serial_start_tx,
|
||||||
.stop_rx = arc_serial_stop_rx,
|
.stop_rx = arc_serial_stop_rx,
|
||||||
.enable_ms = arc_serial_enable_ms,
|
|
||||||
.break_ctl = arc_serial_break_ctl,
|
.break_ctl = arc_serial_break_ctl,
|
||||||
.startup = arc_serial_startup,
|
.startup = arc_serial_startup,
|
||||||
.shutdown = arc_serial_shutdown,
|
.shutdown = arc_serial_shutdown,
|
||||||
|
@ -526,71 +486,6 @@ static struct uart_ops arc_serial_pops = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
|
||||||
arc_uart_init_one(struct platform_device *pdev, int dev_id)
|
|
||||||
{
|
|
||||||
struct resource *res, *res2;
|
|
||||||
unsigned long *plat_data;
|
|
||||||
struct arc_uart_port *uart = &arc_uart_ports[dev_id];
|
|
||||||
|
|
||||||
plat_data = dev_get_platdata(&pdev->dev);
|
|
||||||
if (!plat_data)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
uart->is_emulated = !!plat_data[0]; /* workaround ISS bug */
|
|
||||||
|
|
||||||
if (is_early_platform_device(pdev)) {
|
|
||||||
uart->port.uartclk = plat_data[1];
|
|
||||||
uart->baud = plat_data[2];
|
|
||||||
} else {
|
|
||||||
struct device_node *np = pdev->dev.of_node;
|
|
||||||
u32 val;
|
|
||||||
|
|
||||||
if (of_property_read_u32(np, "clock-frequency", &val)) {
|
|
||||||
dev_err(&pdev->dev, "clock-frequency property NOTset\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
uart->port.uartclk = val;
|
|
||||||
|
|
||||||
if (of_property_read_u32(np, "current-speed", &val)) {
|
|
||||||
dev_err(&pdev->dev, "current-speed property NOT set\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
uart->baud = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
if (!res)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
|
||||||
if (!res2)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
uart->port.mapbase = res->start;
|
|
||||||
uart->port.membase = ioremap_nocache(res->start, resource_size(res));
|
|
||||||
if (!uart->port.membase)
|
|
||||||
/* No point of dev_err since UART itself is hosed here */
|
|
||||||
return -ENXIO;
|
|
||||||
|
|
||||||
uart->port.irq = res2->start;
|
|
||||||
uart->port.dev = &pdev->dev;
|
|
||||||
uart->port.iotype = UPIO_MEM;
|
|
||||||
uart->port.flags = UPF_BOOT_AUTOCONF;
|
|
||||||
uart->port.line = dev_id;
|
|
||||||
uart->port.ops = &arc_serial_pops;
|
|
||||||
|
|
||||||
uart->port.fifosize = ARC_UART_TX_FIFO_SIZE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* uart_insert_char( ) uses it in decideding whether to ignore a
|
|
||||||
* char or not. Explicitly setting it here, removes the subtelty
|
|
||||||
*/
|
|
||||||
uart->port.ignore_status_mask = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_ARC_CONSOLE
|
#ifdef CONFIG_SERIAL_ARC_CONSOLE
|
||||||
|
|
||||||
static int arc_serial_console_setup(struct console *co, char *options)
|
static int arc_serial_console_setup(struct console *co, char *options)
|
||||||
|
@ -624,7 +519,10 @@ static int arc_serial_console_setup(struct console *co, char *options)
|
||||||
|
|
||||||
static void arc_serial_console_putchar(struct uart_port *port, int ch)
|
static void arc_serial_console_putchar(struct uart_port *port, int ch)
|
||||||
{
|
{
|
||||||
arc_serial_poll_putchar(port, (unsigned char)ch);
|
while (!(UART_GET_STATUS(port) & TXEMPTY))
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
UART_SET_DATA(port, (unsigned char)ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -651,48 +549,45 @@ static struct console arc_console = {
|
||||||
.data = &arc_uart_driver
|
.data = &arc_uart_driver
|
||||||
};
|
};
|
||||||
|
|
||||||
static __init void early_serial_write(struct console *con, const char *s,
|
static __init void arc_early_serial_write(struct console *con, const char *s,
|
||||||
unsigned int n)
|
unsigned int n)
|
||||||
{
|
{
|
||||||
struct uart_port *port = &arc_uart_ports[con->index].port;
|
struct earlycon_device *dev = con->data;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++, s++) {
|
uart_console_write(&dev->port, s, n, arc_serial_console_putchar);
|
||||||
if (*s == '\n')
|
|
||||||
arc_serial_poll_putchar(port, '\r');
|
|
||||||
arc_serial_poll_putchar(port, *s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct console arc_early_serial_console __initdata = {
|
static int __init arc_early_console_setup(struct earlycon_device *dev,
|
||||||
.name = "early_ARCuart",
|
const char *opt)
|
||||||
.write = early_serial_write,
|
|
||||||
.flags = CON_PRINTBUFFER | CON_BOOT,
|
|
||||||
.index = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init arc_serial_probe_earlyprintk(struct platform_device *pdev)
|
|
||||||
{
|
{
|
||||||
int dev_id = pdev->id < 0 ? 0 : pdev->id;
|
struct uart_port *port = &dev->port;
|
||||||
int rc;
|
unsigned int l, h, hw_val;
|
||||||
|
|
||||||
arc_early_serial_console.index = dev_id;
|
if (!dev->port.membase)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
rc = arc_uart_init_one(pdev, dev_id);
|
hw_val = port->uartclk / (dev->baud * 4) - 1;
|
||||||
if (rc)
|
l = hw_val & 0xFF;
|
||||||
panic("early console init failed\n");
|
h = (hw_val >> 8) & 0xFF;
|
||||||
|
|
||||||
arc_serial_console_setup(&arc_early_serial_console, NULL);
|
UART_SET_BAUDL(port, l);
|
||||||
|
UART_SET_BAUDH(port, h);
|
||||||
|
|
||||||
register_console(&arc_early_serial_console);
|
dev->con->write = arc_early_serial_write;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EARLYCON_DECLARE(arc_uart, arc_early_console_setup);
|
||||||
|
OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup);
|
||||||
|
|
||||||
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
|
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
|
||||||
|
|
||||||
static int arc_serial_probe(struct platform_device *pdev)
|
static int arc_serial_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int rc, dev_id;
|
|
||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
|
struct arc_uart_port *uart;
|
||||||
|
struct uart_port *port;
|
||||||
|
int dev_id;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
/* no device tree device */
|
/* no device tree device */
|
||||||
if (!np)
|
if (!np)
|
||||||
|
@ -702,12 +597,43 @@ static int arc_serial_probe(struct platform_device *pdev)
|
||||||
if (dev_id < 0)
|
if (dev_id < 0)
|
||||||
dev_id = 0;
|
dev_id = 0;
|
||||||
|
|
||||||
rc = arc_uart_init_one(pdev, dev_id);
|
uart = &arc_uart_ports[dev_id];
|
||||||
if (rc)
|
port = &uart->port;
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc = uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port);
|
if (of_property_read_u32(np, "clock-frequency", &val)) {
|
||||||
return rc;
|
dev_err(&pdev->dev, "clock-frequency property NOTset\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
port->uartclk = val;
|
||||||
|
|
||||||
|
if (of_property_read_u32(np, "current-speed", &val)) {
|
||||||
|
dev_err(&pdev->dev, "current-speed property NOT set\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
uart->baud = val;
|
||||||
|
|
||||||
|
port->membase = of_iomap(np, 0);
|
||||||
|
if (!port->membase)
|
||||||
|
/* No point of dev_err since UART itself is hosed here */
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
|
port->irq = irq_of_parse_and_map(np, 0);
|
||||||
|
|
||||||
|
port->dev = &pdev->dev;
|
||||||
|
port->iotype = UPIO_MEM;
|
||||||
|
port->flags = UPF_BOOT_AUTOCONF;
|
||||||
|
port->line = dev_id;
|
||||||
|
port->ops = &arc_serial_pops;
|
||||||
|
|
||||||
|
port->fifosize = ARC_UART_TX_FIFO_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* uart_insert_char( ) uses it in decideding whether to ignore a
|
||||||
|
* char or not. Explicitly setting it here, removes the subtelty
|
||||||
|
*/
|
||||||
|
port->ignore_status_mask = 0;
|
||||||
|
|
||||||
|
return uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arc_serial_remove(struct platform_device *pdev)
|
static int arc_serial_remove(struct platform_device *pdev)
|
||||||
|
@ -732,27 +658,6 @@ static struct platform_driver arc_platform_driver = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_ARC_CONSOLE
|
|
||||||
|
|
||||||
static struct platform_driver early_arc_platform_driver __initdata = {
|
|
||||||
.probe = arc_serial_probe_earlyprintk,
|
|
||||||
.remove = arc_serial_remove,
|
|
||||||
.driver = {
|
|
||||||
.name = DRIVER_NAME,
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
* Register an early platform driver of "earlyprintk" class.
|
|
||||||
* ARCH platform code installs the driver and probes the early devices
|
|
||||||
* The installation could rely on user specifying earlyprintk=xyx in cmd line
|
|
||||||
* or it could be done independently, for all "earlyprintk" class drivers.
|
|
||||||
* [see arch/arc/plat-arcfpga/platform.c]
|
|
||||||
*/
|
|
||||||
early_platform_init("earlyprintk", &early_arc_platform_driver);
|
|
||||||
|
|
||||||
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
|
|
||||||
|
|
||||||
static int __init arc_serial_init(void)
|
static int __init arc_serial_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -706,7 +706,7 @@ static void atmel_release_tx_dma(struct uart_port *port)
|
||||||
dmaengine_terminate_all(chan);
|
dmaengine_terminate_all(chan);
|
||||||
dma_release_channel(chan);
|
dma_release_channel(chan);
|
||||||
dma_unmap_sg(port->dev, &atmel_port->sg_tx, 1,
|
dma_unmap_sg(port->dev, &atmel_port->sg_tx, 1,
|
||||||
DMA_MEM_TO_DEV);
|
DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
atmel_port->desc_tx = NULL;
|
atmel_port->desc_tx = NULL;
|
||||||
|
@ -804,7 +804,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
|
||||||
nent = dma_map_sg(port->dev,
|
nent = dma_map_sg(port->dev,
|
||||||
&atmel_port->sg_tx,
|
&atmel_port->sg_tx,
|
||||||
1,
|
1,
|
||||||
DMA_MEM_TO_DEV);
|
DMA_TO_DEVICE);
|
||||||
|
|
||||||
if (!nent) {
|
if (!nent) {
|
||||||
dev_dbg(port->dev, "need to release resource of dma\n");
|
dev_dbg(port->dev, "need to release resource of dma\n");
|
||||||
|
@ -883,7 +883,7 @@ static void atmel_release_rx_dma(struct uart_port *port)
|
||||||
dmaengine_terminate_all(chan);
|
dmaengine_terminate_all(chan);
|
||||||
dma_release_channel(chan);
|
dma_release_channel(chan);
|
||||||
dma_unmap_sg(port->dev, &atmel_port->sg_rx, 1,
|
dma_unmap_sg(port->dev, &atmel_port->sg_rx, 1,
|
||||||
DMA_DEV_TO_MEM);
|
DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
atmel_port->desc_rx = NULL;
|
atmel_port->desc_rx = NULL;
|
||||||
|
@ -968,7 +968,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
|
||||||
nent = dma_map_sg(port->dev,
|
nent = dma_map_sg(port->dev,
|
||||||
&atmel_port->sg_rx,
|
&atmel_port->sg_rx,
|
||||||
1,
|
1,
|
||||||
DMA_DEV_TO_MEM);
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
if (!nent) {
|
if (!nent) {
|
||||||
dev_dbg(port->dev, "need to release resource of dma\n");
|
dev_dbg(port->dev, "need to release resource of dma\n");
|
||||||
|
|
|
@ -426,11 +426,6 @@ static void sport_stop_rx(struct uart_port *port)
|
||||||
SSYNC();
|
SSYNC();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sport_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
pr_debug("%s enter\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sport_break_ctl(struct uart_port *port, int break_state)
|
static void sport_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
pr_debug("%s enter\n", __func__);
|
pr_debug("%s enter\n", __func__);
|
||||||
|
@ -500,6 +495,13 @@ static void sport_set_termios(struct uart_port *port,
|
||||||
|
|
||||||
pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
|
pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
||||||
|
if (old == NULL && up->cts_pin != -1)
|
||||||
|
termios->c_cflag |= CRTSCTS;
|
||||||
|
else if (up->cts_pin == -1)
|
||||||
|
termios->c_cflag &= ~CRTSCTS;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (termios->c_cflag & CSIZE) {
|
switch (termios->c_cflag & CSIZE) {
|
||||||
case CS8:
|
case CS8:
|
||||||
up->csize = 8;
|
up->csize = 8;
|
||||||
|
@ -587,7 +589,6 @@ struct uart_ops sport_uart_ops = {
|
||||||
.stop_tx = sport_stop_tx,
|
.stop_tx = sport_stop_tx,
|
||||||
.start_tx = sport_start_tx,
|
.start_tx = sport_start_tx,
|
||||||
.stop_rx = sport_stop_rx,
|
.stop_rx = sport_stop_rx,
|
||||||
.enable_ms = sport_enable_ms,
|
|
||||||
.break_ctl = sport_break_ctl,
|
.break_ctl = sport_break_ctl,
|
||||||
.startup = sport_startup,
|
.startup = sport_startup,
|
||||||
.shutdown = sport_shutdown,
|
.shutdown = sport_shutdown,
|
||||||
|
@ -813,10 +814,8 @@ static int sport_uart_probe(struct platform_device *pdev)
|
||||||
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
sport->cts_pin = -1;
|
sport->cts_pin = -1;
|
||||||
else {
|
else
|
||||||
sport->cts_pin = res->start;
|
sport->cts_pin = res->start;
|
||||||
sport->port.flags |= ASYNC_CTS_FLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
|
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
|
|
|
@ -200,14 +200,6 @@ static void bfin_serial_stop_rx(struct uart_port *port)
|
||||||
UART_CLEAR_IER(uart, ERBFI);
|
UART_CLEAR_IER(uart, ERBFI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the modem control timer to fire immediately.
|
|
||||||
*/
|
|
||||||
static void bfin_serial_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
|
#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
|
||||||
# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
|
# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
|
||||||
# define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
|
# define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
|
||||||
|
@ -793,6 +785,13 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
unsigned int ier, lcr = 0;
|
unsigned int ier, lcr = 0;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
|
||||||
|
if (old == NULL && uart->cts_pin != -1)
|
||||||
|
termios->c_cflag |= CRTSCTS;
|
||||||
|
else if (uart->cts_pin == -1)
|
||||||
|
termios->c_cflag &= ~CRTSCTS;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (termios->c_cflag & CSIZE) {
|
switch (termios->c_cflag & CSIZE) {
|
||||||
case CS8:
|
case CS8:
|
||||||
lcr = WLS(8);
|
lcr = WLS(8);
|
||||||
|
@ -1014,7 +1013,6 @@ static struct uart_ops bfin_serial_pops = {
|
||||||
.stop_tx = bfin_serial_stop_tx,
|
.stop_tx = bfin_serial_stop_tx,
|
||||||
.start_tx = bfin_serial_start_tx,
|
.start_tx = bfin_serial_start_tx,
|
||||||
.stop_rx = bfin_serial_stop_rx,
|
.stop_rx = bfin_serial_stop_rx,
|
||||||
.enable_ms = bfin_serial_enable_ms,
|
|
||||||
.break_ctl = bfin_serial_break_ctl,
|
.break_ctl = bfin_serial_break_ctl,
|
||||||
.startup = bfin_serial_startup,
|
.startup = bfin_serial_startup,
|
||||||
.shutdown = bfin_serial_shutdown,
|
.shutdown = bfin_serial_shutdown,
|
||||||
|
@ -1325,12 +1323,8 @@ static int bfin_serial_probe(struct platform_device *pdev)
|
||||||
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
uart->cts_pin = -1;
|
uart->cts_pin = -1;
|
||||||
else {
|
else
|
||||||
uart->cts_pin = res->start;
|
uart->cts_pin = res->start;
|
||||||
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
|
|
||||||
uart->port.flags |= ASYNC_CTS_FLOW;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
|
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
|
|
|
@ -352,7 +352,6 @@ static const struct uart_ops uart_clps711x_ops = {
|
||||||
.stop_tx = uart_clps711x_stop_tx,
|
.stop_tx = uart_clps711x_stop_tx,
|
||||||
.start_tx = uart_clps711x_start_tx,
|
.start_tx = uart_clps711x_start_tx,
|
||||||
.stop_rx = uart_clps711x_nop_void,
|
.stop_rx = uart_clps711x_nop_void,
|
||||||
.enable_ms = uart_clps711x_nop_void,
|
|
||||||
.break_ctl = uart_clps711x_break_ctl,
|
.break_ctl = uart_clps711x_break_ctl,
|
||||||
.set_ldisc = uart_clps711x_set_ldisc,
|
.set_ldisc = uart_clps711x_set_ldisc,
|
||||||
.startup = uart_clps711x_startup,
|
.startup = uart_clps711x_startup,
|
||||||
|
|
|
@ -201,14 +201,6 @@ static void cpm_uart_stop_rx(struct uart_port *port)
|
||||||
clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
|
clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable Modem status interrupts
|
|
||||||
*/
|
|
||||||
static void cpm_uart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
pr_debug("CPM uart[%d]:enable ms\n", port->line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a break.
|
* Generate a break.
|
||||||
*/
|
*/
|
||||||
|
@ -1122,7 +1114,6 @@ static struct uart_ops cpm_uart_pops = {
|
||||||
.stop_tx = cpm_uart_stop_tx,
|
.stop_tx = cpm_uart_stop_tx,
|
||||||
.start_tx = cpm_uart_start_tx,
|
.start_tx = cpm_uart_start_tx,
|
||||||
.stop_rx = cpm_uart_stop_rx,
|
.stop_rx = cpm_uart_stop_rx,
|
||||||
.enable_ms = cpm_uart_enable_ms,
|
|
||||||
.break_ctl = cpm_uart_break_ctl,
|
.break_ctl = cpm_uart_break_ctl,
|
||||||
.startup = cpm_uart_startup,
|
.startup = cpm_uart_startup,
|
||||||
.shutdown = cpm_uart_shutdown,
|
.shutdown = cpm_uart_shutdown,
|
||||||
|
|
|
@ -3831,14 +3831,13 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int retval;
|
int retval;
|
||||||
int do_clocal = 0, extra_count = 0;
|
int do_clocal = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the device is in the middle of being closed, then block
|
* If the device is in the middle of being closed, then block
|
||||||
* until it's done, and then try again.
|
* until it's done, and then try again.
|
||||||
*/
|
*/
|
||||||
if (tty_hung_up_p(filp) ||
|
if (info->port.flags & ASYNC_CLOSING) {
|
||||||
(info->port.flags & ASYNC_CLOSING)) {
|
|
||||||
wait_event_interruptible_tty(tty, info->port.close_wait,
|
wait_event_interruptible_tty(tty, info->port.close_wait,
|
||||||
!(info->port.flags & ASYNC_CLOSING));
|
!(info->port.flags & ASYNC_CLOSING));
|
||||||
#ifdef SERIAL_DO_RESTART
|
#ifdef SERIAL_DO_RESTART
|
||||||
|
@ -3879,10 +3878,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
info->line, info->port.count);
|
info->line, info->port.count);
|
||||||
#endif
|
#endif
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
if (!tty_hung_up_p(filp)) {
|
info->port.count--;
|
||||||
extra_count++;
|
|
||||||
info->port.count--;
|
|
||||||
}
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
info->port.blocked_open++;
|
info->port.blocked_open++;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -3921,7 +3917,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
}
|
}
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&info->port.open_wait, &wait);
|
remove_wait_queue(&info->port.open_wait, &wait);
|
||||||
if (extra_count)
|
if (!tty_hung_up_p(filp))
|
||||||
info->port.count++;
|
info->port.count++;
|
||||||
info->port.blocked_open--;
|
info->port.blocked_open--;
|
||||||
#ifdef SERIAL_DEBUG_OPEN
|
#ifdef SERIAL_DEBUG_OPEN
|
||||||
|
@ -3976,8 +3972,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
|
||||||
/*
|
/*
|
||||||
* If the port is in the middle of closing, bail out now
|
* If the port is in the middle of closing, bail out now
|
||||||
*/
|
*/
|
||||||
if (tty_hung_up_p(filp) ||
|
if (info->port.flags & ASYNC_CLOSING) {
|
||||||
(info->port.flags & ASYNC_CLOSING)) {
|
|
||||||
wait_event_interruptible_tty(tty, info->port.close_wait,
|
wait_event_interruptible_tty(tty, info->port.close_wait,
|
||||||
!(info->port.flags & ASYNC_CLOSING));
|
!(info->port.flags & ASYNC_CLOSING));
|
||||||
#ifdef SERIAL_DO_RESTART
|
#ifdef SERIAL_DO_RESTART
|
||||||
|
|
|
@ -151,11 +151,6 @@ static void dz_stop_rx(struct uart_port *uport)
|
||||||
dz_out(dport, DZ_LPR, dport->cflag);
|
dz_out(dport, DZ_LPR, dport->cflag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dz_enable_ms(struct uart_port *uport)
|
|
||||||
{
|
|
||||||
/* nothing to do */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ------------------------------------------------------------
|
* ------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
@ -751,7 +746,6 @@ static struct uart_ops dz_ops = {
|
||||||
.stop_tx = dz_stop_tx,
|
.stop_tx = dz_stop_tx,
|
||||||
.start_tx = dz_start_tx,
|
.start_tx = dz_start_tx,
|
||||||
.stop_rx = dz_stop_rx,
|
.stop_rx = dz_stop_rx,
|
||||||
.enable_ms = dz_enable_ms,
|
|
||||||
.break_ctl = dz_break_ctl,
|
.break_ctl = dz_break_ctl,
|
||||||
.startup = dz_startup,
|
.startup = dz_startup,
|
||||||
.shutdown = dz_shutdown,
|
.shutdown = dz_shutdown,
|
||||||
|
|
|
@ -185,11 +185,6 @@ static void efm32_uart_stop_rx(struct uart_port *port)
|
||||||
efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD);
|
efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void efm32_uart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* no handshake lines, no modem status interrupts */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void efm32_uart_break_ctl(struct uart_port *port, int ctl)
|
static void efm32_uart_break_ctl(struct uart_port *port, int ctl)
|
||||||
{
|
{
|
||||||
/* not possible without fiddling with gpios */
|
/* not possible without fiddling with gpios */
|
||||||
|
@ -499,7 +494,6 @@ static struct uart_ops efm32_uart_pops = {
|
||||||
.stop_tx = efm32_uart_stop_tx,
|
.stop_tx = efm32_uart_stop_tx,
|
||||||
.start_tx = efm32_uart_start_tx,
|
.start_tx = efm32_uart_start_tx,
|
||||||
.stop_rx = efm32_uart_stop_rx,
|
.stop_rx = efm32_uart_stop_rx,
|
||||||
.enable_ms = efm32_uart_enable_ms,
|
|
||||||
.break_ctl = efm32_uart_break_ctl,
|
.break_ctl = efm32_uart_break_ctl,
|
||||||
.startup = efm32_uart_startup,
|
.startup = efm32_uart_startup,
|
||||||
.shutdown = efm32_uart_shutdown,
|
.shutdown = efm32_uart_shutdown,
|
||||||
|
@ -671,10 +665,16 @@ 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);
|
ret = of_property_read_u32(np, "energymicro,location", &location);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
/* fall back to wrongly namespaced property */
|
||||||
|
ret = of_property_read_u32(np, "efm32,location", &location);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
/* fall back to old and (wrongly) generic property "location" */
|
/* 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) {
|
||||||
dev_err(&pdev->dev, "invalid location\n");
|
dev_err(&pdev->dev, "invalid location\n");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Freescale lpuart serial port driver
|
* Freescale lpuart serial port driver
|
||||||
*
|
*
|
||||||
* Copyright 2012-2013 Freescale Semiconductor, Inc.
|
* Copyright 2012-2014 Freescale Semiconductor, Inc.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -117,8 +117,113 @@
|
||||||
#define UARTSFIFO_TXOF 0x02
|
#define UARTSFIFO_TXOF 0x02
|
||||||
#define UARTSFIFO_RXUF 0x01
|
#define UARTSFIFO_RXUF 0x01
|
||||||
|
|
||||||
#define DMA_MAXBURST 16
|
/* 32-bit register defination */
|
||||||
#define DMA_MAXBURST_MASK (DMA_MAXBURST - 1)
|
#define UARTBAUD 0x00
|
||||||
|
#define UARTSTAT 0x04
|
||||||
|
#define UARTCTRL 0x08
|
||||||
|
#define UARTDATA 0x0C
|
||||||
|
#define UARTMATCH 0x10
|
||||||
|
#define UARTMODIR 0x14
|
||||||
|
#define UARTFIFO 0x18
|
||||||
|
#define UARTWATER 0x1c
|
||||||
|
|
||||||
|
#define UARTBAUD_MAEN1 0x80000000
|
||||||
|
#define UARTBAUD_MAEN2 0x40000000
|
||||||
|
#define UARTBAUD_M10 0x20000000
|
||||||
|
#define UARTBAUD_TDMAE 0x00800000
|
||||||
|
#define UARTBAUD_RDMAE 0x00200000
|
||||||
|
#define UARTBAUD_MATCFG 0x00400000
|
||||||
|
#define UARTBAUD_BOTHEDGE 0x00020000
|
||||||
|
#define UARTBAUD_RESYNCDIS 0x00010000
|
||||||
|
#define UARTBAUD_LBKDIE 0x00008000
|
||||||
|
#define UARTBAUD_RXEDGIE 0x00004000
|
||||||
|
#define UARTBAUD_SBNS 0x00002000
|
||||||
|
#define UARTBAUD_SBR 0x00000000
|
||||||
|
#define UARTBAUD_SBR_MASK 0x1fff
|
||||||
|
|
||||||
|
#define UARTSTAT_LBKDIF 0x80000000
|
||||||
|
#define UARTSTAT_RXEDGIF 0x40000000
|
||||||
|
#define UARTSTAT_MSBF 0x20000000
|
||||||
|
#define UARTSTAT_RXINV 0x10000000
|
||||||
|
#define UARTSTAT_RWUID 0x08000000
|
||||||
|
#define UARTSTAT_BRK13 0x04000000
|
||||||
|
#define UARTSTAT_LBKDE 0x02000000
|
||||||
|
#define UARTSTAT_RAF 0x01000000
|
||||||
|
#define UARTSTAT_TDRE 0x00800000
|
||||||
|
#define UARTSTAT_TC 0x00400000
|
||||||
|
#define UARTSTAT_RDRF 0x00200000
|
||||||
|
#define UARTSTAT_IDLE 0x00100000
|
||||||
|
#define UARTSTAT_OR 0x00080000
|
||||||
|
#define UARTSTAT_NF 0x00040000
|
||||||
|
#define UARTSTAT_FE 0x00020000
|
||||||
|
#define UARTSTAT_PE 0x00010000
|
||||||
|
#define UARTSTAT_MA1F 0x00008000
|
||||||
|
#define UARTSTAT_M21F 0x00004000
|
||||||
|
|
||||||
|
#define UARTCTRL_R8T9 0x80000000
|
||||||
|
#define UARTCTRL_R9T8 0x40000000
|
||||||
|
#define UARTCTRL_TXDIR 0x20000000
|
||||||
|
#define UARTCTRL_TXINV 0x10000000
|
||||||
|
#define UARTCTRL_ORIE 0x08000000
|
||||||
|
#define UARTCTRL_NEIE 0x04000000
|
||||||
|
#define UARTCTRL_FEIE 0x02000000
|
||||||
|
#define UARTCTRL_PEIE 0x01000000
|
||||||
|
#define UARTCTRL_TIE 0x00800000
|
||||||
|
#define UARTCTRL_TCIE 0x00400000
|
||||||
|
#define UARTCTRL_RIE 0x00200000
|
||||||
|
#define UARTCTRL_ILIE 0x00100000
|
||||||
|
#define UARTCTRL_TE 0x00080000
|
||||||
|
#define UARTCTRL_RE 0x00040000
|
||||||
|
#define UARTCTRL_RWU 0x00020000
|
||||||
|
#define UARTCTRL_SBK 0x00010000
|
||||||
|
#define UARTCTRL_MA1IE 0x00008000
|
||||||
|
#define UARTCTRL_MA2IE 0x00004000
|
||||||
|
#define UARTCTRL_IDLECFG 0x00000100
|
||||||
|
#define UARTCTRL_LOOPS 0x00000080
|
||||||
|
#define UARTCTRL_DOZEEN 0x00000040
|
||||||
|
#define UARTCTRL_RSRC 0x00000020
|
||||||
|
#define UARTCTRL_M 0x00000010
|
||||||
|
#define UARTCTRL_WAKE 0x00000008
|
||||||
|
#define UARTCTRL_ILT 0x00000004
|
||||||
|
#define UARTCTRL_PE 0x00000002
|
||||||
|
#define UARTCTRL_PT 0x00000001
|
||||||
|
|
||||||
|
#define UARTDATA_NOISY 0x00008000
|
||||||
|
#define UARTDATA_PARITYE 0x00004000
|
||||||
|
#define UARTDATA_FRETSC 0x00002000
|
||||||
|
#define UARTDATA_RXEMPT 0x00001000
|
||||||
|
#define UARTDATA_IDLINE 0x00000800
|
||||||
|
#define UARTDATA_MASK 0x3ff
|
||||||
|
|
||||||
|
#define UARTMODIR_IREN 0x00020000
|
||||||
|
#define UARTMODIR_TXCTSSRC 0x00000020
|
||||||
|
#define UARTMODIR_TXCTSC 0x00000010
|
||||||
|
#define UARTMODIR_RXRTSE 0x00000008
|
||||||
|
#define UARTMODIR_TXRTSPOL 0x00000004
|
||||||
|
#define UARTMODIR_TXRTSE 0x00000002
|
||||||
|
#define UARTMODIR_TXCTSE 0x00000001
|
||||||
|
|
||||||
|
#define UARTFIFO_TXEMPT 0x00800000
|
||||||
|
#define UARTFIFO_RXEMPT 0x00400000
|
||||||
|
#define UARTFIFO_TXOF 0x00020000
|
||||||
|
#define UARTFIFO_RXUF 0x00010000
|
||||||
|
#define UARTFIFO_TXFLUSH 0x00008000
|
||||||
|
#define UARTFIFO_RXFLUSH 0x00004000
|
||||||
|
#define UARTFIFO_TXOFE 0x00000200
|
||||||
|
#define UARTFIFO_RXUFE 0x00000100
|
||||||
|
#define UARTFIFO_TXFE 0x00000080
|
||||||
|
#define UARTFIFO_FIFOSIZE_MASK 0x7
|
||||||
|
#define UARTFIFO_TXSIZE_OFF 4
|
||||||
|
#define UARTFIFO_RXFE 0x00000008
|
||||||
|
#define UARTFIFO_RXSIZE_OFF 0
|
||||||
|
|
||||||
|
#define UARTWATER_COUNT_MASK 0xff
|
||||||
|
#define UARTWATER_TXCNT_OFF 8
|
||||||
|
#define UARTWATER_RXCNT_OFF 24
|
||||||
|
#define UARTWATER_WATER_MASK 0xff
|
||||||
|
#define UARTWATER_TXWATER_OFF 0
|
||||||
|
#define UARTWATER_RXWATER_OFF 16
|
||||||
|
|
||||||
#define FSL_UART_RX_DMA_BUFFER_SIZE 64
|
#define FSL_UART_RX_DMA_BUFFER_SIZE 64
|
||||||
|
|
||||||
#define DRIVER_NAME "fsl-lpuart"
|
#define DRIVER_NAME "fsl-lpuart"
|
||||||
|
@ -130,6 +235,7 @@ 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 lpuart32;
|
||||||
|
|
||||||
bool lpuart_dma_use;
|
bool lpuart_dma_use;
|
||||||
struct dma_chan *dma_tx_chan;
|
struct dma_chan *dma_tx_chan;
|
||||||
|
@ -154,6 +260,9 @@ static struct of_device_id lpuart_dt_ids[] = {
|
||||||
{
|
{
|
||||||
.compatible = "fsl,vf610-lpuart",
|
.compatible = "fsl,vf610-lpuart",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.compatible = "fsl,ls1021a-lpuart",
|
||||||
|
},
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
|
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
|
||||||
|
@ -162,6 +271,16 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
|
||||||
static void lpuart_dma_tx_complete(void *arg);
|
static void lpuart_dma_tx_complete(void *arg);
|
||||||
static void lpuart_dma_rx_complete(void *arg);
|
static void lpuart_dma_rx_complete(void *arg);
|
||||||
|
|
||||||
|
static u32 lpuart32_read(void __iomem *addr)
|
||||||
|
{
|
||||||
|
return ioread32be(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpuart32_write(u32 val, void __iomem *addr)
|
||||||
|
{
|
||||||
|
iowrite32be(val, addr);
|
||||||
|
}
|
||||||
|
|
||||||
static void lpuart_stop_tx(struct uart_port *port)
|
static void lpuart_stop_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned char temp;
|
unsigned char temp;
|
||||||
|
@ -171,6 +290,15 @@ static void lpuart_stop_tx(struct uart_port *port)
|
||||||
writeb(temp, port->membase + UARTCR2);
|
writeb(temp, port->membase + UARTCR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpuart32_stop_tx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
unsigned long temp;
|
||||||
|
|
||||||
|
temp = lpuart32_read(port->membase + UARTCTRL);
|
||||||
|
temp &= ~(UARTCTRL_TIE | UARTCTRL_TCIE);
|
||||||
|
lpuart32_write(temp, port->membase + UARTCTRL);
|
||||||
|
}
|
||||||
|
|
||||||
static void lpuart_stop_rx(struct uart_port *port)
|
static void lpuart_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned char temp;
|
unsigned char temp;
|
||||||
|
@ -179,8 +307,12 @@ static void lpuart_stop_rx(struct uart_port *port)
|
||||||
writeb(temp & ~UARTCR2_RE, port->membase + UARTCR2);
|
writeb(temp & ~UARTCR2_RE, port->membase + UARTCR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lpuart_enable_ms(struct uart_port *port)
|
static void lpuart32_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
unsigned long temp;
|
||||||
|
|
||||||
|
temp = lpuart32_read(port->membase + UARTCTRL);
|
||||||
|
lpuart32_write(temp & ~UARTCTRL_RE, port->membase + UARTCTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
|
static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
|
||||||
|
@ -240,7 +372,7 @@ static int lpuart_dma_tx(struct lpuart_port *sport, unsigned long count)
|
||||||
|
|
||||||
dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
|
dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
|
||||||
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
||||||
sport->dma_tx_bytes = count & ~(DMA_MAXBURST_MASK);
|
sport->dma_tx_bytes = count & ~(sport->txfifo_size - 1);
|
||||||
tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
|
tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
|
||||||
sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
|
sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
|
||||||
tx_bus_addr, sport->dma_tx_bytes,
|
tx_bus_addr, sport->dma_tx_bytes,
|
||||||
|
@ -269,7 +401,7 @@ static void lpuart_prepare_tx(struct lpuart_port *sport)
|
||||||
if (!count)
|
if (!count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (count < DMA_MAXBURST)
|
if (count < sport->txfifo_size)
|
||||||
writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
|
writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
|
||||||
sport->port.membase + UARTCR5);
|
sport->port.membase + UARTCR5);
|
||||||
else {
|
else {
|
||||||
|
@ -405,6 +537,30 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
|
||||||
lpuart_stop_tx(&sport->port);
|
lpuart_stop_tx(&sport->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
|
||||||
|
{
|
||||||
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
|
unsigned long txcnt;
|
||||||
|
|
||||||
|
txcnt = lpuart32_read(sport->port.membase + UARTWATER);
|
||||||
|
txcnt = txcnt >> UARTWATER_TXCNT_OFF;
|
||||||
|
txcnt &= UARTWATER_COUNT_MASK;
|
||||||
|
while (!uart_circ_empty(xmit) && (txcnt < sport->txfifo_size)) {
|
||||||
|
lpuart32_write(xmit->buf[xmit->tail], sport->port.membase + UARTDATA);
|
||||||
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
|
sport->port.icount.tx++;
|
||||||
|
txcnt = lpuart32_read(sport->port.membase + UARTWATER);
|
||||||
|
txcnt = txcnt >> UARTWATER_TXCNT_OFF;
|
||||||
|
txcnt &= UARTWATER_COUNT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
|
uart_write_wakeup(&sport->port);
|
||||||
|
|
||||||
|
if (uart_circ_empty(xmit))
|
||||||
|
lpuart32_stop_tx(&sport->port);
|
||||||
|
}
|
||||||
|
|
||||||
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 *sport = container_of(port,
|
||||||
|
@ -424,6 +580,18 @@ static void lpuart_start_tx(struct uart_port *port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpuart32_start_tx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
|
||||||
|
unsigned long temp;
|
||||||
|
|
||||||
|
temp = lpuart32_read(port->membase + UARTCTRL);
|
||||||
|
lpuart32_write(temp | UARTCTRL_TIE, port->membase + UARTCTRL);
|
||||||
|
|
||||||
|
if (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE)
|
||||||
|
lpuart32_transmit_buffer(sport);
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct lpuart_port *sport = dev_id;
|
struct lpuart_port *sport = dev_id;
|
||||||
|
@ -432,16 +600,25 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
||||||
|
|
||||||
spin_lock_irqsave(&sport->port.lock, flags);
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
if (sport->port.x_char) {
|
if (sport->port.x_char) {
|
||||||
writeb(sport->port.x_char, sport->port.membase + UARTDR);
|
if (sport->lpuart32)
|
||||||
|
lpuart32_write(sport->port.x_char, sport->port.membase + UARTDATA);
|
||||||
|
else
|
||||||
|
writeb(sport->port.x_char, sport->port.membase + UARTDR);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
|
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
|
||||||
lpuart_stop_tx(&sport->port);
|
if (sport->lpuart32)
|
||||||
|
lpuart32_stop_tx(&sport->port);
|
||||||
|
else
|
||||||
|
lpuart_stop_tx(&sport->port);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
lpuart_transmit_buffer(sport);
|
if (sport->lpuart32)
|
||||||
|
lpuart32_transmit_buffer(sport);
|
||||||
|
else
|
||||||
|
lpuart_transmit_buffer(sport);
|
||||||
|
|
||||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
uart_write_wakeup(&sport->port);
|
uart_write_wakeup(&sport->port);
|
||||||
|
@ -514,6 +691,70 @@ out:
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static irqreturn_t lpuart32_rxint(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = dev_id;
|
||||||
|
unsigned int flg, ignored = 0;
|
||||||
|
struct tty_port *port = &sport->port.state->port;
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long rx, sr;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
while (!(lpuart32_read(sport->port.membase + UARTFIFO) & UARTFIFO_RXEMPT)) {
|
||||||
|
flg = TTY_NORMAL;
|
||||||
|
sport->port.icount.rx++;
|
||||||
|
/*
|
||||||
|
* to clear the FE, OR, NF, FE, PE flags,
|
||||||
|
* read STAT then read DATA reg
|
||||||
|
*/
|
||||||
|
sr = lpuart32_read(sport->port.membase + UARTSTAT);
|
||||||
|
rx = lpuart32_read(sport->port.membase + UARTDATA);
|
||||||
|
rx &= 0x3ff;
|
||||||
|
|
||||||
|
if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) {
|
||||||
|
if (sr & UARTSTAT_PE)
|
||||||
|
sport->port.icount.parity++;
|
||||||
|
else if (sr & UARTSTAT_FE)
|
||||||
|
sport->port.icount.frame++;
|
||||||
|
|
||||||
|
if (sr & UARTSTAT_OR)
|
||||||
|
sport->port.icount.overrun++;
|
||||||
|
|
||||||
|
if (sr & sport->port.ignore_status_mask) {
|
||||||
|
if (++ignored > 100)
|
||||||
|
goto out;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sr &= sport->port.read_status_mask;
|
||||||
|
|
||||||
|
if (sr & UARTSTAT_PE)
|
||||||
|
flg = TTY_PARITY;
|
||||||
|
else if (sr & UARTSTAT_FE)
|
||||||
|
flg = TTY_FRAME;
|
||||||
|
|
||||||
|
if (sr & UARTSTAT_OR)
|
||||||
|
flg = TTY_OVERRUN;
|
||||||
|
|
||||||
|
#ifdef SUPPORT_SYSRQ
|
||||||
|
sport->port.sysrq = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_insert_flip_char(port, rx, flg);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
tty_flip_buffer_push(port);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t lpuart_int(int irq, void *dev_id)
|
static irqreturn_t lpuart_int(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct lpuart_port *sport = dev_id;
|
struct lpuart_port *sport = dev_id;
|
||||||
|
@ -538,6 +779,26 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static irqreturn_t lpuart32_int(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = dev_id;
|
||||||
|
unsigned long sts, rxcount;
|
||||||
|
|
||||||
|
sts = lpuart32_read(sport->port.membase + UARTSTAT);
|
||||||
|
rxcount = lpuart32_read(sport->port.membase + UARTWATER);
|
||||||
|
rxcount = rxcount >> UARTWATER_RXCNT_OFF;
|
||||||
|
|
||||||
|
if (sts & UARTSTAT_RDRF || rxcount > 0)
|
||||||
|
lpuart32_rxint(irq, dev_id);
|
||||||
|
|
||||||
|
if ((sts & UARTSTAT_TDRE) &&
|
||||||
|
!(lpuart32_read(sport->port.membase + UARTBAUD) & UARTBAUD_TDMAE))
|
||||||
|
lpuart_txint(irq, dev_id);
|
||||||
|
|
||||||
|
lpuart32_write(sts, sport->port.membase + UARTSTAT);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
/* return TIOCSER_TEMT when transmitter is not busy */
|
/* return TIOCSER_TEMT when transmitter is not busy */
|
||||||
static unsigned int lpuart_tx_empty(struct uart_port *port)
|
static unsigned int lpuart_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
@ -545,6 +806,12 @@ static unsigned int lpuart_tx_empty(struct uart_port *port)
|
||||||
TIOCSER_TEMT : 0;
|
TIOCSER_TEMT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int lpuart32_tx_empty(struct uart_port *port)
|
||||||
|
{
|
||||||
|
return (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TC) ?
|
||||||
|
TIOCSER_TEMT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int lpuart_get_mctrl(struct uart_port *port)
|
static unsigned int lpuart_get_mctrl(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned int temp = 0;
|
unsigned int temp = 0;
|
||||||
|
@ -560,6 +827,21 @@ static unsigned int lpuart_get_mctrl(struct uart_port *port)
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int lpuart32_get_mctrl(struct uart_port *port)
|
||||||
|
{
|
||||||
|
unsigned int temp = 0;
|
||||||
|
unsigned long reg;
|
||||||
|
|
||||||
|
reg = lpuart32_read(port->membase + UARTMODIR);
|
||||||
|
if (reg & UARTMODIR_TXCTSE)
|
||||||
|
temp |= TIOCM_CTS;
|
||||||
|
|
||||||
|
if (reg & UARTMODIR_RXRTSE)
|
||||||
|
temp |= TIOCM_RTS;
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
{
|
{
|
||||||
unsigned char temp;
|
unsigned char temp;
|
||||||
|
@ -576,6 +858,22 @@ static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
writeb(temp, port->membase + UARTMODEM);
|
writeb(temp, port->membase + UARTMODEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
|
{
|
||||||
|
unsigned long temp;
|
||||||
|
|
||||||
|
temp = lpuart32_read(port->membase + UARTMODIR) &
|
||||||
|
~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
||||||
|
|
||||||
|
if (mctrl & TIOCM_RTS)
|
||||||
|
temp |= UARTMODIR_RXRTSE;
|
||||||
|
|
||||||
|
if (mctrl & TIOCM_CTS)
|
||||||
|
temp |= UARTMODIR_TXCTSE;
|
||||||
|
|
||||||
|
lpuart32_write(temp, port->membase + UARTMODIR);
|
||||||
|
}
|
||||||
|
|
||||||
static void lpuart_break_ctl(struct uart_port *port, int break_state)
|
static void lpuart_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
unsigned char temp;
|
unsigned char temp;
|
||||||
|
@ -588,6 +886,18 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
|
||||||
writeb(temp, port->membase + UARTCR2);
|
writeb(temp, port->membase + UARTCR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpuart32_break_ctl(struct uart_port *port, int break_state)
|
||||||
|
{
|
||||||
|
unsigned long temp;
|
||||||
|
|
||||||
|
temp = lpuart32_read(port->membase + UARTCTRL) & ~UARTCTRL_SBK;
|
||||||
|
|
||||||
|
if (break_state != 0)
|
||||||
|
temp |= UARTCTRL_SBK;
|
||||||
|
|
||||||
|
lpuart32_write(temp, port->membase + UARTCTRL);
|
||||||
|
}
|
||||||
|
|
||||||
static void lpuart_setup_watermark(struct lpuart_port *sport)
|
static void lpuart_setup_watermark(struct lpuart_port *sport)
|
||||||
{
|
{
|
||||||
unsigned char val, cr2;
|
unsigned char val, cr2;
|
||||||
|
@ -599,15 +909,7 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
|
||||||
UARTCR2_RIE | UARTCR2_RE);
|
UARTCR2_RIE | UARTCR2_RE);
|
||||||
writeb(cr2, sport->port.membase + UARTCR2);
|
writeb(cr2, sport->port.membase + UARTCR2);
|
||||||
|
|
||||||
/* determine FIFO size and enable FIFO mode */
|
|
||||||
val = readb(sport->port.membase + UARTPFIFO);
|
val = readb(sport->port.membase + UARTPFIFO);
|
||||||
|
|
||||||
sport->txfifo_size = 0x1 << (((val >> UARTPFIFO_TXSIZE_OFF) &
|
|
||||||
UARTPFIFO_FIFOSIZE_MASK) + 1);
|
|
||||||
|
|
||||||
sport->rxfifo_size = 0x1 << (((val >> UARTPFIFO_RXSIZE_OFF) &
|
|
||||||
UARTPFIFO_FIFOSIZE_MASK) + 1);
|
|
||||||
|
|
||||||
writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
|
writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
|
||||||
sport->port.membase + UARTPFIFO);
|
sport->port.membase + UARTPFIFO);
|
||||||
|
|
||||||
|
@ -622,6 +924,31 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
|
||||||
writeb(cr2_saved, sport->port.membase + UARTCR2);
|
writeb(cr2_saved, sport->port.membase + UARTCR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpuart32_setup_watermark(struct lpuart_port *sport)
|
||||||
|
{
|
||||||
|
unsigned long val, ctrl;
|
||||||
|
unsigned long ctrl_saved;
|
||||||
|
|
||||||
|
ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
|
||||||
|
ctrl_saved = ctrl;
|
||||||
|
ctrl &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_TE |
|
||||||
|
UARTCTRL_RIE | UARTCTRL_RE);
|
||||||
|
lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
|
||||||
|
|
||||||
|
/* enable FIFO mode */
|
||||||
|
val = lpuart32_read(sport->port.membase + UARTFIFO);
|
||||||
|
val |= UARTFIFO_TXFE | UARTFIFO_RXFE;
|
||||||
|
val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH;
|
||||||
|
lpuart32_write(val, sport->port.membase + UARTFIFO);
|
||||||
|
|
||||||
|
/* set the watermark */
|
||||||
|
val = (0x1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF);
|
||||||
|
lpuart32_write(val, sport->port.membase + UARTWATER);
|
||||||
|
|
||||||
|
/* Restore cr2 */
|
||||||
|
lpuart32_write(ctrl_saved, sport->port.membase + UARTCTRL);
|
||||||
|
}
|
||||||
|
|
||||||
static int lpuart_dma_tx_request(struct uart_port *port)
|
static int lpuart_dma_tx_request(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct lpuart_port *sport = container_of(port,
|
struct lpuart_port *sport = container_of(port,
|
||||||
|
@ -652,7 +979,7 @@ static int lpuart_dma_tx_request(struct uart_port *port)
|
||||||
dma_buf = sport->port.state->xmit.buf;
|
dma_buf = sport->port.state->xmit.buf;
|
||||||
dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
|
dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
|
||||||
dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||||
dma_tx_sconfig.dst_maxburst = DMA_MAXBURST;
|
dma_tx_sconfig.dst_maxburst = sport->txfifo_size;
|
||||||
dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
|
dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
|
||||||
ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
|
ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
|
||||||
|
|
||||||
|
@ -724,13 +1051,6 @@ static int lpuart_dma_rx_request(struct uart_port *port)
|
||||||
sport->dma_rx_buf_bus = dma_bus;
|
sport->dma_rx_buf_bus = dma_bus;
|
||||||
sport->dma_rx_in_progress = 0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,7 +1092,16 @@ 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*/
|
/* determine FIFO size and enable FIFO mode */
|
||||||
|
temp = readb(sport->port.membase + UARTPFIFO);
|
||||||
|
|
||||||
|
sport->txfifo_size = 0x1 << (((temp >> UARTPFIFO_TXSIZE_OFF) &
|
||||||
|
UARTPFIFO_FIFOSIZE_MASK) + 1);
|
||||||
|
|
||||||
|
sport->rxfifo_size = 0x1 << (((temp >> UARTPFIFO_RXSIZE_OFF) &
|
||||||
|
UARTPFIFO_FIFOSIZE_MASK) + 1);
|
||||||
|
|
||||||
|
/* Whether use dma support by dma request results */
|
||||||
if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
|
if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
|
||||||
sport->lpuart_dma_use = false;
|
sport->lpuart_dma_use = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -798,6 +1127,40 @@ static int lpuart_startup(struct uart_port *port)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lpuart32_startup(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
|
||||||
|
int ret;
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long temp;
|
||||||
|
|
||||||
|
/* determine FIFO size */
|
||||||
|
temp = lpuart32_read(sport->port.membase + UARTFIFO);
|
||||||
|
|
||||||
|
sport->txfifo_size = 0x1 << (((temp >> UARTFIFO_TXSIZE_OFF) &
|
||||||
|
UARTFIFO_FIFOSIZE_MASK) - 1);
|
||||||
|
|
||||||
|
sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) &
|
||||||
|
UARTFIFO_FIFOSIZE_MASK) - 1);
|
||||||
|
|
||||||
|
ret = devm_request_irq(port->dev, port->irq, lpuart32_int, 0,
|
||||||
|
DRIVER_NAME, sport);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
lpuart32_setup_watermark(sport);
|
||||||
|
|
||||||
|
temp = lpuart32_read(sport->port.membase + UARTCTRL);
|
||||||
|
temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE | UARTCTRL_TE);
|
||||||
|
temp |= UARTCTRL_ILIE;
|
||||||
|
lpuart32_write(temp, sport->port.membase + UARTCTRL);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void lpuart_shutdown(struct uart_port *port)
|
static void lpuart_shutdown(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);
|
||||||
|
@ -822,6 +1185,25 @@ static void lpuart_shutdown(struct uart_port *port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpuart32_shutdown(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
|
||||||
|
unsigned long temp;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
|
/* disable Rx/Tx and interrupts */
|
||||||
|
temp = lpuart32_read(port->membase + UARTCTRL);
|
||||||
|
temp &= ~(UARTCTRL_TE | UARTCTRL_RE |
|
||||||
|
UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
|
||||||
|
lpuart32_write(temp, port->membase + UARTCTRL);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
devm_free_irq(port->dev, port->irq, sport);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
|
lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
struct ktermios *old)
|
struct ktermios *old)
|
||||||
|
@ -922,6 +1304,17 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
/* update the per-port timeout */
|
/* update the per-port timeout */
|
||||||
uart_update_timeout(port, termios->c_cflag, baud);
|
uart_update_timeout(port, termios->c_cflag, baud);
|
||||||
|
|
||||||
|
if (sport->lpuart_dma_use) {
|
||||||
|
/* Calculate delay for 1.5 DMA buffers */
|
||||||
|
sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
|
||||||
|
FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
|
||||||
|
sport->rxfifo_size / 2;
|
||||||
|
dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
|
||||||
|
sport->dma_rx_timeout * 1000 / HZ, sport->port.timeout);
|
||||||
|
if (sport->dma_rx_timeout < msecs_to_jiffies(20))
|
||||||
|
sport->dma_rx_timeout = msecs_to_jiffies(20);
|
||||||
|
}
|
||||||
|
|
||||||
/* wait transmit engin complete */
|
/* wait transmit engin complete */
|
||||||
while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
|
while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
|
||||||
barrier();
|
barrier();
|
||||||
|
@ -948,6 +1341,125 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
|
struct ktermios *old)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long ctrl, old_ctrl, bd, modem;
|
||||||
|
unsigned int baud;
|
||||||
|
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
|
||||||
|
unsigned int sbr;
|
||||||
|
|
||||||
|
ctrl = old_ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
|
||||||
|
bd = lpuart32_read(sport->port.membase + UARTBAUD);
|
||||||
|
modem = lpuart32_read(sport->port.membase + UARTMODIR);
|
||||||
|
/*
|
||||||
|
* only support CS8 and CS7, and for CS7 must enable PE.
|
||||||
|
* supported mode:
|
||||||
|
* - (7,e/o,1)
|
||||||
|
* - (8,n,1)
|
||||||
|
* - (8,m/s,1)
|
||||||
|
* - (8,e/o,1)
|
||||||
|
*/
|
||||||
|
while ((termios->c_cflag & CSIZE) != CS8 &&
|
||||||
|
(termios->c_cflag & CSIZE) != CS7) {
|
||||||
|
termios->c_cflag &= ~CSIZE;
|
||||||
|
termios->c_cflag |= old_csize;
|
||||||
|
old_csize = CS8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((termios->c_cflag & CSIZE) == CS8 ||
|
||||||
|
(termios->c_cflag & CSIZE) == CS7)
|
||||||
|
ctrl = old_ctrl & ~UARTCTRL_M;
|
||||||
|
|
||||||
|
if (termios->c_cflag & CMSPAR) {
|
||||||
|
if ((termios->c_cflag & CSIZE) != CS8) {
|
||||||
|
termios->c_cflag &= ~CSIZE;
|
||||||
|
termios->c_cflag |= CS8;
|
||||||
|
}
|
||||||
|
ctrl |= UARTCTRL_M;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (termios->c_cflag & CRTSCTS) {
|
||||||
|
modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
|
||||||
|
} else {
|
||||||
|
termios->c_cflag &= ~CRTSCTS;
|
||||||
|
modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (termios->c_cflag & CSTOPB)
|
||||||
|
termios->c_cflag &= ~CSTOPB;
|
||||||
|
|
||||||
|
/* parity must be enabled when CS7 to match 8-bits format */
|
||||||
|
if ((termios->c_cflag & CSIZE) == CS7)
|
||||||
|
termios->c_cflag |= PARENB;
|
||||||
|
|
||||||
|
if ((termios->c_cflag & PARENB)) {
|
||||||
|
if (termios->c_cflag & CMSPAR) {
|
||||||
|
ctrl &= ~UARTCTRL_PE;
|
||||||
|
ctrl |= UARTCTRL_M;
|
||||||
|
} else {
|
||||||
|
ctrl |= UARTCR1_PE;
|
||||||
|
if ((termios->c_cflag & CSIZE) == CS8)
|
||||||
|
ctrl |= UARTCTRL_M;
|
||||||
|
if (termios->c_cflag & PARODD)
|
||||||
|
ctrl |= UARTCTRL_PT;
|
||||||
|
else
|
||||||
|
ctrl &= ~UARTCTRL_PT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ask the core to calculate the divisor */
|
||||||
|
baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
|
sport->port.read_status_mask = 0;
|
||||||
|
if (termios->c_iflag & INPCK)
|
||||||
|
sport->port.read_status_mask |= (UARTSTAT_FE | UARTSTAT_PE);
|
||||||
|
if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
|
||||||
|
sport->port.read_status_mask |= UARTSTAT_FE;
|
||||||
|
|
||||||
|
/* characters to ignore */
|
||||||
|
sport->port.ignore_status_mask = 0;
|
||||||
|
if (termios->c_iflag & IGNPAR)
|
||||||
|
sport->port.ignore_status_mask |= UARTSTAT_PE;
|
||||||
|
if (termios->c_iflag & IGNBRK) {
|
||||||
|
sport->port.ignore_status_mask |= UARTSTAT_FE;
|
||||||
|
/*
|
||||||
|
* if we're ignoring parity and break indicators,
|
||||||
|
* ignore overruns too (for real raw support).
|
||||||
|
*/
|
||||||
|
if (termios->c_iflag & IGNPAR)
|
||||||
|
sport->port.ignore_status_mask |= UARTSTAT_OR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update the per-port timeout */
|
||||||
|
uart_update_timeout(port, termios->c_cflag, baud);
|
||||||
|
|
||||||
|
/* wait transmit engin complete */
|
||||||
|
while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
|
||||||
|
barrier();
|
||||||
|
|
||||||
|
/* disable transmit and receive */
|
||||||
|
lpuart32_write(old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
|
||||||
|
sport->port.membase + UARTCTRL);
|
||||||
|
|
||||||
|
sbr = sport->port.uartclk / (16 * baud);
|
||||||
|
bd &= ~UARTBAUD_SBR_MASK;
|
||||||
|
bd |= sbr & UARTBAUD_SBR_MASK;
|
||||||
|
bd |= UARTBAUD_BOTHEDGE;
|
||||||
|
bd &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
|
||||||
|
lpuart32_write(bd, sport->port.membase + UARTBAUD);
|
||||||
|
lpuart32_write(modem, sport->port.membase + UARTMODIR);
|
||||||
|
lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
|
||||||
|
/* restore control register */
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *lpuart_type(struct uart_port *port)
|
static const char *lpuart_type(struct uart_port *port)
|
||||||
{
|
{
|
||||||
return "FSL_LPUART";
|
return "FSL_LPUART";
|
||||||
|
@ -996,7 +1508,6 @@ static struct uart_ops lpuart_pops = {
|
||||||
.stop_tx = lpuart_stop_tx,
|
.stop_tx = lpuart_stop_tx,
|
||||||
.start_tx = lpuart_start_tx,
|
.start_tx = lpuart_start_tx,
|
||||||
.stop_rx = lpuart_stop_rx,
|
.stop_rx = lpuart_stop_rx,
|
||||||
.enable_ms = lpuart_enable_ms,
|
|
||||||
.break_ctl = lpuart_break_ctl,
|
.break_ctl = lpuart_break_ctl,
|
||||||
.startup = lpuart_startup,
|
.startup = lpuart_startup,
|
||||||
.shutdown = lpuart_shutdown,
|
.shutdown = lpuart_shutdown,
|
||||||
|
@ -1008,6 +1519,24 @@ static struct uart_ops lpuart_pops = {
|
||||||
.verify_port = lpuart_verify_port,
|
.verify_port = lpuart_verify_port,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct uart_ops lpuart32_pops = {
|
||||||
|
.tx_empty = lpuart32_tx_empty,
|
||||||
|
.set_mctrl = lpuart32_set_mctrl,
|
||||||
|
.get_mctrl = lpuart32_get_mctrl,
|
||||||
|
.stop_tx = lpuart32_stop_tx,
|
||||||
|
.start_tx = lpuart32_start_tx,
|
||||||
|
.stop_rx = lpuart32_stop_rx,
|
||||||
|
.break_ctl = lpuart32_break_ctl,
|
||||||
|
.startup = lpuart32_startup,
|
||||||
|
.shutdown = lpuart32_shutdown,
|
||||||
|
.set_termios = lpuart32_set_termios,
|
||||||
|
.type = lpuart_type,
|
||||||
|
.request_port = lpuart_request_port,
|
||||||
|
.release_port = lpuart_release_port,
|
||||||
|
.config_port = lpuart_config_port,
|
||||||
|
.verify_port = lpuart_verify_port,
|
||||||
|
};
|
||||||
|
|
||||||
static struct lpuart_port *lpuart_ports[UART_NR];
|
static struct lpuart_port *lpuart_ports[UART_NR];
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE
|
#ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE
|
||||||
|
@ -1019,6 +1548,14 @@ static void lpuart_console_putchar(struct uart_port *port, int ch)
|
||||||
writeb(ch, port->membase + UARTDR);
|
writeb(ch, port->membase + UARTDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpuart32_console_putchar(struct uart_port *port, int ch)
|
||||||
|
{
|
||||||
|
while (!(lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE))
|
||||||
|
barrier();
|
||||||
|
|
||||||
|
lpuart32_write(ch, port->membase + UARTDATA);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpuart_console_write(struct console *co, const char *s, unsigned int count)
|
lpuart_console_write(struct console *co, const char *s, unsigned int count)
|
||||||
{
|
{
|
||||||
|
@ -1040,6 +1577,27 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
|
||||||
writeb(old_cr2, sport->port.membase + UARTCR2);
|
writeb(old_cr2, sport->port.membase + UARTCR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lpuart32_console_write(struct console *co, const char *s, unsigned int count)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = lpuart_ports[co->index];
|
||||||
|
unsigned long old_cr, cr;
|
||||||
|
|
||||||
|
/* first save CR2 and then disable interrupts */
|
||||||
|
cr = old_cr = lpuart32_read(sport->port.membase + UARTCTRL);
|
||||||
|
cr |= (UARTCTRL_TE | UARTCTRL_RE);
|
||||||
|
cr &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
|
||||||
|
lpuart32_write(cr, sport->port.membase + UARTCTRL);
|
||||||
|
|
||||||
|
uart_console_write(&sport->port, s, count, lpuart32_console_putchar);
|
||||||
|
|
||||||
|
/* wait for transmitter finish complete and restore CR2 */
|
||||||
|
while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
|
||||||
|
barrier();
|
||||||
|
|
||||||
|
lpuart32_write(old_cr, sport->port.membase + UARTCTRL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if the port was already initialised (eg, by a boot loader),
|
* if the port was already initialised (eg, by a boot loader),
|
||||||
* try to determine the current setup.
|
* try to determine the current setup.
|
||||||
|
@ -1093,6 +1651,49 @@ lpuart_console_get_options(struct lpuart_port *sport, int *baud,
|
||||||
"from %d to %d\n", baud_raw, *baud);
|
"from %d to %d\n", baud_raw, *baud);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init
|
||||||
|
lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
|
||||||
|
int *parity, int *bits)
|
||||||
|
{
|
||||||
|
unsigned long cr, bd;
|
||||||
|
unsigned int sbr, uartclk, baud_raw;
|
||||||
|
|
||||||
|
cr = lpuart32_read(sport->port.membase + UARTCTRL);
|
||||||
|
cr &= UARTCTRL_TE | UARTCTRL_RE;
|
||||||
|
if (!cr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* ok, the port was enabled */
|
||||||
|
|
||||||
|
cr = lpuart32_read(sport->port.membase + UARTCTRL);
|
||||||
|
|
||||||
|
*parity = 'n';
|
||||||
|
if (cr & UARTCTRL_PE) {
|
||||||
|
if (cr & UARTCTRL_PT)
|
||||||
|
*parity = 'o';
|
||||||
|
else
|
||||||
|
*parity = 'e';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cr & UARTCTRL_M)
|
||||||
|
*bits = 9;
|
||||||
|
else
|
||||||
|
*bits = 8;
|
||||||
|
|
||||||
|
bd = lpuart32_read(sport->port.membase + UARTBAUD);
|
||||||
|
bd &= UARTBAUD_SBR_MASK;
|
||||||
|
sbr = bd;
|
||||||
|
uartclk = clk_get_rate(sport->clk);
|
||||||
|
/*
|
||||||
|
* baud = mod_clk/(16*(sbr[13]+(brfa)/32)
|
||||||
|
*/
|
||||||
|
baud_raw = uartclk / (16 * sbr);
|
||||||
|
|
||||||
|
if (*baud != baud_raw)
|
||||||
|
printk(KERN_INFO "Serial: Console lpuart rounded baud rate"
|
||||||
|
"from %d to %d\n", baud_raw, *baud);
|
||||||
|
}
|
||||||
|
|
||||||
static int __init lpuart_console_setup(struct console *co, char *options)
|
static int __init lpuart_console_setup(struct console *co, char *options)
|
||||||
{
|
{
|
||||||
struct lpuart_port *sport;
|
struct lpuart_port *sport;
|
||||||
|
@ -1116,9 +1717,15 @@ static int __init lpuart_console_setup(struct console *co, char *options)
|
||||||
if (options)
|
if (options)
|
||||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||||
else
|
else
|
||||||
lpuart_console_get_options(sport, &baud, &parity, &bits);
|
if (sport->lpuart32)
|
||||||
|
lpuart32_console_get_options(sport, &baud, &parity, &bits);
|
||||||
|
else
|
||||||
|
lpuart_console_get_options(sport, &baud, &parity, &bits);
|
||||||
|
|
||||||
lpuart_setup_watermark(sport);
|
if (sport->lpuart32)
|
||||||
|
lpuart32_setup_watermark(sport);
|
||||||
|
else
|
||||||
|
lpuart_setup_watermark(sport);
|
||||||
|
|
||||||
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
|
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
|
||||||
}
|
}
|
||||||
|
@ -1134,9 +1741,21 @@ static struct console lpuart_console = {
|
||||||
.data = &lpuart_reg,
|
.data = &lpuart_reg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct console lpuart32_console = {
|
||||||
|
.name = DEV_NAME,
|
||||||
|
.write = lpuart32_console_write,
|
||||||
|
.device = uart_console_device,
|
||||||
|
.setup = lpuart_console_setup,
|
||||||
|
.flags = CON_PRINTBUFFER,
|
||||||
|
.index = -1,
|
||||||
|
.data = &lpuart_reg,
|
||||||
|
};
|
||||||
|
|
||||||
#define LPUART_CONSOLE (&lpuart_console)
|
#define LPUART_CONSOLE (&lpuart_console)
|
||||||
|
#define LPUART32_CONSOLE (&lpuart32_console)
|
||||||
#else
|
#else
|
||||||
#define LPUART_CONSOLE NULL
|
#define LPUART_CONSOLE NULL
|
||||||
|
#define LPUART32_CONSOLE NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct uart_driver lpuart_reg = {
|
static struct uart_driver lpuart_reg = {
|
||||||
|
@ -1166,7 +1785,7 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
sport->port.line = ret;
|
sport->port.line = ret;
|
||||||
|
sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!res)
|
if (!res)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1180,7 +1799,10 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||||
sport->port.type = PORT_LPUART;
|
sport->port.type = PORT_LPUART;
|
||||||
sport->port.iotype = UPIO_MEM;
|
sport->port.iotype = UPIO_MEM;
|
||||||
sport->port.irq = platform_get_irq(pdev, 0);
|
sport->port.irq = platform_get_irq(pdev, 0);
|
||||||
sport->port.ops = &lpuart_pops;
|
if (sport->lpuart32)
|
||||||
|
sport->port.ops = &lpuart32_pops;
|
||||||
|
else
|
||||||
|
sport->port.ops = &lpuart_pops;
|
||||||
sport->port.flags = UPF_BOOT_AUTOCONF;
|
sport->port.flags = UPF_BOOT_AUTOCONF;
|
||||||
|
|
||||||
sport->clk = devm_clk_get(&pdev->dev, "ipg");
|
sport->clk = devm_clk_get(&pdev->dev, "ipg");
|
||||||
|
@ -1202,6 +1824,11 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, &sport->port);
|
platform_set_drvdata(pdev, &sport->port);
|
||||||
|
|
||||||
|
if (sport->lpuart32)
|
||||||
|
lpuart_reg.cons = LPUART32_CONSOLE;
|
||||||
|
else
|
||||||
|
lpuart_reg.cons = LPUART_CONSOLE;
|
||||||
|
|
||||||
ret = uart_add_one_port(&lpuart_reg, &sport->port);
|
ret = uart_add_one_port(&lpuart_reg, &sport->port);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
clk_disable_unprepare(sport->clk);
|
clk_disable_unprepare(sport->clk);
|
||||||
|
|
|
@ -1052,11 +1052,6 @@ static void icom_stop_rx(struct uart_port *port)
|
||||||
writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
|
writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void icom_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* no-op */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void icom_break(struct uart_port *port, int break_state)
|
static void icom_break(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
unsigned char cmdReg;
|
unsigned char cmdReg;
|
||||||
|
@ -1300,7 +1295,6 @@ static struct uart_ops icom_ops = {
|
||||||
.start_tx = icom_start_tx,
|
.start_tx = icom_start_tx,
|
||||||
.send_xchar = icom_send_xchar,
|
.send_xchar = icom_send_xchar,
|
||||||
.stop_rx = icom_stop_rx,
|
.stop_rx = icom_stop_rx,
|
||||||
.enable_ms = icom_enable_ms,
|
|
||||||
.break_ctl = icom_break,
|
.break_ctl = icom_break,
|
||||||
.startup = icom_open,
|
.startup = icom_open,
|
||||||
.shutdown = icom_close,
|
.shutdown = icom_close,
|
||||||
|
|
|
@ -1880,7 +1880,6 @@ static struct uart_ops ioc3_ops = {
|
||||||
.stop_tx = ic3_stop_tx,
|
.stop_tx = ic3_stop_tx,
|
||||||
.start_tx = ic3_start_tx,
|
.start_tx = ic3_start_tx,
|
||||||
.stop_rx = ic3_stop_rx,
|
.stop_rx = ic3_stop_rx,
|
||||||
.enable_ms = null_void_function,
|
|
||||||
.break_ctl = ic3_break_ctl,
|
.break_ctl = ic3_break_ctl,
|
||||||
.startup = ic3_startup,
|
.startup = ic3_startup,
|
||||||
.shutdown = ic3_shutdown,
|
.shutdown = ic3_shutdown,
|
||||||
|
|
|
@ -2597,7 +2597,6 @@ static struct uart_ops ioc4_ops = {
|
||||||
.stop_tx = ic4_stop_tx,
|
.stop_tx = ic4_stop_tx,
|
||||||
.start_tx = ic4_start_tx,
|
.start_tx = ic4_start_tx,
|
||||||
.stop_rx = null_void_function,
|
.stop_rx = null_void_function,
|
||||||
.enable_ms = null_void_function,
|
|
||||||
.break_ctl = ic4_break_ctl,
|
.break_ctl = ic4_break_ctl,
|
||||||
.startup = ic4_startup,
|
.startup = ic4_startup,
|
||||||
.shutdown = ic4_shutdown,
|
.shutdown = ic4_shutdown,
|
||||||
|
|
|
@ -177,11 +177,6 @@ static void jsm_tty_stop_rx(struct uart_port *port)
|
||||||
channel->ch_bd->bd_ops->disable_receiver(channel);
|
channel->ch_bd->bd_ops->disable_receiver(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jsm_tty_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* Nothing needed */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void jsm_tty_break(struct uart_port *port, int break_state)
|
static void jsm_tty_break(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
unsigned long lock_flags;
|
unsigned long lock_flags;
|
||||||
|
@ -354,7 +349,6 @@ static struct uart_ops jsm_ops = {
|
||||||
.start_tx = jsm_tty_start_tx,
|
.start_tx = jsm_tty_start_tx,
|
||||||
.send_xchar = jsm_tty_send_xchar,
|
.send_xchar = jsm_tty_send_xchar,
|
||||||
.stop_rx = jsm_tty_stop_rx,
|
.stop_rx = jsm_tty_stop_rx,
|
||||||
.enable_ms = jsm_tty_enable_ms,
|
|
||||||
.break_ctl = jsm_tty_break,
|
.break_ctl = jsm_tty_break,
|
||||||
.startup = jsm_tty_open,
|
.startup = jsm_tty_open,
|
||||||
.shutdown = jsm_tty_close,
|
.shutdown = jsm_tty_close,
|
||||||
|
|
|
@ -42,7 +42,7 @@ static char *kgdb_nmi_magic = "$3#33";
|
||||||
module_param_named(magic, kgdb_nmi_magic, charp, 0600);
|
module_param_named(magic, kgdb_nmi_magic, charp, 0600);
|
||||||
MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)");
|
MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)");
|
||||||
|
|
||||||
static bool kgdb_nmi_tty_enabled;
|
static atomic_t kgdb_nmi_num_readers = ATOMIC_INIT(0);
|
||||||
|
|
||||||
static int kgdb_nmi_console_setup(struct console *co, char *options)
|
static int kgdb_nmi_console_setup(struct console *co, char *options)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,7 @@ static int kgdb_nmi_poll_one_knock(void)
|
||||||
n = 0;
|
n = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kgdb_nmi_tty_enabled) {
|
if (atomic_read(&kgdb_nmi_num_readers)) {
|
||||||
kgdb_tty_recv(c);
|
kgdb_tty_recv(c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,8 @@ static void kgdb_nmi_tty_receiver(unsigned long data)
|
||||||
priv->timer.expires = jiffies + (HZ/100);
|
priv->timer.expires = jiffies + (HZ/100);
|
||||||
add_timer(&priv->timer);
|
add_timer(&priv->timer);
|
||||||
|
|
||||||
if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo)))
|
if (likely(!atomic_read(&kgdb_nmi_num_readers) ||
|
||||||
|
!kfifo_len(&priv->fifo)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (kfifo_out(&priv->fifo, &ch, 1))
|
while (kfifo_out(&priv->fifo, &ch, 1))
|
||||||
|
@ -270,13 +271,23 @@ static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
|
||||||
static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file)
|
static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file)
|
||||||
{
|
{
|
||||||
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
|
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
|
||||||
|
unsigned int mode = file->f_flags & O_ACCMODE;
|
||||||
|
int ret;
|
||||||
|
|
||||||
return tty_port_open(&priv->port, tty, file);
|
ret = tty_port_open(&priv->port, tty, file);
|
||||||
|
if (!ret && (mode == O_RDONLY || mode == O_RDWR))
|
||||||
|
atomic_inc(&kgdb_nmi_num_readers);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file)
|
static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file)
|
||||||
{
|
{
|
||||||
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
|
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
|
||||||
|
unsigned int mode = file->f_flags & O_ACCMODE;
|
||||||
|
|
||||||
|
if (mode == O_RDONLY || mode == O_RDWR)
|
||||||
|
atomic_dec(&kgdb_nmi_num_readers);
|
||||||
|
|
||||||
tty_port_close(&priv->port, tty, file);
|
tty_port_close(&priv->port, tty, file);
|
||||||
}
|
}
|
||||||
|
@ -313,12 +324,6 @@ static const struct tty_operations kgdb_nmi_tty_ops = {
|
||||||
.write = kgdb_nmi_tty_write,
|
.write = kgdb_nmi_tty_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int kgdb_nmi_enable_console(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
kgdb_nmi_tty_enabled = !(argc == 1 && !strcmp(argv[1], "off"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kgdb_register_nmi_console(void)
|
int kgdb_register_nmi_console(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -348,19 +353,10 @@ int kgdb_register_nmi_console(void)
|
||||||
goto err_drv_reg;
|
goto err_drv_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = kdb_register("nmi_console", kgdb_nmi_enable_console, "[off]",
|
|
||||||
"switch to Linux NMI console", 0);
|
|
||||||
if (ret) {
|
|
||||||
pr_err("%s: can't register kdb command: %d\n", __func__, ret);
|
|
||||||
goto err_kdb_reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
register_console(&kgdb_nmi_console);
|
register_console(&kgdb_nmi_console);
|
||||||
arch_kgdb_ops.enable_nmi(1);
|
arch_kgdb_ops.enable_nmi(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_kdb_reg:
|
|
||||||
tty_unregister_driver(kgdb_nmi_tty_driver);
|
|
||||||
err_drv_reg:
|
err_drv_reg:
|
||||||
put_tty_driver(kgdb_nmi_tty_driver);
|
put_tty_driver(kgdb_nmi_tty_driver);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -375,8 +371,6 @@ int kgdb_unregister_nmi_console(void)
|
||||||
return 0;
|
return 0;
|
||||||
arch_kgdb_ops.enable_nmi(0);
|
arch_kgdb_ops.enable_nmi(0);
|
||||||
|
|
||||||
kdb_unregister("nmi_console");
|
|
||||||
|
|
||||||
ret = unregister_console(&kgdb_nmi_console);
|
ret = unregister_console(&kgdb_nmi_console);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -154,11 +154,6 @@ lqasc_stop_rx(struct uart_port *port)
|
||||||
ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
|
ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
lqasc_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lqasc_rx_chars(struct uart_port *port)
|
lqasc_rx_chars(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
@ -568,7 +563,6 @@ static struct uart_ops lqasc_pops = {
|
||||||
.stop_tx = lqasc_stop_tx,
|
.stop_tx = lqasc_stop_tx,
|
||||||
.start_tx = lqasc_start_tx,
|
.start_tx = lqasc_start_tx,
|
||||||
.stop_rx = lqasc_stop_rx,
|
.stop_rx = lqasc_stop_rx,
|
||||||
.enable_ms = lqasc_enable_ms,
|
|
||||||
.break_ctl = lqasc_break_ctl,
|
.break_ctl = lqasc_break_ctl,
|
||||||
.startup = lqasc_startup,
|
.startup = lqasc_startup,
|
||||||
.shutdown = lqasc_shutdown,
|
.shutdown = lqasc_shutdown,
|
||||||
|
@ -709,7 +703,7 @@ lqasc_probe(struct platform_device *pdev)
|
||||||
port = <q_port->port;
|
port = <q_port->port;
|
||||||
|
|
||||||
port->iotype = SERIAL_IO_MEM;
|
port->iotype = SERIAL_IO_MEM;
|
||||||
port->flags = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
|
port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
|
||||||
port->ops = &lqasc_pops;
|
port->ops = &lqasc_pops;
|
||||||
port->fifosize = 16;
|
port->fifosize = 16;
|
||||||
port->type = PORT_LTQ_ASC,
|
port->type = PORT_LTQ_ASC,
|
||||||
|
|
|
@ -427,12 +427,6 @@ static void serial_lpc32xx_stop_rx(struct uart_port *port)
|
||||||
LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));
|
LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* port->lock held by caller. */
|
|
||||||
static void serial_lpc32xx_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* Modem status is not supported */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* port->lock is not held. */
|
/* port->lock is not held. */
|
||||||
static void serial_lpc32xx_break_ctl(struct uart_port *port,
|
static void serial_lpc32xx_break_ctl(struct uart_port *port,
|
||||||
int break_state)
|
int break_state)
|
||||||
|
@ -658,7 +652,6 @@ static struct uart_ops serial_lpc32xx_pops = {
|
||||||
.stop_tx = serial_lpc32xx_stop_tx,
|
.stop_tx = serial_lpc32xx_stop_tx,
|
||||||
.start_tx = serial_lpc32xx_start_tx,
|
.start_tx = serial_lpc32xx_start_tx,
|
||||||
.stop_rx = serial_lpc32xx_stop_rx,
|
.stop_rx = serial_lpc32xx_stop_rx,
|
||||||
.enable_ms = serial_lpc32xx_enable_ms,
|
|
||||||
.break_ctl = serial_lpc32xx_break_ctl,
|
.break_ctl = serial_lpc32xx_break_ctl,
|
||||||
.startup = serial_lpc32xx_startup,
|
.startup = serial_lpc32xx_startup,
|
||||||
.shutdown = serial_lpc32xx_shutdown,
|
.shutdown = serial_lpc32xx_shutdown,
|
||||||
|
|
|
@ -1008,7 +1008,6 @@ static const struct uart_ops max310x_ops = {
|
||||||
.stop_tx = max310x_null_void,
|
.stop_tx = max310x_null_void,
|
||||||
.start_tx = max310x_start_tx,
|
.start_tx = max310x_start_tx,
|
||||||
.stop_rx = max310x_null_void,
|
.stop_rx = max310x_null_void,
|
||||||
.enable_ms = max310x_null_void,
|
|
||||||
.break_ctl = max310x_break_ctl,
|
.break_ctl = max310x_break_ctl,
|
||||||
.startup = max310x_startup,
|
.startup = max310x_startup,
|
||||||
.shutdown = max310x_shutdown,
|
.shutdown = max310x_shutdown,
|
||||||
|
|
|
@ -150,12 +150,6 @@ static void mcf_break_ctl(struct uart_port *port, int break_state)
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
static void mcf_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
static int mcf_startup(struct uart_port *port)
|
static int mcf_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
|
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
|
||||||
|
@ -507,7 +501,6 @@ static const struct uart_ops mcf_uart_ops = {
|
||||||
.start_tx = mcf_start_tx,
|
.start_tx = mcf_start_tx,
|
||||||
.stop_tx = mcf_stop_tx,
|
.stop_tx = mcf_stop_tx,
|
||||||
.stop_rx = mcf_stop_rx,
|
.stop_rx = mcf_stop_rx,
|
||||||
.enable_ms = mcf_enable_ms,
|
|
||||||
.break_ctl = mcf_break_ctl,
|
.break_ctl = mcf_break_ctl,
|
||||||
.startup = mcf_startup,
|
.startup = mcf_startup,
|
||||||
.shutdown = mcf_shutdown,
|
.shutdown = mcf_shutdown,
|
||||||
|
@ -544,7 +537,7 @@ int __init early_mcf_setup(struct mcf_platform_uart *platp)
|
||||||
port->iotype = SERIAL_IO_MEM;
|
port->iotype = SERIAL_IO_MEM;
|
||||||
port->irq = platp[i].irq;
|
port->irq = platp[i].irq;
|
||||||
port->uartclk = MCF_BUSCLK;
|
port->uartclk = MCF_BUSCLK;
|
||||||
port->flags = ASYNC_BOOT_AUTOCONF;
|
port->flags = UPF_BOOT_AUTOCONF;
|
||||||
port->ops = &mcf_uart_ops;
|
port->ops = &mcf_uart_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,7 +662,7 @@ static int mcf_probe(struct platform_device *pdev)
|
||||||
port->irq = platp[i].irq;
|
port->irq = platp[i].irq;
|
||||||
port->uartclk = MCF_BUSCLK;
|
port->uartclk = MCF_BUSCLK;
|
||||||
port->ops = &mcf_uart_ops;
|
port->ops = &mcf_uart_ops;
|
||||||
port->flags = ASYNC_BOOT_AUTOCONF;
|
port->flags = UPF_BOOT_AUTOCONF;
|
||||||
|
|
||||||
uart_add_one_port(&mcf_driver, port);
|
uart_add_one_port(&mcf_driver, port);
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,9 +308,6 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
|
||||||
if (port->x_char)
|
if (port->x_char)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
|
||||||
uart_write_wakeup(port);
|
|
||||||
|
|
||||||
/* calculate bytes to copy */
|
/* calculate bytes to copy */
|
||||||
qlen = uart_circ_chars_pending(xmit);
|
qlen = uart_circ_chars_pending(xmit);
|
||||||
if (qlen <= 0)
|
if (qlen <= 0)
|
||||||
|
@ -357,6 +354,9 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
|
||||||
|
|
||||||
port->icount.tx += n;
|
port->icount.tx += n;
|
||||||
|
|
||||||
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
|
uart_write_wakeup(port);
|
||||||
|
|
||||||
irq_en:
|
irq_en:
|
||||||
if (!uart_circ_empty(xmit))
|
if (!uart_circ_empty(xmit))
|
||||||
men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
|
men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
|
||||||
|
|
|
@ -1336,10 +1336,6 @@ static void mpsc_stop_rx(struct uart_port *port)
|
||||||
mpsc_sdma_cmd(pi, SDMA_SDCM_AR);
|
mpsc_sdma_cmd(pi, SDMA_SDCM_AR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mpsc_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpsc_break_ctl(struct uart_port *port, int ctl)
|
static void mpsc_break_ctl(struct uart_port *port, int ctl)
|
||||||
{
|
{
|
||||||
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
|
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
|
||||||
|
@ -1674,7 +1670,6 @@ static struct uart_ops mpsc_pops = {
|
||||||
.stop_tx = mpsc_stop_tx,
|
.stop_tx = mpsc_stop_tx,
|
||||||
.start_tx = mpsc_start_tx,
|
.start_tx = mpsc_start_tx,
|
||||||
.stop_rx = mpsc_stop_rx,
|
.stop_rx = mpsc_stop_rx,
|
||||||
.enable_ms = mpsc_enable_ms,
|
|
||||||
.break_ctl = mpsc_break_ctl,
|
.break_ctl = mpsc_break_ctl,
|
||||||
.startup = mpsc_startup,
|
.startup = mpsc_startup,
|
||||||
.shutdown = mpsc_shutdown,
|
.shutdown = mpsc_shutdown,
|
||||||
|
|
|
@ -698,10 +698,6 @@ static void serial_m3110_pm(struct uart_port *port, unsigned int state,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial_m3110_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct uart_ops serial_m3110_ops = {
|
static struct uart_ops serial_m3110_ops = {
|
||||||
.tx_empty = serial_m3110_tx_empty,
|
.tx_empty = serial_m3110_tx_empty,
|
||||||
.set_mctrl = serial_m3110_set_mctrl,
|
.set_mctrl = serial_m3110_set_mctrl,
|
||||||
|
@ -709,7 +705,6 @@ static struct uart_ops serial_m3110_ops = {
|
||||||
.stop_tx = serial_m3110_stop_tx,
|
.stop_tx = serial_m3110_stop_tx,
|
||||||
.start_tx = serial_m3110_start_tx,
|
.start_tx = serial_m3110_start_tx,
|
||||||
.stop_rx = serial_m3110_stop_rx,
|
.stop_rx = serial_m3110_stop_rx,
|
||||||
.enable_ms = serial_m3110_enable_ms,
|
|
||||||
.break_ctl = serial_m3110_break_ctl,
|
.break_ctl = serial_m3110_break_ctl,
|
||||||
.startup = serial_m3110_startup,
|
.startup = serial_m3110_startup,
|
||||||
.shutdown = serial_m3110_shutdown,
|
.shutdown = serial_m3110_shutdown,
|
||||||
|
|
|
@ -125,14 +125,14 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
|
||||||
port->icount.rx += count;
|
port->icount.rx += count;
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
unsigned int c;
|
unsigned char buf[4];
|
||||||
|
|
||||||
sr = msm_read(port, UART_SR);
|
sr = msm_read(port, UART_SR);
|
||||||
if ((sr & UART_SR_RX_READY) == 0) {
|
if ((sr & UART_SR_RX_READY) == 0) {
|
||||||
msm_port->old_snap_state -= count;
|
msm_port->old_snap_state -= count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
c = msm_read(port, UARTDM_RF);
|
ioread32_rep(port->membase + UARTDM_RF, buf, 1);
|
||||||
if (sr & UART_SR_RX_BREAK) {
|
if (sr & UART_SR_RX_BREAK) {
|
||||||
port->icount.brk++;
|
port->icount.brk++;
|
||||||
if (uart_handle_break(port))
|
if (uart_handle_break(port))
|
||||||
|
@ -141,8 +141,7 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
|
||||||
port->icount.frame++;
|
port->icount.frame++;
|
||||||
|
|
||||||
/* TODO: handle sysrq */
|
/* TODO: handle sysrq */
|
||||||
tty_insert_flip_string(tport, (char *)&c,
|
tty_insert_flip_string(tport, buf, min(count, 4));
|
||||||
(count > 4) ? 4 : count);
|
|
||||||
count -= 4;
|
count -= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +218,12 @@ static void handle_tx(struct uart_port *port)
|
||||||
struct msm_port *msm_port = UART_TO_MSM(port);
|
struct msm_port *msm_port = UART_TO_MSM(port);
|
||||||
unsigned int tx_count, num_chars;
|
unsigned int tx_count, num_chars;
|
||||||
unsigned int tf_pointer = 0;
|
unsigned int tf_pointer = 0;
|
||||||
|
void __iomem *tf;
|
||||||
|
|
||||||
|
if (msm_port->is_uartdm)
|
||||||
|
tf = port->membase + UARTDM_TF;
|
||||||
|
else
|
||||||
|
tf = port->membase + UART_TF;
|
||||||
|
|
||||||
tx_count = uart_circ_chars_pending(xmit);
|
tx_count = uart_circ_chars_pending(xmit);
|
||||||
tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
|
tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
|
||||||
|
@ -228,8 +233,7 @@ static void handle_tx(struct uart_port *port)
|
||||||
if (msm_port->is_uartdm)
|
if (msm_port->is_uartdm)
|
||||||
reset_dm_count(port, tx_count + 1);
|
reset_dm_count(port, tx_count + 1);
|
||||||
|
|
||||||
msm_write(port, port->x_char,
|
iowrite8_rep(tf, &port->x_char, 1);
|
||||||
msm_port->is_uartdm ? UARTDM_TF : UART_TF);
|
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
port->x_char = 0;
|
port->x_char = 0;
|
||||||
} else if (tx_count && msm_port->is_uartdm) {
|
} else if (tx_count && msm_port->is_uartdm) {
|
||||||
|
@ -239,7 +243,6 @@ static void handle_tx(struct uart_port *port)
|
||||||
while (tf_pointer < tx_count) {
|
while (tf_pointer < tx_count) {
|
||||||
int i;
|
int i;
|
||||||
char buf[4] = { 0 };
|
char buf[4] = { 0 };
|
||||||
unsigned int *bf = (unsigned int *)&buf;
|
|
||||||
|
|
||||||
if (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
|
if (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
|
||||||
break;
|
break;
|
||||||
|
@ -255,7 +258,7 @@ static void handle_tx(struct uart_port *port)
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
|
iowrite32_rep(tf, buf, 1);
|
||||||
xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1);
|
xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1);
|
||||||
tf_pointer += num_chars;
|
tf_pointer += num_chars;
|
||||||
}
|
}
|
||||||
|
@ -861,12 +864,18 @@ static void msm_console_write(struct console *co, const char *s,
|
||||||
struct msm_port *msm_port;
|
struct msm_port *msm_port;
|
||||||
int num_newlines = 0;
|
int num_newlines = 0;
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
|
void __iomem *tf;
|
||||||
|
|
||||||
BUG_ON(co->index < 0 || co->index >= UART_NR);
|
BUG_ON(co->index < 0 || co->index >= UART_NR);
|
||||||
|
|
||||||
port = get_port_from_line(co->index);
|
port = get_port_from_line(co->index);
|
||||||
msm_port = UART_TO_MSM(port);
|
msm_port = UART_TO_MSM(port);
|
||||||
|
|
||||||
|
if (msm_port->is_uartdm)
|
||||||
|
tf = port->membase + UARTDM_TF;
|
||||||
|
else
|
||||||
|
tf = port->membase + UART_TF;
|
||||||
|
|
||||||
/* Account for newlines that will get a carriage return added */
|
/* Account for newlines that will get a carriage return added */
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
if (s[i] == '\n')
|
if (s[i] == '\n')
|
||||||
|
@ -882,7 +891,6 @@ static void msm_console_write(struct console *co, const char *s,
|
||||||
int j;
|
int j;
|
||||||
unsigned int num_chars;
|
unsigned int num_chars;
|
||||||
char buf[4] = { 0 };
|
char buf[4] = { 0 };
|
||||||
unsigned int *bf = (unsigned int *)&buf;
|
|
||||||
|
|
||||||
if (msm_port->is_uartdm)
|
if (msm_port->is_uartdm)
|
||||||
num_chars = min(count - i, (unsigned int)sizeof(buf));
|
num_chars = min(count - i, (unsigned int)sizeof(buf));
|
||||||
|
@ -907,7 +915,7 @@ static void msm_console_write(struct console *co, const char *s,
|
||||||
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
|
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
|
iowrite32_rep(tf, buf, 1);
|
||||||
i += num_chars;
|
i += num_chars;
|
||||||
}
|
}
|
||||||
spin_unlock(&port->lock);
|
spin_unlock(&port->lock);
|
||||||
|
@ -917,7 +925,7 @@ static int __init msm_console_setup(struct console *co, char *options)
|
||||||
{
|
{
|
||||||
struct uart_port *port;
|
struct uart_port *port;
|
||||||
struct msm_port *msm_port;
|
struct msm_port *msm_port;
|
||||||
int baud, flow, bits, parity;
|
int baud = 0, flow, bits, parity;
|
||||||
|
|
||||||
if (unlikely(co->index >= UART_NR || co->index < 0))
|
if (unlikely(co->index >= UART_NR || co->index < 0))
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
@ -1057,7 +1065,7 @@ static int msm_serial_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct of_device_id msm_match_table[] = {
|
static const struct of_device_id msm_match_table[] = {
|
||||||
{ .compatible = "qcom,msm-uart" },
|
{ .compatible = "qcom,msm-uart" },
|
||||||
{ .compatible = "qcom,msm-uartdm" },
|
{ .compatible = "qcom,msm-uartdm" },
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -126,13 +126,13 @@
|
||||||
static inline
|
static inline
|
||||||
void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
|
void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
|
||||||
{
|
{
|
||||||
__raw_writel(val, port->membase + off);
|
writel_relaxed(val, port->membase + off);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
unsigned int msm_read(struct uart_port *port, unsigned int off)
|
unsigned int msm_read(struct uart_port *port, unsigned int off)
|
||||||
{
|
{
|
||||||
return __raw_readl(port->membase + off);
|
return readl_relaxed(port->membase + off);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -168,16 +168,6 @@ static void mux_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* mux_enable_ms - Enable modum status interrupts.
|
|
||||||
* @port: Ptr to the uart_port.
|
|
||||||
*
|
|
||||||
* The Serial Mux does not support this function.
|
|
||||||
*/
|
|
||||||
static void mux_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mux_break_ctl - Control the transmitssion of a break signal.
|
* mux_break_ctl - Control the transmitssion of a break signal.
|
||||||
* @port: Ptr to the uart_port.
|
* @port: Ptr to the uart_port.
|
||||||
|
@ -449,7 +439,6 @@ static struct uart_ops mux_pops = {
|
||||||
.stop_tx = mux_stop_tx,
|
.stop_tx = mux_stop_tx,
|
||||||
.start_tx = mux_start_tx,
|
.start_tx = mux_start_tx,
|
||||||
.stop_rx = mux_stop_rx,
|
.stop_rx = mux_stop_rx,
|
||||||
.enable_ms = mux_enable_ms,
|
|
||||||
.break_ctl = mux_break_ctl,
|
.break_ctl = mux_break_ctl,
|
||||||
.startup = mux_startup,
|
.startup = mux_startup,
|
||||||
.shutdown = mux_shutdown,
|
.shutdown = mux_shutdown,
|
||||||
|
|
|
@ -815,17 +815,11 @@ static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
|
||||||
u->membase + AUART_LINECTRL_CLR);
|
u->membase + AUART_LINECTRL_CLR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mxs_auart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* just empty */
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct uart_ops mxs_auart_ops = {
|
static struct uart_ops mxs_auart_ops = {
|
||||||
.tx_empty = mxs_auart_tx_empty,
|
.tx_empty = mxs_auart_tx_empty,
|
||||||
.start_tx = mxs_auart_start_tx,
|
.start_tx = mxs_auart_start_tx,
|
||||||
.stop_tx = mxs_auart_stop_tx,
|
.stop_tx = mxs_auart_stop_tx,
|
||||||
.stop_rx = mxs_auart_stop_rx,
|
.stop_rx = mxs_auart_stop_rx,
|
||||||
.enable_ms = mxs_auart_enable_ms,
|
|
||||||
.break_ctl = mxs_auart_break_ctl,
|
.break_ctl = mxs_auart_break_ctl,
|
||||||
.set_mctrl = mxs_auart_set_mctrl,
|
.set_mctrl = mxs_auart_set_mctrl,
|
||||||
.get_mctrl = mxs_auart_get_mctrl,
|
.get_mctrl = mxs_auart_get_mctrl,
|
||||||
|
|
|
@ -240,11 +240,6 @@ static void nwpserial_break_ctl(struct uart_port *port, int ctl)
|
||||||
/* N/A */
|
/* N/A */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nwpserial_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* N/A */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nwpserial_stop_rx(struct uart_port *port)
|
static void nwpserial_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct nwpserial_port *up;
|
struct nwpserial_port *up;
|
||||||
|
@ -315,7 +310,6 @@ static struct uart_ops nwpserial_pops = {
|
||||||
.stop_tx = nwpserial_stop_tx,
|
.stop_tx = nwpserial_stop_tx,
|
||||||
.start_tx = nwpserial_start_tx,
|
.start_tx = nwpserial_start_tx,
|
||||||
.stop_rx = nwpserial_stop_rx,
|
.stop_rx = nwpserial_stop_rx,
|
||||||
.enable_ms = nwpserial_enable_ms,
|
|
||||||
.break_ctl = nwpserial_break_ctl,
|
.break_ctl = nwpserial_break_ctl,
|
||||||
.startup = nwpserial_startup,
|
.startup = nwpserial_startup,
|
||||||
.shutdown = nwpserial_shutdown,
|
.shutdown = nwpserial_shutdown,
|
||||||
|
|
|
@ -736,9 +736,10 @@ static void pch_request_dma(struct uart_port *port)
|
||||||
dma_cap_zero(mask);
|
dma_cap_zero(mask);
|
||||||
dma_cap_set(DMA_SLAVE, mask);
|
dma_cap_set(DMA_SLAVE, mask);
|
||||||
|
|
||||||
dma_dev = pci_get_bus_and_slot(priv->pdev->bus->number,
|
/* Get DMA's dev information */
|
||||||
PCI_DEVFN(0xa, 0)); /* Get DMA's dev
|
dma_dev = pci_get_slot(priv->pdev->bus,
|
||||||
information */
|
PCI_DEVFN(PCI_SLOT(priv->pdev->devfn), 0));
|
||||||
|
|
||||||
/* Set Tx DMA */
|
/* Set Tx DMA */
|
||||||
param = &priv->param_tx;
|
param = &priv->param_tx;
|
||||||
param->dma_dev = &dma_dev->dev;
|
param->dma_dev = &dma_dev->dev;
|
||||||
|
@ -1047,7 +1048,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
|
||||||
priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
|
priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
|
||||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n",
|
dev_err(priv->port.dev, "%s:dmaengine_prep_slave_sg Failed\n",
|
||||||
__func__);
|
__func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -778,7 +778,7 @@ static struct uart_ops serial_pxa_pops = {
|
||||||
.request_port = serial_pxa_request_port,
|
.request_port = serial_pxa_request_port,
|
||||||
.config_port = serial_pxa_config_port,
|
.config_port = serial_pxa_config_port,
|
||||||
.verify_port = serial_pxa_verify_port,
|
.verify_port = serial_pxa_verify_port,
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_PXA_CONSOLE)
|
||||||
.poll_get_char = serial_pxa_get_poll_char,
|
.poll_get_char = serial_pxa_get_poll_char,
|
||||||
.poll_put_char = serial_pxa_put_poll_char,
|
.poll_put_char = serial_pxa_put_poll_char,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -203,10 +203,6 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void s3c24xx_serial_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
|
static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
|
||||||
{
|
{
|
||||||
return to_ourport(port)->info;
|
return to_ourport(port)->info;
|
||||||
|
@ -952,7 +948,6 @@ static struct uart_ops s3c24xx_serial_ops = {
|
||||||
.stop_tx = s3c24xx_serial_stop_tx,
|
.stop_tx = s3c24xx_serial_stop_tx,
|
||||||
.start_tx = s3c24xx_serial_start_tx,
|
.start_tx = s3c24xx_serial_start_tx,
|
||||||
.stop_rx = s3c24xx_serial_stop_rx,
|
.stop_rx = s3c24xx_serial_stop_rx,
|
||||||
.enable_ms = s3c24xx_serial_enable_ms,
|
|
||||||
.break_ctl = s3c24xx_serial_break_ctl,
|
.break_ctl = s3c24xx_serial_break_ctl,
|
||||||
.startup = s3c24xx_serial_startup,
|
.startup = s3c24xx_serial_startup,
|
||||||
.shutdown = s3c24xx_serial_shutdown,
|
.shutdown = s3c24xx_serial_shutdown,
|
||||||
|
@ -1226,8 +1221,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
||||||
wr_regl(port, S3C64XX_UINTSP, 0xf);
|
wr_regl(port, S3C64XX_UINTSP, 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("port: map=%08x, mem=%p, irq=%d (%d,%d), clock=%u\n",
|
dbg("port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
|
||||||
port->mapbase, port->membase, port->irq,
|
&port->mapbase, port->membase, port->irq,
|
||||||
ourport->rx_irq, ourport->tx_irq, port->uartclk);
|
ourport->rx_irq, ourport->tx_irq, port->uartclk);
|
||||||
|
|
||||||
/* reset the fifos (and setup the uart) */
|
/* reset the fifos (and setup the uart) */
|
||||||
|
@ -1274,12 +1269,20 @@ static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data(
|
||||||
|
|
||||||
static int s3c24xx_serial_probe(struct platform_device *pdev)
|
static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct device_node *np = pdev->dev.of_node;
|
||||||
struct s3c24xx_uart_port *ourport;
|
struct s3c24xx_uart_port *ourport;
|
||||||
|
int index = probe_index;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dbg("s3c24xx_serial_probe(%p) %d\n", pdev, probe_index);
|
if (np) {
|
||||||
|
ret = of_alias_get_id(np, "serial");
|
||||||
|
if (ret >= 0)
|
||||||
|
index = ret;
|
||||||
|
}
|
||||||
|
|
||||||
ourport = &s3c24xx_serial_ports[probe_index];
|
dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index);
|
||||||
|
|
||||||
|
ourport = &s3c24xx_serial_ports[index];
|
||||||
|
|
||||||
ourport->drv_data = s3c24xx_get_driver_data(pdev);
|
ourport->drv_data = s3c24xx_get_driver_data(pdev);
|
||||||
if (!ourport->drv_data) {
|
if (!ourport->drv_data) {
|
||||||
|
@ -1293,9 +1296,15 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||||
dev_get_platdata(&pdev->dev) :
|
dev_get_platdata(&pdev->dev) :
|
||||||
ourport->drv_data->def_cfg;
|
ourport->drv_data->def_cfg;
|
||||||
|
|
||||||
ourport->port.fifosize = (ourport->info->fifosize) ?
|
if (np)
|
||||||
ourport->info->fifosize :
|
of_property_read_u32(np,
|
||||||
ourport->drv_data->fifosize[probe_index];
|
"samsung,uart-fifosize", &ourport->port.fifosize);
|
||||||
|
|
||||||
|
if (!ourport->port.fifosize) {
|
||||||
|
ourport->port.fifosize = (ourport->info->fifosize) ?
|
||||||
|
ourport->info->fifosize :
|
||||||
|
ourport->drv_data->fifosize[index];
|
||||||
|
}
|
||||||
|
|
||||||
probe_index++;
|
probe_index++;
|
||||||
|
|
||||||
|
@ -1303,7 +1312,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
ret = s3c24xx_serial_init_port(ourport, pdev);
|
ret = s3c24xx_serial_init_port(ourport, pdev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto probe_err;
|
return ret;
|
||||||
|
|
||||||
if (!s3c24xx_uart_drv.state) {
|
if (!s3c24xx_uart_drv.state) {
|
||||||
ret = uart_register_driver(&s3c24xx_uart_drv);
|
ret = uart_register_driver(&s3c24xx_uart_drv);
|
||||||
|
@ -1335,9 +1344,6 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||||
dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
|
dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
probe_err:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s3c24xx_serial_remove(struct platform_device *dev)
|
static int s3c24xx_serial_remove(struct platform_device *dev)
|
||||||
|
@ -1537,8 +1543,8 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
|
||||||
case S3C2410_LCON_CS7:
|
case S3C2410_LCON_CS7:
|
||||||
*bits = 7;
|
*bits = 7;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
case S3C2410_LCON_CS8:
|
case S3C2410_LCON_CS8:
|
||||||
|
default:
|
||||||
*bits = 8;
|
*bits = 8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1712,9 +1718,7 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
|
||||||
#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
|
#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) || \
|
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
|
||||||
defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) || \
|
|
||||||
defined(CONFIG_CPU_S5PC100)
|
|
||||||
static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
|
static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
|
||||||
.info = &(struct s3c24xx_uart_info) {
|
.info = &(struct s3c24xx_uart_info) {
|
||||||
.name = "Samsung S3C6400 UART",
|
.name = "Samsung S3C6400 UART",
|
||||||
|
|
|
@ -991,7 +991,6 @@ static const struct uart_ops sc16is7xx_ops = {
|
||||||
.stop_tx = sc16is7xx_stop_tx,
|
.stop_tx = sc16is7xx_stop_tx,
|
||||||
.start_tx = sc16is7xx_start_tx,
|
.start_tx = sc16is7xx_start_tx,
|
||||||
.stop_rx = sc16is7xx_stop_rx,
|
.stop_rx = sc16is7xx_stop_rx,
|
||||||
.enable_ms = sc16is7xx_null_void,
|
|
||||||
.break_ctl = sc16is7xx_break_ctl,
|
.break_ctl = sc16is7xx_break_ctl,
|
||||||
.startup = sc16is7xx_startup,
|
.startup = sc16is7xx_startup,
|
||||||
.shutdown = sc16is7xx_shutdown,
|
.shutdown = sc16is7xx_shutdown,
|
||||||
|
@ -1061,7 +1060,6 @@ static int sc16is7xx_probe(struct device *dev,
|
||||||
struct regmap *regmap, int irq, unsigned long flags)
|
struct regmap *regmap, int irq, unsigned long flags)
|
||||||
{
|
{
|
||||||
unsigned long freq, *pfreq = dev_get_platdata(dev);
|
unsigned long freq, *pfreq = dev_get_platdata(dev);
|
||||||
struct clk *clk;
|
|
||||||
int i, ret;
|
int i, ret;
|
||||||
struct sc16is7xx_port *s;
|
struct sc16is7xx_port *s;
|
||||||
|
|
||||||
|
@ -1077,14 +1075,14 @@ static int sc16is7xx_probe(struct device *dev,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
clk = devm_clk_get(dev, NULL);
|
s->clk = devm_clk_get(dev, NULL);
|
||||||
if (IS_ERR(clk)) {
|
if (IS_ERR(s->clk)) {
|
||||||
if (pfreq)
|
if (pfreq)
|
||||||
freq = *pfreq;
|
freq = *pfreq;
|
||||||
else
|
else
|
||||||
return PTR_ERR(clk);
|
return PTR_ERR(s->clk);
|
||||||
} else {
|
} else {
|
||||||
freq = clk_get_rate(clk);
|
freq = clk_get_rate(s->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->regmap = regmap;
|
s->regmap = regmap;
|
||||||
|
|
|
@ -533,11 +533,6 @@ static unsigned int sccnxp_tx_empty(struct uart_port *port)
|
||||||
return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
|
return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sccnxp_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* Do nothing */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
{
|
{
|
||||||
struct sccnxp_port *s = dev_get_drvdata(port->dev);
|
struct sccnxp_port *s = dev_get_drvdata(port->dev);
|
||||||
|
@ -790,7 +785,6 @@ static const struct uart_ops sccnxp_ops = {
|
||||||
.stop_tx = sccnxp_stop_tx,
|
.stop_tx = sccnxp_stop_tx,
|
||||||
.start_tx = sccnxp_start_tx,
|
.start_tx = sccnxp_start_tx,
|
||||||
.stop_rx = sccnxp_stop_rx,
|
.stop_rx = sccnxp_stop_rx,
|
||||||
.enable_ms = sccnxp_enable_ms,
|
|
||||||
.break_ctl = sccnxp_break_ctl,
|
.break_ctl = sccnxp_break_ctl,
|
||||||
.startup = sccnxp_startup,
|
.startup = sccnxp_startup,
|
||||||
.shutdown = sccnxp_shutdown,
|
.shutdown = sccnxp_shutdown,
|
||||||
|
|
|
@ -482,6 +482,9 @@ static void tegra_uart_stop_tx(struct uart_port *u)
|
||||||
struct dma_tx_state state;
|
struct dma_tx_state state;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
|
if (tup->tx_in_progress != TEGRA_UART_TX_DMA)
|
||||||
|
return;
|
||||||
|
|
||||||
dmaengine_terminate_all(tup->tx_dma_chan);
|
dmaengine_terminate_all(tup->tx_dma_chan);
|
||||||
dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
|
dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
|
||||||
count = tup->tx_bytes_requested - state.residue;
|
count = tup->tx_bytes_requested - state.residue;
|
||||||
|
@ -599,6 +602,7 @@ static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup,
|
||||||
|
|
||||||
dmaengine_terminate_all(tup->rx_dma_chan);
|
dmaengine_terminate_all(tup->rx_dma_chan);
|
||||||
dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
|
dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
|
||||||
|
async_tx_ack(tup->rx_dma_desc);
|
||||||
count = tup->rx_bytes_requested - state.residue;
|
count = tup->rx_bytes_requested - state.residue;
|
||||||
|
|
||||||
/* If we are here, DMA is stopped */
|
/* If we are here, DMA is stopped */
|
||||||
|
|
|
@ -243,6 +243,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
|
||||||
/*
|
/*
|
||||||
* Turn off DTR and RTS early.
|
* Turn off DTR and RTS early.
|
||||||
*/
|
*/
|
||||||
|
if (uart_console(uport) && tty)
|
||||||
|
uport->cons->cflag = tty->termios.c_cflag;
|
||||||
|
|
||||||
if (!tty || (tty->termios.c_cflag & HUPCL))
|
if (!tty || (tty->termios.c_cflag & HUPCL))
|
||||||
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
|
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
|
||||||
|
|
||||||
|
@ -447,6 +450,7 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
termios = &tty->termios;
|
termios = &tty->termios;
|
||||||
|
uport->ops->set_termios(uport, termios, old_termios);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set flags based on termios cflag
|
* Set flags based on termios cflag
|
||||||
|
@ -460,8 +464,6 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
||||||
clear_bit(ASYNCB_CHECK_CD, &port->flags);
|
clear_bit(ASYNCB_CHECK_CD, &port->flags);
|
||||||
else
|
else
|
||||||
set_bit(ASYNCB_CHECK_CD, &port->flags);
|
set_bit(ASYNCB_CHECK_CD, &port->flags);
|
||||||
|
|
||||||
uport->ops->set_termios(uport, termios, old_termios);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int __uart_put_char(struct uart_port *port,
|
static inline int __uart_put_char(struct uart_port *port,
|
||||||
|
@ -1050,6 +1052,15 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void uart_enable_ms(struct uart_port *uport)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Force modem status interrupts on
|
||||||
|
*/
|
||||||
|
if (uport->ops->enable_ms)
|
||||||
|
uport->ops->enable_ms(uport);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
|
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
|
||||||
* - mask passed in arg for lines of interest
|
* - mask passed in arg for lines of interest
|
||||||
|
@ -1073,11 +1084,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
|
||||||
*/
|
*/
|
||||||
spin_lock_irq(&uport->lock);
|
spin_lock_irq(&uport->lock);
|
||||||
memcpy(&cprev, &uport->icount, sizeof(struct uart_icount));
|
memcpy(&cprev, &uport->icount, sizeof(struct uart_icount));
|
||||||
|
uart_enable_ms(uport);
|
||||||
/*
|
|
||||||
* Force modem status interrupts on
|
|
||||||
*/
|
|
||||||
uport->ops->enable_ms(uport);
|
|
||||||
spin_unlock_irq(&uport->lock);
|
spin_unlock_irq(&uport->lock);
|
||||||
|
|
||||||
add_wait_queue(&port->delta_msr_wait, &wait);
|
add_wait_queue(&port->delta_msr_wait, &wait);
|
||||||
|
@ -1274,6 +1281,8 @@ static void uart_set_termios(struct tty_struct *tty,
|
||||||
}
|
}
|
||||||
|
|
||||||
uart_change_speed(tty, state, old_termios);
|
uart_change_speed(tty, state, old_termios);
|
||||||
|
/* reload cflag from termios; port driver may have overriden flags */
|
||||||
|
cflag = tty->termios.c_cflag;
|
||||||
|
|
||||||
/* Handle transition to B0 status */
|
/* Handle transition to B0 status */
|
||||||
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
|
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
|
||||||
|
@ -1360,8 +1369,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
||||||
tty_ldisc_flush(tty);
|
tty_ldisc_flush(tty);
|
||||||
|
|
||||||
tty_port_tty_set(port, NULL);
|
tty_port_tty_set(port, NULL);
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
|
||||||
tty->closing = 0;
|
tty->closing = 0;
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
if (port->blocked_open) {
|
if (port->blocked_open) {
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
@ -1508,7 +1517,7 @@ static int uart_carrier_raised(struct tty_port *port)
|
||||||
struct uart_port *uport = state->uart_port;
|
struct uart_port *uport = state->uart_port;
|
||||||
int mctrl;
|
int mctrl;
|
||||||
spin_lock_irq(&uport->lock);
|
spin_lock_irq(&uport->lock);
|
||||||
uport->ops->enable_ms(uport);
|
uart_enable_ms(uport);
|
||||||
mctrl = uport->ops->get_mctrl(uport);
|
mctrl = uport->ops->get_mctrl(uport);
|
||||||
spin_unlock_irq(&uport->lock);
|
spin_unlock_irq(&uport->lock);
|
||||||
if (mctrl & TIOCM_CAR)
|
if (mctrl & TIOCM_CAR)
|
||||||
|
@ -1575,14 +1584,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
|
||||||
(state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;
|
(state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;
|
||||||
tty_port_tty_set(port, tty);
|
tty_port_tty_set(port, tty);
|
||||||
|
|
||||||
/*
|
|
||||||
* If the port is in the middle of closing, bail out now.
|
|
||||||
*/
|
|
||||||
if (tty_hung_up_p(filp)) {
|
|
||||||
retval = -EAGAIN;
|
|
||||||
goto err_dec_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start up the serial port.
|
* Start up the serial port.
|
||||||
*/
|
*/
|
||||||
|
@ -2563,12 +2564,6 @@ static const struct attribute_group tty_dev_attr_group = {
|
||||||
.attrs = tty_dev_attrs,
|
.attrs = tty_dev_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct attribute_group *tty_dev_attr_groups[] = {
|
|
||||||
&tty_dev_attr_group,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* uart_add_one_port - attach a driver-defined port structure
|
* uart_add_one_port - attach a driver-defined port structure
|
||||||
* @drv: pointer to the uart low level driver structure for this port
|
* @drv: pointer to the uart low level driver structure for this port
|
||||||
|
@ -2585,6 +2580,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||||
struct tty_port *port;
|
struct tty_port *port;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct device *tty_dev;
|
struct device *tty_dev;
|
||||||
|
int num_groups;
|
||||||
|
|
||||||
BUG_ON(in_interrupt());
|
BUG_ON(in_interrupt());
|
||||||
|
|
||||||
|
@ -2618,12 +2614,26 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||||
|
|
||||||
uart_configure_port(drv, state, uport);
|
uart_configure_port(drv, state, uport);
|
||||||
|
|
||||||
|
num_groups = 2;
|
||||||
|
if (uport->attr_group)
|
||||||
|
num_groups++;
|
||||||
|
|
||||||
|
uport->tty_groups = kcalloc(num_groups, sizeof(*uport->tty_groups),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!uport->tty_groups) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
uport->tty_groups[0] = &tty_dev_attr_group;
|
||||||
|
if (uport->attr_group)
|
||||||
|
uport->tty_groups[1] = uport->attr_group;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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 port's 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, uport->tty_groups);
|
||||||
if (likely(!IS_ERR(tty_dev))) {
|
if (likely(!IS_ERR(tty_dev))) {
|
||||||
device_set_wakeup_capable(tty_dev, 1);
|
device_set_wakeup_capable(tty_dev, 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2702,6 +2712,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||||
*/
|
*/
|
||||||
if (uport->type != PORT_UNKNOWN)
|
if (uport->type != PORT_UNKNOWN)
|
||||||
uport->ops->release_port(uport);
|
uport->ops->release_port(uport);
|
||||||
|
kfree(uport->tty_groups);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Indicate that there isn't a port here anymore.
|
* Indicate that there isn't a port here anymore.
|
||||||
|
|
|
@ -142,7 +142,6 @@ struct uart_txx9_port {
|
||||||
#define TXX9_SIFCR_RDIL_12 0x00000180
|
#define TXX9_SIFCR_RDIL_12 0x00000180
|
||||||
#define TXX9_SIFCR_RDIL_MAX 0x00000180
|
#define TXX9_SIFCR_RDIL_MAX 0x00000180
|
||||||
#define TXX9_SIFCR_TDIL_MASK 0x00000018
|
#define TXX9_SIFCR_TDIL_MASK 0x00000018
|
||||||
#define TXX9_SIFCR_TDIL_MASK 0x00000018
|
|
||||||
#define TXX9_SIFCR_TDIL_1 0x00000000
|
#define TXX9_SIFCR_TDIL_1 0x00000000
|
||||||
#define TXX9_SIFCR_TDIL_4 0x00000001
|
#define TXX9_SIFCR_TDIL_4 0x00000001
|
||||||
#define TXX9_SIFCR_TDIL_8 0x00000010
|
#define TXX9_SIFCR_TDIL_8 0x00000010
|
||||||
|
@ -244,11 +243,6 @@ static void serial_txx9_stop_rx(struct uart_port *port)
|
||||||
up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
|
up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial_txx9_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* TXX9-SIO can not control DTR... */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void serial_txx9_initialize(struct uart_port *port)
|
static void serial_txx9_initialize(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_txx9_port *up = to_uart_txx9_port(port);
|
struct uart_txx9_port *up = to_uart_txx9_port(port);
|
||||||
|
@ -858,7 +852,6 @@ static struct uart_ops serial_txx9_pops = {
|
||||||
.stop_tx = serial_txx9_stop_tx,
|
.stop_tx = serial_txx9_stop_tx,
|
||||||
.start_tx = serial_txx9_start_tx,
|
.start_tx = serial_txx9_start_tx,
|
||||||
.stop_rx = serial_txx9_stop_rx,
|
.stop_rx = serial_txx9_stop_rx,
|
||||||
.enable_ms = serial_txx9_enable_ms,
|
|
||||||
.break_ctl = serial_txx9_break_ctl,
|
.break_ctl = serial_txx9_break_ctl,
|
||||||
.startup = serial_txx9_startup,
|
.startup = serial_txx9_startup,
|
||||||
.shutdown = serial_txx9_shutdown,
|
.shutdown = serial_txx9_shutdown,
|
||||||
|
|
|
@ -1560,13 +1560,6 @@ static void sci_stop_rx(struct uart_port *port)
|
||||||
serial_port_out(port, SCSCR, ctrl);
|
serial_port_out(port, SCSCR, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sci_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Not supported by hardware, always a nop.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sci_break_ctl(struct uart_port *port, int break_state)
|
static void sci_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
struct sci_port *s = to_sci_port(port);
|
struct sci_port *s = to_sci_port(port);
|
||||||
|
@ -1783,30 +1776,71 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
|
||||||
return ((freq + 16 * bps) / (32 * bps) - 1);
|
return ((freq + 16 * bps) / (32 * bps) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* calculate frame length from SMR */
|
||||||
|
static int sci_baud_calc_frame_len(unsigned int smr_val)
|
||||||
|
{
|
||||||
|
int len = 10;
|
||||||
|
|
||||||
|
if (smr_val & SCSMR_CHR)
|
||||||
|
len--;
|
||||||
|
if (smr_val & SCSMR_PE)
|
||||||
|
len++;
|
||||||
|
if (smr_val & SCSMR_STOP)
|
||||||
|
len++;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* calculate sample rate, BRR, and clock select for HSCIF */
|
/* calculate sample rate, BRR, and clock select for HSCIF */
|
||||||
static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
|
static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
|
||||||
int *brr, unsigned int *srr,
|
int *brr, unsigned int *srr,
|
||||||
unsigned int *cks)
|
unsigned int *cks, int frame_len)
|
||||||
{
|
{
|
||||||
int sr, c, br, err;
|
int sr, c, br, err, recv_margin;
|
||||||
int min_err = 1000; /* 100% */
|
int min_err = 1000; /* 100% */
|
||||||
|
int recv_max_margin = 0;
|
||||||
|
|
||||||
/* Find the combination of sample rate and clock select with the
|
/* Find the combination of sample rate and clock select with the
|
||||||
smallest deviation from the desired baud rate. */
|
smallest deviation from the desired baud rate. */
|
||||||
for (sr = 8; sr <= 32; sr++) {
|
for (sr = 8; sr <= 32; sr++) {
|
||||||
for (c = 0; c <= 3; c++) {
|
for (c = 0; c <= 3; c++) {
|
||||||
/* integerized formulas from HSCIF documentation */
|
/* integerized formulas from HSCIF documentation */
|
||||||
br = freq / (sr * (1 << (2 * c + 1)) * bps) - 1;
|
br = DIV_ROUND_CLOSEST(freq, (sr *
|
||||||
if (br < 0 || br > 255)
|
(1 << (2 * c + 1)) * bps)) - 1;
|
||||||
|
br = clamp(br, 0, 255);
|
||||||
|
err = DIV_ROUND_CLOSEST(freq, ((br + 1) * bps * sr *
|
||||||
|
(1 << (2 * c + 1)) / 1000)) -
|
||||||
|
1000;
|
||||||
|
if (err < 0)
|
||||||
continue;
|
continue;
|
||||||
err = freq / ((br + 1) * bps * sr *
|
|
||||||
(1 << (2 * c + 1)) / 1000) - 1000;
|
/* Calc recv margin
|
||||||
|
* M: Receive margin (%)
|
||||||
|
* N: Ratio of bit rate to clock (N = sampling rate)
|
||||||
|
* D: Clock duty (D = 0 to 1.0)
|
||||||
|
* L: Frame length (L = 9 to 12)
|
||||||
|
* F: Absolute value of clock frequency deviation
|
||||||
|
*
|
||||||
|
* M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) -
|
||||||
|
* (|D - 0.5| / N * (1 + F))|
|
||||||
|
* NOTE: Usually, treat D for 0.5, F is 0 by this
|
||||||
|
* calculation.
|
||||||
|
*/
|
||||||
|
recv_margin = abs((500 -
|
||||||
|
DIV_ROUND_CLOSEST(1000, sr << 1)) / 10);
|
||||||
if (min_err > err) {
|
if (min_err > err) {
|
||||||
min_err = err;
|
min_err = err;
|
||||||
*brr = br;
|
recv_max_margin = recv_margin;
|
||||||
*srr = sr - 1;
|
} else if ((min_err == err) &&
|
||||||
*cks = c;
|
(recv_margin > recv_max_margin))
|
||||||
}
|
recv_max_margin = recv_margin;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*brr = br;
|
||||||
|
*srr = sr - 1;
|
||||||
|
*cks = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1840,10 +1874,19 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
{
|
{
|
||||||
struct sci_port *s = to_sci_port(port);
|
struct sci_port *s = to_sci_port(port);
|
||||||
struct plat_sci_reg *reg;
|
struct plat_sci_reg *reg;
|
||||||
unsigned int baud, smr_val, max_baud, cks = 0;
|
unsigned int baud, smr_val = 0, max_baud, cks = 0;
|
||||||
int t = -1;
|
int t = -1;
|
||||||
unsigned int srr = 15;
|
unsigned int srr = 15;
|
||||||
|
|
||||||
|
if ((termios->c_cflag & CSIZE) == CS7)
|
||||||
|
smr_val |= SCSMR_CHR;
|
||||||
|
if (termios->c_cflag & PARENB)
|
||||||
|
smr_val |= SCSMR_PE;
|
||||||
|
if (termios->c_cflag & PARODD)
|
||||||
|
smr_val |= SCSMR_PE | SCSMR_ODD;
|
||||||
|
if (termios->c_cflag & CSTOPB)
|
||||||
|
smr_val |= SCSMR_STOP;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* earlyprintk comes here early on with port->uartclk set to zero.
|
* earlyprintk comes here early on with port->uartclk set to zero.
|
||||||
* the clock framework is not up and running at this point so here
|
* the clock framework is not up and running at this point so here
|
||||||
|
@ -1857,8 +1900,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
|
baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
|
||||||
if (likely(baud && port->uartclk)) {
|
if (likely(baud && port->uartclk)) {
|
||||||
if (s->cfg->type == PORT_HSCIF) {
|
if (s->cfg->type == PORT_HSCIF) {
|
||||||
|
int frame_len = sci_baud_calc_frame_len(smr_val);
|
||||||
sci_baud_calc_hscif(baud, port->uartclk, &t, &srr,
|
sci_baud_calc_hscif(baud, port->uartclk, &t, &srr,
|
||||||
&cks);
|
&cks, frame_len);
|
||||||
} else {
|
} else {
|
||||||
t = sci_scbrr_calc(s, baud, port->uartclk);
|
t = sci_scbrr_calc(s, baud, port->uartclk);
|
||||||
for (cks = 0; t >= 256 && cks <= 3; cks++)
|
for (cks = 0; t >= 256 && cks <= 3; cks++)
|
||||||
|
@ -1870,16 +1914,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
|
|
||||||
sci_reset(port);
|
sci_reset(port);
|
||||||
|
|
||||||
smr_val = serial_port_in(port, SCSMR) & 3;
|
smr_val |= serial_port_in(port, SCSMR) & 3;
|
||||||
|
|
||||||
if ((termios->c_cflag & CSIZE) == CS7)
|
|
||||||
smr_val |= SCSMR_CHR;
|
|
||||||
if (termios->c_cflag & PARENB)
|
|
||||||
smr_val |= SCSMR_PE;
|
|
||||||
if (termios->c_cflag & PARODD)
|
|
||||||
smr_val |= SCSMR_PE | SCSMR_ODD;
|
|
||||||
if (termios->c_cflag & CSTOPB)
|
|
||||||
smr_val |= SCSMR_STOP;
|
|
||||||
|
|
||||||
uart_update_timeout(port, termios->c_cflag, baud);
|
uart_update_timeout(port, termios->c_cflag, baud);
|
||||||
|
|
||||||
|
@ -2080,7 +2115,6 @@ static struct uart_ops sci_uart_ops = {
|
||||||
.start_tx = sci_start_tx,
|
.start_tx = sci_start_tx,
|
||||||
.stop_tx = sci_stop_tx,
|
.stop_tx = sci_stop_tx,
|
||||||
.stop_rx = sci_stop_rx,
|
.stop_rx = sci_stop_rx,
|
||||||
.enable_ms = sci_enable_ms,
|
|
||||||
.break_ctl = sci_break_ctl,
|
.break_ctl = sci_break_ctl,
|
||||||
.startup = sci_startup,
|
.startup = sci_startup,
|
||||||
.shutdown = sci_shutdown,
|
.shutdown = sci_shutdown,
|
||||||
|
|
|
@ -290,7 +290,8 @@ static void sirfsoc_uart_start_tx(struct uart_port *port)
|
||||||
if (sirfport->tx_dma_chan)
|
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,
|
||||||
|
SIRFSOC_UART_IO_TX_REASONABLE_CNT);
|
||||||
wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
|
wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
|
||||||
if (!sirfport->is_marco)
|
if (!sirfport->is_marco)
|
||||||
wr_regl(port, ureg->sirfsoc_int_en_reg,
|
wr_regl(port, ureg->sirfsoc_int_en_reg,
|
||||||
|
|
|
@ -449,4 +449,4 @@ struct sirfsoc_uart_port {
|
||||||
|
|
||||||
/* I/O Mode */
|
/* I/O Mode */
|
||||||
#define SIRFSOC_UART_IO_RX_MAX_CNT 256
|
#define SIRFSOC_UART_IO_RX_MAX_CNT 256
|
||||||
#define SIRFSOC_UART_IO_TX_REASONABLE_CNT 6
|
#define SIRFSOC_UART_IO_TX_REASONABLE_CNT 256
|
||||||
|
|
|
@ -274,15 +274,6 @@ static void snp_release_port(struct uart_port *port)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* snp_enable_ms - Force modem status interrupts on - no-op for us
|
|
||||||
* @port: Port to operate on - we ignore - no-op function
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void snp_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snp_shutdown - shut down the port - free irq and disable - no-op for us
|
* snp_shutdown - shut down the port - free irq and disable - no-op for us
|
||||||
* @port: Port to shut down - we ignore
|
* @port: Port to shut down - we ignore
|
||||||
|
@ -396,7 +387,6 @@ static struct uart_ops sn_console_ops = {
|
||||||
.stop_tx = snp_stop_tx,
|
.stop_tx = snp_stop_tx,
|
||||||
.start_tx = snp_start_tx,
|
.start_tx = snp_start_tx,
|
||||||
.stop_rx = snp_stop_rx,
|
.stop_rx = snp_stop_rx,
|
||||||
.enable_ms = snp_enable_ms,
|
|
||||||
.break_ctl = snp_break_ctl,
|
.break_ctl = snp_break_ctl,
|
||||||
.startup = snp_startup,
|
.startup = snp_startup,
|
||||||
.shutdown = snp_shutdown,
|
.shutdown = snp_shutdown,
|
||||||
|
|
|
@ -411,12 +411,6 @@ static void asc_stop_rx(struct uart_port *port)
|
||||||
asc_disable_rx_interrupts(port);
|
asc_disable_rx_interrupts(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Force modem status interrupts on */
|
|
||||||
static void asc_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* Nothing here yet .. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle breaks - ignored by us */
|
/* Handle breaks - ignored by us */
|
||||||
static void asc_break_ctl(struct uart_port *port, int break_state)
|
static void asc_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
|
@ -533,12 +527,12 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
* ASCBaudRate = ------------------------
|
* ASCBaudRate = ------------------------
|
||||||
* inputclock
|
* inputclock
|
||||||
*
|
*
|
||||||
* However to keep the maths inside 32bits we divide top and
|
* To keep maths inside 64bits, we divide inputclock by 16.
|
||||||
* bottom by 64. The +1 is to avoid a divide by zero if the
|
|
||||||
* input clock rate is something unexpected.
|
|
||||||
*/
|
*/
|
||||||
u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1);
|
u64 dividend = (u64)baud * (1 << 16);
|
||||||
asc_out(port, ASC_BAUDRATE, counter);
|
|
||||||
|
do_div(dividend, port->uartclk / 16);
|
||||||
|
asc_out(port, ASC_BAUDRATE, dividend);
|
||||||
ctrl_val |= ASC_CTL_BAUDMODE;
|
ctrl_val |= ASC_CTL_BAUDMODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,7 +638,6 @@ static struct uart_ops asc_uart_ops = {
|
||||||
.start_tx = asc_start_tx,
|
.start_tx = asc_start_tx,
|
||||||
.stop_tx = asc_stop_tx,
|
.stop_tx = asc_stop_tx,
|
||||||
.stop_rx = asc_stop_rx,
|
.stop_rx = asc_stop_rx,
|
||||||
.enable_ms = asc_enable_ms,
|
|
||||||
.break_ctl = asc_break_ctl,
|
.break_ctl = asc_break_ctl,
|
||||||
.startup = asc_startup,
|
.startup = asc_startup,
|
||||||
.shutdown = asc_shutdown,
|
.shutdown = asc_shutdown,
|
||||||
|
@ -849,7 +842,8 @@ static int asc_console_setup(struct console *co, char *options)
|
||||||
* this to be called during the uart port registration when the
|
* this to be called during the uart port registration when the
|
||||||
* driver gets probed and the port should be mapped at that point.
|
* driver gets probed and the port should be mapped at that point.
|
||||||
*/
|
*/
|
||||||
BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL);
|
if (ascport->port.mapbase == 0 || ascport->port.membase == NULL)
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
if (options)
|
if (options)
|
||||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||||
|
|
|
@ -285,11 +285,6 @@ static void sunhv_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* port->lock held by caller. */
|
|
||||||
static void sunhv_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* port->lock is not held. */
|
/* port->lock is not held. */
|
||||||
static void sunhv_break_ctl(struct uart_port *port, int break_state)
|
static void sunhv_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
|
@ -379,7 +374,6 @@ static struct uart_ops sunhv_pops = {
|
||||||
.start_tx = sunhv_start_tx,
|
.start_tx = sunhv_start_tx,
|
||||||
.send_xchar = sunhv_send_xchar,
|
.send_xchar = sunhv_send_xchar,
|
||||||
.stop_rx = sunhv_stop_rx,
|
.stop_rx = sunhv_stop_rx,
|
||||||
.enable_ms = sunhv_enable_ms,
|
|
||||||
.break_ctl = sunhv_break_ctl,
|
.break_ctl = sunhv_break_ctl,
|
||||||
.startup = sunhv_startup,
|
.startup = sunhv_startup,
|
||||||
.shutdown = sunhv_shutdown,
|
.shutdown = sunhv_shutdown,
|
||||||
|
|
|
@ -476,12 +476,6 @@ static void sunsab_stop_rx(struct uart_port *port)
|
||||||
writeb(up->interrupt_mask1, &up->regs->w.imr0);
|
writeb(up->interrupt_mask1, &up->regs->w.imr0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* port->lock held by caller. */
|
|
||||||
static void sunsab_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* For now we always receive these interrupts. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* port->lock is not held. */
|
/* port->lock is not held. */
|
||||||
static void sunsab_break_ctl(struct uart_port *port, int break_state)
|
static void sunsab_break_ctl(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
|
@ -810,7 +804,6 @@ static struct uart_ops sunsab_pops = {
|
||||||
.start_tx = sunsab_start_tx,
|
.start_tx = sunsab_start_tx,
|
||||||
.send_xchar = sunsab_send_xchar,
|
.send_xchar = sunsab_send_xchar,
|
||||||
.stop_rx = sunsab_stop_rx,
|
.stop_rx = sunsab_stop_rx,
|
||||||
.enable_ms = sunsab_enable_ms,
|
|
||||||
.break_ctl = sunsab_break_ctl,
|
.break_ctl = sunsab_break_ctl,
|
||||||
.startup = sunsab_startup,
|
.startup = sunsab_startup,
|
||||||
.shutdown = sunsab_shutdown,
|
.shutdown = sunsab_shutdown,
|
||||||
|
|
|
@ -314,15 +314,6 @@ static void tilegx_stop_rx(struct uart_port *port)
|
||||||
mutex_unlock(&tile_uart->mutex);
|
mutex_unlock(&tile_uart->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable modem status interrupts.
|
|
||||||
*/
|
|
||||||
static void tilegx_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* N/A */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Control the transmission of a break signal.
|
* Control the transmission of a break signal.
|
||||||
*/
|
*/
|
||||||
|
@ -614,7 +605,6 @@ static const struct uart_ops tilegx_ops = {
|
||||||
.stop_tx = tilegx_stop_tx,
|
.stop_tx = tilegx_stop_tx,
|
||||||
.start_tx = tilegx_start_tx,
|
.start_tx = tilegx_start_tx,
|
||||||
.stop_rx = tilegx_stop_rx,
|
.stop_rx = tilegx_stop_rx,
|
||||||
.enable_ms = tilegx_enable_ms,
|
|
||||||
.break_ctl = tilegx_break_ctl,
|
.break_ctl = tilegx_break_ctl,
|
||||||
.startup = tilegx_startup,
|
.startup = tilegx_startup,
|
||||||
.shutdown = tilegx_shutdown,
|
.shutdown = tilegx_shutdown,
|
||||||
|
|
|
@ -244,11 +244,6 @@ static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
|
||||||
*ier |= CTS_DELTA;
|
*ier |= CTS_DELTA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timbuart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* N/A */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void timbuart_break_ctl(struct uart_port *port, int ctl)
|
static void timbuart_break_ctl(struct uart_port *port, int ctl)
|
||||||
{
|
{
|
||||||
/* N/A */
|
/* N/A */
|
||||||
|
@ -405,7 +400,6 @@ static struct uart_ops timbuart_ops = {
|
||||||
.start_tx = timbuart_start_tx,
|
.start_tx = timbuart_start_tx,
|
||||||
.flush_buffer = timbuart_flush_buffer,
|
.flush_buffer = timbuart_flush_buffer,
|
||||||
.stop_rx = timbuart_stop_rx,
|
.stop_rx = timbuart_stop_rx,
|
||||||
.enable_ms = timbuart_enable_ms,
|
|
||||||
.break_ctl = timbuart_break_ctl,
|
.break_ctl = timbuart_break_ctl,
|
||||||
.startup = timbuart_startup,
|
.startup = timbuart_startup,
|
||||||
.shutdown = timbuart_shutdown,
|
.shutdown = timbuart_shutdown,
|
||||||
|
|
|
@ -250,11 +250,6 @@ static void ulite_stop_rx(struct uart_port *port)
|
||||||
| ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
|
| ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ulite_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* N/A */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ulite_break_ctl(struct uart_port *port, int ctl)
|
static void ulite_break_ctl(struct uart_port *port, int ctl)
|
||||||
{
|
{
|
||||||
/* N/A */
|
/* N/A */
|
||||||
|
@ -395,7 +390,6 @@ static struct uart_ops ulite_ops = {
|
||||||
.stop_tx = ulite_stop_tx,
|
.stop_tx = ulite_stop_tx,
|
||||||
.start_tx = ulite_start_tx,
|
.start_tx = ulite_start_tx,
|
||||||
.stop_rx = ulite_stop_rx,
|
.stop_rx = ulite_stop_rx,
|
||||||
.enable_ms = ulite_enable_ms,
|
|
||||||
.break_ctl = ulite_break_ctl,
|
.break_ctl = ulite_break_ctl,
|
||||||
.startup = ulite_startup,
|
.startup = ulite_startup,
|
||||||
.shutdown = ulite_shutdown,
|
.shutdown = ulite_shutdown,
|
||||||
|
|
|
@ -435,16 +435,6 @@ static void qe_uart_stop_rx(struct uart_port *port)
|
||||||
clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
|
clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable status change interrupts
|
|
||||||
*
|
|
||||||
* We don't support status change interrupts, but we need to define this
|
|
||||||
* function otherwise the kernel will panic.
|
|
||||||
*/
|
|
||||||
static void qe_uart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start or stop sending break signal
|
/* Start or stop sending break signal
|
||||||
*
|
*
|
||||||
* This function controls the sending of a break signal. If break_state=1,
|
* This function controls the sending of a break signal. If break_state=1,
|
||||||
|
@ -1102,7 +1092,6 @@ static struct uart_ops qe_uart_pops = {
|
||||||
.stop_tx = qe_uart_stop_tx,
|
.stop_tx = qe_uart_stop_tx,
|
||||||
.start_tx = qe_uart_start_tx,
|
.start_tx = qe_uart_start_tx,
|
||||||
.stop_rx = qe_uart_stop_rx,
|
.stop_rx = qe_uart_stop_rx,
|
||||||
.enable_ms = qe_uart_enable_ms,
|
|
||||||
.break_ctl = qe_uart_break_ctl,
|
.break_ctl = qe_uart_break_ctl,
|
||||||
.startup = qe_uart_startup,
|
.startup = qe_uart_startup,
|
||||||
.shutdown = qe_uart_shutdown,
|
.shutdown = qe_uart_shutdown,
|
||||||
|
|
|
@ -918,11 +918,6 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
/* N/A */
|
/* N/A */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cdns_uart_enable_ms(struct uart_port *port)
|
|
||||||
{
|
|
||||||
/* N/A */
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
static int cdns_uart_poll_get_char(struct uart_port *port)
|
static int cdns_uart_poll_get_char(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
@ -974,7 +969,6 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c)
|
||||||
static struct uart_ops cdns_uart_ops = {
|
static struct uart_ops cdns_uart_ops = {
|
||||||
.set_mctrl = cdns_uart_set_mctrl,
|
.set_mctrl = cdns_uart_set_mctrl,
|
||||||
.get_mctrl = cdns_uart_get_mctrl,
|
.get_mctrl = cdns_uart_get_mctrl,
|
||||||
.enable_ms = cdns_uart_enable_ms,
|
|
||||||
.start_tx = cdns_uart_start_tx,
|
.start_tx = cdns_uart_start_tx,
|
||||||
.stop_tx = cdns_uart_stop_tx,
|
.stop_tx = cdns_uart_stop_tx,
|
||||||
.stop_rx = cdns_uart_stop_rx,
|
.stop_rx = cdns_uart_stop_rx,
|
||||||
|
|
|
@ -3267,7 +3267,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
int retval;
|
int retval;
|
||||||
bool do_clocal = false;
|
bool do_clocal = false;
|
||||||
bool extra_count = false;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int dcd;
|
int dcd;
|
||||||
struct tty_port *port = &info->port;
|
struct tty_port *port = &info->port;
|
||||||
|
@ -3300,10 +3299,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
__FILE__,__LINE__, tty->driver->name, port->count );
|
__FILE__,__LINE__, tty->driver->name, port->count );
|
||||||
|
|
||||||
spin_lock_irqsave(&info->irq_spinlock, flags);
|
spin_lock_irqsave(&info->irq_spinlock, flags);
|
||||||
if (!tty_hung_up_p(filp)) {
|
port->count--;
|
||||||
extra_count = true;
|
|
||||||
port->count--;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&info->irq_spinlock, flags);
|
spin_unlock_irqrestore(&info->irq_spinlock, flags);
|
||||||
port->blocked_open++;
|
port->blocked_open++;
|
||||||
|
|
||||||
|
@ -3342,7 +3338,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
remove_wait_queue(&port->open_wait, &wait);
|
remove_wait_queue(&port->open_wait, &wait);
|
||||||
|
|
||||||
/* FIXME: Racy on hangup during close wait */
|
/* FIXME: Racy on hangup during close wait */
|
||||||
if (extra_count)
|
if (!tty_hung_up_p(filp))
|
||||||
port->count++;
|
port->count++;
|
||||||
port->blocked_open--;
|
port->blocked_open--;
|
||||||
|
|
||||||
|
@ -3403,7 +3399,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
|
||||||
__FILE__,__LINE__,tty->driver->name, info->port.count);
|
__FILE__,__LINE__,tty->driver->name, info->port.count);
|
||||||
|
|
||||||
/* If port is closing, signal caller to try again */
|
/* If port is closing, signal caller to try again */
|
||||||
if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
|
if (info->port.flags & ASYNC_CLOSING){
|
||||||
wait_event_interruptible_tty(tty, info->port.close_wait,
|
wait_event_interruptible_tty(tty, info->port.close_wait,
|
||||||
!(info->port.flags & ASYNC_CLOSING));
|
!(info->port.flags & ASYNC_CLOSING));
|
||||||
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
|
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
|
||||||
|
|
|
@ -673,7 +673,7 @@ static int open(struct tty_struct *tty, struct file *filp)
|
||||||
DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
|
DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
|
||||||
|
|
||||||
/* If port is closing, signal caller to try again */
|
/* If port is closing, signal caller to try again */
|
||||||
if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
|
if (info->port.flags & ASYNC_CLOSING){
|
||||||
wait_event_interruptible_tty(tty, info->port.close_wait,
|
wait_event_interruptible_tty(tty, info->port.close_wait,
|
||||||
!(info->port.flags & ASYNC_CLOSING));
|
!(info->port.flags & ASYNC_CLOSING));
|
||||||
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
|
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
|
||||||
|
@ -3273,7 +3273,6 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
int retval;
|
int retval;
|
||||||
bool do_clocal = false;
|
bool do_clocal = false;
|
||||||
bool extra_count = false;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int cd;
|
int cd;
|
||||||
struct tty_port *port = &info->port;
|
struct tty_port *port = &info->port;
|
||||||
|
@ -3300,10 +3299,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
|
||||||
add_wait_queue(&port->open_wait, &wait);
|
add_wait_queue(&port->open_wait, &wait);
|
||||||
|
|
||||||
spin_lock_irqsave(&info->lock, flags);
|
spin_lock_irqsave(&info->lock, flags);
|
||||||
if (!tty_hung_up_p(filp)) {
|
port->count--;
|
||||||
extra_count = true;
|
|
||||||
port->count--;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&info->lock, flags);
|
spin_unlock_irqrestore(&info->lock, flags);
|
||||||
port->blocked_open++;
|
port->blocked_open++;
|
||||||
|
|
||||||
|
@ -3338,7 +3334,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&port->open_wait, &wait);
|
remove_wait_queue(&port->open_wait, &wait);
|
||||||
|
|
||||||
if (extra_count)
|
if (!tty_hung_up_p(filp))
|
||||||
port->count++;
|
port->count++;
|
||||||
port->blocked_open--;
|
port->blocked_open--;
|
||||||
|
|
||||||
|
|
|
@ -753,7 +753,7 @@ static int open(struct tty_struct *tty, struct file *filp)
|
||||||
__FILE__,__LINE__,tty->driver->name, info->port.count);
|
__FILE__,__LINE__,tty->driver->name, info->port.count);
|
||||||
|
|
||||||
/* If port is closing, signal caller to try again */
|
/* If port is closing, signal caller to try again */
|
||||||
if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
|
if (info->port.flags & ASYNC_CLOSING){
|
||||||
wait_event_interruptible_tty(tty, info->port.close_wait,
|
wait_event_interruptible_tty(tty, info->port.close_wait,
|
||||||
!(info->port.flags & ASYNC_CLOSING));
|
!(info->port.flags & ASYNC_CLOSING));
|
||||||
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
|
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
|
||||||
|
@ -3288,7 +3288,6 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
int retval;
|
int retval;
|
||||||
bool do_clocal = false;
|
bool do_clocal = false;
|
||||||
bool extra_count = false;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int cd;
|
int cd;
|
||||||
struct tty_port *port = &info->port;
|
struct tty_port *port = &info->port;
|
||||||
|
@ -3322,10 +3321,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
|
||||||
__FILE__,__LINE__, tty->driver->name, port->count );
|
__FILE__,__LINE__, tty->driver->name, port->count );
|
||||||
|
|
||||||
spin_lock_irqsave(&info->lock, flags);
|
spin_lock_irqsave(&info->lock, flags);
|
||||||
if (!tty_hung_up_p(filp)) {
|
port->count--;
|
||||||
extra_count = true;
|
|
||||||
port->count--;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&info->lock, flags);
|
spin_unlock_irqrestore(&info->lock, flags);
|
||||||
port->blocked_open++;
|
port->blocked_open++;
|
||||||
|
|
||||||
|
@ -3362,8 +3358,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&port->open_wait, &wait);
|
remove_wait_queue(&port->open_wait, &wait);
|
||||||
|
if (!tty_hung_up_p(filp))
|
||||||
if (extra_count)
|
|
||||||
port->count++;
|
port->count++;
|
||||||
port->blocked_open--;
|
port->blocked_open--;
|
||||||
|
|
||||||
|
|
|
@ -156,20 +156,6 @@ static void release_tty(struct tty_struct *tty, int idx);
|
||||||
static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
|
static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
|
||||||
static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
|
static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
|
||||||
|
|
||||||
/**
|
|
||||||
* alloc_tty_struct - allocate a tty object
|
|
||||||
*
|
|
||||||
* Return a new empty tty structure. The data fields have not
|
|
||||||
* been initialized in any way but has been zeroed
|
|
||||||
*
|
|
||||||
* Locking: none
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct tty_struct *alloc_tty_struct(void)
|
|
||||||
{
|
|
||||||
return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* free_tty_struct - free a disused tty
|
* free_tty_struct - free a disused tty
|
||||||
* @tty: tty struct to free
|
* @tty: tty struct to free
|
||||||
|
@ -688,7 +674,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
|
||||||
for (n = 0; n < closecount; n++)
|
for (n = 0; n < closecount; n++)
|
||||||
tty->ops->close(tty, cons_filp);
|
tty->ops->close(tty, cons_filp);
|
||||||
} else if (tty->ops->hangup)
|
} else if (tty->ops->hangup)
|
||||||
(tty->ops->hangup)(tty);
|
tty->ops->hangup(tty);
|
||||||
/*
|
/*
|
||||||
* We don't want to have driver/ldisc interactions beyond
|
* We don't want to have driver/ldisc interactions beyond
|
||||||
* the ones we did here. The driver layer expects no
|
* the ones we did here. The driver layer expects no
|
||||||
|
@ -1455,12 +1441,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
|
||||||
if (!try_module_get(driver->owner))
|
if (!try_module_get(driver->owner))
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
tty = alloc_tty_struct();
|
tty = alloc_tty_struct(driver, idx);
|
||||||
if (!tty) {
|
if (!tty) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto err_module_put;
|
goto err_module_put;
|
||||||
}
|
}
|
||||||
initialize_tty_struct(tty, driver, idx);
|
|
||||||
|
|
||||||
tty_lock(tty);
|
tty_lock(tty);
|
||||||
retval = tty_driver_install_tty(driver, tty);
|
retval = tty_driver_install_tty(driver, tty);
|
||||||
|
@ -3003,19 +2988,21 @@ static struct device *tty_get_device(struct tty_struct *tty)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize_tty_struct
|
* alloc_tty_struct
|
||||||
* @tty: tty to initialize
|
|
||||||
*
|
*
|
||||||
* This subroutine initializes a tty structure that has been newly
|
* This subroutine allocates and initializes a tty structure.
|
||||||
* allocated.
|
|
||||||
*
|
*
|
||||||
* Locking: none - tty in question must not be exposed at this point
|
* Locking: none - tty in question is not exposed at this point
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void initialize_tty_struct(struct tty_struct *tty,
|
struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
|
||||||
struct tty_driver *driver, int idx)
|
|
||||||
{
|
{
|
||||||
memset(tty, 0, sizeof(struct tty_struct));
|
struct tty_struct *tty;
|
||||||
|
|
||||||
|
tty = kzalloc(sizeof(*tty), GFP_KERNEL);
|
||||||
|
if (!tty)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
kref_init(&tty->kref);
|
kref_init(&tty->kref);
|
||||||
tty->magic = TTY_MAGIC;
|
tty->magic = TTY_MAGIC;
|
||||||
tty_ldisc_init(tty);
|
tty_ldisc_init(tty);
|
||||||
|
@ -3039,6 +3026,8 @@ void initialize_tty_struct(struct tty_struct *tty,
|
||||||
tty->index = idx;
|
tty->index = idx;
|
||||||
tty_line_name(driver, idx, tty->name);
|
tty_line_name(driver, idx, tty->name);
|
||||||
tty->dev = tty_get_device(tty);
|
tty->dev = tty_get_device(tty);
|
||||||
|
|
||||||
|
return tty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -227,6 +227,8 @@ out:
|
||||||
*
|
*
|
||||||
* Perform port level tty hangup flag and count changes. Drop the tty
|
* Perform port level tty hangup flag and count changes. Drop the tty
|
||||||
* reference.
|
* reference.
|
||||||
|
*
|
||||||
|
* Caller holds tty lock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void tty_port_hangup(struct tty_port *port)
|
void tty_port_hangup(struct tty_port *port)
|
||||||
|
@ -348,6 +350,11 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts);
|
||||||
* do carrier detect and the dtr_rts method if it supports software
|
* do carrier detect and the dtr_rts method if it supports software
|
||||||
* management of these lines. Note that the dtr/rts raise is done each
|
* management of these lines. Note that the dtr/rts raise is done each
|
||||||
* iteration as a hangup may have previously dropped them while we wait.
|
* iteration as a hangup may have previously dropped them while we wait.
|
||||||
|
*
|
||||||
|
* Caller holds tty lock.
|
||||||
|
*
|
||||||
|
* NB: May drop and reacquire tty lock when blocking, so tty and tty_port
|
||||||
|
* may have changed state (eg., may have been hung up).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int tty_port_block_til_ready(struct tty_port *port,
|
int tty_port_block_til_ready(struct tty_port *port,
|
||||||
|
@ -358,7 +365,7 @@ int tty_port_block_til_ready(struct tty_port *port,
|
||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
|
|
||||||
/* block if port is in the process of being closed */
|
/* block if port is in the process of being closed */
|
||||||
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
|
if (port->flags & ASYNC_CLOSING) {
|
||||||
wait_event_interruptible_tty(tty, port->close_wait,
|
wait_event_interruptible_tty(tty, port->close_wait,
|
||||||
!(port->flags & ASYNC_CLOSING));
|
!(port->flags & ASYNC_CLOSING));
|
||||||
if (port->flags & ASYNC_HUP_NOTIFY)
|
if (port->flags & ASYNC_HUP_NOTIFY)
|
||||||
|
@ -392,8 +399,7 @@ int tty_port_block_til_ready(struct tty_port *port,
|
||||||
|
|
||||||
/* The port lock protects the port counts */
|
/* The port lock protects the port counts */
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
if (!tty_hung_up_p(filp))
|
port->count--;
|
||||||
port->count--;
|
|
||||||
port->blocked_open++;
|
port->blocked_open++;
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
@ -458,6 +464,10 @@ static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
|
||||||
schedule_timeout_interruptible(timeout);
|
schedule_timeout_interruptible(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Caller holds tty lock.
|
||||||
|
* NB: may drop and reacquire tty lock (in tty_wait_until_sent_from_close())
|
||||||
|
* so tty and tty port may have changed state (but not hung up or reopened).
|
||||||
|
*/
|
||||||
int tty_port_close_start(struct tty_port *port,
|
int tty_port_close_start(struct tty_port *port,
|
||||||
struct tty_struct *tty, struct file *filp)
|
struct tty_struct *tty, struct file *filp)
|
||||||
{
|
{
|
||||||
|
@ -486,9 +496,10 @@ int tty_port_close_start(struct tty_port *port,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
set_bit(ASYNCB_CLOSING, &port->flags);
|
set_bit(ASYNCB_CLOSING, &port->flags);
|
||||||
tty->closing = 1;
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
tty->closing = 1;
|
||||||
|
|
||||||
if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
|
if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
|
||||||
/* Don't block on a stalled port, just pull the chain */
|
/* Don't block on a stalled port, just pull the chain */
|
||||||
if (tty->flow_stopped)
|
if (tty->flow_stopped)
|
||||||
|
@ -506,13 +517,15 @@ int tty_port_close_start(struct tty_port *port,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_port_close_start);
|
EXPORT_SYMBOL(tty_port_close_start);
|
||||||
|
|
||||||
|
/* Caller holds tty lock */
|
||||||
void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
|
void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
|
||||||
tty->closing = 0;
|
tty->closing = 0;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
if (port->blocked_open) {
|
if (port->blocked_open) {
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
if (port->close_delay) {
|
if (port->close_delay) {
|
||||||
|
@ -528,6 +541,15 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_port_close_end);
|
EXPORT_SYMBOL(tty_port_close_end);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tty_port_close
|
||||||
|
*
|
||||||
|
* Caller holds tty lock
|
||||||
|
*
|
||||||
|
* NB: may drop and reacquire tty lock (in tty_port_close_start()->
|
||||||
|
* tty_wait_until_sent_from_close()) so tty and tty_port may have changed
|
||||||
|
* state (but not hung up or reopened).
|
||||||
|
*/
|
||||||
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
|
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
|
||||||
struct file *filp)
|
struct file *filp)
|
||||||
{
|
{
|
||||||
|
@ -558,12 +580,19 @@ int tty_port_install(struct tty_port *port, struct tty_driver *driver,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tty_port_install);
|
EXPORT_SYMBOL_GPL(tty_port_install);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tty_port_open
|
||||||
|
*
|
||||||
|
* Caller holds tty lock.
|
||||||
|
*
|
||||||
|
* NB: may drop and reacquire tty lock (in tty_port_block_til_ready()) so
|
||||||
|
* tty and tty_port may have changed state (eg., may be hung up now)
|
||||||
|
*/
|
||||||
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
|
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
|
||||||
struct file *filp)
|
struct file *filp)
|
||||||
{
|
{
|
||||||
spin_lock_irq(&port->lock);
|
spin_lock_irq(&port->lock);
|
||||||
if (!tty_hung_up_p(filp))
|
++port->count;
|
||||||
++port->count;
|
|
||||||
spin_unlock_irq(&port->lock);
|
spin_unlock_irq(&port->lock);
|
||||||
tty_port_tty_set(port, tty);
|
tty_port_tty_set(port, tty);
|
||||||
|
|
||||||
|
|
|
@ -74,8 +74,10 @@ struct uart_8250_port {
|
||||||
struct list_head list; /* ports on this IRQ */
|
struct list_head list; /* ports on this IRQ */
|
||||||
unsigned short capabilities; /* port capabilities */
|
unsigned short capabilities; /* port capabilities */
|
||||||
unsigned short bugs; /* port bugs */
|
unsigned short bugs; /* port bugs */
|
||||||
|
bool fifo_bug; /* min RX trigger if enabled */
|
||||||
unsigned int tx_loadsz; /* transmit fifo load size */
|
unsigned int tx_loadsz; /* transmit fifo load size */
|
||||||
unsigned char acr;
|
unsigned char acr;
|
||||||
|
unsigned char fcr;
|
||||||
unsigned char ier;
|
unsigned char ier;
|
||||||
unsigned char lcr;
|
unsigned char lcr;
|
||||||
unsigned char mcr;
|
unsigned char mcr;
|
||||||
|
@ -100,6 +102,11 @@ struct uart_8250_port {
|
||||||
void (*dl_write)(struct uart_8250_port *, int);
|
void (*dl_write)(struct uart_8250_port *, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline struct uart_8250_port *up_to_u8250p(struct uart_port *up)
|
||||||
|
{
|
||||||
|
return container_of(up, struct uart_8250_port, port);
|
||||||
|
}
|
||||||
|
|
||||||
int serial8250_register_8250_port(struct uart_8250_port *);
|
int serial8250_register_8250_port(struct uart_8250_port *);
|
||||||
void serial8250_unregister_port(int line);
|
void serial8250_unregister_port(int line);
|
||||||
void serial8250_suspend_port(int line);
|
void serial8250_suspend_port(int line);
|
||||||
|
|
|
@ -199,6 +199,8 @@ struct uart_port {
|
||||||
unsigned char suspended;
|
unsigned char suspended;
|
||||||
unsigned char irq_wake;
|
unsigned char irq_wake;
|
||||||
unsigned char unused[2];
|
unsigned char unused[2];
|
||||||
|
struct attribute_group *attr_group; /* port specific attributes */
|
||||||
|
const struct attribute_group **tty_groups; /* all attributes (serial core use only) */
|
||||||
void *private_data; /* generic platform data pointer */
|
void *private_data; /* generic platform data pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -477,13 +477,11 @@ extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg);
|
unsigned int cmd, unsigned long arg);
|
||||||
extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
|
extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
|
||||||
extern void tty_default_fops(struct file_operations *fops);
|
extern void tty_default_fops(struct file_operations *fops);
|
||||||
extern struct tty_struct *alloc_tty_struct(void);
|
extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx);
|
||||||
extern int tty_alloc_file(struct file *file);
|
extern int tty_alloc_file(struct file *file);
|
||||||
extern void tty_add_file(struct tty_struct *tty, struct file *file);
|
extern void tty_add_file(struct tty_struct *tty, struct file *file);
|
||||||
extern void tty_free_file(struct file *file);
|
extern void tty_free_file(struct file *file);
|
||||||
extern void free_tty_struct(struct tty_struct *tty);
|
extern void free_tty_struct(struct tty_struct *tty);
|
||||||
extern void initialize_tty_struct(struct tty_struct *tty,
|
|
||||||
struct tty_driver *driver, int idx);
|
|
||||||
extern void deinitialize_tty_struct(struct tty_struct *tty);
|
extern void deinitialize_tty_struct(struct tty_struct *tty);
|
||||||
extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
|
extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
|
||||||
extern int tty_release(struct inode *inode, struct file *filp);
|
extern int tty_release(struct inode *inode, struct file *filp);
|
||||||
|
|
|
@ -35,14 +35,14 @@
|
||||||
* This routine is mandatory; if this routine is not filled in,
|
* This routine is mandatory; if this routine is not filled in,
|
||||||
* the attempted open will fail with ENODEV.
|
* the attempted open will fail with ENODEV.
|
||||||
*
|
*
|
||||||
* Required method.
|
* Required method. Called with tty lock held.
|
||||||
*
|
*
|
||||||
* void (*close)(struct tty_struct * tty, struct file * filp);
|
* void (*close)(struct tty_struct * tty, struct file * filp);
|
||||||
*
|
*
|
||||||
* This routine is called when a particular tty device is closed.
|
* This routine is called when a particular tty device is closed.
|
||||||
* Note: called even if the corresponding open() failed.
|
* Note: called even if the corresponding open() failed.
|
||||||
*
|
*
|
||||||
* Required method.
|
* Required method. Called with tty lock held.
|
||||||
*
|
*
|
||||||
* void (*shutdown)(struct tty_struct * tty);
|
* void (*shutdown)(struct tty_struct * tty);
|
||||||
*
|
*
|
||||||
|
@ -172,6 +172,8 @@
|
||||||
*
|
*
|
||||||
* Optional:
|
* Optional:
|
||||||
*
|
*
|
||||||
|
* Called with tty lock held.
|
||||||
|
*
|
||||||
* int (*break_ctl)(struct tty_struct *tty, int state);
|
* int (*break_ctl)(struct tty_struct *tty, int state);
|
||||||
*
|
*
|
||||||
* This optional routine requests the tty driver to turn on or
|
* This optional routine requests the tty driver to turn on or
|
||||||
|
|
|
@ -88,6 +88,11 @@
|
||||||
#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
|
#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
|
||||||
#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode (TI16C750) */
|
#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode (TI16C750) */
|
||||||
|
|
||||||
|
#define UART_FCR_R_TRIG_SHIFT 6
|
||||||
|
#define UART_FCR_R_TRIG_BITS(x) \
|
||||||
|
(((x) & UART_FCR_TRIGGER_MASK) >> UART_FCR_R_TRIG_SHIFT)
|
||||||
|
#define UART_FCR_R_TRIG_MAX_STATE 4
|
||||||
|
|
||||||
#define UART_LCR 3 /* Out: Line Control Register */
|
#define UART_LCR 3 /* Out: Line Control Register */
|
||||||
/*
|
/*
|
||||||
* Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
|
* Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
|
||||||
|
|
|
@ -320,8 +320,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
|
||||||
__FILE__, __LINE__, tty->driver->name, port->count);
|
__FILE__, __LINE__, tty->driver->name, port->count);
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
if (!tty_hung_up_p(filp))
|
port->count--;
|
||||||
port->count--;
|
|
||||||
port->blocked_open++;
|
port->blocked_open++;
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
@ -458,8 +457,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||||
/*
|
/*
|
||||||
* If the port is the middle of closing, bail out now
|
* If the port is the middle of closing, bail out now
|
||||||
*/
|
*/
|
||||||
if (tty_hung_up_p(filp) ||
|
if (test_bit(ASYNCB_CLOSING, &self->port.flags)) {
|
||||||
test_bit(ASYNCB_CLOSING, &self->port.flags)) {
|
|
||||||
|
|
||||||
/* Hm, why are we blocking on ASYNC_CLOSING if we
|
/* Hm, why are we blocking on ASYNC_CLOSING if we
|
||||||
* do return -EAGAIN/-ERESTARTSYS below anyway?
|
* do return -EAGAIN/-ERESTARTSYS below anyway?
|
||||||
|
|
Loading…
Reference in a new issue