TTY/Serial driver changes for 5.18-rc1

Here are the big set of tty and serial driver changes for 5.18-rc1.
 
 Nothing major, some more good cleanups from Jiri and 2 new serial
 drivers.  Highlights include:
 	- termbits cleanups
 	- export symbol cleanups and other core cleanups from Jiri Slaby
 	- new sunplus and mvebu uart drivers (amazing that people are
 	  still creating new uarts...)
 	- samsung serial driver cleanups
 	- ldisc 29 is now "reserved" for experimental/development line
 	  disciplines
 	- lots of other tiny fixes and cleanups to serial drivers and
 	  bindings
 
 All of these have been in linux-next for a while with no reported
 issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYkGznQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ymnFwCgwGD/syV+BH2krgY6cRixZz72vPsAn2RSnicd
 2YUwSNCHoL+B7hvQMtDG
 =A3X9
 -----END PGP SIGNATURE-----

Merge tag 'tty-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial driver updates from Greg KH:
 "Here are the big set of tty and serial driver changes for 5.18-rc1.

  Nothing major, some more good cleanups from Jiri and 2 new serial
  drivers. Highlights include:

   - termbits cleanups

   - export symbol cleanups and other core cleanups from Jiri Slaby

   - new sunplus and mvebu uart drivers (amazing that people are still
     creating new uarts...)

   - samsung serial driver cleanups

   - ldisc 29 is now "reserved" for experimental/development line
     disciplines

   - lots of other tiny fixes and cleanups to serial drivers and
     bindings

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'tty-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (104 commits)
  vt_ioctl: fix potential spectre v1 in VT_DISALLOCATE
  serial: 8250: fix XOFF/XON sending when DMA is used
  tty: serial: samsung: Add ARTPEC-8 support
  dt-bindings: serial: samsung: Add ARTPEC-8 UART
  serial: sc16is7xx: Clear RS485 bits in the shutdown
  tty: serial: samsung: simplify getting OF match data
  tty: serial: samsung: constify variables and pointers
  tty: serial: samsung: constify s3c24xx_serial_drv_data members
  tty: serial: samsung: constify UART name
  tty: serial: samsung: constify s3c24xx_serial_drv_data
  tty: serial: samsung: reduce number of casts
  tty: serial: samsung: embed s3c2410_uartcfg in parent structure
  tty: serial: samsung: embed s3c24xx_uart_info in parent structure
  serial: 8250_tegra: mark acpi_device_id as unused with !ACPI
  tty: serial: bcm63xx: use more precise Kconfig symbol
  serial: SERIAL_SUNPLUS should depend on ARCH_SUNPLUS
  tty: serial: jsm: fix two assignments in if conditions
  tty: serial: jsm: remove redundant assignments to variable linestatus
  serial: 8250_mtk: make two read-only arrays static const
  serial: samsung_tty: do not unlock port->lock for uart_write_wakeup()
  ...
This commit is contained in:
Linus Torvalds 2022-03-28 13:00:51 -07:00
commit 7203062171
115 changed files with 2728 additions and 1474 deletions

View File

@ -0,0 +1,59 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/marvell,armada-3700-uart-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvell Armada 3720 UART clocks
maintainers:
- Pali Rohár <pali@kernel.org>
properties:
compatible:
const: marvell,armada-3700-uart-clock
reg:
items:
- description: UART Clock Control Register
- description: UART 2 Baud Rate Divisor Register
clocks:
description: |
List of parent clocks suitable for UART from following set:
"TBG-A-P", "TBG-B-P", "TBG-A-S", "TBG-B-S", "xtal"
UART clock can use one from this set and when more are provided
then kernel would choose and configure the most suitable one.
It is suggest to specify at least one TBG clock to achieve
baudrates above 230400 and also to specify clock which bootloader
used for UART (most probably xtal) for smooth boot log on UART.
clock-names:
items:
- const: TBG-A-P
- const: TBG-B-P
- const: TBG-A-S
- const: TBG-B-S
- const: xtal
minItems: 1
'#clock-cells':
const: 1
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
additionalProperties: false
examples:
- |
uartclk: clock-controller@12010 {
compatible = "marvell,armada-3700-uart-clock";
reg = <0x12010 0x4>, <0x12210 0x4>;
clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, <&tbg 3>, <&xtalclk>;
clock-names = "TBG-A-P", "TBG-B-P", "TBG-A-S", "TBG-B-S", "xtal";
#clock-cells = <1>;
};

View File

@ -20,15 +20,15 @@ properties:
- fsl,ls1021a-lpuart
- fsl,ls1028a-lpuart
- fsl,imx7ulp-lpuart
- fsl,imx8qm-lpuart
- fsl,imx8qxp-lpuart
- fsl,imxrt1050-lpuart
- items:
- enum:
- fsl,imx8qxp-lpuart
- fsl,imx8ulp-lpuart
- const: fsl,imx8ulp-lpuart
- const: fsl,imx7ulp-lpuart
- items:
- const: fsl,imx8qm-lpuart
- enum:
- fsl,imx8qm-lpuart
- fsl,imx8dxl-lpuart
- const: fsl,imx8qxp-lpuart
reg:

View File

@ -20,6 +20,7 @@ Required properties:
* "mediatek,mt8135-uart" for MT8135 compatible UARTS
* "mediatek,mt8173-uart" for MT8173 compatible UARTS
* "mediatek,mt8183-uart", "mediatek,mt6577-uart" for MT8183 compatible UARTS
* "mediatek,mt8186-uart", "mediatek,mt6577-uart" for MT8183 compatible UARTS
* "mediatek,mt8192-uart", "mediatek,mt6577-uart" for MT8192 compatible UARTS
* "mediatek,mt8195-uart", "mediatek,mt6577-uart" for MT8195 compatible UARTS
* "mediatek,mt8516-uart" for MT8516 compatible UARTS

View File

@ -14,7 +14,10 @@ Required properties:
is provided (possible only with the "marvell,armada-3700-uart"
compatible string for backward compatibility), it will only work
if the baudrate was initialized by the bootloader and no baudrate
change will then be possible.
change will then be possible. When provided it should be UART1-clk
for standard variant of UART and UART2-clk for extended variant
of UART. TBG clock (with UART TBG divisors d1=d2=1) or xtal clock
should not be used and are supported only for backward compatibility.
- interrupts:
- Must contain three elements for the standard variant of the IP
(marvell,armada-3700-uart): "uart-sum", "uart-tx" and "uart-rx",
@ -34,7 +37,7 @@ Example:
uart0: serial@12000 {
compatible = "marvell,armada-3700-uart";
reg = <0x12000 0x18>;
clocks = <&xtalclk>;
clocks = <&uartclk 0>;
interrupts =
<GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
@ -45,7 +48,7 @@ Example:
uart1: serial@12200 {
compatible = "marvell,armada-3700-uart-ext";
reg = <0x12200 0x30>;
clocks = <&xtalclk>;
clocks = <&uartclk 1>;
interrupts =
<GIC_SPI 30 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 31 IRQ_TYPE_EDGE_RISING>;

View File

@ -17,6 +17,7 @@ properties:
oneOf:
- items:
- enum:
- renesas,r9a07g043-sci # RZ/G2UL
- renesas,r9a07g044-sci # RZ/G2{L,LC}
- renesas,r9a07g054-sci # RZ/V2L
- const: renesas,sci # generic SCI compatible UART
@ -67,6 +68,7 @@ if:
compatible:
contains:
enum:
- renesas,r9a07g043-sci
- renesas,r9a07g044-sci
- renesas,r9a07g054-sci
then:

View File

@ -73,12 +73,12 @@ properties:
- items:
- enum:
- renesas,scif-r9a07g044 # RZ/G2{L,LC}
- renesas,scif-r9a07g054 # RZ/V2L
- items:
- enum:
- renesas,scif-r9a07g043 # RZ/G2UL
- renesas,scif-r9a07g054 # RZ/V2L
- const: renesas,scif-r9a07g044 # RZ/G2{L,LC} fallback for RZ/V2L
- const: renesas,scif-r9a07g044 # RZ/G2{L,LC} fallback
reg:
maxItems: 1
@ -167,7 +167,6 @@ if:
- renesas,rcar-gen3-scif
- renesas,rcar-gen4-scif
- renesas,scif-r9a07g044
- renesas,scif-r9a07g054
then:
required:
- resets

View File

@ -20,12 +20,14 @@ properties:
items:
- enum:
- apple,s5l-uart
- axis,artpec8-uart
- samsung,s3c2410-uart
- samsung,s3c2412-uart
- samsung,s3c2440-uart
- samsung,s3c6400-uart
- samsung,s5pv210-uart
- samsung,exynos4210-uart
- samsung,exynos5433-uart
- samsung,exynos850-uart
reg:
@ -110,7 +112,9 @@ allOf:
contains:
enum:
- apple,s5l-uart
- axis,artpec8-uart
- samsung,exynos4210-uart
- samsung,exynos5433-uart
then:
properties:
clocks:

View File

@ -0,0 +1,56 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) Sunplus Co., Ltd. 2021
%YAML 1.2
---
$id: "http://devicetree.org/schemas/serial/sunplus,sp7021-uart.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Sunplus SoC SP7021 UART Controller Device Tree Bindings
maintainers:
- Hammer Hsieh <hammerh0314@gmail.com>
allOf:
- $ref: serial.yaml#
properties:
compatible:
const: sunplus,sp7021-uart
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
resets:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
aliases {
serial0 = &uart0;
};
uart0: serial@9c000900 {
compatible = "sunplus,sp7021-uart";
reg = <0x9c000900 0x80>;
interrupt-parent = <&intc>;
interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clkc 0x28>;
resets = <&rstc 0x18>;
};
...

View File

@ -11665,6 +11665,13 @@ F: Documentation/devicetree/bindings/phy/marvell,armada-3700-utmi-phy.yaml
F: drivers/phy/marvell/phy-mvebu-a3700-comphy.c
F: drivers/phy/marvell/phy-mvebu-a3700-utmi.c
MARVELL ARMADA 3700 SERIAL DRIVER
M: Pali Rohár <pali@kernel.org>
S: Maintained
F: Documentation/devicetree/bindings/clock/marvell,armada-3700-uart-clock.yaml
F: Documentation/devicetree/bindings/serial/mvebu-uart.txt
F: drivers/tty/serial/mvebu-uart.c
MARVELL ARMADA DRM SUPPORT
M: Russell King <linux@armlinux.org.uk>
S: Maintained
@ -18853,6 +18860,12 @@ S: Maintained
F: Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml
F: drivers/spi/spi-sunplus-sp7021.c
SUNPLUS UART DRIVER
M: Hammer Hsieh <hammerh0314@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/serial/sunplus,sp7021-uart.yaml
F: drivers/tty/serial/sunplus-uart.c
SUPERH
M: Yoshinori Sato <ysato@users.sourceforge.jp>
M: Rich Felker <dalias@libc.org>

View File

@ -132,10 +132,20 @@
reg = <0x11500 0x40>;
};
uartclk: clock-controller@12010 {
compatible = "marvell,armada-3700-uart-clock";
reg = <0x12010 0x4>, <0x12210 0x4>;
clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>,
<&tbg 3>, <&xtalclk>;
clock-names = "TBG-A-P", "TBG-B-P", "TBG-A-S",
"TBG-B-S", "xtal";
#clock-cells = <1>;
};
uart0: serial@12000 {
compatible = "marvell,armada-3700-uart";
reg = <0x12000 0x18>;
clocks = <&xtalclk>;
clocks = <&uartclk 0>;
interrupts =
<GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
@ -147,7 +157,7 @@
uart1: serial@12200 {
compatible = "marvell,armada-3700-uart-ext";
reg = <0x12200 0x30>;
clocks = <&xtalclk>;
clocks = <&uartclk 1>;
interrupts =
<GIC_SPI 30 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 31 IRQ_TYPE_EDGE_RISING>;

View File

@ -1,209 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_IA64_TERMBITS_H
#define _ASM_IA64_TERMBITS_H
/*
* Based on <asm-i386/termbits.h>.
*
* Modified 1999
* David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
*
* 99/01/28 Added new baudrates
*/
#include <linux/posix_types.h>
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 19
struct termios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
};
struct termios2 {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
/* c_iflag bits */
#define IGNBRK 0000001
#define BRKINT 0000002
#define IGNPAR 0000004
#define PARMRK 0000010
#define INPCK 0000020
#define ISTRIP 0000040
#define INLCR 0000100
#define IGNCR 0000200
#define ICRNL 0000400
#define IUCLC 0001000
#define IXON 0002000
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
#define OLCUC 0000002
#define ONLCR 0000004
#define OCRNL 0000010
#define ONOCR 0000020
#define ONLRET 0000040
#define OFILL 0000100
#define OFDEL 0000200
#define NLDLY 0000400
#define NL0 0000000
#define NL1 0000400
#define CRDLY 0003000
#define CR0 0000000
#define CR1 0001000
#define CR2 0002000
#define CR3 0003000
#define TABDLY 0014000
#define TAB0 0000000
#define TAB1 0004000
#define TAB2 0010000
#define TAB3 0014000
#define XTABS 0014000
#define BSDLY 0020000
#define BS0 0000000
#define BS1 0020000
#define VTDLY 0040000
#define VT0 0000000
#define VT1 0040000
#define FFDLY 0100000
#define FF0 0000000
#define FF1 0100000
/* c_cflag bit meaning */
#define CBAUD 0010017
#define B0 0000000 /* hang up */
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define EXTA B19200
#define EXTB B38400
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define PARENB 0000400
#define PARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
#define CIBAUD 002003600000 /* input baud rate */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
/* tcflush() and TCFLSH use these */
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
/* tcsetattr uses these */
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
#endif /* _ASM_IA64_TERMBITS_H */

View File

@ -1,221 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* include/asm-xtensa/termbits.h
*
* Copied from SH.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001 - 2005 Tensilica Inc.
*/
#ifndef _XTENSA_TERMBITS_H
#define _XTENSA_TERMBITS_H
#include <linux/posix_types.h>
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 19
struct termios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
};
struct termios2 {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
/* c_iflag bits */
#define IGNBRK 0000001
#define BRKINT 0000002
#define IGNPAR 0000004
#define PARMRK 0000010
#define INPCK 0000020
#define ISTRIP 0000040
#define INLCR 0000100
#define IGNCR 0000200
#define ICRNL 0000400
#define IUCLC 0001000
#define IXON 0002000
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
#define OLCUC 0000002
#define ONLCR 0000004
#define OCRNL 0000010
#define ONOCR 0000020
#define ONLRET 0000040
#define OFILL 0000100
#define OFDEL 0000200
#define NLDLY 0000400
#define NL0 0000000
#define NL1 0000400
#define CRDLY 0003000
#define CR0 0000000
#define CR1 0001000
#define CR2 0002000
#define CR3 0003000
#define TABDLY 0014000
#define TAB0 0000000
#define TAB1 0004000
#define TAB2 0010000
#define TAB3 0014000
#define XTABS 0014000
#define BSDLY 0020000
#define BS0 0000000
#define BS1 0020000
#define VTDLY 0040000
#define VT0 0000000
#define VT1 0040000
#define FFDLY 0100000
#define FF0 0000000
#define FF1 0100000
/* c_cflag bit meaning */
#define CBAUD 0010017
#define B0 0000000 /* hang up */
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define EXTA B19200
#define EXTB B38400
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define PARENB 0000400
#define PARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
#define CIBAUD 002003600000 /* input baud rate */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
/* tcflush() and TCFLSH use these */
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
/* tcsetattr uses these */
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
#endif /* _XTENSA_TERMBITS_H */

View File

@ -28,6 +28,7 @@
#include <linux/sched.h>
#include <linux/mutex.h>
#include <linux/seq_file.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <linux/circ_buf.h>
#include <linux/tty.h>
@ -250,21 +251,7 @@ static void sdio_uart_change_speed(struct sdio_uart_port *port,
unsigned char cval, fcr = 0;
unsigned int baud, quot;
switch (termios->c_cflag & CSIZE) {
case CS5:
cval = UART_LCR_WLEN5;
break;
case CS6:
cval = UART_LCR_WLEN6;
break;
case CS7:
cval = UART_LCR_WLEN7;
break;
default:
case CS8:
cval = UART_LCR_WLEN8;
break;
}
cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag));
if (termios->c_cflag & CSTOPB)
cval |= UART_LCR_STOP;

View File

@ -538,10 +538,8 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info)
*/
free_irq(IRQ_AMIGA_VERTB, info);
if (info->xmit.buf) {
free_page((unsigned long) info->xmit.buf);
info->xmit.buf = NULL;
}
free_page((unsigned long)info->xmit.buf);
info->xmit.buf = NULL;
info->IER = 0;
amiga_custom.intena = IF_RBF | IF_TBE;

View File

@ -434,7 +434,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
}
#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE
static void gf_early_console_putchar(struct uart_port *port, int ch)
static void gf_early_console_putchar(struct uart_port *port, unsigned char ch)
{
__raw_writel(ch, port->membase);
}

View File

@ -15,7 +15,7 @@
#define DCC_STATUS_RX (1 << 30)
#define DCC_STATUS_TX (1 << 29)
static void dcc_uart_console_putchar(struct uart_port *port, int ch)
static void dcc_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
while (__dcc_getstatus() & DCC_STATUS_TX)
cpu_relax();

View File

@ -1417,7 +1417,9 @@ out_error:
*/
static int __init hvc_iucv_config(char *val)
{
return kstrtoul(val, 10, &hvc_iucv_devices);
if (kstrtoul(val, 10, &hvc_iucv_devices))
pr_warn("hvc_iucv= invalid parameter value '%s'\n", val);
return 1;
}

View File

@ -275,9 +275,6 @@ struct mxser_port {
u8 read_status_mask;
u8 ignore_status_mask;
u8 xmit_fifo_size;
unsigned int xmit_head;
unsigned int xmit_tail;
unsigned int xmit_cnt;
spinlock_t slock;
};
@ -591,21 +588,7 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_term
}
/* byte size and parity */
switch (cflag & CSIZE) {
default:
case CS5:
cval = UART_LCR_WLEN5;
break;
case CS6:
cval = UART_LCR_WLEN6;
break;
case CS7:
cval = UART_LCR_WLEN7;
break;
case CS8:
cval = UART_LCR_WLEN8;
break;
}
cval = UART_LCR_WLEN(tty_get_char_size(tty->termios.c_cflag));
if (cflag & CSTOPB)
cval |= UART_LCR_STOP;
@ -742,22 +725,21 @@ static void mxser_disable_and_clear_FIFO(struct mxser_port *info)
static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
{
struct mxser_port *info = container_of(port, struct mxser_port, port);
unsigned long page;
unsigned long flags;
int ret;
page = __get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
ret = tty_port_alloc_xmit_buf(port);
if (ret < 0)
return ret;
spin_lock_irqsave(&info->slock, flags);
if (!info->type) {
set_bit(TTY_IO_ERROR, &tty->flags);
free_page(page);
spin_unlock_irqrestore(&info->slock, flags);
return 0;
ret = 0;
goto err_free_xmit;
}
info->port.xmit_buf = (unsigned char *) page;
/*
* Clear the FIFO buffers and disable them
@ -775,8 +757,10 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
if (capable(CAP_SYS_ADMIN)) {
set_bit(TTY_IO_ERROR, &tty->flags);
return 0;
} else
return -ENODEV;
}
ret = -ENODEV;
goto err_free_xmit;
}
/*
@ -812,7 +796,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
(void) inb(info->ioaddr + UART_MSR);
clear_bit(TTY_IO_ERROR, &tty->flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
kfifo_reset(&port->xmit_fifo);
/*
* and set the speed of the serial port
@ -821,6 +805,9 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
spin_unlock_irqrestore(&info->slock, flags);
return 0;
err_free_xmit:
tty_port_free_xmit_buf(port);
return ret;
}
/*
@ -855,14 +842,6 @@ static void mxser_shutdown_port(struct tty_port *port)
*/
wake_up_interruptible(&info->port.delta_msr_wait);
/*
* Free the xmit buffer, if necessary
*/
if (info->port.xmit_buf) {
free_page((unsigned long) info->port.xmit_buf);
info->port.xmit_buf = NULL;
}
info->IER = 0;
outb(0x00, info->ioaddr + UART_IER);
@ -877,6 +856,11 @@ static void mxser_shutdown_port(struct tty_port *port)
mxser_must_no_sw_flow_control(info->ioaddr);
spin_unlock_irqrestore(&info->slock, flags);
/* make sure ISR is not running while we free the buffer */
synchronize_irq(info->board->irq);
tty_port_free_xmit_buf(port);
}
/*
@ -900,9 +884,8 @@ static void mxser_flush_buffer(struct tty_struct *tty)
struct mxser_port *info = tty->driver_data;
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
kfifo_reset(&info->port.xmit_fifo);
outb(info->FCR | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
info->ioaddr + UART_FCR);
@ -919,50 +902,34 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
int c, total = 0;
struct mxser_port *info = tty->driver_data;
unsigned long flags;
int written;
bool is_empty;
while (1) {
c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head));
if (c <= 0)
break;
spin_lock_irqsave(&info->slock, flags);
written = kfifo_in(&info->port.xmit_fifo, buf, count);
is_empty = kfifo_is_empty(&info->port.xmit_fifo);
spin_unlock_irqrestore(&info->slock, flags);
memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
spin_lock_irqsave(&info->slock, flags);
info->xmit_head = (info->xmit_head + c) &
(SERIAL_XMIT_SIZE - 1);
info->xmit_cnt += c;
spin_unlock_irqrestore(&info->slock, flags);
buf += c;
count -= c;
total += c;
}
if (info->xmit_cnt && !tty->flow.stopped)
if (!is_empty && !tty->flow.stopped)
if (!tty->hw_stopped || mxser_16550A_or_MUST(info))
mxser_start_tx(info);
return total;
return written;
}
static int mxser_put_char(struct tty_struct *tty, unsigned char ch)
{
struct mxser_port *info = tty->driver_data;
unsigned long flags;
if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
return 0;
int ret;
spin_lock_irqsave(&info->slock, flags);
info->port.xmit_buf[info->xmit_head++] = ch;
info->xmit_head &= SERIAL_XMIT_SIZE - 1;
info->xmit_cnt++;
ret = kfifo_put(&info->port.xmit_fifo, ch);
spin_unlock_irqrestore(&info->slock, flags);
return 1;
return ret;
}
@ -970,7 +937,7 @@ static void mxser_flush_chars(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
if (!info->xmit_cnt || tty->flow.stopped ||
if (kfifo_is_empty(&info->port.xmit_fifo) || tty->flow.stopped ||
(tty->hw_stopped && !mxser_16550A_or_MUST(info)))
return;
@ -980,16 +947,15 @@ static void mxser_flush_chars(struct tty_struct *tty)
static unsigned int mxser_write_room(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
int ret;
ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
return ret < 0 ? 0 : ret;
return kfifo_avail(&info->port.xmit_fifo);
}
static unsigned int mxser_chars_in_buffer(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
return info->xmit_cnt;
return kfifo_len(&info->port.xmit_fifo);
}
/*
@ -1378,7 +1344,7 @@ static void mxser_start(struct tty_struct *tty)
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
if (info->xmit_cnt)
if (!kfifo_is_empty(&info->port.xmit_fifo))
__mxser_start_tx(info);
spin_unlock_irqrestore(&info->slock, flags);
}
@ -1609,7 +1575,7 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port
return;
}
if (!port->xmit_cnt || tty->flow.stopped ||
if (kfifo_is_empty(&port->port.xmit_fifo) || tty->flow.stopped ||
(tty->hw_stopped && !mxser_16550A_or_MUST(port))) {
__mxser_stop_tx(port);
return;
@ -1617,18 +1583,19 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port
count = port->xmit_fifo_size;
do {
outb(port->port.xmit_buf[port->xmit_tail++],
port->ioaddr + UART_TX);
port->xmit_tail &= SERIAL_XMIT_SIZE - 1;
port->icount.tx++;
if (!--port->xmit_cnt)
unsigned char c;
if (!kfifo_get(&port->port.xmit_fifo, &c))
break;
outb(c, port->ioaddr + UART_TX);
port->icount.tx++;
} while (--count > 0);
if (port->xmit_cnt < WAKEUP_CHARS)
if (kfifo_len(&port->port.xmit_fifo) < WAKEUP_CHARS)
tty_wakeup(tty);
if (!port->xmit_cnt)
if (kfifo_is_empty(&port->port.xmit_fifo))
__mxser_stop_tx(port);
}

View File

@ -704,13 +704,10 @@ static const struct acpi_device_id serdev_acpi_devices_blacklist[] = {
static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
void *data, void **return_value)
{
struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
struct serdev_controller *ctrl = data;
struct acpi_device *adev;
if (acpi_bus_get_device(handle, &adev))
return AE_OK;
if (acpi_device_enumerated(adev))
if (!adev || acpi_device_enumerated(adev))
return AE_OK;
/* Skip if black listed */

View File

@ -403,7 +403,7 @@ static void serial21285_setup_ports(void)
}
#ifdef CONFIG_SERIAL_21285_CONSOLE
static void serial21285_console_putchar(struct uart_port *port, int ch)
static void serial21285_console_putchar(struct uart_port *port, unsigned char ch)
{
while (*CSR_UARTFLG & 0x20)
barrier();

View File

@ -82,7 +82,7 @@ static ssize_t lpc_address_show(struct device *dev,
addr = (aspeed_vuart_readb(vuart, ASPEED_VUART_ADDRH) << 8) |
(aspeed_vuart_readb(vuart, ASPEED_VUART_ADDRL));
return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr);
return sysfs_emit(buf, "0x%x\n", addr);
}
static int aspeed_vuart_set_lpc_address(struct aspeed_vuart *vuart, u32 addr)
@ -124,7 +124,7 @@ static ssize_t sirq_show(struct device *dev,
reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg);
return sysfs_emit(buf, "%u\n", reg);
}
static int aspeed_vuart_set_sirq(struct aspeed_vuart *vuart, u32 sirq)
@ -171,7 +171,7 @@ static ssize_t sirq_polarity_show(struct device *dev,
reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0);
return sysfs_emit(buf, "%u\n", reg ? 1 : 0);
}
static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart,
@ -487,7 +487,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
port.port.irq = irq_of_parse_and_map(np, 0);
port.port.handle_irq = aspeed_vuart_handle_irq;
port.port.iotype = UPIO_MEM;
port.port.type = PORT_16550A;
port.port.type = PORT_ASPEED_VUART;
port.port.uartclk = clk;
port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
| UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;

View File

@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include "8250.h"
@ -44,6 +45,10 @@ struct bcm2835aux_data {
u32 cntl;
};
struct bcm2835_aux_serial_driver_data {
resource_size_t offset;
};
static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up)
{
if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
@ -80,9 +85,12 @@ static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up)
static int bcm2835aux_serial_probe(struct platform_device *pdev)
{
const struct bcm2835_aux_serial_driver_data *bcm_data;
struct uart_8250_port up = { };
struct bcm2835aux_data *data;
resource_size_t offset = 0;
struct resource *res;
unsigned int uartclk;
int ret;
/* allocate the custom structure */
@ -109,9 +117,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
/* get the clock - this also enables the HW */
data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(data->clk), "could not get clk\n");
data->clk = devm_clk_get_optional(&pdev->dev, NULL);
/* get the interrupt */
ret = platform_get_irq(pdev, 0);
@ -125,8 +131,24 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "memory resource not found");
return -EINVAL;
}
up.port.mapbase = res->start;
up.port.mapsize = resource_size(res);
bcm_data = device_get_match_data(&pdev->dev);
/* Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi)
* describe the miniuart with a base address that encompasses the auxiliary
* registers shared between the miniuart and spi.
*
* This is due to historical reasons, see discussion here :
* https://edk2.groups.io/g/devel/topic/87501357#84349
*
* We need to add the offset between the miniuart and auxiliary
* registers to get the real miniuart base address.
*/
if (bcm_data)
offset = bcm_data->offset;
up.port.mapbase = res->start + offset;
up.port.mapsize = resource_size(res) - offset;
/* Check for a fixed line number */
ret = of_alias_get_id(pdev->dev.of_node, "serial");
@ -141,12 +163,19 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
return ret;
}
uartclk = clk_get_rate(data->clk);
if (!uartclk) {
ret = device_property_read_u32(&pdev->dev, "clock-frequency", &uartclk);
if (ret)
return dev_err_probe(&pdev->dev, ret, "could not get clk rate\n");
}
/* the HW-clock divider for bcm2835aux is 8,
* but 8250 expects a divider of 16,
* so we have to multiply the actual clock by 2
* to get identical baudrates.
*/
up.port.uartclk = clk_get_rate(data->clk) * 2;
up.port.uartclk = uartclk * 2;
/* register the port */
ret = serial8250_register_8250_port(&up);
@ -173,16 +202,27 @@ static int bcm2835aux_serial_remove(struct platform_device *pdev)
return 0;
}
static const struct bcm2835_aux_serial_driver_data bcm2835_acpi_data = {
.offset = 0x40,
};
static const struct of_device_id bcm2835aux_serial_match[] = {
{ .compatible = "brcm,bcm2835-aux-uart" },
{ },
};
MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match);
static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = {
{ "BCM2836", (kernel_ulong_t)&bcm2835_acpi_data },
{ }
};
MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match);
static struct platform_driver bcm2835aux_serial_driver = {
.driver = {
.name = "bcm2835-aux-uart",
.of_match_table = bcm2835aux_serial_match,
.acpi_match_table = bcm2835aux_serial_acpi_match,
},
.probe = bcm2835aux_serial_probe,
.remove = bcm2835aux_serial_remove,

View File

@ -64,10 +64,19 @@ int serial8250_tx_dma(struct uart_8250_port *p)
struct uart_8250_dma *dma = p->dma;
struct circ_buf *xmit = &p->port.state->xmit;
struct dma_async_tx_descriptor *desc;
struct uart_port *up = &p->port;
int ret;
if (dma->tx_running)
if (dma->tx_running) {
if (up->x_char) {
dmaengine_pause(dma->txchan);
uart_xchar_out(up, UART_TX);
dmaengine_resume(dma->txchan);
}
return 0;
} else if (up->x_char) {
uart_xchar_out(up, UART_TX);
}
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
/* We have been called from __dma_tx_complete() */

View File

@ -86,7 +86,7 @@ static void serial8250_early_out(struct uart_port *port, int offset, int value)
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
static void serial_putc(struct uart_port *port, int c)
static void serial_putc(struct uart_port *port, unsigned char c)
{
unsigned int status;

View File

@ -623,7 +623,12 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
maxnr = pci_resource_len(pcidev, bar) >> (board->reg_shift + 3);
nr_ports = board->num_ports ? board->num_ports : pcidev->device & 0x0f;
if (pcidev->vendor == PCI_VENDOR_ID_ACCESSIO)
nr_ports = BIT(((pcidev->device & 0x38) >> 3) - 1);
else if (board->num_ports)
nr_ports = board->num_ports;
else
nr_ports = pcidev->device & 0x0f;
priv = devm_kzalloc(&pcidev->dev, struct_size(priv, line, nr_ports), GFP_KERNEL);
if (!priv)
@ -722,22 +727,6 @@ static int __maybe_unused exar_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
static const struct exar8250_board acces_com_2x = {
.num_ports = 2,
.setup = pci_xr17c154_setup,
};
static const struct exar8250_board acces_com_4x = {
.num_ports = 4,
.setup = pci_xr17c154_setup,
};
static const struct exar8250_board acces_com_8x = {
.num_ports = 8,
.setup = pci_xr17c154_setup,
};
static const struct exar8250_board pbn_fastcom335_2 = {
.num_ports = 2,
.setup = pci_fastcom335_setup,
@ -822,13 +811,13 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
}
static const struct pci_device_id exar_pci_tbl[] = {
EXAR_DEVICE(ACCESSIO, COM_2S, acces_com_2x),
EXAR_DEVICE(ACCESSIO, COM_4S, acces_com_4x),
EXAR_DEVICE(ACCESSIO, COM_8S, acces_com_8x),
EXAR_DEVICE(ACCESSIO, COM232_8, acces_com_8x),
EXAR_DEVICE(ACCESSIO, COM_2SM, acces_com_2x),
EXAR_DEVICE(ACCESSIO, COM_4SM, acces_com_4x),
EXAR_DEVICE(ACCESSIO, COM_8SM, acces_com_8x),
EXAR_DEVICE(ACCESSIO, COM_2S, pbn_exar_XR17C15x),
EXAR_DEVICE(ACCESSIO, COM_4S, pbn_exar_XR17C15x),
EXAR_DEVICE(ACCESSIO, COM_8S, pbn_exar_XR17C15x),
EXAR_DEVICE(ACCESSIO, COM232_8, pbn_exar_XR17C15x),
EXAR_DEVICE(ACCESSIO, COM_2SM, pbn_exar_XR17C15x),
EXAR_DEVICE(ACCESSIO, COM_4SM, pbn_exar_XR17C15x),
EXAR_DEVICE(ACCESSIO, COM_8SM, pbn_exar_XR17C15x),
CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect),
CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect),

View File

@ -52,7 +52,7 @@ static void early_out(struct uart_port *port, int offset, uint8_t value)
writel(value, port->membase + (offset << 2));
}
static void ingenic_early_console_putc(struct uart_port *port, int c)
static void ingenic_early_console_putc(struct uart_port *port, unsigned char c)
{
uint8_t lsr;

View File

@ -117,8 +117,7 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct dw_dma_slave *param = &lpss->dma_param;
struct pci_dev *pdev = to_pci_dev(port->dev);
unsigned int dma_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
struct pci_dev *dma_dev = pci_get_slot(pdev->bus, dma_devfn);
struct pci_dev *dma_dev;
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_BYT_UART1:
@ -137,6 +136,8 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return -EINVAL;
}
dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
param->dma_dev = &dma_dev->dev;
param->m_master = 0;
param->p_master = 1;
@ -152,6 +153,14 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return 0;
}
static void byt_serial_exit(struct lpss8250 *lpss)
{
struct dw_dma_slave *param = &lpss->dma_param;
/* Paired with pci_get_slot() in the byt_serial_setup() above */
put_device(param->dma_dev);
}
static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct uart_8250_dma *dma = &lpss->data.dma;
@ -170,6 +179,13 @@ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return 0;
}
static void ehl_serial_exit(struct lpss8250 *lpss)
{
struct uart_8250_port *up = serial8250_get_port(lpss->data.line);
up->dma = NULL;
}
#ifdef CONFIG_SERIAL_8250_DMA
static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
.nr_channels = 2,
@ -344,8 +360,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err_exit:
if (lpss->board->exit)
lpss->board->exit(lpss);
lpss->board->exit(lpss);
pci_free_irq_vectors(pdev);
return ret;
}
@ -356,8 +371,7 @@ static void lpss8250_remove(struct pci_dev *pdev)
serial8250_unregister_port(lpss->data.line);
if (lpss->board->exit)
lpss->board->exit(lpss);
lpss->board->exit(lpss);
pci_free_irq_vectors(pdev);
}
@ -365,12 +379,14 @@ static const struct lpss8250_board byt_board = {
.freq = 100000000,
.base_baud = 2764800,
.setup = byt_serial_setup,
.exit = byt_serial_exit,
};
static const struct lpss8250_board ehl_board = {
.freq = 200000000,
.base_baud = 12500000,
.setup = ehl_serial_setup,
.exit = ehl_serial_exit,
};
static const struct lpss8250_board qrk_board = {

View File

@ -73,6 +73,11 @@ static int pnw_setup(struct mid8250 *mid, struct uart_port *p)
return 0;
}
static void pnw_exit(struct mid8250 *mid)
{
pci_dev_put(mid->dma_dev);
}
static int tng_handle_irq(struct uart_port *p)
{
struct mid8250 *mid = p->private_data;
@ -124,6 +129,11 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p)
return 0;
}
static void tng_exit(struct mid8250 *mid)
{
pci_dev_put(mid->dma_dev);
}
static int dnv_handle_irq(struct uart_port *p)
{
struct mid8250 *mid = p->private_data;
@ -312,11 +322,9 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!uart.port.membase)
return -ENOMEM;
if (mid->board->setup) {
ret = mid->board->setup(mid, &uart.port);
if (ret)
return ret;
}
ret = mid->board->setup(mid, &uart.port);
if (ret)
return ret;
ret = mid8250_dma_setup(mid, &uart);
if (ret)
@ -330,9 +338,9 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, mid);
return 0;
err:
if (mid->board->exit)
mid->board->exit(mid);
mid->board->exit(mid);
return ret;
}
@ -342,8 +350,7 @@ static void mid8250_remove(struct pci_dev *pdev)
serial8250_unregister_port(mid->line);
if (mid->board->exit)
mid->board->exit(mid);
mid->board->exit(mid);
}
static const struct mid8250_board pnw_board = {
@ -351,6 +358,7 @@ static const struct mid8250_board pnw_board = {
.freq = 50000000,
.base_baud = 115200,
.setup = pnw_setup,
.exit = pnw_exit,
};
static const struct mid8250_board tng_board = {
@ -358,6 +366,7 @@ static const struct mid8250_board tng_board = {
.freq = 38400000,
.base_baud = 1843200,
.setup = tng_setup,
.exit = tng_exit,
};
static const struct mid8250_board dnv_board = {
@ -368,16 +377,14 @@ static const struct mid8250_board dnv_board = {
.exit = dnv_exit,
};
#define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
static const struct pci_device_id pci_ids[] = {
MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART1, pnw_board),
MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board),
MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board),
MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board),
MID_DEVICE(PCI_DEVICE_ID_INTEL_CDF_UART, dnv_board),
MID_DEVICE(PCI_DEVICE_ID_INTEL_DNV_UART, dnv_board),
{ },
{ PCI_DEVICE_DATA(INTEL, PNW_UART1, &pnw_board) },
{ PCI_DEVICE_DATA(INTEL, PNW_UART2, &pnw_board) },
{ PCI_DEVICE_DATA(INTEL, PNW_UART3, &pnw_board) },
{ PCI_DEVICE_DATA(INTEL, TNG_UART, &tng_board) },
{ PCI_DEVICE_DATA(INTEL, CDF_UART, &dnv_board) },
{ PCI_DEVICE_DATA(INTEL, DNV_UART, &dnv_board) },
{ }
};
MODULE_DEVICE_TABLE(pci, pci_ids);

View File

@ -289,10 +289,10 @@ static void
mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
unsigned short fraction_L_mapping[] = {
static const unsigned short fraction_L_mapping[] = {
0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF
};
unsigned short fraction_M_mapping[] = {
static const unsigned short fraction_M_mapping[] = {
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3
};
struct uart_8250_port *up = up_to_u8250p(port);

View File

@ -357,21 +357,7 @@ static void omap_8250_set_termios(struct uart_port *port,
unsigned char cval = 0;
unsigned int baud;
switch (termios->c_cflag & CSIZE) {
case CS5:
cval = UART_LCR_WLEN5;
break;
case CS6:
cval = UART_LCR_WLEN6;
break;
case CS7:
cval = UART_LCR_WLEN7;
break;
default:
case CS8:
cval = UART_LCR_WLEN8;
break;
}
cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag));
if (termios->c_cflag & CSTOPB)
cval |= UART_LCR_STOP;

View File

@ -307,6 +307,14 @@ static const struct serial8250_config uart_config[] = {
.rxtrig_bytes = {1, 32, 64, 112},
.flags = UART_CAP_FIFO | UART_CAP_SLEEP,
},
[PORT_ASPEED_VUART] = {
.name = "ASPEED VUART",
.fifo_size = 16,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO,
},
};
/* Uart divisor latch read */
@ -1615,6 +1623,18 @@ static inline void start_tx_rs485(struct uart_port *port)
struct uart_8250_port *up = up_to_u8250p(port);
struct uart_8250_em485 *em485 = up->em485;
/*
* While serial8250_em485_handle_stop_tx() is a noop if
* em485->active_timer != &em485->stop_tx_timer, it might happen that
* the timer is still armed and triggers only after the current bunch of
* chars is send and em485->active_timer == &em485->stop_tx_timer again.
* So cancel the timer. There is still a theoretical race condition if
* the timer is already running and only comes around to check for
* em485->active_timer when &em485->stop_tx_timer is armed again.
*/
if (em485->active_timer == &em485->stop_tx_timer)
hrtimer_try_to_cancel(&em485->stop_tx_timer);
em485->active_timer = NULL;
if (em485->tx_stopped) {
@ -1657,6 +1677,9 @@ static void serial8250_start_tx(struct uart_port *port)
serial8250_rpm_get_tx(up);
if (!port->x_char && uart_circ_empty(&port->state->xmit))
return;
if (em485 &&
em485->active_timer == &em485->start_tx_timer)
return;
@ -1799,9 +1822,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
int count;
if (port->x_char) {
serial_out(up, UART_TX, port->x_char);
port->icount.tx++;
port->x_char = 0;
uart_xchar_out(port, UART_TX);
return;
}
if (uart_tx_stopped(port)) {
@ -2582,21 +2603,7 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
{
unsigned char cval;
switch (c_cflag & CSIZE) {
case CS5:
cval = UART_LCR_WLEN5;
break;
case CS6:
cval = UART_LCR_WLEN6;
break;
case CS7:
cval = UART_LCR_WLEN7;
break;
default:
case CS8:
cval = UART_LCR_WLEN8;
break;
}
cval = UART_LCR_WLEN(tty_get_char_size(c_cflag));
if (c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
@ -3296,7 +3303,7 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults);
#ifdef CONFIG_SERIAL_8250_CONSOLE
static void serial8250_console_putchar(struct uart_port *port, int ch)
static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
{
struct uart_8250_port *up = up_to_u8250p(port);

View File

@ -175,7 +175,7 @@ static const struct of_device_id tegra_uart_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_uart_of_match);
static const struct acpi_device_id tegra_uart_acpi_match[] = {
static const struct acpi_device_id tegra_uart_acpi_match[] __maybe_unused = {
{ "NVDA0100", 0 },
{ },
};

View File

@ -479,11 +479,12 @@ config SERIAL_8250_LPSS
select DW_DMAC_PCI if (SERIAL_8250_DMA && X86_INTEL_LPSS)
select RATIONAL
help
Selecting this option will enable handling of the extra features
present on the UART found on various Intel platforms such as:
Selecting this option will enable handling of the UART found on
various Intel platforms such as:
- Intel Baytrail SoC
- Intel Braswell SoC
- Intel Quark X1000 SoC
that are not covered by the more generic SERIAL_8250_PCI option.
config SERIAL_8250_MID
tristate "Support for serial ports on Intel MID platforms"
@ -494,17 +495,18 @@ config SERIAL_8250_MID
select HSU_DMA_PCI if (HSU_DMA && X86_INTEL_MID)
select RATIONAL
help
Selecting this option will enable handling of the extra features
present on the UART found on Intel Medfield SOC and various other
Intel platforms.
Selecting this option will enable handling of the UART found on
Intel Medfield SOC and various other Intel platforms that is not
covered by the more generic SERIAL_8250_PCI option.
config SERIAL_8250_PERICOM
tristate "Support for Pericom and Acces I/O serial ports"
default SERIAL_8250
depends on SERIAL_8250 && PCI
help
Selecting this option will enable handling of the extra features
present on the Pericom and Acces I/O UARTs.
Selecting this option will enable handling of the Pericom and Acces
I/O UARTs that are not covered by the more generic SERIAL_8250_PCI
option.
config SERIAL_8250_PXA
tristate "PXA serial port support"

View File

@ -139,6 +139,7 @@ config SERIAL_ATMEL_CONSOLE
bool "Support for console on AT91 serial port"
depends on SERIAL_ATMEL=y
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
help
Say Y here if you wish to use an on-chip UART on a Atmel
AT91 processor as the system console (the system
@ -236,7 +237,7 @@ config SERIAL_CLPS711X_CONSOLE
config SERIAL_SAMSUNG
tristate "Samsung SoC serial support"
depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_APPLE || COMPILE_TEST
depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_APPLE || ARCH_ARTPEC || COMPILE_TEST
select SERIAL_CORE
help
Support for the on-chip UARTs on the Samsung
@ -1099,7 +1100,8 @@ config SERIAL_TIMBERDALE
config SERIAL_BCM63XX
tristate "Broadcom BCM63xx/BCM33xx UART support"
select SERIAL_CORE
depends on COMMON_CLK
depends on ARCH_BCM4908 || ARCH_BCM_63XX || BCM63XX || BMIPS_GENERIC || COMPILE_TEST
default ARCH_BCM4908 || ARCH_BCM_63XX || BCM63XX || BMIPS_GENERIC
help
This enables the driver for the onchip UART core found on
the following chipsets:
@ -1445,6 +1447,7 @@ config SERIAL_STM32_CONSOLE
config SERIAL_MVEBU_UART
bool "Marvell EBU serial port support"
depends on ARCH_MVEBU || COMPILE_TEST
depends on COMMON_CLK
select SERIAL_CORE
help
This driver is for Marvell EBU SoC's UART. If you have a machine
@ -1562,6 +1565,31 @@ config SERIAL_LITEUART_CONSOLE
and warnings and which allows logins in single user mode).
Otherwise, say 'N'.
config SERIAL_SUNPLUS
tristate "Sunplus UART support"
depends on ARCH_SUNPLUS || COMPILE_TEST
select SERIAL_CORE
help
Select this option if you would like to use Sunplus serial port on
Sunplus SoC SP7021.
If you enable this option, Sunplus serial ports in the system will
be registered as ttySUPx.
This driver can also be built as a module. If so, the module will be
called sunplus-uart.
config SERIAL_SUNPLUS_CONSOLE
bool "Console on Sunplus UART"
depends on SERIAL_SUNPLUS
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
help
Select this option if you would like to use a Sunplus UART as the
system console.
Even if you say Y here, the currently visible virtual console
(/dev/tty0) will still be used as the system console by default, but
you can alter that using a kernel command line option such as
"console=ttySUPx".
endmenu
config SERIAL_MCTRL_GPIO

View File

@ -87,6 +87,7 @@ obj-$(CONFIG_SERIAL_RDA) += rda-uart.o
obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o
obj-$(CONFIG_SERIAL_SIFIVE) += sifive.o
obj-$(CONFIG_SERIAL_LITEUART) += liteuart.o
obj-$(CONFIG_SERIAL_SUNPLUS) += sunplus-uart.o
# GPIOLIB helpers for modem control lines
obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o

View File

@ -298,7 +298,7 @@ static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
static void altera_jtaguart_console_putc(struct uart_port *port, int c)
static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c)
{
unsigned long status;
unsigned long flags;
@ -318,7 +318,7 @@ static void altera_jtaguart_console_putc(struct uart_port *port, int c)
spin_unlock_irqrestore(&port->lock, flags);
}
#else
static void altera_jtaguart_console_putc(struct uart_port *port, int c)
static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c)
{
unsigned long flags;

View File

@ -438,7 +438,7 @@ static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
static void altera_uart_console_putc(struct uart_port *port, int c)
static void altera_uart_console_putc(struct uart_port *port, unsigned char c)
{
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK))

View File

@ -110,38 +110,38 @@ static void pl010_enable_ms(struct uart_port *port)
writel(cr, uap->port.membase + UART010_CR);
}
static void pl010_rx_chars(struct uart_amba_port *uap)
static void pl010_rx_chars(struct uart_port *port)
{
unsigned int status, ch, flag, rsr, max_count = 256;
status = readb(uap->port.membase + UART01x_FR);
status = readb(port->membase + UART01x_FR);
while (UART_RX_DATA(status) && max_count--) {
ch = readb(uap->port.membase + UART01x_DR);
ch = readb(port->membase + UART01x_DR);
flag = TTY_NORMAL;
uap->port.icount.rx++;
port->icount.rx++;
/*
* Note that the error handling code is
* out of the main execution path
*/
rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
if (unlikely(rsr & UART01x_RSR_ANY)) {
writel(0, uap->port.membase + UART01x_ECR);
writel(0, port->membase + UART01x_ECR);
if (rsr & UART01x_RSR_BE) {
rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
uap->port.icount.brk++;
if (uart_handle_break(&uap->port))
port->icount.brk++;
if (uart_handle_break(port))
goto ignore_char;
} else if (rsr & UART01x_RSR_PE)
uap->port.icount.parity++;
port->icount.parity++;
else if (rsr & UART01x_RSR_FE)
uap->port.icount.frame++;
port->icount.frame++;
if (rsr & UART01x_RSR_OE)
uap->port.icount.overrun++;
port->icount.overrun++;
rsr &= uap->port.read_status_mask;
rsr &= port->read_status_mask;
if (rsr & UART01x_RSR_BE)
flag = TTY_BREAK;
@ -151,56 +151,57 @@ static void pl010_rx_chars(struct uart_amba_port *uap)
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&uap->port, ch))
if (uart_handle_sysrq_char(port, ch))
goto ignore_char;
uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);
ignore_char:
status = readb(uap->port.membase + UART01x_FR);
status = readb(port->membase + UART01x_FR);
}
tty_flip_buffer_push(&uap->port.state->port);
tty_flip_buffer_push(&port->state->port);
}
static void pl010_tx_chars(struct uart_amba_port *uap)
static void pl010_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &uap->port.state->xmit;
struct circ_buf *xmit = &port->state->xmit;
int count;
if (uap->port.x_char) {
writel(uap->port.x_char, uap->port.membase + UART01x_DR);
uap->port.icount.tx++;
uap->port.x_char = 0;
if (port->x_char) {
writel(port->x_char, port->membase + UART01x_DR);
port->icount.tx++;
port->x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
pl010_stop_tx(&uap->port);
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
pl010_stop_tx(port);
return;
}
count = uap->port.fifosize >> 1;
count = port->fifosize >> 1;
do {
writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
writel(xmit->buf[xmit->tail], port->membase + UART01x_DR);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
uap->port.icount.tx++;
port->icount.tx++;
if (uart_circ_empty(xmit))
break;
} while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port);
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
pl010_stop_tx(&uap->port);
pl010_stop_tx(port);
}
static void pl010_modem_status(struct uart_amba_port *uap)
{
struct uart_port *port = &uap->port;
unsigned int status, delta;
writel(0, uap->port.membase + UART010_ICR);
writel(0, port->membase + UART010_ICR);
status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
delta = status ^ uap->old_status;
uap->old_status = status;
@ -209,65 +210,63 @@ static void pl010_modem_status(struct uart_amba_port *uap)
return;
if (delta & UART01x_FR_DCD)
uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
uart_handle_dcd_change(port, status & UART01x_FR_DCD);
if (delta & UART01x_FR_DSR)
uap->port.icount.dsr++;
port->icount.dsr++;
if (delta & UART01x_FR_CTS)
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
uart_handle_cts_change(port, status & UART01x_FR_CTS);
wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
wake_up_interruptible(&port->state->port.delta_msr_wait);
}
static irqreturn_t pl010_int(int irq, void *dev_id)
{
struct uart_amba_port *uap = dev_id;
struct uart_port *port = &uap->port;
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
int handled = 0;
spin_lock(&uap->port.lock);
spin_lock(&port->lock);
status = readb(uap->port.membase + UART010_IIR);
status = readb(port->membase + UART010_IIR);
if (status) {
do {
if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
pl010_rx_chars(uap);
pl010_rx_chars(port);
if (status & UART010_IIR_MIS)
pl010_modem_status(uap);
if (status & UART010_IIR_TIS)
pl010_tx_chars(uap);
pl010_tx_chars(port);
if (pass_counter-- == 0)
break;
status = readb(uap->port.membase + UART010_IIR);
status = readb(port->membase + UART010_IIR);
} while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
UART010_IIR_TIS));
handled = 1;
}
spin_unlock(&uap->port.lock);
spin_unlock(&port->lock);
return IRQ_RETVAL(handled);
}
static unsigned int pl010_tx_empty(struct uart_port *port)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
unsigned int status = readb(uap->port.membase + UART01x_FR);
unsigned int status = readb(port->membase + UART01x_FR);
return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
}
static unsigned int pl010_get_mctrl(struct uart_port *port)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
unsigned int result = 0;
unsigned int status;
status = readb(uap->port.membase + UART01x_FR);
status = readb(port->membase + UART01x_FR);
if (status & UART01x_FR_DCD)
result |= TIOCM_CAR;
if (status & UART01x_FR_DSR)
@ -284,24 +283,22 @@ static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
container_of(port, struct uart_amba_port, port);
if (uap->data)
uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl);
uap->data->set_mctrl(uap->dev, port->membase, mctrl);
}
static void pl010_break_ctl(struct uart_port *port, int break_state)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
unsigned long flags;
unsigned int lcr_h;
spin_lock_irqsave(&uap->port.lock, flags);
lcr_h = readb(uap->port.membase + UART010_LCRH);
spin_lock_irqsave(&port->lock, flags);
lcr_h = readb(port->membase + UART010_LCRH);
if (break_state == -1)
lcr_h |= UART01x_LCRH_BRK;
else
lcr_h &= ~UART01x_LCRH_BRK;
writel(lcr_h, uap->port.membase + UART010_LCRH);
spin_unlock_irqrestore(&uap->port.lock, flags);
writel(lcr_h, port->membase + UART010_LCRH);
spin_unlock_irqrestore(&port->lock, flags);
}
static int pl010_startup(struct uart_port *port)
@ -317,25 +314,25 @@ static int pl010_startup(struct uart_port *port)
if (retval)
goto out;
uap->port.uartclk = clk_get_rate(uap->clk);
port->uartclk = clk_get_rate(uap->clk);
/*
* Allocate the IRQ
*/
retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap);
retval = request_irq(port->irq, pl010_int, 0, "uart-pl010", uap);
if (retval)
goto clk_dis;
/*
* initialise the old status of the modem signals
*/
uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
/*
* Finally, enable interrupts
*/
writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
uap->port.membase + UART010_CR);
port->membase + UART010_CR);
return 0;
@ -353,17 +350,17 @@ static void pl010_shutdown(struct uart_port *port)
/*
* Free the interrupt
*/
free_irq(uap->port.irq, uap);
free_irq(port->irq, uap);
/*
* disable all interrupts, disable the port
*/
writel(0, uap->port.membase + UART010_CR);
writel(0, port->membase + UART010_CR);
/* disable break condition and fifos */
writel(readb(uap->port.membase + UART010_LCRH) &
writel(readb(port->membase + UART010_LCRH) &
~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
uap->port.membase + UART010_LCRH);
port->membase + UART010_LCRH);
/*
* Shut down the clock producer
@ -375,8 +372,6 @@ static void
pl010_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
unsigned int lcr_h, old_cr;
unsigned long flags;
unsigned int baud, quot;
@ -384,7 +379,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Ask the core to calculate the divisor for us.
*/
baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
quot = uart_get_divisor(port, baud);
switch (termios->c_cflag & CSIZE) {
@ -408,63 +403,63 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
if (!(termios->c_cflag & PARODD))
lcr_h |= UART01x_LCRH_EPS;
}
if (uap->port.fifosize > 1)
if (port->fifosize > 1)
lcr_h |= UART01x_LCRH_FEN;
spin_lock_irqsave(&uap->port.lock, flags);
spin_lock_irqsave(&port->lock, flags);
/*
* Update the per-port timeout.
*/
uart_update_timeout(port, termios->c_cflag, baud);
uap->port.read_status_mask = UART01x_RSR_OE;
port->read_status_mask = UART01x_RSR_OE;
if (termios->c_iflag & INPCK)
uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
uap->port.read_status_mask |= UART01x_RSR_BE;
port->read_status_mask |= UART01x_RSR_BE;
/*
* Characters to ignore
*/
uap->port.ignore_status_mask = 0;
port->ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
if (termios->c_iflag & IGNBRK) {
uap->port.ignore_status_mask |= UART01x_RSR_BE;
port->ignore_status_mask |= UART01x_RSR_BE;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if (termios->c_iflag & IGNPAR)
uap->port.ignore_status_mask |= UART01x_RSR_OE;
port->ignore_status_mask |= UART01x_RSR_OE;
}
/*
* Ignore all characters if CREAD is not set.
*/
if ((termios->c_cflag & CREAD) == 0)
uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX;
port->ignore_status_mask |= UART_DUMMY_RSR_RX;
old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE;
if (UART_ENABLE_MS(port, termios->c_cflag))
old_cr |= UART010_CR_MSIE;
/* Set baud rate */
quot -= 1;
writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
writel(quot & 0xff, uap->port.membase + UART010_LCRL);
writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM);
writel(quot & 0xff, port->membase + UART010_LCRL);
/*
* ----------v----------v----------v----------v-----
* NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
* ----------^----------^----------^----------^-----
*/
writel(lcr_h, uap->port.membase + UART010_LCRH);
writel(old_cr, uap->port.membase + UART010_CR);
writel(lcr_h, port->membase + UART010_LCRH);
writel(old_cr, port->membase + UART010_CR);
spin_unlock_irqrestore(&uap->port.lock, flags);
spin_unlock_irqrestore(&port->lock, flags);
}
static void pl010_set_ldisc(struct uart_port *port, struct ktermios *termios)
@ -556,23 +551,22 @@ static struct uart_amba_port *amba_ports[UART_NR];
#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
static void pl010_console_putchar(struct uart_port *port, int ch)
static void pl010_console_putchar(struct uart_port *port, unsigned char ch)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
unsigned int status;
do {
status = readb(uap->port.membase + UART01x_FR);
status = readb(port->membase + UART01x_FR);
barrier();
} while (!UART_TX_READY(status));
writel(ch, uap->port.membase + UART01x_DR);
writel(ch, port->membase + UART01x_DR);
}
static void
pl010_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_amba_port *uap = amba_ports[co->index];
struct uart_port *port = &uap->port;
unsigned int status, old_cr;
clk_enable(uap->clk);
@ -580,20 +574,20 @@ pl010_console_write(struct console *co, const char *s, unsigned int count)
/*
* First save the CR then disable the interrupts
*/
old_cr = readb(uap->port.membase + UART010_CR);
writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR);
old_cr = readb(port->membase + UART010_CR);
writel(UART01x_CR_UARTEN, port->membase + UART010_CR);
uart_console_write(&uap->port, s, count, pl010_console_putchar);
uart_console_write(port, s, count, pl010_console_putchar);
/*
* Finally, wait for transmitter to become empty
* and restore the TCR
*/
do {
status = readb(uap->port.membase + UART01x_FR);
status = readb(port->membase + UART01x_FR);
barrier();
} while (status & UART01x_FR_BUSY);
writel(old_cr, uap->port.membase + UART010_CR);
writel(old_cr, port->membase + UART010_CR);
clk_disable(uap->clk);
}

View File

@ -2255,7 +2255,7 @@ static struct uart_amba_port *amba_ports[UART_NR];
#ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
static void pl011_console_putchar(struct uart_port *port, int ch)
static void pl011_console_putchar(struct uart_port *port, unsigned char ch)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
@ -2471,7 +2471,7 @@ static struct console amba_console = {
#define AMBA_CONSOLE (&amba_console)
static void qdf2400_e44_putc(struct uart_port *port, int c)
static void qdf2400_e44_putc(struct uart_port *port, unsigned char c)
{
while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
cpu_relax();
@ -2487,7 +2487,7 @@ static void qdf2400_e44_early_write(struct console *con, const char *s, unsigned
uart_console_write(&dev->port, s, n, qdf2400_e44_putc);
}
static void pl011_putc(struct uart_port *port, int c)
static void pl011_putc(struct uart_port *port, unsigned char c)
{
while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
cpu_relax();

View File

@ -413,7 +413,7 @@ static void apbuart_flush_fifo(struct uart_port *port)
#ifdef CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
static void apbuart_console_putchar(struct uart_port *port, int ch)
static void apbuart_console_putchar(struct uart_port *port, unsigned char ch)
{
unsigned int status;
do {

View File

@ -613,7 +613,7 @@ static void ar933x_uart_wait_xmitr(struct ar933x_uart_port *up)
} while ((status & AR933X_UART_DATA_TX_CSR) == 0);
}
static void ar933x_uart_console_putchar(struct uart_port *port, int ch)
static void ar933x_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
struct ar933x_uart_port *up =
container_of(port, struct ar933x_uart_port, port);

View File

@ -508,7 +508,7 @@ static int arc_serial_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
static void arc_serial_console_putchar(struct uart_port *port, int ch)
static void arc_serial_console_putchar(struct uart_port *port, unsigned char ch)
{
while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax();

View File

@ -8,6 +8,7 @@
*
* DMA support added by Chip Coldwell.
*/
#include <linux/circ_buf.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/slab.h>
@ -2540,7 +2541,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
}
#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
static void atmel_console_putchar(struct uart_port *port, int ch)
static void atmel_console_putchar(struct uart_port *port, unsigned char ch)
{
while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
cpu_relax();
@ -2672,6 +2673,30 @@ static struct console atmel_console = {
.data = &atmel_uart,
};
static void atmel_serial_early_write(struct console *con, const char *s,
unsigned int n)
{
struct earlycon_device *dev = con->data;
uart_console_write(&dev->port, s, n, atmel_console_putchar);
}
static int __init atmel_early_console_setup(struct earlycon_device *device,
const char *options)
{
if (!device->port.membase)
return -ENODEV;
device->con->write = atmel_serial_early_write;
return 0;
}
OF_EARLYCON_DECLARE(atmel_serial, "atmel,at91rm9200-usart",
atmel_early_console_setup);
OF_EARLYCON_DECLARE(atmel_serial, "atmel,at91sam9260-usart",
atmel_early_console_setup);
#define ATMEL_CONSOLE_DEVICE (&atmel_console)
#else

View File

@ -681,7 +681,7 @@ static void wait_for_xmitr(struct uart_port *port)
/*
* output given char
*/
static void bcm_console_putchar(struct uart_port *port, int ch)
static void bcm_console_putchar(struct uart_port *port, unsigned char ch)
{
wait_for_xmitr(port);
bcm_uart_writel(port, ch, UART_FIFO_REG);

View File

@ -348,7 +348,7 @@ static const struct uart_ops uart_clps711x_ops = {
};
#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
static void uart_clps711x_console_putchar(struct uart_port *port, unsigned char ch)
{
struct clps711x_port *s = dev_get_drvdata(port->dev);
u32 sysflg = 0;

View File

@ -381,7 +381,7 @@ static const struct uart_ops digicolor_uart_ops = {
.request_port = digicolor_uart_request_port,
};
static void digicolor_uart_console_putchar(struct uart_port *port, int ch)
static void digicolor_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
while (digicolor_uart_tx_full(port))
cpu_relax();

View File

@ -802,7 +802,7 @@ static void __init dz_init_ports(void)
* restored. Welcome to the world of PDP-11!
* -------------------------------------------------------------------
*/
static void dz_console_putchar(struct uart_port *uport, int ch)
static void dz_console_putchar(struct uart_port *uport, unsigned char ch)
{
struct dz_port *dport = to_dport(uport);
unsigned long flags;

View File

@ -21,7 +21,7 @@
/*
* Semihosting-based debug console
*/
static void smh_putc(struct uart_port *port, int c)
static void smh_putc(struct uart_port *port, unsigned char c)
{
#ifdef CONFIG_ARM64
asm volatile("mov x1, %0\n"

View File

@ -10,7 +10,7 @@
#include <linux/serial_core.h>
#include <asm/sbi.h>
static void sbi_putc(struct uart_port *port, int c)
static void sbi_putc(struct uart_port *port, unsigned char c)
{
sbi_console_putchar(c);
}

View File

@ -157,27 +157,29 @@ static void linflex_stop_rx(struct uart_port *port)
writel(ier & ~LINFLEXD_LINIER_DRIE, port->membase + LINIER);
}
static void linflex_put_char(struct uart_port *sport, unsigned char c)
{
unsigned long status;
writeb(c, sport->membase + BDRL);
/* Waiting for data transmission completed. */
while (((status = readl(sport->membase + UARTSR)) &
LINFLEXD_UARTSR_DTFTFF) !=
LINFLEXD_UARTSR_DTFTFF)
;
writel(status | LINFLEXD_UARTSR_DTFTFF, sport->membase + UARTSR);
}
static inline void linflex_transmit_buffer(struct uart_port *sport)
{
struct circ_buf *xmit = &sport->state->xmit;
unsigned char c;
unsigned long status;
while (!uart_circ_empty(xmit)) {
c = xmit->buf[xmit->tail];
writeb(c, sport->membase + BDRL);
/* Waiting for data transmission completed. */
while (((status = readl(sport->membase + UARTSR)) &
LINFLEXD_UARTSR_DTFTFF) !=
LINFLEXD_UARTSR_DTFTFF)
;
linflex_put_char(sport, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
sport->icount.tx++;
writel(status | LINFLEXD_UARTSR_DTFTFF,
sport->membase + UARTSR);
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
@ -201,21 +203,11 @@ static irqreturn_t linflex_txint(int irq, void *dev_id)
struct uart_port *sport = dev_id;
struct circ_buf *xmit = &sport->state->xmit;
unsigned long flags;
unsigned long status;
spin_lock_irqsave(&sport->lock, flags);
if (sport->x_char) {
writeb(sport->x_char, sport->membase + BDRL);
/* waiting for data transmission completed */
while (((status = readl(sport->membase + UARTSR)) &
LINFLEXD_UARTSR_DTFTFF) != LINFLEXD_UARTSR_DTFTFF)
;
writel(status | LINFLEXD_UARTSR_DTFTFF,
sport->membase + UARTSR);
linflex_put_char(sport, sport->x_char);
goto out;
}
@ -225,10 +217,6 @@ static irqreturn_t linflex_txint(int irq, void *dev_id)
}
linflex_transmit_buffer(sport);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(sport);
out:
spin_unlock_irqrestore(&sport->lock, flags);
return IRQ_HANDLED;
@ -565,7 +553,7 @@ static const struct uart_ops linflex_pops = {
static struct uart_port *linflex_ports[UART_NR];
#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE
static void linflex_console_putchar(struct uart_port *port, int ch)
static void linflex_console_putchar(struct uart_port *port, unsigned char ch)
{
unsigned long cr;
@ -590,7 +578,7 @@ static void linflex_console_putchar(struct uart_port *port, int ch)
}
}
static void linflex_earlycon_putchar(struct uart_port *port, int ch)
static void linflex_earlycon_putchar(struct uart_port *port, unsigned char ch)
{
unsigned long flags;
char *ret;

View File

@ -931,7 +931,8 @@ static void lpuart_rxint(struct lpuart_port *sport)
sport->port.sysrq = 0;
}
tty_insert_flip_char(port, rx, flg);
if (tty_insert_flip_char(port, rx, flg) == 0)
sport->port.icount.buf_overrun++;
}
out:
@ -1024,7 +1025,8 @@ static void lpuart32_rxint(struct lpuart_port *sport)
flg = TTY_OVERRUN;
}
tty_insert_flip_char(port, rx, flg);
if (tty_insert_flip_char(port, rx, flg) == 0)
sport->port.icount.buf_overrun++;
}
out:
@ -1116,7 +1118,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
struct dma_chan *chan = sport->dma_rx_chan;
struct circ_buf *ring = &sport->rx_ring;
unsigned long flags;
int count = 0;
int count = 0, copied;
if (lpuart_is_32(sport)) {
unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
@ -1218,20 +1220,24 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
if (ring->head < ring->tail) {
count = sport->rx_sgl.length - ring->tail;
tty_insert_flip_string(port, ring->buf + ring->tail, count);
copied = tty_insert_flip_string(port, ring->buf + ring->tail, count);
if (copied != count)
sport->port.icount.buf_overrun++;
ring->tail = 0;
sport->port.icount.rx += count;
sport->port.icount.rx += copied;
}
/* Finally we read data from tail to head */
if (ring->tail < ring->head) {
count = ring->head - ring->tail;
tty_insert_flip_string(port, ring->buf + ring->tail, count);
copied = tty_insert_flip_string(port, ring->buf + ring->tail, count);
if (copied != count)
sport->port.icount.buf_overrun++;
/* Wrap ring->head if needed */
if (ring->head >= sport->rx_sgl.length)
ring->head = 0;
ring->tail = ring->head;
sport->port.icount.rx += count;
sport->port.icount.rx += copied;
}
exit:
@ -2327,13 +2333,13 @@ static const struct uart_ops lpuart32_pops = {
static struct lpuart_port *lpuart_ports[UART_NR];
#ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE
static void lpuart_console_putchar(struct uart_port *port, int ch)
static void lpuart_console_putchar(struct uart_port *port, unsigned char ch)
{
lpuart_wait_bit_set(port, UARTSR1, UARTSR1_TDRE);
writeb(ch, port->membase + UARTDR);
}
static void lpuart32_console_putchar(struct uart_port *port, int ch)
static void lpuart32_console_putchar(struct uart_port *port, unsigned char ch)
{
lpuart32_wait_bit_set(port, UARTSTAT, UARTSTAT_TDRE);
lpuart32_write(port, ch, UARTDATA);

View File

@ -455,9 +455,14 @@ static void imx_uart_stop_tx(struct uart_port *port)
if (port->rs485.flags & SER_RS485_ENABLED) {
if (sport->tx_state == SEND) {
sport->tx_state = WAIT_AFTER_SEND;
start_hrtimer_ms(&sport->trigger_stop_tx,
if (port->rs485.delay_rts_after_send > 0) {
start_hrtimer_ms(&sport->trigger_stop_tx,
port->rs485.delay_rts_after_send);
return;
return;
}
/* continue without any delay */
}
if (sport->tx_state == WAIT_AFTER_RTS ||
@ -698,9 +703,14 @@ static void imx_uart_start_tx(struct uart_port *port)
imx_uart_stop_rx(port);
sport->tx_state = WAIT_AFTER_RTS;
start_hrtimer_ms(&sport->trigger_start_tx,
if (port->rs485.delay_rts_before_send > 0) {
start_hrtimer_ms(&sport->trigger_start_tx,
port->rs485.delay_rts_before_send);
return;
return;
}
/* continue without any delay */
}
if (sport->tx_state == WAIT_AFTER_SEND
@ -1258,7 +1268,7 @@ static void imx_uart_clear_rx_errors(struct imx_port *sport)
}
#define TXTL_DEFAULT 2 /* reset default */
#define RXTL_DEFAULT 1 /* reset default */
#define RXTL_DEFAULT 8 /* 8 characters or aging timer */
#define TXTL_DMA 8 /* DMA burst setting */
#define RXTL_DMA 9 /* DMA burst setting */
@ -1958,7 +1968,7 @@ static const struct uart_ops imx_uart_pops = {
static struct imx_port *imx_uart_ports[UART_NR];
#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_console_putchar(struct uart_port *port, int ch)
static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
struct imx_port *sport = (struct imx_port *)port;

View File

@ -16,7 +16,7 @@
#define UTS_TXFULL (1<<4) /* TxFIFO full */
#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/
static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
static void imx_uart_console_early_putchar(struct uart_port *port, unsigned char ch)
{
while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
cpu_relax();

View File

@ -990,7 +990,7 @@ static struct zilog_layout * __init get_zs(int chip)
#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
#ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE
static void ip22zilog_put_char(struct uart_port *port, int ch)
static void ip22zilog_put_char(struct uart_port *port, unsigned char ch)
{
struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
int loops = ZS_PUT_CHAR_MAX_DELAY;

View File

@ -350,7 +350,7 @@ static void cls_assert_modem_signals(struct jsm_channel *ch)
static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch)
{
int qleft = 0;
u8 linestatus = 0;
u8 linestatus;
u8 error_mask = 0;
u16 head;
u16 tail;
@ -365,8 +365,6 @@ static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch)
head = ch->ch_r_head & RQUEUEMASK;
tail = ch->ch_r_tail & RQUEUEMASK;
/* Get our cached LSR */
linestatus = ch->ch_cached_lsr;
ch->ch_cached_lsr = 0;
/* Store how much space we have left in the queue */
@ -737,21 +735,7 @@ static void cls_param(struct jsm_channel *ch)
if (ch->ch_c_cflag & CSTOPB)
lcr |= UART_LCR_STOP;
switch (ch->ch_c_cflag & CSIZE) {
case CS5:
lcr |= UART_LCR_WLEN5;
break;
case CS6:
lcr |= UART_LCR_WLEN6;
break;
case CS7:
lcr |= UART_LCR_WLEN7;
break;
case CS8:
default:
lcr |= UART_LCR_WLEN8;
break;
}
lcr |= UART_LCR_WLEN(tty_get_char_size(ch->ch_c_cflag));
ier = readb(&ch->ch_cls_uart->ier);
uart_lcr = readb(&ch->ch_cls_uart->lcr);

View File

@ -291,7 +291,8 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
ch->ch_cached_lsr = 0;
/* Store how much space we have left in the queue */
if ((qleft = tail - head - 1) < 0)
qleft = tail - head - 1;
if (qleft < 0)
qleft += RQUEUEMASK + 1;
/*
@ -1008,21 +1009,7 @@ static void neo_param(struct jsm_channel *ch)
if (ch->ch_c_cflag & CSTOPB)
lcr |= UART_LCR_STOP;
switch (ch->ch_c_cflag & CSIZE) {
case CS5:
lcr |= UART_LCR_WLEN5;
break;
case CS6:
lcr |= UART_LCR_WLEN6;
break;
case CS7:
lcr |= UART_LCR_WLEN7;
break;
case CS8:
default:
lcr |= UART_LCR_WLEN8;
break;
}
lcr |= UART_LCR_WLEN(tty_get_char_size(ch->ch_c_cflag));
ier = readb(&ch->ch_neo_uart->ier);
uart_lcr = readb(&ch->ch_neo_uart->lcr);

View File

@ -749,7 +749,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
int qleft;
/* Store how much space we have left in the queue */
if ((qleft = ch->ch_r_tail - ch->ch_r_head - 1) < 0)
qleft = ch->ch_r_tail - ch->ch_r_head - 1;
if (qleft < 0)
qleft += RQUEUEMASK + 1;
/*

View File

@ -403,16 +403,16 @@ static int kgdboc_option_setup(char *opt)
{
if (!opt) {
pr_err("config string not provided\n");
return -EINVAL;
return 1;
}
if (strlen(opt) >= MAX_CONFIG_LEN) {
pr_err("config string too long\n");
return -ENOSPC;
return 1;
}
strcpy(config, opt);
return 0;
return 1;
}
__setup("kgdboc=", kgdboc_option_setup);

View File

@ -598,7 +598,7 @@ static const struct uart_ops lqasc_pops = {
#ifdef CONFIG_SERIAL_LANTIQ_CONSOLE
static void
lqasc_console_putchar(struct uart_port *port, int ch)
lqasc_console_putchar(struct uart_port *port, unsigned char ch)
{
int fifofree;

View File

@ -93,7 +93,7 @@ static void liteuart_timer(struct timer_list *t)
mod_timer(&uart->timer, jiffies + uart_poll_timeout(port));
}
static void liteuart_putchar(struct uart_port *port, int ch)
static void liteuart_putchar(struct uart_port *port, unsigned char ch)
{
while (litex_read8(port->membase + OFF_TXFULL))
cpu_relax();

View File

@ -122,7 +122,7 @@ static void wait_for_xmit_ready(struct uart_port *port)
}
}
static void lpc32xx_hsuart_console_putchar(struct uart_port *port, int ch)
static void lpc32xx_hsuart_console_putchar(struct uart_port *port, unsigned char ch)
{
wait_for_xmit_ready(port);
writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase));
@ -276,10 +276,11 @@ static void __serial_lpc32xx_rx(struct uart_port *port)
tty_flip_buffer_push(tport);
}
static void serial_lpc32xx_stop_tx(struct uart_port *port);
static void __serial_lpc32xx_tx(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
unsigned int tmp;
if (port->x_char) {
writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase));
@ -306,11 +307,8 @@ static void __serial_lpc32xx_tx(struct uart_port *port)
uart_write_wakeup(port);
exit_tx:
if (uart_circ_empty(xmit)) {
tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
tmp &= ~LPC32XX_HSU_TX_INT_EN;
writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
}
if (uart_circ_empty(xmit))
serial_lpc32xx_stop_tx(port);
}
static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)

View File

@ -554,7 +554,6 @@ static void max3100_shutdown(struct uart_port *port)
del_timer_sync(&s->timer);
if (s->workqueue) {
flush_workqueue(s->workqueue);
destroy_workqueue(s->workqueue);
s->workqueue = NULL;
}

View File

@ -338,7 +338,7 @@ static void mcf_tx_chars(struct mcf_uart *pp)
}
while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) {
if (xmit->head == xmit->tail)
if (uart_circ_empty(xmit))
break;
writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
@ -348,9 +348,8 @@ static void mcf_tx_chars(struct mcf_uart *pp)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (xmit->head == xmit->tail) {
pp->imr &= ~MCFUART_UIR_TXREADY;
writeb(pp->imr, port->membase + MCFUART_UIMR);
if (uart_circ_empty(xmit)) {
mcf_stop_tx(port);
/* Disable TX to negate RTS automatically */
if (port->rs485.flags & SER_RS485_ENABLED)
writeb(MCFUART_UCR_TXDISABLE,

View File

@ -513,7 +513,7 @@ static void meson_uart_enable_tx_engine(struct uart_port *port)
writel(val, port->membase + AML_UART_CONTROL);
}
static void meson_console_putchar(struct uart_port *port, int ch)
static void meson_console_putchar(struct uart_port *port, unsigned char ch)
{
if (!port->membase)
return;

View File

@ -400,7 +400,7 @@ static const struct uart_ops mlb_usio_ops = {
#ifdef CONFIG_SERIAL_MILBEAUT_USIO_CONSOLE
static void mlb_usio_console_putchar(struct uart_port *port, int c)
static void mlb_usio_console_putchar(struct uart_port *port, unsigned char c)
{
while (!(readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TDRE))
cpu_relax();

View File

@ -83,11 +83,11 @@ static irqreturn_t mpc5xxx_uart_process_int(struct uart_port *port);
struct psc_ops {
void (*fifo_init)(struct uart_port *port);
int (*raw_rx_rdy)(struct uart_port *port);
int (*raw_tx_rdy)(struct uart_port *port);
int (*rx_rdy)(struct uart_port *port);
int (*tx_rdy)(struct uart_port *port);
int (*tx_empty)(struct uart_port *port);
unsigned int (*raw_rx_rdy)(struct uart_port *port);
unsigned int (*raw_tx_rdy)(struct uart_port *port);
unsigned int (*rx_rdy)(struct uart_port *port);
unsigned int (*tx_rdy)(struct uart_port *port);
unsigned int (*tx_empty)(struct uart_port *port);
void (*stop_rx)(struct uart_port *port);
void (*start_tx)(struct uart_port *port);
void (*stop_tx)(struct uart_port *port);
@ -203,34 +203,34 @@ static void mpc52xx_psc_fifo_init(struct uart_port *port)
out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
}
static int mpc52xx_psc_raw_rx_rdy(struct uart_port *port)
static unsigned int mpc52xx_psc_raw_rx_rdy(struct uart_port *port)
{
return in_be16(&PSC(port)->mpc52xx_psc_status)
& MPC52xx_PSC_SR_RXRDY;
}
static int mpc52xx_psc_raw_tx_rdy(struct uart_port *port)
static unsigned int mpc52xx_psc_raw_tx_rdy(struct uart_port *port)
{
return in_be16(&PSC(port)->mpc52xx_psc_status)
& MPC52xx_PSC_SR_TXRDY;
}
static int mpc52xx_psc_rx_rdy(struct uart_port *port)
static unsigned int mpc52xx_psc_rx_rdy(struct uart_port *port)
{
return in_be16(&PSC(port)->mpc52xx_psc_isr)
& port->read_status_mask
& MPC52xx_PSC_IMR_RXRDY;
}
static int mpc52xx_psc_tx_rdy(struct uart_port *port)
static unsigned int mpc52xx_psc_tx_rdy(struct uart_port *port)
{
return in_be16(&PSC(port)->mpc52xx_psc_isr)
& port->read_status_mask
& MPC52xx_PSC_IMR_TXRDY;
}
static int mpc52xx_psc_tx_empty(struct uart_port *port)
static unsigned int mpc52xx_psc_tx_empty(struct uart_port *port)
{
u16 sts = in_be16(&PSC(port)->mpc52xx_psc_status);
@ -1365,7 +1365,7 @@ static const struct uart_ops mpc52xx_uart_ops = {
/* Interrupt handling */
/* ======================================================================== */
static inline int
static inline unsigned int
mpc52xx_uart_int_rx_chars(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;

View File

@ -432,7 +432,7 @@ static const struct uart_ops mps2_uart_pops = {
static DEFINE_IDR(ports_idr);
#ifdef CONFIG_SERIAL_MPS2_UART_CONSOLE
static void mps2_uart_console_putchar(struct uart_port *port, int ch)
static void mps2_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
while (mps2_uart_read8(port, UARTn_STATE) & UARTn_STATE_TX_FULL)
cpu_relax();
@ -484,7 +484,7 @@ static struct console mps2_uart_console = {
#define MPS2_SERIAL_CONSOLE (&mps2_uart_console)
static void mps2_early_putchar(struct uart_port *port, int ch)
static void mps2_early_putchar(struct uart_port *port, unsigned char ch)
{
while (readb(port->membase + UARTn_STATE) & UARTn_STATE_TX_FULL)
cpu_relax();

View File

@ -8,12 +8,14 @@
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/math64.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
@ -68,12 +70,36 @@
#define STAT_BRK_ERR (STAT_BRK_DET | STAT_FRM_ERR \
| STAT_PAR_ERR | STAT_OVR_ERR)
/*
* Marvell Armada 3700 Functional Specifications describes that bit 21 of UART
* Clock Control register controls UART1 and bit 20 controls UART2. But in
* reality bit 21 controls UART2 and bit 20 controls UART1. This seems to be an
* error in Marvell's documentation. Hence following CLK_DIS macros are swapped.
*/
#define UART_BRDV 0x10
/* These bits are located in UART1 address space and control UART2 */
#define UART2_CLK_DIS BIT(21)
/* These bits are located in UART1 address space and control UART1 */
#define UART1_CLK_DIS BIT(20)
/* These bits are located in UART1 address space and control both UARTs */
#define CLK_NO_XTAL BIT(19)
#define CLK_TBG_DIV1_SHIFT 15
#define CLK_TBG_DIV1_MASK 0x7
#define CLK_TBG_DIV1_MAX 6
#define CLK_TBG_DIV2_SHIFT 12
#define CLK_TBG_DIV2_MASK 0x7
#define CLK_TBG_DIV2_MAX 6
#define CLK_TBG_SEL_SHIFT 10
#define CLK_TBG_SEL_MASK 0x3
/* These bits are located in both UARTs address space */
#define BRDV_BAUD_MASK 0x3FF
#define BRDV_BAUD_MAX BRDV_BAUD_MASK
#define UART_OSAMP 0x14
#define OSAMP_DEFAULT_DIVISOR 16
#define OSAMP_DIVISORS_MASK 0x3F3F3F3F
#define OSAMP_MAX_DIVISOR 63
#define MVEBU_NR_UARTS 2
@ -153,6 +179,8 @@ static struct mvebu_uart *to_mvuart(struct uart_port *port)
static struct uart_port mvebu_uart_ports[MVEBU_NR_UARTS];
static DEFINE_SPINLOCK(mvebu_uart_lock);
/* Core UART Driver Operations */
static unsigned int mvebu_uart_tx_empty(struct uart_port *port)
{
@ -445,31 +473,79 @@ static void mvebu_uart_shutdown(struct uart_port *port)
static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
{
unsigned int d_divisor, m_divisor;
unsigned long flags;
u32 brdv, osamp;
if (!port->uartclk)
return -EOPNOTSUPP;
/*
* The baudrate is derived from the UART clock thanks to two divisors:
* > D ("baud generator"): can divide the clock from 2 to 2^10 - 1.
* > M ("fractional divisor"): allows a better accuracy for
* baudrates higher than 230400.
* The baudrate is derived from the UART clock thanks to divisors:
* > d1 * d2 ("TBG divisors"): can divide only TBG clock from 1 to 6
* > D ("baud generator"): can divide the clock from 1 to 1023
* > M ("fractional divisor"): allows a better accuracy (from 1 to 63)
*
* As the derivation of M is rather complicated, the code sticks to its
* default value (x16) when all the prescalers are zeroed, and only
* makes use of D to configure the desired baudrate.
* Exact formulas for calculating baudrate:
*
* with default x16 scheme:
* baudrate = xtal / (d * 16)
* baudrate = tbg / (d1 * d2 * d * 16)
*
* with fractional divisor:
* baudrate = 10 * xtal / (d * (3 * (m1 + m2) + 2 * (m3 + m4)))
* baudrate = 10 * tbg / (d1*d2 * d * (3 * (m1 + m2) + 2 * (m3 + m4)))
*
* Oversampling value:
* osamp = (m1 << 0) | (m2 << 8) | (m3 << 16) | (m4 << 24);
*
* Where m1 controls number of clock cycles per bit for bits 1,2,3;
* m2 for bits 4,5,6; m3 for bits 7,8 and m4 for bits 9,10.
*
* To simplify baudrate setup set all the M prescalers to the same
* value. For baudrates 9600 Bd and higher, it is enough to use the
* default (x16) divisor or fractional divisor with M = 63, so there
* is no need to use real fractional support (where the M prescalers
* are not equal).
*
* When all the M prescalers are zeroed then default (x16) divisor is
* used. Default x16 scheme is more stable than M (fractional divisor),
* so use M only when D divisor is not enough to derive baudrate.
*
* Member port->uartclk is either xtal clock rate or TBG clock rate
* divided by (d1 * d2). So d1 and d2 are already set by the UART clock
* driver (and UART driver itself cannot change them). Moreover they are
* shared between both UARTs.
*/
m_divisor = OSAMP_DEFAULT_DIVISOR;
d_divisor = DIV_ROUND_CLOSEST(port->uartclk, baud * m_divisor);
if (d_divisor > BRDV_BAUD_MAX) {
/*
* Experiments show that small M divisors are unstable.
* Use maximal possible M = 63 and calculate D divisor.
*/
m_divisor = OSAMP_MAX_DIVISOR;
d_divisor = DIV_ROUND_CLOSEST(port->uartclk, baud * m_divisor);
}
if (d_divisor < 1)
d_divisor = 1;
else if (d_divisor > BRDV_BAUD_MAX)
d_divisor = BRDV_BAUD_MAX;
spin_lock_irqsave(&mvebu_uart_lock, flags);
brdv = readl(port->membase + UART_BRDV);
brdv &= ~BRDV_BAUD_MASK;
brdv |= d_divisor;
writel(brdv, port->membase + UART_BRDV);
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
osamp = readl(port->membase + UART_OSAMP);
osamp &= ~OSAMP_DIVISORS_MASK;
if (m_divisor != OSAMP_DEFAULT_DIVISOR)
osamp |= (m_divisor << 0) | (m_divisor << 8) |
(m_divisor << 16) | (m_divisor << 24);
writel(osamp, port->membase + UART_OSAMP);
return 0;
@ -499,14 +575,16 @@ static void mvebu_uart_set_termios(struct uart_port *port,
port->ignore_status_mask |= STAT_RX_RDY(port) | STAT_BRK_ERR;
/*
* Maximal divisor is 1023 * 16 when using default (x16) scheme.
* Maximum achievable frequency with simple baudrate divisor is 230400.
* Since the error per bit frame would be of more than 15%, achieving
* higher frequencies would require to implement the fractional divisor
* feature.
* Maximal divisor is 1023 and maximal fractional divisor is 63. And
* experiments show that baudrates above 1/80 of parent clock rate are
* not stable. So disallow baudrates above 1/80 of the parent clock
* rate. If port->uartclk is not available, then
* mvebu_uart_baud_rate_set() fails, so values min_baud and max_baud
* in this case do not matter.
*/
min_baud = DIV_ROUND_UP(port->uartclk, 1023 * 16);
max_baud = 230400;
min_baud = DIV_ROUND_UP(port->uartclk, BRDV_BAUD_MAX *
OSAMP_MAX_DIVISOR);
max_baud = port->uartclk / 80;
baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud);
if (mvebu_uart_baud_rate_set(port, baud)) {
@ -598,7 +676,7 @@ static const struct uart_ops mvebu_uart_ops = {
#ifdef CONFIG_SERIAL_MVEBU_CONSOLE
/* Early Console */
static void mvebu_uart_putc(struct uart_port *port, int c)
static void mvebu_uart_putc(struct uart_port *port, unsigned char c)
{
unsigned int st;
@ -659,7 +737,7 @@ static void wait_for_xmite(struct uart_port *port)
(val & STAT_TX_EMP), 1, 10000);
}
static void mvebu_uart_console_putchar(struct uart_port *port, int ch)
static void mvebu_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
wait_for_xmitr(port);
writel(ch, port->membase + UART_TSH(port));
@ -762,6 +840,7 @@ static int mvebu_uart_suspend(struct device *dev)
{
struct mvebu_uart *mvuart = dev_get_drvdata(dev);
struct uart_port *port = mvuart->port;
unsigned long flags;
uart_suspend_port(&mvebu_uart_driver, port);
@ -770,7 +849,9 @@ static int mvebu_uart_suspend(struct device *dev)
mvuart->pm_regs.ctrl = readl(port->membase + UART_CTRL(port));
mvuart->pm_regs.intr = readl(port->membase + UART_INTR(port));
mvuart->pm_regs.stat = readl(port->membase + UART_STAT);
spin_lock_irqsave(&mvebu_uart_lock, flags);
mvuart->pm_regs.brdv = readl(port->membase + UART_BRDV);
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
mvuart->pm_regs.osamp = readl(port->membase + UART_OSAMP);
device_set_wakeup_enable(dev, true);
@ -782,13 +863,16 @@ static int mvebu_uart_resume(struct device *dev)
{
struct mvebu_uart *mvuart = dev_get_drvdata(dev);
struct uart_port *port = mvuart->port;
unsigned long flags;
writel(mvuart->pm_regs.rbr, port->membase + UART_RBR(port));
writel(mvuart->pm_regs.tsh, port->membase + UART_TSH(port));
writel(mvuart->pm_regs.ctrl, port->membase + UART_CTRL(port));
writel(mvuart->pm_regs.intr, port->membase + UART_INTR(port));
writel(mvuart->pm_regs.stat, port->membase + UART_STAT);
spin_lock_irqsave(&mvebu_uart_lock, flags);
writel(mvuart->pm_regs.brdv, port->membase + UART_BRDV);
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
writel(mvuart->pm_regs.osamp, port->membase + UART_OSAMP);
uart_resume_port(&mvebu_uart_driver, port);
@ -972,6 +1056,477 @@ static struct platform_driver mvebu_uart_platform_driver = {
},
};
/* This code is based on clk-fixed-factor.c driver and modified. */
struct mvebu_uart_clock {
struct clk_hw clk_hw;
int clock_idx;
u32 pm_context_reg1;
u32 pm_context_reg2;
};
struct mvebu_uart_clock_base {
struct mvebu_uart_clock clocks[2];
unsigned int parent_rates[5];
int parent_idx;
unsigned int div;
void __iomem *reg1;
void __iomem *reg2;
bool configured;
};
#define PARENT_CLOCK_XTAL 4
#define to_uart_clock(hw) container_of(hw, struct mvebu_uart_clock, clk_hw)
#define to_uart_clock_base(uart_clock) container_of(uart_clock, \
struct mvebu_uart_clock_base, clocks[uart_clock->clock_idx])
static int mvebu_uart_clock_prepare(struct clk_hw *hw)
{
struct mvebu_uart_clock *uart_clock = to_uart_clock(hw);
struct mvebu_uart_clock_base *uart_clock_base =
to_uart_clock_base(uart_clock);
unsigned int prev_clock_idx, prev_clock_rate, prev_d1d2;
unsigned int parent_clock_idx, parent_clock_rate;
unsigned long flags;
unsigned int d1, d2;
u64 divisor;
u32 val;
/*
* This function just reconfigures UART Clock Control register (located
* in UART1 address space which controls both UART1 and UART2) to
* selected UART base clock and recalculates current UART1/UART2
* divisors in their address spaces, so that final baudrate will not be
* changed by switching UART parent clock. This is required for
* otherwise kernel's boot log stops working - we need to ensure that
* UART baudrate does not change during this setup. It is a one time
* operation, it will execute only once and set `configured` to true,
* and be skipped on subsequent calls. Because this UART Clock Control
* register (UART_BRDV) is shared between UART1 baudrate function,
* UART1 clock selector and UART2 clock selector, every access to
* UART_BRDV (reg1) needs to be protected by a lock.
*/
spin_lock_irqsave(&mvebu_uart_lock, flags);
if (uart_clock_base->configured) {
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
return 0;
}
parent_clock_idx = uart_clock_base->parent_idx;
parent_clock_rate = uart_clock_base->parent_rates[parent_clock_idx];
val = readl(uart_clock_base->reg1);
if (uart_clock_base->div > CLK_TBG_DIV1_MAX) {
d1 = CLK_TBG_DIV1_MAX;
d2 = uart_clock_base->div / CLK_TBG_DIV1_MAX;
} else {
d1 = uart_clock_base->div;
d2 = 1;
}
if (val & CLK_NO_XTAL) {
prev_clock_idx = (val >> CLK_TBG_SEL_SHIFT) & CLK_TBG_SEL_MASK;
prev_d1d2 = ((val >> CLK_TBG_DIV1_SHIFT) & CLK_TBG_DIV1_MASK) *
((val >> CLK_TBG_DIV2_SHIFT) & CLK_TBG_DIV2_MASK);
} else {
prev_clock_idx = PARENT_CLOCK_XTAL;
prev_d1d2 = 1;
}
/* Note that uart_clock_base->parent_rates[i] may not be available */
prev_clock_rate = uart_clock_base->parent_rates[prev_clock_idx];
/* Recalculate UART1 divisor so UART1 baudrate does not change */
if (prev_clock_rate) {
divisor = DIV_U64_ROUND_CLOSEST((u64)(val & BRDV_BAUD_MASK) *
parent_clock_rate * prev_d1d2,
prev_clock_rate * d1 * d2);
if (divisor < 1)
divisor = 1;
else if (divisor > BRDV_BAUD_MAX)
divisor = BRDV_BAUD_MAX;
val = (val & ~BRDV_BAUD_MASK) | divisor;
}
if (parent_clock_idx != PARENT_CLOCK_XTAL) {
/* Do not use XTAL, select TBG clock and TBG d1 * d2 divisors */
val |= CLK_NO_XTAL;
val &= ~(CLK_TBG_DIV1_MASK << CLK_TBG_DIV1_SHIFT);
val |= d1 << CLK_TBG_DIV1_SHIFT;
val &= ~(CLK_TBG_DIV2_MASK << CLK_TBG_DIV2_SHIFT);
val |= d2 << CLK_TBG_DIV2_SHIFT;
val &= ~(CLK_TBG_SEL_MASK << CLK_TBG_SEL_SHIFT);
val |= parent_clock_idx << CLK_TBG_SEL_SHIFT;
} else {
/* Use XTAL, TBG bits are then ignored */
val &= ~CLK_NO_XTAL;
}
writel(val, uart_clock_base->reg1);
/* Recalculate UART2 divisor so UART2 baudrate does not change */
if (prev_clock_rate) {
val = readl(uart_clock_base->reg2);
divisor = DIV_U64_ROUND_CLOSEST((u64)(val & BRDV_BAUD_MASK) *
parent_clock_rate * prev_d1d2,
prev_clock_rate * d1 * d2);
if (divisor < 1)
divisor = 1;
else if (divisor > BRDV_BAUD_MAX)
divisor = BRDV_BAUD_MAX;
val = (val & ~BRDV_BAUD_MASK) | divisor;
writel(val, uart_clock_base->reg2);
}
uart_clock_base->configured = true;
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
return 0;
}
static int mvebu_uart_clock_enable(struct clk_hw *hw)
{
struct mvebu_uart_clock *uart_clock = to_uart_clock(hw);
struct mvebu_uart_clock_base *uart_clock_base =
to_uart_clock_base(uart_clock);
unsigned long flags;
u32 val;
spin_lock_irqsave(&mvebu_uart_lock, flags);
val = readl(uart_clock_base->reg1);
if (uart_clock->clock_idx == 0)
val &= ~UART1_CLK_DIS;
else
val &= ~UART2_CLK_DIS;
writel(val, uart_clock_base->reg1);
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
return 0;
}
static void mvebu_uart_clock_disable(struct clk_hw *hw)
{
struct mvebu_uart_clock *uart_clock = to_uart_clock(hw);
struct mvebu_uart_clock_base *uart_clock_base =
to_uart_clock_base(uart_clock);
unsigned long flags;
u32 val;
spin_lock_irqsave(&mvebu_uart_lock, flags);
val = readl(uart_clock_base->reg1);
if (uart_clock->clock_idx == 0)
val |= UART1_CLK_DIS;
else
val |= UART2_CLK_DIS;
writel(val, uart_clock_base->reg1);
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
}
static int mvebu_uart_clock_is_enabled(struct clk_hw *hw)
{
struct mvebu_uart_clock *uart_clock = to_uart_clock(hw);
struct mvebu_uart_clock_base *uart_clock_base =
to_uart_clock_base(uart_clock);
u32 val;
val = readl(uart_clock_base->reg1);
if (uart_clock->clock_idx == 0)
return !(val & UART1_CLK_DIS);
else
return !(val & UART2_CLK_DIS);
}
static int mvebu_uart_clock_save_context(struct clk_hw *hw)
{
struct mvebu_uart_clock *uart_clock = to_uart_clock(hw);
struct mvebu_uart_clock_base *uart_clock_base =
to_uart_clock_base(uart_clock);
unsigned long flags;
spin_lock_irqsave(&mvebu_uart_lock, flags);
uart_clock->pm_context_reg1 = readl(uart_clock_base->reg1);
uart_clock->pm_context_reg2 = readl(uart_clock_base->reg2);
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
return 0;
}
static void mvebu_uart_clock_restore_context(struct clk_hw *hw)
{
struct mvebu_uart_clock *uart_clock = to_uart_clock(hw);
struct mvebu_uart_clock_base *uart_clock_base =
to_uart_clock_base(uart_clock);
unsigned long flags;
spin_lock_irqsave(&mvebu_uart_lock, flags);
writel(uart_clock->pm_context_reg1, uart_clock_base->reg1);
writel(uart_clock->pm_context_reg2, uart_clock_base->reg2);
spin_unlock_irqrestore(&mvebu_uart_lock, flags);
}
static unsigned long mvebu_uart_clock_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct mvebu_uart_clock *uart_clock = to_uart_clock(hw);
struct mvebu_uart_clock_base *uart_clock_base =
to_uart_clock_base(uart_clock);
return parent_rate / uart_clock_base->div;
}
static long mvebu_uart_clock_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct mvebu_uart_clock *uart_clock = to_uart_clock(hw);
struct mvebu_uart_clock_base *uart_clock_base =
to_uart_clock_base(uart_clock);
return *parent_rate / uart_clock_base->div;
}
static int mvebu_uart_clock_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
/*
* We must report success but we can do so unconditionally because
* mvebu_uart_clock_round_rate returns values that ensure this call is a
* nop.
*/
return 0;
}
static const struct clk_ops mvebu_uart_clock_ops = {
.prepare = mvebu_uart_clock_prepare,
.enable = mvebu_uart_clock_enable,
.disable = mvebu_uart_clock_disable,
.is_enabled = mvebu_uart_clock_is_enabled,
.save_context = mvebu_uart_clock_save_context,
.restore_context = mvebu_uart_clock_restore_context,
.round_rate = mvebu_uart_clock_round_rate,
.set_rate = mvebu_uart_clock_set_rate,
.recalc_rate = mvebu_uart_clock_recalc_rate,
};
static int mvebu_uart_clock_register(struct device *dev,
struct mvebu_uart_clock *uart_clock,
const char *name,
const char *parent_name)
{
struct clk_init_data init = { };
uart_clock->clk_hw.init = &init;
init.name = name;
init.ops = &mvebu_uart_clock_ops;
init.flags = 0;
init.num_parents = 1;
init.parent_names = &parent_name;
return devm_clk_hw_register(dev, &uart_clock->clk_hw);
}
static int mvebu_uart_clock_probe(struct platform_device *pdev)
{
static const char *const uart_clk_names[] = { "uart_1", "uart_2" };
static const char *const parent_clk_names[] = { "TBG-A-P", "TBG-B-P",
"TBG-A-S", "TBG-B-S",
"xtal" };
struct clk *parent_clks[ARRAY_SIZE(parent_clk_names)];
struct mvebu_uart_clock_base *uart_clock_base;
struct clk_hw_onecell_data *hw_clk_data;
struct device *dev = &pdev->dev;
int i, parent_clk_idx, ret;
unsigned long div, rate;
struct resource *res;
unsigned int d1, d2;
BUILD_BUG_ON(ARRAY_SIZE(uart_clk_names) !=
ARRAY_SIZE(uart_clock_base->clocks));
BUILD_BUG_ON(ARRAY_SIZE(parent_clk_names) !=
ARRAY_SIZE(uart_clock_base->parent_rates));
uart_clock_base = devm_kzalloc(dev,
sizeof(*uart_clock_base),
GFP_KERNEL);
if (!uart_clock_base)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "Couldn't get first register\n");
return -ENOENT;
}
/*
* UART Clock Control register (reg1 / UART_BRDV) is in the address
* space of UART1 (standard UART variant), controls parent clock and
* dividers for both UART1 and UART2 and is supplied via DT as the first
* resource. Therefore use ioremap() rather than ioremap_resource() to
* avoid conflicts with UART1 driver. Access to UART_BRDV is protected
* by a lock shared between clock and UART driver.
*/
uart_clock_base->reg1 = devm_ioremap(dev, res->start,
resource_size(res));
if (!uart_clock_base->reg1)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
dev_err(dev, "Couldn't get second register\n");
return -ENOENT;
}
/*
* UART 2 Baud Rate Divisor register (reg2 / UART_BRDV) is in address
* space of UART2 (extended UART variant), controls only one UART2
* specific divider and is supplied via DT as second resource.
* Therefore use ioremap() rather than ioremap_resource() to avoid
* conflicts with UART2 driver. Access to UART_BRDV is protected by a
* by lock shared between clock and UART driver.
*/
uart_clock_base->reg2 = devm_ioremap(dev, res->start,
resource_size(res));
if (!uart_clock_base->reg2)
return -ENOMEM;
hw_clk_data = devm_kzalloc(dev,
struct_size(hw_clk_data, hws,
ARRAY_SIZE(uart_clk_names)),
GFP_KERNEL);
if (!hw_clk_data)
return -ENOMEM;
hw_clk_data->num = ARRAY_SIZE(uart_clk_names);
for (i = 0; i < ARRAY_SIZE(uart_clk_names); i++) {
hw_clk_data->hws[i] = &uart_clock_base->clocks[i].clk_hw;
uart_clock_base->clocks[i].clock_idx = i;
}
parent_clk_idx = -1;
for (i = 0; i < ARRAY_SIZE(parent_clk_names); i++) {
parent_clks[i] = devm_clk_get(dev, parent_clk_names[i]);
if (IS_ERR(parent_clks[i])) {
if (PTR_ERR(parent_clks[i]) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_warn(dev, "Couldn't get the parent clock %s: %ld\n",
parent_clk_names[i], PTR_ERR(parent_clks[i]));
continue;
}
ret = clk_prepare_enable(parent_clks[i]);
if (ret) {
dev_warn(dev, "Couldn't enable parent clock %s: %d\n",
parent_clk_names[i], ret);
continue;
}
rate = clk_get_rate(parent_clks[i]);
uart_clock_base->parent_rates[i] = rate;
if (i != PARENT_CLOCK_XTAL) {
/*
* Calculate the smallest TBG d1 and d2 divisors that
* still can provide 9600 baudrate.
*/
d1 = DIV_ROUND_UP(rate, 9600 * OSAMP_MAX_DIVISOR *
BRDV_BAUD_MAX);
if (d1 < 1)
d1 = 1;
else if (d1 > CLK_TBG_DIV1_MAX)
d1 = CLK_TBG_DIV1_MAX;
d2 = DIV_ROUND_UP(rate, 9600 * OSAMP_MAX_DIVISOR *
BRDV_BAUD_MAX * d1);
if (d2 < 1)
d2 = 1;
else if (d2 > CLK_TBG_DIV2_MAX)
d2 = CLK_TBG_DIV2_MAX;
} else {
/*
* When UART clock uses XTAL clock as a source then it
* is not possible to use d1 and d2 divisors.
*/
d1 = d2 = 1;
}
/* Skip clock source which cannot provide 9600 baudrate */
if (rate > 9600 * OSAMP_MAX_DIVISOR * BRDV_BAUD_MAX * d1 * d2)
continue;
/*
* Choose TBG clock source with the smallest divisors. Use XTAL
* clock source only in case TBG is not available as XTAL cannot
* be used for baudrates higher than 230400.
*/
if (parent_clk_idx == -1 ||
(i != PARENT_CLOCK_XTAL && div > d1 * d2)) {
parent_clk_idx = i;
div = d1 * d2;
}
}
for (i = 0; i < ARRAY_SIZE(parent_clk_names); i++) {
if (i == parent_clk_idx || IS_ERR(parent_clks[i]))
continue;
clk_disable_unprepare(parent_clks[i]);
devm_clk_put(dev, parent_clks[i]);
}
if (parent_clk_idx == -1) {
dev_err(dev, "No usable parent clock\n");
return -ENOENT;
}
uart_clock_base->parent_idx = parent_clk_idx;
uart_clock_base->div = div;
dev_notice(dev, "Using parent clock %s as base UART clock\n",
__clk_get_name(parent_clks[parent_clk_idx]));
for (i = 0; i < ARRAY_SIZE(uart_clk_names); i++) {
ret = mvebu_uart_clock_register(dev,
&uart_clock_base->clocks[i],
uart_clk_names[i],
__clk_get_name(parent_clks[parent_clk_idx]));
if (ret) {
dev_err(dev, "Can't register UART clock %d: %d\n",
i, ret);
return ret;
}
}
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
hw_clk_data);
}
static const struct of_device_id mvebu_uart_clock_of_match[] = {
{ .compatible = "marvell,armada-3700-uart-clock", },
{ }
};
static struct platform_driver mvebu_uart_clock_platform_driver = {
.probe = mvebu_uart_clock_probe,
.driver = {
.name = "mvebu-uart-clock",
.of_match_table = mvebu_uart_clock_of_match,
},
};
static int __init mvebu_uart_init(void)
{
int ret;
@ -980,10 +1535,19 @@ static int __init mvebu_uart_init(void)
if (ret)
return ret;
ret = platform_driver_register(&mvebu_uart_platform_driver);
if (ret)
ret = platform_driver_register(&mvebu_uart_clock_platform_driver);
if (ret) {
uart_unregister_driver(&mvebu_uart_driver);
return ret;
}
return ret;
ret = platform_driver_register(&mvebu_uart_platform_driver);
if (ret) {
platform_driver_unregister(&mvebu_uart_clock_platform_driver);
uart_unregister_driver(&mvebu_uart_driver);
return ret;
}
return 0;
}
arch_initcall(mvebu_uart_init);

View File

@ -1305,7 +1305,7 @@ static const struct uart_ops mxs_auart_ops = {
static struct mxs_auart_port *auart_port[MXS_AUART_PORTS];
#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
static void mxs_auart_console_putchar(struct uart_port *port, int ch)
static void mxs_auart_console_putchar(struct uart_port *port, unsigned char ch)
{
struct mxs_auart_port *s = to_auart_port(port);
unsigned int to = 1000;

View File

@ -808,21 +808,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned long flags;
unsigned int baud, quot;
switch (termios->c_cflag & CSIZE) {
case CS5:
cval = UART_LCR_WLEN5;
break;
case CS6:
cval = UART_LCR_WLEN6;
break;
case CS7:
cval = UART_LCR_WLEN7;
break;
default:
case CS8:
cval = UART_LCR_WLEN8;
break;
}
cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag));
if (termios->c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
@ -1194,7 +1180,7 @@ static void omap_serial_early_out(struct uart_port *port, int offset,
writew(value, port->membase + offset);
}
static void omap_serial_early_putc(struct uart_port *port, int c)
static void omap_serial_early_putc(struct uart_port *port, unsigned char c)
{
unsigned int status;
@ -1238,7 +1224,7 @@ static struct uart_omap_port *serial_omap_console_ports[OMAP_MAX_HSUART_PORTS];
static struct uart_driver serial_omap_reg;
static void serial_omap_console_putchar(struct uart_port *port, int ch)
static void serial_omap_console_putchar(struct uart_port *port, unsigned char ch)
{
struct uart_omap_port *up = to_uart_omap_port(port);

View File

@ -516,7 +516,7 @@ static const struct uart_ops owl_uart_ops = {
#ifdef CONFIG_SERIAL_OWL_CONSOLE
static void owl_console_putchar(struct uart_port *port, int ch)
static void owl_console_putchar(struct uart_port *port, unsigned char ch)
{
if (!port->membase)
return;

View File

@ -1600,7 +1600,7 @@ static const struct uart_ops pch_uart_ops = {
#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
static void pch_console_putchar(struct uart_port *port, int ch)
static void pch_console_putchar(struct uart_port *port, unsigned char ch)
{
struct eg20t_port *priv =
container_of(port, struct eg20t_port, port);

View File

@ -691,7 +691,7 @@ static const struct uart_ops pic32_uart_ops = {
#ifdef CONFIG_SERIAL_PIC32_CONSOLE
/* output given char */
static void pic32_console_putchar(struct uart_port *port, int ch)
static void pic32_console_putchar(struct uart_port *port, unsigned char ch)
{
struct pic32_sport *sport = to_pic32_sport(port);

View File

@ -1944,7 +1944,7 @@ static void __exit exit_pmz(void)
#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
static void pmz_console_putchar(struct uart_port *port, int ch)
static void pmz_console_putchar(struct uart_port *port, unsigned char ch)
{
struct uart_pmac_port *uap =
container_of(port, struct uart_pmac_port, port);

View File

@ -430,21 +430,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned int baud, quot;
unsigned int dll;
switch (termios->c_cflag & CSIZE) {
case CS5:
cval = UART_LCR_WLEN5;
break;
case CS6:
cval = UART_LCR_WLEN6;
break;
case CS7:
cval = UART_LCR_WLEN7;
break;
default:
case CS8:
cval = UART_LCR_WLEN8;
break;
}
cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag));
if (termios->c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
@ -619,7 +605,7 @@ static void wait_for_xmitr(struct uart_pxa_port *up)
}
}
static void serial_pxa_console_putchar(struct uart_port *port, int ch)
static void serial_pxa_console_putchar(struct uart_port *port, unsigned char ch)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;

View File

@ -397,7 +397,7 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport,
#endif
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
static void qcom_geni_serial_wr_char(struct uart_port *uport, int ch)
static void qcom_geni_serial_wr_char(struct uart_port *uport, unsigned char ch)
{
struct qcom_geni_private_data *private_data = uport->private_data;

View File

@ -573,7 +573,7 @@ static const struct uart_ops rda_uart_ops = {
#ifdef CONFIG_SERIAL_RDA_CONSOLE
static void rda_console_putchar(struct uart_port *port, int ch)
static void rda_console_putchar(struct uart_port *port, unsigned char ch)
{
if (!port->membase)
return;

View File

@ -695,7 +695,7 @@ void __init sa1100_register_uart(int idx, int port)
#ifdef CONFIG_SERIAL_SA1100_CONSOLE
static void sa1100_console_putchar(struct uart_port *port, int ch)
static void sa1100_console_putchar(struct uart_port *port, unsigned char ch)
{
struct sa1100_port *sport =
container_of(port, struct sa1100_port, port);

View File

@ -63,7 +63,7 @@ enum s3c24xx_port_type {
};
struct s3c24xx_uart_info {
char *name;
const char *name;
enum s3c24xx_port_type type;
unsigned int port_type;
unsigned int fifosize;
@ -85,9 +85,9 @@ struct s3c24xx_uart_info {
};
struct s3c24xx_serial_drv_data {
struct s3c24xx_uart_info *info;
struct s3c2410_uartcfg *def_cfg;
unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS];
const struct s3c24xx_uart_info info;
const struct s3c2410_uartcfg def_cfg;
const unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS];
};
struct s3c24xx_uart_dma {
@ -136,14 +136,14 @@ struct s3c24xx_uart_port {
unsigned int tx_mode;
unsigned int rx_mode;
struct s3c24xx_uart_info *info;
const struct s3c24xx_uart_info *info;
struct clk *clk;
struct clk *baudclk;
struct uart_port port;
struct s3c24xx_serial_drv_data *drv_data;
const struct s3c24xx_serial_drv_data *drv_data;
/* reference to platform data */
struct s3c2410_uartcfg *cfg;
const struct s3c2410_uartcfg *cfg;
struct s3c24xx_uart_dma *dma;
@ -164,7 +164,7 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport);
#define portaddrl(port, reg) \
((unsigned long *)(unsigned long)((port)->membase + (reg)))
static u32 rd_reg(struct uart_port *port, u32 reg)
static u32 rd_reg(const struct uart_port *port, u32 reg)
{
switch (port->iotype) {
case UPIO_MEM:
@ -179,7 +179,7 @@ static u32 rd_reg(struct uart_port *port, u32 reg)
#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))
static void wr_reg(struct uart_port *port, u32 reg, u32 val)
static void wr_reg(const struct uart_port *port, u32 reg, u32 val)
{
switch (port->iotype) {
case UPIO_MEM:
@ -195,7 +195,7 @@ static void wr_reg(struct uart_port *port, u32 reg, u32 val)
/* Byte-order aware bit setting/clearing functions. */
static inline void s3c24xx_set_bit(struct uart_port *port, int idx,
static inline void s3c24xx_set_bit(const struct uart_port *port, int idx,
unsigned int reg)
{
unsigned long flags;
@ -208,7 +208,7 @@ static inline void s3c24xx_set_bit(struct uart_port *port, int idx,
local_irq_restore(flags);
}
static inline void s3c24xx_clear_bit(struct uart_port *port, int idx,
static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx,
unsigned int reg)
{
unsigned long flags;
@ -228,12 +228,12 @@ static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
/* translate a port to the device name */
static inline const char *s3c24xx_serial_portname(struct uart_port *port)
static inline const char *s3c24xx_serial_portname(const struct uart_port *port)
{
return to_platform_device(port->dev)->name;
}
static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
static int s3c24xx_serial_txempty_nofifo(const struct uart_port *port)
{
return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
}
@ -358,7 +358,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
{
struct uart_port *port = &ourport->port;
const struct uart_port *port = &ourport->port;
u32 ucon;
/* Mask Tx interrupt */
@ -387,7 +387,7 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
{
struct uart_port *port = &ourport->port;
const struct uart_port *port = &ourport->port;
u32 ucon, ufcon;
/* Set ufcon txtrig */
@ -573,16 +573,16 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
}
}
static inline struct s3c24xx_uart_info
static inline const struct s3c24xx_uart_info
*s3c24xx_port_to_info(struct uart_port *port)
{
return to_ourport(port)->info;
}
static inline struct s3c2410_uartcfg
*s3c24xx_port_to_cfg(struct uart_port *port)
static inline const struct s3c2410_uartcfg
*s3c24xx_port_to_cfg(const struct uart_port *port)
{
struct s3c24xx_uart_port *ourport;
const struct s3c24xx_uart_port *ourport;
if (port->dev == NULL)
return NULL;
@ -591,10 +591,10 @@ static inline struct s3c2410_uartcfg
return ourport->cfg;
}
static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
static int s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport,
unsigned long ufstat)
{
struct s3c24xx_uart_info *info = ourport->info;
const struct s3c24xx_uart_info *info = ourport->info;
if (ufstat & info->rx_fifofull)
return ourport->port.fifosize;
@ -921,11 +921,8 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
return;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
spin_unlock(&port->lock);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
spin_lock(&port->lock);
}
if (uart_circ_empty(xmit))
s3c24xx_serial_stop_tx(port);
@ -947,8 +944,8 @@ static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id)
/* interrupt handler for s3c64xx and later SoC's.*/
static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
const struct s3c24xx_uart_port *ourport = id;
const struct uart_port *port = &ourport->port;
unsigned int pend = rd_regl(port, S3C64XX_UINTP);
irqreturn_t ret = IRQ_HANDLED;
@ -966,8 +963,8 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
/* interrupt handler for Apple SoC's.*/
static irqreturn_t apple_serial_handle_irq(int irq, void *id)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
const struct s3c24xx_uart_port *ourport = id;
const struct uart_port *port = &ourport->port;
unsigned int pend = rd_regl(port, S3C2410_UTRSTAT);
irqreturn_t ret = IRQ_NONE;
@ -986,7 +983,7 @@ static irqreturn_t apple_serial_handle_irq(int irq, void *id)
static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
@ -1405,7 +1402,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
static inline int s3c24xx_serial_getsource(struct uart_port *port)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
unsigned int ucon;
if (info->num_clks == 1)
@ -1419,7 +1416,7 @@ static inline int s3c24xx_serial_getsource(struct uart_port *port)
static void s3c24xx_serial_setsource(struct uart_port *port,
unsigned int clk_sel)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
unsigned int ucon;
if (info->num_clks == 1)
@ -1438,7 +1435,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
unsigned int req_baud, struct clk **best_clk,
unsigned int *clk_num)
{
struct s3c24xx_uart_info *info = ourport->info;
const struct s3c24xx_uart_info *info = ourport->info;
struct clk *clk;
unsigned long rate;
unsigned int cnt, baud, quot, best_quot = 0;
@ -1499,7 +1496,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
* This table takes the fractional value of the baud divisor and gives
* the recommended setting for the UDIVSLOT register.
*/
static u16 udivslot_table[16] = {
static const u16 udivslot_table[16] = {
[0] = 0x0000,
[1] = 0x0080,
[2] = 0x0808,
@ -1522,7 +1519,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
{
struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
const struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_port *ourport = to_ourport(port);
struct clk *clk = ERR_PTR(-EINVAL);
unsigned long flags;
@ -1675,7 +1672,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
static const char *s3c24xx_serial_type(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
const struct s3c24xx_uart_port *ourport = to_ourport(port);
switch (ourport->info->type) {
case TYPE_S3C24XX:
@ -1691,7 +1688,7 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
if (flags & UART_CONFIG_TYPE)
port->type = info->port_type;
@ -1703,7 +1700,7 @@ static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
static int
s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
if (ser->type != PORT_UNKNOWN && ser->type != info->port_type)
return -EINVAL;
@ -1873,9 +1870,9 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
*/
static void s3c24xx_serial_resetport(struct uart_port *port,
struct s3c2410_uartcfg *cfg)
const struct s3c2410_uartcfg *cfg)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
unsigned long ucon = rd_regl(port, S3C2410_UCON);
ucon &= (info->clksel_mask | info->ucon_mask);
@ -1979,7 +1976,7 @@ s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
static int s3c24xx_serial_enable_baudclk(struct s3c24xx_uart_port *ourport)
{
struct device *dev = ourport->port.dev;
struct s3c24xx_uart_info *info = ourport->info;
const struct s3c24xx_uart_info *info = ourport->info;
char clk_name[MAX_CLK_NAME_LENGTH];
unsigned int clk_sel;
struct clk *clk;
@ -2021,7 +2018,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
struct platform_device *platdev)
{
struct uart_port *port = &ourport->port;
struct s3c2410_uartcfg *cfg = ourport->cfg;
const struct s3c2410_uartcfg *cfg = ourport->cfg;
struct resource *res;
int ret;
@ -2150,23 +2147,14 @@ err:
/* Device driver serial port probe */
#ifdef CONFIG_OF
static const struct of_device_id s3c24xx_uart_dt_match[];
#endif
static int probe_index;
static inline struct s3c24xx_serial_drv_data *
static inline const struct s3c24xx_serial_drv_data *
s3c24xx_get_driver_data(struct platform_device *pdev)
{
#ifdef CONFIG_OF
if (pdev->dev.of_node) {
const struct of_device_id *match;
if (dev_of_node(&pdev->dev))
return of_device_get_match_data(&pdev->dev);
match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node);
return (struct s3c24xx_serial_drv_data *)match->data;
}
#endif
return (struct s3c24xx_serial_drv_data *)
platform_get_device_id(pdev)->driver_data;
}
@ -2197,10 +2185,10 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
}
ourport->baudclk = ERR_PTR(-EINVAL);
ourport->info = ourport->drv_data->info;
ourport->info = &ourport->drv_data->info;
ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
dev_get_platdata(&pdev->dev) :
ourport->drv_data->def_cfg;
&ourport->drv_data->def_cfg;
switch (ourport->info->type) {
case TYPE_S3C24XX:
@ -2419,7 +2407,7 @@ static struct uart_port *cons_uart;
static int
s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
unsigned long ufstat, utrstat;
if (ufcon & S3C2410_UFCON_FIFOMODE) {
@ -2450,7 +2438,7 @@ s3c24xx_port_configured(unsigned int ucon)
static int s3c24xx_serial_get_poll_char(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
const struct s3c24xx_uart_port *ourport = to_ourport(port);
unsigned int ufstat;
ufstat = rd_regl(port, S3C2410_UFSTAT);
@ -2478,7 +2466,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
#endif /* CONFIG_CONSOLE_POLL */
static void
s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch)
{
unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
@ -2615,8 +2603,8 @@ static struct console s3c24xx_serial_console = {
#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
#ifdef CONFIG_CPU_S3C2410
static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
static const struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
.info = {
.name = "Samsung S3C2410 UART",
.type = TYPE_S3C24XX,
.port_type = PORT_S3C2410,
@ -2632,19 +2620,19 @@ static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
.clksel_mask = S3C2410_UCON_CLKMASK,
.clksel_shift = S3C2410_UCON_CLKSHIFT,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.def_cfg = {
.ucon = S3C2410_UCON_DEFAULT,
.ufcon = S3C2410_UFCON_DEFAULT,
},
};
#define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data)
#define S3C2410_SERIAL_DRV_DATA (&s3c2410_serial_drv_data)
#else
#define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#define S3C2410_SERIAL_DRV_DATA NULL
#endif
#ifdef CONFIG_CPU_S3C2412
static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
static const struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
.info = {
.name = "Samsung S3C2412 UART",
.type = TYPE_S3C24XX,
.port_type = PORT_S3C2412,
@ -2661,20 +2649,20 @@ static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
.clksel_mask = S3C2412_UCON_CLKMASK,
.clksel_shift = S3C2412_UCON_CLKSHIFT,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.def_cfg = {
.ucon = S3C2410_UCON_DEFAULT,
.ufcon = S3C2410_UFCON_DEFAULT,
},
};
#define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data)
#define S3C2412_SERIAL_DRV_DATA (&s3c2412_serial_drv_data)
#else
#define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#define S3C2412_SERIAL_DRV_DATA NULL
#endif
#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \
defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442)
static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
static const struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
.info = {
.name = "Samsung S3C2440 UART",
.type = TYPE_S3C24XX,
.port_type = PORT_S3C2440,
@ -2692,19 +2680,19 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
.clksel_shift = S3C2412_UCON_CLKSHIFT,
.ucon_mask = S3C2440_UCON0_DIVMASK,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.def_cfg = {
.ucon = S3C2410_UCON_DEFAULT,
.ufcon = S3C2410_UFCON_DEFAULT,
},
};
#define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data)
#define S3C2440_SERIAL_DRV_DATA (&s3c2440_serial_drv_data)
#else
#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#define S3C2440_SERIAL_DRV_DATA NULL
#endif
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
static const struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
.info = {
.name = "Samsung S3C6400 UART",
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
@ -2721,19 +2709,19 @@ static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
.clksel_mask = S3C6400_UCON_CLKMASK,
.clksel_shift = S3C6400_UCON_CLKSHIFT,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.def_cfg = {
.ucon = S3C2410_UCON_DEFAULT,
.ufcon = S3C2410_UFCON_DEFAULT,
},
};
#define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data)
#define S3C6400_SERIAL_DRV_DATA (&s3c6400_serial_drv_data)
#else
#define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#define S3C6400_SERIAL_DRV_DATA NULL
#endif
#ifdef CONFIG_CPU_S5PV210
static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.info = {
.name = "Samsung S5PV210 UART",
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
@ -2749,20 +2737,20 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.clksel_mask = S5PV210_UCON_CLKMASK,
.clksel_shift = S5PV210_UCON_CLKSHIFT,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.def_cfg = {
.ucon = S5PV210_UCON_DEFAULT,
.ufcon = S5PV210_UFCON_DEFAULT,
},
.fifosize = { 256, 64, 16, 16 },
};
#define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data)
#define S5PV210_SERIAL_DRV_DATA (&s5pv210_serial_drv_data)
#else
#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#define S5PV210_SERIAL_DRV_DATA NULL
#endif
#if defined(CONFIG_ARCH_EXYNOS)
#define EXYNOS_COMMON_SERIAL_DRV_DATA() \
.info = &(struct s3c24xx_uart_info) { \
.info = { \
.name = "Samsung Exynos UART", \
.type = TYPE_S3C6400, \
.port_type = PORT_S3C6400, \
@ -2778,40 +2766,40 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.clksel_mask = 0, \
.clksel_shift = 0, \
}, \
.def_cfg = &(struct s3c2410_uartcfg) { \
.def_cfg = { \
.ucon = S5PV210_UCON_DEFAULT, \
.ufcon = S5PV210_UFCON_DEFAULT, \
.has_fracval = 1, \
} \
static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
static const struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA(),
.fifosize = { 256, 64, 16, 16 },
};
static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
static const struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA(),
.fifosize = { 64, 256, 16, 256 },
};
static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA(),
.fifosize = { 256, 64, 64, 64 },
};
#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos5433_serial_drv_data)
#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos850_serial_drv_data)
#define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data)
#define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data)
#define EXYNOS850_SERIAL_DRV_DATA (&exynos850_serial_drv_data)
#else
#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#define EXYNOS4210_SERIAL_DRV_DATA NULL
#define EXYNOS5433_SERIAL_DRV_DATA NULL
#define EXYNOS850_SERIAL_DRV_DATA NULL
#endif
#ifdef CONFIG_ARCH_APPLE
static struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
.info = {
.name = "Apple S5L UART",
.type = TYPE_APPLE_S5L,
.port_type = PORT_8250,
@ -2827,44 +2815,77 @@ static struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
.clksel_mask = 0,
.clksel_shift = 0,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.def_cfg = {
.ucon = APPLE_S5L_UCON_DEFAULT,
.ufcon = S3C2410_UFCON_DEFAULT,
},
};
#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)&s5l_serial_drv_data)
#define S5L_SERIAL_DRV_DATA (&s5l_serial_drv_data)
#else
#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#define S5L_SERIAL_DRV_DATA NULL
#endif
#if defined(CONFIG_ARCH_ARTPEC)
static const struct s3c24xx_serial_drv_data artpec8_serial_drv_data = {
.info = {
.name = "Axis ARTPEC-8 UART",
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
.fifosize = 64,
.has_divslot = 1,
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
.rx_fifofull = S5PV210_UFSTAT_RXFULL,
.tx_fifofull = S5PV210_UFSTAT_TXFULL,
.tx_fifomask = S5PV210_UFSTAT_TXMASK,
.tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
.def_clk_sel = S3C2410_UCON_CLKSEL0,
.num_clks = 1,
.clksel_mask = 0,
.clksel_shift = 0,
},
.def_cfg = {
.ucon = S5PV210_UCON_DEFAULT,
.ufcon = S5PV210_UFCON_DEFAULT,
.has_fracval = 1,
}
};
#define ARTPEC8_SERIAL_DRV_DATA (&artpec8_serial_drv_data)
#else
#define ARTPEC8_SERIAL_DRV_DATA (NULL)
#endif
static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
{
.name = "s3c2410-uart",
.driver_data = S3C2410_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)S3C2410_SERIAL_DRV_DATA,
}, {
.name = "s3c2412-uart",
.driver_data = S3C2412_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)S3C2412_SERIAL_DRV_DATA,
}, {
.name = "s3c2440-uart",
.driver_data = S3C2440_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)S3C2440_SERIAL_DRV_DATA,
}, {
.name = "s3c6400-uart",
.driver_data = S3C6400_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)S3C6400_SERIAL_DRV_DATA,
}, {
.name = "s5pv210-uart",
.driver_data = S5PV210_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)S5PV210_SERIAL_DRV_DATA,
}, {
.name = "exynos4210-uart",
.driver_data = EXYNOS4210_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)EXYNOS4210_SERIAL_DRV_DATA,
}, {
.name = "exynos5433-uart",
.driver_data = EXYNOS5433_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)EXYNOS5433_SERIAL_DRV_DATA,
}, {
.name = "s5l-uart",
.driver_data = S5L_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)S5L_SERIAL_DRV_DATA,
}, {
.name = "exynos850-uart",
.driver_data = EXYNOS850_SERIAL_DRV_DATA,
.driver_data = (kernel_ulong_t)EXYNOS850_SERIAL_DRV_DATA,
}, {
.name = "artpec8-uart",
.driver_data = (kernel_ulong_t)ARTPEC8_SERIAL_DRV_DATA,
},
{ },
};
@ -2873,23 +2894,25 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
#ifdef CONFIG_OF
static const struct of_device_id s3c24xx_uart_dt_match[] = {
{ .compatible = "samsung,s3c2410-uart",
.data = (void *)S3C2410_SERIAL_DRV_DATA },
.data = S3C2410_SERIAL_DRV_DATA },
{ .compatible = "samsung,s3c2412-uart",
.data = (void *)S3C2412_SERIAL_DRV_DATA },
.data = S3C2412_SERIAL_DRV_DATA },
{ .compatible = "samsung,s3c2440-uart",
.data = (void *)S3C2440_SERIAL_DRV_DATA },
.data = S3C2440_SERIAL_DRV_DATA },
{ .compatible = "samsung,s3c6400-uart",
.data = (void *)S3C6400_SERIAL_DRV_DATA },
.data = S3C6400_SERIAL_DRV_DATA },
{ .compatible = "samsung,s5pv210-uart",
.data = (void *)S5PV210_SERIAL_DRV_DATA },
.data = S5PV210_SERIAL_DRV_DATA },
{ .compatible = "samsung,exynos4210-uart",
.data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
.data = EXYNOS4210_SERIAL_DRV_DATA },
{ .compatible = "samsung,exynos5433-uart",
.data = (void *)EXYNOS5433_SERIAL_DRV_DATA },
.data = EXYNOS5433_SERIAL_DRV_DATA },
{ .compatible = "apple,s5l-uart",
.data = (void *)S5L_SERIAL_DRV_DATA },
.data = S5L_SERIAL_DRV_DATA },
{ .compatible = "samsung,exynos850-uart",
.data = (void *)EXYNOS850_SERIAL_DRV_DATA },
.data = EXYNOS850_SERIAL_DRV_DATA },
{ .compatible = "axis,artpec8-uart",
.data = ARTPEC8_SERIAL_DRV_DATA },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
@ -2935,7 +2958,7 @@ module_exit(samsung_serial_exit);
* Early console.
*/
static void wr_reg_barrier(struct uart_port *port, u32 reg, u32 val)
static void wr_reg_barrier(const struct uart_port *port, u32 reg, u32 val)
{
switch (port->iotype) {
case UPIO_MEM:
@ -2949,23 +2972,24 @@ static void wr_reg_barrier(struct uart_port *port, u32 reg, u32 val)
struct samsung_early_console_data {
u32 txfull_mask;
u32 rxfifo_mask;
};
static void samsung_early_busyuart(struct uart_port *port)
static void samsung_early_busyuart(const struct uart_port *port)
{
while (!(readl(port->membase + S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXFE))
;
}
static void samsung_early_busyuart_fifo(struct uart_port *port)
static void samsung_early_busyuart_fifo(const struct uart_port *port)
{
struct samsung_early_console_data *data = port->private_data;
const struct samsung_early_console_data *data = port->private_data;
while (readl(port->membase + S3C2410_UFSTAT) & data->txfull_mask)
;
}
static void samsung_early_putc(struct uart_port *port, int c)
static void samsung_early_putc(struct uart_port *port, unsigned char c)
{
if (readl(port->membase + S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE)
samsung_early_busyuart_fifo(port);
@ -2983,6 +3007,26 @@ static void samsung_early_write(struct console *con, const char *s,
uart_console_write(&dev->port, s, n, samsung_early_putc);
}
static int samsung_early_read(struct console *con, char *s, unsigned int n)
{
struct earlycon_device *dev = con->data;
const struct samsung_early_console_data *data = dev->port.private_data;
int ch, ufstat, num_read = 0;
while (num_read < n) {
ufstat = rd_regl(&dev->port, S3C2410_UFSTAT);
if (!(ufstat & data->rxfifo_mask))
break;
ch = rd_reg(&dev->port, S3C2410_URXH);
if (ch == NO_POLL_CHAR)
break;
s[num_read++] = ch;
}
return num_read;
}
static int __init samsung_early_console_setup(struct earlycon_device *device,
const char *opt)
{
@ -2990,12 +3034,14 @@ static int __init samsung_early_console_setup(struct earlycon_device *device,
return -ENODEV;
device->con->write = samsung_early_write;
device->con->read = samsung_early_read;
return 0;
}
/* S3C2410 */
static struct samsung_early_console_data s3c2410_early_console_data = {
.txfull_mask = S3C2410_UFSTAT_TXFULL,
.rxfifo_mask = S3C2410_UFSTAT_RXFULL | S3C2410_UFSTAT_RXMASK,
};
static int __init s3c2410_early_console_setup(struct earlycon_device *device,
@ -3011,6 +3057,7 @@ OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
/* S3C2412, S3C2440, S3C64xx */
static struct samsung_early_console_data s3c2440_early_console_data = {
.txfull_mask = S3C2440_UFSTAT_TXFULL,
.rxfifo_mask = S3C2440_UFSTAT_RXFULL | S3C2440_UFSTAT_RXMASK,
};
static int __init s3c2440_early_console_setup(struct earlycon_device *device,
@ -3030,6 +3077,7 @@ OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart",
/* S5PV210, Exynos */
static struct samsung_early_console_data s5pv210_early_console_data = {
.txfull_mask = S5PV210_UFSTAT_TXFULL,
.rxfifo_mask = S5PV210_UFSTAT_RXFULL | S5PV210_UFSTAT_RXMASK,
};
static int __init s5pv210_early_console_setup(struct earlycon_device *device,
@ -3043,6 +3091,8 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
s5pv210_early_console_setup);
OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
s5pv210_early_console_setup);
OF_EARLYCON_DECLARE(artpec8, "axis,artpec8-uart",
s5pv210_early_console_setup);
/* Apple S5L */
static int __init apple_s5l_early_console_setup(struct earlycon_device *device,

View File

@ -820,7 +820,7 @@ static void __init sbd_probe_duarts(void)
* console output. The console_lock is held by the caller, so we
* shouldn't be interrupted for more console activity.
*/
static void sbd_console_putchar(struct uart_port *uport, int ch)
static void sbd_console_putchar(struct uart_port *uport, unsigned char ch)
{
struct sbd_port *sport = to_sport(uport);

View File

@ -289,6 +289,14 @@
* XON1, XON2, XOFF1 and
* XOFF2
*/
#define SC16IS7XX_EFR_FLOWCTRL_BITS (SC16IS7XX_EFR_AUTORTS_BIT | \
SC16IS7XX_EFR_AUTOCTS_BIT | \
SC16IS7XX_EFR_XOFF2_DETECT_BIT | \
SC16IS7XX_EFR_SWFLOW3_BIT | \
SC16IS7XX_EFR_SWFLOW2_BIT | \
SC16IS7XX_EFR_SWFLOW1_BIT | \
SC16IS7XX_EFR_SWFLOW0_BIT)
/* Misc definitions */
#define SC16IS7XX_FIFO_SIZE (64)
@ -298,6 +306,7 @@ struct sc16is7xx_devtype {
char name[10];
int nr_gpio;
int nr_uart;
int has_mctrl;
};
#define SC16IS7XX_RECONF_MD (1 << 0)
@ -306,7 +315,8 @@ struct sc16is7xx_devtype {
struct sc16is7xx_one_config {
unsigned int flags;
u8 ier_clear;
u8 ier_mask;
u8 ier_val;
};
struct sc16is7xx_one {
@ -314,8 +324,10 @@ struct sc16is7xx_one {
u8 line;
struct kthread_work tx_work;
struct kthread_work reg_work;
struct kthread_delayed_work ms_work;
struct sc16is7xx_one_config config;
bool irda_mode;
unsigned int old_mctrl;
};
struct sc16is7xx_port {
@ -340,6 +352,9 @@ static struct uart_driver sc16is7xx_uart = {
.nr = SC16IS7XX_MAX_DEVS,
};
static void sc16is7xx_ier_set(struct uart_port *port, u8 bit);
static void sc16is7xx_stop_tx(struct uart_port *port);
#define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e)))
#define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e)))
@ -432,30 +447,35 @@ static const struct sc16is7xx_devtype sc16is74x_devtype = {
.name = "SC16IS74X",
.nr_gpio = 0,
.nr_uart = 1,
.has_mctrl = 0,
};
static const struct sc16is7xx_devtype sc16is750_devtype = {
.name = "SC16IS750",
.nr_gpio = 8,
.nr_gpio = 4,
.nr_uart = 1,
.has_mctrl = 1,
};
static const struct sc16is7xx_devtype sc16is752_devtype = {
.name = "SC16IS752",
.nr_gpio = 8,
.nr_gpio = 0,
.nr_uart = 2,
.has_mctrl = 1,
};
static const struct sc16is7xx_devtype sc16is760_devtype = {
.name = "SC16IS760",
.nr_gpio = 8,
.nr_gpio = 4,
.nr_uart = 1,
.has_mctrl = 1,
};
static const struct sc16is7xx_devtype sc16is762_devtype = {
.name = "SC16IS762",
.nr_gpio = 8,
.nr_gpio = 0,
.nr_uart = 2,
.has_mctrl = 1,
};
static bool sc16is7xx_regmap_volatile(struct device *dev, unsigned int reg)
@ -523,8 +543,10 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
/* Enable enhanced features */
regcache_cache_bypass(s->regmap, true);
sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_ENABLE_BIT);
sc16is7xx_port_update(port, SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_ENABLE_BIT,
SC16IS7XX_EFR_ENABLE_BIT);
regcache_cache_bypass(s->regmap, false);
/* Put LCR back to the normal mode */
@ -635,6 +657,7 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct circ_buf *xmit = &port->state->xmit;
unsigned int txlen, to_send, i;
unsigned long flags;
if (unlikely(port->x_char)) {
sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char);
@ -643,8 +666,12 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
spin_lock_irqsave(&port->lock, flags);
sc16is7xx_stop_tx(port);
spin_unlock_irqrestore(&port->lock, flags);
return;
}
/* Get length of data pending in circular buffer */
to_send = uart_circ_chars_pending(xmit);
@ -671,8 +698,56 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
sc16is7xx_fifo_write(port, to_send);
}
spin_lock_irqsave(&port->lock, flags);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
sc16is7xx_stop_tx(port);
spin_unlock_irqrestore(&port->lock, flags);
}
static unsigned int sc16is7xx_get_hwmctrl(struct uart_port *port)
{
u8 msr = sc16is7xx_port_read(port, SC16IS7XX_MSR_REG);
unsigned int mctrl = 0;
mctrl |= (msr & SC16IS7XX_MSR_CTS_BIT) ? TIOCM_CTS : 0;
mctrl |= (msr & SC16IS7XX_MSR_DSR_BIT) ? TIOCM_DSR : 0;
mctrl |= (msr & SC16IS7XX_MSR_CD_BIT) ? TIOCM_CAR : 0;
mctrl |= (msr & SC16IS7XX_MSR_RI_BIT) ? TIOCM_RNG : 0;
return mctrl;
}
static void sc16is7xx_update_mlines(struct sc16is7xx_one *one)
{
struct uart_port *port = &one->port;
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
unsigned long flags;
unsigned int status, changed;
lockdep_assert_held_once(&s->efr_lock);
status = sc16is7xx_get_hwmctrl(port);
changed = status ^ one->old_mctrl;
if (changed == 0)
return;
one->old_mctrl = status;
spin_lock_irqsave(&port->lock, flags);
if ((changed & TIOCM_RNG) && (status & TIOCM_RNG))
port->icount.rng++;
if (changed & TIOCM_DSR)
port->icount.dsr++;
if (changed & TIOCM_CAR)
uart_handle_dcd_change(port, status & TIOCM_CAR);
if (changed & TIOCM_CTS)
uart_handle_cts_change(port, status & TIOCM_CTS);
wake_up_interruptible(&port->state->port.delta_msr_wait);
spin_unlock_irqrestore(&port->lock, flags);
}
static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
@ -681,6 +756,7 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
do {
unsigned int iir, rxlen;
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
iir = sc16is7xx_port_read(port, SC16IS7XX_IIR_REG);
if (iir & SC16IS7XX_IIR_NO_INT_BIT)
@ -697,6 +773,11 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
if (rxlen)
sc16is7xx_handle_rx(port, rxlen, iir);
break;
/* CTSRTS interrupt comes only when CTS goes inactive */
case SC16IS7XX_IIR_CTSRTS_SRC:
case SC16IS7XX_IIR_MSI_SRC:
sc16is7xx_update_mlines(one);
break;
case SC16IS7XX_IIR_THRI_SRC:
sc16is7xx_handle_tx(port);
break;
@ -735,6 +816,7 @@ static void sc16is7xx_tx_proc(struct kthread_work *ws)
{
struct uart_port *port = &(to_sc16is7xx_one(ws, tx_work)->port);
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
unsigned long flags;
if ((port->rs485.flags & SER_RS485_ENABLED) &&
(port->rs485.delay_rts_before_send > 0))
@ -743,6 +825,10 @@ static void sc16is7xx_tx_proc(struct kthread_work *ws)
mutex_lock(&s->efr_lock);
sc16is7xx_handle_tx(port);
mutex_unlock(&s->efr_lock);
spin_lock_irqsave(&port->lock, flags);
sc16is7xx_ier_set(port, SC16IS7XX_IER_THRI_BIT);
spin_unlock_irqrestore(&port->lock, flags);
}
static void sc16is7xx_reconf_rs485(struct uart_port *port)
@ -777,22 +863,27 @@ static void sc16is7xx_reg_proc(struct kthread_work *ws)
spin_unlock_irqrestore(&one->port.lock, irqflags);
if (config.flags & SC16IS7XX_RECONF_MD) {
u8 mcr = 0;
/* Device ignores RTS setting when hardware flow is enabled */
if (one->port.mctrl & TIOCM_RTS)
mcr |= SC16IS7XX_MCR_RTS_BIT;
if (one->port.mctrl & TIOCM_DTR)
mcr |= SC16IS7XX_MCR_DTR_BIT;
if (one->port.mctrl & TIOCM_LOOP)
mcr |= SC16IS7XX_MCR_LOOP_BIT;
sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG,
SC16IS7XX_MCR_RTS_BIT |
SC16IS7XX_MCR_DTR_BIT |
SC16IS7XX_MCR_LOOP_BIT,
(one->port.mctrl & TIOCM_LOOP) ?
SC16IS7XX_MCR_LOOP_BIT : 0);
sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG,
SC16IS7XX_MCR_RTS_BIT,
(one->port.mctrl & TIOCM_RTS) ?
SC16IS7XX_MCR_RTS_BIT : 0);
sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG,
SC16IS7XX_MCR_DTR_BIT,
(one->port.mctrl & TIOCM_DTR) ?
SC16IS7XX_MCR_DTR_BIT : 0);
mcr);
}
if (config.flags & SC16IS7XX_RECONF_IER)
sc16is7xx_port_update(&one->port, SC16IS7XX_IER_REG,
config.ier_clear, 0);
config.ier_mask, config.ier_val);
if (config.flags & SC16IS7XX_RECONF_RS485)
sc16is7xx_reconf_rs485(&one->port);
@ -803,8 +894,24 @@ static void sc16is7xx_ier_clear(struct uart_port *port, u8 bit)
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
lockdep_assert_held_once(&port->lock);
one->config.flags |= SC16IS7XX_RECONF_IER;
one->config.ier_clear |= bit;
one->config.ier_mask |= bit;
one->config.ier_val &= ~bit;
kthread_queue_work(&s->kworker, &one->reg_work);
}
static void sc16is7xx_ier_set(struct uart_port *port, u8 bit)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
lockdep_assert_held_once(&port->lock);
one->config.flags |= SC16IS7XX_RECONF_IER;
one->config.ier_mask |= bit;
one->config.ier_val |= bit;
kthread_queue_work(&s->kworker, &one->reg_work);
}
@ -818,6 +925,30 @@ static void sc16is7xx_stop_rx(struct uart_port *port)
sc16is7xx_ier_clear(port, SC16IS7XX_IER_RDI_BIT);
}
static void sc16is7xx_ms_proc(struct kthread_work *ws)
{
struct sc16is7xx_one *one = to_sc16is7xx_one(ws, ms_work.work);
struct sc16is7xx_port *s = dev_get_drvdata(one->port.dev);
if (one->port.state) {
mutex_lock(&s->efr_lock);
sc16is7xx_update_mlines(one);
mutex_unlock(&s->efr_lock);
kthread_queue_delayed_work(&s->kworker, &one->ms_work, HZ);
}
}
static void sc16is7xx_enable_ms(struct uart_port *port)
{
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
lockdep_assert_held_once(&port->lock);
kthread_queue_delayed_work(&s->kworker, &one->ms_work, 0);
}
static void sc16is7xx_start_tx(struct uart_port *port)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
@ -826,6 +957,29 @@ static void sc16is7xx_start_tx(struct uart_port *port)
kthread_queue_work(&s->kworker, &one->tx_work);
}
static void sc16is7xx_throttle(struct uart_port *port)
{
unsigned long flags;
/*
* Hardware flow control is enabled and thus the device ignores RTS
* value set in MCR register. Stop reading data from RX FIFO so the
* AutoRTS feature will de-activate RTS output.
*/
spin_lock_irqsave(&port->lock, flags);
sc16is7xx_ier_clear(port, SC16IS7XX_IER_RDI_BIT);
spin_unlock_irqrestore(&port->lock, flags);
}
static void sc16is7xx_unthrottle(struct uart_port *port)
{
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
sc16is7xx_ier_set(port, SC16IS7XX_IER_RDI_BIT);
spin_unlock_irqrestore(&port->lock, flags);
}
static unsigned int sc16is7xx_tx_empty(struct uart_port *port)
{
unsigned int lsr;
@ -837,10 +991,10 @@ static unsigned int sc16is7xx_tx_empty(struct uart_port *port)
static unsigned int sc16is7xx_get_mctrl(struct uart_port *port)
{
/* DCD and DSR are not wired and CTS/RTS is handled automatically
* so just indicate DSR and CAR asserted
*/
return TIOCM_DSR | TIOCM_CAR;
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
/* Called with port lock taken so we can only return cached value */
return one->old_mctrl;
}
static void sc16is7xx_set_mctrl(struct uart_port *port, unsigned int mctrl)
@ -864,8 +1018,12 @@ static void sc16is7xx_set_termios(struct uart_port *port,
struct ktermios *old)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
unsigned int lcr, flow = 0;
int baud;
unsigned long flags;
kthread_cancel_delayed_work_sync(&one->ms_work);
/* Mask termios capabilities we don't support */
termios->c_cflag &= ~CMSPAR;
@ -927,15 +1085,22 @@ static void sc16is7xx_set_termios(struct uart_port *port,
regcache_cache_bypass(s->regmap, true);
sc16is7xx_port_write(port, SC16IS7XX_XON1_REG, termios->c_cc[VSTART]);
sc16is7xx_port_write(port, SC16IS7XX_XOFF1_REG, termios->c_cc[VSTOP]);
if (termios->c_cflag & CRTSCTS)
port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS);
if (termios->c_cflag & CRTSCTS) {
flow |= SC16IS7XX_EFR_AUTOCTS_BIT |
SC16IS7XX_EFR_AUTORTS_BIT;
port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
}
if (termios->c_iflag & IXON)
flow |= SC16IS7XX_EFR_SWFLOW3_BIT;
if (termios->c_iflag & IXOFF)
flow |= SC16IS7XX_EFR_SWFLOW1_BIT;
sc16is7xx_port_write(port, SC16IS7XX_EFR_REG, flow);
sc16is7xx_port_update(port,
SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_FLOWCTRL_BITS,
flow);
regcache_cache_bypass(s->regmap, false);
/* Update LCR register */
@ -951,8 +1116,15 @@ static void sc16is7xx_set_termios(struct uart_port *port,
/* Setup baudrate generator */
baud = sc16is7xx_set_baud(port, baud);
spin_lock_irqsave(&port->lock, flags);
/* Update timeout according to new baud rate */
uart_update_timeout(port, termios->c_cflag, baud);
if (UART_ENABLE_MS(port, termios->c_cflag))
sc16is7xx_enable_ms(port);
spin_unlock_irqrestore(&port->lock, flags);
}
static int sc16is7xx_config_rs485(struct uart_port *port,
@ -993,6 +1165,7 @@ static int sc16is7xx_startup(struct uart_port *port)
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
unsigned int val;
unsigned long flags;
sc16is7xx_power(port, 1);
@ -1010,8 +1183,9 @@ static int sc16is7xx_startup(struct uart_port *port)
regcache_cache_bypass(s->regmap, true);
/* Enable write access to enhanced features and internal clock div */
sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_ENABLE_BIT);
sc16is7xx_port_update(port, SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_ENABLE_BIT,
SC16IS7XX_EFR_ENABLE_BIT);
/* Enable TCR/TLR */
sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
@ -1042,23 +1216,34 @@ static int sc16is7xx_startup(struct uart_port *port)
SC16IS7XX_EFCR_TXDISABLE_BIT,
0);
/* Enable RX, TX interrupts */
val = SC16IS7XX_IER_RDI_BIT | SC16IS7XX_IER_THRI_BIT;
/* Enable RX, CTS change and modem lines interrupts */
val = SC16IS7XX_IER_RDI_BIT | SC16IS7XX_IER_CTSI_BIT |
SC16IS7XX_IER_MSI_BIT;
sc16is7xx_port_write(port, SC16IS7XX_IER_REG, val);
/* Enable modem status polling */
spin_lock_irqsave(&port->lock, flags);
sc16is7xx_enable_ms(port);
spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
static void sc16is7xx_shutdown(struct uart_port *port)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
kthread_cancel_delayed_work_sync(&one->ms_work);
/* Disable all interrupts */
sc16is7xx_port_write(port, SC16IS7XX_IER_REG, 0);
/* Disable TX/RX */
/* Disable TX/RX, clear auto RS485 and RTS invert */
sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
SC16IS7XX_EFCR_RXDISABLE_BIT |
SC16IS7XX_EFCR_TXDISABLE_BIT,
SC16IS7XX_EFCR_TXDISABLE_BIT |
SC16IS7XX_EFCR_AUTO_RS485_BIT |
SC16IS7XX_EFCR_RTS_INVERT_BIT,
SC16IS7XX_EFCR_RXDISABLE_BIT |
SC16IS7XX_EFCR_TXDISABLE_BIT);
@ -1114,7 +1299,10 @@ static const struct uart_ops sc16is7xx_ops = {
.get_mctrl = sc16is7xx_get_mctrl,
.stop_tx = sc16is7xx_stop_tx,
.start_tx = sc16is7xx_start_tx,
.throttle = sc16is7xx_throttle,
.unthrottle = sc16is7xx_unthrottle,
.stop_rx = sc16is7xx_stop_rx,
.enable_ms = sc16is7xx_enable_ms,
.break_ctl = sc16is7xx_break_ctl,
.startup = sc16is7xx_startup,
.shutdown = sc16is7xx_shutdown,
@ -1281,7 +1469,9 @@ static int sc16is7xx_probe(struct device *dev,
s->p[i].port.uartclk = freq;
s->p[i].port.rs485_config = sc16is7xx_config_rs485;
s->p[i].port.ops = &sc16is7xx_ops;
s->p[i].old_mctrl = 0;
s->p[i].port.line = sc16is7xx_alloc_line();
if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
ret = -ENOMEM;
goto out_ports;
@ -1293,9 +1483,17 @@ static int sc16is7xx_probe(struct device *dev,
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFCR_REG,
SC16IS7XX_EFCR_RXDISABLE_BIT |
SC16IS7XX_EFCR_TXDISABLE_BIT);
/* Use GPIO lines as modem status registers */
if (devtype->has_mctrl)
sc16is7xx_port_write(&s->p[i].port,
SC16IS7XX_IOCONTROL_REG,
SC16IS7XX_IOCONTROL_MODEM_BIT);
/* Initialize kthread work structs */
kthread_init_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
kthread_init_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
kthread_init_delayed_work(&s->p[i].ms_work, sc16is7xx_ms_proc);
/* Register port */
uart_add_one_port(&sc16is7xx_uart, &s->p[i].port);
@ -1379,6 +1577,7 @@ static void sc16is7xx_remove(struct device *dev)
#endif
for (i = 0; i < s->devtype->nr_uart; i++) {
kthread_cancel_delayed_work_sync(&s->p[i].ms_work);
uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
clear_bit(s->p[i].port.line, &sc16is7xx_lines);
sc16is7xx_power(&s->p[i].port, 0);

View File

@ -828,7 +828,7 @@ static const struct uart_ops sccnxp_ops = {
};
#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
static void sccnxp_console_putchar(struct uart_port *port, int c)
static void sccnxp_console_putchar(struct uart_port *port, unsigned char c)
{
int tryes = 100000;

View File

@ -1277,6 +1277,7 @@ static void tegra_uart_set_termios(struct uart_port *u,
unsigned int baud;
unsigned long flags;
unsigned int lcr;
unsigned char char_bits;
int symb_bit = 1;
struct clk *parent_clk = clk_get_parent(tup->uart_clk);
unsigned long parent_clk_rate = clk_get_rate(parent_clk);
@ -1316,25 +1317,10 @@ static void tegra_uart_set_termios(struct uart_port *u,
}
}
char_bits = tty_get_char_size(termios->c_cflag);
symb_bit += char_bits;
lcr &= ~UART_LCR_WLEN8;
switch (termios->c_cflag & CSIZE) {
case CS5:
lcr |= UART_LCR_WLEN5;
symb_bit += 5;
break;
case CS6:
lcr |= UART_LCR_WLEN6;
symb_bit += 6;
break;
case CS7:
lcr |= UART_LCR_WLEN7;
symb_bit += 7;
break;
default:
lcr |= UART_LCR_WLEN8;
symb_bit += 8;
break;
}
lcr |= UART_LCR_WLEN(char_bits);
/* Stop bits */
if (termios->c_cflag & CSTOPB) {

View File

@ -105,6 +105,7 @@ void uart_write_wakeup(struct uart_port *port)
BUG_ON(!state);
tty_port_tty_wakeup(&state->port);
}
EXPORT_SYMBOL(uart_write_wakeup);
static void uart_stop(struct tty_struct *tty)
{
@ -316,8 +317,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
state->xmit.buf = NULL;
uart_port_unlock(uport, flags);
if (xmit_buf)
free_page((unsigned long)xmit_buf);
free_page((unsigned long)xmit_buf);
}
/**
@ -343,7 +343,6 @@ uart_update_timeout(struct uart_port *port, unsigned int cflag,
*/
port->timeout = (HZ * size) / baud + HZ/50;
}
EXPORT_SYMBOL(uart_update_timeout);
/**
@ -445,7 +444,6 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
WARN_ON(1);
return 0;
}
EXPORT_SYMBOL(uart_get_baud_rate);
/**
@ -470,7 +468,6 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
return quot;
}
EXPORT_SYMBOL(uart_get_divisor);
/* Caller holds port mutex */
@ -644,6 +641,20 @@ static void uart_flush_buffer(struct tty_struct *tty)
tty_port_tty_wakeup(&state->port);
}
/*
* This function performs low-level write of high-priority XON/XOFF
* character and accounting for it.
*
* Requires uart_port to implement .serial_out().
*/
void uart_xchar_out(struct uart_port *uport, int offset)
{
serial_port_out(uport, offset, uport->x_char);
uport->icount.tx++;
uport->x_char = 0;
}
EXPORT_SYMBOL_GPL(uart_xchar_out);
/*
* This function is used to send a high-priority XON/XOFF character to
* the device
@ -1571,8 +1582,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
state->xmit.buf = NULL;
spin_unlock_irq(&uport->lock);
if (buf)
free_page((unsigned long)buf);
free_page((unsigned long)buf);
uart_change_pm(state, UART_PM_STATE_OFF);
}
@ -1915,7 +1925,7 @@ static void uart_port_spin_lock_init(struct uart_port *port)
*/
void uart_console_write(struct uart_port *port, const char *s,
unsigned int count,
void (*putchar)(struct uart_port *, int))
void (*putchar)(struct uart_port *, unsigned char))
{
unsigned int i;
@ -2207,6 +2217,7 @@ unlock:
return 0;
}
EXPORT_SYMBOL(uart_suspend_port);
int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
{
@ -2292,6 +2303,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
return 0;
}
EXPORT_SYMBOL(uart_resume_port);
static inline void
uart_report_port(struct uart_driver *drv, struct uart_port *port)
@ -2589,6 +2601,7 @@ out_kfree:
out:
return retval;
}
EXPORT_SYMBOL(uart_register_driver);
/**
* uart_unregister_driver - remove a driver from the uart core layer
@ -2612,6 +2625,7 @@ void uart_unregister_driver(struct uart_driver *drv)
drv->state = NULL;
drv->tty_driver = NULL;
}
EXPORT_SYMBOL(uart_unregister_driver);
struct tty_driver *uart_console_device(struct console *co, int *index)
{
@ -2946,6 +2960,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
return ret;
}
EXPORT_SYMBOL(uart_add_one_port);
/**
* uart_remove_one_port - detach a driver defined port structure
@ -3026,6 +3041,7 @@ out:
return ret;
}
EXPORT_SYMBOL(uart_remove_one_port);
/*
* Are the two ports equivalent?
@ -3202,14 +3218,6 @@ bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
EXPORT_SYMBOL_GPL(uart_try_toggle_sysrq);
#endif
EXPORT_SYMBOL(uart_write_wakeup);
EXPORT_SYMBOL(uart_register_driver);
EXPORT_SYMBOL(uart_unregister_driver);
EXPORT_SYMBOL(uart_suspend_port);
EXPORT_SYMBOL(uart_resume_port);
EXPORT_SYMBOL(uart_add_one_port);
EXPORT_SYMBOL(uart_remove_one_port);
/**
* uart_get_rs485_mode() - retrieve rs485 properties for given uart
* @port: uart device's target port

View File

@ -299,4 +299,42 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
}
EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms);
void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios)
{
enum mctrl_gpio_idx i;
if (!gpios)
return;
if (!gpios->mctrl_on)
return;
for (i = 0; i < UART_GPIO_MAX; ++i) {
if (!gpios->irq[i])
continue;
enable_irq_wake(gpios->irq[i]);
}
}
EXPORT_SYMBOL_GPL(mctrl_gpio_enable_irq_wake);
void mctrl_gpio_disable_irq_wake(struct mctrl_gpios *gpios)
{
enum mctrl_gpio_idx i;
if (!gpios)
return;
if (!gpios->mctrl_on)
return;
for (i = 0; i < UART_GPIO_MAX; ++i) {
if (!gpios->irq[i])
continue;
disable_irq_wake(gpios->irq[i]);
}
}
EXPORT_SYMBOL_GPL(mctrl_gpio_disable_irq_wake);
MODULE_LICENSE("GPL");

View File

@ -91,6 +91,16 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios);
*/
void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios);
/*
* Enable gpio wakeup interrupts to enable wake up source.
*/
void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios);
/*
* Disable gpio wakeup interrupts to enable wake up source.
*/
void mctrl_gpio_disable_irq_wake(struct mctrl_gpios *gpios);
#else /* GPIOLIB */
static inline
@ -142,6 +152,14 @@ static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
{
}
static inline void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios)
{
}
static inline void mctrl_gpio_disable_irq_wake(struct mctrl_gpios *gpios)
{
}
#endif /* GPIOLIB */
#endif

View File

@ -26,9 +26,6 @@
#include <linux/io.h>
static char *serial_version = "1.11";
static char *serial_name = "TX39/49 Serial driver";
#define PASS_LIMIT 256
#if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
@ -57,11 +54,6 @@ static char *serial_name = "TX39/49 Serial driver";
*/
#define UART_NR CONFIG_SERIAL_TXX9_NR_UARTS
struct uart_txx9_port {
struct uart_port port;
/* No additional info for now */
};
#define TXX9_REGION_SIZE 0x24
/* TXX9 Serial Registers */
@ -163,42 +155,42 @@ struct uart_txx9_port {
#define TXX9_SIBGR_BCLK_T6 0x00000300
#define TXX9_SIBGR_BRD_MASK 0x000000ff
static inline unsigned int sio_in(struct uart_txx9_port *up, int offset)
static inline unsigned int sio_in(struct uart_port *up, int offset)
{
switch (up->port.iotype) {
switch (up->iotype) {
default:
return __raw_readl(up->port.membase + offset);
return __raw_readl(up->membase + offset);
case UPIO_PORT:
return inl(up->port.iobase + offset);
return inl(up->iobase + offset);
}
}
static inline void
sio_out(struct uart_txx9_port *up, int offset, int value)
sio_out(struct uart_port *up, int offset, int value)
{
switch (up->port.iotype) {
switch (up->iotype) {
default:
__raw_writel(value, up->port.membase + offset);
__raw_writel(value, up->membase + offset);
break;
case UPIO_PORT:
outl(value, up->port.iobase + offset);
outl(value, up->iobase + offset);
break;
}
}
static inline void
sio_mask(struct uart_txx9_port *up, int offset, unsigned int value)
sio_mask(struct uart_port *up, int offset, unsigned int value)
{
sio_out(up, offset, sio_in(up, offset) & ~value);
}
static inline void
sio_set(struct uart_txx9_port *up, int offset, unsigned int value)
sio_set(struct uart_port *up, int offset, unsigned int value)
{
sio_out(up, offset, sio_in(up, offset) | value);
}
static inline void
sio_quot_set(struct uart_txx9_port *up, int quot)
sio_quot_set(struct uart_port *up, int quot)
{
quot >>= 1;
if (quot < 256)
@ -213,32 +205,23 @@ sio_quot_set(struct uart_txx9_port *up, int quot)
sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
}
static struct uart_txx9_port *to_uart_txx9_port(struct uart_port *port)
static void serial_txx9_stop_tx(struct uart_port *up)
{
return container_of(port, struct uart_txx9_port, port);
}
static void serial_txx9_stop_tx(struct uart_port *port)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
}
static void serial_txx9_start_tx(struct uart_port *port)
static void serial_txx9_start_tx(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
}
static void serial_txx9_stop_rx(struct uart_port *port)
static void serial_txx9_stop_rx(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
up->read_status_mask &= ~TXX9_SIDISR_RDIS;
}
static void serial_txx9_initialize(struct uart_port *port)
static void serial_txx9_initialize(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int tmout = 10000;
sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
@ -253,15 +236,15 @@ static void serial_txx9_initialize(struct uart_port *port)
/* initial settings */
sio_out(up, TXX9_SILCR,
TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
((up->port.flags & UPF_TXX9_USE_SCLK) ?
((up->flags & UPF_TXX9_USE_SCLK) ?
TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
sio_quot_set(up, uart_get_divisor(port, 9600));
sio_quot_set(up, uart_get_divisor(up, 9600));
sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
sio_out(up, TXX9_SIDICR, 0);
}
static inline void
receive_chars(struct uart_txx9_port *up, unsigned int *status)
receive_chars(struct uart_port *up, unsigned int *status)
{
unsigned char ch;
unsigned int disr = *status;
@ -272,11 +255,11 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status)
do {
ch = sio_in(up, TXX9_SIRFIFO);
flag = TTY_NORMAL;
up->port.icount.rx++;
up->icount.rx++;
/* mask out RFDN_MASK bit added by previous overrun */
next_ignore_status_mask =
up->port.ignore_status_mask & ~TXX9_SIDISR_RFDN_MASK;
up->ignore_status_mask & ~TXX9_SIDISR_RFDN_MASK;
if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER |
TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) {
/*
@ -284,21 +267,21 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status)
*/
if (disr & TXX9_SIDISR_UBRK) {
disr &= ~(TXX9_SIDISR_UFER | TXX9_SIDISR_UPER);
up->port.icount.brk++;
up->icount.brk++;
/*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
* or read_status_mask.
*/
if (uart_handle_break(&up->port))
if (uart_handle_break(up))
goto ignore_char;
} else if (disr & TXX9_SIDISR_UPER)
up->port.icount.parity++;
up->icount.parity++;
else if (disr & TXX9_SIDISR_UFER)
up->port.icount.frame++;
up->icount.frame++;
if (disr & TXX9_SIDISR_UOER) {
up->port.icount.overrun++;
up->icount.overrun++;
/*
* The receiver read buffer still hold
* a char which caused overrun.
@ -312,7 +295,7 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status)
/*
* Mask off conditions which should be ingored.
*/
disr &= up->port.read_status_mask;
disr &= up->read_status_mask;
if (disr & TXX9_SIDISR_UBRK) {
flag = TTY_BREAK;
@ -321,34 +304,34 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status)
else if (disr & TXX9_SIDISR_UFER)
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch))
if (uart_handle_sysrq_char(up, ch))
goto ignore_char;
uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag);
uart_insert_char(up, disr, TXX9_SIDISR_UOER, ch, flag);
ignore_char:
up->port.ignore_status_mask = next_ignore_status_mask;
up->ignore_status_mask = next_ignore_status_mask;
disr = sio_in(up, TXX9_SIDISR);
} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
tty_flip_buffer_push(&up->port.state->port);
tty_flip_buffer_push(&up->state->port);
*status = disr;
}
static inline void transmit_chars(struct uart_txx9_port *up)
static inline void transmit_chars(struct uart_port *up)
{
struct circ_buf *xmit = &up->port.state->xmit;
struct circ_buf *xmit = &up->state->xmit;
int count;
if (up->port.x_char) {
sio_out(up, TXX9_SITFIFO, up->port.x_char);
up->port.icount.tx++;
up->port.x_char = 0;
if (up->x_char) {
sio_out(up, TXX9_SITFIFO, up->x_char);
up->icount.tx++;
up->x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
serial_txx9_stop_tx(&up->port);
if (uart_circ_empty(xmit) || uart_tx_stopped(up)) {
serial_txx9_stop_tx(up);
return;
}
@ -356,32 +339,32 @@ static inline void transmit_chars(struct uart_txx9_port *up)
do {
sio_out(up, TXX9_SITFIFO, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->port.icount.tx++;
up->icount.tx++;
if (uart_circ_empty(xmit))
break;
} while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port);
uart_write_wakeup(up);
if (uart_circ_empty(xmit))
serial_txx9_stop_tx(&up->port);
serial_txx9_stop_tx(up);
}
static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
{
int pass_counter = 0;
struct uart_txx9_port *up = dev_id;
struct uart_port *up = dev_id;
unsigned int status;
while (1) {
spin_lock(&up->port.lock);
spin_lock(&up->lock);
status = sio_in(up, TXX9_SIDISR);
if (!(sio_in(up, TXX9_SIDICR) & TXX9_SIDICR_TIE))
status &= ~TXX9_SIDISR_TDIS;
if (!(status & (TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
TXX9_SIDISR_TOUT))) {
spin_unlock(&up->port.lock);
spin_unlock(&up->lock);
break;
}
@ -393,7 +376,7 @@ static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
sio_mask(up, TXX9_SIDISR,
TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
TXX9_SIDISR_TOUT);
spin_unlock(&up->port.lock);
spin_unlock(&up->lock);
if (pass_counter++ > PASS_LIMIT)
break;
@ -402,22 +385,20 @@ static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
return pass_counter ? IRQ_HANDLED : IRQ_NONE;
}
static unsigned int serial_txx9_tx_empty(struct uart_port *port)
static unsigned int serial_txx9_tx_empty(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
unsigned int ret;
spin_lock_irqsave(&up->port.lock, flags);
spin_lock_irqsave(&up->lock, flags);
ret = (sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS) ? TIOCSER_TEMT : 0;
spin_unlock_irqrestore(&up->port.lock, flags);
spin_unlock_irqrestore(&up->lock, flags);
return ret;
}
static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
static unsigned int serial_txx9_get_mctrl(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int ret;
/* no modem control lines */
@ -428,9 +409,8 @@ static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
return ret;
}
static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
static void serial_txx9_set_mctrl(struct uart_port *up, unsigned int mctrl)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
if (mctrl & TIOCM_RTS)
sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
@ -438,24 +418,23 @@ static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
}
static void serial_txx9_break_ctl(struct uart_port *port, int break_state)
static void serial_txx9_break_ctl(struct uart_port *up, int break_state)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
spin_lock_irqsave(&up->port.lock, flags);
spin_lock_irqsave(&up->lock, flags);
if (break_state == -1)
sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
else
sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
spin_unlock_irqrestore(&up->port.lock, flags);
spin_unlock_irqrestore(&up->lock, flags);
}
#if defined(CONFIG_SERIAL_TXX9_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
/*
* Wait for transmitter & holding register to empty
*/
static void wait_for_xmitr(struct uart_txx9_port *up)
static void wait_for_xmitr(struct uart_port *up)
{
unsigned int tmout = 10000;
@ -465,7 +444,7 @@ static void wait_for_xmitr(struct uart_txx9_port *up)
udelay(1);
/* Wait up to 1s for flow control if necessary */
if (up->port.flags & UPF_CONS_FLOW) {
if (up->flags & UPF_CONS_FLOW) {
tmout = 1000000;
while (--tmout &&
(sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS))
@ -480,11 +459,10 @@ static void wait_for_xmitr(struct uart_txx9_port *up)
* in an interrupt or debug context.
*/
static int serial_txx9_get_poll_char(struct uart_port *port)
static int serial_txx9_get_poll_char(struct uart_port *up)
{
unsigned int ier;
unsigned char c;
struct uart_txx9_port *up = to_uart_txx9_port(port);
/*
* First save the IER then disable the interrupts
@ -507,10 +485,9 @@ static int serial_txx9_get_poll_char(struct uart_port *port)
}
static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c)
static void serial_txx9_put_poll_char(struct uart_port *up, unsigned char c)
{
unsigned int ier;
struct uart_txx9_port *up = to_uart_txx9_port(port);
/*
* First save the IER then disable the interrupts
@ -534,9 +511,8 @@ static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c)
#endif /* CONFIG_CONSOLE_POLL */
static int serial_txx9_startup(struct uart_port *port)
static int serial_txx9_startup(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
int retval;
@ -556,7 +532,7 @@ static int serial_txx9_startup(struct uart_port *port)
*/
sio_out(up, TXX9_SIDISR, 0);
retval = request_irq(up->port.irq, serial_txx9_interrupt,
retval = request_irq(up->irq, serial_txx9_interrupt,
IRQF_SHARED, "serial_txx9", up);
if (retval)
return retval;
@ -564,9 +540,9 @@ static int serial_txx9_startup(struct uart_port *port)
/*
* Now, initialize the UART
*/
spin_lock_irqsave(&up->port.lock, flags);
serial_txx9_set_mctrl(&up->port, up->port.mctrl);
spin_unlock_irqrestore(&up->port.lock, flags);
spin_lock_irqsave(&up->lock, flags);
serial_txx9_set_mctrl(up, up->mctrl);
spin_unlock_irqrestore(&up->lock, flags);
/* Enable RX/TX */
sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
@ -579,9 +555,8 @@ static int serial_txx9_startup(struct uart_port *port)
return 0;
}
static void serial_txx9_shutdown(struct uart_port *port)
static void serial_txx9_shutdown(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
/*
@ -589,9 +564,9 @@ static void serial_txx9_shutdown(struct uart_port *port)
*/
sio_out(up, TXX9_SIDICR, 0); /* disable all intrs */
spin_lock_irqsave(&up->port.lock, flags);
serial_txx9_set_mctrl(&up->port, up->port.mctrl);
spin_unlock_irqrestore(&up->port.lock, flags);
spin_lock_irqsave(&up->lock, flags);
serial_txx9_set_mctrl(up, up->mctrl);
spin_unlock_irqrestore(&up->lock, flags);
/*
* Disable break condition
@ -599,8 +574,8 @@ static void serial_txx9_shutdown(struct uart_port *port)
sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
#ifdef CONFIG_SERIAL_TXX9_CONSOLE
if (up->port.cons && up->port.line == up->port.cons->index) {
free_irq(up->port.irq, up);
if (up->cons && up->line == up->cons->index) {
free_irq(up->irq, up);
return;
}
#endif
@ -614,14 +589,13 @@ static void serial_txx9_shutdown(struct uart_port *port)
/* Disable RX/TX */
sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
free_irq(up->port.irq, up);
free_irq(up->irq, up);
}
static void
serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
serial_txx9_set_termios(struct uart_port *up, struct ktermios *termios,
struct ktermios *old)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int cval, fcr = 0;
unsigned long flags;
unsigned int baud, quot;
@ -661,8 +635,8 @@ serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Ask the core to calculate the divisor for us.
*/
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16/2);
quot = uart_get_divisor(port, baud);
baud = uart_get_baud_rate(up, termios, old, 0, up->uartclk/16/2);
quot = uart_get_divisor(up, baud);
/* Set up FIFOs */
/* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
@ -672,45 +646,45 @@ serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
spin_lock_irqsave(&up->port.lock, flags);
spin_lock_irqsave(&up->lock, flags);
/*
* Update the per-port timeout.
*/
uart_update_timeout(port, termios->c_cflag, baud);
uart_update_timeout(up, termios->c_cflag, baud);
up->port.read_status_mask = TXX9_SIDISR_UOER |
up->read_status_mask = TXX9_SIDISR_UOER |
TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS;
if (termios->c_iflag & INPCK)
up->port.read_status_mask |= TXX9_SIDISR_UFER | TXX9_SIDISR_UPER;
up->read_status_mask |= TXX9_SIDISR_UFER | TXX9_SIDISR_UPER;
if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
up->port.read_status_mask |= TXX9_SIDISR_UBRK;
up->read_status_mask |= TXX9_SIDISR_UBRK;
/*
* Characteres to ignore
*/
up->port.ignore_status_mask = 0;
up->ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
up->port.ignore_status_mask |= TXX9_SIDISR_UPER | TXX9_SIDISR_UFER;
up->ignore_status_mask |= TXX9_SIDISR_UPER | TXX9_SIDISR_UFER;
if (termios->c_iflag & IGNBRK) {
up->port.ignore_status_mask |= TXX9_SIDISR_UBRK;
up->ignore_status_mask |= TXX9_SIDISR_UBRK;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if (termios->c_iflag & IGNPAR)
up->port.ignore_status_mask |= TXX9_SIDISR_UOER;
up->ignore_status_mask |= TXX9_SIDISR_UOER;
}
/*
* ignore all characters if CREAD is not set
*/
if ((termios->c_cflag & CREAD) == 0)
up->port.ignore_status_mask |= TXX9_SIDISR_RDIS;
up->ignore_status_mask |= TXX9_SIDISR_RDIS;
/* CTS flow control flag */
if ((termios->c_cflag & CRTSCTS) &&
(up->port.flags & UPF_TXX9_HAVE_CTS_LINE)) {
(up->flags & UPF_TXX9_HAVE_CTS_LINE)) {
sio_set(up, TXX9_SIFLCR,
TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
} else {
@ -722,8 +696,8 @@ serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
sio_quot_set(up, quot);
sio_out(up, TXX9_SIFCR, fcr);
serial_txx9_set_mctrl(&up->port, up->port.mctrl);
spin_unlock_irqrestore(&up->port.lock, flags);
serial_txx9_set_mctrl(up, up->mctrl);
spin_unlock_irqrestore(&up->lock, flags);
}
static void
@ -742,76 +716,73 @@ serial_txx9_pm(struct uart_port *port, unsigned int state,
serial_txx9_initialize(port);
}
static int serial_txx9_request_resource(struct uart_txx9_port *up)
static int serial_txx9_request_resource(struct uart_port *up)
{
unsigned int size = TXX9_REGION_SIZE;
int ret = 0;
switch (up->port.iotype) {
switch (up->iotype) {
default:
if (!up->port.mapbase)
if (!up->mapbase)
break;
if (!request_mem_region(up->port.mapbase, size, "serial_txx9")) {
if (!request_mem_region(up->mapbase, size, "serial_txx9")) {
ret = -EBUSY;
break;
}
if (up->port.flags & UPF_IOREMAP) {
up->port.membase = ioremap(up->port.mapbase, size);
if (!up->port.membase) {
release_mem_region(up->port.mapbase, size);
if (up->flags & UPF_IOREMAP) {
up->membase = ioremap(up->mapbase, size);
if (!up->membase) {
release_mem_region(up->mapbase, size);
ret = -ENOMEM;
}
}
break;
case UPIO_PORT:
if (!request_region(up->port.iobase, size, "serial_txx9"))
if (!request_region(up->iobase, size, "serial_txx9"))
ret = -EBUSY;
break;
}
return ret;
}
static void serial_txx9_release_resource(struct uart_txx9_port *up)
static void serial_txx9_release_resource(struct uart_port *up)
{
unsigned int size = TXX9_REGION_SIZE;
switch (up->port.iotype) {
switch (up->iotype) {
default:
if (!up->port.mapbase)
if (!up->mapbase)
break;
if (up->port.flags & UPF_IOREMAP) {
iounmap(up->port.membase);
up->port.membase = NULL;
if (up->flags & UPF_IOREMAP) {
iounmap(up->membase);
up->membase = NULL;
}
release_mem_region(up->port.mapbase, size);
release_mem_region(up->mapbase, size);
break;
case UPIO_PORT:
release_region(up->port.iobase, size);
release_region(up->iobase, size);
break;
}
}
static void serial_txx9_release_port(struct uart_port *port)
static void serial_txx9_release_port(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
serial_txx9_release_resource(up);
}
static int serial_txx9_request_port(struct uart_port *port)
static int serial_txx9_request_port(struct uart_port *up)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
return serial_txx9_request_resource(up);
}
static void serial_txx9_config_port(struct uart_port *port, int uflags)
static void serial_txx9_config_port(struct uart_port *up, int uflags)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
int ret;
/*
@ -821,14 +792,14 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags)
ret = serial_txx9_request_resource(up);
if (ret < 0)
return;
port->type = PORT_TXX9;
up->port.fifosize = TXX9_SIO_TX_FIFO;
up->type = PORT_TXX9;
up->fifosize = TXX9_SIO_TX_FIFO;
#ifdef CONFIG_SERIAL_TXX9_CONSOLE
if (up->port.line == up->port.cons->index)
if (up->line == up->cons->index)
return;
#endif
serial_txx9_initialize(port);
serial_txx9_initialize(up);
}
static const char *
@ -859,7 +830,7 @@ static const struct uart_ops serial_txx9_pops = {
#endif
};
static struct uart_txx9_port serial_txx9_ports[UART_NR];
static struct uart_port serial_txx9_ports[UART_NR];
static void __init serial_txx9_register_ports(struct uart_driver *drv,
struct device *dev)
@ -867,22 +838,20 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv,
int i;
for (i = 0; i < UART_NR; i++) {
struct uart_txx9_port *up = &serial_txx9_ports[i];
struct uart_port *up = &serial_txx9_ports[i];
up->port.line = i;
up->port.ops = &serial_txx9_pops;
up->port.dev = dev;
if (up->port.iobase || up->port.mapbase)
uart_add_one_port(drv, &up->port);
up->line = i;
up->ops = &serial_txx9_pops;
up->dev = dev;
if (up->iobase || up->mapbase)
uart_add_one_port(drv, up);
}
}
#ifdef CONFIG_SERIAL_TXX9_CONSOLE
static void serial_txx9_console_putchar(struct uart_port *port, int ch)
static void serial_txx9_console_putchar(struct uart_port *up, unsigned char ch)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
wait_for_xmitr(up);
sio_out(up, TXX9_SITFIFO, ch);
}
@ -896,7 +865,7 @@ static void serial_txx9_console_putchar(struct uart_port *port, int ch)
static void
serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_txx9_port *up = &serial_txx9_ports[co->index];
struct uart_port *up = &serial_txx9_ports[co->index];
unsigned int ier, flcr;
/*
@ -908,10 +877,10 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
* Disable flow-control if enabled (and unnecessary)
*/
flcr = sio_in(up, TXX9_SIFLCR);
if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
if (!(up->flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
uart_console_write(&up->port, s, count, serial_txx9_console_putchar);
uart_console_write(up, s, count, serial_txx9_console_putchar);
/*
* Finally, wait for transmitter to become empty
@ -924,8 +893,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
static int __init serial_txx9_console_setup(struct console *co, char *options)
{
struct uart_port *port;
struct uart_txx9_port *up;
struct uart_port *up;
int baud = 9600;
int bits = 8;
int parity = 'n';
@ -939,16 +907,15 @@ static int __init serial_txx9_console_setup(struct console *co, char *options)
if (co->index >= UART_NR)
co->index = 0;
up = &serial_txx9_ports[co->index];
port = &up->port;
if (!port->ops)
if (!up->ops)
return -ENODEV;
serial_txx9_initialize(&up->port);
serial_txx9_initialize(up);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
return uart_set_options(port, co, baud, parity, bits, flow);
return uart_set_options(up, co, baud, parity, bits, flow);
}
static struct uart_driver serial_txx9_reg;
@ -989,9 +956,9 @@ int __init early_serial_txx9_setup(struct uart_port *port)
if (port->line >= ARRAY_SIZE(serial_txx9_ports))
return -ENODEV;
serial_txx9_ports[port->line].port = *port;
serial_txx9_ports[port->line].port.ops = &serial_txx9_pops;
serial_txx9_ports[port->line].port.flags |=
serial_txx9_ports[port->line] = *port;
serial_txx9_ports[port->line].ops = &serial_txx9_pops;
serial_txx9_ports[port->line].flags |=
UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
return 0;
}
@ -1012,14 +979,14 @@ static DEFINE_MUTEX(serial_txx9_mutex);
static int serial_txx9_register_port(struct uart_port *port)
{
int i;
struct uart_txx9_port *uart;
struct uart_port *uart;
int ret = -ENOSPC;
mutex_lock(&serial_txx9_mutex);
for (i = 0; i < UART_NR; i++) {
uart = &serial_txx9_ports[i];
if (uart_match_port(&uart->port, port)) {
uart_remove_one_port(&serial_txx9_reg, &uart->port);
if (uart_match_port(uart, port)) {
uart_remove_one_port(&serial_txx9_reg, uart);
break;
}
}
@ -1027,24 +994,24 @@ static int serial_txx9_register_port(struct uart_port *port)
/* Find unused port */
for (i = 0; i < UART_NR; i++) {
uart = &serial_txx9_ports[i];
if (!(uart->port.iobase || uart->port.mapbase))
if (!(uart->iobase || uart->mapbase))
break;
}
}
if (i < UART_NR) {
uart->port.iobase = port->iobase;
uart->port.membase = port->membase;
uart->port.irq = port->irq;
uart->port.uartclk = port->uartclk;
uart->port.iotype = port->iotype;
uart->port.flags = port->flags
uart->iobase = port->iobase;
uart->membase = port->membase;
uart->irq = port->irq;
uart->uartclk = port->uartclk;
uart->iotype = port->iotype;
uart->flags = port->flags
| UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
uart->port.mapbase = port->mapbase;
uart->mapbase = port->mapbase;
if (port->dev)
uart->port.dev = port->dev;
ret = uart_add_one_port(&serial_txx9_reg, &uart->port);
uart->dev = port->dev;
ret = uart_add_one_port(&serial_txx9_reg, uart);
if (ret == 0)
ret = uart->port.line;
ret = uart->line;
}
mutex_unlock(&serial_txx9_mutex);
return ret;
@ -1059,16 +1026,16 @@ static int serial_txx9_register_port(struct uart_port *port)
*/
static void serial_txx9_unregister_port(int line)
{
struct uart_txx9_port *uart = &serial_txx9_ports[line];
struct uart_port *uart = &serial_txx9_ports[line];
mutex_lock(&serial_txx9_mutex);
uart_remove_one_port(&serial_txx9_reg, &uart->port);
uart->port.flags = 0;
uart->port.type = PORT_UNKNOWN;
uart->port.iobase = 0;
uart->port.mapbase = 0;
uart->port.membase = NULL;
uart->port.dev = NULL;
uart_remove_one_port(&serial_txx9_reg, uart);
uart->flags = 0;
uart->type = PORT_UNKNOWN;
uart->iobase = 0;
uart->mapbase = 0;
uart->membase = NULL;
uart->dev = NULL;
mutex_unlock(&serial_txx9_mutex);
}
@ -1111,9 +1078,9 @@ static int serial_txx9_remove(struct platform_device *dev)
int i;
for (i = 0; i < UART_NR; i++) {
struct uart_txx9_port *up = &serial_txx9_ports[i];
struct uart_port *up = &serial_txx9_ports[i];
if (up->port.dev == &dev->dev)
if (up->dev == &dev->dev)
serial_txx9_unregister_port(i);
}
return 0;
@ -1125,10 +1092,10 @@ static int serial_txx9_suspend(struct platform_device *dev, pm_message_t state)
int i;
for (i = 0; i < UART_NR; i++) {
struct uart_txx9_port *up = &serial_txx9_ports[i];
struct uart_port *up = &serial_txx9_ports[i];
if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
uart_suspend_port(&serial_txx9_reg, &up->port);
if (up->type != PORT_UNKNOWN && up->dev == &dev->dev)
uart_suspend_port(&serial_txx9_reg, up);
}
return 0;
@ -1139,10 +1106,10 @@ static int serial_txx9_resume(struct platform_device *dev)
int i;
for (i = 0; i < UART_NR; i++) {
struct uart_txx9_port *up = &serial_txx9_ports[i];
struct uart_port *up = &serial_txx9_ports[i];
if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
uart_resume_port(&serial_txx9_reg, &up->port);
if (up->type != PORT_UNKNOWN && up->dev == &dev->dev)
uart_resume_port(&serial_txx9_reg, up);
}
return 0;
@ -1198,10 +1165,10 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
static void pciserial_txx9_remove_one(struct pci_dev *dev)
{
struct uart_txx9_port *up = pci_get_drvdata(dev);
struct uart_port *up = pci_get_drvdata(dev);
if (up) {
serial_txx9_unregister_port(up->port.line);
serial_txx9_unregister_port(up->line);
pci_disable_device(dev);
}
}
@ -1209,10 +1176,10 @@ static void pciserial_txx9_remove_one(struct pci_dev *dev)
#ifdef CONFIG_PM
static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
{
struct uart_txx9_port *up = pci_get_drvdata(dev);
struct uart_port *up = pci_get_drvdata(dev);
if (up)
uart_suspend_port(&serial_txx9_reg, &up->port);
uart_suspend_port(&serial_txx9_reg, up);
pci_save_state(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
@ -1220,12 +1187,12 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
static int pciserial_txx9_resume_one(struct pci_dev *dev)
{
struct uart_txx9_port *up = pci_get_drvdata(dev);
struct uart_port *up = pci_get_drvdata(dev);
pci_set_power_state(dev, PCI_D0);
pci_restore_state(dev);
if (up)
uart_resume_port(&serial_txx9_reg, &up->port);
uart_resume_port(&serial_txx9_reg, up);
return 0;
}
#endif
@ -1255,8 +1222,6 @@ static int __init serial_txx9_init(void)
{
int ret;
printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
ret = uart_register_driver(&serial_txx9_reg);
if (ret)
goto out;
@ -1307,9 +1272,9 @@ static void __exit serial_txx9_exit(void)
platform_driver_unregister(&serial_txx9_plat_driver);
platform_device_unregister(serial_txx9_plat_devs);
for (i = 0; i < UART_NR; i++) {
struct uart_txx9_port *up = &serial_txx9_ports[i];
if (up->port.iobase || up->port.mapbase)
uart_remove_one_port(&serial_txx9_reg, &up->port);
struct uart_port *up = &serial_txx9_ports[i];
if (up->iobase || up->mapbase)
uart_remove_one_port(&serial_txx9_reg, up);
}
uart_unregister_driver(&serial_txx9_reg);

View File

@ -2293,7 +2293,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
for_each_sr(sr, s) {
for (c = 0; c <= 3; c++) {
/* integerized formulas from HSCIF documentation */
prediv = sr * (1 << (2 * c + 1));
prediv = sr << (2 * c + 1);
/*
* We need to calculate:
@ -2960,7 +2960,7 @@ static void sci_cleanup_single(struct sci_port *port)
#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || \
defined(CONFIG_SERIAL_SH_SCI_EARLYCON)
static void serial_console_putchar(struct uart_port *port, int ch)
static void serial_console_putchar(struct uart_port *port, unsigned char ch)
{
sci_poll_put_char(port, ch);
}

View File

@ -756,7 +756,7 @@ static void sifive_serial_poll_put_char(struct uart_port *port,
*/
#ifdef CONFIG_SERIAL_EARLYCON
static void early_sifive_serial_putc(struct uart_port *port, int c)
static void early_sifive_serial_putc(struct uart_port *port, unsigned char c)
{
while (__ssp_early_readl(port, SIFIVE_SERIAL_TXDATA_OFFS) &
SIFIVE_SERIAL_TXDATA_FULL_MASK)
@ -800,7 +800,7 @@ OF_EARLYCON_DECLARE(sifive, "sifive,fu540-c000-uart0",
static struct sifive_serial_port *sifive_serial_console_ports[SIFIVE_SERIAL_MAX_PORTS];
static void sifive_serial_console_putchar(struct uart_port *port, int ch)
static void sifive_serial_console_putchar(struct uart_port *port, unsigned char ch)
{
struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);

View File

@ -984,7 +984,7 @@ static void wait_for_xmitr(struct uart_port *port)
} while (status & SPRD_TX_FIFO_CNT_MASK);
}
static void sprd_console_putchar(struct uart_port *port, int ch)
static void sprd_console_putchar(struct uart_port *port, unsigned char ch)
{
wait_for_xmitr(port);
serial_out(port, SPRD_TXD, ch);
@ -1058,7 +1058,7 @@ console_initcall(sprd_serial_console_init);
#define SPRD_CONSOLE (&sprd_console)
/* Support for earlycon */
static void sprd_putc(struct uart_port *port, int c)
static void sprd_putc(struct uart_port *port, unsigned char c)
{
unsigned int timeout = SPRD_TIMEOUT;

View File

@ -854,7 +854,7 @@ static int asc_serial_resume(struct device *dev)
/*----------------------------------------------------------------------*/
#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE
static void asc_console_putchar(struct uart_port *port, int ch)
static void asc_console_putchar(struct uart_port *port, unsigned char ch)
{
unsigned int timeout = 1000000;

View File

@ -1641,7 +1641,7 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
}
#ifdef CONFIG_SERIAL_STM32_CONSOLE
static void stm32_usart_console_putchar(struct uart_port *port, int ch)
static void stm32_usart_console_putchar(struct uart_port *port, unsigned char ch)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
@ -1756,6 +1756,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
if (enable) {
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_UESM);
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_WUFIE);
mctrl_gpio_enable_irq_wake(stm32_port->gpios);
/*
* When DMA is used for reception, it must be disabled before
@ -1782,7 +1783,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
if (ret)
return ret;
}
mctrl_gpio_disable_irq_wake(stm32_port->gpios);
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_UESM);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
}

View File

@ -0,0 +1,775 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Sunplus SoC UART driver
*
* Author: Hammer Hsieh <hammerh0314@gmail.com>
*
* Note1: This driver is 8250-like uart, but are not register compatible.
*
* Note2: On some buses, for preventing data incoherence, must do a read
* for ensure write made it to hardware. In this driver, function startup
* and shutdown did not do a read but only do a write directly. For what?
* In Sunplus bus communication between memory bus and peripheral bus with
* posted write, it will send a specific command after last write command
* to make sure write done. Then memory bus identify the specific command
* and send done signal back to master device. After master device received
* done signal, then proceed next write command. It is no need to do a read
* before write.
*/
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <asm/irq.h>
/* Register offsets */
#define SUP_UART_DATA 0x00
#define SUP_UART_LSR 0x04
#define SUP_UART_MSR 0x08
#define SUP_UART_LCR 0x0C
#define SUP_UART_MCR 0x10
#define SUP_UART_DIV_L 0x14
#define SUP_UART_DIV_H 0x18
#define SUP_UART_ISC 0x1C
#define SUP_UART_TX_RESIDUE 0x20
#define SUP_UART_RX_RESIDUE 0x24
/* Line Status Register bits */
#define SUP_UART_LSR_BC BIT(5) /* break condition status */
#define SUP_UART_LSR_FE BIT(4) /* frame error status */
#define SUP_UART_LSR_OE BIT(3) /* overrun error status */
#define SUP_UART_LSR_PE BIT(2) /* parity error status */
#define SUP_UART_LSR_RX BIT(1) /* 1: receive fifo not empty */
#define SUP_UART_LSR_TX BIT(0) /* 1: transmit fifo is not full */
#define SUP_UART_LSR_TX_NOT_FULL 1
#define SUP_UART_LSR_BRK_ERROR_BITS GENMASK(5, 2)
/* Line Control Register bits */
#define SUP_UART_LCR_SBC BIT(5) /* select break condition */
/* Modem Control Register bits */
#define SUP_UART_MCR_RI BIT(3) /* ring indicator */
#define SUP_UART_MCR_DCD BIT(2) /* data carrier detect */
/* Interrupt Status/Control Register bits */
#define SUP_UART_ISC_RXM BIT(5) /* RX interrupt enable */
#define SUP_UART_ISC_TXM BIT(4) /* TX interrupt enable */
#define SUP_UART_ISC_RX BIT(1) /* RX interrupt status */
#define SUP_UART_ISC_TX BIT(0) /* TX interrupt status */
#define SUP_DUMMY_READ BIT(16) /* drop bytes received on a !CREAD port */
#define SUP_UART_NR 5
struct sunplus_uart_port {
struct uart_port port;
struct clk *clk;
struct reset_control *rstc;
};
static void sp_uart_put_char(struct uart_port *port, unsigned int ch)
{
writel(ch, port->membase + SUP_UART_DATA);
}
static u32 sunplus_tx_buf_not_full(struct uart_port *port)
{
unsigned int lsr = readl(port->membase + SUP_UART_LSR);
return (lsr & SUP_UART_LSR_TX) ? SUP_UART_LSR_TX_NOT_FULL : 0;
}
static unsigned int sunplus_tx_empty(struct uart_port *port)
{
unsigned int lsr = readl(port->membase + SUP_UART_LSR);
return (lsr & UART_LSR_TEMT) ? TIOCSER_TEMT : 0;
}
static void sunplus_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
unsigned int mcr = readl(port->membase + SUP_UART_MCR);
if (mctrl & TIOCM_DTR)
mcr |= UART_MCR_DTR;
else
mcr &= ~UART_MCR_DTR;
if (mctrl & TIOCM_RTS)
mcr |= UART_MCR_RTS;
else
mcr &= ~UART_MCR_RTS;
if (mctrl & TIOCM_CAR)
mcr |= SUP_UART_MCR_DCD;
else
mcr &= ~SUP_UART_MCR_DCD;
if (mctrl & TIOCM_RI)
mcr |= SUP_UART_MCR_RI;
else
mcr &= ~SUP_UART_MCR_RI;
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
else
mcr &= ~UART_MCR_LOOP;
writel(mcr, port->membase + SUP_UART_MCR);
}
static unsigned int sunplus_get_mctrl(struct uart_port *port)
{
unsigned int mcr, ret = 0;
mcr = readl(port->membase + SUP_UART_MCR);
if (mcr & UART_MCR_DTR)
ret |= TIOCM_DTR;
if (mcr & UART_MCR_RTS)
ret |= TIOCM_RTS;
if (mcr & SUP_UART_MCR_DCD)
ret |= TIOCM_CAR;
if (mcr & SUP_UART_MCR_RI)
ret |= TIOCM_RI;
if (mcr & UART_MCR_LOOP)
ret |= TIOCM_LOOP;
return ret;
}
static void sunplus_stop_tx(struct uart_port *port)
{
unsigned int isc;
isc = readl(port->membase + SUP_UART_ISC);
isc &= ~SUP_UART_ISC_TXM;
writel(isc, port->membase + SUP_UART_ISC);
}
static void sunplus_start_tx(struct uart_port *port)
{
unsigned int isc;
isc = readl(port->membase + SUP_UART_ISC);
isc |= SUP_UART_ISC_TXM;
writel(isc, port->membase + SUP_UART_ISC);
}
static void sunplus_stop_rx(struct uart_port *port)
{
unsigned int isc;
isc = readl(port->membase + SUP_UART_ISC);
isc &= ~SUP_UART_ISC_RXM;
writel(isc, port->membase + SUP_UART_ISC);
}
static void sunplus_break_ctl(struct uart_port *port, int ctl)
{
unsigned long flags;
unsigned int lcr;
spin_lock_irqsave(&port->lock, flags);
lcr = readl(port->membase + SUP_UART_LCR);
if (ctl)
lcr |= SUP_UART_LCR_SBC; /* start break */
else
lcr &= ~SUP_UART_LCR_SBC; /* stop break */
writel(lcr, port->membase + SUP_UART_LCR);
spin_unlock_irqrestore(&port->lock, flags);
}
static void transmit_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
if (port->x_char) {
sp_uart_put_char(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
sunplus_stop_tx(port);
return;
}
do {
sp_uart_put_char(port, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) % UART_XMIT_SIZE;
port->icount.tx++;
if (uart_circ_empty(xmit))
break;
} while (sunplus_tx_buf_not_full(port));
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
sunplus_stop_tx(port);
}
static void receive_chars(struct uart_port *port)
{
unsigned int lsr = readl(port->membase + SUP_UART_LSR);
unsigned int ch, flag;
do {
ch = readl(port->membase + SUP_UART_DATA);
flag = TTY_NORMAL;
port->icount.rx++;
if (unlikely(lsr & SUP_UART_LSR_BRK_ERROR_BITS)) {
if (lsr & SUP_UART_LSR_BC) {
lsr &= ~(SUP_UART_LSR_FE | SUP_UART_LSR_PE);
port->icount.brk++;
flag = TTY_BREAK;
if (uart_handle_break(port))
goto ignore_char;
} else if (lsr & SUP_UART_LSR_PE) {
port->icount.parity++;
flag = TTY_PARITY;
} else if (lsr & SUP_UART_LSR_FE) {
port->icount.frame++;
flag = TTY_FRAME;
}
if (lsr & SUP_UART_LSR_OE)
port->icount.overrun++;
}
if (port->ignore_status_mask & SUP_DUMMY_READ)
goto ignore_char;
if (uart_handle_sysrq_char(port, ch))
goto ignore_char;
uart_insert_char(port, lsr, SUP_UART_LSR_OE, ch, flag);
ignore_char:
lsr = readl(port->membase + SUP_UART_LSR);
} while (lsr & SUP_UART_LSR_RX);
tty_flip_buffer_push(&port->state->port);
}
static irqreturn_t sunplus_uart_irq(int irq, void *args)
{
struct uart_port *port = args;
unsigned int isc;
spin_lock(&port->lock);
isc = readl(port->membase + SUP_UART_ISC);
if (isc & SUP_UART_ISC_RX)
receive_chars(port);
if (isc & SUP_UART_ISC_TX)
transmit_chars(port);
spin_unlock(&port->lock);
return IRQ_HANDLED;
}
static int sunplus_startup(struct uart_port *port)
{
unsigned long flags;
unsigned int isc = 0;
int ret;
ret = request_irq(port->irq, sunplus_uart_irq, 0, "sunplus_uart", port);
if (ret)
return ret;
spin_lock_irqsave(&port->lock, flags);
/* isc define Bit[7:4] int setting, Bit[3:0] int status
* isc register will clean Bit[3:0] int status after read
* only do a write to Bit[7:4] int setting
*/
isc |= SUP_UART_ISC_RXM;
writel(isc, port->membase + SUP_UART_ISC);
spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
static void sunplus_shutdown(struct uart_port *port)
{
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
/* isc define Bit[7:4] int setting, Bit[3:0] int status
* isc register will clean Bit[3:0] int status after read
* only do a write to Bit[7:4] int setting
*/
writel(0, port->membase + SUP_UART_ISC); /* disable all interrupt */
spin_unlock_irqrestore(&port->lock, flags);
free_irq(port->irq, port);
}
static void sunplus_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *oldtermios)
{
u32 ext, div, div_l, div_h, baud, lcr;
u32 clk = port->uartclk;
unsigned long flags;
baud = uart_get_baud_rate(port, termios, oldtermios, 0, port->uartclk / 16);
/* baud rate = uartclk / ((16 * divisor + 1) + divisor_ext) */
clk += baud >> 1;
div = clk / baud;
ext = div & 0x0F;
div = (div >> 4) - 1;
div_l = (div & 0xFF) | (ext << 12);
div_h = div >> 8;
switch (termios->c_cflag & CSIZE) {
case CS5:
lcr = UART_LCR_WLEN5;
break;
case CS6:
lcr = UART_LCR_WLEN6;
break;
case CS7:
lcr = UART_LCR_WLEN7;
break;
default:
lcr = UART_LCR_WLEN8;
break;
}
if (termios->c_cflag & CSTOPB)
lcr |= UART_LCR_STOP;
if (termios->c_cflag & PARENB) {
lcr |= UART_LCR_PARITY;
if (!(termios->c_cflag & PARODD))
lcr |= UART_LCR_EPAR;
}
spin_lock_irqsave(&port->lock, flags);
uart_update_timeout(port, termios->c_cflag, baud);
port->read_status_mask = 0;
if (termios->c_iflag & INPCK)
port->read_status_mask |= SUP_UART_LSR_PE | SUP_UART_LSR_FE;
if (termios->c_iflag & (BRKINT | PARMRK))
port->read_status_mask |= SUP_UART_LSR_BC;
/* Characters to ignore */
port->ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= SUP_UART_LSR_FE | SUP_UART_LSR_PE;
if (termios->c_iflag & IGNBRK) {
port->ignore_status_mask |= SUP_UART_LSR_BC;
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= SUP_UART_LSR_OE;
}
/* Ignore all characters if CREAD is not set */
if ((termios->c_cflag & CREAD) == 0) {
port->ignore_status_mask |= SUP_DUMMY_READ;
/* flush rx data FIFO */
writel(0, port->membase + SUP_UART_RX_RESIDUE);
}
/* Settings for baud rate divisor and lcr */
writel(div_h, port->membase + SUP_UART_DIV_H);
writel(div_l, port->membase + SUP_UART_DIV_L);
writel(lcr, port->membase + SUP_UART_LCR);
spin_unlock_irqrestore(&port->lock, flags);
}
static void sunplus_set_ldisc(struct uart_port *port, struct ktermios *termios)
{
int new = termios->c_line;
if (new == N_PPS)
port->flags |= UPF_HARDPPS_CD;
else
port->flags &= ~UPF_HARDPPS_CD;
}
static const char *sunplus_type(struct uart_port *port)
{
return port->type == PORT_SUNPLUS ? "sunplus_uart" : NULL;
}
static void sunplus_config_port(struct uart_port *port, int type)
{
if (type & UART_CONFIG_TYPE)
port->type = PORT_SUNPLUS;
}
static int sunplus_verify_port(struct uart_port *port, struct serial_struct *ser)
{
if (ser->type != PORT_UNKNOWN && ser->type != PORT_SUNPLUS)
return -EINVAL;
return 0;
}
#if defined(CONFIG_SERIAL_SUNPLUS_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
static void wait_for_xmitr(struct uart_port *port)
{
unsigned int val;
int ret;
/* Wait while FIFO is full or timeout */
ret = readl_poll_timeout_atomic(port->membase + SUP_UART_LSR, val,
(val & SUP_UART_LSR_TX), 1, 10000);
if (ret == -ETIMEDOUT) {
dev_err(port->dev, "Timeout waiting while UART TX FULL\n");
return;
}
}
#endif
#ifdef CONFIG_CONSOLE_POLL
static void sunplus_poll_put_char(struct uart_port *port, unsigned char data)
{
wait_for_xmitr(port);
sp_uart_put_char(port, data);
}
static int sunplus_poll_get_char(struct uart_port *port)
{
unsigned int lsr = readl(port->membase + SUP_UART_LSR);
if (!(lsr & SUP_UART_LSR_RX))
return NO_POLL_CHAR;
return readl(port->membase + SUP_UART_DATA);
}
#endif
static const struct uart_ops sunplus_uart_ops = {
.tx_empty = sunplus_tx_empty,
.set_mctrl = sunplus_set_mctrl,
.get_mctrl = sunplus_get_mctrl,
.stop_tx = sunplus_stop_tx,
.start_tx = sunplus_start_tx,
.stop_rx = sunplus_stop_rx,
.break_ctl = sunplus_break_ctl,
.startup = sunplus_startup,
.shutdown = sunplus_shutdown,
.set_termios = sunplus_set_termios,
.set_ldisc = sunplus_set_ldisc,
.type = sunplus_type,
.config_port = sunplus_config_port,
.verify_port = sunplus_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_put_char = sunplus_poll_put_char,
.poll_get_char = sunplus_poll_get_char,
#endif
};
#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE
struct sunplus_uart_port *sunplus_console_ports[SUP_UART_NR];
static void sunplus_uart_console_putchar(struct uart_port *port,
unsigned char ch)
{
wait_for_xmitr(port);
sp_uart_put_char(port, ch);
}
static void sunplus_console_write(struct console *co,
const char *s,
unsigned int count)
{
unsigned long flags;
int locked = 1;
local_irq_save(flags);
if (sunplus_console_ports[co->index]->port.sysrq)
locked = 0;
else if (oops_in_progress)
locked = spin_trylock(&sunplus_console_ports[co->index]->port.lock);
else
spin_lock(&sunplus_console_ports[co->index]->port.lock);
uart_console_write(&sunplus_console_ports[co->index]->port, s, count,
sunplus_uart_console_putchar);
if (locked)
spin_unlock(&sunplus_console_ports[co->index]->port.lock);
local_irq_restore(flags);
}
static int __init sunplus_console_setup(struct console *co, char *options)
{
struct sunplus_uart_port *sup;
int baud = 115200;
int bits = 8;
int parity = 'n';
int flow = 'n';
if (co->index < 0 || co->index >= SUP_UART_NR)
return -EINVAL;
sup = sunplus_console_ports[co->index];
if (!sup)
return -ENODEV;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
return uart_set_options(&sup->port, co, baud, parity, bits, flow);
}
static struct uart_driver sunplus_uart_driver;
static struct console sunplus_uart_console = {
.name = "ttySUP",
.write = sunplus_console_write,
.device = uart_console_device,
.setup = sunplus_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &sunplus_uart_driver
};
#define SERIAL_SUNPLUS_CONSOLE (&sunplus_uart_console)
#else
#define SERIAL_SUNPLUS_CONSOLE NULL
#endif
static struct uart_driver sunplus_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "sunplus_uart",
.dev_name = "ttySUP",
.major = TTY_MAJOR,
.minor = 64,
.nr = SUP_UART_NR,
.cons = SERIAL_SUNPLUS_CONSOLE,
};
static void sunplus_uart_disable_unprepare(void *data)
{
clk_disable_unprepare(data);
}
static void sunplus_uart_reset_control_assert(void *data)
{
reset_control_assert(data);
}
static int sunplus_uart_probe(struct platform_device *pdev)
{
struct sunplus_uart_port *sup;
struct uart_port *port;
struct resource *res;
int ret, irq;
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
if (pdev->id < 0 || pdev->id >= SUP_UART_NR)
return -EINVAL;
sup = devm_kzalloc(&pdev->dev, sizeof(*sup), GFP_KERNEL);
if (!sup)
return -ENOMEM;
sup->clk = devm_clk_get_optional(&pdev->dev, NULL);
if (IS_ERR(sup->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(sup->clk), "clk not found\n");
ret = clk_prepare_enable(sup->clk);
if (ret)
return ret;
ret = devm_add_action_or_reset(&pdev->dev, sunplus_uart_disable_unprepare, sup->clk);
if (ret)
return ret;
sup->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(sup->rstc))
return dev_err_probe(&pdev->dev, PTR_ERR(sup->rstc), "rstc not found\n");
port = &sup->port;
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(port->membase))
return dev_err_probe(&pdev->dev, PTR_ERR(port->membase), "membase not found\n");
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
port->mapbase = res->start;
port->uartclk = clk_get_rate(sup->clk);
port->line = pdev->id;
port->irq = irq;
port->dev = &pdev->dev;
port->iotype = UPIO_MEM;
port->ops = &sunplus_uart_ops;
port->flags = UPF_BOOT_AUTOCONF;
port->fifosize = 128;
ret = reset_control_deassert(sup->rstc);
if (ret)
return ret;
ret = devm_add_action_or_reset(&pdev->dev, sunplus_uart_reset_control_assert, sup->rstc);
if (ret)
return ret;
#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE
sunplus_console_ports[sup->port.line] = sup;
#endif
platform_set_drvdata(pdev, &sup->port);
ret = uart_add_one_port(&sunplus_uart_driver, &sup->port);
#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE
if (ret)
sunplus_console_ports[sup->port.line] = NULL;
#endif
return ret;
}
static int sunplus_uart_remove(struct platform_device *pdev)
{
struct sunplus_uart_port *sup = platform_get_drvdata(pdev);
uart_remove_one_port(&sunplus_uart_driver, &sup->port);
return 0;
}
static int __maybe_unused sunplus_uart_suspend(struct device *dev)
{
struct sunplus_uart_port *sup = dev_get_drvdata(dev);
if (!uart_console(&sup->port))
uart_suspend_port(&sunplus_uart_driver, &sup->port);
return 0;
}
static int __maybe_unused sunplus_uart_resume(struct device *dev)
{
struct sunplus_uart_port *sup = dev_get_drvdata(dev);
if (!uart_console(&sup->port))
uart_resume_port(&sunplus_uart_driver, &sup->port);
return 0;
}
static const struct dev_pm_ops sunplus_uart_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(sunplus_uart_suspend, sunplus_uart_resume)
};
static const struct of_device_id sp_uart_of_match[] = {
{ .compatible = "sunplus,sp7021-uart" },
{}
};
MODULE_DEVICE_TABLE(of, sp_uart_of_match);
static struct platform_driver sunplus_uart_platform_driver = {
.probe = sunplus_uart_probe,
.remove = sunplus_uart_remove,
.driver = {
.name = "sunplus_uart",
.of_match_table = sp_uart_of_match,
.pm = &sunplus_uart_pm_ops,
}
};
static int __init sunplus_uart_init(void)
{
int ret;
ret = uart_register_driver(&sunplus_uart_driver);
if (ret)
return ret;
ret = platform_driver_register(&sunplus_uart_platform_driver);
if (ret)
uart_unregister_driver(&sunplus_uart_driver);
return ret;
}
module_init(sunplus_uart_init);
static void __exit sunplus_uart_exit(void)
{
platform_driver_unregister(&sunplus_uart_platform_driver);
uart_unregister_driver(&sunplus_uart_driver);
}
module_exit(sunplus_uart_exit);
#ifdef CONFIG_SERIAL_EARLYCON
static void sunplus_uart_putc(struct uart_port *port, unsigned char c)
{
unsigned int val;
int ret;
ret = readl_poll_timeout_atomic(port->membase + SUP_UART_LSR, val,
(val & UART_LSR_TEMT), 1, 10000);
if (ret)
return;
writel(c, port->membase + SUP_UART_DATA);
}
static void sunplus_uart_early_write(struct console *con, const char *s, unsigned int n)
{
struct earlycon_device *dev = con->data;
uart_console_write(&dev->port, s, n, sunplus_uart_putc);
}
static int __init
sunplus_uart_early_setup(struct earlycon_device *dev, const char *opt)
{
if (!(dev->port.membase || dev->port.iobase))
return -ENODEV;
dev->con->write = sunplus_uart_early_write;
return 0;
}
OF_EARLYCON_DECLARE(sunplus_uart, "sunplus,sp7021-uart", sunplus_uart_early_setup);
#endif
MODULE_DESCRIPTION("Sunplus UART driver");
MODULE_AUTHOR("Hammer Hsieh <hammerh0314@gmail.com>");
MODULE_LICENSE("GPL v2");

View File

@ -846,7 +846,7 @@ static struct uart_sunsab_port *sunsab_ports;
#ifdef CONFIG_SERIAL_SUNSAB_CONSOLE
static void sunsab_console_putchar(struct uart_port *port, int c)
static void sunsab_console_putchar(struct uart_port *port, unsigned char c)
{
struct uart_sunsab_port *up =
container_of(port, struct uart_sunsab_port, port);

View File

@ -1281,7 +1281,7 @@ static void wait_for_xmitr(struct uart_sunsu_port *up)
}
}
static void sunsu_console_putchar(struct uart_port *port, int ch)
static void sunsu_console_putchar(struct uart_port *port, unsigned char ch)
{
struct uart_sunsu_port *up =
container_of(port, struct uart_sunsu_port, port);

View File

@ -100,7 +100,7 @@ struct uart_sunzilog_port {
#endif
};
static void sunzilog_putchar(struct uart_port *port, int ch);
static void sunzilog_putchar(struct uart_port *port, unsigned char ch);
#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase))
#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
@ -1125,7 +1125,7 @@ static void sunzilog_free_tables(void)
#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
static void __maybe_unused sunzilog_putchar(struct uart_port *port, int ch)
static void __maybe_unused sunzilog_putchar(struct uart_port *port, unsigned char ch)
{
struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
int loops = ZS_PUT_CHAR_MAX_DELAY;

View File

@ -482,7 +482,7 @@ static void ulite_console_wait_tx(struct uart_port *port)
"timeout waiting for TX buffer empty\n");
}
static void ulite_console_putchar(struct uart_port *port, int ch)
static void ulite_console_putchar(struct uart_port *port, unsigned char ch)
{
ulite_console_wait_tx(port);
uart_out32(ch, ULITE_TX, port);
@ -558,7 +558,7 @@ static struct console ulite_console = {
.data = &ulite_uart_driver,
};
static void early_uartlite_putc(struct uart_port *port, int c)
static void early_uartlite_putc(struct uart_port *port, unsigned char c)
{
/*
* Limit how many times we'll spin waiting for TX FIFO status.

View File

@ -504,20 +504,7 @@ static void siu_set_termios(struct uart_port *port, struct ktermios *new,
unsigned long flags;
c_cflag = new->c_cflag;
switch (c_cflag & CSIZE) {
case CS5:
lcr = UART_LCR_WLEN5;
break;
case CS6:
lcr = UART_LCR_WLEN6;
break;
case CS7:
lcr = UART_LCR_WLEN7;
break;
default:
lcr = UART_LCR_WLEN8;
break;
}
lcr = UART_LCR_WLEN(tty_get_char_size(c_cflag));
if (c_cflag & CSTOPB)
lcr |= UART_LCR_STOP;
@ -743,7 +730,7 @@ static void wait_for_xmitr(struct uart_port *port)
}
}
static void siu_console_putchar(struct uart_port *port, int ch)
static void siu_console_putchar(struct uart_port *port, unsigned char ch)
{
wait_for_xmitr(port);
siu_write(port, UART_TX, ch);

View File

@ -484,7 +484,7 @@ static void wait_for_xmitr(struct uart_port *port)
} while (status & 0x10);
}
static void vt8500_console_putchar(struct uart_port *port, int c)
static void vt8500_console_putchar(struct uart_port *port, unsigned char c)
{
wait_for_xmitr(port);
writeb(c, port->membase + VT8500_TXFIFO);

View File

@ -1142,7 +1142,7 @@ static struct uart_driver cdns_uart_uart_driver;
* @port: Handle to the uart port structure
* @ch: Character to be written
*/
static void cdns_uart_console_putchar(struct uart_port *port, int ch)
static void cdns_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
while (readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)
cpu_relax();

Some files were not shown because too many files have changed in this diff Show More