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:
Linus Torvalds 2016-01-13 10:02:05 -08:00
commit 67ad058d97
71 changed files with 1334 additions and 1501 deletions

View File

@ -2,7 +2,7 @@
Required properties: 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,scif-r7s72100" for R7S72100 (RZ/A1H) SCIF compatible UART.
- "renesas,scifa-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFA 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,scifa-r8a7790" for R8A7790 (R-Car H2) SCIFA compatible UART.
- "renesas,scifb-r8a7790" for R8A7790 (R-Car H2) SCIFB 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,hscif-r8a7790" for R8A7790 (R-Car H2) HSCIF compatible UART.
- "renesas,scif-r8a7791" for R8A7791 (R-Car M2) SCIF compatible UART. - "renesas,scif-r8a7791" for R8A7791 (R-Car M2-W) SCIF compatible UART.
- "renesas,scifa-r8a7791" for R8A7791 (R-Car M2) SCIFA compatible UART. - "renesas,scifa-r8a7791" for R8A7791 (R-Car M2-W) SCIFA compatible UART.
- "renesas,scifb-r8a7791" for R8A7791 (R-Car M2) SCIFB compatible UART. - "renesas,scifb-r8a7791" for R8A7791 (R-Car M2-W) SCIFB compatible UART.
- "renesas,hscif-r8a7791" for R8A7791 (R-Car M2) HSCIF 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,scif-r8a7794" for R8A7794 (R-Car E2) SCIF compatible UART.
- "renesas,scifa-r8a7794" for R8A7794 (R-Car E2) SCIFA compatible UART. - "renesas,scifa-r8a7794" for R8A7794 (R-Car E2) SCIFA compatible UART.
- "renesas,scifb-r8a7794" for R8A7794 (R-Car E2) SCIFB 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,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
- "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA 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,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,scif" for generic SCIF compatible UART.
- "renesas,scifa" for generic SCIFA compatible UART. - "renesas,scifa" for generic SCIFA compatible UART.
- "renesas,scifb" for generic SCIFB compatible UART. - "renesas,scifb" for generic SCIFB compatible UART.
@ -34,15 +46,26 @@ Required properties:
- "renesas,sci" for generic SCI compatible UART. - "renesas,sci" for generic SCI compatible UART.
When compatible with the generic version, nodes must list the When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first followed by the SoC-specific version corresponding to the platform first, followed by the
generic version. family-specific and/or generic versions.
- reg: Base address and length of the I/O registers used by the UART. - reg: Base address and length of the I/O registers used by the UART.
- interrupts: Must contain an interrupt-specifier for the SCIx interrupt. - interrupts: Must contain an interrupt-specifier for the SCIx interrupt.
- clocks: Must contain a phandle and clock-specifier pair for each entry - clocks: Must contain a phandle and clock-specifier pair for each entry
in clock-names. 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 Note: Each enabled SCIx UART should have an alias correctly numbered in the
"aliases" node. "aliases" node.
@ -58,12 +81,13 @@ Example:
}; };
scifa0: serial@e6c40000 { scifa0: serial@e6c40000 {
compatible = "renesas,scifa-r8a7790", "renesas,scifa"; compatible = "renesas,scifa-r8a7790",
"renesas,rcar-gen2-scifa", "renesas,scifa";
reg = <0 0xe6c40000 0 64>; reg = <0 0xe6c40000 0 64>;
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>; clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
clock-names = "sci_ick"; clock-names = "fck";
dmas = <&dmac0 0x21>, <&dmac0 0x22>; dmas = <&dmac0 0x21>, <&dmac0 0x22>;
dma-names = "tx", "rx"; dma-names = "tx", "rx";
}; };

View File

@ -730,16 +730,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
uart[8250],io,<addr>[,options] uart[8250],io,<addr>[,options]
uart[8250],mmio,<addr>[,options] uart[8250],mmio,<addr>[,options]
uart[8250],mmio16,<addr>[,options]
uart[8250],mmio32,<addr>[,options] uart[8250],mmio32,<addr>[,options]
uart[8250],0x<addr>[,options] uart[8250],0x<addr>[,options]
Start an early, polled-mode console on the 8250/16550 Start an early, polled-mode console on the 8250/16550
UART at the specified I/O port or MMIO address, UART at the specified I/O port or MMIO address,
switching to the matching ttyS device later. switching to the matching ttyS device later.
MMIO inter-register address stride is either 8-bit MMIO inter-register address stride is either 8-bit
(mmio) or 32-bit (mmio32). (mmio), 16-bit (mmio16), or 32-bit (mmio32).
If none of [io|mmio|mmio32], <addr> is assumed to be If none of [io|mmio|mmio16|mmio32], <addr> is assumed
equivalent to 'mmio'. 'options' are specified in the to be equivalent to 'mmio'. 'options' are specified in
same format described for ttyS above; if unspecified, the same format described for ttyS above; if unspecified,
the h/w is not re-initialized. the h/w is not re-initialized.
hvc<n> Use the hypervisor console device <n>. This is for 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. unspecified, the h/w is not initialized.
pl011,<addr> pl011,<addr>
pl011,mmio32,<addr>
Start an early, polled-mode console on a pl011 serial Start an early, polled-mode console on a pl011 serial
port at the specified address. The pl011 serial port port at the specified address. The pl011 serial port
must already be setup and configured. Options are not 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> msm_serial,<addr>
Start an early, polled-mode console on an msm serial Start an early, polled-mode console on an msm serial

View File

@ -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-mtu2", "peripheral_clk", NULL);
clk_add_alias("fck", "sh-cmt-16.0", "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("fck", "sh-cmt-32.0", "peripheral_clk", NULL);
clk_add_alias("sci_ick", NULL, "peripheral_clk", NULL);
return ret; return ret;
} }

View File

@ -115,7 +115,14 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
/* MSTP clocks */ /* 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_CON_ID("vdc3", &mstp_clks[MSTP74]),
CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]), CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]),
CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]), CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),

View File

@ -150,14 +150,14 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
/* MSTP clocks */ /* MSTP clocks */
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]), CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP47]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP46]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP45]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP44]), CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP44]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP43]), CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP43]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]), CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP42]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]), CLKDEV_ICK_ID("fck", "sh-sci.6", &mstp_clks[MSTP41]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]), CLKDEV_ICK_ID("fck", "sh-sci.7", &mstp_clks[MSTP40]),
CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]), CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]),
CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]), CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
CLKDEV_ICK_ID("fck", "sh-mtu2", &mstp_clks[MSTP35]), CLKDEV_ICK_ID("fck", "sh-mtu2", &mstp_clks[MSTP35]),

View File

@ -232,10 +232,10 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]), CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]), CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]), CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP004]), CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP004]),
CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]), CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]),
CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]), CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]),

View File

@ -230,9 +230,9 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]), CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]), CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]), CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]),
CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]), CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]), CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),

View File

@ -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.0", &mstp_clks[HWBLK_TMU0]),
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[HWBLK_TMU1]), 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("fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]), CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]), CLKDEV_ICK_ID("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.5", &mstp_clks[HWBLK_SCIF5]),
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]), CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]),
}; };

View File

@ -194,12 +194,12 @@ static struct clk_lookup lookups[] = {
/* MSTP32 clocks */ /* MSTP32 clocks */
CLKDEV_DEV_ID("i2c-sh7734.0", &mstp_clks[MSTP030]), CLKDEV_DEV_ID("i2c-sh7734.0", &mstp_clks[MSTP030]),
CLKDEV_DEV_ID("i2c-sh7734.1", &mstp_clks[MSTP029]), CLKDEV_DEV_ID("i2c-sh7734.1", &mstp_clks[MSTP029]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP026]), CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP026]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP024]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP024]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP023]), CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP023]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP022]), CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP022]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP021]), CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP021]),
CLKDEV_CON_ID("hscif", &mstp_clks[MSTP019]), CLKDEV_CON_ID("hscif", &mstp_clks[MSTP019]),
CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]), CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]),
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]), CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]),

View File

@ -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.0", &mstp_clks[MSTP113]),
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP114]), CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP114]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP112]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP112]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP111]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]), CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP110]),
CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]), CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]),
CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP102]), CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP102]),

View File

@ -132,12 +132,12 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
/* MSTP32 clocks */ /* MSTP32 clocks */
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]), CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP029]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]), CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP028]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]), CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]), CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]),
CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]), CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]), CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]),

View File

@ -139,12 +139,12 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
/* MSTP32 clocks */ /* MSTP32 clocks */
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]), CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP029]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]), CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP028]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]), CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]), CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]),
CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]), CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]),
CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]), CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]),

View File

@ -114,10 +114,10 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
/* MSTP32 clocks */ /* MSTP32 clocks */
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]), CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP027]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]), CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP026]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]), CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP025]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]), CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP024]),
CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]), CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]),
CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]), CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]),

View File

@ -28,7 +28,7 @@ static struct plat_sci_port scif0_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.type = PORT_SCIF, .type = PORT_SCIF,
.regtype = SCIx_SH4_SCIF_REGTYPE, .regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
}; };
static struct resource scif0_resources[] = { static struct resource scif0_resources[] = {
@ -50,7 +50,7 @@ static struct plat_sci_port scif1_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.type = PORT_SCIF, .type = PORT_SCIF,
.regtype = SCIx_SH4_SCIF_REGTYPE, .regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
}; };
static struct resource scif1_resources[] = { static struct resource scif1_resources[] = {
@ -72,7 +72,7 @@ static struct plat_sci_port scif2_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.type = PORT_SCIF, .type = PORT_SCIF,
.regtype = SCIx_SH4_SCIF_REGTYPE, .regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
}; };
static struct resource scif2_resources[] = { static struct resource scif2_resources[] = {
@ -94,7 +94,7 @@ static struct plat_sci_port scif3_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.type = PORT_SCIF, .type = PORT_SCIF,
.regtype = SCIx_SH4_SCIF_REGTYPE, .regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
}; };
static struct resource scif3_resources[] = { static struct resource scif3_resources[] = {
@ -116,7 +116,7 @@ static struct plat_sci_port scif4_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.type = PORT_SCIF, .type = PORT_SCIF,
.regtype = SCIx_SH4_SCIF_REGTYPE, .regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
}; };
static struct resource scif4_resources[] = { static struct resource scif4_resources[] = {
@ -138,7 +138,7 @@ static struct plat_sci_port scif5_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.type = PORT_SCIF, .type = PORT_SCIF,
.regtype = SCIx_SH4_SCIF_REGTYPE, .regtype = SCIx_SH4_SCIF_BRG_REGTYPE,
}; };
static struct resource scif5_resources[] = { static struct resource scif5_resources[] = {

View File

@ -32,7 +32,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#undef SERIAL_PARANOIA_CHECK #undef SERIAL_PARANOIA_CHECK
#define SERIAL_DO_RESTART
/* Set of debugging defines */ /* Set of debugging defines */

View File

@ -292,14 +292,14 @@ static void cyz_rx_restart(unsigned long);
static struct timer_list cyz_rx_full_timer[NR_PORTS]; static struct timer_list cyz_rx_full_timer[NR_PORTS];
#endif /* CONFIG_CYZ_INTR */ #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; struct cyclades_card *card = port->card;
cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val); 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; 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); 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; 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; 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) const char *name, const char *routine)
{ {
#ifdef SERIAL_PARANOIA_CHECK #ifdef SERIAL_PARANOIA_CHECK

View File

@ -220,7 +220,7 @@ static struct isi_port isi_ports[PORT_COUNT];
* it wants to talk. * it wants to talk.
*/ */
static inline int WaitTillCardIsFree(unsigned long base) static int WaitTillCardIsFree(unsigned long base)
{ {
unsigned int count = 0; unsigned int count = 0;
unsigned int a = in_atomic(); /* do we run under spinlock? */ 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 */ /* 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; struct isi_board *card = port->card;
unsigned long base = card->base; unsigned long base = card->base;

View File

@ -155,7 +155,6 @@ struct mon_str {
#define LOWWAIT 2 #define LOWWAIT 2
#define EMPTYWAIT 3 #define EMPTYWAIT 3
#define SERIAL_DO_RESTART
#define WAKEUP_CHARS 256 #define WAKEUP_CHARS 256

View File

@ -162,12 +162,23 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
return put_user(x, ptr); return put_user(x, ptr);
} }
static inline int tty_copy_to_user(struct tty_struct *tty, static int tty_copy_to_user(struct tty_struct *tty, void __user *to,
void __user *to, size_t tail, size_t n)
const void *from,
unsigned long n)
{ {
struct n_tty_data *ldata = tty->disc_data; 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); tty_audit_add_data(tty, from, n, ldata->icanon);
return copy_to_user(to, from, n); return copy_to_user(to, from, n);
@ -1201,9 +1212,7 @@ static void n_tty_receive_overrun(struct tty_struct *tty)
ldata->num_overrun++; ldata->num_overrun++;
if (time_after(jiffies, ldata->overrun_time + HZ) || if (time_after(jiffies, ldata->overrun_time + HZ) ||
time_after(ldata->overrun_time, jiffies)) { time_after(ldata->overrun_time, jiffies)) {
printk(KERN_WARNING "%s: %d input overrun(s)\n", tty_warn(tty, "%d input overrun(s)\n", ldata->num_overrun);
tty_name(tty),
ldata->num_overrun);
ldata->overrun_time = jiffies; ldata->overrun_time = jiffies;
ldata->num_overrun = 0; 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); n_tty_receive_overrun(tty);
break; break;
default: default:
printk(KERN_ERR "%s: unknown flag %d\n", tty_err(tty, "unknown flag %d\n", flag);
tty_name(tty), flag);
break; 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(head - ldata->read_tail, N_TTY_BUF_SIZE - tail);
n = min(*nr, n); n = min(*nr, n);
if (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; n -= retval;
is_eof = n == 1 && read_buf(ldata, tail) == EOF_CHAR(tty); is_eof = n == 1 && *from == EOF_CHAR(tty);
tty_audit_add_data(tty, read_buf_addr(ldata, tail), n, tty_audit_add_data(tty, from, n, ldata->icanon);
ldata->icanon);
smp_store_release(&ldata->read_tail, ldata->read_tail + n); smp_store_release(&ldata->read_tail, ldata->read_tail + n);
/* Turn single EOF into zero-length read */ /* Turn single EOF into zero-length read */
if (L_EXTPROC(tty) && ldata->icanon && is_eof && 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) { if (eol == N_TTY_BUF_SIZE && more) {
/* scan wrapped without finding set bit */ /* scan wrapped without finding set bit */
eol = find_next_bit(ldata->read_flags, more, 0); eol = find_next_bit(ldata->read_flags, more, 0);
if (eol != more) found = eol != more;
found = 1; } else
} else if (eol != size) found = eol != size;
found = 1;
size = N_TTY_BUF_SIZE - tail;
n = eol - tail; n = eol - tail;
if (n > N_TTY_BUF_SIZE) if (n > N_TTY_BUF_SIZE)
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 = c;
} }
n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n", n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n",
__func__, eol, found, n, c, size, more); __func__, eol, found, n, c, tail, 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);
ret = tty_copy_to_user(tty, *b, tail, n);
if (ret) if (ret)
return -EFAULT; return -EFAULT;
*b += n; *b += n;

View File

@ -788,7 +788,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
if (retval) if (retval)
goto err_release; goto err_release;
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count); tty_debug_hangup(tty, "opening (count=%d)\n", tty->count);
tty_unlock(tty); tty_unlock(tty);
return 0; return 0;

View File

@ -157,7 +157,7 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty);
#endif #endif
static int m68328_console_initted = 0; static int m68328_console_initted;
static int m68328_console_baud = CONSOLE_BAUD_RATE; static int m68328_console_baud = CONSOLE_BAUD_RATE;
static int m68328_console_cbaud = DEFAULT_CBAUD; static int m68328_console_cbaud = DEFAULT_CBAUD;
@ -274,8 +274,8 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx)
#endif #endif
ch = GET_FIELD(rx, URX_RXDATA); ch = GET_FIELD(rx, URX_RXDATA);
if(info->is_cons) { if (info->is_cons) {
if(URX_BREAK & rx) { /* whee, break received */ if (URX_BREAK & rx) { /* whee, break received */
return; return;
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
} else if (ch == 0x10) { /* ^P */ } 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); tty_insert_flip_char(&info->tport, ch, flag);
#ifndef CONFIG_XCOPILOT_BUGS #ifndef CONFIG_XCOPILOT_BUGS
} while((rx = uart->urx.w) & URX_DATA_READY); } while ((rx = uart->urx.w) & URX_DATA_READY);
#endif #endif
tty_schedule_flip(&info->tport); 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_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
info->xmit_cnt--; info->xmit_cnt--;
if(info->xmit_cnt <= 0) { if (info->xmit_cnt <= 0) {
/* All done for now... TX ints off */ /* All done for now... TX ints off */
uart->ustcnt &= ~USTCNT_TX_INTR_MASK; uart->ustcnt &= ~USTCNT_TX_INTR_MASK;
goto clear_and_return; goto clear_and_return;
@ -452,45 +452,45 @@ struct {
} }
#ifndef CONFIG_M68VZ328 #ifndef CONFIG_M68VZ328
hw_baud_table[18] = { hw_baud_table[18] = {
{0,0}, /* 0 */ {0, 0}, /* 0 */
{0,0}, /* 50 */ {0, 0}, /* 50 */
{0,0}, /* 75 */ {0, 0}, /* 75 */
{0,0}, /* 110 */ {0, 0}, /* 110 */
{0,0}, /* 134 */ {0, 0}, /* 134 */
{0,0}, /* 150 */ {0, 0}, /* 150 */
{0,0}, /* 200 */ {0, 0}, /* 200 */
{7,0x26}, /* 300 */ {7, 0x26}, /* 300 */
{6,0x26}, /* 600 */ {6, 0x26}, /* 600 */
{5,0x26}, /* 1200 */ {5, 0x26}, /* 1200 */
{0,0}, /* 1800 */ {0, 0}, /* 1800 */
{4,0x26}, /* 2400 */ {4, 0x26}, /* 2400 */
{3,0x26}, /* 4800 */ {3, 0x26}, /* 4800 */
{2,0x26}, /* 9600 */ {2, 0x26}, /* 9600 */
{1,0x26}, /* 19200 */ {1, 0x26}, /* 19200 */
{0,0x26}, /* 38400 */ {0, 0x26}, /* 38400 */
{1,0x38}, /* 57600 */ {1, 0x38}, /* 57600 */
{0,0x38}, /* 115200 */ {0, 0x38}, /* 115200 */
}; };
#else #else
hw_baud_table[18] = { hw_baud_table[18] = {
{0,0}, /* 0 */ {0, 0}, /* 0 */
{0,0}, /* 50 */ {0, 0}, /* 50 */
{0,0}, /* 75 */ {0, 0}, /* 75 */
{0,0}, /* 110 */ {0, 0}, /* 110 */
{0,0}, /* 134 */ {0, 0}, /* 134 */
{0,0}, /* 150 */ {0, 0}, /* 150 */
{0,0}, /* 200 */ {0, 0}, /* 200 */
{0,0}, /* 300 */ {0, 0}, /* 300 */
{7,0x26}, /* 600 */ {7, 0x26}, /* 600 */
{6,0x26}, /* 1200 */ {6, 0x26}, /* 1200 */
{0,0}, /* 1800 */ {0, 0}, /* 1800 */
{5,0x26}, /* 2400 */ {5, 0x26}, /* 2400 */
{4,0x26}, /* 4800 */ {4, 0x26}, /* 4800 */
{3,0x26}, /* 9600 */ {3, 0x26}, /* 9600 */
{2,0x26}, /* 19200 */ {2, 0x26}, /* 19200 */
{1,0x26}, /* 38400 */ {1, 0x26}, /* 38400 */
{0,0x26}, /* 57600 */ {0, 0x26}, /* 57600 */
{1,0x38}, /* 115200 */ {1, 0x38}, /* 115200 */
}; };
#endif #endif
/* rate = 1036800 / ((65 - prescale) * (1<<divider)) */ /* 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 #ifdef CONFIG_SERIAL_68328_RTS_CTS
if (cflag & CRTSCTS) { if (cflag & CRTSCTS) {
uart->utx.w &= ~ UTX_NOCTS; uart->utx.w &= ~UTX_NOCTS;
} else { } else {
uart->utx.w |= UTX_NOCTS; uart->utx.w |= UTX_NOCTS;
} }
@ -591,8 +591,8 @@ void console_print_68328(const char *p)
{ {
char c; char c;
while((c=*(p++)) != 0) { while ((c = *(p++)) != 0) {
if(c == '\n') if (c == '\n')
rs_put_char('\r'); rs_put_char('\r');
rs_put_char(c); 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")) if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
return; return;
#ifndef USE_INTS #ifndef USE_INTS
for(;;) { for (;;) {
#endif #endif
/* Enable transmitter */ /* Enable transmitter */
@ -659,9 +659,9 @@ static void rs_flush_chars(struct tty_struct *tty)
local_irq_restore(flags); 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) const unsigned char *buf, int count)
{ {
int c, total = 0; int c, total = 0;
@ -700,7 +700,7 @@ static int rs_write(struct tty_struct * tty,
/* Enable transmitter */ /* Enable transmitter */
local_irq_disable(); local_irq_disable();
#ifndef USE_INTS #ifndef USE_INTS
while(info->xmit_cnt) { while (info->xmit_cnt) {
#endif #endif
uart->ustcnt |= USTCNT_TXEN; uart->ustcnt |= USTCNT_TXEN;
@ -767,7 +767,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
* incoming characters should be throttled. * 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; 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) */ /* 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; 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, static int get_serial_info(struct m68k_serial *info,
struct serial_struct * retinfo) struct serial_struct *retinfo)
{ {
struct serial_struct tmp; 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, 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 tty_port *port = &info->tport;
struct serial_struct new_serial; struct serial_struct new_serial;
@ -883,7 +883,7 @@ check_and_exit:
* transmit holding register is empty. This functionality * transmit holding register is empty. This functionality
* allows an RS485 driver to be written in user space. * 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 #ifdef CONFIG_SERIAL_68328_RTS_CTS
m68328_uart *uart = &uart_addr[info->line]; 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. * 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]; m68328_uart *uart = &uart_addr[info->line];
unsigned long flags; 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, static int rs_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg) 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; int retval;
if (serial_paranoia_check(info, tty->name, "rs_ioctl")) 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. * 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; struct tty_port *port = &info->tport;
m68328_uart *uart = &uart_addr[info->line]; m68328_uart *uart = &uart_addr[info->line];
unsigned long flags; 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) 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")) if (serial_paranoia_check(info, tty->name, "rs_hangup"))
return; return;
@ -1098,7 +1098,7 @@ void rs_hangup(struct tty_struct *tty)
* the IRQ chain. It also performs the serial-specific * the IRQ chain. It also performs the serial-specific
* initialization for the tty structure. * 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; struct m68k_serial *info;
int retval; int retval;
@ -1180,7 +1180,7 @@ rs68328_init(void)
local_irq_save(flags); local_irq_save(flags);
for(i=0;i<NR_PORTS;i++) { for (i = 0; i < NR_PORTS; i++) {
info = &m68k_soft[i]; info = &m68k_soft[i];
tty_port_init(&info->tport); tty_port_init(&info->tport);
@ -1198,7 +1198,7 @@ rs68328_init(void)
printk(" is a builtin MC68328 UART\n"); printk(" is a builtin MC68328 UART\n");
#ifdef CONFIG_M68VZ328 #ifdef CONFIG_M68VZ328
if (i > 0 ) if (i > 0)
PJSEL &= 0xCF; /* PSW enable second port output */ PJSEL &= 0xCF; /* PSW enable second port output */
#endif #endif
@ -1263,7 +1263,7 @@ int m68328_console_setup(struct console *cp, char *arg)
return(-1); return(-1);
if (arg) if (arg)
n = simple_strtoul(arg,NULL,0); n = simple_strtoul(arg, NULL, 0);
for (i = 0; i < ARRAY_SIZE(baud_table); i++) for (i = 0; i < ARRAY_SIZE(baud_table); i++)
if (baud_table[i] == n) 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 */ 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--) { while (count--) {
if (*str == '\n') if (*str == '\n')
rs_put_char('\r'); rs_put_char('\r');
rs_put_char( *str++ ); rs_put_char(*str++);
} }
} }

View File

@ -620,7 +620,7 @@ static int univ8250_console_setup(struct console *co, char *options)
* @options: ptr to option string from console command line * @options: ptr to option string from console command line
* *
* Only attempts to match console command lines of the form: * 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>] * console=uart[8250],0x<addr>[,<options>]
* This form is used to register an initial earlycon boot console and * This form is used to register an initial earlycon boot console and
* replace it with the serial8250_console at 8250 driver init. * 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) if (port->iotype != iotype)
continue; continue;
if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) && if ((iotype == UPIO_MEM || iotype == UPIO_MEM16 ||
(port->mapbase != addr)) iotype == UPIO_MEM32 || iotype == UPIO_MEM32BE)
&& (port->mapbase != addr))
continue; continue;
if (iotype == UPIO_PORT && port->iobase != addr) if (iotype == UPIO_PORT && port->iobase != addr)
continue; continue;

View File

@ -42,6 +42,8 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
switch (port->iotype) { switch (port->iotype) {
case UPIO_MEM: case UPIO_MEM:
return readb(port->membase + offset); return readb(port->membase + offset);
case UPIO_MEM16:
return readw(port->membase + (offset << 1));
case UPIO_MEM32: case UPIO_MEM32:
return readl(port->membase + (offset << 2)); return readl(port->membase + (offset << 2));
case UPIO_MEM32BE: case UPIO_MEM32BE:
@ -59,6 +61,9 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
case UPIO_MEM: case UPIO_MEM:
writeb(value, port->membase + offset); writeb(value, port->membase + offset);
break; break;
case UPIO_MEM16:
writew(value, port->membase + (offset << 1));
break;
case UPIO_MEM32: case UPIO_MEM32:
writel(value, port->membase + (offset << 2)); writel(value, port->membase + (offset << 2));
break; 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) #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; unsigned int status;
serial8250_early_out(port, UART_TX, c);
for (;;) { for (;;) {
status = serial8250_early_in(port, UART_LSR); status = serial8250_early_in(port, UART_LSR);
if ((status & BOTH_EMPTY) == BOTH_EMPTY) if ((status & BOTH_EMPTY) == BOTH_EMPTY)
return; break;
cpu_relax(); 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, static void __init early_serial8250_write(struct console *console,
const char *s, unsigned int count) const char *s, unsigned int count)
{ {
struct earlycon_device *device = console->data; struct earlycon_device *device = console->data;
struct uart_port *port = &device->port; 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); 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) static void __init init_port(struct earlycon_device *device)

View File

@ -48,6 +48,7 @@ static const struct of_device_id of_match[];
#define UART_MCR_MDCE BIT(7) #define UART_MCR_MDCE BIT(7)
#define UART_MCR_FCM BIT(6) #define UART_MCR_FCM BIT(6)
#ifdef CONFIG_SERIAL_EARLYCON
static struct earlycon_device *early_device; static struct earlycon_device *early_device;
static uint8_t __init early_in(struct uart_port *port, int offset) 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); EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup);
OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart", OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
ingenic_early_console_setup); ingenic_early_console_setup);
#endif /* CONFIG_SERIAL_EARLYCON */
static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
{ {

View File

@ -16,7 +16,7 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -245,23 +245,6 @@ static int mtk8250_probe(struct platform_device *pdev)
return 0; 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 #ifdef CONFIG_PM_SLEEP
static int mtk8250_suspend(struct device *dev) static int mtk8250_suspend(struct device *dev)
{ {
@ -292,18 +275,18 @@ static const struct of_device_id mtk8250_of_match[] = {
{ .compatible = "mediatek,mt6577-uart" }, { .compatible = "mediatek,mt6577-uart" },
{ /* Sentinel */ } { /* Sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, mtk8250_of_match);
static struct platform_driver mtk8250_platform_driver = { static struct platform_driver mtk8250_platform_driver = {
.driver = { .driver = {
.name = "mt6577-uart", .name = "mt6577-uart",
.pm = &mtk8250_pm_ops, .pm = &mtk8250_pm_ops,
.of_match_table = mtk8250_of_match, .of_match_table = mtk8250_of_match,
.suppress_bind_attrs = true,
}, },
.probe = mtk8250_probe, .probe = mtk8250_probe,
.remove = mtk8250_remove,
}; };
module_platform_driver(mtk8250_platform_driver); builtin_platform_driver(mtk8250_platform_driver);
#ifdef CONFIG_SERIAL_8250_CONSOLE #ifdef CONFIG_SERIAL_8250_CONSOLE
static int __init early_mtk8250_setup(struct earlycon_device *device, 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); OF_EARLYCON_DECLARE(mtk8250, "mediatek,mt6577-uart", early_mtk8250_setup);
#endif #endif
MODULE_AUTHOR("Matthias Brugger");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Mediatek 8250 serial port driver");

View File

@ -18,14 +18,9 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/nwpserial.h>
#include <linux/clk.h> #include <linux/clk.h>
#ifdef CONFIG_SERIAL_8250_MODULE #include "8250.h"
#define CONFIG_SERIAL_8250 CONFIG_SERIAL_8250_MODULE
#endif
#include "8250/8250.h"
struct of_serial_info { struct of_serial_info {
struct clk *clk; struct clk *clk;
@ -122,6 +117,9 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
case 1: case 1:
port->iotype = UPIO_MEM; port->iotype = UPIO_MEM;
break; break;
case 2:
port->iotype = UPIO_MEM16;
break;
case 4: case 4:
port->iotype = of_device_is_big_endian(np) ? port->iotype = of_device_is_big_endian(np) ?
UPIO_MEM32BE : UPIO_MEM32; UPIO_MEM32BE : UPIO_MEM32;
@ -195,7 +193,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
goto out; goto out;
switch (port_type) { switch (port_type) {
#ifdef CONFIG_SERIAL_8250
case PORT_8250 ... PORT_MAX_8250: case PORT_8250 ... PORT_MAX_8250:
{ {
struct uart_8250_port port8250; 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); ret = serial8250_register_8250_port(&port8250);
break; break;
} }
#endif
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
case PORT_NWPSERIAL:
ret = nwpserial_register_port(&port);
break;
#endif
default: default:
/* need to add code for these */ /* need to add code for these */
case PORT_UNKNOWN: 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); struct of_serial_info *info = platform_get_drvdata(ofdev);
switch (info->type) { switch (info->type) {
#ifdef CONFIG_SERIAL_8250
case PORT_8250 ... PORT_MAX_8250: case PORT_8250 ... PORT_MAX_8250:
serial8250_unregister_port(info->line); serial8250_unregister_port(info->line);
break; break;
#endif
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
case PORT_NWPSERIAL:
nwpserial_unregister_port(info->line);
break;
#endif
default: default:
/* need to add code for these */ /* need to add code for these */
break; break;
@ -267,7 +251,6 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_SERIAL_8250
static void of_serial_suspend_8250(struct of_serial_info *info) static void of_serial_suspend_8250(struct of_serial_info *info)
{ {
struct uart_8250_port *port8250 = serial8250_get_port(info->line); 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); 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) 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, }, .data = (void *)PORT_XSCALE, },
{ .compatible = "mrvl,pxa-uart", { .compatible = "mrvl,pxa-uart",
.data = (void *)PORT_XSCALE, }, .data = (void *)PORT_XSCALE, },
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
{ .compatible = "ibm,qpace-nwp-serial",
.data = (void *)PORT_NWPSERIAL, },
#endif
{ /* end of list */ }, { /* end of list */ },
}; };
MODULE_DEVICE_TABLE(of, of_platform_serial_table); MODULE_DEVICE_TABLE(of, of_platform_serial_table);

View File

@ -368,6 +368,18 @@ static void mem_serial_out(struct uart_port *p, int offset, int value)
writeb(value, p->membase + offset); 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) static void mem32_serial_out(struct uart_port *p, int offset, int value)
{ {
offset = offset << p->regshift; offset = offset << p->regshift;
@ -425,6 +437,11 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_out = mem_serial_out; p->serial_out = mem_serial_out;
break; break;
case UPIO_MEM16:
p->serial_in = mem16_serial_in;
p->serial_out = mem16_serial_out;
break;
case UPIO_MEM32: case UPIO_MEM32:
p->serial_in = mem32_serial_in; p->serial_in = mem32_serial_in;
p->serial_out = mem32_serial_out; 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) { switch (p->iotype) {
case UPIO_MEM: case UPIO_MEM:
case UPIO_MEM16:
case UPIO_MEM32: case UPIO_MEM32:
case UPIO_MEM32BE: case UPIO_MEM32BE:
case UPIO_AU: case UPIO_AU:
@ -2462,6 +2480,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
case UPIO_TSI: case UPIO_TSI:
case UPIO_MEM32: case UPIO_MEM32:
case UPIO_MEM32BE: case UPIO_MEM32BE:
case UPIO_MEM16:
case UPIO_MEM: case UPIO_MEM:
if (!port->mapbase) if (!port->mapbase)
break; break;
@ -2499,6 +2518,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
case UPIO_TSI: case UPIO_TSI:
case UPIO_MEM32: case UPIO_MEM32:
case UPIO_MEM32BE: case UPIO_MEM32BE:
case UPIO_MEM16:
case UPIO_MEM: case UPIO_MEM:
if (!port->mapbase) if (!port->mapbase)
break; break;

View File

@ -13,6 +13,7 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/console.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
@ -34,6 +35,29 @@ struct uniphier8250_priv {
spinlock_t atomic_write_lock; 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. * The register map is slightly different from that of 8250.
* IO callbacks must be overridden for correct access to FCR, LCR, and MCR. * IO callbacks must be overridden for correct access to FCR, LCR, and MCR.

View File

@ -361,9 +361,8 @@ config SERIAL_8250_UNIPHIER
config SERIAL_8250_INGENIC config SERIAL_8250_INGENIC
bool "Support for Ingenic SoC serial ports" bool "Support for Ingenic SoC serial ports"
depends on SERIAL_8250_CONSOLE && OF_FLATTREE depends on OF_FLATTREE
select LIBFDT select LIBFDT
select SERIAL_EARLYCON
help help
If you have a system using an Ingenic SoC and wish to make use of 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. 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" tristate "Support for serial ports on Intel MID platforms"
depends on SERIAL_8250 && PCI depends on SERIAL_8250 && PCI
select HSU_DMA if SERIAL_8250_DMA 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 select RATIONAL
help help
Selecting this option will enable handling of the extra features Selecting this option will enable handling of the extra features
present on the UART found on Intel Medfield SOC and various other present on the UART found on Intel Medfield SOC and various other
Intel platforms. 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.

View File

@ -28,5 +28,6 @@ obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o
obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.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 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt

View File

@ -115,6 +115,7 @@ config SERIAL_SB1250_DUART_CONSOLE
config SERIAL_ATMEL config SERIAL_ATMEL
bool "AT91 / AT32 on-chip serial port support" bool "AT91 / AT32 on-chip serial port support"
depends on HAS_DMA
depends on ARCH_AT91 || AVR32 || COMPILE_TEST depends on ARCH_AT91 || AVR32 || COMPILE_TEST
select SERIAL_CORE select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB select SERIAL_MCTRL_GPIO if GPIOLIB
@ -571,9 +572,11 @@ config BFIN_UART3_CTSRTS
config SERIAL_IMX config SERIAL_IMX
tristate "IMX serial port support" tristate "IMX serial port support"
depends on HAS_DMA
depends on ARCH_MXC || COMPILE_TEST depends on ARCH_MXC || COMPILE_TEST
select SERIAL_CORE select SERIAL_CORE
select RATIONAL select RATIONAL
select SERIAL_MCTRL_GPIO if GPIOLIB
help help
If you have a machine based on a Motorola IMX CPU you If you have a machine based on a Motorola IMX CPU you
can enable its onboard serial port by enabling this option. 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 If you have enabled the serial port on the Hilscher NetX SoC
you can make it the console by answering Y to this option. 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 config SERIAL_OMAP
tristate "OMAP serial port support" tristate "OMAP serial port support"
depends on ARCH_OMAP2PLUS depends on ARCH_OMAP2PLUS
@ -1131,23 +1124,6 @@ config SERIAL_OMAP_CONSOLE
your boot loader about how to pass options to the kernel at your boot loader about how to pass options to the kernel at
boot time.) 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 config SERIAL_LANTIQ
bool "Lantiq serial driver" bool "Lantiq serial driver"
depends on LANTIQ depends on LANTIQ
@ -1409,8 +1385,9 @@ config SERIAL_PCH_UART_CONSOLE
warnings and which allows logins in single user mode). warnings and which allows logins in single user mode).
config SERIAL_MXS_AUART config SERIAL_MXS_AUART
depends on ARCH_MXS || COMPILE_TEST
tristate "MXS AUART support" tristate "MXS AUART support"
depends on HAS_DMA
depends on ARCH_MXS || COMPILE_TEST
select SERIAL_CORE select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB select SERIAL_MCTRL_GPIO if GPIOLIB
help help

View File

@ -63,8 +63,6 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
obj-$(CONFIG_SERIAL_MSM) += msm_serial.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
obj-$(CONFIG_SERIAL_NETX) += netx-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_KGDB_NMI) += kgdb_nmi.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o

View File

@ -60,6 +60,8 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include "amba-pl011.h"
#define UART_NR 14 #define UART_NR 14
#define SERIAL_AMBA_MAJOR 204 #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_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
#define UART_DUMMY_DR_RX (1 << 16) #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 */ /* There is by now at least one vendor with differing details, so handle it */
struct vendor_data { struct vendor_data {
const u16 *reg_offset;
unsigned int ifls; unsigned int ifls;
unsigned int lcrh_tx; bool access_32b;
unsigned int lcrh_rx;
bool oversampling; bool oversampling;
bool dma_threshold; bool dma_threshold;
bool cts_event_workaround; bool cts_event_workaround;
@ -91,9 +109,8 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
} }
static struct vendor_data vendor_arm = { static struct vendor_data vendor_arm = {
.reg_offset = pl011_std_offsets,
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.lcrh_tx = UART011_LCRH,
.lcrh_rx = UART011_LCRH,
.oversampling = false, .oversampling = false,
.dma_threshold = false, .dma_threshold = false,
.cts_event_workaround = false, .cts_event_workaround = false,
@ -103,6 +120,7 @@ static struct vendor_data vendor_arm = {
}; };
static struct vendor_data vendor_sbsa = { static struct vendor_data vendor_sbsa = {
.reg_offset = pl011_std_offsets,
.oversampling = false, .oversampling = false,
.dma_threshold = false, .dma_threshold = false,
.cts_event_workaround = false, .cts_event_workaround = false,
@ -110,15 +128,41 @@ static struct vendor_data vendor_sbsa = {
.fixed_options = true, .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) static unsigned int get_fifosize_st(struct amba_device *dev)
{ {
return 64; return 64;
} }
static struct vendor_data vendor_st = { static struct vendor_data vendor_st = {
.reg_offset = pl011_st_offsets,
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
.lcrh_tx = ST_UART011_LCRH_TX,
.lcrh_rx = ST_UART011_LCRH_RX,
.oversampling = true, .oversampling = true,
.dma_threshold = true, .dma_threshold = true,
.cts_event_workaround = true, .cts_event_workaround = true,
@ -127,6 +171,29 @@ static struct vendor_data vendor_st = {
.get_fifosize = get_fifosize_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 */ /* Deals with DMA transactions */
struct pl011_sgbuf { struct pl011_sgbuf {
@ -162,14 +229,13 @@ struct pl011_dmatx_data {
*/ */
struct uart_amba_port { struct uart_amba_port {
struct uart_port port; struct uart_port port;
const u16 *reg_offset;
struct clk *clk; struct clk *clk;
const struct vendor_data *vendor; const struct vendor_data *vendor;
unsigned int dmacr; /* dma control reg */ unsigned int dmacr; /* dma control reg */
unsigned int im; /* interrupt mask */ unsigned int im; /* interrupt mask */
unsigned int old_status; unsigned int old_status;
unsigned int fifosize; /* vendor-specific */ unsigned int fifosize; /* vendor-specific */
unsigned int lcrh_tx; /* vendor-specific */
unsigned int lcrh_rx; /* vendor-specific */
unsigned int old_cr; /* state during shutdown */ unsigned int old_cr; /* state during shutdown */
bool autorts; bool autorts;
unsigned int fixed_baud; /* vendor-set fixed baud rate */ unsigned int fixed_baud; /* vendor-set fixed baud rate */
@ -184,6 +250,32 @@ struct uart_amba_port {
#endif #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 * 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 * 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; int fifotaken = 0;
while (max_count--) { while (max_count--) {
status = readw(uap->port.membase + UART01x_FR); status = pl011_read(uap, REG_FR);
if (status & UART01x_FR_RXFE) if (status & UART01x_FR_RXFE)
break; break;
/* Take chars from the FIFO and update status */ /* Take chars from the FIFO and update status */
ch = readw(uap->port.membase + UART01x_DR) | ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX;
UART_DUMMY_DR_RX;
flag = TTY_NORMAL; flag = TTY_NORMAL;
uap->port.icount.rx++; uap->port.icount.rx++;
fifotaken++; 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 amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
struct device *dev = uap->port.dev; struct device *dev = uap->port.dev;
struct dma_slave_config tx_conf = { 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, .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_MEM_TO_DEV, .direction = DMA_MEM_TO_DEV,
.dst_maxburst = uap->fifosize >> 1, .dst_maxburst = uap->fifosize >> 1,
@ -339,7 +431,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
if (chan) { if (chan) {
struct dma_slave_config rx_conf = { 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, .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_DEV_TO_MEM, .direction = DMA_DEV_TO_MEM,
.src_maxburst = uap->fifosize >> 2, .src_maxburst = uap->fifosize >> 2,
@ -438,7 +531,7 @@ static void pl011_dma_tx_callback(void *data)
dmacr = uap->dmacr; dmacr = uap->dmacr;
uap->dmacr = dmacr & ~UART011_TXDMAE; 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 * 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); dma_dev->device_issue_pending(chan);
uap->dmacr |= UART011_TXDMAE; uap->dmacr |= UART011_TXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_write(uap->dmacr, uap, REG_DMACR);
uap->dmatx.queued = true; uap->dmatx.queued = true;
/* /*
@ -588,9 +681,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
*/ */
if (uap->dmatx.queued) { if (uap->dmatx.queued) {
uap->dmacr |= UART011_TXDMAE; uap->dmacr |= UART011_TXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_write(uap->dmacr, uap, REG_DMACR);
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_write(uap->im, uap, REG_IMSC);
return true; return true;
} }
@ -600,7 +693,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
*/ */
if (pl011_dma_tx_refill(uap) > 0) { if (pl011_dma_tx_refill(uap) > 0) {
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_write(uap->im, uap, REG_IMSC);
return true; return true;
} }
return false; return false;
@ -614,7 +707,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
{ {
if (uap->dmatx.queued) { if (uap->dmatx.queued) {
uap->dmacr &= ~UART011_TXDMAE; 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 (!uap->dmatx.queued) {
if (pl011_dma_tx_refill(uap) > 0) { if (pl011_dma_tx_refill(uap) > 0) {
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + pl011_write(uap->im, uap, REG_IMSC);
UART011_IMSC);
} else } else
ret = false; ret = false;
} else if (!(uap->dmacr & UART011_TXDMAE)) { } else if (!(uap->dmacr & UART011_TXDMAE)) {
uap->dmacr |= UART011_TXDMAE; uap->dmacr |= UART011_TXDMAE;
writew(uap->dmacr, pl011_write(uap->dmacr, uap, REG_DMACR);
uap->port.membase + UART011_DMACR);
} }
return ret; return ret;
} }
@ -658,9 +749,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
*/ */
dmacr = uap->dmacr; dmacr = uap->dmacr;
uap->dmacr &= ~UART011_TXDMAE; 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 * No space in the FIFO, so enable the transmit interrupt
* so we know when there is space. Note that once we've * 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; 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.icount.tx++;
uap->port.x_char = 0; uap->port.x_char = 0;
/* Success - restore the DMA state */ /* Success - restore the DMA state */
uap->dmacr = dmacr; uap->dmacr = dmacr;
writew(dmacr, uap->port.membase + UART011_DMACR); pl011_write(dmacr, uap, REG_DMACR);
return true; return true;
} }
@ -703,7 +794,7 @@ __acquires(&uap->port.lock)
DMA_TO_DEVICE); DMA_TO_DEVICE);
uap->dmatx.queued = false; uap->dmatx.queued = false;
uap->dmacr &= ~UART011_TXDMAE; 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); dma_async_issue_pending(rxchan);
uap->dmacr |= UART011_RXDMAE; uap->dmacr |= UART011_RXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_write(uap->dmacr, uap, REG_DMACR);
uap->dmarx.running = true; uap->dmarx.running = true;
uap->im &= ~UART011_RXIM; uap->im &= ~UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_write(uap->im, uap, REG_IMSC);
return 0; return 0;
} }
@ -805,8 +896,8 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
*/ */
if (dma_count == pending && readfifo) { if (dma_count == pending && readfifo) {
/* Clear any error flags */ /* Clear any error flags */
writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
uap->port.membase + UART011_ICR); UART011_FEIS, uap, REG_ICR);
/* /*
* If we read all the DMA'd characters, and we had an * 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 */ /* Disable RX DMA - incoming data will wait in the FIFO */
uap->dmacr &= ~UART011_RXDMAE; uap->dmacr &= ~UART011_RXDMAE;
writew(uap->dmacr, uap->port.membase + UART011_DMACR); pl011_write(uap->dmacr, uap, REG_DMACR);
uap->dmarx.running = false; uap->dmarx.running = false;
pending = sgbuf->sg.length - state.residue; 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 " dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
"fall back to interrupt mode\n"); "fall back to interrupt mode\n");
uap->im |= UART011_RXIM; 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 " dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
"fall back to interrupt mode\n"); "fall back to interrupt mode\n");
uap->im |= UART011_RXIM; 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 */ /* FIXME. Just disable the DMA enable */
uap->dmacr &= ~UART011_RXDMAE; 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); spin_lock_irqsave(&uap->port.lock, flags);
pl011_dma_rx_stop(uap); pl011_dma_rx_stop(uap);
uap->im |= UART011_RXIM; 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); spin_unlock_irqrestore(&uap->port.lock, flags);
uap->dmarx.running = false; uap->dmarx.running = false;
@ -1041,7 +1132,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
skip_rx: skip_rx:
/* Turn on DMA error (RX/TX will be enabled on demand) */ /* Turn on DMA error (RX/TX will be enabled on demand) */
uap->dmacr |= UART011_DMAONERR; 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 * ST Micro variants has some specific dma burst threshold
@ -1049,8 +1140,8 @@ skip_rx:
* be issued above/below 16 bytes. * be issued above/below 16 bytes.
*/ */
if (uap->vendor->dma_threshold) if (uap->vendor->dma_threshold)
writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16, pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
uap->port.membase + ST_UART011_DMAWM); uap, REG_ST_DMAWM);
if (uap->using_rx_dma) { if (uap->using_rx_dma) {
if (pl011_dma_rx_trigger_dma(uap)) if (pl011_dma_rx_trigger_dma(uap))
@ -1075,12 +1166,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
return; return;
/* Disable RX and TX DMA */ /* 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(); barrier();
spin_lock_irq(&uap->port.lock); spin_lock_irq(&uap->port.lock);
uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); 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); spin_unlock_irq(&uap->port.lock);
if (uap->using_tx_dma) { 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); container_of(port, struct uart_amba_port, port);
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_write(uap->im, uap, REG_IMSC);
pl011_dma_tx_stop(uap); 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) static void pl011_start_tx_pio(struct uart_amba_port *uap)
{ {
uap->im |= UART011_TXIM; uap->im |= UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_write(uap->im, uap, REG_IMSC);
pl011_tx_chars(uap, false); 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| uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
UART011_PEIM|UART011_BEIM|UART011_OEIM); 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); 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); container_of(port, struct uart_amba_port, port);
uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM; 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) 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 " dev_dbg(uap->port.dev, "could not trigger RX DMA job "
"fall back to interrupt mode again\n"); "fall back to interrupt mode again\n");
uap->im |= UART011_RXIM; uap->im |= UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_write(uap->im, uap, REG_IMSC);
} else { } else {
#ifdef CONFIG_DMA_ENGINE #ifdef CONFIG_DMA_ENGINE
/* Start Rx DMA poll */ /* Start Rx DMA poll */
@ -1263,10 +1354,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
bool from_irq) bool from_irq)
{ {
if (unlikely(!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 */ return false; /* unable to transmit character */
writew(c, uap->port.membase + UART01x_DR); pl011_write(c, uap, REG_DR);
uap->port.icount.tx++; uap->port.icount.tx++;
return true; return true;
@ -1313,7 +1404,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
{ {
unsigned int status, delta; 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; delta = status ^ uap->old_status;
uap->old_status = status; uap->old_status = status;
@ -1341,15 +1432,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
return; return;
/* workaround to make sure that all bits are unlocked.. */ /* 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; * WA: introduce 26ns(1 uart clk) delay before W1C;
* single apb access will incur 2 pclk(133.12Mhz) delay, * single apb access will incur 2 pclk(133.12Mhz) delay,
* so add 2 dummy reads * so add 2 dummy reads
*/ */
dummy_read = readw(uap->port.membase + UART011_ICR); dummy_read = pl011_read(uap, REG_ICR);
dummy_read = readw(uap->port.membase + UART011_ICR); dummy_read = pl011_read(uap, REG_ICR);
} }
static irqreturn_t pl011_int(int irq, void *dev_id) 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; int handled = 0;
spin_lock_irqsave(&uap->port.lock, flags); spin_lock_irqsave(&uap->port.lock, flags);
imsc = readw(uap->port.membase + UART011_IMSC); imsc = pl011_read(uap, REG_IMSC);
status = readw(uap->port.membase + UART011_RIS) & imsc; status = pl011_read(uap, REG_RIS) & imsc;
if (status) { if (status) {
do { do {
check_apply_cts_event_workaround(uap); check_apply_cts_event_workaround(uap);
writew(status & ~(UART011_TXIS|UART011_RTIS| pl011_write(status & ~(UART011_TXIS|UART011_RTIS|
UART011_RXIS), UART011_RXIS),
uap->port.membase + UART011_ICR); uap, REG_ICR);
if (status & (UART011_RTIS|UART011_RXIS)) { if (status & (UART011_RTIS|UART011_RXIS)) {
if (pl011_dma_rx_running(uap)) if (pl011_dma_rx_running(uap))
@ -1386,7 +1477,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
if (pass_counter-- == 0) if (pass_counter-- == 0)
break; break;
status = readw(uap->port.membase + UART011_RIS) & imsc; status = pl011_read(uap, REG_RIS) & imsc;
} while (status != 0); } while (status != 0);
handled = 1; handled = 1;
} }
@ -1400,7 +1491,7 @@ static unsigned int pl011_tx_empty(struct uart_port *port)
{ {
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); 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; 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 = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
unsigned int result = 0; 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) \ #define TIOCMBIT(uartbit, tiocmbit) \
if (status & uartbit) \ 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); container_of(port, struct uart_amba_port, port);
unsigned int cr; unsigned int cr;
cr = readw(uap->port.membase + UART011_CR); cr = pl011_read(uap, REG_CR);
#define TIOCMBIT(tiocmbit, uartbit) \ #define TIOCMBIT(tiocmbit, uartbit) \
if (mctrl & tiocmbit) \ if (mctrl & tiocmbit) \
@ -1449,7 +1540,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
} }
#undef TIOCMBIT #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) 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; unsigned int lcr_h;
spin_lock_irqsave(&uap->port.lock, flags); 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) if (break_state == -1)
lcr_h |= UART01x_LCRH_BRK; lcr_h |= UART01x_LCRH_BRK;
else else
lcr_h &= ~UART01x_LCRH_BRK; 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); 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 = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); 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 * There is no way to clear TXIM as this is "ready to transmit IRQ", so
* we simply mask it. start_tx() will unmask it. * 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 * (including tx queue), so we're also fine with start_tx()'s caller
* side. * 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) 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); pl011_quiesce_irqs(port);
status = readw(uap->port.membase + UART01x_FR); status = pl011_read(uap, REG_FR);
if (status & UART01x_FR_RXFE) if (status & UART01x_FR_RXFE)
return NO_POLL_CHAR; 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, 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 = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); 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(); barrier();
writew(ch, uap->port.membase + UART01x_DR); pl011_write(ch, uap, REG_DR);
} }
#endif /* CONFIG_CONSOLE_POLL */ #endif /* CONFIG_CONSOLE_POLL */
@ -1546,15 +1637,16 @@ static int pl011_hwinit(struct uart_port *port)
uap->port.uartclk = clk_get_rate(uap->clk); uap->port.uartclk = clk_get_rate(uap->clk);
/* Clear pending error and receive interrupts */ /* Clear pending error and receive interrupts */
writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); UART011_FEIS | UART011_RTIS | UART011_RXIS,
uap, REG_ICR);
/* /*
* Save interrupts enable mask, and enable RX interrupts in case if * Save interrupts enable mask, and enable RX interrupts in case if
* the interrupt is used for NMI entry. * the interrupt is used for NMI entry.
*/ */
uap->im = readw(uap->port.membase + UART011_IMSC); uap->im = pl011_read(uap, REG_IMSC);
writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC);
if (dev_get_platdata(uap->port.dev)) { if (dev_get_platdata(uap->port.dev)) {
struct amba_pl011_data *plat; struct amba_pl011_data *plat;
@ -1566,24 +1658,30 @@ static int pl011_hwinit(struct uart_port *port)
return 0; 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) static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
{ {
writew(lcr_h, uap->port.membase + uap->lcrh_rx); pl011_write(lcr_h, uap, REG_LCRH_RX);
if (uap->lcrh_rx != uap->lcrh_tx) { if (pl011_split_lcrh(uap)) {
int i; int i;
/* /*
* Wait 10 PCLKs before writing LCRH_TX register, * Wait 10 PCLKs before writing LCRH_TX register,
* to get this delay write read only register 10 times * to get this delay write read only register 10 times
*/ */
for (i = 0; i < 10; ++i) for (i = 0; i < 10; ++i)
writew(0xff, uap->port.membase + UART011_MIS); pl011_write(0xff, uap, REG_MIS);
writew(lcr_h, uap->port.membase + uap->lcrh_tx); pl011_write(lcr_h, uap, REG_LCRH_TX);
} }
} }
static int pl011_allocate_irq(struct uart_amba_port *uap) 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); 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); spin_lock_irq(&uap->port.lock);
/* Clear out any spuriously appearing RX interrupts */ /* Clear out any spuriously appearing RX interrupts */
writew(UART011_RTIS | UART011_RXIS, pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
uap->port.membase + UART011_ICR);
uap->im = UART011_RTIM; uap->im = UART011_RTIM;
if (!pl011_dma_rx_running(uap)) if (!pl011_dma_rx_running(uap))
uap->im |= UART011_RXIM; 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); spin_unlock_irq(&uap->port.lock);
} }
@ -1622,21 +1719,21 @@ static int pl011_startup(struct uart_port *port)
if (retval) if (retval)
goto clk_dis; 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); spin_lock_irq(&uap->port.lock);
/* restore RTS and DTR */ /* restore RTS and DTR */
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; 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); spin_unlock_irq(&uap->port.lock);
/* /*
* initialise the old status of the modem signals * 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 */ /* Startup DMA */
pl011_dma_startup(uap); pl011_dma_startup(uap);
@ -1677,9 +1774,9 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
{ {
unsigned long val; unsigned long val;
val = readw(uap->port.membase + lcrh); val = pl011_read(uap, lcrh);
val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); 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; uap->autorts = false;
spin_lock_irq(&uap->port.lock); spin_lock_irq(&uap->port.lock);
cr = readw(uap->port.membase + UART011_CR); cr = pl011_read(uap, REG_CR);
uap->old_cr = cr; uap->old_cr = cr;
cr &= UART011_CR_RTS | UART011_CR_DTR; cr &= UART011_CR_RTS | UART011_CR_DTR;
cr |= UART01x_CR_UARTEN | UART011_CR_TXE; 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); spin_unlock_irq(&uap->port.lock);
/* /*
* disable break condition and fifos * disable break condition and fifos
*/ */
pl011_shutdown_channel(uap, uap->lcrh_rx); pl011_shutdown_channel(uap, REG_LCRH_RX);
if (uap->lcrh_rx != uap->lcrh_tx) if (pl011_split_lcrh(uap))
pl011_shutdown_channel(uap, uap->lcrh_tx); pl011_shutdown_channel(uap, REG_LCRH_TX);
} }
static void pl011_disable_interrupts(struct uart_amba_port *uap) 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 */ /* mask all interrupts and clear all pending ones */
uap->im = 0; uap->im = 0;
writew(uap->im, uap->port.membase + UART011_IMSC); pl011_write(uap->im, uap, REG_IMSC);
writew(0xffff, uap->port.membase + UART011_ICR); pl011_write(0xffff, uap, REG_ICR);
spin_unlock_irq(&uap->port.lock); spin_unlock_irq(&uap->port.lock);
} }
@ -1867,8 +1964,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
pl011_enable_ms(port); pl011_enable_ms(port);
/* first, disable everything */ /* first, disable everything */
old_cr = readw(port->membase + UART011_CR); old_cr = pl011_read(uap, REG_CR);
writew(0, port->membase + UART011_CR); pl011_write(0, uap, REG_CR);
if (termios->c_cflag & CRTSCTS) { if (termios->c_cflag & CRTSCTS) {
if (old_cr & UART011_CR_RTS) if (old_cr & UART011_CR_RTS)
@ -1901,17 +1998,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
quot -= 2; quot -= 2;
} }
/* Set baud rate */ /* Set baud rate */
writew(quot & 0x3f, port->membase + UART011_FBRD); pl011_write(quot & 0x3f, uap, REG_FBRD);
writew(quot >> 6, port->membase + UART011_IBRD); pl011_write(quot >> 6, uap, REG_IBRD);
/* /*
* ----------v----------v----------v----------v----- * ----------v----------v----------v----------v-----
* NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER * NOTE: REG_LCRH_TX and REG_LCRH_RX MUST BE WRITTEN AFTER
* UART011_FBRD & UART011_IBRD. * REG_FBRD & REG_IBRD.
* ----------^----------^----------^----------^----- * ----------^----------^----------^----------^-----
*/ */
pl011_write_lcr_h(uap, lcr_h); 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); 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 = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); 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(); barrier();
writew(ch, uap->port.membase + UART01x_DR); pl011_write(ch, uap, REG_DR);
} }
static void 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 * First save the CR then disable the interrupts
*/ */
if (!uap->vendor->always_enabled) { 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 = old_cr & ~UART011_CR_CTSEN;
new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; 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); 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 * and restore the TCR
*/ */
do { do {
status = readw(uap->port.membase + UART01x_FR); status = pl011_read(uap, REG_FR);
} while (status & UART01x_FR_BUSY); } while (status & UART01x_FR_BUSY);
if (!uap->vendor->always_enabled) if (!uap->vendor->always_enabled)
writew(old_cr, uap->port.membase + UART011_CR); pl011_write(old_cr, uap, REG_CR);
if (locked) if (locked)
spin_unlock(&uap->port.lock); spin_unlock(&uap->port.lock);
@ -2108,10 +2205,10 @@ static void __init
pl011_console_get_options(struct uart_amba_port *uap, int *baud, pl011_console_get_options(struct uart_amba_port *uap, int *baud,
int *parity, int *bits) 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; 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'; *parity = 'n';
if (lcr_h & UART01x_LCRH_PEN) { if (lcr_h & UART01x_LCRH_PEN) {
@ -2126,13 +2223,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
else else
*bits = 8; *bits = 8;
ibrd = readw(uap->port.membase + UART011_IBRD); ibrd = pl011_read(uap, REG_IBRD);
fbrd = readw(uap->port.membase + UART011_FBRD); fbrd = pl011_read(uap, REG_FBRD);
*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
if (uap->vendor->oversampling) { if (uap->vendor->oversampling) {
if (readw(uap->port.membase + UART011_CR) if (pl011_read(uap, REG_CR)
& ST_UART011_CR_OVSFACT) & ST_UART011_CR_OVSFACT)
*baud *= 2; *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) 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) 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.dev = dev;
uap->port.mapbase = mmiobase->start; uap->port.mapbase = mmiobase->start;
uap->port.membase = base; uap->port.membase = base;
uap->port.iotype = UPIO_MEM;
uap->port.fifosize = uap->fifosize; uap->port.fifosize = uap->fifosize;
uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = index; uap->port.line = index;
@ -2334,8 +2433,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
int ret; int ret;
/* Ensure interrupts from this UART are masked and cleared */ /* Ensure interrupts from this UART are masked and cleared */
writew(0, uap->port.membase + UART011_IMSC); pl011_write(0, uap, REG_IMSC);
writew(0xffff, uap->port.membase + UART011_ICR); pl011_write(0xffff, uap, REG_ICR);
if (!amba_reg.state) { if (!amba_reg.state) {
ret = uart_register_driver(&amba_reg); 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)) if (IS_ERR(uap->clk))
return PTR_ERR(uap->clk); return PTR_ERR(uap->clk);
uap->reg_offset = vendor->reg_offset;
uap->vendor = vendor; uap->vendor = vendor;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
uap->fifosize = vendor->get_fifosize(dev); uap->fifosize = vendor->get_fifosize(dev);
uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM;
uap->port.irq = dev->irq[0]; uap->port.irq = dev->irq[0];
uap->port.ops = &amba_pl011_pops; uap->port.ops = &amba_pl011_pops;
@ -2453,8 +2552,10 @@ static int sbsa_uart_probe(struct platform_device *pdev)
if (!uap) if (!uap)
return -ENOMEM; return -ENOMEM;
uap->reg_offset = vendor_sbsa.reg_offset;
uap->vendor = &vendor_sbsa; uap->vendor = &vendor_sbsa;
uap->fifosize = 32; uap->fifosize = 32;
uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM;
uap->port.irq = platform_get_irq(pdev, 0); uap->port.irq = platform_get_irq(pdev, 0);
uap->port.ops = &sbsa_uart_pops; uap->port.ops = &sbsa_uart_pops;
uap->fixed_baud = baudrate; uap->fixed_baud = baudrate;

View 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

View File

@ -22,7 +22,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
*/ */
#include <linux/module.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -155,7 +154,6 @@ struct atmel_uart_port {
struct circ_buf rx_ring; struct circ_buf rx_ring;
struct mctrl_gpios *gpios; struct mctrl_gpios *gpios;
int gpio_irq[UART_GPIO_MAX];
unsigned int tx_done_mask; unsigned int tx_done_mask;
u32 fifo_size; u32 fifo_size;
u32 rts_high; u32 rts_high;
@ -190,8 +188,6 @@ static const struct of_device_id atmel_serial_dt_ids[] = {
{ .compatible = "atmel,at91sam9260-usart" }, { .compatible = "atmel,at91sam9260-usart" },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids);
#endif #endif
static inline struct atmel_uart_port * 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; atmel_port->ms_irq_enabled = true;
if (atmel_port->gpio_irq[UART_GPIO_CTS] >= 0) if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS))
enable_irq(atmel_port->gpio_irq[UART_GPIO_CTS]);
else
ier |= ATMEL_US_CTSIC; ier |= ATMEL_US_CTSIC;
if (atmel_port->gpio_irq[UART_GPIO_DSR] >= 0) if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DSR))
enable_irq(atmel_port->gpio_irq[UART_GPIO_DSR]);
else
ier |= ATMEL_US_DSRIC; ier |= ATMEL_US_DSRIC;
if (atmel_port->gpio_irq[UART_GPIO_RI] >= 0) if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_RI))
enable_irq(atmel_port->gpio_irq[UART_GPIO_RI]);
else
ier |= ATMEL_US_RIIC; ier |= ATMEL_US_RIIC;
if (atmel_port->gpio_irq[UART_GPIO_DCD] >= 0) if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DCD))
enable_irq(atmel_port->gpio_irq[UART_GPIO_DCD]);
else
ier |= ATMEL_US_DCDIC; ier |= ATMEL_US_DCDIC;
atmel_uart_writel(port, ATMEL_US_IER, ier); 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; atmel_port->ms_irq_enabled = false;
if (atmel_port->gpio_irq[UART_GPIO_CTS] >= 0) mctrl_gpio_disable_ms(atmel_port->gpios);
disable_irq(atmel_port->gpio_irq[UART_GPIO_CTS]);
else if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS))
idr |= ATMEL_US_CTSIC; idr |= ATMEL_US_CTSIC;
if (atmel_port->gpio_irq[UART_GPIO_DSR] >= 0) if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DSR))
disable_irq(atmel_port->gpio_irq[UART_GPIO_DSR]);
else
idr |= ATMEL_US_DSRIC; idr |= ATMEL_US_DSRIC;
if (atmel_port->gpio_irq[UART_GPIO_RI] >= 0) if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_RI))
disable_irq(atmel_port->gpio_irq[UART_GPIO_RI]);
else
idr |= ATMEL_US_RIIC; idr |= ATMEL_US_RIIC;
if (atmel_port->gpio_irq[UART_GPIO_DCD] >= 0) if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_DCD))
disable_irq(atmel_port->gpio_irq[UART_GPIO_DCD]);
else
idr |= ATMEL_US_DCDIC; idr |= ATMEL_US_DCDIC;
atmel_uart_writel(port, ATMEL_US_IDR, idr); 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 uart_port *port = dev_id;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status, pending, mask, pass_counter = 0; unsigned int status, pending, mask, pass_counter = 0;
bool gpio_handled = false;
spin_lock(&atmel_port->lock_suspended); 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); status = atmel_get_lines_status(port);
mask = atmel_uart_readl(port, ATMEL_US_IMR); mask = atmel_uart_readl(port, ATMEL_US_IMR);
pending = status & mask; 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) if (!pending)
break; 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 * Perform initialization and enable port for reception
*/ */
@ -1846,13 +1772,6 @@ static int atmel_startup(struct uart_port *port)
return retval; return retval;
} }
/*
* Get the GPIO lines IRQ
*/
retval = atmel_request_gpio_irq(port);
if (retval)
goto free_irq;
tasklet_enable(&atmel_port->tasklet); tasklet_enable(&atmel_port->tasklet);
/* /*
@ -1948,11 +1867,6 @@ static int atmel_startup(struct uart_port *port)
} }
return 0; 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 the interrupts
*/ */
free_irq(port->irq, port); free_irq(port->irq, port);
atmel_free_gpio_irq(port);
atmel_port->ms_irq_enabled = false; atmel_port->ms_irq_enabled = false;
@ -2686,26 +2599,6 @@ static int atmel_serial_resume(struct platform_device *pdev)
#define atmel_serial_resume NULL #define atmel_serial_resume NULL
#endif #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, static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
struct platform_device *pdev) struct platform_device *pdev)
{ {
@ -2788,16 +2681,16 @@ static int atmel_serial_probe(struct platform_device *pdev)
spin_lock_init(&port->lock_suspended); 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); ret = atmel_init_port(port, pdev);
if (ret) if (ret)
goto err_clear_bit; 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)) { if (!atmel_use_pdc_rx(&port->uart)) {
ret = -ENOMEM; ret = -ENOMEM;
data = kmalloc(sizeof(struct atmel_uart_char) data = kmalloc(sizeof(struct atmel_uart_char)
@ -2866,37 +2759,14 @@ err:
return ret; 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 = { static struct platform_driver atmel_serial_driver = {
.probe = atmel_serial_probe, .probe = atmel_serial_probe,
.remove = atmel_serial_remove,
.suspend = atmel_serial_suspend, .suspend = atmel_serial_suspend,
.resume = atmel_serial_resume, .resume = atmel_serial_resume,
.driver = { .driver = {
.name = "atmel_usart", .name = "atmel_usart",
.of_match_table = of_match_ptr(atmel_serial_dt_ids), .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; return ret;
} }
device_initcall(atmel_serial_init);
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");

View File

@ -653,7 +653,7 @@ static struct uart_ops bcm_uart_ops = {
#ifdef CONFIG_SERIAL_BCM63XX_CONSOLE #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; unsigned int tmout;

View File

@ -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) static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
{ {
unsigned int status, ch, flg; unsigned int status, ch, flg;
static struct timeval anomaly_start = { .tv_sec = 0 }; static u64 anomaly_start;
status = UART_GET_LSR(uart); status = UART_GET_LSR(uart);
UART_CLEAR_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 * character time +/- some percent. So 1.5 sounds good. All other
* Blackfin families operate properly. Woo. * Blackfin families operate properly. Woo.
*/ */
if (anomaly_start.tv_sec) { if (anomaly_start > 0) {
struct timeval curr; u64 curr, nsecs, threshold_ns;
suseconds_t usecs;
if ((~ch & (~ch + 1)) & 0xff) if ((~ch & (~ch + 1)) & 0xff)
goto known_good_char; goto known_good_char;
do_gettimeofday(&curr); curr = ktime_get_ns();
if (curr.tv_sec - anomaly_start.tv_sec > 1) nsecs = curr - anomaly_start;
if (nsecs >> 32)
goto known_good_char; goto known_good_char;
usecs = 0; threshold_ns = UART_GET_ANOMALY_THRESHOLD(uart)
if (curr.tv_sec != anomaly_start.tv_sec) * NSEC_PER_USEC;
usecs += USEC_PER_SEC; if (nsecs > threshold_ns)
usecs += curr.tv_usec - anomaly_start.tv_usec;
if (usecs > UART_GET_ANOMALY_THRESHOLD(uart))
goto known_good_char; goto known_good_char;
if (ch) if (ch)
anomaly_start.tv_sec = 0; anomaly_start = 0;
else else
anomaly_start = curr; anomaly_start = curr;
@ -274,14 +271,14 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
known_good_char: known_good_char:
status &= ~BI; status &= ~BI;
anomaly_start.tv_sec = 0; anomaly_start = 0;
} }
} }
if (status & BI) { if (status & BI) {
if (ANOMALY_05000363) if (ANOMALY_05000363)
if (bfin_revid() < 5) if (bfin_revid() < 5)
do_gettimeofday(&anomaly_start); anomaly_start = ktime_get_ns();
uart->port.icount.brk++; uart->port.icount.brk++;
if (uart_handle_break(&uart->port)) if (uart_handle_break(&uart->port))
goto ignore_char; goto ignore_char;

View File

@ -71,10 +71,16 @@ static int __init parse_options(struct earlycon_device *device, char *options)
return -EINVAL; return -EINVAL;
switch (port->iotype) { 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_MEM32:
case UPIO_MEM32BE: case UPIO_MEM32BE:
port->regshift = 2; /* fall-through */ port->regshift = 2;
case UPIO_MEM:
port->mapbase = addr; port->mapbase = addr;
break; break;
case UPIO_PORT: case UPIO_PORT:
@ -91,10 +97,11 @@ static int __init parse_options(struct earlycon_device *device, char *options)
strlcpy(device->options, options, length); strlcpy(device->options, options, length);
} }
if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32 || if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 ||
port->iotype == UPIO_MEM32BE) port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE)
pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
(port->iotype == UPIO_MEM) ? "" : (port->iotype == UPIO_MEM) ? "" :
(port->iotype == UPIO_MEM16) ? "16" :
(port->iotype == UPIO_MEM32) ? "32" : "32be", (port->iotype == UPIO_MEM32) ? "32" : "32be",
(unsigned long long)port->mapbase, (unsigned long long)port->mapbase,
device->options); device->options);

View File

@ -22,7 +22,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
*/ */
#define SERIAL_DO_RESTART
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>

View File

@ -44,6 +44,8 @@
#include <linux/platform_data/serial-imx.h> #include <linux/platform_data/serial-imx.h>
#include <linux/platform_data/dma-imx.h> #include <linux/platform_data/dma-imx.h>
#include "serial_mctrl_gpio.h"
/* Register definitions */ /* Register definitions */
#define URXD0 0x0 /* Receiver Register */ #define URXD0 0x0 /* Receiver Register */
#define URTX0 0x40 /* Transmitter Register */ #define URTX0 0x40 /* Transmitter Register */
@ -148,8 +150,11 @@
#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ #define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */
#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ #define USR2_DTRF (1<<13) /* DTR edge interrupt flag */
#define USR2_IDLE (1<<12) /* Idle condition */ #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_IRINT (1<<8) /* Serial infrared interrupt flag */
#define USR2_WAKE (1<<7) /* Wake */ #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_RTSF (1<<4) /* RTS edge interrupt flag */
#define USR2_TXDC (1<<3) /* Transmitter complete */ #define USR2_TXDC (1<<3) /* Transmitter complete */
#define USR2_BRCD (1<<2) /* Break condition */ #define USR2_BRCD (1<<2) /* Break condition */
@ -206,6 +211,8 @@ struct imx_port {
struct clk *clk_per; struct clk *clk_per;
const struct imx_uart_data *devdata; const struct imx_uart_data *devdata;
struct mctrl_gpios *gpios;
/* DMA fields */ /* DMA fields */
unsigned int dma_is_inited:1; unsigned int dma_is_inited:1;
unsigned int dma_is_enabled:1; unsigned int dma_is_enabled:1;
@ -308,49 +315,24 @@ static void imx_port_ucrs_restore(struct uart_port *port,
} }
#endif #endif
/* static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2)
* 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; *ucr2 &= ~UCR2_CTSC;
*ucr2 |= UCR2_CTS;
status = sport->port.ops->get_mctrl(&sport->port); mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS);
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);
} }
/* static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2)
* 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; *ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
unsigned long flags;
if (sport->port.state) { mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS);
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); 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) { readl(port->membase + USR2) & USR2_TXDC) {
temp = readl(port->membase + UCR2); temp = readl(port->membase + UCR2);
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
temp &= ~UCR2_CTS; imx_port_rts_inactive(sport, &temp);
else else
temp |= UCR2_CTS; imx_port_rts_active(sport, &temp);
writel(temp, port->membase + UCR2); writel(temp, port->membase + UCR2);
temp = readl(port->membase + UCR4); 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; struct imx_port *sport = (struct imx_port *)port;
mod_timer(&sport->timer, jiffies); mod_timer(&sport->timer, jiffies);
mctrl_gpio_enable_ms(sport->gpios);
} }
static void imx_dma_tx(struct imx_port *sport); 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; unsigned long temp;
if (port->rs485.flags & SER_RS485_ENABLED) { if (port->rs485.flags & SER_RS485_ENABLED) {
/* enable transmitter and shifter empty irq */
temp = readl(port->membase + UCR2); temp = readl(port->membase + UCR2);
if (port->rs485.flags & SER_RS485_RTS_ON_SEND) if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
temp &= ~UCR2_CTS; imx_port_rts_inactive(sport, &temp);
else else
temp |= UCR2_CTS; imx_port_rts_active(sport, &temp);
writel(temp, port->membase + UCR2); writel(temp, port->membase + UCR2);
/* enable transmitter and shifter empty irq */
temp = readl(port->membase + UCR4); temp = readl(port->membase + UCR4);
temp |= UCR4_TCEN; temp |= UCR4_TCEN;
writel(temp, port->membase + UCR4); 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. * 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) static unsigned int imx_get_mctrl(struct uart_port *port)
{ {
struct imx_port *sport = (struct imx_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) mctrl_gpio_get(sport->gpios, &ret);
tmp |= TIOCM_CTS;
if (readl(sport->port.membase + UCR2) & UCR2_CTS) return ret;
tmp |= TIOCM_RTS;
if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP)
tmp |= TIOCM_LOOP;
return tmp;
} }
static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) 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); 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; temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
if (mctrl & TIOCM_LOOP) if (mctrl & TIOCM_LOOP)
temp |= UTS_LOOP; temp |= UTS_LOOP;
writel(temp, sport->port.membase + uts_reg(sport)); 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); 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) #define RX_BUF_SIZE (PAGE_SIZE)
static void imx_rx_dma_done(struct imx_port *sport) 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); imx_uart_dma_exit(sport);
} }
mctrl_gpio_disable_ms(sport->gpios);
spin_lock_irqsave(&sport->port.lock, flags); spin_lock_irqsave(&sport->port.lock, flags);
temp = readl(sport->port.membase + UCR2); temp = readl(sport->port.membase + UCR2);
temp &= ~(UCR2_TXEN); 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; struct imx_port *sport = (struct imx_port *)port;
unsigned long flags; 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 old_csize = old ? old->c_cflag & CSIZE : CS8;
unsigned int div, ufcr; unsigned long div, ufcr;
unsigned long num, denom; unsigned long num, denom;
uint64_t tdiv64; uint64_t tdiv64;
@ -1315,19 +1366,25 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
* it under manual control and keep transmitter * it under manual control and keep transmitter
* disabled. * disabled.
*/ */
if (!(port->rs485.flags & if (port->rs485.flags &
SER_RS485_RTS_AFTER_SEND)) SER_RS485_RTS_AFTER_SEND)
ucr2 |= UCR2_CTS; imx_port_rts_inactive(sport, &ucr2);
else
imx_port_rts_active(sport, &ucr2);
} else { } else {
ucr2 |= UCR2_CTSC; imx_port_rts_auto(sport, &ucr2);
} }
} else { } else {
termios->c_cflag &= ~CRTSCTS; termios->c_cflag &= ~CRTSCTS;
} }
} else if (port->rs485.flags & SER_RS485_ENABLED) } else if (port->rs485.flags & SER_RS485_ENABLED) {
/* disable transmitter */ /* disable transmitter */
if (!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND)) if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
ucr2 |= UCR2_CTS; imx_port_rts_inactive(sport, &ucr2);
else
imx_port_rts_active(sport, &ucr2);
}
if (termios->c_cflag & CSTOPB) if (termios->c_cflag & CSTOPB)
ucr2 |= UCR2_STPB; ucr2 |= UCR2_STPB;
@ -1568,11 +1625,10 @@ static int imx_rs485_config(struct uart_port *port,
/* disable transmitter */ /* disable transmitter */
temp = readl(sport->port.membase + UCR2); temp = readl(sport->port.membase + UCR2);
temp &= ~UCR2_CTSC;
if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
temp &= ~UCR2_CTS; imx_port_rts_inactive(sport, &temp);
else else
temp |= UCR2_CTS; imx_port_rts_active(sport, &temp);
writel(temp, sport->port.membase + UCR2); 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 platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; 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; int ret;
if (!np) sport->devdata = of_device_get_match_data(&pdev->dev);
if (!sport->devdata)
/* no device tree device */ /* no device tree device */
return 1; 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)) if (of_get_property(np, "fsl,dte-mode", NULL))
sport->dte_mode = 1; sport->dte_mode = 1;
sport->devdata = of_id->data;
return 0; return 0;
} }
#else #else
@ -1948,6 +2001,10 @@ static int serial_imx_probe(struct platform_device *pdev)
sport->timer.function = imx_timeout; sport->timer.function = imx_timeout;
sport->timer.data = (unsigned long)sport; 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"); sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(sport->clk_ipg)) { if (IS_ERR(sport->clk_ipg)) {
ret = PTR_ERR(sport->clk_ipg); ret = PTR_ERR(sport->clk_ipg);

View File

@ -70,7 +70,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out; goto out;
} }
rc = pci_request_regions(pdev, "jsm"); rc = pci_request_regions(pdev, JSM_DRIVER_NAME);
if (rc) { if (rc) {
dev_err(&pdev->dev, "pci_request_region FAILED\n"); dev_err(&pdev->dev, "pci_request_region FAILED\n");
goto out_disable_device; goto out_disable_device;
@ -328,7 +328,7 @@ static struct pci_device_id jsm_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
static struct pci_driver jsm_driver = { static struct pci_driver jsm_driver = {
.name = "jsm", .name = JSM_DRIVER_NAME,
.id_table = jsm_pci_tbl, .id_table = jsm_pci_tbl,
.probe = jsm_probe_one, .probe = jsm_probe_one,
.remove = jsm_remove_one, .remove = jsm_remove_one,

View File

@ -714,7 +714,7 @@ static void neo_clear_break(struct jsm_channel *ch)
/* /*
* Parse the ISR register. * 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; struct jsm_channel *ch;
u8 isr; u8 isr;

View File

@ -990,7 +990,7 @@ static void __init m32r_sio_register_ports(struct uart_driver *drv)
/* /*
* Wait for transmitter & holding register to empty * 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; unsigned int status, tmout = 10000;

View File

@ -158,7 +158,7 @@ static inline void men_z135_reg_set(struct men_z135_port *uart,
* @addr: Register address * @addr: Register address
* @val: value to clear * @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) u32 addr, u32 val)
{ {
struct uart_port *port = &uart->port; struct uart_port *port = &uart->port;

View File

@ -57,6 +57,7 @@
#define AML_UART_RX_EMPTY BIT(20) #define AML_UART_RX_EMPTY BIT(20)
#define AML_UART_TX_FULL BIT(21) #define AML_UART_TX_FULL BIT(21)
#define AML_UART_TX_EMPTY BIT(22) #define AML_UART_TX_EMPTY BIT(22)
#define AML_UART_XMIT_BUSY BIT(25)
#define AML_UART_ERR (AML_UART_PARITY_ERR | \ #define AML_UART_ERR (AML_UART_PARITY_ERR | \
AML_UART_FRAME_ERR | \ AML_UART_FRAME_ERR | \
AML_UART_TX_FIFO_WERR) AML_UART_TX_FIFO_WERR)
@ -100,7 +101,8 @@ static unsigned int meson_uart_tx_empty(struct uart_port *port)
u32 val; u32 val;
val = readl(port->membase + AML_UART_STATUS); 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) 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; u32 val;
val = readl(port->membase + AML_UART_CONTROL); 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); 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); spin_lock_irqsave(&port->lock, flags);
val = readl(port->membase + AML_UART_CONTROL); 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); val &= ~(AML_UART_RX_INT_EN | AML_UART_TX_INT_EN);
writel(val, port->membase + AML_UART_CONTROL); 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; struct circ_buf *xmit = &port->state->xmit;
unsigned int ch; unsigned int ch;
u32 val;
if (uart_tx_stopped(port)) { if (uart_tx_stopped(port)) {
meson_uart_stop_tx(port); meson_uart_stop_tx(port);
@ -165,6 +168,12 @@ static void meson_uart_start_tx(struct uart_port *port)
port->icount.tx++; 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) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port); 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)) if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY))
meson_receive_chars(port); meson_receive_chars(port);
if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)) if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)) {
meson_uart_start_tx(port); if (readl(port->membase + AML_UART_CONTROL) & AML_UART_TX_INT_EN)
meson_uart_start_tx(port);
}
spin_unlock(&port->lock); 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; 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; u32 val;
int ret = 0;
val = readl(port->membase + AML_UART_CONTROL); val = readl(port->membase + AML_UART_CONTROL);
val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); 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); val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
writel(val, port->membase + AML_UART_CONTROL); 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); val |= (AML_UART_RX_EN | AML_UART_TX_EN);
writel(val, port->membase + AML_UART_CONTROL); 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; u32 val;
while (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_EMPTY)) while (!meson_uart_tx_empty(port))
cpu_relax(); cpu_relax();
val = readl(port->membase + AML_UART_REG5); val = readl(port->membase + AML_UART_REG5);
@ -367,9 +389,26 @@ static int meson_uart_verify_port(struct uart_port *port,
return ret; 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) static void meson_uart_release_port(struct uart_port *port)
{ {
int size = meson_uart_res_size(port);
if (port->flags & UPF_IOREMAP) { if (port->flags & UPF_IOREMAP) {
devm_release_mem_region(port->dev, port->mapbase, size);
devm_iounmap(port->dev, port->membase); devm_iounmap(port->dev, port->membase);
port->membase = NULL; 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) static int meson_uart_request_port(struct uart_port *port)
{ {
struct platform_device *pdev = to_platform_device(port->dev); int size = meson_uart_res_size(port);
struct resource *res;
int size;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (size < 0)
if (!res) { return size;
dev_err(&pdev->dev, "cannot obtain I/O memory region");
return -ENODEV;
}
size = resource_size(res);
if (!devm_request_mem_region(port->dev, port->mapbase, size, if (!devm_request_mem_region(port->dev, port->mapbase, size,
dev_name(port->dev))) { dev_name(port->dev))) {
@ -448,6 +481,7 @@ static void meson_serial_console_write(struct console *co, const char *s,
struct uart_port *port; struct uart_port *port;
unsigned long flags; unsigned long flags;
int locked; int locked;
u32 val, tmp;
port = meson_ports[co->index]; port = meson_ports[co->index];
if (!port) if (!port)
@ -463,7 +497,13 @@ static void meson_serial_console_write(struct console *co, const char *s,
locked = 1; 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); uart_console_write(port, s, count, meson_console_putchar);
writel(val, port->membase + AML_UART_CONTROL);
if (locked) if (locked)
spin_unlock(&port->lock); spin_unlock(&port->lock);
@ -570,6 +610,12 @@ static int meson_uart_probe(struct platform_device *pdev)
meson_ports[pdev->id] = port; meson_ports[pdev->id] = port;
platform_set_drvdata(pdev, 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); ret = uart_add_one_port(&meson_uart_driver, port);
if (ret) if (ret)
meson_ports[pdev->id] = NULL; meson_ports[pdev->id] = NULL;

View File

@ -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 */

View File

@ -1165,7 +1165,7 @@ serial_omap_type(struct uart_port *port)
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) #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; unsigned int status, tmout = 10000;

View File

@ -603,7 +603,7 @@ static struct uart_driver serial_pxa_reg;
/* /*
* Wait for transmitter & holding register to empty * 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; unsigned int status, tmout = 10000;

View File

@ -389,6 +389,13 @@ static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
const u8 line = sc16is7xx_line(port); const u8 line = sc16is7xx_line(port);
u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line; 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); regcache_cache_bypass(s->regmap, true);
regmap_raw_write(s->regmap, addr, s->buf, to_send); regmap_raw_write(s->regmap, addr, s->buf, to_send);
regcache_cache_bypass(s->regmap, false); regcache_cache_bypass(s->regmap, false);
@ -630,6 +637,12 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
if (likely(to_send)) { if (likely(to_send)) {
/* Limit to size of TX FIFO */ /* Limit to size of TX FIFO */
txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG); 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; to_send = (to_send > txlen) ? txlen : to_send;
/* Add data to send */ /* Add data to send */

View File

@ -110,7 +110,7 @@ static void uart_start(struct tty_struct *tty)
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
} }
static inline void static void
uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
{ {
unsigned long flags; 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) * @options: ptr for <options> field; NULL if not present (out)
* *
* Decodes earlycon kernel command line parameters of the form * Decodes earlycon kernel command line parameters of the form
* earlycon=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options> * earlycon=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
* console=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options> * console=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
* *
* The optional form * The optional form
* earlycon=<name>,0x<addr>,<options> * 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) { if (strncmp(p, "mmio,", 5) == 0) {
*iotype = UPIO_MEM; *iotype = UPIO_MEM;
p += 5; p += 5;
} else if (strncmp(p, "mmio16,", 7) == 0) {
*iotype = UPIO_MEM16;
p += 7;
} else if (strncmp(p, "mmio32,", 7) == 0) { } else if (strncmp(p, "mmio32,", 7) == 0) {
*iotype = UPIO_MEM32; *iotype = UPIO_MEM32;
p += 7; 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); "I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
break; break;
case UPIO_MEM: case UPIO_MEM:
case UPIO_MEM16:
case UPIO_MEM32: case UPIO_MEM32:
case UPIO_MEM32BE: case UPIO_MEM32BE:
case UPIO_AU: case UPIO_AU:
@ -2831,6 +2835,7 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
return (port1->iobase == port2->iobase) && return (port1->iobase == port2->iobase) &&
(port1->hub6 == port2->hub6); (port1->hub6 == port2->hub6);
case UPIO_MEM: case UPIO_MEM:
case UPIO_MEM16:
case UPIO_MEM32: case UPIO_MEM32:
case UPIO_MEM32BE: case UPIO_MEM32BE:
case UPIO_AU: case UPIO_AU:

View File

@ -193,6 +193,7 @@ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
return gpios; return gpios;
} }
EXPORT_SYMBOL_GPL(mctrl_gpio_init);
void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios) 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]); disable_irq(gpios->irq[i]);
} }
} }
EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms);

