Merge tag 'tty-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Mar 2024 19:44:10 +0000 (12:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Mar 2024 19:44:10 +0000 (12:44 -0700)
Pull tty / serial driver updates from Greg KH:
 "Here is the big set of TTY/Serial driver updates and cleanups for
  6.9-rc1. Included in here are:

   - more tty cleanups from Jiri

   - loads of 8250 driver cleanups from Andy

   - max310x driver updates

   - samsung serial driver updates

   - uart_prepare_sysrq_char() updates for many drivers

   - platform driver remove callback void cleanups

   - stm32 driver updates

   - other small tty/serial driver updates

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

* tag 'tty-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (199 commits)
  dt-bindings: serial: stm32: add power-domains property
  serial: 8250_dw: Replace ACPI device check by a quirk
  serial: Lock console when calling into driver before registration
  serial: 8250_uniphier: Switch to use uart_read_port_properties()
  serial: 8250_tegra: Switch to use uart_read_port_properties()
  serial: 8250_pxa: Switch to use uart_read_port_properties()
  serial: 8250_omap: Switch to use uart_read_port_properties()
  serial: 8250_of: Switch to use uart_read_port_properties()
  serial: 8250_lpc18xx: Switch to use uart_read_port_properties()
  serial: 8250_ingenic: Switch to use uart_read_port_properties()
  serial: 8250_dw: Switch to use uart_read_port_properties()
  serial: 8250_bcm7271: Switch to use uart_read_port_properties()
  serial: 8250_bcm2835aux: Switch to use uart_read_port_properties()
  serial: 8250_aspeed_vuart: Switch to use uart_read_port_properties()
  serial: port: Introduce a common helper to read properties
  serial: core: Add UPIO_UNKNOWN constant for unknown port type
  serial: core: Move struct uart_port::quirks closer to possible values
  serial: sh-sci: Call sci_serial_{in,out}() directly
  serial: core: only stop transmit when HW fifo is empty
  serial: pch: Use uart_prepare_sysrq_char().
  ...

122 files changed:
Documentation/devicetree/bindings/serial/cdns,uart.yaml
Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
Documentation/devicetree/bindings/serial/renesas,hscif.yaml
Documentation/devicetree/bindings/serial/samsung_uart.yaml
Documentation/devicetree/bindings/serial/serial.yaml
Documentation/devicetree/bindings/serial/st,asc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
Documentation/devicetree/bindings/serial/st-asc.txt [deleted file]
Documentation/devicetree/bindings/w1/w1-uart.yaml [new file with mode: 0644]
Documentation/driver-api/tty/console.rst [new file with mode: 0644]
Documentation/driver-api/tty/index.rst
Documentation/w1/masters/index.rst
Documentation/w1/masters/w1-uart.rst [new file with mode: 0644]
arch/m68k/amiga/config.c
arch/m68k/hp300/config.c
drivers/bluetooth/btmtkuart.c
drivers/bluetooth/btnxpuart.c
drivers/bluetooth/hci_serdev.c
drivers/gnss/serial.c
drivers/gnss/sirf.c
drivers/greybus/gb-beagleplay.c
drivers/iio/chemical/pms7003.c
drivers/iio/chemical/scd30_serial.c
drivers/iio/chemical/sps30_serial.c
drivers/iio/imu/bno055/bno055_ser_core.c
drivers/input/keyboard/amikbd.c
drivers/mfd/rave-sp.c
drivers/net/ethernet/qualcomm/qca_uart.c
drivers/nfc/pn533/uart.c
drivers/nfc/s3fwrn5/uart.c
drivers/platform/chrome/cros_ec_uart.c
drivers/platform/surface/aggregator/core.c
drivers/tty/Kconfig
drivers/tty/amiserial.c
drivers/tty/goldfish.c
drivers/tty/hvc/hvc_iucv.c
drivers/tty/serdev/core.c
drivers/tty/serdev/serdev-ttyport.c
drivers/tty/serial/8250/8250_aspeed_vuart.c
drivers/tty/serial/8250/8250_bcm2835aux.c
drivers/tty/serial/8250/8250_bcm7271.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_exar.c
drivers/tty/serial/8250/8250_ingenic.c
drivers/tty/serial/8250/8250_lpc18xx.c
drivers/tty/serial/8250/8250_of.c
drivers/tty/serial/8250/8250_omap.c
drivers/tty/serial/8250/8250_pci1xxxx.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/8250/8250_pxa.c
drivers/tty/serial/8250/8250_tegra.c
drivers/tty/serial/8250/8250_uniphier.c
drivers/tty/serial/8250/Kconfig
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/ar933x_uart.c
drivers/tty/serial/bcm63xx_uart.c
drivers/tty/serial/fsl_linflexuart.c
drivers/tty/serial/jsm/jsm_cls.c
drivers/tty/serial/lpc32xx_hs.c
drivers/tty/serial/max310x.c
drivers/tty/serial/mcf.c
drivers/tty/serial/meson_uart.c
drivers/tty/serial/msm_serial.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/owl-uart.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/pmac_zilog.c
drivers/tty/serial/pxa.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/rda-uart.c
drivers/tty/serial/samsung_tty.c
drivers/tty/serial/serial_base_bus.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/serial_port.c
drivers/tty/serial/serial_txx9.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sifive.c
drivers/tty/serial/st-asc.c
drivers/tty/serial/stm32-usart.c
drivers/tty/serial/stm32-usart.h
drivers/tty/serial/sunplus-uart.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/tty_buffer.c
drivers/tty/vt/Makefile
drivers/tty/vt/selection.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
drivers/video/console/dummycon.c
drivers/video/console/mdacon.c
drivers/video/console/newport_con.c
drivers/video/console/sticon.c
drivers/video/console/vgacon.c
drivers/video/fbdev/core/bitblit.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbcon.h
drivers/video/fbdev/core/fbcon_ccw.c
drivers/video/fbdev/core/fbcon_cw.c
drivers/video/fbdev/core/fbcon_ud.c
drivers/video/fbdev/core/tileblit.c
drivers/video/fbdev/tgafb.c
drivers/w1/masters/Kconfig
drivers/w1/masters/Makefile
drivers/w1/masters/mxc_w1.c
drivers/w1/masters/omap_hdq.c
drivers/w1/masters/sgi_w1.c
drivers/w1/masters/w1-gpio.c
drivers/w1/masters/w1-uart.c [new file with mode: 0644]
drivers/w1/w1.c
include/linux/console.h
include/linux/console_struct.h
include/linux/selection.h
include/linux/serdev.h
include/linux/serial_8250.h
include/linux/serial_core.h
include/linux/soc/qcom/geni-se.h
include/linux/tty.h
include/linux/vt_kern.h
include/uapi/linux/fb.h
include/uapi/linux/vesa.h [new file with mode: 0644]
kernel/printk/printk.c
lib/Kconfig.kgdb
sound/drivers/serial-generic.c

index e35ad1109efc8b7b13211e5795c5668111e3f5c1..2129247d7c816d5b33e600af41b633aef7efa295 100644 (file)
@@ -55,6 +55,7 @@ required:
 
 allOf:
   - $ref: serial.yaml#
+  - $ref: rs485.yaml#
   - if:
       properties:
         compatible:
index 3a5b59f5d3e35de921e9a0907700e8b4db063850..3f9ace89dee902011d593c19a6d6f46424b1c832 100644 (file)
@@ -30,6 +30,7 @@ properties:
       - items:
           - enum:
               - fsl,imx93-lpuart
+              - fsl,imx95-lpuart
           - const: fsl,imx8ulp-lpuart
           - const: fsl,imx7ulp-lpuart
       - items:
index 2046e2dc0a3d190e932ee052411ec5e04bb66ab6..9480ed30915c9c4ec1ecb3445d013ed5dcef6098 100644 (file)
@@ -59,6 +59,7 @@ properties:
               - renesas,hscif-r8a779a0     # R-Car V3U
               - renesas,hscif-r8a779f0     # R-Car S4-8
               - renesas,hscif-r8a779g0     # R-Car V4H
+              - renesas,hscif-r8a779h0     # R-Car V4M
           - const: renesas,rcar-gen4-hscif # R-Car Gen4
           - const: renesas,hscif           # generic HSCIF compatible UART
 
index 133259ed3a34c577ee86e58f36bdf2a4937afcf4..0f0131026911cd0e07071cf38f0e9b41de9a7237 100644 (file)
@@ -143,6 +143,8 @@ allOf:
     then:
       required:
         - samsung,uart-fifosize
+      properties:
+        reg-io-width: false
 
 unevaluatedProperties: false
 
index 65804ca274ae75e2bfdbbc80a030335c99fd821d..ffc9198ae21469de249c87da75e27521bc2a419f 100644 (file)
@@ -88,7 +88,7 @@ properties:
       TX FIFO threshold configuration (in bytes).
 
 patternProperties:
-  "^(bluetooth|bluetooth-gnss|gnss|gps|mcu)$":
+  "^(bluetooth|bluetooth-gnss|gnss|gps|mcu|onewire)$":
     if:
       type: object
     then:
diff --git a/Documentation/devicetree/bindings/serial/st,asc.yaml b/Documentation/devicetree/bindings/serial/st,asc.yaml
new file mode 100644 (file)
index 0000000..f208338
--- /dev/null
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/st,asc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics STi SoCs Serial Port
+
+maintainers:
+  - Patrice Chotard <patrice.chotard@foss.st.com>
+
+allOf:
+  - $ref: serial.yaml#
+
+properties:
+  compatible:
+    const: st,asc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  st,hw-flow-ctrl:
+    description: When set, enable hardware flow control.
+    type: boolean
+
+  st,force-m1:
+    description: When set, force asc to be in Mode-1. This is recommended for
+      high bit rates above 19.2K.
+    type: boolean
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/stih407-clks.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    serial@9830000 {
+        compatible = "st,asc";
+        reg = <0x9830000 0x2c>;
+        interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+    };
+...
index 1df8ffe95fc615b058e43300876c6e357990d77f..62f97da1b2fd7c944442c17127897d154d6c4acb 100644 (file)
@@ -58,6 +58,9 @@ properties:
 
   wakeup-source: true
 
+  power-domains:
+    maxItems: 1
+
   rx-threshold:
     description:
       If value is set to 1, RX FIFO threshold is disabled.
diff --git a/Documentation/devicetree/bindings/serial/st-asc.txt b/Documentation/devicetree/bindings/serial/st-asc.txt
deleted file mode 100644 (file)
index a1b9b6f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-*st-asc(Serial Port)
-
-Required properties:
-- compatible : Should be "st,asc".
-- reg, reg-names, interrupts, interrupt-names  : Standard way to define device
-                       resources with names. look in
-                       Documentation/devicetree/bindings/resource-names.txt
-
-Optional properties:
-- st,hw-flow-ctrl      bool flag to enable hardware flow control.
-- st,force-m1          bool flat to force asc to be in Mode-1 recommended
-                       for high bit rates (above 19.2K)
-Example:
-serial@fe440000{
-    compatible    = "st,asc";
-    reg         = <0xfe440000 0x2c>;
-    interrupts     =  <0 209 0>;
-};
diff --git a/Documentation/devicetree/bindings/w1/w1-uart.yaml b/Documentation/devicetree/bindings/w1/w1-uart.yaml
new file mode 100644 (file)
index 0000000..bd7c62d
--- /dev/null
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/w1/w1-uart.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: UART 1-Wire Bus
+
+maintainers:
+  - Christoph Winklhofer <cj.winklhofer@gmail.com>
+
+description: |
+  UART 1-wire bus. Utilizes the UART interface via the Serial Device Bus
+  to create the 1-Wire timing patterns.
+
+  The UART peripheral must support full-duplex and operate in open-drain
+  mode. The timing patterns are generated by a specific combination of
+  baud-rate and transmitted byte, which corresponds to a 1-Wire read bit,
+  write bit or reset pulse.
+
+  The default baud-rate for reset and presence detection is 9600 and for
+  a 1-Wire read or write operation 115200. In case the actual baud-rate
+  is different from the requested one, the transmitted byte is adapted
+  to generate the 1-Wire timing patterns.
+
+  https://www.analog.com/en/technical-articles/using-a-uart-to-implement-a-1wire-bus-master.html
+
+properties:
+  compatible:
+    const: w1-uart
+
+  reset-bps:
+    default: 9600
+    description:
+      The baud rate for the 1-Wire reset and presence detect.
+
+  write-0-bps:
+    default: 115200
+    description:
+      The baud rate for the 1-Wire write-0 cycle.
+
+  write-1-bps:
+    default: 115200
+    description:
+      The baud rate for the 1-Wire write-1 and read cycle.
+
+required:
+  - compatible
+
+additionalProperties:
+  type: object
+
+examples:
+  - |
+    serial {
+        onewire {
+            compatible = "w1-uart";
+        };
+    };
diff --git a/Documentation/driver-api/tty/console.rst b/Documentation/driver-api/tty/console.rst
new file mode 100644 (file)
index 0000000..4348e36
--- /dev/null
@@ -0,0 +1,45 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======
+Console
+=======
+
+.. contents:: :local:
+
+Struct Console
+==============
+
+.. kernel-doc:: include/linux/console.h
+   :identifiers: console cons_flags
+
+Internals
+---------
+
+.. kernel-doc:: include/linux/console.h
+   :identifiers: nbcon_state nbcon_prio nbcon_context nbcon_write_context
+
+Struct Consw
+============
+
+.. kernel-doc:: include/linux/console.h
+   :identifiers: consw
+
+Console functions
+=================
+
+.. kernel-doc:: include/linux/console.h
+   :identifiers: console_srcu_read_flags console_srcu_write_flags
+        console_is_registered for_each_console_srcu for_each_console
+
+.. kernel-doc:: drivers/tty/vt/selection.c
+   :export:
+.. kernel-doc:: drivers/tty/vt/vt.c
+   :export:
+
+Internals
+---------
+
+.. kernel-doc:: drivers/tty/vt/selection.c
+   :internal:
+.. kernel-doc:: drivers/tty/vt/vt.c
+   :internal:
index b490da11f257fce6c5469c781bd4fb1556153f67..c1ffe3d1ec46999d8767b66df5b274c075315580 100644 (file)
@@ -38,6 +38,7 @@ In-detail description of the named TTY structures is in separate documents:
    tty_buffer
    tty_ioctl
    tty_internals
+   console
 
 Writing TTY Driver
 ==================
index 4442a98850adf3b8297058fde80dc65ff98a7600..cc40189909fd17098d2a3763a0e1d401de92b889 100644 (file)
@@ -12,3 +12,4 @@
    mxc-w1
    omap-hdq
    w1-gpio
+   w1-uart
diff --git a/Documentation/w1/masters/w1-uart.rst b/Documentation/w1/masters/w1-uart.rst
new file mode 100644 (file)
index 0000000..8d0f122
--- /dev/null
@@ -0,0 +1,54 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+=====================
+Kernel driver w1-uart
+=====================
+
+Author: Christoph Winklhofer <cj.winklhofer@gmail.com>
+
+
+Description
+-----------
+
+UART 1-Wire bus driver. The driver utilizes the UART interface via the
+Serial Device Bus to create the 1-Wire timing patterns as described in
+the document `"Using a UART to Implement a 1-Wire Bus Master"`_.
+
+.. _"Using a UART to Implement a 1-Wire Bus Master": https://www.analog.com/en/technical-articles/using-a-uart-to-implement-a-1wire-bus-master.html
+
+In short, the UART peripheral must support full-duplex and operate in
+open-drain mode. The timing patterns are generated by a specific
+combination of baud-rate and transmitted byte, which corresponds to a
+1-Wire read bit, write bit or reset pulse.
+
+For instance the timing pattern for a 1-Wire reset and presence detect uses
+the baud-rate 9600, i.e. 104.2 us per bit. The transmitted byte 0xf0 over
+UART (least significant bit first, start-bit low) sets the reset low time
+for 1-Wire to 521 us. A present 1-Wire device changes the received byte by
+pulling the line low, which is used by the driver to evaluate the result of
+the 1-Wire operation.
+
+Similar for a 1-Wire read bit or write bit, which uses the baud-rate
+115200, i.e. 8.7 us per bit. The transmitted byte 0x80 is used for a
+Write-0 operation (low time 69.6us) and the byte 0xff for Read-0, Read-1
+and Write-1 (low time 8.7us).
+
+The default baud-rate for reset and presence detection is 9600 and for
+a 1-Wire read or write operation 115200. In case the actual baud-rate
+is different from the requested one, the transmitted byte is adapted
+to generate the 1-Wire timing patterns.
+
+
+Usage
+-----
+
+Specify the UART 1-wire bus in the device tree by adding the single child
+onewire to the serial node (e.g. uart0). For example:
+::
+
+  @uart0 {
+    ...
+    onewire {
+      compatible = "w1-uart";
+    };
+  };
index 7791673e547bf7955baf5a2f91f2754852d66810..99718f3dc686717c9e4756e3dce0cdf6793b8144 100644 (file)
@@ -846,6 +846,6 @@ static void amiga_get_hardware_list(struct seq_file *m)
  * The Amiga keyboard driver needs key_maps, but we cannot export it in
  * drivers/char/defkeymap.c, as it is autogenerated
  */
-#ifdef CONFIG_HW_CONSOLE
+#ifdef CONFIG_VT
 EXPORT_SYMBOL_GPL(key_maps);
 #endif
index e4bd6913f50e9ef3d392d789fbbdce06202f0954..1a27398523517a6592654e806f46f4829ac722c2 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/serial_8250.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/console.h>
@@ -67,9 +68,6 @@ static char *hp300_models[] __initdata = {
 static char hp300_model_name[13] = "HP9000/";
 
 extern void hp300_reset(void);
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-extern int hp300_setup_serial_console(void) __init;
-#endif
 
 int __init hp300_parse_bootinfo(const struct bi_record *record)
 {
@@ -263,7 +261,5 @@ void __init config_hp300(void)
        } else {
                panic("Unknown HP9000 Model");
        }
-#ifdef CONFIG_SERIAL_8250_CONSOLE
        hp300_setup_serial_console();
-#endif
 }
index 3c84fcbda01aa3791aac96c97a6fba9ea6d211ce..e6bc4a73c9fc33ee7645ad903b991e4bf05e686c 100644 (file)
@@ -383,8 +383,8 @@ static void btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count)
        }
 }
 
-static ssize_t btmtkuart_receive_buf(struct serdev_device *serdev,
-                                    const u8 *data, size_t count)
+static size_t btmtkuart_receive_buf(struct serdev_device *serdev,
+                                   const u8 *data, size_t count)
 {
        struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
 
index 0b93c2ff29e49a10b6fbac2336388bc4ceea1214..9d0c7e278114b229f7cc2155e7cc57a2cbfa9c54 100644 (file)
@@ -1285,8 +1285,8 @@ static const struct h4_recv_pkt nxp_recv_pkts[] = {
        { NXP_RECV_FW_REQ_V3,   .recv = nxp_recv_fw_req_v3 },
 };
 
-static ssize_t btnxpuart_receive_buf(struct serdev_device *serdev,
-                                    const u8 *data, size_t count)
+static size_t btnxpuart_receive_buf(struct serdev_device *serdev,
+                                   const u8 *data, size_t count)
 {
        struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
 
index 214fff876eae50e8ef88b7a4df44a3c76fdff240..85c0d9b68f5f76f5274f2ba049c9eaa949274381 100644 (file)
@@ -271,8 +271,8 @@ static void hci_uart_write_wakeup(struct serdev_device *serdev)
  *
  * Return: number of processed bytes
  */
-static ssize_t hci_uart_receive_buf(struct serdev_device *serdev,
-                                   const u8 *data, size_t count)
+static size_t hci_uart_receive_buf(struct serdev_device *serdev,
+                                  const u8 *data, size_t count)
 {
        struct hci_uart *hu = serdev_device_get_drvdata(serdev);
 
index baa956494e79f0aa3651d5c0ab2e550f2337aff3..0e43bf6294f878aa83ab64d8c0b6b4ce3d09b93b 100644 (file)
@@ -80,7 +80,7 @@ static const struct gnss_operations gnss_serial_gnss_ops = {
        .write_raw      = gnss_serial_write_raw,
 };
 
-static ssize_t gnss_serial_receive_buf(struct serdev_device *serdev,
+static size_t gnss_serial_receive_buf(struct serdev_device *serdev,
                                       const u8 *buf, size_t count)
 {
        struct gnss_serial *gserial = serdev_device_get_drvdata(serdev);
index 6801a8fb20401a484aba805be4fe1c0f0ca8e940..79375d14bbb6732e3676c4e8dc8e20c41bbf2c15 100644 (file)
@@ -160,7 +160,7 @@ static const struct gnss_operations sirf_gnss_ops = {
        .write_raw      = sirf_write_raw,
 };
 
-static ssize_t sirf_receive_buf(struct serdev_device *serdev,
+static size_t sirf_receive_buf(struct serdev_device *serdev,
                                const u8 *buf, size_t count)
 {
        struct sirf_data *data = serdev_device_get_drvdata(serdev);
index c3e90025064bdec9ac5cf7de150d708fbecae03a..33f8fad70260a45c6d0042871c9b4e3dff293bb5 100644 (file)
@@ -271,7 +271,7 @@ static void hdlc_rx_frame(struct gb_beagleplay *bg)
        }
 }
 
-static ssize_t hdlc_rx(struct gb_beagleplay *bg, const u8 *data, size_t count)
+static size_t hdlc_rx(struct gb_beagleplay *bg, const u8 *data, size_t count)
 {
        size_t i;
        u8 c;
@@ -331,8 +331,8 @@ static void hdlc_deinit(struct gb_beagleplay *bg)
        flush_work(&bg->tx_work);
 }
 
-static ssize_t gb_tty_receive(struct serdev_device *sd, const u8 *data,
-                             size_t count)
+static size_t gb_tty_receive(struct serdev_device *sd, const u8 *data,
+                            size_t count)
 {
        struct gb_beagleplay *bg = serdev_device_get_drvdata(sd);
 
index b5cf15a515d251a3cb4d862cf7a11ba82596baa8..43025866d5b791c1418898272d2cb2fa53bd125a 100644 (file)
@@ -211,8 +211,8 @@ static bool pms7003_frame_is_okay(struct pms7003_frame *frame)
        return checksum == pms7003_calc_checksum(frame);
 }
 
-static ssize_t pms7003_receive_buf(struct serdev_device *serdev, const u8 *buf,
-                                  size_t size)
+static size_t pms7003_receive_buf(struct serdev_device *serdev, const u8 *buf,
+                                 size_t size)
 {
        struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev);
        struct pms7003_state *state = iio_priv(indio_dev);
index a47654591e555fcf107e5c23180438b99921a15d..2adb76dbb0209edc24c5f20c3c2c01bf609afe41 100644 (file)
@@ -174,8 +174,8 @@ static int scd30_serdev_command(struct scd30_state *state, enum scd30_cmd cmd, u
        return 0;
 }
 
-static ssize_t scd30_serdev_receive_buf(struct serdev_device *serdev,
-                                       const u8 *buf, size_t size)
+static size_t scd30_serdev_receive_buf(struct serdev_device *serdev,
+                                      const u8 *buf, size_t size)
 {
        struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev);
        struct scd30_serdev_priv *priv;
index 3afa89f8acc329c73cf39f22cec98251a32d6120..a6dfbe28c914c7f6e8a3adacf14019447272e21e 100644 (file)
@@ -210,8 +210,8 @@ static int sps30_serial_command(struct sps30_state *state, unsigned char cmd,
        return rsp_size;
 }
 
-static ssize_t sps30_serial_receive_buf(struct serdev_device *serdev,
-                                       const u8 *buf, size_t size)
+static size_t sps30_serial_receive_buf(struct serdev_device *serdev,
+                                      const u8 *buf, size_t size)
 {
        struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev);
        struct sps30_serial_priv *priv;
index 5677bdf4f846ebd0405fbba43d1b9ad108033a3a..694ff14a3aa2795bdfbd8b42420d0f29dc6c4e40 100644 (file)
@@ -378,8 +378,8 @@ static void bno055_ser_handle_rx(struct bno055_ser_priv *priv, int status)
  * Also, we assume to RX one pkt per time (i.e. the HW doesn't send anything
  * unless we require to AND we don't queue more than one request per time).
  */
-static ssize_t bno055_ser_receive_buf(struct serdev_device *serdev,
-                                     const u8 *buf, size_t size)
+static size_t bno055_ser_receive_buf(struct serdev_device *serdev,
+                                    const u8 *buf, size_t size)
 {
        int status;
        struct bno055_ser_priv *priv = serdev_device_get_drvdata(serdev);
index e305c44cd0aa9045f4c62f2d3a42db05552ef224..ecfae0b0b6aa2457ae65b55dd40ef4372a6c73bb 100644 (file)
@@ -26,7 +26,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Amiga keyboard driver");
 MODULE_LICENSE("GPL");
 
-#ifdef CONFIG_HW_CONSOLE
+#ifdef CONFIG_VT
 static unsigned char amikbd_keycode[0x78] __initdata = {
        [0]      = KEY_GRAVE,
        [1]      = KEY_1,
@@ -148,9 +148,9 @@ static void __init amikbd_init_console_keymaps(void)
                memcpy(key_maps[i], temp_map, sizeof(temp_map));
        }
 }
-#else /* !CONFIG_HW_CONSOLE */
+#else /* !CONFIG_VT */
 static inline void amikbd_init_console_keymaps(void) {}
-#endif /* !CONFIG_HW_CONSOLE */
+#endif /* !CONFIG_VT */
 
 static const char *amikbd_messages[8] = {
        [0] = KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n",
index ea5fbcbbe4a56f8a7ba9dd3e57a87c54b97db56d..ef326d6d566e691603cd20604b863c6de091a246 100644 (file)
@@ -471,8 +471,8 @@ static void rave_sp_receive_frame(struct rave_sp *sp,
                rave_sp_receive_reply(sp, data, length);
 }
 
-static ssize_t rave_sp_receive_buf(struct serdev_device *serdev,
-                                  const u8 *buf, size_t size)
+static size_t rave_sp_receive_buf(struct serdev_device *serdev,
+                                 const u8 *buf, size_t size)
 {
        struct device *dev = &serdev->dev;
        struct rave_sp *sp = dev_get_drvdata(dev);
index 321fd8d00730410bc53c9c2e8d8f1fec30947dab..37efb1ea9fcd9ca91067b98b2e2310e9d8881545 100644 (file)
@@ -45,7 +45,7 @@ struct qcauart {
        unsigned char *tx_buffer;
 };
 
-static ssize_t
+static size_t
 qca_tty_receive(struct serdev_device *serdev, const u8 *data, size_t count)
 {
        struct qcauart *qca = serdev_device_get_drvdata(serdev);
index 2eb5978bd79e1b5114bb34bab409fbeaae00faf8..cfbbe0713317f8e5ca9b3a4942373376febfa248 100644 (file)
@@ -203,8 +203,8 @@ static int pn532_uart_rx_is_frame(struct sk_buff *skb)
        return 0;
 }
 
-static ssize_t pn532_receive_buf(struct serdev_device *serdev,
-                                const u8 *data, size_t count)
+static size_t pn532_receive_buf(struct serdev_device *serdev,
+                               const u8 *data, size_t count)
 {
        struct pn532_uart_phy *dev = serdev_device_get_drvdata(serdev);
        size_t i;
index 456d3947116c1c4029fa2477bdf1c12f508927aa..9c09c10c2a4640e626c4f62fc8800c9d2ccc1e5c 100644 (file)
@@ -51,8 +51,8 @@ static const struct s3fwrn5_phy_ops uart_phy_ops = {
        .write = s3fwrn82_uart_write,
 };
 
-static ssize_t s3fwrn82_uart_read(struct serdev_device *serdev,
-                                 const u8 *data, size_t count)
+static size_t s3fwrn82_uart_read(struct serdev_device *serdev,
+                                const u8 *data, size_t count)
 {
        struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
        size_t i;
index 68d80559fddc25b076648aa6c69f99951c15f262..8ea867c2a01a371a64e1eb10327931861d306dc8 100644 (file)
@@ -81,8 +81,8 @@ struct cros_ec_uart {
        struct response_info response;
 };
 
-static ssize_t cros_ec_uart_rx_bytes(struct serdev_device *serdev,
-                                    const u8 *data, size_t count)
+static size_t cros_ec_uart_rx_bytes(struct serdev_device *serdev,
+                                   const u8 *data, size_t count)
 {
        struct ec_host_response *host_response;
        struct cros_ec_device *ec_dev = serdev_device_get_drvdata(serdev);
index 9591a28bc38a9f40da8f9c53fb49c11a6396a968..ba550eaa06fcf594e2b6d3c0d8128b38813daf25 100644 (file)
@@ -227,8 +227,8 @@ EXPORT_SYMBOL_GPL(ssam_client_bind);
 
 /* -- Glue layer (serdev_device -> ssam_controller). ------------------------ */
 
-static ssize_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf,
-                               size_t n)
+static size_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf,
+                              size_t n)
 {
        struct ssam_controller *ctrl;
        int ret;
index 5646dc6242cd9a3771f09258a95ada92329d5897..a45d423ad10f02c3a818021bbb18655a8b690500 100644 (file)
@@ -75,14 +75,9 @@ config VT_CONSOLE_SLEEP
        def_bool y
        depends on VT_CONSOLE && PM_SLEEP
 
-config HW_CONSOLE
-       bool
-       depends on VT
-       default y
-
 config VT_HW_CONSOLE_BINDING
        bool "Support for binding and unbinding console drivers"
-       depends on HW_CONSOLE
+       depends on VT
        help
          The virtual terminal is the device that interacts with the physical
          terminal through console drivers. On these systems, at least one
index 7716ce0d35bc219608bd67b762aac0d4544bd9b9..e27360652d9b6b6e09976b5fda3ff495ed3f9838 100644 (file)
@@ -1566,7 +1566,7 @@ fail_tty_driver_kref_put:
        return error;
 }
 
-static int __exit amiga_serial_remove(struct platform_device *pdev)
+static void __exit amiga_serial_remove(struct platform_device *pdev)
 {
        struct serial_state *state = platform_get_drvdata(pdev);
 
@@ -1576,12 +1576,10 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
 
        free_irq(IRQ_AMIGA_TBE, state);
        free_irq(IRQ_AMIGA_RBF, state);
-
-       return 0;
 }
 
 static struct platform_driver amiga_serial_driver = {
-       .remove = __exit_p(amiga_serial_remove),
+       .remove_new = __exit_p(amiga_serial_remove),
        .driver   = {
                .name   = "amiga-serial",
        },
index d27979eabfdfbee1397140db3e30f0ee8ab7467c..34421ec06a69e217eab4d0013aa641a0d7b1845d 100644 (file)
@@ -408,7 +408,7 @@ err_unmap:
        return ret;
 }
 
-static int goldfish_tty_remove(struct platform_device *pdev)
+static void goldfish_tty_remove(struct platform_device *pdev)
 {
        struct goldfish_tty *qtty = platform_get_drvdata(pdev);
 
@@ -424,7 +424,6 @@ static int goldfish_tty_remove(struct platform_device *pdev)
        if (goldfish_tty_current_line_count == 0)
                goldfish_tty_delete_driver();
        mutex_unlock(&goldfish_tty_lock);
-       return 0;
 }
 
 #ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE
@@ -462,7 +461,7 @@ MODULE_DEVICE_TABLE(of, goldfish_tty_of_match);
 
 static struct platform_driver goldfish_tty_platform_driver = {
        .probe = goldfish_tty_probe,
-       .remove = goldfish_tty_remove,
+       .remove_new = goldfish_tty_remove,
        .driver = {
                .name = "goldfish_tty",
                .of_match_table = goldfish_tty_of_match,
index fdecc0d63731aa268a08ef00bd12cded3b918eca..b1149bc62ca1f35b37d3cd00126c0e81e847b716 100644 (file)
@@ -1035,6 +1035,10 @@ static const struct attribute_group *hvc_iucv_dev_attr_groups[] = {
        NULL,
 };
 
+static void hvc_iucv_free(struct device *data)
+{
+       kfree(data);
+}
 
 /**
  * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
@@ -1097,7 +1101,7 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console)
        priv->dev->bus = &iucv_bus;
        priv->dev->parent = iucv_root;
        priv->dev->groups = hvc_iucv_dev_attr_groups;
-       priv->dev->release = (void (*)(struct device *)) kfree;
+       priv->dev->release = hvc_iucv_free;
        rc = device_register(priv->dev);
        if (rc) {
                put_device(priv->dev);
index 822a5cd05566647d2bea82e2e978d05d214f79b4..613cb356b918d71562e5d48d237d0f64137b7afb 100644 (file)
@@ -431,7 +431,7 @@ static void serdev_drv_remove(struct device *dev)
        dev_pm_domain_detach(dev, true);
 }
 
-static struct bus_type serdev_bus_type = {
+static const struct bus_type serdev_bus_type = {
        .name           = "serial",
        .match          = serdev_device_match,
        .probe          = serdev_drv_probe,
index e94e090cf0a1a5aa31575b21de671c1fe8fb71f5..3d7ae7fa50186bc01481a9e9685aea41b10b6f2b 100644 (file)
@@ -27,19 +27,17 @@ static size_t ttyport_receive_buf(struct tty_port *port, const u8 *cp,
 {
        struct serdev_controller *ctrl = port->client_data;
        struct serport *serport = serdev_controller_get_drvdata(ctrl);
-       int ret;
+       size_t ret;
 
        if (!test_bit(SERPORT_ACTIVE, &serport->flags))
                return 0;
 
        ret = serdev_controller_receive_buf(ctrl, cp, count);
 
-       dev_WARN_ONCE(&ctrl->dev, ret < 0 || ret > count,
-                               "receive_buf returns %d (count = %zu)\n",
+       dev_WARN_ONCE(&ctrl->dev, ret > count,
+                               "receive_buf returns %zu (count = %zu)\n",
                                ret, count);
-       if (ret < 0)
-               return 0;
-       else if (ret > count)
+       if (ret > count)
                return count;
 
        return ret;
index 8c2aaf7af7b75c23587f847f8bc9be9330ddadc2..53d8eee9b1c81054b4e813df6c84797fc5ef5636 100644 (file)
@@ -419,8 +419,8 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
        struct aspeed_vuart *vuart;
        struct device_node *np;
        struct resource *res;
-       u32 clk, prop, sirq[2];
        int rc, sirq_polarity;
+       u32 prop, sirq[2];
        struct clk *vclk;
 
        np = pdev->dev.of_node;
@@ -447,53 +447,35 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
        port.port.status = UPSTAT_SYNC_FIFO;
        port.port.dev = &pdev->dev;
        port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
+       port.port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE |
+                         UPF_NO_THRE_TEST;
        port.bugs |= UART_BUG_TXRACE;
 
        rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
        if (rc < 0)
                return rc;
 
-       if (of_property_read_u32(np, "clock-frequency", &clk)) {
+       rc = uart_read_port_properties(&port.port);
+       if (rc)
+               goto err_sysfs_remove;
+
+       /* Get clk rate through clk driver if present */
+       if (!port.port.uartclk) {
                vclk = devm_clk_get_enabled(dev, NULL);
                if (IS_ERR(vclk)) {
                        rc = dev_err_probe(dev, PTR_ERR(vclk), "clk or clock-frequency not defined\n");
                        goto err_sysfs_remove;
                }
 
-               clk = clk_get_rate(vclk);
+               port.port.uartclk = clk_get_rate(vclk);
        }
 
        /* If current-speed was set, then try not to change it. */
        if (of_property_read_u32(np, "current-speed", &prop) == 0)
-               port.port.custom_divisor = clk / (16 * prop);
-
-       /* Check for shifted address mapping */
-       if (of_property_read_u32(np, "reg-offset", &prop) == 0)
-               port.port.mapbase += prop;
-
-       /* Check for registers offset within the devices address range */
-       if (of_property_read_u32(np, "reg-shift", &prop) == 0)
-               port.port.regshift = prop;
+               port.port.custom_divisor = port.port.uartclk / (16 * prop);
 
-       /* Check for fifo size */
-       if (of_property_read_u32(np, "fifo-size", &prop) == 0)
-               port.port.fifosize = prop;
-
-       /* Check for a fixed line number */
-       rc = of_alias_get_id(np, "serial");
-       if (rc >= 0)
-               port.port.line = rc;
-
-       port.port.irq = irq_of_parse_and_map(np, 0);
        port.port.handle_irq = aspeed_vuart_handle_irq;
-       port.port.iotype = UPIO_MEM;
        port.port.type = PORT_ASPEED_VUART;
-       port.port.uartclk = clk;
-       port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
-               | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
-
-       if (of_property_read_bool(np, "no-loopback-test"))
-               port.port.flags |= UPF_SKIP_TEST;
 
        if (port.port.fifosize)
                port.capabilities = UART_CAP_FIFO;
@@ -503,7 +485,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
 
        rc = serial8250_register_8250_port(&port);
        if (rc < 0)
-               goto err_clk_disable;
+               goto err_sysfs_remove;
 
        vuart->line = rc;
        vuart->port = serial8250_get_port(vuart->line);
@@ -529,7 +511,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
        rc = aspeed_vuart_set_lpc_address(vuart, prop);
        if (rc < 0) {
                dev_err_probe(dev, rc, "invalid value in aspeed,lpc-io-reg property\n");
-               goto err_clk_disable;
+               goto err_sysfs_remove;
        }
 
        rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", sirq, 2);
@@ -541,14 +523,14 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
        rc = aspeed_vuart_set_sirq(vuart, sirq[0]);
        if (rc < 0) {
                dev_err_probe(dev, rc, "invalid sirq number in aspeed,lpc-interrupts property\n");
-               goto err_clk_disable;
+               goto err_sysfs_remove;
        }
 
        sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]);
        if (sirq_polarity < 0) {
                rc = dev_err_probe(dev, sirq_polarity,
                                   "invalid sirq polarity in aspeed,lpc-interrupts property\n");
-               goto err_clk_disable;
+               goto err_sysfs_remove;
        }
 
        aspeed_vuart_set_sirq_polarity(vuart, sirq_polarity);
@@ -559,8 +541,6 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
 
        return 0;
 
-err_clk_disable:
-       irq_dispose_mapping(port.port.irq);
 err_sysfs_remove:
        sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
        return rc;
index beac6b340acef7cac394456e10b6244be7568deb..121a5ce8605089ae2e1877b56bfc4190c808355d 100644 (file)
@@ -45,10 +45,6 @@ struct bcm2835aux_data {
        u32 cntl;
 };
 
-struct bcm2835_aux_serial_driver_data {
-       resource_size_t offset;
-};
-
 static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up)
 {
        if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
@@ -85,10 +81,9 @@ static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up)
 
 static int bcm2835aux_serial_probe(struct platform_device *pdev)
 {
-       const struct bcm2835_aux_serial_driver_data *bcm_data;
+       const struct software_node *bcm2835_swnode;
        struct uart_8250_port up = { };
        struct bcm2835aux_data *data;
-       resource_size_t offset = 0;
        struct resource *res;
        unsigned int uartclk;
        int ret;
@@ -101,12 +96,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
        /* initialize data */
        up.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
        up.port.dev = &pdev->dev;
-       up.port.regshift = 2;
        up.port.type = PORT_16550;
-       up.port.iotype = UPIO_MEM;
-       up.port.fifosize = 8;
-       up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE |
-                       UPF_SKIP_TEST | UPF_IOREMAP;
+       up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_IOREMAP;
        up.port.rs485_config = serial8250_em485_config;
        up.port.rs485_supported = serial8250_em485_supported;
        up.rs485_start_tx = bcm2835aux_rs485_start_tx;
@@ -122,12 +113,6 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
        if (IS_ERR(data->clk))
                return dev_err_probe(&pdev->dev, PTR_ERR(data->clk), "could not get clk\n");
 
-       /* get the interrupt */
-       ret = platform_get_irq(pdev, 0);
-       if (ret < 0)
-               return ret;
-       up.port.irq = ret;
-
        /* map the main registers */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -135,52 +120,40 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       bcm_data = device_get_match_data(&pdev->dev);
-
-       /* Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi)
-        * describe the miniuart with a base address that encompasses the auxiliary
-        * registers shared between the miniuart and spi.
-        *
-        * This is due to historical reasons, see discussion here :
-        * https://edk2.groups.io/g/devel/topic/87501357#84349
-        *
-        * We need to add the offset between the miniuart and auxiliary
-        * registers to get the real miniuart base address.
-        */
-       if (bcm_data)
-               offset = bcm_data->offset;
+       up.port.mapbase = res->start;
+       up.port.mapsize = resource_size(res);
+
+       bcm2835_swnode = device_get_match_data(&pdev->dev);
+       if (bcm2835_swnode) {
+               ret = device_add_software_node(&pdev->dev, bcm2835_swnode);
+               if (ret)
+                       return ret;
+       }
 
-       up.port.mapbase = res->start + offset;
-       up.port.mapsize = resource_size(res) - offset;
+       ret = uart_read_port_properties(&up.port);
+       if (ret)
+               goto rm_swnode;
 
-       /* Check for a fixed line number */
-       ret = of_alias_get_id(pdev->dev.of_node, "serial");
-       if (ret >= 0)
-               up.port.line = ret;
+       up.port.regshift = 2;
+       up.port.fifosize = 8;
 
        /* enable the clock as a last step */
        ret = clk_prepare_enable(data->clk);
        if (ret) {
-               dev_err(&pdev->dev, "unable to enable uart clock - %d\n",
-                       ret);
-               return ret;
+               dev_err_probe(&pdev->dev, ret, "unable to enable uart clock\n");
+               goto rm_swnode;
        }
 
        uartclk = clk_get_rate(data->clk);
-       if (!uartclk) {
-               ret = device_property_read_u32(&pdev->dev, "clock-frequency", &uartclk);
-               if (ret) {
-                       dev_err_probe(&pdev->dev, ret, "could not get clk rate\n");
-                       goto dis_clk;
-               }
-       }
+       if (uartclk)
+               up.port.uartclk = uartclk;
 
        /* the HW-clock divider for bcm2835aux is 8,
         * but 8250 expects a divider of 16,
         * so we have to multiply the actual clock by 2
         * to get identical baudrates.
         */
-       up.port.uartclk = uartclk * 2;
+       up.port.uartclk *= 2;
 
        /* register the port */
        ret = serial8250_register_8250_port(&up);
@@ -194,6 +167,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
 
 dis_clk:
        clk_disable_unprepare(data->clk);
+rm_swnode:
+       device_remove_software_node(&pdev->dev);
        return ret;
 }
 
@@ -203,10 +178,27 @@ static void bcm2835aux_serial_remove(struct platform_device *pdev)
 
        serial8250_unregister_port(data->line);
        clk_disable_unprepare(data->clk);
+       device_remove_software_node(&pdev->dev);
 }
 
-static const struct bcm2835_aux_serial_driver_data bcm2835_acpi_data = {
-       .offset = 0x40,
+/*
+ * Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi)
+ * describe the miniuart with a base address that encompasses the auxiliary
+ * registers shared between the miniuart and spi.
+ *
+ * This is due to historical reasons, see discussion here:
+ * https://edk2.groups.io/g/devel/topic/87501357#84349
+ *
+ * We need to add the offset between the miniuart and auxiliary registers
+ * to get the real miniuart base address.
+ */
+static const struct property_entry bcm2835_acpi_properties[] = {
+       PROPERTY_ENTRY_U32("reg-offset", 0x40),
+       { }
+};
+
+static const struct software_node bcm2835_acpi_node = {
+       .properties = bcm2835_acpi_properties,
 };
 
 static const struct of_device_id bcm2835aux_serial_match[] = {
@@ -216,7 +208,7 @@ static const struct of_device_id bcm2835aux_serial_match[] = {
 MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match);
 
 static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = {
-       { "BCM2836", (kernel_ulong_t)&bcm2835_acpi_data },
+       { "BCM2836", (kernel_ulong_t)&bcm2835_acpi_node },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match);
index 504c4c02085776c610e8a6d9010f6982046c674a..5daa38d9c64e01d32cb1c10e48da065998dfbaa3 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/debugfs.h>
+#include <linux/units.h>
 
 #include "8250.h"
 
 #define TX_BUF_SIZE 4096
 #define RX_BUF_SIZE 4096
 #define RX_BUFS_COUNT 2
-#define KHZ    1000
-#define MHZ(x) ((x) * KHZ * KHZ)
 
 static const u32 brcmstb_rate_table[] = {
-       MHZ(81),
-       MHZ(108),
-       MHZ(64),                /* Actually 64285715 for some chips */
-       MHZ(48),
+       81 * HZ_PER_MHZ,
+       108 * HZ_PER_MHZ,
+       64 * HZ_PER_MHZ,                /* Actually 64285715 for some chips */
+       48 * HZ_PER_MHZ,
 };
 
 static const u32 brcmstb_rate_table_7278[] = {
-       MHZ(81),
-       MHZ(108),
+       81 * HZ_PER_MHZ,
+       108 * HZ_PER_MHZ,
        0,
-       MHZ(48),
+       48 * HZ_PER_MHZ,
 };
 
 struct brcmuart_priv {
@@ -936,17 +935,14 @@ static void brcmuart_init_debugfs(struct brcmuart_priv *priv,
 static int brcmuart_probe(struct platform_device *pdev)
 {
        struct resource *regs;
-       struct device_node *np = pdev->dev.of_node;
        const struct of_device_id *of_id = NULL;
        struct uart_8250_port *new_port;
        struct device *dev = &pdev->dev;
        struct brcmuart_priv *priv;
        struct clk *baud_mux_clk;
        struct uart_8250_port up;
-       int irq;
        void __iomem *membase = NULL;
        resource_size_t mapbase = 0;
-       u32 clk_rate = 0;
        int ret;
        int x;
        int dma_irq;
@@ -954,15 +950,12 @@ static int brcmuart_probe(struct platform_device *pdev)
                "uart", "dma_rx", "dma_tx", "dma_intr2", "dma_arb"
        };
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
        priv = devm_kzalloc(dev, sizeof(struct brcmuart_priv),
                        GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
-       of_id = of_match_node(brcmuart_dt_ids, np);
+       of_id = of_match_node(brcmuart_dt_ids, dev->of_node);
        if (!of_id || !of_id->data)
                priv->rate_table = brcmstb_rate_table;
        else
@@ -1012,7 +1005,23 @@ static int brcmuart_probe(struct platform_device *pdev)
                }
        }
 
-       of_property_read_u32(np, "clock-frequency", &clk_rate);
+       dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
+
+       memset(&up, 0, sizeof(up));
+       up.port.type = PORT_BCM7271;
+       up.port.dev = dev;
+       up.port.mapbase = mapbase;
+       up.port.membase = membase;
+       up.port.handle_irq = brcmuart_handle_irq;
+       up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE;
+       up.port.private_data = priv;
+
+       ret = uart_read_port_properties(&up.port);
+       if (ret)
+               goto release_dma;
+
+       up.port.regshift = 2;
+       up.port.iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32;
 
        /* See if a Baud clock has been specified */
        baud_mux_clk = devm_clk_get_optional_enabled(dev, "sw_baud");
@@ -1024,39 +1033,11 @@ static int brcmuart_probe(struct platform_device *pdev)
 
                priv->baud_mux_clk = baud_mux_clk;
                init_real_clk_rates(dev, priv);
-               clk_rate = priv->default_mux_rate;
+               up.port.uartclk = priv->default_mux_rate;
        } else {
                dev_dbg(dev, "BAUD MUX clock not specified\n");
        }
 
-       if (clk_rate == 0) {
-               ret = dev_err_probe(dev, -EINVAL, "clock-frequency or clk not defined\n");
-               goto release_dma;
-       }
-
-       dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
-
-       memset(&up, 0, sizeof(up));
-       up.port.type = PORT_BCM7271;
-       up.port.uartclk = clk_rate;
-       up.port.dev = dev;
-       up.port.mapbase = mapbase;
-       up.port.membase = membase;
-       up.port.irq = irq;
-       up.port.handle_irq = brcmuart_handle_irq;
-       up.port.regshift = 2;
-       up.port.iotype = of_device_is_big_endian(np) ?
-               UPIO_MEM32BE : UPIO_MEM32;
-       up.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
-               | UPF_FIXED_PORT | UPF_FIXED_TYPE;
-       up.port.dev = dev;
-       up.port.private_data = priv;
-
-       /* Check for a fixed line number */
-       ret = of_alias_get_id(np, "serial");
-       if (ret >= 0)
-               up.port.line = ret;
-
        /* setup HR timer */
        hrtimer_init(&priv->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
        priv->hrt.function = brcmuart_hrtimer_func;
index c1d43f040c43abc517c4ef6b48a5423e936e97f2..a3acbf0f5da1beff6724e839fa14a0a990a15576 100644 (file)
@@ -9,7 +9,6 @@
  * LCR is written whilst busy.  If it is, then a busy detect interrupt is
  * raised, the LCR needs to be rewritten and the uart status register read.
  */
-#include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -17,7 +16,6 @@
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/notifier.h>
-#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/property.h>
@@ -56,6 +54,7 @@
 #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)
+#define DW_UART_QUIRK_APMC0D08         BIT(4)
 
 static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
 {
@@ -445,44 +444,29 @@ static void dw8250_prepare_rx_dma(struct uart_8250_port *p)
 
 static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
 {
-       struct device_node *np = p->dev->of_node;
+       unsigned int quirks = data->pdata ? data->pdata->quirks : 0;
 
-       if (np) {
-               unsigned int quirks = data->pdata->quirks;
-               int id;
-
-               /* get index of serial line, if found in DT aliases */
-               id = of_alias_get_id(np, "serial");
-               if (id >= 0)
-                       p->line = id;
 #ifdef CONFIG_64BIT
-               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->skip_autocfg = true;
-               }
+       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->skip_autocfg = true;
+       }
 #endif
 
-               if (of_device_is_big_endian(np)) {
-                       p->iotype = UPIO_MEM32BE;
-                       p->serial_in = dw8250_serial_in32be;
-                       p->serial_out = dw8250_serial_out32be;
-               }
-
-               if (quirks & DW_UART_QUIRK_ARMADA_38X)
-                       p->serial_out = dw8250_serial_out38x;
-               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)) {
+       if (quirks & DW_UART_QUIRK_ARMADA_38X)
+               p->serial_out = dw8250_serial_out38x;
+       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;
+       }
+       if (quirks & DW_UART_QUIRK_APMC0D08) {
                p->iotype = UPIO_MEM32;
                p->regshift = 2;
                p->serial_in = dw8250_serial_in32;
@@ -510,39 +494,21 @@ static int dw8250_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct dw8250_data *data;
        struct resource *regs;
-       int irq;
        int err;
-       u32 val;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs)
                return dev_err_probe(dev, -EINVAL, "no registers defined\n");
 
-       irq = platform_get_irq_optional(pdev, 0);
-       /* no interrupt -> fall back to polling */
-       if (irq == -ENXIO)
-               irq = 0;
-       if (irq < 0)
-               return irq;
-
        spin_lock_init(&p->lock);
-       p->mapbase      = regs->start;
-       p->irq          = irq;
        p->handle_irq   = dw8250_handle_irq;
        p->pm           = dw8250_do_pm;
        p->type         = PORT_8250;
-       p->flags        = UPF_SHARE_IRQ | UPF_FIXED_PORT;
+       p->flags        = UPF_FIXED_PORT;
        p->dev          = dev;
-       p->iotype       = UPIO_MEM;
-       p->serial_in    = dw8250_serial_in;
-       p->serial_out   = dw8250_serial_out;
        p->set_ldisc    = dw8250_set_ldisc;
        p->set_termios  = dw8250_set_termios;
 
-       p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
-       if (!p->membase)
-               return -ENOMEM;
-
        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -554,15 +520,35 @@ static int dw8250_probe(struct platform_device *pdev)
        data->uart_16550_compatible = device_property_read_bool(dev,
                                                "snps,uart-16550-compatible");
 
-       err = device_property_read_u32(dev, "reg-shift", &val);
-       if (!err)
-               p->regshift = val;
+       p->mapbase = regs->start;
+       p->mapsize = resource_size(regs);
 
-       err = device_property_read_u32(dev, "reg-io-width", &val);
-       if (!err && val == 4) {
-               p->iotype = UPIO_MEM32;
+       p->membase = devm_ioremap(dev, p->mapbase, p->mapsize);
+       if (!p->membase)
+               return -ENOMEM;
+
+       err = uart_read_port_properties(p);
+       /* no interrupt -> fall back to polling */
+       if (err == -ENXIO)
+               err = 0;
+       if (err)
+               return err;
+
+       switch (p->iotype) {
+       case UPIO_MEM:
+               p->serial_in = dw8250_serial_in;
+               p->serial_out = dw8250_serial_out;
+               break;
+       case UPIO_MEM32:
                p->serial_in = dw8250_serial_in32;
                p->serial_out = dw8250_serial_out32;
+               break;
+       case UPIO_MEM32BE:
+               p->serial_in = dw8250_serial_in32be;
+               p->serial_out = dw8250_serial_out32be;
+               break;
+       default:
+               return -ENODEV;
        }
 
        if (device_property_read_bool(dev, "dcd-override")) {
@@ -589,15 +575,13 @@ static int dw8250_probe(struct platform_device *pdev)
                data->msr_mask_off |= UART_MSR_TERI;
        }
 
-       /* Always ask for fixed clock rate from a property. */
-       device_property_read_u32(dev, "clock-frequency", &p->uartclk);
-
        /* If there is separate baudclk, get the rate from it. */
        data->clk = devm_clk_get_optional_enabled(dev, "baudclk");
        if (data->clk == NULL)
                data->clk = devm_clk_get_optional_enabled(dev, NULL);
        if (IS_ERR(data->clk))
-               return PTR_ERR(data->clk);
+               return dev_err_probe(dev, PTR_ERR(data->clk),
+                                    "failed to get baudclk\n");
 
        INIT_WORK(&data->clk_work, dw8250_clk_work_cb);
        data->clk_notifier.notifier_call = dw8250_clk_notifier_cb;
@@ -762,13 +746,18 @@ static const struct of_device_id dw8250_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, dw8250_of_match);
 
+static const struct dw8250_platform_data dw8250_apmc0d08 = {
+       .usr_reg = DW_UART_USR,
+       .quirks = DW_UART_QUIRK_APMC0D08,
+};
+
 static const struct acpi_device_id dw8250_acpi_match[] = {
        { "80860F0A", (kernel_ulong_t)&dw8250_dw_apb },
        { "8086228A", (kernel_ulong_t)&dw8250_dw_apb },
        { "AMD0020", (kernel_ulong_t)&dw8250_dw_apb },
        { "AMDI0020", (kernel_ulong_t)&dw8250_dw_apb },
        { "AMDI0022", (kernel_ulong_t)&dw8250_dw_apb },
-       { "APMC0D08", (kernel_ulong_t)&dw8250_dw_apb},
+       { "APMC0D08", (kernel_ulong_t)&dw8250_apmc0d08 },
        { "BRCM2032", (kernel_ulong_t)&dw8250_dw_apb },
        { "HISI0031", (kernel_ulong_t)&dw8250_dw_apb },
        { "INT33C4", (kernel_ulong_t)&dw8250_dw_apb },
index 23366f868ae3a8391f631e9952eb70baf9959076..0440df7de1ed74379e8862adbf965c320cfc5611 100644 (file)
@@ -6,23 +6,29 @@
  *
  *  Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved.
  */
-#include <linux/acpi.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/dmi.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/kernel.h>
+#include <linux/math.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
 #include <linux/property.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <linux/serial_8250.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
 
 #include <asm/byteorder.h>
 
 #include "8250.h"
+#include "8250_pcilib.h"
 
 #define PCI_DEVICE_ID_ACCESSIO_COM_2S          0x1052
 #define PCI_DEVICE_ID_ACCESSIO_COM_4S          0x105d
@@ -229,13 +235,12 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,
                         struct uart_8250_port *port)
 {
        const struct exar8250_board *board = priv->board;
-       unsigned int bar = 0;
        unsigned char status;
+       int err;
 
-       port->port.iotype = UPIO_MEM;
-       port->port.mapbase = pci_resource_start(pcidev, bar) + offset;
-       port->port.membase = priv->virt + offset;
-       port->port.regshift = board->reg_shift;
+       err = serial8250_pci_setup_port(pcidev, port, 0, offset, board->reg_shift);
+       if (err)
+               return err;
 
        /*
         * XR17V35x UARTs have an extra divisor register, DLD that gets enabled
@@ -375,7 +380,7 @@ static struct platform_device *__xr17v35x_register_gpio(struct pci_dev *pcidev,
                return NULL;
 
        pdev->dev.parent = &pcidev->dev;
-       ACPI_COMPANION_SET(&pdev->dev, ACPI_COMPANION(&pcidev->dev));
+       device_set_node(&pdev->dev, dev_fwnode(&pcidev->dev));
 
        if (device_add_software_node(&pdev->dev, node) < 0 ||
            platform_device_add(pdev) < 0) {
@@ -713,14 +718,14 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
        uart.port.irq = pci_irq_vector(pcidev, 0);
        uart.port.dev = &pcidev->dev;
 
+       /* Clear interrupts */
+       exar_misc_clear(priv);
+
        rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler,
                         IRQF_SHARED, "exar_uart", priv);
        if (rc)
                return rc;
 
-       /* Clear interrupts */
-       exar_misc_clear(priv);
-
        for (i = 0; i < nr_ports && i < maxnr; i++) {
                rc = board->setup(priv, pcidev, &uart, i);
                if (rc) {
@@ -753,28 +758,24 @@ static void exar_pci_remove(struct pci_dev *pcidev)
        for (i = 0; i < priv->nr; i++)
                serial8250_unregister_port(priv->line[i]);
 
+       /* Ensure that every init quirk is properly torn down */
        if (priv->board->exit)
                priv->board->exit(pcidev);
 }
 
-static int __maybe_unused exar_suspend(struct device *dev)
+static int exar_suspend(struct device *dev)
 {
-       struct pci_dev *pcidev = to_pci_dev(dev);
-       struct exar8250 *priv = pci_get_drvdata(pcidev);
+       struct exar8250 *priv = dev_get_drvdata(dev);
        unsigned int i;
 
        for (i = 0; i < priv->nr; i++)
                if (priv->line[i] >= 0)
                        serial8250_suspend_port(priv->line[i]);
 
-       /* Ensure that every init quirk is properly torn down */
-       if (priv->board->exit)
-               priv->board->exit(pcidev);
-
        return 0;
 }
 
-static int __maybe_unused exar_resume(struct device *dev)
+static int exar_resume(struct device *dev)
 {
        struct exar8250 *priv = dev_get_drvdata(dev);
        unsigned int i;
@@ -788,7 +789,7 @@ static int __maybe_unused exar_resume(struct device *dev)
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
 
 static const struct exar8250_board pbn_fastcom335_2 = {
        .num_ports      = 2,
@@ -938,12 +939,13 @@ static struct pci_driver exar_pci_driver = {
        .probe          = exar_pci_probe,
        .remove         = exar_pci_remove,
        .driver         = {
-               .pm     = &exar_pci_pm,
+               .pm     = pm_sleep_ptr(&exar_pci_pm),
        },
        .id_table       = exar_pci_tbl,
 };
 module_pci_driver(exar_pci_driver);
 
+MODULE_IMPORT_NS(SERIAL_8250_PCI);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Exar Serial Driver");
 MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
index a12f737924c0b79c5d85d13e413f412bb7ed6dd6..a2783e38a2e31641c50667df086ecfad27df34bf 100644 (file)
@@ -234,7 +234,7 @@ static int ingenic_uart_probe(struct platform_device *pdev)
        struct ingenic_uart_data *data;
        const struct ingenic_uart_config *cdata;
        struct resource *regs;
-       int irq, err, line;
+       int err;
 
        cdata = of_device_get_match_data(&pdev->dev);
        if (!cdata) {
@@ -242,10 +242,6 @@ static int ingenic_uart_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs) {
                dev_err(&pdev->dev, "no registers defined\n");
@@ -259,21 +255,19 @@ static int ingenic_uart_probe(struct platform_device *pdev)
        spin_lock_init(&uart.port.lock);
        uart.port.type = PORT_16550A;
        uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
-       uart.port.iotype = UPIO_MEM;
        uart.port.mapbase = regs->start;
-       uart.port.regshift = 2;
        uart.port.serial_out = ingenic_uart_serial_out;
        uart.port.serial_in = ingenic_uart_serial_in;
-       uart.port.irq = irq;
        uart.port.dev = &pdev->dev;
-       uart.port.fifosize = cdata->fifosize;
        uart.tx_loadsz = cdata->tx_loadsz;
        uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE;
 
-       /* Check for a fixed line number */
-       line = of_alias_get_id(pdev->dev.of_node, "serial");
-       if (line >= 0)
-               uart.port.line = line;
+       err = uart_read_port_properties(&uart.port);
+       if (err)
+               return err;
+
+       uart.port.regshift = 2;
+       uart.port.fifosize = cdata->fifosize;
 
        uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
                                         resource_size(regs));
index 8d728a6a5991412b23298368aa914971ea4b4261..7984ee05af1dada214e275062a5c831d9a66144c 100644 (file)
@@ -92,11 +92,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
        struct lpc18xx_uart_data *data;
        struct uart_8250_port uart;
        struct resource *res;
-       int irq, ret;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
+       int ret;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -139,19 +135,12 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
                goto dis_clk_reg;
        }
 
-       ret = of_alias_get_id(pdev->dev.of_node, "serial");
-       if (ret >= 0)
-               uart.port.line = ret;
-
        data->dma.rx_param = data;
        data->dma.tx_param = data;
 
        spin_lock_init(&uart.port.lock);
        uart.port.dev = &pdev->dev;
-       uart.port.irq = irq;
-       uart.port.iotype = UPIO_MEM32;
        uart.port.mapbase = res->start;
-       uart.port.regshift = 2;
        uart.port.type = PORT_16550A;
        uart.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST;
        uart.port.uartclk = clk_get_rate(data->clk_uart);
@@ -160,6 +149,13 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
        uart.port.rs485_supported = lpc18xx_rs485_supported;
        uart.port.serial_out = lpc18xx_uart_serial_out;
 
+       ret = uart_read_port_properties(&uart.port);
+       if (ret)
+               return ret;
+
+       uart.port.iotype = UPIO_MEM32;
+       uart.port.regshift = 2;
+
        uart.dma = &data->dma;
        uart.dma->rxconf.src_maxburst = 1;
        uart.dma->txconf.dst_maxburst = 1;
index 34f17a9785e79e1d26b6fbbbea3441a89f523e44..5d1dd992d8fba0df3d9e9e15d0d0c7b675015ffa 100644 (file)
@@ -4,7 +4,10 @@
  *
  *    Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
  */
+
+#include <linux/bits.h>
 #include <linux/console.h>
+#include <linux/math.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/serial_core.h>
@@ -25,6 +28,36 @@ struct of_serial_info {
        int line;
 };
 
+/* Nuvoton NPCM timeout register */
+#define UART_NPCM_TOR          7
+#define UART_NPCM_TOIE         BIT(7)  /* Timeout Interrupt Enable */
+
+static int npcm_startup(struct uart_port *port)
+{
+       /*
+        * Nuvoton calls the scratch register 'UART_TOR' (timeout
+        * register). Enable it, and set TIOC (timeout interrupt
+        * comparator) to be 0x20 for correct operation.
+        */
+       serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20);
+
+       return serial8250_do_startup(port);
+}
+
+/* Nuvoton NPCM UARTs have a custom divisor calculation */
+static unsigned int npcm_get_divisor(struct uart_port *port, unsigned int baud,
+                                    unsigned int *frac)
+{
+       return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2;
+}
+
+static int npcm_setup(struct uart_port *port)
+{
+       port->get_divisor = npcm_get_divisor;
+       port->startup = npcm_startup;
+       return 0;
+}
+
 /*
  * Fill a struct uart_port for a given device node
  */
@@ -36,37 +69,22 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
        struct device *dev = &ofdev->dev;
        struct device_node *np = dev->of_node;
        struct uart_port *port = &up->port;
-       u32 clk, spd, prop;
-       int ret, irq;
+       u32 spd;
+       int ret;
 
        memset(port, 0, sizeof *port);
 
        pm_runtime_enable(&ofdev->dev);
        pm_runtime_get_sync(&ofdev->dev);
 
-       if (of_property_read_u32(np, "clock-frequency", &clk)) {
-
-               /* Get clk rate through clk driver if present */
-               info->clk = devm_clk_get_enabled(dev, NULL);
-               if (IS_ERR(info->clk)) {
-                       ret = dev_err_probe(dev, PTR_ERR(info->clk), "failed to get clock\n");
-                       goto err_pmruntime;
-               }
-
-               clk = clk_get_rate(info->clk);
-       }
-       /* If current-speed was set, then try not to change it. */
-       if (of_property_read_u32(np, "current-speed", &spd) == 0)
-               port->custom_divisor = clk / (16 * spd);
-
        ret = of_address_to_resource(np, 0, &resource);
        if (ret) {
                dev_err_probe(dev, ret, "invalid address\n");
                goto err_pmruntime;
        }
 
-       port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT |
-                                 UPF_FIXED_TYPE;
+       port->dev = &ofdev->dev;
+       port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE;
        spin_lock_init(&port->lock);
 
        if (resource_type(&resource) == IORESOURCE_IO) {
@@ -75,70 +93,31 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
        } else {
                port->mapbase = resource.start;
                port->mapsize = resource_size(&resource);
+               port->flags |= UPF_IOREMAP;
+       }
 
-               /* Check for shifted address mapping */
-               if (of_property_read_u32(np, "reg-offset", &prop) == 0) {
-                       if (prop >= port->mapsize) {
-                               ret = dev_err_probe(dev, -EINVAL, "reg-offset %u exceeds region size %pa\n",
-                                                   prop, &port->mapsize);
-                               goto err_pmruntime;
-                       }
+       ret = uart_read_and_validate_port_properties(port);
+       if (ret)
+               goto err_pmruntime;
 
-                       port->mapbase += prop;
-                       port->mapsize -= prop;
+       /* Get clk rate through clk driver if present */
+       if (!port->uartclk) {
+               info->clk = devm_clk_get_enabled(dev, NULL);
+               if (IS_ERR(info->clk)) {
+                       ret = dev_err_probe(dev, PTR_ERR(info->clk), "failed to get clock\n");
+                       goto err_pmruntime;
                }
 
-               port->iotype = UPIO_MEM;
-               if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
-                       switch (prop) {
-                       case 1:
-                               port->iotype = UPIO_MEM;
-                               break;
-                       case 2:
-                               port->iotype = UPIO_MEM16;
-                               break;
-                       case 4:
-                               port->iotype = of_device_is_big_endian(np) ?
-                                              UPIO_MEM32BE : UPIO_MEM32;
-                               break;
-                       default:
-                               ret = dev_err_probe(dev, -EINVAL, "unsupported reg-io-width (%u)\n",
-                                                   prop);
-                               goto err_pmruntime;
-                       }
-               }
-               port->flags |= UPF_IOREMAP;
+               port->uartclk = clk_get_rate(info->clk);
        }
+       /* If current-speed was set, then try not to change it. */
+       if (of_property_read_u32(np, "current-speed", &spd) == 0)
+               port->custom_divisor = port->uartclk / (16 * spd);
 
        /* Compatibility with the deprecated pxa driver and 8250_pxa drivers. */
        if (of_device_is_compatible(np, "mrvl,mmp-uart"))
                port->regshift = 2;
 
-       /* Check for registers offset within the devices address range */
-       if (of_property_read_u32(np, "reg-shift", &prop) == 0)
-               port->regshift = prop;
-
-       /* Check for fifo size */
-       if (of_property_read_u32(np, "fifo-size", &prop) == 0)
-               port->fifosize = prop;
-
-       /* Check for a fixed line number */
-       ret = of_alias_get_id(np, "serial");
-       if (ret >= 0)
-               port->line = ret;
-
-       irq = of_irq_get(np, 0);
-       if (irq < 0) {
-               if (irq == -EPROBE_DEFER) {
-                       ret = -EPROBE_DEFER;
-                       goto err_pmruntime;
-               }
-               /* IRQ support not mandatory */
-               irq = 0;
-       }
-
-       port->irq = irq;
-
        info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL);
        if (IS_ERR(info->rst)) {
                ret = PTR_ERR(info->rst);
@@ -150,12 +129,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
                goto err_pmruntime;
 
        port->type = type;
-       port->uartclk = clk;
-
-       if (of_property_read_bool(np, "no-loopback-test"))
-               port->flags |= UPF_SKIP_TEST;
-
-       port->dev = &ofdev->dev;
        port->rs485_config = serial8250_em485_config;
        port->rs485_supported = serial8250_em485_supported;
        up->rs485_start_tx = serial8250_em485_start_tx;
@@ -164,10 +137,17 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
        switch (type) {
        case PORT_RT2880:
                ret = rt288x_setup(port);
-               if (ret)
-                       goto err_pmruntime;
+               break;
+       case PORT_NPCM:
+               ret = npcm_setup(port);
+               break;
+       default:
+               /* Nothing to do */
+               ret = 0;
                break;
        }
+       if (ret)
+               goto err_pmruntime;
 
        if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL) &&
            (of_device_is_compatible(np, "fsl,ns16550") ||
@@ -240,7 +220,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
        platform_set_drvdata(ofdev, info);
        return 0;
 err_dispose:
-       irq_dispose_mapping(port8250.port.irq);
        pm_runtime_put_sync(&ofdev->dev);
        pm_runtime_disable(&ofdev->dev);
 err_free:
index 6942990a333c8b6a76520f9d5868e604565034bf..66901d93089a3cbcd3e0f7d16f85936cc859f30c 100644 (file)
@@ -1394,11 +1394,7 @@ static int omap8250_probe(struct platform_device *pdev)
        struct uart_8250_port up;
        struct resource *regs;
        void __iomem *membase;
-       int irq, ret;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
+       int ret;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs) {
@@ -1419,7 +1415,6 @@ static int omap8250_probe(struct platform_device *pdev)
        up.port.dev = &pdev->dev;
        up.port.mapbase = regs->start;
        up.port.membase = membase;
-       up.port.irq = irq;
        /*
         * It claims to be 16C750 compatible however it is a little different.
         * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to
@@ -1429,13 +1424,9 @@ static int omap8250_probe(struct platform_device *pdev)
         * or pm callback.
         */
        up.port.type = PORT_8250;
-       up.port.iotype = UPIO_MEM;
-       up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW |
-               UPF_HARD_FLOW;
+       up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | UPF_HARD_FLOW;
        up.port.private_data = priv;
 
-       up.port.regshift = OMAP_UART_REGSHIFT;
-       up.port.fifosize = 64;
        up.tx_loadsz = 64;
        up.capabilities = UART_CAP_FIFO;
 #ifdef CONFIG_PM
@@ -1461,14 +1452,14 @@ static int omap8250_probe(struct platform_device *pdev)
        up.rs485_stop_tx = serial8250_em485_stop_tx;
        up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
 
-       ret = of_alias_get_id(np, "serial");
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to get alias\n");
+       ret = uart_read_port_properties(&up.port);
+       if (ret)
                return ret;
-       }
-       up.port.line = ret;
 
-       if (of_property_read_u32(np, "clock-frequency", &up.port.uartclk)) {
+       up.port.regshift = OMAP_UART_REGSHIFT;
+       up.port.fifosize = 64;
+
+       if (!up.port.uartclk) {
                struct clk *clk;
 
                clk = devm_clk_get(&pdev->dev, NULL);
@@ -1560,8 +1551,8 @@ static int omap8250_probe(struct platform_device *pdev)
        }
 #endif
 
-       irq_set_status_flags(irq, IRQ_NOAUTOEN);
-       ret = devm_request_irq(&pdev->dev, irq, omap8250_irq, 0,
+       irq_set_status_flags(up.port.irq, IRQ_NOAUTOEN);
+       ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0,
                               dev_name(&pdev->dev), priv);
        if (ret < 0)
                return ret;
index 2dda737b1660bd7bd6f576d2146440d97e945047..2fbb5851f788b7a45f1002f4d276b4968b067f0e 100644 (file)
@@ -7,23 +7,31 @@
  *  Copyright (C) 2022 Microchip Technology Inc., All Rights Reserved.
  */
 
+#include <linux/array_size.h>
 #include <linux/bitfield.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
+#include <linux/bits.h>
+#include <linux/circ_buf.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gfp_types.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
-#include <linux/kernel.h>
+#include <linux/minmax.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/overflow.h>
 #include <linux/pci.h>
+#include <linux/pm.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_8250.h>
-#include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <linux/string.h>
-#include <linux/units.h>
+#include <linux/time.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-#include <linux/8250_pci.h>
+#include <linux/types.h>
+#include <linux/units.h>
 
 #include <asm/byteorder.h>
 
@@ -67,6 +75,7 @@
 #define SYSLOCK_RETRY_CNT                      1000
 
 #define UART_RX_BYTE_FIFO                      0x00
+#define UART_TX_BYTE_FIFO                      0x00
 #define UART_FIFO_CTL                          0x02
 
 #define UART_ACTV_REG                          0x11
 #define ADCL_CFG_PIN_SEL                       BIT(1)
 #define ADCL_CFG_EN                            BIT(0)
 
-#define UART_BIT_SAMPLE_CNT                    16
+#define UART_BIT_SAMPLE_CNT_8                  8
+#define UART_BIT_SAMPLE_CNT_16                 16
 #define BAUD_CLOCK_DIV_INT_MSK                 GENMASK(31, 8)
 #define ADCL_CFG_RTS_DELAY_MASK                        GENMASK(11, 8)
-#define UART_CLOCK_DEFAULT                     (62500 * HZ_PER_KHZ)
 
 #define UART_WAKE_REG                          0x8C
 #define UART_WAKE_MASK_REG                     0x90
        (UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT)
 
 #define UART_BAUD_CLK_DIVISOR_REG              0x54
+#define FRAC_DIV_CFG_REG                       0x58
 
 #define UART_RESET_REG                         0x94
 #define UART_RESET_D3_RESET_DISABLE            BIT(16)
 
 #define UART_BURST_STATUS_REG                  0x9C
+#define UART_TX_BURST_FIFO                     0xA0
 #define UART_RX_BURST_FIFO                     0xA4
 
+#define UART_BIT_DIVISOR_8                     0x26731000
+#define UART_BIT_DIVISOR_16                    0x6ef71000
+#define UART_BAUD_4MBPS                                4000000
+
 #define MAX_PORTS                              4
 #define PORT_OFFSET                            0x100
 #define RX_BUF_SIZE                            512
 #define UART_BURST_SIZE                                4
 
 #define UART_BST_STAT_RX_COUNT_MASK            0x00FF
+#define UART_BST_STAT_TX_COUNT_MASK            0xFF00
 #define UART_BST_STAT_IIR_INT_PEND             0x100000
 #define UART_LSR_OVERRUN_ERR_CLR               0x43
 #define UART_BST_STAT_LSR_RX_MASK              0x9F000000
 #define UART_BST_STAT_LSR_OVERRUN_ERR          0x2000000
 #define UART_BST_STAT_LSR_PARITY_ERR           0x4000000
 #define UART_BST_STAT_LSR_FRAME_ERR            0x8000000
+#define UART_BST_STAT_LSR_THRE                 0x20000000
 
 struct pci1xxxx_8250 {
        unsigned int nr;
@@ -206,15 +223,21 @@ static int pci1xxxx_get_num_ports(struct pci_dev *dev)
 static unsigned int pci1xxxx_get_divisor(struct uart_port *port,
                                         unsigned int baud, unsigned int *frac)
 {
+       unsigned int uart_sample_cnt;
        unsigned int quot;
 
+       if (baud >= UART_BAUD_4MBPS)
+               uart_sample_cnt = UART_BIT_SAMPLE_CNT_8;
+       else
+               uart_sample_cnt = UART_BIT_SAMPLE_CNT_16;
+
        /*
         * Calculate baud rate sampling period in nanoseconds.
         * Fractional part x denotes x/255 parts of a nanosecond.
         */
-       quot = NSEC_PER_SEC / (baud * UART_BIT_SAMPLE_CNT);
-       *frac = (NSEC_PER_SEC - quot * baud * UART_BIT_SAMPLE_CNT) *
-                 255 / UART_BIT_SAMPLE_CNT / baud;
+       quot = NSEC_PER_SEC / (baud * uart_sample_cnt);
+       *frac = (NSEC_PER_SEC - quot * baud * uart_sample_cnt) *
+                 255 / uart_sample_cnt / baud;
 
        return quot;
 }
@@ -222,6 +245,11 @@ static unsigned int pci1xxxx_get_divisor(struct uart_port *port,
 static void pci1xxxx_set_divisor(struct uart_port *port, unsigned int baud,
                                 unsigned int quot, unsigned int frac)
 {
+       if (baud >= UART_BAUD_4MBPS)
+               writel(UART_BIT_DIVISOR_8, port->membase + FRAC_DIV_CFG_REG);
+       else
+               writel(UART_BIT_DIVISOR_16, port->membase + FRAC_DIV_CFG_REG);
+
        writel(FIELD_PREP(BAUD_CLOCK_DIV_INT_MSK, quot) | frac,
               port->membase + UART_BAUD_CLK_DIVISOR_REG);
 }
@@ -233,7 +261,16 @@ static int pci1xxxx_rs485_config(struct uart_port *port,
        u32 delay_in_baud_periods;
        u32 baud_period_in_ns;
        u32 mode_cfg = 0;
+       u32 sample_cnt;
        u32 clock_div;
+       u32 frac_div;
+
+       frac_div = readl(port->membase + FRAC_DIV_CFG_REG);
+
+       if (frac_div == UART_BIT_DIVISOR_16)
+               sample_cnt = UART_BIT_SAMPLE_CNT_16;
+       else
+               sample_cnt = UART_BIT_SAMPLE_CNT_8;
 
        /*
         * pci1xxxx's uart hardware supports only RTS delay after
@@ -249,7 +286,7 @@ static int pci1xxxx_rs485_config(struct uart_port *port,
                        clock_div = readl(port->membase + UART_BAUD_CLK_DIVISOR_REG);
                        baud_period_in_ns =
                                FIELD_GET(BAUD_CLOCK_DIV_INT_MSK, clock_div) *
-                               UART_BIT_SAMPLE_CNT;
+                               sample_cnt;
                        delay_in_baud_periods =
                                rs485->delay_rts_after_send * NSEC_PER_MSEC /
                                baud_period_in_ns;
@@ -344,6 +381,105 @@ static void pci1xxxx_rx_burst(struct uart_port *port, u32 uart_status)
        }
 }
 
+static void pci1xxxx_process_write_data(struct uart_port *port,
+                                       struct circ_buf *xmit,
+                                       int *data_empty_count,
+                                       u32 *valid_byte_count)
+{
+       u32 valid_burst_count = *valid_byte_count / UART_BURST_SIZE;
+
+       /*
+        * Each transaction transfers data in DWORDs. If there are less than
+        * four remaining valid_byte_count to transfer or if the circular
+        * buffer has insufficient space for a DWORD, the data is transferred
+        * one byte at a time.
+        */
+       while (valid_burst_count) {
+               if (*data_empty_count - UART_BURST_SIZE < 0)
+                       break;
+               if (xmit->tail > (UART_XMIT_SIZE - UART_BURST_SIZE))
+                       break;
+               writel(*(unsigned int *)&xmit->buf[xmit->tail],
+                      port->membase + UART_TX_BURST_FIFO);
+               *valid_byte_count -= UART_BURST_SIZE;
+               *data_empty_count -= UART_BURST_SIZE;
+               valid_burst_count -= UART_BYTE_SIZE;
+
+               xmit->tail = (xmit->tail + UART_BURST_SIZE) &
+                            (UART_XMIT_SIZE - 1);
+       }
+
+       while (*valid_byte_count) {
+               if (*data_empty_count - UART_BYTE_SIZE < 0)
+                       break;
+               writeb(xmit->buf[xmit->tail], port->membase +
+                      UART_TX_BYTE_FIFO);
+               *data_empty_count -= UART_BYTE_SIZE;
+               *valid_byte_count -= UART_BYTE_SIZE;
+
+               /*
+                * When the tail of the circular buffer is reached, the next
+                * byte is transferred to the beginning of the buffer.
+                */
+               xmit->tail = (xmit->tail + UART_BYTE_SIZE) &
+                            (UART_XMIT_SIZE - 1);
+
+               /*
+                * If there are any pending burst count, data is handled by
+                * transmitting DWORDs at a time.
+                */
+               if (valid_burst_count && (xmit->tail <
+                  (UART_XMIT_SIZE - UART_BURST_SIZE)))
+                       break;
+       }
+}
+
+static void pci1xxxx_tx_burst(struct uart_port *port, u32 uart_status)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       u32 valid_byte_count;
+       int data_empty_count;
+       struct circ_buf *xmit;
+
+       xmit = &port->state->xmit;
+
+       if (port->x_char) {
+               writeb(port->x_char, port->membase + UART_TX);
+               port->icount.tx++;
+               port->x_char = 0;
+               return;
+       }
+
+       if ((uart_tx_stopped(port)) || (uart_circ_empty(xmit))) {
+               port->ops->stop_tx(port);
+       } else {
+               data_empty_count = (pci1xxxx_read_burst_status(port) &
+                                   UART_BST_STAT_TX_COUNT_MASK) >> 8;
+               do {
+                       valid_byte_count = uart_circ_chars_pending(xmit);
+
+                       pci1xxxx_process_write_data(port, xmit,
+                                                   &data_empty_count,
+                                                   &valid_byte_count);
+
+                       port->icount.tx++;
+                       if (uart_circ_empty(xmit))
+                               break;
+               } while (data_empty_count && valid_byte_count);
+       }
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+
+        /*
+         * With RPM enabled, we have to wait until the FIFO is empty before
+         * the HW can go idle. So we get here once again with empty FIFO and
+         * disable the interrupt and RPM in __stop_tx()
+         */
+       if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
+               port->ops->stop_tx(port);
+}
+
 static int pci1xxxx_handle_irq(struct uart_port *port)
 {
        unsigned long flags;
@@ -359,6 +495,9 @@ static int pci1xxxx_handle_irq(struct uart_port *port)
        if (status & UART_BST_STAT_LSR_RX_MASK)
                pci1xxxx_rx_burst(port, status);
 
+       if (status & UART_BST_STAT_LSR_THRE)
+               pci1xxxx_tx_burst(port, status);
+
        spin_unlock_irqrestore(&port->lock, flags);
 
        return 1;
@@ -481,6 +620,17 @@ static int pci1xxxx_setup(struct pci_dev *pdev,
 
        port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST;
        port->port.type = PORT_MCHP16550A;
+       /*
+        * 8250 core considers prescaller value to be always 16.
+        * The MCHP ports support downscaled mode and hence the
+        * functional UART clock can be lower, i.e. 62.5MHz, than
+        * software expects in order to support higher baud rates.
+        * Assign here 64MHz to support 4Mbps.
+        *
+        * The value itself is not really used anywhere except baud
+        * rate calculations, so we can mangle it as we wish.
+        */
+       port->port.uartclk = 64 * HZ_PER_MHZ;
        port->port.set_termios = serial8250_do_set_termios;
        port->port.get_divisor = pci1xxxx_get_divisor;
        port->port.set_divisor = pci1xxxx_set_divisor;
@@ -594,7 +744,6 @@ static int pci1xxxx_serial_probe(struct pci_dev *pdev,
 
        memset(&uart, 0, sizeof(uart));
        uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT;
-       uart.port.uartclk = UART_CLOCK_DEFAULT;
        uart.port.dev = dev;
 
        if (num_vectors == max_vec_reqd)
index 8ca061d3bbb9215d04a4381a84f07b09147f2c8a..fc9dd5d45295da2a526688d442876d5b2c2e18c1 100644 (file)
 
 #include "8250.h"
 
-/* Nuvoton NPCM timeout register */
-#define UART_NPCM_TOR          7
-#define UART_NPCM_TOIE         BIT(7)  /* Timeout Interrupt Enable */
-
 /*
  * Debugging.
  */
@@ -1329,9 +1325,6 @@ static void autoconfig_irq(struct uart_8250_port *up)
                inb_p(ICP);
        }
 
-       if (uart_console(port))
-               console_lock();
-
        /* forget possible initially masked and pending IRQ */
        probe_irq_off(probe_irq_on());
        save_mcr = serial8250_in_MCR(up);
@@ -1371,9 +1364,6 @@ static void autoconfig_irq(struct uart_8250_port *up)
        if (port->flags & UPF_FOURPORT)
                outb_p(save_ICP, ICP);
 
-       if (uart_console(port))
-               console_unlock();
-
        port->irq = (irq > 0) ? irq : 0;
 }
 
@@ -2235,15 +2225,6 @@ int serial8250_do_startup(struct uart_port *port)
                                UART_DA830_PWREMU_MGMT_FREE);
        }
 
-       if (port->type == PORT_NPCM) {
-               /*
-                * Nuvoton calls the scratch register 'UART_TOR' (timeout
-                * register). Enable it, and set TIOC (timeout interrupt
-                * comparator) to be 0x20 for correct operation.
-                */
-               serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20);
-       }
-
 #ifdef CONFIG_SERIAL_8250_RSA
        /*
         * If this is an RSA port, see if we can kick it up to the
@@ -2545,15 +2526,6 @@ static void serial8250_shutdown(struct uart_port *port)
                serial8250_do_shutdown(port);
 }
 
-/* Nuvoton NPCM UARTs have a custom divisor calculation */
-static unsigned int npcm_get_divisor(struct uart_8250_port *up,
-               unsigned int baud)
-{
-       struct uart_port *port = &up->port;
-
-       return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2;
-}
-
 static unsigned int serial8250_do_get_divisor(struct uart_port *port,
                                              unsigned int baud,
                                              unsigned int *frac)
@@ -2598,8 +2570,6 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port,
                quot = 0x8001;
        else if (magic_multiplier && baud >= port->uartclk / 12)
                quot = 0x8002;
-       else if (up->port.type == PORT_NPCM)
-               quot = npcm_get_divisor(up, baud);
        else
                quot = uart_get_divisor(port, baud);
 
@@ -2714,12 +2684,8 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
  */
 void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
 {
-       struct uart_8250_port *up = up_to_u8250p(port);
        struct tty_port *tport = &port->state->port;
-       unsigned int baud, quot, frac = 0;
-       struct ktermios *termios;
        struct tty_struct *tty;
-       unsigned long flags;
 
        tty = tty_port_tty_get(tport);
        if (!tty) {
@@ -2740,21 +2706,7 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
        if (!tty_port_initialized(tport))
                goto out_unlock;
 
-       termios = &tty->termios;
-
-       baud = serial8250_get_baud_rate(port, termios, NULL);
-       quot = serial8250_get_divisor(port, baud, &frac);
-
-       serial8250_rpm_get(up);
-       uart_port_lock_irqsave(port, &flags);
-
-       uart_update_timeout(port, termios->c_cflag, baud);
-
-       serial8250_set_divisor(port, baud, quot, frac);
-       serial_port_out(port, UART_LCR, up->lcr);
-
-       uart_port_unlock_irqrestore(port, flags);
-       serial8250_rpm_put(up);
+       serial8250_do_set_termios(port, &tty->termios, NULL);
 
 out_unlock:
        mutex_unlock(&tport->mutex);
index 77686da42ce8e93ca42d9c00ffde2d4e8bb9c234..f1a51b00b1b9de84307047e3f216694bfa42fb06 100644 (file)
@@ -92,11 +92,7 @@ static int serial_pxa_probe(struct platform_device *pdev)
        struct uart_8250_port uart = {};
        struct pxa8250_data *data;
        struct resource *mmres;
-       int irq, ret;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
+       int ret;
 
        mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mmres)
@@ -114,21 +110,21 @@ static int serial_pxa_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ret = of_alias_get_id(pdev->dev.of_node, "serial");
-       if (ret >= 0)
-               uart.port.line = ret;
-
        uart.port.type = PORT_XSCALE;
-       uart.port.iotype = UPIO_MEM32;
        uart.port.mapbase = mmres->start;
-       uart.port.regshift = 2;
-       uart.port.irq = irq;
-       uart.port.fifosize = 64;
        uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE;
        uart.port.dev = &pdev->dev;
        uart.port.uartclk = clk_get_rate(data->clk);
        uart.port.pm = serial_pxa_pm;
        uart.port.private_data = data;
+
+       ret = uart_read_port_properties(&uart.port);
+       if (ret)
+               return ret;
+
+       uart.port.iotype = UPIO_MEM32;
+       uart.port.regshift = 2;
+       uart.port.fifosize = 64;
        uart.dl_write = serial_pxa_dl_write;
 
        ret = serial8250_register_8250_port(&uart);
index ba352262df75a7b32c9fa6401abd012e5ccf0ec8..60a80d00d2519b600dfb4fb635f2f1e33551adad 100644 (file)
@@ -57,25 +57,11 @@ static int tegra_uart_probe(struct platform_device *pdev)
        port = &port8250.port;
        spin_lock_init(&port->lock);
 
-       port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT |
-                     UPF_FIXED_TYPE;
-       port->iotype = UPIO_MEM32;
-       port->regshift = 2;
+       port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE;
        port->type = PORT_TEGRA;
-       port->irqflags |= IRQF_SHARED;
        port->dev = &pdev->dev;
        port->handle_break = tegra_uart_handle_break;
 
-       ret = of_alias_get_id(pdev->dev.of_node, "serial");
-       if (ret >= 0)
-               port->line = ret;
-
-       ret = platform_get_irq(pdev, 0);
-       if (ret < 0)
-               return ret;
-
-       port->irq = ret;
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -ENODEV;
@@ -88,12 +74,18 @@ static int tegra_uart_probe(struct platform_device *pdev)
        port->mapbase = res->start;
        port->mapsize = resource_size(res);
 
+       ret = uart_read_port_properties(port);
+       if (ret)
+               return ret;
+
+       port->iotype = UPIO_MEM32;
+       port->regshift = 2;
+
        uart->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
        if (IS_ERR(uart->rst))
                return PTR_ERR(uart->rst);
 
-       if (device_property_read_u32(&pdev->dev, "clock-frequency",
-                                    &port->uartclk)) {
+       if (!port->uartclk) {
                uart->clk = devm_clk_get(&pdev->dev, NULL);
                if (IS_ERR(uart->clk)) {
                        dev_err(&pdev->dev, "failed to get clock!\n");
index 6399a38ecce2ada62168872b33b13ae7c7273b49..670d2ca0f7572948384c67a49855cd96464447c1 100644 (file)
@@ -162,7 +162,6 @@ static int uniphier_uart_probe(struct platform_device *pdev)
        struct uniphier8250_priv *priv;
        struct resource *regs;
        void __iomem *membase;
-       int irq;
        int ret;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -175,23 +174,12 @@ static int uniphier_uart_probe(struct platform_device *pdev)
        if (!membase)
                return -ENOMEM;
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
        memset(&up, 0, sizeof(up));
 
-       ret = of_alias_get_id(dev->of_node, "serial");
-       if (ret < 0) {
-               dev_err(dev, "failed to get alias id\n");
-               return ret;
-       }
-       up.port.line = ret;
-
        priv->clk = devm_clk_get(dev, NULL);
        if (IS_ERR(priv->clk)) {
                dev_err(dev, "failed to get clock\n");
@@ -211,7 +199,10 @@ static int uniphier_uart_probe(struct platform_device *pdev)
        up.port.mapbase = regs->start;
        up.port.mapsize = resource_size(regs);
        up.port.membase = membase;
-       up.port.irq = irq;
+
+       ret = uart_read_port_properties(&up.port);
+       if (ret)
+               return ret;
 
        up.port.type = PORT_16550A;
        up.port.iotype = UPIO_MEM32;
index 8b9a2c4902e2c31c0897d7daf42a0ffd97c285d7..47ff50763c048c89b19b7c9f13f462bc5368ab43 100644 (file)
@@ -149,6 +149,7 @@ config SERIAL_8250_PCI
 config SERIAL_8250_EXAR
        tristate "8250/16550 Exar/Commtech PCI/PCIe device support"
        depends on SERIAL_8250 && PCI
+       select SERIAL_8250_PCILIB
        default SERIAL_8250
        help
          This builds support for XR17C1xx, XR17V3xx and some Commtech
index cf2c890a560f05204e249b931668deca04b3cb27..2fa3fb30dc6c7552667ea68691b28115569c303e 100644 (file)
@@ -348,10 +348,7 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
                                flag = TTY_FRAME;
                }
 
-               uart_port_unlock(&uap->port);
-               sysrq = uart_handle_sysrq_char(&uap->port, ch & 255);
-               uart_port_lock(&uap->port);
-
+               sysrq = uart_prepare_sysrq_char(&uap->port, ch & 255);
                if (!sysrq)
                        uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
        }
@@ -1017,7 +1014,7 @@ static void pl011_dma_rx_callback(void *data)
        ret = pl011_dma_rx_trigger_dma(uap);
 
        pl011_dma_rx_chars(uap, pending, lastbuf, false);
-       uart_port_unlock_irq(&uap->port);
+       uart_unlock_and_check_sysrq(&uap->port);
        /*
         * Do this check after we picked the DMA chars so we don't
         * get some IRQ immediately from RX.
@@ -1540,11 +1537,10 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 static irqreturn_t pl011_int(int irq, void *dev_id)
 {
        struct uart_amba_port *uap = dev_id;
-       unsigned long flags;
        unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
        int handled = 0;
 
-       uart_port_lock_irqsave(&uap->port, &flags);
+       uart_port_lock(&uap->port);
        status = pl011_read(uap, REG_RIS) & uap->im;
        if (status) {
                do {
@@ -1573,7 +1569,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
                handled = 1;
        }
 
-       uart_port_unlock_irqrestore(&uap->port, flags);
+       uart_unlock_and_check_sysrq(&uap->port);
 
        return IRQ_RETVAL(handled);
 }
@@ -2322,13 +2318,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 
        clk_enable(uap->clk);
 
-       local_irq_save(flags);
-       if (uap->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = uart_port_trylock(&uap->port);
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(&uap->port, &flags);
        else
-               uart_port_lock(&uap->port);
+               uart_port_lock_irqsave(&uap->port, &flags);
 
        /*
         *      First save the CR then disable the interrupts
@@ -2354,8 +2347,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
                pl011_write(old_cr, uap, REG_CR);
 
        if (locked)
-               uart_port_unlock(&uap->port);
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(&uap->port, flags);
 
        clk_disable(uap->clk);
 }
index 8d09ace062e5966660e9a077f5b968ff4c8f7b96..7790cbc57391aaafedc70a33cc24fd1f5da5d54d 100644 (file)
@@ -378,7 +378,7 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)
                up->port.icount.rx++;
                ch = rdata & AR933X_UART_DATA_TX_RX_MASK;
 
-               if (uart_handle_sysrq_char(&up->port, ch))
+               if (uart_prepare_sysrq_char(&up->port, ch))
                        continue;
 
                if ((up->port.ignore_status_mask & AR933X_DUMMY_STATUS_RD) == 0)
@@ -468,7 +468,7 @@ static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id)
                ar933x_uart_tx_chars(up);
        }
 
-       uart_port_unlock(&up->port);
+       uart_unlock_and_check_sysrq(&up->port);
 
        return IRQ_HANDLED;
 }
@@ -627,14 +627,10 @@ static void ar933x_uart_console_write(struct console *co, const char *s,
        unsigned int int_en;
        int locked = 1;
 
-       local_irq_save(flags);
-
-       if (up->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = uart_port_trylock(&up->port);
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(&up->port, &flags);
        else
-               uart_port_lock(&up->port);
+               uart_port_lock_irqsave(&up->port, &flags);
 
        /*
         * First save the IER then disable the interrupts
@@ -654,9 +650,7 @@ static void ar933x_uart_console_write(struct console *co, const char *s,
        ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS);
 
        if (locked)
-               uart_port_unlock(&up->port);
-
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(&up->port, flags);
 }
 
 static int ar933x_uart_console_setup(struct console *co, char *options)
index a3cefa153456df4a4d486b3784a03b99e1a4fc6e..34801a6f300b6841464f5195f9399ebd90b654d1 100644 (file)
@@ -285,10 +285,9 @@ static void bcm_uart_do_rx(struct uart_port *port)
                                flag = TTY_PARITY;
                }
 
-               if (uart_handle_sysrq_char(port, c))
+               if (uart_prepare_sysrq_char(port, c))
                        continue;
 
-
                if ((cstat & port->ignore_status_mask) == 0)
                        tty_insert_flip_char(tty_port, c, flag);
 
@@ -353,7 +352,7 @@ static irqreturn_t bcm_uart_interrupt(int irq, void *dev_id)
                                               estat & UART_EXTINP_DCD_MASK);
        }
 
-       uart_port_unlock(port);
+       uart_unlock_and_check_sysrq(port);
        return IRQ_HANDLED;
 }
 
@@ -703,20 +702,14 @@ static void bcm_console_write(struct console *co, const char *s,
 {
        struct uart_port *port;
        unsigned long flags;
-       int locked;
+       int locked = 1;
 
        port = &ports[co->index];
 
-       local_irq_save(flags);
-       if (port->sysrq) {
-               /* bcm_uart_interrupt() already took the lock */
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = uart_port_trylock(port);
-       } else {
-               uart_port_lock(port);
-               locked = 1;
-       }
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(port, &flags);
+       else
+               uart_port_lock_irqsave(port, &flags);
 
        /* call helper to deal with \r\n */
        uart_console_write(port, s, count, bcm_console_putchar);
@@ -725,8 +718,7 @@ static void bcm_console_write(struct console *co, const char *s,
        wait_for_xmitr(port);
 
        if (locked)
-               uart_port_unlock(port);
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(port, flags);
 }
 
 /*
index 52c87876a88de6b7e43969029947744a91f0e3cf..5426322b5f0ca3f8580880bd9bb86131e676b573 100644 (file)
@@ -837,7 +837,6 @@ static int linflex_probe(struct platform_device *pdev)
                return ret;
 
        sport->dev = &pdev->dev;
-       sport->type = PORT_LINFLEXUART;
        sport->iotype = UPIO_MEM;
        sport->irq = ret;
        sport->ops = &linflex_pops;
index 1eda48964c0b6539f0e6281d121d7b17344549b7..ddbd42c09637cdc9bcc2438367b53e2b4fb8f551 100644 (file)
@@ -395,7 +395,6 @@ static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch)
                 * which in this case is the break signal.
                 */
                if (linestatus & error_mask)  {
-                       linestatus = 0;
                        readb(&ch->ch_cls_uart->txrx);
                        continue;
                }
index ec20329f06036d066c00056a39588dc502e9977d..3e4ac46de1bc3786173c72754e0240965aec183c 100644 (file)
@@ -136,20 +136,16 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
        int locked = 1;
 
        touch_nmi_watchdog();
-       local_irq_save(flags);
-       if (up->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = uart_port_trylock(&up->port);
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(&up->port, &flags);
        else
-               uart_port_lock(&up->port);
+               uart_port_lock_irqsave(&up->port, &flags);
 
        uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar);
        wait_for_xmit_empty(&up->port);
 
        if (locked)
-               uart_port_unlock(&up->port);
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(&up->port, flags);
 }
 
 static int __init lpc32xx_hsuart_console_setup(struct console *co,
@@ -233,8 +229,6 @@ static unsigned int __serial_get_clock_div(unsigned long uartclk,
 
                hsu_rate++;
        }
-       if (hsu_rate > 0xFF)
-               hsu_rate = 0xFF;
 
        return goodrate;
 }
@@ -268,7 +262,8 @@ static void __serial_lpc32xx_rx(struct uart_port *port)
                        tty_insert_flip_char(tport, 0, TTY_FRAME);
                }
 
-               tty_insert_flip_char(tport, (tmp & 0xFF), flag);
+               if (!uart_prepare_sysrq_char(port, tmp & 0xff))
+                       tty_insert_flip_char(tport, (tmp & 0xFF), flag);
 
                tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
        }
@@ -333,7 +328,7 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
                __serial_lpc32xx_tx(port);
        }
 
-       uart_port_unlock(port);
+       uart_unlock_and_check_sysrq(port);
 
        return IRQ_HANDLED;
 }
index 10bf6d75bf9ee7f9ee13a36796a8af5439ac5eb9..14dd9cfaa9f76fc388500a637d171e90739291ea 100644 (file)
@@ -30,6 +30,7 @@
 #define MAX310X_MAJOR                  204
 #define MAX310X_MINOR                  209
 #define MAX310X_UART_NRMAX             16
+#define MAX310X_MAX_PORTS              4 /* Maximum number of UART ports per IC. */
 
 /* MAX310X register definitions */
 #define MAX310X_RHR_REG                        (0x00) /* RX FIFO */
@@ -66,6 +67,7 @@
 #define MAX310X_BRGDIVMSB_REG          (0x1d) /* Baud rate divisor MSB */
 #define MAX310X_CLKSRC_REG             (0x1e) /* Clock source */
 #define MAX310X_REG_1F                 (0x1f)
+#define MAX310X_EXTREG_START           (0x20) /* Only relevant in SPI mode. */
 
 #define MAX310X_REVID_REG              MAX310X_REG_1F /* Revision ID */
 
@@ -73,9 +75,9 @@
 #define MAX310X_GLOBALCMD_REG          MAX310X_REG_1F /* Global Command (WO) */
 
 /* Extended registers */
-#define MAX310X_SPI_REVID_EXTREG       MAX310X_REG_05 /* Revision ID */
-#define MAX310X_I2C_REVID_EXTREG       (0x25) /* Revision ID */
-
+#define MAX310X_REVID_EXTREG           (0x25) /* Revision ID
+                                               * (extended addressing space)
+                                               */
 /* IRQ register bits */
 #define MAX310X_IRQ_LSR_BIT            (1 << 0) /* LSR interrupt */
 #define MAX310X_IRQ_SPCHR_BIT          (1 << 1) /* Special char interrupt */
 #define MAX310X_IRDA_SIR_BIT           (1 << 1) /* SIR mode enable */
 
 /* Flow control trigger level register masks */
-#define MAX310X_FLOWLVL_HALT_MASK      (0x000f) /* Flow control halt level */
-#define MAX310X_FLOWLVL_RES_MASK       (0x00f0) /* Flow control resume level */
+#define MAX310X_FLOWLVL_HALT_MASK      GENMASK(3, 0) /* Flow control halt level */
+#define MAX310X_FLOWLVL_RES_MASK       GENMASK(7, 4) /* Flow control resume level */
 #define MAX310X_FLOWLVL_HALT(words)    ((words / 8) & 0x0f)
 #define MAX310X_FLOWLVL_RES(words)     (((words / 8) & 0x0f) << 4)
 
 /* FIFO interrupt trigger level register masks */
-#define MAX310X_FIFOTRIGLVL_TX_MASK    (0x0f) /* TX FIFO trigger level */
-#define MAX310X_FIFOTRIGLVL_RX_MASK    (0xf0) /* RX FIFO trigger level */
+#define MAX310X_FIFOTRIGLVL_TX_MASK    GENMASK(3, 0) /* TX FIFO trigger level */
+#define MAX310X_FIFOTRIGLVL_RX_MASK    GENMASK(7, 4) /* RX FIFO trigger level */
 #define MAX310X_FIFOTRIGLVL_TX(words)  ((words / 8) & 0x0f)
 #define MAX310X_FIFOTRIGLVL_RX(words)  (((words / 8) & 0x0f) << 4)
 
 #define MAX310X_FLOWCTRL_GPIADDR_BIT   (1 << 2) /* Enables that GPIO inputs
                                                  * are used in conjunction with
                                                  * XOFF2 for definition of
-                                                 * special character */
+                                                 * special character
+                                                 */
 #define MAX310X_FLOWCTRL_SWFLOWEN_BIT  (1 << 3) /* Auto SW flow ctrl enable */
 #define MAX310X_FLOWCTRL_SWFLOW0_BIT   (1 << 4) /* SWFLOW bit 0 */
 #define MAX310X_FLOWCTRL_SWFLOW1_BIT   (1 << 5) /* SWFLOW bit 1
                                                  */
 
 /* PLL configuration register masks */
-#define MAX310X_PLLCFG_PREDIV_MASK     (0x3f) /* PLL predivision value */
-#define MAX310X_PLLCFG_PLLFACTOR_MASK  (0xc0) /* PLL multiplication factor */
+#define MAX310X_PLLCFG_PREDIV_MASK     GENMASK(5, 0) /* PLL predivision value */
+#define MAX310X_PLLCFG_PLLFACTOR_MASK  GENMASK(7, 6) /* PLL multiplication factor */
 
 /* Baud rate generator configuration register bits */
 #define MAX310X_BRGCFG_2XMODE_BIT      (1 << 4) /* Double baud rate */
 
 /* Misc definitions */
 #define MAX310X_FIFO_SIZE              (128)
-#define MAX310x_REV_MASK               (0xf8)
+#define MAX310x_REV_MASK               GENMASK(7, 3)
 #define MAX310X_WRITE_BIT              0x80
 
 /* Port startup definitions */
 
 struct max310x_if_cfg {
        int (*extended_reg_enable)(struct device *dev, bool enable);
-
-       unsigned int rev_id_reg;
+       u8 rev_id_offset;
 };
 
 struct max310x_devtype {
        struct {
                unsigned short min;
                unsigned short max;
-       } slave_addr;
-       char    name[9];
+       } slave_addr; /* Relevant only in I2C mode. */
        int     nr;
+       char    name[9];
        u8      mode1;
-       int     (*detect)(struct device *);
-       void    (*power)(struct uart_port *, int);
+       u8      rev_id_val;
+       u8      rev_id_reg; /* Relevant only if rev_id_val is defined. */
+       u8      power_reg; /* Register address for power/sleep control. */
+       u8      power_bit; /* Bit for sleep or power-off mode (active high). */
 };
 
 struct max310x_one {
@@ -331,62 +335,52 @@ static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val)
        regmap_update_bits(one->regmap, reg, mask, val);
 }
 
-static int max3107_detect(struct device *dev)
+static int max310x_detect(struct device *dev)
 {
        struct max310x_port *s = dev_get_drvdata(dev);
        unsigned int val = 0;
        int ret;
 
-       ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val);
-       if (ret)
-               return ret;
+       /* Check if variant supports REV ID register: */
+       if (s->devtype->rev_id_val) {
+               u8 rev_id_reg = s->devtype->rev_id_reg;
 
-       if (((val & MAX310x_REV_MASK) != MAX3107_REV_ID)) {
-               dev_err(dev,
-                       "%s ID 0x%02x does not match\n", s->devtype->name, val);
-               return -ENODEV;
-       }
-
-       return 0;
-}
+               /* Check if REV ID is in extended addressing space: */
+               if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) {
+                       ret = s->if_cfg->extended_reg_enable(dev, true);
+                       if (ret)
+                               return ret;
 
-static int max3108_detect(struct device *dev)
-{
-       struct max310x_port *s = dev_get_drvdata(dev);
-       unsigned int val = 0;
-       int ret;
-
-       /* MAX3108 have not REV ID register, we just check default value
-        * from clocksource register to make sure everything works.
-        */
-       ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
-       if (ret)
-               return ret;
-
-       if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT)) {
-               dev_err(dev, "%s not present\n", s->devtype->name);
-               return -ENODEV;
-       }
+                       /* Adjust REV ID extended addressing space address: */
+                       if (s->if_cfg->rev_id_offset)
+                               rev_id_reg -= s->if_cfg->rev_id_offset;
+               }
 
-       return 0;
-}
+               regmap_read(s->regmap, rev_id_reg, &val);
 
-static int max3109_detect(struct device *dev)
-{
-       struct max310x_port *s = dev_get_drvdata(dev);
-       unsigned int val = 0;
-       int ret;
-
-       ret = s->if_cfg->extended_reg_enable(dev, true);
-       if (ret)
-               return ret;
+               if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) {
+                       ret = s->if_cfg->extended_reg_enable(dev, false);
+                       if (ret)
+                               return ret;
+               }
 
-       regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
-       s->if_cfg->extended_reg_enable(dev, false);
-       if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) {
-               dev_err(dev,
-                       "%s ID 0x%02x does not match\n", s->devtype->name, val);
-               return -ENODEV;
+               if (((val & MAX310x_REV_MASK) != s->devtype->rev_id_val))
+                       return dev_err_probe(dev, -ENODEV,
+                                            "%s ID 0x%02x does not match\n",
+                                            s->devtype->name, val);
+       } else {
+               /*
+                * For variant without REV ID register, just check default value
+                * from clocksource register to make sure everything works.
+                */
+               ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
+               if (ret)
+                       return ret;
+
+               if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT))
+                       return dev_err_probe(dev, -ENODEV,
+                                            "%s not present\n",
+                                            s->devtype->name);
        }
 
        return 0;
@@ -394,39 +388,10 @@ static int max3109_detect(struct device *dev)
 
 static void max310x_power(struct uart_port *port, int on)
 {
-       max310x_port_update(port, MAX310X_MODE1_REG,
-                           MAX310X_MODE1_FORCESLEEP_BIT,
-                           on ? 0 : MAX310X_MODE1_FORCESLEEP_BIT);
-       if (on)
-               msleep(50);
-}
-
-static int max14830_detect(struct device *dev)
-{
-       struct max310x_port *s = dev_get_drvdata(dev);
-       unsigned int val = 0;
-       int ret;
-
-       ret = s->if_cfg->extended_reg_enable(dev, true);
-       if (ret)
-               return ret;
-
-       regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
-       s->if_cfg->extended_reg_enable(dev, false);
-       if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) {
-               dev_err(dev,
-                       "%s ID 0x%02x does not match\n", s->devtype->name, val);
-               return -ENODEV;
-       }
-
-       return 0;
-}
+       struct max310x_port *s = dev_get_drvdata(port->dev);
 
-static void max14830_power(struct uart_port *port, int on)
-{
-       max310x_port_update(port, MAX310X_BRGCFG_REG,
-                           MAX14830_BRGCFG_CLKDIS_BIT,
-                           on ? 0 : MAX14830_BRGCFG_CLKDIS_BIT);
+       max310x_port_update(port, s->devtype->power_reg, s->devtype->power_bit,
+                           on ? 0 : s->devtype->power_bit);
        if (on)
                msleep(50);
 }
@@ -435,8 +400,10 @@ static const struct max310x_devtype max3107_devtype = {
        .name   = "MAX3107",
        .nr     = 1,
        .mode1  = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT,
-       .detect = max3107_detect,
-       .power  = max310x_power,
+       .rev_id_val = MAX3107_REV_ID,
+       .rev_id_reg = MAX310X_REVID_REG,
+       .power_reg = MAX310X_MODE1_REG,
+       .power_bit = MAX310X_MODE1_FORCESLEEP_BIT,
        .slave_addr     = {
                .min = 0x2c,
                .max = 0x2f,
@@ -447,8 +414,10 @@ static const struct max310x_devtype max3108_devtype = {
        .name   = "MAX3108",
        .nr     = 1,
        .mode1  = MAX310X_MODE1_AUTOSLEEP_BIT,
-       .detect = max3108_detect,
-       .power  = max310x_power,
+       .rev_id_val = 0, /* Unsupported. */
+       .rev_id_reg = 0, /* Irrelevant when rev_id_val is not defined. */
+       .power_reg = MAX310X_MODE1_REG,
+       .power_bit = MAX310X_MODE1_FORCESLEEP_BIT,
        .slave_addr     = {
                .min = 0x60,
                .max = 0x6f,
@@ -459,8 +428,10 @@ static const struct max310x_devtype max3109_devtype = {
        .name   = "MAX3109",
        .nr     = 2,
        .mode1  = MAX310X_MODE1_AUTOSLEEP_BIT,
-       .detect = max3109_detect,
-       .power  = max310x_power,
+       .rev_id_val = MAX3109_REV_ID,
+       .rev_id_reg = MAX310X_REVID_EXTREG,
+       .power_reg = MAX310X_MODE1_REG,
+       .power_bit = MAX310X_MODE1_FORCESLEEP_BIT,
        .slave_addr     = {
                .min = 0x60,
                .max = 0x6f,
@@ -471,8 +442,10 @@ static const struct max310x_devtype max14830_devtype = {
        .name   = "MAX14830",
        .nr     = 4,
        .mode1  = MAX310X_MODE1_IRQSEL_BIT,
-       .detect = max14830_detect,
-       .power  = max14830_power,
+       .rev_id_val = MAX14830_REV_ID,
+       .rev_id_reg = MAX310X_REVID_EXTREG,
+       .power_reg = MAX310X_BRGCFG_REG,
+       .power_bit = MAX14830_BRGCFG_CLKDIS_BIT,
        .slave_addr     = {
                .min = 0x60,
                .max = 0x6f,
@@ -490,10 +463,8 @@ static bool max310x_reg_writeable(struct device *dev, unsigned int reg)
        case MAX310X_RXFIFOLVL_REG:
                return false;
        default:
-               break;
+               return true;
        }
-
-       return true;
 }
 
 static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
@@ -512,10 +483,8 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
        case MAX310X_REG_1F:
                return true;
        default:
-               break;
+               return false;
        }
-
-       return false;
 }
 
 static bool max310x_reg_precious(struct device *dev, unsigned int reg)
@@ -527,10 +496,8 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
        case MAX310X_STS_IRQSTS_REG:
                return true;
        default:
-               break;
+               return false;
        }
-
-       return false;
 }
 
 static bool max310x_reg_noinc(struct device *dev, unsigned int reg)
@@ -689,7 +656,8 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
        u8 ch, flag;
 
        if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) {
-               /* We are just reading, happily ignoring any error conditions.
+               /*
+                * We are just reading, happily ignoring any error conditions.
                 * Break condition, parity checking, framing errors -- they
                 * are all ignored. That means that we can do a batch-read.
                 *
@@ -698,7 +666,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
                 * that the LSR register applies to the "current" character.
                 * That's also the reason why we cannot do batched reads when
                 * asked to check the individual statuses.
-                * */
+                */
 
                sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
                max310x_batch_read(port, one->rx_buf, rxlen);
@@ -802,8 +770,10 @@ static void max310x_handle_tx(struct uart_port *port)
                to_send = (to_send > txlen) ? txlen : to_send;
 
                if (until_end < to_send) {
-                       /* It's a circ buffer -- wrap around.
-                        * We could do that in one SPI transaction, but meh. */
+                       /*
+                        * It's a circ buffer -- wrap around.
+                        * We could do that in one SPI transaction, but meh.
+                        */
                        max310x_batch_write(port, xmit->buf + xmit->tail, until_end);
                        max310x_batch_write(port, xmit->buf, to_send - until_end);
                } else {
@@ -848,6 +818,7 @@ static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno)
                if (ists & MAX310X_IRQ_TXEMPTY_BIT)
                        max310x_start_tx(port);
        } while (1);
+
        return res;
 }
 
@@ -892,7 +863,8 @@ static unsigned int max310x_tx_empty(struct uart_port *port)
 
 static unsigned int max310x_get_mctrl(struct uart_port *port)
 {
-       /* DCD and DSR are not wired and CTS/RTS is handled automatically
+       /*
+        * DCD and DSR are not wired and CTS/RTS is handled automatically
         * so just indicate DSR and CAR asserted
         */
        return TIOCM_DSR | TIOCM_CAR;
@@ -984,7 +956,8 @@ static void max310x_set_termios(struct uart_port *port,
        max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]);
        max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]);
 
-       /* Disable transmitter before enabling AutoCTS or auto transmitter
+       /*
+        * Disable transmitter before enabling AutoCTS or auto transmitter
         * flow control
         */
        if (termios->c_cflag & CRTSCTS || termios->c_iflag & IXOFF) {
@@ -1011,7 +984,8 @@ static void max310x_set_termios(struct uart_port *port,
        }
        max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow);
 
-       /* Enable transmitter after disabling AutoCTS and auto transmitter
+       /*
+        * Enable transmitter after disabling AutoCTS and auto transmitter
         * flow control
         */
        if (!(termios->c_cflag & CRTSCTS) && !(termios->c_iflag & IXOFF)) {
@@ -1072,10 +1046,9 @@ static int max310x_rs485_config(struct uart_port *port, struct ktermios *termios
 
 static int max310x_startup(struct uart_port *port)
 {
-       struct max310x_port *s = dev_get_drvdata(port->dev);
        unsigned int val;
 
-       s->devtype->power(port, 1);
+       max310x_power(port, 1);
 
        /* Configure MODE1 register */
        max310x_port_update(port, MAX310X_MODE1_REG,
@@ -1103,8 +1076,11 @@ static int max310x_startup(struct uart_port *port)
                                            MAX310X_MODE2_ECHOSUPR_BIT);
        }
 
-       /* Configure flow control levels */
-       /* Flow control halt level 96, resume level 48 */
+       /*
+        * Configure flow control levels:
+        *   resume: 48
+        *   halt:   96
+        */
        max310x_port_write(port, MAX310X_FLOWLVL_REG,
                           MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96));
 
@@ -1120,12 +1096,10 @@ static int max310x_startup(struct uart_port *port)
 
 static void max310x_shutdown(struct uart_port *port)
 {
-       struct max310x_port *s = dev_get_drvdata(port->dev);
-
        /* Disable all interrupts */
        max310x_port_write(port, MAX310X_IRQEN_REG, 0);
 
-       s->devtype->power(port, 0);
+       max310x_power(port, 0);
 }
 
 static const char *max310x_type(struct uart_port *port)
@@ -1187,7 +1161,7 @@ static int __maybe_unused max310x_suspend(struct device *dev)
 
        for (i = 0; i < s->devtype->nr; i++) {
                uart_suspend_port(&max310x_uart, &s->p[i].port);
-               s->devtype->power(&s->p[i].port, 0);
+               max310x_power(&s->p[i].port, 0);
        }
 
        return 0;
@@ -1199,7 +1173,7 @@ static int __maybe_unused max310x_resume(struct device *dev)
        int i;
 
        for (i = 0; i < s->devtype->nr; i++) {
-               s->devtype->power(&s->p[i].port, 1);
+               max310x_power(&s->p[i].port, 1);
                uart_resume_port(&max310x_uart, &s->p[i].port);
        }
 
@@ -1209,7 +1183,7 @@ static int __maybe_unused max310x_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
 
 #ifdef CONFIG_GPIOLIB
-static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
+static int max310x_gpio_get(struct gpio_chip *chip, unsigned int offset)
 {
        unsigned int val;
        struct max310x_port *s = gpiochip_get_data(chip);
@@ -1220,7 +1194,7 @@ static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
        return !!((val >> 4) & (1 << (offset % 4)));
 }
 
-static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static void max310x_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
 {
        struct max310x_port *s = gpiochip_get_data(chip);
        struct uart_port *port = &s->p[offset / 4].port;
@@ -1229,7 +1203,7 @@ static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
                            value ? 1 << (offset % 4) : 0);
 }
 
-static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
 {
        struct max310x_port *s = gpiochip_get_data(chip);
        struct uart_port *port = &s->p[offset / 4].port;
@@ -1240,7 +1214,7 @@ static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 }
 
 static int max310x_gpio_direction_output(struct gpio_chip *chip,
-                                        unsigned offset, int value)
+                                        unsigned int offset, int value)
 {
        struct max310x_port *s = gpiochip_get_data(chip);
        struct uart_port *port = &s->p[offset / 4].port;
@@ -1296,10 +1270,9 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
 
        /* Alloc port structure */
        s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL);
-       if (!s) {
-               dev_err(dev, "Error allocating port structure\n");
-               return -ENOMEM;
-       }
+       if (!s)
+               return dev_err_probe(dev, -ENOMEM,
+                                    "Error allocating port structure\n");
 
        /* Always ask for fixed clock rate from a property. */
        device_property_read_u32(dev, "clock-frequency", &uartclk);
@@ -1320,8 +1293,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
        if (freq == 0)
                freq = uartclk;
        if (freq == 0) {
-               dev_err(dev, "Cannot get clock rate\n");
-               ret = -EINVAL;
+               ret = dev_err_probe(dev, -EINVAL, "Cannot get clock rate\n");
                goto out_clk;
        }
 
@@ -1345,7 +1317,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
        dev_set_drvdata(dev, s);
 
        /* Check device to ensure we are talking to what we expect */
-       ret = devtype->detect(dev);
+       ret = max310x_detect(dev);
        if (ret)
                goto out_clk;
 
@@ -1427,14 +1399,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
 
                /* Register port */
                ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
-               if (ret) {
-                       s->p[i].port.dev = NULL;
+               if (ret)
                        goto out_uart;
-               }
+
                set_bit(line, max310x_lines);
 
                /* Go to suspend mode */
-               devtype->power(&s->p[i].port, 0);
+               max310x_power(&s->p[i].port, 0);
        }
 
 #ifdef CONFIG_GPIOLIB
@@ -1461,14 +1432,12 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
        if (!ret)
                return 0;
 
-       dev_err(dev, "Unable to reguest IRQ %i\n", irq);
+       dev_err(dev, "Unable to request IRQ %i\n", irq);
 
 out_uart:
        for (i = 0; i < devtype->nr; i++) {
-               if (s->p[i].port.dev) {
+               if (test_and_clear_bit(s->p[i].port.line, max310x_lines))
                        uart_remove_one_port(&max310x_uart, &s->p[i].port);
-                       clear_bit(s->p[i].port.line, max310x_lines);
-               }
        }
 
 out_clk:
@@ -1486,9 +1455,11 @@ static void max310x_remove(struct device *dev)
                cancel_work_sync(&s->p[i].tx_work);
                cancel_work_sync(&s->p[i].md_work);
                cancel_work_sync(&s->p[i].rs_work);
-               uart_remove_one_port(&max310x_uart, &s->p[i].port);
-               clear_bit(s->p[i].port.line, max310x_lines);
-               s->devtype->power(&s->p[i].port, 0);
+
+               if (test_and_clear_bit(s->p[i].port.line, max310x_lines))
+                       uart_remove_one_port(&max310x_uart, &s->p[i].port);
+
+               max310x_power(&s->p[i].port, 0);
        }
 
        clk_disable_unprepare(s->clk);
@@ -1518,6 +1489,19 @@ static struct regmap_config regcfg = {
        .max_raw_write = MAX310X_FIFO_SIZE,
 };
 
+static const char *max310x_regmap_name(u8 port_id)
+{
+       switch (port_id) {
+       case 0: return "port0";
+       case 1: return "port1";
+       case 2: return "port2";
+       case 3: return "port3";
+       default:
+               WARN_ON(true);
+               return NULL;
+       }
+}
+
 #ifdef CONFIG_SPI_MASTER
 static int max310x_spi_extended_reg_enable(struct device *dev, bool enable)
 {
@@ -1529,13 +1513,13 @@ static int max310x_spi_extended_reg_enable(struct device *dev, bool enable)
 
 static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = {
        .extended_reg_enable = max310x_spi_extended_reg_enable,
-       .rev_id_reg = MAX310X_SPI_REVID_EXTREG,
+       .rev_id_offset = MAX310X_EXTREG_START,
 };
 
 static int max310x_spi_probe(struct spi_device *spi)
 {
        const struct max310x_devtype *devtype;
-       struct regmap *regmaps[4];
+       struct regmap *regmaps[MAX310X_MAX_PORTS];
        unsigned int i;
        int ret;
 
@@ -1547,12 +1531,14 @@ static int max310x_spi_probe(struct spi_device *spi)
        if (ret)
                return ret;
 
-       devtype = device_get_match_data(&spi->dev);
+       devtype = spi_get_device_match_data(spi);
        if (!devtype)
-               devtype = (struct max310x_devtype *)spi_get_device_id(spi)->driver_data;
+               return dev_err_probe(&spi->dev, -ENODEV, "Failed to match device\n");
 
        for (i = 0; i < devtype->nr; i++) {
                u8 port_mask = i * 0x20;
+
+               regcfg.name = max310x_regmap_name(i);
                regcfg.read_flag_mask = port_mask;
                regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT;
                regmaps[i] = devm_regmap_init_spi(spi, &regcfg);
@@ -1600,7 +1586,7 @@ static struct regmap_config regcfg_i2c = {
        .writeable_reg = max310x_reg_writeable,
        .volatile_reg = max310x_reg_volatile,
        .precious_reg = max310x_reg_precious,
-       .max_register = MAX310X_I2C_REVID_EXTREG,
+       .max_register = MAX310X_REVID_EXTREG,
        .writeable_noinc_reg = max310x_reg_noinc,
        .readable_noinc_reg = max310x_reg_noinc,
        .max_raw_read = MAX310X_FIFO_SIZE,
@@ -1609,7 +1595,7 @@ static struct regmap_config regcfg_i2c = {
 
 static const struct max310x_if_cfg max310x_i2c_if_cfg = {
        .extended_reg_enable = max310x_i2c_extended_reg_enable,
-       .rev_id_reg = MAX310X_I2C_REVID_EXTREG,
+       .rev_id_offset = 0, /* No offset in I2C mode. */
 };
 
 static unsigned short max310x_i2c_slave_addr(unsigned short addr,
@@ -1619,10 +1605,10 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr,
         * For MAX14830 and MAX3109, the slave address depends on what the
         * A0 and A1 pins are tied to.
         * See Table I2C Address Map of the datasheet.
-        * Based on that table, the following formulas were determined.
-        * UART1 - UART0 = 0x10
-        * UART2 - UART1 = 0x20 + 0x10
-        * UART3 - UART2 = 0x10
+        * Based on that table, the following formulas were determined:
+        *   UART1 - UART0 = 0x10
+        *   UART2 - UART1 = 0x20 + 0x10
+        *   UART3 - UART2 = 0x10
         */
 
        addr -= nr * 0x10;
@@ -1635,20 +1621,24 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr,
 
 static int max310x_i2c_probe(struct i2c_client *client)
 {
-       const struct max310x_devtype *devtype =
-                       device_get_match_data(&client->dev);
+       const struct max310x_devtype *devtype;
        struct i2c_client *port_client;
-       struct regmap *regmaps[4];
+       struct regmap *regmaps[MAX310X_MAX_PORTS];
        unsigned int i;
        u8 port_addr;
 
+       devtype = i2c_get_match_data(client);
+       if (!devtype)
+               return dev_err_probe(&client->dev, -ENODEV, "Failed to match device\n");
+
        if (client->addr < devtype->slave_addr.min ||
-               client->addr > devtype->slave_addr.max)
+           client->addr > devtype->slave_addr.max)
                return dev_err_probe(&client->dev, -EINVAL,
                                     "Slave addr 0x%x outside of range [0x%x, 0x%x]\n",
                                     client->addr, devtype->slave_addr.min,
                                     devtype->slave_addr.max);
 
+       regcfg_i2c.name = max310x_regmap_name(0);
        regmaps[0] = devm_regmap_init_i2c(client, &regcfg_i2c);
 
        for (i = 1; i < devtype->nr; i++) {
@@ -1657,6 +1647,7 @@ static int max310x_i2c_probe(struct i2c_client *client)
                                                        client->adapter,
                                                        port_addr);
 
+               regcfg_i2c.name = max310x_regmap_name(i);
                regmaps[i] = devm_regmap_init_i2c(port_client, &regcfg_i2c);
        }
 
@@ -1669,6 +1660,15 @@ static void max310x_i2c_remove(struct i2c_client *client)
        max310x_remove(&client->dev);
 }
 
+static const struct i2c_device_id max310x_i2c_id_table[] = {
+       { "max3107",    (kernel_ulong_t)&max3107_devtype, },
+       { "max3108",    (kernel_ulong_t)&max3108_devtype, },
+       { "max3109",    (kernel_ulong_t)&max3109_devtype, },
+       { "max14830",   (kernel_ulong_t)&max14830_devtype, },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max310x_i2c_id_table);
+
 static struct i2c_driver max310x_i2c_driver = {
        .driver = {
                .name           = MAX310X_NAME,
@@ -1677,6 +1677,7 @@ static struct i2c_driver max310x_i2c_driver = {
        },
        .probe          = max310x_i2c_probe,
        .remove         = max310x_i2c_remove,
+       .id_table       = max310x_i2c_id_table,
 };
 #endif
 
index 8690a45239e096a14bfa4d4cc6a5cea16c0a9cdd..b0604d6da0257934581368033d4b3b88cb92a4b4 100644 (file)
@@ -470,33 +470,6 @@ static struct mcf_uart mcf_ports[4];
 #if defined(CONFIG_SERIAL_MCF_CONSOLE)
 /****************************************************************************/
 
-int __init early_mcf_setup(struct mcf_platform_uart *platp)
-{
-       struct uart_port *port;
-       int i;
-
-       for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
-               port = &mcf_ports[i].port;
-
-               port->line = i;
-               port->type = PORT_MCF;
-               port->mapbase = platp[i].mapbase;
-               port->membase = (platp[i].membase) ? platp[i].membase :
-                       (unsigned char __iomem *) port->mapbase;
-               port->iotype = SERIAL_IO_MEM;
-               port->irq = platp[i].irq;
-               port->uartclk = MCF_BUSCLK;
-               port->flags = UPF_BOOT_AUTOCONF;
-               port->rs485_config = mcf_config_rs485;
-               port->rs485_supported = mcf_rs485_supported;
-               port->ops = &mcf_uart_ops;
-       }
-
-       return 0;
-}
-
-/****************************************************************************/
-
 static void mcf_console_putc(struct console *co, const char c)
 {
        struct uart_port *port = &(mcf_ports + co->index)->port;
index 8395688f5ee926f92a2345ab1735c2b9058d7a06..6feac459c0cf4f7a2b6fff658023205d9fa81d78 100644 (file)
@@ -220,7 +220,7 @@ static void meson_receive_chars(struct uart_port *port)
                                continue;
                }
 
-               if (uart_handle_sysrq_char(port, ch))
+               if (uart_prepare_sysrq_char(port, ch))
                        continue;
 
                if ((status & port->ignore_status_mask) == 0)
@@ -248,7 +248,7 @@ static irqreturn_t meson_uart_interrupt(int irq, void *dev_id)
                        meson_uart_start_tx(port);
        }
 
-       uart_port_unlock(port);
+       uart_unlock_and_check_sysrq(port);
 
        return IRQ_HANDLED;
 }
@@ -556,18 +556,13 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
                                    u_int count)
 {
        unsigned long flags;
-       int locked;
+       int locked = 1;
        u32 val, tmp;
 
-       local_irq_save(flags);
-       if (port->sysrq) {
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = uart_port_trylock(port);
-       } else {
-               uart_port_lock(port);
-               locked = 1;
-       }
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(port, &flags);
+       else
+               uart_port_lock_irqsave(port, &flags);
 
        val = readl(port->membase + AML_UART_CONTROL);
        tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN);
@@ -577,8 +572,7 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
        writel(val, port->membase + AML_UART_CONTROL);
 
        if (locked)
-               uart_port_unlock(port);
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(port, flags);
 }
 
 static void meson_serial_console_write(struct console *co, const char *s,
index e24204ad35deff4b2911f4e247071aae90c615d9..d27c4c8c84e130c3336cd3b5f3e5dd9a9536afed 100644 (file)
@@ -588,16 +588,14 @@ static void msm_complete_rx_dma(void *args)
                if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK))
                        flag = TTY_NORMAL;
 
-               uart_port_unlock_irqrestore(port, flags);
-               sysrq = uart_handle_sysrq_char(port, dma->virt[i]);
-               uart_port_lock_irqsave(port, &flags);
+               sysrq = uart_prepare_sysrq_char(port, dma->virt[i]);
                if (!sysrq)
                        tty_insert_flip_char(tport, dma->virt[i], flag);
        }
 
        msm_start_rx_dma(msm_port);
 done:
-       uart_port_unlock_irqrestore(port, flags);
+       uart_unlock_and_check_sysrq_irqrestore(port, flags);
 
        if (count)
                tty_flip_buffer_push(tport);
@@ -763,9 +761,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
                        if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK))
                                flag = TTY_NORMAL;
 
-                       uart_port_unlock(port);
-                       sysrq = uart_handle_sysrq_char(port, buf[i]);
-                       uart_port_lock(port);
+                       sysrq = uart_prepare_sysrq_char(port, buf[i]);
                        if (!sysrq)
                                tty_insert_flip_char(tport, buf[i], flag);
                }
@@ -825,9 +821,7 @@ static void msm_handle_rx(struct uart_port *port)
                else if (sr & MSM_UART_SR_PAR_FRAME_ERR)
                        flag = TTY_FRAME;
 
-               uart_port_unlock(port);
-               sysrq = uart_handle_sysrq_char(port, c);
-               uart_port_lock(port);
+               sysrq = uart_prepare_sysrq_char(port, c);
                if (!sysrq)
                        tty_insert_flip_char(tport, c, flag);
        }
@@ -948,11 +942,10 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id)
        struct uart_port *port = dev_id;
        struct msm_port *msm_port = to_msm_port(port);
        struct msm_dma *dma = &msm_port->rx_dma;
-       unsigned long flags;
        unsigned int misr;
        u32 val;
 
-       uart_port_lock_irqsave(port, &flags);
+       uart_port_lock(port);
        misr = msm_read(port, MSM_UART_MISR);
        msm_write(port, 0, MSM_UART_IMR); /* disable interrupt */
 
@@ -984,7 +977,7 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id)
                msm_handle_delta_cts(port);
 
        msm_write(port, msm_port->imr, MSM_UART_IMR); /* restore interrupt */
-       uart_port_unlock_irqrestore(port, flags);
+       uart_unlock_and_check_sysrq(port);
 
        return IRQ_HANDLED;
 }
@@ -1621,14 +1614,10 @@ 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)
-               locked = uart_port_trylock(port);
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(port, &flags);
        else
-               uart_port_lock(port);
+               uart_port_lock_irqsave(port, &flags);
 
        if (is_uartdm)
                msm_reset_dm_count(port, count);
@@ -1667,9 +1656,7 @@ static void __msm_console_write(struct uart_port *port, const char *s,
        }
 
        if (locked)
-               uart_port_unlock(port);
-
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(port, flags);
 }
 
 static void msm_console_write(struct console *co, const char *s,
index f5a0b401af63b15c5c8a8d49ec2742a6ce58e263..9be1c871cf116dc43f150a130d8d2777b3f02454 100644 (file)
@@ -508,7 +508,7 @@ static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)
 
        up->port.icount.rx++;
 
-       if (uart_handle_sysrq_char(&up->port, ch))
+       if (uart_prepare_sysrq_char(&up->port, ch))
                return;
 
        uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, TTY_NORMAL);
@@ -563,7 +563,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
                }
        } while (max_count--);
 
-       uart_port_unlock(&up->port);
+       uart_unlock_and_check_sysrq(&up->port);
 
        tty_flip_buffer_push(&up->port.state->port);
 
@@ -1212,13 +1212,10 @@ serial_omap_console_write(struct console *co, const char *s,
        unsigned int ier;
        int locked = 1;
 
-       local_irq_save(flags);
-       if (up->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = uart_port_trylock(&up->port);
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(&up->port, &flags);
        else
-               uart_port_lock(&up->port);
+               uart_port_lock_irqsave(&up->port, &flags);
 
        /*
         * First save the IER then disable the interrupts
@@ -1245,8 +1242,7 @@ serial_omap_console_write(struct console *co, const char *s,
                check_modem_status(up);
 
        if (locked)
-               uart_port_unlock(&up->port);
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(&up->port, flags);
 }
 
 static int __init
index d9fe85397741dd7813571133ad85d928566f0783..8b60ac0ad7cd341f0415fab558f3d5d2892d68e5 100644 (file)
@@ -199,6 +199,7 @@ static void owl_uart_receive_chars(struct uart_port *port)
        stat = owl_uart_read(port, OWL_UART_STAT);
        while (!(stat & OWL_UART_STAT_RFEM)) {
                char flag = TTY_NORMAL;
+               bool sysrq;
 
                if (stat & OWL_UART_STAT_RXER)
                        port->icount.overrun++;
@@ -217,7 +218,9 @@ static void owl_uart_receive_chars(struct uart_port *port)
                val = owl_uart_read(port, OWL_UART_RXDAT);
                val &= 0xff;
 
-               if ((stat & port->ignore_status_mask) == 0)
+               sysrq = uart_prepare_sysrq_char(port, val);
+
+               if (!sysrq && (stat & port->ignore_status_mask) == 0)
                        tty_insert_flip_char(&port->state->port, val, flag);
 
                stat = owl_uart_read(port, OWL_UART_STAT);
@@ -229,10 +232,9 @@ static void owl_uart_receive_chars(struct uart_port *port)
 static irqreturn_t owl_uart_irq(int irq, void *dev_id)
 {
        struct uart_port *port = dev_id;
-       unsigned long flags;
        u32 stat;
 
-       uart_port_lock_irqsave(port, &flags);
+       uart_port_lock(port);
 
        stat = owl_uart_read(port, OWL_UART_STAT);
 
@@ -246,7 +248,7 @@ static irqreturn_t owl_uart_irq(int irq, void *dev_id)
        stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP;
        owl_uart_write(port, stat, OWL_UART_STAT);
 
-       uart_port_unlock_irqrestore(port, flags);
+       uart_unlock_and_check_sysrq(port);
 
        return IRQ_HANDLED;
 }
@@ -508,18 +510,12 @@ static void owl_uart_port_write(struct uart_port *port, const char *s,
 {
        u32 old_ctl, val;
        unsigned long flags;
-       int locked;
+       int locked = 1;
 
-       local_irq_save(flags);
-
-       if (port->sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = uart_port_trylock(port);
-       else {
-               uart_port_lock(port);
-               locked = 1;
-       }
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(port, &flags);
+       else
+               uart_port_lock_irqsave(port, &flags);
 
        old_ctl = owl_uart_read(port, OWL_UART_CTL);
        val = old_ctl | OWL_UART_CTL_TRFS_TX;
@@ -541,9 +537,7 @@ static void owl_uart_port_write(struct uart_port *port, const char *s,
        owl_uart_write(port, old_ctl, OWL_UART_CTL);
 
        if (locked)
-               uart_port_unlock(port);
-
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(port, flags);
 }
 
 static void owl_uart_console_write(struct console *co, const char *s,
index 436cc6d52a11bfa53eeb4db1b22ed5cea57eecdf..89257cddf540503d3d41a3d2de74f35e81486192 100644 (file)
@@ -237,9 +237,6 @@ struct eg20t_port {
 
 #define IRQ_NAME_SIZE 17
        char                            irq_name[IRQ_NAME_SIZE];
-
-       /* protect the eg20t_port private structure and io access to membase */
-       spinlock_t lock;
 };
 
 /**
@@ -567,7 +564,7 @@ static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
                        if (uart_handle_break(port))
                                continue;
                }
-               if (uart_handle_sysrq_char(port, rbr))
+               if (uart_prepare_sysrq_char(port, rbr))
                        continue;
 
                buf[i++] = rbr;
@@ -599,16 +596,14 @@ static void pch_uart_hal_set_break(struct eg20t_port *priv, int on)
        iowrite8(lcr, priv->membase + UART_LCR);
 }
 
-static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
-                  int size)
+static void push_rx(struct eg20t_port *priv, const unsigned char *buf,
+                   int size)
 {
        struct uart_port *port = &priv->port;
        struct tty_port *tport = &port->state->port;
 
        tty_insert_flip_string(tport, buf, size);
        tty_flip_buffer_push(tport);
-
-       return 0;
 }
 
 static int dma_push_rx(struct eg20t_port *priv, int size)
@@ -761,7 +756,7 @@ static int handle_rx_to(struct eg20t_port *priv)
 {
        struct pch_uart_buffer *buf;
        int rx_size;
-       int ret;
+
        if (!priv->start_rx) {
                pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT |
                                                     PCH_UART_HAL_RX_ERR_INT);
@@ -770,19 +765,12 @@ static int handle_rx_to(struct eg20t_port *priv)
        buf = &priv->rxbuf;
        do {
                rx_size = pch_uart_hal_read(priv, buf->buf, buf->size);
-               ret = push_rx(priv, buf->buf, rx_size);
-               if (ret)
-                       return 0;
+               push_rx(priv, buf->buf, rx_size);
        } while (rx_size == buf->size);
 
        return PCH_UART_HANDLED_RX_INT;
 }
 
-static int handle_rx(struct eg20t_port *priv)
-{
-       return handle_rx_to(priv);
-}
-
 static int dma_handle_rx(struct eg20t_port *priv)
 {
        struct uart_port *port = &priv->port;
@@ -1019,11 +1007,10 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
        u8 lsr;
        int ret = 0;
        unsigned char iid;
-       unsigned long flags;
        int next = 1;
        u8 msr;
 
-       spin_lock_irqsave(&priv->lock, flags);
+       uart_port_lock(&priv->port);
        handled = 0;
        while (next) {
                iid = pch_uart_hal_get_iid(priv);
@@ -1051,7 +1038,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
                                                PCH_UART_HAL_RX_INT |
                                                PCH_UART_HAL_RX_ERR_INT);
                        } else {
-                               ret = handle_rx(priv);
+                               ret = handle_rx_to(priv);
                        }
                        break;
                case PCH_UART_IID_RDR_TO:       /* Received Data Ready
@@ -1083,7 +1070,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
                handled |= (unsigned int)ret;
        }
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       uart_unlock_and_check_sysrq(&priv->port);
        return IRQ_RETVAL(handled);
 }
 
@@ -1194,9 +1181,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl)
        unsigned long flags;
 
        priv = container_of(port, struct eg20t_port, port);
-       spin_lock_irqsave(&priv->lock, flags);
+       uart_port_lock_irqsave(&priv->port, &flags);
        pch_uart_hal_set_break(priv, ctl);
-       spin_unlock_irqrestore(&priv->lock, flags);
+       uart_port_unlock_irqrestore(&priv->port, flags);
 }
 
 /* Grab any interrupt resources and initialise any low level driver state. */
@@ -1346,8 +1333,7 @@ static void pch_uart_set_termios(struct uart_port *port,
 
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
 
-       spin_lock_irqsave(&priv->lock, flags);
-       uart_port_lock(port);
+       uart_port_lock_irqsave(port, &flags);
 
        uart_update_timeout(port, termios->c_cflag, baud);
        rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb);
@@ -1360,8 +1346,7 @@ static void pch_uart_set_termios(struct uart_port *port,
                tty_termios_encode_baud_rate(termios, baud, baud);
 
 out:
-       uart_port_unlock(port);
-       spin_unlock_irqrestore(&priv->lock, flags);
+       uart_port_unlock_irqrestore(port, flags);
 }
 
 static const char *pch_uart_type(struct uart_port *port)
@@ -1565,27 +1550,17 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct eg20t_port *priv;
        unsigned long flags;
-       int priv_locked = 1;
-       int port_locked = 1;
+       int locked = 1;
        u8 ier;
 
        priv = pch_uart_ports[co->index];
 
        touch_nmi_watchdog();
 
-       local_irq_save(flags);
-       if (priv->port.sysrq) {
-               /* call to uart_handle_sysrq_char already took the priv lock */
-               priv_locked = 0;
-               /* serial8250_handle_port() already took the port lock */
-               port_locked = 0;
-       } else if (oops_in_progress) {
-               priv_locked = spin_trylock(&priv->lock);
-               port_locked = uart_port_trylock(&priv->port);
-       } else {
-               spin_lock(&priv->lock);
-               uart_port_lock(&priv->port);
-       }
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(&priv->port, &flags);
+       else
+               uart_port_lock_irqsave(&priv->port, &flags);
 
        /*
         *      First save the IER then disable the interrupts
@@ -1603,11 +1578,8 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
        wait_for_xmitr(priv, UART_LSR_BOTH_EMPTY);
        iowrite8(ier, priv->membase + UART_IER);
 
-       if (port_locked)
-               uart_port_unlock(&priv->port);
-       if (priv_locked)
-               spin_unlock(&priv->lock);
-       local_irq_restore(flags);
+       if (locked)
+               uart_port_unlock_irqrestore(&priv->port, flags);
 }
 
 static int __init pch_console_setup(struct console *co, char *options)
@@ -1704,8 +1676,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
        pci_enable_msi(pdev);
        pci_set_master(pdev);
 
-       spin_lock_init(&priv->lock);
-
        iobase = pci_resource_start(pdev, 0);
        mapbase = pci_resource_start(pdev, 1);
        priv->mapbase = mapbase;
@@ -1735,8 +1705,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
                 KBUILD_MODNAME ":" PCH_UART_DRIVER_DEVICE "%d",
                 priv->port.line);
 
-       spin_lock_init(&priv->port.lock);
-
        pci_set_drvdata(pdev, priv);
        priv->trigger_level = 1;
        priv->fcr = 0;
index 732d821db4f805d539e732367b9ef9df1afb7cc9..05d97e89511e698bee73698edd0a98a58893bb7b 100644 (file)
@@ -1714,18 +1714,13 @@ static int __init pmz_attach(struct platform_device *pdev)
        return uart_add_one_port(&pmz_uart_reg, &uap->port);
 }
 
-static int __exit pmz_detach(struct platform_device *pdev)
+static void __exit pmz_detach(struct platform_device *pdev)
 {
        struct uart_pmac_port *uap = platform_get_drvdata(pdev);
 
-       if (!uap)
-               return -ENODEV;
-
        uart_remove_one_port(&pmz_uart_reg, &uap->port);
 
        uap->port.dev = NULL;
-
-       return 0;
 }
 
 #endif /* !CONFIG_PPC_PMAC */
@@ -1794,7 +1789,7 @@ static struct macio_driver pmz_driver = {
 #else
 
 static struct platform_driver pmz_driver = {
-       .remove         = __exit_p(pmz_detach),
+       .remove_new     = __exit_p(pmz_detach),
        .driver         = {
                .name           = "scc",
        },
index 46e70e155aab210d577ed3df21321df5d0bee823..e395ff29c1a2cfbb3742b2ebeb1545ac850b840d 100644 (file)
@@ -151,7 +151,7 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status)
                                flag = TTY_FRAME;
                }
 
-               if (uart_handle_sysrq_char(&up->port, ch))
+               if (uart_prepare_sysrq_char(&up->port, ch))
                        goto ignore_char;
 
                uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
@@ -232,7 +232,7 @@ static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
        check_modem_status(up);
        if (lsr & UART_LSR_THRE)
                transmit_chars(up);
-       uart_port_unlock(&up->port);
+       uart_unlock_and_check_sysrq(&up->port);
        return IRQ_HANDLED;
 }
 
@@ -604,13 +604,10 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
        int locked = 1;
 
        clk_enable(up->clk);
-       local_irq_save(flags);
-       if (up->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = uart_port_trylock(&up->port);
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(&up->port, &flags);
        else
-               uart_port_lock(&up->port);
+               uart_port_lock_irqsave(&up->port, &flags);
 
        /*
         *      First save the IER then disable the interrupts
@@ -628,10 +625,8 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
        serial_out(up, UART_IER, ier);
 
        if (locked)
-               uart_port_unlock(&up->port);
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(&up->port, flags);
        clk_disable(up->clk);
-
 }
 
 #ifdef CONFIG_CONSOLE_POLL
index 99e08737f293c6868e56d2de80f31bf0e3345ca3..f9f7ac1a10df3d668d41506075359c7601b12185 100644 (file)
@@ -488,18 +488,16 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
 
        geni_status = readl(uport->membase + SE_GENI_STATUS);
 
-       /* Cancel the current write to log the fault */
        if (!locked) {
-               geni_se_cancel_m_cmd(&port->se);
-               if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
-                                               M_CMD_CANCEL_EN, true)) {
-                       geni_se_abort_m_cmd(&port->se);
-                       qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
-                                                       M_CMD_ABORT_EN, true);
-                       writel(M_CMD_ABORT_EN, uport->membase +
-                                                       SE_GENI_M_IRQ_CLEAR);
-               }
-               writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
+               /*
+                * We can only get here if an oops is in progress then we were
+                * unable to get the lock. This means we can't safely access
+                * our state variables like tx_remaining. About the best we
+                * can do is wait for the FIFO to be empty before we start our
+                * transfer, so we'll do that.
+                */
+               qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
+                                         M_TX_FIFO_NOT_EMPTY_EN, false);
        } else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) {
                /*
                 * It seems we can't interrupt existing transfers if all data
@@ -516,11 +514,12 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
 
        __qcom_geni_serial_console_write(uport, s, count);
 
-       if (port->tx_remaining)
-               qcom_geni_serial_setup_tx(uport, port->tx_remaining);
 
-       if (locked)
+       if (locked) {
+               if (port->tx_remaining)
+                       qcom_geni_serial_setup_tx(uport, port->tx_remaining);
                uart_port_unlock_irqrestore(uport, flags);
+       }
 }
 
 static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
index 13deb355cf1bc36509a3c8676bb3aa8eaa11f437..82def9b8632a56102470d3f45f170a4750f3541a 100644 (file)
@@ -394,7 +394,8 @@ static void rda_uart_receive_chars(struct uart_port *port)
                val &= 0xff;
 
                port->icount.rx++;
-               tty_insert_flip_char(&port->state->port, val, flag);
+               if (!uart_prepare_sysrq_char(port, val))
+                       tty_insert_flip_char(&port->state->port, val, flag);
 
                status = rda_uart_read(port, RDA_UART_STATUS);
        }
@@ -405,10 +406,9 @@ static void rda_uart_receive_chars(struct uart_port *port)
 static irqreturn_t rda_interrupt(int irq, void *dev_id)
 {
        struct uart_port *port = dev_id;
-       unsigned long flags;
        u32 val, irq_mask;
 
-       uart_port_lock_irqsave(port, &flags);
+       uart_port_lock(port);
 
        /* Clear IRQ cause */
        val = rda_uart_read(port, RDA_UART_IRQ_CAUSE);
@@ -425,7 +425,7 @@ static irqreturn_t rda_interrupt(int irq, void *dev_id)
                rda_uart_send_chars(port);
        }
 
-       uart_port_unlock_irqrestore(port, flags);
+       uart_unlock_and_check_sysrq(port);
 
        return IRQ_HANDLED;
 }
@@ -590,18 +590,12 @@ static void rda_uart_port_write(struct uart_port *port, const char *s,
 {
        u32 old_irq_mask;
        unsigned long flags;
-       int locked;
-
-       local_irq_save(flags);
+       int locked = 1;
 
-       if (port->sysrq) {
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = uart_port_trylock(port);
-       } else {
-               uart_port_lock(port);
-               locked = 1;
-       }
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(port, &flags);
+       else
+               uart_port_lock_irqsave(port, &flags);
 
        old_irq_mask = rda_uart_read(port, RDA_UART_IRQ_MASK);
        rda_uart_write(port, 0, RDA_UART_IRQ_MASK);
@@ -615,9 +609,7 @@ static void rda_uart_port_write(struct uart_port *port, const char *s,
        rda_uart_write(port, old_irq_mask, RDA_UART_IRQ_MASK);
 
        if (locked)
-               uart_port_unlock(port);
-
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(port, flags);
 }
 
 static void rda_uart_console_write(struct console *co, const char *s,
index 71d17d804fdabb85779a28d866100bbb0325b29e..a2d07e05c50264063983be7e0fe9e0fea80678ca 100644 (file)
  * BJD, 04-Nov-2004
  */
 
-#include <linux/dmaengine.h>
+#include <linux/console.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
 #include <linux/dma-mapping.h>
-#include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
 #include <linux/math.h>
 #include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
+#include <linux/slab.h>
 #include <linux/sysrq.h>
-#include <linux/console.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/serial_s3c.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-#include <linux/of.h>
+#include <linux/types.h>
+
 #include <asm/irq.h>
 
 /* UART name and device definitions */
@@ -73,21 +75,21 @@ struct s3c24xx_uart_info {
        enum s3c24xx_port_type  type;
        unsigned int            port_type;
        unsigned int            fifosize;
-       unsigned long           rx_fifomask;
-       unsigned long           rx_fifoshift;
-       unsigned long           rx_fifofull;
-       unsigned long           tx_fifomask;
-       unsigned long           tx_fifoshift;
-       unsigned long           tx_fifofull;
-       unsigned int            def_clk_sel;
-       unsigned long           num_clks;
-       unsigned long           clksel_mask;
-       unsigned long           clksel_shift;
-       unsigned long           ucon_mask;
+       u32                     rx_fifomask;
+       u32                     rx_fifoshift;
+       u32                     rx_fifofull;
+       u32                     tx_fifomask;
+       u32                     tx_fifoshift;
+       u32                     tx_fifofull;
+       u32                     clksel_mask;
+       u32                     clksel_shift;
+       u32                     ucon_mask;
+       u8                      def_clk_sel;
+       u8                      num_clks;
+       u8                      iotype;
 
        /* uart port features */
-
-       unsigned int            has_divslot:1;
+       bool                    has_divslot;
 };
 
 struct s3c24xx_serial_drv_data {
@@ -196,7 +198,7 @@ static void wr_reg(const struct uart_port *port, u32 reg, u32 val)
 /* Byte-order aware bit setting/clearing functions. */
 
 static inline void s3c24xx_set_bit(const struct uart_port *port, int idx,
-                                  unsigned int reg)
+                                  u32 reg)
 {
        unsigned long flags;
        u32 val;
@@ -209,7 +211,7 @@ static inline void s3c24xx_set_bit(const struct uart_port *port, int idx,
 }
 
 static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx,
-                                    unsigned int reg)
+                                    u32 reg)
 {
        unsigned long flags;
        u32 val;
@@ -233,7 +235,7 @@ static inline const char *s3c24xx_serial_portname(const struct uart_port *port)
        return to_platform_device(port->dev)->name;
 }
 
-static int s3c24xx_serial_txempty_nofifo(const struct uart_port *port)
+static bool s3c24xx_serial_txempty_nofifo(const struct uart_port *port)
 {
        return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
 }
@@ -242,8 +244,8 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port)
 {
        struct s3c24xx_uart_port *ourport = to_ourport(port);
        unsigned long flags;
-       unsigned int ucon, ufcon;
        int count = 10000;
+       u32 ucon, ufcon;
 
        uart_port_lock_irqsave(port, &flags);
 
@@ -266,7 +268,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port)
 {
        struct s3c24xx_uart_port *ourport = to_ourport(port);
        unsigned long flags;
-       unsigned int ucon;
+       u32 ucon;
 
        uart_port_lock_irqsave(port, &flags);
 
@@ -587,8 +589,8 @@ static inline const struct s3c2410_uartcfg
        return ourport->cfg;
 }
 
-static int s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport,
-                                    unsigned long ufstat)
+static unsigned int
+s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport, u32 ufstat)
 {
        const struct s3c24xx_uart_info *info = ourport->info;
 
@@ -660,7 +662,7 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
 static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
 {
        struct uart_port *port = &ourport->port;
-       unsigned int ucon;
+       u32 ucon;
 
        /* set Rx mode to DMA mode */
        ucon = rd_regl(port, S3C2410_UCON);
@@ -683,7 +685,7 @@ static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
 static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
 {
        struct uart_port *port = &ourport->port;
-       unsigned int ucon;
+       u32 ucon;
 
        /* set Rx mode to DMA mode */
        ucon = rd_regl(port, S3C2410_UCON);
@@ -708,13 +710,14 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);
 
 static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
 {
-       unsigned int utrstat, received;
        struct s3c24xx_uart_port *ourport = dev_id;
        struct uart_port *port = &ourport->port;
        struct s3c24xx_uart_dma *dma = ourport->dma;
        struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
        struct tty_port *t = &port->state->port;
        struct dma_tx_state state;
+       unsigned int received;
+       u32 utrstat;
 
        utrstat = rd_regl(port, S3C2410_UTRSTAT);
        rd_regl(port, S3C2410_UFSTAT);
@@ -756,9 +759,9 @@ finish:
 static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
 {
        struct uart_port *port = &ourport->port;
-       unsigned int ufcon, ufstat, uerstat;
+       unsigned int max_count = port->fifosize;
        unsigned int fifocnt = 0;
-       int max_count = port->fifosize;
+       u32 ufcon, ufstat, uerstat;
        u8 ch, flag;
 
        while (max_count-- > 0) {
@@ -778,7 +781,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
                ch = rd_reg(port, S3C2410_URXH);
 
                if (port->flags & UPF_CONS_FLOW) {
-                       int txe = s3c24xx_serial_txempty_nofifo(port);
+                       bool txe = s3c24xx_serial_txempty_nofifo(port);
 
                        if (ourport->rx_enabled) {
                                if (!txe) {
@@ -942,7 +945,7 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
 {
        const struct s3c24xx_uart_port *ourport = id;
        const struct uart_port *port = &ourport->port;
-       unsigned int pend = rd_regl(port, S3C64XX_UINTP);
+       u32 pend = rd_regl(port, S3C64XX_UINTP);
        irqreturn_t ret = IRQ_HANDLED;
 
        if (pend & S3C64XX_UINTM_RXD_MSK) {
@@ -961,7 +964,7 @@ static irqreturn_t apple_serial_handle_irq(int irq, void *id)
 {
        const struct s3c24xx_uart_port *ourport = id;
        const struct uart_port *port = &ourport->port;
-       unsigned int pend = rd_regl(port, S3C2410_UTRSTAT);
+       u32 pend = rd_regl(port, S3C2410_UTRSTAT);
        irqreturn_t ret = IRQ_NONE;
 
        if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) {
@@ -980,24 +983,23 @@ static irqreturn_t apple_serial_handle_irq(int irq, void *id)
 static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
 {
        const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-       unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
-       unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
+       u32 ufstat = rd_regl(port, S3C2410_UFSTAT);
+       u32 ufcon = rd_regl(port, S3C2410_UFCON);
 
        if (ufcon & S3C2410_UFCON_FIFOMODE) {
-               if ((ufstat & info->tx_fifomask) != 0 ||
+               if ((ufstat & info->tx_fifomask) ||
                    (ufstat & info->tx_fifofull))
                        return 0;
-
-               return 1;
+               return TIOCSER_TEMT;
        }
 
-       return s3c24xx_serial_txempty_nofifo(port);
+       return s3c24xx_serial_txempty_nofifo(port) ? TIOCSER_TEMT : 0;
 }
 
 /* no modem control lines */
 static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
 {
-       unsigned int umstat = rd_reg(port, S3C2410_UMSTAT);
+       u32 umstat = rd_reg(port, S3C2410_UMSTAT);
 
        if (umstat & S3C2410_UMSTAT_CTS)
                return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
@@ -1007,8 +1009,8 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
 
 static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-       unsigned int umcon = rd_regl(port, S3C2410_UMCON);
-       unsigned int ucon = rd_regl(port, S3C2410_UCON);
+       u32 umcon = rd_regl(port, S3C2410_UMCON);
+       u32 ucon = rd_regl(port, S3C2410_UCON);
 
        if (mctrl & TIOCM_RTS)
                umcon |= S3C2410_UMCOM_RTS_LOW;
@@ -1028,7 +1030,7 @@ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
 {
        unsigned long flags;
-       unsigned int ucon;
+       u32 ucon;
 
        uart_port_lock_irqsave(port, &flags);
 
@@ -1186,7 +1188,7 @@ static void apple_s5l_serial_shutdown(struct uart_port *port)
 {
        struct s3c24xx_uart_port *ourport = to_ourport(port);
 
-       unsigned int ucon;
+       u32 ucon;
 
        ucon = rd_regl(port, S3C2410_UCON);
        ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
@@ -1212,7 +1214,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
 {
        struct s3c24xx_uart_port *ourport = to_ourport(port);
        unsigned long flags;
-       unsigned int ufcon;
+       u32 ufcon;
        int ret;
 
        wr_regl(port, S3C64XX_UINTM, 0xf);
@@ -1257,7 +1259,7 @@ static int apple_s5l_serial_startup(struct uart_port *port)
 {
        struct s3c24xx_uart_port *ourport = to_ourport(port);
        unsigned long flags;
-       unsigned int ufcon;
+       u32 ufcon;
        int ret;
 
        wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
@@ -1292,8 +1294,6 @@ static int apple_s5l_serial_startup(struct uart_port *port)
        return ret;
 }
 
-/* power power management control */
-
 static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
                              unsigned int old)
 {
@@ -1339,10 +1339,10 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
 
 #define MAX_CLK_NAME_LENGTH 15
 
-static inline int s3c24xx_serial_getsource(struct uart_port *port)
+static inline u8 s3c24xx_serial_getsource(struct uart_port *port)
 {
        const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-       unsigned int ucon;
+       u32 ucon;
 
        if (info->num_clks == 1)
                return 0;
@@ -1352,11 +1352,10 @@ static inline int s3c24xx_serial_getsource(struct uart_port *port)
        return ucon >> info->clksel_shift;
 }
 
-static void s3c24xx_serial_setsource(struct uart_port *port,
-                       unsigned int clk_sel)
+static void s3c24xx_serial_setsource(struct uart_port *port, u8 clk_sel)
 {
        const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-       unsigned int ucon;
+       u32 ucon;
 
        if (info->num_clks == 1)
                return;
@@ -1372,14 +1371,15 @@ static void s3c24xx_serial_setsource(struct uart_port *port,
 
 static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
                        unsigned int req_baud, struct clk **best_clk,
-                       unsigned int *clk_num)
+                       u8 *clk_num)
 {
        const struct s3c24xx_uart_info *info = ourport->info;
        struct clk *clk;
        unsigned long rate;
-       unsigned int cnt, baud, quot, best_quot = 0;
+       unsigned int baud, quot, best_quot = 0;
        char clkname[MAX_CLK_NAME_LENGTH];
        int calc_deviation, deviation = (1 << 30) - 1;
+       u8 cnt;
 
        for (cnt = 0; cnt < info->num_clks; cnt++) {
                /* Keep selected clock if provided */
@@ -1472,10 +1472,10 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
        struct s3c24xx_uart_port *ourport = to_ourport(port);
        struct clk *clk = ERR_PTR(-EINVAL);
        unsigned long flags;
-       unsigned int baud, quot, clk_sel = 0;
-       unsigned int ulcon;
-       unsigned int umcon;
+       unsigned int baud, quot;
        unsigned int udivslot = 0;
+       u32 ulcon, umcon;
+       u8 clk_sel = 0;
 
        /*
         * We don't support modem control lines.
@@ -1737,12 +1737,12 @@ static struct uart_driver s3c24xx_uart_drv = {
 
 static struct s3c24xx_uart_port s3c24xx_serial_ports[UART_NR];
 
-static void s3c24xx_serial_init_port_default(int index) {
+static void s3c24xx_serial_init_port_default(int index)
+{
        struct uart_port *port = &s3c24xx_serial_ports[index].port;
 
        spin_lock_init(&port->lock);
 
-       port->iotype = UPIO_MEM;
        port->uartclk = 0;
        port->fifosize = 16;
        port->flags = UPF_BOOT_AUTOCONF;
@@ -1758,7 +1758,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
                                     const struct s3c2410_uartcfg *cfg)
 {
        const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-       unsigned long ucon = rd_regl(port, S3C2410_UCON);
+       u32 ucon = rd_regl(port, S3C2410_UCON);
 
        ucon &= (info->clksel_mask | info->ucon_mask);
        wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
@@ -1776,10 +1776,9 @@ static int s3c24xx_serial_enable_baudclk(struct s3c24xx_uart_port *ourport)
        struct device *dev = ourport->port.dev;
        const struct s3c24xx_uart_info *info = ourport->info;
        char clk_name[MAX_CLK_NAME_LENGTH];
-       unsigned int clk_sel;
        struct clk *clk;
-       int clk_num;
        int ret;
+       u8 clk_sel, clk_num;
 
        clk_sel = ourport->cfg->clk_sel ? : info->def_clk_sel;
        for (clk_num = 0; clk_num < info->num_clks; clk_num++) {
@@ -1904,7 +1903,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
                wr_regl(port, S3C64XX_UINTSP, 0xf);
                break;
        case TYPE_APPLE_S5L: {
-               unsigned int ucon;
+               u32 ucon;
 
                ucon = rd_regl(port, S3C2410_UCON);
                ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
@@ -1952,7 +1951,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        struct s3c24xx_uart_port *ourport;
        int index = probe_index;
-       int ret, prop = 0;
+       int ret, prop = 0, fifosize_prop = 1;
 
        if (np) {
                ret = of_alias_get_id(np, "serial");
@@ -1989,9 +1988,11 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
                break;
        }
 
+       ourport->port.iotype = ourport->info->iotype;
+
        if (np) {
-               of_property_read_u32(np,
-                       "samsung,uart-fifosize", &ourport->port.fifosize);
+               fifosize_prop = of_property_read_u32(np, "samsung,uart-fifosize",
+                               &ourport->port.fifosize);
 
                if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
                        switch (prop) {
@@ -2009,10 +2010,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
                }
        }
 
-       if (ourport->drv_data->fifosize[index])
-               ourport->port.fifosize = ourport->drv_data->fifosize[index];
-       else if (ourport->info->fifosize)
-               ourport->port.fifosize = ourport->info->fifosize;
+       if (fifosize_prop) {
+               if (ourport->drv_data->fifosize[index])
+                       ourport->port.fifosize = ourport->drv_data->fifosize[index];
+               else if (ourport->info->fifosize)
+                       ourport->port.fifosize = ourport->info->fifosize;
+       }
+
        ourport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SAMSUNG_CONSOLE);
 
        /*
@@ -2058,9 +2062,8 @@ static void s3c24xx_serial_remove(struct platform_device *dev)
 {
        struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
 
-       if (port) {
+       if (port)
                uart_remove_one_port(&s3c24xx_uart_drv, port);
-       }
 
        uart_unregister_driver(&s3c24xx_uart_drv);
 }
@@ -2106,7 +2109,7 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
                /* restore IRQ mask */
                switch (ourport->info->type) {
                case TYPE_S3C6400: {
-                       unsigned int uintm = 0xf;
+                       u32 uintm = 0xf;
 
                        if (ourport->tx_enabled)
                                uintm &= ~S3C64XX_UINTM_TXD_MSK;
@@ -2122,7 +2125,7 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
                        break;
                }
                case TYPE_APPLE_S5L: {
-                       unsigned int ucon;
+                       u32 ucon;
                        int ret;
 
                        ret = clk_prepare_enable(ourport->clk);
@@ -2183,27 +2186,27 @@ static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
 
 static struct uart_port *cons_uart;
 
-static int
-s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
+static bool
+s3c24xx_serial_console_txrdy(struct uart_port *port, u32 ufcon)
 {
        const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-       unsigned long ufstat, utrstat;
+       u32 ufstat, utrstat;
 
        if (ufcon & S3C2410_UFCON_FIFOMODE) {
                /* fifo mode - check amount of data in fifo registers... */
 
                ufstat = rd_regl(port, S3C2410_UFSTAT);
-               return (ufstat & info->tx_fifofull) ? 0 : 1;
+               return !(ufstat & info->tx_fifofull);
        }
 
        /* in non-fifo mode, we go and use the tx buffer empty */
 
        utrstat = rd_regl(port, S3C2410_UTRSTAT);
-       return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
+       return utrstat & S3C2410_UTRSTAT_TXE;
 }
 
 static bool
-s3c24xx_port_configured(unsigned int ucon)
+s3c24xx_port_configured(u32 ucon)
 {
        /* consider the serial port configured if the tx/rx mode set */
        return (ucon & 0xf) != 0;
@@ -2218,7 +2221,7 @@ s3c24xx_port_configured(unsigned int ucon)
 static int s3c24xx_serial_get_poll_char(struct uart_port *port)
 {
        const struct s3c24xx_uart_port *ourport = to_ourport(port);
-       unsigned int ufstat;
+       u32 ufstat;
 
        ufstat = rd_regl(port, S3C2410_UFSTAT);
        if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
@@ -2230,8 +2233,8 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port)
 static void s3c24xx_serial_put_poll_char(struct uart_port *port,
                unsigned char c)
 {
-       unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
-       unsigned int ucon = rd_regl(port, S3C2410_UCON);
+       u32 ufcon = rd_regl(port, S3C2410_UFCON);
+       u32 ucon = rd_regl(port, S3C2410_UCON);
 
        /* not possible to xmit on unconfigured port */
        if (!s3c24xx_port_configured(ucon))
@@ -2247,7 +2250,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
 static void
 s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch)
 {
-       unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
+       u32 ufcon = rd_regl(port, S3C2410_UFCON);
 
        while (!s3c24xx_serial_console_txrdy(port, ufcon))
                cpu_relax();
@@ -2258,7 +2261,7 @@ static void
 s3c24xx_serial_console_write(struct console *co, const char *s,
                             unsigned int count)
 {
-       unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+       u32 ucon = rd_regl(cons_uart, S3C2410_UCON);
        unsigned long flags;
        bool locked = true;
 
@@ -2285,12 +2288,10 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
                           int *parity, int *bits)
 {
        struct clk *clk;
-       unsigned int ulcon;
-       unsigned int ucon;
-       unsigned int ubrdiv;
        unsigned long rate;
-       unsigned int clk_sel;
+       u32 ulcon, ucon, ubrdiv;
        char clk_name[MAX_CLK_NAME_LENGTH];
+       u8 clk_sel;
 
        ulcon  = rd_regl(port, S3C2410_ULCON);
        ucon   = rd_regl(port, S3C2410_UCON);
@@ -2399,8 +2400,9 @@ static const struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
                .name           = "Samsung S3C6400 UART",
                .type           = TYPE_S3C6400,
                .port_type      = PORT_S3C6400,
+               .iotype         = UPIO_MEM,
                .fifosize       = 64,
-               .has_divslot    = 1,
+               .has_divslot    = true,
                .rx_fifomask    = S3C2440_UFSTAT_RXMASK,
                .rx_fifoshift   = S3C2440_UFSTAT_RXSHIFT,
                .rx_fifofull    = S3C2440_UFSTAT_RXFULL,
@@ -2428,7 +2430,8 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
                .name           = "Samsung S5PV210 UART",
                .type           = TYPE_S3C6400,
                .port_type      = PORT_S3C6400,
-               .has_divslot    = 1,
+               .iotype         = UPIO_MEM,
+               .has_divslot    = true,
                .rx_fifomask    = S5PV210_UFSTAT_RXMASK,
                .rx_fifoshift   = S5PV210_UFSTAT_RXSHIFT,
                .rx_fifofull    = S5PV210_UFSTAT_RXFULL,
@@ -2452,12 +2455,13 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
 #endif
 
 #if defined(CONFIG_ARCH_EXYNOS)
-#define EXYNOS_COMMON_SERIAL_DRV_DATA()                                \
+#define EXYNOS_COMMON_SERIAL_DRV_DATA                          \
        .info = {                                               \
                .name           = "Samsung Exynos UART",        \
                .type           = TYPE_S3C6400,                 \
                .port_type      = PORT_S3C6400,                 \
-               .has_divslot    = 1,                            \
+               .iotype         = UPIO_MEM,                     \
+               .has_divslot    = true,                         \
                .rx_fifomask    = S5PV210_UFSTAT_RXMASK,        \
                .rx_fifoshift   = S5PV210_UFSTAT_RXSHIFT,       \
                .rx_fifofull    = S5PV210_UFSTAT_RXFULL,        \
@@ -2476,39 +2480,57 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
        }                                                       \
 
 static const struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
-       EXYNOS_COMMON_SERIAL_DRV_DATA(),
+       EXYNOS_COMMON_SERIAL_DRV_DATA,
        .fifosize = { 256, 64, 16, 16 },
 };
 
 static const struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
-       EXYNOS_COMMON_SERIAL_DRV_DATA(),
+       EXYNOS_COMMON_SERIAL_DRV_DATA,
        .fifosize = { 64, 256, 16, 256 },
 };
 
 static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
-       EXYNOS_COMMON_SERIAL_DRV_DATA(),
+       EXYNOS_COMMON_SERIAL_DRV_DATA,
        .fifosize = { 256, 64, 64, 64 },
 };
 
-/*
- * Common drv_data struct for platforms that specify samsung,uart-fifosize in
- * device tree.
- */
-static const struct s3c24xx_serial_drv_data exynos_fifoszdt_serial_drv_data = {
-       EXYNOS_COMMON_SERIAL_DRV_DATA(),
+static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = {
+       .info = {
+               .name           = "Google GS101 UART",
+               .type           = TYPE_S3C6400,
+               .port_type      = PORT_S3C6400,
+               .iotype         = UPIO_MEM32,
+               .has_divslot    = true,
+               .rx_fifomask    = S5PV210_UFSTAT_RXMASK,
+               .rx_fifoshift   = S5PV210_UFSTAT_RXSHIFT,
+               .rx_fifofull    = S5PV210_UFSTAT_RXFULL,
+               .tx_fifofull    = S5PV210_UFSTAT_TXFULL,
+               .tx_fifomask    = S5PV210_UFSTAT_TXMASK,
+               .tx_fifoshift   = S5PV210_UFSTAT_TXSHIFT,
+               .def_clk_sel    = S3C2410_UCON_CLKSEL0,
+               .num_clks       = 1,
+               .clksel_mask    = 0,
+               .clksel_shift   = 0,
+       },
+       .def_cfg = {
+               .ucon           = S5PV210_UCON_DEFAULT,
+               .ufcon          = S5PV210_UFCON_DEFAULT,
+               .has_fracval    = 1,
+       },
+       /* samsung,uart-fifosize must be specified in the device tree. */
        .fifosize = { 0 },
 };
 
 #define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data)
 #define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data)
 #define EXYNOS850_SERIAL_DRV_DATA (&exynos850_serial_drv_data)
-#define EXYNOS_FIFOSZDT_DRV_DATA (&exynos_fifoszdt_serial_drv_data)
+#define GS101_SERIAL_DRV_DATA (&gs101_serial_drv_data)
 
 #else
 #define EXYNOS4210_SERIAL_DRV_DATA NULL
 #define EXYNOS5433_SERIAL_DRV_DATA NULL
 #define EXYNOS850_SERIAL_DRV_DATA NULL
-#define EXYNOS_FIFOSZDT_DRV_DATA NULL
+#define GS101_SERIAL_DRV_DATA NULL
 #endif
 
 #ifdef CONFIG_ARCH_APPLE
@@ -2517,6 +2539,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
                .name           = "Apple S5L UART",
                .type           = TYPE_APPLE_S5L,
                .port_type      = PORT_8250,
+               .iotype         = UPIO_MEM,
                .fifosize       = 16,
                .rx_fifomask    = S3C2410_UFSTAT_RXMASK,
                .rx_fifoshift   = S3C2410_UFSTAT_RXSHIFT,
@@ -2546,8 +2569,9 @@ static const struct s3c24xx_serial_drv_data artpec8_serial_drv_data = {
                .name           = "Axis ARTPEC-8 UART",
                .type           = TYPE_S3C6400,
                .port_type      = PORT_S3C6400,
+               .iotype         = UPIO_MEM,
                .fifosize       = 64,
-               .has_divslot    = 1,
+               .has_divslot    = true,
                .rx_fifomask    = S5PV210_UFSTAT_RXMASK,
                .rx_fifoshift   = S5PV210_UFSTAT_RXSHIFT,
                .rx_fifofull    = S5PV210_UFSTAT_RXFULL,
@@ -2594,7 +2618,7 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
                .driver_data    = (kernel_ulong_t)ARTPEC8_SERIAL_DRV_DATA,
        }, {
                .name           = "gs101-uart",
-               .driver_data    = (kernel_ulong_t)EXYNOS_FIFOSZDT_DRV_DATA,
+               .driver_data    = (kernel_ulong_t)GS101_SERIAL_DRV_DATA,
        },
        { },
 };
@@ -2617,7 +2641,7 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
        { .compatible = "axis,artpec8-uart",
                .data = ARTPEC8_SERIAL_DRV_DATA },
        { .compatible = "google,gs101-uart",
-               .data = EXYNOS_FIFOSZDT_DRV_DATA },
+               .data = GS101_SERIAL_DRV_DATA },
        {},
 };
 MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
@@ -2716,7 +2740,8 @@ static int samsung_early_read(struct console *con, char *s, unsigned int n)
 {
        struct earlycon_device *dev = con->data;
        const struct samsung_early_console_data *data = dev->port.private_data;
-       int ch, ufstat, num_read = 0;
+       int num_read = 0;
+       u32 ch, ufstat;
 
        while (num_read < n) {
                ufstat = rd_regl(&dev->port, S3C2410_UFSTAT);
@@ -2785,6 +2810,17 @@ OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
 OF_EARLYCON_DECLARE(artpec8, "axis,artpec8-uart",
                        s5pv210_early_console_setup);
 
+static int __init gs101_early_console_setup(struct earlycon_device *device,
+                                           const char *opt)
+{
+       /* gs101 always expects MMIO32 register accesses. */
+       device->port.iotype = UPIO_MEM32;
+
+       return s5pv210_early_console_setup(device, opt);
+}
+
+OF_EARLYCON_DECLARE(gs101, "google,gs101-uart", gs101_early_console_setup);
+
 /* Apple S5L */
 static int __init apple_s5l_early_console_setup(struct earlycon_device *device,
                                                const char *opt)
index 3dfcf20c4eb68c99b71ab06e7c1c1c8925f4261a..4df2a4b10445adde43e83d4b8bd8543a132a1872 100644 (file)
@@ -41,7 +41,7 @@ static int serial_base_match(struct device *dev, struct device_driver *drv)
        return 0;
 }
 
-static struct bus_type serial_base_bus_type = {
+static const struct bus_type serial_base_bus_type = {
        .name = "serial-base",
        .match = serial_base_match,
 };
index d6a58a9e072a1dad7938fbb53627f4d5e5374adc..ff85ebd3a007dba0105e38d732efc0f6a6f8ab5b 100644 (file)
@@ -2608,7 +2608,12 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
                        port->type = PORT_UNKNOWN;
                        flags |= UART_CONFIG_TYPE;
                }
+               /* Synchronize with possible boot console. */
+               if (uart_console(port))
+                       console_lock();
                port->ops->config_port(port, flags);
+               if (uart_console(port))
+                       console_unlock();
        }
 
        if (port->type != PORT_UNKNOWN) {
@@ -2616,6 +2621,10 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
 
                uart_report_port(drv, port);
 
+               /* Synchronize with possible boot console. */
+               if (uart_console(port))
+                       console_lock();
+
                /* Power up port for set_mctrl() */
                uart_change_pm(state, UART_PM_STATE_ON);
 
@@ -2632,6 +2641,9 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
 
                uart_rs485_config(port);
 
+               if (uart_console(port))
+                       console_unlock();
+
                /*
                 * If this driver supports console, and it hasn't been
                 * successfully registered yet, try to re-register it.
index 72b6f4f326e2b04953875062f8ebc6e56f324e45..22b9eeb23e68adb2cfd949ff20c18816bb78b1cb 100644 (file)
@@ -8,7 +8,10 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/property.h>
 #include <linux/serial_core.h>
 #include <linux/spinlock.h>
 
@@ -105,6 +108,148 @@ void uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
 }
 EXPORT_SYMBOL(uart_remove_one_port);
 
+/**
+ * __uart_read_properties - read firmware properties of the given UART port
+ * @port: corresponding port
+ * @use_defaults: apply defaults (when %true) or validate the values (when %false)
+ *
+ * The following device properties are supported:
+ *   - clock-frequency (optional)
+ *   - fifo-size (optional)
+ *   - no-loopback-test (optional)
+ *   - reg-shift (defaults may apply)
+ *   - reg-offset (value may be validated)
+ *   - reg-io-width (defaults may apply or value may be validated)
+ *   - interrupts (OF only)
+ *   - serial [alias ID] (OF only)
+ *
+ * If the port->dev is of struct platform_device type the interrupt line
+ * will be retrieved via platform_get_irq() call against that device.
+ * Otherwise it will be assigned by fwnode_irq_get() call. In both cases
+ * the index 0 of the resource is used.
+ *
+ * The caller is responsible to initialize the following fields of the @port
+ *   ->dev (must be valid)
+ *   ->flags
+ *   ->mapbase
+ *   ->mapsize
+ *   ->regshift (if @use_defaults is false)
+ * before calling this function. Alternatively the above mentioned fields
+ * may be zeroed, in such case the only ones, that have associated properties
+ * found, will be set to the respective values.
+ *
+ * If no error happened, the ->irq, ->mapbase, ->mapsize will be altered.
+ * The ->iotype is always altered.
+ *
+ * When @use_defaults is true and the respective property is not found
+ * the following values will be applied:
+ *   ->regshift = 0
+ * In this case IRQ must be provided, otherwise an error will be returned.
+ *
+ * When @use_defaults is false and the respective property is found
+ * the following values will be validated:
+ *   - reg-io-width (->iotype)
+ *   - reg-offset (->mapsize against ->mapbase)
+ *
+ * Returns: 0 on success or negative errno on failure
+ */
+static int __uart_read_properties(struct uart_port *port, bool use_defaults)
+{
+       struct device *dev = port->dev;
+       u32 value;
+       int ret;
+
+       /* Read optional UART functional clock frequency */
+       device_property_read_u32(dev, "clock-frequency", &port->uartclk);
+
+       /* Read the registers alignment (default: 8-bit) */
+       ret = device_property_read_u32(dev, "reg-shift", &value);
+       if (ret)
+               port->regshift = use_defaults ? 0 : port->regshift;
+       else
+               port->regshift = value;
+
+       /* Read the registers I/O access type (default: MMIO 8-bit) */
+       ret = device_property_read_u32(dev, "reg-io-width", &value);
+       if (ret) {
+               port->iotype = UPIO_MEM;
+       } else {
+               switch (value) {
+               case 1:
+                       port->iotype = UPIO_MEM;
+                       break;
+               case 2:
+                       port->iotype = UPIO_MEM16;
+                       break;
+               case 4:
+                       port->iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32;
+                       break;
+               default:
+                       if (!use_defaults) {
+                               dev_err(dev, "Unsupported reg-io-width (%u)\n", value);
+                               return -EINVAL;
+                       }
+                       port->iotype = UPIO_UNKNOWN;
+                       break;
+               }
+       }
+
+       /* Read the address mapping base offset (default: no offset) */
+       ret = device_property_read_u32(dev, "reg-offset", &value);
+       if (ret)
+               value = 0;
+
+       /* Check for shifted address mapping overflow */
+       if (!use_defaults && port->mapsize < value) {
+               dev_err(dev, "reg-offset %u exceeds region size %pa\n", value, &port->mapsize);
+               return -EINVAL;
+       }
+
+       port->mapbase += value;
+       port->mapsize -= value;
+
+       /* Read optional FIFO size */
+       device_property_read_u32(dev, "fifo-size", &port->fifosize);
+
+       if (device_property_read_bool(dev, "no-loopback-test"))
+               port->flags |= UPF_SKIP_TEST;
+
+       /* Get index of serial line, if found in DT aliases */
+       ret = of_alias_get_id(dev_of_node(dev), "serial");
+       if (ret >= 0)
+               port->line = ret;
+
+       if (dev_is_platform(dev))
+               ret = platform_get_irq(to_platform_device(dev), 0);
+       else
+               ret = fwnode_irq_get(dev_fwnode(dev), 0);
+       if (ret == -EPROBE_DEFER)
+               return ret;
+       if (ret > 0)
+               port->irq = ret;
+       else if (use_defaults)
+               /* By default IRQ support is mandatory */
+               return ret;
+       else
+               port->irq = 0;
+
+       port->flags |= UPF_SHARE_IRQ;
+
+       return 0;
+}
+
+int uart_read_port_properties(struct uart_port *port)
+{
+       return __uart_read_properties(port, true);
+}
+EXPORT_SYMBOL_GPL(uart_read_port_properties);
+
+int uart_read_and_validate_port_properties(struct uart_port *port)
+{
+       return __uart_read_properties(port, false);
+}
+EXPORT_SYMBOL_GPL(uart_read_and_validate_port_properties);
+
 static struct device_driver serial_port_driver = {
        .name = "port",
        .suppress_bind_attrs = true,
index e1897894a4ef58cb69f8bb9edef43ed17786cb34..abba397229581851d05cd09ab393865f4509204d 100644 (file)
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-
 #include <linux/io.h>
 
+#include <asm/txx9/generic.h>
+
 #define PASS_LIMIT     256
 
 #if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
index a85e7b9a2e492391ae7a5c6560bc4b2d31ed96fb..e512eaa57ed562eb758d8da2ca34010ca753c022 100644 (file)
@@ -576,13 +576,13 @@ static void sci_start_tx(struct uart_port *port)
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-               u16 new, scr = serial_port_in(port, SCSCR);
+               u16 new, scr = sci_serial_in(port, SCSCR);
                if (s->chan_tx)
                        new = scr | SCSCR_TDRQE;
                else
                        new = scr & ~SCSCR_TDRQE;
                if (new != scr)
-                       serial_port_out(port, SCSCR, new);
+                       sci_serial_out(port, SCSCR, new);
        }
 
        if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
@@ -599,7 +599,7 @@ static void sci_start_tx(struct uart_port *port)
        if (!s->chan_tx || s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE ||
            port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
                /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
-               ctrl = serial_port_in(port, SCSCR);
+               ctrl = sci_serial_in(port, SCSCR);
 
                /*
                 * For SCI, TE (transmit enable) must be set after setting TIE
@@ -609,7 +609,7 @@ static void sci_start_tx(struct uart_port *port)
                if (port->type == PORT_SCI)
                        ctrl |= SCSCR_TE;
 
-               serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
+               sci_serial_out(port, SCSCR, ctrl | SCSCR_TIE);
        }
 }
 
@@ -618,14 +618,14 @@ static void sci_stop_tx(struct uart_port *port)
        unsigned short ctrl;
 
        /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
-       ctrl = serial_port_in(port, SCSCR);
+       ctrl = sci_serial_in(port, SCSCR);
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~SCSCR_TDRQE;
 
        ctrl &= ~SCSCR_TIE;
 
-       serial_port_out(port, SCSCR, ctrl);
+       sci_serial_out(port, SCSCR, ctrl);
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
        if (to_sci_port(port)->chan_tx &&
@@ -640,41 +640,40 @@ static void sci_start_rx(struct uart_port *port)
 {
        unsigned short ctrl;
 
-       ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
+       ctrl = sci_serial_in(port, SCSCR) | port_rx_irq_mask(port);
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~SCSCR_RDRQE;
 
-       serial_port_out(port, SCSCR, ctrl);
+       sci_serial_out(port, SCSCR, ctrl);
 }
 
 static void sci_stop_rx(struct uart_port *port)
 {
        unsigned short ctrl;
 
-       ctrl = serial_port_in(port, SCSCR);
+       ctrl = sci_serial_in(port, SCSCR);
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~SCSCR_RDRQE;
 
        ctrl &= ~port_rx_irq_mask(port);
 
-       serial_port_out(port, SCSCR, ctrl);
+       sci_serial_out(port, SCSCR, ctrl);
 }
 
 static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask)
 {
        if (port->type == PORT_SCI) {
                /* Just store the mask */
-               serial_port_out(port, SCxSR, mask);
+               sci_serial_out(port, SCxSR, mask);
        } else if (to_sci_port(port)->params->overrun_mask == SCIFA_ORER) {
                /* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */
                /* Only clear the status bits we want to clear */
-               serial_port_out(port, SCxSR,
-                               serial_port_in(port, SCxSR) & mask);
+               sci_serial_out(port, SCxSR, sci_serial_in(port, SCxSR) & mask);
        } else {
                /* Store the mask, clear parity/framing errors */
-               serial_port_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC));
+               sci_serial_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC));
        }
 }
 
@@ -688,7 +687,7 @@ static int sci_poll_get_char(struct uart_port *port)
        int c;
 
        do {
-               status = serial_port_in(port, SCxSR);
+               status = sci_serial_in(port, SCxSR);
                if (status & SCxSR_ERRORS(port)) {
                        sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
                        continue;
@@ -699,10 +698,10 @@ static int sci_poll_get_char(struct uart_port *port)
        if (!(status & SCxSR_RDxF(port)))
                return NO_POLL_CHAR;
 
-       c = serial_port_in(port, SCxRDR);
+       c = sci_serial_in(port, SCxRDR);
 
        /* Dummy read */
-       serial_port_in(port, SCxSR);
+       sci_serial_in(port, SCxSR);
        sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
 
        return c;
@@ -714,10 +713,10 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
        unsigned short status;
 
        do {
-               status = serial_port_in(port, SCxSR);
+               status = sci_serial_in(port, SCxSR);
        } while (!(status & SCxSR_TDxE(port)));
 
-       serial_port_out(port, SCxTDR, c);
+       sci_serial_out(port, SCxTDR, c);
        sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
 }
 #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE ||
@@ -736,8 +735,8 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
        }
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-               u16 data = serial_port_in(port, SCPDR);
-               u16 ctrl = serial_port_in(port, SCPCR);
+               u16 data = sci_serial_in(port, SCPDR);
+               u16 ctrl = sci_serial_in(port, SCPCR);
 
                /* Enable RXD and TXD pin functions */
                ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
@@ -756,10 +755,10 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
                        /* Enable CTS# pin function */
                        ctrl &= ~SCPCR_CTSC;
                }
-               serial_port_out(port, SCPDR, data);
-               serial_port_out(port, SCPCR, ctrl);
+               sci_serial_out(port, SCPDR, data);
+               sci_serial_out(port, SCPCR, ctrl);
        } else if (sci_getreg(port, SCSPTR)->size) {
-               u16 status = serial_port_in(port, SCSPTR);
+               u16 status = sci_serial_in(port, SCSPTR);
 
                /* RTS# is always output; and active low, unless autorts */
                status |= SCSPTR_RTSIO;
@@ -769,7 +768,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
                        status &= ~SCSPTR_RTSDT;
                /* CTS# and SCK are inputs */
                status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO);
-               serial_port_out(port, SCSPTR, status);
+               sci_serial_out(port, SCSPTR, status);
        }
 }
 
@@ -781,13 +780,13 @@ static int sci_txfill(struct uart_port *port)
 
        reg = sci_getreg(port, SCTFDR);
        if (reg->size)
-               return serial_port_in(port, SCTFDR) & fifo_mask;
+               return sci_serial_in(port, SCTFDR) & fifo_mask;
 
        reg = sci_getreg(port, SCFDR);
        if (reg->size)
-               return serial_port_in(port, SCFDR) >> 8;
+               return sci_serial_in(port, SCFDR) >> 8;
 
-       return !(serial_port_in(port, SCxSR) & SCI_TDRE);
+       return !(sci_serial_in(port, SCxSR) & SCI_TDRE);
 }
 
 static int sci_txroom(struct uart_port *port)
@@ -803,13 +802,13 @@ static int sci_rxfill(struct uart_port *port)
 
        reg = sci_getreg(port, SCRFDR);
        if (reg->size)
-               return serial_port_in(port, SCRFDR) & fifo_mask;
+               return sci_serial_in(port, SCRFDR) & fifo_mask;
 
        reg = sci_getreg(port, SCFDR);
        if (reg->size)
-               return serial_port_in(port, SCFDR) & fifo_mask;
+               return sci_serial_in(port, SCFDR) & fifo_mask;
 
-       return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
+       return (sci_serial_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
 }
 
 /* ********************************************************************** *
@@ -824,14 +823,14 @@ static void sci_transmit_chars(struct uart_port *port)
        unsigned short ctrl;
        int count;
 
-       status = serial_port_in(port, SCxSR);
+       status = sci_serial_in(port, SCxSR);
        if (!(status & SCxSR_TDxE(port))) {
-               ctrl = serial_port_in(port, SCSCR);
+               ctrl = sci_serial_in(port, SCSCR);
                if (uart_circ_empty(xmit))
                        ctrl &= ~SCSCR_TIE;
                else
                        ctrl |= SCSCR_TIE;
-               serial_port_out(port, SCSCR, ctrl);
+               sci_serial_out(port, SCSCR, ctrl);
                return;
        }
 
@@ -847,15 +846,15 @@ static void sci_transmit_chars(struct uart_port *port)
                        c = xmit->buf[xmit->tail];
                        xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
                } else if (port->type == PORT_SCI && uart_circ_empty(xmit)) {
-                       ctrl = serial_port_in(port, SCSCR);
+                       ctrl = sci_serial_in(port, SCSCR);
                        ctrl &= ~SCSCR_TE;
-                       serial_port_out(port, SCSCR, ctrl);
+                       sci_serial_out(port, SCSCR, ctrl);
                        return;
                } else {
                        break;
                }
 
-               serial_port_out(port, SCxTDR, c);
+               sci_serial_out(port, SCxTDR, c);
 
                port->icount.tx++;
        } while (--count > 0);
@@ -866,10 +865,10 @@ static void sci_transmit_chars(struct uart_port *port)
                uart_write_wakeup(port);
        if (uart_circ_empty(xmit)) {
                if (port->type == PORT_SCI) {
-                       ctrl = serial_port_in(port, SCSCR);
+                       ctrl = sci_serial_in(port, SCSCR);
                        ctrl &= ~SCSCR_TIE;
                        ctrl |= SCSCR_TEIE;
-                       serial_port_out(port, SCSCR, ctrl);
+                       sci_serial_out(port, SCSCR, ctrl);
                }
 
                sci_stop_tx(port);
@@ -883,7 +882,7 @@ static void sci_receive_chars(struct uart_port *port)
        unsigned short status;
        unsigned char flag;
 
-       status = serial_port_in(port, SCxSR);
+       status = sci_serial_in(port, SCxSR);
        if (!(status & SCxSR_RDxF(port)))
                return;
 
@@ -896,7 +895,7 @@ static void sci_receive_chars(struct uart_port *port)
                        break;
 
                if (port->type == PORT_SCI) {
-                       char c = serial_port_in(port, SCxRDR);
+                       char c = sci_serial_in(port, SCxRDR);
                        if (uart_handle_sysrq_char(port, c))
                                count = 0;
                        else
@@ -907,11 +906,11 @@ static void sci_receive_chars(struct uart_port *port)
 
                                if (port->type == PORT_SCIF ||
                                    port->type == PORT_HSCIF) {
-                                       status = serial_port_in(port, SCxSR);
-                                       c = serial_port_in(port, SCxRDR);
+                                       status = sci_serial_in(port, SCxSR);
+                                       c = sci_serial_in(port, SCxRDR);
                                } else {
-                                       c = serial_port_in(port, SCxRDR);
-                                       status = serial_port_in(port, SCxSR);
+                                       c = sci_serial_in(port, SCxRDR);
+                                       status = sci_serial_in(port, SCxSR);
                                }
                                if (uart_handle_sysrq_char(port, c)) {
                                        count--; i--;
@@ -932,7 +931,7 @@ static void sci_receive_chars(struct uart_port *port)
                        }
                }
 
-               serial_port_in(port, SCxSR); /* dummy read */
+               sci_serial_in(port, SCxSR); /* dummy read */
                sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
 
                copied += count;
@@ -944,8 +943,8 @@ static void sci_receive_chars(struct uart_port *port)
                tty_flip_buffer_push(tport);
        } else {
                /* TTY buffers full; read from RX reg to prevent lockup */
-               serial_port_in(port, SCxRDR);
-               serial_port_in(port, SCxSR); /* dummy read */
+               sci_serial_in(port, SCxRDR);
+               sci_serial_in(port, SCxSR); /* dummy read */
                sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
        }
 }
@@ -953,7 +952,7 @@ static void sci_receive_chars(struct uart_port *port)
 static int sci_handle_errors(struct uart_port *port)
 {
        int copied = 0;
-       unsigned short status = serial_port_in(port, SCxSR);
+       unsigned short status = sci_serial_in(port, SCxSR);
        struct tty_port *tport = &port->state->port;
        struct sci_port *s = to_sci_port(port);
 
@@ -1000,10 +999,10 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
        if (!reg->size)
                return 0;
 
-       status = serial_port_in(port, s->params->overrun_reg);
+       status = sci_serial_in(port, s->params->overrun_reg);
        if (status & s->params->overrun_mask) {
                status &= ~s->params->overrun_mask;
-               serial_port_out(port, s->params->overrun_reg, status);
+               sci_serial_out(port, s->params->overrun_reg, status);
 
                port->icount.overrun++;
 
@@ -1018,7 +1017,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
 static int sci_handle_breaks(struct uart_port *port)
 {
        int copied = 0;
-       unsigned short status = serial_port_in(port, SCxSR);
+       unsigned short status = sci_serial_in(port, SCxSR);
        struct tty_port *tport = &port->state->port;
 
        if (uart_handle_break(port))
@@ -1051,7 +1050,7 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig)
 
        /* HSCIF can be set to an arbitrary level. */
        if (sci_getreg(port, HSRTRGR)->size) {
-               serial_port_out(port, HSRTRGR, rx_trig);
+               sci_serial_out(port, HSRTRGR, rx_trig);
                return rx_trig;
        }
 
@@ -1092,9 +1091,9 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig)
                return 1;
        }
 
-       serial_port_out(port, SCFCR,
-               (serial_port_in(port, SCFCR) &
-               ~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits);
+       sci_serial_out(port, SCFCR,
+                      (sci_serial_in(port, SCFCR) &
+                       ~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits);
 
        return rx_trig;
 }
@@ -1102,9 +1101,9 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig)
 static int scif_rtrg_enabled(struct uart_port *port)
 {
        if (sci_getreg(port, HSRTRGR)->size)
-               return serial_port_in(port, HSRTRGR) != 0;
+               return sci_serial_in(port, HSRTRGR) != 0;
        else
-               return (serial_port_in(port, SCFCR) &
+               return (sci_serial_in(port, SCFCR) &
                        (SCFCR_RTRG0 | SCFCR_RTRG1)) != 0;
 }
 
@@ -1219,8 +1218,8 @@ static void sci_dma_tx_complete(void *arg)
                s->cookie_tx = -EINVAL;
                if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
                    s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
-                       u16 ctrl = serial_port_in(port, SCSCR);
-                       serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+                       u16 ctrl = sci_serial_in(port, SCSCR);
+                       sci_serial_out(port, SCSCR, ctrl & ~SCSCR_TIE);
                        if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
                                /* Switch irq from DMA to SCIF */
                                dmaengine_pause(s->chan_tx_saved);
@@ -1296,7 +1295,7 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s)
        u16 scr;
 
        /* Direct new serial port interrupts back to CPU */
-       scr = serial_port_in(port, SCSCR);
+       scr = sci_serial_in(port, SCSCR);
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
            s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
                enable_irq(s->irqs[SCIx_RXI_IRQ]);
@@ -1305,7 +1304,7 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s)
                else
                        scr &= ~SCSCR_RDRQE;
        }
-       serial_port_out(port, SCSCR, scr | SCSCR_RIE);
+       sci_serial_out(port, SCSCR, scr | SCSCR_RIE);
 }
 
 static void sci_dma_rx_complete(void *arg)
@@ -1714,8 +1713,8 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
        if (s->chan_rx) {
-               u16 scr = serial_port_in(port, SCSCR);
-               u16 ssr = serial_port_in(port, SCxSR);
+               u16 scr = sci_serial_in(port, SCSCR);
+               u16 ssr = sci_serial_in(port, SCxSR);
 
                /* Disable future Rx interrupts */
                if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
@@ -1733,10 +1732,10 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
 
                        scr &= ~SCSCR_RIE;
                }
-               serial_port_out(port, SCSCR, scr);
+               sci_serial_out(port, SCSCR, scr);
                /* Clear current interrupt */
-               serial_port_out(port, SCxSR,
-                               ssr & ~(SCIF_DR | SCxSR_RDxF(port)));
+               sci_serial_out(port, SCxSR,
+                              ssr & ~(SCIF_DR | SCxSR_RDxF(port)));
                dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u us\n",
                        jiffies, s->rx_timeout);
                start_hrtimer_us(&s->rx_timer, s->rx_timeout);
@@ -1786,9 +1785,9 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
                return sci_tx_interrupt(irq, ptr);
 
        uart_port_lock_irqsave(port, &flags);
-       ctrl = serial_port_in(port, SCSCR);
+       ctrl = sci_serial_in(port, SCSCR);
        ctrl &= ~(SCSCR_TE | SCSCR_TEIE);
-       serial_port_out(port, SCSCR, ctrl);
+       sci_serial_out(port, SCSCR, ctrl);
        uart_port_unlock_irqrestore(port, flags);
 
        return IRQ_HANDLED;
@@ -1802,7 +1801,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
        sci_handle_breaks(port);
 
        /* drop invalid character received before break was detected */
-       serial_port_in(port, SCxRDR);
+       sci_serial_in(port, SCxRDR);
 
        sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
 
@@ -1816,7 +1815,7 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr)
 
        if (s->irqs[SCIx_ERI_IRQ] == s->irqs[SCIx_BRI_IRQ]) {
                /* Break and Error interrupts are muxed */
-               unsigned short ssr_status = serial_port_in(port, SCxSR);
+               unsigned short ssr_status = sci_serial_in(port, SCxSR);
 
                /* Break Interrupt */
                if (ssr_status & SCxSR_BRK(port))
@@ -1831,7 +1830,7 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr)
        if (port->type == PORT_SCI) {
                if (sci_handle_errors(port)) {
                        /* discard character in rx buffer */
-                       serial_port_in(port, SCxSR);
+                       sci_serial_in(port, SCxSR);
                        sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
                }
        } else {
@@ -1856,12 +1855,12 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
        struct sci_port *s = to_sci_port(port);
        irqreturn_t ret = IRQ_NONE;
 
-       ssr_status = serial_port_in(port, SCxSR);
-       scr_status = serial_port_in(port, SCSCR);
+       ssr_status = sci_serial_in(port, SCxSR);
+       scr_status = sci_serial_in(port, SCSCR);
        if (s->params->overrun_reg == SCxSR)
                orer_status = ssr_status;
        else if (sci_getreg(port, s->params->overrun_reg)->size)
-               orer_status = serial_port_in(port, s->params->overrun_reg);
+               orer_status = sci_serial_in(port, s->params->overrun_reg);
 
        err_enabled = scr_status & port_rx_irq_mask(port);
 
@@ -2038,7 +2037,7 @@ static void sci_free_irq(struct sci_port *port)
 
 static unsigned int sci_tx_empty(struct uart_port *port)
 {
-       unsigned short status = serial_port_in(port, SCxSR);
+       unsigned short status = sci_serial_in(port, SCxSR);
        unsigned short in_tx_fifo = sci_txfill(port);
 
        return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
@@ -2047,27 +2046,27 @@ static unsigned int sci_tx_empty(struct uart_port *port)
 static void sci_set_rts(struct uart_port *port, bool state)
 {
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-               u16 data = serial_port_in(port, SCPDR);
+               u16 data = sci_serial_in(port, SCPDR);
 
                /* Active low */
                if (state)
                        data &= ~SCPDR_RTSD;
                else
                        data |= SCPDR_RTSD;
-               serial_port_out(port, SCPDR, data);
+               sci_serial_out(port, SCPDR, data);
 
                /* RTS# is output */
-               serial_port_out(port, SCPCR,
-                               serial_port_in(port, SCPCR) | SCPCR_RTSC);
+               sci_serial_out(port, SCPCR,
+                              sci_serial_in(port, SCPCR) | SCPCR_RTSC);
        } else if (sci_getreg(port, SCSPTR)->size) {
-               u16 ctrl = serial_port_in(port, SCSPTR);
+               u16 ctrl = sci_serial_in(port, SCSPTR);
 
                /* Active low */
                if (state)
                        ctrl &= ~SCSPTR_RTSDT;
                else
                        ctrl |= SCSPTR_RTSDT;
-               serial_port_out(port, SCSPTR, ctrl);
+               sci_serial_out(port, SCSPTR, ctrl);
        }
 }
 
@@ -2075,10 +2074,10 @@ static bool sci_get_cts(struct uart_port *port)
 {
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
                /* Active low */
-               return !(serial_port_in(port, SCPDR) & SCPDR_CTSD);
+               return !(sci_serial_in(port, SCPDR) & SCPDR_CTSD);
        } else if (sci_getreg(port, SCSPTR)->size) {
                /* Active low */
-               return !(serial_port_in(port, SCSPTR) & SCSPTR_CTSDT);
+               return !(sci_serial_in(port, SCSPTR) & SCSPTR_CTSDT);
        }
 
        return true;
@@ -2108,9 +2107,8 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
                 */
                reg = sci_getreg(port, SCFCR);
                if (reg->size)
-                       serial_port_out(port, SCFCR,
-                                       serial_port_in(port, SCFCR) |
-                                       SCFCR_LOOP);
+                       sci_serial_out(port, SCFCR,
+                                      sci_serial_in(port, SCFCR) | SCFCR_LOOP);
        }
 
        mctrl_gpio_set(s->gpios, mctrl);
@@ -2120,21 +2118,21 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
        if (!(mctrl & TIOCM_RTS)) {
                /* Disable Auto RTS */
-               serial_port_out(port, SCFCR,
-                               serial_port_in(port, SCFCR) & ~SCFCR_MCE);
+               sci_serial_out(port, SCFCR,
+                              sci_serial_in(port, SCFCR) & ~SCFCR_MCE);
 
                /* Clear RTS */
                sci_set_rts(port, 0);
        } else if (s->autorts) {
                if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
                        /* Enable RTS# pin function */
-                       serial_port_out(port, SCPCR,
-                               serial_port_in(port, SCPCR) & ~SCPCR_RTSC);
+                       sci_serial_out(port, SCPCR,
+                               sci_serial_in(port, SCPCR) & ~SCPCR_RTSC);
                }
 
                /* Enable Auto RTS */
-               serial_port_out(port, SCFCR,
-                               serial_port_in(port, SCFCR) | SCFCR_MCE);
+               sci_serial_out(port, SCFCR,
+                              sci_serial_in(port, SCFCR) | SCFCR_MCE);
        } else {
                /* Set RTS */
                sci_set_rts(port, 1);
@@ -2187,8 +2185,8 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
        }
 
        uart_port_lock_irqsave(port, &flags);
-       scsptr = serial_port_in(port, SCSPTR);
-       scscr = serial_port_in(port, SCSCR);
+       scsptr = sci_serial_in(port, SCSPTR);
+       scscr = sci_serial_in(port, SCSCR);
 
        if (break_state == -1) {
                scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
@@ -2198,8 +2196,8 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
                scscr |= SCSCR_TE;
        }
 
-       serial_port_out(port, SCSPTR, scsptr);
-       serial_port_out(port, SCSCR, scscr);
+       sci_serial_out(port, SCSPTR, scsptr);
+       sci_serial_out(port, SCSCR, scscr);
        uart_port_unlock_irqrestore(port, flags);
 }
 
@@ -2239,9 +2237,9 @@ static void sci_shutdown(struct uart_port *port)
         * Stop RX and TX, disable related interrupts, keep clock source
         * and HSCIF TOT bits
         */
-       scr = serial_port_in(port, SCSCR);
-       serial_port_out(port, SCSCR, scr &
-                       (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot));
+       scr = sci_serial_in(port, SCSCR);
+       sci_serial_out(port, SCSCR,
+                      scr & (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot));
        uart_port_unlock_irqrestore(port, flags);
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -2390,19 +2388,19 @@ static void sci_reset(struct uart_port *port)
        unsigned int status;
        struct sci_port *s = to_sci_port(port);
 
-       serial_port_out(port, SCSCR, s->hscif_tot);     /* TE=0, RE=0, CKE1=0 */
+       sci_serial_out(port, SCSCR, s->hscif_tot);      /* TE=0, RE=0, CKE1=0 */
 
        reg = sci_getreg(port, SCFCR);
        if (reg->size)
-               serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
+               sci_serial_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
 
        sci_clear_SCxSR(port,
                        SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) &
                        SCxSR_BREAK_CLEAR(port));
        if (sci_getreg(port, SCLSR)->size) {
-               status = serial_port_in(port, SCLSR);
+               status = sci_serial_in(port, SCLSR);
                status &= ~(SCLSR_TO | SCLSR_ORER);
-               serial_port_out(port, SCLSR, status);
+               sci_serial_out(port, SCLSR, status);
        }
 
        if (s->rx_trigger > 1) {
@@ -2540,8 +2538,8 @@ done:
         * It controls the mux to select (H)SCK or frequency divided clock.
         */
        if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) {
-               serial_port_out(port, SCDL, dl);
-               serial_port_out(port, SCCKS, sccks);
+               sci_serial_out(port, SCDL, dl);
+               sci_serial_out(port, SCCKS, sccks);
        }
 
        uart_port_lock_irqsave(port, &flags);
@@ -2554,7 +2552,7 @@ done:
        bits = tty_get_frame_size(termios->c_cflag);
 
        if (sci_getreg(port, SEMR)->size)
-               serial_port_out(port, SEMR, 0);
+               sci_serial_out(port, SEMR, 0);
 
        if (best_clk >= 0) {
                if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
@@ -2569,9 +2567,9 @@ done:
                        case 27: smr_val |= SCSMR_SRC_27; break;
                        }
                smr_val |= cks;
-               serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
-               serial_port_out(port, SCSMR, smr_val);
-               serial_port_out(port, SCBRR, brr);
+               sci_serial_out(port, SCSCR, scr_val | s->hscif_tot);
+               sci_serial_out(port, SCSMR, smr_val);
+               sci_serial_out(port, SCBRR, brr);
                if (sci_getreg(port, HSSRR)->size) {
                        unsigned int hssrr = srr | HSCIF_SRE;
                        /* Calculate deviation from intended rate at the
@@ -2593,7 +2591,7 @@ done:
                                         HSCIF_SRHP_MASK;
                                hssrr |= HSCIF_SRDE;
                        }
-                       serial_port_out(port, HSSRR, hssrr);
+                       sci_serial_out(port, HSSRR, hssrr);
                }
 
                /* Wait one bit interval */
@@ -2601,10 +2599,10 @@ done:
        } else {
                /* Don't touch the bit rate configuration */
                scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0);
-               smr_val |= serial_port_in(port, SCSMR) &
+               smr_val |= sci_serial_in(port, SCSMR) &
                           (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS);
-               serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
-               serial_port_out(port, SCSMR, smr_val);
+               sci_serial_out(port, SCSCR, scr_val | s->hscif_tot);
+               sci_serial_out(port, SCSMR, smr_val);
        }
 
        sci_init_pins(port, termios->c_cflag);
@@ -2613,7 +2611,7 @@ done:
        s->autorts = false;
        reg = sci_getreg(port, SCFCR);
        if (reg->size) {
-               unsigned short ctrl = serial_port_in(port, SCFCR);
+               unsigned short ctrl = sci_serial_in(port, SCFCR);
 
                if ((port->flags & UPF_HARD_FLOW) &&
                    (termios->c_cflag & CRTSCTS)) {
@@ -2630,7 +2628,7 @@ done:
                 */
                ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);
 
-               serial_port_out(port, SCFCR, ctrl);
+               sci_serial_out(port, SCFCR, ctrl);
        }
        if (port->flags & UPF_HARD_FLOW) {
                /* Refresh (Auto) RTS */
@@ -2645,7 +2643,7 @@ done:
        if (port->type != PORT_SCI)
                scr_val |= SCSCR_TE;
        scr_val |= SCSCR_RE | (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
-       serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
+       sci_serial_out(port, SCSCR, scr_val | s->hscif_tot);
        if ((srr + 1 == 5) &&
            (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) {
                /*
@@ -3017,9 +3015,6 @@ static int sci_init_single(struct platform_device *dev,
        port->irq               = sci_port->irqs[SCIx_RXI_IRQ];
        port->irqflags          = 0;
 
-       port->serial_in         = sci_serial_in;
-       port->serial_out        = sci_serial_out;
-
        return 0;
 }
 
@@ -3056,21 +3051,21 @@ static void serial_console_write(struct console *co, const char *s,
                uart_port_lock_irqsave(port, &flags);
 
        /* first save SCSCR then disable interrupts, keep clock source */
-       ctrl = serial_port_in(port, SCSCR);
+       ctrl = sci_serial_in(port, SCSCR);
        ctrl_temp = SCSCR_RE | SCSCR_TE |
                    (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) |
                    (ctrl & (SCSCR_CKE1 | SCSCR_CKE0));
-       serial_port_out(port, SCSCR, ctrl_temp | sci_port->hscif_tot);
+       sci_serial_out(port, SCSCR, ctrl_temp | sci_port->hscif_tot);
 
        uart_console_write(port, s, count, serial_console_putchar);
 
        /* wait until fifo is empty and last bit has been transmitted */
        bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
-       while ((serial_port_in(port, SCxSR) & bits) != bits)
+       while ((sci_serial_in(port, SCxSR) & bits) != bits)
                cpu_relax();
 
        /* restore the SCSCR */
-       serial_port_out(port, SCSCR, ctrl);
+       sci_serial_out(port, SCSCR, ctrl);
 
        if (locked)
                uart_port_unlock_irqrestore(port, flags);
@@ -3503,8 +3498,6 @@ static int __init early_console_setup(struct earlycon_device *device,
        if (!device->port.membase)
                return -ENODEV;
 
-       device->port.serial_in = sci_serial_in;
-       device->port.serial_out = sci_serial_out;
        device->port.type = type;
        memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port));
        port_cfg.type = type;
index a4cc569a78a256746e0e4cc262fc2abfe8ad5214..0670fd9f84967a151ebb2a3fbae6add7f918d003 100644 (file)
@@ -412,7 +412,8 @@ static void __ssp_receive_chars(struct sifive_serial_port *ssp)
                        break;
 
                ssp->port.icount.rx++;
-               uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL);
+               if (!uart_prepare_sysrq_char(&ssp->port, ch))
+                       uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL);
        }
 
        tty_flip_buffer_push(&ssp->port.state->port);
@@ -534,7 +535,7 @@ static irqreturn_t sifive_serial_irq(int irq, void *dev_id)
        if (ip & SIFIVE_SERIAL_IP_TXWM_MASK)
                __ssp_transmit_chars(ssp);
 
-       uart_port_unlock(&ssp->port);
+       uart_unlock_and_check_sysrq(&ssp->port);
 
        return IRQ_HANDLED;
 }
@@ -791,13 +792,10 @@ static void sifive_serial_console_write(struct console *co, const char *s,
        if (!ssp)
                return;
 
-       local_irq_save(flags);
-       if (ssp->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = uart_port_trylock(&ssp->port);
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(&ssp->port, &flags);
        else
-               uart_port_lock(&ssp->port);
+               uart_port_lock_irqsave(&ssp->port, &flags);
 
        ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS);
        __ssp_writel(0, SIFIVE_SERIAL_IE_OFFS, ssp);
@@ -807,8 +805,7 @@ static void sifive_serial_console_write(struct console *co, const char *s,
        __ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp);
 
        if (locked)
-               uart_port_unlock(&ssp->port);
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(&ssp->port, flags);
 }
 
 static int sifive_serial_console_setup(struct console *co, char *options)
index bbb5595d7e24cc22a195e7520366ac0e43e94e3c..a23e5955184885fa51dbdf302b9b39968561aaa2 100644 (file)
@@ -465,6 +465,7 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
                            const struct ktermios *old)
 {
        struct asc_port *ascport = to_asc_port(port);
+       bool manual_rts, toggle_rts = false;
        struct gpio_desc *gpiod;
        unsigned int baud;
        u32 ctrl_val;
@@ -518,25 +519,13 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
 
                /* If flow-control selected, stop handling RTS manually */
                if (ascport->rts) {
-                       devm_gpiod_put(port->dev, ascport->rts);
-                       ascport->rts = NULL;
-
-                       pinctrl_select_state(ascport->pinctrl,
-                                            ascport->states[DEFAULT]);
+                       toggle_rts = true;
+                       manual_rts = false;
                }
        } else {
                /* If flow-control disabled, it's safe to handle RTS manually */
-               if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) {
-                       pinctrl_select_state(ascport->pinctrl,
-                                            ascport->states[NO_HW_FLOWCTRL]);
-
-                       gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW);
-                       if (!IS_ERR(gpiod)) {
-                               gpiod_set_consumer_name(gpiod,
-                                               port->dev->of_node->name);
-                               ascport->rts = gpiod;
-                       }
-               }
+               if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL])
+                       manual_rts = toggle_rts = true;
        }
 
        if ((baud < 19200) && !ascport->force_m1) {
@@ -595,6 +584,25 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
        asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN));
 
        uart_port_unlock_irqrestore(port, flags);
+
+       if (toggle_rts) {
+               if (manual_rts) {
+                       pinctrl_select_state(ascport->pinctrl,
+                                            ascport->states[NO_HW_FLOWCTRL]);
+
+                       gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW);
+                       if (!IS_ERR(gpiod)) {
+                               gpiod_set_consumer_name(gpiod,
+                                                       port->dev->of_node->name);
+                               ascport->rts = gpiod;
+                       }
+               } else {
+                               devm_gpiod_put(port->dev, ascport->rts);
+                               ascport->rts = NULL;
+                               pinctrl_select_state(ascport->pinctrl,
+                                                    ascport->states[DEFAULT]);
+               }
+       }
 }
 
 static const char *asc_type(struct uart_port *port)
index 693e932d6feb5842467d1408e04c8d574342cb1f..58d169e5c1db03b910686ac2a229116644f0d6e9 100644 (file)
@@ -9,6 +9,7 @@
  * Inspired by st-asc.c from STMicroelectronics (c)
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/console.h>
 #include <linux/delay.h>
 /* Register offsets */
 static struct stm32_usart_info __maybe_unused stm32f4_info = {
        .ofs = {
-               .isr    = 0x00,
-               .rdr    = 0x04,
-               .tdr    = 0x04,
-               .brr    = 0x08,
-               .cr1    = 0x0c,
-               .cr2    = 0x10,
-               .cr3    = 0x14,
-               .gtpr   = 0x18,
-               .rtor   = UNDEF_REG,
-               .rqr    = UNDEF_REG,
-               .icr    = UNDEF_REG,
+               .isr            = 0x00,
+               .rdr            = 0x04,
+               .tdr            = 0x04,
+               .brr            = 0x08,
+               .cr1            = 0x0c,
+               .cr2            = 0x10,
+               .cr3            = 0x14,
+               .gtpr           = 0x18,
+               .rtor           = UNDEF_REG,
+               .rqr            = UNDEF_REG,
+               .icr            = UNDEF_REG,
+               .presc          = UNDEF_REG,
+               .hwcfgr1        = UNDEF_REG,
        },
        .cfg = {
                .uart_enable_bit = 13,
                .has_7bits_data = false,
-               .fifosize = 1,
        }
 };
 
 static struct stm32_usart_info __maybe_unused stm32f7_info = {
        .ofs = {
-               .cr1    = 0x00,
-               .cr2    = 0x04,
-               .cr3    = 0x08,
-               .brr    = 0x0c,
-               .gtpr   = 0x10,
-               .rtor   = 0x14,
-               .rqr    = 0x18,
-               .isr    = 0x1c,
-               .icr    = 0x20,
-               .rdr    = 0x24,
-               .tdr    = 0x28,
+               .cr1            = 0x00,
+               .cr2            = 0x04,
+               .cr3            = 0x08,
+               .brr            = 0x0c,
+               .gtpr           = 0x10,
+               .rtor           = 0x14,
+               .rqr            = 0x18,
+               .isr            = 0x1c,
+               .icr            = 0x20,
+               .rdr            = 0x24,
+               .tdr            = 0x28,
+               .presc          = UNDEF_REG,
+               .hwcfgr1        = UNDEF_REG,
        },
        .cfg = {
                .uart_enable_bit = 0,
                .has_7bits_data = true,
                .has_swap = true,
-               .fifosize = 1,
        }
 };
 
 static struct stm32_usart_info __maybe_unused stm32h7_info = {
        .ofs = {
-               .cr1    = 0x00,
-               .cr2    = 0x04,
-               .cr3    = 0x08,
-               .brr    = 0x0c,
-               .gtpr   = 0x10,
-               .rtor   = 0x14,
-               .rqr    = 0x18,
-               .isr    = 0x1c,
-               .icr    = 0x20,
-               .rdr    = 0x24,
-               .tdr    = 0x28,
+               .cr1            = 0x00,
+               .cr2            = 0x04,
+               .cr3            = 0x08,
+               .brr            = 0x0c,
+               .gtpr           = 0x10,
+               .rtor           = 0x14,
+               .rqr            = 0x18,
+               .isr            = 0x1c,
+               .icr            = 0x20,
+               .rdr            = 0x24,
+               .tdr            = 0x28,
+               .presc          = 0x2c,
+               .hwcfgr1        = 0x3f0,
        },
        .cfg = {
                .uart_enable_bit = 0,
@@ -100,7 +105,6 @@ static struct stm32_usart_info __maybe_unused stm32h7_info = {
                .has_swap = true,
                .has_wakeup = true,
                .has_fifo = true,
-               .fifosize = 16,
        }
 };
 
@@ -1147,6 +1151,8 @@ static void stm32_usart_shutdown(struct uart_port *port)
        free_irq(port->irq, port);
 }
 
+static const unsigned int stm32_usart_presc_val[] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256};
+
 static void stm32_usart_set_termios(struct uart_port *port,
                                    struct ktermios *termios,
                                    const struct ktermios *old)
@@ -1155,17 +1161,19 @@ static void stm32_usart_set_termios(struct uart_port *port,
        const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
        const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
        struct serial_rs485 *rs485conf = &port->rs485;
-       unsigned int baud, bits;
+       unsigned int baud, bits, uart_clk, uart_clk_pres;
        u32 usartdiv, mantissa, fraction, oversampling;
        tcflag_t cflag = termios->c_cflag;
-       u32 cr1, cr2, cr3, isr;
+       u32 cr1, cr2, cr3, isr, brr, presc;
        unsigned long flags;
        int ret;
 
        if (!stm32_port->hw_flow_control)
                cflag &= ~CRTSCTS;
 
-       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 8);
+       uart_clk = clk_get_rate(stm32_port->clk);
+
+       baud = uart_get_baud_rate(port, termios, old, 0, uart_clk / 8);
 
        uart_port_lock_irqsave(port, &flags);
 
@@ -1267,27 +1275,48 @@ static void stm32_usart_set_termios(struct uart_port *port,
                cr3 |= USART_CR3_CTSE | USART_CR3_RTSE;
        }
 
-       usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
+       for (presc = 0; presc <= USART_PRESC_MAX; presc++) {
+               uart_clk_pres = DIV_ROUND_CLOSEST(uart_clk, stm32_usart_presc_val[presc]);
+               usartdiv = DIV_ROUND_CLOSEST(uart_clk_pres, baud);
 
-       /*
-        * The USART supports 16 or 8 times oversampling.
-        * By default we prefer 16 times oversampling, so that the receiver
-        * has a better tolerance to clock deviations.
-        * 8 times oversampling is only used to achieve higher speeds.
-        */
-       if (usartdiv < 16) {
-               oversampling = 8;
-               cr1 |= USART_CR1_OVER8;
-               stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8);
-       } else {
-               oversampling = 16;
-               cr1 &= ~USART_CR1_OVER8;
-               stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_OVER8);
+               /*
+                * The USART supports 16 or 8 times oversampling.
+                * By default we prefer 16 times oversampling, so that the receiver
+                * has a better tolerance to clock deviations.
+                * 8 times oversampling is only used to achieve higher speeds.
+                */
+               if (usartdiv < 16) {
+                       oversampling = 8;
+                       cr1 |= USART_CR1_OVER8;
+                       stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8);
+               } else {
+                       oversampling = 16;
+                       cr1 &= ~USART_CR1_OVER8;
+                       stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_OVER8);
+               }
+
+               mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT;
+               fraction = usartdiv % oversampling;
+               brr = mantissa | fraction;
+
+               if (FIELD_FIT(USART_BRR_MASK, brr)) {
+                       if (ofs->presc != UNDEF_REG) {
+                               port->uartclk = uart_clk_pres;
+                               writel_relaxed(presc, port->membase + ofs->presc);
+                       } else if (presc) {
+                               /* We need a prescaler but we don't have it (STM32F4, STM32F7) */
+                               dev_err(port->dev,
+                                       "unable to set baudrate, input clock is too high");
+                       }
+                       break;
+               } else if (presc == USART_PRESC_MAX) {
+                       /* Even with prescaler and brr at max value we can't set baudrate */
+                       dev_err(port->dev, "unable to set baudrate, input clock is too high");
+                       break;
+               }
        }
 
-       mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT;
-       fraction = usartdiv % oversampling;
-       writel_relaxed(mantissa | fraction, port->membase + ofs->brr);
+       writel_relaxed(brr, port->membase + ofs->brr);
 
        uart_update_timeout(port, cflag, baud);
 
@@ -1471,37 +1500,57 @@ static const struct uart_ops stm32_uart_ops = {
 #endif /* CONFIG_CONSOLE_POLL */
 };
 
-/*
- * STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG)
- * Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case,
- * RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE.
- * So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1.
- */
-static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 };
+struct stm32_usart_thresh_ratio {
+       int mul;
+       int div;
+};
+
+static const struct stm32_usart_thresh_ratio stm32h7_usart_fifo_thresh_cfg[] = {
+       {1, 8}, {1, 4}, {1, 2}, {3, 4}, {7, 8}, {1, 1} };
+
+static int stm32_usart_get_thresh_value(u32 fifo_size, int index)
+{
+       return fifo_size * stm32h7_usart_fifo_thresh_cfg[index].mul /
+               stm32h7_usart_fifo_thresh_cfg[index].div;
+}
 
-static void stm32_usart_get_ftcfg(struct platform_device *pdev, const char *p,
-                                 int *ftcfg)
+static int stm32_usart_get_ftcfg(struct platform_device *pdev, struct stm32_port *stm32port,
+                                const char *p, int *ftcfg)
 {
-       u32 bytes, i;
+       const struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
+       u32 bytes, i, cfg8;
+       int fifo_size;
+
+       if (WARN_ON(ofs->hwcfgr1 == UNDEF_REG))
+               return 1;
+
+       cfg8 = FIELD_GET(USART_HWCFGR1_CFG8,
+                        readl_relaxed(stm32port->port.membase + ofs->hwcfgr1));
+
+       /* On STM32H7, hwcfgr is not present, so returned value will be 0 */
+       fifo_size = cfg8 ? 1 << cfg8 : STM32H7_USART_FIFO_SIZE;
 
-       /* DT option to get RX & TX FIFO threshold (default to 8 bytes) */
+       /* DT option to get RX & TX FIFO threshold (default to half fifo size) */
        if (of_property_read_u32(pdev->dev.of_node, p, &bytes))
-               bytes = 8;
+               bytes = fifo_size / 2;
 
-       for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++)
-               if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes)
+       if (bytes < stm32_usart_get_thresh_value(fifo_size, 0)) {
+               *ftcfg = -EINVAL;
+               return fifo_size;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++) {
+               if (stm32_usart_get_thresh_value(fifo_size, i) >= bytes)
                        break;
+       }
        if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg))
                i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1;
 
-       dev_dbg(&pdev->dev, "%s set to %d bytes\n", p,
-               stm32h7_usart_fifo_thresh_cfg[i]);
+       dev_dbg(&pdev->dev, "%s set to %d/%d bytes\n", p,
+               stm32_usart_get_thresh_value(fifo_size, i), fifo_size);
 
-       /* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */
-       if (i)
-               *ftcfg = i - 1;
-       else
-               *ftcfg = -EINVAL;
+       *ftcfg = i;
+       return fifo_size;
 }
 
 static void stm32_usart_deinit_port(struct stm32_port *stm32port)
@@ -1531,7 +1580,6 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
        port->flags     = UPF_BOOT_AUTOCONF;
        port->ops       = &stm32_uart_ops;
        port->dev       = &pdev->dev;
-       port->fifosize  = stm32port->info->cfg.fifosize;
        port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE);
        port->irq = irq;
        port->rs485_config = stm32_usart_config_rs485;
@@ -1547,14 +1595,6 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
        stm32port->swap = stm32port->info->cfg.has_swap &&
                of_property_read_bool(pdev->dev.of_node, "rx-tx-swap");
 
-       stm32port->fifoen = stm32port->info->cfg.has_fifo;
-       if (stm32port->fifoen) {
-               stm32_usart_get_ftcfg(pdev, "rx-threshold",
-                                     &stm32port->rxftcfg);
-               stm32_usart_get_ftcfg(pdev, "tx-threshold",
-                                     &stm32port->txftcfg);
-       }
-
        port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
        if (IS_ERR(port->membase))
                return PTR_ERR(port->membase);
@@ -1577,6 +1617,15 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
                goto err_clk;
        }
 
+       stm32port->fifoen = stm32port->info->cfg.has_fifo;
+       if (stm32port->fifoen) {
+               stm32_usart_get_ftcfg(pdev, stm32port, "rx-threshold", &stm32port->rxftcfg);
+               port->fifosize = stm32_usart_get_ftcfg(pdev, stm32port, "tx-threshold",
+                                                      &stm32port->txftcfg);
+       } else {
+               port->fifosize = 1;
+       }
+
        stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0);
        if (IS_ERR(stm32port->gpios)) {
                ret = PTR_ERR(stm32port->gpios);
index f59f831b2a10c4883030acbee52085c64469e23e..af20258ccc7a0fcc57a541b37efcc9848290e141 100644 (file)
@@ -9,17 +9,19 @@
 #define DRIVER_NAME "stm32-usart"
 
 struct stm32_usart_offsets {
-       u8 cr1;
-       u8 cr2;
-       u8 cr3;
-       u8 brr;
-       u8 gtpr;
-       u8 rtor;
-       u8 rqr;
-       u8 isr;
-       u8 icr;
-       u8 rdr;
-       u8 tdr;
+       u16 cr1;
+       u16 cr2;
+       u16 cr3;
+       u16 brr;
+       u16 gtpr;
+       u16 rtor;
+       u16 rqr;
+       u16 isr;
+       u16 icr;
+       u16 rdr;
+       u16 tdr;
+       u16 presc;
+       u16 hwcfgr1;
 };
 
 struct stm32_usart_config {
@@ -28,7 +30,6 @@ struct stm32_usart_config {
        bool has_swap;
        bool has_wakeup;
        bool has_fifo;
-       int fifosize;
 };
 
 struct stm32_usart_info {
@@ -36,7 +37,7 @@ struct stm32_usart_info {
        struct stm32_usart_config cfg;
 };
 
-#define UNDEF_REG 0xff
+#define UNDEF_REG 0xffff
 
 /* USART_SR (F4) / USART_ISR (F7) */
 #define USART_SR_PE            BIT(0)
@@ -71,6 +72,7 @@ struct stm32_usart_info {
 #define USART_BRR_DIV_M_MASK   GENMASK(15, 4)
 #define USART_BRR_DIV_M_SHIFT  4
 #define USART_BRR_04_R_SHIFT   1
+#define USART_BRR_MASK         (USART_BRR_DIV_M_MASK | USART_BRR_DIV_F_MASK)
 
 /* USART_CR1 */
 #define USART_CR1_SBK          BIT(0)
@@ -176,8 +178,16 @@ struct stm32_usart_info {
 #define USART_ICR_CMCF         BIT(17)         /* F7 */
 #define USART_ICR_WUCF         BIT(20)         /* H7 */
 
+/* USART_PRESC */
+#define USART_PRESC            GENMASK(3, 0)   /* H7 */
+#define USART_PRESC_MAX                0b1011
+
+/* USART_HWCFCR1 */
+#define USART_HWCFGR1_CFG8     GENMASK(31, 28) /* MP1 */
+
 #define STM32_SERIAL_NAME "ttySTM"
-#define STM32_MAX_PORTS 8
+#define STM32_MAX_PORTS 9
+#define STM32H7_USART_FIFO_SIZE 16
 
 #define RX_BUF_L 4096           /* dma rx buffer length     */
 #define RX_BUF_P (RX_BUF_L / 2)         /* dma rx buffer period     */
index 99f5285819d4b22645d6e706adfe2be8d69a8ead..f5e29eb4a4ce441911494795aa00fb1221ad17e6 100644 (file)
@@ -260,7 +260,7 @@ static void receive_chars(struct uart_port *port)
                if (port->ignore_status_mask & SUP_DUMMY_READ)
                        goto ignore_char;
 
-               if (uart_handle_sysrq_char(port, ch))
+               if (uart_prepare_sysrq_char(port, ch))
                        goto ignore_char;
 
                uart_insert_char(port, lsr, SUP_UART_LSR_OE, ch, flag);
@@ -287,7 +287,7 @@ static irqreturn_t sunplus_uart_irq(int irq, void *args)
        if (isc & SUP_UART_ISC_TX)
                transmit_chars(port);
 
-       uart_port_unlock(port);
+       uart_unlock_and_check_sysrq(port);
 
        return IRQ_HANDLED;
 }
@@ -512,22 +512,16 @@ static void sunplus_console_write(struct console *co,
        unsigned long flags;
        int locked = 1;
 
-       local_irq_save(flags);
-
-       if (sunplus_console_ports[co->index]->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = uart_port_trylock(&sunplus_console_ports[co->index]->port);
+       if (oops_in_progress)
+               locked = uart_port_trylock_irqsave(&sunplus_console_ports[co->index]->port, &flags);
        else
-               uart_port_lock(&sunplus_console_ports[co->index]->port);
+               uart_port_lock_irqsave(&sunplus_console_ports[co->index]->port, &flags);
 
        uart_console_write(&sunplus_console_ports[co->index]->port, s, count,
                           sunplus_uart_console_putchar);
 
        if (locked)
-               uart_port_unlock(&sunplus_console_ports[co->index]->port);
-
-       local_irq_restore(flags);
+               uart_port_unlock_irqrestore(&sunplus_console_ports[co->index]->port, flags);
 }
 
 static int __init sunplus_console_setup(struct console *co, char *options)
index 920762d7b4a4b2607f6ec9b2b7981af803b65361..5f48ec37cb25ff2e9b55950e5a7cfee7d35397bf 100644 (file)
@@ -22,7 +22,9 @@
 #include <linux/of.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
-#include <linux/iopoll.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
 
 #define CDNS_UART_TTY_NAME     "ttyPS"
 #define CDNS_UART_NAME         "xuartps"
@@ -193,6 +195,9 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255");
  * @clk_rate_change_nb:        Notifier block for clock changes
  * @quirks:            Flags for RXBS support.
  * @cts_override:      Modem control state override
+ * @gpiod_rts:         Pointer to the gpio descriptor
+ * @rs485_tx_started:  RS485 tx state
+ * @tx_timer:          Timer for tx
  */
 struct cdns_uart {
        struct uart_port        *port;
@@ -203,10 +208,21 @@ struct cdns_uart {
        struct notifier_block   clk_rate_change_nb;
        u32                     quirks;
        bool cts_override;
+       struct gpio_desc        *gpiod_rts;
+       bool                    rs485_tx_started;
+       struct hrtimer          tx_timer;
 };
 struct cdns_platform_data {
        u32 quirks;
 };
+
+struct serial_rs485 cdns_rs485_supported = {
+       .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND |
+                SER_RS485_RTS_AFTER_SEND,
+       .delay_rts_before_send = 1,
+       .delay_rts_after_send = 1,
+};
+
 #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \
                clk_rate_change_nb)
 
@@ -306,17 +322,114 @@ static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus)
 }
 
 /**
- * cdns_uart_handle_tx - Handle the bytes to be Txed.
+ * cdns_rts_gpio_enable - Configure RTS/GPIO to high/low
+ * @cdns_uart: Handle to the cdns_uart
+ * @enable: Value to be set to RTS/GPIO
+ */
+static void cdns_rts_gpio_enable(struct cdns_uart *cdns_uart, bool enable)
+{
+       u32 val;
+
+       if (cdns_uart->gpiod_rts) {
+               gpiod_set_value(cdns_uart->gpiod_rts, enable);
+       } else {
+               val = readl(cdns_uart->port->membase + CDNS_UART_MODEMCR);
+               if (enable)
+                       val |= CDNS_UART_MODEMCR_RTS;
+               else
+                       val &= ~CDNS_UART_MODEMCR_RTS;
+               writel(val, cdns_uart->port->membase + CDNS_UART_MODEMCR);
+       }
+}
+
+/**
+ * cdns_rs485_tx_setup - Tx setup specific to rs485
+ * @cdns_uart: Handle to the cdns_uart
+ */
+static void cdns_rs485_tx_setup(struct cdns_uart *cdns_uart)
+{
+       bool enable;
+
+       enable = cdns_uart->port->rs485.flags & SER_RS485_RTS_ON_SEND;
+       cdns_rts_gpio_enable(cdns_uart, enable);
+
+       cdns_uart->rs485_tx_started = true;
+}
+
+/**
+ * cdns_rs485_rx_setup - Rx setup specific to rs485
+ * @cdns_uart: Handle to the cdns_uart
+ */
+static void cdns_rs485_rx_setup(struct cdns_uart *cdns_uart)
+{
+       bool enable;
+
+       enable = cdns_uart->port->rs485.flags & SER_RS485_RTS_AFTER_SEND;
+       cdns_rts_gpio_enable(cdns_uart, enable);
+
+       cdns_uart->rs485_tx_started = false;
+}
+
+/**
+ * cdns_uart_tx_empty -  Check whether TX is empty
+ * @port: Handle to the uart port structure
+ *
+ * Return: TIOCSER_TEMT on success, 0 otherwise
+ */
+static unsigned int cdns_uart_tx_empty(struct uart_port *port)
+{
+       unsigned int status;
+
+       status = readl(port->membase + CDNS_UART_SR);
+       status &= (CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE);
+       return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0;
+}
+
+/**
+ * cdns_rs485_rx_callback - Timer rx callback handler for rs485.
+ * @t: Handle to the hrtimer structure
+ */
+static enum hrtimer_restart cdns_rs485_rx_callback(struct hrtimer *t)
+{
+       struct cdns_uart *cdns_uart = container_of(t, struct cdns_uart, tx_timer);
+
+       /*
+        * Default Rx should be setup, because Rx signaling path
+        * need to enable to receive data.
+        */
+       cdns_rs485_rx_setup(cdns_uart);
+
+       return HRTIMER_NORESTART;
+}
+
+/**
+ * cdns_calc_after_tx_delay - calculate delay required for after tx.
+ * @cdns_uart: Handle to the cdns_uart
+ */
+static u64 cdns_calc_after_tx_delay(struct cdns_uart *cdns_uart)
+{
+       /*
+        * Frame time + stop bit time + rs485.delay_rts_after_send
+        */
+       return cdns_uart->port->frame_time
+              + DIV_ROUND_UP(cdns_uart->port->frame_time, 7)
+              + (u64)cdns_uart->port->rs485.delay_rts_after_send * NSEC_PER_MSEC;
+}
+
+/**
+ * cdns_uart_handle_tx - Handle the bytes to be transmitted.
  * @dev_id: Id of the UART port
  * Return: None
  */
 static void cdns_uart_handle_tx(void *dev_id)
 {
        struct uart_port *port = (struct uart_port *)dev_id;
+       struct cdns_uart *cdns_uart = port->private_data;
        struct circ_buf *xmit = &port->state->xmit;
        unsigned int numbytes;
 
-       if (uart_circ_empty(xmit)) {
+       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+               /* Disable the TX Empty interrupt */
                writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR);
                return;
        }
@@ -332,6 +445,16 @@ static void cdns_uart_handle_tx(void *dev_id)
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(port);
+
+       /* Enable the TX Empty interrupt */
+       writel(CDNS_UART_IXR_TXEMPTY, cdns_uart->port->membase + CDNS_UART_IER);
+
+       if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED &&
+           (uart_circ_empty(xmit) || uart_tx_stopped(port))) {
+               cdns_uart->tx_timer.function = &cdns_rs485_rx_callback;
+               hrtimer_start(&cdns_uart->tx_timer,
+                             ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart)), HRTIMER_MODE_REL);
+       }
 }
 
 /**
@@ -564,6 +687,21 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
 }
 #endif
 
+/**
+ * cdns_rs485_tx_callback - Timer tx callback handler for rs485.
+ * @t: Handle to the hrtimer structure
+ */
+static enum hrtimer_restart cdns_rs485_tx_callback(struct hrtimer *t)
+{
+       struct cdns_uart *cdns_uart = container_of(t, struct cdns_uart, tx_timer);
+
+       uart_port_lock(cdns_uart->port);
+       cdns_uart_handle_tx(cdns_uart->port);
+       uart_port_unlock(cdns_uart->port);
+
+       return HRTIMER_NORESTART;
+}
+
 /**
  * cdns_uart_start_tx -  Start transmitting bytes
  * @port: Handle to the uart port structure
@@ -571,6 +709,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
 static void cdns_uart_start_tx(struct uart_port *port)
 {
        unsigned int status;
+       struct cdns_uart *cdns_uart = port->private_data;
 
        if (uart_tx_stopped(port))
                return;
@@ -587,12 +726,19 @@ static void cdns_uart_start_tx(struct uart_port *port)
        if (uart_circ_empty(&port->state->xmit))
                return;
 
+       /* Clear the TX Empty interrupt */
        writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR);
 
+       if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) {
+               if (!cdns_uart->rs485_tx_started) {
+                       cdns_uart->tx_timer.function = &cdns_rs485_tx_callback;
+                       cdns_rs485_tx_setup(cdns_uart);
+                       return hrtimer_start(&cdns_uart->tx_timer,
+                                            ms_to_ktime(port->rs485.delay_rts_before_send),
+                                            HRTIMER_MODE_REL);
+               }
+       }
        cdns_uart_handle_tx(port);
-
-       /* Enable the TX Empty interrupt */
-       writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER);
 }
 
 /**
@@ -602,6 +748,10 @@ static void cdns_uart_start_tx(struct uart_port *port)
 static void cdns_uart_stop_tx(struct uart_port *port)
 {
        unsigned int regval;
+       struct cdns_uart *cdns_uart = port->private_data;
+
+       if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED)
+               cdns_rs485_rx_setup(cdns_uart);
 
        regval = readl(port->membase + CDNS_UART_CR);
        regval |= CDNS_UART_CR_TX_DIS;
@@ -626,21 +776,6 @@ static void cdns_uart_stop_rx(struct uart_port *port)
        writel(regval, port->membase + CDNS_UART_CR);
 }
 
-/**
- * cdns_uart_tx_empty -  Check whether TX is empty
- * @port: Handle to the uart port structure
- *
- * Return: TIOCSER_TEMT on success, 0 otherwise
- */
-static unsigned int cdns_uart_tx_empty(struct uart_port *port)
-{
-       unsigned int status;
-
-       status = readl(port->membase + CDNS_UART_SR) &
-                      (CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE);
-       return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0;
-}
-
 /**
  * cdns_uart_break_ctl - Based on the input ctl we have to start or stop
  *                     transmitting char breaks
@@ -829,6 +964,9 @@ static int cdns_uart_startup(struct uart_port *port)
                (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST))
                cpu_relax();
 
+       if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED)
+               cdns_rs485_rx_setup(cdns_uart);
+
        /*
         * Clear the RX disable bit and then set the RX enable bit to enable
         * the receiver.
@@ -888,6 +1026,10 @@ static void cdns_uart_shutdown(struct uart_port *port)
 {
        int status;
        unsigned long flags;
+       struct cdns_uart *cdns_uart = port->private_data;
+
+       if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED)
+               hrtimer_cancel(&cdns_uart->tx_timer);
 
        uart_port_lock_irqsave(port, &flags);
 
@@ -1033,6 +1175,8 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
        if (mctrl & TIOCM_RTS)
                val |= CDNS_UART_MODEMCR_RTS;
+       if (cdns_uart_data->gpiod_rts)
+               gpiod_set_value(cdns_uart_data->gpiod_rts, !(mctrl & TIOCM_RTS));
        if (mctrl & TIOCM_DTR)
                val |= CDNS_UART_MODEMCR_DTR;
        if (mctrl & TIOCM_LOOP)
@@ -1455,6 +1599,39 @@ MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
 /* Temporary variable for storing number of instances */
 static int instances;
 
+/**
+ * cdns_rs485_config - Called when an application calls TIOCSRS485 ioctl.
+ * @port: Pointer to the uart_port structure
+ * @termios: Pointer to the ktermios structure
+ * @rs485: Pointer to the serial_rs485 structure
+ *
+ * Return: 0
+ */
+static int cdns_rs485_config(struct uart_port *port, struct ktermios *termios,
+                            struct serial_rs485 *rs485)
+{
+       u32 val;
+       struct cdns_uart *cdns_uart = port->private_data;
+
+       if (rs485->flags & SER_RS485_ENABLED) {
+               dev_dbg(port->dev, "Setting UART to RS485\n");
+               /* Make sure auto RTS is disabled */
+               val = readl(port->membase + CDNS_UART_MODEMCR);
+               val &= ~CDNS_UART_MODEMCR_FCM;
+               writel(val, port->membase + CDNS_UART_MODEMCR);
+
+               /* Timer setup */
+               hrtimer_init(&cdns_uart->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+               cdns_uart->tx_timer.function = &cdns_rs485_tx_callback;
+
+               /* Disable transmitter and make Rx setup*/
+               cdns_uart_stop_tx(port);
+       } else {
+               hrtimer_cancel(&cdns_uart->tx_timer);
+       }
+       return 0;
+}
+
 /**
  * cdns_uart_probe - Platform driver probe
  * @pdev: Pointer to the platform device structure
@@ -1597,9 +1774,23 @@ static int cdns_uart_probe(struct platform_device *pdev)
        port->private_data = cdns_uart_data;
        port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG |
                        CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT;
+       port->rs485_config = cdns_rs485_config;
+       port->rs485_supported = cdns_rs485_supported;
        cdns_uart_data->port = port;
        platform_set_drvdata(pdev, port);
 
+       rc = uart_get_rs485_mode(port);
+       if (rc)
+               goto err_out_clk_notifier;
+
+       cdns_uart_data->gpiod_rts = devm_gpiod_get_optional(&pdev->dev, "rts",
+                                                           GPIOD_OUT_LOW);
+       if (IS_ERR(cdns_uart_data->gpiod_rts)) {
+               rc = PTR_ERR(cdns_uart_data->gpiod_rts);
+               dev_err(port->dev, "xuartps: devm_gpiod_get_optional failed\n");
+               goto err_out_clk_notifier;
+       }
+
        pm_runtime_use_autosuspend(&pdev->dev);
        pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
        pm_runtime_set_active(&pdev->dev);
@@ -1618,6 +1809,8 @@ static int cdns_uart_probe(struct platform_device *pdev)
                console_port = port;
        }
 #endif
+       if (cdns_uart_data->port->rs485.flags & SER_RS485_ENABLED)
+               cdns_rs485_rx_setup(cdns_uart_data);
 
        rc = uart_add_one_port(&cdns_uart_uart_driver, port);
        if (rc) {
@@ -1646,6 +1839,7 @@ err_out_pm_disable:
        pm_runtime_disable(&pdev->dev);
        pm_runtime_set_suspended(&pdev->dev);
        pm_runtime_dont_use_autosuspend(&pdev->dev);
+err_out_clk_notifier:
 #ifdef CONFIG_COMMON_CLK
        clk_notifier_unregister(cdns_uart_data->uartclk,
                        &cdns_uart_data->clk_rate_change_nb);
index f8883afbeeba6d5e305868252864e13692a49341..79f0ff94ce00da1b180d4f01cc26acab7159fdb6 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/errno.h>
 #include <linux/minmax.h>
 #include <linux/tty.h>
+#include <linux/tty_buffer.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 #include <linux/timer.h>
index b3dfe9d5717e3f798dc8b8f4d43e96d535e584d6..2c8ce8b592ed2dc5ae60a5adf72311c058742053 100644 (file)
@@ -5,9 +5,9 @@
 FONTMAPFILE = cp437.uni
 
 obj-$(CONFIG_VT)                       += vt_ioctl.o vc_screen.o \
-                                          selection.o keyboard.o
+                                          selection.o keyboard.o \
+                                          vt.o defkeymap.o
 obj-$(CONFIG_CONSOLE_TRANSLATIONS)     += consolemap.o consolemap_deftbl.o
-obj-$(CONFIG_HW_CONSOLE)               += vt.o defkeymap.o
 
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c
index 8967c3a0d9169a40c496a37b0fde281c341af3cd..564341f1a74f3f6b1b553bf8705fe34b62ed3b5a 100644 (file)
@@ -7,7 +7,7 @@
  *     'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)'
  *     'void clear_selection(void)'
  *     'int paste_selection(struct tty_struct *)'
- *     'int sel_loadlut(char __user *)'
+ *     'int sel_loadlut(u32 __user *)'
  *
  * Now that /dev/vcs exists, most of this can disappear again.
  */
@@ -73,10 +73,12 @@ sel_pos(int n, bool unicode)
 }
 
 /**
- *     clear_selection         -       remove current selection
+ * clear_selection - remove current selection
  *
- *     Remove the current selection highlight, if any from the console
- *     holding the selection. The caller must hold the console lock.
+ * Remove the current selection highlight, if any from the console holding the
+ * selection.
+ *
+ * Locking: The caller must hold the console lock.
  */
 void clear_selection(void)
 {
@@ -88,7 +90,7 @@ void clear_selection(void)
 }
 EXPORT_SYMBOL_GPL(clear_selection);
 
-bool vc_is_sel(struct vc_data *vc)
+bool vc_is_sel(const struct vc_data *vc)
 {
        return vc == vc_sel.cons;
 }
@@ -110,18 +112,25 @@ static inline int inword(const u32 c)
 }
 
 /**
- *     sel_loadlut()           -       load the LUT table
- *     @p: user table
+ * sel_loadlut() - load the LUT table
+ * @lut: user table
+ *
+ * Load the LUT table from user space. Make a temporary copy so a partial
+ * update doesn't make a mess.
  *
- *     Load the LUT table from user space. The caller must hold the console
- *     lock. Make a temporary copy so a partial update doesn't make a mess.
+ * Locking: The console lock is acquired.
  */
-int sel_loadlut(char __user *p)
+int sel_loadlut(u32 __user *lut)
 {
        u32 tmplut[ARRAY_SIZE(inwordLut)];
-       if (copy_from_user(tmplut, (u32 __user *)(p+4), sizeof(inwordLut)))
+
+       if (copy_from_user(tmplut, lut, sizeof(inwordLut)))
                return -EFAULT;
+
+       console_lock();
        memcpy(inwordLut, tmplut, sizeof(inwordLut));
+       console_unlock();
+
        return 0;
 }
 
@@ -166,14 +175,14 @@ static int store_utf8(u32 c, char *p)
 }
 
 /**
- *     set_selection_user      -       set the current selection.
- *     @sel: user selection info
- *     @tty: the console tty
+ * set_selection_user - set the current selection.
+ * @sel: user selection info
+ * @tty: the console tty
  *
- *     Invoked by the ioctl handle for the vt layer.
+ * Invoked by the ioctl handle for the vt layer.
  *
- *     The entire selection process is managed under the console_lock. It's
- *      a lot under the lock but its hardly a performance path
+ * Locking: The entire selection process is managed under the console_lock.
+ * It's a lot under the lock but its hardly a performance path.
  */
 int set_selection_user(const struct tiocl_selection __user *sel,
                       struct tty_struct *tty)
index 38a765eadbe2bc81494f1fbd7a63b50b87101f08..9b5b98dfc8b4017289db11d3a42780760cad38fe 100644 (file)
@@ -145,7 +145,7 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y);
 static void save_cur(struct vc_data *vc);
 static void reset_terminal(struct vc_data *vc, int do_clear);
 static void con_flush_chars(struct tty_struct *tty);
-static int set_vesa_blanking(char __user *p);
+static int set_vesa_blanking(u8 __user *mode);
 static void set_cursor(struct vc_data *vc);
 static void hide_cursor(struct vc_data *vc);
 static void console_callback(struct work_struct *ignored);
@@ -175,7 +175,7 @@ int do_poke_blanked_console;
 int console_blanked;
 EXPORT_SYMBOL(console_blanked);
 
-static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
+static enum vesa_blank_mode vesa_blank_mode;
 static int vesa_off_interval;
 static int blankinterval;
 core_param(consoleblank, blankinterval, int, 0444);
@@ -286,18 +286,20 @@ static inline bool con_should_update(const struct vc_data *vc)
        return con_is_visible(vc) && !console_blanked;
 }
 
-static inline unsigned short *screenpos(const struct vc_data *vc, int offset,
-               bool viewed)
+static inline u16 *screenpos(const struct vc_data *vc, unsigned int offset,
+                            bool viewed)
 {
-       unsigned short *p;
-       
-       if (!viewed)
-               p = (unsigned short *)(vc->vc_origin + offset);
-       else if (!vc->vc_sw->con_screen_pos)
-               p = (unsigned short *)(vc->vc_visible_origin + offset);
+       unsigned long origin = viewed ? vc->vc_visible_origin : vc->vc_origin;
+
+       return (u16 *)(origin + offset);
+}
+
+static void con_putc(struct vc_data *vc, u16 ca, unsigned int y, unsigned int x)
+{
+       if (vc->vc_sw->con_putc)
+               vc->vc_sw->con_putc(vc, ca, y, x);
        else
-               p = vc->vc_sw->con_screen_pos(vc, offset);
-       return p;
+               vc->vc_sw->con_putcs(vc, &ca, 1, y, x);
 }
 
 /* Called  from the keyboard irq path.. */
@@ -591,18 +593,12 @@ static void con_scroll(struct vc_data *vc, unsigned int top,
 static void do_update_region(struct vc_data *vc, unsigned long start, int count)
 {
        unsigned int xx, yy, offset;
-       u16 *p;
+       u16 *p = (u16 *)start;
+
+       offset = (start - vc->vc_origin) / 2;
+       xx = offset % vc->vc_cols;
+       yy = offset / vc->vc_cols;
 
-       p = (u16 *) start;
-       if (!vc->vc_sw->con_getxy) {
-               offset = (start - vc->vc_origin) / 2;
-               xx = offset % vc->vc_cols;
-               yy = offset / vc->vc_cols;
-       } else {
-               int nxx, nyy;
-               start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy);
-               xx = nxx; yy = nyy;
-       }
        for(;;) {
                u16 attrib = scr_readw(p) & 0xff00;
                int startx = xx;
@@ -625,10 +621,6 @@ static void do_update_region(struct vc_data *vc, unsigned long start, int count)
                        break;
                xx = 0;
                yy++;
-               if (vc->vc_sw->con_getxy) {
-                       p = (u16 *)start;
-                       start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
-               }
        }
 }
 
@@ -703,7 +695,7 @@ static void update_attr(struct vc_data *vc)
 /* Note: inverting the screen twice should revert to the original state */
 void invert_screen(struct vc_data *vc, int offset, int count, bool viewed)
 {
-       unsigned short *p;
+       u16 *p;
 
        WARN_CONSOLE_UNLOCKED();
 
@@ -762,7 +754,7 @@ void complement_pos(struct vc_data *vc, int offset)
            old_offset < vc->vc_screenbuf_size) {
                scr_writew(old, screenpos(vc, old_offset, true));
                if (con_should_update(vc))
-                       vc->vc_sw->con_putc(vc, old, oldy, oldx);
+                       con_putc(vc, old, oldy, oldx);
                notify_update(vc);
        }
 
@@ -771,15 +763,14 @@ void complement_pos(struct vc_data *vc, int offset)
        if (offset != -1 && offset >= 0 &&
            offset < vc->vc_screenbuf_size) {
                unsigned short new;
-               unsigned short *p;
-               p = screenpos(vc, offset, true);
+               u16 *p = screenpos(vc, offset, true);
                old = scr_readw(p);
                new = old ^ vc->vc_complement_mask;
                scr_writew(new, p);
                if (con_should_update(vc)) {
                        oldx = (offset >> 1) % vc->vc_cols;
                        oldy = (offset >> 1) / vc->vc_cols;
-                       vc->vc_sw->con_putc(vc, new, oldy, oldx);
+                       con_putc(vc, new, oldy, oldx);
                }
                notify_update(vc);
        }
@@ -833,7 +824,7 @@ static void add_softcursor(struct vc_data *vc)
                i ^= CUR_FG;
        scr_writew(i, (u16 *)vc->vc_pos);
        if (con_should_update(vc))
-               vc->vc_sw->con_putc(vc, i, vc->state.y, vc->state.x);
+               con_putc(vc, i, vc->state.y, vc->state.x);
 }
 
 static void hide_softcursor(struct vc_data *vc)
@@ -841,8 +832,8 @@ static void hide_softcursor(struct vc_data *vc)
        if (softcursor_original != -1) {
                scr_writew(softcursor_original, (u16 *)vc->vc_pos);
                if (con_should_update(vc))
-                       vc->vc_sw->con_putc(vc, softcursor_original,
-                                       vc->state.y, vc->state.x);
+                       con_putc(vc, softcursor_original, vc->state.y,
+                                vc->state.x);
                softcursor_original = -1;
        }
 }
@@ -852,7 +843,7 @@ static void hide_cursor(struct vc_data *vc)
        if (vc_is_sel(vc))
                clear_selection();
 
-       vc->vc_sw->con_cursor(vc, CM_ERASE);
+       vc->vc_sw->con_cursor(vc, false);
        hide_softcursor(vc);
 }
 
@@ -865,7 +856,7 @@ static void set_cursor(struct vc_data *vc)
                        clear_selection();
                add_softcursor(vc);
                if (CUR_SIZE(vc->vc_cursor_type) != CUR_NONE)
-                       vc->vc_sw->con_cursor(vc, CM_DRAW);
+                       vc->vc_sw->con_cursor(vc, true);
        } else
                hide_cursor(vc);
 }
@@ -897,21 +888,18 @@ static void flush_scrollback(struct vc_data *vc)
        WARN_CONSOLE_UNLOCKED();
 
        set_origin(vc);
-       if (vc->vc_sw->con_flush_scrollback) {
-               vc->vc_sw->con_flush_scrollback(vc);
-       } else if (con_is_visible(vc)) {
-               /*
-                * When no con_flush_scrollback method is provided then the
-                * legacy way for flushing the scrollback buffer is to use
-                * a side effect of the con_switch method. We do it only on
-                * the foreground console as background consoles have no
-                * scrollback buffers in that case and we obviously don't
-                * want to switch to them.
-                */
-               hide_cursor(vc);
-               vc->vc_sw->con_switch(vc);
-               set_cursor(vc);
-       }
+       if (!con_is_visible(vc))
+               return;
+
+       /*
+        * The legacy way for flushing the scrollback buffer is to use a side
+        * effect of the con_switch method. We do it only on the foreground
+        * console as background consoles have no scrollback buffers in that
+        * case and we obviously don't want to switch to them.
+        */
+       hide_cursor(vc);
+       vc->vc_sw->con_switch(vc);
+       set_cursor(vc);
 }
 
 /*
@@ -962,7 +950,7 @@ void redraw_screen(struct vc_data *vc, int is_switch)
        }
 
        if (redraw) {
-               int update;
+               bool update;
                int old_was_color = vc->vc_can_do_color;
 
                set_origin(vc);
@@ -999,7 +987,7 @@ int vc_cons_allocated(unsigned int i)
        return (i < MAX_NR_CONSOLES && vc_cons[i].d);
 }
 
-static void visual_init(struct vc_data *vc, int num, int init)
+static void visual_init(struct vc_data *vc, int num, bool init)
 {
        /* ++Geert: vc->vc_sw->con_init determines console size */
        if (vc->vc_sw)
@@ -1083,7 +1071,7 @@ int vc_allocate(unsigned int currcons)    /* return 0 on success */
        vc->port.ops = &vc_port_ops;
        INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
 
-       visual_init(vc, currcons, 1);
+       visual_init(vc, currcons, true);
 
        if (!*vc->uni_pagedict_loc)
                con_set_default_unimap(vc);
@@ -1115,51 +1103,44 @@ err_free:
 }
 
 static inline int resize_screen(struct vc_data *vc, int width, int height,
-                               int user)
+                               bool from_user)
 {
        /* Resizes the resolution of the display adapater */
        int err = 0;
 
        if (vc->vc_sw->con_resize)
-               err = vc->vc_sw->con_resize(vc, width, height, user);
+               err = vc->vc_sw->con_resize(vc, width, height, from_user);
 
        return err;
 }
 
 /**
- *     vc_do_resize    -       resizing method for the tty
- *     @tty: tty being resized
- *     @vc: virtual console private data
- *     @cols: columns
- *     @lines: lines
+ * vc_do_resize - resizing method for the tty
+ * @tty: tty being resized
+ * @vc: virtual console private data
+ * @cols: columns
+ * @lines: lines
+ * @from_user: invoked by a user?
  *
- *     Resize a virtual console, clipping according to the actual constraints.
- *     If the caller passes a tty structure then update the termios winsize
- *     information and perform any necessary signal handling.
+ * Resize a virtual console, clipping according to the actual constraints. If
+ * the caller passes a tty structure then update the termios winsize
+ * information and perform any necessary signal handling.
  *
- *     Caller must hold the console semaphore. Takes the termios rwsem and
- *     ctrl.lock of the tty IFF a tty is passed.
+ * Locking: Caller must hold the console semaphore. Takes the termios rwsem and
+ * ctrl.lock of the tty IFF a tty is passed.
  */
-
 static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
-                               unsigned int cols, unsigned int lines)
+                       unsigned int cols, unsigned int lines, bool from_user)
 {
        unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
        unsigned long end;
        unsigned int old_rows, old_row_size, first_copied_row;
        unsigned int new_cols, new_rows, new_row_size, new_screen_size;
-       unsigned int user;
        unsigned short *oldscreen, *newscreen;
        u32 **new_uniscr = NULL;
 
        WARN_CONSOLE_UNLOCKED();
 
-       if (!vc)
-               return -ENXIO;
-
-       user = vc->vc_resize_user;
-       vc->vc_resize_user = 0;
-
        if (cols > VC_MAXCOL || lines > VC_MAXROW)
                return -EINVAL;
 
@@ -1185,7 +1166,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
                 * to deal with possible errors from the code below, we call
                 * the resize_screen here as well.
                 */
-               return resize_screen(vc, new_cols, new_rows, user);
+               return resize_screen(vc, new_cols, new_rows, from_user);
        }
 
        if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
@@ -1208,7 +1189,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        old_rows = vc->vc_rows;
        old_row_size = vc->vc_size_row;
 
-       err = resize_screen(vc, new_cols, new_rows, user);
+       err = resize_screen(vc, new_cols, new_rows, from_user);
        if (err) {
                kfree(newscreen);
                vc_uniscr_free(new_uniscr);
@@ -1295,34 +1276,35 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
 }
 
 /**
- *     vc_resize               -       resize a VT
- *     @vc: virtual console
- *     @cols: columns
- *     @rows: rows
+ * __vc_resize - resize a VT
+ * @vc: virtual console
+ * @cols: columns
+ * @rows: rows
+ * @from_user: invoked by a user?
+ *
+ * Resize a virtual console as seen from the console end of things. We use the
+ * common vc_do_resize() method to update the structures.
  *
- *     Resize a virtual console as seen from the console end of things. We
- *     use the common vc_do_resize methods to update the structures. The
- *     caller must hold the console sem to protect console internals and
- *     vc->port.tty
+ * Locking: The caller must hold the console sem to protect console internals
+ * and @vc->port.tty.
  */
-
-int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
+int __vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows,
+               bool from_user)
 {
-       return vc_do_resize(vc->port.tty, vc, cols, rows);
+       return vc_do_resize(vc->port.tty, vc, cols, rows, from_user);
 }
-EXPORT_SYMBOL(vc_resize);
+EXPORT_SYMBOL(__vc_resize);
 
 /**
- *     vt_resize               -       resize a VT
- *     @tty: tty to resize
- *     @ws: winsize attributes
+ * vt_resize - resize a VT
+ * @tty: tty to resize
+ * @ws: winsize attributes
  *
- *     Resize a virtual terminal. This is called by the tty layer as we
- *     register our own handler for resizing. The mutual helper does all
- *     the actual work.
+ * Resize a virtual terminal. This is called by the tty layer as we register
+ * our own handler for resizing. The mutual helper does all the actual work.
  *
- *     Takes the console sem and the called methods then take the tty
- *     termios_rwsem and the tty ctrl.lock in that order.
+ * Locking: Takes the console sem and the called methods then take the tty
+ * termios_rwsem and the tty ctrl.lock in that order.
  */
 static int vt_resize(struct tty_struct *tty, struct winsize *ws)
 {
@@ -1330,7 +1312,7 @@ static int vt_resize(struct tty_struct *tty, struct winsize *ws)
        int ret;
 
        console_lock();
-       ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row);
+       ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row, false);
        console_unlock();
        return ret;
 }
@@ -1503,36 +1485,43 @@ static inline void del(struct vc_data *vc)
        /* ignored */
 }
 
-static void csi_J(struct vc_data *vc, int vpar)
+enum CSI_J {
+       CSI_J_CURSOR_TO_END     = 0,
+       CSI_J_START_TO_CURSOR   = 1,
+       CSI_J_VISIBLE           = 2,
+       CSI_J_FULL              = 3,
+};
+
+static void csi_J(struct vc_data *vc, enum CSI_J vpar)
 {
+       unsigned short *start;
        unsigned int count;
-       unsigned short * start;
 
        switch (vpar) {
-               case 0: /* erase from cursor to end of display */
-                       vc_uniscr_clear_line(vc, vc->state.x,
-                                            vc->vc_cols - vc->state.x);
-                       vc_uniscr_clear_lines(vc, vc->state.y + 1,
-                                             vc->vc_rows - vc->state.y - 1);
-                       count = (vc->vc_scr_end - vc->vc_pos) >> 1;
-                       start = (unsigned short *)vc->vc_pos;
-                       break;
-               case 1: /* erase from start to cursor */
-                       vc_uniscr_clear_line(vc, 0, vc->state.x + 1);
-                       vc_uniscr_clear_lines(vc, 0, vc->state.y);
-                       count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
-                       start = (unsigned short *)vc->vc_origin;
-                       break;
-               case 3: /* include scrollback */
-                       flush_scrollback(vc);
-                       fallthrough;
-               case 2: /* erase whole display */
-                       vc_uniscr_clear_lines(vc, 0, vc->vc_rows);
-                       count = vc->vc_cols * vc->vc_rows;
-                       start = (unsigned short *)vc->vc_origin;
-                       break;
-               default:
-                       return;
+       case CSI_J_CURSOR_TO_END:
+               vc_uniscr_clear_line(vc, vc->state.x,
+                                    vc->vc_cols - vc->state.x);
+               vc_uniscr_clear_lines(vc, vc->state.y + 1,
+                                     vc->vc_rows - vc->state.y - 1);
+               count = (vc->vc_scr_end - vc->vc_pos) >> 1;
+               start = (unsigned short *)vc->vc_pos;
+               break;
+       case CSI_J_START_TO_CURSOR:
+               vc_uniscr_clear_line(vc, 0, vc->state.x + 1);
+               vc_uniscr_clear_lines(vc, 0, vc->state.y);
+               count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
+               start = (unsigned short *)vc->vc_origin;
+               break;
+       case CSI_J_FULL:
+               flush_scrollback(vc);
+               fallthrough;
+       case CSI_J_VISIBLE:
+               vc_uniscr_clear_lines(vc, 0, vc->vc_rows);
+               count = vc->vc_cols * vc->vc_rows;
+               start = (unsigned short *)vc->vc_origin;
+               break;
+       default:
+               return;
        }
        scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
        if (con_should_update(vc))
@@ -1540,27 +1529,33 @@ static void csi_J(struct vc_data *vc, int vpar)
        vc->vc_need_wrap = 0;
 }
 
-static void csi_K(struct vc_data *vc, int vpar)
+enum {
+       CSI_K_CURSOR_TO_LINEEND         = 0,
+       CSI_K_LINESTART_TO_CURSOR       = 1,
+       CSI_K_LINE                      = 2,
+};
+
+static void csi_K(struct vc_data *vc)
 {
        unsigned int count;
        unsigned short *start = (unsigned short *)vc->vc_pos;
        int offset;
 
-       switch (vpar) {
-               case 0: /* erase from cursor to end of line */
-                       offset = 0;
-                       count = vc->vc_cols - vc->state.x;
-                       break;
-               case 1: /* erase from start of line to cursor */
-                       offset = -vc->state.x;
-                       count = vc->state.x + 1;
-                       break;
-               case 2: /* erase whole line */
-                       offset = -vc->state.x;
-                       count = vc->vc_cols;
-                       break;
-               default:
-                       return;
+       switch (vc->vc_par[0]) {
+       case CSI_K_CURSOR_TO_LINEEND:
+               offset = 0;
+               count = vc->vc_cols - vc->state.x;
+               break;
+       case CSI_K_LINESTART_TO_CURSOR:
+               offset = -vc->state.x;
+               count = vc->state.x + 1;
+               break;
+       case CSI_K_LINE:
+               offset = -vc->state.x;
+               count = vc->vc_cols;
+               break;
+       default:
+               return;
        }
        vc_uniscr_clear_line(vc, vc->state.x + offset, count);
        scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count);
@@ -1569,20 +1564,15 @@ static void csi_K(struct vc_data *vc, int vpar)
                do_update_region(vc, (unsigned long)(start + offset), count);
 }
 
-/* erase the following vpar positions */
-static void csi_X(struct vc_data *vc, unsigned int vpar)
+/* erase the following count positions */
+static void csi_X(struct vc_data *vc)
 {                                        /* not vt100? */
-       unsigned int count;
-
-       if (!vpar)
-               vpar++;
-
-       count = min(vpar, vc->vc_cols - vc->state.x);
+       unsigned int count = clamp(vc->vc_par[0], 1, vc->vc_cols - vc->state.x);
 
        vc_uniscr_clear_line(vc, vc->state.x, count);
        scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
        if (con_should_update(vc))
-               vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, 1, count);
+               vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, count);
        vc->vc_need_wrap = 0;
 }
 
@@ -1598,7 +1588,7 @@ static void default_attr(struct vc_data *vc)
 
 struct rgb { u8 r; u8 g; u8 b; };
 
-static void rgb_from_256(int i, struct rgb *c)
+static void rgb_from_256(unsigned int i, struct rgb *c)
 {
        if (i < 8) {            /* Standard colours. */
                c->r = i&1 ? 0xaa : 0x00;
@@ -1609,9 +1599,12 @@ static void rgb_from_256(int i, struct rgb *c)
                c->g = i&2 ? 0xff : 0x55;
                c->b = i&4 ? 0xff : 0x55;
        } else if (i < 232) {   /* 6x6x6 colour cube. */
-               c->r = (i - 16) / 36 * 85 / 2;
-               c->g = (i - 16) / 6 % 6 * 85 / 2;
-               c->b = (i - 16) % 6 * 85 / 2;
+               i -= 16;
+               c->b = i % 6 * 255 / 6;
+               i /= 6;
+               c->g = i % 6 * 255 / 6;
+               i /= 6;
+               c->r = i     * 255 / 6;
        } else                  /* Grayscale ramp. */
                c->r = c->g = c->b = i * 10 - 2312;
 }
@@ -1681,6 +1674,39 @@ static int vc_t416_color(struct vc_data *vc, int i,
        return i;
 }
 
+enum {
+       CSI_m_DEFAULT                   = 0,
+       CSI_m_BOLD                      = 1,
+       CSI_m_HALF_BRIGHT               = 2,
+       CSI_m_ITALIC                    = 3,
+       CSI_m_UNDERLINE                 = 4,
+       CSI_m_BLINK                     = 5,
+       CSI_m_REVERSE                   = 7,
+       CSI_m_PRI_FONT                  = 10,
+       CSI_m_ALT_FONT1                 = 11,
+       CSI_m_ALT_FONT2                 = 12,
+       CSI_m_DOUBLE_UNDERLINE          = 21,
+       CSI_m_NORMAL_INTENSITY          = 22,
+       CSI_m_NO_ITALIC                 = 23,
+       CSI_m_NO_UNDERLINE              = 24,
+       CSI_m_NO_BLINK                  = 25,
+       CSI_m_NO_REVERSE                = 27,
+       CSI_m_FG_COLOR_BEG              = 30,
+       CSI_m_FG_COLOR_END              = 37,
+       CSI_m_FG_COLOR                  = 38,
+       CSI_m_DEFAULT_FG_COLOR          = 39,
+       CSI_m_BG_COLOR_BEG              = 40,
+       CSI_m_BG_COLOR_END              = 47,
+       CSI_m_BG_COLOR                  = 48,
+       CSI_m_DEFAULT_BG_COLOR          = 49,
+       CSI_m_BRIGHT_FG_COLOR_BEG       = 90,
+       CSI_m_BRIGHT_FG_COLOR_END       = 97,
+       CSI_m_BRIGHT_FG_COLOR_OFF       = CSI_m_BRIGHT_FG_COLOR_BEG - CSI_m_FG_COLOR_BEG,
+       CSI_m_BRIGHT_BG_COLOR_BEG       = 100,
+       CSI_m_BRIGHT_BG_COLOR_END       = 107,
+       CSI_m_BRIGHT_BG_COLOR_OFF       = CSI_m_BRIGHT_BG_COLOR_BEG - CSI_m_BG_COLOR_BEG,
+};
+
 /* console_lock is held */
 static void csi_m(struct vc_data *vc)
 {
@@ -1688,33 +1714,33 @@ static void csi_m(struct vc_data *vc)
 
        for (i = 0; i <= vc->vc_npar; i++)
                switch (vc->vc_par[i]) {
-               case 0: /* all attributes off */
+               case CSI_m_DEFAULT:     /* all attributes off */
                        default_attr(vc);
                        break;
-               case 1:
+               case CSI_m_BOLD:
                        vc->state.intensity = VCI_BOLD;
                        break;
-               case 2:
+               case CSI_m_HALF_BRIGHT:
                        vc->state.intensity = VCI_HALF_BRIGHT;
                        break;
-               case 3:
+               case CSI_m_ITALIC:
                        vc->state.italic = true;
                        break;
-               case 21:
+               case CSI_m_DOUBLE_UNDERLINE:
                        /*
                         * No console drivers support double underline, so
                         * convert it to a single underline.
                         */
-               case 4:
+               case CSI_m_UNDERLINE:
                        vc->state.underline = true;
                        break;
-               case 5:
+               case CSI_m_BLINK:
                        vc->state.blink = true;
                        break;
-               case 7:
+               case CSI_m_REVERSE:
                        vc->state.reverse = true;
                        break;
-               case 10: /* ANSI X3.64-1979 (SCO-ish?)
+               case CSI_m_PRI_FONT: /* ANSI X3.64-1979 (SCO-ish?)
                          * Select primary font, don't display control chars if
                          * defined, don't set bit 8 on output.
                          */
@@ -1722,7 +1748,7 @@ static void csi_m(struct vc_data *vc)
                        vc->vc_disp_ctrl = 0;
                        vc->vc_toggle_meta = 0;
                        break;
-               case 11: /* ANSI X3.64-1979 (SCO-ish?)
+               case CSI_m_ALT_FONT1: /* ANSI X3.64-1979 (SCO-ish?)
                          * Select first alternate font, lets chars < 32 be
                          * displayed as ROM chars.
                          */
@@ -1730,7 +1756,7 @@ static void csi_m(struct vc_data *vc)
                        vc->vc_disp_ctrl = 1;
                        vc->vc_toggle_meta = 0;
                        break;
-               case 12: /* ANSI X3.64-1979 (SCO-ish?)
+               case CSI_m_ALT_FONT2: /* ANSI X3.64-1979 (SCO-ish?)
                          * Select second alternate font, toggle high bit
                          * before displaying as ROM char.
                          */
@@ -1738,47 +1764,51 @@ static void csi_m(struct vc_data *vc)
                        vc->vc_disp_ctrl = 1;
                        vc->vc_toggle_meta = 1;
                        break;
-               case 22:
+               case CSI_m_NORMAL_INTENSITY:
                        vc->state.intensity = VCI_NORMAL;
                        break;
-               case 23:
+               case CSI_m_NO_ITALIC:
                        vc->state.italic = false;
                        break;
-               case 24:
+               case CSI_m_NO_UNDERLINE:
                        vc->state.underline = false;
                        break;
-               case 25:
+               case CSI_m_NO_BLINK:
                        vc->state.blink = false;
                        break;
-               case 27:
+               case CSI_m_NO_REVERSE:
                        vc->state.reverse = false;
                        break;
-               case 38:
+               case CSI_m_FG_COLOR:
                        i = vc_t416_color(vc, i, rgb_foreground);
                        break;
-               case 48:
+               case CSI_m_BG_COLOR:
                        i = vc_t416_color(vc, i, rgb_background);
                        break;
-               case 39:
+               case CSI_m_DEFAULT_FG_COLOR:
                        vc->state.color = (vc->vc_def_color & 0x0f) |
                                (vc->state.color & 0xf0);
                        break;
-               case 49:
+               case CSI_m_DEFAULT_BG_COLOR:
                        vc->state.color = (vc->vc_def_color & 0xf0) |
                                (vc->state.color & 0x0f);
                        break;
-               default:
-                       if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) {
-                               if (vc->vc_par[i] < 100)
-                                       vc->state.intensity = VCI_BOLD;
-                               vc->vc_par[i] -= 60;
-                       }
-                       if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
-                               vc->state.color = color_table[vc->vc_par[i] - 30]
-                                       | (vc->state.color & 0xf0);
-                       else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
-                               vc->state.color = (color_table[vc->vc_par[i] - 40] << 4)
-                                       | (vc->state.color & 0x0f);
+               case CSI_m_BRIGHT_FG_COLOR_BEG ... CSI_m_BRIGHT_FG_COLOR_END:
+                       vc->state.intensity = VCI_BOLD;
+                       vc->vc_par[i] -= CSI_m_BRIGHT_FG_COLOR_OFF;
+                       fallthrough;
+               case CSI_m_FG_COLOR_BEG ... CSI_m_FG_COLOR_END:
+                       vc->vc_par[i] -= CSI_m_FG_COLOR_BEG;
+                       vc->state.color = color_table[vc->vc_par[i]] |
+                               (vc->state.color & 0xf0);
+                       break;
+               case CSI_m_BRIGHT_BG_COLOR_BEG ... CSI_m_BRIGHT_BG_COLOR_END:
+                       vc->vc_par[i] -= CSI_m_BRIGHT_BG_COLOR_OFF;
+                       fallthrough;
+               case CSI_m_BG_COLOR_BEG ... CSI_m_BG_COLOR_END:
+                       vc->vc_par[i] -= CSI_m_BG_COLOR_BEG;
+                       vc->state.color = (color_table[vc->vc_par[i]] << 4) |
+                               (vc->state.color & 0x0f);
                        break;
                }
        update_attr(vc);
@@ -1832,133 +1862,175 @@ int mouse_reporting(void)
        return vc_cons[fg_console].d->vc_report_mouse;
 }
 
+enum {
+       CSI_DEC_hl_CURSOR_KEYS  = 1,    /* CKM: cursor keys send ^[Ox/^[[x */
+       CSI_DEC_hl_132_COLUMNS  = 3,    /* COLM: 80/132 mode switch */
+       CSI_DEC_hl_REVERSE_VIDEO = 5,   /* SCNM */
+       CSI_DEC_hl_ORIGIN_MODE  = 6,    /* OM: origin relative/absolute */
+       CSI_DEC_hl_AUTOWRAP     = 7,    /* AWM */
+       CSI_DEC_hl_AUTOREPEAT   = 8,    /* ARM */
+       CSI_DEC_hl_MOUSE_X10    = 9,
+       CSI_DEC_hl_SHOW_CURSOR  = 25,   /* TCEM */
+       CSI_DEC_hl_MOUSE_VT200  = 1000,
+};
+
 /* console_lock is held */
-static void set_mode(struct vc_data *vc, int on_off)
+static void csi_DEC_hl(struct vc_data *vc, bool on_off)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i <= vc->vc_npar; i++)
-               if (vc->vc_priv == EPdec) {
-                       switch(vc->vc_par[i]) { /* DEC private modes set/reset */
-                       case 1:                 /* Cursor keys send ^[Ox/^[[x */
-                               if (on_off)
-                                       set_kbd(vc, decckm);
-                               else
-                                       clr_kbd(vc, decckm);
-                               break;
-                       case 3: /* 80/132 mode switch unimplemented */
+               switch (vc->vc_par[i]) {
+               case CSI_DEC_hl_CURSOR_KEYS:
+                       if (on_off)
+                               set_kbd(vc, decckm);
+                       else
+                               clr_kbd(vc, decckm);
+                       break;
+               case CSI_DEC_hl_132_COLUMNS:    /* unimplemented */
 #if 0
-                               vc_resize(deccolm ? 132 : 80, vc->vc_rows);
-                               /* this alone does not suffice; some user mode
-                                  utility has to change the hardware regs */
+                       vc_resize(deccolm ? 132 : 80, vc->vc_rows);
+                       /* this alone does not suffice; some user mode
+                          utility has to change the hardware regs */
 #endif
-                               break;
-                       case 5:                 /* Inverted screen on/off */
-                               if (vc->vc_decscnm != on_off) {
-                                       vc->vc_decscnm = on_off;
-                                       invert_screen(vc, 0,
-                                                       vc->vc_screenbuf_size,
-                                                       false);
-                                       update_attr(vc);
-                               }
-                               break;
-                       case 6:                 /* Origin relative/absolute */
-                               vc->vc_decom = on_off;
-                               gotoxay(vc, 0, 0);
-                               break;
-                       case 7:                 /* Autowrap on/off */
-                               vc->vc_decawm = on_off;
-                               break;
-                       case 8:                 /* Autorepeat on/off */
-                               if (on_off)
-                                       set_kbd(vc, decarm);
-                               else
-                                       clr_kbd(vc, decarm);
-                               break;
-                       case 9:
-                               vc->vc_report_mouse = on_off ? 1 : 0;
-                               break;
-                       case 25:                /* Cursor on/off */
-                               vc->vc_deccm = on_off;
-                               break;
-                       case 1000:
-                               vc->vc_report_mouse = on_off ? 2 : 0;
-                               break;
-                       }
-               } else {
-                       switch(vc->vc_par[i]) { /* ANSI modes set/reset */
-                       case 3:                 /* Monitor (display ctrls) */
-                               vc->vc_disp_ctrl = on_off;
-                               break;
-                       case 4:                 /* Insert Mode on/off */
-                               vc->vc_decim = on_off;
-                               break;
-                       case 20:                /* Lf, Enter == CrLf/Lf */
-                               if (on_off)
-                                       set_kbd(vc, lnm);
-                               else
-                                       clr_kbd(vc, lnm);
-                               break;
+                       break;
+               case CSI_DEC_hl_REVERSE_VIDEO:
+                       if (vc->vc_decscnm != on_off) {
+                               vc->vc_decscnm = on_off;
+                               invert_screen(vc, 0, vc->vc_screenbuf_size,
+                                             false);
+                               update_attr(vc);
                        }
+                       break;
+               case CSI_DEC_hl_ORIGIN_MODE:
+                       vc->vc_decom = on_off;
+                       gotoxay(vc, 0, 0);
+                       break;
+               case CSI_DEC_hl_AUTOWRAP:
+                       vc->vc_decawm = on_off;
+                       break;
+               case CSI_DEC_hl_AUTOREPEAT:
+                       if (on_off)
+                               set_kbd(vc, decarm);
+                       else
+                               clr_kbd(vc, decarm);
+                       break;
+               case CSI_DEC_hl_MOUSE_X10:
+                       vc->vc_report_mouse = on_off ? 1 : 0;
+                       break;
+               case CSI_DEC_hl_SHOW_CURSOR:
+                       vc->vc_deccm = on_off;
+                       break;
+               case CSI_DEC_hl_MOUSE_VT200:
+                       vc->vc_report_mouse = on_off ? 2 : 0;
+                       break;
                }
 }
 
+enum {
+       CSI_hl_DISPLAY_CTRL     = 3,    /* handle ansi control chars */
+       CSI_hl_INSERT           = 4,    /* IRM: insert/replace */
+       CSI_hl_AUTO_NL          = 20,   /* LNM: Enter == CrLf/Lf */
+};
+
 /* console_lock is held */
-static void setterm_command(struct vc_data *vc)
+static void csi_hl(struct vc_data *vc, bool on_off)
+{
+       unsigned int i;
+
+       for (i = 0; i <= vc->vc_npar; i++)
+               switch (vc->vc_par[i]) {        /* ANSI modes set/reset */
+               case CSI_hl_DISPLAY_CTRL:
+                       vc->vc_disp_ctrl = on_off;
+                       break;
+               case CSI_hl_INSERT:
+                       vc->vc_decim = on_off;
+                       break;
+               case CSI_hl_AUTO_NL:
+                       if (on_off)
+                               set_kbd(vc, lnm);
+                       else
+                               clr_kbd(vc, lnm);
+                       break;
+               }
+}
+
+enum CSI_right_square_bracket {
+       CSI_RSB_COLOR_FOR_UNDERLINE             = 1,
+       CSI_RSB_COLOR_FOR_HALF_BRIGHT           = 2,
+       CSI_RSB_MAKE_CUR_COLOR_DEFAULT          = 8,
+       CSI_RSB_BLANKING_INTERVAL               = 9,
+       CSI_RSB_BELL_FREQUENCY                  = 10,
+       CSI_RSB_BELL_DURATION                   = 11,
+       CSI_RSB_BRING_CONSOLE_TO_FRONT          = 12,
+       CSI_RSB_UNBLANK                         = 13,
+       CSI_RSB_VESA_OFF_INTERVAL               = 14,
+       CSI_RSB_BRING_PREV_CONSOLE_TO_FRONT     = 15,
+       CSI_RSB_CURSOR_BLINK_INTERVAL           = 16,
+};
+
+/*
+ * csi_RSB - csi+] (Right Square Bracket) handler
+ *
+ * These are linux console private sequences.
+ *
+ * console_lock is held
+ */
+static void csi_RSB(struct vc_data *vc)
 {
        switch (vc->vc_par[0]) {
-       case 1: /* set color for underline mode */
+       case CSI_RSB_COLOR_FOR_UNDERLINE:
                if (vc->vc_can_do_color && vc->vc_par[1] < 16) {
                        vc->vc_ulcolor = color_table[vc->vc_par[1]];
                        if (vc->state.underline)
                                update_attr(vc);
                }
                break;
-       case 2: /* set color for half intensity mode */
+       case CSI_RSB_COLOR_FOR_HALF_BRIGHT:
                if (vc->vc_can_do_color && vc->vc_par[1] < 16) {
                        vc->vc_halfcolor = color_table[vc->vc_par[1]];
                        if (vc->state.intensity == VCI_HALF_BRIGHT)
                                update_attr(vc);
                }
                break;
-       case 8: /* store colors as defaults */
+       case CSI_RSB_MAKE_CUR_COLOR_DEFAULT:
                vc->vc_def_color = vc->vc_attr;
                if (vc->vc_hi_font_mask == 0x100)
                        vc->vc_def_color >>= 1;
                default_attr(vc);
                update_attr(vc);
                break;
-       case 9: /* set blanking interval */
+       case CSI_RSB_BLANKING_INTERVAL:
                blankinterval = min(vc->vc_par[1], 60U) * 60;
                poke_blanked_console();
                break;
-       case 10: /* set bell frequency in Hz */
+       case CSI_RSB_BELL_FREQUENCY:
                if (vc->vc_npar >= 1)
                        vc->vc_bell_pitch = vc->vc_par[1];
                else
                        vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
                break;
-       case 11: /* set bell duration in msec */
+       case CSI_RSB_BELL_DURATION:
                if (vc->vc_npar >= 1)
                        vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
                                msecs_to_jiffies(vc->vc_par[1]) : 0;
                else
                        vc->vc_bell_duration = DEFAULT_BELL_DURATION;
                break;
-       case 12: /* bring specified console to the front */
+       case CSI_RSB_BRING_CONSOLE_TO_FRONT:
                if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1))
                        set_console(vc->vc_par[1] - 1);
                break;
-       case 13: /* unblank the screen */
+       case CSI_RSB_UNBLANK:
                poke_blanked_console();
                break;
-       case 14: /* set vesa powerdown interval */
+       case CSI_RSB_VESA_OFF_INTERVAL:
                vesa_off_interval = min(vc->vc_par[1], 60U) * 60 * HZ;
                break;
-       case 15: /* activate the previous console */
+       case CSI_RSB_BRING_PREV_CONSOLE_TO_FRONT:
                set_console(last_console);
                break;
-       case 16: /* set cursor blink duration in msec */
+       case CSI_RSB_CURSOR_BLINK_INTERVAL:
                if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 &&
                                vc->vc_par[1] <= USHRT_MAX)
                        vc->vc_cur_blink_ms = vc->vc_par[1];
@@ -1971,41 +2043,32 @@ static void setterm_command(struct vc_data *vc)
 /* console_lock is held */
 static void csi_at(struct vc_data *vc, unsigned int nr)
 {
-       if (nr > vc->vc_cols - vc->state.x)
-               nr = vc->vc_cols - vc->state.x;
-       else if (!nr)
-               nr = 1;
+       nr = clamp(nr, 1, vc->vc_cols - vc->state.x);
        insert_char(vc, nr);
 }
 
 /* console_lock is held */
-static void csi_L(struct vc_data *vc, unsigned int nr)
+static void csi_L(struct vc_data *vc)
 {
-       if (nr > vc->vc_rows - vc->state.y)
-               nr = vc->vc_rows - vc->state.y;
-       else if (!nr)
-               nr = 1;
+       unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_rows - vc->state.y);
+
        con_scroll(vc, vc->state.y, vc->vc_bottom, SM_DOWN, nr);
        vc->vc_need_wrap = 0;
 }
 
 /* console_lock is held */
-static void csi_P(struct vc_data *vc, unsigned int nr)
+static void csi_P(struct vc_data *vc)
 {
-       if (nr > vc->vc_cols - vc->state.x)
-               nr = vc->vc_cols - vc->state.x;
-       else if (!nr)
-               nr = 1;
+       unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_cols - vc->state.x);
+
        delete_char(vc, nr);
 }
 
 /* console_lock is held */
-static void csi_M(struct vc_data *vc, unsigned int nr)
+static void csi_M(struct vc_data *vc)
 {
-       if (nr > vc->vc_rows - vc->state.y)
-               nr = vc->vc_rows - vc->state.y;
-       else if (!nr)
-               nr=1;
+       unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_rows - vc->state.y);
+
        con_scroll(vc, vc->state.y, vc->vc_bottom, SM_UP, nr);
        vc->vc_need_wrap = 0;
 }
@@ -2028,9 +2091,48 @@ static void restore_cur(struct vc_data *vc)
        vc->vc_need_wrap = 0;
 }
 
-enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey,
-       EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd,
-       ESpalette, ESosc, ESapc, ESpm, ESdcs };
+/**
+ * enum vc_ctl_state - control characters state of a vt
+ *
+ * @ESnormal:          initial state, no control characters parsed
+ * @ESesc:             ESC parsed
+ * @ESsquare:          CSI parsed -- modifiers/parameters/ctrl chars expected
+ * @ESgetpars:         CSI parsed -- parameters/ctrl chars expected
+ * @ESfunckey:         CSI [ parsed
+ * @EShash:            ESC # parsed
+ * @ESsetG0:           ESC ( parsed
+ * @ESsetG1:           ESC ) parsed
+ * @ESpercent:         ESC % parsed
+ * @EScsiignore:       CSI [0x20-0x3f] parsed
+ * @ESnonstd:          OSC parsed
+ * @ESpalette:         OSC P parsed
+ * @ESosc:             OSC [0-9] parsed
+ * @ESANSI_first:      first state for ignoring ansi control sequences
+ * @ESapc:             ESC _ parsed
+ * @ESpm:              ESC ^ parsed
+ * @ESdcs:             ESC P parsed
+ * @ESANSI_last:       last state for ignoring ansi control sequences
+ */
+enum vc_ctl_state {
+       ESnormal,
+       ESesc,
+       ESsquare,
+       ESgetpars,
+       ESfunckey,
+       EShash,
+       ESsetG0,
+       ESsetG1,
+       ESpercent,
+       EScsiignore,
+       ESnonstd,
+       ESpalette,
+       ESosc,
+       ESANSI_first = ESosc,
+       ESapc,
+       ESpm,
+       ESdcs,
+       ESANSI_last = ESdcs,
+};
 
 /* console_lock is held (except via vc_init()) */
 static void reset_terminal(struct vc_data *vc, int do_clear)
@@ -2078,10 +2180,10 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
        gotoxy(vc, 0, 0);
        save_cur(vc);
        if (do_clear)
-           csi_J(vc, 2);
+           csi_J(vc, CSI_J_VISIBLE);
 }
 
-static void vc_setGx(struct vc_data *vc, unsigned int which, int c)
+static void vc_setGx(struct vc_data *vc, unsigned int which, u8 c)
 {
        unsigned char *charset = &vc->state.Gx_charset[which];
 
@@ -2104,36 +2206,54 @@ static void vc_setGx(struct vc_data *vc, unsigned int which, int c)
                vc->vc_translate = set_translate(*charset, vc);
 }
 
-/* is this state an ANSI control string? */
-static bool ansi_control_string(unsigned int state)
+static bool ansi_control_string(enum vc_ctl_state state)
 {
-       if (state == ESosc || state == ESapc || state == ESpm || state == ESdcs)
-               return true;
-       return false;
+       return state >= ESANSI_first && state <= ESANSI_last;
 }
 
-/* console_lock is held */
-static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
+enum {
+       ASCII_NULL              = 0,
+       ASCII_BELL              = 7,
+       ASCII_BACKSPACE         = 8,
+       ASCII_IGNORE_FIRST      = ASCII_BACKSPACE,
+       ASCII_HTAB              = 9,
+       ASCII_LINEFEED          = 10,
+       ASCII_VTAB              = 11,
+       ASCII_FORMFEED          = 12,
+       ASCII_CAR_RET           = 13,
+       ASCII_IGNORE_LAST       = ASCII_CAR_RET,
+       ASCII_SHIFTOUT          = 14,
+       ASCII_SHIFTIN           = 15,
+       ASCII_CANCEL            = 24,
+       ASCII_SUBSTITUTE        = 26,
+       ASCII_ESCAPE            = 27,
+       ASCII_CSI_IGNORE_FIRST  = ' ', /* 0x2x, 0x3a and 0x3c - 0x3f */
+       ASCII_CSI_IGNORE_LAST   = '?',
+       ASCII_DEL               = 127,
+       ASCII_EXT_CSI           = 128 + ASCII_ESCAPE,
+};
+
+/*
+ * Handle ascii characters in control sequences and change states accordingly.
+ * E.g. ESC sets the state of vc to ESesc.
+ *
+ * Returns: true if @c handled.
+ */
+static bool handle_ascii(struct tty_struct *tty, struct vc_data *vc, u8 c)
 {
-       /*
-        *  Control characters can be used in the _middle_
-        *  of an escape sequence, aside from ANSI control strings.
-        */
-       if (ansi_control_string(vc->vc_state) && c >= 8 && c <= 13)
-               return;
        switch (c) {
-       case 0:
-               return;
-       case 7:
+       case ASCII_NULL:
+               return true;
+       case ASCII_BELL:
                if (ansi_control_string(vc->vc_state))
                        vc->vc_state = ESnormal;
                else if (vc->vc_bell_duration)
                        kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
-               return;
-       case 8:
+               return true;
+       case ASCII_BACKSPACE:
                bs(vc);
-               return;
-       case 9:
+               return true;
+       case ASCII_HTAB:
                vc->vc_pos -= (vc->state.x << 1);
 
                vc->state.x = find_next_bit(vc->vc_tab_stop,
@@ -2144,119 +2264,330 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 
                vc->vc_pos += (vc->state.x << 1);
                notify_write(vc, '\t');
-               return;
-       case 10: case 11: case 12:
+               return true;
+       case ASCII_LINEFEED:
+       case ASCII_VTAB:
+       case ASCII_FORMFEED:
                lf(vc);
                if (!is_kbd(vc, lnm))
-                       return;
+                       return true;
                fallthrough;
-       case 13:
+       case ASCII_CAR_RET:
                cr(vc);
-               return;
-       case 14:
+               return true;
+       case ASCII_SHIFTOUT:
                vc->state.charset = 1;
                vc->vc_translate = set_translate(vc->state.Gx_charset[1], vc);
                vc->vc_disp_ctrl = 1;
-               return;
-       case 15:
+               return true;
+       case ASCII_SHIFTIN:
                vc->state.charset = 0;
                vc->vc_translate = set_translate(vc->state.Gx_charset[0], vc);
                vc->vc_disp_ctrl = 0;
-               return;
-       case 24: case 26:
+               return true;
+       case ASCII_CANCEL:
+       case ASCII_SUBSTITUTE:
                vc->vc_state = ESnormal;
-               return;
-       case 27:
+               return true;
+       case ASCII_ESCAPE:
                vc->vc_state = ESesc;
-               return;
-       case 127:
+               return true;
+       case ASCII_DEL:
                del(vc);
-               return;
-       case 128+27:
+               return true;
+       case ASCII_EXT_CSI:
                vc->vc_state = ESsquare;
-               return;
+               return true;
        }
-       switch(vc->vc_state) {
-       case ESesc:
-               vc->vc_state = ESnormal;
-               switch (c) {
-               case '[':
-                       vc->vc_state = ESsquare;
-                       return;
-               case ']':
-                       vc->vc_state = ESnonstd;
-                       return;
-               case '_':
-                       vc->vc_state = ESapc;
-                       return;
-               case '^':
-                       vc->vc_state = ESpm;
-                       return;
-               case '%':
-                       vc->vc_state = ESpercent;
-                       return;
-               case 'E':
-                       cr(vc);
-                       lf(vc);
-                       return;
-               case 'M':
-                       ri(vc);
-                       return;
-               case 'D':
-                       lf(vc);
-                       return;
-               case 'H':
-                       if (vc->state.x < VC_TABSTOPS_COUNT)
-                               set_bit(vc->state.x, vc->vc_tab_stop);
-                       return;
-               case 'P':
-                       vc->vc_state = ESdcs;
-                       return;
-               case 'Z':
+
+       return false;
+}
+
+/*
+ * Handle a character (@c) following an ESC (when @vc is in the ESesc state).
+ * E.g. previous ESC with @c == '[' here yields the ESsquare state (that is:
+ * CSI).
+ */
+static void handle_esc(struct tty_struct *tty, struct vc_data *vc, u8 c)
+{
+       vc->vc_state = ESnormal;
+       switch (c) {
+       case '[':
+               vc->vc_state = ESsquare;
+               break;
+       case ']':
+               vc->vc_state = ESnonstd;
+               break;
+       case '_':
+               vc->vc_state = ESapc;
+               break;
+       case '^':
+               vc->vc_state = ESpm;
+               break;
+       case '%':
+               vc->vc_state = ESpercent;
+               break;
+       case 'E':
+               cr(vc);
+               lf(vc);
+               break;
+       case 'M':
+               ri(vc);
+               break;
+       case 'D':
+               lf(vc);
+               break;
+       case 'H':
+               if (vc->state.x < VC_TABSTOPS_COUNT)
+                       set_bit(vc->state.x, vc->vc_tab_stop);
+               break;
+       case 'P':
+               vc->vc_state = ESdcs;
+               break;
+       case 'Z':
+               respond_ID(tty);
+               break;
+       case '7':
+               save_cur(vc);
+               break;
+       case '8':
+               restore_cur(vc);
+               break;
+       case '(':
+               vc->vc_state = ESsetG0;
+               break;
+       case ')':
+               vc->vc_state = ESsetG1;
+               break;
+       case '#':
+               vc->vc_state = EShash;
+               break;
+       case 'c':
+               reset_terminal(vc, 1);
+               break;
+       case '>':  /* Numeric keypad */
+               clr_kbd(vc, kbdapplic);
+               break;
+       case '=':  /* Appl. keypad */
+               set_kbd(vc, kbdapplic);
+               break;
+       }
+}
+
+/*
+ * Handle special DEC control sequences ("ESC [ ? parameters char"). Parameters
+ * are in @vc->vc_par and the char is in @c here.
+ */
+static void csi_DEC(struct tty_struct *tty, struct vc_data *vc, u8 c)
+{
+       switch (c) {
+       case 'h':
+               csi_DEC_hl(vc, true);
+               break;
+       case 'l':
+               csi_DEC_hl(vc, false);
+               break;
+       case 'c':
+               if (vc->vc_par[0])
+                       vc->vc_cursor_type = CUR_MAKE(vc->vc_par[0],
+                                                     vc->vc_par[1],
+                                                     vc->vc_par[2]);
+               else
+                       vc->vc_cursor_type = cur_default;
+               break;
+       case 'm':
+               clear_selection();
+               if (vc->vc_par[0])
+                       vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1];
+               else
+                       vc->vc_complement_mask = vc->vc_s_complement_mask;
+               break;
+       case 'n':
+               if (vc->vc_par[0] == 5)
+                       status_report(tty);
+               else if (vc->vc_par[0] == 6)
+                       cursor_report(vc, tty);
+               break;
+       }
+}
+
+/*
+ * Handle Control Sequence Introducer control characters. That is
+ * "ESC [ parameters char". Parameters are in @vc->vc_par and the char is in
+ * @c here.
+ */
+static void csi_ECMA(struct tty_struct *tty, struct vc_data *vc, u8 c)
+{
+       switch (c) {
+       case 'G':
+       case '`':
+               if (vc->vc_par[0])
+                       vc->vc_par[0]--;
+               gotoxy(vc, vc->vc_par[0], vc->state.y);
+               break;
+       case 'A':
+               if (!vc->vc_par[0])
+                       vc->vc_par[0]++;
+               gotoxy(vc, vc->state.x, vc->state.y - vc->vc_par[0]);
+               break;
+       case 'B':
+       case 'e':
+               if (!vc->vc_par[0])
+                       vc->vc_par[0]++;
+               gotoxy(vc, vc->state.x, vc->state.y + vc->vc_par[0]);
+               break;
+       case 'C':
+       case 'a':
+               if (!vc->vc_par[0])
+                       vc->vc_par[0]++;
+               gotoxy(vc, vc->state.x + vc->vc_par[0], vc->state.y);
+               break;
+       case 'D':
+               if (!vc->vc_par[0])
+                       vc->vc_par[0]++;
+               gotoxy(vc, vc->state.x - vc->vc_par[0], vc->state.y);
+               break;
+       case 'E':
+               if (!vc->vc_par[0])
+                       vc->vc_par[0]++;
+               gotoxy(vc, 0, vc->state.y + vc->vc_par[0]);
+               break;
+       case 'F':
+               if (!vc->vc_par[0])
+                       vc->vc_par[0]++;
+               gotoxy(vc, 0, vc->state.y - vc->vc_par[0]);
+               break;
+       case 'd':
+               if (vc->vc_par[0])
+                       vc->vc_par[0]--;
+               gotoxay(vc, vc->state.x ,vc->vc_par[0]);
+               break;
+       case 'H':
+       case 'f':
+               if (vc->vc_par[0])
+                       vc->vc_par[0]--;
+               if (vc->vc_par[1])
+                       vc->vc_par[1]--;
+               gotoxay(vc, vc->vc_par[1], vc->vc_par[0]);
+               break;
+       case 'J':
+               csi_J(vc, vc->vc_par[0]);
+               break;
+       case 'K':
+               csi_K(vc);
+               break;
+       case 'L':
+               csi_L(vc);
+               break;
+       case 'M':
+               csi_M(vc);
+               break;
+       case 'P':
+               csi_P(vc);
+               break;
+       case 'c':
+               if (!vc->vc_par[0])
                        respond_ID(tty);
-                       return;
-               case '7':
-                       save_cur(vc);
-                       return;
-               case '8':
-                       restore_cur(vc);
-                       return;
-               case '(':
-                       vc->vc_state = ESsetG0;
-                       return;
-               case ')':
-                       vc->vc_state = ESsetG1;
-                       return;
-               case '#':
-                       vc->vc_state = EShash;
-                       return;
-               case 'c':
-                       reset_terminal(vc, 1);
-                       return;
-               case '>':  /* Numeric keypad */
-                       clr_kbd(vc, kbdapplic);
-                       return;
-               case '=':  /* Appl. keypad */
-                       set_kbd(vc, kbdapplic);
-                       return;
+               break;
+       case 'g':
+               if (!vc->vc_par[0] && vc->state.x < VC_TABSTOPS_COUNT)
+                       set_bit(vc->state.x, vc->vc_tab_stop);
+               else if (vc->vc_par[0] == 3)
+                       bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT);
+               break;
+       case 'h':
+               csi_hl(vc, true);
+               break;
+       case 'l':
+               csi_hl(vc, false);
+               break;
+       case 'm':
+               csi_m(vc);
+               break;
+       case 'n':
+               if (vc->vc_par[0] == 5)
+                       status_report(tty);
+               else if (vc->vc_par[0] == 6)
+                       cursor_report(vc, tty);
+               break;
+       case 'q': /* DECLL - but only 3 leds */
+               /* map 0,1,2,3 to 0,1,2,4 */
+               if (vc->vc_par[0] < 4)
+                       vt_set_led_state(vc->vc_num,
+                                   (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4);
+               break;
+       case 'r':
+               if (!vc->vc_par[0])
+                       vc->vc_par[0]++;
+               if (!vc->vc_par[1])
+                       vc->vc_par[1] = vc->vc_rows;
+               /* Minimum allowed region is 2 lines */
+               if (vc->vc_par[0] < vc->vc_par[1] &&
+                   vc->vc_par[1] <= vc->vc_rows) {
+                       vc->vc_top = vc->vc_par[0] - 1;
+                       vc->vc_bottom = vc->vc_par[1];
+                       gotoxay(vc, 0, 0);
                }
+               break;
+       case 's':
+               save_cur(vc);
+               break;
+       case 'u':
+               restore_cur(vc);
+               break;
+       case 'X':
+               csi_X(vc);
+               break;
+       case '@':
+               csi_at(vc, vc->vc_par[0]);
+               break;
+       case ']':
+               csi_RSB(vc);
+               break;
+       }
+
+}
+
+static void vc_reset_params(struct vc_data *vc)
+{
+       memset(vc->vc_par, 0, sizeof(vc->vc_par));
+       vc->vc_npar = 0;
+}
+
+/* console_lock is held */
+static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, u8 c)
+{
+       /*
+        *  Control characters can be used in the _middle_
+        *  of an escape sequence, aside from ANSI control strings.
+        */
+       if (ansi_control_string(vc->vc_state) && c >= ASCII_IGNORE_FIRST &&
+           c <= ASCII_IGNORE_LAST)
+               return;
+
+       if (handle_ascii(tty, vc, c))
+               return;
+
+       switch(vc->vc_state) {
+       case ESesc:     /* ESC */
+               handle_esc(tty, vc, c);
                return;
-       case ESnonstd:
-               if (c=='P') {   /* palette escape sequence */
-                       for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
-                               vc->vc_par[vc->vc_npar] = 0;
-                       vc->vc_npar = 0;
+       case ESnonstd:  /* ESC ] aka OSC */
+               switch (c) {
+               case 'P': /* palette escape sequence */
+                       vc_reset_params(vc);
                        vc->vc_state = ESpalette;
                        return;
-               } else if (c=='R') {   /* reset palette */
+               case 'R': /* reset palette */
                        reset_palette(vc);
-                       vc->vc_state = ESnormal;
-               } else if (c>='0' && c<='9')
+                       break;
+               case '0' ... '9':
                        vc->vc_state = ESosc;
-               else
-                       vc->vc_state = ESnormal;
+                       return;
+               }
+               vc->vc_state = ESnormal;
                return;
-       case ESpalette:
+       case ESpalette: /* ESC ] P aka OSC P */
                if (isxdigit(c)) {
                        vc->vc_par[vc->vc_npar++] = hex_to_bin(c);
                        if (vc->vc_npar == 7) {
@@ -2273,16 +2604,14 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                } else
                        vc->vc_state = ESnormal;
                return;
-       case ESsquare:
-               for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
-                       vc->vc_par[vc->vc_npar] = 0;
-               vc->vc_npar = 0;
+       case ESsquare:  /* ESC [ aka CSI, parameters or modifiers expected */
+               vc_reset_params(vc);
+
                vc->vc_state = ESgetpars;
-               if (c == '[') { /* Function key */
-                       vc->vc_state=ESfunckey;
-                       return;
-               }
                switch (c) {
+               case '[': /* Function key */
+                       vc->vc_state = ESfunckey;
+                       return;
                case '?':
                        vc->vc_priv = EPdec;
                        return;
@@ -2298,182 +2627,44 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                }
                vc->vc_priv = EPecma;
                fallthrough;
-       case ESgetpars:
-               if (c == ';' && vc->vc_npar < NPAR - 1) {
-                       vc->vc_npar++;
-                       return;
-               } else if (c>='0' && c<='9') {
+       case ESgetpars: /* ESC [ aka CSI, parameters expected */
+               switch (c) {
+               case ';':
+                       if (vc->vc_npar < NPAR - 1) {
+                               vc->vc_npar++;
+                               return;
+                       }
+                       break;
+               case '0' ... '9':
                        vc->vc_par[vc->vc_npar] *= 10;
                        vc->vc_par[vc->vc_npar] += c - '0';
                        return;
                }
-               if (c >= 0x20 && c <= 0x3f) { /* 0x2x, 0x3a and 0x3c - 0x3f */
+               if (c >= ASCII_CSI_IGNORE_FIRST && c <= ASCII_CSI_IGNORE_LAST) {
                        vc->vc_state = EScsiignore;
                        return;
                }
+
+               /* parameters done, handle the control char @c */
+
                vc->vc_state = ESnormal;
-               switch(c) {
-               case 'h':
-                       if (vc->vc_priv <= EPdec)
-                               set_mode(vc, 1);
-                       return;
-               case 'l':
-                       if (vc->vc_priv <= EPdec)
-                               set_mode(vc, 0);
-                       return;
-               case 'c':
-                       if (vc->vc_priv == EPdec) {
-                               if (vc->vc_par[0])
-                                       vc->vc_cursor_type =
-                                               CUR_MAKE(vc->vc_par[0],
-                                                        vc->vc_par[1],
-                                                        vc->vc_par[2]);
-                               else
-                                       vc->vc_cursor_type = cur_default;
-                               return;
-                       }
-                       break;
-               case 'm':
-                       if (vc->vc_priv == EPdec) {
-                               clear_selection();
-                               if (vc->vc_par[0])
-                                       vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1];
-                               else
-                                       vc->vc_complement_mask = vc->vc_s_complement_mask;
-                               return;
-                       }
-                       break;
-               case 'n':
-                       if (vc->vc_priv == EPecma) {
-                               if (vc->vc_par[0] == 5)
-                                       status_report(tty);
-                               else if (vc->vc_par[0] == 6)
-                                       cursor_report(vc, tty);
-                       }
-                       return;
-               }
-               if (vc->vc_priv != EPecma) {
-                       vc->vc_priv = EPecma;
-                       return;
-               }
-               switch(c) {
-               case 'G': case '`':
-                       if (vc->vc_par[0])
-                               vc->vc_par[0]--;
-                       gotoxy(vc, vc->vc_par[0], vc->state.y);
-                       return;
-               case 'A':
-                       if (!vc->vc_par[0])
-                               vc->vc_par[0]++;
-                       gotoxy(vc, vc->state.x, vc->state.y - vc->vc_par[0]);
-                       return;
-               case 'B': case 'e':
-                       if (!vc->vc_par[0])
-                               vc->vc_par[0]++;
-                       gotoxy(vc, vc->state.x, vc->state.y + vc->vc_par[0]);
-                       return;
-               case 'C': case 'a':
-                       if (!vc->vc_par[0])
-                               vc->vc_par[0]++;
-                       gotoxy(vc, vc->state.x + vc->vc_par[0], vc->state.y);
-                       return;
-               case 'D':
-                       if (!vc->vc_par[0])
-                               vc->vc_par[0]++;
-                       gotoxy(vc, vc->state.x - vc->vc_par[0], vc->state.y);
-                       return;
-               case 'E':
-                       if (!vc->vc_par[0])
-                               vc->vc_par[0]++;
-                       gotoxy(vc, 0, vc->state.y + vc->vc_par[0]);
-                       return;
-               case 'F':
-                       if (!vc->vc_par[0])
-                               vc->vc_par[0]++;
-                       gotoxy(vc, 0, vc->state.y - vc->vc_par[0]);
-                       return;
-               case 'd':
-                       if (vc->vc_par[0])
-                               vc->vc_par[0]--;
-                       gotoxay(vc, vc->state.x ,vc->vc_par[0]);
-                       return;
-               case 'H': case 'f':
-                       if (vc->vc_par[0])
-                               vc->vc_par[0]--;
-                       if (vc->vc_par[1])
-                               vc->vc_par[1]--;
-                       gotoxay(vc, vc->vc_par[1], vc->vc_par[0]);
-                       return;
-               case 'J':
-                       csi_J(vc, vc->vc_par[0]);
-                       return;
-               case 'K':
-                       csi_K(vc, vc->vc_par[0]);
-                       return;
-               case 'L':
-                       csi_L(vc, vc->vc_par[0]);
-                       return;
-               case 'M':
-                       csi_M(vc, vc->vc_par[0]);
-                       return;
-               case 'P':
-                       csi_P(vc, vc->vc_par[0]);
-                       return;
-               case 'c':
-                       if (!vc->vc_par[0])
-                               respond_ID(tty);
-                       return;
-               case 'g':
-                       if (!vc->vc_par[0] && vc->state.x < VC_TABSTOPS_COUNT)
-                               set_bit(vc->state.x, vc->vc_tab_stop);
-                       else if (vc->vc_par[0] == 3)
-                               bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT);
-                       return;
-               case 'm':
-                       csi_m(vc);
-                       return;
-               case 'q': /* DECLL - but only 3 leds */
-                       /* map 0,1,2,3 to 0,1,2,4 */
-                       if (vc->vc_par[0] < 4)
-                               vt_set_led_state(vc->vc_num,
-                                           (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4);
-                       return;
-               case 'r':
-                       if (!vc->vc_par[0])
-                               vc->vc_par[0]++;
-                       if (!vc->vc_par[1])
-                               vc->vc_par[1] = vc->vc_rows;
-                       /* Minimum allowed region is 2 lines */
-                       if (vc->vc_par[0] < vc->vc_par[1] &&
-                           vc->vc_par[1] <= vc->vc_rows) {
-                               vc->vc_top = vc->vc_par[0] - 1;
-                               vc->vc_bottom = vc->vc_par[1];
-                               gotoxay(vc, 0, 0);
-                       }
-                       return;
-               case 's':
-                       save_cur(vc);
-                       return;
-               case 'u':
-                       restore_cur(vc);
-                       return;
-               case 'X':
-                       csi_X(vc, vc->vc_par[0]);
+
+               switch (vc->vc_priv) {
+               case EPdec:
+                       csi_DEC(tty, vc, c);
                        return;
-               case '@':
-                       csi_at(vc, vc->vc_par[0]);
+               case EPecma:
+                       csi_ECMA(tty, vc, c);
                        return;
-               case ']': /* setterm functions */
-                       setterm_command(vc);
+               default:
                        return;
                }
-               return;
        case EScsiignore:
-               if (c >= 20 && c <= 0x3f)
+               if (c >= ASCII_CSI_IGNORE_FIRST && c <= ASCII_CSI_IGNORE_LAST)
                        return;
                vc->vc_state = ESnormal;
                return;
-       case ESpercent:
+       case ESpercent: /* ESC % */
                vc->vc_state = ESnormal;
                switch (c) {
                case '@':  /* defined in ISO 2022 */
@@ -2485,36 +2676,36 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                        return;
                }
                return;
-       case ESfunckey:
+       case ESfunckey: /* ESC [ [ aka CSI [ */
                vc->vc_state = ESnormal;
                return;
-       case EShash:
+       case EShash:    /* ESC # */
                vc->vc_state = ESnormal;
                if (c == '8') {
                        /* DEC screen alignment test. kludge :-) */
                        vc->vc_video_erase_char =
                                (vc->vc_video_erase_char & 0xff00) | 'E';
-                       csi_J(vc, 2);
+                       csi_J(vc, CSI_J_VISIBLE);
                        vc->vc_video_erase_char =
                                (vc->vc_video_erase_char & 0xff00) | ' ';
                        do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
                }
                return;
-       case ESsetG0:
+       case ESsetG0:   /* ESC ( */
                vc_setGx(vc, 0, c);
                vc->vc_state = ESnormal;
                return;
-       case ESsetG1:
+       case ESsetG1:   /* ESC ) */
                vc_setGx(vc, 1, c);
                vc->vc_state = ESnormal;
                return;
-       case ESapc:
+       case ESapc:     /* ESC _ */
                return;
-       case ESosc:
+       case ESosc:     /* ESC ] [0-9] aka OSC [0-9] */
                return;
-       case ESpm:
+       case ESpm:      /* ESC ^ */
                return;
-       case ESdcs:
+       case ESdcs:     /* ESC P */
                return;
        default:
                vc->vc_state = ESnormal;
@@ -2588,33 +2779,39 @@ static inline int vc_translate_ascii(const struct vc_data *vc, int c)
 
 
 /**
- * vc_sanitize_unicode - Replace invalid Unicode code points with U+FFFD
- * @c: the received character, or U+FFFD for invalid sequences.
+ * vc_sanitize_unicode - Replace invalid Unicode code points with ``U+FFFD``
+ * @c: the received code point
  */
 static inline int vc_sanitize_unicode(const int c)
 {
-       if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff)
+       if (c >= 0xd800 && c <= 0xdfff)
                return 0xfffd;
 
        return c;
 }
 
 /**
- * vc_translate_unicode - Combine UTF-8 into Unicode in @vc_utf_char
+ * vc_translate_unicode - Combine UTF-8 into Unicode in &vc_data.vc_utf_char
  * @vc: virtual console
- * @c: character to translate
- * @rescan: we return true if we need more (continuation) data
+ * @c: UTF-8 byte to translate
+ * @rescan: set to true iff @c wasn't consumed here and needs to be re-processed
+ *
+ * * &vc_data.vc_utf_char is the being-constructed Unicode code point.
+ * * &vc_data.vc_utf_count is the number of continuation bytes still expected to
+ *   arrive.
+ * * &vc_data.vc_npar is the number of continuation bytes arrived so far.
  *
- * @vc_utf_char is the being-constructed unicode character.
- * @vc_utf_count is the number of continuation bytes still expected to arrive.
- * @vc_npar is the number of continuation bytes arrived so far.
+ * Return:
+ * * %-1 - Input OK so far, @c consumed, further bytes expected.
+ * * %0xFFFD - Possibility 1: input invalid, @c may have been consumed (see
+ *             desc. of @rescan). Possibility 2: input OK, @c consumed,
+ *             ``U+FFFD`` is the resulting code point. ``U+FFFD`` is valid,
+ *             ``REPLACEMENT CHARACTER``.
+ * * otherwise - Input OK, @c consumed, resulting code point returned.
  */
 static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan)
 {
-       static const u32 utf8_length_changes[] = {
-               0x0000007f, 0x000007ff, 0x0000ffff,
-               0x001fffff, 0x03ffffff, 0x7fffffff
-       };
+       static const u32 utf8_length_changes[] = {0x7f, 0x7ff, 0xffff, 0x10ffff};
 
        /* Continuation byte received */
        if ((c & 0xc0) == 0x80) {
@@ -2660,14 +2857,7 @@ static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan)
        } else if ((c & 0xf8) == 0xf0) {
                vc->vc_utf_count = 3;
                vc->vc_utf_char = (c & 0x07);
-       } else if ((c & 0xfc) == 0xf8) {
-               vc->vc_utf_count = 4;
-               vc->vc_utf_char = (c & 0x03);
-       } else if ((c & 0xfe) == 0xfc) {
-               vc->vc_utf_count = 5;
-               vc->vc_utf_char = (c & 0x01);
        } else {
-               /* 254 and 255 are invalid */
                return 0xfffd;
        }
 
@@ -2711,9 +2901,13 @@ static bool vc_is_control(struct vc_data *vc, int tc, int c)
         * as cursor movement) and should not be displayed as a glyph unless
         * the disp_ctrl mode is explicitly enabled.
         */
-       static const u32 CTRL_ACTION = 0x0d00ff81;
+       static const u32 CTRL_ACTION = BIT(ASCII_NULL) |
+               GENMASK(ASCII_SHIFTIN, ASCII_BELL) | BIT(ASCII_CANCEL) |
+               BIT(ASCII_SUBSTITUTE) | BIT(ASCII_ESCAPE);
        /* Cannot be overridden by disp_ctrl */
-       static const u32 CTRL_ALWAYS = 0x0800f501;
+       static const u32 CTRL_ALWAYS = BIT(ASCII_NULL) | BIT(ASCII_BACKSPACE) |
+               BIT(ASCII_LINEFEED) | BIT(ASCII_SHIFTIN) | BIT(ASCII_SHIFTOUT) |
+               BIT(ASCII_CAR_RET) | BIT(ASCII_FORMFEED) | BIT(ASCII_ESCAPE);
 
        if (vc->vc_state != ESnormal)
                return true;
@@ -2730,17 +2924,17 @@ static bool vc_is_control(struct vc_data *vc, int tc, int c)
         * useless without them; to display an arbitrary font position use the
         * direct-to-font zone in UTF-8 mode.
         */
-       if (c < 32) {
+       if (c < BITS_PER_TYPE(CTRL_ALWAYS)) {
                if (vc->vc_disp_ctrl)
                        return CTRL_ALWAYS & BIT(c);
                else
                        return vc->vc_utf || (CTRL_ACTION & BIT(c));
        }
 
-       if (c == 127 && !vc->vc_disp_ctrl)
+       if (c == ASCII_DEL && !vc->vc_disp_ctrl)
                return true;
 
-       if (c == 128 + 27)
+       if (c == ASCII_EXT_CSI)
                return true;
 
        return false;
@@ -2852,7 +3046,7 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
        };
        int c, tc, n = 0;
        unsigned int currcons;
-       struct vc_data *vc;
+       struct vc_data *vc = tty->driver_data;
        struct vt_notifier_param param;
        bool rescan;
 
@@ -2860,13 +3054,6 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
                return count;
 
        console_lock();
-       vc = tty->driver_data;
-       if (vc == NULL) {
-               pr_err("vt: argh, driver_data is NULL !\n");
-               console_unlock();
-               return 0;
-       }
-
        currcons = vc->vc_num;
        if (!vc_cons_allocated(currcons)) {
                /* could this happen? */
@@ -2883,7 +3070,7 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
        param.vc = vc;
 
        while (!tty->flow.stopped && count) {
-               int orig = *buf;
+               u8 orig = *buf;
                buf++;
                n++;
                count--;
@@ -2992,16 +3179,16 @@ struct tty_driver *console_driver;
 #ifdef CONFIG_VT_CONSOLE
 
 /**
- * vt_kmsg_redirect() - Sets/gets the kernel message console
- * @new:       The new virtual terminal number or -1 if the console should stay
- *             unchanged
+ * vt_kmsg_redirect() - sets/gets the kernel message console
+ * @new: the new virtual terminal number or -1 if the console should stay
+ *     unchanged
  *
  * By default, the kernel messages are always printed on the current virtual
  * console. However, the user may modify that default with the
- * TIOCL_SETKMSGREDIRECT ioctl call.
+ * %TIOCL_SETKMSGREDIRECT ioctl call.
  *
  * This function sets the kernel message console to be @new. It returns the old
- * virtual console number. The virtual terminal number 0 (both as parameter and
+ * virtual console number. The virtual terminal number %0 (both as parameter and
  * return value) means no redirection (i.e. always printed on the currently
  * active console).
  *
@@ -3009,8 +3196,8 @@ struct tty_driver *console_driver;
  * value is not modified. You may use the macro vt_get_kmsg_redirect() in that
  * case to make the code more understandable.
  *
- * When the kernel is compiled without CONFIG_VT_CONSOLE, this function ignores
- * the parameter and always returns 0.
+ * When the kernel is compiled without %CONFIG_VT_CONSOLE, this function ignores
+ * the parameter and always returns %0.
  */
 int vt_kmsg_redirect(int new)
 {
@@ -3065,22 +3252,23 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        cnt = 0;
        while (count--) {
                c = *b++;
-               if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
+               if (c == ASCII_LINEFEED || c == ASCII_CAR_RET ||
+                   c == ASCII_BACKSPACE || vc->vc_need_wrap) {
                        if (cnt && con_is_visible(vc))
                                vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x);
                        cnt = 0;
-                       if (c == 8) {           /* backspace */
+                       if (c == ASCII_BACKSPACE) {
                                bs(vc);
                                start = (ushort *)vc->vc_pos;
                                start_x = vc->state.x;
                                continue;
                        }
-                       if (c != 13)
+                       if (c != ASCII_CAR_RET)
                                lf(vc);
                        cr(vc);
                        start = (ushort *)vc->vc_pos;
                        start_x = vc->state.x;
-                       if (c == 10 || c == 13)
+                       if (c == ASCII_LINEFEED || c == ASCII_CAR_RET)
                                continue;
                }
                vc_uniscr_putc(vc, c);
@@ -3144,6 +3332,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
 {
        char type, data;
        char __user *p = (char __user *)arg;
+       void __user *param_aligned32 = (u32 __user *)arg + 1;
+       void __user *param = (void __user *)arg + 1;
        int lines;
        int ret;
 
@@ -3157,8 +3347,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
        case TIOCL_SETSEL:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               return set_selection_user((struct tiocl_selection
-                                        __user *)(p+1), tty);
+               return set_selection_user(param, tty);
        case TIOCL_PASTESEL:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
@@ -3171,10 +3360,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
        case TIOCL_SELLOADLUT:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               console_lock();
-               ret = sel_loadlut(p);
-               console_unlock();
-               break;
+               return sel_loadlut(param_aligned32);
        case TIOCL_GETSHIFTSTATE:
                /*
                 * Make it possible to react to Shift+Mousebutton. Note that
@@ -3190,10 +3376,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                console_unlock();
                return put_user(data, p);
        case TIOCL_SETVESABLANK:
-               console_lock();
-               ret = set_vesa_blanking(p);
-               console_unlock();
-               break;
+               return set_vesa_blanking(param);
        case TIOCL_GETKMSGREDIRECT:
                data = vt_get_kmsg_redirect();
                return put_user(data, p);
@@ -3214,7 +3397,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                 */
                return fg_console;
        case TIOCL_SCROLLCONSOLE:
-               if (get_user(lines, (s32 __user *)(p+4)))
+               if (get_user(lines, (s32 __user *)param_aligned32))
                        return -EFAULT;
 
                /*
@@ -3312,16 +3495,13 @@ static void con_start(struct tty_struct *tty)
 
 static void con_flush_chars(struct tty_struct *tty)
 {
-       struct vc_data *vc;
+       struct vc_data *vc = tty->driver_data;
 
        if (in_interrupt())     /* from flush_to_ldisc */
                return;
 
-       /* if we race with con_close(), vt may be null */
        console_lock();
-       vc = tty->driver_data;
-       if (vc)
-               set_cursor(vc);
+       set_cursor(vc);
        console_unlock();
 }
 
@@ -3471,7 +3651,7 @@ static int __init con_init(void)
                vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
                INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
                tty_port_init(&vc->port);
-               visual_init(vc, currcons, 1);
+               visual_init(vc, currcons, true);
                /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */
                vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
                vc_init(vc, currcons || !vc->vc_sw->con_save_screen);
@@ -3481,7 +3661,7 @@ static int __init con_init(void)
        set_origin(vc);
        save_screen(vc);
        gotoxy(vc, vc->state.x, vc->state.y);
-       csi_J(vc, 0);
+       csi_J(vc, CSI_J_CURSOR_TO_END);
        update_screen(vc);
        pr_info("Console: %s %s %dx%d\n",
                vc->vc_can_do_color ? "colour" : "mono",
@@ -3640,7 +3820,7 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last,
                old_was_color = vc->vc_can_do_color;
                vc->vc_sw->con_deinit(vc);
                vc->vc_origin = (unsigned long)vc->vc_screenbuf;
-               visual_init(vc, i, 0);
+               visual_init(vc, i, false);
                set_origin(vc);
                update_attr(vc);
 
@@ -3930,7 +4110,7 @@ static void vtconsole_deinit_device(struct con_driver *con)
  * RETURNS: zero if unbound, nonzero if bound
  *
  * Drivers can call this and if zero, they should release
- * all resources allocated on con_startup()
+ * all resources allocated on &consw.con_startup()
  */
 int con_is_bound(const struct consw *csw)
 {
@@ -3970,15 +4150,9 @@ EXPORT_SYMBOL(con_is_visible);
  * Called when the console is taken over by the kernel debugger, this
  * function needs to save the current console state, then put the console
  * into a state suitable for the kernel debugger.
- *
- * RETURNS:
- * Zero on success, nonzero if a failure occurred when trying to prepare
- * the console for the debugger.
  */
-int con_debug_enter(struct vc_data *vc)
+void con_debug_enter(struct vc_data *vc)
 {
-       int ret = 0;
-
        saved_fg_console = fg_console;
        saved_last_console = last_console;
        saved_want_console = want_console;
@@ -3987,7 +4161,7 @@ int con_debug_enter(struct vc_data *vc)
        vc->vc_mode = KD_TEXT;
        console_blanked = 0;
        if (vc->vc_sw->con_debug_enter)
-               ret = vc->vc_sw->con_debug_enter(vc);
+               vc->vc_sw->con_debug_enter(vc);
 #ifdef CONFIG_KGDB_KDB
        /* Set the initial LINES variable if it is not already set */
        if (vc->vc_rows < 999) {
@@ -4017,7 +4191,6 @@ int con_debug_enter(struct vc_data *vc)
                }
        }
 #endif /* CONFIG_KGDB_KDB */
-       return ret;
 }
 EXPORT_SYMBOL_GPL(con_debug_enter);
 
@@ -4026,15 +4199,10 @@ EXPORT_SYMBOL_GPL(con_debug_enter);
  *
  * Restore the console state to what it was before the kernel debugger
  * was invoked.
- *
- * RETURNS:
- * Zero on success, nonzero if a failure occurred when trying to restore
- * the console.
  */
-int con_debug_leave(void)
+void con_debug_leave(void)
 {
        struct vc_data *vc;
-       int ret = 0;
 
        fg_console = saved_fg_console;
        last_console = saved_last_console;
@@ -4044,8 +4212,7 @@ int con_debug_leave(void)
 
        vc = vc_cons[fg_console].d;
        if (vc->vc_sw->con_debug_leave)
-               ret = vc->vc_sw->con_debug_leave(vc);
-       return ret;
+               vc->vc_sw->con_debug_leave(vc);
 }
 EXPORT_SYMBOL_GPL(con_debug_leave);
 
@@ -4275,14 +4442,17 @@ postcore_initcall(vtconsole_class_init);
  *     Screen blanking
  */
 
-static int set_vesa_blanking(char __user *p)
+static int set_vesa_blanking(u8 __user *mode_user)
 {
-       unsigned int mode;
+       u8 mode;
 
-       if (get_user(mode, p + 1))
+       if (get_user(mode, mode_user))
                return -EFAULT;
 
-       vesa_blank_mode = (mode < 4) ? mode : 0;
+       console_lock();
+       vesa_blank_mode = (mode <= VESA_BLANK_MAX) ? mode : VESA_NO_BLANKING;
+       console_unlock();
+
        return 0;
 }
 
@@ -4307,7 +4477,7 @@ void do_blank_screen(int entering_gfx)
        if (entering_gfx) {
                hide_cursor(vc);
                save_screen(vc);
-               vc->vc_sw->con_blank(vc, -1, 1);
+               vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1);
                console_blanked = fg_console + 1;
                blank_state = blank_off;
                set_origin(vc);
@@ -4328,7 +4498,8 @@ void do_blank_screen(int entering_gfx)
 
        save_screen(vc);
        /* In case we need to reset origin, blanking hook returns 1 */
-       i = vc->vc_sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
+       i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND :
+                                (vesa_blank_mode + 1), 0);
        console_blanked = fg_console + 1;
        if (i)
                set_origin(vc);
@@ -4379,7 +4550,7 @@ void do_unblank_screen(int leaving_gfx)
        }
 
        console_blanked = 0;
-       if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
+       if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
                /* Low-level driver cannot restore -> do it ourselves */
                update_screen(vc);
        if (console_blank_hook)
@@ -4584,7 +4755,7 @@ out:
        return rc;
 }
 
-static int con_font_set(struct vc_data *vc, struct console_font_op *op)
+static int con_font_set(struct vc_data *vc, const struct console_font_op *op)
 {
        struct console_font font;
        int rc = -EINVAL;
@@ -4748,43 +4919,3 @@ void vcs_scr_updated(struct vc_data *vc)
 {
        notify_update(vc);
 }
-
-void vc_scrolldelta_helper(struct vc_data *c, int lines,
-               unsigned int rolled_over, void *base, unsigned int size)
-{
-       unsigned long ubase = (unsigned long)base;
-       ptrdiff_t scr_end = (void *)c->vc_scr_end - base;
-       ptrdiff_t vorigin = (void *)c->vc_visible_origin - base;
-       ptrdiff_t origin = (void *)c->vc_origin - base;
-       int margin = c->vc_size_row * 4;
-       int from, wrap, from_off, avail;
-
-       /* Turn scrollback off */
-       if (!lines) {
-               c->vc_visible_origin = c->vc_origin;
-               return;
-       }
-
-       /* Do we have already enough to allow jumping from 0 to the end? */
-       if (rolled_over > scr_end + margin) {
-               from = scr_end;
-               wrap = rolled_over + c->vc_size_row;
-       } else {
-               from = 0;
-               wrap = size;
-       }
-
-       from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row;
-       avail = (origin - from + wrap) % wrap;
-
-       /* Only a little piece would be left? Show all incl. the piece! */
-       if (avail < 2 * margin)
-               margin = 0;
-       if (from_off < margin)
-               from_off = 0;
-       if (from_off > avail - margin)
-               from_off = avail;
-
-       c->vc_visible_origin = ubase + (from + from_off) % wrap;
-}
-EXPORT_SYMBOL_GPL(vc_scrolldelta_helper);
index 8c685b5014044b891c40e1cf00bd4629a661e33f..4b91072f3a4e916a3acd9ef8841764ab4febb0c9 100644 (file)
@@ -714,8 +714,7 @@ static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
                                vcp->vc_scan_lines = v.v_vlin;
                        if (v.v_clin)
                                vcp->vc_cell_height = v.v_clin;
-                       vcp->vc_resize_user = 1;
-                       ret = vc_resize(vcp, v.v_cols, v.v_rows);
+                       ret = __vc_resize(vcp, v.v_cols, v.v_rows, true);
                        if (ret) {
                                vcp->vc_scan_lines = save_scan_lines;
                                vcp->vc_cell_height = save_cell_height;
@@ -923,9 +922,8 @@ int vt_ioctl(struct tty_struct *tty,
                        vc = vc_cons[i].d;
 
                        if (vc) {
-                               vc->vc_resize_user = 1;
                                /* FIXME: review v tty lock */
-                               vc_resize(vc_cons[i].d, cc, ll);
+                               __vc_resize(vc_cons[i].d, cc, ll, true);
                        }
                }
                console_unlock();
index 14af5d9e13b00efd153c03f4f4553f52a6a01080..139049368fdcf86f8174208d950448d340dfee25 100644 (file)
@@ -50,7 +50,8 @@ void dummycon_unregister_output_notifier(struct notifier_block *nb)
        raw_notifier_chain_unregister(&dummycon_output_nh, nb);
 }
 
-static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos)
+static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y,
+                          unsigned int x)
 {
        WARN_CONSOLE_UNLOCKED();
 
@@ -58,10 +59,10 @@ static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos)
        raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
 }
 
-static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
-                          int count, int ypos, int xpos)
+static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
+                          unsigned int ypos, unsigned int xpos)
 {
-       int i;
+       unsigned int i;
 
        if (!dummycon_putc_called) {
                /* Ignore erases */
@@ -78,18 +79,21 @@ static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
        raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
 }
 
-static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch)
+static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
+                          bool mode_switch)
 {
        /* Redraw, so that we get putc(s) for output done while blanked */
-       return 1;
+       return true;
 }
 #else
-static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
-static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
-                          int count, int ypos, int xpos) { }
-static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch)
+static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y,
+                         unsigned int x) { }
+static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
+                          unsigned int ypos, unsigned int xpos) { }
+static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
+                          bool mode_switch)
 {
-       return 0;
+       return false;
 }
 #endif
 
@@ -98,7 +102,7 @@ static const char *dummycon_startup(void)
     return "dummy device";
 }
 
-static void dummycon_init(struct vc_data *vc, int init)
+static void dummycon_init(struct vc_data *vc, bool init)
 {
     vc->vc_can_do_color = 1;
     if (init) {
@@ -109,9 +113,9 @@ static void dummycon_init(struct vc_data *vc, int init)
 }
 
 static void dummycon_deinit(struct vc_data *vc) { }
-static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height,
-                          int width) { }
-static void dummycon_cursor(struct vc_data *vc, int mode) { }
+static void dummycon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+                          unsigned int width) { }
+static void dummycon_cursor(struct vc_data *vc, bool enable) { }
 
 static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
                            unsigned int bottom, enum con_scroll dir,
@@ -120,9 +124,9 @@ static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
        return false;
 }
 
-static int dummycon_switch(struct vc_data *vc)
+static bool dummycon_switch(struct vc_data *vc)
 {
-       return 0;
+       return false;
 }
 
 /*
index ef29b321967f07353f92714f78a58522e907ddf5..c0e1f4554a44b08e927e932d7e3ba2005f60ad84 100644 (file)
@@ -352,7 +352,7 @@ static const char *mdacon_startup(void)
        return "MDA-2";
 }
 
-static void mdacon_init(struct vc_data *c, int init)
+static void mdacon_init(struct vc_data *c, bool init)
 {
        c->vc_complement_mask = 0x0800;  /* reverse video */
        c->vc_display_fg = &mda_display_fg;
@@ -427,13 +427,8 @@ static inline u16 *mda_addr(unsigned int x, unsigned int y)
        return mda_vram_base + y * mda_num_columns + x;
 }
 
-static void mdacon_putc(struct vc_data *c, int ch, int y, int x)
-{
-       scr_writew(mda_convert_attr(ch), mda_addr(x, y));
-}
-
-static void mdacon_putcs(struct vc_data *c, const unsigned short *s,
-                        int count, int y, int x)
+static void mdacon_putcs(struct vc_data *c, const u16 *s, unsigned int count,
+                        unsigned int y, unsigned int x)
 {
        u16 *dest = mda_addr(x, y);
 
@@ -442,29 +437,22 @@ static void mdacon_putcs(struct vc_data *c, const unsigned short *s,
        }
 }
 
-static void mdacon_clear(struct vc_data *c, int y, int x, 
-                         int height, int width)
+static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x,
+                        unsigned int width)
 {
        u16 *dest = mda_addr(x, y);
        u16 eattr = mda_convert_attr(c->vc_video_erase_char);
 
-       if (width <= 0 || height <= 0)
-               return;
-
-       if (x==0 && width==mda_num_columns) {
-               scr_memsetw(dest, eattr, height*width*2);
-       } else {
-               for (; height > 0; height--, dest+=mda_num_columns)
-                       scr_memsetw(dest, eattr, width*2);
-       }
+       scr_memsetw(dest, eattr, width * 2);
 }
-                        
-static int mdacon_switch(struct vc_data *c)
+
+static bool mdacon_switch(struct vc_data *c)
 {
-       return 1;       /* redrawing needed */
+       return true;    /* redrawing needed */
 }
 
-static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
+static bool mdacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
+                        bool mode_switch)
 {
        if (mda_type == TYPE_MDA) {
                if (blank) 
@@ -472,20 +460,20 @@ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
                                mda_convert_attr(c->vc_video_erase_char),
                                c->vc_screenbuf_size);
                /* Tell console.c that it has to restore the screen itself */
-               return 1;
+               return true;
        } else {
                if (blank)
                        outb_p(0x00, mda_mode_port);    /* disable video */
                else
                        outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, 
                                mda_mode_port);
-               return 0;
+               return false;
        }
 }
 
-static void mdacon_cursor(struct vc_data *c, int mode)
+static void mdacon_cursor(struct vc_data *c, bool enable)
 {
-       if (mode == CM_ERASE) {
+       if (!enable) {
                mda_set_cursor(mda_vram_len - 1);
                return;
        }
@@ -544,7 +532,6 @@ static const struct consw mda_con = {
        .con_init =             mdacon_init,
        .con_deinit =           mdacon_deinit,
        .con_clear =            mdacon_clear,
-       .con_putc =             mdacon_putc,
        .con_putcs =            mdacon_putcs,
        .con_cursor =           mdacon_cursor,
        .con_scroll =           mdacon_scroll,
index e8e4f82cd4a1b845c83f36d126745fffbf176b46..a51cfc1d560e7af172b30da70b1f06668b5e48b1 100644 (file)
@@ -324,7 +324,7 @@ out_unmap:
        return NULL;
 }
 
-static void newport_init(struct vc_data *vc, int init)
+static void newport_init(struct vc_data *vc, bool init)
 {
        int cols, rows;
 
@@ -346,12 +346,12 @@ static void newport_deinit(struct vc_data *c)
        }
 }
 
-static void newport_clear(struct vc_data *vc, int sy, int sx, int height,
-                         int width)
+static void newport_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+                         unsigned int width)
 {
        int xend = ((sx + width) << 3) - 1;
        int ystart = ((sy << 4) + topscan) & 0x3ff;
-       int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff;
+       int yend = (((sy + 1) << 4) + topscan - 1) & 0x3ff;
 
        if (logo_active)
                return;
@@ -367,8 +367,8 @@ static void newport_clear(struct vc_data *vc, int sy, int sx, int height,
        }
 }
 
-static void newport_putc(struct vc_data *vc, int charattr, int ypos,
-                        int xpos)
+static void newport_putc(struct vc_data *vc, u16 charattr, unsigned int ypos,
+                        unsigned int xpos)
 {
        unsigned char *p;
 
@@ -396,12 +396,13 @@ static void newport_putc(struct vc_data *vc, int charattr, int ypos,
        RENDER(npregs, p);
 }
 
-static void newport_putcs(struct vc_data *vc, const unsigned short *s,
-                         int count, int ypos, int xpos)
+static void newport_putcs(struct vc_data *vc, const u16 *s,
+                         unsigned int count, unsigned int ypos,
+                         unsigned int xpos)
 {
-       int i;
-       int charattr;
        unsigned char *p;
+       unsigned int i;
+       u16 charattr;
 
        charattr = (scr_readw(s) >> 8) & 0xff;
 
@@ -437,32 +438,28 @@ static void newport_putcs(struct vc_data *vc, const unsigned short *s,
        }
 }
 
-static void newport_cursor(struct vc_data *vc, int mode)
+static void newport_cursor(struct vc_data *vc, bool enable)
 {
        unsigned short treg;
        int xcurs, ycurs;
 
-       switch (mode) {
-       case CM_ERASE:
-               treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
-               newport_vc2_set(npregs, VC2_IREG_CONTROL,
-                               (treg & ~(VC2_CTRL_ECDISP)));
-               break;
+       treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
 
-       case CM_MOVE:
-       case CM_DRAW:
-               treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+       if (!enable) {
                newport_vc2_set(npregs, VC2_IREG_CONTROL,
-                               (treg | VC2_CTRL_ECDISP));
-               xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2;
-               ycurs = ((xcurs / vc->vc_cols) << 4) + 31;
-               xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction;
-               newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs);
-               newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs);
+                               (treg & ~(VC2_CTRL_ECDISP)));
+               return;
        }
+
+       newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP));
+       xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2;
+       ycurs = ((xcurs / vc->vc_cols) << 4) + 31;
+       xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction;
+       newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs);
+       newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs);
 }
 
-static int newport_switch(struct vc_data *vc)
+static bool newport_switch(struct vc_data *vc)
 {
        static int logo_drawn = 0;
 
@@ -476,14 +473,15 @@ static int newport_switch(struct vc_data *vc)
                }
        }
 
-       return 1;
+       return true;
 }
 
-static int newport_blank(struct vc_data *c, int blank, int mode_switch)
+static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank,
+                         bool mode_switch)
 {
        unsigned short treg;
 
-       if (blank == 0) {
+       if (blank == VESA_NO_BLANKING) {
                /* unblank console */
                treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
                newport_vc2_set(npregs, VC2_IREG_CONTROL,
@@ -494,10 +492,12 @@ static int newport_blank(struct vc_data *c, int blank, int mode_switch)
                newport_vc2_set(npregs, VC2_IREG_CONTROL,
                                (treg & ~(VC2_CTRL_EDISP)));
        }
-       return 1;
+
+       return true;
 }
 
-static int newport_set_font(int unit, struct console_font *op, unsigned int vpitch)
+static int newport_set_font(int unit, const struct console_font *op,
+                           unsigned int vpitch)
 {
        int w = op->width;
        int h = op->height;
@@ -564,12 +564,13 @@ static int newport_set_def_font(int unit, struct console_font *op)
        return 0;
 }
 
-static int newport_font_default(struct vc_data *vc, struct console_font *op, char *name)
+static int newport_font_default(struct vc_data *vc, struct console_font *op,
+                               const char *name)
 {
        return newport_set_def_font(vc->vc_num, op);
 }
 
-static int newport_font_set(struct vc_data *vc, struct console_font *font,
+static int newport_font_set(struct vc_data *vc, const struct console_font *font,
                            unsigned int vpitch, unsigned int flags)
 {
        return newport_set_font(vc->vc_num, font, vpitch);
index 992a4fa431aaa90cbf8f47f9d86a51169b3dda38..4c7b4959a1aab7cb46ebca80c1bba3e0d7b8d911 100644 (file)
@@ -71,19 +71,8 @@ static const char *sticon_startup(void)
     return "STI console";
 }
 
-static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
-{
-    if (vga_is_gfx || console_blanked)
-           return;
-
-    if (conp->vc_mode != KD_TEXT)
-           return;
-
-    sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]);
-}
-
-static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
-                        int count, int ypos, int xpos)
+static void sticon_putcs(struct vc_data *conp, const u16 *s, unsigned int count,
+                        unsigned int ypos, unsigned int xpos)
 {
     if (vga_is_gfx || console_blanked)
            return;
@@ -97,7 +86,7 @@ static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
     }
 }
 
-static void sticon_cursor(struct vc_data *conp, int mode)
+static void sticon_cursor(struct vc_data *conp, bool enable)
 {
     unsigned short car1;
 
@@ -106,23 +95,20 @@ static void sticon_cursor(struct vc_data *conp, int mode)
        return;
 
     car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
-    switch (mode) {
-    case CM_ERASE:
+    if (!enable) {
        sti_putc(sticon_sti, car1, conp->state.y, conp->state.x,
                 font_data[conp->vc_num]);
-       break;
-    case CM_MOVE:
-    case CM_DRAW:
-       switch (CUR_SIZE(conp->vc_cursor_type)) {
-       case CUR_UNDERLINE:
-       case CUR_LOWER_THIRD:
-       case CUR_LOWER_HALF:
-       case CUR_TWO_THIRDS:
-       case CUR_BLOCK:
-           sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
-                    conp->state.y, conp->state.x, font_data[conp->vc_num]);
-           break;
-       }
+       return;
+    }
+
+    switch (CUR_SIZE(conp->vc_cursor_type)) {
+    case CUR_UNDERLINE:
+    case CUR_LOWER_THIRD:
+    case CUR_LOWER_HALF:
+    case CUR_TWO_THIRDS:
+    case CUR_BLOCK:
+       sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
+                conp->state.y, conp->state.x, font_data[conp->vc_num]);
        break;
     }
 }
@@ -135,7 +121,7 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t,
     if (vga_is_gfx)
         return false;
 
-    sticon_cursor(conp, CM_ERASE);
+    sticon_cursor(conp, false);
 
     switch (dir) {
     case SM_UP:
@@ -167,7 +153,7 @@ static void sticon_set_def_font(int unit)
        }
 }
 
-static int sticon_set_font(struct vc_data *vc, struct console_font *op,
+static int sticon_set_font(struct vc_data *vc, const struct console_font *op,
                           unsigned int vpitch)
 {
        struct sti_struct *sti = sticon_sti;
@@ -260,20 +246,21 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op,
        return 0;
 }
 
-static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name)
+static int sticon_font_default(struct vc_data *vc, struct console_font *op,
+                              const char *name)
 {
        sticon_set_def_font(vc->vc_num);
 
        return 0;
 }
 
-static int sticon_font_set(struct vc_data *vc, struct console_font *font,
+static int sticon_font_set(struct vc_data *vc, const struct console_font *font,
                           unsigned int vpitch, unsigned int flags)
 {
        return sticon_set_font(vc, font, vpitch);
 }
 
-static void sticon_init(struct vc_data *c, int init)
+static void sticon_init(struct vc_data *c, bool init)
 {
     struct sti_struct *sti = sticon_sti;
     int vc_cols, vc_rows;
@@ -300,33 +287,32 @@ static void sticon_deinit(struct vc_data *c)
        sticon_set_def_font(i);
 }
 
-static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
-                        int width)
+static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx,
+                        unsigned int width)
 {
-    if (!height || !width)
-       return;
-
-    sti_clear(sticon_sti, sy, sx, height, width,
+    sti_clear(sticon_sti, sy, sx, 1, width,
              conp->vc_video_erase_char, font_data[conp->vc_num]);
 }
 
-static int sticon_switch(struct vc_data *conp)
+static bool sticon_switch(struct vc_data *conp)
 {
-    return 1;  /* needs refreshing */
+    return true;       /* needs refreshing */
 }
 
-static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
+static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank,
+                        bool mode_switch)
 {
-    if (blank == 0) {
+    if (blank == VESA_NO_BLANKING) {
        if (mode_switch)
            vga_is_gfx = 0;
-       return 1;
+       return true;
     }
     sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK,
              font_data[c->vc_num]);
     if (mode_switch)
        vga_is_gfx = 1;
-    return 1;
+
+    return true;
 }
 
 static u8 sticon_build_attr(struct vc_data *conp, u8 color,
@@ -365,7 +351,6 @@ static const struct consw sti_con = {
        .con_init               = sticon_init,
        .con_deinit             = sticon_deinit,
        .con_clear              = sticon_clear,
-       .con_putc               = sticon_putc,
        .con_putcs              = sticon_putcs,
        .con_cursor             = sticon_cursor,
        .con_scroll             = sticon_scroll,
index 8ef1579fa57fdda1b079a17247286d0c809018d9..7597f04b0dc77e7e67516cb69be98a399da8e7c5 100644 (file)
@@ -65,7 +65,7 @@ static struct vgastate vgastate;
  *  Interface used by the world
  */
 
-static int vgacon_set_origin(struct vc_data *c);
+static bool vgacon_set_origin(struct vc_data *c);
 
 static struct uni_pagedict *vgacon_uni_pagedir;
 static int vgacon_refcount;
@@ -81,7 +81,7 @@ static unsigned int   vga_video_num_lines;                    /* Number of text lines */
 static bool            vga_can_do_color;                       /* Do we support colors? */
 static unsigned int    vga_default_font_height __read_mostly;  /* Height of default screen font */
 static unsigned char   vga_video_type          __read_mostly;  /* Card type */
-static int             vga_vesa_blanked;
+static enum vesa_blank_mode vga_vesa_blanked;
 static bool            vga_palette_blanked;
 static bool            vga_is_gfx;
 static bool            vga_512_chars;
@@ -138,8 +138,40 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 static void vgacon_scrolldelta(struct vc_data *c, int lines)
 {
-       vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
-                       vga_vram_size);
+       unsigned long scr_end = c->vc_scr_end - vga_vram_base;
+       unsigned long vorigin = c->vc_visible_origin - vga_vram_base;
+       unsigned long origin = c->vc_origin - vga_vram_base;
+       int margin = c->vc_size_row * 4;
+       int from, wrap, from_off, avail;
+
+       /* Turn scrollback off */
+       if (!lines) {
+               c->vc_visible_origin = c->vc_origin;
+               return;
+       }
+
+       /* Do we have already enough to allow jumping from 0 to the end? */
+       if (vga_rolled_over > scr_end + margin) {
+               from = scr_end;
+               wrap = vga_rolled_over + c->vc_size_row;
+       } else {
+               from = 0;
+               wrap = vga_vram_size;
+       }
+
+       from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row;
+       avail = (origin - from + wrap) % wrap;
+
+       /* Only a little piece would be left? Show all incl. the piece! */
+       if (avail < 2 * margin)
+               margin = 0;
+       if (from_off < margin)
+               from_off = 0;
+       if (from_off > avail - margin)
+               from_off = avail;
+
+       c->vc_visible_origin = vga_vram_base + (from + from_off) % wrap;
+
        vga_set_mem_top(c);
 }
 
@@ -335,7 +367,7 @@ static const char *vgacon_startup(void)
        return display_desc;
 }
 
-static void vgacon_init(struct vc_data *c, int init)
+static void vgacon_init(struct vc_data *c, bool init)
 {
        struct uni_pagedict *p;
 
@@ -352,7 +384,7 @@ static void vgacon_init(struct vc_data *c, int init)
        c->vc_scan_lines = vga_scan_lines;
        c->vc_font.height = c->vc_cell_height = vga_video_font_height;
 
-       /* set dimensions manually if init != 0 since vc_resize() will fail */
+       /* set dimensions manually if init is true since vc_resize() will fail */
        if (init) {
                c->vc_cols = vga_video_num_columns;
                c->vc_rows = vga_video_num_lines;
@@ -471,7 +503,7 @@ static void vgacon_set_cursor_size(int from, int to)
        raw_spin_unlock_irqrestore(&vga_lock, flags);
 }
 
-static void vgacon_cursor(struct vc_data *c, int mode)
+static void vgacon_cursor(struct vc_data *c, bool enable)
 {
        unsigned int c_height;
 
@@ -482,47 +514,41 @@ static void vgacon_cursor(struct vc_data *c, int mode)
 
        c_height = c->vc_cell_height;
 
-       switch (mode) {
-       case CM_ERASE:
-               write_vga(14, (c->vc_pos - vga_vram_base) / 2);
+       write_vga(14, (c->vc_pos - vga_vram_base) / 2);
+
+       if (!enable) {
                if (vga_video_type >= VIDEO_TYPE_VGAC)
                        vgacon_set_cursor_size(31, 30);
                else
                        vgacon_set_cursor_size(31, 31);
-               break;
+               return;
+       }
 
-       case CM_MOVE:
-       case CM_DRAW:
-               write_vga(14, (c->vc_pos - vga_vram_base) / 2);
-               switch (CUR_SIZE(c->vc_cursor_type)) {
-               case CUR_UNDERLINE:
-                       vgacon_set_cursor_size(c_height -
-                                              (c_height < 10 ? 2 : 3),
-                                              c_height -
-                                              (c_height < 10 ? 1 : 2));
-                       break;
-               case CUR_TWO_THIRDS:
-                       vgacon_set_cursor_size(c_height / 3, c_height -
-                                              (c_height < 10 ? 1 : 2));
-                       break;
-               case CUR_LOWER_THIRD:
-                       vgacon_set_cursor_size(c_height * 2 / 3, c_height -
-                                              (c_height < 10 ? 1 : 2));
-                       break;
-               case CUR_LOWER_HALF:
-                       vgacon_set_cursor_size(c_height / 2, c_height -
-                                              (c_height < 10 ? 1 : 2));
-                       break;
-               case CUR_NONE:
-                       if (vga_video_type >= VIDEO_TYPE_VGAC)
-                               vgacon_set_cursor_size(31, 30);
-                       else
-                               vgacon_set_cursor_size(31, 31);
-                       break;
-               default:
-                       vgacon_set_cursor_size(1, c_height);
-                       break;
-               }
+       switch (CUR_SIZE(c->vc_cursor_type)) {
+       case CUR_UNDERLINE:
+               vgacon_set_cursor_size(c_height - (c_height < 10 ? 2 : 3),
+                                      c_height - (c_height < 10 ? 1 : 2));
+               break;
+       case CUR_TWO_THIRDS:
+               vgacon_set_cursor_size(c_height / 3,
+                                      c_height - (c_height < 10 ? 1 : 2));
+               break;
+       case CUR_LOWER_THIRD:
+               vgacon_set_cursor_size(c_height * 2 / 3,
+                                      c_height - (c_height < 10 ? 1 : 2));
+               break;
+       case CUR_LOWER_HALF:
+               vgacon_set_cursor_size(c_height / 2,
+                                      c_height - (c_height < 10 ? 1 : 2));
+               break;
+       case CUR_NONE:
+               if (vga_video_type >= VIDEO_TYPE_VGAC)
+                       vgacon_set_cursor_size(31, 30);
+               else
+                       vgacon_set_cursor_size(31, 31);
+               break;
+       default:
+               vgacon_set_cursor_size(1, c_height);
                break;
        }
 }
@@ -588,7 +614,7 @@ static void vgacon_doresize(struct vc_data *c,
        raw_spin_unlock_irqrestore(&vga_lock, flags);
 }
 
-static int vgacon_switch(struct vc_data *c)
+static bool vgacon_switch(struct vc_data *c)
 {
        int x = c->vc_cols * VGA_FONTWIDTH;
        int y = c->vc_rows * c->vc_cell_height;
@@ -617,7 +643,7 @@ static int vgacon_switch(struct vc_data *c)
                        vgacon_doresize(c, c->vc_cols, c->vc_rows);
        }
 
-       return 0;               /* Redrawing not needed */
+       return false;           /* Redrawing not needed */
 }
 
 static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
@@ -657,7 +683,7 @@ static struct {
        unsigned char ClockingMode;     /* Seq-Controller:01h */
 } vga_state;
 
-static void vga_vesa_blank(struct vgastate *state, int mode)
+static void vga_vesa_blank(struct vgastate *state, enum vesa_blank_mode mode)
 {
        /* save original values of VGA controller registers */
        if (!vga_vesa_blanked) {
@@ -771,13 +797,14 @@ static void vga_pal_blank(struct vgastate *state)
        }
 }
 
-static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
+static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
+                        bool mode_switch)
 {
        switch (blank) {
-       case 0:         /* Unblank */
+       case VESA_NO_BLANKING:          /* Unblank */
                if (vga_vesa_blanked) {
                        vga_vesa_unblank(&vgastate);
-                       vga_vesa_blanked = 0;
+                       vga_vesa_blanked = VESA_NO_BLANKING;
                }
                if (vga_palette_blanked) {
                        vga_set_palette(c, color_table);
@@ -787,8 +814,7 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
                vga_is_gfx = false;
                /* Tell console.c that it has to restore the screen itself */
                return 1;
-       case 1:         /* Normal blanking */
-       case -1:        /* Obsolete */
+       case VESA_VSYNC_SUSPEND:        /* Normal blanking */
                if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
                        vga_pal_blank(&vgastate);
                        vga_palette_blanked = true;
@@ -1004,7 +1030,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
                                /* void size to cause regs to be rewritten */
                                cursor_size_lastfrom = 0;
                                cursor_size_lastto = 0;
-                               c->vc_sw->con_cursor(c, CM_DRAW);
+                               c->vc_sw->con_cursor(c, true);
                        }
                        c->vc_font.height = c->vc_cell_height = fontheight;
                        vc_resize(c, 0, rows);  /* Adjust console size */
@@ -1013,7 +1039,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
        return 0;
 }
 
-static int vgacon_font_set(struct vc_data *c, struct console_font *font,
+static int vgacon_font_set(struct vc_data *c, const struct console_font *font,
                           unsigned int vpitch, unsigned int flags)
 {
        unsigned charcount = font->charcount;
@@ -1049,12 +1075,12 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font, unsigne
 }
 
 static int vgacon_resize(struct vc_data *c, unsigned int width,
-                        unsigned int height, unsigned int user)
+                        unsigned int height, bool from_user)
 {
        if ((width << 1) * height > vga_vram_size)
                return -EINVAL;
 
-       if (user) {
+       if (from_user) {
                /*
                 * Ho ho!  Someone (svgatextmode, eh?) may have reprogrammed
                 * the video mode!  Set the new defaults then and go away.
@@ -1074,15 +1100,15 @@ static int vgacon_resize(struct vc_data *c, unsigned int width,
        return 0;
 }
 
-static int vgacon_set_origin(struct vc_data *c)
+static bool vgacon_set_origin(struct vc_data *c)
 {
        if (vga_is_gfx ||       /* We don't play origin tricks in graphic modes */
            (console_blanked && !vga_palette_blanked))  /* Nor we write to blanked screens */
-               return 0;
+               return false;
        c->vc_origin = c->vc_visible_origin = vga_vram_base;
        vga_set_mem_top(c);
        vga_rolled_over = 0;
-       return 1;
+       return true;
 }
 
 static void vgacon_save_screen(struct vc_data *c)
@@ -1159,11 +1185,10 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
  *  The console `switch' structure for the VGA based console
  */
 
-static void vgacon_clear(struct vc_data *vc, int sy, int sx, int height,
-                        int width) { }
-static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
-static void vgacon_putcs(struct vc_data *vc, const unsigned short *s,
-                        int count, int ypos, int xpos) { }
+static void vgacon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+                        unsigned int width) { }
+static void vgacon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
+                        unsigned int ypos, unsigned int xpos) { }
 
 const struct consw vga_con = {
        .owner = THIS_MODULE,
@@ -1171,7 +1196,6 @@ const struct consw vga_con = {
        .con_init = vgacon_init,
        .con_deinit = vgacon_deinit,
        .con_clear = vgacon_clear,
-       .con_putc = vgacon_putc,
        .con_putcs = vgacon_putcs,
        .con_cursor = vgacon_cursor,
        .con_scroll = vgacon_scroll,
index 8587c9da067003f74f50d3234a759bf3f218bf12..3ff1b2a8659e87c746c39a9fd47815eb82ffdb41 100644 (file)
@@ -233,7 +233,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
        }
 }
 
-static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
                       int fg, int bg)
 {
        struct fb_cursor cursor;
@@ -348,16 +348,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
                        mask[i++] = msk;
        }
 
-       switch (mode) {
-       case CM_ERASE:
-               ops->cursor_state.enable = 0;
-               break;
-       case CM_DRAW:
-       case CM_MOVE:
-       default:
-               ops->cursor_state.enable = (use_sw) ? 0 : 1;
-               break;
-       }
+       ops->cursor_state.enable = enable && !use_sw;
 
        cursor.image.data = src;
        cursor.image.fg_color = ops->cursor_state.image.fg_color;
index 46823c2e2ba1207e327607fa0ca0c757bc0968aa..98d0e2dbcd2f362ff8ea0f3e098f4ec54345ad8d 100644 (file)
@@ -351,7 +351,7 @@ static void fb_flashcursor(struct work_struct *work)
        struct fb_info *info;
        struct vc_data *vc = NULL;
        int c;
-       int mode;
+       bool enable;
        int ret;
 
        /* FIXME: we should sort out the unbind locking instead */
@@ -375,9 +375,8 @@ static void fb_flashcursor(struct work_struct *work)
        }
 
        c = scr_readw((u16 *) vc->vc_pos);
-       mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
-               CM_ERASE : CM_DRAW;
-       ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
+       enable = ops->cursor_flash && !ops->cursor_state.enable;
+       ops->cursor(vc, info, enable, get_color(vc, info, c, 1),
                    get_color(vc, info, c, 0));
        console_unlock();
 
@@ -920,7 +919,7 @@ static void display_to_var(struct fb_var_screeninfo *var,
 
 static const char *fbcon_startup(void)
 {
-       const char *display_desc = "frame buffer device";
+       static const char display_desc[] = "frame buffer device";
        struct fbcon_display *p = &fb_display[fg_console];
        struct vc_data *vc = vc_cons[fg_console].d;
        const struct font_desc *font = NULL;
@@ -987,7 +986,7 @@ static const char *fbcon_startup(void)
        return display_desc;
 }
 
-static void fbcon_init(struct vc_data *vc, int init)
+static void fbcon_init(struct vc_data *vc, bool init)
 {
        struct fb_info *info;
        struct fbcon_ops *ops;
@@ -1234,8 +1233,8 @@ finished:
  *  restriction is simplicity & efficiency at the moment.
  */
 
-static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
-                       int width)
+static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+                         unsigned int height, unsigned int width)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_ops *ops = info->fbcon_par;
@@ -1272,8 +1271,14 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
                ops->clear(vc, info, real_y(p, sy), sx, height, width);
 }
 
-static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
-                       int count, int ypos, int xpos)
+static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+                       unsigned int width)
+{
+       __fbcon_clear(vc, sy, sx, 1, width);
+}
+
+static void fbcon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
+                       unsigned int ypos, unsigned int xpos)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_display *p = &fb_display[vc->vc_num];
@@ -1285,14 +1290,6 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
                           get_color(vc, info, scr_readw(s), 0));
 }
 
-static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
-{
-       unsigned short chr;
-
-       scr_writew(c, &chr);
-       fbcon_putcs(vc, &chr, 1, ypos, xpos);
-}
-
 static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
@@ -1302,7 +1299,7 @@ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
                ops->clear_margins(vc, info, margin_color, bottom_only);
 }
 
-static void fbcon_cursor(struct vc_data *vc, int mode)
+static void fbcon_cursor(struct vc_data *vc, bool enable)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_ops *ops = info->fbcon_par;
@@ -1318,12 +1315,12 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
        else
                fbcon_add_cursor_work(info);
 
-       ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
+       ops->cursor_flash = enable;
 
        if (!ops->cursor)
                return;
 
-       ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
+       ops->cursor(vc, info, enable, get_color(vc, info, c, 1),
                    get_color(vc, info, c, 0));
 }
 
@@ -1743,7 +1740,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
        if (fbcon_is_inactive(vc, info))
                return true;
 
-       fbcon_cursor(vc, CM_ERASE);
+       fbcon_cursor(vc, false);
 
        /*
         * ++Geert: Only use ywrap/ypan if the console is in text mode
@@ -1759,7 +1756,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                case SCROLL_MOVE:
                        fbcon_redraw_blit(vc, info, p, t, b - t - count,
                                     count);
-                       fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        (b - count)),
@@ -1782,7 +1779,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                                            b - t - count, vc->vc_cols);
                        else
                                goto redraw_up;
-                       fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
                        break;
 
                case SCROLL_PAN_REDRAW:
@@ -1800,7 +1797,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                                                          vc->vc_rows - b, b);
                        } else
                                fbcon_redraw_move(vc, p, t + count, b - t - count, t);
-                       fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
                        break;
 
                case SCROLL_PAN_MOVE:
@@ -1823,14 +1820,14 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                                            b - t - count, vc->vc_cols);
                        else
                                goto redraw_up;
-                       fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
                        break;
 
                case SCROLL_REDRAW:
                      redraw_up:
                        fbcon_redraw(vc, t, b - t - count,
                                     count * vc->vc_cols);
-                       fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        (b - count)),
@@ -1847,7 +1844,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                case SCROLL_MOVE:
                        fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
                                     -count);
-                       fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, t, 0, count, vc->vc_cols);
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        t),
@@ -1870,7 +1867,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                                            b - t - count, vc->vc_cols);
                        else
                                goto redraw_down;
-                       fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, t, 0, count, vc->vc_cols);
                        break;
 
                case SCROLL_PAN_MOVE:
@@ -1892,7 +1889,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                                            b - t - count, vc->vc_cols);
                        else
                                goto redraw_down;
-                       fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, t, 0, count, vc->vc_cols);
                        break;
 
                case SCROLL_PAN_REDRAW:
@@ -1909,14 +1906,14 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                                        fbcon_redraw_move(vc, p, count, t, 0);
                        } else
                                fbcon_redraw_move(vc, p, t, b - t - count, t + count);
-                       fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, t, 0, count, vc->vc_cols);
                        break;
 
                case SCROLL_REDRAW:
                      redraw_down:
                        fbcon_redraw(vc, b - 1, b - t - count,
                                     -count * vc->vc_cols);
-                       fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       __fbcon_clear(vc, t, 0, count, vc->vc_cols);
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        t),
@@ -1995,7 +1992,7 @@ static void updatescrollmode(struct fbcon_display *p,
 #define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */
 
 static int fbcon_resize(struct vc_data *vc, unsigned int width,
-                       unsigned int height, unsigned int user)
+                       unsigned int height, bool from_user)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_ops *ops = info->fbcon_par;
@@ -2058,7 +2055,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
        return 0;
 }
 
-static int fbcon_switch(struct vc_data *vc)
+static bool fbcon_switch(struct vc_data *vc)
 {
        struct fb_info *info, *old_info = NULL;
        struct fbcon_ops *ops;
@@ -2180,9 +2177,9 @@ static int fbcon_switch(struct vc_data *vc)
                              vc->vc_origin + vc->vc_size_row * vc->vc_top,
                              vc->vc_size_row * (vc->vc_bottom -
                                                 vc->vc_top) / 2);
-               return 0;
+               return false;
        }
-       return 1;
+       return true;
 }
 
 static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
@@ -2195,12 +2192,13 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
 
                oldc = vc->vc_video_erase_char;
                vc->vc_video_erase_char &= charmask;
-               fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
+               __fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
                vc->vc_video_erase_char = oldc;
        }
 }
 
-static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
+static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
+                       bool mode_switch)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_ops *ops = info->fbcon_par;
@@ -2222,7 +2220,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
        if (!fbcon_is_inactive(vc, info)) {
                if (ops->blank_state != blank) {
                        ops->blank_state = blank;
-                       fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
+                       fbcon_cursor(vc, !blank);
                        ops->cursor_flash = (!blank);
 
                        if (fb_blank(info, blank))
@@ -2239,10 +2237,10 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
        else
                fbcon_add_cursor_work(info);
 
-       return 0;
+       return false;
 }
 
-static int fbcon_debug_enter(struct vc_data *vc)
+static void fbcon_debug_enter(struct vc_data *vc)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_ops *ops = info->fbcon_par;
@@ -2252,10 +2250,9 @@ static int fbcon_debug_enter(struct vc_data *vc)
        if (info->fbops->fb_debug_enter)
                info->fbops->fb_debug_enter(info);
        fbcon_set_palette(vc, color_table);
-       return 0;
 }
 
-static int fbcon_debug_leave(struct vc_data *vc)
+static void fbcon_debug_leave(struct vc_data *vc)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_ops *ops = info->fbcon_par;
@@ -2263,7 +2260,6 @@ static int fbcon_debug_leave(struct vc_data *vc)
        ops->graphics = ops->save_graphics;
        if (info->fbops->fb_debug_leave)
                info->fbops->fb_debug_leave(info);
-       return 0;
 }
 
 static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch)
@@ -2461,7 +2457,7 @@ err_out:
  *  but lets not assume that, since charcount of 512 is small for unicode support.
  */
 
-static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
+static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
                          unsigned int vpitch, unsigned int flags)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
@@ -2534,7 +2530,8 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
        return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1);
 }
 
-static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
+static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font,
+                             const char *name)
 {
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        const struct font_desc *f;
@@ -2593,35 +2590,6 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
        fb_set_cmap(&palette_cmap, info);
 }
 
-static u16 *fbcon_screen_pos(const struct vc_data *vc, int offset)
-{
-       return (u16 *) (vc->vc_origin + offset);
-}
-
-static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
-                                int *px, int *py)
-{
-       unsigned long ret;
-       int x, y;
-
-       if (pos >= vc->vc_origin && pos < vc->vc_scr_end) {
-               unsigned long offset = (pos - vc->vc_origin) / 2;
-
-               x = offset % vc->vc_cols;
-               y = offset / vc->vc_cols;
-               ret = pos + (vc->vc_cols - x) * 2;
-       } else {
-               /* Should not happen */
-               x = y = 0;
-               ret = vc->vc_origin;
-       }
-       if (px)
-               *px = x;
-       if (py)
-               *py = y;
-       return ret;
-}
-
 /* As we might be inside of softback, we may work with non-contiguous buffer,
    that's why we have to use a separate routine. */
 static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
@@ -2650,7 +2618,7 @@ void fbcon_suspended(struct fb_info *info)
        vc = vc_cons[ops->currcon].d;
 
        /* Clear cursor, restore saved data */
-       fbcon_cursor(vc, CM_ERASE);
+       fbcon_cursor(vc, false);
 }
 
 void fbcon_resumed(struct fb_info *info)
@@ -3152,7 +3120,6 @@ static const struct consw fb_con = {
        .con_init               = fbcon_init,
        .con_deinit             = fbcon_deinit,
        .con_clear              = fbcon_clear,
-       .con_putc               = fbcon_putc,
        .con_putcs              = fbcon_putcs,
        .con_cursor             = fbcon_cursor,
        .con_scroll             = fbcon_scroll,
@@ -3163,8 +3130,6 @@ static const struct consw fb_con = {
        .con_font_default       = fbcon_set_def_font,
        .con_set_palette        = fbcon_set_palette,
        .con_invert_region      = fbcon_invert_region,
-       .con_screen_pos         = fbcon_screen_pos,
-       .con_getxy              = fbcon_getxy,
        .con_resize             = fbcon_resize,
        .con_debug_enter        = fbcon_debug_enter,
        .con_debug_leave        = fbcon_debug_leave,
index 0eaf54a211516786ca2863c865654fb248a045e5..df70ea5ec5b379a95105fc35a067181531cfc217 100644 (file)
@@ -61,8 +61,8 @@ struct fbcon_ops {
                      int fg, int bg);
        void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
                              int color, int bottom_only);
-       void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
-                      int fg, int bg);
+       void (*cursor)(struct vc_data *vc, struct fb_info *info,
+                      bool enable, int fg, int bg);
        int  (*update_start)(struct fb_info *info);
        int  (*rotate_font)(struct fb_info *info, struct vc_data *vc);
        struct fb_var_screeninfo var;  /* copy of the current fb_var_screeninfo */
index 2789ace7963427fe80b82c19eb706daa21e316d9..f9b794ff7d396854ccc2dadbb0f41f1b2606dd23 100644 (file)
@@ -218,7 +218,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
        }
 }
 
-static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
                       int fg, int bg)
 {
        struct fb_cursor cursor;
@@ -349,16 +349,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
                kfree(tmp);
        }
 
-       switch (mode) {
-       case CM_ERASE:
-               ops->cursor_state.enable = 0;
-               break;
-       case CM_DRAW:
-       case CM_MOVE:
-       default:
-               ops->cursor_state.enable = (use_sw) ? 0 : 1;
-               break;
-       }
+       ops->cursor_state.enable = enable && !use_sw;
 
        cursor.image.data = src;
        cursor.image.fg_color = ops->cursor_state.image.fg_color;
index 86a254c1b2b7b6bd039fde6cbc588f009b7ed338..903f6fc174e14623eacc2ef2a23bb54d072e2f8e 100644 (file)
@@ -201,7 +201,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
        }
 }
 
-static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
                      int fg, int bg)
 {
        struct fb_cursor cursor;
@@ -332,16 +332,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
                kfree(tmp);
        }
 
-       switch (mode) {
-       case CM_ERASE:
-               ops->cursor_state.enable = 0;
-               break;
-       case CM_DRAW:
-       case CM_MOVE:
-       default:
-               ops->cursor_state.enable = (use_sw) ? 0 : 1;
-               break;
-       }
+       ops->cursor_state.enable = enable && !use_sw;
 
        cursor.image.data = src;
        cursor.image.fg_color = ops->cursor_state.image.fg_color;
index 23bc045769d088e8f9690c03dc8228d71635daa0..594331936fd3cffbd3e75c4ff93dbab8be68cae8 100644 (file)
@@ -248,7 +248,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
        }
 }
 
-static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
                      int fg, int bg)
 {
        struct fb_cursor cursor;
@@ -372,16 +372,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
                        mask[i++] = ~msk;
        }
 
-       switch (mode) {
-       case CM_ERASE:
-               ops->cursor_state.enable = 0;
-               break;
-       case CM_DRAW:
-       case CM_MOVE:
-       default:
-               ops->cursor_state.enable = (use_sw) ? 0 : 1;
-               break;
-       }
+       ops->cursor_state.enable = enable && !use_sw;
 
        cursor.image.data = src;
        cursor.image.fg_color = ops->cursor_state.image.fg_color;
index 2768eff247ba4623dd0beaa8e2d96926c472f519..eff7ec4da1671f0a13c919ec9aad225c071ae0ff 100644 (file)
@@ -79,7 +79,7 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
        return;
 }
 
-static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
                        int fg, int bg)
 {
        struct fb_tilecursor cursor;
@@ -87,7 +87,7 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
 
        cursor.sx = vc->state.x;
        cursor.sy = vc->state.y;
-       cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1;
+       cursor.mode = enable && !use_sw;
        cursor.fg = fg;
        cursor.bg = bg;
 
index ca43774f3156e3d901ca6a8c4d7223581a1e91c3..dccfc38cfbd5232109ab55b2efa9c337f3d250b8 100644 (file)
@@ -380,7 +380,7 @@ tgafb_set_par(struct fb_info *info)
                BT463_LOAD_ADDR(par, 0x0000);
                TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
 
-#ifdef CONFIG_HW_CONSOLE
+#ifdef CONFIG_VT
                for (i = 0; i < 16; i++) {
                        int j = color_table[i];
 
index 513c0b114337c43a1e7b55c2038679b9fb91a387..e6049a75b35b8f099b779104ed9302147e001df8 100644 (file)
@@ -78,5 +78,15 @@ config W1_MASTER_SGI
          This support is also available as a module.  If so, the module
          will be called sgi_w1.
 
+config W1_MASTER_UART
+       tristate "UART 1-wire driver"
+       depends on SERIAL_DEV_BUS
+       help
+         Say Y here if you want to communicate with your 1-wire devices using
+         UART interface.
+
+         This support is also available as a module.  If so, the module
+         will be called w1-uart.
+
 endmenu
 
index 6c5a21f9b88ce211cf80ecad925e9cb8a7e0fa04..227f80987e6986056f47bb7ec096ed17445171ae 100644 (file)
@@ -12,3 +12,4 @@ obj-$(CONFIG_W1_MASTER_MXC)           += mxc_w1.o
 obj-$(CONFIG_W1_MASTER_GPIO)           += w1-gpio.o
 obj-$(CONFIG_HDQ_MASTER_OMAP)          += omap_hdq.o
 obj-$(CONFIG_W1_MASTER_SGI)            += sgi_w1.o
+obj-$(CONFIG_W1_MASTER_UART)           += w1-uart.o
index 090cbbf9e1e2259fc74c020bd2a220f4f3988277..ba1d0866d1c40c99205aae5a15539954e64806fb 100644 (file)
@@ -151,15 +151,13 @@ out_disable_clk:
 /*
  * disassociate the w1 device from the driver
  */
-static int mxc_w1_remove(struct platform_device *pdev)
+static void mxc_w1_remove(struct platform_device *pdev)
 {
        struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
 
        w1_remove_master_device(&mdev->bus_master);
 
        clk_disable_unprepare(mdev->clk);
-
-       return 0;
 }
 
 static const struct of_device_id mxc_w1_dt_ids[] = {
@@ -174,7 +172,7 @@ static struct platform_driver mxc_w1_driver = {
                .of_match_table = mxc_w1_dt_ids,
        },
        .probe = mxc_w1_probe,
-       .remove = mxc_w1_remove,
+       .remove_new = mxc_w1_remove,
 };
 module_platform_driver(mxc_w1_driver);
 
index 6a39b71eb7184e2a7f148cbe077904279273ba30..d1cb5190445a9035799c3879037ee0252bcfcd95 100644 (file)
@@ -647,7 +647,7 @@ err_w1:
        return ret;
 }
 
-static int omap_hdq_remove(struct platform_device *pdev)
+static void omap_hdq_remove(struct platform_device *pdev)
 {
        int active;
 
@@ -661,8 +661,6 @@ static int omap_hdq_remove(struct platform_device *pdev)
        if (active >= 0)
                pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
-
-       return 0;
 }
 
 static const struct of_device_id omap_hdq_dt_ids[] = {
@@ -674,7 +672,7 @@ MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids);
 
 static struct platform_driver omap_hdq_driver = {
        .probe = omap_hdq_probe,
-       .remove = omap_hdq_remove,
+       .remove_new = omap_hdq_remove,
        .driver = {
                .name = "omap_hdq",
                .of_match_table = omap_hdq_dt_ids,
index d7fbc3c146e1c2b98aa3146942416222b19355b3..7bb7876aa70e6f561e16d7f0f198a25f8eee5401 100644 (file)
@@ -105,13 +105,11 @@ static int sgi_w1_probe(struct platform_device *pdev)
 /*
  * disassociate the w1 device from the driver
  */
-static int sgi_w1_remove(struct platform_device *pdev)
+static void sgi_w1_remove(struct platform_device *pdev)
 {
        struct sgi_w1_device *sdev = platform_get_drvdata(pdev);
 
        w1_remove_master_device(&sdev->bus_master);
-
-       return 0;
 }
 
 static struct platform_driver sgi_w1_driver = {
@@ -119,7 +117,7 @@ static struct platform_driver sgi_w1_driver = {
                .name = "sgi_w1",
        },
        .probe = sgi_w1_probe,
-       .remove = sgi_w1_remove,
+       .remove_new = sgi_w1_remove,
 };
 module_platform_driver(sgi_w1_driver);
 
index 05c67038ed20c35e99ff9bbb6de4a771fdf0c74d..34128e6bbbfaf607726be95d4f5a442fdc7117a7 100644 (file)
@@ -141,7 +141,7 @@ static int w1_gpio_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int w1_gpio_remove(struct platform_device *pdev)
+static void w1_gpio_remove(struct platform_device *pdev)
 {
        struct w1_bus_master *master = platform_get_drvdata(pdev);
        struct w1_gpio_ddata *ddata = master->data;
@@ -150,8 +150,6 @@ static int w1_gpio_remove(struct platform_device *pdev)
                gpiod_set_value(ddata->pullup_gpiod, 0);
 
        w1_remove_master_device(master);
-
-       return 0;
 }
 
 static struct platform_driver w1_gpio_driver = {
@@ -160,7 +158,7 @@ static struct platform_driver w1_gpio_driver = {
                .of_match_table = of_match_ptr(w1_gpio_dt_ids),
        },
        .probe = w1_gpio_probe,
-       .remove = w1_gpio_remove,
+       .remove_new = w1_gpio_remove,
 };
 
 module_platform_driver(w1_gpio_driver);
diff --git a/drivers/w1/masters/w1-uart.c b/drivers/w1/masters/w1-uart.c
new file mode 100644 (file)
index 0000000..a31782e
--- /dev/null
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * w1-uart - UART 1-Wire bus driver
+ *
+ * Uses the UART interface (via Serial Device Bus) to create the 1-Wire
+ * timing patterns. Implements the following 1-Wire master interface:
+ *
+ * - reset_bus: requests baud-rate 9600
+ *
+ * - touch_bit: requests baud-rate 115200
+ *
+ * Author: Christoph Winklhofer <cj.winklhofer@gmail.com>
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/serdev.h>
+#include <linux/w1.h>
+
+/* UART packet contains start and stop bit */
+#define W1_UART_BITS_PER_PACKET (BITS_PER_BYTE + 2)
+
+/* Timeout to wait for completion of serdev-receive */
+#define W1_UART_TIMEOUT msecs_to_jiffies(500)
+
+/**
+ * struct w1_uart_config - configuration for 1-Wire operation
+ * @baudrate: baud-rate returned from serdev
+ * @delay_us: delay to complete a 1-Wire cycle (in us)
+ * @tx_byte: byte to generate 1-Wire timing pattern
+ */
+struct w1_uart_config {
+       unsigned int baudrate;
+       unsigned int delay_us;
+       u8 tx_byte;
+};
+
+/**
+ * struct w1_uart_device - 1-Wire UART device structure
+ * @serdev: serial device
+ * @bus: w1-bus master
+ * @cfg_reset: config for 1-Wire reset
+ * @cfg_touch_0: config for 1-Wire write-0 cycle
+ * @cfg_touch_1: config for 1-Wire write-1 and read cycle
+ * @rx_byte_received: completion for serdev receive
+ * @rx_mutex: mutex to protect rx_err and rx_byte
+ * @rx_err: indicates an error in serdev-receive
+ * @rx_byte: result byte from serdev-receive
+ */
+struct w1_uart_device {
+       struct serdev_device *serdev;
+       struct w1_bus_master bus;
+
+       struct w1_uart_config cfg_reset;
+       struct w1_uart_config cfg_touch_0;
+       struct w1_uart_config cfg_touch_1;
+
+       struct completion rx_byte_received;
+       /*
+        * protect rx_err and rx_byte from concurrent access in
+        * w1-callbacks and serdev-receive.
+        */
+       struct mutex rx_mutex;
+       int rx_err;
+       u8 rx_byte;
+};
+
+/**
+ * struct w1_uart_limits - limits for 1-Wire operations
+ * @baudrate: Requested baud-rate to create 1-Wire timing pattern
+ * @bit_min_us: minimum time for a bit (in us)
+ * @bit_max_us: maximum time for a bit (in us)
+ * @sample_us: timespan to sample 1-Wire response
+ * @cycle_us: duration of the 1-Wire cycle
+ */
+struct w1_uart_limits {
+       unsigned int baudrate;
+       unsigned int bit_min_us;
+       unsigned int bit_max_us;
+       unsigned int sample_us;
+       unsigned int cycle_us;
+};
+
+static inline unsigned int baud_to_bit_ns(unsigned int baud)
+{
+       return NSEC_PER_SEC / baud;
+}
+
+static inline unsigned int to_ns(unsigned int us)
+{
+       return us * NSEC_PER_USEC;
+}
+
+/*
+ * Set baud-rate, delay and tx-byte to create a 1-Wire pulse and adapt
+ * the tx-byte according to the actual baud-rate.
+ *
+ * Reject when:
+ * - time for a bit outside min/max range
+ * - a 1-Wire response is not detectable for sent byte
+ */
+static int w1_uart_set_config(struct serdev_device *serdev,
+                             const struct w1_uart_limits *limits,
+                             struct w1_uart_config *w1cfg)
+{
+       unsigned int packet_ns;
+       unsigned int bits_low;
+       unsigned int bit_ns;
+       unsigned int low_ns;
+
+       w1cfg->baudrate = serdev_device_set_baudrate(serdev, limits->baudrate);
+       if (w1cfg->baudrate == 0)
+               return -EINVAL;
+
+       /* Compute in nanoseconds for accuracy */
+       bit_ns = baud_to_bit_ns(w1cfg->baudrate);
+       bits_low = to_ns(limits->bit_min_us) / bit_ns;
+       /* start bit is always low */
+       low_ns = bit_ns * (bits_low + 1);
+
+       if (low_ns < to_ns(limits->bit_min_us))
+               return -EINVAL;
+
+       if (low_ns > to_ns(limits->bit_max_us))
+               return -EINVAL;
+
+       /* 1-Wire response detectable for sent byte */
+       if (limits->sample_us > 0 &&
+           bit_ns * BITS_PER_BYTE < low_ns + to_ns(limits->sample_us))
+               return -EINVAL;
+
+       /* delay: 1-Wire cycle takes longer than the UART packet */
+       packet_ns = bit_ns * W1_UART_BITS_PER_PACKET;
+       w1cfg->delay_us = 0;
+       if (to_ns(limits->cycle_us) > packet_ns)
+               w1cfg->delay_us =
+                       (to_ns(limits->cycle_us) - packet_ns) / NSEC_PER_USEC;
+
+       /* byte to create 1-Wire pulse */
+       w1cfg->tx_byte = 0xff << bits_low;
+
+       return 0;
+}
+
+/*
+ * Configuration for reset and presence detect
+ * - bit_min_us is 480us, add margin and use 485us
+ * - limits for sample time 60us-75us, use 65us
+ */
+static int w1_uart_set_config_reset(struct w1_uart_device *w1dev)
+{
+       struct serdev_device *serdev = w1dev->serdev;
+       struct device_node *np = serdev->dev.of_node;
+
+       struct w1_uart_limits limits = { .baudrate = 9600,
+                                        .bit_min_us = 485,
+                                        .bit_max_us = 640,
+                                        .sample_us = 65,
+                                        .cycle_us = 960 };
+
+       of_property_read_u32(np, "reset-bps", &limits.baudrate);
+
+       return w1_uart_set_config(serdev, &limits, &w1dev->cfg_reset);
+}
+
+/*
+ * Configuration for write-0 cycle (touch bit 0)
+ * - bit_min_us is 60us, add margin and use 65us
+ * - no sampling required, sample_us = 0
+ */
+static int w1_uart_set_config_touch_0(struct w1_uart_device *w1dev)
+{
+       struct serdev_device *serdev = w1dev->serdev;
+       struct device_node *np = serdev->dev.of_node;
+
+       struct w1_uart_limits limits = { .baudrate = 115200,
+                                        .bit_min_us = 65,
+                                        .bit_max_us = 120,
+                                        .sample_us = 0,
+                                        .cycle_us = 70 };
+
+       of_property_read_u32(np, "write-0-bps", &limits.baudrate);
+
+       return w1_uart_set_config(serdev, &limits, &w1dev->cfg_touch_0);
+}
+
+/*
+ * Configuration for write-1 and read cycle (touch bit 1)
+ * - bit_min_us is 5us, add margin and use 6us
+ * - limits for sample time 5us-15us, use 15us
+ */
+static int w1_uart_set_config_touch_1(struct w1_uart_device *w1dev)
+{
+       struct serdev_device *serdev = w1dev->serdev;
+       struct device_node *np = serdev->dev.of_node;
+
+       struct w1_uart_limits limits = { .baudrate = 115200,
+                                        .bit_min_us = 6,
+                                        .bit_max_us = 15,
+                                        .sample_us = 15,
+                                        .cycle_us = 70 };
+
+       of_property_read_u32(np, "write-1-bps", &limits.baudrate);
+
+       return w1_uart_set_config(serdev, &limits, &w1dev->cfg_touch_1);
+}
+
+/*
+ * Configure and open the serial device
+ */
+static int w1_uart_serdev_open(struct w1_uart_device *w1dev)
+{
+       struct serdev_device *serdev = w1dev->serdev;
+       struct device *dev = &serdev->dev;
+       int ret;
+
+       ret = devm_serdev_device_open(dev, serdev);
+       if (ret < 0)
+               return ret;
+
+       ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
+       if (ret < 0) {
+               dev_err(dev, "set parity failed\n");
+               return ret;
+       }
+
+       ret = w1_uart_set_config_reset(w1dev);
+       if (ret < 0) {
+               dev_err(dev, "config for reset failed\n");
+               return ret;
+       }
+
+       ret = w1_uart_set_config_touch_0(w1dev);
+       if (ret < 0) {
+               dev_err(dev, "config for touch-0 failed\n");
+               return ret;
+       }
+
+       ret = w1_uart_set_config_touch_1(w1dev);
+       if (ret < 0) {
+               dev_err(dev, "config for touch-1 failed\n");
+               return ret;
+       }
+
+       serdev_device_set_flow_control(serdev, false);
+
+       return 0;
+}
+
+/*
+ * Send one byte (tx_byte) and read one byte (rx_byte) via serdev.
+ */
+static int w1_uart_serdev_tx_rx(struct w1_uart_device *w1dev,
+                               const struct w1_uart_config *w1cfg, u8 *rx_byte)
+{
+       struct serdev_device *serdev = w1dev->serdev;
+       int ret;
+
+       serdev_device_write_flush(serdev);
+       serdev_device_set_baudrate(serdev, w1cfg->baudrate);
+
+       /* write and immediately read one byte */
+       reinit_completion(&w1dev->rx_byte_received);
+       ret = serdev_device_write_buf(serdev, &w1cfg->tx_byte, 1);
+       if (ret != 1)
+               return -EIO;
+       ret = wait_for_completion_interruptible_timeout(
+               &w1dev->rx_byte_received, W1_UART_TIMEOUT);
+       if (ret <= 0)
+               return -EIO;
+
+       /* locking could fail when serdev is unexpectedly receiving. */
+       if (!mutex_trylock(&w1dev->rx_mutex))
+               return -EIO;
+
+       ret = w1dev->rx_err;
+       if (ret == 0)
+               *rx_byte = w1dev->rx_byte;
+
+       mutex_unlock(&w1dev->rx_mutex);
+
+       if (w1cfg->delay_us > 0)
+               fsleep(w1cfg->delay_us);
+
+       return ret;
+}
+
+static size_t w1_uart_serdev_receive_buf(struct serdev_device *serdev,
+                                         const u8 *buf, size_t count)
+{
+       struct w1_uart_device *w1dev = serdev_device_get_drvdata(serdev);
+
+       mutex_lock(&w1dev->rx_mutex);
+
+       /* sent a single byte and receive one single byte */
+       if (count == 1) {
+               w1dev->rx_byte = buf[0];
+               w1dev->rx_err = 0;
+       } else {
+               w1dev->rx_err = -EIO;
+       }
+
+       mutex_unlock(&w1dev->rx_mutex);
+       complete(&w1dev->rx_byte_received);
+
+       return count;
+}
+
+static const struct serdev_device_ops w1_uart_serdev_ops = {
+       .receive_buf = w1_uart_serdev_receive_buf,
+       .write_wakeup = serdev_device_write_wakeup,
+};
+
+/*
+ * 1-wire reset and presence detect: A present slave will manipulate
+ * the received byte by pulling the 1-Wire low.
+ */
+static u8 w1_uart_reset_bus(void *data)
+{
+       struct w1_uart_device *w1dev = data;
+       const struct w1_uart_config *w1cfg = &w1dev->cfg_reset;
+       int ret;
+       u8 val;
+
+       ret = w1_uart_serdev_tx_rx(w1dev, w1cfg, &val);
+       if (ret < 0)
+               return -1;
+
+       /* Device present (0) or no device (1) */
+       return val != w1cfg->tx_byte ? 0 : 1;
+}
+
+/*
+ * 1-Wire read and write cycle: Only the read-0 manipulates the
+ * received byte, all others left the line untouched.
+ */
+static u8 w1_uart_touch_bit(void *data, u8 bit)
+{
+       struct w1_uart_device *w1dev = data;
+       const struct w1_uart_config *w1cfg = bit ? &w1dev->cfg_touch_1 :
+                                                  &w1dev->cfg_touch_0;
+       int ret;
+       u8 val;
+
+       ret = w1_uart_serdev_tx_rx(w1dev, w1cfg, &val);
+
+       /* return inactive bus state on error */
+       if (ret < 0)
+               return 1;
+
+       return val == w1cfg->tx_byte ? 1 : 0;
+}
+
+static int w1_uart_probe(struct serdev_device *serdev)
+{
+       struct device *dev = &serdev->dev;
+       struct w1_uart_device *w1dev;
+       int ret;
+
+       w1dev = devm_kzalloc(dev, sizeof(*w1dev), GFP_KERNEL);
+       if (!w1dev)
+               return -ENOMEM;
+       w1dev->bus.data = w1dev;
+       w1dev->bus.reset_bus = w1_uart_reset_bus;
+       w1dev->bus.touch_bit = w1_uart_touch_bit;
+       w1dev->serdev = serdev;
+
+       init_completion(&w1dev->rx_byte_received);
+       mutex_init(&w1dev->rx_mutex);
+
+       ret = w1_uart_serdev_open(w1dev);
+       if (ret < 0)
+               return ret;
+       serdev_device_set_drvdata(serdev, w1dev);
+       serdev_device_set_client_ops(serdev, &w1_uart_serdev_ops);
+
+       return w1_add_master_device(&w1dev->bus);
+}
+
+static void w1_uart_remove(struct serdev_device *serdev)
+{
+       struct w1_uart_device *w1dev = serdev_device_get_drvdata(serdev);
+
+       /*
+        * Waits until w1-uart callbacks are finished, serdev is closed
+        * and its device data released automatically by devres (waits
+        * until serdev-receive is finished).
+        */
+       w1_remove_master_device(&w1dev->bus);
+}
+
+static const struct of_device_id w1_uart_of_match[] = {
+       { .compatible = "w1-uart" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, w1_uart_of_match);
+
+static struct serdev_device_driver w1_uart_driver = {
+       .driver = {
+               .name           = "w1-uart",
+               .of_match_table = w1_uart_of_match,
+       },
+       .probe  = w1_uart_probe,
+       .remove = w1_uart_remove,
+};
+
+module_serdev_device_driver(w1_uart_driver);
+
+MODULE_DESCRIPTION("UART w1 bus driver");
+MODULE_AUTHOR("Christoph Winklhofer <cj.winklhofer@gmail.com>");
+MODULE_LICENSE("GPL");
index 5353cbd75126c120f4f202038be16c3e27fdef63..afb1cc4606c5230f4c8fb840875976bb4d110b8c 100644 (file)
@@ -167,7 +167,7 @@ static struct w1_family w1_default_family = {
 
 static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env);
 
-static struct bus_type w1_bus_type = {
+static const struct bus_type w1_bus_type = {
        .name = "w1",
        .uevent = w1_uevent,
 };
index 779d388af8a0a275ecd864baa4089a761ed5c6f6..31a8f5b85f5d7483c402e0cff64a6e4cef1a2893 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/bits.h>
 #include <linux/rculist.h>
 #include <linux/types.h>
+#include <linux/vesa.h>
 
 struct vc_data;
 struct console_font_op;
@@ -36,63 +37,91 @@ enum vc_intensity;
 /**
  * struct consw - callbacks for consoles
  *
+ * @owner:      the module to get references of when this console is used
+ * @con_startup: set up the console and return its name (like VGA, EGA, ...)
+ * @con_init:   initialize the console on @vc. @init is true for the very first
+ *             call on this @vc.
+ * @con_deinit: deinitialize the console from @vc.
+ * @con_clear:  erase @count characters at [@x, @y] on @vc. @count >= 1.
+ * @con_putc:   emit one character with attributes @ca to [@x, @y] on @vc.
+ *             (optional -- @con_putcs would be called instead)
+ * @con_putcs:  emit @count characters with attributes @s to [@x, @y] on @vc.
+ * @con_cursor: enable/disable cursor depending on @enable
  * @con_scroll: move lines from @top to @bottom in direction @dir by @lines.
  *             Return true if no generic handling should be done.
  *             Invoked by csi_M and printing to the console.
- * @con_set_palette: sets the palette of the console to @table (optional)
+ * @con_switch: notifier about the console switch; it is supposed to return
+ *             true if a redraw is needed.
+ * @con_blank:  blank/unblank the console. The target mode is passed in @blank.
+ *             @mode_switch is set if changing from/to text/graphics. The hook
+ *             is supposed to return true if a redraw is needed.
+ * @con_font_set: set console @vc font to @font with height @vpitch. @flags can
+ *             be %KD_FONT_FLAG_DONT_RECALC. (optional)
+ * @con_font_get: fetch the current font on @vc of height @vpitch into @font.
+ *             (optional)
+ * @con_font_default: set default font on @vc. @name can be %NULL or font name
+ *             to search for. @font can be filled back. (optional)
+ * @con_resize:        resize the @vc console to @width x @height. @from_user is true
+ *             when this change comes from the user space.
+ * @con_set_palette: sets the palette of the console @vc to @table (optional)
  * @con_scrolldelta: the contents of the console should be scrolled by @lines.
  *                  Invoked by user. (optional)
+ * @con_set_origin: set origin (see &vc_data::vc_origin) of the @vc. If not
+ *             provided or returns false, the origin is set to
+ *             @vc->vc_screenbuf. (optional)
+ * @con_save_screen: save screen content into @vc->vc_screenbuf. Called e.g.
+ *             upon entering graphics. (optional)
+ * @con_build_attr: build attributes based on @color, @intensity and other
+ *             parameters. The result is used for both normal and erase
+ *             characters. (optional)
+ * @con_invert_region: invert a region of length @count on @vc starting at @p.
+ *             (optional)
+ * @con_debug_enter: prepare the console for the debugger. This includes, but
+ *             is not limited to, unblanking the console, loading an
+ *             appropriate palette, and allowing debugger generated output.
+ *             (optional)
+ * @con_debug_leave: restore the console to its pre-debug state as closely as
+ *             possible. (optional)
  */
 struct consw {
        struct module *owner;
        const char *(*con_startup)(void);
-       void    (*con_init)(struct vc_data *vc, int init);
+       void    (*con_init)(struct vc_data *vc, bool init);
        void    (*con_deinit)(struct vc_data *vc);
-       void    (*con_clear)(struct vc_data *vc, int sy, int sx, int height,
-                       int width);
-       void    (*con_putc)(struct vc_data *vc, int c, int ypos, int xpos);
-       void    (*con_putcs)(struct vc_data *vc, const unsigned short *s,
-                       int count, int ypos, int xpos);
-       void    (*con_cursor)(struct vc_data *vc, int mode);
+       void    (*con_clear)(struct vc_data *vc, unsigned int y,
+                            unsigned int x, unsigned int count);
+       void    (*con_putc)(struct vc_data *vc, u16 ca, unsigned int y,
+                           unsigned int x);
+       void    (*con_putcs)(struct vc_data *vc, const u16 *s,
+                            unsigned int count, unsigned int ypos,
+                            unsigned int xpos);
+       void    (*con_cursor)(struct vc_data *vc, bool enable);
        bool    (*con_scroll)(struct vc_data *vc, unsigned int top,
                        unsigned int bottom, enum con_scroll dir,
                        unsigned int lines);
-       int     (*con_switch)(struct vc_data *vc);
-       int     (*con_blank)(struct vc_data *vc, int blank, int mode_switch);
-       int     (*con_font_set)(struct vc_data *vc, struct console_font *font,
-                       unsigned int vpitch, unsigned int flags);
+       bool    (*con_switch)(struct vc_data *vc);
+       bool    (*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank,
+                            bool mode_switch);
+       int     (*con_font_set)(struct vc_data *vc,
+                               const struct console_font *font,
+                               unsigned int vpitch, unsigned int flags);
        int     (*con_font_get)(struct vc_data *vc, struct console_font *font,
                        unsigned int vpitch);
        int     (*con_font_default)(struct vc_data *vc,
-                       struct console_font *font, char *name);
+                       struct console_font *font, const char *name);
        int     (*con_resize)(struct vc_data *vc, unsigned int width,
-                       unsigned int height, unsigned int user);
+                             unsigned int height, bool from_user);
        void    (*con_set_palette)(struct vc_data *vc,
                        const unsigned char *table);
        void    (*con_scrolldelta)(struct vc_data *vc, int lines);
-       int     (*con_set_origin)(struct vc_data *vc);
+       bool    (*con_set_origin)(struct vc_data *vc);
        void    (*con_save_screen)(struct vc_data *vc);
        u8      (*con_build_attr)(struct vc_data *vc, u8 color,
                        enum vc_intensity intensity,
                        bool blink, bool underline, bool reverse, bool italic);
        void    (*con_invert_region)(struct vc_data *vc, u16 *p, int count);
-       u16    *(*con_screen_pos)(const struct vc_data *vc, int offset);
-       unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position,
-                       int *px, int *py);
-       /*
-        * Flush the video console driver's scrollback buffer
-        */
-       void    (*con_flush_scrollback)(struct vc_data *vc);
-       /*
-        * Prepare the console for the debugger.  This includes, but is not
-        * limited to, unblanking the console, loading an appropriate
-        * palette, and allowing debugger generated output.
-        */
-       int     (*con_debug_enter)(struct vc_data *vc);
-       /*
-        * Restore the console to its pre-debug state as closely as possible.
-        */
-       int     (*con_debug_leave)(struct vc_data *vc);
+       void    (*con_debug_enter)(struct vc_data *vc);
+       void    (*con_debug_leave)(struct vc_data *vc);
 };
 
 extern const struct consw *conswitchp;
@@ -112,32 +141,21 @@ int con_is_bound(const struct consw *csw);
 int do_unregister_con_driver(const struct consw *csw);
 int do_take_over_console(const struct consw *sw, int first, int last, int deflt);
 void give_up_console(const struct consw *sw);
-#ifdef CONFIG_HW_CONSOLE
-int con_debug_enter(struct vc_data *vc);
-int con_debug_leave(void);
+#ifdef CONFIG_VT
+void con_debug_enter(struct vc_data *vc);
+void con_debug_leave(void);
 #else
-static inline int con_debug_enter(struct vc_data *vc)
-{
-       return 0;
-}
-static inline int con_debug_leave(void)
-{
-       return 0;
-}
+static inline void con_debug_enter(struct vc_data *vc) { }
+static inline void con_debug_leave(void) { }
 #endif
 
-/* cursor */
-#define CM_DRAW     (1)
-#define CM_ERASE    (2)
-#define CM_MOVE     (3)
-
 /*
  * The interface for a console, or any other device that wants to capture
  * console messages (printer driver?)
  */
 
 /**
- * cons_flags - General console flags
+ * enum cons_flags - General console flags
  * @CON_PRINTBUFFER:   Used by newly registered consoles to avoid duplicate
  *                     output of messages that were already shown by boot
  *                     consoles or read by userspace via syslog() syscall.
@@ -218,7 +236,7 @@ struct nbcon_state {
 static_assert(sizeof(struct nbcon_state) <= sizeof(int));
 
 /**
- * nbcon_prio - console owner priority for nbcon consoles
+ * enum nbcon_prio - console owner priority for nbcon consoles
  * @NBCON_PRIO_NONE:           Unused
  * @NBCON_PRIO_NORMAL:         Normal (non-emergency) usage
  * @NBCON_PRIO_EMERGENCY:      Emergency output (WARN/OOPS...)
@@ -450,7 +468,7 @@ static inline bool console_is_registered(const struct console *con)
  * for_each_console() - Iterator over registered consoles
  * @con:       struct console pointer used as loop cursor
  *
- * The console list and the console->flags are immutable while iterating.
+ * The console list and the &console.flags are immutable while iterating.
  *
  * Requires console_list_lock to be held.
  */
@@ -520,12 +538,6 @@ void vcs_remove_sysfs(int index);
  */
 extern atomic_t ignore_console_lock_warning;
 
-/* VESA Blanking Levels */
-#define VESA_NO_BLANKING        0
-#define VESA_VSYNC_SUSPEND      1
-#define VESA_HSYNC_SUSPEND      2
-#define VESA_POWERDOWN          3
-
 extern void console_init(void);
 
 /* For deferred console takeover */
index 539f1cd45309472c2be973ce155b8746ef998ed3..20f564e9855234308afc6768d67635435d6c5bed 100644 (file)
@@ -151,7 +151,6 @@ struct vc_data {
        DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */
        unsigned char   vc_palette[16*3];       /* Colour palette for VGA+ */
        unsigned short * vc_translate;
-       unsigned int    vc_resize_user;         /* resize request from user */
        unsigned int    vc_bell_pitch;          /* Console bell pitch */
        unsigned int    vc_bell_duration;       /* Console bell duration */
        unsigned short  vc_cur_blink_ms;        /* Cursor blink duration */
index 170ef28ff26b99e742e5b8209dc4d025ddcbb947..bab7d30d34462ac7305720380f46a7391756fc1d 100644 (file)
 struct tty_struct;
 struct vc_data;
 
-extern void clear_selection(void);
-extern int set_selection_user(const struct tiocl_selection __user *sel,
-                             struct tty_struct *tty);
-extern int set_selection_kernel(struct tiocl_selection *v,
-                               struct tty_struct *tty);
-extern int paste_selection(struct tty_struct *tty);
-extern int sel_loadlut(char __user *p);
-extern int mouse_reporting(void);
-extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry);
-
-bool vc_is_sel(struct vc_data *vc);
+void clear_selection(void);
+int set_selection_user(const struct tiocl_selection __user *sel,
+                      struct tty_struct *tty);
+int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty);
+int paste_selection(struct tty_struct *tty);
+int sel_loadlut(u32 __user *lut);
+int mouse_reporting(void);
+void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry);
+
+bool vc_is_sel(const struct vc_data *vc);
 
 extern int console_blanked;
 
@@ -33,24 +32,21 @@ extern unsigned char default_red[];
 extern unsigned char default_grn[];
 extern unsigned char default_blu[];
 
-extern unsigned short *screen_pos(const struct vc_data *vc, int w_offset,
-               bool viewed);
-extern u16 screen_glyph(const struct vc_data *vc, int offset);
-extern u32 screen_glyph_unicode(const struct vc_data *vc, int offset);
-extern void complement_pos(struct vc_data *vc, int offset);
-extern void invert_screen(struct vc_data *vc, int offset, int count, bool viewed);
-
-extern void getconsxy(const struct vc_data *vc, unsigned char xy[static 2]);
-extern void putconsxy(struct vc_data *vc, unsigned char xy[static const 2]);
-
-extern u16 vcs_scr_readw(const struct vc_data *vc, const u16 *org);
-extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
-extern void vcs_scr_updated(struct vc_data *vc);
-
-extern int vc_uniscr_check(struct vc_data *vc);
-extern void vc_uniscr_copy_line(const struct vc_data *vc, void *dest,
-                               bool viewed,
-                               unsigned int row, unsigned int col,
-                               unsigned int nr);
+unsigned short *screen_pos(const struct vc_data *vc, int w_offset, bool viewed);
+u16 screen_glyph(const struct vc_data *vc, int offset);
+u32 screen_glyph_unicode(const struct vc_data *vc, int offset);
+void complement_pos(struct vc_data *vc, int offset);
+void invert_screen(struct vc_data *vc, int offset, int count, bool viewed);
+
+void getconsxy(const struct vc_data *vc, unsigned char xy[static 2]);
+void putconsxy(struct vc_data *vc, unsigned char xy[static const 2]);
+
+u16 vcs_scr_readw(const struct vc_data *vc, const u16 *org);
+void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
+void vcs_scr_updated(struct vc_data *vc);
+
+int vc_uniscr_check(struct vc_data *vc);
+void vc_uniscr_copy_line(const struct vc_data *vc, void *dest, bool viewed,
+                        unsigned int row, unsigned int col, unsigned int nr);
 
 #endif
index 3fab88ba265ee1d44ce48d9efe0ddc31d5c8e934..ff78efc1f60df4341fc8f9d82ac5e8bd6f6910c1 100644 (file)
@@ -27,7 +27,7 @@ struct serdev_device;
  *                     not sleep.
  */
 struct serdev_device_ops {
-       ssize_t (*receive_buf)(struct serdev_device *, const u8 *, size_t);
+       size_t (*receive_buf)(struct serdev_device *, const u8 *, size_t);
        void (*write_wakeup)(struct serdev_device *);
 };
 
@@ -185,9 +185,9 @@ static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl
        serdev->ops->write_wakeup(serdev);
 }
 
-static inline ssize_t serdev_controller_receive_buf(struct serdev_controller *ctrl,
-                                                   const u8 *data,
-                                                   size_t count)
+static inline size_t serdev_controller_receive_buf(struct serdev_controller *ctrl,
+                                                  const u8 *data,
+                                                  size_t count)
 {
        struct serdev_device *serdev = ctrl->serdev;
 
index be65de65fe612007932c76b71c4b48d2dbd006d8..fd59ed2cca53e967af17fa23c13740d67b6733e7 100644 (file)
@@ -210,6 +210,12 @@ int serial8250_console_exit(struct uart_port *port);
 void serial8250_set_isa_configurator(void (*v)(int port, struct uart_port *up,
                                               u32 *capabilities));
 
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+extern int hp300_setup_serial_console(void) __init;
+#else
+static inline int hp300_setup_serial_console(void) { return 0; }
+#endif
+
 #ifdef CONFIG_SERIAL_8250_RT288X
 int rt288x_setup(struct uart_port *p);
 int au_platform_setup(struct plat_serial8250_port *p);
index 55b1f3ba48ac1725f110747b8d05ce6bbfc1de0b..0a0f6e21d40ec130e458523947c2caaaf28528cd 100644 (file)
@@ -467,9 +467,10 @@ struct uart_port {
        unsigned int            fifosize;               /* tx fifo size */
        unsigned char           x_char;                 /* xon/xoff char */
        unsigned char           regshift;               /* reg offset shift */
+
        unsigned char           iotype;                 /* io access style */
-       unsigned char           quirks;                 /* internal quirks */
 
+#define UPIO_UNKNOWN           ((unsigned char)~0U)    /* UCHAR_MAX */
 #define UPIO_PORT              (SERIAL_IO_PORT)        /* 8b I/O port access */
 #define UPIO_HUB6              (SERIAL_IO_HUB6)        /* Hub6 ISA card */
 #define UPIO_MEM               (SERIAL_IO_MEM)         /* driver-specific */
@@ -479,7 +480,9 @@ struct uart_port {
 #define UPIO_MEM32BE           (SERIAL_IO_MEM32BE)     /* 32b big endian */
 #define UPIO_MEM16             (SERIAL_IO_MEM16)       /* 16b little endian */
 
-       /* quirks must be updated while holding port mutex */
+       unsigned char           quirks;                 /* internal quirks */
+
+       /* internal quirks must be updated while holding port mutex */
 #define UPQ_NO_TXEN_TEST       BIT(0)
 
        unsigned int            read_status_mask;       /* driver specific */
@@ -786,7 +789,8 @@ enum UART_TX_FLAGS {
        if (pending < WAKEUP_CHARS) {                                         \
                uart_write_wakeup(__port);                                    \
                                                                              \
-               if (!((flags) & UART_TX_NOSTOP) && pending == 0)              \
+               if (!((flags) & UART_TX_NOSTOP) && pending == 0 &&            \
+                   __port->ops->tx_empty(__port))                            \
                        __port->ops->stop_tx(__port);                         \
        }                                                                     \
                                                                              \
@@ -959,6 +963,8 @@ int uart_register_driver(struct uart_driver *uart);
 void uart_unregister_driver(struct uart_driver *uart);
 int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
 void uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
+int uart_read_port_properties(struct uart_port *port);
+int uart_read_and_validate_port_properties(struct uart_port *port);
 bool uart_match_port(const struct uart_port *port1,
                const struct uart_port *port2);
 
index 29e06905bc1f0e4509315656d878ecbb48629aca..0f038a1a033099bfeaf094fd3742f59a63a3f076 100644 (file)
@@ -178,6 +178,7 @@ struct geni_se {
 #define M_GP_IRQ_3_EN                  BIT(12)
 #define M_GP_IRQ_4_EN                  BIT(13)
 #define M_GP_IRQ_5_EN                  BIT(14)
+#define M_TX_FIFO_NOT_EMPTY_EN         BIT(21)
 #define M_IO_DATA_DEASSERT_EN          BIT(22)
 #define M_IO_DATA_ASSERT_EN            BIT(23)
 #define M_RX_FIFO_RD_ERR_EN            BIT(24)
index 8c76fd97d4adcd5cb9189dd0eceb5d33dac47b56..2b2e6f0a54d6e6fc0038ca699b76a8d612eb5a38 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/major.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
-#include <linux/tty_buffer.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_ldisc.h>
 #include <linux/tty_port.h>
index c1f5aebef1705c15ba03120653d5cfbea104b39c..d008c3d0a9bbfe0858caee2b89a8f44e5e89fc17 100644 (file)
@@ -25,7 +25,8 @@ extern int fg_console, last_console, want_console;
 
 int vc_allocate(unsigned int console);
 int vc_cons_allocated(unsigned int console);
-int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
+int __vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines,
+               bool from_user);
 struct vc_data *vc_deallocate(unsigned int console);
 void reset_palette(struct vc_data *vc);
 void do_blank_screen(int entering_gfx);
@@ -42,6 +43,12 @@ void redraw_screen(struct vc_data *vc, int is_switch);
 #define update_screen(x) redraw_screen(x, 0)
 #define switch_screen(x) redraw_screen(x, 1)
 
+static inline int vc_resize(struct vc_data *vc, unsigned int cols,
+                           unsigned int lines)
+{
+       return __vc_resize(vc, cols, lines, false);
+}
+
 struct tty_struct;
 int tioclinux(struct tty_struct *tty, unsigned long arg);
 
@@ -168,7 +175,4 @@ void vt_set_led_state(unsigned int console, int leds);
 void vt_kbd_con_start(unsigned int console);
 void vt_kbd_con_stop(unsigned int console);
 
-void vc_scrolldelta_helper(struct vc_data *c, int lines,
-               unsigned int rolled_over, void *_base, unsigned int size);
-
 #endif /* _VT_KERN_H */
index 3a49913d006c9bf6e502ea209336d24d2924effd..cde8f173f566b81a5e602b789ee72278400420d3 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/types.h>
 #include <linux/i2c.h>
+#include <linux/vesa.h>
 
 /* Definitions of frame buffers                                                */
 
@@ -293,13 +294,6 @@ struct fb_con2fbmap {
        __u32 framebuffer;
 };
 
-/* VESA Blanking Levels */
-#define VESA_NO_BLANKING        0
-#define VESA_VSYNC_SUSPEND      1
-#define VESA_HSYNC_SUSPEND      2
-#define VESA_POWERDOWN          3
-
-
 enum {
        /* screen: unblanked, hsync: on,  vsync: on */
        FB_BLANK_UNBLANK       = VESA_NO_BLANKING,
diff --git a/include/uapi/linux/vesa.h b/include/uapi/linux/vesa.h
new file mode 100644 (file)
index 0000000..81947f5
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_VESA_H
+#define _UAPI_LINUX_VESA_H
+
+/* VESA Blanking Levels */
+enum vesa_blank_mode {
+       VESA_NO_BLANKING        = 0,
+#define VESA_NO_BLANKING       VESA_NO_BLANKING
+       VESA_VSYNC_SUSPEND      = 1,
+#define VESA_VSYNC_SUSPEND     VESA_VSYNC_SUSPEND
+       VESA_HSYNC_SUSPEND      = 2,
+#define VESA_HSYNC_SUSPEND     VESA_HSYNC_SUSPEND
+       VESA_POWERDOWN          = VESA_VSYNC_SUSPEND | VESA_HSYNC_SUSPEND,
+#define VESA_POWERDOWN         VESA_POWERDOWN
+       VESA_BLANK_MAX          = VESA_POWERDOWN,
+};
+
+#endif
index a000bef511772b4a10613d16c5ea135686f90033..ca5146006b94c6742ac770323aaf123688d65572 100644 (file)
@@ -3269,6 +3269,21 @@ static int __init keep_bootcon_setup(char *str)
 
 early_param("keep_bootcon", keep_bootcon_setup);
 
+static int console_call_setup(struct console *newcon, char *options)
+{
+       int err;
+
+       if (!newcon->setup)
+               return 0;
+
+       /* Synchronize with possible boot console. */
+       console_lock();
+       err = newcon->setup(newcon, options);
+       console_unlock();
+
+       return err;
+}
+
 /*
  * This is called by register_console() to try to match
  * the newly registered console with any of the ones selected
@@ -3304,8 +3319,8 @@ static int try_enable_preferred_console(struct console *newcon,
                        if (_braille_register_console(newcon, c))
                                return 0;
 
-                       if (newcon->setup &&
-                           (err = newcon->setup(newcon, c->options)) != 0)
+                       err = console_call_setup(newcon, c->options);
+                       if (err)
                                return err;
                }
                newcon->flags |= CON_ENABLED;
@@ -3331,7 +3346,7 @@ static void try_enable_default_console(struct console *newcon)
        if (newcon->index < 0)
                newcon->index = 0;
 
-       if (newcon->setup && newcon->setup(newcon, NULL) != 0)
+       if (console_call_setup(newcon, NULL) != 0)
                return;
 
        newcon->flags |= CON_ENABLED;
index 3b9a44008433201ec86443fe0626967c37a488a3..b5c0e6576749dc31633b4fe0b5135f24c5652da2 100644 (file)
@@ -43,7 +43,7 @@ config KGDB_SERIAL_CONSOLE
        tristate "KGDB: use kgdb over the serial console"
        select CONSOLE_POLL
        select MAGIC_SYSRQ
-       depends on TTY && HW_CONSOLE
+       depends on TTY && VT
        default y
        help
          Share a serial console with kgdb. Sysrq-g must be used
index d6e5aafd697c7e4e06ae8692e935de4bc206c192..36409a56c675e77facc31a5c0873e4f757480b16 100644 (file)
@@ -100,8 +100,8 @@ static void snd_serial_generic_write_wakeup(struct serdev_device *serdev)
        snd_serial_generic_tx_wakeup(drvdata);
 }
 
-static ssize_t snd_serial_generic_receive_buf(struct serdev_device *serdev,
-                                             const u8 *buf, size_t count)
+static size_t snd_serial_generic_receive_buf(struct serdev_device *serdev,
+                                            const u8 *buf, size_t count)
 {
        int ret;
        struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev);