aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-lpuart.yaml4
-rw-r--r--Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml86
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,em-uart.yaml37
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,hscif.yaml9
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,scif.yaml2
-rw-r--r--Documentation/devicetree/bindings/serial/rs485.yaml5
-rw-r--r--Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml5
-rw-r--r--Documentation/driver-api/index.rst1
-rw-r--r--Documentation/driver-api/serial/driver.rst2
-rw-r--r--Documentation/driver-api/serial/index.rst2
-rw-r--r--Documentation/driver-api/serial/n_gsm.rst159
-rw-r--r--Documentation/driver-api/tty/index.rst (renamed from Documentation/tty/index.rst)22
-rw-r--r--Documentation/driver-api/tty/moxa-smartio.rst (renamed from Documentation/driver-api/serial/moxa-smartio.rst)0
-rw-r--r--Documentation/driver-api/tty/n_gsm.rst153
-rw-r--r--Documentation/driver-api/tty/n_tty.rst (renamed from Documentation/tty/n_tty.rst)0
-rw-r--r--Documentation/driver-api/tty/tty_buffer.rst (renamed from Documentation/tty/tty_buffer.rst)0
-rw-r--r--Documentation/driver-api/tty/tty_driver.rst (renamed from Documentation/tty/tty_driver.rst)0
-rw-r--r--Documentation/driver-api/tty/tty_internals.rst (renamed from Documentation/tty/tty_internals.rst)0
-rw-r--r--Documentation/driver-api/tty/tty_ldisc.rst (renamed from Documentation/tty/tty_ldisc.rst)0
-rw-r--r--Documentation/driver-api/tty/tty_port.rst (renamed from Documentation/tty/tty_port.rst)0
-rw-r--r--Documentation/driver-api/tty/tty_struct.rst (renamed from Documentation/tty/tty_struct.rst)0
-rw-r--r--Documentation/firmware-guide/acpi/enumeration.rst25
-rw-r--r--Documentation/index.rst1
-rw-r--r--Documentation/misc-devices/index.rst1
-rw-r--r--Documentation/misc-devices/oxsemi-tornado.rst131
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/alpha/include/uapi/asm/termbits.h214
-rw-r--r--arch/mips/include/uapi/asm/termbits.h249
-rw-r--r--arch/parisc/include/uapi/asm/termbits.h241
-rw-r--r--arch/powerpc/include/uapi/asm/termbits.h182
-rw-r--r--arch/sparc/include/uapi/asm/termbits.h223
-rw-r--r--drivers/char/Kconfig3
-rw-r--r--drivers/char/pcmcia/synclink_cs.c8
-rw-r--r--drivers/char/ttyprintk.c16
-rw-r--r--drivers/tty/amiserial.c2
-rw-r--r--drivers/tty/goldfish.c2
-rw-r--r--drivers/tty/hvc/Kconfig19
-rw-r--r--drivers/tty/hvc/hvc_dcc.c194
-rw-r--r--drivers/tty/hvc/hvc_opal.c6
-rw-r--r--drivers/tty/hvc/hvc_vio.c2
-rw-r--r--drivers/tty/hvc/hvcs.c5
-rw-r--r--drivers/tty/hvc/hvsi.c2
-rw-r--r--drivers/tty/mxser.c5
-rw-r--r--drivers/tty/n_gsm.c37
-rw-r--r--drivers/tty/n_tty.c73
-rw-r--r--drivers/tty/serial/8250/8250.h41
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c2
-rw-r--r--drivers/tty/serial/8250/8250_core.c1
-rw-r--r--drivers/tty/serial/8250/8250_dma.c7
-rw-r--r--drivers/tty/serial/8250/8250_dw.c229
-rw-r--r--drivers/tty/serial/8250/8250_dwlib.c116
-rw-r--r--drivers/tty/serial/8250/8250_dwlib.h51
-rw-r--r--drivers/tty/serial/8250/8250_fintek.c8
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c7
-rw-r--r--drivers/tty/serial/8250/8250_of.c2
-rw-r--r--drivers/tty/serial/8250/8250_pci.c480
-rw-r--r--drivers/tty/serial/8250/8250_port.c140
-rw-r--r--drivers/tty/serial/8250/8250_pxa.c1
-rw-r--r--drivers/tty/serial/8250/Kconfig2
-rw-r--r--drivers/tty/serial/Kconfig9
-rw-r--r--drivers/tty/serial/altera_jtaguart.c6
-rw-r--r--drivers/tty/serial/amba-pl011.c48
-rw-r--r--drivers/tty/serial/amba-pl011.h35
-rw-r--r--drivers/tty/serial/atmel_serial.c4
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart.h2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c1
-rw-r--r--drivers/tty/serial/digicolor-usart.c2
-rw-r--r--drivers/tty/serial/fsl_lpuart.c66
-rw-r--r--drivers/tty/serial/icom.c538
-rw-r--r--drivers/tty/serial/icom.h274
-rw-r--r--drivers/tty/serial/imx.c2
-rw-r--r--drivers/tty/serial/jsm/jsm_cls.c8
-rw-r--r--drivers/tty/serial/jsm/jsm_neo.c8
-rw-r--r--drivers/tty/serial/max310x.c1
-rw-r--r--drivers/tty/serial/men_z135_uart.c1
-rw-r--r--drivers/tty/serial/meson_uart.c40
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c5
-rw-r--r--drivers/tty/serial/msm_serial.c5
-rw-r--r--drivers/tty/serial/omap-serial.c13
-rw-r--r--drivers/tty/serial/owl-uart.c7
-rw-r--r--drivers/tty/serial/pch_uart.c77
-rw-r--r--drivers/tty/serial/pic32_uart.c159
-rw-r--r--drivers/tty/serial/pic32_uart.h125
-rw-r--r--drivers/tty/serial/pmac_zilog.c69
-rw-r--r--drivers/tty/serial/pmac_zilog.h11
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c58
-rw-r--r--drivers/tty/serial/rda-uart.c2
-rw-r--r--drivers/tty/serial/sa1100.c4
-rw-r--r--drivers/tty/serial/samsung_tty.c13
-rw-r--r--drivers/tty/serial/sc16is7xx.c10
-rw-r--r--drivers/tty/serial/serial_core.c89
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c6
-rw-r--r--drivers/tty/serial/sifive.c20
-rw-r--r--drivers/tty/serial/st-asc.c4
-rw-r--r--drivers/tty/serial/stm32-usart.c225
-rw-r--r--drivers/tty/serial/stm32-usart.h3
-rw-r--r--drivers/tty/serial/sunplus-uart.c2
-rw-r--r--drivers/tty/serial/sunsu.c2
-rw-r--r--drivers/tty/serial/uartlite.c3
-rw-r--r--drivers/tty/serial/xilinx_uartps.c46
-rw-r--r--drivers/tty/serial/zs.c2
-rw-r--r--drivers/tty/synclink_gt.c2
-rw-r--r--drivers/tty/sysrq.c27
-rw-r--r--drivers/tty/tty_baudrate.c35
-rw-r--r--drivers/tty/tty_ioctl.c2
-rw-r--r--drivers/usb/class/cdc-acm.h8
-rw-r--r--drivers/usb/serial/ark3116.c3
-rw-r--r--drivers/usb/serial/whiteheat.c4
-rw-r--r--include/linux/serial_core.h1
-rw-r--r--include/linux/serial_s3c.h3
-rw-r--r--include/uapi/asm-generic/termbits-common.h65
-rw-r--r--include/uapi/asm-generic/termbits.h239
114 files changed, 3164 insertions, 2451 deletions
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
index ff364bd0fbac..30eaa62e1aed 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
@@ -23,7 +23,9 @@ properties:
- fsl,imx8qxp-lpuart
- fsl,imxrt1050-lpuart
- items:
- - const: fsl,imx8ulp-lpuart
+ - enum:
+ - fsl,imx93-lpuart
+ - fsl,imx8ulp-lpuart
- const: fsl,imx7ulp-lpuart
- items:
- enum:
diff --git a/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml b/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml
new file mode 100644
index 000000000000..05a6999808d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/serial/qcom,serial-geni-qcom.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Qualcomm Geni based QUP UART interface
+
+maintainers:
+ - Andy Gross <agross@kernel.org>
+ - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+allOf:
+ - $ref: /schemas/serial/serial.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,geni-uart
+ - qcom,geni-debug-uart
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: se
+
+ interconnects:
+ maxItems: 2
+
+ interconnect-names:
+ items:
+ - const: qup-core
+ - const: qup-config
+
+ interrupts:
+ minItems: 1
+ items:
+ - description: UART core irq
+ - description: Wakeup irq (RX GPIO)
+
+ operating-points-v2: true
+
+ pinctrl-0: true
+ pinctrl-1: true
+
+ pinctrl-names:
+ minItems: 1
+ items:
+ - const: default
+ - const: sleep
+
+ power-domains:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - interrupts
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/qcom,gcc-sc7180.h>
+ #include <dt-bindings/interconnect/qcom,sc7180.h>
+
+ serial@a88000 {
+ compatible = "qcom,geni-uart";
+ reg = <0xa88000 0x7000>;
+ interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ pinctrl-0 = <&qup_uart0_default>;
+ pinctrl-names = "default";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>;
+ interconnect-names = "qup-core", "qup-config";
+ };
+...
diff --git a/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml b/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml
index e98ec48fee46..b25aca733b72 100644
--- a/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml
@@ -9,12 +9,16 @@ title: Renesas EMMA Mobile UART Interface
maintainers:
- Magnus Damm <magnus.damm@gmail.com>
-allOf:
- - $ref: serial.yaml#
-
properties:
compatible:
- const: renesas,em-uart
+ oneOf:
+ - items:
+ - enum:
+ - renesas,r9a09g011-uart # RZ/V2M
+ - const: renesas,em-uart # generic EMMA Mobile compatible UART
+
+ - items:
+ - const: renesas,em-uart # generic EMMA Mobile compatible UART
reg:
maxItems: 1
@@ -23,10 +27,31 @@ properties:
maxItems: 1
clocks:
- maxItems: 1
+ minItems: 1
+ items:
+ - description: UART functional clock
+ - description: Internal clock to access the registers
clock-names:
- const: sclk
+ minItems: 1
+ items:
+ - const: sclk
+ - const: pclk
+
+allOf:
+ - $ref: serial.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,r9a09g011-uart
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ clock-names:
+ minItems: 2
required:
- compatible
diff --git a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
index ee9804cd49bb..87180d95cd4c 100644
--- a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
@@ -51,10 +51,16 @@ properties:
- renesas,hscif-r8a77980 # R-Car V3H
- renesas,hscif-r8a77990 # R-Car E3
- renesas,hscif-r8a77995 # R-Car D3
- - renesas,hscif-r8a779a0 # R-Car V3U
- const: renesas,rcar-gen3-hscif # R-Car Gen3 and RZ/G2
- const: renesas,hscif # generic HSCIF compatible UART
+ - items:
+ - enum:
+ - renesas,hscif-r8a779a0 # R-Car V3U
+ - renesas,hscif-r8a779g0 # R-Car V4H
+ - const: renesas,rcar-gen4-hscif # R-Car Gen4
+ - const: renesas,hscif # generic HSCIF compatible UART
+
reg:
maxItems: 1
@@ -113,6 +119,7 @@ if:
enum:
- renesas,rcar-gen2-hscif
- renesas,rcar-gen3-hscif
+ - renesas,rcar-gen4-hscif
then:
required:
- resets
diff --git a/Documentation/devicetree/bindings/serial/renesas,scif.yaml b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
index 5d37f8f189fb..90fe45265fbc 100644
--- a/Documentation/devicetree/bindings/serial/renesas,scif.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
@@ -60,12 +60,12 @@ properties:
- renesas,scif-r8a77980 # R-Car V3H
- renesas,scif-r8a77990 # R-Car E3
- renesas,scif-r8a77995 # R-Car D3
- - renesas,scif-r8a779a0 # R-Car V3U
- const: renesas,rcar-gen3-scif # R-Car Gen3 and RZ/G2
- const: renesas,scif # generic SCIF compatible UART
- items:
- enum:
+ - renesas,scif-r8a779a0 # R-Car V3U
- renesas,scif-r8a779f0 # R-Car S4-8
- const: renesas,rcar-gen4-scif # R-Car Gen4
- const: renesas,scif # generic SCIF compatible UART
diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml
index 0c9fa694f85c..f2c9c9fe6aa7 100644
--- a/Documentation/devicetree/bindings/serial/rs485.yaml
+++ b/Documentation/devicetree/bindings/serial/rs485.yaml
@@ -33,6 +33,11 @@ properties:
description: drive RTS low when sending (default is high).
$ref: /schemas/types.yaml#/definitions/flag
+ rs485-rx-active-high:
+ description: Polarity of receiver enable signal (when separate from RTS).
+ True indicates active high (default is low).
+ $ref: /schemas/types.yaml#/definitions/flag
+
linux,rs485-enabled-at-boot-time:
description: enables the rs485 feature at boot time. It can be disabled
later with proper ioctl.
diff --git a/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml b/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml
index d490c7c4b967..3d01cc355778 100644
--- a/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml
@@ -20,7 +20,10 @@ properties:
maxItems: 1
clocks:
- minItems: 1
+ maxItems: 1
+
+ resets:
+ maxItems: 1
auto-flow-control:
description: enable automatic flow control support.
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index a7b0223e2886..d76a60d95b58 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -101,6 +101,7 @@ available subsections can be seen below.
surface_aggregator/index
switchtec
sync_file
+ tty/index
vfio-mediated-device
vfio
vfio-pci-device-specific-driver-acceptance
diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst
index 06ec04ba086f..7ef83fd3917b 100644
--- a/Documentation/driver-api/serial/driver.rst
+++ b/Documentation/driver-api/serial/driver.rst
@@ -311,7 +311,7 @@ hardware.
This call must not sleep
set_ldisc(port,termios)
- Notifier for discipline change. See Documentation/tty/tty_ldisc.rst.
+ Notifier for discipline change. See ../tty/tty_ldisc.rst.
Locking: caller holds tty_port->mutex
diff --git a/Documentation/driver-api/serial/index.rst b/Documentation/driver-api/serial/index.rst
index 7eb21a695fc3..03a55b987a1d 100644
--- a/Documentation/driver-api/serial/index.rst
+++ b/Documentation/driver-api/serial/index.rst
@@ -16,8 +16,6 @@ Serial drivers
.. toctree::
:maxdepth: 1
- moxa-smartio
- n_gsm
serial-iso7816
serial-rs485
diff --git a/Documentation/driver-api/serial/n_gsm.rst b/Documentation/driver-api/serial/n_gsm.rst
deleted file mode 100644
index 49956509ad73..000000000000
--- a/Documentation/driver-api/serial/n_gsm.rst
+++ /dev/null
@@ -1,159 +0,0 @@
-==============================
-GSM 0710 tty multiplexor HOWTO
-==============================
-
-This line discipline implements the GSM 07.10 multiplexing protocol
-detailed in the following 3GPP document:
-
- https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
-
-This document give some hints on how to use this driver with GPRS and 3G
-modems connected to a physical serial port.
-
-How to use it
--------------
-1. config initiator
-^^^^^^^^^^^^^^^^^^^^^
-
-1.1 initialize the modem in 0710 mux mode (usually AT+CMUX= command) through
- its serial port. Depending on the modem used, you can pass more or less
- parameters to this command.
-
-1.2 switch the serial line to using the n_gsm line discipline by using
- TIOCSETD ioctl.
-
-1.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl.
-
-1.4 obtain base gsmtty number for the used serial port.
-
-Major parts of the initialization program :
-(a good starting point is util-linux-ng/sys-utils/ldattach.c)::
-
- #include <stdio.h>
- #include <stdint.h>
- #include <linux/gsmmux.h>
- #include <linux/tty.h>
- #define DEFAULT_SPEED B115200
- #define SERIAL_PORT /dev/ttyS0
-
- int ldisc = N_GSM0710;
- struct gsm_config c;
- struct termios configuration;
- uint32_t first;
-
- /* open the serial port connected to the modem */
- fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
-
- /* configure the serial port : speed, flow control ... */
-
- /* send the AT commands to switch the modem to CMUX mode
- and check that it's successful (should return OK) */
- write(fd, "AT+CMUX=0\r", 10);
-
- /* experience showed that some modems need some time before
- being able to answer to the first MUX packet so a delay
- may be needed here in some case */
- sleep(3);
-
- /* use n_gsm line discipline */
- ioctl(fd, TIOCSETD, &ldisc);
-
- /* get n_gsm configuration */
- ioctl(fd, GSMIOC_GETCONF, &c);
- /* we are initiator and need encoding 0 (basic) */
- c.initiator = 1;
- c.encapsulation = 0;
- /* our modem defaults to a maximum size of 127 bytes */
- c.mru = 127;
- c.mtu = 127;
- /* set the new configuration */
- ioctl(fd, GSMIOC_SETCONF, &c);
- /* get first gsmtty device node */
- ioctl(fd, GSMIOC_GETFIRST, &first);
- printf("first muxed line: /dev/gsmtty%i\n", first);
-
- /* and wait for ever to keep the line discipline enabled */
- daemon(0,0);
- pause();
-
-1.5 use these devices as plain serial ports.
-
- for example, it's possible:
-
- - and to use gnokii to send / receive SMS on ttygsm1
- - to use ppp to establish a datalink on ttygsm2
-
-1.6 first close all virtual ports before closing the physical port.
-
- Note that after closing the physical port the modem is still in multiplexing
- mode. This may prevent a successful re-opening of the port later. To avoid
- this situation either reset the modem if your hardware allows that or send
- a disconnect command frame manually before initializing the multiplexing mode
- for the second time. The byte sequence for the disconnect command frame is::
-
- 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9.
-
-2. config requester
-^^^^^^^^^^^^^^^^^^^^^
-
-2.1 receive string "AT+CMUX= command" through its serial port,initialize
- mux mode config
-
-2.2 switch the serial line to using the n_gsm line discipline by using
- TIOCSETD ioctl.
-
-2.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl.
-
-2.4 obtain base gsmtty number for the used serial port::
-
- #include <stdio.h>
- #include <stdint.h>
- #include <linux/gsmmux.h>
- #include <linux/tty.h>
- #define DEFAULT_SPEED B115200
- #define SERIAL_PORT /dev/ttyS0
-
- int ldisc = N_GSM0710;
- struct gsm_config c;
- struct termios configuration;
- uint32_t first;
-
- /* open the serial port */
- fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
-
- /* configure the serial port : speed, flow control ... */
-
- /* get serial data and check "AT+CMUX=command" parameter ... */
-
- /* use n_gsm line discipline */
- ioctl(fd, TIOCSETD, &ldisc);
-
- /* get n_gsm configuration */
- ioctl(fd, GSMIOC_GETCONF, &c);
- /* we are requester and need encoding 0 (basic) */
- c.initiator = 0;
- c.encapsulation = 0;
- /* our modem defaults to a maximum size of 127 bytes */
- c.mru = 127;
- c.mtu = 127;
- /* set the new configuration */
- ioctl(fd, GSMIOC_SETCONF, &c);
- /* get first gsmtty device node */
- ioctl(fd, GSMIOC_GETFIRST, &first);
- printf("first muxed line: /dev/gsmtty%i\n", first);
-
- /* and wait for ever to keep the line discipline enabled */
- daemon(0,0);
- pause();
-
-Additional Documentation
-------------------------
-More practical details on the protocol and how it's supported by industrial
-modems can be found in the following documents :
-
-- http://www.telit.com/module/infopool/download.php?id=616
-- http://www.u-blox.com/images/downloads/Product_Docs/LEON-G100-G200-MuxImplementation_ApplicationNote_%28GSM%20G1-CS-10002%29.pdf
-- http://www.sierrawireless.com/Support/Downloads/AirPrime/WMP_Series/~/media/Support_Downloads/AirPrime/Application_notes/CMUX_Feature_Application_Note-Rev004.ashx
-- http://wm.sim.com/sim/News/photo/2010721161442.pdf
-
-11-03-08 - Eric Bénard - <eric@eukrea.com>
diff --git a/Documentation/tty/index.rst b/Documentation/driver-api/tty/index.rst
index 21ea0cb21e55..2d32606a4278 100644
--- a/Documentation/tty/index.rst
+++ b/Documentation/driver-api/tty/index.rst
@@ -36,18 +36,16 @@ In-detail description of the named TTY structures is in separate documents:
tty_struct
tty_ldisc
tty_buffer
- n_tty
tty_internals
Writing TTY Driver
==================
Before one starts writing a TTY driver, they must consider
-:doc:`Serial <../driver-api/serial/driver>` and :doc:`USB Serial
-<../usb/usb-serial>` layers
-first. Drivers for serial devices can often use one of these specific layers to
-implement a serial driver. Only special devices should be handled directly by
-the TTY Layer. If you are about to write such a driver, read on.
+:doc:`Serial <../serial/driver>` and :doc:`USB Serial <../../usb/usb-serial>`
+layers first. Drivers for serial devices can often use one of these specific
+layers to implement a serial driver. Only special devices should be handled
+directly by the TTY Layer. If you are about to write such a driver, read on.
A *typical* sequence a TTY driver performs is as follows:
@@ -61,3 +59,15 @@ A *typical* sequence a TTY driver performs is as follows:
Steps regarding driver, i.e. 1., 3., and 5. are described in detail in
:doc:`tty_driver`. For the other two (devices handling), look into
:doc:`tty_port`.
+
+Other Documentation
+===================
+
+Miscellaneous documentation can be further found in these documents:
+
+.. toctree::
+ :maxdepth: 2
+
+ moxa-smartio
+ n_gsm
+ n_tty
diff --git a/Documentation/driver-api/serial/moxa-smartio.rst b/Documentation/driver-api/tty/moxa-smartio.rst
index af25bc5cc3e6..af25bc5cc3e6 100644
--- a/Documentation/driver-api/serial/moxa-smartio.rst
+++ b/Documentation/driver-api/tty/moxa-smartio.rst
diff --git a/Documentation/driver-api/tty/n_gsm.rst b/Documentation/driver-api/tty/n_gsm.rst
new file mode 100644
index 000000000000..35d7381515b0
--- /dev/null
+++ b/Documentation/driver-api/tty/n_gsm.rst
@@ -0,0 +1,153 @@
+==============================
+GSM 0710 tty multiplexor HOWTO
+==============================
+
+.. contents:: :local:
+
+This line discipline implements the GSM 07.10 multiplexing protocol
+detailed in the following 3GPP document:
+
+ https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
+
+This document give some hints on how to use this driver with GPRS and 3G
+modems connected to a physical serial port.
+
+How to use it
+=============
+
+Config Initiator
+----------------
+
+#. Initialize the modem in 0710 mux mode (usually ``AT+CMUX=`` command) through
+ its serial port. Depending on the modem used, you can pass more or less
+ parameters to this command.
+
+#. Switch the serial line to using the n_gsm line discipline by using
+ ``TIOCSETD`` ioctl.
+
+#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.
+
+#. Obtain base gsmtty number for the used serial port.
+
+ Major parts of the initialization program
+ (a good starting point is util-linux-ng/sys-utils/ldattach.c)::
+
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <linux/gsmmux.h>
+ #include <linux/tty.h>
+
+ #define DEFAULT_SPEED B115200
+ #define SERIAL_PORT /dev/ttyS0
+
+ int ldisc = N_GSM0710;
+ struct gsm_config c;
+ struct termios configuration;
+ uint32_t first;
+
+ /* open the serial port connected to the modem */
+ fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
+
+ /* configure the serial port : speed, flow control ... */
+
+ /* send the AT commands to switch the modem to CMUX mode
+ and check that it's successful (should return OK) */
+ write(fd, "AT+CMUX=0\r", 10);
+
+ /* experience showed that some modems need some time before
+ being able to answer to the first MUX packet so a delay
+ may be needed here in some case */
+ sleep(3);
+
+ /* use n_gsm line discipline */
+ ioctl(fd, TIOCSETD, &ldisc);
+
+ /* get n_gsm configuration */
+ ioctl(fd, GSMIOC_GETCONF, &c);
+ /* we are initiator and need encoding 0 (basic) */
+ c.initiator = 1;
+ c.encapsulation = 0;
+ /* our modem defaults to a maximum size of 127 bytes */
+ c.mru = 127;
+ c.mtu = 127;
+ /* set the new configuration */
+ ioctl(fd, GSMIOC_SETCONF, &c);
+ /* get first gsmtty device node */
+ ioctl(fd, GSMIOC_GETFIRST, &first);
+ printf("first muxed line: /dev/gsmtty%i\n", first);
+
+ /* and wait for ever to keep the line discipline enabled */
+ daemon(0,0);
+ pause();
+
+#. Use these devices as plain serial ports.
+
+ For example, it's possible:
+
+ - to use *gnokii* to send / receive SMS on ``ttygsm1``
+ - to use *ppp* to establish a datalink on ``ttygsm2``
+
+#. First close all virtual ports before closing the physical port.
+
+ Note that after closing the physical port the modem is still in multiplexing
+ mode. This may prevent a successful re-opening of the port later. To avoid
+ this situation either reset the modem if your hardware allows that or send
+ a disconnect command frame manually before initializing the multiplexing mode
+ for the second time. The byte sequence for the disconnect command frame is::
+
+ 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9
+
+Config Requester
+----------------
+
+#. Receive ``AT+CMUX=`` command through its serial port, initialize mux mode
+ config.
+
+#. Switch the serial line to using the *n_gsm* line discipline by using
+ ``TIOCSETD`` ioctl.
+
+#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.
+
+#. Obtain base gsmtty number for the used serial port::
+
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <linux/gsmmux.h>
+ #include <linux/tty.h>
+ #define DEFAULT_SPEED B115200
+ #define SERIAL_PORT /dev/ttyS0
+
+ int ldisc = N_GSM0710;
+ struct gsm_config c;
+ struct termios configuration;
+ uint32_t first;
+
+ /* open the serial port */
+ fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
+
+ /* configure the serial port : speed, flow control ... */
+
+ /* get serial data and check "AT+CMUX=command" parameter ... */
+
+ /* use n_gsm line discipline */
+ ioctl(fd, TIOCSETD, &ldisc);
+
+ /* get n_gsm configuration */
+ ioctl(fd, GSMIOC_GETCONF, &c);
+ /* we are requester and need encoding 0 (basic) */
+ c.initiator = 0;
+ c.encapsulation = 0;
+ /* our modem defaults to a maximum size of 127 bytes */
+ c.mru = 127;
+ c.mtu = 127;
+ /* set the new configuration */
+ ioctl(fd, GSMIOC_SETCONF, &c);
+ /* get first gsmtty device node */
+ ioctl(fd, GSMIOC_GETFIRST, &first);
+ printf("first muxed line: /dev/gsmtty%i\n", first);
+
+ /* and wait for ever to keep the line discipline enabled */
+ daemon(0,0);
+ pause();
+
+11-03-08 - Eric Bénard - <eric@eukrea.com>
diff --git a/Documentation/tty/n_tty.rst b/Documentation/driver-api/tty/n_tty.rst
index 15b70faee72d..15b70faee72d 100644
--- a/Documentation/tty/n_tty.rst
+++ b/Documentation/driver-api/tty/n_tty.rst
diff --git a/Documentation/tty/tty_buffer.rst b/Documentation/driver-api/tty/tty_buffer.rst
index a39d4781e0d2..a39d4781e0d2 100644
--- a/Documentation/tty/tty_buffer.rst
+++ b/Documentation/driver-api/tty/tty_buffer.rst
diff --git a/Documentation/tty/tty_driver.rst b/Documentation/driver-api/tty/tty_driver.rst
index cc529f863406..cc529f863406 100644
--- a/Documentation/tty/tty_driver.rst
+++ b/Documentation/driver-api/tty/tty_driver.rst
diff --git a/Documentation/tty/tty_internals.rst b/Documentation/driver-api/tty/tty_internals.rst
index d0d415820300..d0d415820300 100644
--- a/Documentation/tty/tty_internals.rst
+++ b/Documentation/driver-api/tty/tty_internals.rst
diff --git a/Documentation/tty/tty_ldisc.rst b/Documentation/driver-api/tty/tty_ldisc.rst
index 5144751be804..5144751be804 100644
--- a/Documentation/tty/tty_ldisc.rst
+++ b/Documentation/driver-api/tty/tty_ldisc.rst
diff --git a/Documentation/tty/tty_port.rst b/Documentation/driver-api/tty/tty_port.rst
index 5cb90e954fcf..5cb90e954fcf 100644
--- a/Documentation/tty/tty_port.rst
+++ b/Documentation/driver-api/tty/tty_port.rst
diff --git a/Documentation/tty/tty_struct.rst b/Documentation/driver-api/tty/tty_struct.rst
index c72f5a4293b2..c72f5a4293b2 100644
--- a/Documentation/tty/tty_struct.rst
+++ b/Documentation/driver-api/tty/tty_struct.rst
diff --git a/Documentation/firmware-guide/acpi/enumeration.rst b/Documentation/firmware-guide/acpi/enumeration.rst
index 6b62425ef9cd..dbb03022b127 100644
--- a/Documentation/firmware-guide/acpi/enumeration.rst
+++ b/Documentation/firmware-guide/acpi/enumeration.rst
@@ -389,6 +389,31 @@ descriptors once the device is released.
See Documentation/firmware-guide/acpi/gpio-properties.rst for more information
about the _DSD binding related to GPIOs.
+RS-485 support
+==============
+
+ACPI _DSD (Device Specific Data) can be used to describe RS-485 capability
+of UART.
+
+For example::
+
+ Device (DEV)
+ {
+ ...
+
+ // ACPI 5.1 _DSD used for RS-485 capabilities
+ Name (_DSD, Package ()
+ {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package ()
+ {
+ Package () {"rs485-rts-active-low", Zero},
+ Package () {"rs485-rx-active-high", Zero},
+ Package () {"rs485-rx-during-tx", Zero},
+ }
+ })
+ ...
+
MFD devices
===========
diff --git a/Documentation/index.rst b/Documentation/index.rst
index 062cf88c2216..67036a05b771 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -136,7 +136,6 @@ needed).
misc-devices/index
scheduler/index
mhi/index
- tty/index
peci/index
Architecture-agnostic documentation
diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst
index 30ac58f81901..756be15a49a4 100644
--- a/Documentation/misc-devices/index.rst
+++ b/Documentation/misc-devices/index.rst
@@ -25,6 +25,7 @@ fit into other categories.
isl29003
lis3lv02d
max6875
+ oxsemi-tornado
pci-endpoint-test
spear-pcie-gadget
uacce
diff --git a/Documentation/misc-devices/oxsemi-tornado.rst b/Documentation/misc-devices/oxsemi-tornado.rst
new file mode 100644
index 000000000000..b33351bef6cf
--- /dev/null
+++ b/Documentation/misc-devices/oxsemi-tornado.rst
@@ -0,0 +1,131 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+====================================================================
+Notes on Oxford Semiconductor PCIe (Tornado) 950 serial port devices
+====================================================================
+
+Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven
+by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock.
+
+The baud rate produced by the baud generator is obtained from this input
+frequency by dividing it by the clock prescaler, which can be set to any
+value from 1 to 63.875 in increments of 0.125, and then the usual 16-bit
+divisor is used as with the original 8250, to divide the frequency by a
+value from 1 to 65535. Finally a programmable oversampling rate is used
+that can take any value from 4 to 16 to divide the frequency further and
+determine the actual baud rate used. Baud rates from 15625000bps down
+to 0.933bps can be obtained this way.
+
+By default the oversampling rate is set to 16 and the clock prescaler is
+set to 33.875, meaning that the frequency to be used as the reference
+for the usual 16-bit divisor is 115313.653, which is close enough to the
+frequency of 115200 used by the original 8250 for the same values to be
+used for the divisor to obtain the requested baud rates by software that
+is unaware of the extra clock controls available.
+
+The oversampling rate is programmed with the TCR register and the clock
+prescaler is programmed with the CPR/CPR2 register pair [OX200]_ [OX952]_
+[OX954]_ [OX958]_. To switch away from the default value of 33.875 for
+the prescaler the enhanced mode has to be explicitly enabled though, by
+setting bit 4 of the EFR. In that mode setting bit 7 in the MCR enables
+the prescaler or otherwise it is bypassed as if the value of 1 was used.
+Additionally writing any value to CPR clears CPR2 for compatibility with
+old software written for older conventional PCI Oxford Semiconductor
+devices that do not have the extra prescaler's 9th bit in CPR2, so the
+CPR/CPR2 register pair has to be programmed in the right order.
+
+By using these parameters rates from 15625000bps down to 1bps can be
+obtained, with either exact or highly-accurate actual bit rates for
+standard and many non-standard rates.
+
+Here are the figures for the standard and some non-standard baud rates
+(including those quoted in Oxford Semiconductor documentation), giving
+the requested rate (r), the actual rate yielded (a) and its deviation
+from the requested rate (d), and the values of the oversampling rate
+(tcr), the clock prescaler (cpr) and the divisor (div) produced by the
+new ``get_divisor`` handler:
+
+::
+
+ r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1
+ r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1
+ r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1
+ r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1
+ r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1
+ r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1
+ r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1
+ r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1
+ r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1
+ r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1
+ r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1
+ r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1
+ r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1
+ r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1
+ r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2
+ r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2
+ r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5
+ r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5
+ r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31
+ r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35
+ r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30
+ r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105
+ r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643
+ r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647
+ r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286
+ r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294
+ r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215
+ r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625
+ r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245
+ r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153
+ r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348
+ r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461
+ r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500
+ r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500
+ r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828
+ r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828
+ r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154
+
+With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX
+limitation imposed by ``serial8250_get_baud_rate`` standard baud rates
+below 300bps become unavailable in the regular way, e.g. the rate of
+200bps requires the baud base to be divided by 78125 and that is beyond
+the unsigned 16-bit range. The historic spd_cust feature can still be
+used by encoding the values for, the prescaler, the oversampling rate
+and the clock divisor (DLM/DLL) as follows to obtain such rates if so
+required:
+
+::
+
+ 31 29 28 20 19 16 15 0
+ +-----+-----------------+-------+-------------------------------+
+ |0 0 0| CPR2:CPR | TCR | DLM:DLL |
+ +-----+-----------------+-------+-------------------------------+
+
+Use a value such encoded for the ``custom_divisor`` field along with the
+ASYNC_SPD_CUST flag set in the ``flags`` field in ``struct serial_struct``
+passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8)
+utility and its ``divisor`` and ``spd_cust`` parameters, and then select
+the baud rate of 38400bps. Note that the value of 0 in TCR sets the
+oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are
+clamped by the driver to 1.
+
+For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL
+respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value,
+the oversampling rate and the clock divisor of 62.500, 16 and 1250
+respectively. These parameters will set the baud rate for the serial
+port to 62500000 / 62.500 / 1250 / 16 = 50bps.
+
+Maciej W. Rozycki <macro@orcam.me.uk>
+
+.. [OX200] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor,
+ Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65
+
+.. [OX952] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port",
+ Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode",
+ p. 20
+
+.. [OX954] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford
+ Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20
+
+.. [OX958] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford
+ Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20
diff --git a/MAINTAINERS b/MAINTAINERS
index b87c91203c52..22cb6669892e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13411,7 +13411,7 @@ F: drivers/net/phy/motorcomm.c
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
M: Jiri Slaby <jirislaby@kernel.org>
S: Maintained
-F: Documentation/driver-api/serial/moxa-smartio.rst
+F: Documentation/driver-api/tty/moxa-smartio.rst
F: drivers/tty/mxser.*
MR800 AVERMEDIA USB FM RADIO DRIVER
diff --git a/arch/alpha/include/uapi/asm/termbits.h b/arch/alpha/include/uapi/asm/termbits.h
index 4575ba34a0ea..f1290b22072b 100644
--- a/arch/alpha/include/uapi/asm/termbits.h
+++ b/arch/alpha/include/uapi/asm/termbits.h
@@ -2,10 +2,8 @@
#ifndef _ALPHA_TERMBITS_H
#define _ALPHA_TERMBITS_H
-#include <linux/posix_types.h>
+#include <asm-generic/termbits-common.h>
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
/*
@@ -53,76 +51,58 @@ struct ktermios {
};
/* c_cc characters */
-#define VEOF 0
-#define VEOL 1
-#define VEOL2 2
-#define VERASE 3
-#define VWERASE 4
-#define VKILL 5
-#define VREPRINT 6
-#define VSWTC 7
-#define VINTR 8
-#define VQUIT 9
-#define VSUSP 10
-#define VSTART 12
-#define VSTOP 13
-#define VLNEXT 14
-#define VDISCARD 15
-#define VMIN 16
-#define VTIME 17
+#define VEOF 0
+#define VEOL 1
+#define VEOL2 2
+#define VERASE 3
+#define VWERASE 4
+#define VKILL 5
+#define VREPRINT 6
+#define VSWTC 7
+#define VINTR 8
+#define VQUIT 9
+#define VSUSP 10
+#define VSTART 12
+#define VSTOP 13
+#define VLNEXT 14
+#define VDISCARD 15
+#define VMIN 16
+#define VTIME 17
/* 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 IXON 0001000
-#define IXOFF 0002000
-#define IXANY 0004000
-#define IUCLC 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
+#define IXON 0x0200
+#define IXOFF 0x0400
+#define IUCLC 0x1000
+#define IMAXBEL 0x2000
+#define IUTF8 0x4000
/* c_oflag bits */
-#define OPOST 0000001
-#define ONLCR 0000002
-#define OLCUC 0000004
-
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-
-#define OFILL 00000100
-#define OFDEL 00000200
-#define NLDLY 00001400
-#define NL0 00000000
-#define NL1 00000400
-#define NL2 00001000
-#define NL3 00001400
-#define TABDLY 00006000
-#define TAB0 00000000
-#define TAB1 00002000
-#define TAB2 00004000
-#define TAB3 00006000
-#define CRDLY 00030000
-#define CR0 00000000
-#define CR1 00010000
-#define CR2 00020000
-#define CR3 00030000
-#define FFDLY 00040000
-#define FF0 00000000
-#define FF1 00040000
-#define BSDLY 00100000
-#define BS0 00000000
-#define BS1 00100000
-#define VTDLY 00200000
-#define VT0 00000000
-#define VT1 00200000
+#define ONLCR 0x00002
+#define OLCUC 0x00004
+#define NLDLY 0x00300
+#define NL0 0x00000
+#define NL1 0x00100
+#define NL2 0x00200
+#define NL3 0x00300
+#define TABDLY 0x00c00
+#define TAB0 0x00000
+#define TAB1 0x00400
+#define TAB2 0x00800
+#define TAB3 0x00c00
+#define CRDLY 0x03000
+#define CR0 0x00000
+#define CR1 0x01000
+#define CR2 0x02000
+#define CR3 0x03000
+#define FFDLY 0x04000
+#define FF0 0x00000
+#define FF1 0x04000
+#define BSDLY 0x08000
+#define BS0 0x00000
+#define BS1 0x08000
+#define VTDLY 0x10000
+#define VT0 0x00000
+#define VT1 0x10000
/*
* Should be equivalent to TAB3, see description of TAB3 in
* POSIX.1-2008, Ch. 11.2.3 "Output Modes"
@@ -130,61 +110,36 @@ struct ktermios {
#define XTABS TAB3
/* c_cflag bit meaning */
-#define CBAUD 0000037
-#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 CBAUDEX 0000000
-#define B57600 00020
-#define B115200 00021
-#define B230400 00022
-#define B460800 00023
-#define B500000 00024
-#define B576000 00025
-#define B921600 00026
-#define B1000000 00027
-#define B1152000 00030
-#define B1500000 00031
-#define B2000000 00032
-#define B2500000 00033
-#define B3000000 00034
-#define B3500000 00035
-#define B4000000 00036
-#define BOTHER 00037
-
-#define CSIZE 00001400
-#define CS5 00000000
-#define CS6 00000400
-#define CS7 00001000
-#define CS8 00001400
-
-#define CSTOPB 00002000
-#define CREAD 00004000
-#define PARENB 00010000
-#define PARODD 00020000
-#define HUPCL 00040000
-
-#define CLOCAL 00100000
-#define CMSPAR 010000000000 /* mark or space (stick) parity */
-#define CRTSCTS 020000000000 /* flow control */
-
-#define CIBAUD 07600000
-#define IBSHIFT 16
+#define CBAUD 0x0000001f
+#define CBAUDEX 0x00000000
+#define BOTHER 0x0000001f
+#define B57600 0x00000010
+#define B115200 0x00000011
+#define B230400 0x00000012
+#define B460800 0x00000013
+#define B500000 0x00000014
+#define B576000 0x00000015
+#define B921600 0x00000016
+#define B1000000 0x00000017
+#define B1152000 0x00000018
+#define B1500000 0x00000019
+#define B2000000 0x0000001a
+#define B2500000 0x0000001b
+#define B3000000 0x0000001c
+#define B3500000 0x0000001d
+#define B4000000 0x0000001e
+#define CSIZE 0x00000300
+#define CS5 0x00000000
+#define CS6 0x00000100
+#define CS7 0x00000200
+#define CS8 0x00000300
+#define CSTOPB 0x00000400
+#define CREAD 0x00000800
+#define PARENB 0x00001000
+#define PARODD 0x00002000
+#define HUPCL 0x00004000
+#define CLOCAL 0x00008000
+#define CIBAUD 0x001f0000
/* c_lflag bits */
#define ISIG 0x00000080
@@ -204,17 +159,6 @@ struct ktermios {
#define IEXTEN 0x00000400
#define EXTPROC 0x10000000
-/* Values for the ACTION argument to `tcflow'. */
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-
-/* Values for the QUEUE_SELECTOR argument to `tcflush'. */
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
-
/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */
#define TCSANOW 0
#define TCSADRAIN 1
diff --git a/arch/mips/include/uapi/asm/termbits.h b/arch/mips/include/uapi/asm/termbits.h
index dfeffba729b7..1eb60903d6f0 100644
--- a/arch/mips/include/uapi/asm/termbits.h
+++ b/arch/mips/include/uapi/asm/termbits.h
@@ -11,11 +11,9 @@
#ifndef _ASM_TERMBITS_H
#define _ASM_TERMBITS_H
-#include <linux/posix_types.h>
+#include <asm-generic/termbits-common.h>
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
-typedef unsigned int tcflag_t;
+typedef unsigned int tcflag_t;
/*
* The ABI says nothing about NCC but seems to use NCCS as
@@ -54,175 +52,126 @@ struct ktermios {
};
/* c_cc characters */
-#define VINTR 0 /* Interrupt character [ISIG]. */
-#define VQUIT 1 /* Quit character [ISIG]. */
-#define VERASE 2 /* Erase character [ICANON]. */
-#define VKILL 3 /* Kill-line character [ICANON]. */
-#define VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */
-#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */
-#define VEOL2 6 /* Second EOL character [ICANON]. */
+#define VINTR 0 /* Interrupt character [ISIG] */
+#define VQUIT 1 /* Quit character [ISIG] */
+#define VERASE 2 /* Erase character [ICANON] */
+#define VKILL 3 /* Kill-line character [ICANON] */
+#define VMIN 4 /* Minimum number of bytes read at once [!ICANON] */
+#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON] */
+#define VEOL2 6 /* Second EOL character [ICANON] */
#define VSWTC 7 /* ??? */
#define VSWTCH VSWTC
-#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF]. */
-#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF]. */
-#define VSUSP 10 /* Suspend character [ISIG]. */
+#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF] */
+#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF] */
+#define VSUSP 10 /* Suspend character [ISIG] */
#if 0
/*
* VDSUSP is not supported
*/
-#define VDSUSP 11 /* Delayed suspend character [ISIG]. */
+#define VDSUSP 11 /* Delayed suspend character [ISIG] */
#endif
-#define VREPRINT 12 /* Reprint-line character [ICANON]. */
-#define VDISCARD 13 /* Discard character [IEXTEN]. */
-#define VWERASE 14 /* Word-erase character [ICANON]. */
-#define VLNEXT 15 /* Literal-next character [IEXTEN]. */
-#define VEOF 16 /* End-of-file character [ICANON]. */
-#define VEOL 17 /* End-of-line character [ICANON]. */
+#define VREPRINT 12 /* Reprint-line character [ICANON] */
+#define VDISCARD 13 /* Discard character [IEXTEN] */
+#define VWERASE 14 /* Word-erase character [ICANON] */
+#define VLNEXT 15 /* Literal-next character [IEXTEN] */
+#define VEOF 16 /* End-of-file character [ICANON] */
+#define VEOL 17 /* End-of-line character [ICANON] */
/* c_iflag bits */
-#define IGNBRK 0000001 /* Ignore break condition. */
-#define BRKINT 0000002 /* Signal interrupt on break. */
-#define IGNPAR 0000004 /* Ignore characters with parity errors. */
-#define PARMRK 0000010 /* Mark parity and framing errors. */
-#define INPCK 0000020 /* Enable input parity check. */
-#define ISTRIP 0000040 /* Strip 8th bit off characters. */
-#define INLCR 0000100 /* Map NL to CR on input. */
-#define IGNCR 0000200 /* Ignore CR. */
-#define ICRNL 0000400 /* Map CR to NL on input. */
-#define IUCLC 0001000 /* Map upper case to lower case on input. */
-#define IXON 0002000 /* Enable start/stop output control. */
-#define IXANY 0004000 /* Any character will restart after stop. */
-#define IXOFF 0010000 /* Enable start/stop input control. */
-#define IMAXBEL 0020000 /* Ring bell when input queue is full. */
-#define IUTF8 0040000 /* Input is UTF-8 */
+#define IUCLC 0x0200 /* Map upper case to lower case on input */
+#define IXON 0x0400 /* Enable start/stop output control */
+#define IXOFF 0x1000 /* Enable start/stop input control */
+#define IMAXBEL 0x2000 /* Ring bell when input queue is full */
+#define IUTF8 0x4000 /* Input is UTF-8 */
/* c_oflag bits */
-#define OPOST 0000001 /* Perform output processing. */
-#define OLCUC 0000002 /* Map lower case to upper case on output. */
-#define ONLCR 0000004 /* Map NL to CR-NL on output. */
-#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
+#define OLCUC 0x00002 /* Map lower case to upper case on output */
+#define ONLCR 0x00004 /* Map NL to CR-NL on output */
+#define NLDLY 0x00100
+#define NL0 0x00000
+#define NL1 0x00100
+#define CRDLY 0x00600
+#define CR0 0x00000
+#define CR1 0x00200
+#define CR2 0x00400
+#define CR3 0x00600
+#define TABDLY 0x01800
+#define TAB0 0x00000
+#define TAB1 0x00800
+#define TAB2 0x01000
+#define TAB3 0x01800
+#define XTABS 0x01800
+#define BSDLY 0x02000
+#define BS0 0x00000
+#define BS1 0x02000
+#define VTDLY 0x04000
+#define VT0 0x00000
+#define VT1 0x04000
+#define FFDLY 0x08000
+#define FF0 0x00000
+#define FF1 0x08000
/*
#define PAGEOUT ???
#define WRAP ???
*/
/* 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 /* Number of bits per byte (mask). */
-#define CS5 0000000 /* 5 bits per byte. */
-#define CS6 0000020 /* 6 bits per byte. */
-#define CS7 0000040 /* 7 bits per byte. */
-#define CS8 0000060 /* 8 bits per byte. */
-#define CSTOPB 0000100 /* Two stop bits instead of one. */
-#define CREAD 0000200 /* Enable receiver. */
-#define PARENB 0000400 /* Parity enable. */
-#define PARODD 0001000 /* Odd parity instead of even. */
-#define HUPCL 0002000 /* Hang up on last close. */
-#define CLOCAL 0004000 /* Ignore modem status lines. */
-#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 */
+#define CBAUD 0x0000100f
+#define CSIZE 0x00000030 /* Number of bits per byte (mask) */
+#define CS5 0x00000000 /* 5 bits per byte */
+#define CS6 0x00000010 /* 6 bits per byte */
+#define CS7 0x00000020 /* 7 bits per byte */
+#define CS8 0x00000030 /* 8 bits per byte */
+#define CSTOPB 0x00000040 /* Two stop bits instead of one */
+#define CREAD 0x00000080 /* Enable receiver */
+#define PARENB 0x00000100 /* Parity enable */
+#define PARODD 0x00000200 /* Odd parity instead of even */
+#define HUPCL 0x00000400 /* Hang up on last close */
+#define CLOCAL 0x00000800 /* Ignore modem status lines */
+#define CBAUDEX 0x00001000
+#define BOTHER 0x00001000
+#define B57600 0x00001001
+#define B115200 0x00001002
+#define B230400 0x00001003
+#define B460800 0x00001004
+#define B500000 0x00001005
+#define B576000 0x00001006
+#define B921600 0x00001007
+#define B1000000 0x00001008
+#define B1152000 0x00001009
+#define B1500000 0x0000100a
+#define B2000000 0x0000100b
+#define B2500000 0x0000100c
+#define B3000000 0x0000100d
+#define B3500000 0x0000100e
+#define B4000000 0x0000100f
+#define CIBAUD 0x100f0000 /* input baud rate */
/* c_lflag bits */
-#define ISIG 0000001 /* Enable signals. */
-#define ICANON 0000002 /* Do erase and kill processing. */
-#define XCASE 0000004
-#define ECHO 0000010 /* Enable echo. */
-#define ECHOE 0000020 /* Visual erase for ERASE. */
-#define ECHOK 0000040 /* Echo NL after KILL. */
-#define ECHONL 0000100 /* Echo NL even if ECHO is off. */
-#define NOFLSH 0000200 /* Disable flush after interrupt. */
-#define IEXTEN 0000400 /* Enable DISCARD and LNEXT. */
-#define ECHOCTL 0001000 /* Echo control characters as ^X. */
-#define ECHOPRT 0002000 /* Hardcopy visual erase. */
-#define ECHOKE 0004000 /* Visual erase for KILL. */
-#define FLUSHO 0020000
-#define PENDIN 0040000 /* Retype pending input (state). */
-#define TOSTOP 0100000 /* Send SIGTTOU for background output. */
-#define ITOSTOP TOSTOP
-#define EXTPROC 0200000 /* External processing on pty */
+#define ISIG 0x00001 /* Enable signals */
+#define ICANON 0x00002 /* Do erase and kill processing */
+#define XCASE 0x00004
+#define ECHO 0x00008 /* Enable echo */
+#define ECHOE 0x00010 /* Visual erase for ERASE */
+#define ECHOK 0x00020 /* Echo NL after KILL */
+#define ECHONL 0x00040 /* Echo NL even if ECHO is off */
+#define NOFLSH 0x00080 /* Disable flush after interrupt */
+#define IEXTEN 0x00100 /* Enable DISCARD and LNEXT */
+#define ECHOCTL 0x00200 /* Echo control characters as ^X */
+#define ECHOPRT 0x00400 /* Hardcopy visual erase */
+#define ECHOKE 0x00800 /* Visual erase for KILL */
+#define FLUSHO 0x02000
+#define PENDIN 0x04000 /* Retype pending input (state) */
+#define TOSTOP 0x08000 /* Send SIGTTOU for background output */
+#define ITOSTOP TOSTOP
+#define EXTPROC 0x10000 /* External processing on pty */
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
-/* tcflow() and TCXONC use these */
-#define TCOOFF 0 /* Suspend output. */
-#define TCOON 1 /* Restart suspended output. */
-#define TCIOFF 2 /* Send a STOP character. */
-#define TCION 3 /* Send a START character. */
-
-/* tcflush() and TCFLSH use these */
-#define TCIFLUSH 0 /* Discard data received but not yet read. */
-#define TCOFLUSH 1 /* Discard data written but not yet sent. */
-#define TCIOFLUSH 2 /* Discard all pending data. */
-
/* tcsetattr uses these */
-#define TCSANOW TCSETS /* Change immediately. */
-#define TCSADRAIN TCSETSW /* Change when pending output is written. */
-#define TCSAFLUSH TCSETSF /* Flush pending input before changing. */
+#define TCSANOW TCSETS /* Change immediately */
+#define TCSADRAIN TCSETSW /* Change when pending output is written */
+#define TCSAFLUSH TCSETSF /* Flush pending input before changing */
#endif /* _ASM_TERMBITS_H */
diff --git a/arch/parisc/include/uapi/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h
index 40e920f8d683..3a8938d26fb4 100644
--- a/arch/parisc/include/uapi/asm/termbits.h
+++ b/arch/parisc/include/uapi/asm/termbits.h
@@ -2,10 +2,8 @@
#ifndef __ARCH_PARISC_TERMBITS_H__
#define __ARCH_PARISC_TERMBITS_H__
-#include <linux/posix_types.h>
+#include <asm-generic/termbits-common.h>
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 19
@@ -41,158 +39,107 @@ struct ktermios {
};
/* 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
-
+#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 0040000
-#define IUTF8 0100000
+#define IUCLC 0x0200
+#define IXON 0x0400
+#define IXOFF 0x1000
+#define IMAXBEL 0x4000
+#define IUTF8 0x8000
/* 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
+#define OLCUC 0x00002
+#define ONLCR 0x00004
+#define NLDLY 0x00100
+#define NL0 0x00000
+#define NL1 0x00100
+#define CRDLY 0x00600
+#define CR0 0x00000
+#define CR1 0x00200
+#define CR2 0x00400
+#define CR3 0x00600
+#define TABDLY 0x01800
+#define TAB0 0x00000
+#define TAB1 0x00800
+#define TAB2 0x01000
+#define TAB3 0x01800
+#define XTABS 0x01800
+#define BSDLY 0x02000
+#define BS0 0x00000
+#define BS1 0x02000
+#define VTDLY 0x04000
+#define VT0 0x00000
+#define VT1 0x04000
+#define FFDLY 0x08000
+#define FF0 0x00000
+#define FF1 0x08000
/* 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 */
-
+#define CBAUD 0x0000100f
+#define CSIZE 0x00000030
+#define CS5 0x00000000
+#define CS6 0x00000010
+#define CS7 0x00000020
+#define CS8 0x00000030
+#define CSTOPB 0x00000040
+#define CREAD 0x00000080
+#define PARENB 0x00000100
+#define PARODD 0x00000200
+#define HUPCL 0x00000400
+#define CLOCAL 0x00000800
+#define CBAUDEX 0x00001000
+#define BOTHER 0x00001000
+#define B57600 0x00001001
+#define B115200 0x00001002
+#define B230400 0x00001003
+#define B460800 0x00001004
+#define B500000 0x00001005
+#define B576000 0x00001006
+#define B921600 0x00001007
+#define B1000000 0x00001008
+#define B1152000 0x00001009
+#define B1500000 0x0000100a
+#define B2000000 0x0000100b
+#define B2500000 0x0000100c
+#define B3000000 0x0000100d
+#define B3500000 0x0000100e
+#define B4000000 0x0000100f
+#define CIBAUD 0x100f0000 /* input baud rate */
/* 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
+#define ISIG 0x00001
+#define ICANON 0x00002
+#define XCASE 0x00004
+#define ECHO 0x00008
+#define ECHOE 0x00010
+#define ECHOK 0x00020
+#define ECHONL 0x00040
+#define NOFLSH 0x00080
+#define TOSTOP 0x00100
+#define ECHOCTL 0x00200
+#define ECHOPRT 0x00400
+#define ECHOKE 0x00800
+#define FLUSHO 0x01000
+#define PENDIN 0x04000
+#define IEXTEN 0x08000
+#define EXTPROC 0x10000
/* tcsetattr uses these */
#define TCSANOW 0
diff --git a/arch/powerpc/include/uapi/asm/termbits.h b/arch/powerpc/include/uapi/asm/termbits.h
index ed18bc61f63d..21dc86dcb2f1 100644
--- a/arch/powerpc/include/uapi/asm/termbits.h
+++ b/arch/powerpc/include/uapi/asm/termbits.h
@@ -9,8 +9,8 @@
* 2 of the License, or (at your option) any later version.
*/
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
+#include <asm-generic/termbits-common.h>
+
typedef unsigned int tcflag_t;
/*
@@ -64,115 +64,72 @@ struct ktermios {
#define VDISCARD 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 IXON 0001000
-#define IXOFF 0002000
-#define IXANY 0004000
-#define IUCLC 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
+#define IXON 0x0200
+#define IXOFF 0x0400
+#define IUCLC 0x1000
+#define IMAXBEL 0x2000
+#define IUTF8 0x4000
/* c_oflag bits */
-#define OPOST 0000001
-#define ONLCR 0000002
-#define OLCUC 0000004
-
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-
-#define OFILL 00000100
-#define OFDEL 00000200
-#define NLDLY 00001400
-#define NL0 00000000
-#define NL1 00000400
-#define NL2 00001000
-#define NL3 00001400
-#define TABDLY 00006000
-#define TAB0 00000000
-#define TAB1 00002000
-#define TAB2 00004000
-#define TAB3 00006000
-#define XTABS 00006000 /* required by POSIX to == TAB3 */
-#define CRDLY 00030000
-#define CR0 00000000
-#define CR1 00010000
-#define CR2 00020000
-#define CR3 00030000
-#define FFDLY 00040000
-#define FF0 00000000
-#define FF1 00040000
-#define BSDLY 00100000
-#define BS0 00000000
-#define BS1 00100000
-#define VTDLY 00200000
-#define VT0 00000000
-#define VT1 00200000
+#define ONLCR 0x00002
+#define OLCUC 0x00004
+#define NLDLY 0x00300
+#define NL0 0x00000
+#define NL1 0x00100
+#define NL2 0x00200
+#define NL3 0x00300
+#define TABDLY 0x00c00
+#define TAB0 0x00000
+#define TAB1 0x00400
+#define TAB2 0x00800
+#define TAB3 0x00c00
+#define XTABS 0x00c00 /* required by POSIX to == TAB3 */
+#define CRDLY 0x03000
+#define CR0 0x00000
+#define CR1 0x01000
+#define CR2 0x02000
+#define CR3 0x03000
+#define FFDLY 0x04000
+#define FF0 0x00000
+#define FF1 0x04000
+#define BSDLY 0x08000
+#define BS0 0x00000
+#define BS1 0x08000
+#define VTDLY 0x10000
+#define VT0 0x00000
+#define VT1 0x10000
/* c_cflag bit meaning */
-#define CBAUD 0000377
-#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 CBAUDEX 0000000
-#define B57600 00020
-#define B115200 00021
-#define B230400 00022
-#define B460800 00023
-#define B500000 00024
-#define B576000 00025
-#define B921600 00026
-#define B1000000 00027
-#define B1152000 00030
-#define B1500000 00031
-#define B2000000 00032
-#define B2500000 00033
-#define B3000000 00034
-#define B3500000 00035
-#define B4000000 00036
-#define BOTHER 00037
-
-#define CIBAUD 077600000
-#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
-
-#define CSIZE 00001400
-#define CS5 00000000
-#define CS6 00000400
-#define CS7 00001000
-#define CS8 00001400
-
-#define CSTOPB 00002000
-#define CREAD 00004000
-#define PARENB 00010000
-#define PARODD 00020000
-#define HUPCL 00040000
-
-#define CLOCAL 00100000
-#define CMSPAR 010000000000 /* mark or space (stick) parity */
-#define CRTSCTS 020000000000 /* flow control */
+#define CBAUD 0x000000ff
+#define CBAUDEX 0x00000000
+#define BOTHER 0x0000001f
+#define B57600 0x00000010
+#define B115200 0x00000011
+#define B230400 0x00000012
+#define B460800 0x00000013
+#define B500000 0x00000014
+#define B576000 0x00000015
+#define B921600 0x00000016
+#define B1000000 0x00000017
+#define B1152000 0x00000018
+#define B1500000 0x00000019
+#define B2000000 0x0000001a
+#define B2500000 0x0000001b
+#define B3000000 0x0000001c
+#define B3500000 0x0000001d
+#define B4000000 0x0000001e
+#define CSIZE 0x00000300
+#define CS5 0x00000000
+#define CS6 0x00000100
+#define CS7 0x00000200
+#define CS8 0x00000300
+#define CSTOPB 0x00000400
+#define CREAD 0x00000800
+#define PARENB 0x00001000
+#define PARODD 0x00002000
+#define HUPCL 0x00004000
+#define CLOCAL 0x00008000
+#define CIBAUD 0x00ff0000
/* c_lflag bits */
#define ISIG 0x00000080
@@ -192,17 +149,6 @@ struct ktermios {
#define IEXTEN 0x00000400
#define EXTPROC 0x10000000
-/* Values for the ACTION argument to `tcflow'. */
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-
-/* Values for the QUEUE_SELECTOR argument to `tcflush'. */
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
-
/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */
#define TCSANOW 0
#define TCSADRAIN 1
diff --git a/arch/sparc/include/uapi/asm/termbits.h b/arch/sparc/include/uapi/asm/termbits.h
index ce5ad5d0f105..4321322701fc 100644
--- a/arch/sparc/include/uapi/asm/termbits.h
+++ b/arch/sparc/include/uapi/asm/termbits.h
@@ -2,15 +2,12 @@
#ifndef _UAPI_SPARC_TERMBITS_H
#define _UAPI_SPARC_TERMBITS_H
-#include <linux/posix_types.h>
-
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
+#include <asm-generic/termbits-common.h>
#if defined(__sparc__) && defined(__arch64__)
-typedef unsigned int tcflag_t;
+typedef unsigned int tcflag_t;
#else
-typedef unsigned long tcflag_t;
+typedef unsigned long tcflag_t;
#endif
#define NCC 8
@@ -61,21 +58,19 @@ struct ktermios {
};
/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VEOL 5
-#define VEOL2 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-
-
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VEOL 5
+#define VEOL2 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
#define VSUSP 10
-#define VDSUSP 11 /* SunOS POSIX nicety I do believe... */
+#define VDSUSP 11 /* SunOS POSIX nicety I do believe... */
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
@@ -90,121 +85,83 @@ struct ktermios {
#endif
/* c_iflag bits */
-#define IGNBRK 0x00000001
-#define BRKINT 0x00000002
-#define IGNPAR 0x00000004
-#define PARMRK 0x00000008
-#define INPCK 0x00000010
-#define ISTRIP 0x00000020
-#define INLCR 0x00000040
-#define IGNCR 0x00000080
-#define ICRNL 0x00000100
-#define IUCLC 0x00000200
-#define IXON 0x00000400
-#define IXANY 0x00000800
-#define IXOFF 0x00001000
-#define IMAXBEL 0x00002000
-#define IUTF8 0x00004000
+#define IUCLC 0x0200
+#define IXON 0x0400
+#define IXOFF 0x1000
+#define IMAXBEL 0x2000
+#define IUTF8 0x4000
/* c_oflag bits */
-#define OPOST 0x00000001
-#define OLCUC 0x00000002
-#define ONLCR 0x00000004
-#define OCRNL 0x00000008
-#define ONOCR 0x00000010
-#define ONLRET 0x00000020
-#define OFILL 0x00000040
-#define OFDEL 0x00000080
-#define NLDLY 0x00000100
-#define NL0 0x00000000
-#define NL1 0x00000100
-#define CRDLY 0x00000600
-#define CR0 0x00000000
-#define CR1 0x00000200
-#define CR2 0x00000400
-#define CR3 0x00000600
-#define TABDLY 0x00001800
-#define TAB0 0x00000000
-#define TAB1 0x00000800
-#define TAB2 0x00001000
-#define TAB3 0x00001800
-#define XTABS 0x00001800
-#define BSDLY 0x00002000
-#define BS0 0x00000000
-#define BS1 0x00002000
-#define VTDLY 0x00004000
-#define VT0 0x00000000
-#define VT1 0x00004000
-#define FFDLY 0x00008000
-#define FF0 0x00000000
-#define FF1 0x00008000
-#define PAGEOUT 0x00010000 /* SUNOS specific */
-#define WRAP 0x00020000 /* SUNOS specific */
+#define OLCUC 0x00002
+#define ONLCR 0x00004
+#define NLDLY 0x00100
+#define NL0 0x00000
+#define NL1 0x00100
+#define CRDLY 0x00600
+#define CR0 0x00000
+#define CR1 0x00200
+#define CR2 0x00400
+#define CR3 0x00600
+#define TABDLY 0x01800
+#define TAB0 0x00000
+#define TAB1 0x00800
+#define TAB2 0x01000
+#define TAB3 0x01800
+#define XTABS 0x01800
+#define BSDLY 0x02000
+#define BS0 0x00000
+#define BS1 0x02000
+#define VTDLY 0x04000
+#define VT0 0x00000
+#define VT1 0x04000
+#define FFDLY 0x08000
+#define FF0 0x00000
+#define FF1 0x08000
+#define PAGEOUT 0x10000 /* SUNOS specific */
+#define WRAP 0x20000 /* SUNOS specific */
/* c_cflag bit meaning */
-#define CBAUD 0x0000100f
-#define B0 0x00000000 /* hang up */
-#define B50 0x00000001
-#define B75 0x00000002
-#define B110 0x00000003
-#define B134 0x00000004
-#define B150 0x00000005
-#define B200 0x00000006
-#define B300 0x00000007
-#define B600 0x00000008
-#define B1200 0x00000009
-#define B1800 0x0000000a
-#define B2400 0x0000000b
-#define B4800 0x0000000c
-#define B9600 0x0000000d
-#define B19200 0x0000000e
-#define B38400 0x0000000f
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE 0x00000030
-#define CS5 0x00000000
-#define CS6 0x00000010
-#define CS7 0x00000020
-#define CS8 0x00000030
-#define CSTOPB 0x00000040
-#define CREAD 0x00000080
-#define PARENB 0x00000100
-#define PARODD 0x00000200
-#define HUPCL 0x00000400
-#define CLOCAL 0x00000800
-#define CBAUDEX 0x00001000
+#define CBAUD 0x0000100f
+#define CSIZE 0x00000030
+#define CS5 0x00000000
+#define CS6 0x00000010
+#define CS7 0x00000020
+#define CS8 0x00000030
+#define CSTOPB 0x00000040
+#define CREAD 0x00000080
+#define PARENB 0x00000100
+#define PARODD 0x00000200
+#define HUPCL 0x00000400
+#define CLOCAL 0x00000800
+#define CBAUDEX 0x00001000
/* We'll never see these speeds with the Zilogs, but for completeness... */
-#define BOTHER 0x00001000
-#define B57600 0x00001001
-#define B115200 0x00001002
-#define B230400 0x00001003
-#define B460800 0x00001004
+#define BOTHER 0x00001000
+#define B57600 0x00001001
+#define B115200 0x00001002
+#define B230400 0x00001003
+#define B460800 0x00001004
/* This is what we can do with the Zilogs. */
-#define B76800 0x00001005
+#define B76800 0x00001005
/* This is what we can do with the SAB82532. */
-#define B153600 0x00001006
-#define B307200 0x00001007
-#define B614400 0x00001008
-#define B921600 0x00001009
+#define B153600 0x00001006
+#define B307200 0x00001007
+#define B614400 0x00001008
+#define B921600 0x00001009
/* And these are the rest... */
-#define B500000 0x0000100a
-#define B576000 0x0000100b
-#define B1000000 0x0000100c
-#define B1152000 0x0000100d
-#define B1500000 0x0000100e
-#define B2000000 0x0000100f
+#define B500000 0x0000100a
+#define B576000 0x0000100b
+#define B1000000 0x0000100c
+#define B1152000 0x0000100d
+#define B1500000 0x0000100e
+#define B2000000 0x0000100f
/* These have totally bogus values and nobody uses them
so far. Later on we'd have to use say 0x10000x and
adjust CBAUD constant and drivers accordingly.
-#define B2500000 0x00001010
-#define B3000000 0x00001011
-#define B3500000 0x00001012
-#define B4000000 0x00001013 */
-#define CIBAUD 0x100f0000 /* input baud rate (not used) */
-#define CMSPAR 0x40000000 /* mark or space (stick) parity */
-#define CRTSCTS 0x80000000 /* flow control */
-
-#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+#define B2500000 0x00001010
+#define B3000000 0x00001011
+#define B3500000 0x00001012
+#define B4000000 0x00001013 */
+#define CIBAUD 0x100f0000 /* input baud rate (not used) */
/* c_lflag bits */
#define ISIG 0x00000001
@@ -219,7 +176,7 @@ struct ktermios {
#define ECHOCTL 0x00000200
#define ECHOPRT 0x00000400
#define ECHOKE 0x00000800
-#define DEFECHO 0x00001000 /* SUNOS thing, what is it? */
+#define DEFECHO 0x00001000 /* SUNOS thing, what is it? */
#define FLUSHO 0x00002000
#define PENDIN 0x00004000
#define IEXTEN 0x00008000
@@ -244,21 +201,9 @@ struct ktermios {
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
-
-/* 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
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
#endif /* _UAPI_SPARC_TERMBITS_H */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 55f48375e3fe..69fd31ffb847 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -18,7 +18,8 @@ config TTY_PRINTK
The feature is useful to inline user messages with kernel
messages.
In order to use this feature, you should output user messages
- to /dev/ttyprintk or redirect console to this TTY.
+ to /dev/ttyprintk or redirect console to this TTY, or boot
+ the kernel with console=ttyprintk.
If unsure, say N.
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 78baba55a8b5..0daf1bc95360 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1418,7 +1418,11 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)
info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR);
/* byte size and parity */
-
+ if ((cflag & CSIZE) != CS8) {
+ cflag &= ~CSIZE;
+ cflag |= CS7;
+ tty->termios.c_cflag = cflag;
+ }
info->params.data_bits = tty_get_char_size(cflag);
if (cflag & CSTOPB)
@@ -1432,10 +1436,8 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)
info->params.parity = ASYNC_PARITY_ODD;
else
info->params.parity = ASYNC_PARITY_EVEN;
-#ifdef CMSPAR
if (cflag & CMSPAR)
info->params.parity = ASYNC_PARITY_SPACE;
-#endif
}
/* calculate number of jiffies to transmit a full
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index adf941c47506..ed45d04905c2 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -11,6 +11,7 @@
* of the boot process, for example.
*/
+#include <linux/console.h>
#include <linux/device.h>
#include <linux/serial.h>
#include <linux/tty.h>
@@ -163,6 +164,18 @@ static const struct tty_port_operations tpk_port_ops = {
static struct tty_driver *ttyprintk_driver;
+static struct tty_driver *ttyprintk_console_device(struct console *c,
+ int *index)
+{
+ *index = 0;
+ return ttyprintk_driver;
+}
+
+static struct console ttyprintk_console = {
+ .name = "ttyprintk",
+ .device = ttyprintk_console_device,
+};
+
static int __init ttyprintk_init(void)
{
int ret;
@@ -195,6 +208,8 @@ static int __init ttyprintk_init(void)
goto error;
}
+ register_console(&ttyprintk_console);
+
return 0;
error:
@@ -205,6 +220,7 @@ error:
static void __exit ttyprintk_exit(void)
{
+ unregister_console(&ttyprintk_console);
tty_unregister_driver(ttyprintk_driver);
tty_driver_kref_put(ttyprintk_driver);
tty_port_destroy(&tpk_port.port);
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 533d02b38e02..afb2d373dd47 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -588,10 +588,8 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
}
if (!(cflag & PARODD))
cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
if (cflag & CMSPAR)
cval |= UART_LCR_SPAR;
-#endif
/* Determine divisor based on baud rate */
baud = tty_get_baud_rate(tty);
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
index 9e8ccb8ed6d6..c7968aecd870 100644
--- a/drivers/tty/goldfish.c
+++ b/drivers/tty/goldfish.c
@@ -405,6 +405,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
err_tty_register_device_failed:
free_irq(irq, qtty);
err_dec_line_count:
+ tty_port_destroy(&qtty->port);
goldfish_tty_current_line_count--;
if (goldfish_tty_current_line_count == 0)
goldfish_tty_delete_driver();
@@ -426,6 +427,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
iounmap(qtty->base);
qtty->base = NULL;
free_irq(qtty->irq, pdev);
+ tty_port_destroy(&qtty->port);
goldfish_tty_current_line_count--;
if (goldfish_tty_current_line_count == 0)
goldfish_tty_delete_driver();
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 8d60e0ff67b4..4f9264d005c0 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -87,6 +87,25 @@ config HVC_DCC
driver. This console is used through a JTAG only on ARM. If you don't have
a JTAG then you probably don't want this option.
+config HVC_DCC_SERIALIZE_SMP
+ bool "Use DCC only on CPU core 0"
+ depends on SMP && HVC_DCC
+ help
+ This is a DEBUG option to serialize all console input and output to CPU 0.
+ Some external debuggers, do not handle reads/writes from/to DCC on more
+ than one CPU core. Each core has its own DCC device registers, so when a
+ CPU core reads or writes from/to DCC, it only accesses its own DCC device.
+ Since kernel code can run on any CPU core, every time the kernel wants to
+ write to the console, it might write to a different DCC.
+
+ In SMP mode, external debuggers create multiple windows, and each window
+ shows the DCC output only from that core's DCC. The result is that
+ console output is either lost or scattered across windows.
+
+ Enable this option only if you are sure that you do not need features like
+ CPU hotplug to work. For example, during early chipset bringups without
+ debug serial console support. If unsure, say N.
+
config HVC_RISCV_SBI
bool "RISC-V SBI console support"
depends on RISCV_SBI_V01
diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c
index bd61f9372d83..1751108cf763 100644
--- a/drivers/tty/hvc/hvc_dcc.c
+++ b/drivers/tty/hvc/hvc_dcc.c
@@ -1,10 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2010, 2014, 2022 The Linux Foundation. All rights reserved. */
#include <linux/console.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
#include <linux/init.h>
+#include <linux/kfifo.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
#include <asm/dcc.h>
#include <asm/processor.h>
@@ -15,6 +20,15 @@
#define DCC_STATUS_RX (1 << 30)
#define DCC_STATUS_TX (1 << 29)
+#define DCC_INBUF_SIZE 128
+#define DCC_OUTBUF_SIZE 1024
+
+/* Lock to serialize access to DCC fifo */
+static DEFINE_SPINLOCK(dcc_lock);
+
+static DEFINE_KFIFO(inbuf, unsigned char, DCC_INBUF_SIZE);
+static DEFINE_KFIFO(outbuf, unsigned char, DCC_OUTBUF_SIZE);
+
static void dcc_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
while (__dcc_getstatus() & DCC_STATUS_TX)
@@ -67,24 +81,176 @@ static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
return i;
}
+/*
+ * Check if the DCC is enabled. If CONFIG_HVC_DCC_SERIALIZE_SMP is enabled,
+ * then we assume then this function will be called first on core0. That way,
+ * dcc_core0_available will be true only if it's available on core0.
+ */
static bool hvc_dcc_check(void)
{
unsigned long time = jiffies + (HZ / 10);
+ static bool dcc_core0_available;
+
+ /*
+ * If we're not on core 0, but we previously confirmed that DCC is
+ * active, then just return true.
+ */
+ int cpu = get_cpu();
+
+ if (IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP) && cpu && dcc_core0_available) {
+ put_cpu();
+ return true;
+ }
+
+ put_cpu();
/* Write a test character to check if it is handled */
__dcc_putchar('\n');
while (time_is_after_jiffies(time)) {
- if (!(__dcc_getstatus() & DCC_STATUS_TX))
+ if (!(__dcc_getstatus() & DCC_STATUS_TX)) {
+ dcc_core0_available = true;
return true;
+ }
}
return false;
}
+/*
+ * Workqueue function that writes the output FIFO to the DCC on core 0.
+ */
+static void dcc_put_work(struct work_struct *work)
+{
+ unsigned char ch;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dcc_lock, irqflags);
+
+ /* While there's data in the output FIFO, write it to the DCC */
+ while (kfifo_get(&outbuf, &ch))
+ hvc_dcc_put_chars(0, &ch, 1);
+
+ /* While we're at it, check for any input characters */
+ while (!kfifo_is_full(&inbuf)) {
+ if (!hvc_dcc_get_chars(0, &ch, 1))
+ break;
+ kfifo_put(&inbuf, ch);
+ }
+
+ spin_unlock_irqrestore(&dcc_lock, irqflags);
+}
+
+static DECLARE_WORK(dcc_pwork, dcc_put_work);
+
+/*
+ * Workqueue function that reads characters from DCC and puts them into the
+ * input FIFO.
+ */
+static void dcc_get_work(struct work_struct *work)
+{
+ unsigned char ch;
+ unsigned long irqflags;
+
+ /*
+ * Read characters from DCC and put them into the input FIFO, as
+ * long as there is room and we have characters to read.
+ */
+ spin_lock_irqsave(&dcc_lock, irqflags);
+
+ while (!kfifo_is_full(&inbuf)) {
+ if (!hvc_dcc_get_chars(0, &ch, 1))
+ break;
+ kfifo_put(&inbuf, ch);
+ }
+ spin_unlock_irqrestore(&dcc_lock, irqflags);
+}
+
+static DECLARE_WORK(dcc_gwork, dcc_get_work);
+
+/*
+ * Write characters directly to the DCC if we're on core 0 and the FIFO
+ * is empty, or write them to the FIFO if we're not.
+ */
+static int hvc_dcc0_put_chars(u32 vt, const char *buf, int count)
+{
+ int len;
+ unsigned long irqflags;
+
+ if (!IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP))
+ return hvc_dcc_put_chars(vt, buf, count);
+
+ spin_lock_irqsave(&dcc_lock, irqflags);
+ if (smp_processor_id() || (!kfifo_is_empty(&outbuf))) {
+ len = kfifo_in(&outbuf, buf, count);
+ spin_unlock_irqrestore(&dcc_lock, irqflags);
+
+ /*
+ * We just push data to the output FIFO, so schedule the
+ * workqueue that will actually write that data to DCC.
+ * CPU hotplug is disabled in dcc_init so CPU0 cannot be
+ * offlined after the cpu online check.
+ */
+ if (cpu_online(0))
+ schedule_work_on(0, &dcc_pwork);
+
+ return len;
+ }
+
+ /*
+ * If we're already on core 0, and the FIFO is empty, then just
+ * write the data to DCC.
+ */
+ len = hvc_dcc_put_chars(vt, buf, count);
+ spin_unlock_irqrestore(&dcc_lock, irqflags);
+
+ return len;
+}
+
+/*
+ * Read characters directly from the DCC if we're on core 0 and the FIFO
+ * is empty, or read them from the FIFO if we're not.
+ */
+static int hvc_dcc0_get_chars(u32 vt, char *buf, int count)
+{
+ int len;
+ unsigned long irqflags;
+
+ if (!IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP))
+ return hvc_dcc_get_chars(vt, buf, count);
+
+ spin_lock_irqsave(&dcc_lock, irqflags);
+
+ if (smp_processor_id() || (!kfifo_is_empty(&inbuf))) {
+ len = kfifo_out(&inbuf, buf, count);
+ spin_unlock_irqrestore(&dcc_lock, irqflags);
+
+ /*
+ * If the FIFO was empty, there may be characters in the DCC
+ * that we haven't read yet. Schedule a workqueue to fill
+ * the input FIFO, so that the next time this function is
+ * called, we'll have data. CPU hotplug is disabled in dcc_init
+ * so CPU0 cannot be offlined after the cpu online check.
+ */
+ if (!len && cpu_online(0))
+ schedule_work_on(0, &dcc_gwork);
+
+ return len;
+ }
+
+ /*
+ * If we're already on core 0, and the FIFO is empty, then just
+ * read the data from DCC.
+ */
+ len = hvc_dcc_get_chars(vt, buf, count);
+ spin_unlock_irqrestore(&dcc_lock, irqflags);
+
+ return len;
+}
+
static const struct hv_ops hvc_dcc_get_put_ops = {
- .get_chars = hvc_dcc_get_chars,
- .put_chars = hvc_dcc_put_chars,
+ .get_chars = hvc_dcc0_get_chars,
+ .put_chars = hvc_dcc0_put_chars,
};
static int __init hvc_dcc_console_init(void)
@@ -108,6 +274,26 @@ static int __init hvc_dcc_init(void)
if (!hvc_dcc_check())
return -ENODEV;
+ if (IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP)) {
+ pr_warn("\n");
+ pr_warn("********************************************************************\n");
+ pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
+ pr_warn("** **\n");
+ pr_warn("** HVC_DCC_SERIALIZE_SMP SUPPORT HAS BEEN ENABLED IN THIS KERNEL **\n");
+ pr_warn("** **\n");
+ pr_warn("** This means that this is a DEBUG kernel and unsafe for **\n");
+ pr_warn("** production use and has important feature like CPU hotplug **\n");
+ pr_warn("** disabled. **\n");
+ pr_warn("** **\n");
+ pr_warn("** If you see this message and you are not debugging the **\n");
+ pr_warn("** kernel, report this immediately to your vendor! **\n");
+ pr_warn("** **\n");
+ pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
+ pr_warn("********************************************************************\n");
+
+ cpu_hotplug_disable();
+ }
+
p = hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
return PTR_ERR_OR_ZERO(p);
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
index 056ae21a5121..794c7b18aa06 100644
--- a/drivers/tty/hvc/hvc_opal.c
+++ b/drivers/tty/hvc/hvc_opal.c
@@ -13,12 +13,12 @@
#include <linux/slab.h>
#include <linux/console.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <asm/hvconsole.h>
-#include <asm/prom.h>
#include <asm/firmware.h>
#include <asm/hvsi.h>
#include <asm/udbg.h>
@@ -342,9 +342,9 @@ void __init hvc_opal_init_early(void)
* path, so we hard wire it
*/
opal = of_find_node_by_path("/ibm,opal/consoles");
- if (opal)
+ if (opal) {
pr_devel("hvc_opal: Found consoles in new location\n");
- if (!opal) {
+ } else {
opal = of_find_node_by_path("/ibm,opal");
if (opal)
pr_devel("hvc_opal: "
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index 72b11aa7e0a6..736b230f5ec0 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -28,10 +28,10 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/console.h>
+#include <linux/of.h>
#include <asm/hvconsole.h>
#include <asm/vio.h>
-#include <asm/prom.h>
#include <asm/hvsi.h>
#include <asm/udbg.h>
#include <asm/machdep.h>
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 245da1dfd818..9b7e8246a464 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -581,10 +581,9 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
spin_unlock_irqrestore(&hvcsd->lock, flags);
/* This is synch -- FIXME :js: it is not! */
- if(got)
+ if (got)
tty_flip_buffer_push(&hvcsd->port);
-
- if (!got) {
+ else {
/* Do this _after_ the flip_buffer_push */
spin_lock_irqsave(&hvcsd->lock, flags);
vio_enable_interrupts(hvcsd->vdev);
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index aa81f4835fef..a200d01eceed 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -26,13 +26,13 @@
#include <linux/module.h>
#include <linux/major.h>
#include <linux/kernel.h>
+#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <asm/hvcall.h>
#include <asm/hvconsole.h>
-#include <asm/prom.h>
#include <linux/uaccess.h>
#include <asm/vio.h>
#include <asm/param.h>
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 6ebd3e4ed859..70b982b2c6b2 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -528,7 +528,6 @@ static int mxser_set_baud(struct tty_struct *tty, speed_t newspd)
outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */
outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
-#ifdef BOTHER
if (C_BAUD(tty) == BOTHER) {
quot = MXSER_BAUD_BASE % newspd;
quot *= 8;
@@ -539,9 +538,9 @@ static int mxser_set_baud(struct tty_struct *tty, speed_t newspd)
quot /= newspd;
mxser_set_must_enum_value(info->ioaddr, quot);
- } else
-#endif
+ } else {
mxser_set_must_enum_value(info->ioaddr, 0);
+ }
return 0;
}
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index fd8b86dde525..137eebdcfda9 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -444,6 +444,25 @@ static u8 gsm_encode_modem(const struct gsm_dlci *dlci)
return modembits;
}
+static void gsm_hex_dump_bytes(const char *fname, const u8 *data,
+ unsigned long len)
+{
+ char *prefix;
+
+ if (!fname) {
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, data, len,
+ true);
+ return;
+ }
+
+ prefix = kasprintf(GFP_KERNEL, "%s: ", fname);
+ if (!prefix)
+ return;
+ print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 16, 1, data, len,
+ true);
+ kfree(prefix);
+}
+
/**
* gsm_print_packet - display a frame for debug
* @hdr: header to print before decode
@@ -508,7 +527,7 @@ static void gsm_print_packet(const char *hdr, int addr, int cr,
else
pr_cont("(F)");
- print_hex_dump_bytes("", DUMP_PREFIX_NONE, data, dlen);
+ gsm_hex_dump_bytes(NULL, data, dlen);
}
@@ -698,9 +717,7 @@ static void gsm_data_kick(struct gsm_mux *gsm, struct gsm_dlci *dlci)
}
if (debug & 4)
- print_hex_dump_bytes("gsm_data_kick: ",
- DUMP_PREFIX_OFFSET,
- gsm->txframe, len);
+ gsm_hex_dump_bytes(__func__, gsm->txframe, len);
if (gsmld_output(gsm, gsm->txframe, len) <= 0)
break;
/* FIXME: Can eliminate one SOF in many more cases */
@@ -749,7 +766,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
*--dp = msg->ctrl;
if (gsm->initiator)
- *--dp = (msg->addr << 2) | 2 | EA;
+ *--dp = (msg->addr << 2) | CR | EA;
else
*--dp = (msg->addr << 2) | EA;
*fcs = gsm_fcs_add_block(INIT_FCS, dp , msg->data - dp);
@@ -1907,10 +1924,6 @@ static void gsm_queue(struct gsm_mux *gsm)
case UI|PF:
case UIH:
case UIH|PF:
-#if 0
- if (cr)
- goto invalid;
-#endif
if (dlci == NULL || dlci->state != DLCI_OPEN) {
gsm_command(gsm, address, DM|PF);
return;
@@ -2448,8 +2461,7 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
return -ENOSPC;
}
if (debug & 4)
- print_hex_dump_bytes("gsmld_output: ", DUMP_PREFIX_OFFSET,
- data, len);
+ gsm_hex_dump_bytes(__func__, data, len);
return gsm->tty->ops->write(gsm->tty, data, len);
}
@@ -2525,8 +2537,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char flags = TTY_NORMAL;
if (debug & 4)
- print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
- cp, count);
+ gsm_hex_dump_bytes(__func__, cp, count);
for (; count; count--, cp++) {
if (fp)
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index efc72104c840..640c9e871044 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1220,21 +1220,34 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c)
process_echoes(tty);
}
+static bool n_tty_is_char_flow_ctrl(struct tty_struct *tty, unsigned char c)
+{
+ return c == START_CHAR(tty) || c == STOP_CHAR(tty);
+}
+
+/* Returns true if c is consumed as flow-control character */
+static bool n_tty_receive_char_flow_ctrl(struct tty_struct *tty, unsigned char c)
+{
+ if (!n_tty_is_char_flow_ctrl(tty, c))
+ return false;
+
+ if (c == START_CHAR(tty)) {
+ start_tty(tty);
+ process_echoes(tty);
+ return true;
+ }
+
+ /* STOP_CHAR */
+ stop_tty(tty);
+ return true;
+}
+
static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
{
struct n_tty_data *ldata = tty->disc_data;
- if (I_IXON(tty)) {
- if (c == START_CHAR(tty)) {
- start_tty(tty);
- process_echoes(tty);
- return;
- }
- if (c == STOP_CHAR(tty)) {
- stop_tty(tty);
- return;
- }
- }
+ if (I_IXON(tty) && n_tty_receive_char_flow_ctrl(tty, c))
+ return;
if (L_ISIG(tty)) {
if (c == INTR_CHAR(tty)) {
@@ -1975,6 +1988,35 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty,
return ldata->read_tail != canon_head;
}
+/*
+ * If we finished a read at the exact location of an
+ * EOF (special EOL character that's a __DISABLED_CHAR)
+ * in the stream, silently eat the EOF.
+ */
+static void canon_skip_eof(struct tty_struct *tty)
+{
+ struct n_tty_data *ldata = tty->disc_data;
+ size_t tail, canon_head;
+
+ canon_head = smp_load_acquire(&ldata->canon_head);
+ tail = ldata->read_tail;
+
+ // No data?
+ if (tail == canon_head)
+ return;
+
+ // See if the tail position is EOF in the circular buffer
+ tail &= (N_TTY_BUF_SIZE - 1);
+ if (!test_bit(tail, ldata->read_flags))
+ return;
+ if (read_buf(ldata, tail) != __DISABLED_CHAR)
+ return;
+
+ // Clear the EOL bit, skip the EOF char.
+ clear_bit(tail, ldata->read_flags);
+ smp_store_release(&ldata->read_tail, ldata->read_tail + 1);
+}
+
/**
* job_control - check job control
* @tty: tty
@@ -2045,7 +2087,14 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
*/
if (*cookie) {
if (ldata->icanon && !L_EXTPROC(tty)) {
- if (canon_copy_from_read_buf(tty, &kb, &nr))
+ /*
+ * If we have filled the user buffer, see
+ * if we should skip an EOF character before
+ * releasing the lock and returning done.
+ */
+ if (!nr)
+ canon_skip_eof(tty);
+ else if (canon_copy_from_read_buf(tty, &kb, &nr))
return kb - kbuf;
} else {
if (copy_from_read_buf(tty, &kb, &nr))
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index a8830e15a22c..696030cfcb09 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -17,6 +17,8 @@
struct uart_8250_dma {
int (*tx_dma)(struct uart_8250_port *p);
int (*rx_dma)(struct uart_8250_port *p);
+ void (*prepare_tx_dma)(struct uart_8250_port *p);
+ void (*prepare_rx_dma)(struct uart_8250_port *p);
/* Filter function */
dma_filter_fn fn;
@@ -83,6 +85,7 @@ struct serial8250_config {
#define UART_CAP_MINI BIT(17) /* Mini UART on BCM283X family lacks:
* STOP PARITY EPAR SPAR WLEN5 WLEN6
*/
+#define UART_CAP_NOTEMT BIT(18) /* UART without interrupt on TEMT available */
#define UART_BUG_QUOT BIT(0) /* UART has buggy quot LSB */
#define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */
@@ -120,6 +123,28 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value)
up->port.serial_out(&up->port, offset, value);
}
+/*
+ * For the 16C950
+ */
+static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
+{
+ serial_out(up, UART_SCR, offset);
+ serial_out(up, UART_ICR, value);
+}
+
+static unsigned int __maybe_unused serial_icr_read(struct uart_8250_port *up,
+ int offset)
+{
+ unsigned int value;
+
+ serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
+ serial_out(up, UART_SCR, offset);
+ value = serial_in(up, UART_ICR);
+ serial_icr_write(up, UART_ACR, up->acr);
+
+ return value;
+}
+
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
static inline int serial_dl_read(struct uart_8250_port *up)
@@ -302,6 +327,22 @@ extern int serial8250_rx_dma(struct uart_8250_port *);
extern void serial8250_rx_dma_flush(struct uart_8250_port *);
extern int serial8250_request_dma(struct uart_8250_port *);
extern void serial8250_release_dma(struct uart_8250_port *);
+
+static inline void serial8250_do_prepare_tx_dma(struct uart_8250_port *p)
+{
+ struct uart_8250_dma *dma = p->dma;
+
+ if (dma->prepare_tx_dma)
+ dma->prepare_tx_dma(p);
+}
+
+static inline void serial8250_do_prepare_rx_dma(struct uart_8250_port *p)
+{
+ struct uart_8250_dma *dma = p->dma;
+
+ if (dma->prepare_rx_dma)
+ dma->prepare_rx_dma(p);
+}
#else
static inline int serial8250_tx_dma(struct uart_8250_port *p)
{
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index 93fe10c680fb..9d2a7856784f 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -429,6 +429,8 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
memset(&port, 0, sizeof(port));
port.port.private_data = vuart;
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 01d30f6ed8fb..cfbd2de0ca6e 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -32,7 +32,6 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
-#include <linux/pm_runtime.h>
#include <linux/io.h>
#ifdef CONFIG_SPARC
#include <linux/sunserialcore.h>
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index b3c3f7e5851a..7133fceed35e 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -34,7 +34,7 @@ static void __dma_tx_complete(void *param)
uart_write_wakeup(&p->port);
ret = serial8250_tx_dma(p);
- if (ret)
+ if (ret || !dma->tx_running)
serial8250_set_THRI(p);
spin_unlock_irqrestore(&p->port.lock, flags);
@@ -80,12 +80,13 @@ int serial8250_tx_dma(struct uart_8250_port *p)
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
/* We have been called from __dma_tx_complete() */
- serial8250_rpm_put_tx(p);
return 0;
}
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+ serial8250_do_prepare_tx_dma(p);
+
desc = dmaengine_prep_slave_single(dma->txchan,
dma->tx_addr + xmit->tail,
dma->tx_size, DMA_MEM_TO_DEV,
@@ -123,6 +124,8 @@ int serial8250_rx_dma(struct uart_8250_port *p)
if (dma->rx_running)
return 0;
+ serial8250_do_prepare_rx_dma(p);
+
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
dma->rx_size, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 1769808031c5..f57bbd32ef11 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -12,13 +12,13 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/workqueue.h>
#include <linux/notifier.h>
#include <linux/slab.h>
@@ -33,30 +33,28 @@
/* Offsets for the DesignWare specific registers */
#define DW_UART_USR 0x1f /* UART Status Register */
+#define DW_UART_DMASA 0xa8 /* DMA Software Ack */
+
+#define OCTEON_UART_USR 0x27 /* UART Status Register */
+
+#define RZN1_UART_TDMACR 0x10c /* DMA Control Register Transmit Mode */
+#define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */
/* DesignWare specific register fields */
#define DW_UART_MCR_SIRE BIT(6)
-struct dw8250_data {
- struct dw8250_port_data data;
+/* Renesas specific register fields */
+#define RZN1_UART_xDMACR_DMA_EN BIT(0)
+#define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1)
+#define RZN1_UART_xDMACR_4_WORD_BURST (1 << 1)
+#define RZN1_UART_xDMACR_8_WORD_BURST (3 << 1)
+#define RZN1_UART_xDMACR_BLK_SZ(x) ((x) << 3)
- u8 usr_reg;
- int msr_mask_on;
- int msr_mask_off;
- struct clk *clk;
- struct clk *pclk;
- struct notifier_block clk_notifier;
- struct work_struct clk_work;
- struct reset_control *rst;
-
- unsigned int skip_autocfg:1;
- unsigned int uart_16550_compatible:1;
-};
-
-static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
-{
- return container_of(data, struct dw8250_data, data);
-}
+/* Quirks */
+#define DW_UART_QUIRK_OCTEON BIT(0)
+#define DW_UART_QUIRK_ARMADA_38X BIT(1)
+#define DW_UART_QUIRK_SKIP_SET_RATE BIT(2)
+#define DW_UART_QUIRK_IS_DMA_FC BIT(3)
static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
{
@@ -238,6 +236,8 @@ static int dw8250_handle_irq(struct uart_port *p)
struct uart_8250_port *up = up_to_u8250p(p);
struct dw8250_data *d = to_dw8250_data(p->private_data);
unsigned int iir = p->serial_in(p, UART_IIR);
+ bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT;
+ unsigned int quirks = d->pdata->quirks;
unsigned int status;
unsigned long flags;
@@ -251,7 +251,7 @@ static int dw8250_handle_irq(struct uart_port *p)
* This problem has only been observed so far when not in DMA mode
* so we limit the workaround only to non-DMA mode.
*/
- if (!up->dma && ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)) {
+ if (!up->dma && rx_timeout) {
spin_lock_irqsave(&p->lock, flags);
status = p->serial_in(p, UART_LSR);
@@ -261,12 +261,21 @@ static int dw8250_handle_irq(struct uart_port *p)
spin_unlock_irqrestore(&p->lock, flags);
}
+ /* Manually stop the Rx DMA transfer when acting as flow controller */
+ if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) {
+ status = p->serial_in(p, UART_LSR);
+ if (status & (UART_LSR_DR | UART_LSR_BI)) {
+ dw8250_writel_ext(p, RZN1_UART_RDMACR, 0);
+ dw8250_writel_ext(p, DW_UART_DMASA, 1);
+ }
+ }
+
if (serial8250_handle_irq(p, iir))
return 1;
if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
/* Clear the USR */
- (void)p->serial_in(p, d->usr_reg);
+ (void)p->serial_in(p, d->pdata->usr_reg);
return 1;
}
@@ -384,11 +393,48 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
return param == chan->device->dev;
}
+static u32 dw8250_rzn1_get_dmacr_burst(int max_burst)
+{
+ if (max_burst >= 8)
+ return RZN1_UART_xDMACR_8_WORD_BURST;
+ else if (max_burst >= 4)
+ return RZN1_UART_xDMACR_4_WORD_BURST;
+ else
+ return RZN1_UART_xDMACR_1_WORD_BURST;
+}
+
+static void dw8250_prepare_tx_dma(struct uart_8250_port *p)
+{
+ struct uart_port *up = &p->port;
+ struct uart_8250_dma *dma = p->dma;
+ u32 val;
+
+ dw8250_writel_ext(up, RZN1_UART_TDMACR, 0);
+ val = dw8250_rzn1_get_dmacr_burst(dma->txconf.dst_maxburst) |
+ RZN1_UART_xDMACR_BLK_SZ(dma->tx_size) |
+ RZN1_UART_xDMACR_DMA_EN;
+ dw8250_writel_ext(up, RZN1_UART_TDMACR, val);
+}
+
+static void dw8250_prepare_rx_dma(struct uart_8250_port *p)
+{
+ struct uart_port *up = &p->port;
+ struct uart_8250_dma *dma = p->dma;
+ u32 val;
+
+ dw8250_writel_ext(up, RZN1_UART_RDMACR, 0);
+ val = dw8250_rzn1_get_dmacr_burst(dma->rxconf.src_maxburst) |
+ RZN1_UART_xDMACR_BLK_SZ(dma->rx_size) |
+ RZN1_UART_xDMACR_DMA_EN;
+ dw8250_writel_ext(up, RZN1_UART_RDMACR, val);
+}
+
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
{
struct device_node *np = p->dev->of_node;
if (np) {
+ unsigned int quirks = data->pdata->quirks;
int id;
/* get index of serial line, if found in DT aliases */
@@ -396,12 +442,11 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
if (id >= 0)
p->line = id;
#ifdef CONFIG_64BIT
- if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
+ if (quirks & DW_UART_QUIRK_OCTEON) {
p->serial_in = dw8250_serial_inq;
p->serial_out = dw8250_serial_outq;
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
p->type = PORT_OCTEON;
- data->usr_reg = 0x27;
data->skip_autocfg = true;
}
#endif
@@ -412,10 +457,16 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
p->serial_out = dw8250_serial_out32be;
}
- if (of_device_is_compatible(np, "marvell,armada-38x-uart"))
+ if (quirks & DW_UART_QUIRK_ARMADA_38X)
p->serial_out = dw8250_serial_out38x;
- if (of_device_is_compatible(np, "starfive,jh7100-uart"))
+ if (quirks & DW_UART_QUIRK_SKIP_SET_RATE)
p->set_termios = dw8250_do_set_termios;
+ if (quirks & DW_UART_QUIRK_IS_DMA_FC) {
+ data->data.dma.txconf.device_fc = 1;
+ data->data.dma.rxconf.device_fc = 1;
+ data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma;
+ data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma;
+ }
} else if (acpi_dev_present("APMC0D08", NULL, -1)) {
p->iotype = UPIO_MEM32;
@@ -433,21 +484,30 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
}
}
+static void dw8250_clk_disable_unprepare(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+static void dw8250_reset_control_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
static int dw8250_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {}, *up = &uart;
- struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct uart_port *p = &up->port;
struct device *dev = &pdev->dev;
struct dw8250_data *data;
+ struct resource *regs;
int irq;
int err;
u32 val;
- if (!regs) {
- dev_err(dev, "no registers defined\n");
- return -EINVAL;
- }
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs)
+ return dev_err_probe(dev, -EINVAL, "no registers defined\n");
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -476,7 +536,7 @@ static int dw8250_probe(struct platform_device *pdev)
return -ENOMEM;
data->data.dma.fn = dw8250_fallback_dma_filter;
- data->usr_reg = DW_UART_USR;
+ data->pdata = device_get_match_data(p->dev);
p->private_data = &data->data;
data->uart_16550_compatible = device_property_read_bool(dev,
@@ -532,37 +592,41 @@ static int dw8250_probe(struct platform_device *pdev)
err = clk_prepare_enable(data->clk);
if (err)
- dev_warn(dev, "could not enable optional baudclk: %d\n", err);
+ return dev_err_probe(dev, err, "could not enable optional baudclk\n");
+
+ err = devm_add_action_or_reset(dev, dw8250_clk_disable_unprepare, data->clk);
+ if (err)
+ return err;
if (data->clk)
p->uartclk = clk_get_rate(data->clk);
/* If no clock rate is defined, fail. */
- if (!p->uartclk) {
- dev_err(dev, "clock rate not defined\n");
- err = -EINVAL;
- goto err_clk;
- }
+ if (!p->uartclk)
+ return dev_err_probe(dev, -EINVAL, "clock rate not defined\n");
data->pclk = devm_clk_get_optional(dev, "apb_pclk");
- if (IS_ERR(data->pclk)) {
- err = PTR_ERR(data->pclk);
- goto err_clk;
- }
+ if (IS_ERR(data->pclk))
+ return PTR_ERR(data->pclk);
err = clk_prepare_enable(data->pclk);
- if (err) {
- dev_err(dev, "could not enable apb_pclk\n");
- goto err_clk;
- }
+ if (err)
+ return dev_err_probe(dev, err, "could not enable apb_pclk\n");
+
+ err = devm_add_action_or_reset(dev, dw8250_clk_disable_unprepare, data->pclk);
+ if (err)
+ return err;
data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
- if (IS_ERR(data->rst)) {
- err = PTR_ERR(data->rst);
- goto err_pclk;
- }
+ if (IS_ERR(data->rst))
+ return PTR_ERR(data->rst);
+
reset_control_deassert(data->rst);
+ err = devm_add_action_or_reset(dev, dw8250_reset_control_assert, data->rst);
+ if (err)
+ return err;
+
dw8250_quirks(p, data);
/* If the Busy Functionality is not implemented, don't handle it */
@@ -580,10 +644,8 @@ static int dw8250_probe(struct platform_device *pdev)
}
data->data.line = serial8250_register_8250_port(up);
- if (data->data.line < 0) {
- err = data->data.line;
- goto err_reset;
- }
+ if (data->data.line < 0)
+ return data->data.line;
/*
* Some platforms may provide a reference clock shared between several
@@ -593,9 +655,8 @@ static int dw8250_probe(struct platform_device *pdev)
if (data->clk) {
err = clk_notifier_register(data->clk, &data->clk_notifier);
if (err)
- dev_warn(p->dev, "Failed to set the clock notifier\n");
- else
- queue_work(system_unbound_wq, &data->clk_work);
+ return dev_err_probe(dev, err, "Failed to set the clock notifier\n");
+ queue_work(system_unbound_wq, &data->clk_work);
}
platform_set_drvdata(pdev, data);
@@ -604,17 +665,6 @@ static int dw8250_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
return 0;
-
-err_reset:
- reset_control_assert(data->rst);
-
-err_pclk:
- clk_disable_unprepare(data->pclk);
-
-err_clk:
- clk_disable_unprepare(data->clk);
-
- return err;
}
static int dw8250_remove(struct platform_device *pdev)
@@ -632,12 +682,6 @@ static int dw8250_remove(struct platform_device *pdev)
serial8250_unregister_port(data->data.line);
- reset_control_assert(data->rst);
-
- clk_disable_unprepare(data->pclk);
-
- clk_disable_unprepare(data->clk);
-
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
@@ -693,12 +737,37 @@ static const struct dev_pm_ops dw8250_pm_ops = {
SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
};
+static const struct dw8250_platform_data dw8250_dw_apb = {
+ .usr_reg = DW_UART_USR,
+};
+
+static const struct dw8250_platform_data dw8250_octeon_3860_data = {
+ .usr_reg = OCTEON_UART_USR,
+ .quirks = DW_UART_QUIRK_OCTEON,
+};
+
+static const struct dw8250_platform_data dw8250_armada_38x_data = {
+ .usr_reg = DW_UART_USR,
+ .quirks = DW_UART_QUIRK_ARMADA_38X,
+};
+
+static const struct dw8250_platform_data dw8250_renesas_rzn1_data = {
+ .usr_reg = DW_UART_USR,
+ .cpr_val = 0x00012f32,
+ .quirks = DW_UART_QUIRK_IS_DMA_FC,
+};
+
+static const struct dw8250_platform_data dw8250_starfive_jh7100_data = {
+ .usr_reg = DW_UART_USR,
+ .quirks = DW_UART_QUIRK_SKIP_SET_RATE,
+};
+
static const struct of_device_id dw8250_of_match[] = {
- { .compatible = "snps,dw-apb-uart" },
- { .compatible = "cavium,octeon-3860-uart" },
- { .compatible = "marvell,armada-38x-uart" },
- { .compatible = "renesas,rzn1-uart" },
- { .compatible = "starfive,jh7100-uart" },
+ { .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
+ { .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
+ { .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
+ { .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
+ { .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dw8250_of_match);
diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index 622d3b0d89e7..fbabfdd8c7b8 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -2,19 +2,32 @@
/* Synopsys DesignWare 8250 library. */
#include <linux/bitops.h>
+#include <linux/bitfield.h>
#include <linux/device.h>
-#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/property.h>
#include <linux/serial_8250.h>
#include <linux/serial_core.h>
#include "8250_dwlib.h"
/* Offsets for the DesignWare specific registers */
+#define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */
+#define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */
+#define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */
#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
#define DW_UART_UCV 0xf8 /* UART Component Version */
+/* Transceiver Control Register bits */
+#define DW_UART_TCR_RS485_EN BIT(0)
+#define DW_UART_TCR_RE_POL BIT(1)
+#define DW_UART_TCR_DE_POL BIT(2)
+#define DW_UART_TCR_XFER_MODE GENMASK(4, 3)
+#define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0)
+#define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1)
+#define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2)
+
/* Component Parameter Register bits */
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
#define DW_UART_CPR_AFCE_MODE (1 << 4)
@@ -32,21 +45,6 @@
/* Helper for FIFO size calculation */
#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16)
-static inline u32 dw8250_readl_ext(struct uart_port *p, int offset)
-{
- if (p->iotype == UPIO_MEM32BE)
- return ioread32be(p->membase + offset);
- return readl(p->membase + offset);
-}
-
-static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg)
-{
- if (p->iotype == UPIO_MEM32BE)
- iowrite32be(reg, p->membase + offset);
- else
- writel(reg, p->membase + offset);
-}
-
/*
* divisor = div(I) + div(F)
* "I" means integer, "F" means fractional
@@ -87,11 +85,87 @@ void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct
}
EXPORT_SYMBOL_GPL(dw8250_do_set_termios);
+static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485)
+{
+ u32 tcr;
+
+ tcr = dw8250_readl_ext(p, DW_UART_TCR);
+ tcr &= ~DW_UART_TCR_XFER_MODE;
+
+ if (rs485->flags & SER_RS485_ENABLED) {
+ /* Clear unsupported flags. */
+ rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX |
+ SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND;
+ tcr |= DW_UART_TCR_RS485_EN;
+
+ if (rs485->flags & SER_RS485_RX_DURING_TX) {
+ tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE;
+ } else {
+ /* HW does not support same DE level for tx and rx */
+ if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
+ !(rs485->flags & SER_RS485_RTS_AFTER_SEND))
+ return -EINVAL;
+
+ tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE;
+ }
+ dw8250_writel_ext(p, DW_UART_DE_EN, 1);
+ dw8250_writel_ext(p, DW_UART_RE_EN, 1);
+ } else {
+ rs485->flags = 0;
+
+ tcr &= ~DW_UART_TCR_RS485_EN;
+ }
+
+ /* Reset to default polarity */
+ tcr |= DW_UART_TCR_DE_POL;
+ tcr &= ~DW_UART_TCR_RE_POL;
+
+ if (!(rs485->flags & SER_RS485_RTS_ON_SEND))
+ tcr &= ~DW_UART_TCR_DE_POL;
+ if (device_property_read_bool(p->dev, "rs485-rx-active-high"))
+ tcr |= DW_UART_TCR_RE_POL;
+
+ dw8250_writel_ext(p, DW_UART_TCR, tcr);
+
+ rs485->delay_rts_before_send = 0;
+ rs485->delay_rts_after_send = 0;
+
+ p->rs485 = *rs485;
+
+ return 0;
+}
+
+/*
+ * Tests if RE_EN register can have non-zero value to see if RS-485 HW support
+ * is present.
+ */
+static bool dw8250_detect_rs485_hw(struct uart_port *p)
+{
+ u32 reg;
+
+ dw8250_writel_ext(p, DW_UART_RE_EN, 1);
+ reg = dw8250_readl_ext(p, DW_UART_RE_EN);
+ dw8250_writel_ext(p, DW_UART_RE_EN, 0);
+ return reg;
+}
+
void dw8250_setup_port(struct uart_port *p)
{
+ struct dw8250_port_data *pd = p->private_data;
+ struct dw8250_data *data = to_dw8250_data(pd);
struct uart_8250_port *up = up_to_u8250p(p);
u32 reg;
+ pd->hw_rs485_support = dw8250_detect_rs485_hw(p);
+ if (pd->hw_rs485_support) {
+ p->rs485_config = dw8250_rs485_config;
+ } else {
+ p->rs485_config = serial8250_em485_config;
+ up->rs485_start_tx = serial8250_em485_start_tx;
+ up->rs485_stop_tx = serial8250_em485_stop_tx;
+ }
+ up->capabilities |= UART_CAP_NOTEMT;
+
/*
* If the Component Version Register returns zero, we know that
* ADDITIONAL_FEATURES are not enabled. No need to go any further.
@@ -108,14 +182,16 @@ void dw8250_setup_port(struct uart_port *p)
dw8250_writel_ext(p, DW_UART_DLF, 0);
if (reg) {
- struct dw8250_port_data *d = p->private_data;
-
- d->dlf_size = fls(reg);
+ pd->dlf_size = fls(reg);
p->get_divisor = dw8250_get_divisor;
p->set_divisor = dw8250_set_divisor;
}
reg = dw8250_readl_ext(p, DW_UART_CPR);
+ if (!reg) {
+ reg = data->pdata->cpr_val;
+ dev_dbg(p->dev, "CPR is not available, using 0x%08x instead\n", reg);
+ }
if (!reg)
return;
@@ -124,7 +200,7 @@ void dw8250_setup_port(struct uart_port *p)
p->type = PORT_16550A;
p->flags |= UPF_FIXED_TYPE;
p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
- up->capabilities = UART_CAP_FIFO;
+ up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT;
}
if (reg & DW_UART_CPR_AFCE_MODE)
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index 83d528e5cc21..055bfdc87985 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -1,10 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Synopsys DesignWare 8250 library header file. */
+#include <linux/io.h>
+#include <linux/notifier.h>
#include <linux/types.h>
+#include <linux/workqueue.h>
#include "8250.h"
+struct clk;
+struct reset_control;
+
struct dw8250_port_data {
/* Port properties */
int line;
@@ -14,7 +20,52 @@ struct dw8250_port_data {
/* Hardware configuration */
u8 dlf_size;
+
+ /* RS485 variables */
+ bool hw_rs485_support;
+};
+
+struct dw8250_platform_data {
+ u8 usr_reg;
+ u32 cpr_val;
+ unsigned int quirks;
+};
+
+struct dw8250_data {
+ struct dw8250_port_data data;
+ const struct dw8250_platform_data *pdata;
+
+ int msr_mask_on;
+ int msr_mask_off;
+ struct clk *clk;
+ struct clk *pclk;
+ struct notifier_block clk_notifier;
+ struct work_struct clk_work;
+ struct reset_control *rst;
+
+ unsigned int skip_autocfg:1;
+ unsigned int uart_16550_compatible:1;
};
void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);
void dw8250_setup_port(struct uart_port *p);
+
+static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
+{
+ return container_of(data, struct dw8250_data, data);
+}
+
+static inline u32 dw8250_readl_ext(struct uart_port *p, int offset)
+{
+ if (p->iotype == UPIO_MEM32BE)
+ return ioread32be(p->membase + offset);
+ return readl(p->membase + offset);
+}
+
+static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg)
+{
+ if (p->iotype == UPIO_MEM32BE)
+ iowrite32be(reg, p->membase + offset);
+ else
+ writel(reg, p->membase + offset);
+}
diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c
index 251f0018ae8c..dba5950b8d0e 100644
--- a/drivers/tty/serial/8250/8250_fintek.c
+++ b/drivers/tty/serial/8250/8250_fintek.c
@@ -200,12 +200,12 @@ static int fintek_8250_rs485_config(struct uart_port *port,
if (!pdata)
return -EINVAL;
- /* Hardware do not support same RTS level on send and receive */
- if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
- !(rs485->flags & SER_RS485_RTS_AFTER_SEND))
- return -EINVAL;
if (rs485->flags & SER_RS485_ENABLED) {
+ /* Hardware do not support same RTS level on send and receive */
+ if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
+ !(rs485->flags & SER_RS485_RTS_AFTER_SEND))
+ return -EINVAL;
memset(rs485->padding, 0, sizeof(rs485->padding));
config |= RS485_URA;
} else {
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 21053db93ff1..54051ec7b499 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -54,9 +54,6 @@
#define MTK_UART_TX_TRIGGER 1
#define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
-#define MTK_UART_FEATURE_SEL 39 /* Feature Selection register */
-#define MTK_UART_FEAT_NEWRMAP BIT(0) /* Use new register map */
-
#define MTK_UART_XON1 40 /* I/O: Xon character 1 */
#define MTK_UART_XOFF1 42 /* I/O: Xoff character 1 */
@@ -575,10 +572,6 @@ static int mtk8250_probe(struct platform_device *pdev)
uart.dma = data->dma;
#endif
- /* Set AP UART new register map */
- writel(MTK_UART_FEAT_NEWRMAP, uart.port.membase +
- (MTK_UART_FEATURE_SEL << uart.port.regshift));
-
/* Disable Rate Fix function */
writel(0x0, uart.port.membase +
(MTK_UART_RATE_FIX << uart.port.regshift));
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index be8626234627..5a699a1aa79c 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -326,6 +326,8 @@ static const struct of_device_id of_platform_serial_table[] = {
.data = (void *)PORT_ALTR_16550_F64, },
{ .compatible = "altr,16550-FIFO128",
.data = (void *)PORT_ALTR_16550_F128, },
+ { .compatible = "fsl,16550-FIFO64",
+ .data = (void *)PORT_16550A_FSL64, },
{ .compatible = "mediatek,mtk-btif",
.data = (void *)PORT_MTK_BTIF, },
{ .compatible = "mrvl,mmp-uart",
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index a293e9f107d0..a17619db7939 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/math.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/tty.h>
@@ -994,41 +995,29 @@ static void pci_ite887x_exit(struct pci_dev *dev)
}
/*
- * EndRun Technologies.
- * Determine the number of ports available on the device.
+ * Oxford Semiconductor Inc.
+ * Check if an OxSemi device is part of the Tornado range of devices.
*/
#define PCI_VENDOR_ID_ENDRUN 0x7401
#define PCI_DEVICE_ID_ENDRUN_1588 0xe100
-static int pci_endrun_init(struct pci_dev *dev)
+static bool pci_oxsemi_tornado_p(struct pci_dev *dev)
{
- u8 __iomem *p;
- unsigned long deviceID;
- unsigned int number_uarts = 0;
+ /* OxSemi Tornado devices are all 0xCxxx */
+ if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
+ (dev->device & 0xf000) != 0xc000)
+ return false;
- /* EndRun device is all 0xexxx */
+ /* EndRun devices are all 0xExxx */
if (dev->vendor == PCI_VENDOR_ID_ENDRUN &&
- (dev->device & 0xf000) != 0xe000)
- return 0;
-
- p = pci_iomap(dev, 0, 5);
- if (p == NULL)
- return -ENOMEM;
+ (dev->device & 0xf000) != 0xe000)
+ return false;
- deviceID = ioread32(p);
- /* EndRun device */
- if (deviceID == 0x07000200) {
- number_uarts = ioread8(p + 4);
- pci_dbg(dev, "%d ports detected on EndRun PCI Express device\n", number_uarts);
- }
- pci_iounmap(dev, p);
- return number_uarts;
+ return true;
}
/*
- * Oxford Semiconductor Inc.
- * Check that device is part of the Tornado range of devices, then determine
- * the number of ports available on the device.
+ * Determine the number of ports available on a Tornado device.
*/
static int pci_oxsemi_tornado_init(struct pci_dev *dev)
{
@@ -1036,9 +1025,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
unsigned long deviceID;
unsigned int number_uarts = 0;
- /* OxSemi Tornado devices are all 0xCxxx */
- if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
- (dev->device & 0xF000) != 0xC000)
+ if (!pci_oxsemi_tornado_p(dev))
return 0;
p = pci_iomap(dev, 0, 5);
@@ -1049,12 +1036,217 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
/* Tornado device */
if (deviceID == 0x07000200) {
number_uarts = ioread8(p + 4);
- pci_dbg(dev, "%d ports detected on Oxford PCI Express device\n", number_uarts);
+ pci_dbg(dev, "%d ports detected on %s PCI Express device\n",
+ number_uarts,
+ dev->vendor == PCI_VENDOR_ID_ENDRUN ?
+ "EndRun" : "Oxford");
}
pci_iounmap(dev, p);
return number_uarts;
}
+/* Tornado-specific constants for the TCR and CPR registers; see below. */
+#define OXSEMI_TORNADO_TCR_MASK 0xf
+#define OXSEMI_TORNADO_CPR_MASK 0x1ff
+#define OXSEMI_TORNADO_CPR_MIN 0x008
+#define OXSEMI_TORNADO_CPR_DEF 0x10f
+
+/*
+ * Determine the oversampling rate, the clock prescaler, and the clock
+ * divisor for the requested baud rate. The clock rate is 62.5 MHz,
+ * which is four times the baud base, and the prescaler increments in
+ * steps of 1/8. Therefore to make calculations on integers we need
+ * to use a scaled clock rate, which is the baud base multiplied by 32
+ * (or our assumed UART clock rate multiplied by 2).
+ *
+ * The allowed oversampling rates are from 4 up to 16 inclusive (values
+ * from 0 to 3 inclusive map to 16). Likewise the clock prescaler allows
+ * values between 1.000 and 63.875 inclusive (operation for values from
+ * 0.000 to 0.875 has not been specified). The clock divisor is the usual
+ * unsigned 16-bit integer.
+ *
+ * For the most accurate baud rate we use a table of predetermined
+ * oversampling rates and clock prescalers that records all possible
+ * products of the two parameters in the range from 4 up to 255 inclusive,
+ * and additionally 335 for the 1500000bps rate, with the prescaler scaled
+ * by 8. The table is sorted by the decreasing value of the oversampling
+ * rate and ties are resolved by sorting by the decreasing value of the
+ * product. This way preference is given to higher oversampling rates.
+ *
+ * We iterate over the table and choose the product of an oversampling
+ * rate and a clock prescaler that gives the lowest integer division
+ * result deviation, or if an exact integer divider is found we stop
+ * looking for it right away. We do some fixup if the resulting clock
+ * divisor required would be out of its unsigned 16-bit integer range.
+ *
+ * Finally we abuse the supposed fractional part returned to encode the
+ * 4-bit value of the oversampling rate and the 9-bit value of the clock
+ * prescaler which will end up in the TCR and CPR/CPR2 registers.
+ */
+static unsigned int pci_oxsemi_tornado_get_divisor(struct uart_port *port,
+ unsigned int baud,
+ unsigned int *frac)
+{
+ static u8 p[][2] = {
+ { 16, 14, }, { 16, 13, }, { 16, 12, }, { 16, 11, },
+ { 16, 10, }, { 16, 9, }, { 16, 8, }, { 15, 17, },
+ { 15, 16, }, { 15, 15, }, { 15, 14, }, { 15, 13, },
+ { 15, 12, }, { 15, 11, }, { 15, 10, }, { 15, 9, },
+ { 15, 8, }, { 14, 18, }, { 14, 17, }, { 14, 14, },
+ { 14, 13, }, { 14, 12, }, { 14, 11, }, { 14, 10, },
+ { 14, 9, }, { 14, 8, }, { 13, 19, }, { 13, 18, },
+ { 13, 17, }, { 13, 13, }, { 13, 12, }, { 13, 11, },
+ { 13, 10, }, { 13, 9, }, { 13, 8, }, { 12, 19, },
+ { 12, 18, }, { 12, 17, }, { 12, 11, }, { 12, 9, },
+ { 12, 8, }, { 11, 23, }, { 11, 22, }, { 11, 21, },
+ { 11, 20, }, { 11, 19, }, { 11, 18, }, { 11, 17, },
+ { 11, 11, }, { 11, 10, }, { 11, 9, }, { 11, 8, },
+ { 10, 25, }, { 10, 23, }, { 10, 20, }, { 10, 19, },
+ { 10, 17, }, { 10, 10, }, { 10, 9, }, { 10, 8, },
+ { 9, 27, }, { 9, 23, }, { 9, 21, }, { 9, 19, },
+ { 9, 18, }, { 9, 17, }, { 9, 9, }, { 9, 8, },
+ { 8, 31, }, { 8, 29, }, { 8, 23, }, { 8, 19, },
+ { 8, 17, }, { 8, 8, }, { 7, 35, }, { 7, 31, },
+ { 7, 29, }, { 7, 25, }, { 7, 23, }, { 7, 21, },
+ { 7, 19, }, { 7, 17, }, { 7, 15, }, { 7, 14, },
+ { 7, 13, }, { 7, 12, }, { 7, 11, }, { 7, 10, },
+ { 7, 9, }, { 7, 8, }, { 6, 41, }, { 6, 37, },
+ { 6, 31, }, { 6, 29, }, { 6, 23, }, { 6, 19, },
+ { 6, 17, }, { 6, 13, }, { 6, 11, }, { 6, 10, },
+ { 6, 9, }, { 6, 8, }, { 5, 67, }, { 5, 47, },
+ { 5, 43, }, { 5, 41, }, { 5, 37, }, { 5, 31, },
+ { 5, 29, }, { 5, 25, }, { 5, 23, }, { 5, 19, },
+ { 5, 17, }, { 5, 15, }, { 5, 13, }, { 5, 11, },
+ { 5, 10, }, { 5, 9, }, { 5, 8, }, { 4, 61, },
+ { 4, 59, }, { 4, 53, }, { 4, 47, }, { 4, 43, },
+ { 4, 41, }, { 4, 37, }, { 4, 31, }, { 4, 29, },
+ { 4, 23, }, { 4, 19, }, { 4, 17, }, { 4, 13, },
+ { 4, 9, }, { 4, 8, },
+ };
+ /* Scale the quotient for comparison to get the fractional part. */
+ const unsigned int quot_scale = 65536;
+ unsigned int sclk = port->uartclk * 2;
+ unsigned int sdiv = DIV_ROUND_CLOSEST(sclk, baud);
+ unsigned int best_squot;
+ unsigned int squot;
+ unsigned int quot;
+ u16 cpr;
+ u8 tcr;
+ int i;
+
+ /* Old custom speed handling. */
+ if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
+ unsigned int cust_div = port->custom_divisor;
+
+ quot = cust_div & UART_DIV_MAX;
+ tcr = (cust_div >> 16) & OXSEMI_TORNADO_TCR_MASK;
+ cpr = (cust_div >> 20) & OXSEMI_TORNADO_CPR_MASK;
+ if (cpr < OXSEMI_TORNADO_CPR_MIN)
+ cpr = OXSEMI_TORNADO_CPR_DEF;
+ } else {
+ best_squot = quot_scale;
+ for (i = 0; i < ARRAY_SIZE(p); i++) {
+ unsigned int spre;
+ unsigned int srem;
+ u8 cp;
+ u8 tc;
+
+ tc = p[i][0];
+ cp = p[i][1];
+ spre = tc * cp;
+
+ srem = sdiv % spre;
+ if (srem > spre / 2)
+ srem = spre - srem;
+ squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre);
+
+ if (srem == 0) {
+ tcr = tc;
+ cpr = cp;
+ quot = sdiv / spre;
+ break;
+ } else if (squot < best_squot) {
+ best_squot = squot;
+ tcr = tc;
+ cpr = cp;
+ quot = DIV_ROUND_CLOSEST(sdiv, spre);
+ }
+ }
+ while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 &&
+ quot % 2 == 0) {
+ quot >>= 1;
+ tcr <<= 1;
+ }
+ while (quot > UART_DIV_MAX) {
+ if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) {
+ quot >>= 1;
+ tcr <<= 1;
+ } else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) {
+ quot >>= 1;
+ cpr <<= 1;
+ } else {
+ quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK;
+ cpr = OXSEMI_TORNADO_CPR_MASK;
+ }
+ }
+ }
+
+ *frac = (cpr << 8) | (tcr & OXSEMI_TORNADO_TCR_MASK);
+ return quot;
+}
+
+/*
+ * Set the oversampling rate in the transmitter clock cycle register (TCR),
+ * the clock prescaler in the clock prescaler register (CPR and CPR2), and
+ * the clock divisor in the divisor latch (DLL and DLM). Note that for
+ * backwards compatibility any write to CPR clears CPR2 and therefore CPR
+ * has to be written first, followed by CPR2, which occupies the location
+ * of CKS used with earlier UART designs.
+ */
+static void pci_oxsemi_tornado_set_divisor(struct uart_port *port,
+ unsigned int baud,
+ unsigned int quot,
+ unsigned int quot_frac)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ u8 cpr2 = quot_frac >> 16;
+ u8 cpr = quot_frac >> 8;
+ u8 tcr = quot_frac;
+
+ serial_icr_write(up, UART_TCR, tcr);
+ serial_icr_write(up, UART_CPR, cpr);
+ serial_icr_write(up, UART_CKS, cpr2);
+ serial8250_do_set_divisor(port, baud, quot, 0);
+}
+
+/*
+ * For Tornado devices we force MCR[7] set for the Divide-by-M N/8 baud rate
+ * generator prescaler (CPR and CPR2). Otherwise no prescaler would be used.
+ */
+static void pci_oxsemi_tornado_set_mctrl(struct uart_port *port,
+ unsigned int mctrl)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ up->mcr |= UART_MCR_CLKSEL;
+ serial8250_do_set_mctrl(port, mctrl);
+}
+
+static int pci_oxsemi_tornado_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *up, int idx)
+{
+ struct pci_dev *dev = priv->dev;
+
+ if (pci_oxsemi_tornado_p(dev)) {
+ up->port.get_divisor = pci_oxsemi_tornado_get_divisor;
+ up->port.set_divisor = pci_oxsemi_tornado_set_divisor;
+ up->port.set_mctrl = pci_oxsemi_tornado_set_mctrl;
+ }
+
+ return pci_default_setup(priv, board, up, idx);
+}
+
static int pci_asix_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
@@ -2244,7 +2436,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .init = pci_endrun_init,
+ .init = pci_oxsemi_tornado_init,
.setup = pci_default_setup,
},
/*
@@ -2256,7 +2448,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_oxsemi_tornado_init,
- .setup = pci_default_setup,
+ .setup = pci_oxsemi_tornado_setup,
},
{
.vendor = PCI_VENDOR_ID_MAINPINE,
@@ -2264,7 +2456,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_oxsemi_tornado_init,
- .setup = pci_default_setup,
+ .setup = pci_oxsemi_tornado_setup,
},
{
.vendor = PCI_VENDOR_ID_DIGI,
@@ -2272,7 +2464,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.subvendor = PCI_SUBVENDOR_ID_IBM,
.subdevice = PCI_ANY_ID,
.init = pci_oxsemi_tornado_init,
- .setup = pci_default_setup,
+ .setup = pci_oxsemi_tornado_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
@@ -2589,7 +2781,7 @@ enum pci_board_num_t {
pbn_b0_2_1843200,
pbn_b0_4_1843200,
- pbn_b0_1_3906250,
+ pbn_b0_1_15625000,
pbn_b0_bt_1_115200,
pbn_b0_bt_2_115200,
@@ -2667,12 +2859,11 @@ enum pci_board_num_t {
pbn_panacom2,
pbn_panacom4,
pbn_plx_romulus,
- pbn_endrun_2_3906250,
pbn_oxsemi,
- pbn_oxsemi_1_3906250,
- pbn_oxsemi_2_3906250,
- pbn_oxsemi_4_3906250,
- pbn_oxsemi_8_3906250,
+ pbn_oxsemi_1_15625000,
+ pbn_oxsemi_2_15625000,
+ pbn_oxsemi_4_15625000,
+ pbn_oxsemi_8_15625000,
pbn_intel_i960,
pbn_sgi_ioc3,
pbn_computone_4,
@@ -2815,10 +3006,10 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 8,
},
- [pbn_b0_1_3906250] = {
+ [pbn_b0_1_15625000] = {
.flags = FL_BASE0,
.num_ports = 1,
- .base_baud = 3906250,
+ .base_baud = 15625000,
.uart_offset = 8,
},
@@ -3190,20 +3381,6 @@ static struct pciserial_board pci_boards[] = {
},
/*
- * EndRun Technologies
- * Uses the size of PCI Base region 0 to
- * signal now many ports are available
- * 2 port 952 Uart support
- */
- [pbn_endrun_2_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
-
- /*
* This board uses the size of PCI Base region 0 to
* signal now many ports are available
*/
@@ -3213,31 +3390,31 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 115200,
.uart_offset = 8,
},
- [pbn_oxsemi_1_3906250] = {
+ [pbn_oxsemi_1_15625000] = {
.flags = FL_BASE0,
.num_ports = 1,
- .base_baud = 3906250,
+ .base_baud = 15625000,
.uart_offset = 0x200,
.first_offset = 0x1000,
},
- [pbn_oxsemi_2_3906250] = {
+ [pbn_oxsemi_2_15625000] = {
.flags = FL_BASE0,
.num_ports = 2,
- .base_baud = 3906250,
+ .base_baud = 15625000,
.uart_offset = 0x200,
.first_offset = 0x1000,
},
- [pbn_oxsemi_4_3906250] = {
+ [pbn_oxsemi_4_15625000] = {
.flags = FL_BASE0,
.num_ports = 4,
- .base_baud = 3906250,
+ .base_baud = 15625000,
.uart_offset = 0x200,
.first_offset = 0x1000,
},
- [pbn_oxsemi_8_3906250] = {
+ [pbn_oxsemi_8_15625000] = {
.flags = FL_BASE0,
.num_ports = 8,
- .base_baud = 3906250,
+ .base_baud = 15625000,
.uart_offset = 0x200,
.first_offset = 0x1000,
},
@@ -3518,6 +3695,12 @@ static struct pciserial_board pci_boards[] = {
},
};
+#define REPORT_CONFIG(option) \
+ (IS_ENABLED(CONFIG_##option) ? 0 : (kernel_ulong_t)&#option)
+#define REPORT_8250_CONFIG(option) \
+ (IS_ENABLED(CONFIG_SERIAL_8250_##option) ? \
+ 0 : (kernel_ulong_t)&"SERIAL_8250_"#option)
+
static const struct pci_device_id blacklist[] = {
/* softmodems */
{ PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
@@ -3525,40 +3708,43 @@ static const struct pci_device_id blacklist[] = {
{ PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
/* multi-io cards handled by parport_serial */
- { PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
- { PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
- { PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
+ /* WCH CH353 2S1P */
+ { PCI_DEVICE(0x4348, 0x7053), 0, 0, REPORT_CONFIG(PARPORT_SERIAL), },
+ /* WCH CH353 1S1P */
+ { PCI_DEVICE(0x4348, 0x5053), 0, 0, REPORT_CONFIG(PARPORT_SERIAL), },
+ /* WCH CH382 2S1P */
+ { PCI_DEVICE(0x1c00, 0x3250), 0, 0, REPORT_CONFIG(PARPORT_SERIAL), },
/* Intel platforms with MID UART */
- { PCI_VDEVICE(INTEL, 0x081b), },
- { PCI_VDEVICE(INTEL, 0x081c), },
- { PCI_VDEVICE(INTEL, 0x081d), },
- { PCI_VDEVICE(INTEL, 0x1191), },
- { PCI_VDEVICE(INTEL, 0x18d8), },
- { PCI_VDEVICE(INTEL, 0x19d8), },
+ { PCI_VDEVICE(INTEL, 0x081b), REPORT_8250_CONFIG(MID), },
+ { PCI_VDEVICE(INTEL, 0x081c), REPORT_8250_CONFIG(MID), },
+ { PCI_VDEVICE(INTEL, 0x081d), REPORT_8250_CONFIG(MID), },
+ { PCI_VDEVICE(INTEL, 0x1191), REPORT_8250_CONFIG(MID), },
+ { PCI_VDEVICE(INTEL, 0x18d8), REPORT_8250_CONFIG(MID), },
+ { PCI_VDEVICE(INTEL, 0x19d8), REPORT_8250_CONFIG(MID), },
/* Intel platforms with DesignWare UART */
- { PCI_VDEVICE(INTEL, 0x0936), },
- { PCI_VDEVICE(INTEL, 0x0f0a), },
- { PCI_VDEVICE(INTEL, 0x0f0c), },
- { PCI_VDEVICE(INTEL, 0x228a), },
- { PCI_VDEVICE(INTEL, 0x228c), },
- { PCI_VDEVICE(INTEL, 0x4b96), },
- { PCI_VDEVICE(INTEL, 0x4b97), },
- { PCI_VDEVICE(INTEL, 0x4b98), },
- { PCI_VDEVICE(INTEL, 0x4b99), },
- { PCI_VDEVICE(INTEL, 0x4b9a), },
- { PCI_VDEVICE(INTEL, 0x4b9b), },
- { PCI_VDEVICE(INTEL, 0x9ce3), },
- { PCI_VDEVICE(INTEL, 0x9ce4), },
+ { PCI_VDEVICE(INTEL, 0x0936), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x0f0a), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x0f0c), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x228a), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x228c), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x4b96), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x4b97), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x4b98), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x4b99), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x4b9a), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x4b9b), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x9ce3), REPORT_8250_CONFIG(LPSS), },
+ { PCI_VDEVICE(INTEL, 0x9ce4), REPORT_8250_CONFIG(LPSS), },
/* Exar devices */
- { PCI_VDEVICE(EXAR, PCI_ANY_ID), },
- { PCI_VDEVICE(COMMTECH, PCI_ANY_ID), },
+ { PCI_VDEVICE(EXAR, PCI_ANY_ID), REPORT_8250_CONFIG(EXAR), },
+ { PCI_VDEVICE(COMMTECH, PCI_ANY_ID), REPORT_8250_CONFIG(EXAR), },
/* Pericom devices */
- { PCI_VDEVICE(PERICOM, PCI_ANY_ID), },
- { PCI_VDEVICE(ACCESSIO, PCI_ANY_ID), },
+ { PCI_VDEVICE(PERICOM, PCI_ANY_ID), REPORT_8250_CONFIG(PERICOM), },
+ { PCI_VDEVICE(ACCESSIO, PCI_ANY_ID), REPORT_8250_CONFIG(PERICOM), },
/* End of the black list */
{ }
@@ -3840,8 +4026,12 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
board = &pci_boards[ent->driver_data];
exclude = pci_match_id(blacklist, dev);
- if (exclude)
+ if (exclude) {
+ if (exclude->driver_data)
+ pci_warn(dev, "ignoring port, enable %s to handle\n",
+ (const char *)exclude->driver_data);
return -ENODEV;
+ }
rc = pcim_enable_device(dev);
pci_save_state(dev);
@@ -4110,13 +4300,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
0x10b5, 0x106a, 0, 0,
pbn_plx_romulus },
/*
- * EndRun Technologies. PCI express device range.
- * EndRun PTP/1588 has 2 Native UARTs.
- */
- { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_endrun_2_3906250 },
- /*
* Quatech cards. These actually have configurable clocks but for
* now we just use the default.
*
@@ -4225,158 +4408,165 @@ static const struct pci_device_id serial_pci_tbl[] = {
*/
{ PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_3906250 },
+ pbn_b0_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_3906250 },
+ pbn_b0_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_3906250 },
+ pbn_b0_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_3906250 },
+ pbn_b0_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_3906250 },
+ pbn_b0_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_3906250 },
+ pbn_b0_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_3906250 },
+ pbn_b0_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_3906250 },
+ pbn_b0_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_3906250 },
+ pbn_oxsemi_2_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_3906250 },
+ pbn_oxsemi_2_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_3906250 },
+ pbn_oxsemi_4_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_3906250 },
+ pbn_oxsemi_4_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_3906250 },
+ pbn_oxsemi_8_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_3906250 },
+ pbn_oxsemi_8_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
/*
* Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
*/
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
- pbn_oxsemi_1_3906250 },
+ pbn_oxsemi_1_15625000 },
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
- pbn_oxsemi_2_3906250 },
+ pbn_oxsemi_2_15625000 },
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
- pbn_oxsemi_4_3906250 },
+ pbn_oxsemi_4_15625000 },
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
- pbn_oxsemi_8_3906250 },
+ pbn_oxsemi_8_15625000 },
/*
* Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
*/
{ PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_3906250 },
+ pbn_oxsemi_2_15625000 },
+ /*
+ * EndRun Technologies. PCI express device range.
+ * EndRun PTP/1588 has 2 Native UARTs utilizing OxSemi 952.
+ */
+ { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_15625000 },
/*
* SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 1fbd5bf264be..78b6dedc43e6 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -263,7 +263,7 @@ static const struct serial8250_config uart_config[] = {
.tx_loadsz = 63,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
UART_FCR7_64BYTE,
- .flags = UART_CAP_FIFO,
+ .flags = UART_CAP_FIFO | UART_CAP_NOTEMT,
},
[PORT_RT2880] = {
.name = "Palmchip BK-3103",
@@ -538,27 +538,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
}
/*
- * For the 16C950
- */
-static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
-{
- serial_out(up, UART_SCR, offset);
- serial_out(up, UART_ICR, value);
-}
-
-static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
-{
- unsigned int value;
-
- serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
- serial_out(up, UART_SCR, offset);
- value = serial_in(up, UART_ICR);
- serial_icr_write(up, UART_ACR, up->acr);
-
- return value;
-}
-
-/*
* FIFO support.
*/
static void serial8250_clear_fifos(struct uart_8250_port *p)
@@ -1504,18 +1483,19 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL);
}
-static void __stop_tx_rs485(struct uart_8250_port *p)
+static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay)
{
struct uart_8250_em485 *em485 = p->em485;
+ stop_delay += (u64)p->port.rs485.delay_rts_after_send * NSEC_PER_MSEC;
+
/*
* rs485_stop_tx() is going to set RTS according to config
* AND flush RX FIFO if required.
*/
- if (p->port.rs485.delay_rts_after_send > 0) {
+ if (stop_delay > 0) {
em485->active_timer = &em485->stop_tx_timer;
- start_hrtimer_ms(&em485->stop_tx_timer,
- p->port.rs485.delay_rts_after_send);
+ hrtimer_start(&em485->stop_tx_timer, ns_to_ktime(stop_delay), HRTIMER_MODE_REL);
} else {
p->rs485_stop_tx(p);
em485->active_timer = NULL;
@@ -1535,16 +1515,32 @@ static inline void __stop_tx(struct uart_8250_port *p)
if (em485) {
unsigned char lsr = serial_in(p, UART_LSR);
+ u64 stop_delay = 0;
+
+ if (!(lsr & UART_LSR_THRE))
+ return;
/*
* To provide required timeing and allow FIFO transfer,
* __stop_tx_rs485() must be called only when both FIFO and
- * shift register are empty. It is for device driver to enable
- * interrupt on TEMT.
+ * shift register are empty. The device driver should either
+ * enable interrupt on TEMT or set UART_CAP_NOTEMT that will
+ * enlarge stop_tx_timer by the tx time of one frame to cover
+ * for emptying of the shift register.
*/
- if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
- return;
+ if (!(lsr & UART_LSR_TEMT)) {
+ if (!(p->capabilities & UART_CAP_NOTEMT))
+ return;
+ /*
+ * RTS might get deasserted too early with the normal
+ * frame timing formula. It seems to suggest THRE might
+ * get asserted already during tx of the stop bit
+ * rather than after it is fully sent.
+ * Roughly estimate 1 extra bit here with / 7.
+ */
+ stop_delay = p->port.frame_time + DIV_ROUND_UP(p->port.frame_time, 7);
+ }
- __stop_tx_rs485(p);
+ __stop_tx_rs485(p, stop_delay);
}
__do_stop_tx(p);
}
@@ -1948,9 +1944,12 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
status = serial8250_rx_chars(up, status);
}
serial8250_modem_status(up);
- if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) &&
- (up->ier & UART_IER_THRI))
- serial8250_tx_chars(up);
+ if ((status & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) {
+ if (!up->dma || up->dma->tx_err)
+ serial8250_tx_chars(up);
+ else
+ __stop_tx(up);
+ }
uart_unlock_and_check_sysrq_irqrestore(port, flags);
@@ -2077,10 +2076,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
serial8250_rpm_put(up);
}
-/*
- * Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+static void wait_for_lsr(struct uart_8250_port *up, int bits)
{
unsigned int status, tmout = 10000;
@@ -2097,6 +2093,16 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
udelay(1);
touch_nmi_watchdog();
}
+}
+
+/*
+ * Wait for transmitter & holding register to empty
+ */
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+ unsigned int tmout;
+
+ wait_for_lsr(up, bits);
/* Wait up to 1s for flow control if necessary */
if (up->port.flags & UPF_CONS_FLOW) {
@@ -2614,10 +2620,8 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
}
if (!(c_cflag & PARODD))
cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
if (c_cflag & CMSPAR)
cval |= UART_LCR_SPAR;
-#endif
return cval;
}
@@ -3333,6 +3337,35 @@ static void serial8250_console_restore(struct uart_8250_port *up)
}
/*
+ * Print a string to the serial port using the device FIFO
+ *
+ * It sends fifosize bytes and then waits for the fifo
+ * to get empty.
+ */
+static void serial8250_console_fifo_write(struct uart_8250_port *up,
+ const char *s, unsigned int count)
+{
+ int i;
+ const char *end = s + count;
+ unsigned int fifosize = up->tx_loadsz;
+ bool cr_sent = false;
+
+ while (s != end) {
+ wait_for_lsr(up, UART_LSR_THRE);
+
+ for (i = 0; i < fifosize && s != end; ++i) {
+ if (*s == '\n' && !cr_sent) {
+ serial_out(up, UART_TX, '\r');
+ cr_sent = true;
+ } else {
+ serial_out(up, UART_TX, *s++);
+ cr_sent = false;
+ }
+ }
+ }
+}
+
+/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
*
@@ -3347,7 +3380,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
struct uart_8250_em485 *em485 = up->em485;
struct uart_port *port = &up->port;
unsigned long flags;
- unsigned int ier;
+ unsigned int ier, use_fifo;
int locked = 1;
touch_nmi_watchdog();
@@ -3379,7 +3412,30 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
mdelay(port->rs485.delay_rts_before_send);
}
- uart_console_write(port, s, count, serial8250_console_putchar);
+ use_fifo = (up->capabilities & UART_CAP_FIFO) &&
+ /*
+ * BCM283x requires to check the fifo
+ * after each byte.
+ */
+ !(up->capabilities & UART_CAP_MINI) &&
+ /*
+ * tx_loadsz contains the transmit fifo size
+ */
+ up->tx_loadsz > 1 &&
+ (up->fcr & UART_FCR_ENABLE_FIFO) &&
+ port->state &&
+ test_bit(TTY_PORT_INITIALIZED, &port->state->port.iflags) &&
+ /*
+ * After we put a data in the fifo, the controller will send
+ * it regardless of the CTS state. Therefore, only use fifo
+ * if we don't use control flow.
+ */
+ !(up->port.flags & UPF_CONS_FLOW);
+
+ if (likely(use_fifo))
+ serial8250_console_fifo_write(up, s, count);
+ else
+ uart_console_write(port, s, count, serial8250_console_putchar);
/*
* Finally, wait for transmitter to become empty
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
index 33ca98bfa5b3..795e55142d4c 100644
--- a/drivers/tty/serial/8250/8250_pxa.c
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -22,7 +22,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/clk.h>
-#include <linux/pm_runtime.h>
#include "8250.h"
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index cd93ea6eed65..fdb6c4188695 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -380,7 +380,7 @@ config SERIAL_8250_DW
config SERIAL_8250_EM
tristate "Support for Emma Mobile integrated serial port"
depends on SERIAL_8250 && HAVE_CLK
- depends on (ARM && ARCH_RENESAS) || COMPILE_TEST
+ depends on ARCH_RENESAS || COMPILE_TEST
help
Selecting this option will add support for the integrated serial
port hardware found on the Emma Mobile line of processors.
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index dbac90e2e209..a452748c69b2 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -782,7 +782,7 @@ config SERIAL_PMACZILOG_CONSOLE
config SERIAL_CPM
tristate "CPM SCC/SMC serial port support"
- depends on CPM2 || CPM1
+ depends on CPM2 || CPM1 || (PPC32 && COMPILE_TEST)
select SERIAL_CORE
help
This driver supports the SCC and SMC serial ports on Motorola
@@ -806,7 +806,7 @@ config SERIAL_CPM_CONSOLE
config SERIAL_PIC32
tristate "Microchip PIC32 serial support"
- depends on MACH_PIC32
+ depends on MACH_PIC32 || (MIPS && COMPILE_TEST)
select SERIAL_CORE
help
If you have a PIC32, this driver supports the serial ports.
@@ -817,7 +817,7 @@ config SERIAL_PIC32
config SERIAL_PIC32_CONSOLE
bool "PIC32 serial console support"
- depends on SERIAL_PIC32
+ depends on SERIAL_PIC32=y
select SERIAL_CORE_CONSOLE
help
If you have a PIC32, this driver supports the putting a console on one
@@ -1246,7 +1246,7 @@ config SERIAL_XILINX_PS_UART_CONSOLE
config SERIAL_AR933X
tristate "AR933X serial port support"
- depends on HAVE_CLK && ATH79
+ depends on (HAVE_CLK && ATH79) || (MIPS && COMPILE_TEST)
select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
help
@@ -1442,6 +1442,7 @@ config SERIAL_STM32_CONSOLE
bool "Support for console on STM32"
depends on SERIAL_STM32=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
config SERIAL_MVEBU_UART
bool "Marvell EBU serial port support"
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index 1c16345d0a1f..cb791c5149a3 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -168,10 +168,8 @@ static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
}
}
- if (pending == 0) {
- pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
- writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
- }
+ if (pending == 0)
+ altera_jtaguart_stop_tx(port);
}
static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 4d11a3e547f9..97ef41cb2721 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -42,8 +42,6 @@
#include <linux/io.h>
#include <linux/acpi.h>
-#include "amba-pl011.h"
-
#define UART_NR 14
#define SERIAL_AMBA_MAJOR 204
@@ -55,6 +53,36 @@
#define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
#define UART_DUMMY_DR_RX (1 << 16)
+enum {
+ REG_DR,
+ REG_ST_DMAWM,
+ REG_ST_TIMEOUT,
+ REG_FR,
+ REG_LCRH_RX,
+ REG_LCRH_TX,
+ REG_IBRD,
+ REG_FBRD,
+ REG_CR,
+ REG_IFLS,
+ REG_IMSC,
+ REG_RIS,
+ REG_MIS,
+ REG_ICR,
+ REG_DMACR,
+ REG_ST_XFCR,
+ REG_ST_XON1,
+ REG_ST_XON2,
+ REG_ST_XOFF1,
+ REG_ST_XOFF2,
+ REG_ST_ITCR,
+ REG_ST_ITIP,
+ REG_ST_ABCR,
+ REG_ST_ABIMSC,
+
+ /* The size of the array - must be last */
+ REG_ARRAY_SIZE,
+};
+
static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
[REG_DR] = UART01x_DR,
[REG_FR] = UART01x_FR,
@@ -2175,25 +2203,11 @@ static int pl011_rs485_config(struct uart_port *port,
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
- /* pick sane settings if the user hasn't */
- if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
- !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
- rs485->flags |= SER_RS485_RTS_ON_SEND;
- rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
- }
- /* clamp the delays to [0, 100ms] */
- rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
- rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
- memset(rs485->padding, 0, sizeof(rs485->padding));
-
if (port->rs485.flags & SER_RS485_ENABLED)
pl011_rs485_tx_stop(uap);
- /* Set new configuration */
- port->rs485 = *rs485;
-
/* Make sure auto RTS is disabled */
- if (port->rs485.flags & SER_RS485_ENABLED) {
+ if (rs485->flags & SER_RS485_ENABLED) {
u32 cr = pl011_read(uap, REG_CR);
cr &= ~UART011_CR_RTSEN;
diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h
deleted file mode 100644
index 077eb12a3472..000000000000
--- a/drivers/tty/serial/amba-pl011.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef AMBA_PL011_H
-#define AMBA_PL011_H
-
-enum {
- REG_DR,
- REG_ST_DMAWM,
- REG_ST_TIMEOUT,
- REG_FR,
- REG_LCRH_RX,
- REG_LCRH_TX,
- REG_IBRD,
- REG_FBRD,
- REG_CR,
- REG_IFLS,
- REG_IMSC,
- REG_RIS,
- REG_MIS,
- REG_ICR,
- REG_DMACR,
- REG_ST_XFCR,
- REG_ST_XON1,
- REG_ST_XON2,
- REG_ST_XOFF1,
- REG_ST_XOFF2,
- REG_ST_ITCR,
- REG_ST_ITIP,
- REG_ST_ABCR,
- REG_ST_ABIMSC,
-
- /* The size of the array - must be last */
- REG_ARRAY_SIZE,
-};
-
-#endif
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 3a45e4fc7993..dd1c7e4bd1c9 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -299,11 +299,9 @@ static int atmel_config_rs485(struct uart_port *port,
/* Resetting serial mode to RS232 (0x0) */
mode &= ~ATMEL_US_USMODE;
- port->rs485 = *rs485conf;
-
if (rs485conf->flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
- if (port->rs485.flags & SER_RS485_RX_DURING_TX)
+ if (rs485conf->flags & SER_RS485_RX_DURING_TX)
atmel_port->tx_done_mask = ATMEL_US_TXRDY;
else
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart/cpm_uart.h
index 6113b953ce25..8c582779cf22 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart.h
+++ b/drivers/tty/serial/cpm_uart/cpm_uart.h
@@ -19,6 +19,8 @@ struct gpio_desc;
#include "cpm_uart_cpm2.h"
#elif defined(CONFIG_CPM1)
#include "cpm_uart_cpm1.h"
+#elif defined(CONFIG_COMPILE_TEST)
+#include "cpm_uart_cpm2.h"
#endif
#define SERIAL_CPM_MAJOR 204
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index d6d3db9c3b1f..db07d6a5d764 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1247,7 +1247,7 @@ static int cpm_uart_init_port(struct device_node *np,
}
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
-#ifdef CONFIG_CONSOLE_POLL
+#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_CPM_CONSOLE)
if (!udbg_port)
#endif
udbg_putc = NULL;
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c
index 6a1cd03bfe39..108af254e8f3 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c
@@ -25,7 +25,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/fs_pd.h>
-#include <asm/prom.h>
#include <linux/serial_core.h>
#include <linux/kernel.h>
diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c
index e37a917b9dbb..af951e6a2ef4 100644
--- a/drivers/tty/serial/digicolor-usart.c
+++ b/drivers/tty/serial/digicolor-usart.c
@@ -309,6 +309,8 @@ static void digicolor_uart_set_termios(struct uart_port *port,
case CS8:
default:
config |= UA_CONFIG_CHAR_LEN;
+ termios->c_cflag &= ~CSIZE;
+ termios->c_cflag |= CS8;
break;
}
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index be12fee94db5..0d6e62f6bb07 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -239,8 +239,6 @@
/* IMX lpuart has four extra unused regs located at the beginning */
#define IMX_REG_OFF 0x10
-static DEFINE_IDA(fsl_lpuart_ida);
-
enum lpuart_type {
VF610_LPUART,
LS1021A_LPUART,
@@ -276,7 +274,6 @@ struct lpuart_port {
int rx_dma_rng_buf_len;
unsigned int dma_tx_nents;
wait_queue_head_t dma_wait;
- bool id_allocated;
};
struct lpuart_soc_data {
@@ -1118,7 +1115,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, copied;
+ int count, copied;
if (lpuart_is_32(sport)) {
unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
@@ -1378,19 +1375,6 @@ static int lpuart_config_rs485(struct uart_port *port,
modem |= UARTMODEM_TXRTSE;
/*
- * RTS needs to be logic HIGH either during transfer _or_ after
- * transfer, other variants are not supported by the hardware.
- */
-
- if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
- SER_RS485_RTS_AFTER_SEND)))
- rs485->flags |= SER_RS485_RTS_ON_SEND;
-
- if (rs485->flags & SER_RS485_RTS_ON_SEND &&
- rs485->flags & SER_RS485_RTS_AFTER_SEND)
- rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
-
- /*
* The hardware defaults to RTS logic HIGH while transfer.
* Switch polarity in case RTS shall be logic HIGH
* after transfer.
@@ -1402,9 +1386,6 @@ static int lpuart_config_rs485(struct uart_port *port,
modem |= UARTMODEM_TXRTSPOL;
}
- /* Store the new configuration */
- sport->port.rs485 = *rs485;
-
writeb(modem, sport->port.membase + UARTMODEM);
return 0;
}
@@ -1429,19 +1410,6 @@ static int lpuart32_config_rs485(struct uart_port *port,
modem |= UARTMODEM_TXRTSE;
/*
- * RTS needs to be logic HIGH either during transfer _or_ after
- * transfer, other variants are not supported by the hardware.
- */
-
- if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
- SER_RS485_RTS_AFTER_SEND)))
- rs485->flags |= SER_RS485_RTS_ON_SEND;
-
- if (rs485->flags & SER_RS485_RTS_ON_SEND &&
- rs485->flags & SER_RS485_RTS_AFTER_SEND)
- rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
-
- /*
* The hardware defaults to RTS logic HIGH while transfer.
* Switch polarity in case RTS shall be logic HIGH
* after transfer.
@@ -1453,9 +1421,6 @@ static int lpuart32_config_rs485(struct uart_port *port,
modem |= UARTMODEM_TXRTSPOL;
}
- /* Store the new configuration */
- sport->port.rs485 = *rs485;
-
lpuart32_write(&sport->port, modem, UARTMODIR);
return 0;
}
@@ -2145,12 +2110,10 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
if (sport->port.rs485.flags & SER_RS485_ENABLED)
termios->c_cflag &= ~CRTSCTS;
- if (termios->c_cflag & CRTSCTS) {
- modem |= (UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
- } else {
- termios->c_cflag &= ~CRTSCTS;
+ if (termios->c_cflag & CRTSCTS)
+ modem |= UARTMODIR_RXRTSE | UARTMODIR_TXCTSE;
+ else
modem &= ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
- }
if (termios->c_cflag & CSTOPB)
bd |= UARTBAUD_SBNS;
@@ -2717,23 +2680,18 @@ static int lpuart_probe(struct platform_device *pdev)
ret = of_alias_get_id(np, "serial");
if (ret < 0) {
- ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL);
- if (ret < 0) {
- dev_err(&pdev->dev, "port line is full, add device failed\n");
- return ret;
- }
- sport->id_allocated = true;
+ dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
+ return ret;
}
if (ret >= ARRAY_SIZE(lpuart_ports)) {
dev_err(&pdev->dev, "serial%d out of range\n", ret);
- ret = -EINVAL;
- goto failed_out_of_range;
+ return -EINVAL;
}
sport->port.line = ret;
ret = lpuart_enable_clks(sport);
if (ret)
- goto failed_clock_enable;
+ return ret;
sport->port.uartclk = lpuart_get_baud_clk_rate(sport);
lpuart_ports[sport->port.line] = sport;
@@ -2781,10 +2739,6 @@ failed_reset:
uart_remove_one_port(&lpuart_reg, &sport->port);
failed_attach_port:
lpuart_disable_clks(sport);
-failed_clock_enable:
-failed_out_of_range:
- if (sport->id_allocated)
- ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
return ret;
}
@@ -2794,9 +2748,6 @@ static int lpuart_remove(struct platform_device *pdev)
uart_remove_one_port(&lpuart_reg, &sport->port);
- if (sport->id_allocated)
- ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
-
lpuart_disable_clks(sport);
if (sport->dma_tx_chan)
@@ -2926,7 +2877,6 @@ static int __init lpuart_serial_init(void)
static void __exit lpuart_serial_exit(void)
{
- ida_destroy(&fsl_lpuart_ida);
platform_driver_unregister(&lpuart_driver);
uart_unregister_driver(&lpuart_reg);
}
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index 03a2fe9f4c9a..45df29947fe8 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
+#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/major.h>
#include <linux/string.h>
@@ -41,15 +42,273 @@
#include <asm/irq.h>
#include <linux/uaccess.h>
-#include "icom.h"
-
/*#define ICOM_TRACE enable port trace capabilities */
#define ICOM_DRIVER_NAME "icom"
-#define ICOM_VERSION_STR "1.3.1"
#define NR_PORTS 128
-#define ICOM_PORT ((struct icom_port *)port)
-#define to_icom_adapter(d) container_of(d, struct icom_adapter, kref)
+
+static const unsigned int icom_acfg_baud[] = {
+ 300,
+ 600,
+ 900,
+ 1200,
+ 1800,
+ 2400,
+ 3600,
+ 4800,
+ 7200,
+ 9600,
+ 14400,
+ 19200,
+ 28800,
+ 38400,
+ 57600,
+ 76800,
+ 115200,
+ 153600,
+ 230400,
+ 307200,
+ 460800,
+};
+#define BAUD_TABLE_LIMIT (ARRAY_SIZE(icom_acfg_baud) - 1)
+
+struct icom_regs {
+ u32 control; /* Adapter Control Register */
+ u32 interrupt; /* Adapter Interrupt Register */
+ u32 int_mask; /* Adapter Interrupt Mask Reg */
+ u32 int_pri; /* Adapter Interrupt Priority r */
+ u32 int_reg_b; /* Adapter non-masked Interrupt */
+ u32 resvd01;
+ u32 resvd02;
+ u32 resvd03;
+ u32 control_2; /* Adapter Control Register 2 */
+ u32 interrupt_2; /* Adapter Interrupt Register 2 */
+ u32 int_mask_2; /* Adapter Interrupt Mask 2 */
+ u32 int_pri_2; /* Adapter Interrupt Prior 2 */
+ u32 int_reg_2b; /* Adapter non-masked 2 */
+};
+
+struct func_dram {
+ u32 reserved[108]; /* 0-1B0 reserved by personality code */
+ u32 RcvStatusAddr; /* 1B0-1B3 Status Address for Next rcv */
+ u8 RcvStnAddr; /* 1B4 Receive Station Addr */
+ u8 IdleState; /* 1B5 Idle State */
+ u8 IdleMonitor; /* 1B6 Idle Monitor */
+ u8 FlagFillIdleTimer; /* 1B7 Flag Fill Idle Timer */
+ u32 XmitStatusAddr; /* 1B8-1BB Transmit Status Address */
+ u8 StartXmitCmd; /* 1BC Start Xmit Command */
+ u8 HDLCConfigReg; /* 1BD Reserved */
+ u8 CauseCode; /* 1BE Cause code for fatal error */
+ u8 xchar; /* 1BF High priority send */
+ u32 reserved3; /* 1C0-1C3 Reserved */
+ u8 PrevCmdReg; /* 1C4 Reserved */
+ u8 CmdReg; /* 1C5 Command Register */
+ u8 async_config2; /* 1C6 Async Config Byte 2 */
+ u8 async_config3; /* 1C7 Async Config Byte 3 */
+ u8 dce_resvd[20]; /* 1C8-1DB DCE Rsvd */
+ u8 dce_resvd21; /* 1DC DCE Rsvd (21st byte */
+ u8 misc_flags; /* 1DD misc flags */
+#define V2_HARDWARE 0x40
+#define ICOM_HDW_ACTIVE 0x01
+ u8 call_length; /* 1DE Phone #/CFI buff ln */
+ u8 call_length2; /* 1DF Upper byte (unused) */
+ u32 call_addr; /* 1E0-1E3 Phn #/CFI buff addr */
+ u16 timer_value; /* 1E4-1E5 general timer value */
+ u8 timer_command; /* 1E6 general timer cmd */
+ u8 dce_command; /* 1E7 dce command reg */
+ u8 dce_cmd_status; /* 1E8 dce command stat */
+ u8 x21_r1_ioff; /* 1E9 dce ready counter */
+ u8 x21_r0_ioff; /* 1EA dce not ready ctr */
+ u8 x21_ralt_ioff; /* 1EB dce CNR counter */
+ u8 x21_r1_ion; /* 1EC dce ready I on ctr */
+ u8 rsvd_ier; /* 1ED Rsvd for IER (if ne */
+ u8 ier; /* 1EE Interrupt Enable */
+ u8 isr; /* 1EF Input Signal Reg */
+ u8 osr; /* 1F0 Output Signal Reg */
+ u8 reset; /* 1F1 Reset/Reload Reg */
+ u8 disable; /* 1F2 Disable Reg */
+ u8 sync; /* 1F3 Sync Reg */
+ u8 error_stat; /* 1F4 Error Status */
+ u8 cable_id; /* 1F5 Cable ID */
+ u8 cs_length; /* 1F6 CS Load Length */
+ u8 mac_length; /* 1F7 Mac Load Length */
+ u32 cs_load_addr; /* 1F8-1FB Call Load PCI Addr */
+ u32 mac_load_addr; /* 1FC-1FF Mac Load PCI Addr */
+};
+
+/*
+ * adapter defines and structures
+ */
+#define ICOM_CONTROL_START_A 0x00000008
+#define ICOM_CONTROL_STOP_A 0x00000004
+#define ICOM_CONTROL_START_B 0x00000002
+#define ICOM_CONTROL_STOP_B 0x00000001
+#define ICOM_CONTROL_START_C 0x00000008
+#define ICOM_CONTROL_STOP_C 0x00000004
+#define ICOM_CONTROL_START_D 0x00000002
+#define ICOM_CONTROL_STOP_D 0x00000001
+#define ICOM_IRAM_OFFSET 0x1000
+#define ICOM_IRAM_SIZE 0x0C00
+#define ICOM_DCE_IRAM_OFFSET 0x0A00
+#define ICOM_CABLE_ID_VALID 0x01
+#define ICOM_CABLE_ID_MASK 0xF0
+#define ICOM_DISABLE 0x80
+#define CMD_XMIT_RCV_ENABLE 0xC0
+#define CMD_XMIT_ENABLE 0x40
+#define CMD_RCV_DISABLE 0x00
+#define CMD_RCV_ENABLE 0x80
+#define CMD_RESTART 0x01
+#define CMD_HOLD_XMIT 0x02
+#define CMD_SND_BREAK 0x04
+#define RS232_CABLE 0x06
+#define V24_CABLE 0x0E
+#define V35_CABLE 0x0C
+#define V36_CABLE 0x02
+#define NO_CABLE 0x00
+#define START_DOWNLOAD 0x80
+#define ICOM_INT_MASK_PRC_A 0x00003FFF
+#define ICOM_INT_MASK_PRC_B 0x3FFF0000
+#define ICOM_INT_MASK_PRC_C 0x00003FFF
+#define ICOM_INT_MASK_PRC_D 0x3FFF0000
+#define INT_RCV_COMPLETED 0x1000
+#define INT_XMIT_COMPLETED 0x2000
+#define INT_IDLE_DETECT 0x0800
+#define INT_RCV_DISABLED 0x0400
+#define INT_XMIT_DISABLED 0x0200
+#define INT_RCV_XMIT_SHUTDOWN 0x0100
+#define INT_FATAL_ERROR 0x0080
+#define INT_CABLE_PULL 0x0020
+#define INT_SIGNAL_CHANGE 0x0010
+#define HDLC_PPP_PURE_ASYNC 0x02
+#define HDLC_FF_FILL 0x00
+#define HDLC_HDW_FLOW 0x01
+#define START_XMIT 0x80
+#define ICOM_ACFG_DRIVE1 0x20
+#define ICOM_ACFG_NO_PARITY 0x00
+#define ICOM_ACFG_PARITY_ENAB 0x02
+#define ICOM_ACFG_PARITY_ODD 0x01
+#define ICOM_ACFG_8BPC 0x00
+#define ICOM_ACFG_7BPC 0x04
+#define ICOM_ACFG_6BPC 0x08
+#define ICOM_ACFG_5BPC 0x0C
+#define ICOM_ACFG_1STOP_BIT 0x00
+#define ICOM_ACFG_2STOP_BIT 0x10
+#define ICOM_DTR 0x80
+#define ICOM_RTS 0x40
+#define ICOM_RI 0x08
+#define ICOM_DSR 0x80
+#define ICOM_DCD 0x20
+#define ICOM_CTS 0x40
+
+#define NUM_XBUFFS 1
+#define NUM_RBUFFS 2
+#define RCV_BUFF_SZ 0x0200
+#define XMIT_BUFF_SZ 0x1000
+struct statusArea {
+ /**********************************************/
+ /* Transmit Status Area */
+ /**********************************************/
+ struct xmit_status_area{
+ __le32 leNext; /* Next entry in Little Endian on Adapter */
+ __le32 leNextASD;
+ __le32 leBuffer; /* Buffer for entry in LE for Adapter */
+ __le16 leLengthASD;
+ __le16 leOffsetASD;
+ __le16 leLength; /* Length of data in segment */
+ __le16 flags;
+#define SA_FLAGS_DONE 0x0080 /* Done with Segment */
+#define SA_FLAGS_CONTINUED 0x8000 /* More Segments */
+#define SA_FLAGS_IDLE 0x4000 /* Mark IDLE after frm */
+#define SA_FLAGS_READY_TO_XMIT 0x0800
+#define SA_FLAGS_STAT_MASK 0x007F
+ } xmit[NUM_XBUFFS];
+
+ /**********************************************/
+ /* Receive Status Area */
+ /**********************************************/
+ struct {
+ __le32 leNext; /* Next entry in Little Endian on Adapter */
+ __le32 leNextASD;
+ __le32 leBuffer; /* Buffer for entry in LE for Adapter */
+ __le16 WorkingLength; /* size of segment */
+ __le16 reserv01;
+ __le16 leLength; /* Length of data in segment */
+ __le16 flags;
+#define SA_FL_RCV_DONE 0x0010 /* Data ready */
+#define SA_FLAGS_OVERRUN 0x0040
+#define SA_FLAGS_PARITY_ERROR 0x0080
+#define SA_FLAGS_FRAME_ERROR 0x0001
+#define SA_FLAGS_FRAME_TRUNC 0x0002
+#define SA_FLAGS_BREAK_DET 0x0004 /* set conditionally by device driver, not hardware */
+#define SA_FLAGS_RCV_MASK 0xFFE6
+ } rcv[NUM_RBUFFS];
+};
+
+struct icom_adapter;
+
+
+#define ICOM_MAJOR 243
+#define ICOM_MINOR_START 0
+
+struct icom_port {
+ struct uart_port uart_port;
+ unsigned char cable_id;
+ unsigned char read_status_mask;
+ unsigned char ignore_status_mask;
+ void __iomem * int_reg;
+ struct icom_regs __iomem *global_reg;
+ struct func_dram __iomem *dram;
+ int port;
+ struct statusArea *statStg;
+ dma_addr_t statStg_pci;
+ __le32 *xmitRestart;
+ dma_addr_t xmitRestart_pci;
+ unsigned char *xmit_buf;
+ dma_addr_t xmit_buf_pci;
+ unsigned char *recv_buf;
+ dma_addr_t recv_buf_pci;
+ int next_rcv;
+ int status;
+#define ICOM_PORT_ACTIVE 1 /* Port exists. */
+#define ICOM_PORT_OFF 0 /* Port does not exist. */
+ struct icom_adapter *adapter;
+};
+
+struct icom_adapter {
+ void __iomem * base_addr;
+ unsigned long base_addr_pci;
+ struct pci_dev *pci_dev;
+ struct icom_port port_info[4];
+ int index;
+ int version;
+#define ADAPTER_V1 0x0001
+#define ADAPTER_V2 0x0002
+ u32 subsystem_id;
+#define FOUR_PORT_MODEL 0x0252
+#define V2_TWO_PORTS_RVX 0x021A
+#define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM 0x0251
+ int numb_ports;
+ struct list_head icom_adapter_entry;
+ struct kref kref;
+};
+
+/* prototype */
+extern void iCom_sercons_init(void);
+
+struct lookup_proc_table {
+ u32 __iomem *global_control_reg;
+ unsigned long processor_id;
+};
+
+struct lookup_int_table {
+ u32 __iomem *global_int_mask;
+ unsigned long processor_id;
+};
+
+static inline struct icom_port *to_icom_port(struct uart_port *port)
+{
+ return container_of(port, struct icom_port, uart_port);
+}
static const struct pci_device_id icom_pci_table[] = {
{
@@ -222,7 +481,7 @@ static int get_port_memory(struct icom_port *icom_port)
if (index < (NUM_XBUFFS - 1)) {
memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
icom_port->statStg->xmit[index].leLengthASD =
- (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
+ cpu_to_le16(XMIT_BUFF_SZ);
trace(icom_port, "FOD_ADDR", stgAddr);
trace(icom_port, "FOD_XBUFF",
(unsigned long) icom_port->xmit_buf);
@@ -231,7 +490,7 @@ static int get_port_memory(struct icom_port *icom_port)
} else if (index == (NUM_XBUFFS - 1)) {
memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
icom_port->statStg->xmit[index].leLengthASD =
- (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
+ cpu_to_le16(XMIT_BUFF_SZ);
trace(icom_port, "FOD_XBUFF",
(unsigned long) icom_port->xmit_buf);
icom_port->statStg->xmit[index].leBuffer =
@@ -249,7 +508,7 @@ static int get_port_memory(struct icom_port *icom_port)
stgAddr = stgAddr + sizeof(icom_port->statStg->rcv[0]);
icom_port->statStg->rcv[index].leLength = 0;
icom_port->statStg->rcv[index].WorkingLength =
- (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+ cpu_to_le16(RCV_BUFF_SZ);
if (index < (NUM_RBUFFS - 1) ) {
offset = stgAddr - (unsigned long) icom_port->statStg;
icom_port->statStg->rcv[index].leNext =
@@ -617,16 +876,17 @@ unlock:
static int icom_write(struct uart_port *port)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned long data_count;
unsigned char cmdReg;
unsigned long offset;
int temp_tail = port->state->xmit.tail;
- trace(ICOM_PORT, "WRITE", 0);
+ trace(icom_port, "WRITE", 0);
- if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
+ if (le16_to_cpu(icom_port->statStg->xmit[0].flags) &
SA_FLAGS_READY_TO_XMIT) {
- trace(ICOM_PORT, "WRITE_FULL", 0);
+ trace(icom_port, "WRITE_FULL", 0);
return 0;
}
@@ -634,7 +894,7 @@ static int icom_write(struct uart_port *port)
while ((port->state->xmit.head != temp_tail) &&
(data_count <= XMIT_BUFF_SZ)) {
- ICOM_PORT->xmit_buf[data_count++] =
+ icom_port->xmit_buf[data_count++] =
port->state->xmit.buf[temp_tail];
temp_tail++;
@@ -642,22 +902,22 @@ static int icom_write(struct uart_port *port)
}
if (data_count) {
- ICOM_PORT->statStg->xmit[0].flags =
+ icom_port->statStg->xmit[0].flags =
cpu_to_le16(SA_FLAGS_READY_TO_XMIT);
- ICOM_PORT->statStg->xmit[0].leLength =
+ icom_port->statStg->xmit[0].leLength =
cpu_to_le16(data_count);
offset =
- (unsigned long) &ICOM_PORT->statStg->xmit[0] -
- (unsigned long) ICOM_PORT->statStg;
- *ICOM_PORT->xmitRestart =
- cpu_to_le32(ICOM_PORT->statStg_pci + offset);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+ (unsigned long) &icom_port->statStg->xmit[0] -
+ (unsigned long) icom_port->statStg;
+ *icom_port->xmitRestart =
+ cpu_to_le32(icom_port->statStg_pci + offset);
+ cmdReg = readb(&icom_port->dram->CmdReg);
writeb(cmdReg | CMD_XMIT_RCV_ENABLE,
- &ICOM_PORT->dram->CmdReg);
- writeb(START_XMIT, &ICOM_PORT->dram->StartXmitCmd);
- trace(ICOM_PORT, "WRITE_START", data_count);
+ &icom_port->dram->CmdReg);
+ writeb(START_XMIT, &icom_port->dram->StartXmitCmd);
+ trace(icom_port, "WRITE_START", data_count);
/* write flush */
- readb(&ICOM_PORT->dram->StartXmitCmd);
+ readb(&icom_port->dram->StartXmitCmd);
}
return data_count;
@@ -696,8 +956,7 @@ static inline void check_modem_status(struct icom_port *icom_port)
static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
{
- unsigned short int count;
- int i;
+ u16 count, i;
if (port_int_reg & (INT_XMIT_COMPLETED)) {
trace(icom_port, "XMIT_COMPLETE", 0);
@@ -706,8 +965,7 @@ static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
icom_port->statStg->xmit[0].flags &=
cpu_to_le16(~SA_FLAGS_READY_TO_XMIT);
- count = (unsigned short int)
- cpu_to_le16(icom_port->statStg->xmit[0].leLength);
+ count = le16_to_cpu(icom_port->statStg->xmit[0].leLength);
icom_port->uart_port.icount.tx += count;
for (i=0; i<count &&
@@ -729,7 +987,7 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
{
short int count, rcv_buff;
struct tty_port *port = &icom_port->uart_port.state->port;
- unsigned short int status;
+ u16 status;
struct uart_icount *icount;
unsigned long offset;
unsigned char flag;
@@ -737,19 +995,18 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
trace(icom_port, "RCV_COMPLETE", 0);
rcv_buff = icom_port->next_rcv;
- status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
+ status = le16_to_cpu(icom_port->statStg->rcv[rcv_buff].flags);
while (status & SA_FL_RCV_DONE) {
int first = -1;
trace(icom_port, "FID_STATUS", status);
- count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
+ count = le16_to_cpu(icom_port->statStg->rcv[rcv_buff].leLength);
trace(icom_port, "RCV_COUNT", count);
trace(icom_port, "REAL_COUNT", count);
- offset =
- cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
+ offset = le32_to_cpu(icom_port->statStg->rcv[rcv_buff].leBuffer) -
icom_port->recv_buf_pci;
/* Block copy all but the last byte as this may have status */
@@ -819,13 +1076,13 @@ ignore_char:
icom_port->statStg->rcv[rcv_buff].flags = 0;
icom_port->statStg->rcv[rcv_buff].leLength = 0;
icom_port->statStg->rcv[rcv_buff].WorkingLength =
- (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+ cpu_to_le16(RCV_BUFF_SZ);
rcv_buff++;
if (rcv_buff == NUM_RBUFFS)
rcv_buff = 0;
- status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
+ status = le16_to_cpu(icom_port->statStg->rcv[rcv_buff].flags);
}
icom_port->next_rcv = rcv_buff;
@@ -925,11 +1182,12 @@ static irqreturn_t icom_interrupt(int irq, void *dev_id)
*/
static unsigned int icom_tx_empty(struct uart_port *port)
{
+ struct icom_port *icom_port = to_icom_port(port);
int ret;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
+ if (le16_to_cpu(icom_port->statStg->xmit[0].flags) &
SA_FLAGS_READY_TO_XMIT)
ret = TIOCSER_TEMT;
else
@@ -941,38 +1199,40 @@ static unsigned int icom_tx_empty(struct uart_port *port)
static void icom_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned char local_osr;
- trace(ICOM_PORT, "SET_MODEM", 0);
- local_osr = readb(&ICOM_PORT->dram->osr);
+ trace(icom_port, "SET_MODEM", 0);
+ local_osr = readb(&icom_port->dram->osr);
if (mctrl & TIOCM_RTS) {
- trace(ICOM_PORT, "RAISE_RTS", 0);
+ trace(icom_port, "RAISE_RTS", 0);
local_osr |= ICOM_RTS;
} else {
- trace(ICOM_PORT, "LOWER_RTS", 0);
+ trace(icom_port, "LOWER_RTS", 0);
local_osr &= ~ICOM_RTS;
}
if (mctrl & TIOCM_DTR) {
- trace(ICOM_PORT, "RAISE_DTR", 0);
+ trace(icom_port, "RAISE_DTR", 0);
local_osr |= ICOM_DTR;
} else {
- trace(ICOM_PORT, "LOWER_DTR", 0);
+ trace(icom_port, "LOWER_DTR", 0);
local_osr &= ~ICOM_DTR;
}
- writeb(local_osr, &ICOM_PORT->dram->osr);
+ writeb(local_osr, &icom_port->dram->osr);
}
static unsigned int icom_get_mctrl(struct uart_port *port)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned char status;
unsigned int result;
- trace(ICOM_PORT, "GET_MODEM", 0);
+ trace(icom_port, "GET_MODEM", 0);
- status = readb(&ICOM_PORT->dram->isr);
+ status = readb(&icom_port->dram->isr);
result = ((status & ICOM_DCD) ? TIOCM_CAR : 0)
| ((status & ICOM_RI) ? TIOCM_RNG : 0)
@@ -983,44 +1243,47 @@ static unsigned int icom_get_mctrl(struct uart_port *port)
static void icom_stop_tx(struct uart_port *port)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned char cmdReg;
- trace(ICOM_PORT, "STOP", 0);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
+ trace(icom_port, "STOP", 0);
+ cmdReg = readb(&icom_port->dram->CmdReg);
+ writeb(cmdReg | CMD_HOLD_XMIT, &icom_port->dram->CmdReg);
}
static void icom_start_tx(struct uart_port *port)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned char cmdReg;
- trace(ICOM_PORT, "START", 0);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+ trace(icom_port, "START", 0);
+ cmdReg = readb(&icom_port->dram->CmdReg);
if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
writeb(cmdReg & ~CMD_HOLD_XMIT,
- &ICOM_PORT->dram->CmdReg);
+ &icom_port->dram->CmdReg);
icom_write(port);
}
static void icom_send_xchar(struct uart_port *port, char ch)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned char xdata;
int index;
unsigned long flags;
- trace(ICOM_PORT, "SEND_XCHAR", ch);
+ trace(icom_port, "SEND_XCHAR", ch);
/* wait .1 sec to send char */
for (index = 0; index < 10; index++) {
spin_lock_irqsave(&port->lock, flags);
- xdata = readb(&ICOM_PORT->dram->xchar);
+ xdata = readb(&icom_port->dram->xchar);
if (xdata == 0x00) {
- trace(ICOM_PORT, "QUICK_WRITE", 0);
- writeb(ch, &ICOM_PORT->dram->xchar);
+ trace(icom_port, "QUICK_WRITE", 0);
+ writeb(ch, &icom_port->dram->xchar);
/* flush write operation */
- xdata = readb(&ICOM_PORT->dram->xchar);
+ xdata = readb(&icom_port->dram->xchar);
spin_unlock_irqrestore(&port->lock, flags);
break;
}
@@ -1031,38 +1294,41 @@ static void icom_send_xchar(struct uart_port *port, char ch)
static void icom_stop_rx(struct uart_port *port)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned char cmdReg;
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
+ cmdReg = readb(&icom_port->dram->CmdReg);
+ writeb(cmdReg & ~CMD_RCV_ENABLE, &icom_port->dram->CmdReg);
}
static void icom_break(struct uart_port *port, int break_state)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned char cmdReg;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- trace(ICOM_PORT, "BREAK", 0);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+ trace(icom_port, "BREAK", 0);
+ cmdReg = readb(&icom_port->dram->CmdReg);
if (break_state == -1) {
- writeb(cmdReg | CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
+ writeb(cmdReg | CMD_SND_BREAK, &icom_port->dram->CmdReg);
} else {
- writeb(cmdReg & ~CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
+ writeb(cmdReg & ~CMD_SND_BREAK, &icom_port->dram->CmdReg);
}
spin_unlock_irqrestore(&port->lock, flags);
}
static int icom_open(struct uart_port *port)
{
+ struct icom_port *icom_port = to_icom_port(port);
int retval;
- kref_get(&ICOM_PORT->adapter->kref);
- retval = startup(ICOM_PORT);
+ kref_get(&icom_port->adapter->kref);
+ retval = startup(icom_port);
if (retval) {
- kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
- trace(ICOM_PORT, "STARTUP_ERROR", 0);
+ kref_put(&icom_port->adapter->kref, icom_kref_release);
+ trace(icom_port, "STARTUP_ERROR", 0);
return retval;
}
@@ -1071,23 +1337,25 @@ static int icom_open(struct uart_port *port)
static void icom_close(struct uart_port *port)
{
+ struct icom_port *icom_port = to_icom_port(port);
unsigned char cmdReg;
- trace(ICOM_PORT, "CLOSE", 0);
+ trace(icom_port, "CLOSE", 0);
/* stop receiver */
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
+ cmdReg = readb(&icom_port->dram->CmdReg);
+ writeb(cmdReg & ~CMD_RCV_ENABLE, &icom_port->dram->CmdReg);
- shutdown(ICOM_PORT);
+ shutdown(icom_port);
- kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
+ kref_put(&icom_port->adapter->kref, icom_kref_release);
}
static void icom_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old_termios)
{
+ struct icom_port *icom_port = to_icom_port(port);
int baud;
unsigned cflag, iflag;
char new_config2;
@@ -1099,7 +1367,7 @@ static void icom_set_termios(struct uart_port *port,
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- trace(ICOM_PORT, "CHANGE_SPEED", 0);
+ trace(icom_port, "CHANGE_SPEED", 0);
cflag = termios->c_cflag;
iflag = termios->c_iflag;
@@ -1130,12 +1398,12 @@ static void icom_set_termios(struct uart_port *port,
if (cflag & PARENB) {
/* parity bit enabled */
new_config2 |= ICOM_ACFG_PARITY_ENAB;
- trace(ICOM_PORT, "PARENB", 0);
+ trace(icom_port, "PARENB", 0);
}
if (cflag & PARODD) {
/* odd parity */
new_config2 |= ICOM_ACFG_PARITY_ODD;
- trace(ICOM_PORT, "PARODD", 0);
+ trace(icom_port, "PARODD", 0);
}
/* Determine divisor based on baud rate */
@@ -1155,100 +1423,99 @@ static void icom_set_termios(struct uart_port *port,
uart_update_timeout(port, cflag, baud);
/* CTS flow control flag and modem status interrupts */
- tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
+ tmp_byte = readb(&(icom_port->dram->HDLCConfigReg));
if (cflag & CRTSCTS)
tmp_byte |= HDLC_HDW_FLOW;
else
tmp_byte &= ~HDLC_HDW_FLOW;
- writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
+ writeb(tmp_byte, &(icom_port->dram->HDLCConfigReg));
/*
* Set up parity check flag
*/
- ICOM_PORT->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
+ icom_port->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
if (iflag & INPCK)
- ICOM_PORT->read_status_mask |=
+ icom_port->read_status_mask |=
SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
if ((iflag & BRKINT) || (iflag & PARMRK))
- ICOM_PORT->read_status_mask |= SA_FLAGS_BREAK_DET;
+ icom_port->read_status_mask |= SA_FLAGS_BREAK_DET;
/*
* Characters to ignore
*/
- ICOM_PORT->ignore_status_mask = 0;
+ icom_port->ignore_status_mask = 0;
if (iflag & IGNPAR)
- ICOM_PORT->ignore_status_mask |=
+ icom_port->ignore_status_mask |=
SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
if (iflag & IGNBRK) {
- ICOM_PORT->ignore_status_mask |= SA_FLAGS_BREAK_DET;
+ icom_port->ignore_status_mask |= SA_FLAGS_BREAK_DET;
/*
* If we're ignore parity and break indicators, ignore
* overruns too. (For real raw support).
*/
if (iflag & IGNPAR)
- ICOM_PORT->ignore_status_mask |= SA_FLAGS_OVERRUN;
+ icom_port->ignore_status_mask |= SA_FLAGS_OVERRUN;
}
/*
* !!! ignore all characters if CREAD is not set
*/
if ((cflag & CREAD) == 0)
- ICOM_PORT->ignore_status_mask |= SA_FL_RCV_DONE;
+ icom_port->ignore_status_mask |= SA_FL_RCV_DONE;
/* Turn off Receiver to prepare for reset */
- writeb(CMD_RCV_DISABLE, &ICOM_PORT->dram->CmdReg);
+ writeb(CMD_RCV_DISABLE, &icom_port->dram->CmdReg);
for (index = 0; index < 10; index++) {
- if (readb(&ICOM_PORT->dram->PrevCmdReg) == 0x00) {
+ if (readb(&icom_port->dram->PrevCmdReg) == 0x00) {
break;
}
}
/* clear all current buffers of data */
for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
- ICOM_PORT->statStg->rcv[rcv_buff].flags = 0;
- ICOM_PORT->statStg->rcv[rcv_buff].leLength = 0;
- ICOM_PORT->statStg->rcv[rcv_buff].WorkingLength =
- (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+ icom_port->statStg->rcv[rcv_buff].flags = 0;
+ icom_port->statStg->rcv[rcv_buff].leLength = 0;
+ icom_port->statStg->rcv[rcv_buff].WorkingLength =
+ cpu_to_le16(RCV_BUFF_SZ);
}
for (xmit_buff = 0; xmit_buff < NUM_XBUFFS; xmit_buff++) {
- ICOM_PORT->statStg->xmit[xmit_buff].flags = 0;
+ icom_port->statStg->xmit[xmit_buff].flags = 0;
}
/* activate changes and start xmit and receiver here */
/* Enable the receiver */
- writeb(new_config3, &(ICOM_PORT->dram->async_config3));
- writeb(new_config2, &(ICOM_PORT->dram->async_config2));
- tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
+ writeb(new_config3, &(icom_port->dram->async_config3));
+ writeb(new_config2, &(icom_port->dram->async_config2));
+ tmp_byte = readb(&(icom_port->dram->HDLCConfigReg));
tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
- writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
- writeb(0x04, &(ICOM_PORT->dram->FlagFillIdleTimer)); /* 0.5 seconds */
- writeb(0xFF, &(ICOM_PORT->dram->ier)); /* enable modem signal interrupts */
+ writeb(tmp_byte, &(icom_port->dram->HDLCConfigReg));
+ writeb(0x04, &(icom_port->dram->FlagFillIdleTimer)); /* 0.5 seconds */
+ writeb(0xFF, &(icom_port->dram->ier)); /* enable modem signal interrupts */
/* reset processor */
- writeb(CMD_RESTART, &ICOM_PORT->dram->CmdReg);
+ writeb(CMD_RESTART, &icom_port->dram->CmdReg);
for (index = 0; index < 10; index++) {
- if (readb(&ICOM_PORT->dram->CmdReg) == 0x00) {
+ if (readb(&icom_port->dram->CmdReg) == 0x00) {
break;
}
}
/* Enable Transmitter and Receiver */
offset =
- (unsigned long) &ICOM_PORT->statStg->rcv[0] -
- (unsigned long) ICOM_PORT->statStg;
- writel(ICOM_PORT->statStg_pci + offset,
- &ICOM_PORT->dram->RcvStatusAddr);
- ICOM_PORT->next_rcv = 0;
- ICOM_PORT->put_length = 0;
- *ICOM_PORT->xmitRestart = 0;
- writel(ICOM_PORT->xmitRestart_pci,
- &ICOM_PORT->dram->XmitStatusAddr);
- trace(ICOM_PORT, "XR_ENAB", 0);
- writeb(CMD_XMIT_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
+ (unsigned long) &icom_port->statStg->rcv[0] -
+ (unsigned long) icom_port->statStg;
+ writel(icom_port->statStg_pci + offset,
+ &icom_port->dram->RcvStatusAddr);
+ icom_port->next_rcv = 0;
+ *icom_port->xmitRestart = 0;
+ writel(icom_port->xmitRestart_pci,
+ &icom_port->dram->XmitStatusAddr);
+ trace(icom_port, "XR_ENAB", 0);
+ writeb(CMD_XMIT_RCV_ENABLE, &icom_port->dram->CmdReg);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -1258,15 +1525,6 @@ static const char *icom_type(struct uart_port *port)
return "icom";
}
-static void icom_release_port(struct uart_port *port)
-{
-}
-
-static int icom_request_port(struct uart_port *port)
-{
- return 0;
-}
-
static void icom_config_port(struct uart_port *port, int flags)
{
port->type = PORT_ICOM;
@@ -1285,8 +1543,6 @@ static const struct uart_ops icom_ops = {
.shutdown = icom_close,
.set_termios = icom_set_termios,
.type = icom_type,
- .release_port = icom_release_port,
- .request_port = icom_request_port,
.config_port = icom_config_port,
};
@@ -1315,7 +1571,6 @@ static int icom_init_ports(struct icom_adapter *icom_adapter)
icom_port = &icom_adapter->port_info[i];
icom_port->port = i;
icom_port->status = ICOM_PORT_ACTIVE;
- icom_port->imbed_modem = ICOM_UNKNOWN;
}
} else {
if (subsystem_id == PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL) {
@@ -1326,26 +1581,15 @@ static int icom_init_ports(struct icom_adapter *icom_adapter)
icom_port->port = i;
icom_port->status = ICOM_PORT_ACTIVE;
- icom_port->imbed_modem = ICOM_IMBED_MODEM;
}
} else {
icom_adapter->numb_ports = 4;
icom_adapter->port_info[0].port = 0;
icom_adapter->port_info[0].status = ICOM_PORT_ACTIVE;
-
- if (subsystem_id ==
- PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM) {
- icom_adapter->port_info[0].imbed_modem = ICOM_IMBED_MODEM;
- } else {
- icom_adapter->port_info[0].imbed_modem = ICOM_RVX;
- }
-
icom_adapter->port_info[1].status = ICOM_PORT_OFF;
-
icom_adapter->port_info[2].port = 2;
icom_adapter->port_info[2].status = ICOM_PORT_ACTIVE;
- icom_adapter->port_info[2].imbed_modem = ICOM_RVX;
icom_adapter->port_info[3].status = ICOM_PORT_OFF;
}
}
@@ -1401,7 +1645,6 @@ static int icom_alloc_adapter(struct icom_adapter
int adapter_count = 0;
struct icom_adapter *icom_adapter;
struct icom_adapter *cur_adapter_entry;
- struct list_head *tmp;
icom_adapter = kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
@@ -1409,10 +1652,8 @@ static int icom_alloc_adapter(struct icom_adapter
return -ENOMEM;
}
- list_for_each(tmp, &icom_adapter_head) {
- cur_adapter_entry =
- list_entry(tmp, struct icom_adapter,
- icom_adapter_entry);
+ list_for_each_entry(cur_adapter_entry, &icom_adapter_head,
+ icom_adapter_entry) {
if (cur_adapter_entry->index != adapter_count) {
break;
}
@@ -1420,7 +1661,8 @@ static int icom_alloc_adapter(struct icom_adapter
}
icom_adapter->index = adapter_count;
- list_add_tail(&icom_adapter->icom_adapter_entry, tmp);
+ list_add_tail(&icom_adapter->icom_adapter_entry,
+ &cur_adapter_entry->icom_adapter_entry);
*icom_adapter_ref = icom_adapter;
return 0;
@@ -1432,8 +1674,10 @@ static void icom_free_adapter(struct icom_adapter *icom_adapter)
kfree(icom_adapter);
}
-static void icom_remove_adapter(struct icom_adapter *icom_adapter)
+static void icom_kref_release(struct kref *kref)
{
+ struct icom_adapter *icom_adapter = container_of(kref,
+ struct icom_adapter, kref);
struct icom_port *icom_port;
int index;
@@ -1466,14 +1710,6 @@ static void icom_remove_adapter(struct icom_adapter *icom_adapter)
icom_free_adapter(icom_adapter);
}
-static void icom_kref_release(struct kref *kref)
-{
- struct icom_adapter *icom_adapter;
-
- icom_adapter = to_icom_adapter(kref);
- icom_remove_adapter(icom_adapter);
-}
-
static int icom_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
@@ -1501,7 +1737,7 @@ static int icom_probe(struct pci_dev *dev,
retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg);
if (retval) {
dev_err(&dev->dev, "PCI Config read FAILED\n");
- return retval;
+ goto probe_exit0;
}
pci_write_config_dword(dev, PCI_COMMAND,
@@ -1589,11 +1825,9 @@ probe_exit0:
static void icom_remove(struct pci_dev *dev)
{
struct icom_adapter *icom_adapter;
- struct list_head *tmp;
- list_for_each(tmp, &icom_adapter_head) {
- icom_adapter = list_entry(tmp, struct icom_adapter,
- icom_adapter_entry);
+ list_for_each_entry(icom_adapter, &icom_adapter_head,
+ icom_adapter_entry) {
if (icom_adapter->pci_dev == dev) {
kref_put(&icom_adapter->kref, icom_kref_release);
return;
diff --git a/drivers/tty/serial/icom.h b/drivers/tty/serial/icom.h
deleted file mode 100644
index 26e3aa7b01e2..000000000000
--- a/drivers/tty/serial/icom.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * icom.h
- *
- * Copyright (C) 2001 Michael Anderson, IBM Corporation
- *
- * Serial device driver include file.
- */
-
-#include <linux/serial_core.h>
-
-#define BAUD_TABLE_LIMIT ((sizeof(icom_acfg_baud)/sizeof(int)) - 1)
-static int icom_acfg_baud[] = {
- 300,
- 600,
- 900,
- 1200,
- 1800,
- 2400,
- 3600,
- 4800,
- 7200,
- 9600,
- 14400,
- 19200,
- 28800,
- 38400,
- 57600,
- 76800,
- 115200,
- 153600,
- 230400,
- 307200,
- 460800,
-};
-
-struct icom_regs {
- u32 control; /* Adapter Control Register */
- u32 interrupt; /* Adapter Interrupt Register */
- u32 int_mask; /* Adapter Interrupt Mask Reg */
- u32 int_pri; /* Adapter Interrupt Priority r */
- u32 int_reg_b; /* Adapter non-masked Interrupt */
- u32 resvd01;
- u32 resvd02;
- u32 resvd03;
- u32 control_2; /* Adapter Control Register 2 */
- u32 interrupt_2; /* Adapter Interrupt Register 2 */
- u32 int_mask_2; /* Adapter Interrupt Mask 2 */
- u32 int_pri_2; /* Adapter Interrupt Prior 2 */
- u32 int_reg_2b; /* Adapter non-masked 2 */
-};
-
-struct func_dram {
- u32 reserved[108]; /* 0-1B0 reserved by personality code */
- u32 RcvStatusAddr; /* 1B0-1B3 Status Address for Next rcv */
- u8 RcvStnAddr; /* 1B4 Receive Station Addr */
- u8 IdleState; /* 1B5 Idle State */
- u8 IdleMonitor; /* 1B6 Idle Monitor */
- u8 FlagFillIdleTimer; /* 1B7 Flag Fill Idle Timer */
- u32 XmitStatusAddr; /* 1B8-1BB Transmit Status Address */
- u8 StartXmitCmd; /* 1BC Start Xmit Command */
- u8 HDLCConfigReg; /* 1BD Reserved */
- u8 CauseCode; /* 1BE Cause code for fatal error */
- u8 xchar; /* 1BF High priority send */
- u32 reserved3; /* 1C0-1C3 Reserved */
- u8 PrevCmdReg; /* 1C4 Reserved */
- u8 CmdReg; /* 1C5 Command Register */
- u8 async_config2; /* 1C6 Async Config Byte 2 */
- u8 async_config3; /* 1C7 Async Config Byte 3 */
- u8 dce_resvd[20]; /* 1C8-1DB DCE Rsvd */
- u8 dce_resvd21; /* 1DC DCE Rsvd (21st byte */
- u8 misc_flags; /* 1DD misc flags */
-#define V2_HARDWARE 0x40
-#define ICOM_HDW_ACTIVE 0x01
- u8 call_length; /* 1DE Phone #/CFI buff ln */
- u8 call_length2; /* 1DF Upper byte (unused) */
- u32 call_addr; /* 1E0-1E3 Phn #/CFI buff addr */
- u16 timer_value; /* 1E4-1E5 general timer value */
- u8 timer_command; /* 1E6 general timer cmd */
- u8 dce_command; /* 1E7 dce command reg */
- u8 dce_cmd_status; /* 1E8 dce command stat */
- u8 x21_r1_ioff; /* 1E9 dce ready counter */
- u8 x21_r0_ioff; /* 1EA dce not ready ctr */
- u8 x21_ralt_ioff; /* 1EB dce CNR counter */
- u8 x21_r1_ion; /* 1EC dce ready I on ctr */
- u8 rsvd_ier; /* 1ED Rsvd for IER (if ne */
- u8 ier; /* 1EE Interrupt Enable */
- u8 isr; /* 1EF Input Signal Reg */
- u8 osr; /* 1F0 Output Signal Reg */
- u8 reset; /* 1F1 Reset/Reload Reg */
- u8 disable; /* 1F2 Disable Reg */
- u8 sync; /* 1F3 Sync Reg */
- u8 error_stat; /* 1F4 Error Status */
- u8 cable_id; /* 1F5 Cable ID */
- u8 cs_length; /* 1F6 CS Load Length */
- u8 mac_length; /* 1F7 Mac Load Length */
- u32 cs_load_addr; /* 1F8-1FB Call Load PCI Addr */
- u32 mac_load_addr; /* 1FC-1FF Mac Load PCI Addr */
-};
-
-/*
- * adapter defines and structures
- */
-#define ICOM_CONTROL_START_A 0x00000008
-#define ICOM_CONTROL_STOP_A 0x00000004
-#define ICOM_CONTROL_START_B 0x00000002
-#define ICOM_CONTROL_STOP_B 0x00000001
-#define ICOM_CONTROL_START_C 0x00000008
-#define ICOM_CONTROL_STOP_C 0x00000004
-#define ICOM_CONTROL_START_D 0x00000002
-#define ICOM_CONTROL_STOP_D 0x00000001
-#define ICOM_IRAM_OFFSET 0x1000
-#define ICOM_IRAM_SIZE 0x0C00
-#define ICOM_DCE_IRAM_OFFSET 0x0A00
-#define ICOM_CABLE_ID_VALID 0x01
-#define ICOM_CABLE_ID_MASK 0xF0
-#define ICOM_DISABLE 0x80
-#define CMD_XMIT_RCV_ENABLE 0xC0
-#define CMD_XMIT_ENABLE 0x40
-#define CMD_RCV_DISABLE 0x00
-#define CMD_RCV_ENABLE 0x80
-#define CMD_RESTART 0x01
-#define CMD_HOLD_XMIT 0x02
-#define CMD_SND_BREAK 0x04
-#define RS232_CABLE 0x06
-#define V24_CABLE 0x0E
-#define V35_CABLE 0x0C
-#define V36_CABLE 0x02
-#define NO_CABLE 0x00
-#define START_DOWNLOAD 0x80
-#define ICOM_INT_MASK_PRC_A 0x00003FFF
-#define ICOM_INT_MASK_PRC_B 0x3FFF0000
-#define ICOM_INT_MASK_PRC_C 0x00003FFF
-#define ICOM_INT_MASK_PRC_D 0x3FFF0000
-#define INT_RCV_COMPLETED 0x1000
-#define INT_XMIT_COMPLETED 0x2000
-#define INT_IDLE_DETECT 0x0800
-#define INT_RCV_DISABLED 0x0400
-#define INT_XMIT_DISABLED 0x0200
-#define INT_RCV_XMIT_SHUTDOWN 0x0100
-#define INT_FATAL_ERROR 0x0080
-#define INT_CABLE_PULL 0x0020
-#define INT_SIGNAL_CHANGE 0x0010
-#define HDLC_PPP_PURE_ASYNC 0x02
-#define HDLC_FF_FILL 0x00
-#define HDLC_HDW_FLOW 0x01
-#define START_XMIT 0x80
-#define ICOM_ACFG_DRIVE1 0x20
-#define ICOM_ACFG_NO_PARITY 0x00
-#define ICOM_ACFG_PARITY_ENAB 0x02
-#define ICOM_ACFG_PARITY_ODD 0x01
-#define ICOM_ACFG_8BPC 0x00
-#define ICOM_ACFG_7BPC 0x04
-#define ICOM_ACFG_6BPC 0x08
-#define ICOM_ACFG_5BPC 0x0C
-#define ICOM_ACFG_1STOP_BIT 0x00
-#define ICOM_ACFG_2STOP_BIT 0x10
-#define ICOM_DTR 0x80
-#define ICOM_RTS 0x40
-#define ICOM_RI 0x08
-#define ICOM_DSR 0x80
-#define ICOM_DCD 0x20
-#define ICOM_CTS 0x40
-
-#define NUM_XBUFFS 1
-#define NUM_RBUFFS 2
-#define RCV_BUFF_SZ 0x0200
-#define XMIT_BUFF_SZ 0x1000
-struct statusArea {
- /**********************************************/
- /* Transmit Status Area */
- /**********************************************/
- struct xmit_status_area{
- u32 leNext; /* Next entry in Little Endian on Adapter */
- u32 leNextASD;
- u32 leBuffer; /* Buffer for entry in LE for Adapter */
- u16 leLengthASD;
- u16 leOffsetASD;
- u16 leLength; /* Length of data in segment */
- u16 flags;
-#define SA_FLAGS_DONE 0x0080 /* Done with Segment */
-#define SA_FLAGS_CONTINUED 0x8000 /* More Segments */
-#define SA_FLAGS_IDLE 0x4000 /* Mark IDLE after frm */
-#define SA_FLAGS_READY_TO_XMIT 0x0800
-#define SA_FLAGS_STAT_MASK 0x007F
- } xmit[NUM_XBUFFS];
-
- /**********************************************/
- /* Receive Status Area */
- /**********************************************/
- struct {
- u32 leNext; /* Next entry in Little Endian on Adapter */
- u32 leNextASD;
- u32 leBuffer; /* Buffer for entry in LE for Adapter */
- u16 WorkingLength; /* size of segment */
- u16 reserv01;
- u16 leLength; /* Length of data in segment */
- u16 flags;
-#define SA_FL_RCV_DONE 0x0010 /* Data ready */
-#define SA_FLAGS_OVERRUN 0x0040
-#define SA_FLAGS_PARITY_ERROR 0x0080
-#define SA_FLAGS_FRAME_ERROR 0x0001
-#define SA_FLAGS_FRAME_TRUNC 0x0002
-#define SA_FLAGS_BREAK_DET 0x0004 /* set conditionally by device driver, not hardware */
-#define SA_FLAGS_RCV_MASK 0xFFE6
- } rcv[NUM_RBUFFS];
-};
-
-struct icom_adapter;
-
-
-#define ICOM_MAJOR 243
-#define ICOM_MINOR_START 0
-
-struct icom_port {
- struct uart_port uart_port;
- u8 imbed_modem;
-#define ICOM_UNKNOWN 1
-#define ICOM_RVX 2
-#define ICOM_IMBED_MODEM 3
- unsigned char cable_id;
- unsigned char read_status_mask;
- unsigned char ignore_status_mask;
- void __iomem * int_reg;
- struct icom_regs __iomem *global_reg;
- struct func_dram __iomem *dram;
- int port;
- struct statusArea *statStg;
- dma_addr_t statStg_pci;
- u32 *xmitRestart;
- dma_addr_t xmitRestart_pci;
- unsigned char *xmit_buf;
- dma_addr_t xmit_buf_pci;
- unsigned char *recv_buf;
- dma_addr_t recv_buf_pci;
- int next_rcv;
- int put_length;
- int status;
-#define ICOM_PORT_ACTIVE 1 /* Port exists. */
-#define ICOM_PORT_OFF 0 /* Port does not exist. */
- int load_in_progress;
- struct icom_adapter *adapter;
-};
-
-struct icom_adapter {
- void __iomem * base_addr;
- unsigned long base_addr_pci;
- struct pci_dev *pci_dev;
- struct icom_port port_info[4];
- int index;
- int version;
-#define ADAPTER_V1 0x0001
-#define ADAPTER_V2 0x0002
- u32 subsystem_id;
-#define FOUR_PORT_MODEL 0x0252
-#define V2_TWO_PORTS_RVX 0x021A
-#define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM 0x0251
- int numb_ports;
- struct list_head icom_adapter_entry;
- struct kref kref;
-};
-
-/* prototype */
-extern void iCom_sercons_init(void);
-
-struct lookup_proc_table {
- u32 __iomem *global_control_reg;
- unsigned long processor_id;
-};
-
-struct lookup_int_table {
- u32 __iomem *global_int_mask;
- unsigned long processor_id;
-};
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index b1639b174292..30edb35a6a15 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1937,8 +1937,6 @@ static int imx_uart_rs485_config(struct uart_port *port,
rs485conf->flags & SER_RS485_RX_DURING_TX)
imx_uart_start_rx(port);
- port->rs485 = *rs485conf;
-
return 0;
}
diff --git a/drivers/tty/serial/jsm/jsm_cls.c b/drivers/tty/serial/jsm/jsm_cls.c
index 444f233ebd1f..3fd57ac3ad81 100644
--- a/drivers/tty/serial/jsm/jsm_cls.c
+++ b/drivers/tty/serial/jsm/jsm_cls.c
@@ -689,7 +689,7 @@ static void cls_param(struct jsm_channel *ch)
/*
* If baud rate is zero, flush queues, and set mval to drop DTR.
*/
- if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+ if ((ch->ch_c_cflag & CBAUD) == B0) {
ch->ch_r_head = 0;
ch->ch_r_tail = 0;
ch->ch_e_head = 0;
@@ -723,14 +723,8 @@ static void cls_param(struct jsm_channel *ch)
if (!(ch->ch_c_cflag & PARODD))
lcr |= UART_LCR_EPAR;
- /*
- * Not all platforms support mark/space parity,
- * so this will hide behind an ifdef.
- */
-#ifdef CMSPAR
if (ch->ch_c_cflag & CMSPAR)
lcr |= UART_LCR_SPAR;
-#endif
if (ch->ch_c_cflag & CSTOPB)
lcr |= UART_LCR_STOP;
diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c
index 110696cdaa1d..0c78f66276cd 100644
--- a/drivers/tty/serial/jsm/jsm_neo.c
+++ b/drivers/tty/serial/jsm/jsm_neo.c
@@ -938,7 +938,7 @@ static void neo_param(struct jsm_channel *ch)
/*
* If baud rate is zero, flush queues, and set mval to drop DTR.
*/
- if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+ if ((ch->ch_c_cflag & CBAUD) == B0) {
ch->ch_r_head = ch->ch_r_tail = 0;
ch->ch_e_head = ch->ch_e_tail = 0;
@@ -997,14 +997,8 @@ static void neo_param(struct jsm_channel *ch)
if (!(ch->ch_c_cflag & PARODD))
lcr |= UART_LCR_EPAR;
- /*
- * Not all platforms support mark/space parity,
- * so this will hide behind an ifdef.
- */
-#ifdef CMSPAR
if (ch->ch_c_cflag & CMSPAR)
lcr |= UART_LCR_SPAR;
-#endif
if (ch->ch_c_cflag & CSTOPB)
lcr |= UART_LCR_STOP;
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 3112b4a05448..a0b6ea52d133 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1037,7 +1037,6 @@ static int max310x_rs485_config(struct uart_port *port,
rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX |
SER_RS485_ENABLED;
- memset(rs485->padding, 0, sizeof(rs485->padding));
port->rs485 = *rs485;
schedule_work(&one->rs_work);
diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z135_uart.c
index 9acae5f8fc32..12117b596e73 100644
--- a/drivers/tty/serial/men_z135_uart.c
+++ b/drivers/tty/serial/men_z135_uart.c
@@ -833,7 +833,6 @@ static int men_z135_probe(struct mcb_device *mdev,
uart->port.iotype = UPIO_MEM;
uart->port.ops = &men_z135_ops;
uart->port.irq = mcb_get_irq(mdev);
- uart->port.iotype = UPIO_MEM;
uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
uart->port.line = line++;
uart->port.dev = dev;
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 2bf1c57e0981..4869c0059c98 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -68,6 +68,7 @@
#define AML_UART_BAUD_MASK 0x7fffff
#define AML_UART_BAUD_USE BIT(23)
#define AML_UART_BAUD_XTAL BIT(24)
+#define AML_UART_BAUD_XTAL_DIV2 BIT(27)
#define AML_UART_PORT_NUM 12
#define AML_UART_PORT_OFFSET 6
@@ -80,6 +81,10 @@ static struct uart_driver meson_uart_driver;
static struct uart_port *meson_ports[AML_UART_PORT_NUM];
+struct meson_uart_data {
+ bool has_xtal_div2;
+};
+
static void meson_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
}
@@ -253,6 +258,14 @@ static const char *meson_uart_type(struct uart_port *port)
return (port->type == PORT_MESON) ? "meson_uart" : NULL;
}
+/*
+ * This function is called only from probe() using a temporary io mapping
+ * in order to perform a reset before setting up the device. Since the
+ * temporarily mapped region was successfully requested, there can be no
+ * console on this port at this time. Hence it is not necessary for this
+ * function to acquire the port->lock. (Since there is no console on this
+ * port at this time, the port->lock is not initialized yet.)
+ */
static void meson_uart_reset(struct uart_port *port)
{
u32 val;
@@ -267,9 +280,12 @@ static void meson_uart_reset(struct uart_port *port)
static int meson_uart_startup(struct uart_port *port)
{
+ unsigned long flags;
u32 val;
int ret = 0;
+ spin_lock_irqsave(&port->lock, flags);
+
val = readl(port->membase + AML_UART_CONTROL);
val |= AML_UART_CLEAR_ERR;
writel(val, port->membase + AML_UART_CONTROL);
@@ -285,6 +301,8 @@ static int meson_uart_startup(struct uart_port *port)
val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2));
writel(val, port->membase + AML_UART_MISC);
+ spin_unlock_irqrestore(&port->lock, flags);
+
ret = request_irq(port->irq, meson_uart_interrupt, 0,
port->name, port);
@@ -293,16 +311,23 @@ static int meson_uart_startup(struct uart_port *port)
static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
{
- u32 val;
+ const struct meson_uart_data *private_data = port->private_data;
+ u32 val = 0;
while (!meson_uart_tx_empty(port))
cpu_relax();
if (port->uartclk == 24000000) {
- val = ((port->uartclk / 3) / baud) - 1;
+ unsigned int xtal_div = 3;
+
+ if (private_data && private_data->has_xtal_div2) {
+ xtal_div = 2;
+ val |= AML_UART_BAUD_XTAL_DIV2;
+ }
+ val |= DIV_ROUND_CLOSEST(port->uartclk / xtal_div, baud) - 1;
val |= AML_UART_BAUD_XTAL;
} else {
- val = ((port->uartclk * 10 / (baud * 4) + 5) / 10) - 1;
+ val = DIV_ROUND_CLOSEST(port->uartclk / 4, baud) - 1;
}
val |= AML_UART_BAUD_USE;
writel(val, port->membase + AML_UART_REG5);
@@ -749,6 +774,7 @@ static int meson_uart_probe(struct platform_device *pdev)
port->x_char = 0;
port->ops = &meson_uart_ops;
port->fifosize = fifosize;
+ port->private_data = (void *)device_get_match_data(&pdev->dev);
meson_ports[pdev->id] = port;
platform_set_drvdata(pdev, port);
@@ -777,11 +803,19 @@ static int meson_uart_remove(struct platform_device *pdev)
return 0;
}
+static struct meson_uart_data s4_uart_data = {
+ .has_xtal_div2 = true,
+};
+
static const struct of_device_id meson_uart_dt_match[] = {
{ .compatible = "amlogic,meson6-uart" },
{ .compatible = "amlogic,meson8-uart" },
{ .compatible = "amlogic,meson8b-uart" },
{ .compatible = "amlogic,meson-gx-uart" },
+ {
+ .compatible = "amlogic,meson-s4-uart",
+ .data = (void *)&s4_uart_data,
+ },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 3acc0f185762..e50f069b5ebb 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -38,6 +38,8 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
@@ -754,9 +756,6 @@ static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np)
port->irqflags = IRQF_SHARED;
port->irq = psc_fifoc_irq;
}
-#endif
-
-#ifdef CONFIG_PPC_MPC512x
#define PSC_5125(port) ((struct mpc5125_psc __iomem *)((port)->membase))
#define FIFO_5125(port) ((struct mpc512x_psc_fifo __iomem *)(PSC_5125(port)+1))
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 23c94b927776..e676ec761f18 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -1599,6 +1599,7 @@ static inline struct uart_port *msm_get_port_from_line(unsigned int line)
static void __msm_console_write(struct uart_port *port, const char *s,
unsigned int count, bool is_uartdm)
{
+ unsigned long flags;
int i;
int num_newlines = 0;
bool replaced = false;
@@ -1616,6 +1617,8 @@ static void __msm_console_write(struct uart_port *port, const char *s,
num_newlines++;
count += num_newlines;
+ local_irq_save(flags);
+
if (port->sysrq)
locked = 0;
else if (oops_in_progress)
@@ -1661,6 +1664,8 @@ static void __msm_console_write(struct uart_port *port, const char *s,
if (locked)
spin_unlock(&port->lock);
+
+ local_irq_restore(flags);
}
static void msm_console_write(struct console *co, const char *s,
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 8d5ffa196097..46f4d4cacb6e 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1336,18 +1336,11 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
up->ier = 0;
serial_out(up, UART_IER, 0);
- /* Clamp the delays to [0, 100ms] */
- rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
- rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
-
- /* store new config */
- port->rs485 = *rs485;
-
if (up->rts_gpiod) {
/* enable / disable rts */
- val = (port->rs485.flags & SER_RS485_ENABLED) ?
+ val = (rs485->flags & SER_RS485_ENABLED) ?
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
- val = (port->rs485.flags & val) ? 1 : 0;
+ val = (rs485->flags & val) ? 1 : 0;
gpiod_set_value(up->rts_gpiod, val);
}
@@ -1358,7 +1351,7 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
/* If RS-485 is disabled, make sure the THR interrupt is fired when
* TX FIFO is below the trigger level.
*/
- if (!(port->rs485.flags & SER_RS485_ENABLED) &&
+ if (!(rs485->flags & SER_RS485_ENABLED) &&
(up->scr & OMAP_UART_SCR_TX_EMPTY)) {
up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
serial_out(up, UART_OMAP_SCR, up->scr);
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
index 5250bd7d390a..44d20e5a7dd3 100644
--- a/drivers/tty/serial/owl-uart.c
+++ b/drivers/tty/serial/owl-uart.c
@@ -184,9 +184,6 @@ static void owl_uart_send_chars(struct uart_port *port)
struct circ_buf *xmit = &port->state->xmit;
unsigned int ch;
- if (uart_tx_stopped(port))
- return;
-
if (port->x_char) {
while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU))
cpu_relax();
@@ -195,6 +192,9 @@ static void owl_uart_send_chars(struct uart_port *port)
port->x_char = 0;
}
+ if (uart_tx_stopped(port))
+ return;
+
while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU)) {
if (uart_circ_empty(xmit))
break;
@@ -731,6 +731,7 @@ static int owl_uart_probe(struct platform_device *pdev)
owl_port->port.uartclk = clk_get_rate(owl_port->clk);
if (owl_port->port.uartclk == 0) {
dev_err(&pdev->dev, "clock rate is zero\n");
+ clk_disable_unprepare(owl_port->clk);
return -EINVAL;
}
owl_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY;
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index affe71f8b50c..3b26524d48e3 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -550,18 +550,6 @@ static u8 pch_uart_hal_get_modem(struct eg20t_port *priv)
return (u8)msr;
}
-static void pch_uart_hal_write(struct eg20t_port *priv,
- const unsigned char *buf, int tx_size)
-{
- int i;
- unsigned int thr;
-
- for (i = 0; i < tx_size;) {
- thr = buf[i++];
- iowrite8(thr, priv->membase + PCH_UART_THR);
- }
-}
-
static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
int rx_size)
{
@@ -624,22 +612,6 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
return 0;
}
-static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
-{
- int ret = 0;
- struct uart_port *port = &priv->port;
-
- if (port->x_char) {
- dev_dbg(priv->port.dev, "%s:X character send %02x (%lu)\n",
- __func__, port->x_char, jiffies);
- buf[0] = port->x_char;
- port->x_char = 0;
- ret = 1;
- }
-
- return ret;
-}
-
static int dma_push_rx(struct eg20t_port *priv, int size)
{
int room;
@@ -785,31 +757,6 @@ static void pch_dma_tx_complete(void *arg)
pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
}
-static int pop_tx(struct eg20t_port *priv, int size)
-{
- int count = 0;
- struct uart_port *port = &priv->port;
- struct circ_buf *xmit = &port->state->xmit;
-
- if (uart_tx_stopped(port) || uart_circ_empty(xmit) || count >= size)
- goto pop_tx_end;
-
- do {
- int cnt_to_end =
- CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
- int sz = min(size - count, cnt_to_end);
- pch_uart_hal_write(priv, &xmit->buf[xmit->tail], sz);
- xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1);
- count += sz;
- } while (!uart_circ_empty(xmit) && count < size);
-
-pop_tx_end:
- dev_dbg(priv->port.dev, "%d characters. Remained %d characters.(%lu)\n",
- count, size - count, jiffies);
-
- return count;
-}
-
static int handle_rx_to(struct eg20t_port *priv)
{
struct pch_uart_buffer *buf;
@@ -875,8 +822,6 @@ static unsigned int handle_tx(struct eg20t_port *priv)
struct uart_port *port = &priv->port;
struct circ_buf *xmit = &port->state->xmit;
int fifo_size;
- int tx_size;
- int size;
int tx_empty;
if (!priv->start_tx) {
@@ -889,19 +834,19 @@ static unsigned int handle_tx(struct eg20t_port *priv)
fifo_size = max(priv->fifo_size, 1);
tx_empty = 1;
- if (pop_tx_x(priv, xmit->buf)) {
- pch_uart_hal_write(priv, xmit->buf, 1);
+ if (port->x_char) {
+ iowrite8(port->x_char, priv->membase + PCH_UART_THR);
port->icount.tx++;
+ port->x_char = 0;
tx_empty = 0;
fifo_size--;
}
- size = min(xmit->head - xmit->tail, fifo_size);
- if (size < 0)
- size = fifo_size;
- tx_size = pop_tx(priv, size);
- if (tx_size > 0) {
- port->icount.tx += tx_size;
+ while (!uart_tx_stopped(port) && !uart_circ_empty(xmit) && fifo_size) {
+ iowrite8(xmit->buf[xmit->tail], priv->membase + PCH_UART_THR);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ fifo_size--;
tx_empty = 0;
}
@@ -946,9 +891,11 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
}
fifo_size = max(priv->fifo_size, 1);
- if (pop_tx_x(priv, xmit->buf)) {
- pch_uart_hal_write(priv, xmit->buf, 1);
+
+ if (port->x_char) {
+ iowrite8(port->x_char, priv->membase + PCH_UART_THR);
port->icount.tx++;
+ port->x_char = 0;
fifo_size--;
}
diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c
index b7a3a1b959b1..b399aac530fe 100644
--- a/drivers/tty/serial/pic32_uart.c
+++ b/drivers/tty/serial/pic32_uart.c
@@ -25,38 +25,114 @@
#include <linux/delay.h>
#include <asm/mach-pic32/pic32.h>
-#include "pic32_uart.h"
/* UART name and device definitions */
#define PIC32_DEV_NAME "pic32-uart"
#define PIC32_MAX_UARTS 6
#define PIC32_SDEV_NAME "ttyPIC"
-/* pic32_sport pointer for console use */
-static struct pic32_sport *pic32_sports[PIC32_MAX_UARTS];
+#define PIC32_UART_DFLT_BRATE 9600
+#define PIC32_UART_TX_FIFO_DEPTH 8
+#define PIC32_UART_RX_FIFO_DEPTH 8
+
+#define PIC32_UART_MODE 0x00
+#define PIC32_UART_STA 0x10
+#define PIC32_UART_TX 0x20
+#define PIC32_UART_RX 0x30
+#define PIC32_UART_BRG 0x40
+
+/* struct pic32_sport - pic32 serial port descriptor
+ * @port: uart port descriptor
+ * @idx: port index
+ * @irq_fault: virtual fault interrupt number
+ * @irq_fault_name: irq fault name
+ * @irq_rx: virtual rx interrupt number
+ * @irq_rx_name: irq rx name
+ * @irq_tx: virtual tx interrupt number
+ * @irq_tx_name: irq tx name
+ * @cts_gpio: clear to send gpio
+ * @dev: device descriptor
+ **/
+struct pic32_sport {
+ struct uart_port port;
+ int idx;
+
+ int irq_fault;
+ const char *irq_fault_name;
+ int irq_rx;
+ const char *irq_rx_name;
+ int irq_tx;
+ const char *irq_tx_name;
+ bool enable_tx_irq;
+
+ bool hw_flow_ctrl;
+ int cts_gpio;
+
+ struct clk *clk;
+
+ struct device *dev;
+};
-static inline void pic32_wait_deplete_txbuf(struct pic32_sport *sport)
+static inline struct pic32_sport *to_pic32_sport(struct uart_port *port)
{
- /* wait for tx empty, otherwise chars will be lost or corrupted */
- while (!(pic32_uart_readl(sport, PIC32_UART_STA) & PIC32_UART_STA_TRMT))
- udelay(1);
+ return container_of(port, struct pic32_sport, port);
}
-static inline int pic32_enable_clock(struct pic32_sport *sport)
+static inline void pic32_uart_writel(struct pic32_sport *sport,
+ u32 reg, u32 val)
{
- int ret = clk_prepare_enable(sport->clk);
-
- if (ret)
- return ret;
+ __raw_writel(val, sport->port.membase + reg);
+}
- sport->ref_clk++;
- return 0;
+static inline u32 pic32_uart_readl(struct pic32_sport *sport, u32 reg)
+{
+ return __raw_readl(sport->port.membase + reg);
}
-static inline void pic32_disable_clock(struct pic32_sport *sport)
+/* pic32 uart mode register bits */
+#define PIC32_UART_MODE_ON BIT(15)
+#define PIC32_UART_MODE_FRZ BIT(14)
+#define PIC32_UART_MODE_SIDL BIT(13)
+#define PIC32_UART_MODE_IREN BIT(12)
+#define PIC32_UART_MODE_RTSMD BIT(11)
+#define PIC32_UART_MODE_RESV1 BIT(10)
+#define PIC32_UART_MODE_UEN1 BIT(9)
+#define PIC32_UART_MODE_UEN0 BIT(8)
+#define PIC32_UART_MODE_WAKE BIT(7)
+#define PIC32_UART_MODE_LPBK BIT(6)
+#define PIC32_UART_MODE_ABAUD BIT(5)
+#define PIC32_UART_MODE_RXINV BIT(4)
+#define PIC32_UART_MODE_BRGH BIT(3)
+#define PIC32_UART_MODE_PDSEL1 BIT(2)
+#define PIC32_UART_MODE_PDSEL0 BIT(1)
+#define PIC32_UART_MODE_STSEL BIT(0)
+
+/* pic32 uart status register bits */
+#define PIC32_UART_STA_UTXISEL1 BIT(15)
+#define PIC32_UART_STA_UTXISEL0 BIT(14)
+#define PIC32_UART_STA_UTXINV BIT(13)
+#define PIC32_UART_STA_URXEN BIT(12)
+#define PIC32_UART_STA_UTXBRK BIT(11)
+#define PIC32_UART_STA_UTXEN BIT(10)
+#define PIC32_UART_STA_UTXBF BIT(9)
+#define PIC32_UART_STA_TRMT BIT(8)
+#define PIC32_UART_STA_URXISEL1 BIT(7)
+#define PIC32_UART_STA_URXISEL0 BIT(6)
+#define PIC32_UART_STA_ADDEN BIT(5)
+#define PIC32_UART_STA_RIDLE BIT(4)
+#define PIC32_UART_STA_PERR BIT(3)
+#define PIC32_UART_STA_FERR BIT(2)
+#define PIC32_UART_STA_OERR BIT(1)
+#define PIC32_UART_STA_URXDA BIT(0)
+
+/* pic32_sport pointer for console use */
+static struct pic32_sport *pic32_sports[PIC32_MAX_UARTS];
+
+static inline void pic32_wait_deplete_txbuf(struct pic32_sport *sport)
{
- sport->ref_clk--;
- clk_disable_unprepare(sport->clk);
+ /* wait for tx empty, otherwise chars will be lost or corrupted */
+ while (!(pic32_uart_readl(sport, PIC32_UART_STA) & PIC32_UART_STA_TRMT))
+ udelay(1);
}
/* serial core request to check if uart tx buffer is empty */
@@ -117,16 +193,16 @@ static unsigned int pic32_uart_get_mctrl(struct uart_port *port)
*/
static inline void pic32_uart_irqtxen(struct pic32_sport *sport, u8 en)
{
- if (en && !tx_irq_enabled(sport)) {
+ if (en && !sport->enable_tx_irq) {
enable_irq(sport->irq_tx);
- tx_irq_enabled(sport) = 1;
- } else if (!en && tx_irq_enabled(sport)) {
+ sport->enable_tx_irq = true;
+ } else if (!en && sport->enable_tx_irq) {
/* use disable_irq_nosync() and not disable_irq() to avoid self
* imposed deadlock by not waiting for irq handler to end,
* since this callback is called from interrupt context.
*/
disable_irq_nosync(sport->irq_tx);
- tx_irq_enabled(sport) = 0;
+ sport->enable_tx_irq = false;
}
}
@@ -395,7 +471,7 @@ static int pic32_uart_startup(struct uart_port *port)
local_irq_save(flags);
- ret = pic32_enable_clock(sport);
+ ret = clk_prepare_enable(sport->clk);
if (ret) {
local_irq_restore(flags);
goto out_done;
@@ -419,7 +495,7 @@ static int pic32_uart_startup(struct uart_port *port)
* For each irq request_irq() is called with interrupt disabled.
* And the irq is enabled as soon as we are ready to handle them.
*/
- tx_irq_enabled(sport) = 0;
+ sport->enable_tx_irq = false;
sport->irq_fault_name = kasprintf(GFP_KERNEL, "%s%d-fault",
pic32_uart_type(port),
@@ -431,7 +507,7 @@ static int pic32_uart_startup(struct uart_port *port)
}
irq_set_status_flags(sport->irq_fault, IRQ_NOAUTOEN);
ret = request_irq(sport->irq_fault, pic32_uart_fault_interrupt,
- sport->irqflags_fault, sport->irq_fault_name, port);
+ IRQF_NO_THREAD, sport->irq_fault_name, port);
if (ret) {
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
__func__, sport->irq_fault, ret,
@@ -449,7 +525,7 @@ static int pic32_uart_startup(struct uart_port *port)
}
irq_set_status_flags(sport->irq_rx, IRQ_NOAUTOEN);
ret = request_irq(sport->irq_rx, pic32_uart_rx_interrupt,
- sport->irqflags_rx, sport->irq_rx_name, port);
+ IRQF_NO_THREAD, sport->irq_rx_name, port);
if (ret) {
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
__func__, sport->irq_rx, ret,
@@ -467,7 +543,7 @@ static int pic32_uart_startup(struct uart_port *port)
}
irq_set_status_flags(sport->irq_tx, IRQ_NOAUTOEN);
ret = request_irq(sport->irq_tx, pic32_uart_tx_interrupt,
- sport->irqflags_tx, sport->irq_tx_name, port);
+ IRQF_NO_THREAD, sport->irq_tx_name, port);
if (ret) {
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
__func__, sport->irq_tx, ret,
@@ -488,19 +564,21 @@ static int pic32_uart_startup(struct uart_port *port)
/* enable all interrupts and eanable uart */
pic32_uart_en_and_unmask(port);
+ local_irq_restore(flags);
+
enable_irq(sport->irq_rx);
return 0;
out_t:
- kfree(sport->irq_tx_name);
free_irq(sport->irq_tx, port);
+ kfree(sport->irq_tx_name);
out_r:
- kfree(sport->irq_rx_name);
free_irq(sport->irq_rx, port);
+ kfree(sport->irq_rx_name);
out_f:
- kfree(sport->irq_fault_name);
free_irq(sport->irq_fault, port);
+ kfree(sport->irq_fault_name);
out_done:
return ret;
}
@@ -515,12 +593,15 @@ static void pic32_uart_shutdown(struct uart_port *port)
spin_lock_irqsave(&port->lock, flags);
pic32_uart_dsbl_and_mask(port);
spin_unlock_irqrestore(&port->lock, flags);
- pic32_disable_clock(sport);
+ clk_disable_unprepare(sport->clk);
/* free all 3 interrupts for this UART */
free_irq(sport->irq_fault, port);
+ kfree(sport->irq_fault_name);
free_irq(sport->irq_tx, port);
+ kfree(sport->irq_tx_name);
free_irq(sport->irq_rx, port);
+ kfree(sport->irq_rx_name);
}
/* serial core request to change current uart setting */
@@ -712,10 +793,9 @@ static void pic32_console_write(struct console *co, const char *s,
unsigned int count)
{
struct pic32_sport *sport = pic32_sports[co->index];
- struct uart_port *port = pic32_get_port(sport);
/* call uart helper to deal with \r\n */
- uart_console_write(port, s, count, pic32_console_putchar);
+ uart_console_write(&sport->port, s, count, pic32_console_putchar);
}
/* console core request to setup given console, find matching uart
@@ -724,7 +804,6 @@ static void pic32_console_write(struct console *co, const char *s,
static int pic32_console_setup(struct console *co, char *options)
{
struct pic32_sport *sport;
- struct uart_port *port = NULL;
int baud = 115200;
int bits = 8;
int parity = 'n';
@@ -737,16 +816,15 @@ static int pic32_console_setup(struct console *co, char *options)
sport = pic32_sports[co->index];
if (!sport)
return -ENODEV;
- port = pic32_get_port(sport);
- ret = pic32_enable_clock(sport);
+ ret = clk_prepare_enable(sport->clk);
if (ret)
return ret;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
- return uart_set_options(port, co, baud, parity, bits, flow);
+ return uart_set_options(&sport->port, co, baud, parity, bits, flow);
}
static struct uart_driver pic32_uart_driver;
@@ -816,13 +894,9 @@ static int pic32_uart_probe(struct platform_device *pdev)
sport->idx = uart_idx;
sport->irq_fault = irq_of_parse_and_map(np, 0);
- sport->irqflags_fault = IRQF_NO_THREAD;
sport->irq_rx = irq_of_parse_and_map(np, 1);
- sport->irqflags_rx = IRQF_NO_THREAD;
sport->irq_tx = irq_of_parse_and_map(np, 2);
- sport->irqflags_tx = IRQF_NO_THREAD;
sport->clk = devm_clk_get(&pdev->dev, NULL);
- sport->cts_gpio = -EINVAL;
sport->dev = &pdev->dev;
/* Hardware flow control: gpios
@@ -850,7 +924,6 @@ static int pic32_uart_probe(struct platform_device *pdev)
pic32_sports[uart_idx] = sport;
port = &sport->port;
- memset(port, 0, sizeof(*port));
port->iotype = UPIO_MEM;
port->mapbase = res_mem->start;
port->ops = &pic32_uart_ops;
@@ -872,7 +945,7 @@ static int pic32_uart_probe(struct platform_device *pdev)
/* The peripheral clock has been enabled by console_setup,
* so disable it till the port is used.
*/
- pic32_disable_clock(sport);
+ clk_disable_unprepare(sport->clk);
}
#endif
@@ -893,7 +966,7 @@ static int pic32_uart_remove(struct platform_device *pdev)
struct pic32_sport *sport = to_pic32_sport(port);
uart_remove_one_port(&pic32_uart_driver, port);
- pic32_disable_clock(sport);
+ clk_disable_unprepare(sport->clk);
platform_set_drvdata(pdev, NULL);
pic32_sports[sport->idx] = NULL;
diff --git a/drivers/tty/serial/pic32_uart.h b/drivers/tty/serial/pic32_uart.h
deleted file mode 100644
index b15639cc336b..000000000000
--- a/drivers/tty/serial/pic32_uart.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * PIC32 Integrated Serial Driver.
- *
- * Copyright (C) 2015 Microchip Technology, Inc.
- *
- * Authors:
- * Sorin-Andrei Pistirica <andrei.pistirica@microchip.com>
- */
-#ifndef __DT_PIC32_UART_H__
-#define __DT_PIC32_UART_H__
-
-#define PIC32_UART_DFLT_BRATE (9600)
-#define PIC32_UART_TX_FIFO_DEPTH (8)
-#define PIC32_UART_RX_FIFO_DEPTH (8)
-
-#define PIC32_UART_MODE 0x00
-#define PIC32_UART_STA 0x10
-#define PIC32_UART_TX 0x20
-#define PIC32_UART_RX 0x30
-#define PIC32_UART_BRG 0x40
-
-struct pic32_console_opt {
- int baud;
- int parity;
- int bits;
- int flow;
-};
-
-/* struct pic32_sport - pic32 serial port descriptor
- * @port: uart port descriptor
- * @idx: port index
- * @irq_fault: virtual fault interrupt number
- * @irqflags_fault: flags related to fault irq
- * @irq_fault_name: irq fault name
- * @irq_rx: virtual rx interrupt number
- * @irqflags_rx: flags related to rx irq
- * @irq_rx_name: irq rx name
- * @irq_tx: virtual tx interrupt number
- * @irqflags_tx: : flags related to tx irq
- * @irq_tx_name: irq tx name
- * @cts_gpio: clear to send gpio
- * @dev: device descriptor
- **/
-struct pic32_sport {
- struct uart_port port;
- struct pic32_console_opt opt;
- int idx;
-
- int irq_fault;
- int irqflags_fault;
- const char *irq_fault_name;
- int irq_rx;
- int irqflags_rx;
- const char *irq_rx_name;
- int irq_tx;
- int irqflags_tx;
- const char *irq_tx_name;
- u8 enable_tx_irq;
-
- bool hw_flow_ctrl;
- int cts_gpio;
-
- int ref_clk;
- struct clk *clk;
-
- struct device *dev;
-};
-#define to_pic32_sport(c) container_of(c, struct pic32_sport, port)
-#define pic32_get_port(sport) (&sport->port)
-#define pic32_get_opt(sport) (&sport->opt)
-#define tx_irq_enabled(sport) (sport->enable_tx_irq)
-
-static inline void pic32_uart_writel(struct pic32_sport *sport,
- u32 reg, u32 val)
-{
- struct uart_port *port = pic32_get_port(sport);
-
- __raw_writel(val, port->membase + reg);
-}
-
-static inline u32 pic32_uart_readl(struct pic32_sport *sport, u32 reg)
-{
- struct uart_port *port = pic32_get_port(sport);
-
- return __raw_readl(port->membase + reg);
-}
-
-/* pic32 uart mode register bits */
-#define PIC32_UART_MODE_ON BIT(15)
-#define PIC32_UART_MODE_FRZ BIT(14)
-#define PIC32_UART_MODE_SIDL BIT(13)
-#define PIC32_UART_MODE_IREN BIT(12)
-#define PIC32_UART_MODE_RTSMD BIT(11)
-#define PIC32_UART_MODE_RESV1 BIT(10)
-#define PIC32_UART_MODE_UEN1 BIT(9)
-#define PIC32_UART_MODE_UEN0 BIT(8)
-#define PIC32_UART_MODE_WAKE BIT(7)
-#define PIC32_UART_MODE_LPBK BIT(6)
-#define PIC32_UART_MODE_ABAUD BIT(5)
-#define PIC32_UART_MODE_RXINV BIT(4)
-#define PIC32_UART_MODE_BRGH BIT(3)
-#define PIC32_UART_MODE_PDSEL1 BIT(2)
-#define PIC32_UART_MODE_PDSEL0 BIT(1)
-#define PIC32_UART_MODE_STSEL BIT(0)
-
-/* pic32 uart status register bits */
-#define PIC32_UART_STA_UTXISEL1 BIT(15)
-#define PIC32_UART_STA_UTXISEL0 BIT(14)
-#define PIC32_UART_STA_UTXINV BIT(13)
-#define PIC32_UART_STA_URXEN BIT(12)
-#define PIC32_UART_STA_UTXBRK BIT(11)
-#define PIC32_UART_STA_UTXEN BIT(10)
-#define PIC32_UART_STA_UTXBF BIT(9)
-#define PIC32_UART_STA_TRMT BIT(8)
-#define PIC32_UART_STA_URXISEL1 BIT(7)
-#define PIC32_UART_STA_URXISEL0 BIT(6)
-#define PIC32_UART_STA_ADDEN BIT(5)
-#define PIC32_UART_STA_RIDLE BIT(4)
-#define PIC32_UART_STA_PERR BIT(3)
-#define PIC32_UART_STA_FERR BIT(2)
-#define PIC32_UART_STA_OERR BIT(1)
-#define PIC32_UART_STA_URXDA BIT(0)
-
-#endif /* __DT_PIC32_UART_H__ */
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index 5d97c201ad88..3133446e806c 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -24,7 +24,6 @@
*/
#undef DEBUG
-#undef DEBUG_HARD
#undef USE_CTRL_O_SYSRQ
#include <linux/module.h>
@@ -51,7 +50,6 @@
#include <asm/irq.h>
#ifdef CONFIG_PPC_PMAC
-#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
@@ -66,10 +64,6 @@
#include "pmac_zilog.h"
-/* Not yet implemented */
-#undef HAS_DBDMA
-
-static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports.");
MODULE_LICENSE("GPL");
@@ -446,9 +440,6 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
spin_lock(&uap_a->port.lock);
r3 = read_zsreg(uap_a, R3);
-#ifdef DEBUG_HARD
- pmz_debug("irq, r3: %x\n", r3);
-#endif
/* Channel A */
push = false;
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
@@ -613,8 +604,6 @@ static void pmz_start_tx(struct uart_port *port)
struct uart_pmac_port *uap = to_pmz(port);
unsigned char status;
- pmz_debug("pmz: start_tx()\n");
-
uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
@@ -636,7 +625,7 @@ static void pmz_start_tx(struct uart_port *port)
struct circ_buf *xmit = &port->state->xmit;
if (uart_circ_empty(xmit))
- goto out;
+ return;
write_zsdata(uap, xmit->buf[xmit->tail]);
zssync(uap);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -645,8 +634,6 @@ static void pmz_start_tx(struct uart_port *port)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port);
}
- out:
- pmz_debug("pmz: start_tx() done.\n");
}
/*
@@ -659,13 +646,9 @@ static void pmz_stop_rx(struct uart_port *port)
{
struct uart_pmac_port *uap = to_pmz(port);
- pmz_debug("pmz: stop_rx()()\n");
-
/* Disable all RX interrupts. */
uap->curregs[R1] &= ~RxINT_MASK;
pmz_maybe_update_regs(uap);
-
- pmz_debug("pmz: stop_rx() done.\n");
}
/*
@@ -910,8 +893,6 @@ static int pmz_startup(struct uart_port *port)
unsigned long flags;
int pwr_delay = 0;
- pmz_debug("pmz: startup()\n");
-
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
/* A console is never powered down. Else, power up and
@@ -947,8 +928,6 @@ static int pmz_startup(struct uart_port *port)
pmz_interrupt_control(uap, 1);
spin_unlock_irqrestore(&port->lock, flags);
- pmz_debug("pmz: startup() done.\n");
-
return 0;
}
@@ -957,8 +936,6 @@ static void pmz_shutdown(struct uart_port *port)
struct uart_pmac_port *uap = to_pmz(port);
unsigned long flags;
- pmz_debug("pmz: shutdown()\n");
-
spin_lock_irqsave(&port->lock, flags);
/* Disable interrupt requests for the channel */
@@ -987,8 +964,6 @@ static void pmz_shutdown(struct uart_port *port)
pmz_set_scc_power(uap, 0); /* Shut the chip down */
spin_unlock_irqrestore(&port->lock, flags);
-
- pmz_debug("pmz: shutdown() done.\n");
}
/* Shared by TTY driver and serial console setup. The port lock is held
@@ -1233,10 +1208,6 @@ static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
struct uart_pmac_port *uap = to_pmz(port);
unsigned long baud;
- pmz_debug("pmz: set_termios()\n");
-
- memcpy(&uap->termios_cache, termios, sizeof(struct ktermios));
-
/* XXX Check which revs of machines actually allow 1 and 4Mb speeds
* on the IR dongle. Note that the IRTTY driver currently doesn't know
* about the FIR mode and high speed modes. So these are unused. For
@@ -1270,8 +1241,6 @@ static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
pmz_maybe_update_regs(uap);
}
uart_update_timeout(port, termios->c_cflag, baud);
-
- pmz_debug("pmz: set_termios() done.\n");
}
/* The port lock is not held. */
@@ -1400,7 +1369,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
char name[1];
} *slots;
int len;
- struct resource r_ports, r_rxdma, r_txdma;
+ struct resource r_ports;
/*
* Request & map chip registers
@@ -1412,35 +1381,6 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
uap->control_reg = uap->port.membase;
uap->data_reg = uap->control_reg + 0x10;
-
- /*
- * Request & map DBDMA registers
- */
-#ifdef HAS_DBDMA
- if (of_address_to_resource(np, 1, &r_txdma) == 0 &&
- of_address_to_resource(np, 2, &r_rxdma) == 0)
- uap->flags |= PMACZILOG_FLAG_HAS_DMA;
-#else
- memset(&r_txdma, 0, sizeof(struct resource));
- memset(&r_rxdma, 0, sizeof(struct resource));
-#endif
- if (ZS_HAS_DMA(uap)) {
- uap->tx_dma_regs = ioremap(r_txdma.start, 0x100);
- if (uap->tx_dma_regs == NULL) {
- uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
- goto no_dma;
- }
- uap->rx_dma_regs = ioremap(r_rxdma.start, 0x100);
- if (uap->rx_dma_regs == NULL) {
- iounmap(uap->tx_dma_regs);
- uap->tx_dma_regs = NULL;
- uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
- goto no_dma;
- }
- uap->tx_dma_irq = irq_of_parse_and_map(np, 1);
- uap->rx_dma_irq = irq_of_parse_and_map(np, 2);
- }
-no_dma:
/*
* Detect port type
@@ -1506,8 +1446,6 @@ no_dma:
of_device_is_compatible(np->parent->parent, "gatwick")) {
/* IRQs on gatwick are offset by 64 */
uap->port.irq = irq_create_mapping(NULL, 64 + 15);
- uap->tx_dma_irq = irq_create_mapping(NULL, 64 + 4);
- uap->rx_dma_irq = irq_create_mapping(NULL, 64 + 5);
}
/* Setup some valid baud rate information in the register
@@ -1527,8 +1465,6 @@ static void pmz_dispose_port(struct uart_pmac_port *uap)
struct device_node *np;
np = uap->node;
- iounmap(uap->rx_dma_regs);
- iounmap(uap->tx_dma_regs);
iounmap(uap->control_reg);
uap->node = NULL;
of_node_put(np);
@@ -1875,7 +1811,6 @@ static struct platform_driver pmz_driver = {
static int __init init_pmz(void)
{
int rc, i;
- printk(KERN_INFO "%s\n", version);
/*
* First, we need to do a direct OF-based probe pass. We
diff --git a/drivers/tty/serial/pmac_zilog.h b/drivers/tty/serial/pmac_zilog.h
index fa85b0de5c2f..837b97ca0a90 100644
--- a/drivers/tty/serial/pmac_zilog.h
+++ b/drivers/tty/serial/pmac_zilog.h
@@ -43,7 +43,6 @@ struct uart_pmac_port {
#define PMACZILOG_FLAG_TX_ACTIVE 0x00000040
#define PMACZILOG_FLAG_IS_IRDA 0x00000100
#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
-#define PMACZILOG_FLAG_HAS_DMA 0x00000400
#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
@@ -55,16 +54,7 @@ struct uart_pmac_port {
volatile u8 __iomem *control_reg;
volatile u8 __iomem *data_reg;
-#ifdef CONFIG_PPC_PMAC
- unsigned int tx_dma_irq;
- unsigned int rx_dma_irq;
- volatile struct dbdma_regs __iomem *tx_dma_regs;
- volatile struct dbdma_regs __iomem *rx_dma_regs;
-#endif
-
unsigned char irq_name[8];
-
- struct ktermios termios_cache;
};
#define to_pmz(p) ((struct uart_pmac_port *)(p))
@@ -377,7 +367,6 @@ static inline void zssync(struct uart_pmac_port *port)
#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & PMACZILOG_FLAG_MODEM_STATUS)
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
-#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 1543a6028856..4733a233bd0c 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -149,12 +149,6 @@ static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port);
static void qcom_geni_serial_stop_rx(struct uart_port *uport);
static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
-static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
- 32000000, 48000000, 51200000, 64000000,
- 80000000, 96000000, 100000000,
- 102400000, 112000000, 120000000,
- 128000000};
-
#define to_dev_port(ptr, member) \
container_of(ptr, struct qcom_geni_serial_port, member)
@@ -507,7 +501,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
*/
qcom_geni_serial_poll_tx_done(uport);
- if (uart_circ_chars_pending(&uport->state->xmit)) {
+ if (!uart_circ_empty(&uport->state->xmit)) {
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
writel(irq_en | M_TX_FIFO_WATERMARK_EN,
uport->membase + SE_GENI_M_IRQ_EN);
@@ -946,25 +940,43 @@ static int qcom_geni_serial_startup(struct uart_port *uport)
return 0;
}
-static unsigned long get_clk_cfg(unsigned long clk_freq)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(root_freq); i++) {
- if (!(root_freq[i] % clk_freq))
- return root_freq[i];
- }
- return 0;
-}
-
-static unsigned long get_clk_div_rate(unsigned int baud,
+static unsigned long get_clk_div_rate(struct clk *clk, unsigned int baud,
unsigned int sampling_rate, unsigned int *clk_div)
{
unsigned long ser_clk;
unsigned long desired_clk;
+ unsigned long freq, prev;
+ unsigned long div, maxdiv;
+ int64_t mult;
desired_clk = baud * sampling_rate;
- ser_clk = get_clk_cfg(desired_clk);
+ if (!desired_clk) {
+ pr_err("%s: Invalid frequency\n", __func__);
+ return 0;
+ }
+
+ maxdiv = CLK_DIV_MSK >> CLK_DIV_SHFT;
+ prev = 0;
+
+ for (div = 1; div <= maxdiv; div++) {
+ mult = div * desired_clk;
+ if (mult > ULONG_MAX)
+ break;
+
+ freq = clk_round_rate(clk, (unsigned long)mult);
+ if (!(freq % desired_clk)) {
+ ser_clk = freq;
+ break;
+ }
+
+ if (!prev)
+ ser_clk = freq;
+ else if (prev == freq)
+ break;
+
+ prev = freq;
+ }
+
if (!ser_clk) {
pr_err("%s: Can't find matching DFS entry for baud %d\n",
__func__, baud);
@@ -972,6 +984,9 @@ static unsigned long get_clk_div_rate(unsigned int baud,
}
*clk_div = ser_clk / desired_clk;
+ if (!(*clk_div))
+ *clk_div = 1;
+
return ser_clk;
}
@@ -1003,7 +1018,8 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
if (ver >= QUP_SE_VERSION_2_5)
sampling_rate /= 2;
- clk_rate = get_clk_div_rate(baud, sampling_rate, &clk_div);
+ clk_rate = get_clk_div_rate(port->se.clk, baud,
+ sampling_rate, &clk_div);
if (!clk_rate)
goto out_restart_rx;
diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c
index e5f1fded423a..f556b4955f59 100644
--- a/drivers/tty/serial/rda-uart.c
+++ b/drivers/tty/serial/rda-uart.c
@@ -262,6 +262,8 @@ static void rda_uart_set_termios(struct uart_port *port,
fallthrough;
case CS7:
ctrl &= ~RDA_UART_DBITS_8;
+ termios->c_cflag &= ~CSIZE;
+ termios->c_cflag |= CS7;
break;
default:
ctrl |= RDA_UART_DBITS_8;
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index 5fe6cccfc1ae..e64e42a19d1a 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -446,6 +446,8 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
quot = uart_get_divisor(port, baud);
+ del_timer_sync(&sport->timer);
+
spin_lock_irqsave(&sport->port.lock, flags);
sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
@@ -476,8 +478,6 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
UTSR1_TO_SM(UTSR1_ROR);
}
- del_timer_sync(&sport->timer);
-
/*
* Update the per-port timeout.
*/
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index e1585fbae909..d5ca904def34 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -2480,12 +2480,24 @@ s3c24xx_serial_console_write(struct console *co, const char *s,
unsigned int count)
{
unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+ unsigned long flags;
+ bool locked = true;
/* not possible to xmit on unconfigured port */
if (!s3c24xx_port_configured(ucon))
return;
+ if (cons_uart->sysrq)
+ locked = false;
+ else if (oops_in_progress)
+ locked = spin_trylock_irqsave(&cons_uart->lock, flags);
+ else
+ spin_lock_irqsave(&cons_uart->lock, flags);
+
uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
+
+ if (locked)
+ spin_unlock_irqrestore(&cons_uart->lock, flags);
}
/* Shouldn't be __init, as it can be instantiated from other module */
@@ -2814,6 +2826,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
.num_clks = 1,
.clksel_mask = 0,
.clksel_shift = 0,
+ .ucon_mask = APPLE_S5L_UCON_MASK,
},
.def_cfg = {
.ucon = APPLE_S5L_UCON_DEFAULT,
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 5fb201c1b563..8472bf70477c 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1134,16 +1134,6 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
if (rs485->flags & SER_RS485_ENABLED) {
- bool rts_during_rx, rts_during_tx;
-
- rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND;
- rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND;
-
- if (rts_during_rx == rts_during_tx)
- dev_err(port->dev,
- "unsupported RTS signalling on_send:%d after_send:%d - exactly one of RS485 RTS flags should be set\n",
- rts_during_tx, rts_during_rx);
-
/*
* RTS signal is handled by HW, it's timing can't be influenced.
* However, it's sometimes useful to delay TX even without RTS
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 6a8963caf954..9a85b41caa0a 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -24,6 +24,7 @@
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <linux/math64.h>
#include <linux/security.h>
#include <linux/irq.h>
@@ -42,6 +43,11 @@ static struct lock_class_key port_lock_key;
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
+/*
+ * Max time with active RTS before/after data is sent.
+ */
+#define RS485_MAX_RTS_DELAY 100 /* msecs */
+
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
struct ktermios *old_termios);
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
@@ -333,15 +339,18 @@ void
uart_update_timeout(struct uart_port *port, unsigned int cflag,
unsigned int baud)
{
- unsigned int size;
+ unsigned int size = tty_get_frame_size(cflag);
+ u64 frame_time;
- size = tty_get_frame_size(cflag) * port->fifosize;
+ frame_time = (u64)size * NSEC_PER_SEC;
+ size *= port->fifosize;
/*
* Figure the timeout to send the above number of bits.
* Add .02 seconds of slop
*/
port->timeout = (HZ * size) / baud + HZ/50;
+ port->frame_time = DIV64_U64_ROUND_UP(frame_time, baud);
}
EXPORT_SYMBOL(uart_update_timeout);
@@ -1296,8 +1305,36 @@ static int uart_set_rs485_config(struct uart_port *port,
if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user)))
return -EFAULT;
+ /* pick sane settings if the user hasn't */
+ if (!(rs485.flags & SER_RS485_RTS_ON_SEND) ==
+ !(rs485.flags & SER_RS485_RTS_AFTER_SEND)) {
+ dev_warn_ratelimited(port->dev,
+ "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n",
+ port->name, port->line);
+ rs485.flags |= SER_RS485_RTS_ON_SEND;
+ rs485.flags &= ~SER_RS485_RTS_AFTER_SEND;
+ }
+
+ if (rs485.delay_rts_before_send > RS485_MAX_RTS_DELAY) {
+ rs485.delay_rts_before_send = RS485_MAX_RTS_DELAY;
+ dev_warn_ratelimited(port->dev,
+ "%s (%d): RTS delay before sending clamped to %u ms\n",
+ port->name, port->line, rs485.delay_rts_before_send);
+ }
+
+ if (rs485.delay_rts_after_send > RS485_MAX_RTS_DELAY) {
+ rs485.delay_rts_after_send = RS485_MAX_RTS_DELAY;
+ dev_warn_ratelimited(port->dev,
+ "%s (%d): RTS delay after sending clamped to %u ms\n",
+ port->name, port->line, rs485.delay_rts_after_send);
+ }
+ /* Return clean padding area to userspace */
+ memset(rs485.padding, 0, sizeof(rs485.padding));
+
spin_lock_irqsave(&port->lock, flags);
ret = port->rs485_config(port, &rs485);
+ if (!ret)
+ port->rs485 = rs485;
spin_unlock_irqrestore(&port->lock, flags);
if (ret)
return ret;
@@ -1610,24 +1647,24 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
* Note: we have to use pretty tight timings here to satisfy
* the NIST-PCTS.
*/
- char_time = (port->timeout - HZ/50) / port->fifosize;
- char_time = char_time / 5;
- if (char_time == 0)
- char_time = 1;
+ char_time = max(nsecs_to_jiffies(port->frame_time / 5), 1UL);
+
if (timeout && timeout < char_time)
char_time = timeout;
- /*
- * If the transmitter hasn't cleared in twice the approximate
- * amount of time to send the entire FIFO, it probably won't
- * ever clear. This assumes the UART isn't doing flow
- * control, which is currently the case. Hence, if it ever
- * takes longer than port->timeout, this is probably due to a
- * UART bug of some kind. So, we clamp the timeout parameter at
- * 2*port->timeout.
- */
- if (timeout == 0 || timeout > 2 * port->timeout)
- timeout = 2 * port->timeout;
+ if (!uart_cts_enabled(port)) {
+ /*
+ * If the transmitter hasn't cleared in twice the approximate
+ * amount of time to send the entire FIFO, it probably won't
+ * ever clear. This assumes the UART isn't doing flow
+ * control, which is currently the case. Hence, if it ever
+ * takes longer than port->timeout, this is probably due to a
+ * UART bug of some kind. So, we clamp the timeout parameter at
+ * 2*port->timeout.
+ */
+ if (timeout == 0 || timeout > 2 * port->timeout)
+ timeout = 2 * port->timeout;
+ }
expire = jiffies + timeout;
@@ -1643,7 +1680,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
msleep_interruptible(jiffies_to_msecs(char_time));
if (signal_pending(current))
break;
- if (time_after(jiffies, expire))
+ if (timeout && time_after(jiffies, expire))
break;
}
uart_port_deref(port);
@@ -2174,15 +2211,23 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
}
put_device(tty_dev);
- /* Nothing to do if the console is not suspending */
- if (!console_suspend_enabled && uart_console(uport))
+ /*
+ * Nothing to do if the console is not suspending
+ * except stop_rx to prevent any asynchronous data
+ * over RX line. Re-start_rx, when required, is
+ * done by set_termios in resume sequence
+ */
+ if (!console_suspend_enabled && uart_console(uport)) {
+ uport->ops->stop_rx(uport);
goto unlock;
+ }
uport->suspended = 1;
if (tty_port_initialized(port)) {
const struct uart_ops *ops = uport->ops;
int tries;
+ unsigned int mctrl;
tty_port_set_suspended(port, 1);
tty_port_set_initialized(port, 0);
@@ -2190,6 +2235,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
spin_lock_irq(&uport->lock);
ops->stop_tx(uport);
ops->set_mctrl(uport, 0);
+ /* save mctrl so it can be restored on resume */
+ mctrl = uport->mctrl;
+ uport->mctrl = 0;
ops->stop_rx(uport);
spin_unlock_irq(&uport->lock);
@@ -2203,6 +2251,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
uport->name);
ops->shutdown(uport);
+ uport->mctrl = mctrl;
}
/*
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 2213e6b841d3..228e380db080 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -618,6 +618,8 @@ serial_txx9_set_termios(struct uart_port *up, struct ktermios *termios,
case CS6: /* not supported */
case CS8:
cval |= TXX9_SILCR_UMODE_8BIT;
+ termios->c_cflag &= ~CSIZE;
+ termios->c_cflag |= CS8;
break;
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 0f9b8bd23500..0075a1420005 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2379,8 +2379,12 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
int best_clk = -1;
unsigned long flags;
- if ((termios->c_cflag & CSIZE) == CS7)
+ if ((termios->c_cflag & CSIZE) == CS7) {
smr_val |= SCSMR_CHR;
+ } else {
+ termios->c_cflag &= ~CSIZE;
+ termios->c_cflag |= CS8;
+ }
if (termios->c_cflag & PARENB)
smr_val |= SCSMR_PE;
if (termios->c_cflag & PARODD)
diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
index f5ac14c384c4..c0869b080cc3 100644
--- a/drivers/tty/serial/sifive.c
+++ b/drivers/tty/serial/sifive.c
@@ -148,7 +148,6 @@
* @port: struct uart_port embedded in this struct
* @dev: struct device *
* @ier: shadowed copy of the interrupt enable register
- * @clkin_rate: input clock to the UART IP block.
* @baud_rate: UART serial line rate (e.g., 115200 baud)
* @clk: reference to this device's clock
* @clk_notifier: clock rate change notifier for upstream clock changes
@@ -159,7 +158,6 @@ struct sifive_serial_port {
struct uart_port port;
struct device *dev;
unsigned char ier;
- unsigned long clkin_rate;
unsigned long baud_rate;
struct clk *clk;
struct notifier_block clk_notifier;
@@ -463,7 +461,7 @@ static void __ssp_update_div(struct sifive_serial_port *ssp)
{
u16 div;
- div = DIV_ROUND_UP(ssp->clkin_rate, ssp->baud_rate) - 1;
+ div = DIV_ROUND_UP(ssp->port.uartclk, ssp->baud_rate) - 1;
__ssp_writel(div, SIFIVE_SERIAL_DIV_OFFS, ssp);
}
@@ -648,8 +646,8 @@ static int sifive_serial_clk_notifier(struct notifier_block *nb,
udelay(DIV_ROUND_UP(12 * 1000 * 1000, ssp->baud_rate));
}
- if (event == POST_RATE_CHANGE && ssp->clkin_rate != cnd->new_rate) {
- ssp->clkin_rate = cnd->new_rate;
+ if (event == POST_RATE_CHANGE && ssp->port.uartclk != cnd->new_rate) {
+ ssp->port.uartclk = cnd->new_rate;
__ssp_update_div(ssp);
}
@@ -666,19 +664,24 @@ static void sifive_serial_set_termios(struct uart_port *port,
int rate;
char nstop;
- if ((termios->c_cflag & CSIZE) != CS8)
+ if ((termios->c_cflag & CSIZE) != CS8) {
dev_err_once(ssp->port.dev, "only 8-bit words supported\n");
+ termios->c_cflag &= ~CSIZE;
+ termios->c_cflag |= CS8;
+ }
if (termios->c_iflag & (INPCK | PARMRK))
dev_err_once(ssp->port.dev, "parity checking not supported\n");
if (termios->c_iflag & BRKINT)
dev_err_once(ssp->port.dev, "BREAK detection not supported\n");
+ termios->c_iflag &= ~(INPCK|PARMRK|BRKINT);
/* Set number of stop bits */
nstop = (termios->c_cflag & CSTOPB) ? 2 : 1;
__ssp_set_stop_bits(ssp, nstop);
/* Set line rate */
- rate = uart_get_baud_rate(port, termios, old, 0, ssp->clkin_rate / 16);
+ rate = uart_get_baud_rate(port, termios, old, 0,
+ ssp->port.uartclk / 16);
__ssp_update_baud_rate(ssp, rate);
spin_lock_irqsave(&ssp->port.lock, flags);
@@ -996,9 +999,8 @@ static int sifive_serial_probe(struct platform_device *pdev)
}
/* Set up clock divider */
- ssp->clkin_rate = clk_get_rate(ssp->clk);
+ ssp->port.uartclk = clk_get_rate(ssp->clk);
ssp->baud_rate = SIFIVE_DEFAULT_BAUD_RATE;
- ssp->port.uartclk = ssp->baud_rate * 16;
__ssp_update_div(ssp);
platform_set_drvdata(pdev, ssp);
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index d7fd692286cf..1b0da603ab54 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -535,10 +535,14 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
/* set character length */
if ((cflag & CSIZE) == CS7) {
ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
+ cflag |= PARENB;
} else {
ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR :
ASC_CTL_MODE_8BIT;
+ cflag &= ~CSIZE;
+ cflag |= CS8;
}
+ termios->c_cflag = cflag;
/* set stop bit */
ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 87b5cd4c9743..b7b44f4050d4 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -37,6 +37,7 @@
static void stm32_usart_stop_tx(struct uart_port *port);
static void stm32_usart_transmit_chars(struct uart_port *port);
+static void __maybe_unused stm32_usart_console_putchar(struct uart_port *port, unsigned char ch);
static inline struct stm32_port *to_stm32_port(struct uart_port *port)
{
@@ -107,8 +108,6 @@ static int stm32_usart_config_rs485(struct uart_port *port,
stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
- port->rs485 = *rs485conf;
-
rs485conf->flags |= SER_RS485_RX_DURING_TX;
if (rs485conf->flags & SER_RS485_ENABLED) {
@@ -128,13 +127,10 @@ static int stm32_usart_config_rs485(struct uart_port *port,
rs485conf->delay_rts_after_send,
baud);
- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND)
cr3 &= ~USART_CR3_DEP;
- rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
- } else {
+ else
cr3 |= USART_CR3_DEP;
- rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
- }
writel_relaxed(cr3, port->membase + ofs->cr3);
writel_relaxed(cr1, port->membase + ofs->cr1);
@@ -421,6 +417,14 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
}
+static void stm32_usart_tc_interrupt_enable(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TCIE);
+}
+
static void stm32_usart_rx_dma_complete(void *arg)
{
struct uart_port *port = arg;
@@ -446,6 +450,50 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
}
+static void stm32_usart_tc_interrupt_disable(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
+}
+
+static void stm32_usart_rs485_rts_enable(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ struct serial_rs485 *rs485conf = &port->rs485;
+
+ if (stm32_port->hw_flow_control ||
+ !(rs485conf->flags & SER_RS485_ENABLED))
+ return;
+
+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+ mctrl_gpio_set(stm32_port->gpios,
+ stm32_port->port.mctrl | TIOCM_RTS);
+ } else {
+ mctrl_gpio_set(stm32_port->gpios,
+ stm32_port->port.mctrl & ~TIOCM_RTS);
+ }
+}
+
+static void stm32_usart_rs485_rts_disable(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ struct serial_rs485 *rs485conf = &port->rs485;
+
+ if (stm32_port->hw_flow_control ||
+ !(rs485conf->flags & SER_RS485_ENABLED))
+ return;
+
+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+ mctrl_gpio_set(stm32_port->gpios,
+ stm32_port->port.mctrl & ~TIOCM_RTS);
+ } else {
+ mctrl_gpio_set(stm32_port->gpios,
+ stm32_port->port.mctrl | TIOCM_RTS);
+ }
+}
+
static void stm32_usart_transmit_chars_pio(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
@@ -553,6 +601,13 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
u32 isr;
int ret;
+ if (!stm32_port->hw_flow_control &&
+ port->rs485.flags & SER_RS485_ENABLED) {
+ stm32_port->txdone = false;
+ stm32_usart_tc_interrupt_disable(port);
+ stm32_usart_rs485_rts_enable(port);
+ }
+
if (port->x_char) {
if (stm32_usart_tx_dma_started(stm32_port) &&
stm32_usart_tx_dma_enabled(stm32_port))
@@ -593,8 +648,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
- if (uart_circ_empty(xmit))
+ if (uart_circ_empty(xmit)) {
stm32_usart_tx_interrupt_disable(port);
+ if (!stm32_port->hw_flow_control &&
+ port->rs485.flags & SER_RS485_ENABLED) {
+ stm32_port->txdone = true;
+ stm32_usart_tc_interrupt_enable(port);
+ }
+ }
}
static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
@@ -608,6 +669,13 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
sr = readl_relaxed(port->membase + ofs->isr);
+ if (!stm32_port->hw_flow_control &&
+ port->rs485.flags & SER_RS485_ENABLED &&
+ (sr & USART_SR_TC)) {
+ stm32_usart_tc_interrupt_disable(port);
+ stm32_usart_rs485_rts_disable(port);
+ }
+
if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
writel_relaxed(USART_ICR_RTOCF,
port->membase + ofs->icr);
@@ -717,44 +785,27 @@ static void stm32_usart_disable_ms(struct uart_port *port)
static void stm32_usart_stop_tx(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
- struct serial_rs485 *rs485conf = &port->rs485;
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
stm32_usart_tx_interrupt_disable(port);
if (stm32_usart_tx_dma_started(stm32_port) && stm32_usart_tx_dma_enabled(stm32_port))
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
- if (rs485conf->flags & SER_RS485_ENABLED) {
- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
- mctrl_gpio_set(stm32_port->gpios,
- stm32_port->port.mctrl & ~TIOCM_RTS);
- } else {
- mctrl_gpio_set(stm32_port->gpios,
- stm32_port->port.mctrl | TIOCM_RTS);
- }
- }
+ stm32_usart_rs485_rts_disable(port);
}
/* There are probably characters waiting to be transmitted. */
static void stm32_usart_start_tx(struct uart_port *port)
{
- struct stm32_port *stm32_port = to_stm32_port(port);
- struct serial_rs485 *rs485conf = &port->rs485;
struct circ_buf *xmit = &port->state->xmit;
- if (uart_circ_empty(xmit) && !port->x_char)
+ if (uart_circ_empty(xmit) && !port->x_char) {
+ stm32_usart_rs485_rts_disable(port);
return;
-
- if (rs485conf->flags & SER_RS485_ENABLED) {
- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
- mctrl_gpio_set(stm32_port->gpios,
- stm32_port->port.mctrl | TIOCM_RTS);
- } else {
- mctrl_gpio_set(stm32_port->gpios,
- stm32_port->port.mctrl & ~TIOCM_RTS);
- }
}
+ stm32_usart_rs485_rts_enable(port);
+
stm32_usart_transmit_chars(port);
}
@@ -1037,13 +1088,22 @@ static void stm32_usart_set_termios(struct uart_port *port,
* CS8 or (CS7 + parity), 8 bits word aka [M1:M0] = 0b00
* M0 and M1 already cleared by cr1 initialization.
*/
- if (bits == 9)
+ if (bits == 9) {
cr1 |= USART_CR1_M0;
- else if ((bits == 7) && cfg->has_7bits_data)
+ } else if ((bits == 7) && cfg->has_7bits_data) {
cr1 |= USART_CR1_M1;
- else if (bits != 8)
+ } else if (bits != 8) {
dev_dbg(port->dev, "Unsupported data bits config: %u bits\n"
, bits);
+ cflag &= ~CSIZE;
+ cflag |= CS8;
+ termios->c_cflag = cflag;
+ bits = 8;
+ if (cflag & PARENB) {
+ bits++;
+ cr1 |= USART_CR1_M0;
+ }
+ }
if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch ||
(stm32_port->fifoen &&
@@ -1222,6 +1282,33 @@ static void stm32_usart_pm(struct uart_port *port, unsigned int state,
}
}
+#if defined(CONFIG_CONSOLE_POLL)
+
+ /* Callbacks for characters polling in debug context (i.e. KGDB). */
+static int stm32_usart_poll_init(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+
+ return clk_prepare_enable(stm32_port->clk);
+}
+
+static int stm32_usart_poll_get_char(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_RXNE))
+ return NO_POLL_CHAR;
+
+ return readl_relaxed(port->membase + ofs->rdr) & stm32_port->rdr_mask;
+}
+
+static void stm32_usart_poll_put_char(struct uart_port *port, unsigned char ch)
+{
+ stm32_usart_console_putchar(port, ch);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
static const struct uart_ops stm32_uart_ops = {
.tx_empty = stm32_usart_tx_empty,
.set_mctrl = stm32_usart_set_mctrl,
@@ -1243,6 +1330,11 @@ static const struct uart_ops stm32_uart_ops = {
.request_port = stm32_usart_request_port,
.config_port = stm32_usart_config_port,
.verify_port = stm32_usart_verify_port,
+#if defined(CONFIG_CONSOLE_POLL)
+ .poll_init = stm32_usart_poll_init,
+ .poll_get_char = stm32_usart_poll_get_char,
+ .poll_put_char = stm32_usart_poll_put_char,
+#endif /* CONFIG_CONSOLE_POLL */
};
/*
@@ -1640,18 +1732,24 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_SERIAL_STM32_CONSOLE
-static void stm32_usart_console_putchar(struct uart_port *port, unsigned char ch)
+static void __maybe_unused 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;
+ u32 isr;
+ int ret;
- while (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE))
- cpu_relax();
-
+ ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, isr,
+ (isr & USART_SR_TXE), 100,
+ STM32_USART_TIMEOUT_USEC);
+ if (ret != 0) {
+ dev_err(port->dev, "Error while sending data in UART TX : %d\n", ret);
+ return;
+ }
writel_relaxed(ch, port->membase + ofs->tdr);
}
+#ifdef CONFIG_SERIAL_STM32_CONSOLE
static void stm32_usart_console_write(struct console *co, const char *s,
unsigned int cnt)
{
@@ -1727,6 +1825,57 @@ static struct console stm32_console = {
#define STM32_SERIAL_CONSOLE NULL
#endif /* CONFIG_SERIAL_STM32_CONSOLE */
+#ifdef CONFIG_SERIAL_EARLYCON
+static void early_stm32_usart_console_putchar(struct uart_port *port, unsigned char ch)
+{
+ struct stm32_usart_info *info = port->private_data;
+
+ while (!(readl_relaxed(port->membase + info->ofs.isr) & USART_SR_TXE))
+ cpu_relax();
+
+ writel_relaxed(ch, port->membase + info->ofs.tdr);
+}
+
+static void early_stm32_serial_write(struct console *console, const char *s, unsigned int count)
+{
+ struct earlycon_device *device = console->data;
+ struct uart_port *port = &device->port;
+
+ uart_console_write(port, s, count, early_stm32_usart_console_putchar);
+}
+
+static int __init early_stm32_h7_serial_setup(struct earlycon_device *device, const char *options)
+{
+ if (!(device->port.membase || device->port.iobase))
+ return -ENODEV;
+ device->port.private_data = &stm32h7_info;
+ device->con->write = early_stm32_serial_write;
+ return 0;
+}
+
+static int __init early_stm32_f7_serial_setup(struct earlycon_device *device, const char *options)
+{
+ if (!(device->port.membase || device->port.iobase))
+ return -ENODEV;
+ device->port.private_data = &stm32f7_info;
+ device->con->write = early_stm32_serial_write;
+ return 0;
+}
+
+static int __init early_stm32_f4_serial_setup(struct earlycon_device *device, const char *options)
+{
+ if (!(device->port.membase || device->port.iobase))
+ return -ENODEV;
+ device->port.private_data = &stm32f4_info;
+ device->con->write = early_stm32_serial_write;
+ return 0;
+}
+
+OF_EARLYCON_DECLARE(stm32, "st,stm32h7-uart", early_stm32_h7_serial_setup);
+OF_EARLYCON_DECLARE(stm32, "st,stm32f7-uart", early_stm32_f7_serial_setup);
+OF_EARLYCON_DECLARE(stm32, "st,stm32-uart", early_stm32_f4_serial_setup);
+#endif /* CONFIG_SERIAL_EARLYCON */
+
static struct uart_driver stm32_usart_driver = {
.driver_name = DRIVER_NAME,
.dev_name = STM32_SERIAL_NAME,
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index feab952aec16..ee69c203b926 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -251,6 +251,8 @@ struct stm32_usart_info stm32h7_info = {
#define RX_BUF_P (RX_BUF_L / 2) /* dma rx buffer period */
#define TX_BUF_L RX_BUF_L /* dma tx buffer length */
+#define STM32_USART_TIMEOUT_USEC USEC_PER_SEC /* 1s timeout in µs */
+
struct stm32_port {
struct uart_port port;
struct clk *clk;
@@ -269,6 +271,7 @@ struct stm32_port {
bool hw_flow_control;
bool swap; /* swap RX & TX pins */
bool fifoen;
+ bool txdone;
int rxftcfg; /* RX FIFO threshold CFG */
int txftcfg; /* TX FIFO threshold CFG */
bool wakeup_src;
diff --git a/drivers/tty/serial/sunplus-uart.c b/drivers/tty/serial/sunplus-uart.c
index 9f15922e681b..60c73662f955 100644
--- a/drivers/tty/serial/sunplus-uart.c
+++ b/drivers/tty/serial/sunplus-uart.c
@@ -498,7 +498,7 @@ static const struct uart_ops sunplus_uart_ops = {
};
#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE
-struct sunplus_uart_port *sunplus_console_ports[SUP_UART_NR];
+static struct sunplus_uart_port *sunplus_console_ports[SUP_UART_NR];
static void sunplus_uart_console_putchar(struct uart_port *port,
unsigned char ch)
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index c31389114b86..fff50b5b82eb 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -798,10 +798,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
cval |= UART_LCR_PARITY;
if (!(cflag & PARODD))
cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
if (cflag & CMSPAR)
cval |= UART_LCR_SPAR;
-#endif
/*
* Work around a bug in the Oxford Semiconductor 952 rev B
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 007db67292a2..880e2afbb97b 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -321,7 +321,8 @@ static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
struct uartlite_data *pdata = port->private_data;
/* Set termios to what the hardware supports */
- termios->c_cflag &= ~(BRKINT | CSTOPB | PARENB | PARODD | CSIZE);
+ termios->c_iflag &= ~BRKINT;
+ termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE);
termios->c_cflag |= pdata->cflags & (PARENB | PARODD | CSIZE);
tty_termios_encode_baud_rate(termios, pdata->baud, pdata->baud);
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 250a1d888eeb..9e01fe6c0ab8 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -313,41 +313,27 @@ static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus)
static void cdns_uart_handle_tx(void *dev_id)
{
struct uart_port *port = (struct uart_port *)dev_id;
+ struct circ_buf *xmit = &port->state->xmit;
unsigned int numbytes;
- if (uart_circ_empty(&port->state->xmit)) {
+ if (uart_circ_empty(xmit)) {
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR);
- } else {
- numbytes = port->fifosize;
- while (numbytes && !uart_circ_empty(&port->state->xmit) &&
- !(readl(port->membase + CDNS_UART_SR) &
- CDNS_UART_SR_TXFULL)) {
- /*
- * Get the data from the UART circular buffer
- * and write it to the cdns_uart's TX_FIFO
- * register.
- */
- writel(
- port->state->xmit.buf[port->state->xmit.tail],
- port->membase + CDNS_UART_FIFO);
-
- port->icount.tx++;
-
- /*
- * Adjust the tail of the UART buffer and wrap
- * the buffer if it reaches limit.
- */
- port->state->xmit.tail =
- (port->state->xmit.tail + 1) &
- (UART_XMIT_SIZE - 1);
-
- numbytes--;
- }
+ return;
+ }
- if (uart_circ_chars_pending(
- &port->state->xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
+ numbytes = port->fifosize;
+ while (numbytes && !uart_circ_empty(xmit) &&
+ !(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) {
+
+ writel(xmit->buf[xmit->tail], port->membase + CDNS_UART_FIFO);
+
+ port->icount.tx++;
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ numbytes--;
}
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
}
/**
diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c
index 70969bf9d82c..5bc58591665a 100644
--- a/drivers/tty/serial/zs.c
+++ b/drivers/tty/serial/zs.c
@@ -981,7 +981,7 @@ static const char *zs_type(struct uart_port *uport)
static void zs_release_port(struct uart_port *uport)
{
iounmap(uport->membase);
- uport->membase = 0;
+ uport->membase = NULL;
release_mem_region(uport->mapbase, ZS_CHAN_IO_SIZE);
}
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index 25c558e65ece..9bc2a9265277 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -1746,6 +1746,8 @@ static int hdlcdev_init(struct slgt_info *info)
*/
static void hdlcdev_exit(struct slgt_info *info)
{
+ if (!info->netdev)
+ return;
unregister_hdlc_device(info->netdev);
free_netdev(info->netdev);
info->netdev = NULL;
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 2884cd638d64..18e623325887 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -232,8 +232,10 @@ static void showacpu(void *dummy)
unsigned long flags;
/* Idle CPUs have no interesting backtrace. */
- if (idle_cpu(smp_processor_id()))
+ if (idle_cpu(smp_processor_id())) {
+ pr_info("CPU%d: backtrace skipped as idling\n", smp_processor_id());
return;
+ }
raw_spin_lock_irqsave(&show_lock, flags);
pr_info("CPU%d:\n", smp_processor_id());
@@ -260,10 +262,13 @@ static void sysrq_handle_showallcpus(int key)
if (in_hardirq())
regs = get_irq_regs();
- if (regs) {
- pr_info("CPU%d:\n", smp_processor_id());
+
+ pr_info("CPU%d:\n", smp_processor_id());
+ if (regs)
show_regs(regs);
- }
+ else
+ show_stack(NULL, NULL, KERN_INFO);
+
schedule_work(&sysrq_showallcpus);
}
}
@@ -274,6 +279,8 @@ static const struct sysrq_key_op sysrq_showallcpus_op = {
.action_msg = "Show backtrace of all active CPUs",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
+#else
+#define sysrq_showallcpus_op (*(const struct sysrq_key_op *)NULL)
#endif
static void sysrq_handle_showregs(int key)
@@ -405,6 +412,7 @@ static const struct sysrq_key_op sysrq_moom_op = {
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
+#ifdef CONFIG_BLOCK
static void sysrq_handle_thaw(int key)
{
emergency_thaw_all();
@@ -415,6 +423,9 @@ static const struct sysrq_key_op sysrq_thaw_op = {
.action_msg = "Emergency Thaw of all frozen filesystems",
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
+#else
+#define sysrq_thaw_op (*(const struct sysrq_key_op *)NULL)
+#endif
static void sysrq_handle_kill(int key)
{
@@ -468,17 +479,9 @@ static const struct sysrq_key_op *sysrq_key_table[62] = {
NULL, /* g */
NULL, /* h - reserved for help */
&sysrq_kill_op, /* i */
-#ifdef CONFIG_BLOCK
&sysrq_thaw_op, /* j */
-#else
- NULL, /* j */
-#endif
&sysrq_SAK_op, /* k */
-#ifdef CONFIG_SMP
&sysrq_showallcpus_op, /* l */
-#else
- NULL, /* l */
-#endif
&sysrq_showmem_op, /* m */
&sysrq_unrt_op, /* n */
/* o: This will often be registered as 'Off' at init time */
diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c
index d903e111dbcb..3cd99ed7c710 100644
--- a/drivers/tty/tty_baudrate.c
+++ b/drivers/tty/tty_baudrate.c
@@ -61,11 +61,10 @@ speed_t tty_termios_baud_rate(struct ktermios *termios)
cbaud = termios->c_cflag & CBAUD;
-#ifdef BOTHER
/* Magic token for arbitrary speed via c_ispeed/c_ospeed */
if (cbaud == BOTHER)
return termios->c_ospeed;
-#endif
+
if (cbaud & CBAUDEX) {
cbaud &= ~CBAUDEX;
@@ -92,16 +91,15 @@ EXPORT_SYMBOL(tty_termios_baud_rate);
speed_t tty_termios_input_baud_rate(struct ktermios *termios)
{
-#ifdef IBSHIFT
unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
if (cbaud == B0)
return tty_termios_baud_rate(termios);
-#ifdef BOTHER
+
/* Magic token for arbitrary speed via c_ispeed*/
if (cbaud == BOTHER)
return termios->c_ispeed;
-#endif
+
if (cbaud & CBAUDEX) {
cbaud &= ~CBAUDEX;
@@ -111,9 +109,6 @@ speed_t tty_termios_input_baud_rate(struct ktermios *termios)
cbaud += 15;
}
return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
-#else /* IBSHIFT */
- return tty_termios_baud_rate(termios);
-#endif /* IBSHIFT */
}
EXPORT_SYMBOL(tty_termios_input_baud_rate);
@@ -153,11 +148,9 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
termios->c_ispeed = ibaud;
termios->c_ospeed = obaud;
-#ifdef IBSHIFT
if (((termios->c_cflag >> IBSHIFT) & CBAUD) != B0)
ibinput = 1; /* An input speed was specified */
-#endif
-#ifdef BOTHER
+
/* If the user asked for a precise weird speed give a precise weird
* answer. If they asked for a Bfoo speed they may have problems
* digesting non-exact replies so fuzz a bit.
@@ -170,11 +163,9 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
}
if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
iclose = 0;
-#endif
+
termios->c_cflag &= ~CBAUD;
-#ifdef IBSHIFT
termios->c_cflag &= ~(CBAUD << IBSHIFT);
-#endif
/*
* Our goal is to find a close match to the standard baud rate
@@ -194,22 +185,16 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
/* For the case input == output don't set IBAUD bits
* if the user didn't do so.
*/
- if (ofound == i && !ibinput)
+ if (ofound == i && !ibinput) {
ifound = i;
-#ifdef IBSHIFT
- else {
+ } else {
ifound = i;
termios->c_cflag |= (baud_bits[i] << IBSHIFT);
}
-#endif
}
} while (++i < n_baud_table);
- /*
- * If we found no match then use BOTHER if provided or warn
- * the user their platform maintainer needs to wake up if not.
- */
-#ifdef BOTHER
+ /* If we found no match then use BOTHER. */
if (ofound == -1)
termios->c_cflag |= BOTHER;
/* Set exact input bits only if the input and output differ or the
@@ -217,10 +202,6 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
*/
if (ifound == -1 && (ibaud != obaud || ibinput))
termios->c_cflag |= (BOTHER << IBSHIFT);
-#else
- if (ifound == -1 || ofound == -1)
- pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
-#endif
}
EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 63181925ec1a..adae687f654b 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -562,10 +562,8 @@ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
termios.c_cc[VKILL] = tmp.sg_kill;
set_sgflags(&termios, tmp.sg_flags);
/* Try and encode into Bfoo format */
-#ifdef BOTHER
tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
termios.c_ospeed);
-#endif
up_write(&tty->termios_rwsem);
tty_set_termios(tty, &termios);
return 0;
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 3aa7f0a3ad71..d26ecd15be60 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -8,14 +8,6 @@
*/
/*
- * CMSPAR, some architectures can't have space and mark parity.
- */
-
-#ifndef CMSPAR
-#define CMSPAR 0
-#endif
-
-/*
* Major and minor numbers.
*/
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index c0e4df87ff22..39eaa7b97c40 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -208,10 +208,9 @@ static void ark3116_set_termios(struct tty_struct *tty,
lcr |= UART_LCR_PARITY;
if (!(cflag & PARODD))
lcr |= UART_LCR_EPAR;
-#ifdef CMSPAR
if (cflag & CMSPAR)
lcr |= UART_LCR_SPAR;
-#endif
+
/* handshake control */
hcr = (cflag & CRTSCTS) ? 0x03 : 0x00;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 06aad0d727dd..332fb92ae575 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -30,10 +30,6 @@
#include <linux/usb/ezusb.h>
#include "whiteheat.h" /* WhiteHEAT specific commands */
-#ifndef CMSPAR
-#define CMSPAR 0
-#endif
-
/*
* Version Information
*/
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index d4828e69087a..cbd5070bc87f 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -232,6 +232,7 @@ struct uart_port {
int hw_stopped; /* sw-assisted CTS flow state */
unsigned int mctrl; /* current modem ctrl settings */
unsigned int timeout; /* character-based timeout */
+ unsigned int frame_time; /* frame timing in ns */
unsigned int type; /* port type */
const struct uart_ops *ops;
unsigned int custom_divisor;
diff --git a/include/linux/serial_s3c.h b/include/linux/serial_s3c.h
index f6c3323fc4c5..dec15f5b3dec 100644
--- a/include/linux/serial_s3c.h
+++ b/include/linux/serial_s3c.h
@@ -256,6 +256,9 @@
#define APPLE_S5L_UCON_DEFAULT (S3C2410_UCON_TXIRQMODE | \
S3C2410_UCON_RXIRQMODE | \
S3C2410_UCON_RXFIFO_TOI)
+#define APPLE_S5L_UCON_MASK (APPLE_S5L_UCON_RXTO_ENA_MSK | \
+ APPLE_S5L_UCON_RXTHRESH_ENA_MSK | \
+ APPLE_S5L_UCON_TXTHRESH_ENA_MSK)
#define APPLE_S5L_UTRSTAT_RXTHRESH (1<<4)
#define APPLE_S5L_UTRSTAT_TXTHRESH (1<<5)
diff --git a/include/uapi/asm-generic/termbits-common.h b/include/uapi/asm-generic/termbits-common.h
new file mode 100644
index 000000000000..4d084fe8def5
--- /dev/null
+++ b/include/uapi/asm-generic/termbits-common.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __ASM_GENERIC_TERMBITS_COMMON_H
+#define __ASM_GENERIC_TERMBITS_COMMON_H
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+
+/* c_iflag bits */
+#define IGNBRK 0x001 /* Ignore break condition */
+#define BRKINT 0x002 /* Signal interrupt on break */
+#define IGNPAR 0x004 /* Ignore characters with parity errors */
+#define PARMRK 0x008 /* Mark parity and framing errors */
+#define INPCK 0x010 /* Enable input parity check */
+#define ISTRIP 0x020 /* Strip 8th bit off characters */
+#define INLCR 0x040 /* Map NL to CR on input */
+#define IGNCR 0x080 /* Ignore CR */
+#define ICRNL 0x100 /* Map CR to NL on input */
+#define IXANY 0x800 /* Any character will restart after stop */
+
+/* c_oflag bits */
+#define OPOST 0x01 /* Perform output processing */
+#define OCRNL 0x08
+#define ONOCR 0x10
+#define ONLRET 0x20
+#define OFILL 0x40
+#define OFDEL 0x80
+
+/* c_cflag bit meaning */
+/* Common CBAUD rates */
+#define B0 0x00000000 /* hang up */
+#define B50 0x00000001
+#define B75 0x00000002
+#define B110 0x00000003
+#define B134 0x00000004
+#define B150 0x00000005
+#define B200 0x00000006
+#define B300 0x00000007
+#define B600 0x00000008
+#define B1200 0x00000009
+#define B1800 0x0000000a
+#define B2400 0x0000000b
+#define B4800 0x0000000c
+#define B9600 0x0000000d
+#define B19200 0x0000000e
+#define B38400 0x0000000f
+#define EXTA B19200
+#define EXTB B38400
+
+#define CMSPAR 0x40000000 /* mark or space (stick) parity */
+#define CRTSCTS 0x80000000 /* flow control */
+
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
+/* tcflow() ACTION argument and TCXONC use these */
+#define TCOOFF 0 /* Suspend output */
+#define TCOON 1 /* Restart suspended output */
+#define TCIOFF 2 /* Send a STOP character */
+#define TCION 3 /* Send a START character */
+
+/* tcflush() QUEUE_SELECTOR argument and TCFLSH use these */
+#define TCIFLUSH 0 /* Discard data received but not yet read */
+#define TCOFLUSH 1 /* Discard data written but not yet sent */
+#define TCIOFLUSH 2 /* Discard all pending data */
+
+#endif /* __ASM_GENERIC_TERMBITS_COMMON_H */
diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h
index 2fbaf9ae89dd..890ef29053e2 100644
--- a/include/uapi/asm-generic/termbits.h
+++ b/include/uapi/asm-generic/termbits.h
@@ -2,10 +2,8 @@
#ifndef __ASM_GENERIC_TERMBITS_H
#define __ASM_GENERIC_TERMBITS_H
-#include <linux/posix_types.h>
+#include <asm-generic/termbits-common.h>
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 19
@@ -41,156 +39,107 @@ struct ktermios {
};
/* 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
+#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
+#define IUCLC 0x0200
+#define IXON 0x0400
+#define IXOFF 0x1000
+#define IMAXBEL 0x2000
+#define IUTF8 0x4000
/* 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
+#define OLCUC 0x00002
+#define ONLCR 0x00004
+#define NLDLY 0x00100
+#define NL0 0x00000
+#define NL1 0x00100
+#define CRDLY 0x00600
+#define CR0 0x00000
+#define CR1 0x00200
+#define CR2 0x00400
+#define CR3 0x00600
+#define TABDLY 0x01800
+#define TAB0 0x00000
+#define TAB1 0x00800
+#define TAB2 0x01000
+#define TAB3 0x01800
+#define XTABS 0x01800
+#define BSDLY 0x02000
+#define BS0 0x00000
+#define BS1 0x02000
+#define VTDLY 0x04000
+#define VT0 0x00000
+#define VT1 0x04000
+#define FFDLY 0x08000
+#define FF0 0x00000
+#define FF1 0x08000
/* 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 */
+#define CBAUD 0x0000100f
+#define CSIZE 0x00000030
+#define CS5 0x00000000
+#define CS6 0x00000010
+#define CS7 0x00000020
+#define CS8 0x00000030
+#define CSTOPB 0x00000040
+#define CREAD 0x00000080
+#define PARENB 0x00000100
+#define PARODD 0x00000200
+#define HUPCL 0x00000400
+#define CLOCAL 0x00000800
+#define CBAUDEX 0x00001000
+#define BOTHER 0x00001000
+#define B57600 0x00001001
+#define B115200 0x00001002
+#define B230400 0x00001003
+#define B460800 0x00001004
+#define B500000 0x00001005
+#define B576000 0x00001006
+#define B921600 0x00001007
+#define B1000000 0x00001008
+#define B1152000 0x00001009
+#define B1500000 0x0000100a
+#define B2000000 0x0000100b
+#define B2500000 0x0000100c
+#define B3000000 0x0000100d
+#define B3500000 0x0000100e
+#define B4000000 0x0000100f
+#define CIBAUD 0x100f0000 /* input baud rate */
/* 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
+#define ISIG 0x00001
+#define ICANON 0x00002
+#define XCASE 0x00004
+#define ECHO 0x00008
+#define ECHOE 0x00010
+#define ECHOK 0x00020
+#define ECHONL 0x00040
+#define NOFLSH 0x00080
+#define TOSTOP 0x00100
+#define ECHOCTL 0x00200
+#define ECHOPRT 0x00400
+#define ECHOKE 0x00800
+#define FLUSHO 0x01000
+#define PENDIN 0x04000
+#define IEXTEN 0x08000
+#define EXTPROC 0x10000
/* tcsetattr uses these */
#define TCSANOW 0