View File

@ -2,6 +2,7 @@
* SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
* *
* Copyright (C) 2002 - 2011 Paul Mundt * Copyright (C) 2002 - 2011 Paul Mundt
* Copyright (C) 2015 Glider bvba
* Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007). * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
* *
* based off of the old drivers/char/sh-sci.c by: * based off of the old drivers/char/sh-sci.c by:
@ -38,7 +39,6 @@
#include <linux/major.h> #include <linux/major.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/notifier.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
@ -76,6 +76,14 @@ enum {
((port)->irqs[SCIx_ERI_IRQ] && \ ((port)->irqs[SCIx_ERI_IRQ] && \
((port)->irqs[SCIx_RXI_IRQ] < 0)) ((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 sci_port {
struct uart_port port; struct uart_port port;
@ -92,10 +100,9 @@ struct sci_port {
struct timer_list break_timer; struct timer_list break_timer;
int break_flag; int break_flag;
/* Interface clock */ /* Clocks */
struct clk *iclk; struct clk *clks[SCI_NUM_CLKS];
/* Function clock */ unsigned long clk_rates[SCI_NUM_CLKS];
struct clk *fclk;
int irqs[SCIx_NR_IRQS]; int irqs[SCIx_NR_IRQS];
char *irqstr[SCIx_NR_IRQS]; char *irqstr[SCIx_NR_IRQS];
@ -116,8 +123,6 @@ struct sci_port {
struct timer_list rx_timer; struct timer_list rx_timer;
unsigned int rx_timeout; unsigned int rx_timeout;
#endif #endif
struct notifier_block freq_transition;
}; };
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS #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, [HSSRR] = sci_reg_invalid,
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = { 0x30, 16 }, [SCPCR] = { 0x30, 16 },
[SCPDR] = { 0x34, 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = { 0x30, 16 }, [SCPCR] = { 0x30, 16 },
[SCPDR] = { 0x34, 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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 }, [HSSRR] = { 0x40, 16 },
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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, [HSSRR] = sci_reg_invalid,
[SCPCR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid,
[SCPDR] = 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) static void sci_port_enable(struct sci_port *sci_port)
{ {
unsigned int i;
if (!sci_port->port.dev) if (!sci_port->port.dev)
return; return;
pm_runtime_get_sync(sci_port->port.dev); pm_runtime_get_sync(sci_port->port.dev);
clk_prepare_enable(sci_port->iclk); for (i = 0; i < SCI_NUM_CLKS; i++) {
sci_port->port.uartclk = clk_get_rate(sci_port->iclk); clk_prepare_enable(sci_port->clks[i]);
clk_prepare_enable(sci_port->fclk); 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) static void sci_port_disable(struct sci_port *sci_port)
{ {
unsigned int i;
if (!sci_port->port.dev) if (!sci_port->port.dev)
return; return;
@ -475,8 +532,8 @@ static void sci_port_disable(struct sci_port *sci_port)
del_timer_sync(&sci_port->break_timer); del_timer_sync(&sci_port->break_timer);
sci_port->break_flag = 0; sci_port->break_flag = 0;
clk_disable_unprepare(sci_port->fclk); for (i = SCI_NUM_CLKS; i-- > 0; )
clk_disable_unprepare(sci_port->iclk); clk_disable_unprepare(sci_port->clks[i]);
pm_runtime_put_sync(sci_port->port.dev); pm_runtime_put_sync(sci_port->port.dev);
} }
@ -1606,29 +1663,6 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
return ret; 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 { static const struct sci_irq_desc {
const char *desc; const char *desc;
irq_handler_t handler; irq_handler_t handler;
@ -1864,90 +1898,149 @@ static void sci_shutdown(struct uart_port *port)
sci_free_irq(s); sci_free_irq(s);
} }
static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, static int sci_sck_calc(struct sci_port *s, unsigned int bps,
unsigned long freq) unsigned int *srr)
{ {
if (s->sampling_rate) unsigned long freq = s->clk_rates[SCI_SCK];
return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; unsigned int min_sr, max_sr, sr;
int err, min_err = INT_MAX;
/* Warn, but use a safe default */ if (s->sampling_rate) {
WARN_ON(1); /* 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_brg_calc(struct sci_port *s, unsigned int bps,
static int sci_baud_calc_frame_len(unsigned int smr_val) 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) if (s->sampling_rate) {
len--; /* SCIF has a fixed sampling rate */
if (smr_val & SCSMR_PE) min_sr = max_sr = s->sampling_rate / 2;
len++; } else {
if (smr_val & SCSMR_STOP) /* HSCIF has a variable 1/(8..32) sampling rate */
len++; 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 */
/* calculate sample rate, BRR, and clock select for HSCIF */ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, unsigned int *brr, unsigned int *srr,
int *brr, unsigned int *srr, unsigned int *cks)
unsigned int *cks, int frame_len)
{ {
int sr, c, br, err, recv_margin; unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c;
int min_err = 1000; /* 100% */ unsigned long freq = s->clk_rates[SCI_FCK];
int recv_max_margin = 0; int err, min_err = INT_MAX;
/* Find the combination of sample rate and clock select with the if (s->sampling_rate) {
smallest deviation from the desired baud rate. */ min_sr = max_sr = s->sampling_rate;
for (sr = 8; sr <= 32; sr++) { 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++) { for (c = 0; c <= 3; c++) {
/* integerized formulas from HSCIF documentation */ /* integerized formulas from HSCIF documentation */
br = DIV_ROUND_CLOSEST(freq, (sr * prediv = sr * (1 << (2 * c + shift));
(1 << (2 * c + 1)) * bps)) - 1;
br = clamp(br, 0, 255); /*
err = DIV_ROUND_CLOSEST(freq, ((br + 1) * bps * sr * * We need to calculate:
(1 << (2 * c + 1)) / 1000)) -
1000;
/* Calc recv margin
* M: Receive margin (%)
* N: Ratio of bit rate to clock (N = sampling rate)
* D: Clock duty (D = 0 to 1.0)
* L: Frame length (L = 9 to 12)
* F: Absolute value of clock frequency deviation
* *
* M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) - * br = freq / (prediv * bps) clamped to [1..256]
* (|D - 0.5| / N * (1 + F))| * err = freq / (br * prediv) - bps
* NOTE: Usually, treat D for 0.5, F is 0 by this *
* calculation. * Watch out for overflow when calculating the desired
* sampling clock rate!
*/ */
recv_margin = abs((500 - if (bps > UINT_MAX / prediv)
DIV_ROUND_CLOSEST(1000, sr << 1)) / 10); break;
if (abs(min_err) > abs(err)) {
min_err = err; scrate = prediv * bps;
recv_max_margin = recv_margin; br = DIV_ROUND_CLOSEST(freq, scrate);
} else if ((min_err == err) && br = clamp(br, 1U, 256U);
(recv_margin > recv_max_margin))
recv_max_margin = recv_margin; err = DIV_ROUND_CLOSEST(freq, br * prediv) - bps;
else if (abs(err) >= abs(min_err))
continue; continue;
*brr = br; min_err = err;
*brr = br - 1;
*srr = sr - 1; *srr = sr - 1;
*cks = c; *cks = c;
if (!err)
goto found;
} }
} }
if (min_err == 1000) { found:
WARN_ON(1); dev_dbg(s->port.dev, "BRR: %u%+d bps using N %u SR %u cks %u\n", bps,
/* use defaults */ min_err, *brr, *srr + 1, *cks);
*brr = 255; return min_err;
*srr = 15;
*cks = 0;
}
} }
static void sci_reset(struct uart_port *port) 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, static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old) 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); struct sci_port *s = to_sci_port(port);
const struct plat_sci_reg *reg; const struct plat_sci_reg *reg;
unsigned int baud, smr_val = 0, max_baud, cks = 0; int min_err = INT_MAX, err;
int t = -1; unsigned long max_freq = 0;
unsigned int srr = 15; int best_clk = -1;
if ((termios->c_cflag & CSIZE) == CS7) if ((termios->c_cflag & CSIZE) == CS7)
smr_val |= SCSMR_CHR; 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 * that the previous boot loader has enabled required clocks and
* setup the baud rate generator hardware for us already. * 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); for (i = 0; i < SCI_NUM_CLKS; i++)
if (likely(baud && port->uartclk)) { max_freq = max(max_freq, s->clk_rates[i]);
if (s->cfg->type == PORT_HSCIF) {
int frame_len = sci_baud_calc_frame_len(smr_val); baud = uart_get_baud_rate(port, termios, old, 0,
sci_baud_calc_hscif(baud, port->uartclk, &t, &srr, max_freq / max(s->sampling_rate, 8U));
&cks, frame_len); if (!baud)
} else { goto done;
t = sci_scbrr_calc(s, baud, port->uartclk);
for (cks = 0; t >= 256 && cks <= 3; cks++) /*
t >>= 2; * 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); 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); sci_reset(port);
smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS;
uart_update_timeout(port, termios->c_cflag, baud); uart_update_timeout(port, termios->c_cflag, baud);
dev_dbg(port->dev, "%s: SMR %x, cks %x, t %x, SCSCR %x\n", if (best_clk >= 0) {
__func__, smr_val, cks, t, s->cfg->scscr); smr_val |= cks;
dev_dbg(port->dev,
if (t >= 0) { "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n",
serial_port_out(port, SCSMR, (smr_val & ~SCSMR_CKS) | cks); scr_val, smr_val, brr, sccks, dl, srr);
serial_port_out(port, SCBRR, t); serial_port_out(port, SCSCR, scr_val);
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
serial_port_out(port, SCSMR, smr_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); 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, 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 #ifdef CONFIG_SERIAL_SH_SCI_DMA
/* /*
@ -2241,6 +2421,63 @@ static struct uart_ops sci_uart_ops = {
#endif #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, static int sci_init_single(struct platform_device *dev,
struct sci_port *sci_port, unsigned int index, struct sci_port *sci_port, unsigned int index,
struct plat_sci_port *p, bool early) 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; sci_port->sampling_rate = p->sampling_rate;
if (!early) { if (!early) {
sci_port->iclk = clk_get(&dev->dev, "sci_ick"); ret = sci_init_clocks(sci_port, &dev->dev);
if (IS_ERR(sci_port->iclk)) { if (ret < 0)
sci_port->iclk = clk_get(&dev->dev, "peripheral_clk"); return ret;
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;
port->dev = &dev->dev; 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) static void sci_cleanup_single(struct sci_port *port)
{ {
clk_put(port->iclk);
clk_put(port->fclk);
pm_runtime_disable(port->port.dev); 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 sci_port *sci_port = &sci_ports[co->index];
struct uart_port *port = &sci_port->port; struct uart_port *port = &sci_port->port;
unsigned short bits, ctrl; unsigned short bits, ctrl, ctrl_temp;
unsigned long flags; unsigned long flags;
int locked = 1; int locked = 1;
@ -2438,9 +2659,11 @@ static void serial_console_write(struct console *co, const char *s,
else else
spin_lock(&port->lock); 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); 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); 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); 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); uart_remove_one_port(&sci_uart_driver, &port->port);
sci_cleanup_single(port); sci_cleanup_single(port);
@ -2569,42 +2789,44 @@ static int sci_remove(struct platform_device *dev)
return 0; return 0;
} }
struct sci_port_info {
unsigned int type; #define SCI_OF_DATA(type, regtype) (void *)((type) << 16 | (regtype))
unsigned int 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[] = { 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", .compatible = "renesas,scif",
.data = &(const struct sci_port_info) { .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_REGTYPE),
.type = PORT_SCIF,
.regtype = SCIx_SH4_SCIF_REGTYPE,
},
}, { }, {
.compatible = "renesas,scifa", .compatible = "renesas,scifa",
.data = &(const struct sci_port_info) { .data = SCI_OF_DATA(PORT_SCIFA, SCIx_SCIFA_REGTYPE),
.type = PORT_SCIFA,
.regtype = SCIx_SCIFA_REGTYPE,
},
}, { }, {
.compatible = "renesas,scifb", .compatible = "renesas,scifb",
.data = &(const struct sci_port_info) { .data = SCI_OF_DATA(PORT_SCIFB, SCIx_SCIFB_REGTYPE),
.type = PORT_SCIFB,
.regtype = SCIx_SCIFB_REGTYPE,
},
}, { }, {
.compatible = "renesas,hscif", .compatible = "renesas,hscif",
.data = &(const struct sci_port_info) { .data = SCI_OF_DATA(PORT_HSCIF, SCIx_HSCIF_REGTYPE),
.type = PORT_HSCIF,
.regtype = SCIx_HSCIF_REGTYPE,
},
}, { }, {
.compatible = "renesas,sci", .compatible = "renesas,sci",
.data = &(const struct sci_port_info) { .data = SCI_OF_DATA(PORT_SCI, SCIx_SCI_REGTYPE),
.type = PORT_SCI,
.regtype = SCIx_SCI_REGTYPE,
},
}, { }, {
/* Terminator */ /* Terminator */
}, },
@ -2616,24 +2838,21 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match; const struct of_device_id *match;
const struct sci_port_info *info;
struct plat_sci_port *p; struct plat_sci_port *p;
int id; int id;
if (!IS_ENABLED(CONFIG_OF) || !np) if (!IS_ENABLED(CONFIG_OF) || !np)
return NULL; return NULL;
match = of_match_node(of_sci_match, pdev->dev.of_node); match = of_match_node(of_sci_match, np);
if (!match) if (!match)
return NULL; return NULL;
info = match->data;
p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL); p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
if (!p) if (!p)
return NULL; 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"); id = of_alias_get_id(np, "serial");
if (id < 0) { if (id < 0) {
dev_err(&pdev->dev, "failed to get alias id (%d)\n", id); 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; *dev_id = id;
p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
p->type = info->type; p->type = SCI_OF_TYPE(match->data);
p->regtype = info->regtype; p->regtype = SCI_OF_REGTYPE(match->data);
p->scscr = SCSCR_RE | SCSCR_TE; p->scscr = SCSCR_RE | SCSCR_TE;
return p; return p;
@ -2714,16 +2933,6 @@ static int sci_probe(struct platform_device *dev)
if (ret) if (ret)
return 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 #ifdef CONFIG_SH_STANDARD_BIOS
sh_bios_gdb_detach(); sh_bios_gdb_detach();
#endif #endif

View File

@ -27,6 +27,8 @@ enum {
HSSRR, /* Sampling Rate Register */ HSSRR, /* Sampling Rate Register */
SCPCR, /* Serial Port Control Register */ SCPCR, /* Serial Port Control Register */
SCPDR, /* Serial Port Data Register */ SCPDR, /* Serial Port Data Register */
SCDL, /* BRG Frequency Division Register */
SCCKS, /* BRG Clock Select Register */
SCIx_NR_REGS, SCIx_NR_REGS,
}; };
@ -109,6 +111,14 @@ enum {
#define SCPDR_RTSD BIT(4) /* Serial Port RTS Output Pin Data */ #define SCPDR_RTSD BIT(4) /* Serial Port RTS Output Pin Data */
#define SCPDR_CTSD BIT(3) /* Serial Port CTS Input 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_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND)
#define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF) #define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF)

View File

@ -517,7 +517,7 @@ static struct uart_ops serial_sprd_ops = {
}; };
#ifdef CONFIG_SERIAL_SPRD_CONSOLE #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; unsigned int status, tmout = 10000;

View File

@ -1262,7 +1262,7 @@ static int sunsu_kbd_ms_init(struct uart_sunsu_port *up)
/* /*
* Wait for transmitter & holding register to empty * 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; unsigned int status, tmout = 10000;

View File

@ -485,7 +485,7 @@ static struct uart_driver vt8500_uart_driver;
#ifdef CONFIG_SERIAL_VT8500_CONSOLE #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; unsigned int status, tmout = 10000;

View File

@ -89,7 +89,7 @@
* module identification * module identification
*/ */
static char *driver_name = "SyncLink GT"; 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"; static char *tty_dev_prefix = "ttySLG";
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define MGSL_MAGIC 0x5401 #define MGSL_MAGIC 0x5401
@ -3799,7 +3799,7 @@ static int __init slgt_init(void)
/* Initialize the tty_driver structure */ /* 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->name = tty_dev_prefix;
serial_driver->major = ttymajor; serial_driver->major = ttymajor;
serial_driver->minor_start = 64; serial_driver->minor_start = 64;

View File

@ -256,19 +256,24 @@ const char *tty_name(const struct tty_struct *tty)
EXPORT_SYMBOL(tty_name); 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) const char *routine)
{ {
#ifdef TTY_PARANOIA_CHECK #ifdef TTY_PARANOIA_CHECK
if (!tty) { if (!tty) {
printk(KERN_WARNING pr_warn("(%d:%d): %s: NULL tty\n",
"null TTY for (%d:%d) in %s\n",
imajor(inode), iminor(inode), routine); imajor(inode), iminor(inode), routine);
return 1; return 1;
} }
if (tty->magic != TTY_MAGIC) { if (tty->magic != TTY_MAGIC) {
printk(KERN_WARNING pr_warn("(%d:%d): %s: bad magic number\n",
"bad magic number for tty struct (%d:%d) in %s\n",
imajor(inode), iminor(inode), routine); imajor(inode), iminor(inode), routine);
return 1; return 1;
} }
@ -293,9 +298,8 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
tty->link && tty->link->count) tty->link && tty->link->count)
count++; count++;
if (tty->count != count) { if (tty->count != count) {
printk(KERN_WARNING "Warning: dev (%s) tty->count(%d) " tty_warn(tty, "%s: tty->count(%d) != #fd's(%d)\n",
"!= #fd's(%d) in %s\n", routine, tty->count, count);
tty->name, tty->count, count, routine);
return count; return count;
} }
#endif #endif
@ -420,10 +424,8 @@ int __tty_check_change(struct tty_struct *tty, int sig)
} }
rcu_read_unlock(); rcu_read_unlock();
if (!tty_pgrp) { if (!tty_pgrp)
pr_warn("%s: tty_check_change: sig=%d, tty->pgrp == NULL!\n", tty_warn(tty, "sig=%d, tty->pgrp == NULL!\n", sig);
tty_name(tty), sig);
}
return ret; return ret;
} }
@ -781,7 +783,7 @@ static void do_tty_hangup(struct work_struct *work)
void tty_hangup(struct tty_struct *tty) void tty_hangup(struct tty_struct *tty)
{ {
tty_debug_hangup(tty, "\n"); tty_debug_hangup(tty, "hangup\n");
schedule_work(&tty->hangup_work); schedule_work(&tty->hangup_work);
} }
@ -798,7 +800,7 @@ EXPORT_SYMBOL(tty_hangup);
void tty_vhangup(struct tty_struct *tty) void tty_vhangup(struct tty_struct *tty)
{ {
tty_debug_hangup(tty, "\n"); tty_debug_hangup(tty, "vhangup\n");
__tty_hangup(tty, 0); __tty_hangup(tty, 0);
} }
@ -835,7 +837,7 @@ void tty_vhangup_self(void)
static void tty_vhangup_session(struct tty_struct *tty) 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); __tty_hangup(tty, 1);
} }
@ -1239,8 +1241,7 @@ static ssize_t tty_write(struct file *file, const char __user *buf,
return -EIO; return -EIO;
/* Short term debug to catch buggy drivers */ /* Short term debug to catch buggy drivers */
if (tty->ops->write_room == NULL) if (tty->ops->write_room == NULL)
printk(KERN_ERR "tty driver %s lacks a write_room method.\n", tty_err(tty, "missing write_room method\n");
tty->driver->name);
ld = tty_ldisc_ref_wait(tty); ld = tty_ldisc_ref_wait(tty);
if (!ld->ops->write) if (!ld->ops->write)
ret = -EIO; ret = -EIO;
@ -1561,8 +1562,8 @@ err_module_put:
/* call the tty release_tty routine to clean out this slot */ /* call the tty release_tty routine to clean out this slot */
err_release_tty: err_release_tty:
tty_unlock(tty); tty_unlock(tty);
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " tty_info_ratelimited(tty, "ldisc open failed (%d), clearing slot %d\n",
"clearing slot %d\n", idx); retval, idx);
release_tty(tty, idx); release_tty(tty, idx);
return ERR_PTR(retval); return ERR_PTR(retval);
} }
@ -1580,10 +1581,8 @@ void tty_free_termios(struct tty_struct *tty)
tp = tty->driver->termios[idx]; tp = tty->driver->termios[idx];
if (tp == NULL) { if (tp == NULL) {
tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
if (tp == NULL) { if (tp == NULL)
pr_warn("tty: no memory to save termios state.\n");
return; return;
}
tty->driver->termios[idx] = tp; tty->driver->termios[idx] = tp;
} }
*tp = tty->termios; *tp = tty->termios;
@ -1788,7 +1787,7 @@ int tty_release(struct inode *inode, struct file *filp)
return 0; 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) if (tty->ops->close)
tty->ops->close(tty, filp); tty->ops->close(tty, filp);
@ -1837,8 +1836,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (once) { if (once) {
once = 0; once = 0;
printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", tty_warn(tty, "read/write wait queue active!\n");
__func__, tty_name(tty));
} }
schedule_timeout_killable(timeout); schedule_timeout_killable(timeout);
if (timeout < 120 * HZ) if (timeout < 120 * HZ)
@ -1849,14 +1847,12 @@ int tty_release(struct inode *inode, struct file *filp)
if (o_tty) { if (o_tty) {
if (--o_tty->count < 0) { if (--o_tty->count < 0) {
printk(KERN_WARNING "%s: bad pty slave count (%d) for %s\n", tty_warn(tty, "bad slave count (%d)\n", o_tty->count);
__func__, o_tty->count, tty_name(o_tty));
o_tty->count = 0; o_tty->count = 0;
} }
} }
if (--tty->count < 0) { if (--tty->count < 0) {
printk(KERN_WARNING "%s: bad tty->count (%d) for %s\n", tty_warn(tty, "bad tty->count (%d)\n", tty->count);
__func__, tty->count, tty_name(tty));
tty->count = 0; tty->count = 0;
} }
@ -1907,7 +1903,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* Wait for pending work before tty destruction commmences */ /* Wait for pending work before tty destruction commmences */
tty_flush_works(tty); tty_flush_works(tty);
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 release_tty function takes care of the details of clearing
* the slots and preserving the termios structure. The tty_unlock_pair * the slots and preserving the termios structure. The tty_unlock_pair
@ -2097,7 +2093,7 @@ retry_open:
tty->driver->subtype == PTY_TYPE_MASTER) tty->driver->subtype == PTY_TYPE_MASTER)
noctty = 1; 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) if (tty->ops->open)
retval = tty->ops->open(tty, filp); retval = tty->ops->open(tty, filp);
@ -2106,7 +2102,7 @@ retry_open:
filp->f_flags = saved_flags; filp->f_flags = saved_flags;
if (retval) { 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_unlock(tty); /* need to call tty_release without BTM */
tty_release(inode, filp); tty_release(inode, filp);
@ -2870,7 +2866,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
no_tty(); no_tty();
return 0; return 0;
case TIOCSCTTY: case TIOCSCTTY:
return tiocsctty(tty, file, arg); return tiocsctty(real_tty, file, arg);
case TIOCGPGRP: case TIOCGPGRP:
return tiocgpgrp(tty, real_tty, p); return tiocgpgrp(tty, real_tty, p);
case TIOCSPGRP: case TIOCSPGRP:
@ -3028,28 +3024,24 @@ void __do_SAK(struct tty_struct *tty)
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
/* Kill the entire session */ /* Kill the entire session */
do_each_pid_task(session, PIDTYPE_SID, p) { do_each_pid_task(session, PIDTYPE_SID, p) {
printk(KERN_NOTICE "SAK: killed process %d" tty_notice(tty, "SAK: killed process %d (%s): by session\n",
" (%s): task_session(p)==tty->session\n", task_pid_nr(p), p->comm);
task_pid_nr(p), p->comm);
send_sig(SIGKILL, p, 1); send_sig(SIGKILL, p, 1);
} while_each_pid_task(session, PIDTYPE_SID, p); } 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) { do_each_thread(g, p) {
if (p->signal->tty == tty) { if (p->signal->tty == tty) {
printk(KERN_NOTICE "SAK: killed process %d" tty_notice(tty, "SAK: killed process %d (%s): by controlling tty\n",
" (%s): task_session(p)==tty->session\n", task_pid_nr(p), p->comm);
task_pid_nr(p), p->comm);
send_sig(SIGKILL, p, 1); send_sig(SIGKILL, p, 1);
continue; continue;
} }
task_lock(p); task_lock(p);
i = iterate_fd(p->files, 0, this_tty, tty); i = iterate_fd(p->files, 0, this_tty, tty);
if (i != 0) { if (i != 0) {
printk(KERN_NOTICE "SAK: killed process %d" tty_notice(tty, "SAK: killed process %d (%s): by fd#%d\n",
" (%s): fd#%d opened to the tty\n", task_pid_nr(p), p->comm, i - 1);
task_pid_nr(p), p->comm, i - 1);
force_sig(SIGKILL, p); force_sig(SIGKILL, p);
} }
task_unlock(p); task_unlock(p);
@ -3219,7 +3211,7 @@ EXPORT_SYMBOL(tty_register_device);
static void tty_device_create_release(struct device *dev) 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); kfree(dev);
} }
@ -3255,8 +3247,8 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
bool cdev = false; bool cdev = false;
if (index >= driver->num) { if (index >= driver->num) {
printk(KERN_ERR "Attempt to register invalid tty line number " pr_err("%s: Attempt to register invalid tty line number (%d)\n",
" (%d).\n", index); driver->name, index);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }

View File

@ -216,7 +216,7 @@ int tty_unthrottle_safe(struct tty_struct *tty)
void tty_wait_until_sent(struct tty_struct *tty, long timeout) void tty_wait_until_sent(struct tty_struct *tty, long timeout)
{ {
tty_debug_wait_until_sent(tty, "\n"); tty_debug_wait_until_sent(tty, "wait until sent, timeout=%ld\n", timeout);
if (!timeout) if (!timeout)
timeout = MAX_SCHEDULE_TIMEOUT; timeout = MAX_SCHEDULE_TIMEOUT;
@ -239,19 +239,14 @@ EXPORT_SYMBOL(tty_wait_until_sent);
* Termios Helper Methods * Termios Helper Methods
*/ */
static void unset_locked_termios(struct ktermios *termios, static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old)
struct ktermios *old,
struct ktermios *locked)
{ {
struct ktermios *termios = &tty->termios;
struct ktermios *locked = &tty->termios_locked;
int i; int i;
#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z))) #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_iflag, old->c_iflag, locked->c_iflag);
NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag); NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag); 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)) if (ifound == -1 && (ibaud != obaud || ibinput))
termios->c_cflag |= (BOTHER << IBSHIFT); termios->c_cflag |= (BOTHER << IBSHIFT);
#else #else
if (ifound == -1 || ofound == -1) { if (ifound == -1 || ofound == -1)
printk_once(KERN_WARNING "tty: Unable to return correct " pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
"speed data as your architecture needs updating.\n");
}
#endif #endif
} }
EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); 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); down_write(&tty->termios_rwsem);
old_termios = tty->termios; old_termios = tty->termios;
tty->termios = *new_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) if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios); tty->ops->set_termios(tty, &old_termios);

