mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
TTY/Serial patches for 4.5-rc1
Here is the big serial/tty driver updates for 4.5-rc1. Lots of driver updates and some tty core changes. All of these have been in linux-next and the details are in the shortlog. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iEYEABECAAYFAlaV0iQACgkQMUfUDdst+ynukgCeNdulE6XMg5Xp3Wn3hs0ZW6fo YmUAoMRrtjFCixhiGHoNKTm35V4gC2sy =D64i -----END PGP SIGNATURE----- Merge tag 'tty-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial updates from Greg KH: "Here is the big serial/tty driver update for 4.5-rc1. Lots of driver updates and some tty core changes. All of these have been in linux-next and the details are in the shortlog" * tag 'tty-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (127 commits) drivers/tty/serial: delete unused MODULE_DEVICE_TABLE from atmel_serial.c serial: sh-sci: Remove cpufreq notifier to fix crash/deadlock serial: 8250: of: Fix the driver and actually compile the 8250_of tty: amba-pl011: use iotype instead of access_32b to track 32-bit I/O tty: amba-pl011: fix earlycon register offsets serial: sh-sci: Drop the sci_fck clock fallback sh: sh7734: Correct SCIF type for BRG sh: Remove sci_ick clock alias sh: Rename sci_ick and sci_fck clock to fck serial: sh-sci: Add support for optional BRG on (H)SCIF serial: sh-sci: Add support for optional external (H)SCK input serial: sh-sci: Prepare for multiple sampling clock sources serial: sh-sci: Correct SCIF type on R-Car for BRG serial: sh-sci: Correct SCIF type on RZ/A1H serial: sh-sci: Replace struct sci_port_info by type/regtype encoding serial: sh-sci: Add BRG register definitions serial: sh-sci: Take into account sampling rate for max baud rate serial: sh-sci: Merge sci_scbrr_calc() and sci_baud_calc_hscif() serial: sh-sci: Avoid calculating the receive margin for HSCIF serial: sh-sci: Improve bit rate error calculation for HSCIF ...
This commit is contained in:
commit
67ad058d97
@ -2,7 +2,7 @@
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Must contain one of the following:
|
||||
- compatible: Must contain one or more of the following:
|
||||
|
||||
- "renesas,scif-r7s72100" for R7S72100 (RZ/A1H) SCIF compatible UART.
|
||||
- "renesas,scifa-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFA compatible UART.
|
||||
@ -15,10 +15,14 @@ Required properties:
|
||||
- "renesas,scifa-r8a7790" for R8A7790 (R-Car H2) SCIFA compatible UART.
|
||||
- "renesas,scifb-r8a7790" for R8A7790 (R-Car H2) SCIFB compatible UART.
|
||||
- "renesas,hscif-r8a7790" for R8A7790 (R-Car H2) HSCIF compatible UART.
|
||||
- "renesas,scif-r8a7791" for R8A7791 (R-Car M2) SCIF compatible UART.
|
||||
- "renesas,scifa-r8a7791" for R8A7791 (R-Car M2) SCIFA compatible UART.
|
||||
- "renesas,scifb-r8a7791" for R8A7791 (R-Car M2) SCIFB compatible UART.
|
||||
- "renesas,hscif-r8a7791" for R8A7791 (R-Car M2) HSCIF compatible UART.
|
||||
- "renesas,scif-r8a7791" for R8A7791 (R-Car M2-W) SCIF compatible UART.
|
||||
- "renesas,scifa-r8a7791" for R8A7791 (R-Car M2-W) SCIFA compatible UART.
|
||||
- "renesas,scifb-r8a7791" for R8A7791 (R-Car M2-W) SCIFB compatible UART.
|
||||
- "renesas,hscif-r8a7791" for R8A7791 (R-Car M2-W) HSCIF compatible UART.
|
||||
- "renesas,scif-r8a7793" for R8A7793 (R-Car M2-N) SCIF compatible UART.
|
||||
- "renesas,scifa-r8a7793" for R8A7793 (R-Car M2-N) SCIFA compatible UART.
|
||||
- "renesas,scifb-r8a7793" for R8A7793 (R-Car M2-N) SCIFB compatible UART.
|
||||
- "renesas,hscif-r8a7793" for R8A7793 (R-Car M2-N) HSCIF compatible UART.
|
||||
- "renesas,scif-r8a7794" for R8A7794 (R-Car E2) SCIF compatible UART.
|
||||
- "renesas,scifa-r8a7794" for R8A7794 (R-Car E2) SCIFA compatible UART.
|
||||
- "renesas,scifb-r8a7794" for R8A7794 (R-Car E2) SCIFB compatible UART.
|
||||
@ -27,6 +31,14 @@ Required properties:
|
||||
- "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
|
||||
- "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART.
|
||||
- "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART.
|
||||
- "renesas,rcar-gen1-scif" for R-Car Gen1 SCIF compatible UART,
|
||||
- "renesas,rcar-gen2-scif" for R-Car Gen2 SCIF compatible UART,
|
||||
- "renesas,rcar-gen3-scif" for R-Car Gen3 SCIF compatible UART,
|
||||
- "renesas,rcar-gen2-scifa" for R-Car Gen2 SCIFA compatible UART,
|
||||
- "renesas,rcar-gen2-scifb" for R-Car Gen2 SCIFB compatible UART,
|
||||
- "renesas,rcar-gen1-hscif" for R-Car Gen1 HSCIF compatible UART,
|
||||
- "renesas,rcar-gen2-hscif" for R-Car Gen2 HSCIF compatible UART,
|
||||
- "renesas,rcar-gen3-hscif" for R-Car Gen3 HSCIF compatible UART,
|
||||
- "renesas,scif" for generic SCIF compatible UART.
|
||||
- "renesas,scifa" for generic SCIFA compatible UART.
|
||||
- "renesas,scifb" for generic SCIFB compatible UART.
|
||||
@ -34,15 +46,26 @@ Required properties:
|
||||
- "renesas,sci" for generic SCI compatible UART.
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first followed by the
|
||||
generic version.
|
||||
SoC-specific version corresponding to the platform first, followed by the
|
||||
family-specific and/or generic versions.
|
||||
|
||||
- reg: Base address and length of the I/O registers used by the UART.
|
||||
- interrupts: Must contain an interrupt-specifier for the SCIx interrupt.
|
||||
|
||||
- clocks: Must contain a phandle and clock-specifier pair for each entry
|
||||
in clock-names.
|
||||
- clock-names: Must contain "sci_ick" for the SCIx UART interface clock.
|
||||
- clock-names: Must contain "fck" for the SCIx UART functional clock.
|
||||
Apart from the divided functional clock, there may be other possible
|
||||
sources for the sampling clock, depending on SCIx variant.
|
||||
On (H)SCI(F) and some SCIFA, an additional clock may be specified:
|
||||
- "hsck" for the optional external clock input (on HSCIF),
|
||||
- "sck" for the optional external clock input (on other variants).
|
||||
On UARTs equipped with a Baud Rate Generator for External Clock (BRG)
|
||||
(some SCIF and HSCIF), additional clocks may be specified:
|
||||
- "brg_int" for the optional internal clock source for the frequency
|
||||
divider (typically the (AXI or SHwy) bus clock),
|
||||
- "scif_clk" for the optional external clock source for the frequency
|
||||
divider (SCIF_CLK).
|
||||
|
||||
Note: Each enabled SCIx UART should have an alias correctly numbered in the
|
||||
"aliases" node.
|
||||
@ -58,12 +81,13 @@ Example:
|
||||
};
|
||||
|
||||
scifa0: serial@e6c40000 {
|
||||
compatible = "renesas,scifa-r8a7790", "renesas,scifa";
|
||||
compatible = "renesas,scifa-r8a7790",
|
||||
"renesas,rcar-gen2-scifa", "renesas,scifa";
|
||||
reg = <0 0xe6c40000 0 64>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
|
||||
clock-names = "sci_ick";
|
||||
clock-names = "fck";
|
||||
dmas = <&dmac0 0x21>, <&dmac0 0x22>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
@ -730,16 +730,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
|
||||
uart[8250],io,<addr>[,options]
|
||||
uart[8250],mmio,<addr>[,options]
|
||||
uart[8250],mmio16,<addr>[,options]
|
||||
uart[8250],mmio32,<addr>[,options]
|
||||
uart[8250],0x<addr>[,options]
|
||||
Start an early, polled-mode console on the 8250/16550
|
||||
UART at the specified I/O port or MMIO address,
|
||||
switching to the matching ttyS device later.
|
||||
MMIO inter-register address stride is either 8-bit
|
||||
(mmio) or 32-bit (mmio32).
|
||||
If none of [io|mmio|mmio32], <addr> is assumed to be
|
||||
equivalent to 'mmio'. 'options' are specified in the
|
||||
same format described for ttyS above; if unspecified,
|
||||
(mmio), 16-bit (mmio16), or 32-bit (mmio32).
|
||||
If none of [io|mmio|mmio16|mmio32], <addr> is assumed
|
||||
to be equivalent to 'mmio'. 'options' are specified in
|
||||
the same format described for ttyS above; if unspecified,
|
||||
the h/w is not re-initialized.
|
||||
|
||||
hvc<n> Use the hypervisor console device <n>. This is for
|
||||
@ -1011,10 +1012,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
unspecified, the h/w is not initialized.
|
||||
|
||||
pl011,<addr>
|
||||
pl011,mmio32,<addr>
|
||||
Start an early, polled-mode console on a pl011 serial
|
||||
port at the specified address. The pl011 serial port
|
||||
must already be setup and configured. Options are not
|
||||
yet supported.
|
||||
yet supported. If 'mmio32' is specified, then only
|
||||
the driver will use only 32-bit accessors to read/write
|
||||
the device registers.
|
||||
|
||||
msm_serial,<addr>
|
||||
Start an early, polled-mode console on an msm serial
|
||||
|
@ -63,7 +63,6 @@ int __init __deprecated cpg_clk_init(void)
|
||||
clk_add_alias("fck", "sh-mtu2", "peripheral_clk", NULL);
|
||||
clk_add_alias("fck", "sh-cmt-16.0", "peripheral_clk", NULL);
|
||||
clk_add_alias("fck", "sh-cmt-32.0", "peripheral_clk", NULL);
|
||||
clk_add_alias("sci_ick", NULL, "peripheral_clk", NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -115,7 +115,14 @@ static struct clk_lookup lookups[] = {
|
||||
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
|
||||
|
||||
/* MSTP clocks */
|
||||
CLKDEV_CON_ID("sci_ick", &mstp_clks[MSTP77]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP77]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP77]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP77]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP77]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP77]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP77]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.6", &mstp_clks[MSTP77]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.7", &mstp_clks[MSTP77]),
|
||||
CLKDEV_CON_ID("vdc3", &mstp_clks[MSTP74]),
|
||||
CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]),
|
||||
CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
|
||||
|
@ -150,14 +150,14 @@ static struct clk_lookup lookups[] = {
|
||||
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
|
||||
|
||||
/* MSTP clocks */
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP44]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP43]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP47]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP46]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP45]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP44]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP43]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP42]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.6", &mstp_clks[MSTP41]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.7", &mstp_clks[MSTP40]),
|
||||
CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]),
|
||||
CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
|
||||
CLKDEV_ICK_ID("fck", "sh-mtu2", &mstp_clks[MSTP35]),
|
||||
|
@ -232,10 +232,10 @@ static struct clk_lookup lookups[] = {
|
||||
CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
|
||||
CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
|
||||
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP004]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP004]),
|
||||
|
||||
CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]),
|
||||
CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]),
|
||||
|
@ -230,9 +230,9 @@ static struct clk_lookup lookups[] = {
|
||||
CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
|
||||
CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
|
||||
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]),
|
||||
|
||||
CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
|
||||
CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),
|
||||
|
@ -267,12 +267,12 @@ static struct clk_lookup lookups[] = {
|
||||
CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[HWBLK_TMU0]),
|
||||
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[HWBLK_TMU1]),
|
||||
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[HWBLK_SCIF5]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[HWBLK_SCIF5]),
|
||||
|
||||
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]),
|
||||
};
|
||||
|
@ -194,12 +194,12 @@ static struct clk_lookup lookups[] = {
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_DEV_ID("i2c-sh7734.0", &mstp_clks[MSTP030]),
|
||||
CLKDEV_DEV_ID("i2c-sh7734.1", &mstp_clks[MSTP029]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP026]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP024]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP023]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP022]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP021]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP026]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP024]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP023]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP022]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP021]),
|
||||
CLKDEV_CON_ID("hscif", &mstp_clks[MSTP019]),
|
||||
CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]),
|
||||
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]),
|
||||
|
@ -125,9 +125,9 @@ static struct clk_lookup lookups[] = {
|
||||
|
||||
CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP113]),
|
||||
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP114]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP112]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP112]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP111]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP110]),
|
||||
|
||||
CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]),
|
||||
CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP102]),
|
||||
|
@ -132,12 +132,12 @@ static struct clk_lookup lookups[] = {
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP029]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP028]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]),
|
||||
|
||||
CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
|
||||
CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]),
|
||||
|
@ -139,12 +139,12 @@ static struct clk_lookup lookups[] = {
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP029]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP028]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]),
|
||||
|
||||
CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]),
|
||||
CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]),
|
||||
|
@ -114,10 +114,10 @@ static struct clk_lookup lookups[] = {
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
|
||||
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]),
|
||||
CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]),
|
||||
|
||||
CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]),
|
||||
CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]),
|
||||
|
@ -28,7 +28,7 @@ static struct plat_sci_port scif0_platform_data = {
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
|
||||
.type = PORT_SCIF,
|
||||
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
||||
.regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
|
||||
};
|
||||
|
||||
static struct resource scif0_resources[] = {
|
||||
@ -50,7 +50,7 @@ static struct plat_sci_port scif1_platform_data = {
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
|
||||
.type = PORT_SCIF,
|
||||
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
||||
.regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
|
||||
};
|
||||
|
||||
static struct resource scif1_resources[] = {
|
||||
@ -72,7 +72,7 @@ static struct plat_sci_port scif2_platform_data = {
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
|
||||
.type = PORT_SCIF,
|
||||
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
||||
.regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
|
||||
};
|
||||
|
||||
static struct resource scif2_resources[] = {
|
||||
@ -94,7 +94,7 @@ static struct plat_sci_port scif3_platform_data = {
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
|
||||
.type = PORT_SCIF,
|
||||
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
||||
.regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
|
||||
};
|
||||
|
||||
static struct resource scif3_resources[] = {
|
||||
@ -116,7 +116,7 @@ static struct plat_sci_port scif4_platform_data = {
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
|
||||
.type = PORT_SCIF,
|
||||
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
||||
.regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
|
||||
};
|
||||
|
||||
static struct resource scif4_resources[] = {
|
||||
@ -138,7 +138,7 @@ static struct plat_sci_port scif5_platform_data = {
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
|
||||
.type = PORT_SCIF,
|
||||
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
||||
.regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
|
||||
};
|
||||
|
||||
static struct resource scif5_resources[] = {
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <linux/delay.h>
|
||||
|
||||
#undef SERIAL_PARANOIA_CHECK
|
||||
#define SERIAL_DO_RESTART
|
||||
|
||||
/* Set of debugging defines */
|
||||
|
||||
|
@ -292,14 +292,14 @@ static void cyz_rx_restart(unsigned long);
|
||||
static struct timer_list cyz_rx_full_timer[NR_PORTS];
|
||||
#endif /* CONFIG_CYZ_INTR */
|
||||
|
||||
static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val)
|
||||
static void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val)
|
||||
{
|
||||
struct cyclades_card *card = port->card;
|
||||
|
||||
cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val);
|
||||
}
|
||||
|
||||
static inline u8 cyy_readb(struct cyclades_port *port, u32 reg)
|
||||
static u8 cyy_readb(struct cyclades_port *port, u32 reg)
|
||||
{
|
||||
struct cyclades_card *card = port->card;
|
||||
|
||||
@ -321,7 +321,7 @@ static inline bool cyz_fpga_loaded(struct cyclades_card *card)
|
||||
return __cyz_fpga_loaded(card->ctl_addr.p9060);
|
||||
}
|
||||
|
||||
static inline bool cyz_is_loaded(struct cyclades_card *card)
|
||||
static bool cyz_is_loaded(struct cyclades_card *card)
|
||||
{
|
||||
struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS;
|
||||
|
||||
@ -329,7 +329,7 @@ static inline bool cyz_is_loaded(struct cyclades_card *card)
|
||||
readl(&fw_id->signature) == ZFIRM_ID;
|
||||
}
|
||||
|
||||
static inline int serial_paranoia_check(struct cyclades_port *info,
|
||||
static int serial_paranoia_check(struct cyclades_port *info,
|
||||
const char *name, const char *routine)
|
||||
{
|
||||
#ifdef SERIAL_PARANOIA_CHECK
|
||||
|
@ -220,7 +220,7 @@ static struct isi_port isi_ports[PORT_COUNT];
|
||||
* it wants to talk.
|
||||
*/
|
||||
|
||||
static inline int WaitTillCardIsFree(unsigned long base)
|
||||
static int WaitTillCardIsFree(unsigned long base)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
unsigned int a = in_atomic(); /* do we run under spinlock? */
|
||||
@ -280,7 +280,7 @@ static void raise_dtr(struct isi_port *port)
|
||||
}
|
||||
|
||||
/* card->lock HAS to be held */
|
||||
static inline void drop_dtr(struct isi_port *port)
|
||||
static void drop_dtr(struct isi_port *port)
|
||||
{
|
||||
struct isi_board *card = port->card;
|
||||
unsigned long base = card->base;
|
||||
|
@ -155,7 +155,6 @@ struct mon_str {
|
||||
#define LOWWAIT 2
|
||||
#define EMPTYWAIT 3
|
||||
|
||||
#define SERIAL_DO_RESTART
|
||||
|
||||
#define WAKEUP_CHARS 256
|
||||
|
||||
|
@ -162,12 +162,23 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
|
||||
return put_user(x, ptr);
|
||||
}
|
||||
|
||||
static inline int tty_copy_to_user(struct tty_struct *tty,
|
||||
void __user *to,
|
||||
const void *from,
|
||||
unsigned long n)
|
||||
static int tty_copy_to_user(struct tty_struct *tty, void __user *to,
|
||||
size_t tail, size_t n)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
size_t size = N_TTY_BUF_SIZE - tail;
|
||||
const void *from = read_buf_addr(ldata, tail);
|
||||
int uncopied;
|
||||
|
||||
if (n > size) {
|
||||
tty_audit_add_data(tty, from, size, ldata->icanon);
|
||||
uncopied = copy_to_user(to, from, size);
|
||||
if (uncopied)
|
||||
return uncopied;
|
||||
to += size;
|
||||
n -= size;
|
||||
from = ldata->read_buf;
|
||||
}
|
||||
|
||||
tty_audit_add_data(tty, from, n, ldata->icanon);
|
||||
return copy_to_user(to, from, n);
|
||||
@ -1201,9 +1212,7 @@ static void n_tty_receive_overrun(struct tty_struct *tty)
|
||||
ldata->num_overrun++;
|
||||
if (time_after(jiffies, ldata->overrun_time + HZ) ||
|
||||
time_after(ldata->overrun_time, jiffies)) {
|
||||
printk(KERN_WARNING "%s: %d input overrun(s)\n",
|
||||
tty_name(tty),
|
||||
ldata->num_overrun);
|
||||
tty_warn(tty, "%d input overrun(s)\n", ldata->num_overrun);
|
||||
ldata->overrun_time = jiffies;
|
||||
ldata->num_overrun = 0;
|
||||
}
|
||||
@ -1486,8 +1495,7 @@ n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag)
|
||||
n_tty_receive_overrun(tty);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "%s: unknown flag %d\n",
|
||||
tty_name(tty), flag);
|
||||
tty_err(tty, "unknown flag %d\n", flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2006,11 +2014,11 @@ static int copy_from_read_buf(struct tty_struct *tty,
|
||||
n = min(head - ldata->read_tail, N_TTY_BUF_SIZE - tail);
|
||||
n = min(*nr, n);
|
||||
if (n) {
|
||||
retval = copy_to_user(*b, read_buf_addr(ldata, tail), n);
|
||||
const unsigned char *from = read_buf_addr(ldata, tail);
|
||||
retval = copy_to_user(*b, from, n);
|
||||
n -= retval;
|
||||
is_eof = n == 1 && read_buf(ldata, tail) == EOF_CHAR(tty);
|
||||
tty_audit_add_data(tty, read_buf_addr(ldata, tail), n,
|
||||
ldata->icanon);
|
||||
is_eof = n == 1 && *from == EOF_CHAR(tty);
|
||||
tty_audit_add_data(tty, from, n, ldata->icanon);
|
||||
smp_store_release(&ldata->read_tail, ldata->read_tail + n);
|
||||
/* Turn single EOF into zero-length read */
|
||||
if (L_EXTPROC(tty) && ldata->icanon && is_eof &&
|
||||
@ -2072,12 +2080,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
|
||||
if (eol == N_TTY_BUF_SIZE && more) {
|
||||
/* scan wrapped without finding set bit */
|
||||
eol = find_next_bit(ldata->read_flags, more, 0);
|
||||
if (eol != more)
|
||||
found = 1;
|
||||
} else if (eol != size)
|
||||
found = 1;
|
||||
found = eol != more;
|
||||
} else
|
||||
found = eol != size;
|
||||
|
||||
size = N_TTY_BUF_SIZE - tail;
|
||||
n = eol - tail;
|
||||
if (n > N_TTY_BUF_SIZE)
|
||||
n += N_TTY_BUF_SIZE;
|
||||
@ -2088,17 +2094,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
|
||||
n = c;
|
||||
}
|
||||
|
||||
n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n",
|
||||
__func__, eol, found, n, c, size, more);
|
||||
|
||||
if (n > size) {
|
||||
ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), size);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
ret = tty_copy_to_user(tty, *b + size, ldata->read_buf, n - size);
|
||||
} else
|
||||
ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), n);
|
||||
n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n",
|
||||
__func__, eol, found, n, c, tail, more);
|
||||
|
||||
ret = tty_copy_to_user(tty, *b, tail, n);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
*b += n;
|
||||
|
@ -788,7 +788,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
||||
if (retval)
|
||||
goto err_release;
|
||||
|
||||
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
|
||||
tty_debug_hangup(tty, "opening (count=%d)\n", tty->count);
|
||||
|
||||
tty_unlock(tty);
|
||||
return 0;
|
||||
|
@ -157,7 +157,7 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty);
|
||||
#endif
|
||||
|
||||
|
||||
static int m68328_console_initted = 0;
|
||||
static int m68328_console_initted;
|
||||
static int m68328_console_baud = CONSOLE_BAUD_RATE;
|
||||
static int m68328_console_cbaud = DEFAULT_CBAUD;
|
||||
|
||||
@ -274,8 +274,8 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx)
|
||||
#endif
|
||||
ch = GET_FIELD(rx, URX_RXDATA);
|
||||
|
||||
if(info->is_cons) {
|
||||
if(URX_BREAK & rx) { /* whee, break received */
|
||||
if (info->is_cons) {
|
||||
if (URX_BREAK & rx) { /* whee, break received */
|
||||
return;
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
} else if (ch == 0x10) { /* ^P */
|
||||
@ -302,7 +302,7 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx)
|
||||
|
||||
tty_insert_flip_char(&info->tport, ch, flag);
|
||||
#ifndef CONFIG_XCOPILOT_BUGS
|
||||
} while((rx = uart->urx.w) & URX_DATA_READY);
|
||||
} while ((rx = uart->urx.w) & URX_DATA_READY);
|
||||
#endif
|
||||
|
||||
tty_schedule_flip(&info->tport);
|
||||
@ -330,7 +330,7 @@ static void transmit_chars(struct m68k_serial *info, struct tty_struct *tty)
|
||||
info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
|
||||
info->xmit_cnt--;
|
||||
|
||||
if(info->xmit_cnt <= 0) {
|
||||
if (info->xmit_cnt <= 0) {
|
||||
/* All done for now... TX ints off */
|
||||
uart->ustcnt &= ~USTCNT_TX_INTR_MASK;
|
||||
goto clear_and_return;
|
||||
@ -452,45 +452,45 @@ struct {
|
||||
}
|
||||
#ifndef CONFIG_M68VZ328
|
||||
hw_baud_table[18] = {
|
||||
{0,0}, /* 0 */
|
||||
{0,0}, /* 50 */
|
||||
{0,0}, /* 75 */
|
||||
{0,0}, /* 110 */
|
||||
{0,0}, /* 134 */
|
||||
{0,0}, /* 150 */
|
||||
{0,0}, /* 200 */
|
||||
{7,0x26}, /* 300 */
|
||||
{6,0x26}, /* 600 */
|
||||
{5,0x26}, /* 1200 */
|
||||
{0,0}, /* 1800 */
|
||||
{4,0x26}, /* 2400 */
|
||||
{3,0x26}, /* 4800 */
|
||||
{2,0x26}, /* 9600 */
|
||||
{1,0x26}, /* 19200 */
|
||||
{0,0x26}, /* 38400 */
|
||||
{1,0x38}, /* 57600 */
|
||||
{0,0x38}, /* 115200 */
|
||||
{0, 0}, /* 0 */
|
||||
{0, 0}, /* 50 */
|
||||
{0, 0}, /* 75 */
|
||||
{0, 0}, /* 110 */
|
||||
{0, 0}, /* 134 */
|
||||
{0, 0}, /* 150 */
|
||||
{0, 0}, /* 200 */
|
||||
{7, 0x26}, /* 300 */
|
||||
{6, 0x26}, /* 600 */
|
||||
{5, 0x26}, /* 1200 */
|
||||
{0, 0}, /* 1800 */
|
||||
{4, 0x26}, /* 2400 */
|
||||
{3, 0x26}, /* 4800 */
|
||||
{2, 0x26}, /* 9600 */
|
||||
{1, 0x26}, /* 19200 */
|
||||
{0, 0x26}, /* 38400 */
|
||||
{1, 0x38}, /* 57600 */
|
||||
{0, 0x38}, /* 115200 */
|
||||
};
|
||||
#else
|
||||
hw_baud_table[18] = {
|
||||
{0,0}, /* 0 */
|
||||
{0,0}, /* 50 */
|
||||
{0,0}, /* 75 */
|
||||
{0,0}, /* 110 */
|
||||
{0,0}, /* 134 */
|
||||
{0,0}, /* 150 */
|
||||
{0,0}, /* 200 */
|
||||
{0,0}, /* 300 */
|
||||
{7,0x26}, /* 600 */
|
||||
{6,0x26}, /* 1200 */
|
||||
{0,0}, /* 1800 */
|
||||
{5,0x26}, /* 2400 */
|
||||
{4,0x26}, /* 4800 */
|
||||
{3,0x26}, /* 9600 */
|
||||
{2,0x26}, /* 19200 */
|
||||
{1,0x26}, /* 38400 */
|
||||
{0,0x26}, /* 57600 */
|
||||
{1,0x38}, /* 115200 */
|
||||
{0, 0}, /* 0 */
|
||||
{0, 0}, /* 50 */
|
||||
{0, 0}, /* 75 */
|
||||
{0, 0}, /* 110 */
|
||||
{0, 0}, /* 134 */
|
||||
{0, 0}, /* 150 */
|
||||
{0, 0}, /* 200 */
|
||||
{0, 0}, /* 300 */
|
||||
{7, 0x26}, /* 600 */
|
||||
{6, 0x26}, /* 1200 */
|
||||
{0, 0}, /* 1800 */
|
||||
{5, 0x26}, /* 2400 */
|
||||
{4, 0x26}, /* 4800 */
|
||||
{3, 0x26}, /* 9600 */
|
||||
{2, 0x26}, /* 19200 */
|
||||
{1, 0x26}, /* 38400 */
|
||||
{0, 0x26}, /* 57600 */
|
||||
{1, 0x38}, /* 115200 */
|
||||
};
|
||||
#endif
|
||||
/* rate = 1036800 / ((65 - prescale) * (1<<divider)) */
|
||||
@ -538,7 +538,7 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty)
|
||||
|
||||
#ifdef CONFIG_SERIAL_68328_RTS_CTS
|
||||
if (cflag & CRTSCTS) {
|
||||
uart->utx.w &= ~ UTX_NOCTS;
|
||||
uart->utx.w &= ~UTX_NOCTS;
|
||||
} else {
|
||||
uart->utx.w |= UTX_NOCTS;
|
||||
}
|
||||
@ -591,8 +591,8 @@ void console_print_68328(const char *p)
|
||||
{
|
||||
char c;
|
||||
|
||||
while((c=*(p++)) != 0) {
|
||||
if(c == '\n')
|
||||
while ((c = *(p++)) != 0) {
|
||||
if (c == '\n')
|
||||
rs_put_char('\r');
|
||||
rs_put_char(c);
|
||||
}
|
||||
@ -624,7 +624,7 @@ static void rs_flush_chars(struct tty_struct *tty)
|
||||
if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
|
||||
return;
|
||||
#ifndef USE_INTS
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
#endif
|
||||
|
||||
/* Enable transmitter */
|
||||
@ -659,9 +659,9 @@ static void rs_flush_chars(struct tty_struct *tty)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
extern void console_printn(const char * b, int count);
|
||||
extern void console_printn(const char *b, int count);
|
||||
|
||||
static int rs_write(struct tty_struct * tty,
|
||||
static int rs_write(struct tty_struct *tty,
|
||||
const unsigned char *buf, int count)
|
||||
{
|
||||
int c, total = 0;
|
||||
@ -700,7 +700,7 @@ static int rs_write(struct tty_struct * tty,
|
||||
/* Enable transmitter */
|
||||
local_irq_disable();
|
||||
#ifndef USE_INTS
|
||||
while(info->xmit_cnt) {
|
||||
while (info->xmit_cnt) {
|
||||
#endif
|
||||
|
||||
uart->ustcnt |= USTCNT_TXEN;
|
||||
@ -767,7 +767,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
|
||||
* incoming characters should be throttled.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
static void rs_throttle(struct tty_struct * tty)
|
||||
static void rs_throttle(struct tty_struct *tty)
|
||||
{
|
||||
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
|
||||
|
||||
@ -780,7 +780,7 @@ static void rs_throttle(struct tty_struct * tty)
|
||||
/* Turn off RTS line (do this atomic) */
|
||||
}
|
||||
|
||||
static void rs_unthrottle(struct tty_struct * tty)
|
||||
static void rs_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
|
||||
|
||||
@ -803,8 +803,8 @@ static void rs_unthrottle(struct tty_struct * tty)
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int get_serial_info(struct m68k_serial * info,
|
||||
struct serial_struct * retinfo)
|
||||
static int get_serial_info(struct m68k_serial *info,
|
||||
struct serial_struct *retinfo)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
|
||||
@ -827,7 +827,7 @@ static int get_serial_info(struct m68k_serial * info,
|
||||
}
|
||||
|
||||
static int set_serial_info(struct m68k_serial *info, struct tty_struct *tty,
|
||||
struct serial_struct * new_info)
|
||||
struct serial_struct *new_info)
|
||||
{
|
||||
struct tty_port *port = &info->tport;
|
||||
struct serial_struct new_serial;
|
||||
@ -883,7 +883,7 @@ check_and_exit:
|
||||
* transmit holding register is empty. This functionality
|
||||
* allows an RS485 driver to be written in user space.
|
||||
*/
|
||||
static int get_lsr_info(struct m68k_serial * info, unsigned int *value)
|
||||
static int get_lsr_info(struct m68k_serial *info, unsigned int *value)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_68328_RTS_CTS
|
||||
m68328_uart *uart = &uart_addr[info->line];
|
||||
@ -904,7 +904,7 @@ static int get_lsr_info(struct m68k_serial * info, unsigned int *value)
|
||||
/*
|
||||
* This routine sends a break character out the serial port.
|
||||
*/
|
||||
static void send_break(struct m68k_serial * info, unsigned int duration)
|
||||
static void send_break(struct m68k_serial *info, unsigned int duration)
|
||||
{
|
||||
m68328_uart *uart = &uart_addr[info->line];
|
||||
unsigned long flags;
|
||||
@ -922,7 +922,7 @@ static void send_break(struct m68k_serial * info, unsigned int duration)
|
||||
static int rs_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;
|
||||
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
|
||||
int retval;
|
||||
|
||||
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
|
||||
@ -992,9 +992,9 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
|
||||
* that IRQ if nothing is left in the chain.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
static void rs_close(struct tty_struct *tty, struct file * filp)
|
||||
static void rs_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;
|
||||
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
|
||||
struct tty_port *port = &info->tport;
|
||||
m68328_uart *uart = &uart_addr[info->line];
|
||||
unsigned long flags;
|
||||
@ -1079,7 +1079,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
|
||||
*/
|
||||
void rs_hangup(struct tty_struct *tty)
|
||||
{
|
||||
struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;
|
||||
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
|
||||
|
||||
if (serial_paranoia_check(info, tty->name, "rs_hangup"))
|
||||
return;
|
||||
@ -1098,7 +1098,7 @@ void rs_hangup(struct tty_struct *tty)
|
||||
* the IRQ chain. It also performs the serial-specific
|
||||
* initialization for the tty structure.
|
||||
*/
|
||||
int rs_open(struct tty_struct *tty, struct file * filp)
|
||||
int rs_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
struct m68k_serial *info;
|
||||
int retval;
|
||||
@ -1180,7 +1180,7 @@ rs68328_init(void)
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
for(i=0;i<NR_PORTS;i++) {
|
||||
for (i = 0; i < NR_PORTS; i++) {
|
||||
|
||||
info = &m68k_soft[i];
|
||||
tty_port_init(&info->tport);
|
||||
@ -1198,7 +1198,7 @@ rs68328_init(void)
|
||||
printk(" is a builtin MC68328 UART\n");
|
||||
|
||||
#ifdef CONFIG_M68VZ328
|
||||
if (i > 0 )
|
||||
if (i > 0)
|
||||
PJSEL &= 0xCF; /* PSW enable second port output */
|
||||
#endif
|
||||
|
||||
@ -1263,7 +1263,7 @@ int m68328_console_setup(struct console *cp, char *arg)
|
||||
return(-1);
|
||||
|
||||
if (arg)
|
||||
n = simple_strtoul(arg,NULL,0);
|
||||
n = simple_strtoul(arg, NULL, 0);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(baud_table); i++)
|
||||
if (baud_table[i] == n)
|
||||
@ -1279,7 +1279,7 @@ int m68328_console_setup(struct console *cp, char *arg)
|
||||
}
|
||||
|
||||
m68328_set_baud(); /* make sure baud rate changes */
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1298,7 +1298,7 @@ void m68328_console_write (struct console *co, const char *str,
|
||||
while (count--) {
|
||||
if (*str == '\n')
|
||||
rs_put_char('\r');
|
||||
rs_put_char( *str++ );
|
||||
rs_put_char(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,7 +620,7 @@ static int univ8250_console_setup(struct console *co, char *options)
|
||||
* @options: ptr to option string from console command line
|
||||
*
|
||||
* Only attempts to match console command lines of the form:
|
||||
* console=uart[8250],io|mmio|mmio32,<addr>[,<options>]
|
||||
* console=uart[8250],io|mmio|mmio16|mmio32,<addr>[,<options>]
|
||||
* console=uart[8250],0x<addr>[,<options>]
|
||||
* This form is used to register an initial earlycon boot console and
|
||||
* replace it with the serial8250_console at 8250 driver init.
|
||||
@ -650,8 +650,9 @@ static int univ8250_console_match(struct console *co, char *name, int idx,
|
||||
|
||||
if (port->iotype != iotype)
|
||||
continue;
|
||||
if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) &&
|
||||
(port->mapbase != addr))
|
||||
if ((iotype == UPIO_MEM || iotype == UPIO_MEM16 ||
|
||||
iotype == UPIO_MEM32 || iotype == UPIO_MEM32BE)
|
||||
&& (port->mapbase != addr))
|
||||
continue;
|
||||
if (iotype == UPIO_PORT && port->iobase != addr)
|
||||
continue;
|
||||
|
@ -42,6 +42,8 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
|
||||
switch (port->iotype) {
|
||||
case UPIO_MEM:
|
||||
return readb(port->membase + offset);
|
||||
case UPIO_MEM16:
|
||||
return readw(port->membase + (offset << 1));
|
||||
case UPIO_MEM32:
|
||||
return readl(port->membase + (offset << 2));
|
||||
case UPIO_MEM32BE:
|
||||
@ -59,6 +61,9 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
|
||||
case UPIO_MEM:
|
||||
writeb(value, port->membase + offset);
|
||||
break;
|
||||
case UPIO_MEM16:
|
||||
writew(value, port->membase + (offset << 1));
|
||||
break;
|
||||
case UPIO_MEM32:
|
||||
writel(value, port->membase + (offset << 2));
|
||||
break;
|
||||
@ -73,43 +78,27 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
|
||||
|
||||
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
||||
|
||||
static void __init wait_for_xmitr(struct uart_port *port)
|
||||
static void __init serial_putc(struct uart_port *port, int c)
|
||||
{
|
||||
unsigned int status;
|
||||
|
||||
serial8250_early_out(port, UART_TX, c);
|
||||
|
||||
for (;;) {
|
||||
status = serial8250_early_in(port, UART_LSR);
|
||||
if ((status & BOTH_EMPTY) == BOTH_EMPTY)
|
||||
return;
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
static void __init serial_putc(struct uart_port *port, int c)
|
||||
{
|
||||
wait_for_xmitr(port);
|
||||
serial8250_early_out(port, UART_TX, c);
|
||||
}
|
||||
|
||||
static void __init early_serial8250_write(struct console *console,
|
||||
const char *s, unsigned int count)
|
||||
{
|
||||
struct earlycon_device *device = console->data;
|
||||
struct uart_port *port = &device->port;
|
||||
unsigned int ier;
|
||||
|
||||
/* Save the IER and disable interrupts preserving the UUE bit */
|
||||
ier = serial8250_early_in(port, UART_IER);
|
||||
if (ier)
|
||||
serial8250_early_out(port, UART_IER, ier & UART_IER_UUE);
|
||||
|
||||
uart_console_write(port, s, count, serial_putc);
|
||||
|
||||
/* Wait for transmitter to become empty and restore the IER */
|
||||
wait_for_xmitr(port);
|
||||
|
||||
if (ier)
|
||||
serial8250_early_out(port, UART_IER, ier);
|
||||
}
|
||||
|
||||
static void __init init_port(struct earlycon_device *device)
|
||||
|
@ -48,6 +48,7 @@ static const struct of_device_id of_match[];
|
||||
#define UART_MCR_MDCE BIT(7)
|
||||
#define UART_MCR_FCM BIT(6)
|
||||
|
||||
#ifdef CONFIG_SERIAL_EARLYCON
|
||||
static struct earlycon_device *early_device;
|
||||
|
||||
static uint8_t __init early_in(struct uart_port *port, int offset)
|
||||
@ -140,6 +141,7 @@ OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",
|
||||
EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
|
||||
ingenic_early_console_setup);
|
||||
#endif /* CONFIG_SERIAL_EARLYCON */
|
||||
|
||||
static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -245,23 +245,6 @@ static int mtk8250_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk8250_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mtk8250_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
serial8250_unregister_port(data->line);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
|
||||
if (!pm_runtime_status_suspended(&pdev->dev))
|
||||
mtk8250_runtime_suspend(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mtk8250_suspend(struct device *dev)
|
||||
{
|
||||
@ -292,18 +275,18 @@ static const struct of_device_id mtk8250_of_match[] = {
|
||||
{ .compatible = "mediatek,mt6577-uart" },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk8250_of_match);
|
||||
|
||||
static struct platform_driver mtk8250_platform_driver = {
|
||||
.driver = {
|
||||
.name = "mt6577-uart",
|
||||
.pm = &mtk8250_pm_ops,
|
||||
.of_match_table = mtk8250_of_match,
|
||||
.name = "mt6577-uart",
|
||||
.pm = &mtk8250_pm_ops,
|
||||
.of_match_table = mtk8250_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
|
||||
},
|
||||
.probe = mtk8250_probe,
|
||||
.remove = mtk8250_remove,
|
||||
};
|
||||
module_platform_driver(mtk8250_platform_driver);
|
||||
builtin_platform_driver(mtk8250_platform_driver);
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
static int __init early_mtk8250_setup(struct earlycon_device *device,
|
||||
@ -319,7 +302,3 @@ static int __init early_mtk8250_setup(struct earlycon_device *device,
|
||||
|
||||
OF_EARLYCON_DECLARE(mtk8250, "mediatek,mt6577-uart", early_mtk8250_setup);
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Matthias Brugger");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Mediatek 8250 serial port driver");
|
||||
|
@ -18,14 +18,9 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/nwpserial.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_MODULE
|
||||
#define CONFIG_SERIAL_8250 CONFIG_SERIAL_8250_MODULE
|
||||
#endif
|
||||
|
||||
#include "8250/8250.h"
|
||||
#include "8250.h"
|
||||
|
||||
struct of_serial_info {
|
||||
struct clk *clk;
|
||||
@ -122,6 +117,9 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
||||
case 1:
|
||||
port->iotype = UPIO_MEM;
|
||||
break;
|
||||
case 2:
|
||||
port->iotype = UPIO_MEM16;
|
||||
break;
|
||||
case 4:
|
||||
port->iotype = of_device_is_big_endian(np) ?
|
||||
UPIO_MEM32BE : UPIO_MEM32;
|
||||
@ -195,7 +193,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
|
||||
goto out;
|
||||
|
||||
switch (port_type) {
|
||||
#ifdef CONFIG_SERIAL_8250
|
||||
case PORT_8250 ... PORT_MAX_8250:
|
||||
{
|
||||
struct uart_8250_port port8250;
|
||||
@ -212,12 +209,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
|
||||
ret = serial8250_register_8250_port(&port8250);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
|
||||
case PORT_NWPSERIAL:
|
||||
ret = nwpserial_register_port(&port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* need to add code for these */
|
||||
case PORT_UNKNOWN:
|
||||
@ -245,16 +236,9 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
|
||||
{
|
||||
struct of_serial_info *info = platform_get_drvdata(ofdev);
|
||||
switch (info->type) {
|
||||
#ifdef CONFIG_SERIAL_8250
|
||||
case PORT_8250 ... PORT_MAX_8250:
|
||||
serial8250_unregister_port(info->line);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
|
||||
case PORT_NWPSERIAL:
|
||||
nwpserial_unregister_port(info->line);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* need to add code for these */
|
||||
break;
|
||||
@ -267,7 +251,6 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_SERIAL_8250
|
||||
static void of_serial_suspend_8250(struct of_serial_info *info)
|
||||
{
|
||||
struct uart_8250_port *port8250 = serial8250_get_port(info->line);
|
||||
@ -288,15 +271,6 @@ static void of_serial_resume_8250(struct of_serial_info *info)
|
||||
|
||||
serial8250_resume_port(info->line);
|
||||
}
|
||||
#else
|
||||
static inline void of_serial_suspend_8250(struct of_serial_info *info)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void of_serial_resume_8250(struct of_serial_info *info)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static int of_serial_suspend(struct device *dev)
|
||||
{
|
||||
@ -353,10 +327,6 @@ static const struct of_device_id of_platform_serial_table[] = {
|
||||
.data = (void *)PORT_XSCALE, },
|
||||
{ .compatible = "mrvl,pxa-uart",
|
||||
.data = (void *)PORT_XSCALE, },
|
||||
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
|
||||
{ .compatible = "ibm,qpace-nwp-serial",
|
||||
.data = (void *)PORT_NWPSERIAL, },
|
||||
#endif
|
||||
{ /* end of list */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_platform_serial_table);
|
@ -368,6 +368,18 @@ static void mem_serial_out(struct uart_port *p, int offset, int value)
|
||||
writeb(value, p->membase + offset);
|
||||
}
|
||||
|
||||
static void mem16_serial_out(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
offset = offset << p->regshift;
|
||||
writew(value, p->membase + offset);
|
||||
}
|
||||
|
||||
static unsigned int mem16_serial_in(struct uart_port *p, int offset)
|
||||
{
|
||||
offset = offset << p->regshift;
|
||||
return readw(p->membase + offset);
|
||||
}
|
||||
|
||||
static void mem32_serial_out(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
offset = offset << p->regshift;
|
||||
@ -425,6 +437,11 @@ static void set_io_from_upio(struct uart_port *p)
|
||||
p->serial_out = mem_serial_out;
|
||||
break;
|
||||
|
||||
case UPIO_MEM16:
|
||||
p->serial_in = mem16_serial_in;
|
||||
p->serial_out = mem16_serial_out;
|
||||
break;
|
||||
|
||||
case UPIO_MEM32:
|
||||
p->serial_in = mem32_serial_in;
|
||||
p->serial_out = mem32_serial_out;
|
||||
@ -459,6 +476,7 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
switch (p->iotype) {
|
||||
case UPIO_MEM:
|
||||
case UPIO_MEM16:
|
||||
case UPIO_MEM32:
|
||||
case UPIO_MEM32BE:
|
||||
case UPIO_AU:
|
||||
@ -2462,6 +2480,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
|
||||
case UPIO_TSI:
|
||||
case UPIO_MEM32:
|
||||
case UPIO_MEM32BE:
|
||||
case UPIO_MEM16:
|
||||
case UPIO_MEM:
|
||||
if (!port->mapbase)
|
||||
break;
|
||||
@ -2499,6 +2518,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
|
||||
case UPIO_TSI:
|
||||
case UPIO_MEM32:
|
||||
case UPIO_MEM32BE:
|
||||
case UPIO_MEM16:
|
||||
case UPIO_MEM:
|
||||
if (!port->mapbase)
|
||||
break;
|
||||
|
@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
@ -34,6 +35,29 @@ struct uniphier8250_priv {
|
||||
spinlock_t atomic_write_lock;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
static int __init uniphier_early_console_setup(struct earlycon_device *device,
|
||||
const char *options)
|
||||
{
|
||||
if (!device->port.membase)
|
||||
return -ENODEV;
|
||||
|
||||
/* This hardware always expects MMIO32 register interface. */
|
||||
device->port.iotype = UPIO_MEM32;
|
||||
device->port.regshift = 2;
|
||||
|
||||
/*
|
||||
* Do not touch the divisor register in early_serial8250_setup();
|
||||
* we assume it has been initialized by a boot loader.
|
||||
*/
|
||||
device->baud = 0;
|
||||
|
||||
return early_serial8250_setup(device, options);
|
||||
}
|
||||
OF_EARLYCON_DECLARE(uniphier, "socionext,uniphier-uart",
|
||||
uniphier_early_console_setup);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The register map is slightly different from that of 8250.
|
||||
* IO callbacks must be overridden for correct access to FCR, LCR, and MCR.
|
||||
|
@ -361,9 +361,8 @@ config SERIAL_8250_UNIPHIER
|
||||
|
||||
config SERIAL_8250_INGENIC
|
||||
bool "Support for Ingenic SoC serial ports"
|
||||
depends on SERIAL_8250_CONSOLE && OF_FLATTREE
|
||||
depends on OF_FLATTREE
|
||||
select LIBFDT
|
||||
select SERIAL_EARLYCON
|
||||
help
|
||||
If you have a system using an Ingenic SoC and wish to make use of
|
||||
its UARTs, say Y to this option. If unsure, say N.
|
||||
@ -372,9 +371,18 @@ config SERIAL_8250_MID
|
||||
tristate "Support for serial ports on Intel MID platforms"
|
||||
depends on SERIAL_8250 && PCI
|
||||
select HSU_DMA if SERIAL_8250_DMA
|
||||
select HSU_DMA_PCI if X86_INTEL_MID
|
||||
select HSU_DMA_PCI if (HSU_DMA && X86_INTEL_MID)
|
||||
select RATIONAL
|
||||
help
|
||||
Selecting this option will enable handling of the extra features
|
||||
present on the UART found on Intel Medfield SOC and various other
|
||||
Intel platforms.
|
||||
|
||||
config SERIAL_OF_PLATFORM
|
||||
tristate "Devicetree based probing for 8250 ports"
|
||||
depends on SERIAL_8250 && OF
|
||||
help
|
||||
This option is used for all 8250 compatible serial ports that
|
||||
are probed through devicetree, including Open Firmware based
|
||||
PowerPC systems and embedded systems on architectures using the
|
||||
flattened device tree format.
|
||||
|
@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o
|
||||
obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
|
||||
obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
|
||||
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
|
||||
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
|
||||
|
||||
CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
|
||||
|
@ -115,6 +115,7 @@ config SERIAL_SB1250_DUART_CONSOLE
|
||||
|
||||
config SERIAL_ATMEL
|
||||
bool "AT91 / AT32 on-chip serial port support"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_AT91 || AVR32 || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
@ -571,9 +572,11 @@ config BFIN_UART3_CTSRTS
|
||||
|
||||
config SERIAL_IMX
|
||||
tristate "IMX serial port support"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
select RATIONAL
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
help
|
||||
If you have a machine based on a Motorola IMX CPU you
|
||||
can enable its onboard serial port by enabling this option.
|
||||
@ -1094,16 +1097,6 @@ config SERIAL_NETX_CONSOLE
|
||||
If you have enabled the serial port on the Hilscher NetX SoC
|
||||
you can make it the console by answering Y to this option.
|
||||
|
||||
config SERIAL_OF_PLATFORM
|
||||
tristate "Serial port on Open Firmware platform bus"
|
||||
depends on OF
|
||||
depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
|
||||
help
|
||||
If you have a PowerPC based system that has serial ports
|
||||
on a platform specific bus, you should enable this option.
|
||||
Currently, only 8250 compatible ports are supported, but
|
||||
others can easily be added.
|
||||
|
||||
config SERIAL_OMAP
|
||||
tristate "OMAP serial port support"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
@ -1131,23 +1124,6 @@ config SERIAL_OMAP_CONSOLE
|
||||
your boot loader about how to pass options to the kernel at
|
||||
boot time.)
|
||||
|
||||
config SERIAL_OF_PLATFORM_NWPSERIAL
|
||||
tristate "NWP serial port driver"
|
||||
depends on PPC_DCR
|
||||
select SERIAL_OF_PLATFORM
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver supports the cell network processor nwp serial
|
||||
device.
|
||||
|
||||
config SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
|
||||
bool "Console on NWP serial port"
|
||||
depends on SERIAL_OF_PLATFORM_NWPSERIAL=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Support for Console on the NWP serial ports.
|
||||
|
||||
config SERIAL_LANTIQ
|
||||
bool "Lantiq serial driver"
|
||||
depends on LANTIQ
|
||||
@ -1409,8 +1385,9 @@ config SERIAL_PCH_UART_CONSOLE
|
||||
warnings and which allows logins in single user mode).
|
||||
|
||||
config SERIAL_MXS_AUART
|
||||
depends on ARCH_MXS || COMPILE_TEST
|
||||
tristate "MXS AUART support"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_MXS || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
help
|
||||
|
@ -63,8 +63,6 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
|
||||
obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
|
||||
obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
|
||||
obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
|
||||
obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
|
||||
obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
|
||||
obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
|
||||
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
|
||||
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
|
||||
|
@ -60,6 +60,8 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include "amba-pl011.h"
|
||||
|
||||
#define UART_NR 14
|
||||
|
||||
#define SERIAL_AMBA_MAJOR 204
|
||||
@ -71,11 +73,27 @@
|
||||
#define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
|
||||
#define UART_DUMMY_DR_RX (1 << 16)
|
||||
|
||||
static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
|
||||
[REG_DR] = UART01x_DR,
|
||||
[REG_FR] = UART01x_FR,
|
||||
[REG_LCRH_RX] = UART011_LCRH,
|
||||
[REG_LCRH_TX] = UART011_LCRH,
|
||||
[REG_IBRD] = UART011_IBRD,
|
||||
[REG_FBRD] = UART011_FBRD,
|
||||
[REG_CR] = UART011_CR,
|
||||
[REG_IFLS] = UART011_IFLS,
|
||||
[REG_IMSC] = UART011_IMSC,
|
||||
[REG_RIS] = UART011_RIS,
|
||||
[REG_MIS] = UART011_MIS,
|
||||
[REG_ICR] = UART011_ICR,
|
||||
[REG_DMACR] = UART011_DMACR,
|
||||
};
|
||||
|
||||
/* There is by now at least one vendor with differing details, so handle it */
|
||||
struct vendor_data {
|
||||
const u16 *reg_offset;
|
||||
unsigned int ifls;
|
||||
unsigned int lcrh_tx;
|
||||
unsigned int lcrh_rx;
|
||||
bool access_32b;
|
||||
bool oversampling;
|
||||
bool dma_threshold;
|
||||
bool cts_event_workaround;
|
||||
@ -91,9 +109,8 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
|
||||
}
|
||||
|
||||
static struct vendor_data vendor_arm = {
|
||||
.reg_offset = pl011_std_offsets,
|
||||
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
|
||||
.lcrh_tx = UART011_LCRH,
|
||||
.lcrh_rx = UART011_LCRH,
|
||||
.oversampling = false,
|
||||
.dma_threshold = false,
|
||||
.cts_event_workaround = false,
|
||||
@ -103,6 +120,7 @@ static struct vendor_data vendor_arm = {
|
||||
};
|
||||
|
||||
static struct vendor_data vendor_sbsa = {
|
||||
.reg_offset = pl011_std_offsets,
|
||||
.oversampling = false,
|
||||
.dma_threshold = false,
|
||||
.cts_event_workaround = false,
|
||||
@ -110,15 +128,41 @@ static struct vendor_data vendor_sbsa = {
|
||||
.fixed_options = true,
|
||||
};
|
||||
|
||||
static u16 pl011_st_offsets[REG_ARRAY_SIZE] = {
|
||||
[REG_DR] = UART01x_DR,
|
||||
[REG_ST_DMAWM] = ST_UART011_DMAWM,
|
||||
[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
|
||||
[REG_FR] = UART01x_FR,
|
||||
[REG_LCRH_RX] = ST_UART011_LCRH_RX,
|
||||
[REG_LCRH_TX] = ST_UART011_LCRH_TX,
|
||||
[REG_IBRD] = UART011_IBRD,
|
||||
[REG_FBRD] = UART011_FBRD,
|
||||
[REG_CR] = UART011_CR,
|
||||
[REG_IFLS] = UART011_IFLS,
|
||||
[REG_IMSC] = UART011_IMSC,
|
||||
[REG_RIS] = UART011_RIS,
|
||||
[REG_MIS] = UART011_MIS,
|
||||
[REG_ICR] = UART011_ICR,
|
||||
[REG_DMACR] = UART011_DMACR,
|
||||
[REG_ST_XFCR] = ST_UART011_XFCR,
|
||||
[REG_ST_XON1] = ST_UART011_XON1,
|
||||
[REG_ST_XON2] = ST_UART011_XON2,
|
||||
[REG_ST_XOFF1] = ST_UART011_XOFF1,
|
||||
[REG_ST_XOFF2] = ST_UART011_XOFF2,
|
||||
[REG_ST_ITCR] = ST_UART011_ITCR,
|
||||
[REG_ST_ITIP] = ST_UART011_ITIP,
|
||||
[REG_ST_ABCR] = ST_UART011_ABCR,
|
||||
[REG_ST_ABIMSC] = ST_UART011_ABIMSC,
|
||||
};
|
||||
|
||||
static unsigned int get_fifosize_st(struct amba_device *dev)
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
|
||||
static struct vendor_data vendor_st = {
|
||||
.reg_offset = pl011_st_offsets,
|
||||
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
|
||||
.lcrh_tx = ST_UART011_LCRH_TX,
|
||||
.lcrh_rx = ST_UART011_LCRH_RX,
|
||||
.oversampling = true,
|
||||
.dma_threshold = true,
|
||||
.cts_event_workaround = true,
|
||||
@ -127,6 +171,29 @@ static struct vendor_data vendor_st = {
|
||||
.get_fifosize = get_fifosize_st,
|
||||
};
|
||||
|
||||
static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = {
|
||||
[REG_DR] = ZX_UART011_DR,
|
||||
[REG_FR] = ZX_UART011_FR,
|
||||
[REG_LCRH_RX] = ZX_UART011_LCRH,
|
||||
[REG_LCRH_TX] = ZX_UART011_LCRH,
|
||||
[REG_IBRD] = ZX_UART011_IBRD,
|
||||
[REG_FBRD] = ZX_UART011_FBRD,
|
||||
[REG_CR] = ZX_UART011_CR,
|
||||
[REG_IFLS] = ZX_UART011_IFLS,
|
||||
[REG_IMSC] = ZX_UART011_IMSC,
|
||||
[REG_RIS] = ZX_UART011_RIS,
|
||||
[REG_MIS] = ZX_UART011_MIS,
|
||||
[REG_ICR] = ZX_UART011_ICR,
|
||||
[REG_DMACR] = ZX_UART011_DMACR,
|
||||
};
|
||||
|
||||
static struct vendor_data vendor_zte = {
|
||||
.reg_offset = pl011_zte_offsets,
|
||||
.access_32b = true,
|
||||
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
|
||||
.get_fifosize = get_fifosize_arm,
|
||||
};
|
||||
|
||||
/* Deals with DMA transactions */
|
||||
|
||||
struct pl011_sgbuf {
|
||||
@ -162,14 +229,13 @@ struct pl011_dmatx_data {
|
||||
*/
|
||||
struct uart_amba_port {
|
||||
struct uart_port port;
|
||||
const u16 *reg_offset;
|
||||
struct clk *clk;
|
||||
const struct vendor_data *vendor;
|
||||
unsigned int dmacr; /* dma control reg */
|
||||
unsigned int im; /* interrupt mask */
|
||||
unsigned int old_status;
|
||||
unsigned int fifosize; /* vendor-specific */
|
||||
unsigned int lcrh_tx; /* vendor-specific */
|
||||
unsigned int lcrh_rx; /* vendor-specific */
|
||||
unsigned int old_cr; /* state during shutdown */
|
||||
bool autorts;
|
||||
unsigned int fixed_baud; /* vendor-set fixed baud rate */
|
||||
@ -184,6 +250,32 @@ struct uart_amba_port {
|
||||
#endif
|
||||
};
|
||||
|
||||
static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
|
||||
unsigned int reg)
|
||||
{
|
||||
return uap->reg_offset[reg];
|
||||
}
|
||||
|
||||
static unsigned int pl011_read(const struct uart_amba_port *uap,
|
||||
unsigned int reg)
|
||||
{
|
||||
void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
|
||||
|
||||
return (uap->port.iotype == UPIO_MEM32) ?
|
||||
readl_relaxed(addr) : readw_relaxed(addr);
|
||||
}
|
||||
|
||||
static void pl011_write(unsigned int val, const struct uart_amba_port *uap,
|
||||
unsigned int reg)
|
||||
{
|
||||
void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
|
||||
|
||||
if (uap->port.iotype == UPIO_MEM32)
|
||||
writel_relaxed(val, addr);
|
||||
else
|
||||
writew_relaxed(val, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads up to 256 characters from the FIFO or until it's empty and
|
||||
* inserts them into the TTY layer. Returns the number of characters
|
||||
@ -196,13 +288,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
|
||||
int fifotaken = 0;
|
||||
|
||||
while (max_count--) {
|
||||
status = readw(uap->port.membase + UART01x_FR);
|
||||
status = pl011_read(uap, REG_FR);
|
||||
if (status & UART01x_FR_RXFE)
|
||||
break;
|
||||
|
||||
/* Take chars from the FIFO and update status */
|
||||
ch = readw(uap->port.membase + UART01x_DR) |
|
||||
UART_DUMMY_DR_RX;
|
||||
ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX;
|
||||
flag = TTY_NORMAL;
|
||||
uap->port.icount.rx++;
|
||||
fifotaken++;
|
||||
@ -284,7 +375,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
|
||||
struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
|
||||
struct device *dev = uap->port.dev;
|
||||
struct dma_slave_config tx_conf = {
|
||||
.dst_addr = uap->port.mapbase + UART01x_DR,
|
||||
.dst_addr = uap->port.mapbase +
|
||||
pl011_reg_to_offset(uap, REG_DR),
|
||||
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
|
||||
.direction = DMA_MEM_TO_DEV,
|
||||
.dst_maxburst = uap->fifosize >> 1,
|
||||
@ -339,7 +431,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
|
||||
|
||||
if (chan) {
|
||||
struct dma_slave_config rx_conf = {
|
||||
.src_addr = uap->port.mapbase + UART01x_DR,
|
||||
.src_addr = uap->port.mapbase +
|
||||
pl011_reg_to_offset(uap, REG_DR),
|
||||
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
|
||||
.direction = DMA_DEV_TO_MEM,
|
||||
.src_maxburst = uap->fifosize >> 2,
|
||||
@ -438,7 +531,7 @@ static void pl011_dma_tx_callback(void *data)
|
||||
|
||||
dmacr = uap->dmacr;
|
||||
uap->dmacr = dmacr & ~UART011_TXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
|
||||
/*
|
||||
* If TX DMA was disabled, it means that we've stopped the DMA for
|
||||
@ -552,7 +645,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
|
||||
dma_dev->device_issue_pending(chan);
|
||||
|
||||
uap->dmacr |= UART011_TXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
uap->dmatx.queued = true;
|
||||
|
||||
/*
|
||||
@ -588,9 +681,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
|
||||
*/
|
||||
if (uap->dmatx.queued) {
|
||||
uap->dmacr |= UART011_TXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
uap->im &= ~UART011_TXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -600,7 +693,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
|
||||
*/
|
||||
if (pl011_dma_tx_refill(uap) > 0) {
|
||||
uap->im &= ~UART011_TXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -614,7 +707,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
|
||||
{
|
||||
if (uap->dmatx.queued) {
|
||||
uap->dmacr &= ~UART011_TXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,14 +733,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
|
||||
if (!uap->dmatx.queued) {
|
||||
if (pl011_dma_tx_refill(uap) > 0) {
|
||||
uap->im &= ~UART011_TXIM;
|
||||
writew(uap->im, uap->port.membase +
|
||||
UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
} else
|
||||
ret = false;
|
||||
} else if (!(uap->dmacr & UART011_TXDMAE)) {
|
||||
uap->dmacr |= UART011_TXDMAE;
|
||||
writew(uap->dmacr,
|
||||
uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -658,9 +749,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
|
||||
*/
|
||||
dmacr = uap->dmacr;
|
||||
uap->dmacr &= ~UART011_TXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
|
||||
if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
|
||||
if (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) {
|
||||
/*
|
||||
* No space in the FIFO, so enable the transmit interrupt
|
||||
* so we know when there is space. Note that once we've
|
||||
@ -669,13 +760,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
|
||||
return false;
|
||||
}
|
||||
|
||||
writew(uap->port.x_char, uap->port.membase + UART01x_DR);
|
||||
pl011_write(uap->port.x_char, uap, REG_DR);
|
||||
uap->port.icount.tx++;
|
||||
uap->port.x_char = 0;
|
||||
|
||||
/* Success - restore the DMA state */
|
||||
uap->dmacr = dmacr;
|
||||
writew(dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(dmacr, uap, REG_DMACR);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -703,7 +794,7 @@ __acquires(&uap->port.lock)
|
||||
DMA_TO_DEVICE);
|
||||
uap->dmatx.queued = false;
|
||||
uap->dmacr &= ~UART011_TXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -743,11 +834,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
|
||||
dma_async_issue_pending(rxchan);
|
||||
|
||||
uap->dmacr |= UART011_RXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
uap->dmarx.running = true;
|
||||
|
||||
uap->im &= ~UART011_RXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -805,8 +896,8 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
|
||||
*/
|
||||
if (dma_count == pending && readfifo) {
|
||||
/* Clear any error flags */
|
||||
writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
|
||||
uap->port.membase + UART011_ICR);
|
||||
pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
|
||||
UART011_FEIS, uap, REG_ICR);
|
||||
|
||||
/*
|
||||
* If we read all the DMA'd characters, and we had an
|
||||
@ -854,7 +945,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
|
||||
|
||||
/* Disable RX DMA - incoming data will wait in the FIFO */
|
||||
uap->dmacr &= ~UART011_RXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
uap->dmarx.running = false;
|
||||
|
||||
pending = sgbuf->sg.length - state.residue;
|
||||
@ -874,7 +965,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
|
||||
dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
|
||||
"fall back to interrupt mode\n");
|
||||
uap->im |= UART011_RXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -922,7 +1013,7 @@ static void pl011_dma_rx_callback(void *data)
|
||||
dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
|
||||
"fall back to interrupt mode\n");
|
||||
uap->im |= UART011_RXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -935,7 +1026,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
|
||||
{
|
||||
/* FIXME. Just disable the DMA enable */
|
||||
uap->dmacr &= ~UART011_RXDMAE;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -979,7 +1070,7 @@ static void pl011_dma_rx_poll(unsigned long args)
|
||||
spin_lock_irqsave(&uap->port.lock, flags);
|
||||
pl011_dma_rx_stop(uap);
|
||||
uap->im |= UART011_RXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||
|
||||
uap->dmarx.running = false;
|
||||
@ -1041,7 +1132,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
|
||||
skip_rx:
|
||||
/* Turn on DMA error (RX/TX will be enabled on demand) */
|
||||
uap->dmacr |= UART011_DMAONERR;
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
|
||||
/*
|
||||
* ST Micro variants has some specific dma burst threshold
|
||||
@ -1049,8 +1140,8 @@ skip_rx:
|
||||
* be issued above/below 16 bytes.
|
||||
*/
|
||||
if (uap->vendor->dma_threshold)
|
||||
writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
|
||||
uap->port.membase + ST_UART011_DMAWM);
|
||||
pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
|
||||
uap, REG_ST_DMAWM);
|
||||
|
||||
if (uap->using_rx_dma) {
|
||||
if (pl011_dma_rx_trigger_dma(uap))
|
||||
@ -1075,12 +1166,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
|
||||
return;
|
||||
|
||||
/* Disable RX and TX DMA */
|
||||
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
|
||||
while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY)
|
||||
barrier();
|
||||
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
|
||||
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
|
||||
pl011_write(uap->dmacr, uap, REG_DMACR);
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
|
||||
if (uap->using_tx_dma) {
|
||||
@ -1181,7 +1272,7 @@ static void pl011_stop_tx(struct uart_port *port)
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
|
||||
uap->im &= ~UART011_TXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
pl011_dma_tx_stop(uap);
|
||||
}
|
||||
|
||||
@ -1191,7 +1282,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
|
||||
static void pl011_start_tx_pio(struct uart_amba_port *uap)
|
||||
{
|
||||
uap->im |= UART011_TXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
pl011_tx_chars(uap, false);
|
||||
}
|
||||
|
||||
@ -1211,7 +1302,7 @@ static void pl011_stop_rx(struct uart_port *port)
|
||||
|
||||
uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
|
||||
UART011_PEIM|UART011_BEIM|UART011_OEIM);
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
|
||||
pl011_dma_rx_stop(uap);
|
||||
}
|
||||
@ -1222,7 +1313,7 @@ static void pl011_enable_ms(struct uart_port *port)
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
|
||||
uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
}
|
||||
|
||||
static void pl011_rx_chars(struct uart_amba_port *uap)
|
||||
@ -1242,7 +1333,7 @@ __acquires(&uap->port.lock)
|
||||
dev_dbg(uap->port.dev, "could not trigger RX DMA job "
|
||||
"fall back to interrupt mode again\n");
|
||||
uap->im |= UART011_RXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
} else {
|
||||
#ifdef CONFIG_DMA_ENGINE
|
||||
/* Start Rx DMA poll */
|
||||
@ -1263,10 +1354,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
|
||||
bool from_irq)
|
||||
{
|
||||
if (unlikely(!from_irq) &&
|
||||
readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
|
||||
pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
|
||||
return false; /* unable to transmit character */
|
||||
|
||||
writew(c, uap->port.membase + UART01x_DR);
|
||||
pl011_write(c, uap, REG_DR);
|
||||
uap->port.icount.tx++;
|
||||
|
||||
return true;
|
||||
@ -1313,7 +1404,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
|
||||
{
|
||||
unsigned int status, delta;
|
||||
|
||||
status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
||||
status = pl011_read(uap, REG_FR) & UART01x_FR_MODEM_ANY;
|
||||
|
||||
delta = status ^ uap->old_status;
|
||||
uap->old_status = status;
|
||||
@ -1341,15 +1432,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
|
||||
return;
|
||||
|
||||
/* workaround to make sure that all bits are unlocked.. */
|
||||
writew(0x00, uap->port.membase + UART011_ICR);
|
||||
pl011_write(0x00, uap, REG_ICR);
|
||||
|
||||
/*
|
||||
* WA: introduce 26ns(1 uart clk) delay before W1C;
|
||||
* single apb access will incur 2 pclk(133.12Mhz) delay,
|
||||
* so add 2 dummy reads
|
||||
*/
|
||||
dummy_read = readw(uap->port.membase + UART011_ICR);
|
||||
dummy_read = readw(uap->port.membase + UART011_ICR);
|
||||
dummy_read = pl011_read(uap, REG_ICR);
|
||||
dummy_read = pl011_read(uap, REG_ICR);
|
||||
}
|
||||
|
||||
static irqreturn_t pl011_int(int irq, void *dev_id)
|
||||
@ -1361,15 +1452,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
|
||||
int handled = 0;
|
||||
|
||||
spin_lock_irqsave(&uap->port.lock, flags);
|
||||
imsc = readw(uap->port.membase + UART011_IMSC);
|
||||
status = readw(uap->port.membase + UART011_RIS) & imsc;
|
||||
imsc = pl011_read(uap, REG_IMSC);
|
||||
status = pl011_read(uap, REG_RIS) & imsc;
|
||||
if (status) {
|
||||
do {
|
||||
check_apply_cts_event_workaround(uap);
|
||||
|
||||
writew(status & ~(UART011_TXIS|UART011_RTIS|
|
||||
UART011_RXIS),
|
||||
uap->port.membase + UART011_ICR);
|
||||
pl011_write(status & ~(UART011_TXIS|UART011_RTIS|
|
||||
UART011_RXIS),
|
||||
uap, REG_ICR);
|
||||
|
||||
if (status & (UART011_RTIS|UART011_RXIS)) {
|
||||
if (pl011_dma_rx_running(uap))
|
||||
@ -1386,7 +1477,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
|
||||
if (pass_counter-- == 0)
|
||||
break;
|
||||
|
||||
status = readw(uap->port.membase + UART011_RIS) & imsc;
|
||||
status = pl011_read(uap, REG_RIS) & imsc;
|
||||
} while (status != 0);
|
||||
handled = 1;
|
||||
}
|
||||
@ -1400,7 +1491,7 @@ static unsigned int pl011_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
unsigned int status = readw(uap->port.membase + UART01x_FR);
|
||||
unsigned int status = pl011_read(uap, REG_FR);
|
||||
return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
@ -1409,7 +1500,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
|
||||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
unsigned int result = 0;
|
||||
unsigned int status = readw(uap->port.membase + UART01x_FR);
|
||||
unsigned int status = pl011_read(uap, REG_FR);
|
||||
|
||||
#define TIOCMBIT(uartbit, tiocmbit) \
|
||||
if (status & uartbit) \
|
||||
@ -1429,7 +1520,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
unsigned int cr;
|
||||
|
||||
cr = readw(uap->port.membase + UART011_CR);
|
||||
cr = pl011_read(uap, REG_CR);
|
||||
|
||||
#define TIOCMBIT(tiocmbit, uartbit) \
|
||||
if (mctrl & tiocmbit) \
|
||||
@ -1449,7 +1540,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
}
|
||||
#undef TIOCMBIT
|
||||
|
||||
writew(cr, uap->port.membase + UART011_CR);
|
||||
pl011_write(cr, uap, REG_CR);
|
||||
}
|
||||
|
||||
static void pl011_break_ctl(struct uart_port *port, int break_state)
|
||||
@ -1460,12 +1551,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
|
||||
unsigned int lcr_h;
|
||||
|
||||
spin_lock_irqsave(&uap->port.lock, flags);
|
||||
lcr_h = readw(uap->port.membase + uap->lcrh_tx);
|
||||
lcr_h = pl011_read(uap, REG_LCRH_TX);
|
||||
if (break_state == -1)
|
||||
lcr_h |= UART01x_LCRH_BRK;
|
||||
else
|
||||
lcr_h &= ~UART01x_LCRH_BRK;
|
||||
writew(lcr_h, uap->port.membase + uap->lcrh_tx);
|
||||
pl011_write(lcr_h, uap, REG_LCRH_TX);
|
||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||
}
|
||||
|
||||
@ -1475,9 +1566,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
unsigned char __iomem *regs = uap->port.membase;
|
||||
|
||||
writew(readw(regs + UART011_MIS), regs + UART011_ICR);
|
||||
pl011_write(pl011_read(uap, REG_MIS), uap, REG_ICR);
|
||||
/*
|
||||
* There is no way to clear TXIM as this is "ready to transmit IRQ", so
|
||||
* we simply mask it. start_tx() will unmask it.
|
||||
@ -1491,7 +1581,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
|
||||
* (including tx queue), so we're also fine with start_tx()'s caller
|
||||
* side.
|
||||
*/
|
||||
writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC);
|
||||
pl011_write(pl011_read(uap, REG_IMSC) & ~UART011_TXIM, uap,
|
||||
REG_IMSC);
|
||||
}
|
||||
|
||||
static int pl011_get_poll_char(struct uart_port *port)
|
||||
@ -1506,11 +1597,11 @@ static int pl011_get_poll_char(struct uart_port *port)
|
||||
*/
|
||||
pl011_quiesce_irqs(port);
|
||||
|
||||
status = readw(uap->port.membase + UART01x_FR);
|
||||
status = pl011_read(uap, REG_FR);
|
||||
if (status & UART01x_FR_RXFE)
|
||||
return NO_POLL_CHAR;
|
||||
|
||||
return readw(uap->port.membase + UART01x_DR);
|
||||
return pl011_read(uap, REG_DR);
|
||||
}
|
||||
|
||||
static void pl011_put_poll_char(struct uart_port *port,
|
||||
@ -1519,10 +1610,10 @@ static void pl011_put_poll_char(struct uart_port *port,
|
||||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
|
||||
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
|
||||
while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
|
||||
barrier();
|
||||
|
||||
writew(ch, uap->port.membase + UART01x_DR);
|
||||
pl011_write(ch, uap, REG_DR);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CONSOLE_POLL */
|
||||
@ -1546,15 +1637,16 @@ static int pl011_hwinit(struct uart_port *port)
|
||||
uap->port.uartclk = clk_get_rate(uap->clk);
|
||||
|
||||
/* Clear pending error and receive interrupts */
|
||||
writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
|
||||
UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
|
||||
pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
|
||||
UART011_FEIS | UART011_RTIS | UART011_RXIS,
|
||||
uap, REG_ICR);
|
||||
|
||||
/*
|
||||
* Save interrupts enable mask, and enable RX interrupts in case if
|
||||
* the interrupt is used for NMI entry.
|
||||
*/
|
||||
uap->im = readw(uap->port.membase + UART011_IMSC);
|
||||
writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC);
|
||||
uap->im = pl011_read(uap, REG_IMSC);
|
||||
pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC);
|
||||
|
||||
if (dev_get_platdata(uap->port.dev)) {
|
||||
struct amba_pl011_data *plat;
|
||||
@ -1566,24 +1658,30 @@ static int pl011_hwinit(struct uart_port *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool pl011_split_lcrh(const struct uart_amba_port *uap)
|
||||
{
|
||||
return pl011_reg_to_offset(uap, REG_LCRH_RX) !=
|
||||
pl011_reg_to_offset(uap, REG_LCRH_TX);
|
||||
}
|
||||
|
||||
static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
|
||||
{
|
||||
writew(lcr_h, uap->port.membase + uap->lcrh_rx);
|
||||
if (uap->lcrh_rx != uap->lcrh_tx) {
|
||||
pl011_write(lcr_h, uap, REG_LCRH_RX);
|
||||
if (pl011_split_lcrh(uap)) {
|
||||
int i;
|
||||
/*
|
||||
* Wait 10 PCLKs before writing LCRH_TX register,
|
||||
* to get this delay write read only register 10 times
|
||||
*/
|
||||
for (i = 0; i < 10; ++i)
|
||||
writew(0xff, uap->port.membase + UART011_MIS);
|
||||
writew(lcr_h, uap->port.membase + uap->lcrh_tx);
|
||||
pl011_write(0xff, uap, REG_MIS);
|
||||
pl011_write(lcr_h, uap, REG_LCRH_TX);
|
||||
}
|
||||
}
|
||||
|
||||
static int pl011_allocate_irq(struct uart_amba_port *uap)
|
||||
{
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
|
||||
return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
|
||||
}
|
||||
@ -1598,12 +1696,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
|
||||
/* Clear out any spuriously appearing RX interrupts */
|
||||
writew(UART011_RTIS | UART011_RXIS,
|
||||
uap->port.membase + UART011_ICR);
|
||||
pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
|
||||
uap->im = UART011_RTIM;
|
||||
if (!pl011_dma_rx_running(uap))
|
||||
uap->im |= UART011_RXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
}
|
||||
|
||||
@ -1622,21 +1719,21 @@ static int pl011_startup(struct uart_port *port)
|
||||
if (retval)
|
||||
goto clk_dis;
|
||||
|
||||
writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
|
||||
pl011_write(uap->vendor->ifls, uap, REG_IFLS);
|
||||
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
|
||||
/* restore RTS and DTR */
|
||||
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
|
||||
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
|
||||
writew(cr, uap->port.membase + UART011_CR);
|
||||
pl011_write(cr, uap, REG_CR);
|
||||
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
|
||||
/*
|
||||
* initialise the old status of the modem signals
|
||||
*/
|
||||
uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
||||
uap->old_status = pl011_read(uap, REG_FR) & UART01x_FR_MODEM_ANY;
|
||||
|
||||
/* Startup DMA */
|
||||
pl011_dma_startup(uap);
|
||||
@ -1677,9 +1774,9 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
val = readw(uap->port.membase + lcrh);
|
||||
val = pl011_read(uap, lcrh);
|
||||
val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
|
||||
writew(val, uap->port.membase + lcrh);
|
||||
pl011_write(val, uap, lcrh);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1693,19 +1790,19 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
|
||||
|
||||
uap->autorts = false;
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
cr = readw(uap->port.membase + UART011_CR);
|
||||
cr = pl011_read(uap, REG_CR);
|
||||
uap->old_cr = cr;
|
||||
cr &= UART011_CR_RTS | UART011_CR_DTR;
|
||||
cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
|
||||
writew(cr, uap->port.membase + UART011_CR);
|
||||
pl011_write(cr, uap, REG_CR);
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
|
||||
/*
|
||||
* disable break condition and fifos
|
||||
*/
|
||||
pl011_shutdown_channel(uap, uap->lcrh_rx);
|
||||
if (uap->lcrh_rx != uap->lcrh_tx)
|
||||
pl011_shutdown_channel(uap, uap->lcrh_tx);
|
||||
pl011_shutdown_channel(uap, REG_LCRH_RX);
|
||||
if (pl011_split_lcrh(uap))
|
||||
pl011_shutdown_channel(uap, REG_LCRH_TX);
|
||||
}
|
||||
|
||||
static void pl011_disable_interrupts(struct uart_amba_port *uap)
|
||||
@ -1714,8 +1811,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
|
||||
|
||||
/* mask all interrupts and clear all pending ones */
|
||||
uap->im = 0;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
writew(0xffff, uap->port.membase + UART011_ICR);
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
pl011_write(0xffff, uap, REG_ICR);
|
||||
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
}
|
||||
@ -1867,8 +1964,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
pl011_enable_ms(port);
|
||||
|
||||
/* first, disable everything */
|
||||
old_cr = readw(port->membase + UART011_CR);
|
||||
writew(0, port->membase + UART011_CR);
|
||||
old_cr = pl011_read(uap, REG_CR);
|
||||
pl011_write(0, uap, REG_CR);
|
||||
|
||||
if (termios->c_cflag & CRTSCTS) {
|
||||
if (old_cr & UART011_CR_RTS)
|
||||
@ -1901,17 +1998,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
quot -= 2;
|
||||
}
|
||||
/* Set baud rate */
|
||||
writew(quot & 0x3f, port->membase + UART011_FBRD);
|
||||
writew(quot >> 6, port->membase + UART011_IBRD);
|
||||
pl011_write(quot & 0x3f, uap, REG_FBRD);
|
||||
pl011_write(quot >> 6, uap, REG_IBRD);
|
||||
|
||||
/*
|
||||
* ----------v----------v----------v----------v-----
|
||||
* NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
|
||||
* UART011_FBRD & UART011_IBRD.
|
||||
* NOTE: REG_LCRH_TX and REG_LCRH_RX MUST BE WRITTEN AFTER
|
||||
* REG_FBRD & REG_IBRD.
|
||||
* ----------^----------^----------^----------^-----
|
||||
*/
|
||||
pl011_write_lcr_h(uap, lcr_h);
|
||||
writew(old_cr, port->membase + UART011_CR);
|
||||
pl011_write(old_cr, uap, REG_CR);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
@ -2052,9 +2149,9 @@ static void pl011_console_putchar(struct uart_port *port, int ch)
|
||||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
|
||||
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
|
||||
while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
|
||||
barrier();
|
||||
writew(ch, uap->port.membase + UART01x_DR);
|
||||
pl011_write(ch, uap, REG_DR);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2079,10 +2176,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
|
||||
* First save the CR then disable the interrupts
|
||||
*/
|
||||
if (!uap->vendor->always_enabled) {
|
||||
old_cr = readw(uap->port.membase + UART011_CR);
|
||||
old_cr = pl011_read(uap, REG_CR);
|
||||
new_cr = old_cr & ~UART011_CR_CTSEN;
|
||||
new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
|
||||
writew(new_cr, uap->port.membase + UART011_CR);
|
||||
pl011_write(new_cr, uap, REG_CR);
|
||||
}
|
||||
|
||||
uart_console_write(&uap->port, s, count, pl011_console_putchar);
|
||||
@ -2092,10 +2189,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
|
||||
* and restore the TCR
|
||||
*/
|
||||
do {
|
||||
status = readw(uap->port.membase + UART01x_FR);
|
||||
status = pl011_read(uap, REG_FR);
|
||||
} while (status & UART01x_FR_BUSY);
|
||||
if (!uap->vendor->always_enabled)
|
||||
writew(old_cr, uap->port.membase + UART011_CR);
|
||||
pl011_write(old_cr, uap, REG_CR);
|
||||
|
||||
if (locked)
|
||||
spin_unlock(&uap->port.lock);
|
||||
@ -2108,10 +2205,10 @@ static void __init
|
||||
pl011_console_get_options(struct uart_amba_port *uap, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
|
||||
if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
|
||||
unsigned int lcr_h, ibrd, fbrd;
|
||||
|
||||
lcr_h = readw(uap->port.membase + uap->lcrh_tx);
|
||||
lcr_h = pl011_read(uap, REG_LCRH_TX);
|
||||
|
||||
*parity = 'n';
|
||||
if (lcr_h & UART01x_LCRH_PEN) {
|
||||
@ -2126,13 +2223,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
|
||||
else
|
||||
*bits = 8;
|
||||
|
||||
ibrd = readw(uap->port.membase + UART011_IBRD);
|
||||
fbrd = readw(uap->port.membase + UART011_FBRD);
|
||||
ibrd = pl011_read(uap, REG_IBRD);
|
||||
fbrd = pl011_read(uap, REG_FBRD);
|
||||
|
||||
*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
|
||||
|
||||
if (uap->vendor->oversampling) {
|
||||
if (readw(uap->port.membase + UART011_CR)
|
||||
if (pl011_read(uap, REG_CR)
|
||||
& ST_UART011_CR_OVSFACT)
|
||||
*baud *= 2;
|
||||
}
|
||||
@ -2206,7 +2303,10 @@ static void pl011_putc(struct uart_port *port, int c)
|
||||
{
|
||||
while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
|
||||
;
|
||||
writeb(c, port->membase + UART01x_DR);
|
||||
if (port->iotype == UPIO_MEM32)
|
||||
writel(c, port->membase + UART01x_DR);
|
||||
else
|
||||
writeb(c, port->membase + UART01x_DR);
|
||||
while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
|
||||
;
|
||||
}
|
||||
@ -2319,7 +2419,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
|
||||
uap->port.dev = dev;
|
||||
uap->port.mapbase = mmiobase->start;
|
||||
uap->port.membase = base;
|
||||
uap->port.iotype = UPIO_MEM;
|
||||
uap->port.fifosize = uap->fifosize;
|
||||
uap->port.flags = UPF_BOOT_AUTOCONF;
|
||||
uap->port.line = index;
|
||||
@ -2334,8 +2433,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
|
||||
int ret;
|
||||
|
||||
/* Ensure interrupts from this UART are masked and cleared */
|
||||
writew(0, uap->port.membase + UART011_IMSC);
|
||||
writew(0xffff, uap->port.membase + UART011_ICR);
|
||||
pl011_write(0, uap, REG_IMSC);
|
||||
pl011_write(0xffff, uap, REG_ICR);
|
||||
|
||||
if (!amba_reg.state) {
|
||||
ret = uart_register_driver(&amba_reg);
|
||||
@ -2372,10 +2471,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
if (IS_ERR(uap->clk))
|
||||
return PTR_ERR(uap->clk);
|
||||
|
||||
uap->reg_offset = vendor->reg_offset;
|
||||
uap->vendor = vendor;
|
||||
uap->lcrh_rx = vendor->lcrh_rx;
|
||||
uap->lcrh_tx = vendor->lcrh_tx;
|
||||
uap->fifosize = vendor->get_fifosize(dev);
|
||||
uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM;
|
||||
uap->port.irq = dev->irq[0];
|
||||
uap->port.ops = &amba_pl011_pops;
|
||||
|
||||
@ -2453,8 +2552,10 @@ static int sbsa_uart_probe(struct platform_device *pdev)
|
||||
if (!uap)
|
||||
return -ENOMEM;
|
||||
|
||||
uap->reg_offset = vendor_sbsa.reg_offset;
|
||||
uap->vendor = &vendor_sbsa;
|
||||
uap->fifosize = 32;
|
||||
uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM;
|
||||
uap->port.irq = platform_get_irq(pdev, 0);
|
||||
uap->port.ops = &sbsa_uart_pops;
|
||||
uap->fixed_baud = baudrate;
|
||||
|
34
drivers/tty/serial/amba-pl011.h
Normal file
34
drivers/tty/serial/amba-pl011.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef AMBA_PL011_H
|
||||
#define AMBA_PL011_H
|
||||
|
||||
enum {
|
||||
REG_DR,
|
||||
REG_ST_DMAWM,
|
||||
REG_ST_TIMEOUT,
|
||||
REG_FR,
|
||||
REG_LCRH_RX,
|
||||
REG_LCRH_TX,
|
||||
REG_IBRD,
|
||||
REG_FBRD,
|
||||
REG_CR,
|
||||
REG_IFLS,
|
||||
REG_IMSC,
|
||||
REG_RIS,
|
||||
REG_MIS,
|
||||
REG_ICR,
|
||||
REG_DMACR,
|
||||
REG_ST_XFCR,
|
||||
REG_ST_XON1,
|
||||
REG_ST_XON2,
|
||||
REG_ST_XOFF1,
|
||||
REG_ST_XOFF2,
|
||||
REG_ST_ITCR,
|
||||
REG_ST_ITIP,
|
||||
REG_ST_ABCR,
|
||||
REG_ST_ABIMSC,
|
||||
|
||||
/* The size of the array - must be last */
|
||||
REG_ARRAY_SIZE,
|
||||
};
|
||||
|
||||
#endif
|
@ -22,7 +22,6 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/slab.h>
|
||||
@ -155,7 +154,6 @@ struct atmel_uart_port {
|
||||
struct circ_buf rx_ring;
|
||||
|
||||
struct mctrl_gpios *gpios;
|
||||
int gpio_irq[UART_GPIO_MAX];
|
||||
unsigned int tx_done_mask;
|
||||
u32 fifo_size;
|
||||
u32 rts_high;
|
||||
@ -190,8 +188,6 @@ static const struct of_device_id atmel_serial_dt_ids[] = {
|
||||
{ .compatible = "atmel,at91sam9260-usart" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids);
|
||||
#endif
|
||||
|
||||
static inline struct atmel_uart_port *
|
||||
@ -550,27 +546,21 @@ static void atmel_enable_ms(struct uart_port *port)
|
||||
|
||||
atmel_port->ms_irq_enabled = true;
|
||||
|
||||
if (atmel_port->gpio_irq[UART_GPIO_CTS] >= 0)
|
||||
enable_irq(atmel_port->gpio_irq[UART_GPIO_CTS]);
|
||||
else
|
||||
if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS))
|
||||
ier |= ATMEL_US_CTSIC;
|
||||
|
||||
if (atmel_port->gpio_irq[UART_GPIO_DSR] >= 0)
|
||||
enable_irq(atmel_port->gpio_irq[UART_GPIO_DSR]);
|
||||
else
|
||||
if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DSR))
|
||||
ier |= ATMEL_US_DSRIC;
|
||||
|
||||
if (atmel_port->gpio_irq[UART_GPIO_RI] >= 0)
|
||||
enable_irq(atmel_port->gpio_irq[UART_GPIO_RI]);
|
||||
else
|
||||
if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_RI))
|
||||
ier |= ATMEL_US_RIIC;
|
||||
|
||||
if (atmel_port->gpio_irq[UART_GPIO_DCD] >= 0)
|
||||
enable_irq(atmel_port->gpio_irq[UART_GPIO_DCD]);
|
||||
else
|
||||
if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DCD))
|
||||
ier |= ATMEL_US_DCDIC;
|
||||
|
||||
atmel_uart_writel(port, ATMEL_US_IER, ier);
|
||||
|
||||
mctrl_gpio_enable_ms(atmel_port->gpios);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -589,24 +579,18 @@ static void atmel_disable_ms(struct uart_port *port)
|
||||
|
||||
atmel_port->ms_irq_enabled = false;
|
||||
|
||||
if (atmel_port->gpio_irq[UART_GPIO_CTS] >= 0)
|
||||
disable_irq(atmel_port->gpio_irq[UART_GPIO_CTS]);
|
||||
else
|
||||
mctrl_gpio_disable_ms(atmel_port->gpios);
|
||||
|
||||
if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS))
|
||||
idr |= ATMEL_US_CTSIC;
|
||||
|
||||
if (atmel_port->gpio_irq[UART_GPIO_DSR] >= 0)
|
||||
disable_irq(atmel_port->gpio_irq[UART_GPIO_DSR]);
|
||||
else
|
||||
if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DSR))
|
||||
idr |= ATMEL_US_DSRIC;
|
||||
|
||||
if (atmel_port->gpio_irq[UART_GPIO_RI] >= 0)
|
||||
disable_irq(atmel_port->gpio_irq[UART_GPIO_RI]);
|
||||
else
|
||||
if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_RI))
|
||||
idr |= ATMEL_US_RIIC;
|
||||
|
||||
if (atmel_port->gpio_irq[UART_GPIO_DCD] >= 0)
|
||||
disable_irq(atmel_port->gpio_irq[UART_GPIO_DCD]);
|
||||
else
|
||||
if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DCD))
|
||||
idr |= ATMEL_US_DCDIC;
|
||||
|
||||
atmel_uart_writel(port, ATMEL_US_IDR, idr);
|
||||
@ -1264,7 +1248,6 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
|
||||
struct uart_port *port = dev_id;
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
unsigned int status, pending, mask, pass_counter = 0;
|
||||
bool gpio_handled = false;
|
||||
|
||||
spin_lock(&atmel_port->lock_suspended);
|
||||
|
||||
@ -1272,24 +1255,6 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
|
||||
status = atmel_get_lines_status(port);
|
||||
mask = atmel_uart_readl(port, ATMEL_US_IMR);
|
||||
pending = status & mask;
|
||||
if (!gpio_handled) {
|
||||
/*
|
||||
* Dealing with GPIO interrupt
|
||||
*/
|
||||
if (irq == atmel_port->gpio_irq[UART_GPIO_CTS])
|
||||
pending |= ATMEL_US_CTSIC;
|
||||
|
||||
if (irq == atmel_port->gpio_irq[UART_GPIO_DSR])
|
||||
pending |= ATMEL_US_DSRIC;
|
||||
|
||||
if (irq == atmel_port->gpio_irq[UART_GPIO_RI])
|
||||
pending |= ATMEL_US_RIIC;
|
||||
|
||||
if (irq == atmel_port->gpio_irq[UART_GPIO_DCD])
|
||||
pending |= ATMEL_US_DCDIC;
|
||||
|
||||
gpio_handled = true;
|
||||
}
|
||||
if (!pending)
|
||||
break;
|
||||
|
||||
@ -1778,45 +1743,6 @@ static void atmel_get_ip_name(struct uart_port *port)
|
||||
}
|
||||
}
|
||||
|
||||
static void atmel_free_gpio_irq(struct uart_port *port)
|
||||
{
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
enum mctrl_gpio_idx i;
|
||||
|
||||
for (i = 0; i < UART_GPIO_MAX; i++)
|
||||
if (atmel_port->gpio_irq[i] >= 0)
|
||||
free_irq(atmel_port->gpio_irq[i], port);
|
||||
}
|
||||
|
||||
static int atmel_request_gpio_irq(struct uart_port *port)
|
||||
{
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
int *irq = atmel_port->gpio_irq;
|
||||
enum mctrl_gpio_idx i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 0; (i < UART_GPIO_MAX) && !err; i++) {
|
||||
if (irq[i] < 0)
|
||||
continue;
|
||||
|
||||
irq_set_status_flags(irq[i], IRQ_NOAUTOEN);
|
||||
err = request_irq(irq[i], atmel_interrupt, IRQ_TYPE_EDGE_BOTH,
|
||||
"atmel_serial", port);
|
||||
if (err)
|
||||
dev_err(port->dev, "atmel_startup - Can't get %d irq\n",
|
||||
irq[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* If something went wrong, rollback.
|
||||
*/
|
||||
while (err && (--i >= 0))
|
||||
if (irq[i] >= 0)
|
||||
free_irq(irq[i], port);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform initialization and enable port for reception
|
||||
*/
|
||||
@ -1846,13 +1772,6 @@ static int atmel_startup(struct uart_port *port)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the GPIO lines IRQ
|
||||
*/
|
||||
retval = atmel_request_gpio_irq(port);
|
||||
if (retval)
|
||||
goto free_irq;
|
||||
|
||||
tasklet_enable(&atmel_port->tasklet);
|
||||
|
||||
/*
|
||||
@ -1948,11 +1867,6 @@ static int atmel_startup(struct uart_port *port)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_irq:
|
||||
free_irq(port->irq, port);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2018,7 +1932,6 @@ static void atmel_shutdown(struct uart_port *port)
|
||||
* Free the interrupts
|
||||
*/
|
||||
free_irq(port->irq, port);
|
||||
atmel_free_gpio_irq(port);
|
||||
|
||||
atmel_port->ms_irq_enabled = false;
|
||||
|
||||
@ -2686,26 +2599,6 @@ static int atmel_serial_resume(struct platform_device *pdev)
|
||||
#define atmel_serial_resume NULL
|
||||
#endif
|
||||
|
||||
static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
|
||||
{
|
||||
enum mctrl_gpio_idx i;
|
||||
struct gpio_desc *gpiod;
|
||||
|
||||
p->gpios = mctrl_gpio_init_noauto(dev, 0);
|
||||
if (IS_ERR(p->gpios))
|
||||
return PTR_ERR(p->gpios);
|
||||
|
||||
for (i = 0; i < UART_GPIO_MAX; i++) {
|
||||
gpiod = mctrl_gpio_to_gpiod(p->gpios, i);
|
||||
if (gpiod && (gpiod_get_direction(gpiod) == GPIOF_DIR_IN))
|
||||
p->gpio_irq[i] = gpiod_to_irq(gpiod);
|
||||
else
|
||||
p->gpio_irq[i] = -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
@ -2788,16 +2681,16 @@ static int atmel_serial_probe(struct platform_device *pdev)
|
||||
|
||||
spin_lock_init(&port->lock_suspended);
|
||||
|
||||
ret = atmel_init_gpios(port, &pdev->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to initialize GPIOs.");
|
||||
goto err_clear_bit;
|
||||
}
|
||||
|
||||
ret = atmel_init_port(port, pdev);
|
||||
if (ret)
|
||||
goto err_clear_bit;
|
||||
|
||||
port->gpios = mctrl_gpio_init(&port->uart, 0);
|
||||
if (IS_ERR(port->gpios)) {
|
||||
ret = PTR_ERR(port->gpios);
|
||||
goto err_clear_bit;
|
||||
}
|
||||
|
||||
if (!atmel_use_pdc_rx(&port->uart)) {
|
||||
ret = -ENOMEM;
|
||||
data = kmalloc(sizeof(struct atmel_uart_char)
|
||||
@ -2866,37 +2759,14 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int atmel_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
int ret = 0;
|
||||
|
||||
tasklet_kill(&atmel_port->tasklet);
|
||||
|
||||
device_init_wakeup(&pdev->dev, 0);
|
||||
|
||||
ret = uart_remove_one_port(&atmel_uart, port);
|
||||
|
||||
kfree(atmel_port->rx_ring.buf);
|
||||
|
||||
/* "port" is allocated statically, so we shouldn't free it */
|
||||
|
||||
clear_bit(port->line, atmel_ports_in_use);
|
||||
|
||||
clk_put(atmel_port->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver atmel_serial_driver = {
|
||||
.probe = atmel_serial_probe,
|
||||
.remove = atmel_serial_remove,
|
||||
.suspend = atmel_serial_suspend,
|
||||
.resume = atmel_serial_resume,
|
||||
.driver = {
|
||||
.name = "atmel_usart",
|
||||
.of_match_table = of_match_ptr(atmel_serial_dt_ids),
|
||||
.name = "atmel_usart",
|
||||
.of_match_table = of_match_ptr(atmel_serial_dt_ids),
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2914,17 +2784,4 @@ static int __init atmel_serial_init(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit atmel_serial_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&atmel_serial_driver);
|
||||
uart_unregister_driver(&atmel_uart);
|
||||
}
|
||||
|
||||
module_init(atmel_serial_init);
|
||||
module_exit(atmel_serial_exit);
|
||||
|
||||
MODULE_AUTHOR("Rick Bronson");
|
||||
MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:atmel_usart");
|
||||
device_initcall(atmel_serial_init);
|
||||
|
@ -653,7 +653,7 @@ static struct uart_ops bcm_uart_ops = {
|
||||
|
||||
|
||||
#ifdef CONFIG_SERIAL_BCM63XX_CONSOLE
|
||||
static inline void wait_for_xmitr(struct uart_port *port)
|
||||
static void wait_for_xmitr(struct uart_port *port)
|
||||
{
|
||||
unsigned int tmout;
|
||||
|
||||
|
@ -213,7 +213,7 @@ static void bfin_serial_stop_rx(struct uart_port *port)
|
||||
static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
|
||||
{
|
||||
unsigned int status, ch, flg;
|
||||
static struct timeval anomaly_start = { .tv_sec = 0 };
|
||||
static u64 anomaly_start;
|
||||
|
||||
status = UART_GET_LSR(uart);
|
||||
UART_CLEAR_LSR(uart);
|
||||
@ -246,27 +246,24 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
|
||||
* character time +/- some percent. So 1.5 sounds good. All other
|
||||
* Blackfin families operate properly. Woo.
|
||||
*/
|
||||
if (anomaly_start.tv_sec) {
|
||||
struct timeval curr;
|
||||
suseconds_t usecs;
|
||||
if (anomaly_start > 0) {
|
||||
u64 curr, nsecs, threshold_ns;
|
||||
|
||||
if ((~ch & (~ch + 1)) & 0xff)
|
||||
goto known_good_char;
|
||||
|
||||
do_gettimeofday(&curr);
|
||||
if (curr.tv_sec - anomaly_start.tv_sec > 1)
|
||||
curr = ktime_get_ns();
|
||||
nsecs = curr - anomaly_start;
|
||||
if (nsecs >> 32)
|
||||
goto known_good_char;
|
||||
|
||||
usecs = 0;
|
||||
if (curr.tv_sec != anomaly_start.tv_sec)
|
||||
usecs += USEC_PER_SEC;
|
||||
usecs += curr.tv_usec - anomaly_start.tv_usec;
|
||||
|
||||
if (usecs > UART_GET_ANOMALY_THRESHOLD(uart))
|
||||
threshold_ns = UART_GET_ANOMALY_THRESHOLD(uart)
|
||||
* NSEC_PER_USEC;
|
||||
if (nsecs > threshold_ns)
|
||||
goto known_good_char;
|
||||
|
||||
if (ch)
|
||||
anomaly_start.tv_sec = 0;
|
||||
anomaly_start = 0;
|
||||
else
|
||||
anomaly_start = curr;
|
||||
|
||||
@ -274,14 +271,14 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
|
||||
|
||||
known_good_char:
|
||||
status &= ~BI;
|
||||
anomaly_start.tv_sec = 0;
|
||||
anomaly_start = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (status & BI) {
|
||||
if (ANOMALY_05000363)
|
||||
if (bfin_revid() < 5)
|
||||
do_gettimeofday(&anomaly_start);
|
||||
anomaly_start = ktime_get_ns();
|
||||
uart->port.icount.brk++;
|
||||
if (uart_handle_break(&uart->port))
|
||||
goto ignore_char;
|
||||
|
@ -71,10 +71,16 @@ static int __init parse_options(struct earlycon_device *device, char *options)
|
||||
return -EINVAL;
|
||||
|
||||
switch (port->iotype) {
|
||||
case UPIO_MEM:
|
||||
port->mapbase = addr;
|
||||
break;
|
||||
case UPIO_MEM16:
|
||||
port->regshift = 1;
|
||||
port->mapbase = addr;
|
||||
break;
|
||||
case UPIO_MEM32:
|
||||
case UPIO_MEM32BE:
|
||||
port->regshift = 2; /* fall-through */
|
||||
case UPIO_MEM:
|
||||
port->regshift = 2;
|
||||
port->mapbase = addr;
|
||||
break;
|
||||
case UPIO_PORT:
|
||||
@ -91,10 +97,11 @@ static int __init parse_options(struct earlycon_device *device, char *options)
|
||||
strlcpy(device->options, options, length);
|
||||
}
|
||||
|
||||
if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32 ||
|
||||
port->iotype == UPIO_MEM32BE)
|
||||
if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 ||
|
||||
port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE)
|
||||
pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
|
||||
(port->iotype == UPIO_MEM) ? "" :
|
||||
(port->iotype == UPIO_MEM16) ? "16" :
|
||||
(port->iotype == UPIO_MEM32) ? "32" : "32be",
|
||||
(unsigned long long)port->mapbase,
|
||||
device->options);
|
||||
|
@ -22,7 +22,6 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#define SERIAL_DO_RESTART
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include <linux/platform_data/serial-imx.h>
|
||||
#include <linux/platform_data/dma-imx.h>
|
||||
|
||||
#include "serial_mctrl_gpio.h"
|
||||
|
||||
/* Register definitions */
|
||||
#define URXD0 0x0 /* Receiver Register */
|
||||
#define URTX0 0x40 /* Transmitter Register */
|
||||
@ -148,8 +150,11 @@
|
||||
#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */
|
||||
#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */
|
||||
#define USR2_IDLE (1<<12) /* Idle condition */
|
||||
#define USR2_RIDELT (1<<10) /* Ring Interrupt Delta */
|
||||
#define USR2_RIIN (1<<9) /* Ring Indicator Input */
|
||||
#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */
|
||||
#define USR2_WAKE (1<<7) /* Wake */
|
||||
#define USR2_DCDIN (1<<5) /* Data Carrier Detect Input */
|
||||
#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */
|
||||
#define USR2_TXDC (1<<3) /* Transmitter complete */
|
||||
#define USR2_BRCD (1<<2) /* Break condition */
|
||||
@ -206,6 +211,8 @@ struct imx_port {
|
||||
struct clk *clk_per;
|
||||
const struct imx_uart_data *devdata;
|
||||
|
||||
struct mctrl_gpios *gpios;
|
||||
|
||||
/* DMA fields */
|
||||
unsigned int dma_is_inited:1;
|
||||
unsigned int dma_is_enabled:1;
|
||||
@ -308,49 +315,24 @@ static void imx_port_ucrs_restore(struct uart_port *port,
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle any change of modem status signal since we were last called.
|
||||
*/
|
||||
static void imx_mctrl_check(struct imx_port *sport)
|
||||
static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2)
|
||||
{
|
||||
unsigned int status, changed;
|
||||
*ucr2 &= ~UCR2_CTSC;
|
||||
*ucr2 |= UCR2_CTS;
|
||||
|
||||
status = sport->port.ops->get_mctrl(&sport->port);
|
||||
changed = status ^ sport->old_status;
|
||||
|
||||
if (changed == 0)
|
||||
return;
|
||||
|
||||
sport->old_status = status;
|
||||
|
||||
if (changed & TIOCM_RI)
|
||||
sport->port.icount.rng++;
|
||||
if (changed & TIOCM_DSR)
|
||||
sport->port.icount.dsr++;
|
||||
if (changed & TIOCM_CAR)
|
||||
uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
|
||||
if (changed & TIOCM_CTS)
|
||||
uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
|
||||
|
||||
wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
|
||||
mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is our per-port timeout handler, for checking the
|
||||
* modem status signals.
|
||||
*/
|
||||
static void imx_timeout(unsigned long data)
|
||||
static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)data;
|
||||
unsigned long flags;
|
||||
*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
|
||||
|
||||
if (sport->port.state) {
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
imx_mctrl_check(sport);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS);
|
||||
}
|
||||
|
||||
mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
|
||||
}
|
||||
static void imx_port_rts_auto(struct imx_port *sport, unsigned long *ucr2)
|
||||
{
|
||||
*ucr2 |= UCR2_CTSC;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -376,9 +358,9 @@ static void imx_stop_tx(struct uart_port *port)
|
||||
readl(port->membase + USR2) & USR2_TXDC) {
|
||||
temp = readl(port->membase + UCR2);
|
||||
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
temp &= ~UCR2_CTS;
|
||||
imx_port_rts_inactive(sport, &temp);
|
||||
else
|
||||
temp |= UCR2_CTS;
|
||||
imx_port_rts_active(sport, &temp);
|
||||
writel(temp, port->membase + UCR2);
|
||||
|
||||
temp = readl(port->membase + UCR4);
|
||||
@ -420,6 +402,8 @@ static void imx_enable_ms(struct uart_port *port)
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
mod_timer(&sport->timer, jiffies);
|
||||
|
||||
mctrl_gpio_enable_ms(sport->gpios);
|
||||
}
|
||||
|
||||
static void imx_dma_tx(struct imx_port *sport);
|
||||
@ -579,14 +563,14 @@ static void imx_start_tx(struct uart_port *port)
|
||||
unsigned long temp;
|
||||
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
/* enable transmitter and shifter empty irq */
|
||||
temp = readl(port->membase + UCR2);
|
||||
if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
|
||||
temp &= ~UCR2_CTS;
|
||||
imx_port_rts_inactive(sport, &temp);
|
||||
else
|
||||
temp |= UCR2_CTS;
|
||||
imx_port_rts_active(sport, &temp);
|
||||
writel(temp, port->membase + UCR2);
|
||||
|
||||
/* enable transmitter and shifter empty irq */
|
||||
temp = readl(port->membase + UCR4);
|
||||
temp |= UCR4_TCEN;
|
||||
writel(temp, port->membase + UCR4);
|
||||
@ -801,21 +785,33 @@ static unsigned int imx_tx_empty(struct uart_port *port)
|
||||
/*
|
||||
* We have a modem side uart, so the meanings of RTS and CTS are inverted.
|
||||
*/
|
||||
static unsigned int imx_get_hwmctrl(struct imx_port *sport)
|
||||
{
|
||||
unsigned int tmp = TIOCM_DSR;
|
||||
unsigned usr1 = readl(sport->port.membase + USR1);
|
||||
|
||||
if (usr1 & USR1_RTSS)
|
||||
tmp |= TIOCM_CTS;
|
||||
|
||||
/* in DCE mode DCDIN is always 0 */
|
||||
if (!(usr1 & USR2_DCDIN))
|
||||
tmp |= TIOCM_CAR;
|
||||
|
||||
/* in DCE mode RIIN is always 0 */
|
||||
if (readl(sport->port.membase + USR2) & USR2_RIIN)
|
||||
tmp |= TIOCM_RI;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static unsigned int imx_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
|
||||
unsigned int ret = imx_get_hwmctrl(sport);
|
||||
|
||||
if (readl(sport->port.membase + USR1) & USR1_RTSS)
|
||||
tmp |= TIOCM_CTS;
|
||||
mctrl_gpio_get(sport->gpios, &ret);
|
||||
|
||||
if (readl(sport->port.membase + UCR2) & UCR2_CTS)
|
||||
tmp |= TIOCM_RTS;
|
||||
|
||||
if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP)
|
||||
tmp |= TIOCM_LOOP;
|
||||
|
||||
return tmp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
@ -831,10 +827,17 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
writel(temp, sport->port.membase + UCR2);
|
||||
}
|
||||
|
||||
temp = readl(sport->port.membase + UCR3) & ~UCR3_DSR;
|
||||
if (!(mctrl & TIOCM_DTR))
|
||||
temp |= UCR3_DSR;
|
||||
writel(temp, sport->port.membase + UCR3);
|
||||
|
||||
temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
|
||||
if (mctrl & TIOCM_LOOP)
|
||||
temp |= UTS_LOOP;
|
||||
writel(temp, sport->port.membase + uts_reg(sport));
|
||||
|
||||
mctrl_gpio_set(sport->gpios, mctrl);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -857,6 +860,51 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle any change of modem status signal since we were last called.
|
||||
*/
|
||||
static void imx_mctrl_check(struct imx_port *sport)
|
||||
{
|
||||
unsigned int status, changed;
|
||||
|
||||
status = imx_get_hwmctrl(sport);
|
||||
changed = status ^ sport->old_status;
|
||||
|
||||
if (changed == 0)
|
||||
return;
|
||||
|
||||
sport->old_status = status;
|
||||
|
||||
if (changed & TIOCM_RI)
|
||||
sport->port.icount.rng++;
|
||||
if (changed & TIOCM_DSR)
|
||||
sport->port.icount.dsr++;
|
||||
if (changed & TIOCM_CAR)
|
||||
uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
|
||||
if (changed & TIOCM_CTS)
|
||||
uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
|
||||
|
||||
wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is our per-port timeout handler, for checking the
|
||||
* modem status signals.
|
||||
*/
|
||||
static void imx_timeout(unsigned long data)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)data;
|
||||
unsigned long flags;
|
||||
|
||||
if (sport->port.state) {
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
imx_mctrl_check(sport);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
|
||||
mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
#define RX_BUF_SIZE (PAGE_SIZE)
|
||||
static void imx_rx_dma_done(struct imx_port *sport)
|
||||
{
|
||||
@ -1207,6 +1255,8 @@ static void imx_shutdown(struct uart_port *port)
|
||||
imx_uart_dma_exit(sport);
|
||||
}
|
||||
|
||||
mctrl_gpio_disable_ms(sport->gpios);
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
temp = readl(sport->port.membase + UCR2);
|
||||
temp &= ~(UCR2_TXEN);
|
||||
@ -1284,9 +1334,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned int ucr2, old_ucr1, old_ucr2, baud, quot;
|
||||
unsigned long ucr2, old_ucr1, old_ucr2;
|
||||
unsigned int baud, quot;
|
||||
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
|
||||
unsigned int div, ufcr;
|
||||
unsigned long div, ufcr;
|
||||
unsigned long num, denom;
|
||||
uint64_t tdiv64;
|
||||
|
||||
@ -1315,19 +1366,25 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
* it under manual control and keep transmitter
|
||||
* disabled.
|
||||
*/
|
||||
if (!(port->rs485.flags &
|
||||
SER_RS485_RTS_AFTER_SEND))
|
||||
ucr2 |= UCR2_CTS;
|
||||
if (port->rs485.flags &
|
||||
SER_RS485_RTS_AFTER_SEND)
|
||||
imx_port_rts_inactive(sport, &ucr2);
|
||||
else
|
||||
imx_port_rts_active(sport, &ucr2);
|
||||
} else {
|
||||
ucr2 |= UCR2_CTSC;
|
||||
imx_port_rts_auto(sport, &ucr2);
|
||||
}
|
||||
} else {
|
||||
termios->c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
} else if (port->rs485.flags & SER_RS485_ENABLED)
|
||||
} else if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
/* disable transmitter */
|
||||
if (!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND))
|
||||
ucr2 |= UCR2_CTS;
|
||||
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
imx_port_rts_inactive(sport, &ucr2);
|
||||
else
|
||||
imx_port_rts_active(sport, &ucr2);
|
||||
}
|
||||
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
ucr2 |= UCR2_STPB;
|
||||
@ -1568,11 +1625,10 @@ static int imx_rs485_config(struct uart_port *port,
|
||||
|
||||
/* disable transmitter */
|
||||
temp = readl(sport->port.membase + UCR2);
|
||||
temp &= ~UCR2_CTSC;
|
||||
if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
|
||||
temp &= ~UCR2_CTS;
|
||||
imx_port_rts_inactive(sport, &temp);
|
||||
else
|
||||
temp |= UCR2_CTS;
|
||||
imx_port_rts_active(sport, &temp);
|
||||
writel(temp, sport->port.membase + UCR2);
|
||||
}
|
||||
|
||||
@ -1857,11 +1913,10 @@ static int serial_imx_probe_dt(struct imx_port *sport,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(imx_uart_dt_ids, &pdev->dev);
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
sport->devdata = of_device_get_match_data(&pdev->dev);
|
||||
if (!sport->devdata)
|
||||
/* no device tree device */
|
||||
return 1;
|
||||
|
||||
@ -1878,8 +1933,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
|
||||
if (of_get_property(np, "fsl,dte-mode", NULL))
|
||||
sport->dte_mode = 1;
|
||||
|
||||
sport->devdata = of_id->data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
@ -1948,6 +2001,10 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||
sport->timer.function = imx_timeout;
|
||||
sport->timer.data = (unsigned long)sport;
|
||||
|
||||
sport->gpios = mctrl_gpio_init(&sport->port, 0);
|
||||
if (IS_ERR(sport->gpios))
|
||||
return PTR_ERR(sport->gpios);
|
||||
|
||||
sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||
if (IS_ERR(sport->clk_ipg)) {
|
||||
ret = PTR_ERR(sport->clk_ipg);
|
||||
|
@ -70,7 +70,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = pci_request_regions(pdev, "jsm");
|
||||
rc = pci_request_regions(pdev, JSM_DRIVER_NAME);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "pci_request_region FAILED\n");
|
||||
goto out_disable_device;
|
||||
@ -328,7 +328,7 @@ static struct pci_device_id jsm_pci_tbl[] = {
|
||||
MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
|
||||
|
||||
static struct pci_driver jsm_driver = {
|
||||
.name = "jsm",
|
||||
.name = JSM_DRIVER_NAME,
|
||||
.id_table = jsm_pci_tbl,
|
||||
.probe = jsm_probe_one,
|
||||
.remove = jsm_remove_one,
|
||||
|
@ -714,7 +714,7 @@ static void neo_clear_break(struct jsm_channel *ch)
|
||||
/*
|
||||
* Parse the ISR register.
|
||||
*/
|
||||
static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
|
||||
static void neo_parse_isr(struct jsm_board *brd, u32 port)
|
||||
{
|
||||
struct jsm_channel *ch;
|
||||
u8 isr;
|
||||
|
@ -990,7 +990,7 @@ static void __init m32r_sio_register_ports(struct uart_driver *drv)
|
||||
/*
|
||||
* Wait for transmitter & holding register to empty
|
||||
*/
|
||||
static inline void wait_for_xmitr(struct uart_sio_port *up)
|
||||
static void wait_for_xmitr(struct uart_sio_port *up)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
|
@ -158,7 +158,7 @@ static inline void men_z135_reg_set(struct men_z135_port *uart,
|
||||
* @addr: Register address
|
||||
* @val: value to clear
|
||||
*/
|
||||
static inline void men_z135_reg_clr(struct men_z135_port *uart,
|
||||
static void men_z135_reg_clr(struct men_z135_port *uart,
|
||||
u32 addr, u32 val)
|
||||
{
|
||||
struct uart_port *port = &uart->port;
|
||||
|
@ -57,6 +57,7 @@
|
||||
#define AML_UART_RX_EMPTY BIT(20)
|
||||
#define AML_UART_TX_FULL BIT(21)
|
||||
#define AML_UART_TX_EMPTY BIT(22)
|
||||
#define AML_UART_XMIT_BUSY BIT(25)
|
||||
#define AML_UART_ERR (AML_UART_PARITY_ERR | \
|
||||
AML_UART_FRAME_ERR | \
|
||||
AML_UART_TX_FIFO_WERR)
|
||||
@ -100,7 +101,8 @@ static unsigned int meson_uart_tx_empty(struct uart_port *port)
|
||||
u32 val;
|
||||
|
||||
val = readl(port->membase + AML_UART_STATUS);
|
||||
return (val & AML_UART_TX_EMPTY) ? TIOCSER_TEMT : 0;
|
||||
val &= (AML_UART_TX_EMPTY | AML_UART_XMIT_BUSY);
|
||||
return (val == AML_UART_TX_EMPTY) ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
static void meson_uart_stop_tx(struct uart_port *port)
|
||||
@ -108,7 +110,7 @@ static void meson_uart_stop_tx(struct uart_port *port)
|
||||
u32 val;
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val &= ~AML_UART_TX_EN;
|
||||
val &= ~AML_UART_TX_INT_EN;
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
}
|
||||
|
||||
@ -131,7 +133,7 @@ static void meson_uart_shutdown(struct uart_port *port)
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val &= ~(AML_UART_RX_EN | AML_UART_TX_EN);
|
||||
val &= ~AML_UART_RX_EN;
|
||||
val &= ~(AML_UART_RX_INT_EN | AML_UART_TX_INT_EN);
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
|
||||
@ -142,6 +144,7 @@ static void meson_uart_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
unsigned int ch;
|
||||
u32 val;
|
||||
|
||||
if (uart_tx_stopped(port)) {
|
||||
meson_uart_stop_tx(port);
|
||||
@ -165,6 +168,12 @@ static void meson_uart_start_tx(struct uart_port *port)
|
||||
port->icount.tx++;
|
||||
}
|
||||
|
||||
if (!uart_circ_empty(xmit)) {
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val |= AML_UART_TX_INT_EN;
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
}
|
||||
@ -228,8 +237,10 @@ static irqreturn_t meson_uart_interrupt(int irq, void *dev_id)
|
||||
if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY))
|
||||
meson_receive_chars(port);
|
||||
|
||||
if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL))
|
||||
meson_uart_start_tx(port);
|
||||
if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)) {
|
||||
if (readl(port->membase + AML_UART_CONTROL) & AML_UART_TX_INT_EN)
|
||||
meson_uart_start_tx(port);
|
||||
}
|
||||
|
||||
spin_unlock(&port->lock);
|
||||
|
||||
@ -241,10 +252,9 @@ static const char *meson_uart_type(struct uart_port *port)
|
||||
return (port->type == PORT_MESON) ? "meson_uart" : NULL;
|
||||
}
|
||||
|
||||
static int meson_uart_startup(struct uart_port *port)
|
||||
static void meson_uart_reset(struct uart_port *port)
|
||||
{
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
|
||||
@ -252,6 +262,18 @@ static int meson_uart_startup(struct uart_port *port)
|
||||
|
||||
val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
}
|
||||
|
||||
static int meson_uart_startup(struct uart_port *port)
|
||||
{
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val |= AML_UART_CLR_ERR;
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
val &= ~AML_UART_CLR_ERR;
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
|
||||
val |= (AML_UART_RX_EN | AML_UART_TX_EN);
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
@ -272,7 +294,7 @@ static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
while (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_EMPTY))
|
||||
while (!meson_uart_tx_empty(port))
|
||||
cpu_relax();
|
||||
|
||||
val = readl(port->membase + AML_UART_REG5);
|
||||
@ -367,9 +389,26 @@ static int meson_uart_verify_port(struct uart_port *port,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int meson_uart_res_size(struct uart_port *port)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(port->dev);
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(port->dev, "cannot obtain I/O memory region");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return resource_size(res);
|
||||
}
|
||||
|
||||
static void meson_uart_release_port(struct uart_port *port)
|
||||
{
|
||||
int size = meson_uart_res_size(port);
|
||||
|
||||
if (port->flags & UPF_IOREMAP) {
|
||||
devm_release_mem_region(port->dev, port->mapbase, size);
|
||||
devm_iounmap(port->dev, port->membase);
|
||||
port->membase = NULL;
|
||||
}
|
||||
@ -377,16 +416,10 @@ static void meson_uart_release_port(struct uart_port *port)
|
||||
|
||||
static int meson_uart_request_port(struct uart_port *port)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(port->dev);
|
||||
struct resource *res;
|
||||
int size;
|
||||
int size = meson_uart_res_size(port);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "cannot obtain I/O memory region");
|
||||
return -ENODEV;
|
||||
}
|
||||
size = resource_size(res);
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
if (!devm_request_mem_region(port->dev, port->mapbase, size,
|
||||
dev_name(port->dev))) {
|
||||
@ -448,6 +481,7 @@ static void meson_serial_console_write(struct console *co, const char *s,
|
||||
struct uart_port *port;
|
||||
unsigned long flags;
|
||||
int locked;
|
||||
u32 val, tmp;
|
||||
|
||||
port = meson_ports[co->index];
|
||||
if (!port)
|
||||
@ -463,7 +497,13 @@ static void meson_serial_console_write(struct console *co, const char *s,
|
||||
locked = 1;
|
||||
}
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val |= AML_UART_TX_EN;
|
||||
tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN);
|
||||
writel(tmp, port->membase + AML_UART_CONTROL);
|
||||
|
||||
uart_console_write(port, s, count, meson_console_putchar);
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
|
||||
if (locked)
|
||||
spin_unlock(&port->lock);
|
||||
@ -570,6 +610,12 @@ static int meson_uart_probe(struct platform_device *pdev)
|
||||
meson_ports[pdev->id] = port;
|
||||
platform_set_drvdata(pdev, port);
|
||||
|
||||
/* reset port before registering (and possibly registering console) */
|
||||
if (meson_uart_request_port(port) >= 0) {
|
||||
meson_uart_reset(port);
|
||||
meson_uart_release_port(port);
|
||||
}
|
||||
|
||||
ret = uart_add_one_port(&meson_uart_driver, port);
|
||||
if (ret)
|
||||
meson_ports[pdev->id] = NULL;
|
||||
|
@ -1,477 +0,0 @@
|
||||
/*
|
||||
* Serial Port driver for a NWP uart device
|
||||
*
|
||||
* Copyright (C) 2008 IBM Corp., Benjamin Krill <ben@codiert.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/nwpserial.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/dcr.h>
|
||||
|
||||
#define NWPSERIAL_NR 2
|
||||
|
||||
#define NWPSERIAL_STATUS_RXVALID 0x1
|
||||
#define NWPSERIAL_STATUS_TXFULL 0x2
|
||||
|
||||
struct nwpserial_port {
|
||||
struct uart_port port;
|
||||
dcr_host_t dcr_host;
|
||||
unsigned int ier;
|
||||
unsigned int mcr;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(nwpserial_mutex);
|
||||
static struct nwpserial_port nwpserial_ports[NWPSERIAL_NR];
|
||||
|
||||
static void wait_for_bits(struct nwpserial_port *up, int bits)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
/* Wait up to 10ms for the character(s) to be sent. */
|
||||
do {
|
||||
status = dcr_read(up->dcr_host, UART_LSR);
|
||||
|
||||
if (--tmout == 0)
|
||||
break;
|
||||
udelay(1);
|
||||
} while ((status & bits) != bits);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
|
||||
static void nwpserial_console_putchar(struct uart_port *port, int c)
|
||||
{
|
||||
struct nwpserial_port *up;
|
||||
up = container_of(port, struct nwpserial_port, port);
|
||||
/* check if tx buffer is full */
|
||||
wait_for_bits(up, UART_LSR_THRE);
|
||||
dcr_write(up->dcr_host, UART_TX, c);
|
||||
up->port.icount.tx++;
|
||||
}
|
||||
|
||||
static void
|
||||
nwpserial_console_write(struct console *co, const char *s, unsigned int count)
|
||||
{
|
||||
struct nwpserial_port *up = &nwpserial_ports[co->index];
|
||||
unsigned long flags;
|
||||
int locked = 1;
|
||||
|
||||
if (oops_in_progress)
|
||||
locked = spin_trylock_irqsave(&up->port.lock, flags);
|
||||
else
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
|
||||
/* save and disable interrupt */
|
||||
up->ier = dcr_read(up->dcr_host, UART_IER);
|
||||
dcr_write(up->dcr_host, UART_IER, up->ier & ~UART_IER_RDI);
|
||||
|
||||
uart_console_write(&up->port, s, count, nwpserial_console_putchar);
|
||||
|
||||
/* wait for transmitter to become empty */
|
||||
while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0)
|
||||
cpu_relax();
|
||||
|
||||
/* restore interrupt state */
|
||||
dcr_write(up->dcr_host, UART_IER, up->ier);
|
||||
|
||||
if (locked)
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
}
|
||||
|
||||
static struct uart_driver nwpserial_reg;
|
||||
static struct console nwpserial_console = {
|
||||
.name = "ttySQ",
|
||||
.write = nwpserial_console_write,
|
||||
.device = uart_console_device,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &nwpserial_reg,
|
||||
};
|
||||
#define NWPSERIAL_CONSOLE (&nwpserial_console)
|
||||
#else
|
||||
#define NWPSERIAL_CONSOLE NULL
|
||||
#endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int nwpserial_request_port(struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nwpserial_release_port(struct uart_port *port)
|
||||
{
|
||||
/* N/A */
|
||||
}
|
||||
|
||||
static void nwpserial_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
port->type = PORT_NWPSERIAL;
|
||||
}
|
||||
|
||||
static irqreturn_t nwpserial_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct nwpserial_port *up = dev_id;
|
||||
struct tty_port *port = &up->port.state->port;
|
||||
irqreturn_t ret;
|
||||
unsigned int iir;
|
||||
unsigned char ch;
|
||||
|
||||
spin_lock(&up->port.lock);
|
||||
|
||||
/* check if the uart was the interrupt source. */
|
||||
iir = dcr_read(up->dcr_host, UART_IIR);
|
||||
if (!iir) {
|
||||
ret = IRQ_NONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
up->port.icount.rx++;
|
||||
ch = dcr_read(up->dcr_host, UART_RX);
|
||||
if (up->port.ignore_status_mask != NWPSERIAL_STATUS_RXVALID)
|
||||
tty_insert_flip_char(port, ch, TTY_NORMAL);
|
||||
} while (dcr_read(up->dcr_host, UART_LSR) & UART_LSR_DR);
|
||||
|
||||
spin_unlock(&up->port.lock);
|
||||
tty_flip_buffer_push(port);
|
||||
spin_lock(&up->port.lock);
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
/* clear interrupt */
|
||||
dcr_write(up->dcr_host, UART_IIR, 1);
|
||||
out:
|
||||
spin_unlock(&up->port.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nwpserial_startup(struct uart_port *port)
|
||||
{
|
||||
struct nwpserial_port *up;
|
||||
int err;
|
||||
|
||||
up = container_of(port, struct nwpserial_port, port);
|
||||
|
||||
/* disable flow control by default */
|
||||
up->mcr = dcr_read(up->dcr_host, UART_MCR) & ~UART_MCR_AFE;
|
||||
dcr_write(up->dcr_host, UART_MCR, up->mcr);
|
||||
|
||||
/* register interrupt handler */
|
||||
err = request_irq(up->port.irq, nwpserial_interrupt,
|
||||
IRQF_SHARED, "nwpserial", up);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* enable interrupts */
|
||||
up->ier = UART_IER_RDI;
|
||||
dcr_write(up->dcr_host, UART_IER, up->ier);
|
||||
|
||||
/* enable receiving */
|
||||
up->port.ignore_status_mask &= ~NWPSERIAL_STATUS_RXVALID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nwpserial_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct nwpserial_port *up;
|
||||
up = container_of(port, struct nwpserial_port, port);
|
||||
|
||||
/* disable receiving */
|
||||
up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID;
|
||||
|
||||
/* disable interrupts from this port */
|
||||
up->ier = 0;
|
||||
dcr_write(up->dcr_host, UART_IER, up->ier);
|
||||
|
||||
/* free irq */
|
||||
free_irq(up->port.irq, up);
|
||||
}
|
||||
|
||||
static int nwpserial_verify_port(struct uart_port *port,
|
||||
struct serial_struct *ser)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const char *nwpserial_type(struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_NWPSERIAL ? "nwpserial" : NULL;
|
||||
}
|
||||
|
||||
static void nwpserial_set_termios(struct uart_port *port,
|
||||
struct ktermios *termios, struct ktermios *old)
|
||||
{
|
||||
struct nwpserial_port *up;
|
||||
up = container_of(port, struct nwpserial_port, port);
|
||||
|
||||
up->port.read_status_mask = NWPSERIAL_STATUS_RXVALID
|
||||
| NWPSERIAL_STATUS_TXFULL;
|
||||
|
||||
up->port.ignore_status_mask = 0;
|
||||
/* ignore all characters if CREAD is not set */
|
||||
if ((termios->c_cflag & CREAD) == 0)
|
||||
up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID;
|
||||
|
||||
/* Copy back the old hardware settings */
|
||||
if (old)
|
||||
tty_termios_copy_hw(termios, old);
|
||||
}
|
||||
|
||||
static void nwpserial_break_ctl(struct uart_port *port, int ctl)
|
||||
{
|
||||
/* N/A */
|
||||
}
|
||||
|
||||
static void nwpserial_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct nwpserial_port *up;
|
||||
up = container_of(port, struct nwpserial_port, port);
|
||||
/* don't forward any more data (like !CREAD) */
|
||||
up->port.ignore_status_mask = NWPSERIAL_STATUS_RXVALID;
|
||||
}
|
||||
|
||||
static void nwpserial_putchar(struct nwpserial_port *up, unsigned char c)
|
||||
{
|
||||
/* check if tx buffer is full */
|
||||
wait_for_bits(up, UART_LSR_THRE);
|
||||
dcr_write(up->dcr_host, UART_TX, c);
|
||||
up->port.icount.tx++;
|
||||
}
|
||||
|
||||
static void nwpserial_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct nwpserial_port *up;
|
||||
struct circ_buf *xmit;
|
||||
up = container_of(port, struct nwpserial_port, port);
|
||||
xmit = &up->port.state->xmit;
|
||||
|
||||
if (port->x_char) {
|
||||
nwpserial_putchar(up, up->port.x_char);
|
||||
port->x_char = 0;
|
||||
}
|
||||
|
||||
while (!(uart_circ_empty(xmit) || uart_tx_stopped(&up->port))) {
|
||||
nwpserial_putchar(up, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int nwpserial_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nwpserial_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
/* N/A */
|
||||
}
|
||||
|
||||
static void nwpserial_stop_tx(struct uart_port *port)
|
||||
{
|
||||
/* N/A */
|
||||
}
|
||||
|
||||
static unsigned int nwpserial_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct nwpserial_port *up;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
up = container_of(port, struct nwpserial_port, port);
|
||||
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
ret = dcr_read(up->dcr_host, UART_LSR);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
|
||||
return ret & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
static struct uart_ops nwpserial_pops = {
|
||||
.tx_empty = nwpserial_tx_empty,
|
||||
.set_mctrl = nwpserial_set_mctrl,
|
||||
.get_mctrl = nwpserial_get_mctrl,
|
||||
.stop_tx = nwpserial_stop_tx,
|
||||
.start_tx = nwpserial_start_tx,
|
||||
.stop_rx = nwpserial_stop_rx,
|
||||
.break_ctl = nwpserial_break_ctl,
|
||||
.startup = nwpserial_startup,
|
||||
.shutdown = nwpserial_shutdown,
|
||||
.set_termios = nwpserial_set_termios,
|
||||
.type = nwpserial_type,
|
||||
.release_port = nwpserial_release_port,
|
||||
.request_port = nwpserial_request_port,
|
||||
.config_port = nwpserial_config_port,
|
||||
.verify_port = nwpserial_verify_port,
|
||||
};
|
||||
|
||||
static struct uart_driver nwpserial_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "nwpserial",
|
||||
.dev_name = "ttySQ",
|
||||
.major = TTY_MAJOR,
|
||||
.minor = 68,
|
||||
.nr = NWPSERIAL_NR,
|
||||
.cons = NWPSERIAL_CONSOLE,
|
||||
};
|
||||
|
||||
int nwpserial_register_port(struct uart_port *port)
|
||||
{
|
||||
struct nwpserial_port *up = NULL;
|
||||
int ret = -1;
|
||||
int i;
|
||||
static int first = 1;
|
||||
int dcr_len;
|
||||
int dcr_base;
|
||||
struct device_node *dn;
|
||||
|
||||
mutex_lock(&nwpserial_mutex);
|
||||
|
||||
dn = port->dev->of_node;
|
||||
if (dn == NULL)
|
||||
goto out;
|
||||
|
||||
/* get dcr base. */
|
||||
dcr_base = dcr_resource_start(dn, 0);
|
||||
|
||||
/* find matching entry */
|
||||
for (i = 0; i < NWPSERIAL_NR; i++)
|
||||
if (nwpserial_ports[i].port.iobase == dcr_base) {
|
||||
up = &nwpserial_ports[i];
|
||||
break;
|
||||
}
|
||||
|
||||
/* we didn't find a mtching entry, search for a free port */
|
||||
if (up == NULL)
|
||||
for (i = 0; i < NWPSERIAL_NR; i++)
|
||||
if (nwpserial_ports[i].port.type == PORT_UNKNOWN &&
|
||||
nwpserial_ports[i].port.iobase == 0) {
|
||||
up = &nwpserial_ports[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (up == NULL) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (first)
|
||||
uart_register_driver(&nwpserial_reg);
|
||||
first = 0;
|
||||
|
||||
up->port.membase = port->membase;
|
||||
up->port.irq = port->irq;
|
||||
up->port.uartclk = port->uartclk;
|
||||
up->port.fifosize = port->fifosize;
|
||||
up->port.regshift = port->regshift;
|
||||
up->port.iotype = port->iotype;
|
||||
up->port.flags = port->flags;
|
||||
up->port.mapbase = port->mapbase;
|
||||
up->port.private_data = port->private_data;
|
||||
|
||||
if (port->dev)
|
||||
up->port.dev = port->dev;
|
||||
|
||||
if (up->port.iobase != dcr_base) {
|
||||
up->port.ops = &nwpserial_pops;
|
||||
up->port.fifosize = 16;
|
||||
|
||||
spin_lock_init(&up->port.lock);
|
||||
|
||||
up->port.iobase = dcr_base;
|
||||
dcr_len = dcr_resource_len(dn, 0);
|
||||
|
||||
up->dcr_host = dcr_map(dn, dcr_base, dcr_len);
|
||||
if (!DCR_MAP_OK(up->dcr_host)) {
|
||||
printk(KERN_ERR "Cannot map DCR resources for NWPSERIAL");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = uart_add_one_port(&nwpserial_reg, &up->port);
|
||||
if (ret == 0)
|
||||
ret = up->port.line;
|
||||
|
||||
out:
|
||||
mutex_unlock(&nwpserial_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(nwpserial_register_port);
|
||||
|
||||
void nwpserial_unregister_port(int line)
|
||||
{
|
||||
struct nwpserial_port *up = &nwpserial_ports[line];
|
||||
mutex_lock(&nwpserial_mutex);
|
||||
uart_remove_one_port(&nwpserial_reg, &up->port);
|
||||
|
||||
up->port.type = PORT_UNKNOWN;
|
||||
|
||||
mutex_unlock(&nwpserial_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(nwpserial_unregister_port);
|
||||
|
||||
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
|
||||
static int __init nwpserial_console_init(void)
|
||||
{
|
||||
struct nwpserial_port *up = NULL;
|
||||
struct device_node *dn;
|
||||
const char *name;
|
||||
int dcr_base;
|
||||
int dcr_len;
|
||||
int i;
|
||||
|
||||
/* search for a free port */
|
||||
for (i = 0; i < NWPSERIAL_NR; i++)
|
||||
if (nwpserial_ports[i].port.type == PORT_UNKNOWN) {
|
||||
up = &nwpserial_ports[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (up == NULL)
|
||||
return -1;
|
||||
|
||||
name = of_get_property(of_chosen, "linux,stdout-path", NULL);
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
|
||||
dn = of_find_node_by_path(name);
|
||||
if (!dn)
|
||||
return -1;
|
||||
|
||||
spin_lock_init(&up->port.lock);
|
||||
up->port.ops = &nwpserial_pops;
|
||||
up->port.type = PORT_NWPSERIAL;
|
||||
up->port.fifosize = 16;
|
||||
|
||||
dcr_base = dcr_resource_start(dn, 0);
|
||||
dcr_len = dcr_resource_len(dn, 0);
|
||||
up->port.iobase = dcr_base;
|
||||
|
||||
up->dcr_host = dcr_map(dn, dcr_base, dcr_len);
|
||||
if (!DCR_MAP_OK(up->dcr_host)) {
|
||||
printk("Cannot map DCR resources for SERIAL");
|
||||
return -1;
|
||||
}
|
||||
register_console(&nwpserial_console);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(nwpserial_console_init);
|
||||
#endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
|
@ -1165,7 +1165,7 @@ serial_omap_type(struct uart_port *port)
|
||||
|
||||
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
||||
|
||||
static inline void wait_for_xmitr(struct uart_omap_port *up)
|
||||
static void wait_for_xmitr(struct uart_omap_port *up)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
|
@ -603,7 +603,7 @@ static struct uart_driver serial_pxa_reg;
|
||||
/*
|
||||
* Wait for transmitter & holding register to empty
|
||||
*/
|
||||
static inline void wait_for_xmitr(struct uart_pxa_port *up)
|
||||
static void wait_for_xmitr(struct uart_pxa_port *up)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
|
@ -389,6 +389,13 @@ static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
|
||||
const u8 line = sc16is7xx_line(port);
|
||||
u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line;
|
||||
|
||||
/*
|
||||
* Don't send zero-length data, at least on SPI it confuses the chip
|
||||
* delivering wrong TXLVL data.
|
||||
*/
|
||||
if (unlikely(!to_send))
|
||||
return;
|
||||
|
||||
regcache_cache_bypass(s->regmap, true);
|
||||
regmap_raw_write(s->regmap, addr, s->buf, to_send);
|
||||
regcache_cache_bypass(s->regmap, false);
|
||||
@ -630,6 +637,12 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
|
||||
if (likely(to_send)) {
|
||||
/* Limit to size of TX FIFO */
|
||||
txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG);
|
||||
if (txlen > SC16IS7XX_FIFO_SIZE) {
|
||||
dev_err_ratelimited(port->dev,
|
||||
"chip reports %d free bytes in TX fifo, but it only has %d",
|
||||
txlen, SC16IS7XX_FIFO_SIZE);
|
||||
txlen = 0;
|
||||
}
|
||||
to_send = (to_send > txlen) ? txlen : to_send;
|
||||
|
||||
/* Add data to send */
|
||||
|
@ -110,7 +110,7 @@ static void uart_start(struct tty_struct *tty)
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -1818,8 +1818,8 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
|
||||
* @options: ptr for <options> field; NULL if not present (out)
|
||||
*
|
||||
* Decodes earlycon kernel command line parameters of the form
|
||||
* earlycon=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options>
|
||||
* console=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options>
|
||||
* earlycon=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
|
||||
* console=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
|
||||
*
|
||||
* The optional form
|
||||
* earlycon=<name>,0x<addr>,<options>
|
||||
@ -1834,6 +1834,9 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
|
||||
if (strncmp(p, "mmio,", 5) == 0) {
|
||||
*iotype = UPIO_MEM;
|
||||
p += 5;
|
||||
} else if (strncmp(p, "mmio16,", 7) == 0) {
|
||||
*iotype = UPIO_MEM16;
|
||||
p += 7;
|
||||
} else if (strncmp(p, "mmio32,", 7) == 0) {
|
||||
*iotype = UPIO_MEM32;
|
||||
p += 7;
|
||||
@ -2186,6 +2189,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
|
||||
"I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
|
||||
break;
|
||||
case UPIO_MEM:
|
||||
case UPIO_MEM16:
|
||||
case UPIO_MEM32:
|
||||
case UPIO_MEM32BE:
|
||||
case UPIO_AU:
|
||||
@ -2831,6 +2835,7 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
|
||||
return (port1->iobase == port2->iobase) &&
|
||||
(port1->hub6 == port2->hub6);
|
||||
case UPIO_MEM:
|
||||
case UPIO_MEM16:
|
||||
case UPIO_MEM32:
|
||||
case UPIO_MEM32BE:
|
||||
case UPIO_AU:
|
||||
|
@ -193,6 +193,7 @@ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
|
||||
|
||||
return gpios;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mctrl_gpio_init);
|
||||
|
||||
void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
|
||||
{
|
||||
@ -247,3 +248,4 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
|
||||
disable_irq(gpios->irq[i]);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms);
|
||||
|
@ -2,6 +2,7 @@
|
||||
* SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
|
||||
*
|
||||
* Copyright (C) 2002 - 2011 Paul Mundt
|
||||
* Copyright (C) 2015 Glider bvba
|
||||
* Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
|
||||
*
|
||||
* based off of the old drivers/char/sh-sci.c by:
|
||||
@ -38,7 +39,6 @@
|
||||
#include <linux/major.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
@ -76,6 +76,14 @@ enum {
|
||||
((port)->irqs[SCIx_ERI_IRQ] && \
|
||||
((port)->irqs[SCIx_RXI_IRQ] < 0))
|
||||
|
||||
enum SCI_CLKS {
|
||||
SCI_FCK, /* Functional Clock */
|
||||
SCI_SCK, /* Optional External Clock */
|
||||
SCI_BRG_INT, /* Optional BRG Internal Clock Source */
|
||||
SCI_SCIF_CLK, /* Optional BRG External Clock Source */
|
||||
SCI_NUM_CLKS
|
||||
};
|
||||
|
||||
struct sci_port {
|
||||
struct uart_port port;
|
||||
|
||||
@ -92,10 +100,9 @@ struct sci_port {
|
||||
struct timer_list break_timer;
|
||||
int break_flag;
|
||||
|
||||
/* Interface clock */
|
||||
struct clk *iclk;
|
||||
/* Function clock */
|
||||
struct clk *fclk;
|
||||
/* Clocks */
|
||||
struct clk *clks[SCI_NUM_CLKS];
|
||||
unsigned long clk_rates[SCI_NUM_CLKS];
|
||||
|
||||
int irqs[SCIx_NR_IRQS];
|
||||
char *irqstr[SCIx_NR_IRQS];
|
||||
@ -116,8 +123,6 @@ struct sci_port {
|
||||
struct timer_list rx_timer;
|
||||
unsigned int rx_timeout;
|
||||
#endif
|
||||
|
||||
struct notifier_block freq_transition;
|
||||
};
|
||||
|
||||
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
|
||||
@ -163,6 +168,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -185,6 +192,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -206,6 +215,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = { 0x30, 16 },
|
||||
[SCPDR] = { 0x34, 16 },
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -227,6 +238,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = { 0x30, 16 },
|
||||
[SCPDR] = { 0x34, 16 },
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -249,6 +262,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -270,6 +285,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -291,6 +308,32 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
* Common SCIF definitions for ports with a Baud Rate Generator for
|
||||
* External Clock (BRG).
|
||||
*/
|
||||
[SCIx_SH4_SCIF_BRG_REGTYPE] = {
|
||||
[SCSMR] = { 0x00, 16 },
|
||||
[SCBRR] = { 0x04, 8 },
|
||||
[SCSCR] = { 0x08, 16 },
|
||||
[SCxTDR] = { 0x0c, 8 },
|
||||
[SCxSR] = { 0x10, 16 },
|
||||
[SCxRDR] = { 0x14, 8 },
|
||||
[SCFCR] = { 0x18, 16 },
|
||||
[SCFDR] = { 0x1c, 16 },
|
||||
[SCTFDR] = sci_reg_invalid,
|
||||
[SCRFDR] = sci_reg_invalid,
|
||||
[SCSPTR] = { 0x20, 16 },
|
||||
[SCLSR] = { 0x24, 16 },
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = { 0x30, 16 },
|
||||
[SCCKS] = { 0x34, 16 },
|
||||
},
|
||||
|
||||
/*
|
||||
@ -312,6 +355,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = { 0x40, 16 },
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = { 0x30, 16 },
|
||||
[SCCKS] = { 0x34, 16 },
|
||||
},
|
||||
|
||||
/*
|
||||
@ -334,6 +379,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -356,6 +403,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -378,6 +427,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
|
||||
[HSSRR] = sci_reg_invalid,
|
||||
[SCPCR] = sci_reg_invalid,
|
||||
[SCPDR] = sci_reg_invalid,
|
||||
[SCDL] = sci_reg_invalid,
|
||||
[SCCKS] = sci_reg_invalid,
|
||||
},
|
||||
};
|
||||
|
||||
@ -452,18 +503,24 @@ static int sci_probe_regmap(struct plat_sci_port *cfg)
|
||||
|
||||
static void sci_port_enable(struct sci_port *sci_port)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!sci_port->port.dev)
|
||||
return;
|
||||
|
||||
pm_runtime_get_sync(sci_port->port.dev);
|
||||
|
||||
clk_prepare_enable(sci_port->iclk);
|
||||
sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
|
||||
clk_prepare_enable(sci_port->fclk);
|
||||
for (i = 0; i < SCI_NUM_CLKS; i++) {
|
||||
clk_prepare_enable(sci_port->clks[i]);
|
||||
sci_port->clk_rates[i] = clk_get_rate(sci_port->clks[i]);
|
||||
}
|
||||
sci_port->port.uartclk = sci_port->clk_rates[SCI_FCK];
|
||||
}
|
||||
|
||||
static void sci_port_disable(struct sci_port *sci_port)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!sci_port->port.dev)
|
||||
return;
|
||||
|
||||
@ -475,8 +532,8 @@ static void sci_port_disable(struct sci_port *sci_port)
|
||||
del_timer_sync(&sci_port->break_timer);
|
||||
sci_port->break_flag = 0;
|
||||
|
||||
clk_disable_unprepare(sci_port->fclk);
|
||||
clk_disable_unprepare(sci_port->iclk);
|
||||
for (i = SCI_NUM_CLKS; i-- > 0; )
|
||||
clk_disable_unprepare(sci_port->clks[i]);
|
||||
|
||||
pm_runtime_put_sync(sci_port->port.dev);
|
||||
}
|
||||
@ -1606,29 +1663,6 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we define a transition notifier so that we can update all of our
|
||||
* ports' baud rate when the peripheral clock changes.
|
||||
*/
|
||||
static int sci_notifier(struct notifier_block *self,
|
||||
unsigned long phase, void *p)
|
||||
{
|
||||
struct sci_port *sci_port;
|
||||
unsigned long flags;
|
||||
|
||||
sci_port = container_of(self, struct sci_port, freq_transition);
|
||||
|
||||
if (phase == CPUFREQ_POSTCHANGE) {
|
||||
struct uart_port *port = &sci_port->port;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
port->uartclk = clk_get_rate(sci_port->iclk);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static const struct sci_irq_desc {
|
||||
const char *desc;
|
||||
irq_handler_t handler;
|
||||
@ -1864,90 +1898,149 @@ static void sci_shutdown(struct uart_port *port)
|
||||
sci_free_irq(s);
|
||||
}
|
||||
|
||||
static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
|
||||
unsigned long freq)
|
||||
static int sci_sck_calc(struct sci_port *s, unsigned int bps,
|
||||
unsigned int *srr)
|
||||
{
|
||||
if (s->sampling_rate)
|
||||
return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1;
|
||||
unsigned long freq = s->clk_rates[SCI_SCK];
|
||||
unsigned int min_sr, max_sr, sr;
|
||||
int err, min_err = INT_MAX;
|
||||
|
||||
/* Warn, but use a safe default */
|
||||
WARN_ON(1);
|
||||
if (s->sampling_rate) {
|
||||
/* SCI(F) has a fixed sampling rate */
|
||||
min_sr = max_sr = s->sampling_rate / 2;
|
||||
} else {
|
||||
/* HSCIF has a variable 1/(8..32) sampling rate */
|
||||
min_sr = 8;
|
||||
max_sr = 32;
|
||||
}
|
||||
|
||||
return ((freq + 16 * bps) / (32 * bps) - 1);
|
||||
for (sr = max_sr; sr >= min_sr; sr--) {
|
||||
err = DIV_ROUND_CLOSEST(freq, sr) - bps;
|
||||
if (abs(err) >= abs(min_err))
|
||||
continue;
|
||||
|
||||
min_err = err;
|
||||
*srr = sr - 1;
|
||||
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(s->port.dev, "SCK: %u%+d bps using SR %u\n", bps, min_err,
|
||||
*srr + 1);
|
||||
return min_err;
|
||||
}
|
||||
|
||||
/* calculate frame length from SMR */
|
||||
static int sci_baud_calc_frame_len(unsigned int smr_val)
|
||||
static int sci_brg_calc(struct sci_port *s, unsigned int bps,
|
||||
unsigned long freq, unsigned int *dlr,
|
||||
unsigned int *srr)
|
||||
{
|
||||
int len = 10;
|
||||
unsigned int min_sr, max_sr, sr, dl;
|
||||
int err, min_err = INT_MAX;
|
||||
|
||||
if (smr_val & SCSMR_CHR)
|
||||
len--;
|
||||
if (smr_val & SCSMR_PE)
|
||||
len++;
|
||||
if (smr_val & SCSMR_STOP)
|
||||
len++;
|
||||
if (s->sampling_rate) {
|
||||
/* SCIF has a fixed sampling rate */
|
||||
min_sr = max_sr = s->sampling_rate / 2;
|
||||
} else {
|
||||
/* HSCIF has a variable 1/(8..32) sampling rate */
|
||||
min_sr = 8;
|
||||
max_sr = 32;
|
||||
}
|
||||
|
||||
return len;
|
||||
for (sr = max_sr; sr >= min_sr; sr--) {
|
||||
dl = DIV_ROUND_CLOSEST(freq, sr * bps);
|
||||
dl = clamp(dl, 1U, 65535U);
|
||||
|
||||
err = DIV_ROUND_CLOSEST(freq, sr * dl) - bps;
|
||||
if (abs(err) >= abs(min_err))
|
||||
continue;
|
||||
|
||||
min_err = err;
|
||||
*dlr = dl;
|
||||
*srr = sr - 1;
|
||||
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(s->port.dev, "BRG: %u%+d bps using DL %u SR %u\n", bps,
|
||||
min_err, *dlr, *srr + 1);
|
||||
return min_err;
|
||||
}
|
||||
|
||||
|
||||
/* calculate sample rate, BRR, and clock select for HSCIF */
|
||||
static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
|
||||
int *brr, unsigned int *srr,
|
||||
unsigned int *cks, int frame_len)
|
||||
/* calculate sample rate, BRR, and clock select */
|
||||
static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
|
||||
unsigned int *brr, unsigned int *srr,
|
||||
unsigned int *cks)
|
||||
{
|
||||
int sr, c, br, err, recv_margin;
|
||||
int min_err = 1000; /* 100% */
|
||||
int recv_max_margin = 0;
|
||||
unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c;
|
||||
unsigned long freq = s->clk_rates[SCI_FCK];
|
||||
int err, min_err = INT_MAX;
|
||||
|
||||
/* Find the combination of sample rate and clock select with the
|
||||
smallest deviation from the desired baud rate. */
|
||||
for (sr = 8; sr <= 32; sr++) {
|
||||
if (s->sampling_rate) {
|
||||
min_sr = max_sr = s->sampling_rate;
|
||||
shift = 0;
|
||||
} else {
|
||||
/* HSCIF has a variable sample rate */
|
||||
min_sr = 8;
|
||||
max_sr = 32;
|
||||
shift = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the combination of sample rate and clock select with the
|
||||
* smallest deviation from the desired baud rate.
|
||||
* Prefer high sample rates to maximise the receive 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.
|
||||
*/
|
||||
for (sr = max_sr; sr >= min_sr; sr--) {
|
||||
for (c = 0; c <= 3; c++) {
|
||||
/* integerized formulas from HSCIF documentation */
|
||||
br = DIV_ROUND_CLOSEST(freq, (sr *
|
||||
(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;
|
||||
/* 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
|
||||
prediv = sr * (1 << (2 * c + shift));
|
||||
|
||||
/*
|
||||
* We need to calculate:
|
||||
*
|
||||
* 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.
|
||||
* br = freq / (prediv * bps) clamped to [1..256]
|
||||
* err = freq / (br * prediv) - bps
|
||||
*
|
||||
* Watch out for overflow when calculating the desired
|
||||
* sampling clock rate!
|
||||
*/
|
||||
recv_margin = abs((500 -
|
||||
DIV_ROUND_CLOSEST(1000, sr << 1)) / 10);
|
||||
if (abs(min_err) > abs(err)) {
|
||||
min_err = err;
|
||||
recv_max_margin = recv_margin;
|
||||
} else if ((min_err == err) &&
|
||||
(recv_margin > recv_max_margin))
|
||||
recv_max_margin = recv_margin;
|
||||
else
|
||||
if (bps > UINT_MAX / prediv)
|
||||
break;
|
||||
|
||||
scrate = prediv * bps;
|
||||
br = DIV_ROUND_CLOSEST(freq, scrate);
|
||||
br = clamp(br, 1U, 256U);
|
||||
|
||||
err = DIV_ROUND_CLOSEST(freq, br * prediv) - bps;
|
||||
if (abs(err) >= abs(min_err))
|
||||
continue;
|
||||
|
||||
*brr = br;
|
||||
min_err = err;
|
||||
*brr = br - 1;
|
||||
*srr = sr - 1;
|
||||
*cks = c;
|
||||
|
||||
if (!err)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
if (min_err == 1000) {
|
||||
WARN_ON(1);
|
||||
/* use defaults */
|
||||
*brr = 255;
|
||||
*srr = 15;
|
||||
*cks = 0;
|
||||
}
|
||||
found:
|
||||
dev_dbg(s->port.dev, "BRR: %u%+d bps using N %u SR %u cks %u\n", bps,
|
||||
min_err, *brr, *srr + 1, *cks);
|
||||
return min_err;
|
||||
}
|
||||
|
||||
static void sci_reset(struct uart_port *port)
|
||||
@ -1969,11 +2062,14 @@ static void sci_reset(struct uart_port *port)
|
||||
static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned int baud, smr_val = 0, scr_val = 0, i;
|
||||
unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0;
|
||||
unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0;
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
const struct plat_sci_reg *reg;
|
||||
unsigned int baud, smr_val = 0, max_baud, cks = 0;
|
||||
int t = -1;
|
||||
unsigned int srr = 15;
|
||||
int min_err = INT_MAX, err;
|
||||
unsigned long max_freq = 0;
|
||||
int best_clk = -1;
|
||||
|
||||
if ((termios->c_cflag & CSIZE) == CS7)
|
||||
smr_val |= SCSMR_CHR;
|
||||
@ -1992,41 +2088,123 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
* that the previous boot loader has enabled required clocks and
|
||||
* setup the baud rate generator hardware for us already.
|
||||
*/
|
||||
max_baud = port->uartclk ? port->uartclk / 16 : 115200;
|
||||
if (!port->uartclk) {
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, 115200);
|
||||
goto done;
|
||||
}
|
||||
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
|
||||
if (likely(baud && port->uartclk)) {
|
||||
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,
|
||||
&cks, frame_len);
|
||||
} else {
|
||||
t = sci_scbrr_calc(s, baud, port->uartclk);
|
||||
for (cks = 0; t >= 256 && cks <= 3; cks++)
|
||||
t >>= 2;
|
||||
for (i = 0; i < SCI_NUM_CLKS; i++)
|
||||
max_freq = max(max_freq, s->clk_rates[i]);
|
||||
|
||||
baud = uart_get_baud_rate(port, termios, old, 0,
|
||||
max_freq / max(s->sampling_rate, 8U));
|
||||
if (!baud)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* There can be multiple sources for the sampling clock. Find the one
|
||||
* that gives us the smallest deviation from the desired baud rate.
|
||||
*/
|
||||
|
||||
/* Optional Undivided External Clock */
|
||||
if (s->clk_rates[SCI_SCK] && port->type != PORT_SCIFA &&
|
||||
port->type != PORT_SCIFB) {
|
||||
err = sci_sck_calc(s, baud, &srr1);
|
||||
if (abs(err) < abs(min_err)) {
|
||||
best_clk = SCI_SCK;
|
||||
scr_val = SCSCR_CKE1;
|
||||
sccks = SCCKS_CKS;
|
||||
min_err = err;
|
||||
srr = srr1;
|
||||
if (!err)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Optional BRG Frequency Divided External Clock */
|
||||
if (s->clk_rates[SCI_SCIF_CLK] && sci_getreg(port, SCDL)->size) {
|
||||
err = sci_brg_calc(s, baud, s->clk_rates[SCI_SCIF_CLK], &dl1,
|
||||
&srr1);
|
||||
if (abs(err) < abs(min_err)) {
|
||||
best_clk = SCI_SCIF_CLK;
|
||||
scr_val = SCSCR_CKE1;
|
||||
sccks = 0;
|
||||
min_err = err;
|
||||
dl = dl1;
|
||||
srr = srr1;
|
||||
if (!err)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Optional BRG Frequency Divided Internal Clock */
|
||||
if (s->clk_rates[SCI_BRG_INT] && sci_getreg(port, SCDL)->size) {
|
||||
err = sci_brg_calc(s, baud, s->clk_rates[SCI_BRG_INT], &dl1,
|
||||
&srr1);
|
||||
if (abs(err) < abs(min_err)) {
|
||||
best_clk = SCI_BRG_INT;
|
||||
scr_val = SCSCR_CKE1;
|
||||
sccks = SCCKS_XIN;
|
||||
min_err = err;
|
||||
dl = dl1;
|
||||
srr = srr1;
|
||||
if (!min_err)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Divided Functional Clock using standard Bit Rate Register */
|
||||
err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1);
|
||||
if (abs(err) < abs(min_err)) {
|
||||
best_clk = SCI_FCK;
|
||||
scr_val = 0;
|
||||
min_err = err;
|
||||
brr = brr1;
|
||||
srr = srr1;
|
||||
cks = cks1;
|
||||
}
|
||||
|
||||
done:
|
||||
if (best_clk >= 0)
|
||||
dev_dbg(port->dev, "Using clk %pC for %u%+d bps\n",
|
||||
s->clks[best_clk], baud, min_err);
|
||||
|
||||
sci_port_enable(s);
|
||||
|
||||
/*
|
||||
* Program the optional External Baud Rate Generator (BRG) first.
|
||||
* It controls the mux to select (H)SCK or frequency divided clock.
|
||||
*/
|
||||
if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) {
|
||||
serial_port_out(port, SCDL, dl);
|
||||
serial_port_out(port, SCCKS, sccks);
|
||||
}
|
||||
|
||||
sci_reset(port);
|
||||
|
||||
smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS;
|
||||
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
dev_dbg(port->dev, "%s: SMR %x, cks %x, t %x, SCSCR %x\n",
|
||||
__func__, smr_val, cks, t, s->cfg->scscr);
|
||||
|
||||
if (t >= 0) {
|
||||
serial_port_out(port, SCSMR, (smr_val & ~SCSMR_CKS) | cks);
|
||||
serial_port_out(port, SCBRR, t);
|
||||
reg = sci_getreg(port, HSSRR);
|
||||
if (reg->size)
|
||||
serial_port_out(port, HSSRR, srr | HSCIF_SRE);
|
||||
udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
|
||||
} else
|
||||
if (best_clk >= 0) {
|
||||
smr_val |= cks;
|
||||
dev_dbg(port->dev,
|
||||
"SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n",
|
||||
scr_val, smr_val, brr, sccks, dl, srr);
|
||||
serial_port_out(port, SCSCR, scr_val);
|
||||
serial_port_out(port, SCSMR, smr_val);
|
||||
serial_port_out(port, SCBRR, brr);
|
||||
if (sci_getreg(port, HSSRR)->size)
|
||||
serial_port_out(port, HSSRR, srr | HSCIF_SRE);
|
||||
|
||||
/* Wait one bit interval */
|
||||
udelay((1000000 + (baud - 1)) / baud);
|
||||
} else {
|
||||
/* Don't touch the bit rate configuration */
|
||||
scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0);
|
||||
smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS;
|
||||
dev_dbg(port->dev, "SCR 0x%x SMR 0x%x\n", scr_val, smr_val);
|
||||
serial_port_out(port, SCSCR, scr_val);
|
||||
serial_port_out(port, SCSMR, smr_val);
|
||||
}
|
||||
|
||||
sci_init_pins(port, termios->c_cflag);
|
||||
|
||||
@ -2051,7 +2229,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
serial_port_out(port, SCFCR, ctrl);
|
||||
}
|
||||
|
||||
serial_port_out(port, SCSCR, s->cfg->scscr);
|
||||
scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0);
|
||||
dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val);
|
||||
serial_port_out(port, SCSCR, scr_val);
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
/*
|
||||
@ -2241,6 +2421,63 @@ static struct uart_ops sci_uart_ops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
|
||||
{
|
||||
const char *clk_names[] = {
|
||||
[SCI_FCK] = "fck",
|
||||
[SCI_SCK] = "sck",
|
||||
[SCI_BRG_INT] = "brg_int",
|
||||
[SCI_SCIF_CLK] = "scif_clk",
|
||||
};
|
||||
struct clk *clk;
|
||||
unsigned int i;
|
||||
|
||||
if (sci_port->cfg->type == PORT_HSCIF)
|
||||
clk_names[SCI_SCK] = "hsck";
|
||||
|
||||
for (i = 0; i < SCI_NUM_CLKS; i++) {
|
||||
clk = devm_clk_get(dev, clk_names[i]);
|
||||
if (PTR_ERR(clk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
if (IS_ERR(clk) && i == SCI_FCK) {
|
||||
/*
|
||||
* "fck" used to be called "sci_ick", and we need to
|
||||
* maintain DT backward compatibility.
|
||||
*/
|
||||
clk = devm_clk_get(dev, "sci_ick");
|
||||
if (PTR_ERR(clk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
if (!IS_ERR(clk))
|
||||
goto found;
|
||||
|
||||
/*
|
||||
* Not all SH platforms declare a clock lookup entry
|
||||
* for SCI devices, in which case we need to get the
|
||||
* global "peripheral_clk" clock.
|
||||
*/
|
||||
clk = devm_clk_get(dev, "peripheral_clk");
|
||||
if (!IS_ERR(clk))
|
||||
goto found;
|
||||
|
||||
dev_err(dev, "failed to get %s (%ld)\n", clk_names[i],
|
||||
PTR_ERR(clk));
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
found:
|
||||
if (IS_ERR(clk))
|
||||
dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i],
|
||||
PTR_ERR(clk));
|
||||
else
|
||||
dev_dbg(dev, "clk %s is %pC rate %pCr\n", clk_names[i],
|
||||
clk, clk);
|
||||
sci_port->clks[i] = IS_ERR(clk) ? NULL : clk;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sci_init_single(struct platform_device *dev,
|
||||
struct sci_port *sci_port, unsigned int index,
|
||||
struct plat_sci_port *p, bool early)
|
||||
@ -2333,22 +2570,9 @@ static int sci_init_single(struct platform_device *dev,
|
||||
sci_port->sampling_rate = p->sampling_rate;
|
||||
|
||||
if (!early) {
|
||||
sci_port->iclk = clk_get(&dev->dev, "sci_ick");
|
||||
if (IS_ERR(sci_port->iclk)) {
|
||||
sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
|
||||
if (IS_ERR(sci_port->iclk)) {
|
||||
dev_err(&dev->dev, "can't get iclk\n");
|
||||
return PTR_ERR(sci_port->iclk);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The function clock is optional, ignore it if we can't
|
||||
* find it.
|
||||
*/
|
||||
sci_port->fclk = clk_get(&dev->dev, "sci_fck");
|
||||
if (IS_ERR(sci_port->fclk))
|
||||
sci_port->fclk = NULL;
|
||||
ret = sci_init_clocks(sci_port, &dev->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
port->dev = &dev->dev;
|
||||
|
||||
@ -2405,9 +2629,6 @@ static int sci_init_single(struct platform_device *dev,
|
||||
|
||||
static void sci_cleanup_single(struct sci_port *port)
|
||||
{
|
||||
clk_put(port->iclk);
|
||||
clk_put(port->fclk);
|
||||
|
||||
pm_runtime_disable(port->port.dev);
|
||||
}
|
||||
|
||||
@ -2426,7 +2647,7 @@ static void serial_console_write(struct console *co, const char *s,
|
||||
{
|
||||
struct sci_port *sci_port = &sci_ports[co->index];
|
||||
struct uart_port *port = &sci_port->port;
|
||||
unsigned short bits, ctrl;
|
||||
unsigned short bits, ctrl, ctrl_temp;
|
||||
unsigned long flags;
|
||||
int locked = 1;
|
||||
|
||||
@ -2438,9 +2659,11 @@ static void serial_console_write(struct console *co, const char *s,
|
||||
else
|
||||
spin_lock(&port->lock);
|
||||
|
||||
/* first save the SCSCR then disable the interrupts */
|
||||
/* first save SCSCR then disable interrupts, keep clock source */
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
serial_port_out(port, SCSCR, sci_port->cfg->scscr);
|
||||
ctrl_temp = (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) |
|
||||
(ctrl & (SCSCR_CKE1 | SCSCR_CKE0));
|
||||
serial_port_out(port, SCSCR, ctrl_temp);
|
||||
|
||||
uart_console_write(port, s, count, serial_console_putchar);
|
||||
|
||||
@ -2559,9 +2782,6 @@ static int sci_remove(struct platform_device *dev)
|
||||
{
|
||||
struct sci_port *port = platform_get_drvdata(dev);
|
||||
|
||||
cpufreq_unregister_notifier(&port->freq_transition,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
|
||||
uart_remove_one_port(&sci_uart_driver, &port->port);
|
||||
|
||||
sci_cleanup_single(port);
|
||||
@ -2569,42 +2789,44 @@ static int sci_remove(struct platform_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sci_port_info {
|
||||
unsigned int type;
|
||||
unsigned int regtype;
|
||||
};
|
||||
|
||||
#define SCI_OF_DATA(type, regtype) (void *)((type) << 16 | (regtype))
|
||||
#define SCI_OF_TYPE(data) ((unsigned long)(data) >> 16)
|
||||
#define SCI_OF_REGTYPE(data) ((unsigned long)(data) & 0xffff)
|
||||
|
||||
static const struct of_device_id of_sci_match[] = {
|
||||
/* SoC-specific types */
|
||||
{
|
||||
.compatible = "renesas,scif-r7s72100",
|
||||
.data = SCI_OF_DATA(PORT_SCIF, SCIx_SH2_SCIF_FIFODATA_REGTYPE),
|
||||
},
|
||||
/* Family-specific types */
|
||||
{
|
||||
.compatible = "renesas,rcar-gen1-scif",
|
||||
.data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE),
|
||||
}, {
|
||||
.compatible = "renesas,rcar-gen2-scif",
|
||||
.data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE),
|
||||
}, {
|
||||
.compatible = "renesas,rcar-gen3-scif",
|
||||
.data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE),
|
||||
},
|
||||
/* Generic types */
|
||||
{
|
||||
.compatible = "renesas,scif",
|
||||
.data = &(const struct sci_port_info) {
|
||||
.type = PORT_SCIF,
|
||||
.regtype = SCIx_SH4_SCIF_REGTYPE,
|
||||
},
|
||||
.data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_REGTYPE),
|
||||
}, {
|
||||
.compatible = "renesas,scifa",
|
||||
.data = &(const struct sci_port_info) {
|
||||
.type = PORT_SCIFA,
|
||||
.regtype = SCIx_SCIFA_REGTYPE,
|
||||
},
|
||||
.data = SCI_OF_DATA(PORT_SCIFA, SCIx_SCIFA_REGTYPE),
|
||||
}, {
|
||||
.compatible = "renesas,scifb",
|
||||
.data = &(const struct sci_port_info) {
|
||||
.type = PORT_SCIFB,
|
||||
.regtype = SCIx_SCIFB_REGTYPE,
|
||||
},
|
||||
.data = SCI_OF_DATA(PORT_SCIFB, SCIx_SCIFB_REGTYPE),
|
||||
}, {
|
||||
.compatible = "renesas,hscif",
|
||||
.data = &(const struct sci_port_info) {
|
||||
.type = PORT_HSCIF,
|
||||
.regtype = SCIx_HSCIF_REGTYPE,
|
||||
},
|
||||
.data = SCI_OF_DATA(PORT_HSCIF, SCIx_HSCIF_REGTYPE),
|
||||
}, {
|
||||
.compatible = "renesas,sci",
|
||||
.data = &(const struct sci_port_info) {
|
||||
.type = PORT_SCI,
|
||||
.regtype = SCIx_SCI_REGTYPE,
|
||||
},
|
||||
.data = SCI_OF_DATA(PORT_SCI, SCIx_SCI_REGTYPE),
|
||||
}, {
|
||||
/* Terminator */
|
||||
},
|
||||
@ -2616,24 +2838,21 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
const struct sci_port_info *info;
|
||||
struct plat_sci_port *p;
|
||||
int id;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_OF) || !np)
|
||||
return NULL;
|
||||
|
||||
match = of_match_node(of_sci_match, pdev->dev.of_node);
|
||||
match = of_match_node(of_sci_match, np);
|
||||
if (!match)
|
||||
return NULL;
|
||||
|
||||
info = match->data;
|
||||
|
||||
p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
/* Get the line number for the aliases node. */
|
||||
/* Get the line number from the aliases node. */
|
||||
id = of_alias_get_id(np, "serial");
|
||||
if (id < 0) {
|
||||
dev_err(&pdev->dev, "failed to get alias id (%d)\n", id);
|
||||
@ -2643,8 +2862,8 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
|
||||
*dev_id = id;
|
||||
|
||||
p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
|
||||
p->type = info->type;
|
||||
p->regtype = info->regtype;
|
||||
p->type = SCI_OF_TYPE(match->data);
|
||||
p->regtype = SCI_OF_REGTYPE(match->data);
|
||||
p->scscr = SCSCR_RE | SCSCR_TE;
|
||||
|
||||
return p;
|
||||
@ -2714,16 +2933,6 @@ static int sci_probe(struct platform_device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sp->freq_transition.notifier_call = sci_notifier;
|
||||
|
||||
ret = cpufreq_register_notifier(&sp->freq_transition,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
if (unlikely(ret < 0)) {
|
||||
uart_remove_one_port(&sci_uart_driver, &sp->port);
|
||||
sci_cleanup_single(sp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SH_STANDARD_BIOS
|
||||
sh_bios_gdb_detach();
|
||||
#endif
|
||||
|
@ -27,6 +27,8 @@ enum {
|
||||
HSSRR, /* Sampling Rate Register */
|
||||
SCPCR, /* Serial Port Control Register */
|
||||
SCPDR, /* Serial Port Data Register */
|
||||
SCDL, /* BRG Frequency Division Register */
|
||||
SCCKS, /* BRG Clock Select Register */
|
||||
|
||||
SCIx_NR_REGS,
|
||||
};
|
||||
@ -109,6 +111,14 @@ enum {
|
||||
#define SCPDR_RTSD BIT(4) /* Serial Port RTS Output Pin Data */
|
||||
#define SCPDR_CTSD BIT(3) /* Serial Port CTS Input Pin Data */
|
||||
|
||||
/*
|
||||
* BRG Clock Select Register (Some SCIF and HSCIF)
|
||||
* The Baud Rate Generator for external clock can provide a clock source for
|
||||
* the sampling clock. It outputs either its frequency divided clock, or the
|
||||
* (undivided) (H)SCK external clock.
|
||||
*/
|
||||
#define SCCKS_CKS BIT(15) /* Select (H)SCK (1) or divided SC_CLK (0) */
|
||||
#define SCCKS_XIN BIT(14) /* SC_CLK uses bus clock (1) or SCIF_CLK (0) */
|
||||
|
||||
#define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND)
|
||||
#define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF)
|
||||
|
@ -517,7 +517,7 @@ static struct uart_ops serial_sprd_ops = {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SERIAL_SPRD_CONSOLE
|
||||
static inline void wait_for_xmitr(struct uart_port *port)
|
||||
static void wait_for_xmitr(struct uart_port *port)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
|
@ -1262,7 +1262,7 @@ static int sunsu_kbd_ms_init(struct uart_sunsu_port *up)
|
||||
/*
|
||||
* Wait for transmitter & holding register to empty
|
||||
*/
|
||||
static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up)
|
||||
static void wait_for_xmitr(struct uart_sunsu_port *up)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
|
@ -485,7 +485,7 @@ static struct uart_driver vt8500_uart_driver;
|
||||
|
||||
#ifdef CONFIG_SERIAL_VT8500_CONSOLE
|
||||
|
||||
static inline void wait_for_xmitr(struct uart_port *port)
|
||||
static void wait_for_xmitr(struct uart_port *port)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
|
@ -89,7 +89,7 @@
|
||||
* module identification
|
||||
*/
|
||||
static char *driver_name = "SyncLink GT";
|
||||
static char *tty_driver_name = "synclink_gt";
|
||||
static char *slgt_driver_name = "synclink_gt";
|
||||
static char *tty_dev_prefix = "ttySLG";
|
||||
MODULE_LICENSE("GPL");
|
||||
#define MGSL_MAGIC 0x5401
|
||||
@ -3799,7 +3799,7 @@ static int __init slgt_init(void)
|
||||
|
||||
/* Initialize the tty_driver structure */
|
||||
|
||||
serial_driver->driver_name = tty_driver_name;
|
||||
serial_driver->driver_name = slgt_driver_name;
|
||||
serial_driver->name = tty_dev_prefix;
|
||||
serial_driver->major = ttymajor;
|
||||
serial_driver->minor_start = 64;
|
||||
|
@ -256,19 +256,24 @@ const char *tty_name(const struct tty_struct *tty)
|
||||
|
||||
EXPORT_SYMBOL(tty_name);
|
||||
|
||||
int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
|
||||
const char *tty_driver_name(const struct tty_struct *tty)
|
||||
{
|
||||
if (!tty || !tty->driver)
|
||||
return "";
|
||||
return tty->driver->name;
|
||||
}
|
||||
|
||||
static int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
|
||||
const char *routine)
|
||||
{
|
||||
#ifdef TTY_PARANOIA_CHECK
|
||||
if (!tty) {
|
||||
printk(KERN_WARNING
|
||||
"null TTY for (%d:%d) in %s\n",
|
||||
pr_warn("(%d:%d): %s: NULL tty\n",
|
||||
imajor(inode), iminor(inode), routine);
|
||||
return 1;
|
||||
}
|
||||
if (tty->magic != TTY_MAGIC) {
|
||||
printk(KERN_WARNING
|
||||
"bad magic number for tty struct (%d:%d) in %s\n",
|
||||
pr_warn("(%d:%d): %s: bad magic number\n",
|
||||
imajor(inode), iminor(inode), routine);
|
||||
return 1;
|
||||
}
|
||||
@ -293,9 +298,8 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
|
||||
tty->link && tty->link->count)
|
||||
count++;
|
||||
if (tty->count != count) {
|
||||
printk(KERN_WARNING "Warning: dev (%s) tty->count(%d) "
|
||||
"!= #fd's(%d) in %s\n",
|
||||
tty->name, tty->count, count, routine);
|
||||
tty_warn(tty, "%s: tty->count(%d) != #fd's(%d)\n",
|
||||
routine, tty->count, count);
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
@ -420,10 +424,8 @@ int __tty_check_change(struct tty_struct *tty, int sig)
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!tty_pgrp) {
|
||||
pr_warn("%s: tty_check_change: sig=%d, tty->pgrp == NULL!\n",
|
||||
tty_name(tty), sig);
|
||||
}
|
||||
if (!tty_pgrp)
|
||||
tty_warn(tty, "sig=%d, tty->pgrp == NULL!\n", sig);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -781,7 +783,7 @@ static void do_tty_hangup(struct work_struct *work)
|
||||
|
||||
void tty_hangup(struct tty_struct *tty)
|
||||
{
|
||||
tty_debug_hangup(tty, "\n");
|
||||
tty_debug_hangup(tty, "hangup\n");
|
||||
schedule_work(&tty->hangup_work);
|
||||
}
|
||||
|
||||
@ -798,7 +800,7 @@ EXPORT_SYMBOL(tty_hangup);
|
||||
|
||||
void tty_vhangup(struct tty_struct *tty)
|
||||
{
|
||||
tty_debug_hangup(tty, "\n");
|
||||
tty_debug_hangup(tty, "vhangup\n");
|
||||
__tty_hangup(tty, 0);
|
||||
}
|
||||
|
||||
@ -835,7 +837,7 @@ void tty_vhangup_self(void)
|
||||
|
||||
static void tty_vhangup_session(struct tty_struct *tty)
|
||||
{
|
||||
tty_debug_hangup(tty, "\n");
|
||||
tty_debug_hangup(tty, "session hangup\n");
|
||||
__tty_hangup(tty, 1);
|
||||
}
|
||||
|
||||
@ -1239,8 +1241,7 @@ static ssize_t tty_write(struct file *file, const char __user *buf,
|
||||
return -EIO;
|
||||
/* Short term debug to catch buggy drivers */
|
||||
if (tty->ops->write_room == NULL)
|
||||
printk(KERN_ERR "tty driver %s lacks a write_room method.\n",
|
||||
tty->driver->name);
|
||||
tty_err(tty, "missing write_room method\n");
|
||||
ld = tty_ldisc_ref_wait(tty);
|
||||
if (!ld->ops->write)
|
||||
ret = -EIO;
|
||||
@ -1561,8 +1562,8 @@ err_module_put:
|
||||
/* call the tty release_tty routine to clean out this slot */
|
||||
err_release_tty:
|
||||
tty_unlock(tty);
|
||||
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
|
||||
"clearing slot %d\n", idx);
|
||||
tty_info_ratelimited(tty, "ldisc open failed (%d), clearing slot %d\n",
|
||||
retval, idx);
|
||||
release_tty(tty, idx);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
@ -1580,10 +1581,8 @@ void tty_free_termios(struct tty_struct *tty)
|
||||
tp = tty->driver->termios[idx];
|
||||
if (tp == NULL) {
|
||||
tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
|
||||
if (tp == NULL) {
|
||||
pr_warn("tty: no memory to save termios state.\n");
|
||||
if (tp == NULL)
|
||||
return;
|
||||
}
|
||||
tty->driver->termios[idx] = tp;
|
||||
}
|
||||
*tp = tty->termios;
|
||||
@ -1788,7 +1787,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
tty_debug_hangup(tty, "(tty count=%d)...\n", tty->count);
|
||||
tty_debug_hangup(tty, "releasing (count=%d)\n", tty->count);
|
||||
|
||||
if (tty->ops->close)
|
||||
tty->ops->close(tty, filp);
|
||||
@ -1837,8 +1836,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||
|
||||
if (once) {
|
||||
once = 0;
|
||||
printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
|
||||
__func__, tty_name(tty));
|
||||
tty_warn(tty, "read/write wait queue active!\n");
|
||||
}
|
||||
schedule_timeout_killable(timeout);
|
||||
if (timeout < 120 * HZ)
|
||||
@ -1849,14 +1847,12 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||
|
||||
if (o_tty) {
|
||||
if (--o_tty->count < 0) {
|
||||
printk(KERN_WARNING "%s: bad pty slave count (%d) for %s\n",
|
||||
__func__, o_tty->count, tty_name(o_tty));
|
||||
tty_warn(tty, "bad slave count (%d)\n", o_tty->count);
|
||||
o_tty->count = 0;
|
||||
}
|
||||
}
|
||||
if (--tty->count < 0) {
|
||||
printk(KERN_WARNING "%s: bad tty->count (%d) for %s\n",
|
||||
__func__, tty->count, tty_name(tty));
|
||||
tty_warn(tty, "bad tty->count (%d)\n", tty->count);
|
||||
tty->count = 0;
|
||||
}
|
||||
|
||||
@ -1907,7 +1903,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||
/* Wait for pending work before tty destruction commmences */
|
||||
tty_flush_works(tty);
|
||||
|
||||
tty_debug_hangup(tty, "freeing structure...\n");
|
||||
tty_debug_hangup(tty, "freeing structure\n");
|
||||
/*
|
||||
* The release_tty function takes care of the details of clearing
|
||||
* the slots and preserving the termios structure. The tty_unlock_pair
|
||||
@ -2097,7 +2093,7 @@ retry_open:
|
||||
tty->driver->subtype == PTY_TYPE_MASTER)
|
||||
noctty = 1;
|
||||
|
||||
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
|
||||
tty_debug_hangup(tty, "opening (count=%d)\n", tty->count);
|
||||
|
||||
if (tty->ops->open)
|
||||
retval = tty->ops->open(tty, filp);
|
||||
@ -2106,7 +2102,7 @@ retry_open:
|
||||
filp->f_flags = saved_flags;
|
||||
|
||||
if (retval) {
|
||||
tty_debug_hangup(tty, "error %d, releasing...\n", retval);
|
||||
tty_debug_hangup(tty, "open error %d, releasing\n", retval);
|
||||
|
||||
tty_unlock(tty); /* need to call tty_release without BTM */
|
||||
tty_release(inode, filp);
|
||||
@ -2870,7 +2866,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
no_tty();
|
||||
return 0;
|
||||
case TIOCSCTTY:
|
||||
return tiocsctty(tty, file, arg);
|
||||
return tiocsctty(real_tty, file, arg);
|
||||
case TIOCGPGRP:
|
||||
return tiocgpgrp(tty, real_tty, p);
|
||||
case TIOCSPGRP:
|
||||
@ -3028,28 +3024,24 @@ void __do_SAK(struct tty_struct *tty)
|
||||
read_lock(&tasklist_lock);
|
||||
/* Kill the entire session */
|
||||
do_each_pid_task(session, PIDTYPE_SID, p) {
|
||||
printk(KERN_NOTICE "SAK: killed process %d"
|
||||
" (%s): task_session(p)==tty->session\n",
|
||||
task_pid_nr(p), p->comm);
|
||||
tty_notice(tty, "SAK: killed process %d (%s): by session\n",
|
||||
task_pid_nr(p), p->comm);
|
||||
send_sig(SIGKILL, p, 1);
|
||||
} while_each_pid_task(session, PIDTYPE_SID, p);
|
||||
/* Now kill any processes that happen to have the
|
||||
* tty open.
|
||||
*/
|
||||
|
||||
/* Now kill any processes that happen to have the tty open */
|
||||
do_each_thread(g, p) {
|
||||
if (p->signal->tty == tty) {
|
||||
printk(KERN_NOTICE "SAK: killed process %d"
|
||||
" (%s): task_session(p)==tty->session\n",
|
||||
task_pid_nr(p), p->comm);
|
||||
tty_notice(tty, "SAK: killed process %d (%s): by controlling tty\n",
|
||||
task_pid_nr(p), p->comm);
|
||||
send_sig(SIGKILL, p, 1);
|
||||
continue;
|
||||
}
|
||||
task_lock(p);
|
||||
i = iterate_fd(p->files, 0, this_tty, tty);
|
||||
if (i != 0) {
|
||||
printk(KERN_NOTICE "SAK: killed process %d"
|
||||
" (%s): fd#%d opened to the tty\n",
|
||||
task_pid_nr(p), p->comm, i - 1);
|
||||
tty_notice(tty, "SAK: killed process %d (%s): by fd#%d\n",
|
||||
task_pid_nr(p), p->comm, i - 1);
|
||||
force_sig(SIGKILL, p);
|
||||
}
|
||||
task_unlock(p);
|
||||
@ -3219,7 +3211,7 @@ EXPORT_SYMBOL(tty_register_device);
|
||||
|
||||
static void tty_device_create_release(struct device *dev)
|
||||
{
|
||||
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
|
||||
dev_dbg(dev, "releasing...\n");
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
@ -3255,8 +3247,8 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
|
||||
bool cdev = false;
|
||||
|
||||
if (index >= driver->num) {
|
||||
printk(KERN_ERR "Attempt to register invalid tty line number "
|
||||
" (%d).\n", index);
|
||||
pr_err("%s: Attempt to register invalid tty line number (%d)\n",
|
||||
driver->name, index);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ int tty_unthrottle_safe(struct tty_struct *tty)
|
||||
|
||||
void tty_wait_until_sent(struct tty_struct *tty, long timeout)
|
||||
{
|
||||
tty_debug_wait_until_sent(tty, "\n");
|
||||
tty_debug_wait_until_sent(tty, "wait until sent, timeout=%ld\n", timeout);
|
||||
|
||||
if (!timeout)
|
||||
timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
@ -239,19 +239,14 @@ EXPORT_SYMBOL(tty_wait_until_sent);
|
||||
* Termios Helper Methods
|
||||
*/
|
||||
|
||||
static void unset_locked_termios(struct ktermios *termios,
|
||||
struct ktermios *old,
|
||||
struct ktermios *locked)
|
||||
static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
{
|
||||
struct ktermios *termios = &tty->termios;
|
||||
struct ktermios *locked = &tty->termios_locked;
|
||||
int i;
|
||||
|
||||
#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
|
||||
|
||||
if (!locked) {
|
||||
printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
|
||||
NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
|
||||
NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
|
||||
@ -463,10 +458,8 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
|
||||
if (ifound == -1 && (ibaud != obaud || ibinput))
|
||||
termios->c_cflag |= (BOTHER << IBSHIFT);
|
||||
#else
|
||||
if (ifound == -1 || ofound == -1) {
|
||||
printk_once(KERN_WARNING "tty: Unable to return correct "
|
||||
"speed data as your architecture needs updating.\n");
|
||||
}
|
||||
if (ifound == -1 || ofound == -1)
|
||||
pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
|
||||
@ -556,7 +549,7 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
||||
down_write(&tty->termios_rwsem);
|
||||
old_termios = tty->termios;
|
||||
tty->termios = *new_termios;
|
||||
unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked);
|
||||
unset_locked_termios(tty, &old_termios);
|
||||
|
||||
if (tty->ops->set_termios)
|
||||
tty->ops->set_termios(tty, &old_termios);
|
||||
|
@ -185,7 +185,7 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
|
||||
*
|
||||
* Complement of tty_ldisc_get().
|
||||
*/
|
||||
static inline void tty_ldisc_put(struct tty_ldisc *ld)
|
||||
static void tty_ldisc_put(struct tty_ldisc *ld)
|
||||
{
|
||||
if (WARN_ON_ONCE(!ld))
|
||||
return;
|
||||
@ -417,6 +417,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
|
||||
* they are not on hot paths so a little discipline won't do
|
||||
* any harm.
|
||||
*
|
||||
* The line discipline-related tty_struct fields are reset to
|
||||
* prevent the ldisc driver from re-using stale information for
|
||||
* the new ldisc instance.
|
||||
*
|
||||
* Locking: takes termios_rwsem
|
||||
*/
|
||||
|
||||
@ -425,6 +429,9 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
|
||||
down_write(&tty->termios_rwsem);
|
||||
tty->termios.c_line = num;
|
||||
up_write(&tty->termios_rwsem);
|
||||
|
||||
tty->disc_data = NULL;
|
||||
tty->receive_room = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -529,34 +536,21 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||
|
||||
tty_lock(tty);
|
||||
retval = tty_ldisc_lock(tty, 5 * HZ);
|
||||
if (retval) {
|
||||
tty_ldisc_put(new_ldisc);
|
||||
tty_unlock(tty);
|
||||
return retval;
|
||||
}
|
||||
if (retval)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Check the no-op case
|
||||
*/
|
||||
/* Check the no-op case */
|
||||
if (tty->ldisc->ops->num == ldisc)
|
||||
goto out;
|
||||
|
||||
if (tty->ldisc->ops->num == ldisc) {
|
||||
tty_ldisc_unlock(tty);
|
||||
tty_ldisc_put(new_ldisc);
|
||||
tty_unlock(tty);
|
||||
return 0;
|
||||
if (test_bit(TTY_HUPPED, &tty->flags)) {
|
||||
/* We were raced by hangup */
|
||||
retval = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
old_ldisc = tty->ldisc;
|
||||
|
||||
if (test_bit(TTY_HUPPED, &tty->flags)) {
|
||||
/* We were raced by the hangup method. It will have stomped
|
||||
the ldisc data and closed the ldisc down */
|
||||
tty_ldisc_unlock(tty);
|
||||
tty_ldisc_put(new_ldisc);
|
||||
tty_unlock(tty);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Shutdown the old discipline. */
|
||||
tty_ldisc_close(tty, old_ldisc);
|
||||
|
||||
@ -582,18 +576,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||
the old ldisc (if it was restored as part of error cleanup
|
||||
above). In either case, releasing a single reference from
|
||||
the old ldisc is correct. */
|
||||
|
||||
tty_ldisc_put(old_ldisc);
|
||||
|
||||
/*
|
||||
* Allow ldisc referencing to occur again
|
||||
*/
|
||||
new_ldisc = old_ldisc;
|
||||
out:
|
||||
tty_ldisc_unlock(tty);
|
||||
|
||||
/* Restart the work queue in case no characters kick it off. Safe if
|
||||
already running */
|
||||
tty_buffer_restart_work(tty->port);
|
||||
|
||||
err:
|
||||
tty_ldisc_put(new_ldisc); /* drop the extra reference */
|
||||
tty_unlock(tty);
|
||||
return retval;
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ down_write_failed(struct ld_semaphore *sem, long count, long timeout)
|
||||
|
||||
|
||||
|
||||
static inline int __ldsem_down_read_nested(struct ld_semaphore *sem,
|
||||
static int __ldsem_down_read_nested(struct ld_semaphore *sem,
|
||||
int subclass, long timeout)
|
||||
{
|
||||
long count;
|
||||
@ -338,7 +338,7 @@ static inline int __ldsem_down_read_nested(struct ld_semaphore *sem,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int __ldsem_down_write_nested(struct ld_semaphore *sem,
|
||||
static int __ldsem_down_write_nested(struct ld_semaphore *sem,
|
||||
int subclass, long timeout)
|
||||
{
|
||||
long count;
|
||||
|
@ -12,11 +12,8 @@
|
||||
|
||||
void __lockfunc tty_lock(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->magic != TTY_MAGIC) {
|
||||
pr_err("L Bad %p\n", tty);
|
||||
WARN_ON(1);
|
||||
if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
|
||||
return;
|
||||
}
|
||||
tty_kref_get(tty);
|
||||
mutex_lock(&tty->legacy_mutex);
|
||||
}
|
||||
@ -24,11 +21,8 @@ EXPORT_SYMBOL(tty_lock);
|
||||
|
||||
void __lockfunc tty_unlock(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->magic != TTY_MAGIC) {
|
||||
pr_err("U Bad %p\n", tty);
|
||||
WARN_ON(1);
|
||||
if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty))
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&tty->legacy_mutex);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
@ -462,14 +462,13 @@ int tty_port_close_start(struct tty_port *port,
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (tty->count == 1 && port->count != 1) {
|
||||
printk(KERN_WARNING
|
||||
"tty_port_close_start: tty->count = 1 port count = %d.\n",
|
||||
port->count);
|
||||
tty_warn(tty, "%s: tty->count = 1 port count = %d\n", __func__,
|
||||
port->count);
|
||||
port->count = 1;
|
||||
}
|
||||
if (--port->count < 0) {
|
||||
printk(KERN_WARNING "tty_port_close_start: count = %d\n",
|
||||
port->count);
|
||||
tty_warn(tty, "%s: bad port count (%d)\n", __func__,
|
||||
port->count);
|
||||
port->count = 0;
|
||||
}
|
||||
|
||||
|
@ -634,7 +634,7 @@ static void set_origin(struct vc_data *vc)
|
||||
vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
|
||||
}
|
||||
|
||||
static inline void save_screen(struct vc_data *vc)
|
||||
static void save_screen(struct vc_data *vc)
|
||||
{
|
||||
WARN_CONSOLE_UNLOCKED();
|
||||
|
||||
|
@ -65,6 +65,24 @@
|
||||
#define ST_UART011_ABCR 0x100 /* Autobaud control register. */
|
||||
#define ST_UART011_ABIMSC 0x15C /* Autobaud interrupt mask/clear register. */
|
||||
|
||||
/*
|
||||
* ZTE UART register offsets. This UART has a radically different address
|
||||
* allocation from the ARM and ST variants, so we list all registers here.
|
||||
* We assume unlisted registers do not exist.
|
||||
*/
|
||||
#define ZX_UART011_DR 0x04
|
||||
#define ZX_UART011_FR 0x14
|
||||
#define ZX_UART011_IBRD 0x24
|
||||
#define ZX_UART011_FBRD 0x28
|
||||
#define ZX_UART011_LCRH 0x30
|
||||
#define ZX_UART011_CR 0x34
|
||||
#define ZX_UART011_IFLS 0x38
|
||||
#define ZX_UART011_IMSC 0x40
|
||||
#define ZX_UART011_RIS 0x44
|
||||
#define ZX_UART011_MIS 0x48
|
||||
#define ZX_UART011_ICR 0x4c
|
||||
#define ZX_UART011_DMACR 0x50
|
||||
|
||||
#define UART011_DR_OE (1 << 11)
|
||||
#define UART011_DR_BE (1 << 10)
|
||||
#define UART011_DR_PE (1 << 9)
|
||||
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Serial Port driver for a NWP uart device
|
||||
*
|
||||
* Copyright (C) 2008 IBM Corp., Benjamin Krill <ben@codiert.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
#ifndef _NWPSERIAL_H
|
||||
#define _NWPSERIAL_H
|
||||
|
||||
int nwpserial_register_port(struct uart_port *port);
|
||||
void nwpserial_unregister_port(int line);
|
||||
|
||||
#endif /* _NWPSERIAL_H */
|
@ -145,11 +145,12 @@ struct uart_port {
|
||||
|
||||
#define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */
|
||||
#define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */
|
||||
#define UPIO_MEM (SERIAL_IO_MEM) /* 8b MMIO access */
|
||||
#define UPIO_MEM (SERIAL_IO_MEM) /* driver-specific */
|
||||
#define UPIO_MEM32 (SERIAL_IO_MEM32) /* 32b little endian */
|
||||
#define UPIO_AU (SERIAL_IO_AU) /* Au1x00 and RT288x type IO */
|
||||
#define UPIO_TSI (SERIAL_IO_TSI) /* Tsi108/109 type IO */
|
||||
#define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */
|
||||
#define UPIO_MEM16 (SERIAL_IO_MEM16) /* 16b little endian */
|
||||
|
||||
unsigned int read_status_mask; /* driver specific */
|
||||
unsigned int ignore_status_mask; /* driver specific */
|
||||
|
@ -32,6 +32,7 @@ enum {
|
||||
SCIx_SH2_SCIF_FIFODATA_REGTYPE,
|
||||
SCIx_SH3_SCIF_REGTYPE,
|
||||
SCIx_SH4_SCIF_REGTYPE,
|
||||
SCIx_SH4_SCIF_BRG_REGTYPE,
|
||||
SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
|
||||
SCIx_SH4_SCIF_FIFODATA_REGTYPE,
|
||||
SCIx_SH7705_SCIF_REGTYPE,
|
||||
|
@ -345,8 +345,6 @@ struct tty_file_private {
|
||||
#define TTY_HUPPED 18 /* Post driver->hangup() */
|
||||
#define TTY_LDISC_HALTED 22 /* Line discipline is halted */
|
||||
|
||||
#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
|
||||
|
||||
/* Values for tty->flow_change */
|
||||
#define TTY_THROTTLE_SAFE 1
|
||||
#define TTY_UNTHROTTLE_SAFE 2
|
||||
@ -395,8 +393,6 @@ static inline int __init tty_init(void)
|
||||
{ return 0; }
|
||||
#endif
|
||||
|
||||
extern void tty_write_flush(struct tty_struct *);
|
||||
|
||||
extern struct ktermios tty_std_termios;
|
||||
|
||||
extern int vcs_init(void);
|
||||
@ -419,9 +415,8 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty)
|
||||
return tty;
|
||||
}
|
||||
|
||||
extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
|
||||
const char *routine);
|
||||
extern const char *tty_name(const struct tty_struct *tty);
|
||||
extern const char *tty_driver_name(const struct tty_struct *tty);
|
||||
extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
|
||||
extern int __tty_check_change(struct tty_struct *tty, int sig);
|
||||
extern int tty_check_change(struct tty_struct *tty);
|
||||
@ -667,10 +662,16 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {}
|
||||
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
|
||||
#endif
|
||||
|
||||
#define tty_debug(tty, f, args...) \
|
||||
do { \
|
||||
printk(KERN_DEBUG "%s: %s: " f, __func__, \
|
||||
tty_name(tty), ##args); \
|
||||
} while (0)
|
||||
#define tty_msg(fn, tty, f, ...) \
|
||||
fn("%s %s: " f, tty_driver_name(tty), tty_name(tty), ##__VA_ARGS__)
|
||||
|
||||
#define tty_debug(tty, f, ...) tty_msg(pr_debug, tty, f, ##__VA_ARGS__)
|
||||
#define tty_info(tty, f, ...) tty_msg(pr_info, tty, f, ##__VA_ARGS__)
|
||||
#define tty_notice(tty, f, ...) tty_msg(pr_notice, tty, f, ##__VA_ARGS__)
|
||||
#define tty_warn(tty, f, ...) tty_msg(pr_warn, tty, f, ##__VA_ARGS__)
|
||||
#define tty_err(tty, f, ...) tty_msg(pr_err, tty, f, ##__VA_ARGS__)
|
||||
|
||||
#define tty_info_ratelimited(tty, f, ...) \
|
||||
tty_msg(pr_info_ratelimited, tty, f, ##__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
@ -69,6 +69,7 @@ struct serial_struct {
|
||||
#define SERIAL_IO_AU 4
|
||||
#define SERIAL_IO_TSI 5
|
||||
#define SERIAL_IO_MEM32BE 6
|
||||
#define SERIAL_IO_MEM16 7
|
||||
|
||||
#define UART_CLEAR_FIFO 0x01
|
||||
#define UART_USE_FIFO 0x02
|
||||
|
@ -176,7 +176,7 @@
|
||||
|
||||
#define PORT_S3C6400 84
|
||||
|
||||
/* NWPSERIAL */
|
||||
/* NWPSERIAL, now removed */
|
||||
#define PORT_NWPSERIAL 85
|
||||
|
||||
/* MAX3100 */
|
||||
|
Loading…
Reference in New Issue
Block a user