View File

@ -185,7 +185,7 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
* *
* Complement of tty_ldisc_get(). * 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)) if (WARN_ON_ONCE(!ld))
return; return;
@ -417,6 +417,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
* they are not on hot paths so a little discipline won't do * they are not on hot paths so a little discipline won't do
* any harm. * 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 * 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); down_write(&tty->termios_rwsem);
tty->termios.c_line = num; tty->termios.c_line = num;
up_write(&tty->termios_rwsem); 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); tty_lock(tty);
retval = tty_ldisc_lock(tty, 5 * HZ); retval = tty_ldisc_lock(tty, 5 * HZ);
if (retval) { if (retval)
tty_ldisc_put(new_ldisc); goto err;
tty_unlock(tty);
return retval;
}
/* /* Check the no-op case */
* Check the no-op case if (tty->ldisc->ops->num == ldisc)
*/ goto out;
if (tty->ldisc->ops->num == ldisc) { if (test_bit(TTY_HUPPED, &tty->flags)) {
tty_ldisc_unlock(tty); /* We were raced by hangup */
tty_ldisc_put(new_ldisc); retval = -EIO;
tty_unlock(tty); goto out;
return 0;
} }
old_ldisc = tty->ldisc; 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. */ /* Shutdown the old discipline. */
tty_ldisc_close(tty, old_ldisc); 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 the old ldisc (if it was restored as part of error cleanup
above). In either case, releasing a single reference from above). In either case, releasing a single reference from
the old ldisc is correct. */ the old ldisc is correct. */
new_ldisc = old_ldisc;
tty_ldisc_put(old_ldisc); out:
/*
* Allow ldisc referencing to occur again
*/
tty_ldisc_unlock(tty); tty_ldisc_unlock(tty);
/* Restart the work queue in case no characters kick it off. Safe if /* Restart the work queue in case no characters kick it off. Safe if
already running */ already running */
tty_buffer_restart_work(tty->port); tty_buffer_restart_work(tty->port);
err:
tty_ldisc_put(new_ldisc); /* drop the extra reference */
tty_unlock(tty); tty_unlock(tty);
return retval; return retval;
} }

View File

@ -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) int subclass, long timeout)
{ {
long count; long count;
@ -338,7 +338,7 @@ static inline int __ldsem_down_read_nested(struct ld_semaphore *sem,
return 1; 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) int subclass, long timeout)
{ {
long count; long count;

View File

@ -12,11 +12,8 @@
void __lockfunc tty_lock(struct tty_struct *tty) void __lockfunc tty_lock(struct tty_struct *tty)
{ {
if (tty->magic != TTY_MAGIC) { if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
pr_err("L Bad %p\n", tty);
WARN_ON(1);
return; return;
}
tty_kref_get(tty); tty_kref_get(tty);
mutex_lock(&tty->legacy_mutex); mutex_lock(&tty->legacy_mutex);
} }
@ -24,11 +21,8 @@ EXPORT_SYMBOL(tty_lock);
void __lockfunc tty_unlock(struct tty_struct *tty) void __lockfunc tty_unlock(struct tty_struct *tty)
{ {
if (tty->magic != TTY_MAGIC) { if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty))
pr_err("U Bad %p\n", tty);
WARN_ON(1);
return; return;
}
mutex_unlock(&tty->legacy_mutex); mutex_unlock(&tty->legacy_mutex);
tty_kref_put(tty); tty_kref_put(tty);
} }

View File

@ -462,14 +462,13 @@ int tty_port_close_start(struct tty_port *port,
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
if (tty->count == 1 && port->count != 1) { if (tty->count == 1 && port->count != 1) {
printk(KERN_WARNING tty_warn(tty, "%s: tty->count = 1 port count = %d\n", __func__,
"tty_port_close_start: tty->count = 1 port count = %d.\n", port->count);
port->count);
port->count = 1; port->count = 1;
} }
if (--port->count < 0) { if (--port->count < 0) {
printk(KERN_WARNING "tty_port_close_start: count = %d\n", tty_warn(tty, "%s: bad port count (%d)\n", __func__,
port->count); port->count);
port->count = 0; port->count = 0;
} }

View File

@ -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; 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(); WARN_CONSOLE_UNLOCKED();

View File

@ -65,6 +65,24 @@
#define ST_UART011_ABCR 0x100 /* Autobaud control register. */ #define ST_UART011_ABCR 0x100 /* Autobaud control register. */
#define ST_UART011_ABIMSC 0x15C /* Autobaud interrupt mask/clear 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_OE (1 << 11)
#define UART011_DR_BE (1 << 10) #define UART011_DR_BE (1 << 10)
#define UART011_DR_PE (1 << 9) #define UART011_DR_PE (1 << 9)

View File

@ -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 */

View File

@ -145,11 +145,12 @@ struct uart_port {
#define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */ #define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */
#define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */ #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_MEM32 (SERIAL_IO_MEM32) /* 32b little endian */
#define UPIO_AU (SERIAL_IO_AU) /* Au1x00 and RT288x type IO */ #define UPIO_AU (SERIAL_IO_AU) /* Au1x00 and RT288x type IO */
#define UPIO_TSI (SERIAL_IO_TSI) /* Tsi108/109 type IO */ #define UPIO_TSI (SERIAL_IO_TSI) /* Tsi108/109 type IO */
#define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */ #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 read_status_mask; /* driver specific */
unsigned int ignore_status_mask; /* driver specific */ unsigned int ignore_status_mask; /* driver specific */

View File

@ -32,6 +32,7 @@ enum {
SCIx_SH2_SCIF_FIFODATA_REGTYPE, SCIx_SH2_SCIF_FIFODATA_REGTYPE,
SCIx_SH3_SCIF_REGTYPE, SCIx_SH3_SCIF_REGTYPE,
SCIx_SH4_SCIF_REGTYPE, SCIx_SH4_SCIF_REGTYPE,
SCIx_SH4_SCIF_BRG_REGTYPE,
SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
SCIx_SH4_SCIF_FIFODATA_REGTYPE, SCIx_SH4_SCIF_FIFODATA_REGTYPE,
SCIx_SH7705_SCIF_REGTYPE, SCIx_SH7705_SCIF_REGTYPE,

View File

@ -345,8 +345,6 @@ struct tty_file_private {
#define TTY_HUPPED 18 /* Post driver->hangup() */ #define TTY_HUPPED 18 /* Post driver->hangup() */
#define TTY_LDISC_HALTED 22 /* Line discipline is halted */ #define TTY_LDISC_HALTED 22 /* Line discipline is halted */
#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
/* Values for tty->flow_change */ /* Values for tty->flow_change */
#define TTY_THROTTLE_SAFE 1 #define TTY_THROTTLE_SAFE 1
#define TTY_UNTHROTTLE_SAFE 2 #define TTY_UNTHROTTLE_SAFE 2
@ -395,8 +393,6 @@ static inline int __init tty_init(void)
{ return 0; } { return 0; }
#endif #endif
extern void tty_write_flush(struct tty_struct *);
extern struct ktermios tty_std_termios; extern struct ktermios tty_std_termios;
extern int vcs_init(void); extern int vcs_init(void);
@ -419,9 +415,8 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty)
return 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_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 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, int sig);
extern int tty_check_change(struct tty_struct *tty); 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) {} static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
#endif #endif
#define tty_debug(tty, f, args...) \ #define tty_msg(fn, tty, f, ...) \
do { \ fn("%s %s: " f, tty_driver_name(tty), tty_name(tty), ##__VA_ARGS__)
printk(KERN_DEBUG "%s: %s: " f, __func__, \
tty_name(tty), ##args); \ #define tty_debug(tty, f, ...) tty_msg(pr_debug, tty, f, ##__VA_ARGS__)
} while (0) #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 #endif

View File

@ -69,6 +69,7 @@ struct serial_struct {
#define SERIAL_IO_AU 4 #define SERIAL_IO_AU 4
#define SERIAL_IO_TSI 5 #define SERIAL_IO_TSI 5
#define SERIAL_IO_MEM32BE 6 #define SERIAL_IO_MEM32BE 6
#define SERIAL_IO_MEM16 7
#define UART_CLEAR_FIFO 0x01 #define UART_CLEAR_FIFO 0x01
#define UART_USE_FIFO 0x02 #define UART_USE_FIFO 0x02

View File

@ -176,7 +176,7 @@
#define PORT_S3C6400 84 #define PORT_S3C6400 84
/* NWPSERIAL */ /* NWPSERIAL, now removed */
#define PORT_NWPSERIAL 85 #define PORT_NWPSERIAL 85
/* MAX3100 */ /* MAX3100 */