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(). ...
Unified · Split
| @@ -55,6 +55,7 @@ required: · 54 unmodified lines | ||
| 55 | 55 | |
| 56 | 56 | allOf: |
| 57 | 57 | - $ref: serial.yaml# |
| 58 | + - $ref: rs485.yaml# | |
| 58 | 59 | - if: |
| 59 | 60 | properties: |
| 60 | 61 | compatible: |
| @@ -30,6 +30,7 @@ properties: · 29 unmodified lines | ||
| 30 | 30 | - items: |
| 31 | 31 | - enum: |
| 32 | 32 | - fsl,imx93-lpuart |
| 33 | + - fsl,imx95-lpuart | |
| 33 | 34 | - const: fsl,imx8ulp-lpuart |
| 34 | 35 | - const: fsl,imx7ulp-lpuart |
| 35 | 36 | - items: |
| @@ -59,6 +59,7 @@ properties: · 58 unmodified lines | ||
| 59 | 59 | - renesas,hscif-r8a779a0 # R-Car V3U |
| 60 | 60 | - renesas,hscif-r8a779f0 # R-Car S4-8 |
| 61 | 61 | - renesas,hscif-r8a779g0 # R-Car V4H |
| 62 | + - renesas,hscif-r8a779h0 # R-Car V4M | |
| 62 | 63 | - const: renesas,rcar-gen4-hscif # R-Car Gen4 |
| 63 | 64 | - const: renesas,hscif # generic HSCIF compatible UART |
| 64 | 65 | |
| @@ -143,6 +143,8 @@ allOf: · 142 unmodified lines | ||
| 143 | 143 | then: |
| 144 | 144 | required: |
| 145 | 145 | - samsung,uart-fifosize |
| 146 | + properties: | |
| 147 | + reg-io-width: false | |
| 146 | 148 | |
| 147 | 149 | unevaluatedProperties: false |
| 148 | 150 | |
| @@ -88,7 +88,7 @@ properties: · 87 unmodified lines | ||
| 88 | 88 | TX FIFO threshold configuration (in bytes). |
| 89 | 89 | |
| 90 | 90 | patternProperties: |
| 91 | − "^(bluetooth|bluetooth-gnss|gnss|gps|mcu)$": | |
| 91 | + "^(bluetooth|bluetooth-gnss|gnss|gps|mcu|onewire)$": | |
| 92 | 92 | if: |
| 93 | 93 | type: object |
| 94 | 94 | then: |
| @@ -0,0 +1,55 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/serial/st,asc.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: STMicroelectronics STi SoCs Serial Port | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Patrice Chotard <patrice.chotard@foss.st.com> | |
| 11 | + | |
| 12 | +allOf: | |
| 13 | + - $ref: serial.yaml# | |
| 14 | + | |
| 15 | +properties: | |
| 16 | + compatible: | |
| 17 | + const: st,asc | |
| 18 | + | |
| 19 | + reg: | |
| 20 | + maxItems: 1 | |
| 21 | + | |
| 22 | + interrupts: | |
| 23 | + maxItems: 1 | |
| 24 | + | |
| 25 | + clocks: | |
| 26 | + maxItems: 1 | |
| 27 | + | |
| 28 | + st,hw-flow-ctrl: | |
| 29 | + description: When set, enable hardware flow control. | |
| 30 | + type: boolean | |
| 31 | + | |
| 32 | + st,force-m1: | |
| 33 | + description: When set, force asc to be in Mode-1. This is recommended for | |
| 34 | + high bit rates above 19.2K. | |
| 35 | + type: boolean | |
| 36 | + | |
| 37 | +required: | |
| 38 | + - compatible | |
| 39 | + - reg | |
| 40 | + - interrupts | |
| 41 | + - clocks | |
| 42 | + | |
| 43 | +unevaluatedProperties: false | |
| 44 | + | |
| 45 | +examples: | |
| 46 | + - | | |
| 47 | + #include <dt-bindings/clock/stih407-clks.h> | |
| 48 | + #include <dt-bindings/interrupt-controller/arm-gic.h> | |
| 49 | + serial@9830000 { | |
| 50 | + compatible = "st,asc"; | |
| 51 | + reg = <0x9830000 0x2c>; | |
| 52 | + interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; | |
| 53 | + clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>; | |
| 54 | + }; | |
| 55 | +... | |
| @@ -58,6 +58,9 @@ properties: · 57 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | wakeup-source: true |
| 60 | 60 | |
| 61 | + power-domains: | |
| 62 | + maxItems: 1 | |
| 63 | + | |
| 61 | 64 | rx-threshold: |
| 62 | 65 | description: |
| 63 | 66 | If value is set to 1, RX FIFO threshold is disabled. |
| @@ -1,18 +0,0 @@ | ||
| 1 | −*st-asc(Serial Port) | |
| 2 | − | |
| 3 | −Required properties: | |
| 4 | −- compatible : Should be "st,asc". | |
| 5 | −- reg, reg-names, interrupts, interrupt-names : Standard way to define device | |
| 6 | − resources with names. look in | |
| 7 | − Documentation/devicetree/bindings/resource-names.txt | |
| 8 | − | |
| 9 | −Optional properties: | |
| 10 | −- st,hw-flow-ctrl bool flag to enable hardware flow control. | |
| 11 | −- st,force-m1 bool flat to force asc to be in Mode-1 recommended | |
| 12 | − for high bit rates (above 19.2K) | |
| 13 | −Example: | |
| 14 | −serial@fe440000{ | |
| 15 | − compatible = "st,asc"; | |
| 16 | − reg = <0xfe440000 0x2c>; | |
| 17 | − interrupts = <0 209 0>; | |
| 18 | −}; | |
| @@ -0,0 +1,59 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/w1/w1-uart.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: UART 1-Wire Bus | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Christoph Winklhofer <cj.winklhofer@gmail.com> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + UART 1-wire bus. Utilizes the UART interface via the Serial Device Bus | |
| 14 | + to create the 1-Wire timing patterns. | |
| 15 | + | |
| 16 | + The UART peripheral must support full-duplex and operate in open-drain | |
| 17 | + mode. The timing patterns are generated by a specific combination of | |
| 18 | + baud-rate and transmitted byte, which corresponds to a 1-Wire read bit, | |
| 19 | + write bit or reset pulse. | |
| 20 | + | |
| 21 | + The default baud-rate for reset and presence detection is 9600 and for | |
| 22 | + a 1-Wire read or write operation 115200. In case the actual baud-rate | |
| 23 | + is different from the requested one, the transmitted byte is adapted | |
| 24 | + to generate the 1-Wire timing patterns. | |
| 25 | + | |
| 26 | + https://www.analog.com/en/technical-articles/using-a-uart-to-implement-a-1wire-bus-master.html | |
| 27 | + | |
| 28 | +properties: | |
| 29 | + compatible: | |
| 30 | + const: w1-uart | |
| 31 | + | |
| 32 | + reset-bps: | |
| 33 | + default: 9600 | |
| 34 | + description: | |
| 35 | + The baud rate for the 1-Wire reset and presence detect. | |
| 36 | + | |
| 37 | + write-0-bps: | |
| 38 | + default: 115200 | |
| 39 | + description: | |
| 40 | + The baud rate for the 1-Wire write-0 cycle. | |
| 41 | + | |
| 42 | + write-1-bps: | |
| 43 | + default: 115200 | |
| 44 | + description: | |
| 45 | + The baud rate for the 1-Wire write-1 and read cycle. | |
| 46 | + | |
| 47 | +required: | |
| 48 | + - compatible | |
| 49 | + | |
| 50 | +additionalProperties: | |
| 51 | + type: object | |
| 52 | + | |
| 53 | +examples: | |
| 54 | + - | | |
| 55 | + serial { | |
| 56 | + onewire { | |
| 57 | + compatible = "w1-uart"; | |
| 58 | + }; | |
| 59 | + }; | |
| @@ -0,0 +1,45 @@ | ||
| 1 | +.. SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +======= | |
| 4 | +Console | |
| 5 | +======= | |
| 6 | + | |
| 7 | +.. contents:: :local: | |
| 8 | + | |
| 9 | +Struct Console | |
| 10 | +============== | |
| 11 | + | |
| 12 | +.. kernel-doc:: include/linux/console.h | |
| 13 | + :identifiers: console cons_flags | |
| 14 | + | |
| 15 | +Internals | |
| 16 | +--------- | |
| 17 | + | |
| 18 | +.. kernel-doc:: include/linux/console.h | |
| 19 | + :identifiers: nbcon_state nbcon_prio nbcon_context nbcon_write_context | |
| 20 | + | |
| 21 | +Struct Consw | |
| 22 | +============ | |
| 23 | + | |
| 24 | +.. kernel-doc:: include/linux/console.h | |
| 25 | + :identifiers: consw | |
| 26 | + | |
| 27 | +Console functions | |
| 28 | +================= | |
| 29 | + | |
| 30 | +.. kernel-doc:: include/linux/console.h | |
| 31 | + :identifiers: console_srcu_read_flags console_srcu_write_flags | |
| 32 | + console_is_registered for_each_console_srcu for_each_console | |
| 33 | + | |
| 34 | +.. kernel-doc:: drivers/tty/vt/selection.c | |
| 35 | + :export: | |
| 36 | +.. kernel-doc:: drivers/tty/vt/vt.c | |
| 37 | + :export: | |
| 38 | + | |
| 39 | +Internals | |
| 40 | +--------- | |
| 41 | + | |
| 42 | +.. kernel-doc:: drivers/tty/vt/selection.c | |
| 43 | + :internal: | |
| 44 | +.. kernel-doc:: drivers/tty/vt/vt.c | |
| 45 | + :internal: | |
| @@ -38,6 +38,7 @@ In-detail description of the named TTY structures is in separate documents: · 37 unmodified lines | ||
| 38 | 38 | tty_buffer |
| 39 | 39 | tty_ioctl |
| 40 | 40 | tty_internals |
| 41 | + console | |
| 41 | 42 | |
| 42 | 43 | Writing TTY Driver |
| 43 | 44 | ================== |
| @@ -12,3 +12,4 @@ · 11 unmodified lines | ||
| 12 | 12 | mxc-w1 |
| 13 | 13 | omap-hdq |
| 14 | 14 | w1-gpio |
| 15 | + w1-uart | |
| @@ -0,0 +1,54 @@ | ||
| 1 | +.. SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | + | |
| 3 | +===================== | |
| 4 | +Kernel driver w1-uart | |
| 5 | +===================== | |
| 6 | + | |
| 7 | +Author: Christoph Winklhofer <cj.winklhofer@gmail.com> | |
| 8 | + | |
| 9 | + | |
| 10 | +Description | |
| 11 | +----------- | |
| 12 | + | |
| 13 | +UART 1-Wire bus driver. The driver utilizes the UART interface via the | |
| 14 | +Serial Device Bus to create the 1-Wire timing patterns as described in | |
| 15 | +the document `"Using a UART to Implement a 1-Wire Bus Master"`_. | |
| 16 | + | |
| 17 | +.. _"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 | |
| 18 | + | |
| 19 | +In short, the UART peripheral must support full-duplex and operate in | |
| 20 | +open-drain mode. The timing patterns are generated by a specific | |
| 21 | +combination of baud-rate and transmitted byte, which corresponds to a | |
| 22 | +1-Wire read bit, write bit or reset pulse. | |
| 23 | + | |
| 24 | +For instance the timing pattern for a 1-Wire reset and presence detect uses | |
| 25 | +the baud-rate 9600, i.e. 104.2 us per bit. The transmitted byte 0xf0 over | |
| 26 | +UART (least significant bit first, start-bit low) sets the reset low time | |
| 27 | +for 1-Wire to 521 us. A present 1-Wire device changes the received byte by | |
| 28 | +pulling the line low, which is used by the driver to evaluate the result of | |
| 29 | +the 1-Wire operation. | |
| 30 | + | |
| 31 | +Similar for a 1-Wire read bit or write bit, which uses the baud-rate | |
| 32 | +115200, i.e. 8.7 us per bit. The transmitted byte 0x80 is used for a | |
| 33 | +Write-0 operation (low time 69.6us) and the byte 0xff for Read-0, Read-1 | |
| 34 | +and Write-1 (low time 8.7us). | |
| 35 | + | |
| 36 | +The default baud-rate for reset and presence detection is 9600 and for | |
| 37 | +a 1-Wire read or write operation 115200. In case the actual baud-rate | |
| 38 | +is different from the requested one, the transmitted byte is adapted | |
| 39 | +to generate the 1-Wire timing patterns. | |
| 40 | + | |
| 41 | + | |
| 42 | +Usage | |
| 43 | +----- | |
| 44 | + | |
| 45 | +Specify the UART 1-wire bus in the device tree by adding the single child | |
| 46 | +onewire to the serial node (e.g. uart0). For example: | |
| 47 | +:: | |
| 48 | + | |
| 49 | + @uart0 { | |
| 50 | + ... | |
| 51 | + onewire { | |
| 52 | + compatible = "w1-uart"; | |
| 53 | + }; | |
| 54 | + }; | |
| @@ -846,6 +846,6 @@ static void amiga_get_hardware_list(struct seq_file *m) · 845 unmodified lines | ||
| 846 | 846 | * The Amiga keyboard driver needs key_maps, but we cannot export it in |
| 847 | 847 | * drivers/char/defkeymap.c, as it is autogenerated |
| 848 | 848 | */ |
| 849 | −#ifdef CONFIG_HW_CONSOLE | |
| 849 | +#ifdef CONFIG_VT | |
| 850 | 850 | EXPORT_SYMBOL_GPL(key_maps); |
| 851 | 851 | #endif |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include <linux/module.h> |
| 12 | 12 | #include <linux/init.h> |
| 13 | +#include <linux/serial_8250.h> | |
| 13 | 14 | #include <linux/string.h> |
| 14 | 15 | #include <linux/kernel.h> |
| 15 | 16 | #include <linux/console.h> |
| @@ -67,9 +68,6 @@ static char *hp300_models[] __initdata = { · 51 unmodified lines | ||
| 67 | 68 | static char hp300_model_name[13] = "HP9000/"; |
| 68 | 69 | |
| 69 | 70 | extern void hp300_reset(void); |
| 70 | −#ifdef CONFIG_SERIAL_8250_CONSOLE | |
| 71 | −extern int hp300_setup_serial_console(void) __init; | |
| 72 | −#endif | |
| 73 | 71 | |
| 74 | 72 | int __init hp300_parse_bootinfo(const struct bi_record *record) |
| 75 | 73 | { |
| @@ -263,7 +261,5 @@ void __init config_hp300(void) · 187 unmodified lines | ||
| 263 | 261 | } else { |
| 264 | 262 | panic("Unknown HP9000 Model"); |
| 265 | 263 | } |
| 266 | −#ifdef CONFIG_SERIAL_8250_CONSOLE | |
| 267 | 264 | hp300_setup_serial_console(); |
| 268 | −#endif | |
| 269 | 265 | } |
| @@ -383,8 +383,8 @@ static void btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count) · 382 unmodified lines | ||
| 383 | 383 | } |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | −static ssize_t btmtkuart_receive_buf(struct serdev_device *serdev, | |
| 387 | − const u8 *data, size_t count) | |
| 386 | +static size_t btmtkuart_receive_buf(struct serdev_device *serdev, | |
| 387 | + const u8 *data, size_t count) | |
| 388 | 388 | { |
| 389 | 389 | struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); |
| 390 | 390 | |
| @@ -1285,8 +1285,8 @@ static const struct h4_recv_pkt nxp_recv_pkts[] = { · 1284 unmodified lines | ||
| 1285 | 1285 | { NXP_RECV_FW_REQ_V3, .recv = nxp_recv_fw_req_v3 }, |
| 1286 | 1286 | }; |
| 1287 | 1287 | |
| 1288 | −static ssize_t btnxpuart_receive_buf(struct serdev_device *serdev, | |
| 1289 | − const u8 *data, size_t count) | |
| 1288 | +static size_t btnxpuart_receive_buf(struct serdev_device *serdev, | |
| 1289 | + const u8 *data, size_t count) | |
| 1290 | 1290 | { |
| 1291 | 1291 | struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev); |
| 1292 | 1292 | |
| @@ -271,8 +271,8 @@ static void hci_uart_write_wakeup(struct serdev_device *serdev) · 270 unmodified lines | ||
| 271 | 271 | * |
| 272 | 272 | * Return: number of processed bytes |
| 273 | 273 | */ |
| 274 | −static ssize_t hci_uart_receive_buf(struct serdev_device *serdev, | |
| 275 | − const u8 *data, size_t count) | |
| 274 | +static size_t hci_uart_receive_buf(struct serdev_device *serdev, | |
| 275 | + const u8 *data, size_t count) | |
| 276 | 276 | { |
| 277 | 277 | struct hci_uart *hu = serdev_device_get_drvdata(serdev); |
| 278 | 278 | |
| @@ -80,7 +80,7 @@ static const struct gnss_operations gnss_serial_gnss_ops = { · 79 unmodified lines | ||
| 80 | 80 | .write_raw = gnss_serial_write_raw, |
| 81 | 81 | }; |
| 82 | 82 | |
| 83 | −static ssize_t gnss_serial_receive_buf(struct serdev_device *serdev, | |
| 83 | +static size_t gnss_serial_receive_buf(struct serdev_device *serdev, | |
| 84 | 84 | const u8 *buf, size_t count) |
| 85 | 85 | { |
| 86 | 86 | struct gnss_serial *gserial = serdev_device_get_drvdata(serdev); |
| @@ -160,7 +160,7 @@ static const struct gnss_operations sirf_gnss_ops = { · 159 unmodified lines | ||
| 160 | 160 | .write_raw = sirf_write_raw, |
| 161 | 161 | }; |
| 162 | 162 | |
| 163 | −static ssize_t sirf_receive_buf(struct serdev_device *serdev, | |
| 163 | +static size_t sirf_receive_buf(struct serdev_device *serdev, | |
| 164 | 164 | const u8 *buf, size_t count) |
| 165 | 165 | { |
| 166 | 166 | struct sirf_data *data = serdev_device_get_drvdata(serdev); |
| @@ -271,7 +271,7 @@ static void hdlc_rx_frame(struct gb_beagleplay *bg) · 270 unmodified lines | ||
| 271 | 271 | } |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | −static ssize_t hdlc_rx(struct gb_beagleplay *bg, const u8 *data, size_t count) | |
| 274 | +static size_t hdlc_rx(struct gb_beagleplay *bg, const u8 *data, size_t count) | |
| 275 | 275 | { |
| 276 | 276 | size_t i; |
| 277 | 277 | u8 c; |
| @@ -331,8 +331,8 @@ static void hdlc_deinit(struct gb_beagleplay *bg) · 53 unmodified lines | ||
| 331 | 331 | flush_work(&bg->tx_work); |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | −static ssize_t gb_tty_receive(struct serdev_device *sd, const u8 *data, | |
| 335 | − size_t count) | |
| 334 | +static size_t gb_tty_receive(struct serdev_device *sd, const u8 *data, | |
| 335 | + size_t count) | |
| 336 | 336 | { |
| 337 | 337 | struct gb_beagleplay *bg = serdev_device_get_drvdata(sd); |
| 338 | 338 | |
| @@ -211,8 +211,8 @@ static bool pms7003_frame_is_okay(struct pms7003_frame *frame) · 210 unmodified lines | ||
| 211 | 211 | return checksum == pms7003_calc_checksum(frame); |
| 212 | 212 | } |
| 213 | 213 | |
| 214 | −static ssize_t pms7003_receive_buf(struct serdev_device *serdev, const u8 *buf, | |
| 215 | − size_t size) | |
| 214 | +static size_t pms7003_receive_buf(struct serdev_device *serdev, const u8 *buf, | |
| 215 | + size_t size) | |
| 216 | 216 | { |
| 217 | 217 | struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev); |
| 218 | 218 | struct pms7003_state *state = iio_priv(indio_dev); |
| @@ -174,8 +174,8 @@ static int scd30_serdev_command(struct scd30_state *state, enum scd30_cmd cmd, u · 173 unmodified lines | ||
| 174 | 174 | return 0; |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | −static ssize_t scd30_serdev_receive_buf(struct serdev_device *serdev, | |
| 178 | − const u8 *buf, size_t size) | |
| 177 | +static size_t scd30_serdev_receive_buf(struct serdev_device *serdev, | |
| 178 | + const u8 *buf, size_t size) | |
| 179 | 179 | { |
| 180 | 180 | struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev); |
| 181 | 181 | struct scd30_serdev_priv *priv; |
| @@ -210,8 +210,8 @@ static int sps30_serial_command(struct sps30_state *state, unsigned char cmd, · 209 unmodified lines | ||
| 210 | 210 | return rsp_size; |
| 211 | 211 | } |
| 212 | 212 | |
| 213 | −static ssize_t sps30_serial_receive_buf(struct serdev_device *serdev, | |
| 214 | − const u8 *buf, size_t size) | |
| 213 | +static size_t sps30_serial_receive_buf(struct serdev_device *serdev, | |
| 214 | + const u8 *buf, size_t size) | |
| 215 | 215 | { |
| 216 | 216 | struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev); |
| 217 | 217 | struct sps30_serial_priv *priv; |
| @@ -378,8 +378,8 @@ static void bno055_ser_handle_rx(struct bno055_ser_priv *priv, int status) · 377 unmodified lines | ||
| 378 | 378 | * Also, we assume to RX one pkt per time (i.e. the HW doesn't send anything |
| 379 | 379 | * unless we require to AND we don't queue more than one request per time). |
| 380 | 380 | */ |
| 381 | −static ssize_t bno055_ser_receive_buf(struct serdev_device *serdev, | |
| 382 | − const u8 *buf, size_t size) | |
| 381 | +static size_t bno055_ser_receive_buf(struct serdev_device *serdev, | |
| 382 | + const u8 *buf, size_t size) | |
| 383 | 383 | { |
| 384 | 384 | int status; |
| 385 | 385 | struct bno055_ser_priv *priv = serdev_device_get_drvdata(serdev); |
| @@ -26,7 +26,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); · 25 unmodified lines | ||
| 26 | 26 | MODULE_DESCRIPTION("Amiga keyboard driver"); |
| 27 | 27 | MODULE_LICENSE("GPL"); |
| 28 | 28 | |
| 29 | −#ifdef CONFIG_HW_CONSOLE | |
| 29 | +#ifdef CONFIG_VT | |
| 30 | 30 | static unsigned char amikbd_keycode[0x78] __initdata = { |
| 31 | 31 | [0] = KEY_GRAVE, |
| 32 | 32 | [1] = KEY_1, |
| @@ -148,9 +148,9 @@ static void __init amikbd_init_console_keymaps(void) · 115 unmodified lines | ||
| 148 | 148 | memcpy(key_maps[i], temp_map, sizeof(temp_map)); |
| 149 | 149 | } |
| 150 | 150 | } |
| 151 | −#else /* !CONFIG_HW_CONSOLE */ | |
| 151 | +#else /* !CONFIG_VT */ | |
| 152 | 152 | static inline void amikbd_init_console_keymaps(void) {} |
| 153 | −#endif /* !CONFIG_HW_CONSOLE */ | |
| 153 | +#endif /* !CONFIG_VT */ | |
| 154 | 154 | |
| 155 | 155 | static const char *amikbd_messages[8] = { |
| 156 | 156 | [0] = KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n", |
| @@ -471,8 +471,8 @@ static void rave_sp_receive_frame(struct rave_sp *sp, · 470 unmodified lines | ||
| 471 | 471 | rave_sp_receive_reply(sp, data, length); |
| 472 | 472 | } |
| 473 | 473 | |
| 474 | −static ssize_t rave_sp_receive_buf(struct serdev_device *serdev, | |
| 475 | − const u8 *buf, size_t size) | |
| 474 | +static size_t rave_sp_receive_buf(struct serdev_device *serdev, | |
| 475 | + const u8 *buf, size_t size) | |
| 476 | 476 | { |
| 477 | 477 | struct device *dev = &serdev->dev; |
| 478 | 478 | struct rave_sp *sp = dev_get_drvdata(dev); |
| @@ -45,7 +45,7 @@ struct qcauart { · 44 unmodified lines | ||
| 45 | 45 | unsigned char *tx_buffer; |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | −static ssize_t | |
| 48 | +static size_t | |
| 49 | 49 | qca_tty_receive(struct serdev_device *serdev, const u8 *data, size_t count) |
| 50 | 50 | { |
| 51 | 51 | struct qcauart *qca = serdev_device_get_drvdata(serdev); |
| @@ -203,8 +203,8 @@ static int pn532_uart_rx_is_frame(struct sk_buff *skb) · 202 unmodified lines | ||
| 203 | 203 | return 0; |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | −static ssize_t pn532_receive_buf(struct serdev_device *serdev, | |
| 207 | − const u8 *data, size_t count) | |
| 206 | +static size_t pn532_receive_buf(struct serdev_device *serdev, | |
| 207 | + const u8 *data, size_t count) | |
| 208 | 208 | { |
| 209 | 209 | struct pn532_uart_phy *dev = serdev_device_get_drvdata(serdev); |
| 210 | 210 | size_t i; |
| @@ -51,8 +51,8 @@ static const struct s3fwrn5_phy_ops uart_phy_ops = { · 50 unmodified lines | ||
| 51 | 51 | .write = s3fwrn82_uart_write, |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | −static ssize_t s3fwrn82_uart_read(struct serdev_device *serdev, | |
| 55 | − const u8 *data, size_t count) | |
| 54 | +static size_t s3fwrn82_uart_read(struct serdev_device *serdev, | |
| 55 | + const u8 *data, size_t count) | |
| 56 | 56 | { |
| 57 | 57 | struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev); |
| 58 | 58 | size_t i; |
| @@ -81,8 +81,8 @@ struct cros_ec_uart { · 80 unmodified lines | ||
| 81 | 81 | struct response_info response; |
| 82 | 82 | }; |
| 83 | 83 | |
| 84 | −static ssize_t cros_ec_uart_rx_bytes(struct serdev_device *serdev, | |
| 85 | − const u8 *data, size_t count) | |
| 84 | +static size_t cros_ec_uart_rx_bytes(struct serdev_device *serdev, | |
| 85 | + const u8 *data, size_t count) | |
| 86 | 86 | { |
| 87 | 87 | struct ec_host_response *host_response; |
| 88 | 88 | struct cros_ec_device *ec_dev = serdev_device_get_drvdata(serdev); |
| @@ -227,8 +227,8 @@ EXPORT_SYMBOL_GPL(ssam_client_bind); · 226 unmodified lines | ||
| 227 | 227 | |
| 228 | 228 | /* -- Glue layer (serdev_device -> ssam_controller). ------------------------ */ |
| 229 | 229 | |
| 230 | −static ssize_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf, | |
| 231 | − size_t n) | |
| 230 | +static size_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf, | |
| 231 | + size_t n) | |
| 232 | 232 | { |
| 233 | 233 | struct ssam_controller *ctrl; |
| 234 | 234 | int ret; |
| @@ -75,14 +75,9 @@ config VT_CONSOLE_SLEEP · 74 unmodified lines | ||
| 75 | 75 | def_bool y |
| 76 | 76 | depends on VT_CONSOLE && PM_SLEEP |
| 77 | 77 | |
| 78 | −config HW_CONSOLE | |
| 79 | − bool | |
| 80 | − depends on VT | |
| 81 | − default y | |
| 82 | − | |
| 83 | 78 | config VT_HW_CONSOLE_BINDING |
| 84 | 79 | bool "Support for binding and unbinding console drivers" |
| 85 | − depends on HW_CONSOLE | |
| 80 | + depends on VT | |
| 86 | 81 | help |
| 87 | 82 | The virtual terminal is the device that interacts with the physical |
| 88 | 83 | terminal through console drivers. On these systems, at least one |
| @@ -1566,7 +1566,7 @@ fail_tty_driver_kref_put: · 1565 unmodified lines | ||
| 1566 | 1566 | return error; |
| 1567 | 1567 | } |
| 1568 | 1568 | |
| 1569 | −static int __exit amiga_serial_remove(struct platform_device *pdev) | |
| 1569 | +static void __exit amiga_serial_remove(struct platform_device *pdev) | |
| 1570 | 1570 | { |
| 1571 | 1571 | struct serial_state *state = platform_get_drvdata(pdev); |
| 1572 | 1572 | |
| @@ -1576,12 +1576,10 @@ static int __exit amiga_serial_remove(struct platform_device *pdev) · 3 unmodified lines | ||
| 1576 | 1576 | |
| 1577 | 1577 | free_irq(IRQ_AMIGA_TBE, state); |
| 1578 | 1578 | free_irq(IRQ_AMIGA_RBF, state); |
| 1579 | − | |
| 1580 | − return 0; | |
| 1581 | 1579 | } |
| 1582 | 1580 | |
| 1583 | 1581 | static struct platform_driver amiga_serial_driver = { |
| 1584 | − .remove = __exit_p(amiga_serial_remove), | |
| 1582 | + .remove_new = __exit_p(amiga_serial_remove), | |
| 1585 | 1583 | .driver = { |
| 1586 | 1584 | .name = "amiga-serial", |
| 1587 | 1585 | }, |
| @@ -408,7 +408,7 @@ err_unmap: · 407 unmodified lines | ||
| 408 | 408 | return ret; |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | −static int goldfish_tty_remove(struct platform_device *pdev) | |
| 411 | +static void goldfish_tty_remove(struct platform_device *pdev) | |
| 412 | 412 | { |
| 413 | 413 | struct goldfish_tty *qtty = platform_get_drvdata(pdev); |
| 414 | 414 | |
| @@ -424,7 +424,6 @@ static int goldfish_tty_remove(struct platform_device *pdev) · 9 unmodified lines | ||
| 424 | 424 | if (goldfish_tty_current_line_count == 0) |
| 425 | 425 | goldfish_tty_delete_driver(); |
| 426 | 426 | mutex_unlock(&goldfish_tty_lock); |
| 427 | − return 0; | |
| 428 | 427 | } |
| 429 | 428 | |
| 430 | 429 | #ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE |
| @@ -462,7 +461,7 @@ MODULE_DEVICE_TABLE(of, goldfish_tty_of_match); · 31 unmodified lines | ||
| 462 | 461 | |
| 463 | 462 | static struct platform_driver goldfish_tty_platform_driver = { |
| 464 | 463 | .probe = goldfish_tty_probe, |
| 465 | − .remove = goldfish_tty_remove, | |
| 464 | + .remove_new = goldfish_tty_remove, | |
| 466 | 465 | .driver = { |
| 467 | 466 | .name = "goldfish_tty", |
| 468 | 467 | .of_match_table = goldfish_tty_of_match, |
| @@ -1035,6 +1035,10 @@ static const struct attribute_group *hvc_iucv_dev_attr_groups[] = { · 1034 unmodified lines | ||
| 1035 | 1035 | NULL, |
| 1036 | 1036 | }; |
| 1037 | 1037 | |
| 1038 | +static void hvc_iucv_free(struct device *data) | |
| 1039 | +{ | |
| 1040 | + kfree(data); | |
| 1041 | +} | |
| 1038 | 1042 | |
| 1039 | 1043 | /** |
| 1040 | 1044 | * 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) · 56 unmodified lines | ||
| 1097 | 1101 | priv->dev->bus = &iucv_bus; |
| 1098 | 1102 | priv->dev->parent = iucv_root; |
| 1099 | 1103 | priv->dev->groups = hvc_iucv_dev_attr_groups; |
| 1100 | − priv->dev->release = (void (*)(struct device *)) kfree; | |
| 1104 | + priv->dev->release = hvc_iucv_free; | |
| 1101 | 1105 | rc = device_register(priv->dev); |
| 1102 | 1106 | if (rc) { |
| 1103 | 1107 | put_device(priv->dev); |
| @@ -431,7 +431,7 @@ static void serdev_drv_remove(struct device *dev) · 430 unmodified lines | ||
| 431 | 431 | dev_pm_domain_detach(dev, true); |
| 432 | 432 | } |
| 433 | 433 | |
| 434 | −static struct bus_type serdev_bus_type = { | |
| 434 | +static const struct bus_type serdev_bus_type = { | |
| 435 | 435 | .name = "serial", |
| 436 | 436 | .match = serdev_device_match, |
| 437 | 437 | .probe = serdev_drv_probe, |
| @@ -27,19 +27,17 @@ static size_t ttyport_receive_buf(struct tty_port *port, const u8 *cp, · 26 unmodified lines | ||
| 27 | 27 | { |
| 28 | 28 | struct serdev_controller *ctrl = port->client_data; |
| 29 | 29 | struct serport *serport = serdev_controller_get_drvdata(ctrl); |
| 30 | − int ret; | |
| 30 | + size_t ret; | |
| 31 | 31 | |
| 32 | 32 | if (!test_bit(SERPORT_ACTIVE, &serport->flags)) |
| 33 | 33 | return 0; |
| 34 | 34 | |
| 35 | 35 | ret = serdev_controller_receive_buf(ctrl, cp, count); |
| 36 | 36 | |
| 37 | − dev_WARN_ONCE(&ctrl->dev, ret < 0 || ret > count, | |
| 38 | − "receive_buf returns %d (count = %zu)\n", | |
| 37 | + dev_WARN_ONCE(&ctrl->dev, ret > count, | |
| 38 | + "receive_buf returns %zu (count = %zu)\n", | |
| 39 | 39 | ret, count); |
| 40 | − if (ret < 0) | |
| 41 | − return 0; | |
| 42 | − else if (ret > count) | |
| 40 | + if (ret > count) | |
| 43 | 41 | return count; |
| 44 | 42 | |
| 45 | 43 | return ret; |
| @@ -419,8 +419,8 @@ static int aspeed_vuart_probe(struct platform_device *pdev) · 418 unmodified lines | ||
| 419 | 419 | struct aspeed_vuart *vuart; |
| 420 | 420 | struct device_node *np; |
| 421 | 421 | struct resource *res; |
| 422 | − u32 clk, prop, sirq[2]; | |
| 423 | 422 | int rc, sirq_polarity; |
| 423 | + u32 prop, sirq[2]; | |
| 424 | 424 | struct clk *vclk; |
| 425 | 425 | |
| 426 | 426 | np = pdev->dev.of_node; |
| @@ -447,53 +447,35 @@ static int aspeed_vuart_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 447 | 447 | port.port.status = UPSTAT_SYNC_FIFO; |
| 448 | 448 | port.port.dev = &pdev->dev; |
| 449 | 449 | port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); |
| 450 | + port.port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE | | |
| 451 | + UPF_NO_THRE_TEST; | |
| 450 | 452 | port.bugs |= UART_BUG_TXRACE; |
| 451 | 453 | |
| 452 | 454 | rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); |
| 453 | 455 | if (rc < 0) |
| 454 | 456 | return rc; |
| 455 | 457 | |
| 456 | − if (of_property_read_u32(np, "clock-frequency", &clk)) { | |
| 458 | + rc = uart_read_port_properties(&port.port); | |
| 459 | + if (rc) | |
| 460 | + goto err_sysfs_remove; | |
| 461 | + | |
| 462 | + /* Get clk rate through clk driver if present */ | |
| 463 | + if (!port.port.uartclk) { | |
| 457 | 464 | vclk = devm_clk_get_enabled(dev, NULL); |
| 458 | 465 | if (IS_ERR(vclk)) { |
| 459 | 466 | rc = dev_err_probe(dev, PTR_ERR(vclk), "clk or clock-frequency not defined\n"); |
| 460 | 467 | goto err_sysfs_remove; |
| 461 | 468 | } |
| 462 | 469 | |
| 463 | − clk = clk_get_rate(vclk); | |
| 470 | + port.port.uartclk = clk_get_rate(vclk); | |
| 464 | 471 | } |
| 465 | 472 | |
| 466 | 473 | /* If current-speed was set, then try not to change it. */ |
| 467 | 474 | if (of_property_read_u32(np, "current-speed", &prop) == 0) |
| 468 | − port.port.custom_divisor = clk / (16 * prop); | |
| 469 | − | |
| 470 | − /* Check for shifted address mapping */ | |
| 471 | − if (of_property_read_u32(np, "reg-offset", &prop) == 0) | |
| 472 | − port.port.mapbase += prop; | |
| 473 | − | |
| 474 | − /* Check for registers offset within the devices address range */ | |
| 475 | − if (of_property_read_u32(np, "reg-shift", &prop) == 0) | |
| 476 | − port.port.regshift = prop; | |
| 475 | + port.port.custom_divisor = port.port.uartclk / (16 * prop); | |
| 477 | 476 | |
| 478 | − /* Check for fifo size */ | |
| 479 | − if (of_property_read_u32(np, "fifo-size", &prop) == 0) | |
| 480 | − port.port.fifosize = prop; | |
| 481 | − | |
| 482 | − /* Check for a fixed line number */ | |
| 483 | − rc = of_alias_get_id(np, "serial"); | |
| 484 | − if (rc >= 0) | |
| 485 | − port.port.line = rc; | |
| 486 | − | |
| 487 | − port.port.irq = irq_of_parse_and_map(np, 0); | |
| 488 | 477 | port.port.handle_irq = aspeed_vuart_handle_irq; |
| 489 | − port.port.iotype = UPIO_MEM; | |
| 490 | 478 | port.port.type = PORT_ASPEED_VUART; |
| 491 | − port.port.uartclk = clk; | |
| 492 | − port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | |
| 493 | − | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST; | |
| 494 | − | |
| 495 | − if (of_property_read_bool(np, "no-loopback-test")) | |
| 496 | − port.port.flags |= UPF_SKIP_TEST; | |
| 497 | 479 | |
| 498 | 480 | if (port.port.fifosize) |
| 499 | 481 | port.capabilities = UART_CAP_FIFO; |
| @@ -503,7 +485,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 503 | 485 | |
| 504 | 486 | rc = serial8250_register_8250_port(&port); |
| 505 | 487 | if (rc < 0) |
| 506 | − goto err_clk_disable; | |
| 488 | + goto err_sysfs_remove; | |
| 507 | 489 | |
| 508 | 490 | vuart->line = rc; |
| 509 | 491 | vuart->port = serial8250_get_port(vuart->line); |
| @@ -529,7 +511,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev) · 19 unmodified lines | ||
| 529 | 511 | rc = aspeed_vuart_set_lpc_address(vuart, prop); |
| 530 | 512 | if (rc < 0) { |
| 531 | 513 | dev_err_probe(dev, rc, "invalid value in aspeed,lpc-io-reg property\n"); |
| 532 | − goto err_clk_disable; | |
| 514 | + goto err_sysfs_remove; | |
| 533 | 515 | } |
| 534 | 516 | |
| 535 | 517 | 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) · 5 unmodified lines | ||
| 541 | 523 | rc = aspeed_vuart_set_sirq(vuart, sirq[0]); |
| 542 | 524 | if (rc < 0) { |
| 543 | 525 | dev_err_probe(dev, rc, "invalid sirq number in aspeed,lpc-interrupts property\n"); |
| 544 | − goto err_clk_disable; | |
| 526 | + goto err_sysfs_remove; | |
| 545 | 527 | } |
| 546 | 528 | |
| 547 | 529 | sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]); |
| 548 | 530 | if (sirq_polarity < 0) { |
| 549 | 531 | rc = dev_err_probe(dev, sirq_polarity, |
| 550 | 532 | "invalid sirq polarity in aspeed,lpc-interrupts property\n"); |
| 551 | − goto err_clk_disable; | |
| 533 | + goto err_sysfs_remove; | |
| 552 | 534 | } |
| 553 | 535 | |
| 554 | 536 | aspeed_vuart_set_sirq_polarity(vuart, sirq_polarity); |
| @@ -559,8 +541,6 @@ static int aspeed_vuart_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 559 | 541 | |
| 560 | 542 | return 0; |
| 561 | 543 | |
| 562 | −err_clk_disable: | |
| 563 | − irq_dispose_mapping(port.port.irq); | |
| 564 | 544 | err_sysfs_remove: |
| 565 | 545 | sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); |
| 566 | 546 | return rc; |
| @@ -45,10 +45,6 @@ struct bcm2835aux_data { · 44 unmodified lines | ||
| 45 | 45 | u32 cntl; |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | −struct bcm2835_aux_serial_driver_data { | |
| 49 | − resource_size_t offset; | |
| 50 | −}; | |
| 51 | − | |
| 52 | 48 | static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) |
| 53 | 49 | { |
| 54 | 50 | 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) · 30 unmodified lines | ||
| 85 | 81 | |
| 86 | 82 | static int bcm2835aux_serial_probe(struct platform_device *pdev) |
| 87 | 83 | { |
| 88 | − const struct bcm2835_aux_serial_driver_data *bcm_data; | |
| 84 | + const struct software_node *bcm2835_swnode; | |
| 89 | 85 | struct uart_8250_port up = { }; |
| 90 | 86 | struct bcm2835aux_data *data; |
| 91 | − resource_size_t offset = 0; | |
| 92 | 87 | struct resource *res; |
| 93 | 88 | unsigned int uartclk; |
| 94 | 89 | int ret; |
| @@ -101,12 +96,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) · 6 unmodified lines | ||
| 101 | 96 | /* initialize data */ |
| 102 | 97 | up.capabilities = UART_CAP_FIFO | UART_CAP_MINI; |
| 103 | 98 | up.port.dev = &pdev->dev; |
| 104 | − up.port.regshift = 2; | |
| 105 | 99 | up.port.type = PORT_16550; |
| 106 | − up.port.iotype = UPIO_MEM; | |
| 107 | − up.port.fifosize = 8; | |
| 108 | − up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE | | |
| 109 | − UPF_SKIP_TEST | UPF_IOREMAP; | |
| 100 | + up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_IOREMAP; | |
| 110 | 101 | up.port.rs485_config = serial8250_em485_config; |
| 111 | 102 | up.port.rs485_supported = serial8250_em485_supported; |
| 112 | 103 | up.rs485_start_tx = bcm2835aux_rs485_start_tx; |
| @@ -122,12 +113,6 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 122 | 113 | if (IS_ERR(data->clk)) |
| 123 | 114 | return dev_err_probe(&pdev->dev, PTR_ERR(data->clk), "could not get clk\n"); |
| 124 | 115 | |
| 125 | − /* get the interrupt */ | |
| 126 | − ret = platform_get_irq(pdev, 0); | |
| 127 | − if (ret < 0) | |
| 128 | − return ret; | |
| 129 | − up.port.irq = ret; | |
| 130 | − | |
| 131 | 116 | /* map the main registers */ |
| 132 | 117 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 133 | 118 | if (!res) { |
| @@ -135,52 +120,40 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 135 | 120 | return -EINVAL; |
| 136 | 121 | } |
| 137 | 122 | |
| 138 | − bcm_data = device_get_match_data(&pdev->dev); | |
| 139 | − | |
| 140 | − /* Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi) | |
| 141 | − * describe the miniuart with a base address that encompasses the auxiliary | |
| 142 | − * registers shared between the miniuart and spi. | |
| 143 | − * | |
| 144 | − * This is due to historical reasons, see discussion here : | |
| 145 | − * https://edk2.groups.io/g/devel/topic/87501357#84349 | |
| 146 | − * | |
| 147 | − * We need to add the offset between the miniuart and auxiliary | |
| 148 | − * registers to get the real miniuart base address. | |
| 149 | − */ | |
| 150 | − if (bcm_data) | |
| 151 | − offset = bcm_data->offset; | |
| 123 | + up.port.mapbase = res->start; | |
| 124 | + up.port.mapsize = resource_size(res); | |
| 125 | + | |
| 126 | + bcm2835_swnode = device_get_match_data(&pdev->dev); | |
| 127 | + if (bcm2835_swnode) { | |
| 128 | + ret = device_add_software_node(&pdev->dev, bcm2835_swnode); | |
| 129 | + if (ret) | |
| 130 | + return ret; | |
| 131 | + } | |
| 152 | 132 | |
| 153 | − up.port.mapbase = res->start + offset; | |
| 154 | − up.port.mapsize = resource_size(res) - offset; | |
| 133 | + ret = uart_read_port_properties(&up.port); | |
| 134 | + if (ret) | |
| 135 | + goto rm_swnode; | |
| 155 | 136 | |
| 156 | − /* Check for a fixed line number */ | |
| 157 | − ret = of_alias_get_id(pdev->dev.of_node, "serial"); | |
| 158 | − if (ret >= 0) | |
| 159 | − up.port.line = ret; | |
| 137 | + up.port.regshift = 2; | |
| 138 | + up.port.fifosize = 8; | |
| 160 | 139 | |
| 161 | 140 | /* enable the clock as a last step */ |
| 162 | 141 | ret = clk_prepare_enable(data->clk); |
| 163 | 142 | if (ret) { |
| 164 | − dev_err(&pdev->dev, "unable to enable uart clock - %d\n", | |
| 165 | − ret); | |
| 166 | − return ret; | |
| 143 | + dev_err_probe(&pdev->dev, ret, "unable to enable uart clock\n"); | |
| 144 | + goto rm_swnode; | |
| 167 | 145 | } |
| 168 | 146 | |
| 169 | 147 | uartclk = clk_get_rate(data->clk); |
| 170 | − if (!uartclk) { | |
| 171 | − ret = device_property_read_u32(&pdev->dev, "clock-frequency", &uartclk); | |
| 172 | − if (ret) { | |
| 173 | − dev_err_probe(&pdev->dev, ret, "could not get clk rate\n"); | |
| 174 | − goto dis_clk; | |
| 175 | − } | |
| 176 | − } | |
| 148 | + if (uartclk) | |
| 149 | + up.port.uartclk = uartclk; | |
| 177 | 150 | |
| 178 | 151 | /* the HW-clock divider for bcm2835aux is 8, |
| 179 | 152 | * but 8250 expects a divider of 16, |
| 180 | 153 | * so we have to multiply the actual clock by 2 |
| 181 | 154 | * to get identical baudrates. |
| 182 | 155 | */ |
| 183 | − up.port.uartclk = uartclk * 2; | |
| 156 | + up.port.uartclk *= 2; | |
| 184 | 157 | |
| 185 | 158 | /* register the port */ |
| 186 | 159 | ret = serial8250_register_8250_port(&up); |
| @@ -194,6 +167,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) · 7 unmodified lines | ||
| 194 | 167 | |
| 195 | 168 | dis_clk: |
| 196 | 169 | clk_disable_unprepare(data->clk); |
| 170 | +rm_swnode: | |
| 171 | + device_remove_software_node(&pdev->dev); | |
| 197 | 172 | return ret; |
| 198 | 173 | } |
| 199 | 174 | |
| @@ -203,10 +178,27 @@ static void bcm2835aux_serial_remove(struct platform_device *pdev) · 3 unmodified lines | ||
| 203 | 178 | |
| 204 | 179 | serial8250_unregister_port(data->line); |
| 205 | 180 | clk_disable_unprepare(data->clk); |
| 181 | + device_remove_software_node(&pdev->dev); | |
| 206 | 182 | } |
| 207 | 183 | |
| 208 | −static const struct bcm2835_aux_serial_driver_data bcm2835_acpi_data = { | |
| 209 | − .offset = 0x40, | |
| 184 | +/* | |
| 185 | + * Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi) | |
| 186 | + * describe the miniuart with a base address that encompasses the auxiliary | |
| 187 | + * registers shared between the miniuart and spi. | |
| 188 | + * | |
| 189 | + * This is due to historical reasons, see discussion here: | |
| 190 | + * https://edk2.groups.io/g/devel/topic/87501357#84349 | |
| 191 | + * | |
| 192 | + * We need to add the offset between the miniuart and auxiliary registers | |
| 193 | + * to get the real miniuart base address. | |
| 194 | + */ | |
| 195 | +static const struct property_entry bcm2835_acpi_properties[] = { | |
| 196 | + PROPERTY_ENTRY_U32("reg-offset", 0x40), | |
| 197 | + { } | |
| 198 | +}; | |
| 199 | + | |
| 200 | +static const struct software_node bcm2835_acpi_node = { | |
| 201 | + .properties = bcm2835_acpi_properties, | |
| 210 | 202 | }; |
| 211 | 203 | |
| 212 | 204 | static const struct of_device_id bcm2835aux_serial_match[] = { |
| @@ -216,7 +208,7 @@ static const struct of_device_id bcm2835aux_serial_match[] = { · 3 unmodified lines | ||
| 216 | 208 | MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match); |
| 217 | 209 | |
| 218 | 210 | static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = { |
| 219 | − { "BCM2836", (kernel_ulong_t)&bcm2835_acpi_data }, | |
| 211 | + { "BCM2836", (kernel_ulong_t)&bcm2835_acpi_node }, | |
| 220 | 212 | { } |
| 221 | 213 | }; |
| 222 | 214 | MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match); |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/delay.h> |
| 23 | 23 | #include <linux/clk.h> |
| 24 | 24 | #include <linux/debugfs.h> |
| 25 | +#include <linux/units.h> | |
| 25 | 26 | |
| 26 | 27 | #include "8250.h" |
| 27 | 28 | |
| @@ -187,21 +188,19 @@ · 159 unmodified lines | ||
| 187 | 188 | #define TX_BUF_SIZE 4096 |
| 188 | 189 | #define RX_BUF_SIZE 4096 |
| 189 | 190 | #define RX_BUFS_COUNT 2 |
| 190 | −#define KHZ 1000 | |
| 191 | −#define MHZ(x) ((x) * KHZ * KHZ) | |
| 192 | 191 | |
| 193 | 192 | static const u32 brcmstb_rate_table[] = { |
| 194 | − MHZ(81), | |
| 195 | − MHZ(108), | |
| 196 | − MHZ(64), /* Actually 64285715 for some chips */ | |
| 197 | − MHZ(48), | |
| 193 | + 81 * HZ_PER_MHZ, | |
| 194 | + 108 * HZ_PER_MHZ, | |
| 195 | + 64 * HZ_PER_MHZ, /* Actually 64285715 for some chips */ | |
| 196 | + 48 * HZ_PER_MHZ, | |
| 198 | 197 | }; |
| 199 | 198 | |
| 200 | 199 | static const u32 brcmstb_rate_table_7278[] = { |
| 201 | − MHZ(81), | |
| 202 | − MHZ(108), | |
| 200 | + 81 * HZ_PER_MHZ, | |
| 201 | + 108 * HZ_PER_MHZ, | |
| 203 | 202 | 0, |
| 204 | − MHZ(48), | |
| 203 | + 48 * HZ_PER_MHZ, | |
| 205 | 204 | }; |
| 206 | 205 | |
| 207 | 206 | struct brcmuart_priv { |
| @@ -936,17 +935,14 @@ static void brcmuart_init_debugfs(struct brcmuart_priv *priv, · 728 unmodified lines | ||
| 936 | 935 | static int brcmuart_probe(struct platform_device *pdev) |
| 937 | 936 | { |
| 938 | 937 | struct resource *regs; |
| 939 | − struct device_node *np = pdev->dev.of_node; | |
| 940 | 938 | const struct of_device_id *of_id = NULL; |
| 941 | 939 | struct uart_8250_port *new_port; |
| 942 | 940 | struct device *dev = &pdev->dev; |
| 943 | 941 | struct brcmuart_priv *priv; |
| 944 | 942 | struct clk *baud_mux_clk; |
| 945 | 943 | struct uart_8250_port up; |
| 946 | − int irq; | |
| 947 | 944 | void __iomem *membase = NULL; |
| 948 | 945 | resource_size_t mapbase = 0; |
| 949 | − u32 clk_rate = 0; | |
| 950 | 946 | int ret; |
| 951 | 947 | int x; |
| 952 | 948 | int dma_irq; |
| @@ -954,15 +950,12 @@ static int brcmuart_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 954 | 950 | "uart", "dma_rx", "dma_tx", "dma_intr2", "dma_arb" |
| 955 | 951 | }; |
| 956 | 952 | |
| 957 | − irq = platform_get_irq(pdev, 0); | |
| 958 | − if (irq < 0) | |
| 959 | − return irq; | |
| 960 | 953 | priv = devm_kzalloc(dev, sizeof(struct brcmuart_priv), |
| 961 | 954 | GFP_KERNEL); |
| 962 | 955 | if (!priv) |
| 963 | 956 | return -ENOMEM; |
| 964 | 957 | |
| 965 | − of_id = of_match_node(brcmuart_dt_ids, np); | |
| 958 | + of_id = of_match_node(brcmuart_dt_ids, dev->of_node); | |
| 966 | 959 | if (!of_id || !of_id->data) |
| 967 | 960 | priv->rate_table = brcmstb_rate_table; |
| 968 | 961 | else |
| @@ -1012,7 +1005,23 @@ static int brcmuart_probe(struct platform_device *pdev) · 43 unmodified lines | ||
| 1012 | 1005 | } |
| 1013 | 1006 | } |
| 1014 | 1007 | |
| 1015 | − of_property_read_u32(np, "clock-frequency", &clk_rate); | |
| 1008 | + dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not "); | |
| 1009 | + | |
| 1010 | + memset(&up, 0, sizeof(up)); | |
| 1011 | + up.port.type = PORT_BCM7271; | |
| 1012 | + up.port.dev = dev; | |
| 1013 | + up.port.mapbase = mapbase; | |
| 1014 | + up.port.membase = membase; | |
| 1015 | + up.port.handle_irq = brcmuart_handle_irq; | |
| 1016 | + up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE; | |
| 1017 | + up.port.private_data = priv; | |
| 1018 | + | |
| 1019 | + ret = uart_read_port_properties(&up.port); | |
| 1020 | + if (ret) | |
| 1021 | + goto release_dma; | |
| 1022 | + | |
| 1023 | + up.port.regshift = 2; | |
| 1024 | + up.port.iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32; | |
| 1016 | 1025 | |
| 1017 | 1026 | /* See if a Baud clock has been specified */ |
| 1018 | 1027 | baud_mux_clk = devm_clk_get_optional_enabled(dev, "sw_baud"); |
| @@ -1024,39 +1033,11 @@ static int brcmuart_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 1024 | 1033 | |
| 1025 | 1034 | priv->baud_mux_clk = baud_mux_clk; |
| 1026 | 1035 | init_real_clk_rates(dev, priv); |
| 1027 | − clk_rate = priv->default_mux_rate; | |
| 1036 | + up.port.uartclk = priv->default_mux_rate; | |
| 1028 | 1037 | } else { |
| 1029 | 1038 | dev_dbg(dev, "BAUD MUX clock not specified\n"); |
| 1030 | 1039 | } |
| 1031 | 1040 | |
| 1032 | − if (clk_rate == 0) { | |
| 1033 | − ret = dev_err_probe(dev, -EINVAL, "clock-frequency or clk not defined\n"); | |
| 1034 | − goto release_dma; | |
| 1035 | − } | |
| 1036 | − | |
| 1037 | − dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not "); | |
| 1038 | − | |
| 1039 | − memset(&up, 0, sizeof(up)); | |
| 1040 | − up.port.type = PORT_BCM7271; | |
| 1041 | − up.port.uartclk = clk_rate; | |
| 1042 | − up.port.dev = dev; | |
| 1043 | − up.port.mapbase = mapbase; | |
| 1044 | − up.port.membase = membase; | |
| 1045 | − up.port.irq = irq; | |
| 1046 | − up.port.handle_irq = brcmuart_handle_irq; | |
| 1047 | − up.port.regshift = 2; | |
| 1048 | − up.port.iotype = of_device_is_big_endian(np) ? | |
| 1049 | − UPIO_MEM32BE : UPIO_MEM32; | |
| 1050 | − up.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | |
| 1051 | − | UPF_FIXED_PORT | UPF_FIXED_TYPE; | |
| 1052 | − up.port.dev = dev; | |
| 1053 | − up.port.private_data = priv; | |
| 1054 | − | |
| 1055 | − /* Check for a fixed line number */ | |
| 1056 | − ret = of_alias_get_id(np, "serial"); | |
| 1057 | − if (ret >= 0) | |
| 1058 | − up.port.line = ret; | |
| 1059 | − | |
| 1060 | 1041 | /* setup HR timer */ |
| 1061 | 1042 | hrtimer_init(&priv->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
| 1062 | 1043 | priv->hrt.function = brcmuart_hrtimer_func; |
| @@ -9,7 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * LCR is written whilst busy. If it is, then a busy detect interrupt is |
| 10 | 10 | * raised, the LCR needs to be rewritten and the uart status register read. |
| 11 | 11 | */ |
| 12 | −#include <linux/acpi.h> | |
| 13 | 12 | #include <linux/clk.h> |
| 14 | 13 | #include <linux/delay.h> |
| 15 | 14 | #include <linux/device.h> |
| @@ -17,7 +16,6 @@ · 1 unmodified line | ||
| 17 | 16 | #include <linux/mod_devicetable.h> |
| 18 | 17 | #include <linux/module.h> |
| 19 | 18 | #include <linux/notifier.h> |
| 20 | −#include <linux/of.h> | |
| 21 | 19 | #include <linux/platform_device.h> |
| 22 | 20 | #include <linux/pm_runtime.h> |
| 23 | 21 | #include <linux/property.h> |
| @@ -56,6 +54,7 @@ · 32 unmodified lines | ||
| 56 | 54 | #define DW_UART_QUIRK_ARMADA_38X BIT(1) |
| 57 | 55 | #define DW_UART_QUIRK_SKIP_SET_RATE BIT(2) |
| 58 | 56 | #define DW_UART_QUIRK_IS_DMA_FC BIT(3) |
| 57 | +#define DW_UART_QUIRK_APMC0D08 BIT(4) | |
| 59 | 58 | |
| 60 | 59 | static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb) |
| 61 | 60 | { |
| @@ -445,44 +444,29 @@ static void dw8250_prepare_rx_dma(struct uart_8250_port *p) · 383 unmodified lines | ||
| 445 | 444 | |
| 446 | 445 | static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) |
| 447 | 446 | { |
| 448 | − struct device_node *np = p->dev->of_node; | |
| 447 | + unsigned int quirks = data->pdata ? data->pdata->quirks : 0; | |
| 449 | 448 | |
| 450 | − if (np) { | |
| 451 | − unsigned int quirks = data->pdata->quirks; | |
| 452 | − int id; | |
| 453 | − | |
| 454 | − /* get index of serial line, if found in DT aliases */ | |
| 455 | − id = of_alias_get_id(np, "serial"); | |
| 456 | − if (id >= 0) | |
| 457 | − p->line = id; | |
| 458 | 449 | #ifdef CONFIG_64BIT |
| 459 | − if (quirks & DW_UART_QUIRK_OCTEON) { | |
| 460 | − p->serial_in = dw8250_serial_inq; | |
| 461 | − p->serial_out = dw8250_serial_outq; | |
| 462 | − p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; | |
| 463 | − p->type = PORT_OCTEON; | |
| 464 | − data->skip_autocfg = true; | |
| 465 | − } | |
| 450 | + if (quirks & DW_UART_QUIRK_OCTEON) { | |
| 451 | + p->serial_in = dw8250_serial_inq; | |
| 452 | + p->serial_out = dw8250_serial_outq; | |
| 453 | + p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; | |
| 454 | + p->type = PORT_OCTEON; | |
| 455 | + data->skip_autocfg = true; | |
| 456 | + } | |
| 466 | 457 | #endif |
| 467 | 458 | |
| 468 | − if (of_device_is_big_endian(np)) { | |
| 469 | − p->iotype = UPIO_MEM32BE; | |
| 470 | − p->serial_in = dw8250_serial_in32be; | |
| 471 | − p->serial_out = dw8250_serial_out32be; | |
| 472 | − } | |
| 473 | − | |
| 474 | − if (quirks & DW_UART_QUIRK_ARMADA_38X) | |
| 475 | − p->serial_out = dw8250_serial_out38x; | |
| 476 | − if (quirks & DW_UART_QUIRK_SKIP_SET_RATE) | |
| 477 | − p->set_termios = dw8250_do_set_termios; | |
| 478 | − if (quirks & DW_UART_QUIRK_IS_DMA_FC) { | |
| 479 | − data->data.dma.txconf.device_fc = 1; | |
| 480 | − data->data.dma.rxconf.device_fc = 1; | |
| 481 | − data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma; | |
| 482 | − data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma; | |
| 483 | − } | |
| 484 | − | |
| 485 | − } else if (acpi_dev_present("APMC0D08", NULL, -1)) { | |
| 459 | + if (quirks & DW_UART_QUIRK_ARMADA_38X) | |
| 460 | + p->serial_out = dw8250_serial_out38x; | |
| 461 | + if (quirks & DW_UART_QUIRK_SKIP_SET_RATE) | |
| 462 | + p->set_termios = dw8250_do_set_termios; | |
| 463 | + if (quirks & DW_UART_QUIRK_IS_DMA_FC) { | |
| 464 | + data->data.dma.txconf.device_fc = 1; | |
| 465 | + data->data.dma.rxconf.device_fc = 1; | |
| 466 | + data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma; | |
| 467 | + data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma; | |
| 468 | + } | |
| 469 | + if (quirks & DW_UART_QUIRK_APMC0D08) { | |
| 486 | 470 | p->iotype = UPIO_MEM32; |
| 487 | 471 | p->regshift = 2; |
| 488 | 472 | p->serial_in = dw8250_serial_in32; |
| @@ -510,39 +494,21 @@ static int dw8250_probe(struct platform_device *pdev) · 21 unmodified lines | ||
| 510 | 494 | struct device *dev = &pdev->dev; |
| 511 | 495 | struct dw8250_data *data; |
| 512 | 496 | struct resource *regs; |
| 513 | − int irq; | |
| 514 | 497 | int err; |
| 515 | − u32 val; | |
| 516 | 498 | |
| 517 | 499 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 518 | 500 | if (!regs) |
| 519 | 501 | return dev_err_probe(dev, -EINVAL, "no registers defined\n"); |
| 520 | 502 | |
| 521 | − irq = platform_get_irq_optional(pdev, 0); | |
| 522 | − /* no interrupt -> fall back to polling */ | |
| 523 | − if (irq == -ENXIO) | |
| 524 | − irq = 0; | |
| 525 | − if (irq < 0) | |
| 526 | − return irq; | |
| 527 | − | |
| 528 | 503 | spin_lock_init(&p->lock); |
| 529 | − p->mapbase = regs->start; | |
| 530 | − p->irq = irq; | |
| 531 | 504 | p->handle_irq = dw8250_handle_irq; |
| 532 | 505 | p->pm = dw8250_do_pm; |
| 533 | 506 | p->type = PORT_8250; |
| 534 | − p->flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; | |
| 507 | + p->flags = UPF_FIXED_PORT; | |
| 535 | 508 | p->dev = dev; |
| 536 | − p->iotype = UPIO_MEM; | |
| 537 | − p->serial_in = dw8250_serial_in; | |
| 538 | − p->serial_out = dw8250_serial_out; | |
| 539 | 509 | p->set_ldisc = dw8250_set_ldisc; |
| 540 | 510 | p->set_termios = dw8250_set_termios; |
| 541 | 511 | |
| 542 | − p->membase = devm_ioremap(dev, regs->start, resource_size(regs)); | |
| 543 | − if (!p->membase) | |
| 544 | − return -ENOMEM; | |
| 545 | − | |
| 546 | 512 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
| 547 | 513 | if (!data) |
| 548 | 514 | return -ENOMEM; |
| @@ -554,15 +520,35 @@ static int dw8250_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 554 | 520 | data->uart_16550_compatible = device_property_read_bool(dev, |
| 555 | 521 | "snps,uart-16550-compatible"); |
| 556 | 522 | |
| 557 | − err = device_property_read_u32(dev, "reg-shift", &val); | |
| 558 | − if (!err) | |
| 559 | − p->regshift = val; | |
| 523 | + p->mapbase = regs->start; | |
| 524 | + p->mapsize = resource_size(regs); | |
| 560 | 525 | |
| 561 | − err = device_property_read_u32(dev, "reg-io-width", &val); | |
| 562 | − if (!err && val == 4) { | |
| 563 | − p->iotype = UPIO_MEM32; | |
| 526 | + p->membase = devm_ioremap(dev, p->mapbase, p->mapsize); | |
| 527 | + if (!p->membase) | |
| 528 | + return -ENOMEM; | |
| 529 | + | |
| 530 | + err = uart_read_port_properties(p); | |
| 531 | + /* no interrupt -> fall back to polling */ | |
| 532 | + if (err == -ENXIO) | |
| 533 | + err = 0; | |
| 534 | + if (err) | |
| 535 | + return err; | |
| 536 | + | |
| 537 | + switch (p->iotype) { | |
| 538 | + case UPIO_MEM: | |
| 539 | + p->serial_in = dw8250_serial_in; | |
| 540 | + p->serial_out = dw8250_serial_out; | |
| 541 | + break; | |
| 542 | + case UPIO_MEM32: | |
| 564 | 543 | p->serial_in = dw8250_serial_in32; |
| 565 | 544 | p->serial_out = dw8250_serial_out32; |
| 545 | + break; | |
| 546 | + case UPIO_MEM32BE: | |
| 547 | + p->serial_in = dw8250_serial_in32be; | |
| 548 | + p->serial_out = dw8250_serial_out32be; | |
| 549 | + break; | |
| 550 | + default: | |
| 551 | + return -ENODEV; | |
| 566 | 552 | } |
| 567 | 553 | |
| 568 | 554 | if (device_property_read_bool(dev, "dcd-override")) { |
| @@ -589,15 +575,13 @@ static int dw8250_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 589 | 575 | data->msr_mask_off |= UART_MSR_TERI; |
| 590 | 576 | } |
| 591 | 577 | |
| 592 | − /* Always ask for fixed clock rate from a property. */ | |
| 593 | − device_property_read_u32(dev, "clock-frequency", &p->uartclk); | |
| 594 | − | |
| 595 | 578 | /* If there is separate baudclk, get the rate from it. */ |
| 596 | 579 | data->clk = devm_clk_get_optional_enabled(dev, "baudclk"); |
| 597 | 580 | if (data->clk == NULL) |
| 598 | 581 | data->clk = devm_clk_get_optional_enabled(dev, NULL); |
| 599 | 582 | if (IS_ERR(data->clk)) |
| 600 | − return PTR_ERR(data->clk); | |
| 583 | + return dev_err_probe(dev, PTR_ERR(data->clk), | |
| 584 | + "failed to get baudclk\n"); | |
| 601 | 585 | |
| 602 | 586 | INIT_WORK(&data->clk_work, dw8250_clk_work_cb); |
| 603 | 587 | data->clk_notifier.notifier_call = dw8250_clk_notifier_cb; |
| @@ -762,13 +746,18 @@ static const struct of_device_id dw8250_of_match[] = { · 158 unmodified lines | ||
| 762 | 746 | }; |
| 763 | 747 | MODULE_DEVICE_TABLE(of, dw8250_of_match); |
| 764 | 748 | |
| 749 | +static const struct dw8250_platform_data dw8250_apmc0d08 = { | |
| 750 | + .usr_reg = DW_UART_USR, | |
| 751 | + .quirks = DW_UART_QUIRK_APMC0D08, | |
| 752 | +}; | |
| 753 | + | |
| 765 | 754 | static const struct acpi_device_id dw8250_acpi_match[] = { |
| 766 | 755 | { "80860F0A", (kernel_ulong_t)&dw8250_dw_apb }, |
| 767 | 756 | { "8086228A", (kernel_ulong_t)&dw8250_dw_apb }, |
| 768 | 757 | { "AMD0020", (kernel_ulong_t)&dw8250_dw_apb }, |
| 769 | 758 | { "AMDI0020", (kernel_ulong_t)&dw8250_dw_apb }, |
| 770 | 759 | { "AMDI0022", (kernel_ulong_t)&dw8250_dw_apb }, |
| 771 | − { "APMC0D08", (kernel_ulong_t)&dw8250_dw_apb}, | |
| 760 | + { "APMC0D08", (kernel_ulong_t)&dw8250_apmc0d08 }, | |
| 772 | 761 | { "BRCM2032", (kernel_ulong_t)&dw8250_dw_apb }, |
| 773 | 762 | { "HISI0031", (kernel_ulong_t)&dw8250_dw_apb }, |
| 774 | 763 | { "INT33C4", (kernel_ulong_t)&dw8250_dw_apb }, |
| @@ -6,23 +6,29 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved. |
| 8 | 8 | */ |
| 9 | −#include <linux/acpi.h> | |
| 9 | +#include <linux/bits.h> | |
| 10 | +#include <linux/delay.h> | |
| 11 | +#include <linux/device.h> | |
| 10 | 12 | #include <linux/dmi.h> |
| 13 | +#include <linux/interrupt.h> | |
| 11 | 14 | #include <linux/io.h> |
| 12 | −#include <linux/kernel.h> | |
| 15 | +#include <linux/math.h> | |
| 13 | 16 | #include <linux/module.h> |
| 14 | 17 | #include <linux/pci.h> |
| 18 | +#include <linux/platform_device.h> | |
| 19 | +#include <linux/pm.h> | |
| 15 | 20 | #include <linux/property.h> |
| 21 | +#include <linux/string.h> | |
| 22 | +#include <linux/types.h> | |
| 23 | + | |
| 24 | +#include <linux/serial_8250.h> | |
| 16 | 25 | #include <linux/serial_core.h> |
| 17 | 26 | #include <linux/serial_reg.h> |
| 18 | −#include <linux/slab.h> | |
| 19 | −#include <linux/string.h> | |
| 20 | −#include <linux/tty.h> | |
| 21 | −#include <linux/delay.h> | |
| 22 | 27 | |
| 23 | 28 | #include <asm/byteorder.h> |
| 24 | 29 | |
| 25 | 30 | #include "8250.h" |
| 31 | +#include "8250_pcilib.h" | |
| 26 | 32 | |
| 27 | 33 | #define PCI_DEVICE_ID_ACCESSIO_COM_2S 0x1052 |
| 28 | 34 | #define PCI_DEVICE_ID_ACCESSIO_COM_4S 0x105d |
| @@ -229,13 +235,12 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev, · 200 unmodified lines | ||
| 229 | 235 | struct uart_8250_port *port) |
| 230 | 236 | { |
| 231 | 237 | const struct exar8250_board *board = priv->board; |
| 232 | − unsigned int bar = 0; | |
| 233 | 238 | unsigned char status; |
| 239 | + int err; | |
| 234 | 240 | |
| 235 | − port->port.iotype = UPIO_MEM; | |
| 236 | − port->port.mapbase = pci_resource_start(pcidev, bar) + offset; | |
| 237 | − port->port.membase = priv->virt + offset; | |
| 238 | − port->port.regshift = board->reg_shift; | |
| 241 | + err = serial8250_pci_setup_port(pcidev, port, 0, offset, board->reg_shift); | |
| 242 | + if (err) | |
| 243 | + return err; | |
| 239 | 244 | |
| 240 | 245 | /* |
| 241 | 246 | * 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, · 133 unmodified lines | ||
| 375 | 380 | return NULL; |
| 376 | 381 | |
| 377 | 382 | pdev->dev.parent = &pcidev->dev; |
| 378 | − ACPI_COMPANION_SET(&pdev->dev, ACPI_COMPANION(&pcidev->dev)); | |
| 383 | + device_set_node(&pdev->dev, dev_fwnode(&pcidev->dev)); | |
| 379 | 384 | |
| 380 | 385 | if (device_add_software_node(&pdev->dev, node) < 0 || |
| 381 | 386 | platform_device_add(pdev) < 0) { |
| @@ -713,14 +718,14 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) · 331 unmodified lines | ||
| 713 | 718 | uart.port.irq = pci_irq_vector(pcidev, 0); |
| 714 | 719 | uart.port.dev = &pcidev->dev; |
| 715 | 720 | |
| 721 | + /* Clear interrupts */ | |
| 722 | + exar_misc_clear(priv); | |
| 723 | + | |
| 716 | 724 | rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler, |
| 717 | 725 | IRQF_SHARED, "exar_uart", priv); |
| 718 | 726 | if (rc) |
| 719 | 727 | return rc; |
| 720 | 728 | |
| 721 | − /* Clear interrupts */ | |
| 722 | − exar_misc_clear(priv); | |
| 723 | − | |
| 724 | 729 | for (i = 0; i < nr_ports && i < maxnr; i++) { |
| 725 | 730 | rc = board->setup(priv, pcidev, &uart, i); |
| 726 | 731 | if (rc) { |
| @@ -753,28 +758,24 @@ static void exar_pci_remove(struct pci_dev *pcidev) · 26 unmodified lines | ||
| 753 | 758 | for (i = 0; i < priv->nr; i++) |
| 754 | 759 | serial8250_unregister_port(priv->line[i]); |
| 755 | 760 | |
| 761 | + /* Ensure that every init quirk is properly torn down */ | |
| 756 | 762 | if (priv->board->exit) |
| 757 | 763 | priv->board->exit(pcidev); |
| 758 | 764 | } |
| 759 | 765 | |
| 760 | −static int __maybe_unused exar_suspend(struct device *dev) | |
| 766 | +static int exar_suspend(struct device *dev) | |
| 761 | 767 | { |
| 762 | − struct pci_dev *pcidev = to_pci_dev(dev); | |
| 763 | − struct exar8250 *priv = pci_get_drvdata(pcidev); | |
| 768 | + struct exar8250 *priv = dev_get_drvdata(dev); | |
| 764 | 769 | unsigned int i; |
| 765 | 770 | |
| 766 | 771 | for (i = 0; i < priv->nr; i++) |
| 767 | 772 | if (priv->line[i] >= 0) |
| 768 | 773 | serial8250_suspend_port(priv->line[i]); |
| 769 | 774 | |
| 770 | − /* Ensure that every init quirk is properly torn down */ | |
| 771 | − if (priv->board->exit) | |
| 772 | − priv->board->exit(pcidev); | |
| 773 | − | |
| 774 | 775 | return 0; |
| 775 | 776 | } |
| 776 | 777 | |
| 777 | −static int __maybe_unused exar_resume(struct device *dev) | |
| 778 | +static int exar_resume(struct device *dev) | |
| 778 | 779 | { |
| 779 | 780 | struct exar8250 *priv = dev_get_drvdata(dev); |
| 780 | 781 | unsigned int i; |
| @@ -788,7 +789,7 @@ static int __maybe_unused exar_resume(struct device *dev) · 7 unmodified lines | ||
| 788 | 789 | return 0; |
| 789 | 790 | } |
| 790 | 791 | |
| 791 | −static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume); | |
| 792 | +static DEFINE_SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume); | |
| 792 | 793 | |
| 793 | 794 | static const struct exar8250_board pbn_fastcom335_2 = { |
| 794 | 795 | .num_ports = 2, |
| @@ -938,12 +939,13 @@ static struct pci_driver exar_pci_driver = { · 143 unmodified lines | ||
| 938 | 939 | .probe = exar_pci_probe, |
| 939 | 940 | .remove = exar_pci_remove, |
| 940 | 941 | .driver = { |
| 941 | − .pm = &exar_pci_pm, | |
| 942 | + .pm = pm_sleep_ptr(&exar_pci_pm), | |
| 942 | 943 | }, |
| 943 | 944 | .id_table = exar_pci_tbl, |
| 944 | 945 | }; |
| 945 | 946 | module_pci_driver(exar_pci_driver); |
| 946 | 947 | |
| 948 | +MODULE_IMPORT_NS(SERIAL_8250_PCI); | |
| 947 | 949 | MODULE_LICENSE("GPL"); |
| 948 | 950 | MODULE_DESCRIPTION("Exar Serial Driver"); |
| 949 | 951 | MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>"); |
| @@ -234,7 +234,7 @@ static int ingenic_uart_probe(struct platform_device *pdev) · 233 unmodified lines | ||
| 234 | 234 | struct ingenic_uart_data *data; |
| 235 | 235 | const struct ingenic_uart_config *cdata; |
| 236 | 236 | struct resource *regs; |
| 237 | − int irq, err, line; | |
| 237 | + int err; | |
| 238 | 238 | |
| 239 | 239 | cdata = of_device_get_match_data(&pdev->dev); |
| 240 | 240 | if (!cdata) { |
| @@ -242,10 +242,6 @@ static int ingenic_uart_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 242 | 242 | return -ENODEV; |
| 243 | 243 | } |
| 244 | 244 | |
| 245 | − irq = platform_get_irq(pdev, 0); | |
| 246 | − if (irq < 0) | |
| 247 | − return irq; | |
| 248 | − | |
| 249 | 245 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 250 | 246 | if (!regs) { |
| 251 | 247 | dev_err(&pdev->dev, "no registers defined\n"); |
| @@ -259,21 +255,19 @@ static int ingenic_uart_probe(struct platform_device *pdev) · 7 unmodified lines | ||
| 259 | 255 | spin_lock_init(&uart.port.lock); |
| 260 | 256 | uart.port.type = PORT_16550A; |
| 261 | 257 | uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE; |
| 262 | − uart.port.iotype = UPIO_MEM; | |
| 263 | 258 | uart.port.mapbase = regs->start; |
| 264 | − uart.port.regshift = 2; | |
| 265 | 259 | uart.port.serial_out = ingenic_uart_serial_out; |
| 266 | 260 | uart.port.serial_in = ingenic_uart_serial_in; |
| 267 | − uart.port.irq = irq; | |
| 268 | 261 | uart.port.dev = &pdev->dev; |
| 269 | − uart.port.fifosize = cdata->fifosize; | |
| 270 | 262 | uart.tx_loadsz = cdata->tx_loadsz; |
| 271 | 263 | uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE; |
| 272 | 264 | |
| 273 | − /* Check for a fixed line number */ | |
| 274 | − line = of_alias_get_id(pdev->dev.of_node, "serial"); | |
| 275 | − if (line >= 0) | |
| 276 | − uart.port.line = line; | |
| 265 | + err = uart_read_port_properties(&uart.port); | |
| 266 | + if (err) | |
| 267 | + return err; | |
| 268 | + | |
| 269 | + uart.port.regshift = 2; | |
| 270 | + uart.port.fifosize = cdata->fifosize; | |
| 277 | 271 | |
| 278 | 272 | uart.port.membase = devm_ioremap(&pdev->dev, regs->start, |
| 279 | 273 | resource_size(regs)); |
| @@ -92,11 +92,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) · 91 unmodified lines | ||
| 92 | 92 | struct lpc18xx_uart_data *data; |
| 93 | 93 | struct uart_8250_port uart; |
| 94 | 94 | struct resource *res; |
| 95 | − int irq, ret; | |
| 96 | − | |
| 97 | − irq = platform_get_irq(pdev, 0); | |
| 98 | − if (irq < 0) | |
| 99 | − return irq; | |
| 95 | + int ret; | |
| 100 | 96 | |
| 101 | 97 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 102 | 98 | if (!res) { |
| @@ -139,19 +135,12 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) · 36 unmodified lines | ||
| 139 | 135 | goto dis_clk_reg; |
| 140 | 136 | } |
| 141 | 137 | |
| 142 | − ret = of_alias_get_id(pdev->dev.of_node, "serial"); | |
| 143 | − if (ret >= 0) | |
| 144 | − uart.port.line = ret; | |
| 145 | − | |
| 146 | 138 | data->dma.rx_param = data; |
| 147 | 139 | data->dma.tx_param = data; |
| 148 | 140 | |
| 149 | 141 | spin_lock_init(&uart.port.lock); |
| 150 | 142 | uart.port.dev = &pdev->dev; |
| 151 | − uart.port.irq = irq; | |
| 152 | − uart.port.iotype = UPIO_MEM32; | |
| 153 | 143 | uart.port.mapbase = res->start; |
| 154 | − uart.port.regshift = 2; | |
| 155 | 144 | uart.port.type = PORT_16550A; |
| 156 | 145 | uart.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST; |
| 157 | 146 | uart.port.uartclk = clk_get_rate(data->clk_uart); |
| @@ -160,6 +149,13 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 160 | 149 | uart.port.rs485_supported = lpc18xx_rs485_supported; |
| 161 | 150 | uart.port.serial_out = lpc18xx_uart_serial_out; |
| 162 | 151 | |
| 152 | + ret = uart_read_port_properties(&uart.port); | |
| 153 | + if (ret) | |
| 154 | + return ret; | |
| 155 | + | |
| 156 | + uart.port.iotype = UPIO_MEM32; | |
| 157 | + uart.port.regshift = 2; | |
| 158 | + | |
| 163 | 159 | uart.dma = &data->dma; |
| 164 | 160 | uart.dma->rxconf.src_maxburst = 1; |
| 165 | 161 | uart.dma->txconf.dst_maxburst = 1; |
| @@ -4,7 +4,10 @@ · 3 unmodified lines | ||
| 4 | 4 | * |
| 5 | 5 | * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp. |
| 6 | 6 | */ |
| 7 | + | |
| 8 | +#include <linux/bits.h> | |
| 7 | 9 | #include <linux/console.h> |
| 10 | +#include <linux/math.h> | |
| 8 | 11 | #include <linux/module.h> |
| 9 | 12 | #include <linux/slab.h> |
| 10 | 13 | #include <linux/serial_core.h> |
| @@ -25,6 +28,36 @@ struct of_serial_info { · 14 unmodified lines | ||
| 25 | 28 | int line; |
| 26 | 29 | }; |
| 27 | 30 | |
| 31 | +/* Nuvoton NPCM timeout register */ | |
| 32 | +#define UART_NPCM_TOR 7 | |
| 33 | +#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */ | |
| 34 | + | |
| 35 | +static int npcm_startup(struct uart_port *port) | |
| 36 | +{ | |
| 37 | + /* | |
| 38 | + * Nuvoton calls the scratch register 'UART_TOR' (timeout | |
| 39 | + * register). Enable it, and set TIOC (timeout interrupt | |
| 40 | + * comparator) to be 0x20 for correct operation. | |
| 41 | + */ | |
| 42 | + serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20); | |
| 43 | + | |
| 44 | + return serial8250_do_startup(port); | |
| 45 | +} | |
| 46 | + | |
| 47 | +/* Nuvoton NPCM UARTs have a custom divisor calculation */ | |
| 48 | +static unsigned int npcm_get_divisor(struct uart_port *port, unsigned int baud, | |
| 49 | + unsigned int *frac) | |
| 50 | +{ | |
| 51 | + return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2; | |
| 52 | +} | |
| 53 | + | |
| 54 | +static int npcm_setup(struct uart_port *port) | |
| 55 | +{ | |
| 56 | + port->get_divisor = npcm_get_divisor; | |
| 57 | + port->startup = npcm_startup; | |
| 58 | + return 0; | |
| 59 | +} | |
| 60 | + | |
| 28 | 61 | /* |
| 29 | 62 | * Fill a struct uart_port for a given device node |
| 30 | 63 | */ |
| @@ -36,37 +69,22 @@ static int of_platform_serial_setup(struct platform_device *ofdev, · 5 unmodified lines | ||
| 36 | 69 | struct device *dev = &ofdev->dev; |
| 37 | 70 | struct device_node *np = dev->of_node; |
| 38 | 71 | struct uart_port *port = &up->port; |
| 39 | − u32 clk, spd, prop; | |
| 40 | − int ret, irq; | |
| 72 | + u32 spd; | |
| 73 | + int ret; | |
| 41 | 74 | |
| 42 | 75 | memset(port, 0, sizeof *port); |
| 43 | 76 | |
| 44 | 77 | pm_runtime_enable(&ofdev->dev); |
| 45 | 78 | pm_runtime_get_sync(&ofdev->dev); |
| 46 | 79 | |
| 47 | − if (of_property_read_u32(np, "clock-frequency", &clk)) { | |
| 48 | − | |
| 49 | − /* Get clk rate through clk driver if present */ | |
| 50 | − info->clk = devm_clk_get_enabled(dev, NULL); | |
| 51 | − if (IS_ERR(info->clk)) { | |
| 52 | − ret = dev_err_probe(dev, PTR_ERR(info->clk), "failed to get clock\n"); | |
| 53 | − goto err_pmruntime; | |
| 54 | − } | |
| 55 | − | |
| 56 | − clk = clk_get_rate(info->clk); | |
| 57 | − } | |
| 58 | − /* If current-speed was set, then try not to change it. */ | |
| 59 | − if (of_property_read_u32(np, "current-speed", &spd) == 0) | |
| 60 | − port->custom_divisor = clk / (16 * spd); | |
| 61 | − | |
| 62 | 80 | ret = of_address_to_resource(np, 0, &resource); |
| 63 | 81 | if (ret) { |
| 64 | 82 | dev_err_probe(dev, ret, "invalid address\n"); |
| 65 | 83 | goto err_pmruntime; |
| 66 | 84 | } |
| 67 | 85 | |
| 68 | − port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | | |
| 69 | − UPF_FIXED_TYPE; | |
| 86 | + port->dev = &ofdev->dev; | |
| 87 | + port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE; | |
| 70 | 88 | spin_lock_init(&port->lock); |
| 71 | 89 | |
| 72 | 90 | if (resource_type(&resource) == IORESOURCE_IO) { |
| @@ -75,70 +93,31 @@ static int of_platform_serial_setup(struct platform_device *ofdev, · 2 unmodified lines | ||
| 75 | 93 | } else { |
| 76 | 94 | port->mapbase = resource.start; |
| 77 | 95 | port->mapsize = resource_size(&resource); |
| 96 | + port->flags |= UPF_IOREMAP; | |
| 97 | + } | |
| 78 | 98 | |
| 79 | − /* Check for shifted address mapping */ | |
| 80 | − if (of_property_read_u32(np, "reg-offset", &prop) == 0) { | |
| 81 | − if (prop >= port->mapsize) { | |
| 82 | − ret = dev_err_probe(dev, -EINVAL, "reg-offset %u exceeds region size %pa\n", | |
| 83 | − prop, &port->mapsize); | |
| 84 | − goto err_pmruntime; | |
| 85 | − } | |
| 99 | + ret = uart_read_and_validate_port_properties(port); | |
| 100 | + if (ret) | |
| 101 | + goto err_pmruntime; | |
| 86 | 102 | |
| 87 | − port->mapbase += prop; | |
| 88 | − port->mapsize -= prop; | |
| 103 | + /* Get clk rate through clk driver if present */ | |
| 104 | + if (!port->uartclk) { | |
| 105 | + info->clk = devm_clk_get_enabled(dev, NULL); | |
| 106 | + if (IS_ERR(info->clk)) { | |
| 107 | + ret = dev_err_probe(dev, PTR_ERR(info->clk), "failed to get clock\n"); | |
| 108 | + goto err_pmruntime; | |
| 89 | 109 | } |
| 90 | 110 | |
| 91 | − port->iotype = UPIO_MEM; | |
| 92 | − if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { | |
| 93 | − switch (prop) { | |
| 94 | − case 1: | |
| 95 | − port->iotype = UPIO_MEM; | |
| 96 | − break; | |
| 97 | − case 2: | |
| 98 | − port->iotype = UPIO_MEM16; | |
| 99 | − break; | |
| 100 | − case 4: | |
| 101 | − port->iotype = of_device_is_big_endian(np) ? | |
| 102 | − UPIO_MEM32BE : UPIO_MEM32; | |
| 103 | − break; | |
| 104 | − default: | |
| 105 | − ret = dev_err_probe(dev, -EINVAL, "unsupported reg-io-width (%u)\n", | |
| 106 | − prop); | |
| 107 | − goto err_pmruntime; | |
| 108 | − } | |
| 109 | − } | |
| 110 | − port->flags |= UPF_IOREMAP; | |
| 111 | + port->uartclk = clk_get_rate(info->clk); | |
| 111 | 112 | } |
| 113 | + /* If current-speed was set, then try not to change it. */ | |
| 114 | + if (of_property_read_u32(np, "current-speed", &spd) == 0) | |
| 115 | + port->custom_divisor = port->uartclk / (16 * spd); | |
| 112 | 116 | |
| 113 | 117 | /* Compatibility with the deprecated pxa driver and 8250_pxa drivers. */ |
| 114 | 118 | if (of_device_is_compatible(np, "mrvl,mmp-uart")) |
| 115 | 119 | port->regshift = 2; |
| 116 | 120 | |
| 117 | − /* Check for registers offset within the devices address range */ | |
| 118 | − if (of_property_read_u32(np, "reg-shift", &prop) == 0) | |
| 119 | − port->regshift = prop; | |
| 120 | − | |
| 121 | − /* Check for fifo size */ | |
| 122 | − if (of_property_read_u32(np, "fifo-size", &prop) == 0) | |
| 123 | − port->fifosize = prop; | |
| 124 | − | |
| 125 | − /* Check for a fixed line number */ | |
| 126 | − ret = of_alias_get_id(np, "serial"); | |
| 127 | − if (ret >= 0) | |
| 128 | − port->line = ret; | |
| 129 | − | |
| 130 | − irq = of_irq_get(np, 0); | |
| 131 | − if (irq < 0) { | |
| 132 | − if (irq == -EPROBE_DEFER) { | |
| 133 | − ret = -EPROBE_DEFER; | |
| 134 | − goto err_pmruntime; | |
| 135 | − } | |
| 136 | − /* IRQ support not mandatory */ | |
| 137 | − irq = 0; | |
| 138 | − } | |
| 139 | − | |
| 140 | − port->irq = irq; | |
| 141 | − | |
| 142 | 121 | info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL); |
| 143 | 122 | if (IS_ERR(info->rst)) { |
| 144 | 123 | ret = PTR_ERR(info->rst); |
| @@ -150,12 +129,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev, · 5 unmodified lines | ||
| 150 | 129 | goto err_pmruntime; |
| 151 | 130 | |
| 152 | 131 | port->type = type; |
| 153 | − port->uartclk = clk; | |
| 154 | − | |
| 155 | − if (of_property_read_bool(np, "no-loopback-test")) | |
| 156 | − port->flags |= UPF_SKIP_TEST; | |
| 157 | − | |
| 158 | − port->dev = &ofdev->dev; | |
| 159 | 132 | port->rs485_config = serial8250_em485_config; |
| 160 | 133 | port->rs485_supported = serial8250_em485_supported; |
| 161 | 134 | up->rs485_start_tx = serial8250_em485_start_tx; |
| @@ -164,10 +137,17 @@ static int of_platform_serial_setup(struct platform_device *ofdev, · 2 unmodified lines | ||
| 164 | 137 | switch (type) { |
| 165 | 138 | case PORT_RT2880: |
| 166 | 139 | ret = rt288x_setup(port); |
| 167 | − if (ret) | |
| 168 | − goto err_pmruntime; | |
| 140 | + break; | |
| 141 | + case PORT_NPCM: | |
| 142 | + ret = npcm_setup(port); | |
| 143 | + break; | |
| 144 | + default: | |
| 145 | + /* Nothing to do */ | |
| 146 | + ret = 0; | |
| 169 | 147 | break; |
| 170 | 148 | } |
| 149 | + if (ret) | |
| 150 | + goto err_pmruntime; | |
| 171 | 151 | |
| 172 | 152 | if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL) && |
| 173 | 153 | (of_device_is_compatible(np, "fsl,ns16550") || |
| @@ -240,7 +220,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev) · 66 unmodified lines | ||
| 240 | 220 | platform_set_drvdata(ofdev, info); |
| 241 | 221 | return 0; |
| 242 | 222 | err_dispose: |
| 243 | − irq_dispose_mapping(port8250.port.irq); | |
| 244 | 223 | pm_runtime_put_sync(&ofdev->dev); |
| 245 | 224 | pm_runtime_disable(&ofdev->dev); |
| 246 | 225 | err_free: |
| @@ -1394,11 +1394,7 @@ static int omap8250_probe(struct platform_device *pdev) · 1393 unmodified lines | ||
| 1394 | 1394 | struct uart_8250_port up; |
| 1395 | 1395 | struct resource *regs; |
| 1396 | 1396 | void __iomem *membase; |
| 1397 | − int irq, ret; | |
| 1398 | − | |
| 1399 | − irq = platform_get_irq(pdev, 0); | |
| 1400 | − if (irq < 0) | |
| 1401 | − return irq; | |
| 1397 | + int ret; | |
| 1402 | 1398 | |
| 1403 | 1399 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1404 | 1400 | if (!regs) { |
| @@ -1419,7 +1415,6 @@ static int omap8250_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 1419 | 1415 | up.port.dev = &pdev->dev; |
| 1420 | 1416 | up.port.mapbase = regs->start; |
| 1421 | 1417 | up.port.membase = membase; |
| 1422 | − up.port.irq = irq; | |
| 1423 | 1418 | /* |
| 1424 | 1419 | * It claims to be 16C750 compatible however it is a little different. |
| 1425 | 1420 | * 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) · 3 unmodified lines | ||
| 1429 | 1424 | * or pm callback. |
| 1430 | 1425 | */ |
| 1431 | 1426 | up.port.type = PORT_8250; |
| 1432 | − up.port.iotype = UPIO_MEM; | |
| 1433 | − up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | | |
| 1434 | − UPF_HARD_FLOW; | |
| 1427 | + up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | UPF_HARD_FLOW; | |
| 1435 | 1428 | up.port.private_data = priv; |
| 1436 | 1429 | |
| 1437 | − up.port.regshift = OMAP_UART_REGSHIFT; | |
| 1438 | − up.port.fifosize = 64; | |
| 1439 | 1430 | up.tx_loadsz = 64; |
| 1440 | 1431 | up.capabilities = UART_CAP_FIFO; |
| 1441 | 1432 | #ifdef CONFIG_PM |
| @@ -1461,14 +1452,14 @@ static int omap8250_probe(struct platform_device *pdev) · 19 unmodified lines | ||
| 1461 | 1452 | up.rs485_stop_tx = serial8250_em485_stop_tx; |
| 1462 | 1453 | up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); |
| 1463 | 1454 | |
| 1464 | − ret = of_alias_get_id(np, "serial"); | |
| 1465 | − if (ret < 0) { | |
| 1466 | − dev_err(&pdev->dev, "failed to get alias\n"); | |
| 1455 | + ret = uart_read_port_properties(&up.port); | |
| 1456 | + if (ret) | |
| 1467 | 1457 | return ret; |
| 1468 | − } | |
| 1469 | − up.port.line = ret; | |
| 1470 | 1458 | |
| 1471 | − if (of_property_read_u32(np, "clock-frequency", &up.port.uartclk)) { | |
| 1459 | + up.port.regshift = OMAP_UART_REGSHIFT; | |
| 1460 | + up.port.fifosize = 64; | |
| 1461 | + | |
| 1462 | + if (!up.port.uartclk) { | |
| 1472 | 1463 | struct clk *clk; |
| 1473 | 1464 | |
| 1474 | 1465 | clk = devm_clk_get(&pdev->dev, NULL); |
| @@ -1560,8 +1551,8 @@ static int omap8250_probe(struct platform_device *pdev) · 85 unmodified lines | ||
| 1560 | 1551 | } |
| 1561 | 1552 | #endif |
| 1562 | 1553 | |
| 1563 | − irq_set_status_flags(irq, IRQ_NOAUTOEN); | |
| 1564 | − ret = devm_request_irq(&pdev->dev, irq, omap8250_irq, 0, | |
| 1554 | + irq_set_status_flags(up.port.irq, IRQ_NOAUTOEN); | |
| 1555 | + ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0, | |
| 1565 | 1556 | dev_name(&pdev->dev), priv); |
| 1566 | 1557 | if (ret < 0) |
| 1567 | 1558 | return ret; |
| @@ -7,23 +7,31 @@ · 6 unmodified lines | ||
| 7 | 7 | * Copyright (C) 2022 Microchip Technology Inc., All Rights Reserved. |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | +#include <linux/array_size.h> | |
| 10 | 11 | #include <linux/bitfield.h> |
| 11 | −#include <linux/bitops.h> | |
| 12 | −#include <linux/delay.h> | |
| 12 | +#include <linux/bits.h> | |
| 13 | +#include <linux/circ_buf.h> | |
| 14 | +#include <linux/device.h> | |
| 15 | +#include <linux/errno.h> | |
| 16 | +#include <linux/gfp_types.h> | |
| 13 | 17 | #include <linux/io.h> |
| 14 | 18 | #include <linux/iopoll.h> |
| 15 | −#include <linux/kernel.h> | |
| 19 | +#include <linux/minmax.h> | |
| 16 | 20 | #include <linux/module.h> |
| 21 | +#include <linux/mutex.h> | |
| 22 | +#include <linux/overflow.h> | |
| 17 | 23 | #include <linux/pci.h> |
| 24 | +#include <linux/pm.h> | |
| 18 | 25 | #include <linux/serial_core.h> |
| 19 | 26 | #include <linux/serial_reg.h> |
| 20 | 27 | #include <linux/serial_8250.h> |
| 21 | −#include <linux/slab.h> | |
| 28 | +#include <linux/spinlock.h> | |
| 22 | 29 | #include <linux/string.h> |
| 23 | −#include <linux/units.h> | |
| 30 | +#include <linux/time.h> | |
| 24 | 31 | #include <linux/tty.h> |
| 25 | 32 | #include <linux/tty_flip.h> |
| 26 | −#include <linux/8250_pci.h> | |
| 33 | +#include <linux/types.h> | |
| 34 | +#include <linux/units.h> | |
| 27 | 35 | |
| 28 | 36 | #include <asm/byteorder.h> |
| 29 | 37 | |
| @@ -67,6 +75,7 @@ · 37 unmodified lines | ||
| 67 | 75 | #define SYSLOCK_RETRY_CNT 1000 |
| 68 | 76 | |
| 69 | 77 | #define UART_RX_BYTE_FIFO 0x00 |
| 78 | +#define UART_TX_BYTE_FIFO 0x00 | |
| 70 | 79 | #define UART_FIFO_CTL 0x02 |
| 71 | 80 | |
| 72 | 81 | #define UART_ACTV_REG 0x11 |
| @@ -81,10 +90,10 @@ · 8 unmodified lines | ||
| 81 | 90 | #define ADCL_CFG_PIN_SEL BIT(1) |
| 82 | 91 | #define ADCL_CFG_EN BIT(0) |
| 83 | 92 | |
| 84 | −#define UART_BIT_SAMPLE_CNT 16 | |
| 93 | +#define UART_BIT_SAMPLE_CNT_8 8 | |
| 94 | +#define UART_BIT_SAMPLE_CNT_16 16 | |
| 85 | 95 | #define BAUD_CLOCK_DIV_INT_MSK GENMASK(31, 8) |
| 86 | 96 | #define ADCL_CFG_RTS_DELAY_MASK GENMASK(11, 8) |
| 87 | −#define UART_CLOCK_DEFAULT (62500 * HZ_PER_KHZ) | |
| 88 | 97 | |
| 89 | 98 | #define UART_WAKE_REG 0x8C |
| 90 | 99 | #define UART_WAKE_MASK_REG 0x90 |
| @@ -95,13 +104,19 @@ · 4 unmodified lines | ||
| 95 | 104 | (UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT) |
| 96 | 105 | |
| 97 | 106 | #define UART_BAUD_CLK_DIVISOR_REG 0x54 |
| 107 | +#define FRAC_DIV_CFG_REG 0x58 | |
| 98 | 108 | |
| 99 | 109 | #define UART_RESET_REG 0x94 |
| 100 | 110 | #define UART_RESET_D3_RESET_DISABLE BIT(16) |
| 101 | 111 | |
| 102 | 112 | #define UART_BURST_STATUS_REG 0x9C |
| 113 | +#define UART_TX_BURST_FIFO 0xA0 | |
| 103 | 114 | #define UART_RX_BURST_FIFO 0xA4 |
| 104 | 115 | |
| 116 | +#define UART_BIT_DIVISOR_8 0x26731000 | |
| 117 | +#define UART_BIT_DIVISOR_16 0x6ef71000 | |
| 118 | +#define UART_BAUD_4MBPS 4000000 | |
| 119 | + | |
| 105 | 120 | #define MAX_PORTS 4 |
| 106 | 121 | #define PORT_OFFSET 0x100 |
| 107 | 122 | #define RX_BUF_SIZE 512 |
| @@ -109,6 +124,7 @@ · 1 unmodified line | ||
| 109 | 124 | #define UART_BURST_SIZE 4 |
| 110 | 125 | |
| 111 | 126 | #define UART_BST_STAT_RX_COUNT_MASK 0x00FF |
| 127 | +#define UART_BST_STAT_TX_COUNT_MASK 0xFF00 | |
| 112 | 128 | #define UART_BST_STAT_IIR_INT_PEND 0x100000 |
| 113 | 129 | #define UART_LSR_OVERRUN_ERR_CLR 0x43 |
| 114 | 130 | #define UART_BST_STAT_LSR_RX_MASK 0x9F000000 |
| @@ -116,6 +132,7 @@ · 1 unmodified line | ||
| 116 | 132 | #define UART_BST_STAT_LSR_OVERRUN_ERR 0x2000000 |
| 117 | 133 | #define UART_BST_STAT_LSR_PARITY_ERR 0x4000000 |
| 118 | 134 | #define UART_BST_STAT_LSR_FRAME_ERR 0x8000000 |
| 135 | +#define UART_BST_STAT_LSR_THRE 0x20000000 | |
| 119 | 136 | |
| 120 | 137 | struct pci1xxxx_8250 { |
| 121 | 138 | unsigned int nr; |
| @@ -206,15 +223,21 @@ static int pci1xxxx_get_num_ports(struct pci_dev *dev) · 84 unmodified lines | ||
| 206 | 223 | static unsigned int pci1xxxx_get_divisor(struct uart_port *port, |
| 207 | 224 | unsigned int baud, unsigned int *frac) |
| 208 | 225 | { |
| 226 | + unsigned int uart_sample_cnt; | |
| 209 | 227 | unsigned int quot; |
| 210 | 228 | |
| 229 | + if (baud >= UART_BAUD_4MBPS) | |
| 230 | + uart_sample_cnt = UART_BIT_SAMPLE_CNT_8; | |
| 231 | + else | |
| 232 | + uart_sample_cnt = UART_BIT_SAMPLE_CNT_16; | |
| 233 | + | |
| 211 | 234 | /* |
| 212 | 235 | * Calculate baud rate sampling period in nanoseconds. |
| 213 | 236 | * Fractional part x denotes x/255 parts of a nanosecond. |
| 214 | 237 | */ |
| 215 | − quot = NSEC_PER_SEC / (baud * UART_BIT_SAMPLE_CNT); | |
| 216 | − *frac = (NSEC_PER_SEC - quot * baud * UART_BIT_SAMPLE_CNT) * | |
| 217 | − 255 / UART_BIT_SAMPLE_CNT / baud; | |
| 238 | + quot = NSEC_PER_SEC / (baud * uart_sample_cnt); | |
| 239 | + *frac = (NSEC_PER_SEC - quot * baud * uart_sample_cnt) * | |
| 240 | + 255 / uart_sample_cnt / baud; | |
| 218 | 241 | |
| 219 | 242 | return quot; |
| 220 | 243 | } |
| @@ -222,6 +245,11 @@ static unsigned int pci1xxxx_get_divisor(struct uart_port *port, · 1 unmodified line | ||
| 222 | 245 | static void pci1xxxx_set_divisor(struct uart_port *port, unsigned int baud, |
| 223 | 246 | unsigned int quot, unsigned int frac) |
| 224 | 247 | { |
| 248 | + if (baud >= UART_BAUD_4MBPS) | |
| 249 | + writel(UART_BIT_DIVISOR_8, port->membase + FRAC_DIV_CFG_REG); | |
| 250 | + else | |
| 251 | + writel(UART_BIT_DIVISOR_16, port->membase + FRAC_DIV_CFG_REG); | |
| 252 | + | |
| 225 | 253 | writel(FIELD_PREP(BAUD_CLOCK_DIV_INT_MSK, quot) | frac, |
| 226 | 254 | port->membase + UART_BAUD_CLK_DIVISOR_REG); |
| 227 | 255 | } |
| @@ -233,7 +261,16 @@ static int pci1xxxx_rs485_config(struct uart_port *port, · 5 unmodified lines | ||
| 233 | 261 | u32 delay_in_baud_periods; |
| 234 | 262 | u32 baud_period_in_ns; |
| 235 | 263 | u32 mode_cfg = 0; |
| 264 | + u32 sample_cnt; | |
| 236 | 265 | u32 clock_div; |
| 266 | + u32 frac_div; | |
| 267 | + | |
| 268 | + frac_div = readl(port->membase + FRAC_DIV_CFG_REG); | |
| 269 | + | |
| 270 | + if (frac_div == UART_BIT_DIVISOR_16) | |
| 271 | + sample_cnt = UART_BIT_SAMPLE_CNT_16; | |
| 272 | + else | |
| 273 | + sample_cnt = UART_BIT_SAMPLE_CNT_8; | |
| 237 | 274 | |
| 238 | 275 | /* |
| 239 | 276 | * pci1xxxx's uart hardware supports only RTS delay after |
| @@ -249,7 +286,7 @@ static int pci1xxxx_rs485_config(struct uart_port *port, · 9 unmodified lines | ||
| 249 | 286 | clock_div = readl(port->membase + UART_BAUD_CLK_DIVISOR_REG); |
| 250 | 287 | baud_period_in_ns = |
| 251 | 288 | FIELD_GET(BAUD_CLOCK_DIV_INT_MSK, clock_div) * |
| 252 | − UART_BIT_SAMPLE_CNT; | |
| 289 | + sample_cnt; | |
| 253 | 290 | delay_in_baud_periods = |
| 254 | 291 | rs485->delay_rts_after_send * NSEC_PER_MSEC / |
| 255 | 292 | baud_period_in_ns; |
| @@ -344,6 +381,105 @@ static void pci1xxxx_rx_burst(struct uart_port *port, u32 uart_status) · 88 unmodified lines | ||
| 344 | 381 | } |
| 345 | 382 | } |
| 346 | 383 | |
| 384 | +static void pci1xxxx_process_write_data(struct uart_port *port, | |
| 385 | + struct circ_buf *xmit, | |
| 386 | + int *data_empty_count, | |
| 387 | + u32 *valid_byte_count) | |
| 388 | +{ | |
| 389 | + u32 valid_burst_count = *valid_byte_count / UART_BURST_SIZE; | |
| 390 | + | |
| 391 | + /* | |
| 392 | + * Each transaction transfers data in DWORDs. If there are less than | |
| 393 | + * four remaining valid_byte_count to transfer or if the circular | |
| 394 | + * buffer has insufficient space for a DWORD, the data is transferred | |
| 395 | + * one byte at a time. | |
| 396 | + */ | |
| 397 | + while (valid_burst_count) { | |
| 398 | + if (*data_empty_count - UART_BURST_SIZE < 0) | |
| 399 | + break; | |
| 400 | + if (xmit->tail > (UART_XMIT_SIZE - UART_BURST_SIZE)) | |
| 401 | + break; | |
| 402 | + writel(*(unsigned int *)&xmit->buf[xmit->tail], | |
| 403 | + port->membase + UART_TX_BURST_FIFO); | |
| 404 | + *valid_byte_count -= UART_BURST_SIZE; | |
| 405 | + *data_empty_count -= UART_BURST_SIZE; | |
| 406 | + valid_burst_count -= UART_BYTE_SIZE; | |
| 407 | + | |
| 408 | + xmit->tail = (xmit->tail + UART_BURST_SIZE) & | |
| 409 | + (UART_XMIT_SIZE - 1); | |
| 410 | + } | |
| 411 | + | |
| 412 | + while (*valid_byte_count) { | |
| 413 | + if (*data_empty_count - UART_BYTE_SIZE < 0) | |
| 414 | + break; | |
| 415 | + writeb(xmit->buf[xmit->tail], port->membase + | |
| 416 | + UART_TX_BYTE_FIFO); | |
| 417 | + *data_empty_count -= UART_BYTE_SIZE; | |
| 418 | + *valid_byte_count -= UART_BYTE_SIZE; | |
| 419 | + | |
| 420 | + /* | |
| 421 | + * When the tail of the circular buffer is reached, the next | |
| 422 | + * byte is transferred to the beginning of the buffer. | |
| 423 | + */ | |
| 424 | + xmit->tail = (xmit->tail + UART_BYTE_SIZE) & | |
| 425 | + (UART_XMIT_SIZE - 1); | |
| 426 | + | |
| 427 | + /* | |
| 428 | + * If there are any pending burst count, data is handled by | |
| 429 | + * transmitting DWORDs at a time. | |
| 430 | + */ | |
| 431 | + if (valid_burst_count && (xmit->tail < | |
| 432 | + (UART_XMIT_SIZE - UART_BURST_SIZE))) | |
| 433 | + break; | |
| 434 | + } | |
| 435 | +} | |
| 436 | + | |
| 437 | +static void pci1xxxx_tx_burst(struct uart_port *port, u32 uart_status) | |
| 438 | +{ | |
| 439 | + struct uart_8250_port *up = up_to_u8250p(port); | |
| 440 | + u32 valid_byte_count; | |
| 441 | + int data_empty_count; | |
| 442 | + struct circ_buf *xmit; | |
| 443 | + | |
| 444 | + xmit = &port->state->xmit; | |
| 445 | + | |
| 446 | + if (port->x_char) { | |
| 447 | + writeb(port->x_char, port->membase + UART_TX); | |
| 448 | + port->icount.tx++; | |
| 449 | + port->x_char = 0; | |
| 450 | + return; | |
| 451 | + } | |
| 452 | + | |
| 453 | + if ((uart_tx_stopped(port)) || (uart_circ_empty(xmit))) { | |
| 454 | + port->ops->stop_tx(port); | |
| 455 | + } else { | |
| 456 | + data_empty_count = (pci1xxxx_read_burst_status(port) & | |
| 457 | + UART_BST_STAT_TX_COUNT_MASK) >> 8; | |
| 458 | + do { | |
| 459 | + valid_byte_count = uart_circ_chars_pending(xmit); | |
| 460 | + | |
| 461 | + pci1xxxx_process_write_data(port, xmit, | |
| 462 | + &data_empty_count, | |
| 463 | + &valid_byte_count); | |
| 464 | + | |
| 465 | + port->icount.tx++; | |
| 466 | + if (uart_circ_empty(xmit)) | |
| 467 | + break; | |
| 468 | + } while (data_empty_count && valid_byte_count); | |
| 469 | + } | |
| 470 | + | |
| 471 | + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | |
| 472 | + uart_write_wakeup(port); | |
| 473 | + | |
| 474 | + /* | |
| 475 | + * With RPM enabled, we have to wait until the FIFO is empty before | |
| 476 | + * the HW can go idle. So we get here once again with empty FIFO and | |
| 477 | + * disable the interrupt and RPM in __stop_tx() | |
| 478 | + */ | |
| 479 | + if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM)) | |
| 480 | + port->ops->stop_tx(port); | |
| 481 | +} | |
| 482 | + | |
| 347 | 483 | static int pci1xxxx_handle_irq(struct uart_port *port) |
| 348 | 484 | { |
| 349 | 485 | unsigned long flags; |
| @@ -359,6 +495,9 @@ static int pci1xxxx_handle_irq(struct uart_port *port) · 9 unmodified lines | ||
| 359 | 495 | if (status & UART_BST_STAT_LSR_RX_MASK) |
| 360 | 496 | pci1xxxx_rx_burst(port, status); |
| 361 | 497 | |
| 498 | + if (status & UART_BST_STAT_LSR_THRE) | |
| 499 | + pci1xxxx_tx_burst(port, status); | |
| 500 | + | |
| 362 | 501 | spin_unlock_irqrestore(&port->lock, flags); |
| 363 | 502 | |
| 364 | 503 | return 1; |
| @@ -481,6 +620,17 @@ static int pci1xxxx_setup(struct pci_dev *pdev, · 116 unmodified lines | ||
| 481 | 620 | |
| 482 | 621 | port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST; |
| 483 | 622 | port->port.type = PORT_MCHP16550A; |
| 623 | + /* | |
| 624 | + * 8250 core considers prescaller value to be always 16. | |
| 625 | + * The MCHP ports support downscaled mode and hence the | |
| 626 | + * functional UART clock can be lower, i.e. 62.5MHz, than | |
| 627 | + * software expects in order to support higher baud rates. | |
| 628 | + * Assign here 64MHz to support 4Mbps. | |
| 629 | + * | |
| 630 | + * The value itself is not really used anywhere except baud | |
| 631 | + * rate calculations, so we can mangle it as we wish. | |
| 632 | + */ | |
| 633 | + port->port.uartclk = 64 * HZ_PER_MHZ; | |
| 484 | 634 | port->port.set_termios = serial8250_do_set_termios; |
| 485 | 635 | port->port.get_divisor = pci1xxxx_get_divisor; |
| 486 | 636 | port->port.set_divisor = pci1xxxx_set_divisor; |
| @@ -594,7 +744,6 @@ static int pci1xxxx_serial_probe(struct pci_dev *pdev, · 107 unmodified lines | ||
| 594 | 744 | |
| 595 | 745 | memset(&uart, 0, sizeof(uart)); |
| 596 | 746 | uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; |
| 597 | − uart.port.uartclk = UART_CLOCK_DEFAULT; | |
| 598 | 747 | uart.port.dev = dev; |
| 599 | 748 | |
| 600 | 749 | if (num_vectors == max_vec_reqd) |
| @@ -38,10 +38,6 @@ · 37 unmodified lines | ||
| 38 | 38 | |
| 39 | 39 | #include "8250.h" |
| 40 | 40 | |
| 41 | −/* Nuvoton NPCM timeout register */ | |
| 42 | −#define UART_NPCM_TOR 7 | |
| 43 | −#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */ | |
| 44 | − | |
| 45 | 41 | /* |
| 46 | 42 | * Debugging. |
| 47 | 43 | */ |
| @@ -1329,9 +1325,6 @@ static void autoconfig_irq(struct uart_8250_port *up) · 1281 unmodified lines | ||
| 1329 | 1325 | inb_p(ICP); |
| 1330 | 1326 | } |
| 1331 | 1327 | |
| 1332 | − if (uart_console(port)) | |
| 1333 | − console_lock(); | |
| 1334 | − | |
| 1335 | 1328 | /* forget possible initially masked and pending IRQ */ |
| 1336 | 1329 | probe_irq_off(probe_irq_on()); |
| 1337 | 1330 | save_mcr = serial8250_in_MCR(up); |
| @@ -1371,9 +1364,6 @@ static void autoconfig_irq(struct uart_8250_port *up) · 33 unmodified lines | ||
| 1371 | 1364 | if (port->flags & UPF_FOURPORT) |
| 1372 | 1365 | outb_p(save_ICP, ICP); |
| 1373 | 1366 | |
| 1374 | − if (uart_console(port)) | |
| 1375 | − console_unlock(); | |
| 1376 | − | |
| 1377 | 1367 | port->irq = (irq > 0) ? irq : 0; |
| 1378 | 1368 | } |
| 1379 | 1369 | |
| @@ -2235,15 +2225,6 @@ int serial8250_do_startup(struct uart_port *port) · 855 unmodified lines | ||
| 2235 | 2225 | UART_DA830_PWREMU_MGMT_FREE); |
| 2236 | 2226 | } |
| 2237 | 2227 | |
| 2238 | − if (port->type == PORT_NPCM) { | |
| 2239 | − /* | |
| 2240 | − * Nuvoton calls the scratch register 'UART_TOR' (timeout | |
| 2241 | − * register). Enable it, and set TIOC (timeout interrupt | |
| 2242 | − * comparator) to be 0x20 for correct operation. | |
| 2243 | − */ | |
| 2244 | − serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20); | |
| 2245 | − } | |
| 2246 | − | |
| 2247 | 2228 | #ifdef CONFIG_SERIAL_8250_RSA |
| 2248 | 2229 | /* |
| 2249 | 2230 | * 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) · 295 unmodified lines | ||
| 2545 | 2526 | serial8250_do_shutdown(port); |
| 2546 | 2527 | } |
| 2547 | 2528 | |
| 2548 | −/* Nuvoton NPCM UARTs have a custom divisor calculation */ | |
| 2549 | −static unsigned int npcm_get_divisor(struct uart_8250_port *up, | |
| 2550 | − unsigned int baud) | |
| 2551 | −{ | |
| 2552 | − struct uart_port *port = &up->port; | |
| 2553 | − | |
| 2554 | − return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2; | |
| 2555 | −} | |
| 2556 | − | |
| 2557 | 2529 | static unsigned int serial8250_do_get_divisor(struct uart_port *port, |
| 2558 | 2530 | unsigned int baud, |
| 2559 | 2531 | unsigned int *frac) |
| @@ -2598,8 +2570,6 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port, · 38 unmodified lines | ||
| 2598 | 2570 | quot = 0x8001; |
| 2599 | 2571 | else if (magic_multiplier && baud >= port->uartclk / 12) |
| 2600 | 2572 | quot = 0x8002; |
| 2601 | − else if (up->port.type == PORT_NPCM) | |
| 2602 | − quot = npcm_get_divisor(up, baud); | |
| 2603 | 2573 | else |
| 2604 | 2574 | quot = uart_get_divisor(port, baud); |
| 2605 | 2575 | |
| @@ -2714,12 +2684,8 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, · 108 unmodified lines | ||
| 2714 | 2684 | */ |
| 2715 | 2685 | void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) |
| 2716 | 2686 | { |
| 2717 | − struct uart_8250_port *up = up_to_u8250p(port); | |
| 2718 | 2687 | struct tty_port *tport = &port->state->port; |
| 2719 | − unsigned int baud, quot, frac = 0; | |
| 2720 | − struct ktermios *termios; | |
| 2721 | 2688 | struct tty_struct *tty; |
| 2722 | − unsigned long flags; | |
| 2723 | 2689 | |
| 2724 | 2690 | tty = tty_port_tty_get(tport); |
| 2725 | 2691 | if (!tty) { |
| @@ -2740,21 +2706,7 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) · 14 unmodified lines | ||
| 2740 | 2706 | if (!tty_port_initialized(tport)) |
| 2741 | 2707 | goto out_unlock; |
| 2742 | 2708 | |
| 2743 | − termios = &tty->termios; | |
| 2744 | − | |
| 2745 | − baud = serial8250_get_baud_rate(port, termios, NULL); | |
| 2746 | − quot = serial8250_get_divisor(port, baud, &frac); | |
| 2747 | − | |
| 2748 | − serial8250_rpm_get(up); | |
| 2749 | − uart_port_lock_irqsave(port, &flags); | |
| 2750 | − | |
| 2751 | − uart_update_timeout(port, termios->c_cflag, baud); | |
| 2752 | − | |
| 2753 | − serial8250_set_divisor(port, baud, quot, frac); | |
| 2754 | − serial_port_out(port, UART_LCR, up->lcr); | |
| 2755 | − | |
| 2756 | − uart_port_unlock_irqrestore(port, flags); | |
| 2757 | − serial8250_rpm_put(up); | |
| 2709 | + serial8250_do_set_termios(port, &tty->termios, NULL); | |
| 2758 | 2710 | |
| 2759 | 2711 | out_unlock: |
| 2760 | 2712 | mutex_unlock(&tport->mutex); |
| @@ -92,11 +92,7 @@ static int serial_pxa_probe(struct platform_device *pdev) · 91 unmodified lines | ||
| 92 | 92 | struct uart_8250_port uart = {}; |
| 93 | 93 | struct pxa8250_data *data; |
| 94 | 94 | struct resource *mmres; |
| 95 | − int irq, ret; | |
| 96 | − | |
| 97 | − irq = platform_get_irq(pdev, 0); | |
| 98 | − if (irq < 0) | |
| 99 | − return irq; | |
| 95 | + int ret; | |
| 100 | 96 | |
| 101 | 97 | mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 102 | 98 | if (!mmres) |
| @@ -114,21 +110,21 @@ static int serial_pxa_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 114 | 110 | if (ret) |
| 115 | 111 | return ret; |
| 116 | 112 | |
| 117 | − ret = of_alias_get_id(pdev->dev.of_node, "serial"); | |
| 118 | − if (ret >= 0) | |
| 119 | − uart.port.line = ret; | |
| 120 | − | |
| 121 | 113 | uart.port.type = PORT_XSCALE; |
| 122 | − uart.port.iotype = UPIO_MEM32; | |
| 123 | 114 | uart.port.mapbase = mmres->start; |
| 124 | − uart.port.regshift = 2; | |
| 125 | − uart.port.irq = irq; | |
| 126 | − uart.port.fifosize = 64; | |
| 127 | 115 | uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE; |
| 128 | 116 | uart.port.dev = &pdev->dev; |
| 129 | 117 | uart.port.uartclk = clk_get_rate(data->clk); |
| 130 | 118 | uart.port.pm = serial_pxa_pm; |
| 131 | 119 | uart.port.private_data = data; |
| 120 | + | |
| 121 | + ret = uart_read_port_properties(&uart.port); | |
| 122 | + if (ret) | |
| 123 | + return ret; | |
| 124 | + | |
| 125 | + uart.port.iotype = UPIO_MEM32; | |
| 126 | + uart.port.regshift = 2; | |
| 127 | + uart.port.fifosize = 64; | |
| 132 | 128 | uart.dl_write = serial_pxa_dl_write; |
| 133 | 129 | |
| 134 | 130 | ret = serial8250_register_8250_port(&uart); |
| @@ -57,25 +57,11 @@ static int tegra_uart_probe(struct platform_device *pdev) · 56 unmodified lines | ||
| 57 | 57 | port = &port8250.port; |
| 58 | 58 | spin_lock_init(&port->lock); |
| 59 | 59 | |
| 60 | − port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | | |
| 61 | − UPF_FIXED_TYPE; | |
| 62 | − port->iotype = UPIO_MEM32; | |
| 63 | − port->regshift = 2; | |
| 60 | + port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE; | |
| 64 | 61 | port->type = PORT_TEGRA; |
| 65 | − port->irqflags |= IRQF_SHARED; | |
| 66 | 62 | port->dev = &pdev->dev; |
| 67 | 63 | port->handle_break = tegra_uart_handle_break; |
| 68 | 64 | |
| 69 | − ret = of_alias_get_id(pdev->dev.of_node, "serial"); | |
| 70 | − if (ret >= 0) | |
| 71 | − port->line = ret; | |
| 72 | − | |
| 73 | − ret = platform_get_irq(pdev, 0); | |
| 74 | − if (ret < 0) | |
| 75 | − return ret; | |
| 76 | − | |
| 77 | − port->irq = ret; | |
| 78 | − | |
| 79 | 65 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 80 | 66 | if (!res) |
| 81 | 67 | return -ENODEV; |
| @@ -88,12 +74,18 @@ static int tegra_uart_probe(struct platform_device *pdev) · 6 unmodified lines | ||
| 88 | 74 | port->mapbase = res->start; |
| 89 | 75 | port->mapsize = resource_size(res); |
| 90 | 76 | |
| 77 | + ret = uart_read_port_properties(port); | |
| 78 | + if (ret) | |
| 79 | + return ret; | |
| 80 | + | |
| 81 | + port->iotype = UPIO_MEM32; | |
| 82 | + port->regshift = 2; | |
| 83 | + | |
| 91 | 84 | uart->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); |
| 92 | 85 | if (IS_ERR(uart->rst)) |
| 93 | 86 | return PTR_ERR(uart->rst); |
| 94 | 87 | |
| 95 | − if (device_property_read_u32(&pdev->dev, "clock-frequency", | |
| 96 | − &port->uartclk)) { | |
| 88 | + if (!port->uartclk) { | |
| 97 | 89 | uart->clk = devm_clk_get(&pdev->dev, NULL); |
| 98 | 90 | if (IS_ERR(uart->clk)) { |
| 99 | 91 | dev_err(&pdev->dev, "failed to get clock!\n"); |
| @@ -162,7 +162,6 @@ static int uniphier_uart_probe(struct platform_device *pdev) · 161 unmodified lines | ||
| 162 | 162 | struct uniphier8250_priv *priv; |
| 163 | 163 | struct resource *regs; |
| 164 | 164 | void __iomem *membase; |
| 165 | − int irq; | |
| 166 | 165 | int ret; |
| 167 | 166 | |
| 168 | 167 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -175,23 +174,12 @@ static int uniphier_uart_probe(struct platform_device *pdev) · 6 unmodified lines | ||
| 175 | 174 | if (!membase) |
| 176 | 175 | return -ENOMEM; |
| 177 | 176 | |
| 178 | − irq = platform_get_irq(pdev, 0); | |
| 179 | − if (irq < 0) | |
| 180 | − return irq; | |
| 181 | − | |
| 182 | 177 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
| 183 | 178 | if (!priv) |
| 184 | 179 | return -ENOMEM; |
| 185 | 180 | |
| 186 | 181 | memset(&up, 0, sizeof(up)); |
| 187 | 182 | |
| 188 | − ret = of_alias_get_id(dev->of_node, "serial"); | |
| 189 | − if (ret < 0) { | |
| 190 | − dev_err(dev, "failed to get alias id\n"); | |
| 191 | − return ret; | |
| 192 | − } | |
| 193 | − up.port.line = ret; | |
| 194 | − | |
| 195 | 183 | priv->clk = devm_clk_get(dev, NULL); |
| 196 | 184 | if (IS_ERR(priv->clk)) { |
| 197 | 185 | dev_err(dev, "failed to get clock\n"); |
| @@ -211,7 +199,10 @@ static int uniphier_uart_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 211 | 199 | up.port.mapbase = regs->start; |
| 212 | 200 | up.port.mapsize = resource_size(regs); |
| 213 | 201 | up.port.membase = membase; |
| 214 | − up.port.irq = irq; | |
| 202 | + | |
| 203 | + ret = uart_read_port_properties(&up.port); | |
| 204 | + if (ret) | |
| 205 | + return ret; | |
| 215 | 206 | |
| 216 | 207 | up.port.type = PORT_16550A; |
| 217 | 208 | up.port.iotype = UPIO_MEM32; |
| @@ -149,6 +149,7 @@ config SERIAL_8250_PCI · 148 unmodified lines | ||
| 149 | 149 | config SERIAL_8250_EXAR |
| 150 | 150 | tristate "8250/16550 Exar/Commtech PCI/PCIe device support" |
| 151 | 151 | depends on SERIAL_8250 && PCI |
| 152 | + select SERIAL_8250_PCILIB | |
| 152 | 153 | default SERIAL_8250 |
| 153 | 154 | help |
| 154 | 155 | This builds support for XR17C1xx, XR17V3xx and some Commtech |
| @@ -348,10 +348,7 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) · 347 unmodified lines | ||
| 348 | 348 | flag = TTY_FRAME; |
| 349 | 349 | } |
| 350 | 350 | |
| 351 | − uart_port_unlock(&uap->port); | |
| 352 | − sysrq = uart_handle_sysrq_char(&uap->port, ch & 255); | |
| 353 | − uart_port_lock(&uap->port); | |
| 354 | − | |
| 351 | + sysrq = uart_prepare_sysrq_char(&uap->port, ch & 255); | |
| 355 | 352 | if (!sysrq) |
| 356 | 353 | uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); |
| 357 | 354 | } |
| @@ -1017,7 +1014,7 @@ static void pl011_dma_rx_callback(void *data) · 659 unmodified lines | ||
| 1017 | 1014 | ret = pl011_dma_rx_trigger_dma(uap); |
| 1018 | 1015 | |
| 1019 | 1016 | pl011_dma_rx_chars(uap, pending, lastbuf, false); |
| 1020 | − uart_port_unlock_irq(&uap->port); | |
| 1017 | + uart_unlock_and_check_sysrq(&uap->port); | |
| 1021 | 1018 | /* |
| 1022 | 1019 | * Do this check after we picked the DMA chars so we don't |
| 1023 | 1020 | * get some IRQ immediately from RX. |
| @@ -1540,11 +1537,10 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap) · 516 unmodified lines | ||
| 1540 | 1537 | static irqreturn_t pl011_int(int irq, void *dev_id) |
| 1541 | 1538 | { |
| 1542 | 1539 | struct uart_amba_port *uap = dev_id; |
| 1543 | − unsigned long flags; | |
| 1544 | 1540 | unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; |
| 1545 | 1541 | int handled = 0; |
| 1546 | 1542 | |
| 1547 | − uart_port_lock_irqsave(&uap->port, &flags); | |
| 1543 | + uart_port_lock(&uap->port); | |
| 1548 | 1544 | status = pl011_read(uap, REG_RIS) & uap->im; |
| 1549 | 1545 | if (status) { |
| 1550 | 1546 | do { |
| @@ -1573,7 +1569,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) · 22 unmodified lines | ||
| 1573 | 1569 | handled = 1; |
| 1574 | 1570 | } |
| 1575 | 1571 | |
| 1576 | − uart_port_unlock_irqrestore(&uap->port, flags); | |
| 1572 | + uart_unlock_and_check_sysrq(&uap->port); | |
| 1577 | 1573 | |
| 1578 | 1574 | return IRQ_RETVAL(handled); |
| 1579 | 1575 | } |
| @@ -2322,13 +2318,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) · 742 unmodified lines | ||
| 2322 | 2318 | |
| 2323 | 2319 | clk_enable(uap->clk); |
| 2324 | 2320 | |
| 2325 | − local_irq_save(flags); | |
| 2326 | − if (uap->port.sysrq) | |
| 2327 | − locked = 0; | |
| 2328 | − else if (oops_in_progress) | |
| 2329 | − locked = uart_port_trylock(&uap->port); | |
| 2321 | + if (oops_in_progress) | |
| 2322 | + locked = uart_port_trylock_irqsave(&uap->port, &flags); | |
| 2330 | 2323 | else |
| 2331 | − uart_port_lock(&uap->port); | |
| 2324 | + uart_port_lock_irqsave(&uap->port, &flags); | |
| 2332 | 2325 | |
| 2333 | 2326 | /* |
| 2334 | 2327 | * First save the CR then disable the interrupts |
| @@ -2354,8 +2347,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) · 19 unmodified lines | ||
| 2354 | 2347 | pl011_write(old_cr, uap, REG_CR); |
| 2355 | 2348 | |
| 2356 | 2349 | if (locked) |
| 2357 | − uart_port_unlock(&uap->port); | |
| 2358 | − local_irq_restore(flags); | |
| 2350 | + uart_port_unlock_irqrestore(&uap->port, flags); | |
| 2359 | 2351 | |
| 2360 | 2352 | clk_disable(uap->clk); |
| 2361 | 2353 | } |
| @@ -378,7 +378,7 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up) · 377 unmodified lines | ||
| 378 | 378 | up->port.icount.rx++; |
| 379 | 379 | ch = rdata & AR933X_UART_DATA_TX_RX_MASK; |
| 380 | 380 | |
| 381 | − if (uart_handle_sysrq_char(&up->port, ch)) | |
| 381 | + if (uart_prepare_sysrq_char(&up->port, ch)) | |
| 382 | 382 | continue; |
| 383 | 383 | |
| 384 | 384 | 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) · 83 unmodified lines | ||
| 468 | 468 | ar933x_uart_tx_chars(up); |
| 469 | 469 | } |
| 470 | 470 | |
| 471 | − uart_port_unlock(&up->port); | |
| 471 | + uart_unlock_and_check_sysrq(&up->port); | |
| 472 | 472 | |
| 473 | 473 | return IRQ_HANDLED; |
| 474 | 474 | } |
| @@ -627,14 +627,10 @@ static void ar933x_uart_console_write(struct console *co, const char *s, · 152 unmodified lines | ||
| 627 | 627 | unsigned int int_en; |
| 628 | 628 | int locked = 1; |
| 629 | 629 | |
| 630 | − local_irq_save(flags); | |
| 631 | − | |
| 632 | − if (up->port.sysrq) | |
| 633 | − locked = 0; | |
| 634 | − else if (oops_in_progress) | |
| 635 | − locked = uart_port_trylock(&up->port); | |
| 630 | + if (oops_in_progress) | |
| 631 | + locked = uart_port_trylock_irqsave(&up->port, &flags); | |
| 636 | 632 | else |
| 637 | − uart_port_lock(&up->port); | |
| 633 | + uart_port_lock_irqsave(&up->port, &flags); | |
| 638 | 634 | |
| 639 | 635 | /* |
| 640 | 636 | * First save the IER then disable the interrupts |
| @@ -654,9 +650,7 @@ static void ar933x_uart_console_write(struct console *co, const char *s, · 13 unmodified lines | ||
| 654 | 650 | ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS); |
| 655 | 651 | |
| 656 | 652 | if (locked) |
| 657 | − uart_port_unlock(&up->port); | |
| 658 | − | |
| 659 | − local_irq_restore(flags); | |
| 653 | + uart_port_unlock_irqrestore(&up->port, flags); | |
| 660 | 654 | } |
| 661 | 655 | |
| 662 | 656 | static int ar933x_uart_console_setup(struct console *co, char *options) |
| @@ -285,10 +285,9 @@ static void bcm_uart_do_rx(struct uart_port *port) · 284 unmodified lines | ||
| 285 | 285 | flag = TTY_PARITY; |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | − if (uart_handle_sysrq_char(port, c)) | |
| 288 | + if (uart_prepare_sysrq_char(port, c)) | |
| 289 | 289 | continue; |
| 290 | 290 | |
| 291 | − | |
| 292 | 291 | if ((cstat & port->ignore_status_mask) == 0) |
| 293 | 292 | tty_insert_flip_char(tty_port, c, flag); |
| 294 | 293 | |
| @@ -353,7 +352,7 @@ static irqreturn_t bcm_uart_interrupt(int irq, void *dev_id) · 58 unmodified lines | ||
| 353 | 352 | estat & UART_EXTINP_DCD_MASK); |
| 354 | 353 | } |
| 355 | 354 | |
| 356 | − uart_port_unlock(port); | |
| 355 | + uart_unlock_and_check_sysrq(port); | |
| 357 | 356 | return IRQ_HANDLED; |
| 358 | 357 | } |
| 359 | 358 | |
| @@ -703,20 +702,14 @@ static void bcm_console_write(struct console *co, const char *s, · 343 unmodified lines | ||
| 703 | 702 | { |
| 704 | 703 | struct uart_port *port; |
| 705 | 704 | unsigned long flags; |
| 706 | − int locked; | |
| 705 | + int locked = 1; | |
| 707 | 706 | |
| 708 | 707 | port = &ports[co->index]; |
| 709 | 708 | |
| 710 | − local_irq_save(flags); | |
| 711 | − if (port->sysrq) { | |
| 712 | − /* bcm_uart_interrupt() already took the lock */ | |
| 713 | − locked = 0; | |
| 714 | − } else if (oops_in_progress) { | |
| 715 | − locked = uart_port_trylock(port); | |
| 716 | − } else { | |
| 717 | − uart_port_lock(port); | |
| 718 | − locked = 1; | |
| 719 | − } | |
| 709 | + if (oops_in_progress) | |
| 710 | + locked = uart_port_trylock_irqsave(port, &flags); | |
| 711 | + else | |
| 712 | + uart_port_lock_irqsave(port, &flags); | |
| 720 | 713 | |
| 721 | 714 | /* call helper to deal with \r\n */ |
| 722 | 715 | uart_console_write(port, s, count, bcm_console_putchar); |
| @@ -725,8 +718,7 @@ static void bcm_console_write(struct console *co, const char *s, · 2 unmodified lines | ||
| 725 | 718 | wait_for_xmitr(port); |
| 726 | 719 | |
| 727 | 720 | if (locked) |
| 728 | − uart_port_unlock(port); | |
| 729 | − local_irq_restore(flags); | |
| 721 | + uart_port_unlock_irqrestore(port, flags); | |
| 730 | 722 | } |
| 731 | 723 | |
| 732 | 724 | /* |
| @@ -837,7 +837,6 @@ static int linflex_probe(struct platform_device *pdev) · 836 unmodified lines | ||
| 837 | 837 | return ret; |
| 838 | 838 | |
| 839 | 839 | sport->dev = &pdev->dev; |
| 840 | − sport->type = PORT_LINFLEXUART; | |
| 841 | 840 | sport->iotype = UPIO_MEM; |
| 842 | 841 | sport->irq = ret; |
| 843 | 842 | sport->ops = &linflex_pops; |
| @@ -395,7 +395,6 @@ static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch) · 394 unmodified lines | ||
| 395 | 395 | * which in this case is the break signal. |
| 396 | 396 | */ |
| 397 | 397 | if (linestatus & error_mask) { |
| 398 | − linestatus = 0; | |
| 399 | 398 | readb(&ch->ch_cls_uart->txrx); |
| 400 | 399 | continue; |
| 401 | 400 | } |
| @@ -136,20 +136,16 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s, · 135 unmodified lines | ||
| 136 | 136 | int locked = 1; |
| 137 | 137 | |
| 138 | 138 | touch_nmi_watchdog(); |
| 139 | − local_irq_save(flags); | |
| 140 | − if (up->port.sysrq) | |
| 141 | − locked = 0; | |
| 142 | − else if (oops_in_progress) | |
| 143 | − locked = uart_port_trylock(&up->port); | |
| 139 | + if (oops_in_progress) | |
| 140 | + locked = uart_port_trylock_irqsave(&up->port, &flags); | |
| 144 | 141 | else |
| 145 | − uart_port_lock(&up->port); | |
| 142 | + uart_port_lock_irqsave(&up->port, &flags); | |
| 146 | 143 | |
| 147 | 144 | uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar); |
| 148 | 145 | wait_for_xmit_empty(&up->port); |
| 149 | 146 | |
| 150 | 147 | if (locked) |
| 151 | − uart_port_unlock(&up->port); | |
| 152 | − local_irq_restore(flags); | |
| 148 | + uart_port_unlock_irqrestore(&up->port, flags); | |
| 153 | 149 | } |
| 154 | 150 | |
| 155 | 151 | static int __init lpc32xx_hsuart_console_setup(struct console *co, |
| @@ -233,8 +229,6 @@ static unsigned int __serial_get_clock_div(unsigned long uartclk, · 77 unmodified lines | ||
| 233 | 229 | |
| 234 | 230 | hsu_rate++; |
| 235 | 231 | } |
| 236 | − if (hsu_rate > 0xFF) | |
| 237 | − hsu_rate = 0xFF; | |
| 238 | 232 | |
| 239 | 233 | return goodrate; |
| 240 | 234 | } |
| @@ -268,7 +262,8 @@ static void __serial_lpc32xx_rx(struct uart_port *port) · 27 unmodified lines | ||
| 268 | 262 | tty_insert_flip_char(tport, 0, TTY_FRAME); |
| 269 | 263 | } |
| 270 | 264 | |
| 271 | − tty_insert_flip_char(tport, (tmp & 0xFF), flag); | |
| 265 | + if (!uart_prepare_sysrq_char(port, tmp & 0xff)) | |
| 266 | + tty_insert_flip_char(tport, (tmp & 0xFF), flag); | |
| 272 | 267 | |
| 273 | 268 | tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); |
| 274 | 269 | } |
| @@ -333,7 +328,7 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id) · 58 unmodified lines | ||
| 333 | 328 | __serial_lpc32xx_tx(port); |
| 334 | 329 | } |
| 335 | 330 | |
| 336 | − uart_port_unlock(port); | |
| 331 | + uart_unlock_and_check_sysrq(port); | |
| 337 | 332 | |
| 338 | 333 | return IRQ_HANDLED; |
| 339 | 334 | } |
| @@ -30,6 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #define MAX310X_MAJOR 204 |
| 31 | 31 | #define MAX310X_MINOR 209 |
| 32 | 32 | #define MAX310X_UART_NRMAX 16 |
| 33 | +#define MAX310X_MAX_PORTS 4 /* Maximum number of UART ports per IC. */ | |
| 33 | 34 | |
| 34 | 35 | /* MAX310X register definitions */ |
| 35 | 36 | #define MAX310X_RHR_REG (0x00) /* RX FIFO */ |
| @@ -66,6 +67,7 @@ · 30 unmodified lines | ||
| 66 | 67 | #define MAX310X_BRGDIVMSB_REG (0x1d) /* Baud rate divisor MSB */ |
| 67 | 68 | #define MAX310X_CLKSRC_REG (0x1e) /* Clock source */ |
| 68 | 69 | #define MAX310X_REG_1F (0x1f) |
| 70 | +#define MAX310X_EXTREG_START (0x20) /* Only relevant in SPI mode. */ | |
| 69 | 71 | |
| 70 | 72 | #define MAX310X_REVID_REG MAX310X_REG_1F /* Revision ID */ |
| 71 | 73 | |
| @@ -73,9 +75,9 @@ · 1 unmodified line | ||
| 73 | 75 | #define MAX310X_GLOBALCMD_REG MAX310X_REG_1F /* Global Command (WO) */ |
| 74 | 76 | |
| 75 | 77 | /* Extended registers */ |
| 76 | −#define MAX310X_SPI_REVID_EXTREG MAX310X_REG_05 /* Revision ID */ | |
| 77 | −#define MAX310X_I2C_REVID_EXTREG (0x25) /* Revision ID */ | |
| 78 | − | |
| 78 | +#define MAX310X_REVID_EXTREG (0x25) /* Revision ID | |
| 79 | + * (extended addressing space) | |
| 80 | + */ | |
| 79 | 81 | /* IRQ register bits */ |
| 80 | 82 | #define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ |
| 81 | 83 | #define MAX310X_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */ |
| @@ -160,14 +162,14 @@ · 78 unmodified lines | ||
| 160 | 162 | #define MAX310X_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */ |
| 161 | 163 | |
| 162 | 164 | /* Flow control trigger level register masks */ |
| 163 | −#define MAX310X_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */ | |
| 164 | −#define MAX310X_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */ | |
| 165 | +#define MAX310X_FLOWLVL_HALT_MASK GENMASK(3, 0) /* Flow control halt level */ | |
| 166 | +#define MAX310X_FLOWLVL_RES_MASK GENMASK(7, 4) /* Flow control resume level */ | |
| 165 | 167 | #define MAX310X_FLOWLVL_HALT(words) ((words / 8) & 0x0f) |
| 166 | 168 | #define MAX310X_FLOWLVL_RES(words) (((words / 8) & 0x0f) << 4) |
| 167 | 169 | |
| 168 | 170 | /* FIFO interrupt trigger level register masks */ |
| 169 | −#define MAX310X_FIFOTRIGLVL_TX_MASK (0x0f) /* TX FIFO trigger level */ | |
| 170 | −#define MAX310X_FIFOTRIGLVL_RX_MASK (0xf0) /* RX FIFO trigger level */ | |
| 171 | +#define MAX310X_FIFOTRIGLVL_TX_MASK GENMASK(3, 0) /* TX FIFO trigger level */ | |
| 172 | +#define MAX310X_FIFOTRIGLVL_RX_MASK GENMASK(7, 4) /* RX FIFO trigger level */ | |
| 171 | 173 | #define MAX310X_FIFOTRIGLVL_TX(words) ((words / 8) & 0x0f) |
| 172 | 174 | #define MAX310X_FIFOTRIGLVL_RX(words) (((words / 8) & 0x0f) << 4) |
| 173 | 175 | |
| @@ -177,7 +179,8 @@ · 3 unmodified lines | ||
| 177 | 179 | #define MAX310X_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs |
| 178 | 180 | * are used in conjunction with |
| 179 | 181 | * XOFF2 for definition of |
| 180 | − * special character */ | |
| 182 | + * special character | |
| 183 | + */ | |
| 181 | 184 | #define MAX310X_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */ |
| 182 | 185 | #define MAX310X_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */ |
| 183 | 186 | #define MAX310X_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1 |
| @@ -214,8 +217,8 @@ · 30 unmodified lines | ||
| 214 | 217 | */ |
| 215 | 218 | |
| 216 | 219 | /* PLL configuration register masks */ |
| 217 | −#define MAX310X_PLLCFG_PREDIV_MASK (0x3f) /* PLL predivision value */ | |
| 218 | −#define MAX310X_PLLCFG_PLLFACTOR_MASK (0xc0) /* PLL multiplication factor */ | |
| 220 | +#define MAX310X_PLLCFG_PREDIV_MASK GENMASK(5, 0) /* PLL predivision value */ | |
| 221 | +#define MAX310X_PLLCFG_PLLFACTOR_MASK GENMASK(7, 6) /* PLL multiplication factor */ | |
| 219 | 222 | |
| 220 | 223 | /* Baud rate generator configuration register bits */ |
| 221 | 224 | #define MAX310X_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */ |
| @@ -234,7 +237,7 @@ · 12 unmodified lines | ||
| 234 | 237 | |
| 235 | 238 | /* Misc definitions */ |
| 236 | 239 | #define MAX310X_FIFO_SIZE (128) |
| 237 | −#define MAX310x_REV_MASK (0xf8) | |
| 240 | +#define MAX310x_REV_MASK GENMASK(7, 3) | |
| 238 | 241 | #define MAX310X_WRITE_BIT 0x80 |
| 239 | 242 | |
| 240 | 243 | /* Port startup definitions */ |
| @@ -257,20 +260,21 @@ · 16 unmodified lines | ||
| 257 | 260 | |
| 258 | 261 | struct max310x_if_cfg { |
| 259 | 262 | int (*extended_reg_enable)(struct device *dev, bool enable); |
| 260 | − | |
| 261 | − unsigned int rev_id_reg; | |
| 263 | + u8 rev_id_offset; | |
| 262 | 264 | }; |
| 263 | 265 | |
| 264 | 266 | struct max310x_devtype { |
| 265 | 267 | struct { |
| 266 | 268 | unsigned short min; |
| 267 | 269 | unsigned short max; |
| 268 | − } slave_addr; | |
| 269 | − char name[9]; | |
| 270 | + } slave_addr; /* Relevant only in I2C mode. */ | |
| 270 | 271 | int nr; |
| 272 | + char name[9]; | |
| 271 | 273 | u8 mode1; |
| 272 | − int (*detect)(struct device *); | |
| 273 | − void (*power)(struct uart_port *, int); | |
| 274 | + u8 rev_id_val; | |
| 275 | + u8 rev_id_reg; /* Relevant only if rev_id_val is defined. */ | |
| 276 | + u8 power_reg; /* Register address for power/sleep control. */ | |
| 277 | + u8 power_bit; /* Bit for sleep or power-off mode (active high). */ | |
| 274 | 278 | }; |
| 275 | 279 | |
| 276 | 280 | struct max310x_one { |
| @@ -331,62 +335,52 @@ static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val) · 54 unmodified lines | ||
| 331 | 335 | regmap_update_bits(one->regmap, reg, mask, val); |
| 332 | 336 | } |
| 333 | 337 | |
| 334 | −static int max3107_detect(struct device *dev) | |
| 338 | +static int max310x_detect(struct device *dev) | |
| 335 | 339 | { |
| 336 | 340 | struct max310x_port *s = dev_get_drvdata(dev); |
| 337 | 341 | unsigned int val = 0; |
| 338 | 342 | int ret; |
| 339 | 343 | |
| 340 | − ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val); | |
| 341 | − if (ret) | |
| 342 | − return ret; | |
| 344 | + /* Check if variant supports REV ID register: */ | |
| 345 | + if (s->devtype->rev_id_val) { | |
| 346 | + u8 rev_id_reg = s->devtype->rev_id_reg; | |
| 343 | 347 | |
| 344 | − if (((val & MAX310x_REV_MASK) != MAX3107_REV_ID)) { | |
| 345 | − dev_err(dev, | |
| 346 | − "%s ID 0x%02x does not match\n", s->devtype->name, val); | |
| 347 | − return -ENODEV; | |
| 348 | − } | |
| 349 | − | |
| 350 | − return 0; | |
| 351 | −} | |
| 348 | + /* Check if REV ID is in extended addressing space: */ | |
| 349 | + if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) { | |
| 350 | + ret = s->if_cfg->extended_reg_enable(dev, true); | |
| 351 | + if (ret) | |
| 352 | + return ret; | |
| 352 | 353 | |
| 353 | −static int max3108_detect(struct device *dev) | |
| 354 | −{ | |
| 355 | − struct max310x_port *s = dev_get_drvdata(dev); | |
| 356 | − unsigned int val = 0; | |
| 357 | − int ret; | |
| 358 | − | |
| 359 | − /* MAX3108 have not REV ID register, we just check default value | |
| 360 | − * from clocksource register to make sure everything works. | |
| 361 | − */ | |
| 362 | − ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val); | |
| 363 | − if (ret) | |
| 364 | − return ret; | |
| 365 | − | |
| 366 | − if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT)) { | |
| 367 | − dev_err(dev, "%s not present\n", s->devtype->name); | |
| 368 | − return -ENODEV; | |
| 369 | − } | |
| 354 | + /* Adjust REV ID extended addressing space address: */ | |
| 355 | + if (s->if_cfg->rev_id_offset) | |
| 356 | + rev_id_reg -= s->if_cfg->rev_id_offset; | |
| 357 | + } | |
| 370 | 358 | |
| 371 | − return 0; | |
| 372 | −} | |
| 359 | + regmap_read(s->regmap, rev_id_reg, &val); | |
| 373 | 360 | |
| 374 | −static int max3109_detect(struct device *dev) | |
| 375 | −{ | |
| 376 | − struct max310x_port *s = dev_get_drvdata(dev); | |
| 377 | − unsigned int val = 0; | |
| 378 | − int ret; | |
| 379 | − | |
| 380 | − ret = s->if_cfg->extended_reg_enable(dev, true); | |
| 381 | − if (ret) | |
| 382 | − return ret; | |
| 361 | + if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) { | |
| 362 | + ret = s->if_cfg->extended_reg_enable(dev, false); | |
| 363 | + if (ret) | |
| 364 | + return ret; | |
| 365 | + } | |
| 383 | 366 | |
| 384 | − regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val); | |
| 385 | − s->if_cfg->extended_reg_enable(dev, false); | |
| 386 | − if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) { | |
| 387 | − dev_err(dev, | |
| 388 | − "%s ID 0x%02x does not match\n", s->devtype->name, val); | |
| 389 | − return -ENODEV; | |
| 367 | + if (((val & MAX310x_REV_MASK) != s->devtype->rev_id_val)) | |
| 368 | + return dev_err_probe(dev, -ENODEV, | |
| 369 | + "%s ID 0x%02x does not match\n", | |
| 370 | + s->devtype->name, val); | |
| 371 | + } else { | |
| 372 | + /* | |
| 373 | + * For variant without REV ID register, just check default value | |
| 374 | + * from clocksource register to make sure everything works. | |
| 375 | + */ | |
| 376 | + ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val); | |
| 377 | + if (ret) | |
| 378 | + return ret; | |
| 379 | + | |
| 380 | + if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT)) | |
| 381 | + return dev_err_probe(dev, -ENODEV, | |
| 382 | + "%s not present\n", | |
| 383 | + s->devtype->name); | |
| 390 | 384 | } |
| 391 | 385 | |
| 392 | 386 | return 0; |
| @@ -394,39 +388,10 @@ static int max3109_detect(struct device *dev) · 1 unmodified line | ||
| 394 | 388 | |
| 395 | 389 | static void max310x_power(struct uart_port *port, int on) |
| 396 | 390 | { |
| 397 | − max310x_port_update(port, MAX310X_MODE1_REG, | |
| 398 | − MAX310X_MODE1_FORCESLEEP_BIT, | |
| 399 | − on ? 0 : MAX310X_MODE1_FORCESLEEP_BIT); | |
| 400 | − if (on) | |
| 401 | − msleep(50); | |
| 402 | −} | |
| 403 | − | |
| 404 | −static int max14830_detect(struct device *dev) | |
| 405 | −{ | |
| 406 | − struct max310x_port *s = dev_get_drvdata(dev); | |
| 407 | − unsigned int val = 0; | |
| 408 | − int ret; | |
| 409 | − | |
| 410 | − ret = s->if_cfg->extended_reg_enable(dev, true); | |
| 411 | − if (ret) | |
| 412 | − return ret; | |
| 413 | − | |
| 414 | − regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val); | |
| 415 | − s->if_cfg->extended_reg_enable(dev, false); | |
| 416 | − if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) { | |
| 417 | − dev_err(dev, | |
| 418 | − "%s ID 0x%02x does not match\n", s->devtype->name, val); | |
| 419 | − return -ENODEV; | |
| 420 | − } | |
| 421 | − | |
| 422 | − return 0; | |
| 423 | −} | |
| 391 | + struct max310x_port *s = dev_get_drvdata(port->dev); | |
| 424 | 392 | |
| 425 | −static void max14830_power(struct uart_port *port, int on) | |
| 426 | −{ | |
| 427 | − max310x_port_update(port, MAX310X_BRGCFG_REG, | |
| 428 | − MAX14830_BRGCFG_CLKDIS_BIT, | |
| 429 | − on ? 0 : MAX14830_BRGCFG_CLKDIS_BIT); | |
| 393 | + max310x_port_update(port, s->devtype->power_reg, s->devtype->power_bit, | |
| 394 | + on ? 0 : s->devtype->power_bit); | |
| 430 | 395 | if (on) |
| 431 | 396 | msleep(50); |
| 432 | 397 | } |
| @@ -435,8 +400,10 @@ static const struct max310x_devtype max3107_devtype = { · 2 unmodified lines | ||
| 435 | 400 | .name = "MAX3107", |
| 436 | 401 | .nr = 1, |
| 437 | 402 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT, |
| 438 | − .detect = max3107_detect, | |
| 439 | − .power = max310x_power, | |
| 403 | + .rev_id_val = MAX3107_REV_ID, | |
| 404 | + .rev_id_reg = MAX310X_REVID_REG, | |
| 405 | + .power_reg = MAX310X_MODE1_REG, | |
| 406 | + .power_bit = MAX310X_MODE1_FORCESLEEP_BIT, | |
| 440 | 407 | .slave_addr = { |
| 441 | 408 | .min = 0x2c, |
| 442 | 409 | .max = 0x2f, |
| @@ -447,8 +414,10 @@ static const struct max310x_devtype max3108_devtype = { · 4 unmodified lines | ||
| 447 | 414 | .name = "MAX3108", |
| 448 | 415 | .nr = 1, |
| 449 | 416 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, |
| 450 | − .detect = max3108_detect, | |
| 451 | − .power = max310x_power, | |
| 417 | + .rev_id_val = 0, /* Unsupported. */ | |
| 418 | + .rev_id_reg = 0, /* Irrelevant when rev_id_val is not defined. */ | |
| 419 | + .power_reg = MAX310X_MODE1_REG, | |
| 420 | + .power_bit = MAX310X_MODE1_FORCESLEEP_BIT, | |
| 452 | 421 | .slave_addr = { |
| 453 | 422 | .min = 0x60, |
| 454 | 423 | .max = 0x6f, |
| @@ -459,8 +428,10 @@ static const struct max310x_devtype max3109_devtype = { · 4 unmodified lines | ||
| 459 | 428 | .name = "MAX3109", |
| 460 | 429 | .nr = 2, |
| 461 | 430 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, |
| 462 | − .detect = max3109_detect, | |
| 463 | − .power = max310x_power, | |
| 431 | + .rev_id_val = MAX3109_REV_ID, | |
| 432 | + .rev_id_reg = MAX310X_REVID_EXTREG, | |
| 433 | + .power_reg = MAX310X_MODE1_REG, | |
| 434 | + .power_bit = MAX310X_MODE1_FORCESLEEP_BIT, | |
| 464 | 435 | .slave_addr = { |
| 465 | 436 | .min = 0x60, |
| 466 | 437 | .max = 0x6f, |
| @@ -471,8 +442,10 @@ static const struct max310x_devtype max14830_devtype = { · 4 unmodified lines | ||
| 471 | 442 | .name = "MAX14830", |
| 472 | 443 | .nr = 4, |
| 473 | 444 | .mode1 = MAX310X_MODE1_IRQSEL_BIT, |
| 474 | − .detect = max14830_detect, | |
| 475 | − .power = max14830_power, | |
| 445 | + .rev_id_val = MAX14830_REV_ID, | |
| 446 | + .rev_id_reg = MAX310X_REVID_EXTREG, | |
| 447 | + .power_reg = MAX310X_BRGCFG_REG, | |
| 448 | + .power_bit = MAX14830_BRGCFG_CLKDIS_BIT, | |
| 476 | 449 | .slave_addr = { |
| 477 | 450 | .min = 0x60, |
| 478 | 451 | .max = 0x6f, |
| @@ -490,10 +463,8 @@ static bool max310x_reg_writeable(struct device *dev, unsigned int reg) · 11 unmodified lines | ||
| 490 | 463 | case MAX310X_RXFIFOLVL_REG: |
| 491 | 464 | return false; |
| 492 | 465 | default: |
| 493 | − break; | |
| 466 | + return true; | |
| 494 | 467 | } |
| 495 | − | |
| 496 | − return true; | |
| 497 | 468 | } |
| 498 | 469 | |
| 499 | 470 | 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) · 12 unmodified lines | ||
| 512 | 483 | case MAX310X_REG_1F: |
| 513 | 484 | return true; |
| 514 | 485 | default: |
| 515 | − break; | |
| 486 | + return false; | |
| 516 | 487 | } |
| 517 | − | |
| 518 | − return false; | |
| 519 | 488 | } |
| 520 | 489 | |
| 521 | 490 | 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) · 5 unmodified lines | ||
| 527 | 496 | case MAX310X_STS_IRQSTS_REG: |
| 528 | 497 | return true; |
| 529 | 498 | default: |
| 530 | − break; | |
| 499 | + return false; | |
| 531 | 500 | } |
| 532 | − | |
| 533 | − return false; | |
| 534 | 501 | } |
| 535 | 502 | |
| 536 | 503 | 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) · 152 unmodified lines | ||
| 689 | 656 | u8 ch, flag; |
| 690 | 657 | |
| 691 | 658 | if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) { |
| 692 | − /* We are just reading, happily ignoring any error conditions. | |
| 659 | + /* | |
| 660 | + * We are just reading, happily ignoring any error conditions. | |
| 693 | 661 | * Break condition, parity checking, framing errors -- they |
| 694 | 662 | * are all ignored. That means that we can do a batch-read. |
| 695 | 663 | * |
| @@ -698,7 +666,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) · 2 unmodified lines | ||
| 698 | 666 | * that the LSR register applies to the "current" character. |
| 699 | 667 | * That's also the reason why we cannot do batched reads when |
| 700 | 668 | * asked to check the individual statuses. |
| 701 | − * */ | |
| 669 | + */ | |
| 702 | 670 | |
| 703 | 671 | sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); |
| 704 | 672 | max310x_batch_read(port, one->rx_buf, rxlen); |
| @@ -802,8 +770,10 @@ static void max310x_handle_tx(struct uart_port *port) · 97 unmodified lines | ||
| 802 | 770 | to_send = (to_send > txlen) ? txlen : to_send; |
| 803 | 771 | |
| 804 | 772 | if (until_end < to_send) { |
| 805 | − /* It's a circ buffer -- wrap around. | |
| 806 | − * We could do that in one SPI transaction, but meh. */ | |
| 773 | + /* | |
| 774 | + * It's a circ buffer -- wrap around. | |
| 775 | + * We could do that in one SPI transaction, but meh. | |
| 776 | + */ | |
| 807 | 777 | max310x_batch_write(port, xmit->buf + xmit->tail, until_end); |
| 808 | 778 | max310x_batch_write(port, xmit->buf, to_send - until_end); |
| 809 | 779 | } else { |
| @@ -848,6 +818,7 @@ static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno) · 38 unmodified lines | ||
| 848 | 818 | if (ists & MAX310X_IRQ_TXEMPTY_BIT) |
| 849 | 819 | max310x_start_tx(port); |
| 850 | 820 | } while (1); |
| 821 | + | |
| 851 | 822 | return res; |
| 852 | 823 | } |
| 853 | 824 | |
| @@ -892,7 +863,8 @@ static unsigned int max310x_tx_empty(struct uart_port *port) · 38 unmodified lines | ||
| 892 | 863 | |
| 893 | 864 | static unsigned int max310x_get_mctrl(struct uart_port *port) |
| 894 | 865 | { |
| 895 | − /* DCD and DSR are not wired and CTS/RTS is handled automatically | |
| 866 | + /* | |
| 867 | + * DCD and DSR are not wired and CTS/RTS is handled automatically | |
| 896 | 868 | * so just indicate DSR and CAR asserted |
| 897 | 869 | */ |
| 898 | 870 | return TIOCM_DSR | TIOCM_CAR; |
| @@ -984,7 +956,8 @@ static void max310x_set_termios(struct uart_port *port, · 85 unmodified lines | ||
| 984 | 956 | max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]); |
| 985 | 957 | max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]); |
| 986 | 958 | |
| 987 | − /* Disable transmitter before enabling AutoCTS or auto transmitter | |
| 959 | + /* | |
| 960 | + * Disable transmitter before enabling AutoCTS or auto transmitter | |
| 988 | 961 | * flow control |
| 989 | 962 | */ |
| 990 | 963 | if (termios->c_cflag & CRTSCTS || termios->c_iflag & IXOFF) { |
| @@ -1011,7 +984,8 @@ static void max310x_set_termios(struct uart_port *port, · 20 unmodified lines | ||
| 1011 | 984 | } |
| 1012 | 985 | max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow); |
| 1013 | 986 | |
| 1014 | − /* Enable transmitter after disabling AutoCTS and auto transmitter | |
| 987 | + /* | |
| 988 | + * Enable transmitter after disabling AutoCTS and auto transmitter | |
| 1015 | 989 | * flow control |
| 1016 | 990 | */ |
| 1017 | 991 | 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 · 54 unmodified lines | ||
| 1072 | 1046 | |
| 1073 | 1047 | static int max310x_startup(struct uart_port *port) |
| 1074 | 1048 | { |
| 1075 | − struct max310x_port *s = dev_get_drvdata(port->dev); | |
| 1076 | 1049 | unsigned int val; |
| 1077 | 1050 | |
| 1078 | − s->devtype->power(port, 1); | |
| 1051 | + max310x_power(port, 1); | |
| 1079 | 1052 | |
| 1080 | 1053 | /* Configure MODE1 register */ |
| 1081 | 1054 | max310x_port_update(port, MAX310X_MODE1_REG, |
| @@ -1103,8 +1076,11 @@ static int max310x_startup(struct uart_port *port) · 21 unmodified lines | ||
| 1103 | 1076 | MAX310X_MODE2_ECHOSUPR_BIT); |
| 1104 | 1077 | } |
| 1105 | 1078 | |
| 1106 | − /* Configure flow control levels */ | |
| 1107 | − /* Flow control halt level 96, resume level 48 */ | |
| 1079 | + /* | |
| 1080 | + * Configure flow control levels: | |
| 1081 | + * resume: 48 | |
| 1082 | + * halt: 96 | |
| 1083 | + */ | |
| 1108 | 1084 | max310x_port_write(port, MAX310X_FLOWLVL_REG, |
| 1109 | 1085 | MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96)); |
| 1110 | 1086 | |
| @@ -1120,12 +1096,10 @@ static int max310x_startup(struct uart_port *port) · 9 unmodified lines | ||
| 1120 | 1096 | |
| 1121 | 1097 | static void max310x_shutdown(struct uart_port *port) |
| 1122 | 1098 | { |
| 1123 | − struct max310x_port *s = dev_get_drvdata(port->dev); | |
| 1124 | − | |
| 1125 | 1099 | /* Disable all interrupts */ |
| 1126 | 1100 | max310x_port_write(port, MAX310X_IRQEN_REG, 0); |
| 1127 | 1101 | |
| 1128 | − s->devtype->power(port, 0); | |
| 1102 | + max310x_power(port, 0); | |
| 1129 | 1103 | } |
| 1130 | 1104 | |
| 1131 | 1105 | static const char *max310x_type(struct uart_port *port) |
| @@ -1187,7 +1161,7 @@ static int __maybe_unused max310x_suspend(struct device *dev) · 55 unmodified lines | ||
| 1187 | 1161 | |
| 1188 | 1162 | for (i = 0; i < s->devtype->nr; i++) { |
| 1189 | 1163 | uart_suspend_port(&max310x_uart, &s->p[i].port); |
| 1190 | − s->devtype->power(&s->p[i].port, 0); | |
| 1164 | + max310x_power(&s->p[i].port, 0); | |
| 1191 | 1165 | } |
| 1192 | 1166 | |
| 1193 | 1167 | return 0; |
| @@ -1199,7 +1173,7 @@ static int __maybe_unused max310x_resume(struct device *dev) · 5 unmodified lines | ||
| 1199 | 1173 | int i; |
| 1200 | 1174 | |
| 1201 | 1175 | for (i = 0; i < s->devtype->nr; i++) { |
| 1202 | − s->devtype->power(&s->p[i].port, 1); | |
| 1176 | + max310x_power(&s->p[i].port, 1); | |
| 1203 | 1177 | uart_resume_port(&max310x_uart, &s->p[i].port); |
| 1204 | 1178 | } |
| 1205 | 1179 | |
| @@ -1209,7 +1183,7 @@ static int __maybe_unused max310x_resume(struct device *dev) · 3 unmodified lines | ||
| 1209 | 1183 | static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); |
| 1210 | 1184 | |
| 1211 | 1185 | #ifdef CONFIG_GPIOLIB |
| 1212 | −static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) | |
| 1186 | +static int max310x_gpio_get(struct gpio_chip *chip, unsigned int offset) | |
| 1213 | 1187 | { |
| 1214 | 1188 | unsigned int val; |
| 1215 | 1189 | struct max310x_port *s = gpiochip_get_data(chip); |
| @@ -1220,7 +1194,7 @@ static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) · 4 unmodified lines | ||
| 1220 | 1194 | return !!((val >> 4) & (1 << (offset % 4))); |
| 1221 | 1195 | } |
| 1222 | 1196 | |
| 1223 | −static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |
| 1197 | +static void max310x_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) | |
| 1224 | 1198 | { |
| 1225 | 1199 | struct max310x_port *s = gpiochip_get_data(chip); |
| 1226 | 1200 | 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) · 2 unmodified lines | ||
| 1229 | 1203 | value ? 1 << (offset % 4) : 0); |
| 1230 | 1204 | } |
| 1231 | 1205 | |
| 1232 | −static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | |
| 1206 | +static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) | |
| 1233 | 1207 | { |
| 1234 | 1208 | struct max310x_port *s = gpiochip_get_data(chip); |
| 1235 | 1209 | 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) · 4 unmodified lines | ||
| 1240 | 1214 | } |
| 1241 | 1215 | |
| 1242 | 1216 | static int max310x_gpio_direction_output(struct gpio_chip *chip, |
| 1243 | − unsigned offset, int value) | |
| 1217 | + unsigned int offset, int value) | |
| 1244 | 1218 | { |
| 1245 | 1219 | struct max310x_port *s = gpiochip_get_data(chip); |
| 1246 | 1220 | 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 · 49 unmodified lines | ||
| 1296 | 1270 | |
| 1297 | 1271 | /* Alloc port structure */ |
| 1298 | 1272 | s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL); |
| 1299 | − if (!s) { | |
| 1300 | − dev_err(dev, "Error allocating port structure\n"); | |
| 1301 | − return -ENOMEM; | |
| 1302 | − } | |
| 1273 | + if (!s) | |
| 1274 | + return dev_err_probe(dev, -ENOMEM, | |
| 1275 | + "Error allocating port structure\n"); | |
| 1303 | 1276 | |
| 1304 | 1277 | /* Always ask for fixed clock rate from a property. */ |
| 1305 | 1278 | device_property_read_u32(dev, "clock-frequency", &uartclk); |
| @@ -1320,8 +1293,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty · 14 unmodified lines | ||
| 1320 | 1293 | if (freq == 0) |
| 1321 | 1294 | freq = uartclk; |
| 1322 | 1295 | if (freq == 0) { |
| 1323 | − dev_err(dev, "Cannot get clock rate\n"); | |
| 1324 | − ret = -EINVAL; | |
| 1296 | + ret = dev_err_probe(dev, -EINVAL, "Cannot get clock rate\n"); | |
| 1325 | 1297 | goto out_clk; |
| 1326 | 1298 | } |
| 1327 | 1299 | |
| @@ -1345,7 +1317,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty · 17 unmodified lines | ||
| 1345 | 1317 | dev_set_drvdata(dev, s); |
| 1346 | 1318 | |
| 1347 | 1319 | /* Check device to ensure we are talking to what we expect */ |
| 1348 | − ret = devtype->detect(dev); | |
| 1320 | + ret = max310x_detect(dev); | |
| 1349 | 1321 | if (ret) |
| 1350 | 1322 | goto out_clk; |
| 1351 | 1323 | |
| @@ -1427,14 +1399,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty · 75 unmodified lines | ||
| 1427 | 1399 | |
| 1428 | 1400 | /* Register port */ |
| 1429 | 1401 | ret = uart_add_one_port(&max310x_uart, &s->p[i].port); |
| 1430 | − if (ret) { | |
| 1431 | − s->p[i].port.dev = NULL; | |
| 1402 | + if (ret) | |
| 1432 | 1403 | goto out_uart; |
| 1433 | − } | |
| 1404 | + | |
| 1434 | 1405 | set_bit(line, max310x_lines); |
| 1435 | 1406 | |
| 1436 | 1407 | /* Go to suspend mode */ |
| 1437 | − devtype->power(&s->p[i].port, 0); | |
| 1408 | + max310x_power(&s->p[i].port, 0); | |
| 1438 | 1409 | } |
| 1439 | 1410 | |
| 1440 | 1411 | #ifdef CONFIG_GPIOLIB |
| @@ -1461,14 +1432,12 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty · 20 unmodified lines | ||
| 1461 | 1432 | if (!ret) |
| 1462 | 1433 | return 0; |
| 1463 | 1434 | |
| 1464 | − dev_err(dev, "Unable to reguest IRQ %i\n", irq); | |
| 1435 | + dev_err(dev, "Unable to request IRQ %i\n", irq); | |
| 1465 | 1436 | |
| 1466 | 1437 | out_uart: |
| 1467 | 1438 | for (i = 0; i < devtype->nr; i++) { |
| 1468 | − if (s->p[i].port.dev) { | |
| 1439 | + if (test_and_clear_bit(s->p[i].port.line, max310x_lines)) | |
| 1469 | 1440 | uart_remove_one_port(&max310x_uart, &s->p[i].port); |
| 1470 | − clear_bit(s->p[i].port.line, max310x_lines); | |
| 1471 | − } | |
| 1472 | 1441 | } |
| 1473 | 1442 | |
| 1474 | 1443 | out_clk: |
| @@ -1486,9 +1455,11 @@ static void max310x_remove(struct device *dev) · 11 unmodified lines | ||
| 1486 | 1455 | cancel_work_sync(&s->p[i].tx_work); |
| 1487 | 1456 | cancel_work_sync(&s->p[i].md_work); |
| 1488 | 1457 | cancel_work_sync(&s->p[i].rs_work); |
| 1489 | − uart_remove_one_port(&max310x_uart, &s->p[i].port); | |
| 1490 | − clear_bit(s->p[i].port.line, max310x_lines); | |
| 1491 | − s->devtype->power(&s->p[i].port, 0); | |
| 1458 | + | |
| 1459 | + if (test_and_clear_bit(s->p[i].port.line, max310x_lines)) | |
| 1460 | + uart_remove_one_port(&max310x_uart, &s->p[i].port); | |
| 1461 | + | |
| 1462 | + max310x_power(&s->p[i].port, 0); | |
| 1492 | 1463 | } |
| 1493 | 1464 | |
| 1494 | 1465 | clk_disable_unprepare(s->clk); |
| @@ -1518,6 +1489,19 @@ static struct regmap_config regcfg = { · 23 unmodified lines | ||
| 1518 | 1489 | .max_raw_write = MAX310X_FIFO_SIZE, |
| 1519 | 1490 | }; |
| 1520 | 1491 | |
| 1492 | +static const char *max310x_regmap_name(u8 port_id) | |
| 1493 | +{ | |
| 1494 | + switch (port_id) { | |
| 1495 | + case 0: return "port0"; | |
| 1496 | + case 1: return "port1"; | |
| 1497 | + case 2: return "port2"; | |
| 1498 | + case 3: return "port3"; | |
| 1499 | + default: | |
| 1500 | + WARN_ON(true); | |
| 1501 | + return NULL; | |
| 1502 | + } | |
| 1503 | +} | |
| 1504 | + | |
| 1521 | 1505 | #ifdef CONFIG_SPI_MASTER |
| 1522 | 1506 | static int max310x_spi_extended_reg_enable(struct device *dev, bool enable) |
| 1523 | 1507 | { |
| @@ -1529,13 +1513,13 @@ static int max310x_spi_extended_reg_enable(struct device *dev, bool enable) · 5 unmodified lines | ||
| 1529 | 1513 | |
| 1530 | 1514 | static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = { |
| 1531 | 1515 | .extended_reg_enable = max310x_spi_extended_reg_enable, |
| 1532 | − .rev_id_reg = MAX310X_SPI_REVID_EXTREG, | |
| 1516 | + .rev_id_offset = MAX310X_EXTREG_START, | |
| 1533 | 1517 | }; |
| 1534 | 1518 | |
| 1535 | 1519 | static int max310x_spi_probe(struct spi_device *spi) |
| 1536 | 1520 | { |
| 1537 | 1521 | const struct max310x_devtype *devtype; |
| 1538 | − struct regmap *regmaps[4]; | |
| 1522 | + struct regmap *regmaps[MAX310X_MAX_PORTS]; | |
| 1539 | 1523 | unsigned int i; |
| 1540 | 1524 | int ret; |
| 1541 | 1525 | |
| @@ -1547,12 +1531,14 @@ static int max310x_spi_probe(struct spi_device *spi) · 5 unmodified lines | ||
| 1547 | 1531 | if (ret) |
| 1548 | 1532 | return ret; |
| 1549 | 1533 | |
| 1550 | − devtype = device_get_match_data(&spi->dev); | |
| 1534 | + devtype = spi_get_device_match_data(spi); | |
| 1551 | 1535 | if (!devtype) |
| 1552 | − devtype = (struct max310x_devtype *)spi_get_device_id(spi)->driver_data; | |
| 1536 | + return dev_err_probe(&spi->dev, -ENODEV, "Failed to match device\n"); | |
| 1553 | 1537 | |
| 1554 | 1538 | for (i = 0; i < devtype->nr; i++) { |
| 1555 | 1539 | u8 port_mask = i * 0x20; |
| 1540 | + | |
| 1541 | + regcfg.name = max310x_regmap_name(i); | |
| 1556 | 1542 | regcfg.read_flag_mask = port_mask; |
| 1557 | 1543 | regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT; |
| 1558 | 1544 | regmaps[i] = devm_regmap_init_spi(spi, ®cfg); |
| @@ -1600,7 +1586,7 @@ static struct regmap_config regcfg_i2c = { · 41 unmodified lines | ||
| 1600 | 1586 | .writeable_reg = max310x_reg_writeable, |
| 1601 | 1587 | .volatile_reg = max310x_reg_volatile, |
| 1602 | 1588 | .precious_reg = max310x_reg_precious, |
| 1603 | − .max_register = MAX310X_I2C_REVID_EXTREG, | |
| 1589 | + .max_register = MAX310X_REVID_EXTREG, | |
| 1604 | 1590 | .writeable_noinc_reg = max310x_reg_noinc, |
| 1605 | 1591 | .readable_noinc_reg = max310x_reg_noinc, |
| 1606 | 1592 | .max_raw_read = MAX310X_FIFO_SIZE, |
| @@ -1609,7 +1595,7 @@ static struct regmap_config regcfg_i2c = { · 2 unmodified lines | ||
| 1609 | 1595 | |
| 1610 | 1596 | static const struct max310x_if_cfg max310x_i2c_if_cfg = { |
| 1611 | 1597 | .extended_reg_enable = max310x_i2c_extended_reg_enable, |
| 1612 | − .rev_id_reg = MAX310X_I2C_REVID_EXTREG, | |
| 1598 | + .rev_id_offset = 0, /* No offset in I2C mode. */ | |
| 1613 | 1599 | }; |
| 1614 | 1600 | |
| 1615 | 1601 | static unsigned short max310x_i2c_slave_addr(unsigned short addr, |
| @@ -1619,10 +1605,10 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr, · 3 unmodified lines | ||
| 1619 | 1605 | * For MAX14830 and MAX3109, the slave address depends on what the |
| 1620 | 1606 | * A0 and A1 pins are tied to. |
| 1621 | 1607 | * See Table I2C Address Map of the datasheet. |
| 1622 | − * Based on that table, the following formulas were determined. | |
| 1623 | − * UART1 - UART0 = 0x10 | |
| 1624 | − * UART2 - UART1 = 0x20 + 0x10 | |
| 1625 | − * UART3 - UART2 = 0x10 | |
| 1608 | + * Based on that table, the following formulas were determined: | |
| 1609 | + * UART1 - UART0 = 0x10 | |
| 1610 | + * UART2 - UART1 = 0x20 + 0x10 | |
| 1611 | + * UART3 - UART2 = 0x10 | |
| 1626 | 1612 | */ |
| 1627 | 1613 | |
| 1628 | 1614 | addr -= nr * 0x10; |
| @@ -1635,20 +1621,24 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr, · 6 unmodified lines | ||
| 1635 | 1621 | |
| 1636 | 1622 | static int max310x_i2c_probe(struct i2c_client *client) |
| 1637 | 1623 | { |
| 1638 | − const struct max310x_devtype *devtype = | |
| 1639 | − device_get_match_data(&client->dev); | |
| 1624 | + const struct max310x_devtype *devtype; | |
| 1640 | 1625 | struct i2c_client *port_client; |
| 1641 | − struct regmap *regmaps[4]; | |
| 1626 | + struct regmap *regmaps[MAX310X_MAX_PORTS]; | |
| 1642 | 1627 | unsigned int i; |
| 1643 | 1628 | u8 port_addr; |
| 1644 | 1629 | |
| 1630 | + devtype = i2c_get_match_data(client); | |
| 1631 | + if (!devtype) | |
| 1632 | + return dev_err_probe(&client->dev, -ENODEV, "Failed to match device\n"); | |
| 1633 | + | |
| 1645 | 1634 | if (client->addr < devtype->slave_addr.min || |
| 1646 | − client->addr > devtype->slave_addr.max) | |
| 1635 | + client->addr > devtype->slave_addr.max) | |
| 1647 | 1636 | return dev_err_probe(&client->dev, -EINVAL, |
| 1648 | 1637 | "Slave addr 0x%x outside of range [0x%x, 0x%x]\n", |
| 1649 | 1638 | client->addr, devtype->slave_addr.min, |
| 1650 | 1639 | devtype->slave_addr.max); |
| 1651 | 1640 | |
| 1641 | + regcfg_i2c.name = max310x_regmap_name(0); | |
| 1652 | 1642 | regmaps[0] = devm_regmap_init_i2c(client, ®cfg_i2c); |
| 1653 | 1643 | |
| 1654 | 1644 | for (i = 1; i < devtype->nr; i++) { |
| @@ -1657,6 +1647,7 @@ static int max310x_i2c_probe(struct i2c_client *client) · 2 unmodified lines | ||
| 1657 | 1647 | client->adapter, |
| 1658 | 1648 | port_addr); |
| 1659 | 1649 | |
| 1650 | + regcfg_i2c.name = max310x_regmap_name(i); | |
| 1660 | 1651 | regmaps[i] = devm_regmap_init_i2c(port_client, ®cfg_i2c); |
| 1661 | 1652 | } |
| 1662 | 1653 | |
| @@ -1669,6 +1660,15 @@ static void max310x_i2c_remove(struct i2c_client *client) · 6 unmodified lines | ||
| 1669 | 1660 | max310x_remove(&client->dev); |
| 1670 | 1661 | } |
| 1671 | 1662 | |
| 1663 | +static const struct i2c_device_id max310x_i2c_id_table[] = { | |
| 1664 | + { "max3107", (kernel_ulong_t)&max3107_devtype, }, | |
| 1665 | + { "max3108", (kernel_ulong_t)&max3108_devtype, }, | |
| 1666 | + { "max3109", (kernel_ulong_t)&max3109_devtype, }, | |
| 1667 | + { "max14830", (kernel_ulong_t)&max14830_devtype, }, | |
| 1668 | + { } | |
| 1669 | +}; | |
| 1670 | +MODULE_DEVICE_TABLE(i2c, max310x_i2c_id_table); | |
| 1671 | + | |
| 1672 | 1672 | static struct i2c_driver max310x_i2c_driver = { |
| 1673 | 1673 | .driver = { |
| 1674 | 1674 | .name = MAX310X_NAME, |
| @@ -1677,6 +1677,7 @@ static struct i2c_driver max310x_i2c_driver = { · 2 unmodified lines | ||
| 1677 | 1677 | }, |
| 1678 | 1678 | .probe = max310x_i2c_probe, |
| 1679 | 1679 | .remove = max310x_i2c_remove, |
| 1680 | + .id_table = max310x_i2c_id_table, | |
| 1680 | 1681 | }; |
| 1681 | 1682 | #endif |
| 1682 | 1683 | |
| @@ -470,33 +470,6 @@ static struct mcf_uart mcf_ports[4]; · 469 unmodified lines | ||
| 470 | 470 | #if defined(CONFIG_SERIAL_MCF_CONSOLE) |
| 471 | 471 | /****************************************************************************/ |
| 472 | 472 | |
| 473 | −int __init early_mcf_setup(struct mcf_platform_uart *platp) | |
| 474 | −{ | |
| 475 | − struct uart_port *port; | |
| 476 | − int i; | |
| 477 | − | |
| 478 | − for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { | |
| 479 | − port = &mcf_ports[i].port; | |
| 480 | − | |
| 481 | − port->line = i; | |
| 482 | − port->type = PORT_MCF; | |
| 483 | − port->mapbase = platp[i].mapbase; | |
| 484 | − port->membase = (platp[i].membase) ? platp[i].membase : | |
| 485 | − (unsigned char __iomem *) port->mapbase; | |
| 486 | − port->iotype = SERIAL_IO_MEM; | |
| 487 | − port->irq = platp[i].irq; | |
| 488 | − port->uartclk = MCF_BUSCLK; | |
| 489 | − port->flags = UPF_BOOT_AUTOCONF; | |
| 490 | − port->rs485_config = mcf_config_rs485; | |
| 491 | − port->rs485_supported = mcf_rs485_supported; | |
| 492 | − port->ops = &mcf_uart_ops; | |
| 493 | − } | |
| 494 | − | |
| 495 | − return 0; | |
| 496 | −} | |
| 497 | − | |
| 498 | −/****************************************************************************/ | |
| 499 | − | |
| 500 | 473 | static void mcf_console_putc(struct console *co, const char c) |
| 501 | 474 | { |
| 502 | 475 | struct uart_port *port = &(mcf_ports + co->index)->port; |
| @@ -220,7 +220,7 @@ static void meson_receive_chars(struct uart_port *port) · 219 unmodified lines | ||
| 220 | 220 | continue; |
| 221 | 221 | } |
| 222 | 222 | |
| 223 | − if (uart_handle_sysrq_char(port, ch)) | |
| 223 | + if (uart_prepare_sysrq_char(port, ch)) | |
| 224 | 224 | continue; |
| 225 | 225 | |
| 226 | 226 | if ((status & port->ignore_status_mask) == 0) |
| @@ -248,7 +248,7 @@ static irqreturn_t meson_uart_interrupt(int irq, void *dev_id) · 21 unmodified lines | ||
| 248 | 248 | meson_uart_start_tx(port); |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | − uart_port_unlock(port); | |
| 251 | + uart_unlock_and_check_sysrq(port); | |
| 252 | 252 | |
| 253 | 253 | return IRQ_HANDLED; |
| 254 | 254 | } |
| @@ -556,18 +556,13 @@ static void meson_serial_port_write(struct uart_port *port, const char *s, · 301 unmodified lines | ||
| 556 | 556 | u_int count) |
| 557 | 557 | { |
| 558 | 558 | unsigned long flags; |
| 559 | − int locked; | |
| 559 | + int locked = 1; | |
| 560 | 560 | u32 val, tmp; |
| 561 | 561 | |
| 562 | − local_irq_save(flags); | |
| 563 | − if (port->sysrq) { | |
| 564 | − locked = 0; | |
| 565 | − } else if (oops_in_progress) { | |
| 566 | − locked = uart_port_trylock(port); | |
| 567 | − } else { | |
| 568 | − uart_port_lock(port); | |
| 569 | − locked = 1; | |
| 570 | − } | |
| 562 | + if (oops_in_progress) | |
| 563 | + locked = uart_port_trylock_irqsave(port, &flags); | |
| 564 | + else | |
| 565 | + uart_port_lock_irqsave(port, &flags); | |
| 571 | 566 | |
| 572 | 567 | val = readl(port->membase + AML_UART_CONTROL); |
| 573 | 568 | 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, · 3 unmodified lines | ||
| 577 | 572 | writel(val, port->membase + AML_UART_CONTROL); |
| 578 | 573 | |
| 579 | 574 | if (locked) |
| 580 | − uart_port_unlock(port); | |
| 581 | − local_irq_restore(flags); | |
| 575 | + uart_port_unlock_irqrestore(port, flags); | |
| 582 | 576 | } |
| 583 | 577 | |
| 584 | 578 | static void meson_serial_console_write(struct console *co, const char *s, |
| @@ -588,16 +588,14 @@ static void msm_complete_rx_dma(void *args) · 587 unmodified lines | ||
| 588 | 588 | if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) |
| 589 | 589 | flag = TTY_NORMAL; |
| 590 | 590 | |
| 591 | − uart_port_unlock_irqrestore(port, flags); | |
| 592 | − sysrq = uart_handle_sysrq_char(port, dma->virt[i]); | |
| 593 | − uart_port_lock_irqsave(port, &flags); | |
| 591 | + sysrq = uart_prepare_sysrq_char(port, dma->virt[i]); | |
| 594 | 592 | if (!sysrq) |
| 595 | 593 | tty_insert_flip_char(tport, dma->virt[i], flag); |
| 596 | 594 | } |
| 597 | 595 | |
| 598 | 596 | msm_start_rx_dma(msm_port); |
| 599 | 597 | done: |
| 600 | − uart_port_unlock_irqrestore(port, flags); | |
| 598 | + uart_unlock_and_check_sysrq_irqrestore(port, flags); | |
| 601 | 599 | |
| 602 | 600 | if (count) |
| 603 | 601 | tty_flip_buffer_push(tport); |
| @@ -763,9 +761,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) · 159 unmodified lines | ||
| 763 | 761 | if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) |
| 764 | 762 | flag = TTY_NORMAL; |
| 765 | 763 | |
| 766 | − uart_port_unlock(port); | |
| 767 | − sysrq = uart_handle_sysrq_char(port, buf[i]); | |
| 768 | − uart_port_lock(port); | |
| 764 | + sysrq = uart_prepare_sysrq_char(port, buf[i]); | |
| 769 | 765 | if (!sysrq) |
| 770 | 766 | tty_insert_flip_char(tport, buf[i], flag); |
| 771 | 767 | } |
| @@ -825,9 +821,7 @@ static void msm_handle_rx(struct uart_port *port) · 53 unmodified lines | ||
| 825 | 821 | else if (sr & MSM_UART_SR_PAR_FRAME_ERR) |
| 826 | 822 | flag = TTY_FRAME; |
| 827 | 823 | |
| 828 | − uart_port_unlock(port); | |
| 829 | − sysrq = uart_handle_sysrq_char(port, c); | |
| 830 | − uart_port_lock(port); | |
| 824 | + sysrq = uart_prepare_sysrq_char(port, c); | |
| 831 | 825 | if (!sysrq) |
| 832 | 826 | tty_insert_flip_char(tport, c, flag); |
| 833 | 827 | } |
| @@ -948,11 +942,10 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) · 114 unmodified lines | ||
| 948 | 942 | struct uart_port *port = dev_id; |
| 949 | 943 | struct msm_port *msm_port = to_msm_port(port); |
| 950 | 944 | struct msm_dma *dma = &msm_port->rx_dma; |
| 951 | − unsigned long flags; | |
| 952 | 945 | unsigned int misr; |
| 953 | 946 | u32 val; |
| 954 | 947 | |
| 955 | − uart_port_lock_irqsave(port, &flags); | |
| 948 | + uart_port_lock(port); | |
| 956 | 949 | misr = msm_read(port, MSM_UART_MISR); |
| 957 | 950 | msm_write(port, 0, MSM_UART_IMR); /* disable interrupt */ |
| 958 | 951 | |
| @@ -984,7 +977,7 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) · 25 unmodified lines | ||
| 984 | 977 | msm_handle_delta_cts(port); |
| 985 | 978 | |
| 986 | 979 | msm_write(port, msm_port->imr, MSM_UART_IMR); /* restore interrupt */ |
| 987 | − uart_port_unlock_irqrestore(port, flags); | |
| 980 | + uart_unlock_and_check_sysrq(port); | |
| 988 | 981 | |
| 989 | 982 | return IRQ_HANDLED; |
| 990 | 983 | } |
| @@ -1621,14 +1614,10 @@ static void __msm_console_write(struct uart_port *port, const char *s, · 630 unmodified lines | ||
| 1621 | 1614 | num_newlines++; |
| 1622 | 1615 | count += num_newlines; |
| 1623 | 1616 | |
| 1624 | − local_irq_save(flags); | |
| 1625 | − | |
| 1626 | − if (port->sysrq) | |
| 1627 | − locked = 0; | |
| 1628 | − else if (oops_in_progress) | |
| 1629 | − locked = uart_port_trylock(port); | |
| 1617 | + if (oops_in_progress) | |
| 1618 | + locked = uart_port_trylock_irqsave(port, &flags); | |
| 1630 | 1619 | else |
| 1631 | − uart_port_lock(port); | |
| 1620 | + uart_port_lock_irqsave(port, &flags); | |
| 1632 | 1621 | |
| 1633 | 1622 | if (is_uartdm) |
| 1634 | 1623 | msm_reset_dm_count(port, count); |
| @@ -1667,9 +1656,7 @@ static void __msm_console_write(struct uart_port *port, const char *s, · 32 unmodified lines | ||
| 1667 | 1656 | } |
| 1668 | 1657 | |
| 1669 | 1658 | if (locked) |
| 1670 | − uart_port_unlock(port); | |
| 1671 | − | |
| 1672 | − local_irq_restore(flags); | |
| 1659 | + uart_port_unlock_irqrestore(port, flags); | |
| 1673 | 1660 | } |
| 1674 | 1661 | |
| 1675 | 1662 | static void msm_console_write(struct console *co, const char *s, |
| @@ -508,7 +508,7 @@ static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr) · 507 unmodified lines | ||
| 508 | 508 | |
| 509 | 509 | up->port.icount.rx++; |
| 510 | 510 | |
| 511 | − if (uart_handle_sysrq_char(&up->port, ch)) | |
| 511 | + if (uart_prepare_sysrq_char(&up->port, ch)) | |
| 512 | 512 | return; |
| 513 | 513 | |
| 514 | 514 | 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) · 48 unmodified lines | ||
| 563 | 563 | } |
| 564 | 564 | } while (max_count--); |
| 565 | 565 | |
| 566 | − uart_port_unlock(&up->port); | |
| 566 | + uart_unlock_and_check_sysrq(&up->port); | |
| 567 | 567 | |
| 568 | 568 | tty_flip_buffer_push(&up->port.state->port); |
| 569 | 569 | |
| @@ -1212,13 +1212,10 @@ serial_omap_console_write(struct console *co, const char *s, · 642 unmodified lines | ||
| 1212 | 1212 | unsigned int ier; |
| 1213 | 1213 | int locked = 1; |
| 1214 | 1214 | |
| 1215 | − local_irq_save(flags); | |
| 1216 | − if (up->port.sysrq) | |
| 1217 | − locked = 0; | |
| 1218 | − else if (oops_in_progress) | |
| 1219 | − locked = uart_port_trylock(&up->port); | |
| 1215 | + if (oops_in_progress) | |
| 1216 | + locked = uart_port_trylock_irqsave(&up->port, &flags); | |
| 1220 | 1217 | else |
| 1221 | − uart_port_lock(&up->port); | |
| 1218 | + uart_port_lock_irqsave(&up->port, &flags); | |
| 1222 | 1219 | |
| 1223 | 1220 | /* |
| 1224 | 1221 | * First save the IER then disable the interrupts |
| @@ -1245,8 +1242,7 @@ serial_omap_console_write(struct console *co, const char *s, · 20 unmodified lines | ||
| 1245 | 1242 | check_modem_status(up); |
| 1246 | 1243 | |
| 1247 | 1244 | if (locked) |
| 1248 | − uart_port_unlock(&up->port); | |
| 1249 | − local_irq_restore(flags); | |
| 1245 | + uart_port_unlock_irqrestore(&up->port, flags); | |
| 1250 | 1246 | } |
| 1251 | 1247 | |
| 1252 | 1248 | static int __init |
| @@ -199,6 +199,7 @@ static void owl_uart_receive_chars(struct uart_port *port) · 198 unmodified lines | ||
| 199 | 199 | stat = owl_uart_read(port, OWL_UART_STAT); |
| 200 | 200 | while (!(stat & OWL_UART_STAT_RFEM)) { |
| 201 | 201 | char flag = TTY_NORMAL; |
| 202 | + bool sysrq; | |
| 202 | 203 | |
| 203 | 204 | if (stat & OWL_UART_STAT_RXER) |
| 204 | 205 | port->icount.overrun++; |
| @@ -217,7 +218,9 @@ static void owl_uart_receive_chars(struct uart_port *port) · 12 unmodified lines | ||
| 217 | 218 | val = owl_uart_read(port, OWL_UART_RXDAT); |
| 218 | 219 | val &= 0xff; |
| 219 | 220 | |
| 220 | − if ((stat & port->ignore_status_mask) == 0) | |
| 221 | + sysrq = uart_prepare_sysrq_char(port, val); | |
| 222 | + | |
| 223 | + if (!sysrq && (stat & port->ignore_status_mask) == 0) | |
| 221 | 224 | tty_insert_flip_char(&port->state->port, val, flag); |
| 222 | 225 | |
| 223 | 226 | stat = owl_uart_read(port, OWL_UART_STAT); |
| @@ -229,10 +232,9 @@ static void owl_uart_receive_chars(struct uart_port *port) · 5 unmodified lines | ||
| 229 | 232 | static irqreturn_t owl_uart_irq(int irq, void *dev_id) |
| 230 | 233 | { |
| 231 | 234 | struct uart_port *port = dev_id; |
| 232 | − unsigned long flags; | |
| 233 | 235 | u32 stat; |
| 234 | 236 | |
| 235 | − uart_port_lock_irqsave(port, &flags); | |
| 237 | + uart_port_lock(port); | |
| 236 | 238 | |
| 237 | 239 | stat = owl_uart_read(port, OWL_UART_STAT); |
| 238 | 240 | |
| @@ -246,7 +248,7 @@ static irqreturn_t owl_uart_irq(int irq, void *dev_id) · 7 unmodified lines | ||
| 246 | 248 | stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP; |
| 247 | 249 | owl_uart_write(port, stat, OWL_UART_STAT); |
| 248 | 250 | |
| 249 | − uart_port_unlock_irqrestore(port, flags); | |
| 251 | + uart_unlock_and_check_sysrq(port); | |
| 250 | 252 | |
| 251 | 253 | return IRQ_HANDLED; |
| 252 | 254 | } |
| @@ -508,18 +510,12 @@ static void owl_uart_port_write(struct uart_port *port, const char *s, · 255 unmodified lines | ||
| 508 | 510 | { |
| 509 | 511 | u32 old_ctl, val; |
| 510 | 512 | unsigned long flags; |
| 511 | − int locked; | |
| 513 | + int locked = 1; | |
| 512 | 514 | |
| 513 | − local_irq_save(flags); | |
| 514 | − | |
| 515 | − if (port->sysrq) | |
| 516 | − locked = 0; | |
| 517 | − else if (oops_in_progress) | |
| 518 | − locked = uart_port_trylock(port); | |
| 519 | − else { | |
| 520 | − uart_port_lock(port); | |
| 521 | − locked = 1; | |
| 522 | − } | |
| 515 | + if (oops_in_progress) | |
| 516 | + locked = uart_port_trylock_irqsave(port, &flags); | |
| 517 | + else | |
| 518 | + uart_port_lock_irqsave(port, &flags); | |
| 523 | 519 | |
| 524 | 520 | old_ctl = owl_uart_read(port, OWL_UART_CTL); |
| 525 | 521 | 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, · 15 unmodified lines | ||
| 541 | 537 | owl_uart_write(port, old_ctl, OWL_UART_CTL); |
| 542 | 538 | |
| 543 | 539 | if (locked) |
| 544 | − uart_port_unlock(port); | |
| 545 | − | |
| 546 | − local_irq_restore(flags); | |
| 540 | + uart_port_unlock_irqrestore(port, flags); | |
| 547 | 541 | } |
| 548 | 542 | |
| 549 | 543 | static void owl_uart_console_write(struct console *co, const char *s, |
| @@ -237,9 +237,6 @@ struct eg20t_port { · 236 unmodified lines | ||
| 237 | 237 | |
| 238 | 238 | #define IRQ_NAME_SIZE 17 |
| 239 | 239 | char irq_name[IRQ_NAME_SIZE]; |
| 240 | − | |
| 241 | − /* protect the eg20t_port private structure and io access to membase */ | |
| 242 | − spinlock_t lock; | |
| 243 | 240 | }; |
| 244 | 241 | |
| 245 | 242 | /** |
| @@ -567,7 +564,7 @@ static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf, · 321 unmodified lines | ||
| 567 | 564 | if (uart_handle_break(port)) |
| 568 | 565 | continue; |
| 569 | 566 | } |
| 570 | − if (uart_handle_sysrq_char(port, rbr)) | |
| 567 | + if (uart_prepare_sysrq_char(port, rbr)) | |
| 571 | 568 | continue; |
| 572 | 569 | |
| 573 | 570 | buf[i++] = rbr; |
| @@ -599,16 +596,14 @@ static void pch_uart_hal_set_break(struct eg20t_port *priv, int on) · 25 unmodified lines | ||
| 599 | 596 | iowrite8(lcr, priv->membase + UART_LCR); |
| 600 | 597 | } |
| 601 | 598 | |
| 602 | −static int push_rx(struct eg20t_port *priv, const unsigned char *buf, | |
| 603 | − int size) | |
| 599 | +static void push_rx(struct eg20t_port *priv, const unsigned char *buf, | |
| 600 | + int size) | |
| 604 | 601 | { |
| 605 | 602 | struct uart_port *port = &priv->port; |
| 606 | 603 | struct tty_port *tport = &port->state->port; |
| 607 | 604 | |
| 608 | 605 | tty_insert_flip_string(tport, buf, size); |
| 609 | 606 | tty_flip_buffer_push(tport); |
| 610 | − | |
| 611 | − return 0; | |
| 612 | 607 | } |
| 613 | 608 | |
| 614 | 609 | static int dma_push_rx(struct eg20t_port *priv, int size) |
| @@ -761,7 +756,7 @@ static int handle_rx_to(struct eg20t_port *priv) · 146 unmodified lines | ||
| 761 | 756 | { |
| 762 | 757 | struct pch_uart_buffer *buf; |
| 763 | 758 | int rx_size; |
| 764 | − int ret; | |
| 759 | + | |
| 765 | 760 | if (!priv->start_rx) { |
| 766 | 761 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | |
| 767 | 762 | PCH_UART_HAL_RX_ERR_INT); |
| @@ -770,19 +765,12 @@ static int handle_rx_to(struct eg20t_port *priv) · 2 unmodified lines | ||
| 770 | 765 | buf = &priv->rxbuf; |
| 771 | 766 | do { |
| 772 | 767 | rx_size = pch_uart_hal_read(priv, buf->buf, buf->size); |
| 773 | − ret = push_rx(priv, buf->buf, rx_size); | |
| 774 | − if (ret) | |
| 775 | − return 0; | |
| 768 | + push_rx(priv, buf->buf, rx_size); | |
| 776 | 769 | } while (rx_size == buf->size); |
| 777 | 770 | |
| 778 | 771 | return PCH_UART_HANDLED_RX_INT; |
| 779 | 772 | } |
| 780 | 773 | |
| 781 | −static int handle_rx(struct eg20t_port *priv) | |
| 782 | −{ | |
| 783 | − return handle_rx_to(priv); | |
| 784 | −} | |
| 785 | − | |
| 786 | 774 | static int dma_handle_rx(struct eg20t_port *priv) |
| 787 | 775 | { |
| 788 | 776 | struct uart_port *port = &priv->port; |
| @@ -1019,11 +1007,10 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) · 230 unmodified lines | ||
| 1019 | 1007 | u8 lsr; |
| 1020 | 1008 | int ret = 0; |
| 1021 | 1009 | unsigned char iid; |
| 1022 | − unsigned long flags; | |
| 1023 | 1010 | int next = 1; |
| 1024 | 1011 | u8 msr; |
| 1025 | 1012 | |
| 1026 | − spin_lock_irqsave(&priv->lock, flags); | |
| 1013 | + uart_port_lock(&priv->port); | |
| 1027 | 1014 | handled = 0; |
| 1028 | 1015 | while (next) { |
| 1029 | 1016 | iid = pch_uart_hal_get_iid(priv); |
| @@ -1051,7 +1038,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) · 21 unmodified lines | ||
| 1051 | 1038 | PCH_UART_HAL_RX_INT | |
| 1052 | 1039 | PCH_UART_HAL_RX_ERR_INT); |
| 1053 | 1040 | } else { |
| 1054 | − ret = handle_rx(priv); | |
| 1041 | + ret = handle_rx_to(priv); | |
| 1055 | 1042 | } |
| 1056 | 1043 | break; |
| 1057 | 1044 | case PCH_UART_IID_RDR_TO: /* Received Data Ready |
| @@ -1083,7 +1070,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) · 25 unmodified lines | ||
| 1083 | 1070 | handled |= (unsigned int)ret; |
| 1084 | 1071 | } |
| 1085 | 1072 | |
| 1086 | − spin_unlock_irqrestore(&priv->lock, flags); | |
| 1073 | + uart_unlock_and_check_sysrq(&priv->port); | |
| 1087 | 1074 | return IRQ_RETVAL(handled); |
| 1088 | 1075 | } |
| 1089 | 1076 | |
| @@ -1194,9 +1181,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl) · 104 unmodified lines | ||
| 1194 | 1181 | unsigned long flags; |
| 1195 | 1182 | |
| 1196 | 1183 | priv = container_of(port, struct eg20t_port, port); |
| 1197 | − spin_lock_irqsave(&priv->lock, flags); | |
| 1184 | + uart_port_lock_irqsave(&priv->port, &flags); | |
| 1198 | 1185 | pch_uart_hal_set_break(priv, ctl); |
| 1199 | − spin_unlock_irqrestore(&priv->lock, flags); | |
| 1186 | + uart_port_unlock_irqrestore(&priv->port, flags); | |
| 1200 | 1187 | } |
| 1201 | 1188 | |
| 1202 | 1189 | /* 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, · 143 unmodified lines | ||
| 1346 | 1333 | |
| 1347 | 1334 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); |
| 1348 | 1335 | |
| 1349 | − spin_lock_irqsave(&priv->lock, flags); | |
| 1350 | − uart_port_lock(port); | |
| 1336 | + uart_port_lock_irqsave(port, &flags); | |
| 1351 | 1337 | |
| 1352 | 1338 | uart_update_timeout(port, termios->c_cflag, baud); |
| 1353 | 1339 | 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, · 6 unmodified lines | ||
| 1360 | 1346 | tty_termios_encode_baud_rate(termios, baud, baud); |
| 1361 | 1347 | |
| 1362 | 1348 | out: |
| 1363 | − uart_port_unlock(port); | |
| 1364 | − spin_unlock_irqrestore(&priv->lock, flags); | |
| 1349 | + uart_port_unlock_irqrestore(port, flags); | |
| 1365 | 1350 | } |
| 1366 | 1351 | |
| 1367 | 1352 | 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) · 197 unmodified lines | ||
| 1565 | 1550 | { |
| 1566 | 1551 | struct eg20t_port *priv; |
| 1567 | 1552 | unsigned long flags; |
| 1568 | − int priv_locked = 1; | |
| 1569 | − int port_locked = 1; | |
| 1553 | + int locked = 1; | |
| 1570 | 1554 | u8 ier; |
| 1571 | 1555 | |
| 1572 | 1556 | priv = pch_uart_ports[co->index]; |
| 1573 | 1557 | |
| 1574 | 1558 | touch_nmi_watchdog(); |
| 1575 | 1559 | |
| 1576 | − local_irq_save(flags); | |
| 1577 | − if (priv->port.sysrq) { | |
| 1578 | − /* call to uart_handle_sysrq_char already took the priv lock */ | |
| 1579 | − priv_locked = 0; | |
| 1580 | − /* serial8250_handle_port() already took the port lock */ | |
| 1581 | − port_locked = 0; | |
| 1582 | − } else if (oops_in_progress) { | |
| 1583 | − priv_locked = spin_trylock(&priv->lock); | |
| 1584 | − port_locked = uart_port_trylock(&priv->port); | |
| 1585 | − } else { | |
| 1586 | − spin_lock(&priv->lock); | |
| 1587 | − uart_port_lock(&priv->port); | |
| 1588 | − } | |
| 1560 | + if (oops_in_progress) | |
| 1561 | + locked = uart_port_trylock_irqsave(&priv->port, &flags); | |
| 1562 | + else | |
| 1563 | + uart_port_lock_irqsave(&priv->port, &flags); | |
| 1589 | 1564 | |
| 1590 | 1565 | /* |
| 1591 | 1566 | * First save the IER then disable the interrupts |
| @@ -1603,11 +1578,8 @@ pch_console_write(struct console *co, const char *s, unsigned int count) · 11 unmodified lines | ||
| 1603 | 1578 | wait_for_xmitr(priv, UART_LSR_BOTH_EMPTY); |
| 1604 | 1579 | iowrite8(ier, priv->membase + UART_IER); |
| 1605 | 1580 | |
| 1606 | − if (port_locked) | |
| 1607 | − uart_port_unlock(&priv->port); | |
| 1608 | − if (priv_locked) | |
| 1609 | − spin_unlock(&priv->lock); | |
| 1610 | − local_irq_restore(flags); | |
| 1581 | + if (locked) | |
| 1582 | + uart_port_unlock_irqrestore(&priv->port, flags); | |
| 1611 | 1583 | } |
| 1612 | 1584 | |
| 1613 | 1585 | 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, · 90 unmodified lines | ||
| 1704 | 1676 | pci_enable_msi(pdev); |
| 1705 | 1677 | pci_set_master(pdev); |
| 1706 | 1678 | |
| 1707 | − spin_lock_init(&priv->lock); | |
| 1708 | − | |
| 1709 | 1679 | iobase = pci_resource_start(pdev, 0); |
| 1710 | 1680 | mapbase = pci_resource_start(pdev, 1); |
| 1711 | 1681 | priv->mapbase = mapbase; |
| @@ -1735,8 +1705,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, · 23 unmodified lines | ||
| 1735 | 1705 | KBUILD_MODNAME ":" PCH_UART_DRIVER_DEVICE "%d", |
| 1736 | 1706 | priv->port.line); |
| 1737 | 1707 | |
| 1738 | − spin_lock_init(&priv->port.lock); | |
| 1739 | − | |
| 1740 | 1708 | pci_set_drvdata(pdev, priv); |
| 1741 | 1709 | priv->trigger_level = 1; |
| 1742 | 1710 | priv->fcr = 0; |
| @@ -1714,18 +1714,13 @@ static int __init pmz_attach(struct platform_device *pdev) · 1713 unmodified lines | ||
| 1714 | 1714 | return uart_add_one_port(&pmz_uart_reg, &uap->port); |
| 1715 | 1715 | } |
| 1716 | 1716 | |
| 1717 | −static int __exit pmz_detach(struct platform_device *pdev) | |
| 1717 | +static void __exit pmz_detach(struct platform_device *pdev) | |
| 1718 | 1718 | { |
| 1719 | 1719 | struct uart_pmac_port *uap = platform_get_drvdata(pdev); |
| 1720 | 1720 | |
| 1721 | − if (!uap) | |
| 1722 | − return -ENODEV; | |
| 1723 | − | |
| 1724 | 1721 | uart_remove_one_port(&pmz_uart_reg, &uap->port); |
| 1725 | 1722 | |
| 1726 | 1723 | uap->port.dev = NULL; |
| 1727 | − | |
| 1728 | − return 0; | |
| 1729 | 1724 | } |
| 1730 | 1725 | |
| 1731 | 1726 | #endif /* !CONFIG_PPC_PMAC */ |
| @@ -1794,7 +1789,7 @@ static struct macio_driver pmz_driver = { · 62 unmodified lines | ||
| 1794 | 1789 | #else |
| 1795 | 1790 | |
| 1796 | 1791 | static struct platform_driver pmz_driver = { |
| 1797 | − .remove = __exit_p(pmz_detach), | |
| 1792 | + .remove_new = __exit_p(pmz_detach), | |
| 1798 | 1793 | .driver = { |
| 1799 | 1794 | .name = "scc", |
| 1800 | 1795 | }, |
| @@ -151,7 +151,7 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status) · 150 unmodified lines | ||
| 151 | 151 | flag = TTY_FRAME; |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | − if (uart_handle_sysrq_char(&up->port, ch)) | |
| 154 | + if (uart_prepare_sysrq_char(&up->port, ch)) | |
| 155 | 155 | goto ignore_char; |
| 156 | 156 | |
| 157 | 157 | 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) · 74 unmodified lines | ||
| 232 | 232 | check_modem_status(up); |
| 233 | 233 | if (lsr & UART_LSR_THRE) |
| 234 | 234 | transmit_chars(up); |
| 235 | − uart_port_unlock(&up->port); | |
| 235 | + uart_unlock_and_check_sysrq(&up->port); | |
| 236 | 236 | return IRQ_HANDLED; |
| 237 | 237 | } |
| 238 | 238 | |
| @@ -604,13 +604,10 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) · 365 unmodified lines | ||
| 604 | 604 | int locked = 1; |
| 605 | 605 | |
| 606 | 606 | clk_enable(up->clk); |
| 607 | − local_irq_save(flags); | |
| 608 | − if (up->port.sysrq) | |
| 609 | − locked = 0; | |
| 610 | − else if (oops_in_progress) | |
| 611 | − locked = uart_port_trylock(&up->port); | |
| 607 | + if (oops_in_progress) | |
| 608 | + locked = uart_port_trylock_irqsave(&up->port, &flags); | |
| 612 | 609 | else |
| 613 | − uart_port_lock(&up->port); | |
| 610 | + uart_port_lock_irqsave(&up->port, &flags); | |
| 614 | 611 | |
| 615 | 612 | /* |
| 616 | 613 | * 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) · 11 unmodified lines | ||
| 628 | 625 | serial_out(up, UART_IER, ier); |
| 629 | 626 | |
| 630 | 627 | if (locked) |
| 631 | − uart_port_unlock(&up->port); | |
| 632 | − local_irq_restore(flags); | |
| 628 | + uart_port_unlock_irqrestore(&up->port, flags); | |
| 633 | 629 | clk_disable(up->clk); |
| 634 | − | |
| 635 | 630 | } |
| 636 | 631 | |
| 637 | 632 | #ifdef CONFIG_CONSOLE_POLL |
| @@ -488,18 +488,16 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, · 487 unmodified lines | ||
| 488 | 488 | |
| 489 | 489 | geni_status = readl(uport->membase + SE_GENI_STATUS); |
| 490 | 490 | |
| 491 | − /* Cancel the current write to log the fault */ | |
| 492 | 491 | if (!locked) { |
| 493 | − geni_se_cancel_m_cmd(&port->se); | |
| 494 | − if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, | |
| 495 | − M_CMD_CANCEL_EN, true)) { | |
| 496 | − geni_se_abort_m_cmd(&port->se); | |
| 497 | − qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, | |
| 498 | − M_CMD_ABORT_EN, true); | |
| 499 | − writel(M_CMD_ABORT_EN, uport->membase + | |
| 500 | − SE_GENI_M_IRQ_CLEAR); | |
| 501 | − } | |
| 502 | − writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); | |
| 492 | + /* | |
| 493 | + * We can only get here if an oops is in progress then we were | |
| 494 | + * unable to get the lock. This means we can't safely access | |
| 495 | + * our state variables like tx_remaining. About the best we | |
| 496 | + * can do is wait for the FIFO to be empty before we start our | |
| 497 | + * transfer, so we'll do that. | |
| 498 | + */ | |
| 499 | + qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, | |
| 500 | + M_TX_FIFO_NOT_EMPTY_EN, false); | |
| 503 | 501 | } else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) { |
| 504 | 502 | /* |
| 505 | 503 | * 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, · 10 unmodified lines | ||
| 516 | 514 | |
| 517 | 515 | __qcom_geni_serial_console_write(uport, s, count); |
| 518 | 516 | |
| 519 | − if (port->tx_remaining) | |
| 520 | − qcom_geni_serial_setup_tx(uport, port->tx_remaining); | |
| 521 | 517 | |
| 522 | − if (locked) | |
| 518 | + if (locked) { | |
| 519 | + if (port->tx_remaining) | |
| 520 | + qcom_geni_serial_setup_tx(uport, port->tx_remaining); | |
| 523 | 521 | uart_port_unlock_irqrestore(uport, flags); |
| 522 | + } | |
| 524 | 523 | } |
| 525 | 524 | |
| 526 | 525 | static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop) |
| @@ -394,7 +394,8 @@ static void rda_uart_receive_chars(struct uart_port *port) · 393 unmodified lines | ||
| 394 | 394 | val &= 0xff; |
| 395 | 395 | |
| 396 | 396 | port->icount.rx++; |
| 397 | − tty_insert_flip_char(&port->state->port, val, flag); | |
| 397 | + if (!uart_prepare_sysrq_char(port, val)) | |
| 398 | + tty_insert_flip_char(&port->state->port, val, flag); | |
| 398 | 399 | |
| 399 | 400 | status = rda_uart_read(port, RDA_UART_STATUS); |
| 400 | 401 | } |
| @@ -405,10 +406,9 @@ static void rda_uart_receive_chars(struct uart_port *port) · 4 unmodified lines | ||
| 405 | 406 | static irqreturn_t rda_interrupt(int irq, void *dev_id) |
| 406 | 407 | { |
| 407 | 408 | struct uart_port *port = dev_id; |
| 408 | − unsigned long flags; | |
| 409 | 409 | u32 val, irq_mask; |
| 410 | 410 | |
| 411 | − uart_port_lock_irqsave(port, &flags); | |
| 411 | + uart_port_lock(port); | |
| 412 | 412 | |
| 413 | 413 | /* Clear IRQ cause */ |
| 414 | 414 | val = rda_uart_read(port, RDA_UART_IRQ_CAUSE); |
| @@ -425,7 +425,7 @@ static irqreturn_t rda_interrupt(int irq, void *dev_id) · 10 unmodified lines | ||
| 425 | 425 | rda_uart_send_chars(port); |
| 426 | 426 | } |
| 427 | 427 | |
| 428 | − uart_port_unlock_irqrestore(port, flags); | |
| 428 | + uart_unlock_and_check_sysrq(port); | |
| 429 | 429 | |
| 430 | 430 | return IRQ_HANDLED; |
| 431 | 431 | } |
| @@ -590,18 +590,12 @@ static void rda_uart_port_write(struct uart_port *port, const char *s, · 158 unmodified lines | ||
| 590 | 590 | { |
| 591 | 591 | u32 old_irq_mask; |
| 592 | 592 | unsigned long flags; |
| 593 | − int locked; | |
| 594 | − | |
| 595 | − local_irq_save(flags); | |
| 593 | + int locked = 1; | |
| 596 | 594 | |
| 597 | − if (port->sysrq) { | |
| 598 | − locked = 0; | |
| 599 | − } else if (oops_in_progress) { | |
| 600 | − locked = uart_port_trylock(port); | |
| 601 | − } else { | |
| 602 | − uart_port_lock(port); | |
| 603 | − locked = 1; | |
| 604 | − } | |
| 595 | + if (oops_in_progress) | |
| 596 | + locked = uart_port_trylock_irqsave(port, &flags); | |
| 597 | + else | |
| 598 | + uart_port_lock_irqsave(port, &flags); | |
| 605 | 599 | |
| 606 | 600 | old_irq_mask = rda_uart_read(port, RDA_UART_IRQ_MASK); |
| 607 | 601 | 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, · 7 unmodified lines | ||
| 615 | 609 | rda_uart_write(port, old_irq_mask, RDA_UART_IRQ_MASK); |
| 616 | 610 | |
| 617 | 611 | if (locked) |
| 618 | − uart_port_unlock(port); | |
| 619 | − | |
| 620 | − local_irq_restore(flags); | |
| 612 | + uart_port_unlock_irqrestore(port, flags); | |
| 621 | 613 | } |
| 622 | 614 | |
| 623 | 615 | static void rda_uart_console_write(struct console *co, const char *s, |
| @@ -21,26 +21,28 @@ · 20 unmodified lines | ||
| 21 | 21 | * BJD, 04-Nov-2004 |
| 22 | 22 | */ |
| 23 | 23 | |
| 24 | −#include <linux/dmaengine.h> | |
| 24 | +#include <linux/console.h> | |
| 25 | +#include <linux/clk.h> | |
| 26 | +#include <linux/cpufreq.h> | |
| 27 | +#include <linux/delay.h> | |
| 25 | 28 | #include <linux/dma-mapping.h> |
| 26 | −#include <linux/slab.h> | |
| 29 | +#include <linux/dmaengine.h> | |
| 30 | +#include <linux/init.h> | |
| 31 | +#include <linux/io.h> | |
| 32 | +#include <linux/ioport.h> | |
| 27 | 33 | #include <linux/math.h> |
| 28 | 34 | #include <linux/module.h> |
| 29 | −#include <linux/ioport.h> | |
| 30 | −#include <linux/io.h> | |
| 35 | +#include <linux/of.h> | |
| 31 | 36 | #include <linux/platform_device.h> |
| 32 | −#include <linux/init.h> | |
| 37 | +#include <linux/serial.h> | |
| 38 | +#include <linux/serial_core.h> | |
| 39 | +#include <linux/serial_s3c.h> | |
| 40 | +#include <linux/slab.h> | |
| 33 | 41 | #include <linux/sysrq.h> |
| 34 | −#include <linux/console.h> | |
| 35 | 42 | #include <linux/tty.h> |
| 36 | 43 | #include <linux/tty_flip.h> |
| 37 | −#include <linux/serial_core.h> | |
| 38 | −#include <linux/serial.h> | |
| 39 | −#include <linux/serial_s3c.h> | |
| 40 | −#include <linux/delay.h> | |
| 41 | −#include <linux/clk.h> | |
| 42 | −#include <linux/cpufreq.h> | |
| 43 | −#include <linux/of.h> | |
| 44 | +#include <linux/types.h> | |
| 45 | + | |
| 44 | 46 | #include <asm/irq.h> |
| 45 | 47 | |
| 46 | 48 | /* UART name and device definitions */ |
| @@ -73,21 +75,21 @@ struct s3c24xx_uart_info { · 26 unmodified lines | ||
| 73 | 75 | enum s3c24xx_port_type type; |
| 74 | 76 | unsigned int port_type; |
| 75 | 77 | unsigned int fifosize; |
| 76 | − unsigned long rx_fifomask; | |
| 77 | − unsigned long rx_fifoshift; | |
| 78 | − unsigned long rx_fifofull; | |
| 79 | − unsigned long tx_fifomask; | |
| 80 | − unsigned long tx_fifoshift; | |
| 81 | − unsigned long tx_fifofull; | |
| 82 | − unsigned int def_clk_sel; | |
| 83 | − unsigned long num_clks; | |
| 84 | − unsigned long clksel_mask; | |
| 85 | − unsigned long clksel_shift; | |
| 86 | − unsigned long ucon_mask; | |
| 78 | + u32 rx_fifomask; | |
| 79 | + u32 rx_fifoshift; | |
| 80 | + u32 rx_fifofull; | |
| 81 | + u32 tx_fifomask; | |
| 82 | + u32 tx_fifoshift; | |
| 83 | + u32 tx_fifofull; | |
| 84 | + u32 clksel_mask; | |
| 85 | + u32 clksel_shift; | |
| 86 | + u32 ucon_mask; | |
| 87 | + u8 def_clk_sel; | |
| 88 | + u8 num_clks; | |
| 89 | + u8 iotype; | |
| 87 | 90 | |
| 88 | 91 | /* uart port features */ |
| 89 | − | |
| 90 | − unsigned int has_divslot:1; | |
| 92 | + bool has_divslot; | |
| 91 | 93 | }; |
| 92 | 94 | |
| 93 | 95 | struct s3c24xx_serial_drv_data { |
| @@ -196,7 +198,7 @@ static void wr_reg(const struct uart_port *port, u32 reg, u32 val) · 102 unmodified lines | ||
| 196 | 198 | /* Byte-order aware bit setting/clearing functions. */ |
| 197 | 199 | |
| 198 | 200 | static inline void s3c24xx_set_bit(const struct uart_port *port, int idx, |
| 199 | − unsigned int reg) | |
| 201 | + u32 reg) | |
| 200 | 202 | { |
| 201 | 203 | unsigned long flags; |
| 202 | 204 | u32 val; |
| @@ -209,7 +211,7 @@ static inline void s3c24xx_set_bit(const struct uart_port *port, int idx, · 6 unmodified lines | ||
| 209 | 211 | } |
| 210 | 212 | |
| 211 | 213 | static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx, |
| 212 | − unsigned int reg) | |
| 214 | + u32 reg) | |
| 213 | 215 | { |
| 214 | 216 | unsigned long flags; |
| 215 | 217 | u32 val; |
| @@ -233,7 +235,7 @@ static inline const char *s3c24xx_serial_portname(const struct uart_port *port) · 17 unmodified lines | ||
| 233 | 235 | return to_platform_device(port->dev)->name; |
| 234 | 236 | } |
| 235 | 237 | |
| 236 | −static int s3c24xx_serial_txempty_nofifo(const struct uart_port *port) | |
| 238 | +static bool s3c24xx_serial_txempty_nofifo(const struct uart_port *port) | |
| 237 | 239 | { |
| 238 | 240 | return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE; |
| 239 | 241 | } |
| @@ -242,8 +244,8 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port) · 2 unmodified lines | ||
| 242 | 244 | { |
| 243 | 245 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 244 | 246 | unsigned long flags; |
| 245 | − unsigned int ucon, ufcon; | |
| 246 | 247 | int count = 10000; |
| 248 | + u32 ucon, ufcon; | |
| 247 | 249 | |
| 248 | 250 | uart_port_lock_irqsave(port, &flags); |
| 249 | 251 | |
| @@ -266,7 +268,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port) · 16 unmodified lines | ||
| 266 | 268 | { |
| 267 | 269 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 268 | 270 | unsigned long flags; |
| 269 | − unsigned int ucon; | |
| 271 | + u32 ucon; | |
| 270 | 272 | |
| 271 | 273 | uart_port_lock_irqsave(port, &flags); |
| 272 | 274 | |
| @@ -587,8 +589,8 @@ static inline const struct s3c2410_uartcfg · 314 unmodified lines | ||
| 587 | 589 | return ourport->cfg; |
| 588 | 590 | } |
| 589 | 591 | |
| 590 | −static int s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport, | |
| 591 | − unsigned long ufstat) | |
| 592 | +static unsigned int | |
| 593 | +s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport, u32 ufstat) | |
| 592 | 594 | { |
| 593 | 595 | const struct s3c24xx_uart_info *info = ourport->info; |
| 594 | 596 | |
| @@ -660,7 +662,7 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport) · 65 unmodified lines | ||
| 660 | 662 | static void enable_rx_dma(struct s3c24xx_uart_port *ourport) |
| 661 | 663 | { |
| 662 | 664 | struct uart_port *port = &ourport->port; |
| 663 | − unsigned int ucon; | |
| 665 | + u32 ucon; | |
| 664 | 666 | |
| 665 | 667 | /* set Rx mode to DMA mode */ |
| 666 | 668 | ucon = rd_regl(port, S3C2410_UCON); |
| @@ -683,7 +685,7 @@ static void enable_rx_dma(struct s3c24xx_uart_port *ourport) · 16 unmodified lines | ||
| 683 | 685 | static void enable_rx_pio(struct s3c24xx_uart_port *ourport) |
| 684 | 686 | { |
| 685 | 687 | struct uart_port *port = &ourport->port; |
| 686 | − unsigned int ucon; | |
| 688 | + u32 ucon; | |
| 687 | 689 | |
| 688 | 690 | /* set Rx mode to DMA mode */ |
| 689 | 691 | ucon = rd_regl(port, S3C2410_UCON); |
| @@ -708,13 +710,14 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport); · 18 unmodified lines | ||
| 708 | 710 | |
| 709 | 711 | static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) |
| 710 | 712 | { |
| 711 | − unsigned int utrstat, received; | |
| 712 | 713 | struct s3c24xx_uart_port *ourport = dev_id; |
| 713 | 714 | struct uart_port *port = &ourport->port; |
| 714 | 715 | struct s3c24xx_uart_dma *dma = ourport->dma; |
| 715 | 716 | struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port); |
| 716 | 717 | struct tty_port *t = &port->state->port; |
| 717 | 718 | struct dma_tx_state state; |
| 719 | + unsigned int received; | |
| 720 | + u32 utrstat; | |
| 718 | 721 | |
| 719 | 722 | utrstat = rd_regl(port, S3C2410_UTRSTAT); |
| 720 | 723 | rd_regl(port, S3C2410_UFSTAT); |
| @@ -756,9 +759,9 @@ finish: · 35 unmodified lines | ||
| 756 | 759 | static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) |
| 757 | 760 | { |
| 758 | 761 | struct uart_port *port = &ourport->port; |
| 759 | − unsigned int ufcon, ufstat, uerstat; | |
| 762 | + unsigned int max_count = port->fifosize; | |
| 760 | 763 | unsigned int fifocnt = 0; |
| 761 | − int max_count = port->fifosize; | |
| 764 | + u32 ufcon, ufstat, uerstat; | |
| 762 | 765 | u8 ch, flag; |
| 763 | 766 | |
| 764 | 767 | while (max_count-- > 0) { |
| @@ -778,7 +781,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) · 13 unmodified lines | ||
| 778 | 781 | ch = rd_reg(port, S3C2410_URXH); |
| 779 | 782 | |
| 780 | 783 | if (port->flags & UPF_CONS_FLOW) { |
| 781 | − int txe = s3c24xx_serial_txempty_nofifo(port); | |
| 784 | + bool txe = s3c24xx_serial_txempty_nofifo(port); | |
| 782 | 785 | |
| 783 | 786 | if (ourport->rx_enabled) { |
| 784 | 787 | if (!txe) { |
| @@ -942,7 +945,7 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) · 157 unmodified lines | ||
| 942 | 945 | { |
| 943 | 946 | const struct s3c24xx_uart_port *ourport = id; |
| 944 | 947 | const struct uart_port *port = &ourport->port; |
| 945 | − unsigned int pend = rd_regl(port, S3C64XX_UINTP); | |
| 948 | + u32 pend = rd_regl(port, S3C64XX_UINTP); | |
| 946 | 949 | irqreturn_t ret = IRQ_HANDLED; |
| 947 | 950 | |
| 948 | 951 | if (pend & S3C64XX_UINTM_RXD_MSK) { |
| @@ -961,7 +964,7 @@ static irqreturn_t apple_serial_handle_irq(int irq, void *id) · 12 unmodified lines | ||
| 961 | 964 | { |
| 962 | 965 | const struct s3c24xx_uart_port *ourport = id; |
| 963 | 966 | const struct uart_port *port = &ourport->port; |
| 964 | − unsigned int pend = rd_regl(port, S3C2410_UTRSTAT); | |
| 967 | + u32 pend = rd_regl(port, S3C2410_UTRSTAT); | |
| 965 | 968 | irqreturn_t ret = IRQ_NONE; |
| 966 | 969 | |
| 967 | 970 | 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) · 12 unmodified lines | ||
| 980 | 983 | static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) |
| 981 | 984 | { |
| 982 | 985 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 983 | − unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT); | |
| 984 | − unsigned long ufcon = rd_regl(port, S3C2410_UFCON); | |
| 986 | + u32 ufstat = rd_regl(port, S3C2410_UFSTAT); | |
| 987 | + u32 ufcon = rd_regl(port, S3C2410_UFCON); | |
| 985 | 988 | |
| 986 | 989 | if (ufcon & S3C2410_UFCON_FIFOMODE) { |
| 987 | − if ((ufstat & info->tx_fifomask) != 0 || | |
| 990 | + if ((ufstat & info->tx_fifomask) || | |
| 988 | 991 | (ufstat & info->tx_fifofull)) |
| 989 | 992 | return 0; |
| 990 | − | |
| 991 | − return 1; | |
| 993 | + return TIOCSER_TEMT; | |
| 992 | 994 | } |
| 993 | 995 | |
| 994 | − return s3c24xx_serial_txempty_nofifo(port); | |
| 996 | + return s3c24xx_serial_txempty_nofifo(port) ? TIOCSER_TEMT : 0; | |
| 995 | 997 | } |
| 996 | 998 | |
| 997 | 999 | /* no modem control lines */ |
| 998 | 1000 | static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) |
| 999 | 1001 | { |
| 1000 | − unsigned int umstat = rd_reg(port, S3C2410_UMSTAT); | |
| 1002 | + u32 umstat = rd_reg(port, S3C2410_UMSTAT); | |
| 1001 | 1003 | |
| 1002 | 1004 | if (umstat & S3C2410_UMSTAT_CTS) |
| 1003 | 1005 | return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; |
| @@ -1007,8 +1009,8 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) · 3 unmodified lines | ||
| 1007 | 1009 | |
| 1008 | 1010 | static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) |
| 1009 | 1011 | { |
| 1010 | − unsigned int umcon = rd_regl(port, S3C2410_UMCON); | |
| 1011 | − unsigned int ucon = rd_regl(port, S3C2410_UCON); | |
| 1012 | + u32 umcon = rd_regl(port, S3C2410_UMCON); | |
| 1013 | + u32 ucon = rd_regl(port, S3C2410_UCON); | |
| 1012 | 1014 | |
| 1013 | 1015 | if (mctrl & TIOCM_RTS) |
| 1014 | 1016 | umcon |= S3C2410_UMCOM_RTS_LOW; |
| @@ -1028,7 +1030,7 @@ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) · 13 unmodified lines | ||
| 1028 | 1030 | static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) |
| 1029 | 1031 | { |
| 1030 | 1032 | unsigned long flags; |
| 1031 | − unsigned int ucon; | |
| 1033 | + u32 ucon; | |
| 1032 | 1034 | |
| 1033 | 1035 | uart_port_lock_irqsave(port, &flags); |
| 1034 | 1036 | |
| @@ -1186,7 +1188,7 @@ static void apple_s5l_serial_shutdown(struct uart_port *port) · 151 unmodified lines | ||
| 1186 | 1188 | { |
| 1187 | 1189 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 1188 | 1190 | |
| 1189 | − unsigned int ucon; | |
| 1191 | + u32 ucon; | |
| 1190 | 1192 | |
| 1191 | 1193 | ucon = rd_regl(port, S3C2410_UCON); |
| 1192 | 1194 | ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK | |
| @@ -1212,7 +1214,7 @@ static int s3c64xx_serial_startup(struct uart_port *port) · 19 unmodified lines | ||
| 1212 | 1214 | { |
| 1213 | 1215 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 1214 | 1216 | unsigned long flags; |
| 1215 | − unsigned int ufcon; | |
| 1217 | + u32 ufcon; | |
| 1216 | 1218 | int ret; |
| 1217 | 1219 | |
| 1218 | 1220 | wr_regl(port, S3C64XX_UINTM, 0xf); |
| @@ -1257,7 +1259,7 @@ static int apple_s5l_serial_startup(struct uart_port *port) · 38 unmodified lines | ||
| 1257 | 1259 | { |
| 1258 | 1260 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 1259 | 1261 | unsigned long flags; |
| 1260 | − unsigned int ufcon; | |
| 1262 | + u32 ufcon; | |
| 1261 | 1263 | int ret; |
| 1262 | 1264 | |
| 1263 | 1265 | wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS); |
| @@ -1292,8 +1294,6 @@ static int apple_s5l_serial_startup(struct uart_port *port) · 28 unmodified lines | ||
| 1292 | 1294 | return ret; |
| 1293 | 1295 | } |
| 1294 | 1296 | |
| 1295 | −/* power power management control */ | |
| 1296 | − | |
| 1297 | 1297 | static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, |
| 1298 | 1298 | unsigned int old) |
| 1299 | 1299 | { |
| @@ -1339,10 +1339,10 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, · 39 unmodified lines | ||
| 1339 | 1339 | |
| 1340 | 1340 | #define MAX_CLK_NAME_LENGTH 15 |
| 1341 | 1341 | |
| 1342 | −static inline int s3c24xx_serial_getsource(struct uart_port *port) | |
| 1342 | +static inline u8 s3c24xx_serial_getsource(struct uart_port *port) | |
| 1343 | 1343 | { |
| 1344 | 1344 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 1345 | − unsigned int ucon; | |
| 1345 | + u32 ucon; | |
| 1346 | 1346 | |
| 1347 | 1347 | if (info->num_clks == 1) |
| 1348 | 1348 | return 0; |
| @@ -1352,11 +1352,10 @@ static inline int s3c24xx_serial_getsource(struct uart_port *port) · 3 unmodified lines | ||
| 1352 | 1352 | return ucon >> info->clksel_shift; |
| 1353 | 1353 | } |
| 1354 | 1354 | |
| 1355 | −static void s3c24xx_serial_setsource(struct uart_port *port, | |
| 1356 | − unsigned int clk_sel) | |
| 1355 | +static void s3c24xx_serial_setsource(struct uart_port *port, u8 clk_sel) | |
| 1357 | 1356 | { |
| 1358 | 1357 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 1359 | − unsigned int ucon; | |
| 1358 | + u32 ucon; | |
| 1360 | 1359 | |
| 1361 | 1360 | if (info->num_clks == 1) |
| 1362 | 1361 | return; |
| @@ -1372,14 +1371,15 @@ static void s3c24xx_serial_setsource(struct uart_port *port, · 9 unmodified lines | ||
| 1372 | 1371 | |
| 1373 | 1372 | static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, |
| 1374 | 1373 | unsigned int req_baud, struct clk **best_clk, |
| 1375 | − unsigned int *clk_num) | |
| 1374 | + u8 *clk_num) | |
| 1376 | 1375 | { |
| 1377 | 1376 | const struct s3c24xx_uart_info *info = ourport->info; |
| 1378 | 1377 | struct clk *clk; |
| 1379 | 1378 | unsigned long rate; |
| 1380 | − unsigned int cnt, baud, quot, best_quot = 0; | |
| 1379 | + unsigned int baud, quot, best_quot = 0; | |
| 1381 | 1380 | char clkname[MAX_CLK_NAME_LENGTH]; |
| 1382 | 1381 | int calc_deviation, deviation = (1 << 30) - 1; |
| 1382 | + u8 cnt; | |
| 1383 | 1383 | |
| 1384 | 1384 | for (cnt = 0; cnt < info->num_clks; cnt++) { |
| 1385 | 1385 | /* Keep selected clock if provided */ |
| @@ -1472,10 +1472,10 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, · 86 unmodified lines | ||
| 1472 | 1472 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 1473 | 1473 | struct clk *clk = ERR_PTR(-EINVAL); |
| 1474 | 1474 | unsigned long flags; |
| 1475 | − unsigned int baud, quot, clk_sel = 0; | |
| 1476 | − unsigned int ulcon; | |
| 1477 | − unsigned int umcon; | |
| 1475 | + unsigned int baud, quot; | |
| 1478 | 1476 | unsigned int udivslot = 0; |
| 1477 | + u32 ulcon, umcon; | |
| 1478 | + u8 clk_sel = 0; | |
| 1479 | 1479 | |
| 1480 | 1480 | /* |
| 1481 | 1481 | * We don't support modem control lines. |
| @@ -1737,12 +1737,12 @@ static struct uart_driver s3c24xx_uart_drv = { · 255 unmodified lines | ||
| 1737 | 1737 | |
| 1738 | 1738 | static struct s3c24xx_uart_port s3c24xx_serial_ports[UART_NR]; |
| 1739 | 1739 | |
| 1740 | −static void s3c24xx_serial_init_port_default(int index) { | |
| 1740 | +static void s3c24xx_serial_init_port_default(int index) | |
| 1741 | +{ | |
| 1741 | 1742 | struct uart_port *port = &s3c24xx_serial_ports[index].port; |
| 1742 | 1743 | |
| 1743 | 1744 | spin_lock_init(&port->lock); |
| 1744 | 1745 | |
| 1745 | − port->iotype = UPIO_MEM; | |
| 1746 | 1746 | port->uartclk = 0; |
| 1747 | 1747 | port->fifosize = 16; |
| 1748 | 1748 | port->flags = UPF_BOOT_AUTOCONF; |
| @@ -1758,7 +1758,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port, · 9 unmodified lines | ||
| 1758 | 1758 | const struct s3c2410_uartcfg *cfg) |
| 1759 | 1759 | { |
| 1760 | 1760 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 1761 | − unsigned long ucon = rd_regl(port, S3C2410_UCON); | |
| 1761 | + u32 ucon = rd_regl(port, S3C2410_UCON); | |
| 1762 | 1762 | |
| 1763 | 1763 | ucon &= (info->clksel_mask | info->ucon_mask); |
| 1764 | 1764 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); |
| @@ -1776,10 +1776,9 @@ static int s3c24xx_serial_enable_baudclk(struct s3c24xx_uart_port *ourport) · 11 unmodified lines | ||
| 1776 | 1776 | struct device *dev = ourport->port.dev; |
| 1777 | 1777 | const struct s3c24xx_uart_info *info = ourport->info; |
| 1778 | 1778 | char clk_name[MAX_CLK_NAME_LENGTH]; |
| 1779 | − unsigned int clk_sel; | |
| 1780 | 1779 | struct clk *clk; |
| 1781 | − int clk_num; | |
| 1782 | 1780 | int ret; |
| 1781 | + u8 clk_sel, clk_num; | |
| 1783 | 1782 | |
| 1784 | 1783 | clk_sel = ourport->cfg->clk_sel ? : info->def_clk_sel; |
| 1785 | 1784 | 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, · 118 unmodified lines | ||
| 1904 | 1903 | wr_regl(port, S3C64XX_UINTSP, 0xf); |
| 1905 | 1904 | break; |
| 1906 | 1905 | case TYPE_APPLE_S5L: { |
| 1907 | − unsigned int ucon; | |
| 1906 | + u32 ucon; | |
| 1908 | 1907 | |
| 1909 | 1908 | ucon = rd_regl(port, S3C2410_UCON); |
| 1910 | 1909 | ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK | |
| @@ -1952,7 +1951,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) · 41 unmodified lines | ||
| 1952 | 1951 | struct device_node *np = pdev->dev.of_node; |
| 1953 | 1952 | struct s3c24xx_uart_port *ourport; |
| 1954 | 1953 | int index = probe_index; |
| 1955 | − int ret, prop = 0; | |
| 1954 | + int ret, prop = 0, fifosize_prop = 1; | |
| 1956 | 1955 | |
| 1957 | 1956 | if (np) { |
| 1958 | 1957 | ret = of_alias_get_id(np, "serial"); |
| @@ -1989,9 +1988,11 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) · 30 unmodified lines | ||
| 1989 | 1988 | break; |
| 1990 | 1989 | } |
| 1991 | 1990 | |
| 1991 | + ourport->port.iotype = ourport->info->iotype; | |
| 1992 | + | |
| 1992 | 1993 | if (np) { |
| 1993 | − of_property_read_u32(np, | |
| 1994 | − "samsung,uart-fifosize", &ourport->port.fifosize); | |
| 1994 | + fifosize_prop = of_property_read_u32(np, "samsung,uart-fifosize", | |
| 1995 | + &ourport->port.fifosize); | |
| 1995 | 1996 | |
| 1996 | 1997 | if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { |
| 1997 | 1998 | switch (prop) { |
| @@ -2009,10 +2010,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 2009 | 2010 | } |
| 2010 | 2011 | } |
| 2011 | 2012 | |
| 2012 | − if (ourport->drv_data->fifosize[index]) | |
| 2013 | − ourport->port.fifosize = ourport->drv_data->fifosize[index]; | |
| 2014 | − else if (ourport->info->fifosize) | |
| 2015 | − ourport->port.fifosize = ourport->info->fifosize; | |
| 2013 | + if (fifosize_prop) { | |
| 2014 | + if (ourport->drv_data->fifosize[index]) | |
| 2015 | + ourport->port.fifosize = ourport->drv_data->fifosize[index]; | |
| 2016 | + else if (ourport->info->fifosize) | |
| 2017 | + ourport->port.fifosize = ourport->info->fifosize; | |
| 2018 | + } | |
| 2019 | + | |
| 2016 | 2020 | ourport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SAMSUNG_CONSOLE); |
| 2017 | 2021 | |
| 2018 | 2022 | /* |
| @@ -2058,9 +2062,8 @@ static void s3c24xx_serial_remove(struct platform_device *dev) · 39 unmodified lines | ||
| 2058 | 2062 | { |
| 2059 | 2063 | struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); |
| 2060 | 2064 | |
| 2061 | − if (port) { | |
| 2065 | + if (port) | |
| 2062 | 2066 | uart_remove_one_port(&s3c24xx_uart_drv, port); |
| 2063 | − } | |
| 2064 | 2067 | |
| 2065 | 2068 | uart_unregister_driver(&s3c24xx_uart_drv); |
| 2066 | 2069 | } |
| @@ -2106,7 +2109,7 @@ static int s3c24xx_serial_resume_noirq(struct device *dev) · 39 unmodified lines | ||
| 2106 | 2109 | /* restore IRQ mask */ |
| 2107 | 2110 | switch (ourport->info->type) { |
| 2108 | 2111 | case TYPE_S3C6400: { |
| 2109 | − unsigned int uintm = 0xf; | |
| 2112 | + u32 uintm = 0xf; | |
| 2110 | 2113 | |
| 2111 | 2114 | if (ourport->tx_enabled) |
| 2112 | 2115 | uintm &= ~S3C64XX_UINTM_TXD_MSK; |
| @@ -2122,7 +2125,7 @@ static int s3c24xx_serial_resume_noirq(struct device *dev) · 9 unmodified lines | ||
| 2122 | 2125 | break; |
| 2123 | 2126 | } |
| 2124 | 2127 | case TYPE_APPLE_S5L: { |
| 2125 | − unsigned int ucon; | |
| 2128 | + u32 ucon; | |
| 2126 | 2129 | int ret; |
| 2127 | 2130 | |
| 2128 | 2131 | ret = clk_prepare_enable(ourport->clk); |
| @@ -2183,27 +2186,27 @@ static const struct dev_pm_ops s3c24xx_serial_pm_ops = { · 54 unmodified lines | ||
| 2183 | 2186 | |
| 2184 | 2187 | static struct uart_port *cons_uart; |
| 2185 | 2188 | |
| 2186 | −static int | |
| 2187 | −s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) | |
| 2189 | +static bool | |
| 2190 | +s3c24xx_serial_console_txrdy(struct uart_port *port, u32 ufcon) | |
| 2188 | 2191 | { |
| 2189 | 2192 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 2190 | − unsigned long ufstat, utrstat; | |
| 2193 | + u32 ufstat, utrstat; | |
| 2191 | 2194 | |
| 2192 | 2195 | if (ufcon & S3C2410_UFCON_FIFOMODE) { |
| 2193 | 2196 | /* fifo mode - check amount of data in fifo registers... */ |
| 2194 | 2197 | |
| 2195 | 2198 | ufstat = rd_regl(port, S3C2410_UFSTAT); |
| 2196 | − return (ufstat & info->tx_fifofull) ? 0 : 1; | |
| 2199 | + return !(ufstat & info->tx_fifofull); | |
| 2197 | 2200 | } |
| 2198 | 2201 | |
| 2199 | 2202 | /* in non-fifo mode, we go and use the tx buffer empty */ |
| 2200 | 2203 | |
| 2201 | 2204 | utrstat = rd_regl(port, S3C2410_UTRSTAT); |
| 2202 | − return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; | |
| 2205 | + return utrstat & S3C2410_UTRSTAT_TXE; | |
| 2203 | 2206 | } |
| 2204 | 2207 | |
| 2205 | 2208 | static bool |
| 2206 | −s3c24xx_port_configured(unsigned int ucon) | |
| 2209 | +s3c24xx_port_configured(u32 ucon) | |
| 2207 | 2210 | { |
| 2208 | 2211 | /* consider the serial port configured if the tx/rx mode set */ |
| 2209 | 2212 | return (ucon & 0xf) != 0; |
| @@ -2218,7 +2221,7 @@ s3c24xx_port_configured(unsigned int ucon) · 8 unmodified lines | ||
| 2218 | 2221 | static int s3c24xx_serial_get_poll_char(struct uart_port *port) |
| 2219 | 2222 | { |
| 2220 | 2223 | const struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 2221 | − unsigned int ufstat; | |
| 2224 | + u32 ufstat; | |
| 2222 | 2225 | |
| 2223 | 2226 | ufstat = rd_regl(port, S3C2410_UFSTAT); |
| 2224 | 2227 | if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) |
| @@ -2230,8 +2233,8 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port) · 5 unmodified lines | ||
| 2230 | 2233 | static void s3c24xx_serial_put_poll_char(struct uart_port *port, |
| 2231 | 2234 | unsigned char c) |
| 2232 | 2235 | { |
| 2233 | − unsigned int ufcon = rd_regl(port, S3C2410_UFCON); | |
| 2234 | − unsigned int ucon = rd_regl(port, S3C2410_UCON); | |
| 2236 | + u32 ufcon = rd_regl(port, S3C2410_UFCON); | |
| 2237 | + u32 ucon = rd_regl(port, S3C2410_UCON); | |
| 2235 | 2238 | |
| 2236 | 2239 | /* not possible to xmit on unconfigured port */ |
| 2237 | 2240 | if (!s3c24xx_port_configured(ucon)) |
| @@ -2247,7 +2250,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port, · 9 unmodified lines | ||
| 2247 | 2250 | static void |
| 2248 | 2251 | s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch) |
| 2249 | 2252 | { |
| 2250 | − unsigned int ufcon = rd_regl(port, S3C2410_UFCON); | |
| 2253 | + u32 ufcon = rd_regl(port, S3C2410_UFCON); | |
| 2251 | 2254 | |
| 2252 | 2255 | while (!s3c24xx_serial_console_txrdy(port, ufcon)) |
| 2253 | 2256 | cpu_relax(); |
| @@ -2258,7 +2261,7 @@ static void · 4 unmodified lines | ||
| 2258 | 2261 | s3c24xx_serial_console_write(struct console *co, const char *s, |
| 2259 | 2262 | unsigned int count) |
| 2260 | 2263 | { |
| 2261 | − unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); | |
| 2264 | + u32 ucon = rd_regl(cons_uart, S3C2410_UCON); | |
| 2262 | 2265 | unsigned long flags; |
| 2263 | 2266 | bool locked = true; |
| 2264 | 2267 | |
| @@ -2285,12 +2288,10 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, · 20 unmodified lines | ||
| 2285 | 2288 | int *parity, int *bits) |
| 2286 | 2289 | { |
| 2287 | 2290 | struct clk *clk; |
| 2288 | − unsigned int ulcon; | |
| 2289 | − unsigned int ucon; | |
| 2290 | − unsigned int ubrdiv; | |
| 2291 | 2291 | unsigned long rate; |
| 2292 | − unsigned int clk_sel; | |
| 2292 | + u32 ulcon, ucon, ubrdiv; | |
| 2293 | 2293 | char clk_name[MAX_CLK_NAME_LENGTH]; |
| 2294 | + u8 clk_sel; | |
| 2294 | 2295 | |
| 2295 | 2296 | ulcon = rd_regl(port, S3C2410_ULCON); |
| 2296 | 2297 | ucon = rd_regl(port, S3C2410_UCON); |
| @@ -2399,8 +2400,9 @@ static const struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = { · 102 unmodified lines | ||
| 2399 | 2400 | .name = "Samsung S3C6400 UART", |
| 2400 | 2401 | .type = TYPE_S3C6400, |
| 2401 | 2402 | .port_type = PORT_S3C6400, |
| 2403 | + .iotype = UPIO_MEM, | |
| 2402 | 2404 | .fifosize = 64, |
| 2403 | − .has_divslot = 1, | |
| 2405 | + .has_divslot = true, | |
| 2404 | 2406 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, |
| 2405 | 2407 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, |
| 2406 | 2408 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, |
| @@ -2428,7 +2430,8 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { · 21 unmodified lines | ||
| 2428 | 2430 | .name = "Samsung S5PV210 UART", |
| 2429 | 2431 | .type = TYPE_S3C6400, |
| 2430 | 2432 | .port_type = PORT_S3C6400, |
| 2431 | − .has_divslot = 1, | |
| 2433 | + .iotype = UPIO_MEM, | |
| 2434 | + .has_divslot = true, | |
| 2432 | 2435 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, |
| 2433 | 2436 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, |
| 2434 | 2437 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, |
| @@ -2452,12 +2455,13 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { · 17 unmodified lines | ||
| 2452 | 2455 | #endif |
| 2453 | 2456 | |
| 2454 | 2457 | #if defined(CONFIG_ARCH_EXYNOS) |
| 2455 | −#define EXYNOS_COMMON_SERIAL_DRV_DATA() \ | |
| 2458 | +#define EXYNOS_COMMON_SERIAL_DRV_DATA \ | |
| 2456 | 2459 | .info = { \ |
| 2457 | 2460 | .name = "Samsung Exynos UART", \ |
| 2458 | 2461 | .type = TYPE_S3C6400, \ |
| 2459 | 2462 | .port_type = PORT_S3C6400, \ |
| 2460 | − .has_divslot = 1, \ | |
| 2463 | + .iotype = UPIO_MEM, \ | |
| 2464 | + .has_divslot = true, \ | |
| 2461 | 2465 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ |
| 2462 | 2466 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \ |
| 2463 | 2467 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, \ |
| @@ -2476,39 +2480,57 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { · 12 unmodified lines | ||
| 2476 | 2480 | } \ |
| 2477 | 2481 | |
| 2478 | 2482 | static const struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = { |
| 2479 | − EXYNOS_COMMON_SERIAL_DRV_DATA(), | |
| 2483 | + EXYNOS_COMMON_SERIAL_DRV_DATA, | |
| 2480 | 2484 | .fifosize = { 256, 64, 16, 16 }, |
| 2481 | 2485 | }; |
| 2482 | 2486 | |
| 2483 | 2487 | static const struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = { |
| 2484 | − EXYNOS_COMMON_SERIAL_DRV_DATA(), | |
| 2488 | + EXYNOS_COMMON_SERIAL_DRV_DATA, | |
| 2485 | 2489 | .fifosize = { 64, 256, 16, 256 }, |
| 2486 | 2490 | }; |
| 2487 | 2491 | |
| 2488 | 2492 | static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = { |
| 2489 | − EXYNOS_COMMON_SERIAL_DRV_DATA(), | |
| 2493 | + EXYNOS_COMMON_SERIAL_DRV_DATA, | |
| 2490 | 2494 | .fifosize = { 256, 64, 64, 64 }, |
| 2491 | 2495 | }; |
| 2492 | 2496 | |
| 2493 | −/* | |
| 2494 | − * Common drv_data struct for platforms that specify samsung,uart-fifosize in | |
| 2495 | − * device tree. | |
| 2496 | − */ | |
| 2497 | −static const struct s3c24xx_serial_drv_data exynos_fifoszdt_serial_drv_data = { | |
| 2498 | − EXYNOS_COMMON_SERIAL_DRV_DATA(), | |
| 2497 | +static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = { | |
| 2498 | + .info = { | |
| 2499 | + .name = "Google GS101 UART", | |
| 2500 | + .type = TYPE_S3C6400, | |
| 2501 | + .port_type = PORT_S3C6400, | |
| 2502 | + .iotype = UPIO_MEM32, | |
| 2503 | + .has_divslot = true, | |
| 2504 | + .rx_fifomask = S5PV210_UFSTAT_RXMASK, | |
| 2505 | + .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, | |
| 2506 | + .rx_fifofull = S5PV210_UFSTAT_RXFULL, | |
| 2507 | + .tx_fifofull = S5PV210_UFSTAT_TXFULL, | |
| 2508 | + .tx_fifomask = S5PV210_UFSTAT_TXMASK, | |
| 2509 | + .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, | |
| 2510 | + .def_clk_sel = S3C2410_UCON_CLKSEL0, | |
| 2511 | + .num_clks = 1, | |
| 2512 | + .clksel_mask = 0, | |
| 2513 | + .clksel_shift = 0, | |
| 2514 | + }, | |
| 2515 | + .def_cfg = { | |
| 2516 | + .ucon = S5PV210_UCON_DEFAULT, | |
| 2517 | + .ufcon = S5PV210_UFCON_DEFAULT, | |
| 2518 | + .has_fracval = 1, | |
| 2519 | + }, | |
| 2520 | + /* samsung,uart-fifosize must be specified in the device tree. */ | |
| 2499 | 2521 | .fifosize = { 0 }, |
| 2500 | 2522 | }; |
| 2501 | 2523 | |
| 2502 | 2524 | #define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data) |
| 2503 | 2525 | #define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data) |
| 2504 | 2526 | #define EXYNOS850_SERIAL_DRV_DATA (&exynos850_serial_drv_data) |
| 2505 | −#define EXYNOS_FIFOSZDT_DRV_DATA (&exynos_fifoszdt_serial_drv_data) | |
| 2527 | +#define GS101_SERIAL_DRV_DATA (&gs101_serial_drv_data) | |
| 2506 | 2528 | |
| 2507 | 2529 | #else |
| 2508 | 2530 | #define EXYNOS4210_SERIAL_DRV_DATA NULL |
| 2509 | 2531 | #define EXYNOS5433_SERIAL_DRV_DATA NULL |
| 2510 | 2532 | #define EXYNOS850_SERIAL_DRV_DATA NULL |
| 2511 | −#define EXYNOS_FIFOSZDT_DRV_DATA NULL | |
| 2533 | +#define GS101_SERIAL_DRV_DATA NULL | |
| 2512 | 2534 | #endif |
| 2513 | 2535 | |
| 2514 | 2536 | #ifdef CONFIG_ARCH_APPLE |
| @@ -2517,6 +2539,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = { · 2 unmodified lines | ||
| 2517 | 2539 | .name = "Apple S5L UART", |
| 2518 | 2540 | .type = TYPE_APPLE_S5L, |
| 2519 | 2541 | .port_type = PORT_8250, |
| 2542 | + .iotype = UPIO_MEM, | |
| 2520 | 2543 | .fifosize = 16, |
| 2521 | 2544 | .rx_fifomask = S3C2410_UFSTAT_RXMASK, |
| 2522 | 2545 | .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, |
| @@ -2546,8 +2569,9 @@ static const struct s3c24xx_serial_drv_data artpec8_serial_drv_data = { · 23 unmodified lines | ||
| 2546 | 2569 | .name = "Axis ARTPEC-8 UART", |
| 2547 | 2570 | .type = TYPE_S3C6400, |
| 2548 | 2571 | .port_type = PORT_S3C6400, |
| 2572 | + .iotype = UPIO_MEM, | |
| 2549 | 2573 | .fifosize = 64, |
| 2550 | − .has_divslot = 1, | |
| 2574 | + .has_divslot = true, | |
| 2551 | 2575 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, |
| 2552 | 2576 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, |
| 2553 | 2577 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, |
| @@ -2594,7 +2618,7 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = { · 40 unmodified lines | ||
| 2594 | 2618 | .driver_data = (kernel_ulong_t)ARTPEC8_SERIAL_DRV_DATA, |
| 2595 | 2619 | }, { |
| 2596 | 2620 | .name = "gs101-uart", |
| 2597 | − .driver_data = (kernel_ulong_t)EXYNOS_FIFOSZDT_DRV_DATA, | |
| 2621 | + .driver_data = (kernel_ulong_t)GS101_SERIAL_DRV_DATA, | |
| 2598 | 2622 | }, |
| 2599 | 2623 | { }, |
| 2600 | 2624 | }; |
| @@ -2617,7 +2641,7 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = { · 16 unmodified lines | ||
| 2617 | 2641 | { .compatible = "axis,artpec8-uart", |
| 2618 | 2642 | .data = ARTPEC8_SERIAL_DRV_DATA }, |
| 2619 | 2643 | { .compatible = "google,gs101-uart", |
| 2620 | − .data = EXYNOS_FIFOSZDT_DRV_DATA }, | |
| 2644 | + .data = GS101_SERIAL_DRV_DATA }, | |
| 2621 | 2645 | {}, |
| 2622 | 2646 | }; |
| 2623 | 2647 | 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) · 92 unmodified lines | ||
| 2716 | 2740 | { |
| 2717 | 2741 | struct earlycon_device *dev = con->data; |
| 2718 | 2742 | const struct samsung_early_console_data *data = dev->port.private_data; |
| 2719 | − int ch, ufstat, num_read = 0; | |
| 2743 | + int num_read = 0; | |
| 2744 | + u32 ch, ufstat; | |
| 2720 | 2745 | |
| 2721 | 2746 | while (num_read < n) { |
| 2722 | 2747 | ufstat = rd_regl(&dev->port, S3C2410_UFSTAT); |
| @@ -2785,6 +2810,17 @@ OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", · 62 unmodified lines | ||
| 2785 | 2810 | OF_EARLYCON_DECLARE(artpec8, "axis,artpec8-uart", |
| 2786 | 2811 | s5pv210_early_console_setup); |
| 2787 | 2812 | |
| 2813 | +static int __init gs101_early_console_setup(struct earlycon_device *device, | |
| 2814 | + const char *opt) | |
| 2815 | +{ | |
| 2816 | + /* gs101 always expects MMIO32 register accesses. */ | |
| 2817 | + device->port.iotype = UPIO_MEM32; | |
| 2818 | + | |
| 2819 | + return s5pv210_early_console_setup(device, opt); | |
| 2820 | +} | |
| 2821 | + | |
| 2822 | +OF_EARLYCON_DECLARE(gs101, "google,gs101-uart", gs101_early_console_setup); | |
| 2823 | + | |
| 2788 | 2824 | /* Apple S5L */ |
| 2789 | 2825 | static int __init apple_s5l_early_console_setup(struct earlycon_device *device, |
| 2790 | 2826 | const char *opt) |
| @@ -41,7 +41,7 @@ static int serial_base_match(struct device *dev, struct device_driver *drv) · 40 unmodified lines | ||
| 41 | 41 | return 0; |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | −static struct bus_type serial_base_bus_type = { | |
| 44 | +static const struct bus_type serial_base_bus_type = { | |
| 45 | 45 | .name = "serial-base", |
| 46 | 46 | .match = serial_base_match, |
| 47 | 47 | }; |
| @@ -2608,7 +2608,12 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, · 2607 unmodified lines | ||
| 2608 | 2608 | port->type = PORT_UNKNOWN; |
| 2609 | 2609 | flags |= UART_CONFIG_TYPE; |
| 2610 | 2610 | } |
| 2611 | + /* Synchronize with possible boot console. */ | |
| 2612 | + if (uart_console(port)) | |
| 2613 | + console_lock(); | |
| 2611 | 2614 | port->ops->config_port(port, flags); |
| 2615 | + if (uart_console(port)) | |
| 2616 | + console_unlock(); | |
| 2612 | 2617 | } |
| 2613 | 2618 | |
| 2614 | 2619 | if (port->type != PORT_UNKNOWN) { |
| @@ -2616,6 +2621,10 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, · 1 unmodified line | ||
| 2616 | 2621 | |
| 2617 | 2622 | uart_report_port(drv, port); |
| 2618 | 2623 | |
| 2624 | + /* Synchronize with possible boot console. */ | |
| 2625 | + if (uart_console(port)) | |
| 2626 | + console_lock(); | |
| 2627 | + | |
| 2619 | 2628 | /* Power up port for set_mctrl() */ |
| 2620 | 2629 | uart_change_pm(state, UART_PM_STATE_ON); |
| 2621 | 2630 | |
| @@ -2632,6 +2641,9 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, · 10 unmodified lines | ||
| 2632 | 2641 | |
| 2633 | 2642 | uart_rs485_config(port); |
| 2634 | 2643 | |
| 2644 | + if (uart_console(port)) | |
| 2645 | + console_unlock(); | |
| 2646 | + | |
| 2635 | 2647 | /* |
| 2636 | 2648 | * If this driver supports console, and it hasn't been |
| 2637 | 2649 | * successfully registered yet, try to re-register it. |
| @@ -8,7 +8,10 @@ · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | #include <linux/device.h> |
| 10 | 10 | #include <linux/module.h> |
| 11 | +#include <linux/of.h> | |
| 12 | +#include <linux/platform_device.h> | |
| 11 | 13 | #include <linux/pm_runtime.h> |
| 14 | +#include <linux/property.h> | |
| 12 | 15 | #include <linux/serial_core.h> |
| 13 | 16 | #include <linux/spinlock.h> |
| 14 | 17 | |
| @@ -105,6 +108,148 @@ void uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) · 90 unmodified lines | ||
| 105 | 108 | } |
| 106 | 109 | EXPORT_SYMBOL(uart_remove_one_port); |
| 107 | 110 | |
| 111 | +/** | |
| 112 | + * __uart_read_properties - read firmware properties of the given UART port | |
| 113 | + * @port: corresponding port | |
| 114 | + * @use_defaults: apply defaults (when %true) or validate the values (when %false) | |
| 115 | + * | |
| 116 | + * The following device properties are supported: | |
| 117 | + * - clock-frequency (optional) | |
| 118 | + * - fifo-size (optional) | |
| 119 | + * - no-loopback-test (optional) | |
| 120 | + * - reg-shift (defaults may apply) | |
| 121 | + * - reg-offset (value may be validated) | |
| 122 | + * - reg-io-width (defaults may apply or value may be validated) | |
| 123 | + * - interrupts (OF only) | |
| 124 | + * - serial [alias ID] (OF only) | |
| 125 | + * | |
| 126 | + * If the port->dev is of struct platform_device type the interrupt line | |
| 127 | + * will be retrieved via platform_get_irq() call against that device. | |
| 128 | + * Otherwise it will be assigned by fwnode_irq_get() call. In both cases | |
| 129 | + * the index 0 of the resource is used. | |
| 130 | + * | |
| 131 | + * The caller is responsible to initialize the following fields of the @port | |
| 132 | + * ->dev (must be valid) | |
| 133 | + * ->flags | |
| 134 | + * ->mapbase | |
| 135 | + * ->mapsize | |
| 136 | + * ->regshift (if @use_defaults is false) | |
| 137 | + * before calling this function. Alternatively the above mentioned fields | |
| 138 | + * may be zeroed, in such case the only ones, that have associated properties | |
| 139 | + * found, will be set to the respective values. | |
| 140 | + * | |
| 141 | + * If no error happened, the ->irq, ->mapbase, ->mapsize will be altered. | |
| 142 | + * The ->iotype is always altered. | |
| 143 | + * | |
| 144 | + * When @use_defaults is true and the respective property is not found | |
| 145 | + * the following values will be applied: | |
| 146 | + * ->regshift = 0 | |
| 147 | + * In this case IRQ must be provided, otherwise an error will be returned. | |
| 148 | + * | |
| 149 | + * When @use_defaults is false and the respective property is found | |
| 150 | + * the following values will be validated: | |
| 151 | + * - reg-io-width (->iotype) | |
| 152 | + * - reg-offset (->mapsize against ->mapbase) | |
| 153 | + * | |
| 154 | + * Returns: 0 on success or negative errno on failure | |
| 155 | + */ | |
| 156 | +static int __uart_read_properties(struct uart_port *port, bool use_defaults) | |
| 157 | +{ | |
| 158 | + struct device *dev = port->dev; | |
| 159 | + u32 value; | |
| 160 | + int ret; | |
| 161 | + | |
| 162 | + /* Read optional UART functional clock frequency */ | |
| 163 | + device_property_read_u32(dev, "clock-frequency", &port->uartclk); | |
| 164 | + | |
| 165 | + /* Read the registers alignment (default: 8-bit) */ | |
| 166 | + ret = device_property_read_u32(dev, "reg-shift", &value); | |
| 167 | + if (ret) | |
| 168 | + port->regshift = use_defaults ? 0 : port->regshift; | |
| 169 | + else | |
| 170 | + port->regshift = value; | |
| 171 | + | |
| 172 | + /* Read the registers I/O access type (default: MMIO 8-bit) */ | |
| 173 | + ret = device_property_read_u32(dev, "reg-io-width", &value); | |
| 174 | + if (ret) { | |
| 175 | + port->iotype = UPIO_MEM; | |
| 176 | + } else { | |
| 177 | + switch (value) { | |
| 178 | + case 1: | |
| 179 | + port->iotype = UPIO_MEM; | |
| 180 | + break; | |
| 181 | + case 2: | |
| 182 | + port->iotype = UPIO_MEM16; | |
| 183 | + break; | |
| 184 | + case 4: | |
| 185 | + port->iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32; | |
| 186 | + break; | |
| 187 | + default: | |
| 188 | + if (!use_defaults) { | |
| 189 | + dev_err(dev, "Unsupported reg-io-width (%u)\n", value); | |
| 190 | + return -EINVAL; | |
| 191 | + } | |
| 192 | + port->iotype = UPIO_UNKNOWN; | |
| 193 | + break; | |
| 194 | + } | |
| 195 | + } | |
| 196 | + | |
| 197 | + /* Read the address mapping base offset (default: no offset) */ | |
| 198 | + ret = device_property_read_u32(dev, "reg-offset", &value); | |
| 199 | + if (ret) | |
| 200 | + value = 0; | |
| 201 | + | |
| 202 | + /* Check for shifted address mapping overflow */ | |
| 203 | + if (!use_defaults && port->mapsize < value) { | |
| 204 | + dev_err(dev, "reg-offset %u exceeds region size %pa\n", value, &port->mapsize); | |
| 205 | + return -EINVAL; | |
| 206 | + } | |
| 207 | + | |
| 208 | + port->mapbase += value; | |
| 209 | + port->mapsize -= value; | |
| 210 | + | |
| 211 | + /* Read optional FIFO size */ | |
| 212 | + device_property_read_u32(dev, "fifo-size", &port->fifosize); | |
| 213 | + | |
| 214 | + if (device_property_read_bool(dev, "no-loopback-test")) | |
| 215 | + port->flags |= UPF_SKIP_TEST; | |
| 216 | + | |
| 217 | + /* Get index of serial line, if found in DT aliases */ | |
| 218 | + ret = of_alias_get_id(dev_of_node(dev), "serial"); | |
| 219 | + if (ret >= 0) | |
| 220 | + port->line = ret; | |
| 221 | + | |
| 222 | + if (dev_is_platform(dev)) | |
| 223 | + ret = platform_get_irq(to_platform_device(dev), 0); | |
| 224 | + else | |
| 225 | + ret = fwnode_irq_get(dev_fwnode(dev), 0); | |
| 226 | + if (ret == -EPROBE_DEFER) | |
| 227 | + return ret; | |
| 228 | + if (ret > 0) | |
| 229 | + port->irq = ret; | |
| 230 | + else if (use_defaults) | |
| 231 | + /* By default IRQ support is mandatory */ | |
| 232 | + return ret; | |
| 233 | + else | |
| 234 | + port->irq = 0; | |
| 235 | + | |
| 236 | + port->flags |= UPF_SHARE_IRQ; | |
| 237 | + | |
| 238 | + return 0; | |
| 239 | +} | |
| 240 | + | |
| 241 | +int uart_read_port_properties(struct uart_port *port) | |
| 242 | +{ | |
| 243 | + return __uart_read_properties(port, true); | |
| 244 | +} | |
| 245 | +EXPORT_SYMBOL_GPL(uart_read_port_properties); | |
| 246 | + | |
| 247 | +int uart_read_and_validate_port_properties(struct uart_port *port) | |
| 248 | +{ | |
| 249 | + return __uart_read_properties(port, false); | |
| 250 | +} | |
| 251 | +EXPORT_SYMBOL_GPL(uart_read_and_validate_port_properties); | |
| 252 | + | |
| 108 | 253 | static struct device_driver serial_port_driver = { |
| 109 | 254 | .name = "port", |
| 110 | 255 | .suppress_bind_attrs = true, |
| @@ -23,9 +23,10 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <linux/serial.h> |
| 24 | 24 | #include <linux/tty.h> |
| 25 | 25 | #include <linux/tty_flip.h> |
| 26 | − | |
| 27 | 26 | #include <linux/io.h> |
| 28 | 27 | |
| 28 | +#include <asm/txx9/generic.h> | |
| 29 | + | |
| 29 | 30 | #define PASS_LIMIT 256 |
| 30 | 31 | |
| 31 | 32 | #if !defined(CONFIG_SERIAL_TXX9_STDSERIAL) |
| @@ -576,13 +576,13 @@ static void sci_start_tx(struct uart_port *port) · 575 unmodified lines | ||
| 576 | 576 | |
| 577 | 577 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 578 | 578 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 579 | − u16 new, scr = serial_port_in(port, SCSCR); | |
| 579 | + u16 new, scr = sci_serial_in(port, SCSCR); | |
| 580 | 580 | if (s->chan_tx) |
| 581 | 581 | new = scr | SCSCR_TDRQE; |
| 582 | 582 | else |
| 583 | 583 | new = scr & ~SCSCR_TDRQE; |
| 584 | 584 | if (new != scr) |
| 585 | − serial_port_out(port, SCSCR, new); | |
| 585 | + sci_serial_out(port, SCSCR, new); | |
| 586 | 586 | } |
| 587 | 587 | |
| 588 | 588 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && |
| @@ -599,7 +599,7 @@ static void sci_start_tx(struct uart_port *port) · 10 unmodified lines | ||
| 599 | 599 | if (!s->chan_tx || s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE || |
| 600 | 600 | port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 601 | 601 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
| 602 | − ctrl = serial_port_in(port, SCSCR); | |
| 602 | + ctrl = sci_serial_in(port, SCSCR); | |
| 603 | 603 | |
| 604 | 604 | /* |
| 605 | 605 | * For SCI, TE (transmit enable) must be set after setting TIE |
| @@ -609,7 +609,7 @@ static void sci_start_tx(struct uart_port *port) · 3 unmodified lines | ||
| 609 | 609 | if (port->type == PORT_SCI) |
| 610 | 610 | ctrl |= SCSCR_TE; |
| 611 | 611 | |
| 612 | − serial_port_out(port, SCSCR, ctrl | SCSCR_TIE); | |
| 612 | + sci_serial_out(port, SCSCR, ctrl | SCSCR_TIE); | |
| 613 | 613 | } |
| 614 | 614 | } |
| 615 | 615 | |
| @@ -618,14 +618,14 @@ static void sci_stop_tx(struct uart_port *port) · 2 unmodified lines | ||
| 618 | 618 | unsigned short ctrl; |
| 619 | 619 | |
| 620 | 620 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ |
| 621 | − ctrl = serial_port_in(port, SCSCR); | |
| 621 | + ctrl = sci_serial_in(port, SCSCR); | |
| 622 | 622 | |
| 623 | 623 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
| 624 | 624 | ctrl &= ~SCSCR_TDRQE; |
| 625 | 625 | |
| 626 | 626 | ctrl &= ~SCSCR_TIE; |
| 627 | 627 | |
| 628 | − serial_port_out(port, SCSCR, ctrl); | |
| 628 | + sci_serial_out(port, SCSCR, ctrl); | |
| 629 | 629 | |
| 630 | 630 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 631 | 631 | if (to_sci_port(port)->chan_tx && |
| @@ -640,41 +640,40 @@ static void sci_start_rx(struct uart_port *port) · 8 unmodified lines | ||
| 640 | 640 | { |
| 641 | 641 | unsigned short ctrl; |
| 642 | 642 | |
| 643 | − ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port); | |
| 643 | + ctrl = sci_serial_in(port, SCSCR) | port_rx_irq_mask(port); | |
| 644 | 644 | |
| 645 | 645 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
| 646 | 646 | ctrl &= ~SCSCR_RDRQE; |
| 647 | 647 | |
| 648 | − serial_port_out(port, SCSCR, ctrl); | |
| 648 | + sci_serial_out(port, SCSCR, ctrl); | |
| 649 | 649 | } |
| 650 | 650 | |
| 651 | 651 | static void sci_stop_rx(struct uart_port *port) |
| 652 | 652 | { |
| 653 | 653 | unsigned short ctrl; |
| 654 | 654 | |
| 655 | − ctrl = serial_port_in(port, SCSCR); | |
| 655 | + ctrl = sci_serial_in(port, SCSCR); | |
| 656 | 656 | |
| 657 | 657 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
| 658 | 658 | ctrl &= ~SCSCR_RDRQE; |
| 659 | 659 | |
| 660 | 660 | ctrl &= ~port_rx_irq_mask(port); |
| 661 | 661 | |
| 662 | − serial_port_out(port, SCSCR, ctrl); | |
| 662 | + sci_serial_out(port, SCSCR, ctrl); | |
| 663 | 663 | } |
| 664 | 664 | |
| 665 | 665 | static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask) |
| 666 | 666 | { |
| 667 | 667 | if (port->type == PORT_SCI) { |
| 668 | 668 | /* Just store the mask */ |
| 669 | − serial_port_out(port, SCxSR, mask); | |
| 669 | + sci_serial_out(port, SCxSR, mask); | |
| 670 | 670 | } else if (to_sci_port(port)->params->overrun_mask == SCIFA_ORER) { |
| 671 | 671 | /* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */ |
| 672 | 672 | /* Only clear the status bits we want to clear */ |
| 673 | − serial_port_out(port, SCxSR, | |
| 674 | − serial_port_in(port, SCxSR) & mask); | |
| 673 | + sci_serial_out(port, SCxSR, sci_serial_in(port, SCxSR) & mask); | |
| 675 | 674 | } else { |
| 676 | 675 | /* Store the mask, clear parity/framing errors */ |
| 677 | − serial_port_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC)); | |
| 676 | + sci_serial_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC)); | |
| 678 | 677 | } |
| 679 | 678 | } |
| 680 | 679 | |
| @@ -688,7 +687,7 @@ static int sci_poll_get_char(struct uart_port *port) · 7 unmodified lines | ||
| 688 | 687 | int c; |
| 689 | 688 | |
| 690 | 689 | do { |
| 691 | − status = serial_port_in(port, SCxSR); | |
| 690 | + status = sci_serial_in(port, SCxSR); | |
| 692 | 691 | if (status & SCxSR_ERRORS(port)) { |
| 693 | 692 | sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port)); |
| 694 | 693 | continue; |
| @@ -699,10 +698,10 @@ static int sci_poll_get_char(struct uart_port *port) · 4 unmodified lines | ||
| 699 | 698 | if (!(status & SCxSR_RDxF(port))) |
| 700 | 699 | return NO_POLL_CHAR; |
| 701 | 700 | |
| 702 | − c = serial_port_in(port, SCxRDR); | |
| 701 | + c = sci_serial_in(port, SCxRDR); | |
| 703 | 702 | |
| 704 | 703 | /* Dummy read */ |
| 705 | − serial_port_in(port, SCxSR); | |
| 704 | + sci_serial_in(port, SCxSR); | |
| 706 | 705 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); |
| 707 | 706 | |
| 708 | 707 | return c; |
| @@ -714,10 +713,10 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) · 5 unmodified lines | ||
| 714 | 713 | unsigned short status; |
| 715 | 714 | |
| 716 | 715 | do { |
| 717 | − status = serial_port_in(port, SCxSR); | |
| 716 | + status = sci_serial_in(port, SCxSR); | |
| 718 | 717 | } while (!(status & SCxSR_TDxE(port))); |
| 719 | 718 | |
| 720 | − serial_port_out(port, SCxTDR, c); | |
| 719 | + sci_serial_out(port, SCxTDR, c); | |
| 721 | 720 | sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); |
| 722 | 721 | } |
| 723 | 722 | #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) · 12 unmodified lines | ||
| 736 | 735 | } |
| 737 | 736 | |
| 738 | 737 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 739 | − u16 data = serial_port_in(port, SCPDR); | |
| 740 | − u16 ctrl = serial_port_in(port, SCPCR); | |
| 738 | + u16 data = sci_serial_in(port, SCPDR); | |
| 739 | + u16 ctrl = sci_serial_in(port, SCPCR); | |
| 741 | 740 | |
| 742 | 741 | /* Enable RXD and TXD pin functions */ |
| 743 | 742 | ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC); |
| @@ -756,10 +755,10 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) · 12 unmodified lines | ||
| 756 | 755 | /* Enable CTS# pin function */ |
| 757 | 756 | ctrl &= ~SCPCR_CTSC; |
| 758 | 757 | } |
| 759 | − serial_port_out(port, SCPDR, data); | |
| 760 | − serial_port_out(port, SCPCR, ctrl); | |
| 758 | + sci_serial_out(port, SCPDR, data); | |
| 759 | + sci_serial_out(port, SCPCR, ctrl); | |
| 761 | 760 | } else if (sci_getreg(port, SCSPTR)->size) { |
| 762 | − u16 status = serial_port_in(port, SCSPTR); | |
| 761 | + u16 status = sci_serial_in(port, SCSPTR); | |
| 763 | 762 | |
| 764 | 763 | /* RTS# is always output; and active low, unless autorts */ |
| 765 | 764 | status |= SCSPTR_RTSIO; |
| @@ -769,7 +768,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) · 3 unmodified lines | ||
| 769 | 768 | status &= ~SCSPTR_RTSDT; |
| 770 | 769 | /* CTS# and SCK are inputs */ |
| 771 | 770 | status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO); |
| 772 | − serial_port_out(port, SCSPTR, status); | |
| 771 | + sci_serial_out(port, SCSPTR, status); | |
| 773 | 772 | } |
| 774 | 773 | } |
| 775 | 774 | |
| @@ -781,13 +780,13 @@ static int sci_txfill(struct uart_port *port) · 5 unmodified lines | ||
| 781 | 780 | |
| 782 | 781 | reg = sci_getreg(port, SCTFDR); |
| 783 | 782 | if (reg->size) |
| 784 | − return serial_port_in(port, SCTFDR) & fifo_mask; | |
| 783 | + return sci_serial_in(port, SCTFDR) & fifo_mask; | |
| 785 | 784 | |
| 786 | 785 | reg = sci_getreg(port, SCFDR); |
| 787 | 786 | if (reg->size) |
| 788 | − return serial_port_in(port, SCFDR) >> 8; | |
| 787 | + return sci_serial_in(port, SCFDR) >> 8; | |
| 789 | 788 | |
| 790 | − return !(serial_port_in(port, SCxSR) & SCI_TDRE); | |
| 789 | + return !(sci_serial_in(port, SCxSR) & SCI_TDRE); | |
| 791 | 790 | } |
| 792 | 791 | |
| 793 | 792 | static int sci_txroom(struct uart_port *port) |
| @@ -803,13 +802,13 @@ static int sci_rxfill(struct uart_port *port) · 9 unmodified lines | ||
| 803 | 802 | |
| 804 | 803 | reg = sci_getreg(port, SCRFDR); |
| 805 | 804 | if (reg->size) |
| 806 | − return serial_port_in(port, SCRFDR) & fifo_mask; | |
| 805 | + return sci_serial_in(port, SCRFDR) & fifo_mask; | |
| 807 | 806 | |
| 808 | 807 | reg = sci_getreg(port, SCFDR); |
| 809 | 808 | if (reg->size) |
| 810 | − return serial_port_in(port, SCFDR) & fifo_mask; | |
| 809 | + return sci_serial_in(port, SCFDR) & fifo_mask; | |
| 811 | 810 | |
| 812 | − return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; | |
| 811 | + return (sci_serial_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; | |
| 813 | 812 | } |
| 814 | 813 | |
| 815 | 814 | /* ********************************************************************** * |
| @@ -824,14 +823,14 @@ static void sci_transmit_chars(struct uart_port *port) · 8 unmodified lines | ||
| 824 | 823 | unsigned short ctrl; |
| 825 | 824 | int count; |
| 826 | 825 | |
| 827 | − status = serial_port_in(port, SCxSR); | |
| 826 | + status = sci_serial_in(port, SCxSR); | |
| 828 | 827 | if (!(status & SCxSR_TDxE(port))) { |
| 829 | − ctrl = serial_port_in(port, SCSCR); | |
| 828 | + ctrl = sci_serial_in(port, SCSCR); | |
| 830 | 829 | if (uart_circ_empty(xmit)) |
| 831 | 830 | ctrl &= ~SCSCR_TIE; |
| 832 | 831 | else |
| 833 | 832 | ctrl |= SCSCR_TIE; |
| 834 | − serial_port_out(port, SCSCR, ctrl); | |
| 833 | + sci_serial_out(port, SCSCR, ctrl); | |
| 835 | 834 | return; |
| 836 | 835 | } |
| 837 | 836 | |
| @@ -847,15 +846,15 @@ static void sci_transmit_chars(struct uart_port *port) · 9 unmodified lines | ||
| 847 | 846 | c = xmit->buf[xmit->tail]; |
| 848 | 847 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| 849 | 848 | } else if (port->type == PORT_SCI && uart_circ_empty(xmit)) { |
| 850 | − ctrl = serial_port_in(port, SCSCR); | |
| 849 | + ctrl = sci_serial_in(port, SCSCR); | |
| 851 | 850 | ctrl &= ~SCSCR_TE; |
| 852 | − serial_port_out(port, SCSCR, ctrl); | |
| 851 | + sci_serial_out(port, SCSCR, ctrl); | |
| 853 | 852 | return; |
| 854 | 853 | } else { |
| 855 | 854 | break; |
| 856 | 855 | } |
| 857 | 856 | |
| 858 | − serial_port_out(port, SCxTDR, c); | |
| 857 | + sci_serial_out(port, SCxTDR, c); | |
| 859 | 858 | |
| 860 | 859 | port->icount.tx++; |
| 861 | 860 | } while (--count > 0); |
| @@ -866,10 +865,10 @@ static void sci_transmit_chars(struct uart_port *port) · 4 unmodified lines | ||
| 866 | 865 | uart_write_wakeup(port); |
| 867 | 866 | if (uart_circ_empty(xmit)) { |
| 868 | 867 | if (port->type == PORT_SCI) { |
| 869 | − ctrl = serial_port_in(port, SCSCR); | |
| 868 | + ctrl = sci_serial_in(port, SCSCR); | |
| 870 | 869 | ctrl &= ~SCSCR_TIE; |
| 871 | 870 | ctrl |= SCSCR_TEIE; |
| 872 | − serial_port_out(port, SCSCR, ctrl); | |
| 871 | + sci_serial_out(port, SCSCR, ctrl); | |
| 873 | 872 | } |
| 874 | 873 | |
| 875 | 874 | sci_stop_tx(port); |
| @@ -883,7 +882,7 @@ static void sci_receive_chars(struct uart_port *port) · 7 unmodified lines | ||
| 883 | 882 | unsigned short status; |
| 884 | 883 | unsigned char flag; |
| 885 | 884 | |
| 886 | − status = serial_port_in(port, SCxSR); | |
| 885 | + status = sci_serial_in(port, SCxSR); | |
| 887 | 886 | if (!(status & SCxSR_RDxF(port))) |
| 888 | 887 | return; |
| 889 | 888 | |
| @@ -896,7 +895,7 @@ static void sci_receive_chars(struct uart_port *port) · 6 unmodified lines | ||
| 896 | 895 | break; |
| 897 | 896 | |
| 898 | 897 | if (port->type == PORT_SCI) { |
| 899 | − char c = serial_port_in(port, SCxRDR); | |
| 898 | + char c = sci_serial_in(port, SCxRDR); | |
| 900 | 899 | if (uart_handle_sysrq_char(port, c)) |
| 901 | 900 | count = 0; |
| 902 | 901 | else |
| @@ -907,11 +906,11 @@ static void sci_receive_chars(struct uart_port *port) · 4 unmodified lines | ||
| 907 | 906 | |
| 908 | 907 | if (port->type == PORT_SCIF || |
| 909 | 908 | port->type == PORT_HSCIF) { |
| 910 | − status = serial_port_in(port, SCxSR); | |
| 911 | − c = serial_port_in(port, SCxRDR); | |
| 909 | + status = sci_serial_in(port, SCxSR); | |
| 910 | + c = sci_serial_in(port, SCxRDR); | |
| 912 | 911 | } else { |
| 913 | − c = serial_port_in(port, SCxRDR); | |
| 914 | − status = serial_port_in(port, SCxSR); | |
| 912 | + c = sci_serial_in(port, SCxRDR); | |
| 913 | + status = sci_serial_in(port, SCxSR); | |
| 915 | 914 | } |
| 916 | 915 | if (uart_handle_sysrq_char(port, c)) { |
| 917 | 916 | count--; i--; |
| @@ -932,7 +931,7 @@ static void sci_receive_chars(struct uart_port *port) · 14 unmodified lines | ||
| 932 | 931 | } |
| 933 | 932 | } |
| 934 | 933 | |
| 935 | − serial_port_in(port, SCxSR); /* dummy read */ | |
| 934 | + sci_serial_in(port, SCxSR); /* dummy read */ | |
| 936 | 935 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); |
| 937 | 936 | |
| 938 | 937 | copied += count; |
| @@ -944,8 +943,8 @@ static void sci_receive_chars(struct uart_port *port) · 5 unmodified lines | ||
| 944 | 943 | tty_flip_buffer_push(tport); |
| 945 | 944 | } else { |
| 946 | 945 | /* TTY buffers full; read from RX reg to prevent lockup */ |
| 947 | − serial_port_in(port, SCxRDR); | |
| 948 | − serial_port_in(port, SCxSR); /* dummy read */ | |
| 946 | + sci_serial_in(port, SCxRDR); | |
| 947 | + sci_serial_in(port, SCxSR); /* dummy read */ | |
| 949 | 948 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); |
| 950 | 949 | } |
| 951 | 950 | } |
| @@ -953,7 +952,7 @@ static void sci_receive_chars(struct uart_port *port) · 1 unmodified line | ||
| 953 | 952 | static int sci_handle_errors(struct uart_port *port) |
| 954 | 953 | { |
| 955 | 954 | int copied = 0; |
| 956 | − unsigned short status = serial_port_in(port, SCxSR); | |
| 955 | + unsigned short status = sci_serial_in(port, SCxSR); | |
| 957 | 956 | struct tty_port *tport = &port->state->port; |
| 958 | 957 | struct sci_port *s = to_sci_port(port); |
| 959 | 958 | |
| @@ -1000,10 +999,10 @@ static int sci_handle_fifo_overrun(struct uart_port *port) · 40 unmodified lines | ||
| 1000 | 999 | if (!reg->size) |
| 1001 | 1000 | return 0; |
| 1002 | 1001 | |
| 1003 | − status = serial_port_in(port, s->params->overrun_reg); | |
| 1002 | + status = sci_serial_in(port, s->params->overrun_reg); | |
| 1004 | 1003 | if (status & s->params->overrun_mask) { |
| 1005 | 1004 | status &= ~s->params->overrun_mask; |
| 1006 | − serial_port_out(port, s->params->overrun_reg, status); | |
| 1005 | + sci_serial_out(port, s->params->overrun_reg, status); | |
| 1007 | 1006 | |
| 1008 | 1007 | port->icount.overrun++; |
| 1009 | 1008 | |
| @@ -1018,7 +1017,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port) · 8 unmodified lines | ||
| 1018 | 1017 | static int sci_handle_breaks(struct uart_port *port) |
| 1019 | 1018 | { |
| 1020 | 1019 | int copied = 0; |
| 1021 | − unsigned short status = serial_port_in(port, SCxSR); | |
| 1020 | + unsigned short status = sci_serial_in(port, SCxSR); | |
| 1022 | 1021 | struct tty_port *tport = &port->state->port; |
| 1023 | 1022 | |
| 1024 | 1023 | if (uart_handle_break(port)) |
| @@ -1051,7 +1050,7 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig) · 26 unmodified lines | ||
| 1051 | 1050 | |
| 1052 | 1051 | /* HSCIF can be set to an arbitrary level. */ |
| 1053 | 1052 | if (sci_getreg(port, HSRTRGR)->size) { |
| 1054 | − serial_port_out(port, HSRTRGR, rx_trig); | |
| 1053 | + sci_serial_out(port, HSRTRGR, rx_trig); | |
| 1055 | 1054 | return rx_trig; |
| 1056 | 1055 | } |
| 1057 | 1056 | |
| @@ -1092,9 +1091,9 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig) · 34 unmodified lines | ||
| 1092 | 1091 | return 1; |
| 1093 | 1092 | } |
| 1094 | 1093 | |
| 1095 | − serial_port_out(port, SCFCR, | |
| 1096 | − (serial_port_in(port, SCFCR) & | |
| 1097 | − ~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits); | |
| 1094 | + sci_serial_out(port, SCFCR, | |
| 1095 | + (sci_serial_in(port, SCFCR) & | |
| 1096 | + ~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits); | |
| 1098 | 1097 | |
| 1099 | 1098 | return rx_trig; |
| 1100 | 1099 | } |
| @@ -1102,9 +1101,9 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig) · 1 unmodified line | ||
| 1102 | 1101 | static int scif_rtrg_enabled(struct uart_port *port) |
| 1103 | 1102 | { |
| 1104 | 1103 | if (sci_getreg(port, HSRTRGR)->size) |
| 1105 | − return serial_port_in(port, HSRTRGR) != 0; | |
| 1104 | + return sci_serial_in(port, HSRTRGR) != 0; | |
| 1106 | 1105 | else |
| 1107 | − return (serial_port_in(port, SCFCR) & | |
| 1106 | + return (sci_serial_in(port, SCFCR) & | |
| 1108 | 1107 | (SCFCR_RTRG0 | SCFCR_RTRG1)) != 0; |
| 1109 | 1108 | } |
| 1110 | 1109 | |
| @@ -1219,8 +1218,8 @@ static void sci_dma_tx_complete(void *arg) · 108 unmodified lines | ||
| 1219 | 1218 | s->cookie_tx = -EINVAL; |
| 1220 | 1219 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || |
| 1221 | 1220 | s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { |
| 1222 | − u16 ctrl = serial_port_in(port, SCSCR); | |
| 1223 | − serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE); | |
| 1221 | + u16 ctrl = sci_serial_in(port, SCSCR); | |
| 1222 | + sci_serial_out(port, SCSCR, ctrl & ~SCSCR_TIE); | |
| 1224 | 1223 | if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { |
| 1225 | 1224 | /* Switch irq from DMA to SCIF */ |
| 1226 | 1225 | dmaengine_pause(s->chan_tx_saved); |
| @@ -1296,7 +1295,7 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s) · 69 unmodified lines | ||
| 1296 | 1295 | u16 scr; |
| 1297 | 1296 | |
| 1298 | 1297 | /* Direct new serial port interrupts back to CPU */ |
| 1299 | − scr = serial_port_in(port, SCSCR); | |
| 1298 | + scr = sci_serial_in(port, SCSCR); | |
| 1300 | 1299 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || |
| 1301 | 1300 | s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { |
| 1302 | 1301 | enable_irq(s->irqs[SCIx_RXI_IRQ]); |
| @@ -1305,7 +1304,7 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s) · 2 unmodified lines | ||
| 1305 | 1304 | else |
| 1306 | 1305 | scr &= ~SCSCR_RDRQE; |
| 1307 | 1306 | } |
| 1308 | − serial_port_out(port, SCSCR, scr | SCSCR_RIE); | |
| 1307 | + sci_serial_out(port, SCSCR, scr | SCSCR_RIE); | |
| 1309 | 1308 | } |
| 1310 | 1309 | |
| 1311 | 1310 | static void sci_dma_rx_complete(void *arg) |
| @@ -1714,8 +1713,8 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) · 402 unmodified lines | ||
| 1714 | 1713 | |
| 1715 | 1714 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 1716 | 1715 | if (s->chan_rx) { |
| 1717 | − u16 scr = serial_port_in(port, SCSCR); | |
| 1718 | − u16 ssr = serial_port_in(port, SCxSR); | |
| 1716 | + u16 scr = sci_serial_in(port, SCSCR); | |
| 1717 | + u16 ssr = sci_serial_in(port, SCxSR); | |
| 1719 | 1718 | |
| 1720 | 1719 | /* Disable future Rx interrupts */ |
| 1721 | 1720 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || |
| @@ -1733,10 +1732,10 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) · 11 unmodified lines | ||
| 1733 | 1732 | |
| 1734 | 1733 | scr &= ~SCSCR_RIE; |
| 1735 | 1734 | } |
| 1736 | − serial_port_out(port, SCSCR, scr); | |
| 1735 | + sci_serial_out(port, SCSCR, scr); | |
| 1737 | 1736 | /* Clear current interrupt */ |
| 1738 | − serial_port_out(port, SCxSR, | |
| 1739 | − ssr & ~(SCIF_DR | SCxSR_RDxF(port))); | |
| 1737 | + sci_serial_out(port, SCxSR, | |
| 1738 | + ssr & ~(SCIF_DR | SCxSR_RDxF(port))); | |
| 1740 | 1739 | dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u us\n", |
| 1741 | 1740 | jiffies, s->rx_timeout); |
| 1742 | 1741 | start_hrtimer_us(&s->rx_timer, s->rx_timeout); |
| @@ -1786,9 +1785,9 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr) · 43 unmodified lines | ||
| 1786 | 1785 | return sci_tx_interrupt(irq, ptr); |
| 1787 | 1786 | |
| 1788 | 1787 | uart_port_lock_irqsave(port, &flags); |
| 1789 | − ctrl = serial_port_in(port, SCSCR); | |
| 1788 | + ctrl = sci_serial_in(port, SCSCR); | |
| 1790 | 1789 | ctrl &= ~(SCSCR_TE | SCSCR_TEIE); |
| 1791 | − serial_port_out(port, SCSCR, ctrl); | |
| 1790 | + sci_serial_out(port, SCSCR, ctrl); | |
| 1792 | 1791 | uart_port_unlock_irqrestore(port, flags); |
| 1793 | 1792 | |
| 1794 | 1793 | return IRQ_HANDLED; |
| @@ -1802,7 +1801,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) · 7 unmodified lines | ||
| 1802 | 1801 | sci_handle_breaks(port); |
| 1803 | 1802 | |
| 1804 | 1803 | /* drop invalid character received before break was detected */ |
| 1805 | − serial_port_in(port, SCxRDR); | |
| 1804 | + sci_serial_in(port, SCxRDR); | |
| 1806 | 1805 | |
| 1807 | 1806 | sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port)); |
| 1808 | 1807 | |
| @@ -1816,7 +1815,7 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr) · 7 unmodified lines | ||
| 1816 | 1815 | |
| 1817 | 1816 | if (s->irqs[SCIx_ERI_IRQ] == s->irqs[SCIx_BRI_IRQ]) { |
| 1818 | 1817 | /* Break and Error interrupts are muxed */ |
| 1819 | − unsigned short ssr_status = serial_port_in(port, SCxSR); | |
| 1818 | + unsigned short ssr_status = sci_serial_in(port, SCxSR); | |
| 1820 | 1819 | |
| 1821 | 1820 | /* Break Interrupt */ |
| 1822 | 1821 | if (ssr_status & SCxSR_BRK(port)) |
| @@ -1831,7 +1830,7 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr) · 8 unmodified lines | ||
| 1831 | 1830 | if (port->type == PORT_SCI) { |
| 1832 | 1831 | if (sci_handle_errors(port)) { |
| 1833 | 1832 | /* discard character in rx buffer */ |
| 1834 | − serial_port_in(port, SCxSR); | |
| 1833 | + sci_serial_in(port, SCxSR); | |
| 1835 | 1834 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); |
| 1836 | 1835 | } |
| 1837 | 1836 | } else { |
| @@ -1856,12 +1855,12 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) · 18 unmodified lines | ||
| 1856 | 1855 | struct sci_port *s = to_sci_port(port); |
| 1857 | 1856 | irqreturn_t ret = IRQ_NONE; |
| 1858 | 1857 | |
| 1859 | − ssr_status = serial_port_in(port, SCxSR); | |
| 1860 | − scr_status = serial_port_in(port, SCSCR); | |
| 1858 | + ssr_status = sci_serial_in(port, SCxSR); | |
| 1859 | + scr_status = sci_serial_in(port, SCSCR); | |
| 1861 | 1860 | if (s->params->overrun_reg == SCxSR) |
| 1862 | 1861 | orer_status = ssr_status; |
| 1863 | 1862 | else if (sci_getreg(port, s->params->overrun_reg)->size) |
| 1864 | − orer_status = serial_port_in(port, s->params->overrun_reg); | |
| 1863 | + orer_status = sci_serial_in(port, s->params->overrun_reg); | |
| 1865 | 1864 | |
| 1866 | 1865 | err_enabled = scr_status & port_rx_irq_mask(port); |
| 1867 | 1866 | |
| @@ -2038,7 +2037,7 @@ static void sci_free_irq(struct sci_port *port) · 170 unmodified lines | ||
| 2038 | 2037 | |
| 2039 | 2038 | static unsigned int sci_tx_empty(struct uart_port *port) |
| 2040 | 2039 | { |
| 2041 | − unsigned short status = serial_port_in(port, SCxSR); | |
| 2040 | + unsigned short status = sci_serial_in(port, SCxSR); | |
| 2042 | 2041 | unsigned short in_tx_fifo = sci_txfill(port); |
| 2043 | 2042 | |
| 2044 | 2043 | 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) · 2 unmodified lines | ||
| 2047 | 2046 | static void sci_set_rts(struct uart_port *port, bool state) |
| 2048 | 2047 | { |
| 2049 | 2048 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 2050 | − u16 data = serial_port_in(port, SCPDR); | |
| 2049 | + u16 data = sci_serial_in(port, SCPDR); | |
| 2051 | 2050 | |
| 2052 | 2051 | /* Active low */ |
| 2053 | 2052 | if (state) |
| 2054 | 2053 | data &= ~SCPDR_RTSD; |
| 2055 | 2054 | else |
| 2056 | 2055 | data |= SCPDR_RTSD; |
| 2057 | − serial_port_out(port, SCPDR, data); | |
| 2056 | + sci_serial_out(port, SCPDR, data); | |
| 2058 | 2057 | |
| 2059 | 2058 | /* RTS# is output */ |
| 2060 | − serial_port_out(port, SCPCR, | |
| 2061 | − serial_port_in(port, SCPCR) | SCPCR_RTSC); | |
| 2059 | + sci_serial_out(port, SCPCR, | |
| 2060 | + sci_serial_in(port, SCPCR) | SCPCR_RTSC); | |
| 2062 | 2061 | } else if (sci_getreg(port, SCSPTR)->size) { |
| 2063 | − u16 ctrl = serial_port_in(port, SCSPTR); | |
| 2062 | + u16 ctrl = sci_serial_in(port, SCSPTR); | |
| 2064 | 2063 | |
| 2065 | 2064 | /* Active low */ |
| 2066 | 2065 | if (state) |
| 2067 | 2066 | ctrl &= ~SCSPTR_RTSDT; |
| 2068 | 2067 | else |
| 2069 | 2068 | ctrl |= SCSPTR_RTSDT; |
| 2070 | − serial_port_out(port, SCSPTR, ctrl); | |
| 2069 | + sci_serial_out(port, SCSPTR, ctrl); | |
| 2071 | 2070 | } |
| 2072 | 2071 | } |
| 2073 | 2072 | |
| @@ -2075,10 +2074,10 @@ static bool sci_get_cts(struct uart_port *port) · 1 unmodified line | ||
| 2075 | 2074 | { |
| 2076 | 2075 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 2077 | 2076 | /* Active low */ |
| 2078 | − return !(serial_port_in(port, SCPDR) & SCPDR_CTSD); | |
| 2077 | + return !(sci_serial_in(port, SCPDR) & SCPDR_CTSD); | |
| 2079 | 2078 | } else if (sci_getreg(port, SCSPTR)->size) { |
| 2080 | 2079 | /* Active low */ |
| 2081 | − return !(serial_port_in(port, SCSPTR) & SCSPTR_CTSDT); | |
| 2080 | + return !(sci_serial_in(port, SCSPTR) & SCSPTR_CTSDT); | |
| 2082 | 2081 | } |
| 2083 | 2082 | |
| 2084 | 2083 | return true; |
| @@ -2108,9 +2107,8 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) · 23 unmodified lines | ||
| 2108 | 2107 | */ |
| 2109 | 2108 | reg = sci_getreg(port, SCFCR); |
| 2110 | 2109 | if (reg->size) |
| 2111 | − serial_port_out(port, SCFCR, | |
| 2112 | − serial_port_in(port, SCFCR) | | |
| 2113 | − SCFCR_LOOP); | |
| 2110 | + sci_serial_out(port, SCFCR, | |
| 2111 | + sci_serial_in(port, SCFCR) | SCFCR_LOOP); | |
| 2114 | 2112 | } |
| 2115 | 2113 | |
| 2116 | 2114 | mctrl_gpio_set(s->gpios, mctrl); |
| @@ -2120,21 +2118,21 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) · 3 unmodified lines | ||
| 2120 | 2118 | |
| 2121 | 2119 | if (!(mctrl & TIOCM_RTS)) { |
| 2122 | 2120 | /* Disable Auto RTS */ |
| 2123 | − serial_port_out(port, SCFCR, | |
| 2124 | − serial_port_in(port, SCFCR) & ~SCFCR_MCE); | |
| 2121 | + sci_serial_out(port, SCFCR, | |
| 2122 | + sci_serial_in(port, SCFCR) & ~SCFCR_MCE); | |
| 2125 | 2123 | |
| 2126 | 2124 | /* Clear RTS */ |
| 2127 | 2125 | sci_set_rts(port, 0); |
| 2128 | 2126 | } else if (s->autorts) { |
| 2129 | 2127 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 2130 | 2128 | /* Enable RTS# pin function */ |
| 2131 | − serial_port_out(port, SCPCR, | |
| 2132 | − serial_port_in(port, SCPCR) & ~SCPCR_RTSC); | |
| 2129 | + sci_serial_out(port, SCPCR, | |
| 2130 | + sci_serial_in(port, SCPCR) & ~SCPCR_RTSC); | |
| 2133 | 2131 | } |
| 2134 | 2132 | |
| 2135 | 2133 | /* Enable Auto RTS */ |
| 2136 | − serial_port_out(port, SCFCR, | |
| 2137 | − serial_port_in(port, SCFCR) | SCFCR_MCE); | |
| 2134 | + sci_serial_out(port, SCFCR, | |
| 2135 | + sci_serial_in(port, SCFCR) | SCFCR_MCE); | |
| 2138 | 2136 | } else { |
| 2139 | 2137 | /* Set RTS */ |
| 2140 | 2138 | sci_set_rts(port, 1); |
| @@ -2187,8 +2185,8 @@ static void sci_break_ctl(struct uart_port *port, int break_state) · 46 unmodified lines | ||
| 2187 | 2185 | } |
| 2188 | 2186 | |
| 2189 | 2187 | uart_port_lock_irqsave(port, &flags); |
| 2190 | − scsptr = serial_port_in(port, SCSPTR); | |
| 2191 | − scscr = serial_port_in(port, SCSCR); | |
| 2188 | + scsptr = sci_serial_in(port, SCSPTR); | |
| 2189 | + scscr = sci_serial_in(port, SCSCR); | |
| 2192 | 2190 | |
| 2193 | 2191 | if (break_state == -1) { |
| 2194 | 2192 | scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT; |
| @@ -2198,8 +2196,8 @@ static void sci_break_ctl(struct uart_port *port, int break_state) · 3 unmodified lines | ||
| 2198 | 2196 | scscr |= SCSCR_TE; |
| 2199 | 2197 | } |
| 2200 | 2198 | |
| 2201 | − serial_port_out(port, SCSPTR, scsptr); | |
| 2202 | − serial_port_out(port, SCSCR, scscr); | |
| 2199 | + sci_serial_out(port, SCSPTR, scsptr); | |
| 2200 | + sci_serial_out(port, SCSCR, scscr); | |
| 2203 | 2201 | uart_port_unlock_irqrestore(port, flags); |
| 2204 | 2202 | } |
| 2205 | 2203 | |
| @@ -2239,9 +2237,9 @@ static void sci_shutdown(struct uart_port *port) · 33 unmodified lines | ||
| 2239 | 2237 | * Stop RX and TX, disable related interrupts, keep clock source |
| 2240 | 2238 | * and HSCIF TOT bits |
| 2241 | 2239 | */ |
| 2242 | − scr = serial_port_in(port, SCSCR); | |
| 2243 | − serial_port_out(port, SCSCR, scr & | |
| 2244 | − (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot)); | |
| 2240 | + scr = sci_serial_in(port, SCSCR); | |
| 2241 | + sci_serial_out(port, SCSCR, | |
| 2242 | + scr & (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot)); | |
| 2245 | 2243 | uart_port_unlock_irqrestore(port, flags); |
| 2246 | 2244 | |
| 2247 | 2245 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| @@ -2390,19 +2388,19 @@ static void sci_reset(struct uart_port *port) · 142 unmodified lines | ||
| 2390 | 2388 | unsigned int status; |
| 2391 | 2389 | struct sci_port *s = to_sci_port(port); |
| 2392 | 2390 | |
| 2393 | − serial_port_out(port, SCSCR, s->hscif_tot); /* TE=0, RE=0, CKE1=0 */ | |
| 2391 | + sci_serial_out(port, SCSCR, s->hscif_tot); /* TE=0, RE=0, CKE1=0 */ | |
| 2394 | 2392 | |
| 2395 | 2393 | reg = sci_getreg(port, SCFCR); |
| 2396 | 2394 | if (reg->size) |
| 2397 | − serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | |
| 2395 | + sci_serial_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | |
| 2398 | 2396 | |
| 2399 | 2397 | sci_clear_SCxSR(port, |
| 2400 | 2398 | SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) & |
| 2401 | 2399 | SCxSR_BREAK_CLEAR(port)); |
| 2402 | 2400 | if (sci_getreg(port, SCLSR)->size) { |
| 2403 | − status = serial_port_in(port, SCLSR); | |
| 2401 | + status = sci_serial_in(port, SCLSR); | |
| 2404 | 2402 | status &= ~(SCLSR_TO | SCLSR_ORER); |
| 2405 | − serial_port_out(port, SCLSR, status); | |
| 2403 | + sci_serial_out(port, SCLSR, status); | |
| 2406 | 2404 | } |
| 2407 | 2405 | |
| 2408 | 2406 | if (s->rx_trigger > 1) { |
| @@ -2540,8 +2538,8 @@ done: · 131 unmodified lines | ||
| 2540 | 2538 | * It controls the mux to select (H)SCK or frequency divided clock. |
| 2541 | 2539 | */ |
| 2542 | 2540 | if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) { |
| 2543 | − serial_port_out(port, SCDL, dl); | |
| 2544 | − serial_port_out(port, SCCKS, sccks); | |
| 2541 | + sci_serial_out(port, SCDL, dl); | |
| 2542 | + sci_serial_out(port, SCCKS, sccks); | |
| 2545 | 2543 | } |
| 2546 | 2544 | |
| 2547 | 2545 | uart_port_lock_irqsave(port, &flags); |
| @@ -2554,7 +2552,7 @@ done: · 6 unmodified lines | ||
| 2554 | 2552 | bits = tty_get_frame_size(termios->c_cflag); |
| 2555 | 2553 | |
| 2556 | 2554 | if (sci_getreg(port, SEMR)->size) |
| 2557 | − serial_port_out(port, SEMR, 0); | |
| 2555 | + sci_serial_out(port, SEMR, 0); | |
| 2558 | 2556 | |
| 2559 | 2557 | if (best_clk >= 0) { |
| 2560 | 2558 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
| @@ -2569,9 +2567,9 @@ done: · 8 unmodified lines | ||
| 2569 | 2567 | case 27: smr_val |= SCSMR_SRC_27; break; |
| 2570 | 2568 | } |
| 2571 | 2569 | smr_val |= cks; |
| 2572 | − serial_port_out(port, SCSCR, scr_val | s->hscif_tot); | |
| 2573 | − serial_port_out(port, SCSMR, smr_val); | |
| 2574 | − serial_port_out(port, SCBRR, brr); | |
| 2570 | + sci_serial_out(port, SCSCR, scr_val | s->hscif_tot); | |
| 2571 | + sci_serial_out(port, SCSMR, smr_val); | |
| 2572 | + sci_serial_out(port, SCBRR, brr); | |
| 2575 | 2573 | if (sci_getreg(port, HSSRR)->size) { |
| 2576 | 2574 | unsigned int hssrr = srr | HSCIF_SRE; |
| 2577 | 2575 | /* Calculate deviation from intended rate at the |
| @@ -2593,7 +2591,7 @@ done: · 15 unmodified lines | ||
| 2593 | 2591 | HSCIF_SRHP_MASK; |
| 2594 | 2592 | hssrr |= HSCIF_SRDE; |
| 2595 | 2593 | } |
| 2596 | − serial_port_out(port, HSSRR, hssrr); | |
| 2594 | + sci_serial_out(port, HSSRR, hssrr); | |
| 2597 | 2595 | } |
| 2598 | 2596 | |
| 2599 | 2597 | /* Wait one bit interval */ |
| @@ -2601,10 +2599,10 @@ done: · 1 unmodified line | ||
| 2601 | 2599 | } else { |
| 2602 | 2600 | /* Don't touch the bit rate configuration */ |
| 2603 | 2601 | scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0); |
| 2604 | − smr_val |= serial_port_in(port, SCSMR) & | |
| 2602 | + smr_val |= sci_serial_in(port, SCSMR) & | |
| 2605 | 2603 | (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS); |
| 2606 | − serial_port_out(port, SCSCR, scr_val | s->hscif_tot); | |
| 2607 | − serial_port_out(port, SCSMR, smr_val); | |
| 2604 | + sci_serial_out(port, SCSCR, scr_val | s->hscif_tot); | |
| 2605 | + sci_serial_out(port, SCSMR, smr_val); | |
| 2608 | 2606 | } |
| 2609 | 2607 | |
| 2610 | 2608 | sci_init_pins(port, termios->c_cflag); |
| @@ -2613,7 +2611,7 @@ done: · 2 unmodified lines | ||
| 2613 | 2611 | s->autorts = false; |
| 2614 | 2612 | reg = sci_getreg(port, SCFCR); |
| 2615 | 2613 | if (reg->size) { |
| 2616 | − unsigned short ctrl = serial_port_in(port, SCFCR); | |
| 2614 | + unsigned short ctrl = sci_serial_in(port, SCFCR); | |
| 2617 | 2615 | |
| 2618 | 2616 | if ((port->flags & UPF_HARD_FLOW) && |
| 2619 | 2617 | (termios->c_cflag & CRTSCTS)) { |
| @@ -2630,7 +2628,7 @@ done: · 10 unmodified lines | ||
| 2630 | 2628 | */ |
| 2631 | 2629 | ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST); |
| 2632 | 2630 | |
| 2633 | − serial_port_out(port, SCFCR, ctrl); | |
| 2631 | + sci_serial_out(port, SCFCR, ctrl); | |
| 2634 | 2632 | } |
| 2635 | 2633 | if (port->flags & UPF_HARD_FLOW) { |
| 2636 | 2634 | /* Refresh (Auto) RTS */ |
| @@ -2645,7 +2643,7 @@ done: · 8 unmodified lines | ||
| 2645 | 2643 | if (port->type != PORT_SCI) |
| 2646 | 2644 | scr_val |= SCSCR_TE; |
| 2647 | 2645 | scr_val |= SCSCR_RE | (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)); |
| 2648 | − serial_port_out(port, SCSCR, scr_val | s->hscif_tot); | |
| 2646 | + sci_serial_out(port, SCSCR, scr_val | s->hscif_tot); | |
| 2649 | 2647 | if ((srr + 1 == 5) && |
| 2650 | 2648 | (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) { |
| 2651 | 2649 | /* |
| @@ -3017,9 +3015,6 @@ static int sci_init_single(struct platform_device *dev, · 365 unmodified lines | ||
| 3017 | 3015 | port->irq = sci_port->irqs[SCIx_RXI_IRQ]; |
| 3018 | 3016 | port->irqflags = 0; |
| 3019 | 3017 | |
| 3020 | − port->serial_in = sci_serial_in; | |
| 3021 | − port->serial_out = sci_serial_out; | |
| 3022 | − | |
| 3023 | 3018 | return 0; |
| 3024 | 3019 | } |
| 3025 | 3020 | |
| @@ -3056,21 +3051,21 @@ static void serial_console_write(struct console *co, const char *s, · 30 unmodified lines | ||
| 3056 | 3051 | uart_port_lock_irqsave(port, &flags); |
| 3057 | 3052 | |
| 3058 | 3053 | /* first save SCSCR then disable interrupts, keep clock source */ |
| 3059 | − ctrl = serial_port_in(port, SCSCR); | |
| 3054 | + ctrl = sci_serial_in(port, SCSCR); | |
| 3060 | 3055 | ctrl_temp = SCSCR_RE | SCSCR_TE | |
| 3061 | 3056 | (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | |
| 3062 | 3057 | (ctrl & (SCSCR_CKE1 | SCSCR_CKE0)); |
| 3063 | − serial_port_out(port, SCSCR, ctrl_temp | sci_port->hscif_tot); | |
| 3058 | + sci_serial_out(port, SCSCR, ctrl_temp | sci_port->hscif_tot); | |
| 3064 | 3059 | |
| 3065 | 3060 | uart_console_write(port, s, count, serial_console_putchar); |
| 3066 | 3061 | |
| 3067 | 3062 | /* wait until fifo is empty and last bit has been transmitted */ |
| 3068 | 3063 | bits = SCxSR_TDxE(port) | SCxSR_TEND(port); |
| 3069 | − while ((serial_port_in(port, SCxSR) & bits) != bits) | |
| 3064 | + while ((sci_serial_in(port, SCxSR) & bits) != bits) | |
| 3070 | 3065 | cpu_relax(); |
| 3071 | 3066 | |
| 3072 | 3067 | /* restore the SCSCR */ |
| 3073 | − serial_port_out(port, SCSCR, ctrl); | |
| 3068 | + sci_serial_out(port, SCSCR, ctrl); | |
| 3074 | 3069 | |
| 3075 | 3070 | if (locked) |
| 3076 | 3071 | uart_port_unlock_irqrestore(port, flags); |
| @@ -3503,8 +3498,6 @@ static int __init early_console_setup(struct earlycon_device *device, · 426 unmodified lines | ||
| 3503 | 3498 | if (!device->port.membase) |
| 3504 | 3499 | return -ENODEV; |
| 3505 | 3500 | |
| 3506 | − device->port.serial_in = sci_serial_in; | |
| 3507 | − device->port.serial_out = sci_serial_out; | |
| 3508 | 3501 | device->port.type = type; |
| 3509 | 3502 | memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port)); |
| 3510 | 3503 | port_cfg.type = type; |
| @@ -412,7 +412,8 @@ static void __ssp_receive_chars(struct sifive_serial_port *ssp) · 411 unmodified lines | ||
| 412 | 412 | break; |
| 413 | 413 | |
| 414 | 414 | ssp->port.icount.rx++; |
| 415 | − uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL); | |
| 415 | + if (!uart_prepare_sysrq_char(&ssp->port, ch)) | |
| 416 | + uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL); | |
| 416 | 417 | } |
| 417 | 418 | |
| 418 | 419 | tty_flip_buffer_push(&ssp->port.state->port); |
| @@ -534,7 +535,7 @@ static irqreturn_t sifive_serial_irq(int irq, void *dev_id) · 115 unmodified lines | ||
| 534 | 535 | if (ip & SIFIVE_SERIAL_IP_TXWM_MASK) |
| 535 | 536 | __ssp_transmit_chars(ssp); |
| 536 | 537 | |
| 537 | − uart_port_unlock(&ssp->port); | |
| 538 | + uart_unlock_and_check_sysrq(&ssp->port); | |
| 538 | 539 | |
| 539 | 540 | return IRQ_HANDLED; |
| 540 | 541 | } |
| @@ -791,13 +792,10 @@ static void sifive_serial_console_write(struct console *co, const char *s, · 250 unmodified lines | ||
| 791 | 792 | if (!ssp) |
| 792 | 793 | return; |
| 793 | 794 | |
| 794 | − local_irq_save(flags); | |
| 795 | − if (ssp->port.sysrq) | |
| 796 | − locked = 0; | |
| 797 | − else if (oops_in_progress) | |
| 798 | − locked = uart_port_trylock(&ssp->port); | |
| 795 | + if (oops_in_progress) | |
| 796 | + locked = uart_port_trylock_irqsave(&ssp->port, &flags); | |
| 799 | 797 | else |
| 800 | − uart_port_lock(&ssp->port); | |
| 798 | + uart_port_lock_irqsave(&ssp->port, &flags); | |
| 801 | 799 | |
| 802 | 800 | ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS); |
| 803 | 801 | __ssp_writel(0, SIFIVE_SERIAL_IE_OFFS, ssp); |
| @@ -807,8 +805,7 @@ static void sifive_serial_console_write(struct console *co, const char *s, · 3 unmodified lines | ||
| 807 | 805 | __ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp); |
| 808 | 806 | |
| 809 | 807 | if (locked) |
| 810 | − uart_port_unlock(&ssp->port); | |
| 811 | − local_irq_restore(flags); | |
| 808 | + uart_port_unlock_irqrestore(&ssp->port, flags); | |
| 812 | 809 | } |
| 813 | 810 | |
| 814 | 811 | static int sifive_serial_console_setup(struct console *co, char *options) |
| @@ -465,6 +465,7 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, · 464 unmodified lines | ||
| 465 | 465 | const struct ktermios *old) |
| 466 | 466 | { |
| 467 | 467 | struct asc_port *ascport = to_asc_port(port); |
| 468 | + bool manual_rts, toggle_rts = false; | |
| 468 | 469 | struct gpio_desc *gpiod; |
| 469 | 470 | unsigned int baud; |
| 470 | 471 | u32 ctrl_val; |
| @@ -518,25 +519,13 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, · 47 unmodified lines | ||
| 518 | 519 | |
| 519 | 520 | /* If flow-control selected, stop handling RTS manually */ |
| 520 | 521 | if (ascport->rts) { |
| 521 | − devm_gpiod_put(port->dev, ascport->rts); | |
| 522 | − ascport->rts = NULL; | |
| 523 | − | |
| 524 | − pinctrl_select_state(ascport->pinctrl, | |
| 525 | − ascport->states[DEFAULT]); | |
| 522 | + toggle_rts = true; | |
| 523 | + manual_rts = false; | |
| 526 | 524 | } |
| 527 | 525 | } else { |
| 528 | 526 | /* If flow-control disabled, it's safe to handle RTS manually */ |
| 529 | − if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) { | |
| 530 | − pinctrl_select_state(ascport->pinctrl, | |
| 531 | − ascport->states[NO_HW_FLOWCTRL]); | |
| 532 | − | |
| 533 | − gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW); | |
| 534 | − if (!IS_ERR(gpiod)) { | |
| 535 | − gpiod_set_consumer_name(gpiod, | |
| 536 | − port->dev->of_node->name); | |
| 537 | − ascport->rts = gpiod; | |
| 538 | − } | |
| 539 | − } | |
| 527 | + if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) | |
| 528 | + manual_rts = toggle_rts = true; | |
| 540 | 529 | } |
| 541 | 530 | |
| 542 | 531 | if ((baud < 19200) && !ascport->force_m1) { |
| @@ -595,6 +584,25 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, · 52 unmodified lines | ||
| 595 | 584 | asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN)); |
| 596 | 585 | |
| 597 | 586 | uart_port_unlock_irqrestore(port, flags); |
| 587 | + | |
| 588 | + if (toggle_rts) { | |
| 589 | + if (manual_rts) { | |
| 590 | + pinctrl_select_state(ascport->pinctrl, | |
| 591 | + ascport->states[NO_HW_FLOWCTRL]); | |
| 592 | + | |
| 593 | + gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW); | |
| 594 | + if (!IS_ERR(gpiod)) { | |
| 595 | + gpiod_set_consumer_name(gpiod, | |
| 596 | + port->dev->of_node->name); | |
| 597 | + ascport->rts = gpiod; | |
| 598 | + } | |
| 599 | + } else { | |
| 600 | + devm_gpiod_put(port->dev, ascport->rts); | |
| 601 | + ascport->rts = NULL; | |
| 602 | + pinctrl_select_state(ascport->pinctrl, | |
| 603 | + ascport->states[DEFAULT]); | |
| 604 | + } | |
| 605 | + } | |
| 598 | 606 | } |
| 599 | 607 | |
| 600 | 608 | static const char *asc_type(struct uart_port *port) |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | * Inspired by st-asc.c from STMicroelectronics (c) |
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | +#include <linux/bitfield.h> | |
| 12 | 13 | #include <linux/clk.h> |
| 13 | 14 | #include <linux/console.h> |
| 14 | 15 | #include <linux/delay.h> |
| @@ -39,60 +40,64 @@ · 24 unmodified lines | ||
| 39 | 40 | /* Register offsets */ |
| 40 | 41 | static struct stm32_usart_info __maybe_unused stm32f4_info = { |
| 41 | 42 | .ofs = { |
| 42 | − .isr = 0x00, | |
| 43 | − .rdr = 0x04, | |
| 44 | − .tdr = 0x04, | |
| 45 | − .brr = 0x08, | |
| 46 | − .cr1 = 0x0c, | |
| 47 | − .cr2 = 0x10, | |
| 48 | − .cr3 = 0x14, | |
| 49 | − .gtpr = 0x18, | |
| 50 | − .rtor = UNDEF_REG, | |
| 51 | − .rqr = UNDEF_REG, | |
| 52 | − .icr = UNDEF_REG, | |
| 43 | + .isr = 0x00, | |
| 44 | + .rdr = 0x04, | |
| 45 | + .tdr = 0x04, | |
| 46 | + .brr = 0x08, | |
| 47 | + .cr1 = 0x0c, | |
| 48 | + .cr2 = 0x10, | |
| 49 | + .cr3 = 0x14, | |
| 50 | + .gtpr = 0x18, | |
| 51 | + .rtor = UNDEF_REG, | |
| 52 | + .rqr = UNDEF_REG, | |
| 53 | + .icr = UNDEF_REG, | |
| 54 | + .presc = UNDEF_REG, | |
| 55 | + .hwcfgr1 = UNDEF_REG, | |
| 53 | 56 | }, |
| 54 | 57 | .cfg = { |
| 55 | 58 | .uart_enable_bit = 13, |
| 56 | 59 | .has_7bits_data = false, |
| 57 | − .fifosize = 1, | |
| 58 | 60 | } |
| 59 | 61 | }; |
| 60 | 62 | |
| 61 | 63 | static struct stm32_usart_info __maybe_unused stm32f7_info = { |
| 62 | 64 | .ofs = { |
| 63 | − .cr1 = 0x00, | |
| 64 | − .cr2 = 0x04, | |
| 65 | − .cr3 = 0x08, | |
| 66 | − .brr = 0x0c, | |
| 67 | − .gtpr = 0x10, | |
| 68 | − .rtor = 0x14, | |
| 69 | − .rqr = 0x18, | |
| 70 | − .isr = 0x1c, | |
| 71 | − .icr = 0x20, | |
| 72 | − .rdr = 0x24, | |
| 73 | − .tdr = 0x28, | |
| 65 | + .cr1 = 0x00, | |
| 66 | + .cr2 = 0x04, | |
| 67 | + .cr3 = 0x08, | |
| 68 | + .brr = 0x0c, | |
| 69 | + .gtpr = 0x10, | |
| 70 | + .rtor = 0x14, | |
| 71 | + .rqr = 0x18, | |
| 72 | + .isr = 0x1c, | |
| 73 | + .icr = 0x20, | |
| 74 | + .rdr = 0x24, | |
| 75 | + .tdr = 0x28, | |
| 76 | + .presc = UNDEF_REG, | |
| 77 | + .hwcfgr1 = UNDEF_REG, | |
| 74 | 78 | }, |
| 75 | 79 | .cfg = { |
| 76 | 80 | .uart_enable_bit = 0, |
| 77 | 81 | .has_7bits_data = true, |
| 78 | 82 | .has_swap = true, |
| 79 | − .fifosize = 1, | |
| 80 | 83 | } |
| 81 | 84 | }; |
| 82 | 85 | |
| 83 | 86 | static struct stm32_usart_info __maybe_unused stm32h7_info = { |
| 84 | 87 | .ofs = { |
| 85 | − .cr1 = 0x00, | |
| 86 | − .cr2 = 0x04, | |
| 87 | − .cr3 = 0x08, | |
| 88 | − .brr = 0x0c, | |
| 89 | − .gtpr = 0x10, | |
| 90 | − .rtor = 0x14, | |
| 91 | − .rqr = 0x18, | |
| 92 | − .isr = 0x1c, | |
| 93 | − .icr = 0x20, | |
| 94 | − .rdr = 0x24, | |
| 95 | − .tdr = 0x28, | |
| 88 | + .cr1 = 0x00, | |
| 89 | + .cr2 = 0x04, | |
| 90 | + .cr3 = 0x08, | |
| 91 | + .brr = 0x0c, | |
| 92 | + .gtpr = 0x10, | |
| 93 | + .rtor = 0x14, | |
| 94 | + .rqr = 0x18, | |
| 95 | + .isr = 0x1c, | |
| 96 | + .icr = 0x20, | |
| 97 | + .rdr = 0x24, | |
| 98 | + .tdr = 0x28, | |
| 99 | + .presc = 0x2c, | |
| 100 | + .hwcfgr1 = 0x3f0, | |
| 96 | 101 | }, |
| 97 | 102 | .cfg = { |
| 98 | 103 | .uart_enable_bit = 0, |
| @@ -100,7 +105,6 @@ static struct stm32_usart_info __maybe_unused stm32h7_info = { · 1 unmodified line | ||
| 100 | 105 | .has_swap = true, |
| 101 | 106 | .has_wakeup = true, |
| 102 | 107 | .has_fifo = true, |
| 103 | − .fifosize = 16, | |
| 104 | 108 | } |
| 105 | 109 | }; |
| 106 | 110 | |
| @@ -1147,6 +1151,8 @@ static void stm32_usart_shutdown(struct uart_port *port) · 1040 unmodified lines | ||
| 1147 | 1151 | free_irq(port->irq, port); |
| 1148 | 1152 | } |
| 1149 | 1153 | |
| 1154 | +static const unsigned int stm32_usart_presc_val[] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256}; | |
| 1155 | + | |
| 1150 | 1156 | static void stm32_usart_set_termios(struct uart_port *port, |
| 1151 | 1157 | struct ktermios *termios, |
| 1152 | 1158 | const struct ktermios *old) |
| @@ -1155,17 +1161,19 @@ static void stm32_usart_set_termios(struct uart_port *port, · 2 unmodified lines | ||
| 1155 | 1161 | const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| 1156 | 1162 | const struct stm32_usart_config *cfg = &stm32_port->info->cfg; |
| 1157 | 1163 | struct serial_rs485 *rs485conf = &port->rs485; |
| 1158 | − unsigned int baud, bits; | |
| 1164 | + unsigned int baud, bits, uart_clk, uart_clk_pres; | |
| 1159 | 1165 | u32 usartdiv, mantissa, fraction, oversampling; |
| 1160 | 1166 | tcflag_t cflag = termios->c_cflag; |
| 1161 | − u32 cr1, cr2, cr3, isr; | |
| 1167 | + u32 cr1, cr2, cr3, isr, brr, presc; | |
| 1162 | 1168 | unsigned long flags; |
| 1163 | 1169 | int ret; |
| 1164 | 1170 | |
| 1165 | 1171 | if (!stm32_port->hw_flow_control) |
| 1166 | 1172 | cflag &= ~CRTSCTS; |
| 1167 | 1173 | |
| 1168 | − baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 8); | |
| 1174 | + uart_clk = clk_get_rate(stm32_port->clk); | |
| 1175 | + | |
| 1176 | + baud = uart_get_baud_rate(port, termios, old, 0, uart_clk / 8); | |
| 1169 | 1177 | |
| 1170 | 1178 | uart_port_lock_irqsave(port, &flags); |
| 1171 | 1179 | |
| @@ -1267,27 +1275,48 @@ static void stm32_usart_set_termios(struct uart_port *port, · 95 unmodified lines | ||
| 1267 | 1275 | cr3 |= USART_CR3_CTSE | USART_CR3_RTSE; |
| 1268 | 1276 | } |
| 1269 | 1277 | |
| 1270 | − usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud); | |
| 1278 | + for (presc = 0; presc <= USART_PRESC_MAX; presc++) { | |
| 1279 | + uart_clk_pres = DIV_ROUND_CLOSEST(uart_clk, stm32_usart_presc_val[presc]); | |
| 1280 | + usartdiv = DIV_ROUND_CLOSEST(uart_clk_pres, baud); | |
| 1271 | 1281 | |
| 1272 | − /* | |
| 1273 | − * The USART supports 16 or 8 times oversampling. | |
| 1274 | − * By default we prefer 16 times oversampling, so that the receiver | |
| 1275 | − * has a better tolerance to clock deviations. | |
| 1276 | − * 8 times oversampling is only used to achieve higher speeds. | |
| 1277 | − */ | |
| 1278 | − if (usartdiv < 16) { | |
| 1279 | − oversampling = 8; | |
| 1280 | − cr1 |= USART_CR1_OVER8; | |
| 1281 | − stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8); | |
| 1282 | − } else { | |
| 1283 | − oversampling = 16; | |
| 1284 | − cr1 &= ~USART_CR1_OVER8; | |
| 1285 | − stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_OVER8); | |
| 1282 | + /* | |
| 1283 | + * The USART supports 16 or 8 times oversampling. | |
| 1284 | + * By default we prefer 16 times oversampling, so that the receiver | |
| 1285 | + * has a better tolerance to clock deviations. | |
| 1286 | + * 8 times oversampling is only used to achieve higher speeds. | |
| 1287 | + */ | |
| 1288 | + if (usartdiv < 16) { | |
| 1289 | + oversampling = 8; | |
| 1290 | + cr1 |= USART_CR1_OVER8; | |
| 1291 | + stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8); | |
| 1292 | + } else { | |
| 1293 | + oversampling = 16; | |
| 1294 | + cr1 &= ~USART_CR1_OVER8; | |
| 1295 | + stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_OVER8); | |
| 1296 | + } | |
| 1297 | + | |
| 1298 | + mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT; | |
| 1299 | + fraction = usartdiv % oversampling; | |
| 1300 | + brr = mantissa | fraction; | |
| 1301 | + | |
| 1302 | + if (FIELD_FIT(USART_BRR_MASK, brr)) { | |
| 1303 | + if (ofs->presc != UNDEF_REG) { | |
| 1304 | + port->uartclk = uart_clk_pres; | |
| 1305 | + writel_relaxed(presc, port->membase + ofs->presc); | |
| 1306 | + } else if (presc) { | |
| 1307 | + /* We need a prescaler but we don't have it (STM32F4, STM32F7) */ | |
| 1308 | + dev_err(port->dev, | |
| 1309 | + "unable to set baudrate, input clock is too high"); | |
| 1310 | + } | |
| 1311 | + break; | |
| 1312 | + } else if (presc == USART_PRESC_MAX) { | |
| 1313 | + /* Even with prescaler and brr at max value we can't set baudrate */ | |
| 1314 | + dev_err(port->dev, "unable to set baudrate, input clock is too high"); | |
| 1315 | + break; | |
| 1316 | + } | |
| 1286 | 1317 | } |
| 1287 | 1318 | |
| 1288 | − mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT; | |
| 1289 | − fraction = usartdiv % oversampling; | |
| 1290 | − writel_relaxed(mantissa | fraction, port->membase + ofs->brr); | |
| 1319 | + writel_relaxed(brr, port->membase + ofs->brr); | |
| 1291 | 1320 | |
| 1292 | 1321 | uart_update_timeout(port, cflag, baud); |
| 1293 | 1322 | |
| @@ -1471,37 +1500,57 @@ static const struct uart_ops stm32_uart_ops = { · 177 unmodified lines | ||
| 1471 | 1500 | #endif /* CONFIG_CONSOLE_POLL */ |
| 1472 | 1501 | }; |
| 1473 | 1502 | |
| 1474 | −/* | |
| 1475 | − * STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG) | |
| 1476 | − * Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case, | |
| 1477 | − * RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE. | |
| 1478 | − * So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1. | |
| 1479 | − */ | |
| 1480 | −static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 }; | |
| 1503 | +struct stm32_usart_thresh_ratio { | |
| 1504 | + int mul; | |
| 1505 | + int div; | |
| 1506 | +}; | |
| 1507 | + | |
| 1508 | +static const struct stm32_usart_thresh_ratio stm32h7_usart_fifo_thresh_cfg[] = { | |
| 1509 | + {1, 8}, {1, 4}, {1, 2}, {3, 4}, {7, 8}, {1, 1} }; | |
| 1510 | + | |
| 1511 | +static int stm32_usart_get_thresh_value(u32 fifo_size, int index) | |
| 1512 | +{ | |
| 1513 | + return fifo_size * stm32h7_usart_fifo_thresh_cfg[index].mul / | |
| 1514 | + stm32h7_usart_fifo_thresh_cfg[index].div; | |
| 1515 | +} | |
| 1481 | 1516 | |
| 1482 | −static void stm32_usart_get_ftcfg(struct platform_device *pdev, const char *p, | |
| 1483 | − int *ftcfg) | |
| 1517 | +static int stm32_usart_get_ftcfg(struct platform_device *pdev, struct stm32_port *stm32port, | |
| 1518 | + const char *p, int *ftcfg) | |
| 1484 | 1519 | { |
| 1485 | − u32 bytes, i; | |
| 1520 | + const struct stm32_usart_offsets *ofs = &stm32port->info->ofs; | |
| 1521 | + u32 bytes, i, cfg8; | |
| 1522 | + int fifo_size; | |
| 1523 | + | |
| 1524 | + if (WARN_ON(ofs->hwcfgr1 == UNDEF_REG)) | |
| 1525 | + return 1; | |
| 1526 | + | |
| 1527 | + cfg8 = FIELD_GET(USART_HWCFGR1_CFG8, | |
| 1528 | + readl_relaxed(stm32port->port.membase + ofs->hwcfgr1)); | |
| 1529 | + | |
| 1530 | + /* On STM32H7, hwcfgr is not present, so returned value will be 0 */ | |
| 1531 | + fifo_size = cfg8 ? 1 << cfg8 : STM32H7_USART_FIFO_SIZE; | |
| 1486 | 1532 | |
| 1487 | − /* DT option to get RX & TX FIFO threshold (default to 8 bytes) */ | |
| 1533 | + /* DT option to get RX & TX FIFO threshold (default to half fifo size) */ | |
| 1488 | 1534 | if (of_property_read_u32(pdev->dev.of_node, p, &bytes)) |
| 1489 | − bytes = 8; | |
| 1535 | + bytes = fifo_size / 2; | |
| 1490 | 1536 | |
| 1491 | − for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++) | |
| 1492 | − if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes) | |
| 1537 | + if (bytes < stm32_usart_get_thresh_value(fifo_size, 0)) { | |
| 1538 | + *ftcfg = -EINVAL; | |
| 1539 | + return fifo_size; | |
| 1540 | + } | |
| 1541 | + | |
| 1542 | + for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++) { | |
| 1543 | + if (stm32_usart_get_thresh_value(fifo_size, i) >= bytes) | |
| 1493 | 1544 | break; |
| 1545 | + } | |
| 1494 | 1546 | if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg)) |
| 1495 | 1547 | i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1; |
| 1496 | 1548 | |
| 1497 | − dev_dbg(&pdev->dev, "%s set to %d bytes\n", p, | |
| 1498 | − stm32h7_usart_fifo_thresh_cfg[i]); | |
| 1549 | + dev_dbg(&pdev->dev, "%s set to %d/%d bytes\n", p, | |
| 1550 | + stm32_usart_get_thresh_value(fifo_size, i), fifo_size); | |
| 1499 | 1551 | |
| 1500 | − /* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */ | |
| 1501 | − if (i) | |
| 1502 | − *ftcfg = i - 1; | |
| 1503 | − else | |
| 1504 | − *ftcfg = -EINVAL; | |
| 1552 | + *ftcfg = i; | |
| 1553 | + return fifo_size; | |
| 1505 | 1554 | } |
| 1506 | 1555 | |
| 1507 | 1556 | static void stm32_usart_deinit_port(struct stm32_port *stm32port) |
| @@ -1531,7 +1580,6 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, · 23 unmodified lines | ||
| 1531 | 1580 | port->flags = UPF_BOOT_AUTOCONF; |
| 1532 | 1581 | port->ops = &stm32_uart_ops; |
| 1533 | 1582 | port->dev = &pdev->dev; |
| 1534 | − port->fifosize = stm32port->info->cfg.fifosize; | |
| 1535 | 1583 | port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); |
| 1536 | 1584 | port->irq = irq; |
| 1537 | 1585 | port->rs485_config = stm32_usart_config_rs485; |
| @@ -1547,14 +1595,6 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, · 9 unmodified lines | ||
| 1547 | 1595 | stm32port->swap = stm32port->info->cfg.has_swap && |
| 1548 | 1596 | of_property_read_bool(pdev->dev.of_node, "rx-tx-swap"); |
| 1549 | 1597 | |
| 1550 | − stm32port->fifoen = stm32port->info->cfg.has_fifo; | |
| 1551 | − if (stm32port->fifoen) { | |
| 1552 | − stm32_usart_get_ftcfg(pdev, "rx-threshold", | |
| 1553 | − &stm32port->rxftcfg); | |
| 1554 | − stm32_usart_get_ftcfg(pdev, "tx-threshold", | |
| 1555 | − &stm32port->txftcfg); | |
| 1556 | − } | |
| 1557 | − | |
| 1558 | 1598 | port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); |
| 1559 | 1599 | if (IS_ERR(port->membase)) |
| 1560 | 1600 | return PTR_ERR(port->membase); |
| @@ -1577,6 +1617,15 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, · 16 unmodified lines | ||
| 1577 | 1617 | goto err_clk; |
| 1578 | 1618 | } |
| 1579 | 1619 | |
| 1620 | + stm32port->fifoen = stm32port->info->cfg.has_fifo; | |
| 1621 | + if (stm32port->fifoen) { | |
| 1622 | + stm32_usart_get_ftcfg(pdev, stm32port, "rx-threshold", &stm32port->rxftcfg); | |
| 1623 | + port->fifosize = stm32_usart_get_ftcfg(pdev, stm32port, "tx-threshold", | |
| 1624 | + &stm32port->txftcfg); | |
| 1625 | + } else { | |
| 1626 | + port->fifosize = 1; | |
| 1627 | + } | |
| 1628 | + | |
| 1580 | 1629 | stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0); |
| 1581 | 1630 | if (IS_ERR(stm32port->gpios)) { |
| 1582 | 1631 | ret = PTR_ERR(stm32port->gpios); |
| @@ -9,17 +9,19 @@ · 8 unmodified lines | ||
| 9 | 9 | #define DRIVER_NAME "stm32-usart" |
| 10 | 10 | |
| 11 | 11 | struct stm32_usart_offsets { |
| 12 | − u8 cr1; | |
| 13 | − u8 cr2; | |
| 14 | − u8 cr3; | |
| 15 | − u8 brr; | |
| 16 | − u8 gtpr; | |
| 17 | − u8 rtor; | |
| 18 | − u8 rqr; | |
| 19 | − u8 isr; | |
| 20 | − u8 icr; | |
| 21 | − u8 rdr; | |
| 22 | − u8 tdr; | |
| 12 | + u16 cr1; | |
| 13 | + u16 cr2; | |
| 14 | + u16 cr3; | |
| 15 | + u16 brr; | |
| 16 | + u16 gtpr; | |
| 17 | + u16 rtor; | |
| 18 | + u16 rqr; | |
| 19 | + u16 isr; | |
| 20 | + u16 icr; | |
| 21 | + u16 rdr; | |
| 22 | + u16 tdr; | |
| 23 | + u16 presc; | |
| 24 | + u16 hwcfgr1; | |
| 23 | 25 | }; |
| 24 | 26 | |
| 25 | 27 | struct stm32_usart_config { |
| @@ -28,7 +30,6 @@ struct stm32_usart_config { · 2 unmodified lines | ||
| 28 | 30 | bool has_swap; |
| 29 | 31 | bool has_wakeup; |
| 30 | 32 | bool has_fifo; |
| 31 | − int fifosize; | |
| 32 | 33 | }; |
| 33 | 34 | |
| 34 | 35 | struct stm32_usart_info { |
| @@ -36,7 +37,7 @@ struct stm32_usart_info { · 1 unmodified line | ||
| 36 | 37 | struct stm32_usart_config cfg; |
| 37 | 38 | }; |
| 38 | 39 | |
| 39 | −#define UNDEF_REG 0xff | |
| 40 | +#define UNDEF_REG 0xffff | |
| 40 | 41 | |
| 41 | 42 | /* USART_SR (F4) / USART_ISR (F7) */ |
| 42 | 43 | #define USART_SR_PE BIT(0) |
| @@ -71,6 +72,7 @@ struct stm32_usart_info { · 28 unmodified lines | ||
| 71 | 72 | #define USART_BRR_DIV_M_MASK GENMASK(15, 4) |
| 72 | 73 | #define USART_BRR_DIV_M_SHIFT 4 |
| 73 | 74 | #define USART_BRR_04_R_SHIFT 1 |
| 75 | +#define USART_BRR_MASK (USART_BRR_DIV_M_MASK | USART_BRR_DIV_F_MASK) | |
| 74 | 76 | |
| 75 | 77 | /* USART_CR1 */ |
| 76 | 78 | #define USART_CR1_SBK BIT(0) |
| @@ -176,8 +178,16 @@ struct stm32_usart_info { · 99 unmodified lines | ||
| 176 | 178 | #define USART_ICR_CMCF BIT(17) /* F7 */ |
| 177 | 179 | #define USART_ICR_WUCF BIT(20) /* H7 */ |
| 178 | 180 | |
| 181 | +/* USART_PRESC */ | |
| 182 | +#define USART_PRESC GENMASK(3, 0) /* H7 */ | |
| 183 | +#define USART_PRESC_MAX 0b1011 | |
| 184 | + | |
| 185 | +/* USART_HWCFCR1 */ | |
| 186 | +#define USART_HWCFGR1_CFG8 GENMASK(31, 28) /* MP1 */ | |
| 187 | + | |
| 179 | 188 | #define STM32_SERIAL_NAME "ttySTM" |
| 180 | −#define STM32_MAX_PORTS 8 | |
| 189 | +#define STM32_MAX_PORTS 9 | |
| 190 | +#define STM32H7_USART_FIFO_SIZE 16 | |
| 181 | 191 | |
| 182 | 192 | #define RX_BUF_L 4096 /* dma rx buffer length */ |
| 183 | 193 | #define RX_BUF_P (RX_BUF_L / 2) /* dma rx buffer period */ |
| @@ -260,7 +260,7 @@ static void receive_chars(struct uart_port *port) · 259 unmodified lines | ||
| 260 | 260 | if (port->ignore_status_mask & SUP_DUMMY_READ) |
| 261 | 261 | goto ignore_char; |
| 262 | 262 | |
| 263 | − if (uart_handle_sysrq_char(port, ch)) | |
| 263 | + if (uart_prepare_sysrq_char(port, ch)) | |
| 264 | 264 | goto ignore_char; |
| 265 | 265 | |
| 266 | 266 | 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) · 20 unmodified lines | ||
| 287 | 287 | if (isc & SUP_UART_ISC_TX) |
| 288 | 288 | transmit_chars(port); |
| 289 | 289 | |
| 290 | − uart_port_unlock(port); | |
| 290 | + uart_unlock_and_check_sysrq(port); | |
| 291 | 291 | |
| 292 | 292 | return IRQ_HANDLED; |
| 293 | 293 | } |
| @@ -512,22 +512,16 @@ static void sunplus_console_write(struct console *co, · 218 unmodified lines | ||
| 512 | 512 | unsigned long flags; |
| 513 | 513 | int locked = 1; |
| 514 | 514 | |
| 515 | − local_irq_save(flags); | |
| 516 | − | |
| 517 | − if (sunplus_console_ports[co->index]->port.sysrq) | |
| 518 | − locked = 0; | |
| 519 | − else if (oops_in_progress) | |
| 520 | − locked = uart_port_trylock(&sunplus_console_ports[co->index]->port); | |
| 515 | + if (oops_in_progress) | |
| 516 | + locked = uart_port_trylock_irqsave(&sunplus_console_ports[co->index]->port, &flags); | |
| 521 | 517 | else |
| 522 | − uart_port_lock(&sunplus_console_ports[co->index]->port); | |
| 518 | + uart_port_lock_irqsave(&sunplus_console_ports[co->index]->port, &flags); | |
| 523 | 519 | |
| 524 | 520 | uart_console_write(&sunplus_console_ports[co->index]->port, s, count, |
| 525 | 521 | sunplus_uart_console_putchar); |
| 526 | 522 | |
| 527 | 523 | if (locked) |
| 528 | − uart_port_unlock(&sunplus_console_ports[co->index]->port); | |
| 529 | − | |
| 530 | − local_irq_restore(flags); | |
| 524 | + uart_port_unlock_irqrestore(&sunplus_console_ports[co->index]->port, flags); | |
| 531 | 525 | } |
| 532 | 526 | |
| 533 | 527 | static int __init sunplus_console_setup(struct console *co, char *options) |
| @@ -22,7 +22,9 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/of.h> |
| 23 | 23 | #include <linux/module.h> |
| 24 | 24 | #include <linux/pm_runtime.h> |
| 25 | −#include <linux/iopoll.h> | |
| 25 | +#include <linux/gpio.h> | |
| 26 | +#include <linux/gpio/consumer.h> | |
| 27 | +#include <linux/delay.h> | |
| 26 | 28 | |
| 27 | 29 | #define CDNS_UART_TTY_NAME "ttyPS" |
| 28 | 30 | #define CDNS_UART_NAME "xuartps" |
| @@ -193,6 +195,9 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); · 164 unmodified lines | ||
| 193 | 195 | * @clk_rate_change_nb: Notifier block for clock changes |
| 194 | 196 | * @quirks: Flags for RXBS support. |
| 195 | 197 | * @cts_override: Modem control state override |
| 198 | + * @gpiod_rts: Pointer to the gpio descriptor | |
| 199 | + * @rs485_tx_started: RS485 tx state | |
| 200 | + * @tx_timer: Timer for tx | |
| 196 | 201 | */ |
| 197 | 202 | struct cdns_uart { |
| 198 | 203 | struct uart_port *port; |
| @@ -203,10 +208,21 @@ struct cdns_uart { · 4 unmodified lines | ||
| 203 | 208 | struct notifier_block clk_rate_change_nb; |
| 204 | 209 | u32 quirks; |
| 205 | 210 | bool cts_override; |
| 211 | + struct gpio_desc *gpiod_rts; | |
| 212 | + bool rs485_tx_started; | |
| 213 | + struct hrtimer tx_timer; | |
| 206 | 214 | }; |
| 207 | 215 | struct cdns_platform_data { |
| 208 | 216 | u32 quirks; |
| 209 | 217 | }; |
| 218 | + | |
| 219 | +struct serial_rs485 cdns_rs485_supported = { | |
| 220 | + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | | |
| 221 | + SER_RS485_RTS_AFTER_SEND, | |
| 222 | + .delay_rts_before_send = 1, | |
| 223 | + .delay_rts_after_send = 1, | |
| 224 | +}; | |
| 225 | + | |
| 210 | 226 | #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ |
| 211 | 227 | clk_rate_change_nb) |
| 212 | 228 | |
| @@ -306,17 +322,114 @@ static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus) · 93 unmodified lines | ||
| 306 | 322 | } |
| 307 | 323 | |
| 308 | 324 | /** |
| 309 | − * cdns_uart_handle_tx - Handle the bytes to be Txed. | |
| 325 | + * cdns_rts_gpio_enable - Configure RTS/GPIO to high/low | |
| 326 | + * @cdns_uart: Handle to the cdns_uart | |
| 327 | + * @enable: Value to be set to RTS/GPIO | |
| 328 | + */ | |
| 329 | +static void cdns_rts_gpio_enable(struct cdns_uart *cdns_uart, bool enable) | |
| 330 | +{ | |
| 331 | + u32 val; | |
| 332 | + | |
| 333 | + if (cdns_uart->gpiod_rts) { | |
| 334 | + gpiod_set_value(cdns_uart->gpiod_rts, enable); | |
| 335 | + } else { | |
| 336 | + val = readl(cdns_uart->port->membase + CDNS_UART_MODEMCR); | |
| 337 | + if (enable) | |
| 338 | + val |= CDNS_UART_MODEMCR_RTS; | |
| 339 | + else | |
| 340 | + val &= ~CDNS_UART_MODEMCR_RTS; | |
| 341 | + writel(val, cdns_uart->port->membase + CDNS_UART_MODEMCR); | |
| 342 | + } | |
| 343 | +} | |
| 344 | + | |
| 345 | +/** | |
| 346 | + * cdns_rs485_tx_setup - Tx setup specific to rs485 | |
| 347 | + * @cdns_uart: Handle to the cdns_uart | |
| 348 | + */ | |
| 349 | +static void cdns_rs485_tx_setup(struct cdns_uart *cdns_uart) | |
| 350 | +{ | |
| 351 | + bool enable; | |
| 352 | + | |
| 353 | + enable = cdns_uart->port->rs485.flags & SER_RS485_RTS_ON_SEND; | |
| 354 | + cdns_rts_gpio_enable(cdns_uart, enable); | |
| 355 | + | |
| 356 | + cdns_uart->rs485_tx_started = true; | |
| 357 | +} | |
| 358 | + | |
| 359 | +/** | |
| 360 | + * cdns_rs485_rx_setup - Rx setup specific to rs485 | |
| 361 | + * @cdns_uart: Handle to the cdns_uart | |
| 362 | + */ | |
| 363 | +static void cdns_rs485_rx_setup(struct cdns_uart *cdns_uart) | |
| 364 | +{ | |
| 365 | + bool enable; | |
| 366 | + | |
| 367 | + enable = cdns_uart->port->rs485.flags & SER_RS485_RTS_AFTER_SEND; | |
| 368 | + cdns_rts_gpio_enable(cdns_uart, enable); | |
| 369 | + | |
| 370 | + cdns_uart->rs485_tx_started = false; | |
| 371 | +} | |
| 372 | + | |
| 373 | +/** | |
| 374 | + * cdns_uart_tx_empty - Check whether TX is empty | |
| 375 | + * @port: Handle to the uart port structure | |
| 376 | + * | |
| 377 | + * Return: TIOCSER_TEMT on success, 0 otherwise | |
| 378 | + */ | |
| 379 | +static unsigned int cdns_uart_tx_empty(struct uart_port *port) | |
| 380 | +{ | |
| 381 | + unsigned int status; | |
| 382 | + | |
| 383 | + status = readl(port->membase + CDNS_UART_SR); | |
| 384 | + status &= (CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE); | |
| 385 | + return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0; | |
| 386 | +} | |
| 387 | + | |
| 388 | +/** | |
| 389 | + * cdns_rs485_rx_callback - Timer rx callback handler for rs485. | |
| 390 | + * @t: Handle to the hrtimer structure | |
| 391 | + */ | |
| 392 | +static enum hrtimer_restart cdns_rs485_rx_callback(struct hrtimer *t) | |
| 393 | +{ | |
| 394 | + struct cdns_uart *cdns_uart = container_of(t, struct cdns_uart, tx_timer); | |
| 395 | + | |
| 396 | + /* | |
| 397 | + * Default Rx should be setup, because Rx signaling path | |
| 398 | + * need to enable to receive data. | |
| 399 | + */ | |
| 400 | + cdns_rs485_rx_setup(cdns_uart); | |
| 401 | + | |
| 402 | + return HRTIMER_NORESTART; | |
| 403 | +} | |
| 404 | + | |
| 405 | +/** | |
| 406 | + * cdns_calc_after_tx_delay - calculate delay required for after tx. | |
| 407 | + * @cdns_uart: Handle to the cdns_uart | |
| 408 | + */ | |
| 409 | +static u64 cdns_calc_after_tx_delay(struct cdns_uart *cdns_uart) | |
| 410 | +{ | |
| 411 | + /* | |
| 412 | + * Frame time + stop bit time + rs485.delay_rts_after_send | |
| 413 | + */ | |
| 414 | + return cdns_uart->port->frame_time | |
| 415 | + + DIV_ROUND_UP(cdns_uart->port->frame_time, 7) | |
| 416 | + + (u64)cdns_uart->port->rs485.delay_rts_after_send * NSEC_PER_MSEC; | |
| 417 | +} | |
| 418 | + | |
| 419 | +/** | |
| 420 | + * cdns_uart_handle_tx - Handle the bytes to be transmitted. | |
| 310 | 421 | * @dev_id: Id of the UART port |
| 311 | 422 | * Return: None |
| 312 | 423 | */ |
| 313 | 424 | static void cdns_uart_handle_tx(void *dev_id) |
| 314 | 425 | { |
| 315 | 426 | struct uart_port *port = (struct uart_port *)dev_id; |
| 427 | + struct cdns_uart *cdns_uart = port->private_data; | |
| 316 | 428 | struct circ_buf *xmit = &port->state->xmit; |
| 317 | 429 | unsigned int numbytes; |
| 318 | 430 | |
| 319 | − if (uart_circ_empty(xmit)) { | |
| 431 | + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | |
| 432 | + /* Disable the TX Empty interrupt */ | |
| 320 | 433 | writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR); |
| 321 | 434 | return; |
| 322 | 435 | } |
| @@ -332,6 +445,16 @@ static void cdns_uart_handle_tx(void *dev_id) · 9 unmodified lines | ||
| 332 | 445 | |
| 333 | 446 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| 334 | 447 | uart_write_wakeup(port); |
| 448 | + | |
| 449 | + /* Enable the TX Empty interrupt */ | |
| 450 | + writel(CDNS_UART_IXR_TXEMPTY, cdns_uart->port->membase + CDNS_UART_IER); | |
| 451 | + | |
| 452 | + if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED && | |
| 453 | + (uart_circ_empty(xmit) || uart_tx_stopped(port))) { | |
| 454 | + cdns_uart->tx_timer.function = &cdns_rs485_rx_callback; | |
| 455 | + hrtimer_start(&cdns_uart->tx_timer, | |
| 456 | + ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart)), HRTIMER_MODE_REL); | |
| 457 | + } | |
| 335 | 458 | } |
| 336 | 459 | |
| 337 | 460 | /** |
| @@ -564,6 +687,21 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, · 226 unmodified lines | ||
| 564 | 687 | } |
| 565 | 688 | #endif |
| 566 | 689 | |
| 690 | +/** | |
| 691 | + * cdns_rs485_tx_callback - Timer tx callback handler for rs485. | |
| 692 | + * @t: Handle to the hrtimer structure | |
| 693 | + */ | |
| 694 | +static enum hrtimer_restart cdns_rs485_tx_callback(struct hrtimer *t) | |
| 695 | +{ | |
| 696 | + struct cdns_uart *cdns_uart = container_of(t, struct cdns_uart, tx_timer); | |
| 697 | + | |
| 698 | + uart_port_lock(cdns_uart->port); | |
| 699 | + cdns_uart_handle_tx(cdns_uart->port); | |
| 700 | + uart_port_unlock(cdns_uart->port); | |
| 701 | + | |
| 702 | + return HRTIMER_NORESTART; | |
| 703 | +} | |
| 704 | + | |
| 567 | 705 | /** |
| 568 | 706 | * cdns_uart_start_tx - Start transmitting bytes |
| 569 | 707 | * @port: Handle to the uart port structure |
| @@ -571,6 +709,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, · 1 unmodified line | ||
| 571 | 709 | static void cdns_uart_start_tx(struct uart_port *port) |
| 572 | 710 | { |
| 573 | 711 | unsigned int status; |
| 712 | + struct cdns_uart *cdns_uart = port->private_data; | |
| 574 | 713 | |
| 575 | 714 | if (uart_tx_stopped(port)) |
| 576 | 715 | return; |
| @@ -587,12 +726,19 @@ static void cdns_uart_start_tx(struct uart_port *port) · 10 unmodified lines | ||
| 587 | 726 | if (uart_circ_empty(&port->state->xmit)) |
| 588 | 727 | return; |
| 589 | 728 | |
| 729 | + /* Clear the TX Empty interrupt */ | |
| 590 | 730 | writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); |
| 591 | 731 | |
| 732 | + if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) { | |
| 733 | + if (!cdns_uart->rs485_tx_started) { | |
| 734 | + cdns_uart->tx_timer.function = &cdns_rs485_tx_callback; | |
| 735 | + cdns_rs485_tx_setup(cdns_uart); | |
| 736 | + return hrtimer_start(&cdns_uart->tx_timer, | |
| 737 | + ms_to_ktime(port->rs485.delay_rts_before_send), | |
| 738 | + HRTIMER_MODE_REL); | |
| 739 | + } | |
| 740 | + } | |
| 592 | 741 | cdns_uart_handle_tx(port); |
| 593 | − | |
| 594 | − /* Enable the TX Empty interrupt */ | |
| 595 | − writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER); | |
| 596 | 742 | } |
| 597 | 743 | |
| 598 | 744 | /** |
| @@ -602,6 +748,10 @@ static void cdns_uart_start_tx(struct uart_port *port) · 3 unmodified lines | ||
| 602 | 748 | static void cdns_uart_stop_tx(struct uart_port *port) |
| 603 | 749 | { |
| 604 | 750 | unsigned int regval; |
| 751 | + struct cdns_uart *cdns_uart = port->private_data; | |
| 752 | + | |
| 753 | + if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) | |
| 754 | + cdns_rs485_rx_setup(cdns_uart); | |
| 605 | 755 | |
| 606 | 756 | regval = readl(port->membase + CDNS_UART_CR); |
| 607 | 757 | regval |= CDNS_UART_CR_TX_DIS; |
| @@ -626,21 +776,6 @@ static void cdns_uart_stop_rx(struct uart_port *port) · 18 unmodified lines | ||
| 626 | 776 | writel(regval, port->membase + CDNS_UART_CR); |
| 627 | 777 | } |
| 628 | 778 | |
| 629 | −/** | |
| 630 | − * cdns_uart_tx_empty - Check whether TX is empty | |
| 631 | − * @port: Handle to the uart port structure | |
| 632 | − * | |
| 633 | − * Return: TIOCSER_TEMT on success, 0 otherwise | |
| 634 | − */ | |
| 635 | −static unsigned int cdns_uart_tx_empty(struct uart_port *port) | |
| 636 | −{ | |
| 637 | − unsigned int status; | |
| 638 | − | |
| 639 | − status = readl(port->membase + CDNS_UART_SR) & | |
| 640 | − (CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE); | |
| 641 | − return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0; | |
| 642 | −} | |
| 643 | − | |
| 644 | 779 | /** |
| 645 | 780 | * cdns_uart_break_ctl - Based on the input ctl we have to start or stop |
| 646 | 781 | * transmitting char breaks |
| @@ -829,6 +964,9 @@ static int cdns_uart_startup(struct uart_port *port) · 182 unmodified lines | ||
| 829 | 964 | (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) |
| 830 | 965 | cpu_relax(); |
| 831 | 966 | |
| 967 | + if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) | |
| 968 | + cdns_rs485_rx_setup(cdns_uart); | |
| 969 | + | |
| 832 | 970 | /* |
| 833 | 971 | * Clear the RX disable bit and then set the RX enable bit to enable |
| 834 | 972 | * the receiver. |
| @@ -888,6 +1026,10 @@ static void cdns_uart_shutdown(struct uart_port *port) · 53 unmodified lines | ||
| 888 | 1026 | { |
| 889 | 1027 | int status; |
| 890 | 1028 | unsigned long flags; |
| 1029 | + struct cdns_uart *cdns_uart = port->private_data; | |
| 1030 | + | |
| 1031 | + if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) | |
| 1032 | + hrtimer_cancel(&cdns_uart->tx_timer); | |
| 891 | 1033 | |
| 892 | 1034 | uart_port_lock_irqsave(port, &flags); |
| 893 | 1035 | |
| @@ -1033,6 +1175,8 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) · 139 unmodified lines | ||
| 1033 | 1175 | |
| 1034 | 1176 | if (mctrl & TIOCM_RTS) |
| 1035 | 1177 | val |= CDNS_UART_MODEMCR_RTS; |
| 1178 | + if (cdns_uart_data->gpiod_rts) | |
| 1179 | + gpiod_set_value(cdns_uart_data->gpiod_rts, !(mctrl & TIOCM_RTS)); | |
| 1036 | 1180 | if (mctrl & TIOCM_DTR) |
| 1037 | 1181 | val |= CDNS_UART_MODEMCR_DTR; |
| 1038 | 1182 | if (mctrl & TIOCM_LOOP) |
| @@ -1455,6 +1599,39 @@ MODULE_DEVICE_TABLE(of, cdns_uart_of_match); · 416 unmodified lines | ||
| 1455 | 1599 | /* Temporary variable for storing number of instances */ |
| 1456 | 1600 | static int instances; |
| 1457 | 1601 | |
| 1602 | +/** | |
| 1603 | + * cdns_rs485_config - Called when an application calls TIOCSRS485 ioctl. | |
| 1604 | + * @port: Pointer to the uart_port structure | |
| 1605 | + * @termios: Pointer to the ktermios structure | |
| 1606 | + * @rs485: Pointer to the serial_rs485 structure | |
| 1607 | + * | |
| 1608 | + * Return: 0 | |
| 1609 | + */ | |
| 1610 | +static int cdns_rs485_config(struct uart_port *port, struct ktermios *termios, | |
| 1611 | + struct serial_rs485 *rs485) | |
| 1612 | +{ | |
| 1613 | + u32 val; | |
| 1614 | + struct cdns_uart *cdns_uart = port->private_data; | |
| 1615 | + | |
| 1616 | + if (rs485->flags & SER_RS485_ENABLED) { | |
| 1617 | + dev_dbg(port->dev, "Setting UART to RS485\n"); | |
| 1618 | + /* Make sure auto RTS is disabled */ | |
| 1619 | + val = readl(port->membase + CDNS_UART_MODEMCR); | |
| 1620 | + val &= ~CDNS_UART_MODEMCR_FCM; | |
| 1621 | + writel(val, port->membase + CDNS_UART_MODEMCR); | |
| 1622 | + | |
| 1623 | + /* Timer setup */ | |
| 1624 | + hrtimer_init(&cdns_uart->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | |
| 1625 | + cdns_uart->tx_timer.function = &cdns_rs485_tx_callback; | |
| 1626 | + | |
| 1627 | + /* Disable transmitter and make Rx setup*/ | |
| 1628 | + cdns_uart_stop_tx(port); | |
| 1629 | + } else { | |
| 1630 | + hrtimer_cancel(&cdns_uart->tx_timer); | |
| 1631 | + } | |
| 1632 | + return 0; | |
| 1633 | +} | |
| 1634 | + | |
| 1458 | 1635 | /** |
| 1459 | 1636 | * cdns_uart_probe - Platform driver probe |
| 1460 | 1637 | * @pdev: Pointer to the platform device structure |
| @@ -1597,9 +1774,23 @@ static int cdns_uart_probe(struct platform_device *pdev) · 136 unmodified lines | ||
| 1597 | 1774 | port->private_data = cdns_uart_data; |
| 1598 | 1775 | port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG | |
| 1599 | 1776 | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT; |
| 1777 | + port->rs485_config = cdns_rs485_config; | |
| 1778 | + port->rs485_supported = cdns_rs485_supported; | |
| 1600 | 1779 | cdns_uart_data->port = port; |
| 1601 | 1780 | platform_set_drvdata(pdev, port); |
| 1602 | 1781 | |
| 1782 | + rc = uart_get_rs485_mode(port); | |
| 1783 | + if (rc) | |
| 1784 | + goto err_out_clk_notifier; | |
| 1785 | + | |
| 1786 | + cdns_uart_data->gpiod_rts = devm_gpiod_get_optional(&pdev->dev, "rts", | |
| 1787 | + GPIOD_OUT_LOW); | |
| 1788 | + if (IS_ERR(cdns_uart_data->gpiod_rts)) { | |
| 1789 | + rc = PTR_ERR(cdns_uart_data->gpiod_rts); | |
| 1790 | + dev_err(port->dev, "xuartps: devm_gpiod_get_optional failed\n"); | |
| 1791 | + goto err_out_clk_notifier; | |
| 1792 | + } | |
| 1793 | + | |
| 1603 | 1794 | pm_runtime_use_autosuspend(&pdev->dev); |
| 1604 | 1795 | pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); |
| 1605 | 1796 | pm_runtime_set_active(&pdev->dev); |
| @@ -1618,6 +1809,8 @@ static int cdns_uart_probe(struct platform_device *pdev) · 12 unmodified lines | ||
| 1618 | 1809 | console_port = port; |
| 1619 | 1810 | } |
| 1620 | 1811 | #endif |
| 1812 | + if (cdns_uart_data->port->rs485.flags & SER_RS485_ENABLED) | |
| 1813 | + cdns_rs485_rx_setup(cdns_uart_data); | |
| 1621 | 1814 | |
| 1622 | 1815 | rc = uart_add_one_port(&cdns_uart_uart_driver, port); |
| 1623 | 1816 | if (rc) { |
| @@ -1646,6 +1839,7 @@ err_out_pm_disable: · 22 unmodified lines | ||
| 1646 | 1839 | pm_runtime_disable(&pdev->dev); |
| 1647 | 1840 | pm_runtime_set_suspended(&pdev->dev); |
| 1648 | 1841 | pm_runtime_dont_use_autosuspend(&pdev->dev); |
| 1842 | +err_out_clk_notifier: | |
| 1649 | 1843 | #ifdef CONFIG_COMMON_CLK |
| 1650 | 1844 | clk_notifier_unregister(cdns_uart_data->uartclk, |
| 1651 | 1845 | &cdns_uart_data->clk_rate_change_nb); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/errno.h> |
| 8 | 8 | #include <linux/minmax.h> |
| 9 | 9 | #include <linux/tty.h> |
| 10 | +#include <linux/tty_buffer.h> | |
| 10 | 11 | #include <linux/tty_driver.h> |
| 11 | 12 | #include <linux/tty_flip.h> |
| 12 | 13 | #include <linux/timer.h> |
| @@ -5,9 +5,9 @@ · 4 unmodified lines | ||
| 5 | 5 | FONTMAPFILE = cp437.uni |
| 6 | 6 | |
| 7 | 7 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \ |
| 8 | − selection.o keyboard.o | |
| 8 | + selection.o keyboard.o \ | |
| 9 | + vt.o defkeymap.o | |
| 9 | 10 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o |
| 10 | −obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | |
| 11 | 11 | |
| 12 | 12 | # Files generated that shall be removed upon make clean |
| 13 | 13 | clean-files := consolemap_deftbl.c defkeymap.c |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | * 'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)' |
| 8 | 8 | * 'void clear_selection(void)' |
| 9 | 9 | * 'int paste_selection(struct tty_struct *)' |
| 10 | − * 'int sel_loadlut(char __user *)' | |
| 10 | + * 'int sel_loadlut(u32 __user *)' | |
| 11 | 11 | * |
| 12 | 12 | * Now that /dev/vcs exists, most of this can disappear again. |
| 13 | 13 | */ |
| @@ -73,10 +73,12 @@ sel_pos(int n, bool unicode) · 59 unmodified lines | ||
| 73 | 73 | } |
| 74 | 74 | |
| 75 | 75 | /** |
| 76 | − * clear_selection - remove current selection | |
| 76 | + * clear_selection - remove current selection | |
| 77 | 77 | * |
| 78 | − * Remove the current selection highlight, if any from the console | |
| 79 | − * holding the selection. The caller must hold the console lock. | |
| 78 | + * Remove the current selection highlight, if any from the console holding the | |
| 79 | + * selection. | |
| 80 | + * | |
| 81 | + * Locking: The caller must hold the console lock. | |
| 80 | 82 | */ |
| 81 | 83 | void clear_selection(void) |
| 82 | 84 | { |
| @@ -88,7 +90,7 @@ void clear_selection(void) · 5 unmodified lines | ||
| 88 | 90 | } |
| 89 | 91 | EXPORT_SYMBOL_GPL(clear_selection); |
| 90 | 92 | |
| 91 | −bool vc_is_sel(struct vc_data *vc) | |
| 93 | +bool vc_is_sel(const struct vc_data *vc) | |
| 92 | 94 | { |
| 93 | 95 | return vc == vc_sel.cons; |
| 94 | 96 | } |
| @@ -110,18 +112,25 @@ static inline int inword(const u32 c) · 15 unmodified lines | ||
| 110 | 112 | } |
| 111 | 113 | |
| 112 | 114 | /** |
| 113 | − * sel_loadlut() - load the LUT table | |
| 114 | − * @p: user table | |
| 115 | + * sel_loadlut() - load the LUT table | |
| 116 | + * @lut: user table | |
| 117 | + * | |
| 118 | + * Load the LUT table from user space. Make a temporary copy so a partial | |
| 119 | + * update doesn't make a mess. | |
| 115 | 120 | * |
| 116 | − * Load the LUT table from user space. The caller must hold the console | |
| 117 | − * lock. Make a temporary copy so a partial update doesn't make a mess. | |
| 121 | + * Locking: The console lock is acquired. | |
| 118 | 122 | */ |
| 119 | −int sel_loadlut(char __user *p) | |
| 123 | +int sel_loadlut(u32 __user *lut) | |
| 120 | 124 | { |
| 121 | 125 | u32 tmplut[ARRAY_SIZE(inwordLut)]; |
| 122 | − if (copy_from_user(tmplut, (u32 __user *)(p+4), sizeof(inwordLut))) | |
| 126 | + | |
| 127 | + if (copy_from_user(tmplut, lut, sizeof(inwordLut))) | |
| 123 | 128 | return -EFAULT; |
| 129 | + | |
| 130 | + console_lock(); | |
| 124 | 131 | memcpy(inwordLut, tmplut, sizeof(inwordLut)); |
| 132 | + console_unlock(); | |
| 133 | + | |
| 125 | 134 | return 0; |
| 126 | 135 | } |
| 127 | 136 | |
| @@ -166,14 +175,14 @@ static int store_utf8(u32 c, char *p) · 38 unmodified lines | ||
| 166 | 175 | } |
| 167 | 176 | |
| 168 | 177 | /** |
| 169 | − * set_selection_user - set the current selection. | |
| 170 | − * @sel: user selection info | |
| 171 | − * @tty: the console tty | |
| 178 | + * set_selection_user - set the current selection. | |
| 179 | + * @sel: user selection info | |
| 180 | + * @tty: the console tty | |
| 172 | 181 | * |
| 173 | − * Invoked by the ioctl handle for the vt layer. | |
| 182 | + * Invoked by the ioctl handle for the vt layer. | |
| 174 | 183 | * |
| 175 | − * The entire selection process is managed under the console_lock. It's | |
| 176 | − * a lot under the lock but its hardly a performance path | |
| 184 | + * Locking: The entire selection process is managed under the console_lock. | |
| 185 | + * It's a lot under the lock but its hardly a performance path. | |
| 177 | 186 | */ |
| 178 | 187 | int set_selection_user(const struct tiocl_selection __user *sel, |
| 179 | 188 | struct tty_struct *tty) |
| @@ -145,7 +145,7 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y); · 144 unmodified lines | ||
| 145 | 145 | static void save_cur(struct vc_data *vc); |
| 146 | 146 | static void reset_terminal(struct vc_data *vc, int do_clear); |
| 147 | 147 | static void con_flush_chars(struct tty_struct *tty); |
| 148 | −static int set_vesa_blanking(char __user *p); | |
| 148 | +static int set_vesa_blanking(u8 __user *mode); | |
| 149 | 149 | static void set_cursor(struct vc_data *vc); |
| 150 | 150 | static void hide_cursor(struct vc_data *vc); |
| 151 | 151 | static void console_callback(struct work_struct *ignored); |
| @@ -175,7 +175,7 @@ int do_poke_blanked_console; · 23 unmodified lines | ||
| 175 | 175 | int console_blanked; |
| 176 | 176 | EXPORT_SYMBOL(console_blanked); |
| 177 | 177 | |
| 178 | −static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ | |
| 178 | +static enum vesa_blank_mode vesa_blank_mode; | |
| 179 | 179 | static int vesa_off_interval; |
| 180 | 180 | static int blankinterval; |
| 181 | 181 | core_param(consoleblank, blankinterval, int, 0444); |
| @@ -286,18 +286,20 @@ static inline bool con_should_update(const struct vc_data *vc) · 104 unmodified lines | ||
| 286 | 286 | return con_is_visible(vc) && !console_blanked; |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | −static inline unsigned short *screenpos(const struct vc_data *vc, int offset, | |
| 290 | − bool viewed) | |
| 289 | +static inline u16 *screenpos(const struct vc_data *vc, unsigned int offset, | |
| 290 | + bool viewed) | |
| 291 | 291 | { |
| 292 | − unsigned short *p; | |
| 293 | − | |
| 294 | − if (!viewed) | |
| 295 | − p = (unsigned short *)(vc->vc_origin + offset); | |
| 296 | − else if (!vc->vc_sw->con_screen_pos) | |
| 297 | − p = (unsigned short *)(vc->vc_visible_origin + offset); | |
| 292 | + unsigned long origin = viewed ? vc->vc_visible_origin : vc->vc_origin; | |
| 293 | + | |
| 294 | + return (u16 *)(origin + offset); | |
| 295 | +} | |
| 296 | + | |
| 297 | +static void con_putc(struct vc_data *vc, u16 ca, unsigned int y, unsigned int x) | |
| 298 | +{ | |
| 299 | + if (vc->vc_sw->con_putc) | |
| 300 | + vc->vc_sw->con_putc(vc, ca, y, x); | |
| 298 | 301 | else |
| 299 | − p = vc->vc_sw->con_screen_pos(vc, offset); | |
| 300 | − return p; | |
| 302 | + vc->vc_sw->con_putcs(vc, &ca, 1, y, x); | |
| 301 | 303 | } |
| 302 | 304 | |
| 303 | 305 | /* Called from the keyboard irq path.. */ |
| @@ -591,18 +593,12 @@ static void con_scroll(struct vc_data *vc, unsigned int top, · 287 unmodified lines | ||
| 591 | 593 | static void do_update_region(struct vc_data *vc, unsigned long start, int count) |
| 592 | 594 | { |
| 593 | 595 | unsigned int xx, yy, offset; |
| 594 | − u16 *p; | |
| 596 | + u16 *p = (u16 *)start; | |
| 597 | + | |
| 598 | + offset = (start - vc->vc_origin) / 2; | |
| 599 | + xx = offset % vc->vc_cols; | |
| 600 | + yy = offset / vc->vc_cols; | |
| 595 | 601 | |
| 596 | − p = (u16 *) start; | |
| 597 | − if (!vc->vc_sw->con_getxy) { | |
| 598 | − offset = (start - vc->vc_origin) / 2; | |
| 599 | − xx = offset % vc->vc_cols; | |
| 600 | − yy = offset / vc->vc_cols; | |
| 601 | − } else { | |
| 602 | − int nxx, nyy; | |
| 603 | − start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy); | |
| 604 | − xx = nxx; yy = nyy; | |
| 605 | − } | |
| 606 | 602 | for(;;) { |
| 607 | 603 | u16 attrib = scr_readw(p) & 0xff00; |
| 608 | 604 | int startx = xx; |
| @@ -625,10 +621,6 @@ static void do_update_region(struct vc_data *vc, unsigned long start, int count) · 16 unmodified lines | ||
| 625 | 621 | break; |
| 626 | 622 | xx = 0; |
| 627 | 623 | yy++; |
| 628 | − if (vc->vc_sw->con_getxy) { | |
| 629 | − p = (u16 *)start; | |
| 630 | − start = vc->vc_sw->con_getxy(vc, start, NULL, NULL); | |
| 631 | − } | |
| 632 | 624 | } |
| 633 | 625 | } |
| 634 | 626 | |
| @@ -703,7 +695,7 @@ static void update_attr(struct vc_data *vc) · 68 unmodified lines | ||
| 703 | 695 | /* Note: inverting the screen twice should revert to the original state */ |
| 704 | 696 | void invert_screen(struct vc_data *vc, int offset, int count, bool viewed) |
| 705 | 697 | { |
| 706 | − unsigned short *p; | |
| 698 | + u16 *p; | |
| 707 | 699 | |
| 708 | 700 | WARN_CONSOLE_UNLOCKED(); |
| 709 | 701 | |
| @@ -762,7 +754,7 @@ void complement_pos(struct vc_data *vc, int offset) · 52 unmodified lines | ||
| 762 | 754 | old_offset < vc->vc_screenbuf_size) { |
| 763 | 755 | scr_writew(old, screenpos(vc, old_offset, true)); |
| 764 | 756 | if (con_should_update(vc)) |
| 765 | − vc->vc_sw->con_putc(vc, old, oldy, oldx); | |
| 757 | + con_putc(vc, old, oldy, oldx); | |
| 766 | 758 | notify_update(vc); |
| 767 | 759 | } |
| 768 | 760 | |
| @@ -771,15 +763,14 @@ void complement_pos(struct vc_data *vc, int offset) · 2 unmodified lines | ||
| 771 | 763 | if (offset != -1 && offset >= 0 && |
| 772 | 764 | offset < vc->vc_screenbuf_size) { |
| 773 | 765 | unsigned short new; |
| 774 | − unsigned short *p; | |
| 775 | − p = screenpos(vc, offset, true); | |
| 766 | + u16 *p = screenpos(vc, offset, true); | |
| 776 | 767 | old = scr_readw(p); |
| 777 | 768 | new = old ^ vc->vc_complement_mask; |
| 778 | 769 | scr_writew(new, p); |
| 779 | 770 | if (con_should_update(vc)) { |
| 780 | 771 | oldx = (offset >> 1) % vc->vc_cols; |
| 781 | 772 | oldy = (offset >> 1) / vc->vc_cols; |
| 782 | − vc->vc_sw->con_putc(vc, new, oldy, oldx); | |
| 773 | + con_putc(vc, new, oldy, oldx); | |
| 783 | 774 | } |
| 784 | 775 | notify_update(vc); |
| 785 | 776 | } |
| @@ -833,7 +824,7 @@ static void add_softcursor(struct vc_data *vc) · 47 unmodified lines | ||
| 833 | 824 | i ^= CUR_FG; |
| 834 | 825 | scr_writew(i, (u16 *)vc->vc_pos); |
| 835 | 826 | if (con_should_update(vc)) |
| 836 | − vc->vc_sw->con_putc(vc, i, vc->state.y, vc->state.x); | |
| 827 | + con_putc(vc, i, vc->state.y, vc->state.x); | |
| 837 | 828 | } |
| 838 | 829 | |
| 839 | 830 | static void hide_softcursor(struct vc_data *vc) |
| @@ -841,8 +832,8 @@ static void hide_softcursor(struct vc_data *vc) · 1 unmodified line | ||
| 841 | 832 | if (softcursor_original != -1) { |
| 842 | 833 | scr_writew(softcursor_original, (u16 *)vc->vc_pos); |
| 843 | 834 | if (con_should_update(vc)) |
| 844 | − vc->vc_sw->con_putc(vc, softcursor_original, | |
| 845 | − vc->state.y, vc->state.x); | |
| 835 | + con_putc(vc, softcursor_original, vc->state.y, | |
| 836 | + vc->state.x); | |
| 846 | 837 | softcursor_original = -1; |
| 847 | 838 | } |
| 848 | 839 | } |
| @@ -852,7 +843,7 @@ static void hide_cursor(struct vc_data *vc) · 3 unmodified lines | ||
| 852 | 843 | if (vc_is_sel(vc)) |
| 853 | 844 | clear_selection(); |
| 854 | 845 | |
| 855 | − vc->vc_sw->con_cursor(vc, CM_ERASE); | |
| 846 | + vc->vc_sw->con_cursor(vc, false); | |
| 856 | 847 | hide_softcursor(vc); |
| 857 | 848 | } |
| 858 | 849 | |
| @@ -865,7 +856,7 @@ static void set_cursor(struct vc_data *vc) · 6 unmodified lines | ||
| 865 | 856 | clear_selection(); |
| 866 | 857 | add_softcursor(vc); |
| 867 | 858 | if (CUR_SIZE(vc->vc_cursor_type) != CUR_NONE) |
| 868 | − vc->vc_sw->con_cursor(vc, CM_DRAW); | |
| 859 | + vc->vc_sw->con_cursor(vc, true); | |
| 869 | 860 | } else |
| 870 | 861 | hide_cursor(vc); |
| 871 | 862 | } |
| @@ -897,21 +888,18 @@ static void flush_scrollback(struct vc_data *vc) · 25 unmodified lines | ||
| 897 | 888 | WARN_CONSOLE_UNLOCKED(); |
| 898 | 889 | |
| 899 | 890 | set_origin(vc); |
| 900 | − if (vc->vc_sw->con_flush_scrollback) { | |
| 901 | − vc->vc_sw->con_flush_scrollback(vc); | |
| 902 | − } else if (con_is_visible(vc)) { | |
| 903 | − /* | |
| 904 | − * When no con_flush_scrollback method is provided then the | |
| 905 | − * legacy way for flushing the scrollback buffer is to use | |
| 906 | − * a side effect of the con_switch method. We do it only on | |
| 907 | − * the foreground console as background consoles have no | |
| 908 | − * scrollback buffers in that case and we obviously don't | |
| 909 | − * want to switch to them. | |
| 910 | − */ | |
| 911 | − hide_cursor(vc); | |
| 912 | − vc->vc_sw->con_switch(vc); | |
| 913 | − set_cursor(vc); | |
| 914 | − } | |
| 891 | + if (!con_is_visible(vc)) | |
| 892 | + return; | |
| 893 | + | |
| 894 | + /* | |
| 895 | + * The legacy way for flushing the scrollback buffer is to use a side | |
| 896 | + * effect of the con_switch method. We do it only on the foreground | |
| 897 | + * console as background consoles have no scrollback buffers in that | |
| 898 | + * case and we obviously don't want to switch to them. | |
| 899 | + */ | |
| 900 | + hide_cursor(vc); | |
| 901 | + vc->vc_sw->con_switch(vc); | |
| 902 | + set_cursor(vc); | |
| 915 | 903 | } |
| 916 | 904 | |
| 917 | 905 | /* |
| @@ -962,7 +950,7 @@ void redraw_screen(struct vc_data *vc, int is_switch) · 44 unmodified lines | ||
| 962 | 950 | } |
| 963 | 951 | |
| 964 | 952 | if (redraw) { |
| 965 | − int update; | |
| 953 | + bool update; | |
| 966 | 954 | int old_was_color = vc->vc_can_do_color; |
| 967 | 955 | |
| 968 | 956 | set_origin(vc); |
| @@ -999,7 +987,7 @@ int vc_cons_allocated(unsigned int i) · 30 unmodified lines | ||
| 999 | 987 | return (i < MAX_NR_CONSOLES && vc_cons[i].d); |
| 1000 | 988 | } |
| 1001 | 989 | |
| 1002 | −static void visual_init(struct vc_data *vc, int num, int init) | |
| 990 | +static void visual_init(struct vc_data *vc, int num, bool init) | |
| 1003 | 991 | { |
| 1004 | 992 | /* ++Geert: vc->vc_sw->con_init determines console size */ |
| 1005 | 993 | if (vc->vc_sw) |
| @@ -1083,7 +1071,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ · 77 unmodified lines | ||
| 1083 | 1071 | vc->port.ops = &vc_port_ops; |
| 1084 | 1072 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
| 1085 | 1073 | |
| 1086 | − visual_init(vc, currcons, 1); | |
| 1074 | + visual_init(vc, currcons, true); | |
| 1087 | 1075 | |
| 1088 | 1076 | if (!*vc->uni_pagedict_loc) |
| 1089 | 1077 | con_set_default_unimap(vc); |
| @@ -1115,51 +1103,44 @@ err_free: · 25 unmodified lines | ||
| 1115 | 1103 | } |
| 1116 | 1104 | |
| 1117 | 1105 | static inline int resize_screen(struct vc_data *vc, int width, int height, |
| 1118 | − int user) | |
| 1106 | + bool from_user) | |
| 1119 | 1107 | { |
| 1120 | 1108 | /* Resizes the resolution of the display adapater */ |
| 1121 | 1109 | int err = 0; |
| 1122 | 1110 | |
| 1123 | 1111 | if (vc->vc_sw->con_resize) |
| 1124 | − err = vc->vc_sw->con_resize(vc, width, height, user); | |
| 1112 | + err = vc->vc_sw->con_resize(vc, width, height, from_user); | |
| 1125 | 1113 | |
| 1126 | 1114 | return err; |
| 1127 | 1115 | } |
| 1128 | 1116 | |
| 1129 | 1117 | /** |
| 1130 | − * vc_do_resize - resizing method for the tty | |
| 1131 | − * @tty: tty being resized | |
| 1132 | − * @vc: virtual console private data | |
| 1133 | − * @cols: columns | |
| 1134 | − * @lines: lines | |
| 1118 | + * vc_do_resize - resizing method for the tty | |
| 1119 | + * @tty: tty being resized | |
| 1120 | + * @vc: virtual console private data | |
| 1121 | + * @cols: columns | |
| 1122 | + * @lines: lines | |
| 1123 | + * @from_user: invoked by a user? | |
| 1135 | 1124 | * |
| 1136 | − * Resize a virtual console, clipping according to the actual constraints. | |
| 1137 | − * If the caller passes a tty structure then update the termios winsize | |
| 1138 | − * information and perform any necessary signal handling. | |
| 1125 | + * Resize a virtual console, clipping according to the actual constraints. If | |
| 1126 | + * the caller passes a tty structure then update the termios winsize | |
| 1127 | + * information and perform any necessary signal handling. | |
| 1139 | 1128 | * |
| 1140 | − * Caller must hold the console semaphore. Takes the termios rwsem and | |
| 1141 | − * ctrl.lock of the tty IFF a tty is passed. | |
| 1129 | + * Locking: Caller must hold the console semaphore. Takes the termios rwsem and | |
| 1130 | + * ctrl.lock of the tty IFF a tty is passed. | |
| 1142 | 1131 | */ |
| 1143 | − | |
| 1144 | 1132 | static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, |
| 1145 | − unsigned int cols, unsigned int lines) | |
| 1133 | + unsigned int cols, unsigned int lines, bool from_user) | |
| 1146 | 1134 | { |
| 1147 | 1135 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
| 1148 | 1136 | unsigned long end; |
| 1149 | 1137 | unsigned int old_rows, old_row_size, first_copied_row; |
| 1150 | 1138 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; |
| 1151 | − unsigned int user; | |
| 1152 | 1139 | unsigned short *oldscreen, *newscreen; |
| 1153 | 1140 | u32 **new_uniscr = NULL; |
| 1154 | 1141 | |
| 1155 | 1142 | WARN_CONSOLE_UNLOCKED(); |
| 1156 | 1143 | |
| 1157 | − if (!vc) | |
| 1158 | − return -ENXIO; | |
| 1159 | − | |
| 1160 | − user = vc->vc_resize_user; | |
| 1161 | − vc->vc_resize_user = 0; | |
| 1162 | − | |
| 1163 | 1144 | if (cols > VC_MAXCOL || lines > VC_MAXROW) |
| 1164 | 1145 | return -EINVAL; |
| 1165 | 1146 | |
| @@ -1185,7 +1166,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, · 19 unmodified lines | ||
| 1185 | 1166 | * to deal with possible errors from the code below, we call |
| 1186 | 1167 | * the resize_screen here as well. |
| 1187 | 1168 | */ |
| 1188 | − return resize_screen(vc, new_cols, new_rows, user); | |
| 1169 | + return resize_screen(vc, new_cols, new_rows, from_user); | |
| 1189 | 1170 | } |
| 1190 | 1171 | |
| 1191 | 1172 | 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, · 16 unmodified lines | ||
| 1208 | 1189 | old_rows = vc->vc_rows; |
| 1209 | 1190 | old_row_size = vc->vc_size_row; |
| 1210 | 1191 | |
| 1211 | − err = resize_screen(vc, new_cols, new_rows, user); | |
| 1192 | + err = resize_screen(vc, new_cols, new_rows, from_user); | |
| 1212 | 1193 | if (err) { |
| 1213 | 1194 | kfree(newscreen); |
| 1214 | 1195 | vc_uniscr_free(new_uniscr); |
| @@ -1295,34 +1276,35 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, · 80 unmodified lines | ||
| 1295 | 1276 | } |
| 1296 | 1277 | |
| 1297 | 1278 | /** |
| 1298 | − * vc_resize - resize a VT | |
| 1299 | − * @vc: virtual console | |
| 1300 | − * @cols: columns | |
| 1301 | − * @rows: rows | |
| 1279 | + * __vc_resize - resize a VT | |
| 1280 | + * @vc: virtual console | |
| 1281 | + * @cols: columns | |
| 1282 | + * @rows: rows | |
| 1283 | + * @from_user: invoked by a user? | |
| 1284 | + * | |
| 1285 | + * Resize a virtual console as seen from the console end of things. We use the | |
| 1286 | + * common vc_do_resize() method to update the structures. | |
| 1302 | 1287 | * |
| 1303 | − * Resize a virtual console as seen from the console end of things. We | |
| 1304 | − * use the common vc_do_resize methods to update the structures. The | |
| 1305 | − * caller must hold the console sem to protect console internals and | |
| 1306 | − * vc->port.tty | |
| 1288 | + * Locking: The caller must hold the console sem to protect console internals | |
| 1289 | + * and @vc->port.tty. | |
| 1307 | 1290 | */ |
| 1308 | − | |
| 1309 | −int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | |
| 1291 | +int __vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows, | |
| 1292 | + bool from_user) | |
| 1310 | 1293 | { |
| 1311 | − return vc_do_resize(vc->port.tty, vc, cols, rows); | |
| 1294 | + return vc_do_resize(vc->port.tty, vc, cols, rows, from_user); | |
| 1312 | 1295 | } |
| 1313 | −EXPORT_SYMBOL(vc_resize); | |
| 1296 | +EXPORT_SYMBOL(__vc_resize); | |
| 1314 | 1297 | |
| 1315 | 1298 | /** |
| 1316 | − * vt_resize - resize a VT | |
| 1317 | − * @tty: tty to resize | |
| 1318 | − * @ws: winsize attributes | |
| 1299 | + * vt_resize - resize a VT | |
| 1300 | + * @tty: tty to resize | |
| 1301 | + * @ws: winsize attributes | |
| 1319 | 1302 | * |
| 1320 | − * Resize a virtual terminal. This is called by the tty layer as we | |
| 1321 | − * register our own handler for resizing. The mutual helper does all | |
| 1322 | − * the actual work. | |
| 1303 | + * Resize a virtual terminal. This is called by the tty layer as we register | |
| 1304 | + * our own handler for resizing. The mutual helper does all the actual work. | |
| 1323 | 1305 | * |
| 1324 | − * Takes the console sem and the called methods then take the tty | |
| 1325 | − * termios_rwsem and the tty ctrl.lock in that order. | |
| 1306 | + * Locking: Takes the console sem and the called methods then take the tty | |
| 1307 | + * termios_rwsem and the tty ctrl.lock in that order. | |
| 1326 | 1308 | */ |
| 1327 | 1309 | static int vt_resize(struct tty_struct *tty, struct winsize *ws) |
| 1328 | 1310 | { |
| @@ -1330,7 +1312,7 @@ static int vt_resize(struct tty_struct *tty, struct winsize *ws) · 1 unmodified line | ||
| 1330 | 1312 | int ret; |
| 1331 | 1313 | |
| 1332 | 1314 | console_lock(); |
| 1333 | − ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row); | |
| 1315 | + ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row, false); | |
| 1334 | 1316 | console_unlock(); |
| 1335 | 1317 | return ret; |
| 1336 | 1318 | } |
| @@ -1503,36 +1485,43 @@ static inline void del(struct vc_data *vc) · 166 unmodified lines | ||
| 1503 | 1485 | /* ignored */ |
| 1504 | 1486 | } |
| 1505 | 1487 | |
| 1506 | −static void csi_J(struct vc_data *vc, int vpar) | |
| 1488 | +enum CSI_J { | |
| 1489 | + CSI_J_CURSOR_TO_END = 0, | |
| 1490 | + CSI_J_START_TO_CURSOR = 1, | |
| 1491 | + CSI_J_VISIBLE = 2, | |
| 1492 | + CSI_J_FULL = 3, | |
| 1493 | +}; | |
| 1494 | + | |
| 1495 | +static void csi_J(struct vc_data *vc, enum CSI_J vpar) | |
| 1507 | 1496 | { |
| 1497 | + unsigned short *start; | |
| 1508 | 1498 | unsigned int count; |
| 1509 | − unsigned short * start; | |
| 1510 | 1499 | |
| 1511 | 1500 | switch (vpar) { |
| 1512 | − case 0: /* erase from cursor to end of display */ | |
| 1513 | − vc_uniscr_clear_line(vc, vc->state.x, | |
| 1514 | − vc->vc_cols - vc->state.x); | |
| 1515 | − vc_uniscr_clear_lines(vc, vc->state.y + 1, | |
| 1516 | − vc->vc_rows - vc->state.y - 1); | |
| 1517 | − count = (vc->vc_scr_end - vc->vc_pos) >> 1; | |
| 1518 | − start = (unsigned short *)vc->vc_pos; | |
| 1519 | − break; | |
| 1520 | − case 1: /* erase from start to cursor */ | |
| 1521 | − vc_uniscr_clear_line(vc, 0, vc->state.x + 1); | |
| 1522 | − vc_uniscr_clear_lines(vc, 0, vc->state.y); | |
| 1523 | − count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; | |
| 1524 | − start = (unsigned short *)vc->vc_origin; | |
| 1525 | − break; | |
| 1526 | − case 3: /* include scrollback */ | |
| 1527 | − flush_scrollback(vc); | |
| 1528 | − fallthrough; | |
| 1529 | − case 2: /* erase whole display */ | |
| 1530 | − vc_uniscr_clear_lines(vc, 0, vc->vc_rows); | |
| 1531 | − count = vc->vc_cols * vc->vc_rows; | |
| 1532 | − start = (unsigned short *)vc->vc_origin; | |
| 1533 | − break; | |
| 1534 | − default: | |
| 1535 | − return; | |
| 1501 | + case CSI_J_CURSOR_TO_END: | |
| 1502 | + vc_uniscr_clear_line(vc, vc->state.x, | |
| 1503 | + vc->vc_cols - vc->state.x); | |
| 1504 | + vc_uniscr_clear_lines(vc, vc->state.y + 1, | |
| 1505 | + vc->vc_rows - vc->state.y - 1); | |
| 1506 | + count = (vc->vc_scr_end - vc->vc_pos) >> 1; | |
| 1507 | + start = (unsigned short *)vc->vc_pos; | |
| 1508 | + break; | |
| 1509 | + case CSI_J_START_TO_CURSOR: | |
| 1510 | + vc_uniscr_clear_line(vc, 0, vc->state.x + 1); | |
| 1511 | + vc_uniscr_clear_lines(vc, 0, vc->state.y); | |
| 1512 | + count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; | |
| 1513 | + start = (unsigned short *)vc->vc_origin; | |
| 1514 | + break; | |
| 1515 | + case CSI_J_FULL: | |
| 1516 | + flush_scrollback(vc); | |
| 1517 | + fallthrough; | |
| 1518 | + case CSI_J_VISIBLE: | |
| 1519 | + vc_uniscr_clear_lines(vc, 0, vc->vc_rows); | |
| 1520 | + count = vc->vc_cols * vc->vc_rows; | |
| 1521 | + start = (unsigned short *)vc->vc_origin; | |
| 1522 | + break; | |
| 1523 | + default: | |
| 1524 | + return; | |
| 1536 | 1525 | } |
| 1537 | 1526 | scr_memsetw(start, vc->vc_video_erase_char, 2 * count); |
| 1538 | 1527 | if (con_should_update(vc)) |
| @@ -1540,27 +1529,33 @@ static void csi_J(struct vc_data *vc, int vpar) · 1 unmodified line | ||
| 1540 | 1529 | vc->vc_need_wrap = 0; |
| 1541 | 1530 | } |
| 1542 | 1531 | |
| 1543 | −static void csi_K(struct vc_data *vc, int vpar) | |
| 1532 | +enum { | |
| 1533 | + CSI_K_CURSOR_TO_LINEEND = 0, | |
| 1534 | + CSI_K_LINESTART_TO_CURSOR = 1, | |
| 1535 | + CSI_K_LINE = 2, | |
| 1536 | +}; | |
| 1537 | + | |
| 1538 | +static void csi_K(struct vc_data *vc) | |
| 1544 | 1539 | { |
| 1545 | 1540 | unsigned int count; |
| 1546 | 1541 | unsigned short *start = (unsigned short *)vc->vc_pos; |
| 1547 | 1542 | int offset; |
| 1548 | 1543 | |
| 1549 | − switch (vpar) { | |
| 1550 | − case 0: /* erase from cursor to end of line */ | |
| 1551 | − offset = 0; | |
| 1552 | − count = vc->vc_cols - vc->state.x; | |
| 1553 | − break; | |
| 1554 | − case 1: /* erase from start of line to cursor */ | |
| 1555 | − offset = -vc->state.x; | |
| 1556 | − count = vc->state.x + 1; | |
| 1557 | − break; | |
| 1558 | − case 2: /* erase whole line */ | |
| 1559 | − offset = -vc->state.x; | |
| 1560 | − count = vc->vc_cols; | |
| 1561 | − break; | |
| 1562 | − default: | |
| 1563 | − return; | |
| 1544 | + switch (vc->vc_par[0]) { | |
| 1545 | + case CSI_K_CURSOR_TO_LINEEND: | |
| 1546 | + offset = 0; | |
| 1547 | + count = vc->vc_cols - vc->state.x; | |
| 1548 | + break; | |
| 1549 | + case CSI_K_LINESTART_TO_CURSOR: | |
| 1550 | + offset = -vc->state.x; | |
| 1551 | + count = vc->state.x + 1; | |
| 1552 | + break; | |
| 1553 | + case CSI_K_LINE: | |
| 1554 | + offset = -vc->state.x; | |
| 1555 | + count = vc->vc_cols; | |
| 1556 | + break; | |
| 1557 | + default: | |
| 1558 | + return; | |
| 1564 | 1559 | } |
| 1565 | 1560 | vc_uniscr_clear_line(vc, vc->state.x + offset, count); |
| 1566 | 1561 | 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) · 2 unmodified lines | ||
| 1569 | 1564 | do_update_region(vc, (unsigned long)(start + offset), count); |
| 1570 | 1565 | } |
| 1571 | 1566 | |
| 1572 | −/* erase the following vpar positions */ | |
| 1573 | −static void csi_X(struct vc_data *vc, unsigned int vpar) | |
| 1567 | +/* erase the following count positions */ | |
| 1568 | +static void csi_X(struct vc_data *vc) | |
| 1574 | 1569 | { /* not vt100? */ |
| 1575 | − unsigned int count; | |
| 1576 | − | |
| 1577 | − if (!vpar) | |
| 1578 | − vpar++; | |
| 1579 | − | |
| 1580 | − count = min(vpar, vc->vc_cols - vc->state.x); | |
| 1570 | + unsigned int count = clamp(vc->vc_par[0], 1, vc->vc_cols - vc->state.x); | |
| 1581 | 1571 | |
| 1582 | 1572 | vc_uniscr_clear_line(vc, vc->state.x, count); |
| 1583 | 1573 | scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); |
| 1584 | 1574 | if (con_should_update(vc)) |
| 1585 | − vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, 1, count); | |
| 1575 | + vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, count); | |
| 1586 | 1576 | vc->vc_need_wrap = 0; |
| 1587 | 1577 | } |
| 1588 | 1578 | |
| @@ -1598,7 +1588,7 @@ static void default_attr(struct vc_data *vc) · 9 unmodified lines | ||
| 1598 | 1588 | |
| 1599 | 1589 | struct rgb { u8 r; u8 g; u8 b; }; |
| 1600 | 1590 | |
| 1601 | −static void rgb_from_256(int i, struct rgb *c) | |
| 1591 | +static void rgb_from_256(unsigned int i, struct rgb *c) | |
| 1602 | 1592 | { |
| 1603 | 1593 | if (i < 8) { /* Standard colours. */ |
| 1604 | 1594 | c->r = i&1 ? 0xaa : 0x00; |
| @@ -1609,9 +1599,12 @@ static void rgb_from_256(int i, struct rgb *c) · 4 unmodified lines | ||
| 1609 | 1599 | c->g = i&2 ? 0xff : 0x55; |
| 1610 | 1600 | c->b = i&4 ? 0xff : 0x55; |
| 1611 | 1601 | } else if (i < 232) { /* 6x6x6 colour cube. */ |
| 1612 | − c->r = (i - 16) / 36 * 85 / 2; | |
| 1613 | − c->g = (i - 16) / 6 % 6 * 85 / 2; | |
| 1614 | − c->b = (i - 16) % 6 * 85 / 2; | |
| 1602 | + i -= 16; | |
| 1603 | + c->b = i % 6 * 255 / 6; | |
| 1604 | + i /= 6; | |
| 1605 | + c->g = i % 6 * 255 / 6; | |
| 1606 | + i /= 6; | |
| 1607 | + c->r = i * 255 / 6; | |
| 1615 | 1608 | } else /* Grayscale ramp. */ |
| 1616 | 1609 | c->r = c->g = c->b = i * 10 - 2312; |
| 1617 | 1610 | } |
| @@ -1681,6 +1674,39 @@ static int vc_t416_color(struct vc_data *vc, int i, · 63 unmodified lines | ||
| 1681 | 1674 | return i; |
| 1682 | 1675 | } |
| 1683 | 1676 | |
| 1677 | +enum { | |
| 1678 | + CSI_m_DEFAULT = 0, | |
| 1679 | + CSI_m_BOLD = 1, | |
| 1680 | + CSI_m_HALF_BRIGHT = 2, | |
| 1681 | + CSI_m_ITALIC = 3, | |
| 1682 | + CSI_m_UNDERLINE = 4, | |
| 1683 | + CSI_m_BLINK = 5, | |
| 1684 | + CSI_m_REVERSE = 7, | |
| 1685 | + CSI_m_PRI_FONT = 10, | |
| 1686 | + CSI_m_ALT_FONT1 = 11, | |
| 1687 | + CSI_m_ALT_FONT2 = 12, | |
| 1688 | + CSI_m_DOUBLE_UNDERLINE = 21, | |
| 1689 | + CSI_m_NORMAL_INTENSITY = 22, | |
| 1690 | + CSI_m_NO_ITALIC = 23, | |
| 1691 | + CSI_m_NO_UNDERLINE = 24, | |
| 1692 | + CSI_m_NO_BLINK = 25, | |
| 1693 | + CSI_m_NO_REVERSE = 27, | |
| 1694 | + CSI_m_FG_COLOR_BEG = 30, | |
| 1695 | + CSI_m_FG_COLOR_END = 37, | |
| 1696 | + CSI_m_FG_COLOR = 38, | |
| 1697 | + CSI_m_DEFAULT_FG_COLOR = 39, | |
| 1698 | + CSI_m_BG_COLOR_BEG = 40, | |
| 1699 | + CSI_m_BG_COLOR_END = 47, | |
| 1700 | + CSI_m_BG_COLOR = 48, | |
| 1701 | + CSI_m_DEFAULT_BG_COLOR = 49, | |
| 1702 | + CSI_m_BRIGHT_FG_COLOR_BEG = 90, | |
| 1703 | + CSI_m_BRIGHT_FG_COLOR_END = 97, | |
| 1704 | + CSI_m_BRIGHT_FG_COLOR_OFF = CSI_m_BRIGHT_FG_COLOR_BEG - CSI_m_FG_COLOR_BEG, | |
| 1705 | + CSI_m_BRIGHT_BG_COLOR_BEG = 100, | |
| 1706 | + CSI_m_BRIGHT_BG_COLOR_END = 107, | |
| 1707 | + CSI_m_BRIGHT_BG_COLOR_OFF = CSI_m_BRIGHT_BG_COLOR_BEG - CSI_m_BG_COLOR_BEG, | |
| 1708 | +}; | |
| 1709 | + | |
| 1684 | 1710 | /* console_lock is held */ |
| 1685 | 1711 | static void csi_m(struct vc_data *vc) |
| 1686 | 1712 | { |
| @@ -1688,33 +1714,33 @@ static void csi_m(struct vc_data *vc) · 1 unmodified line | ||
| 1688 | 1714 | |
| 1689 | 1715 | for (i = 0; i <= vc->vc_npar; i++) |
| 1690 | 1716 | switch (vc->vc_par[i]) { |
| 1691 | − case 0: /* all attributes off */ | |
| 1717 | + case CSI_m_DEFAULT: /* all attributes off */ | |
| 1692 | 1718 | default_attr(vc); |
| 1693 | 1719 | break; |
| 1694 | − case 1: | |
| 1720 | + case CSI_m_BOLD: | |
| 1695 | 1721 | vc->state.intensity = VCI_BOLD; |
| 1696 | 1722 | break; |
| 1697 | − case 2: | |
| 1723 | + case CSI_m_HALF_BRIGHT: | |
| 1698 | 1724 | vc->state.intensity = VCI_HALF_BRIGHT; |
| 1699 | 1725 | break; |
| 1700 | − case 3: | |
| 1726 | + case CSI_m_ITALIC: | |
| 1701 | 1727 | vc->state.italic = true; |
| 1702 | 1728 | break; |
| 1703 | − case 21: | |
| 1729 | + case CSI_m_DOUBLE_UNDERLINE: | |
| 1704 | 1730 | /* |
| 1705 | 1731 | * No console drivers support double underline, so |
| 1706 | 1732 | * convert it to a single underline. |
| 1707 | 1733 | */ |
| 1708 | − case 4: | |
| 1734 | + case CSI_m_UNDERLINE: | |
| 1709 | 1735 | vc->state.underline = true; |
| 1710 | 1736 | break; |
| 1711 | − case 5: | |
| 1737 | + case CSI_m_BLINK: | |
| 1712 | 1738 | vc->state.blink = true; |
| 1713 | 1739 | break; |
| 1714 | − case 7: | |
| 1740 | + case CSI_m_REVERSE: | |
| 1715 | 1741 | vc->state.reverse = true; |
| 1716 | 1742 | break; |
| 1717 | − case 10: /* ANSI X3.64-1979 (SCO-ish?) | |
| 1743 | + case CSI_m_PRI_FONT: /* ANSI X3.64-1979 (SCO-ish?) | |
| 1718 | 1744 | * Select primary font, don't display control chars if |
| 1719 | 1745 | * defined, don't set bit 8 on output. |
| 1720 | 1746 | */ |
| @@ -1722,7 +1748,7 @@ static void csi_m(struct vc_data *vc) · 1 unmodified line | ||
| 1722 | 1748 | vc->vc_disp_ctrl = 0; |
| 1723 | 1749 | vc->vc_toggle_meta = 0; |
| 1724 | 1750 | break; |
| 1725 | − case 11: /* ANSI X3.64-1979 (SCO-ish?) | |
| 1751 | + case CSI_m_ALT_FONT1: /* ANSI X3.64-1979 (SCO-ish?) | |
| 1726 | 1752 | * Select first alternate font, lets chars < 32 be |
| 1727 | 1753 | * displayed as ROM chars. |
| 1728 | 1754 | */ |
| @@ -1730,7 +1756,7 @@ static void csi_m(struct vc_data *vc) · 1 unmodified line | ||
| 1730 | 1756 | vc->vc_disp_ctrl = 1; |
| 1731 | 1757 | vc->vc_toggle_meta = 0; |
| 1732 | 1758 | break; |
| 1733 | − case 12: /* ANSI X3.64-1979 (SCO-ish?) | |
| 1759 | + case CSI_m_ALT_FONT2: /* ANSI X3.64-1979 (SCO-ish?) | |
| 1734 | 1760 | * Select second alternate font, toggle high bit |
| 1735 | 1761 | * before displaying as ROM char. |
| 1736 | 1762 | */ |
| @@ -1738,47 +1764,51 @@ static void csi_m(struct vc_data *vc) · 1 unmodified line | ||
| 1738 | 1764 | vc->vc_disp_ctrl = 1; |
| 1739 | 1765 | vc->vc_toggle_meta = 1; |
| 1740 | 1766 | break; |
| 1741 | − case 22: | |
| 1767 | + case CSI_m_NORMAL_INTENSITY: | |
| 1742 | 1768 | vc->state.intensity = VCI_NORMAL; |
| 1743 | 1769 | break; |
| 1744 | − case 23: | |
| 1770 | + case CSI_m_NO_ITALIC: | |
| 1745 | 1771 | vc->state.italic = false; |
| 1746 | 1772 | break; |
| 1747 | − case 24: | |
| 1773 | + case CSI_m_NO_UNDERLINE: | |
| 1748 | 1774 | vc->state.underline = false; |
| 1749 | 1775 | break; |
| 1750 | − case 25: | |
| 1776 | + case CSI_m_NO_BLINK: | |
| 1751 | 1777 | vc->state.blink = false; |
| 1752 | 1778 | break; |
| 1753 | − case 27: | |
| 1779 | + case CSI_m_NO_REVERSE: | |
| 1754 | 1780 | vc->state.reverse = false; |
| 1755 | 1781 | break; |
| 1756 | − case 38: | |
| 1782 | + case CSI_m_FG_COLOR: | |
| 1757 | 1783 | i = vc_t416_color(vc, i, rgb_foreground); |
| 1758 | 1784 | break; |
| 1759 | − case 48: | |
| 1785 | + case CSI_m_BG_COLOR: | |
| 1760 | 1786 | i = vc_t416_color(vc, i, rgb_background); |
| 1761 | 1787 | break; |
| 1762 | − case 39: | |
| 1788 | + case CSI_m_DEFAULT_FG_COLOR: | |
| 1763 | 1789 | vc->state.color = (vc->vc_def_color & 0x0f) | |
| 1764 | 1790 | (vc->state.color & 0xf0); |
| 1765 | 1791 | break; |
| 1766 | − case 49: | |
| 1792 | + case CSI_m_DEFAULT_BG_COLOR: | |
| 1767 | 1793 | vc->state.color = (vc->vc_def_color & 0xf0) | |
| 1768 | 1794 | (vc->state.color & 0x0f); |
| 1769 | 1795 | break; |
| 1770 | − default: | |
| 1771 | − if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) { | |
| 1772 | − if (vc->vc_par[i] < 100) | |
| 1773 | − vc->state.intensity = VCI_BOLD; | |
| 1774 | − vc->vc_par[i] -= 60; | |
| 1775 | − } | |
| 1776 | − if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37) | |
| 1777 | − vc->state.color = color_table[vc->vc_par[i] - 30] | |
| 1778 | − | (vc->state.color & 0xf0); | |
| 1779 | − else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47) | |
| 1780 | − vc->state.color = (color_table[vc->vc_par[i] - 40] << 4) | |
| 1781 | − | (vc->state.color & 0x0f); | |
| 1796 | + case CSI_m_BRIGHT_FG_COLOR_BEG ... CSI_m_BRIGHT_FG_COLOR_END: | |
| 1797 | + vc->state.intensity = VCI_BOLD; | |
| 1798 | + vc->vc_par[i] -= CSI_m_BRIGHT_FG_COLOR_OFF; | |
| 1799 | + fallthrough; | |
| 1800 | + case CSI_m_FG_COLOR_BEG ... CSI_m_FG_COLOR_END: | |
| 1801 | + vc->vc_par[i] -= CSI_m_FG_COLOR_BEG; | |
| 1802 | + vc->state.color = color_table[vc->vc_par[i]] | | |
| 1803 | + (vc->state.color & 0xf0); | |
| 1804 | + break; | |
| 1805 | + case CSI_m_BRIGHT_BG_COLOR_BEG ... CSI_m_BRIGHT_BG_COLOR_END: | |
| 1806 | + vc->vc_par[i] -= CSI_m_BRIGHT_BG_COLOR_OFF; | |
| 1807 | + fallthrough; | |
| 1808 | + case CSI_m_BG_COLOR_BEG ... CSI_m_BG_COLOR_END: | |
| 1809 | + vc->vc_par[i] -= CSI_m_BG_COLOR_BEG; | |
| 1810 | + vc->state.color = (color_table[vc->vc_par[i]] << 4) | | |
| 1811 | + (vc->state.color & 0x0f); | |
| 1782 | 1812 | break; |
| 1783 | 1813 | } |
| 1784 | 1814 | update_attr(vc); |
| @@ -1832,133 +1862,175 @@ int mouse_reporting(void) · 47 unmodified lines | ||
| 1832 | 1862 | return vc_cons[fg_console].d->vc_report_mouse; |
| 1833 | 1863 | } |
| 1834 | 1864 | |
| 1865 | +enum { | |
| 1866 | + CSI_DEC_hl_CURSOR_KEYS = 1, /* CKM: cursor keys send ^[Ox/^[[x */ | |
| 1867 | + CSI_DEC_hl_132_COLUMNS = 3, /* COLM: 80/132 mode switch */ | |
| 1868 | + CSI_DEC_hl_REVERSE_VIDEO = 5, /* SCNM */ | |
| 1869 | + CSI_DEC_hl_ORIGIN_MODE = 6, /* OM: origin relative/absolute */ | |
| 1870 | + CSI_DEC_hl_AUTOWRAP = 7, /* AWM */ | |
| 1871 | + CSI_DEC_hl_AUTOREPEAT = 8, /* ARM */ | |
| 1872 | + CSI_DEC_hl_MOUSE_X10 = 9, | |
| 1873 | + CSI_DEC_hl_SHOW_CURSOR = 25, /* TCEM */ | |
| 1874 | + CSI_DEC_hl_MOUSE_VT200 = 1000, | |
| 1875 | +}; | |
| 1876 | + | |
| 1835 | 1877 | /* console_lock is held */ |
| 1836 | −static void set_mode(struct vc_data *vc, int on_off) | |
| 1878 | +static void csi_DEC_hl(struct vc_data *vc, bool on_off) | |
| 1837 | 1879 | { |
| 1838 | − int i; | |
| 1880 | + unsigned int i; | |
| 1839 | 1881 | |
| 1840 | 1882 | for (i = 0; i <= vc->vc_npar; i++) |
| 1841 | − if (vc->vc_priv == EPdec) { | |
| 1842 | − switch(vc->vc_par[i]) { /* DEC private modes set/reset */ | |
| 1843 | − case 1: /* Cursor keys send ^[Ox/^[[x */ | |
| 1844 | − if (on_off) | |
| 1845 | − set_kbd(vc, decckm); | |
| 1846 | − else | |
| 1847 | − clr_kbd(vc, decckm); | |
| 1848 | − break; | |
| 1849 | − case 3: /* 80/132 mode switch unimplemented */ | |
| 1883 | + switch (vc->vc_par[i]) { | |
| 1884 | + case CSI_DEC_hl_CURSOR_KEYS: | |
| 1885 | + if (on_off) | |
| 1886 | + set_kbd(vc, decckm); | |
| 1887 | + else | |
| 1888 | + clr_kbd(vc, decckm); | |
| 1889 | + break; | |
| 1890 | + case CSI_DEC_hl_132_COLUMNS: /* unimplemented */ | |
| 1850 | 1891 | #if 0 |
| 1851 | − vc_resize(deccolm ? 132 : 80, vc->vc_rows); | |
| 1852 | − /* this alone does not suffice; some user mode | |
| 1853 | − utility has to change the hardware regs */ | |
| 1892 | + vc_resize(deccolm ? 132 : 80, vc->vc_rows); | |
| 1893 | + /* this alone does not suffice; some user mode | |
| 1894 | + utility has to change the hardware regs */ | |
| 1854 | 1895 | #endif |
| 1855 | − break; | |
| 1856 | − case 5: /* Inverted screen on/off */ | |
| 1857 | − if (vc->vc_decscnm != on_off) { | |
| 1858 | − vc->vc_decscnm = on_off; | |
| 1859 | − invert_screen(vc, 0, | |
| 1860 | − vc->vc_screenbuf_size, | |
| 1861 | − false); | |
| 1862 | − update_attr(vc); | |
| 1863 | − } | |
| 1864 | − break; | |
| 1865 | − case 6: /* Origin relative/absolute */ | |
| 1866 | − vc->vc_decom = on_off; | |
| 1867 | − gotoxay(vc, 0, 0); | |
| 1868 | − break; | |
| 1869 | − case 7: /* Autowrap on/off */ | |
| 1870 | − vc->vc_decawm = on_off; | |
| 1871 | − break; | |
| 1872 | − case 8: /* Autorepeat on/off */ | |
| 1873 | − if (on_off) | |
| 1874 | − set_kbd(vc, decarm); | |
| 1875 | − else | |
| 1876 | − clr_kbd(vc, decarm); | |
| 1877 | − break; | |
| 1878 | − case 9: | |
| 1879 | − vc->vc_report_mouse = on_off ? 1 : 0; | |
| 1880 | − break; | |
| 1881 | − case 25: /* Cursor on/off */ | |
| 1882 | − vc->vc_deccm = on_off; | |
| 1883 | − break; | |
| 1884 | − case 1000: | |
| 1885 | − vc->vc_report_mouse = on_off ? 2 : 0; | |
| 1886 | − break; | |
| 1887 | − } | |
| 1888 | − } else { | |
| 1889 | − switch(vc->vc_par[i]) { /* ANSI modes set/reset */ | |
| 1890 | − case 3: /* Monitor (display ctrls) */ | |
| 1891 | − vc->vc_disp_ctrl = on_off; | |
| 1892 | − break; | |
| 1893 | − case 4: /* Insert Mode on/off */ | |
| 1894 | − vc->vc_decim = on_off; | |
| 1895 | − break; | |
| 1896 | − case 20: /* Lf, Enter == CrLf/Lf */ | |
| 1897 | − if (on_off) | |
| 1898 | − set_kbd(vc, lnm); | |
| 1899 | − else | |
| 1900 | − clr_kbd(vc, lnm); | |
| 1901 | − break; | |
| 1896 | + break; | |
| 1897 | + case CSI_DEC_hl_REVERSE_VIDEO: | |
| 1898 | + if (vc->vc_decscnm != on_off) { | |
| 1899 | + vc->vc_decscnm = on_off; | |
| 1900 | + invert_screen(vc, 0, vc->vc_screenbuf_size, | |
| 1901 | + false); | |
| 1902 | + update_attr(vc); | |
| 1902 | 1903 | } |
| 1904 | + break; | |
| 1905 | + case CSI_DEC_hl_ORIGIN_MODE: | |
| 1906 | + vc->vc_decom = on_off; | |
| 1907 | + gotoxay(vc, 0, 0); | |
| 1908 | + break; | |
| 1909 | + case CSI_DEC_hl_AUTOWRAP: | |
| 1910 | + vc->vc_decawm = on_off; | |
| 1911 | + break; | |
| 1912 | + case CSI_DEC_hl_AUTOREPEAT: | |
| 1913 | + if (on_off) | |
| 1914 | + set_kbd(vc, decarm); | |
| 1915 | + else | |
| 1916 | + clr_kbd(vc, decarm); | |
| 1917 | + break; | |
| 1918 | + case CSI_DEC_hl_MOUSE_X10: | |
| 1919 | + vc->vc_report_mouse = on_off ? 1 : 0; | |
| 1920 | + break; | |
| 1921 | + case CSI_DEC_hl_SHOW_CURSOR: | |
| 1922 | + vc->vc_deccm = on_off; | |
| 1923 | + break; | |
| 1924 | + case CSI_DEC_hl_MOUSE_VT200: | |
| 1925 | + vc->vc_report_mouse = on_off ? 2 : 0; | |
| 1926 | + break; | |
| 1903 | 1927 | } |
| 1904 | 1928 | } |
| 1905 | 1929 | |
| 1930 | +enum { | |
| 1931 | + CSI_hl_DISPLAY_CTRL = 3, /* handle ansi control chars */ | |
| 1932 | + CSI_hl_INSERT = 4, /* IRM: insert/replace */ | |
| 1933 | + CSI_hl_AUTO_NL = 20, /* LNM: Enter == CrLf/Lf */ | |
| 1934 | +}; | |
| 1935 | + | |
| 1906 | 1936 | /* console_lock is held */ |
| 1907 | −static void setterm_command(struct vc_data *vc) | |
| 1937 | +static void csi_hl(struct vc_data *vc, bool on_off) | |
| 1938 | +{ | |
| 1939 | + unsigned int i; | |
| 1940 | + | |
| 1941 | + for (i = 0; i <= vc->vc_npar; i++) | |
| 1942 | + switch (vc->vc_par[i]) { /* ANSI modes set/reset */ | |
| 1943 | + case CSI_hl_DISPLAY_CTRL: | |
| 1944 | + vc->vc_disp_ctrl = on_off; | |
| 1945 | + break; | |
| 1946 | + case CSI_hl_INSERT: | |
| 1947 | + vc->vc_decim = on_off; | |
| 1948 | + break; | |
| 1949 | + case CSI_hl_AUTO_NL: | |
| 1950 | + if (on_off) | |
| 1951 | + set_kbd(vc, lnm); | |
| 1952 | + else | |
| 1953 | + clr_kbd(vc, lnm); | |
| 1954 | + break; | |
| 1955 | + } | |
| 1956 | +} | |
| 1957 | + | |
| 1958 | +enum CSI_right_square_bracket { | |
| 1959 | + CSI_RSB_COLOR_FOR_UNDERLINE = 1, | |
| 1960 | + CSI_RSB_COLOR_FOR_HALF_BRIGHT = 2, | |
| 1961 | + CSI_RSB_MAKE_CUR_COLOR_DEFAULT = 8, | |
| 1962 | + CSI_RSB_BLANKING_INTERVAL = 9, | |
| 1963 | + CSI_RSB_BELL_FREQUENCY = 10, | |
| 1964 | + CSI_RSB_BELL_DURATION = 11, | |
| 1965 | + CSI_RSB_BRING_CONSOLE_TO_FRONT = 12, | |
| 1966 | + CSI_RSB_UNBLANK = 13, | |
| 1967 | + CSI_RSB_VESA_OFF_INTERVAL = 14, | |
| 1968 | + CSI_RSB_BRING_PREV_CONSOLE_TO_FRONT = 15, | |
| 1969 | + CSI_RSB_CURSOR_BLINK_INTERVAL = 16, | |
| 1970 | +}; | |
| 1971 | + | |
| 1972 | +/* | |
| 1973 | + * csi_RSB - csi+] (Right Square Bracket) handler | |
| 1974 | + * | |
| 1975 | + * These are linux console private sequences. | |
| 1976 | + * | |
| 1977 | + * console_lock is held | |
| 1978 | + */ | |
| 1979 | +static void csi_RSB(struct vc_data *vc) | |
| 1908 | 1980 | { |
| 1909 | 1981 | switch (vc->vc_par[0]) { |
| 1910 | − case 1: /* set color for underline mode */ | |
| 1982 | + case CSI_RSB_COLOR_FOR_UNDERLINE: | |
| 1911 | 1983 | if (vc->vc_can_do_color && vc->vc_par[1] < 16) { |
| 1912 | 1984 | vc->vc_ulcolor = color_table[vc->vc_par[1]]; |
| 1913 | 1985 | if (vc->state.underline) |
| 1914 | 1986 | update_attr(vc); |
| 1915 | 1987 | } |
| 1916 | 1988 | break; |
| 1917 | − case 2: /* set color for half intensity mode */ | |
| 1989 | + case CSI_RSB_COLOR_FOR_HALF_BRIGHT: | |
| 1918 | 1990 | if (vc->vc_can_do_color && vc->vc_par[1] < 16) { |
| 1919 | 1991 | vc->vc_halfcolor = color_table[vc->vc_par[1]]; |
| 1920 | 1992 | if (vc->state.intensity == VCI_HALF_BRIGHT) |
| 1921 | 1993 | update_attr(vc); |
| 1922 | 1994 | } |
| 1923 | 1995 | break; |
| 1924 | − case 8: /* store colors as defaults */ | |
| 1996 | + case CSI_RSB_MAKE_CUR_COLOR_DEFAULT: | |
| 1925 | 1997 | vc->vc_def_color = vc->vc_attr; |
| 1926 | 1998 | if (vc->vc_hi_font_mask == 0x100) |
| 1927 | 1999 | vc->vc_def_color >>= 1; |
| 1928 | 2000 | default_attr(vc); |
| 1929 | 2001 | update_attr(vc); |
| 1930 | 2002 | break; |
| 1931 | − case 9: /* set blanking interval */ | |
| 2003 | + case CSI_RSB_BLANKING_INTERVAL: | |
| 1932 | 2004 | blankinterval = min(vc->vc_par[1], 60U) * 60; |
| 1933 | 2005 | poke_blanked_console(); |
| 1934 | 2006 | break; |
| 1935 | − case 10: /* set bell frequency in Hz */ | |
| 2007 | + case CSI_RSB_BELL_FREQUENCY: | |
| 1936 | 2008 | if (vc->vc_npar >= 1) |
| 1937 | 2009 | vc->vc_bell_pitch = vc->vc_par[1]; |
| 1938 | 2010 | else |
| 1939 | 2011 | vc->vc_bell_pitch = DEFAULT_BELL_PITCH; |
| 1940 | 2012 | break; |
| 1941 | − case 11: /* set bell duration in msec */ | |
| 2013 | + case CSI_RSB_BELL_DURATION: | |
| 1942 | 2014 | if (vc->vc_npar >= 1) |
| 1943 | 2015 | vc->vc_bell_duration = (vc->vc_par[1] < 2000) ? |
| 1944 | 2016 | msecs_to_jiffies(vc->vc_par[1]) : 0; |
| 1945 | 2017 | else |
| 1946 | 2018 | vc->vc_bell_duration = DEFAULT_BELL_DURATION; |
| 1947 | 2019 | break; |
| 1948 | − case 12: /* bring specified console to the front */ | |
| 2020 | + case CSI_RSB_BRING_CONSOLE_TO_FRONT: | |
| 1949 | 2021 | if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1)) |
| 1950 | 2022 | set_console(vc->vc_par[1] - 1); |
| 1951 | 2023 | break; |
| 1952 | − case 13: /* unblank the screen */ | |
| 2024 | + case CSI_RSB_UNBLANK: | |
| 1953 | 2025 | poke_blanked_console(); |
| 1954 | 2026 | break; |
| 1955 | − case 14: /* set vesa powerdown interval */ | |
| 2027 | + case CSI_RSB_VESA_OFF_INTERVAL: | |
| 1956 | 2028 | vesa_off_interval = min(vc->vc_par[1], 60U) * 60 * HZ; |
| 1957 | 2029 | break; |
| 1958 | − case 15: /* activate the previous console */ | |
| 2030 | + case CSI_RSB_BRING_PREV_CONSOLE_TO_FRONT: | |
| 1959 | 2031 | set_console(last_console); |
| 1960 | 2032 | break; |
| 1961 | − case 16: /* set cursor blink duration in msec */ | |
| 2033 | + case CSI_RSB_CURSOR_BLINK_INTERVAL: | |
| 1962 | 2034 | if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 && |
| 1963 | 2035 | vc->vc_par[1] <= USHRT_MAX) |
| 1964 | 2036 | vc->vc_cur_blink_ms = vc->vc_par[1]; |
| @@ -1971,41 +2043,32 @@ static void setterm_command(struct vc_data *vc) · 6 unmodified lines | ||
| 1971 | 2043 | /* console_lock is held */ |
| 1972 | 2044 | static void csi_at(struct vc_data *vc, unsigned int nr) |
| 1973 | 2045 | { |
| 1974 | − if (nr > vc->vc_cols - vc->state.x) | |
| 1975 | − nr = vc->vc_cols - vc->state.x; | |
| 1976 | − else if (!nr) | |
| 1977 | − nr = 1; | |
| 2046 | + nr = clamp(nr, 1, vc->vc_cols - vc->state.x); | |
| 1978 | 2047 | insert_char(vc, nr); |
| 1979 | 2048 | } |
| 1980 | 2049 | |
| 1981 | 2050 | /* console_lock is held */ |
| 1982 | −static void csi_L(struct vc_data *vc, unsigned int nr) | |
| 2051 | +static void csi_L(struct vc_data *vc) | |
| 1983 | 2052 | { |
| 1984 | − if (nr > vc->vc_rows - vc->state.y) | |
| 1985 | − nr = vc->vc_rows - vc->state.y; | |
| 1986 | − else if (!nr) | |
| 1987 | − nr = 1; | |
| 2053 | + unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_rows - vc->state.y); | |
| 2054 | + | |
| 1988 | 2055 | con_scroll(vc, vc->state.y, vc->vc_bottom, SM_DOWN, nr); |
| 1989 | 2056 | vc->vc_need_wrap = 0; |
| 1990 | 2057 | } |
| 1991 | 2058 | |
| 1992 | 2059 | /* console_lock is held */ |
| 1993 | −static void csi_P(struct vc_data *vc, unsigned int nr) | |
| 2060 | +static void csi_P(struct vc_data *vc) | |
| 1994 | 2061 | { |
| 1995 | − if (nr > vc->vc_cols - vc->state.x) | |
| 1996 | − nr = vc->vc_cols - vc->state.x; | |
| 1997 | − else if (!nr) | |
| 1998 | − nr = 1; | |
| 2062 | + unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_cols - vc->state.x); | |
| 2063 | + | |
| 1999 | 2064 | delete_char(vc, nr); |
| 2000 | 2065 | } |
| 2001 | 2066 | |
| 2002 | 2067 | /* console_lock is held */ |
| 2003 | −static void csi_M(struct vc_data *vc, unsigned int nr) | |
| 2068 | +static void csi_M(struct vc_data *vc) | |
| 2004 | 2069 | { |
| 2005 | − if (nr > vc->vc_rows - vc->state.y) | |
| 2006 | − nr = vc->vc_rows - vc->state.y; | |
| 2007 | − else if (!nr) | |
| 2008 | − nr=1; | |
| 2070 | + unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_rows - vc->state.y); | |
| 2071 | + | |
| 2009 | 2072 | con_scroll(vc, vc->state.y, vc->vc_bottom, SM_UP, nr); |
| 2010 | 2073 | vc->vc_need_wrap = 0; |
| 2011 | 2074 | } |
| @@ -2028,9 +2091,48 @@ static void restore_cur(struct vc_data *vc) · 16 unmodified lines | ||
| 2028 | 2091 | vc->vc_need_wrap = 0; |
| 2029 | 2092 | } |
| 2030 | 2093 | |
| 2031 | −enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, | |
| 2032 | − EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd, | |
| 2033 | − ESpalette, ESosc, ESapc, ESpm, ESdcs }; | |
| 2094 | +/** | |
| 2095 | + * enum vc_ctl_state - control characters state of a vt | |
| 2096 | + * | |
| 2097 | + * @ESnormal: initial state, no control characters parsed | |
| 2098 | + * @ESesc: ESC parsed | |
| 2099 | + * @ESsquare: CSI parsed -- modifiers/parameters/ctrl chars expected | |
| 2100 | + * @ESgetpars: CSI parsed -- parameters/ctrl chars expected | |
| 2101 | + * @ESfunckey: CSI [ parsed | |
| 2102 | + * @EShash: ESC # parsed | |
| 2103 | + * @ESsetG0: ESC ( parsed | |
| 2104 | + * @ESsetG1: ESC ) parsed | |
| 2105 | + * @ESpercent: ESC % parsed | |
| 2106 | + * @EScsiignore: CSI [0x20-0x3f] parsed | |
| 2107 | + * @ESnonstd: OSC parsed | |
| 2108 | + * @ESpalette: OSC P parsed | |
| 2109 | + * @ESosc: OSC [0-9] parsed | |
| 2110 | + * @ESANSI_first: first state for ignoring ansi control sequences | |
| 2111 | + * @ESapc: ESC _ parsed | |
| 2112 | + * @ESpm: ESC ^ parsed | |
| 2113 | + * @ESdcs: ESC P parsed | |
| 2114 | + * @ESANSI_last: last state for ignoring ansi control sequences | |
| 2115 | + */ | |
| 2116 | +enum vc_ctl_state { | |
| 2117 | + ESnormal, | |
| 2118 | + ESesc, | |
| 2119 | + ESsquare, | |
| 2120 | + ESgetpars, | |
| 2121 | + ESfunckey, | |
| 2122 | + EShash, | |
| 2123 | + ESsetG0, | |
| 2124 | + ESsetG1, | |
| 2125 | + ESpercent, | |
| 2126 | + EScsiignore, | |
| 2127 | + ESnonstd, | |
| 2128 | + ESpalette, | |
| 2129 | + ESosc, | |
| 2130 | + ESANSI_first = ESosc, | |
| 2131 | + ESapc, | |
| 2132 | + ESpm, | |
| 2133 | + ESdcs, | |
| 2134 | + ESANSI_last = ESdcs, | |
| 2135 | +}; | |
| 2034 | 2136 | |
| 2035 | 2137 | /* console_lock is held (except via vc_init()) */ |
| 2036 | 2138 | 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) · 41 unmodified lines | ||
| 2078 | 2180 | gotoxy(vc, 0, 0); |
| 2079 | 2181 | save_cur(vc); |
| 2080 | 2182 | if (do_clear) |
| 2081 | − csi_J(vc, 2); | |
| 2183 | + csi_J(vc, CSI_J_VISIBLE); | |
| 2082 | 2184 | } |
| 2083 | 2185 | |
| 2084 | −static void vc_setGx(struct vc_data *vc, unsigned int which, int c) | |
| 2186 | +static void vc_setGx(struct vc_data *vc, unsigned int which, u8 c) | |
| 2085 | 2187 | { |
| 2086 | 2188 | unsigned char *charset = &vc->state.Gx_charset[which]; |
| 2087 | 2189 | |
| @@ -2104,36 +2206,54 @@ static void vc_setGx(struct vc_data *vc, unsigned int which, int c) · 16 unmodified lines | ||
| 2104 | 2206 | vc->vc_translate = set_translate(*charset, vc); |
| 2105 | 2207 | } |
| 2106 | 2208 | |
| 2107 | −/* is this state an ANSI control string? */ | |
| 2108 | −static bool ansi_control_string(unsigned int state) | |
| 2209 | +static bool ansi_control_string(enum vc_ctl_state state) | |
| 2109 | 2210 | { |
| 2110 | − if (state == ESosc || state == ESapc || state == ESpm || state == ESdcs) | |
| 2111 | − return true; | |
| 2112 | − return false; | |
| 2211 | + return state >= ESANSI_first && state <= ESANSI_last; | |
| 2113 | 2212 | } |
| 2114 | 2213 | |
| 2115 | −/* console_lock is held */ | |
| 2116 | −static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | |
| 2214 | +enum { | |
| 2215 | + ASCII_NULL = 0, | |
| 2216 | + ASCII_BELL = 7, | |
| 2217 | + ASCII_BACKSPACE = 8, | |
| 2218 | + ASCII_IGNORE_FIRST = ASCII_BACKSPACE, | |
| 2219 | + ASCII_HTAB = 9, | |
| 2220 | + ASCII_LINEFEED = 10, | |
| 2221 | + ASCII_VTAB = 11, | |
| 2222 | + ASCII_FORMFEED = 12, | |
| 2223 | + ASCII_CAR_RET = 13, | |
| 2224 | + ASCII_IGNORE_LAST = ASCII_CAR_RET, | |
| 2225 | + ASCII_SHIFTOUT = 14, | |
| 2226 | + ASCII_SHIFTIN = 15, | |
| 2227 | + ASCII_CANCEL = 24, | |
| 2228 | + ASCII_SUBSTITUTE = 26, | |
| 2229 | + ASCII_ESCAPE = 27, | |
| 2230 | + ASCII_CSI_IGNORE_FIRST = ' ', /* 0x2x, 0x3a and 0x3c - 0x3f */ | |
| 2231 | + ASCII_CSI_IGNORE_LAST = '?', | |
| 2232 | + ASCII_DEL = 127, | |
| 2233 | + ASCII_EXT_CSI = 128 + ASCII_ESCAPE, | |
| 2234 | +}; | |
| 2235 | + | |
| 2236 | +/* | |
| 2237 | + * Handle ascii characters in control sequences and change states accordingly. | |
| 2238 | + * E.g. ESC sets the state of vc to ESesc. | |
| 2239 | + * | |
| 2240 | + * Returns: true if @c handled. | |
| 2241 | + */ | |
| 2242 | +static bool handle_ascii(struct tty_struct *tty, struct vc_data *vc, u8 c) | |
| 2117 | 2243 | { |
| 2118 | − /* | |
| 2119 | − * Control characters can be used in the _middle_ | |
| 2120 | − * of an escape sequence, aside from ANSI control strings. | |
| 2121 | − */ | |
| 2122 | − if (ansi_control_string(vc->vc_state) && c >= 8 && c <= 13) | |
| 2123 | − return; | |
| 2124 | 2244 | switch (c) { |
| 2125 | − case 0: | |
| 2126 | − return; | |
| 2127 | − case 7: | |
| 2245 | + case ASCII_NULL: | |
| 2246 | + return true; | |
| 2247 | + case ASCII_BELL: | |
| 2128 | 2248 | if (ansi_control_string(vc->vc_state)) |
| 2129 | 2249 | vc->vc_state = ESnormal; |
| 2130 | 2250 | else if (vc->vc_bell_duration) |
| 2131 | 2251 | kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration); |
| 2132 | − return; | |
| 2133 | − case 8: | |
| 2252 | + return true; | |
| 2253 | + case ASCII_BACKSPACE: | |
| 2134 | 2254 | bs(vc); |
| 2135 | − return; | |
| 2136 | − case 9: | |
| 2255 | + return true; | |
| 2256 | + case ASCII_HTAB: | |
| 2137 | 2257 | vc->vc_pos -= (vc->state.x << 1); |
| 2138 | 2258 | |
| 2139 | 2259 | 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) · 4 unmodified lines | ||
| 2144 | 2264 | |
| 2145 | 2265 | vc->vc_pos += (vc->state.x << 1); |
| 2146 | 2266 | notify_write(vc, '\t'); |
| 2147 | − return; | |
| 2148 | − case 10: case 11: case 12: | |
| 2267 | + return true; | |
| 2268 | + case ASCII_LINEFEED: | |
| 2269 | + case ASCII_VTAB: | |
| 2270 | + case ASCII_FORMFEED: | |
| 2149 | 2271 | lf(vc); |
| 2150 | 2272 | if (!is_kbd(vc, lnm)) |
| 2151 | − return; | |
| 2273 | + return true; | |
| 2152 | 2274 | fallthrough; |
| 2153 | − case 13: | |
| 2275 | + case ASCII_CAR_RET: | |
| 2154 | 2276 | cr(vc); |
| 2155 | − return; | |
| 2156 | − case 14: | |
| 2277 | + return true; | |
| 2278 | + case ASCII_SHIFTOUT: | |
| 2157 | 2279 | vc->state.charset = 1; |
| 2158 | 2280 | vc->vc_translate = set_translate(vc->state.Gx_charset[1], vc); |
| 2159 | 2281 | vc->vc_disp_ctrl = 1; |
| 2160 | − return; | |
| 2161 | − case 15: | |
| 2282 | + return true; | |
| 2283 | + case ASCII_SHIFTIN: | |
| 2162 | 2284 | vc->state.charset = 0; |
| 2163 | 2285 | vc->vc_translate = set_translate(vc->state.Gx_charset[0], vc); |
| 2164 | 2286 | vc->vc_disp_ctrl = 0; |
| 2165 | − return; | |
| 2166 | − case 24: case 26: | |
| 2287 | + return true; | |
| 2288 | + case ASCII_CANCEL: | |
| 2289 | + case ASCII_SUBSTITUTE: | |
| 2167 | 2290 | vc->vc_state = ESnormal; |
| 2168 | − return; | |
| 2169 | − case 27: | |
| 2291 | + return true; | |
| 2292 | + case ASCII_ESCAPE: | |
| 2170 | 2293 | vc->vc_state = ESesc; |
| 2171 | − return; | |
| 2172 | − case 127: | |
| 2294 | + return true; | |
| 2295 | + case ASCII_DEL: | |
| 2173 | 2296 | del(vc); |
| 2174 | − return; | |
| 2175 | − case 128+27: | |
| 2297 | + return true; | |
| 2298 | + case ASCII_EXT_CSI: | |
| 2176 | 2299 | vc->vc_state = ESsquare; |
| 2177 | − return; | |
| 2300 | + return true; | |
| 2178 | 2301 | } |
| 2179 | − switch(vc->vc_state) { | |
| 2180 | − case ESesc: | |
| 2181 | − vc->vc_state = ESnormal; | |
| 2182 | − switch (c) { | |
| 2183 | − case '[': | |
| 2184 | − vc->vc_state = ESsquare; | |
| 2185 | − return; | |
| 2186 | − case ']': | |
| 2187 | − vc->vc_state = ESnonstd; | |
| 2188 | − return; | |
| 2189 | − case '_': | |
| 2190 | − vc->vc_state = ESapc; | |
| 2191 | − return; | |
| 2192 | − case '^': | |
| 2193 | − vc->vc_state = ESpm; | |
| 2194 | − return; | |
| 2195 | − case '%': | |
| 2196 | − vc->vc_state = ESpercent; | |
| 2197 | − return; | |
| 2198 | − case 'E': | |
| 2199 | − cr(vc); | |
| 2200 | − lf(vc); | |
| 2201 | − return; | |
| 2202 | − case 'M': | |
| 2203 | − ri(vc); | |
| 2204 | − return; | |
| 2205 | − case 'D': | |
| 2206 | − lf(vc); | |
| 2207 | − return; | |
| 2208 | − case 'H': | |
| 2209 | − if (vc->state.x < VC_TABSTOPS_COUNT) | |
| 2210 | − set_bit(vc->state.x, vc->vc_tab_stop); | |
| 2211 | − return; | |
| 2212 | − case 'P': | |
| 2213 | − vc->vc_state = ESdcs; | |
| 2214 | − return; | |
| 2215 | − case 'Z': | |
| 2302 | + | |
| 2303 | + return false; | |
| 2304 | +} | |
| 2305 | + | |
| 2306 | +/* | |
| 2307 | + * Handle a character (@c) following an ESC (when @vc is in the ESesc state). | |
| 2308 | + * E.g. previous ESC with @c == '[' here yields the ESsquare state (that is: | |
| 2309 | + * CSI). | |
| 2310 | + */ | |
| 2311 | +static void handle_esc(struct tty_struct *tty, struct vc_data *vc, u8 c) | |
| 2312 | +{ | |
| 2313 | + vc->vc_state = ESnormal; | |
| 2314 | + switch (c) { | |
| 2315 | + case '[': | |
| 2316 | + vc->vc_state = ESsquare; | |
| 2317 | + break; | |
| 2318 | + case ']': | |
| 2319 | + vc->vc_state = ESnonstd; | |
| 2320 | + break; | |
| 2321 | + case '_': | |
| 2322 | + vc->vc_state = ESapc; | |
| 2323 | + break; | |
| 2324 | + case '^': | |
| 2325 | + vc->vc_state = ESpm; | |
| 2326 | + break; | |
| 2327 | + case '%': | |
| 2328 | + vc->vc_state = ESpercent; | |
| 2329 | + break; | |
| 2330 | + case 'E': | |
| 2331 | + cr(vc); | |
| 2332 | + lf(vc); | |
| 2333 | + break; | |
| 2334 | + case 'M': | |
| 2335 | + ri(vc); | |
| 2336 | + break; | |
| 2337 | + case 'D': | |
| 2338 | + lf(vc); | |
| 2339 | + break; | |
| 2340 | + case 'H': | |
| 2341 | + if (vc->state.x < VC_TABSTOPS_COUNT) | |
| 2342 | + set_bit(vc->state.x, vc->vc_tab_stop); | |
| 2343 | + break; | |
| 2344 | + case 'P': | |
| 2345 | + vc->vc_state = ESdcs; | |
| 2346 | + break; | |
| 2347 | + case 'Z': | |
| 2348 | + respond_ID(tty); | |
| 2349 | + break; | |
| 2350 | + case '7': | |
| 2351 | + save_cur(vc); | |
| 2352 | + break; | |
| 2353 | + case '8': | |
| 2354 | + restore_cur(vc); | |
| 2355 | + break; | |
| 2356 | + case '(': | |
| 2357 | + vc->vc_state = ESsetG0; | |
| 2358 | + break; | |
| 2359 | + case ')': | |
| 2360 | + vc->vc_state = ESsetG1; | |
| 2361 | + break; | |
| 2362 | + case '#': | |
| 2363 | + vc->vc_state = EShash; | |
| 2364 | + break; | |
| 2365 | + case 'c': | |
| 2366 | + reset_terminal(vc, 1); | |
| 2367 | + break; | |
| 2368 | + case '>': /* Numeric keypad */ | |
| 2369 | + clr_kbd(vc, kbdapplic); | |
| 2370 | + break; | |
| 2371 | + case '=': /* Appl. keypad */ | |
| 2372 | + set_kbd(vc, kbdapplic); | |
| 2373 | + break; | |
| 2374 | + } | |
| 2375 | +} | |
| 2376 | + | |
| 2377 | +/* | |
| 2378 | + * Handle special DEC control sequences ("ESC [ ? parameters char"). Parameters | |
| 2379 | + * are in @vc->vc_par and the char is in @c here. | |
| 2380 | + */ | |
| 2381 | +static void csi_DEC(struct tty_struct *tty, struct vc_data *vc, u8 c) | |
| 2382 | +{ | |
| 2383 | + switch (c) { | |
| 2384 | + case 'h': | |
| 2385 | + csi_DEC_hl(vc, true); | |
| 2386 | + break; | |
| 2387 | + case 'l': | |
| 2388 | + csi_DEC_hl(vc, false); | |
| 2389 | + break; | |
| 2390 | + case 'c': | |
| 2391 | + if (vc->vc_par[0]) | |
| 2392 | + vc->vc_cursor_type = CUR_MAKE(vc->vc_par[0], | |
| 2393 | + vc->vc_par[1], | |
| 2394 | + vc->vc_par[2]); | |
| 2395 | + else | |
| 2396 | + vc->vc_cursor_type = cur_default; | |
| 2397 | + break; | |
| 2398 | + case 'm': | |
| 2399 | + clear_selection(); | |
| 2400 | + if (vc->vc_par[0]) | |
| 2401 | + vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1]; | |
| 2402 | + else | |
| 2403 | + vc->vc_complement_mask = vc->vc_s_complement_mask; | |
| 2404 | + break; | |
| 2405 | + case 'n': | |
| 2406 | + if (vc->vc_par[0] == 5) | |
| 2407 | + status_report(tty); | |
| 2408 | + else if (vc->vc_par[0] == 6) | |
| 2409 | + cursor_report(vc, tty); | |
| 2410 | + break; | |
| 2411 | + } | |
| 2412 | +} | |
| 2413 | + | |
| 2414 | +/* | |
| 2415 | + * Handle Control Sequence Introducer control characters. That is | |
| 2416 | + * "ESC [ parameters char". Parameters are in @vc->vc_par and the char is in | |
| 2417 | + * @c here. | |
| 2418 | + */ | |
| 2419 | +static void csi_ECMA(struct tty_struct *tty, struct vc_data *vc, u8 c) | |
| 2420 | +{ | |
| 2421 | + switch (c) { | |
| 2422 | + case 'G': | |
| 2423 | + case '`': | |
| 2424 | + if (vc->vc_par[0]) | |
| 2425 | + vc->vc_par[0]--; | |
| 2426 | + gotoxy(vc, vc->vc_par[0], vc->state.y); | |
| 2427 | + break; | |
| 2428 | + case 'A': | |
| 2429 | + if (!vc->vc_par[0]) | |
| 2430 | + vc->vc_par[0]++; | |
| 2431 | + gotoxy(vc, vc->state.x, vc->state.y - vc->vc_par[0]); | |
| 2432 | + break; | |
| 2433 | + case 'B': | |
| 2434 | + case 'e': | |
| 2435 | + if (!vc->vc_par[0]) | |
| 2436 | + vc->vc_par[0]++; | |
| 2437 | + gotoxy(vc, vc->state.x, vc->state.y + vc->vc_par[0]); | |
| 2438 | + break; | |
| 2439 | + case 'C': | |
| 2440 | + case 'a': | |
| 2441 | + if (!vc->vc_par[0]) | |
| 2442 | + vc->vc_par[0]++; | |
| 2443 | + gotoxy(vc, vc->state.x + vc->vc_par[0], vc->state.y); | |
| 2444 | + break; | |
| 2445 | + case 'D': | |
| 2446 | + if (!vc->vc_par[0]) | |
| 2447 | + vc->vc_par[0]++; | |
| 2448 | + gotoxy(vc, vc->state.x - vc->vc_par[0], vc->state.y); | |
| 2449 | + break; | |
| 2450 | + case 'E': | |
| 2451 | + if (!vc->vc_par[0]) | |
| 2452 | + vc->vc_par[0]++; | |
| 2453 | + gotoxy(vc, 0, vc->state.y + vc->vc_par[0]); | |
| 2454 | + break; | |
| 2455 | + case 'F': | |
| 2456 | + if (!vc->vc_par[0]) | |
| 2457 | + vc->vc_par[0]++; | |
| 2458 | + gotoxy(vc, 0, vc->state.y - vc->vc_par[0]); | |
| 2459 | + break; | |
| 2460 | + case 'd': | |
| 2461 | + if (vc->vc_par[0]) | |
| 2462 | + vc->vc_par[0]--; | |
| 2463 | + gotoxay(vc, vc->state.x ,vc->vc_par[0]); | |
| 2464 | + break; | |
| 2465 | + case 'H': | |
| 2466 | + case 'f': | |
| 2467 | + if (vc->vc_par[0]) | |
| 2468 | + vc->vc_par[0]--; | |
| 2469 | + if (vc->vc_par[1]) | |
| 2470 | + vc->vc_par[1]--; | |
| 2471 | + gotoxay(vc, vc->vc_par[1], vc->vc_par[0]); | |
| 2472 | + break; | |
| 2473 | + case 'J': | |
| 2474 | + csi_J(vc, vc->vc_par[0]); | |
| 2475 | + break; | |
| 2476 | + case 'K': | |
| 2477 | + csi_K(vc); | |
| 2478 | + break; | |
| 2479 | + case 'L': | |
| 2480 | + csi_L(vc); | |
| 2481 | + break; | |
| 2482 | + case 'M': | |
| 2483 | + csi_M(vc); | |
| 2484 | + break; | |
| 2485 | + case 'P': | |
| 2486 | + csi_P(vc); | |
| 2487 | + break; | |
| 2488 | + case 'c': | |
| 2489 | + if (!vc->vc_par[0]) | |
| 2216 | 2490 | respond_ID(tty); |
| 2217 | − return; | |
| 2218 | − case '7': | |
| 2219 | − save_cur(vc); | |
| 2220 | − return; | |
| 2221 | − case '8': | |
| 2222 | − restore_cur(vc); | |
| 2223 | − return; | |
| 2224 | − case '(': | |
| 2225 | − vc->vc_state = ESsetG0; | |
| 2226 | − return; | |
| 2227 | − case ')': | |
| 2228 | − vc->vc_state = ESsetG1; | |
| 2229 | − return; | |
| 2230 | − case '#': | |
| 2231 | − vc->vc_state = EShash; | |
| 2232 | − return; | |
| 2233 | − case 'c': | |
| 2234 | − reset_terminal(vc, 1); | |
| 2235 | − return; | |
| 2236 | − case '>': /* Numeric keypad */ | |
| 2237 | − clr_kbd(vc, kbdapplic); | |
| 2238 | − return; | |
| 2239 | − case '=': /* Appl. keypad */ | |
| 2240 | − set_kbd(vc, kbdapplic); | |
| 2241 | − return; | |
| 2491 | + break; | |
| 2492 | + case 'g': | |
| 2493 | + if (!vc->vc_par[0] && vc->state.x < VC_TABSTOPS_COUNT) | |
| 2494 | + set_bit(vc->state.x, vc->vc_tab_stop); | |
| 2495 | + else if (vc->vc_par[0] == 3) | |
| 2496 | + bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT); | |
| 2497 | + break; | |
| 2498 | + case 'h': | |
| 2499 | + csi_hl(vc, true); | |
| 2500 | + break; | |
| 2501 | + case 'l': | |
| 2502 | + csi_hl(vc, false); | |
| 2503 | + break; | |
| 2504 | + case 'm': | |
| 2505 | + csi_m(vc); | |
| 2506 | + break; | |
| 2507 | + case 'n': | |
| 2508 | + if (vc->vc_par[0] == 5) | |
| 2509 | + status_report(tty); | |
| 2510 | + else if (vc->vc_par[0] == 6) | |
| 2511 | + cursor_report(vc, tty); | |
| 2512 | + break; | |
| 2513 | + case 'q': /* DECLL - but only 3 leds */ | |
| 2514 | + /* map 0,1,2,3 to 0,1,2,4 */ | |
| 2515 | + if (vc->vc_par[0] < 4) | |
| 2516 | + vt_set_led_state(vc->vc_num, | |
| 2517 | + (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4); | |
| 2518 | + break; | |
| 2519 | + case 'r': | |
| 2520 | + if (!vc->vc_par[0]) | |
| 2521 | + vc->vc_par[0]++; | |
| 2522 | + if (!vc->vc_par[1]) | |
| 2523 | + vc->vc_par[1] = vc->vc_rows; | |
| 2524 | + /* Minimum allowed region is 2 lines */ | |
| 2525 | + if (vc->vc_par[0] < vc->vc_par[1] && | |
| 2526 | + vc->vc_par[1] <= vc->vc_rows) { | |
| 2527 | + vc->vc_top = vc->vc_par[0] - 1; | |
| 2528 | + vc->vc_bottom = vc->vc_par[1]; | |
| 2529 | + gotoxay(vc, 0, 0); | |
| 2242 | 2530 | } |
| 2531 | + break; | |
| 2532 | + case 's': | |
| 2533 | + save_cur(vc); | |
| 2534 | + break; | |
| 2535 | + case 'u': | |
| 2536 | + restore_cur(vc); | |
| 2537 | + break; | |
| 2538 | + case 'X': | |
| 2539 | + csi_X(vc); | |
| 2540 | + break; | |
| 2541 | + case '@': | |
| 2542 | + csi_at(vc, vc->vc_par[0]); | |
| 2543 | + break; | |
| 2544 | + case ']': | |
| 2545 | + csi_RSB(vc); | |
| 2546 | + break; | |
| 2547 | + } | |
| 2548 | + | |
| 2549 | +} | |
| 2550 | + | |
| 2551 | +static void vc_reset_params(struct vc_data *vc) | |
| 2552 | +{ | |
| 2553 | + memset(vc->vc_par, 0, sizeof(vc->vc_par)); | |
| 2554 | + vc->vc_npar = 0; | |
| 2555 | +} | |
| 2556 | + | |
| 2557 | +/* console_lock is held */ | |
| 2558 | +static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, u8 c) | |
| 2559 | +{ | |
| 2560 | + /* | |
| 2561 | + * Control characters can be used in the _middle_ | |
| 2562 | + * of an escape sequence, aside from ANSI control strings. | |
| 2563 | + */ | |
| 2564 | + if (ansi_control_string(vc->vc_state) && c >= ASCII_IGNORE_FIRST && | |
| 2565 | + c <= ASCII_IGNORE_LAST) | |
| 2566 | + return; | |
| 2567 | + | |
| 2568 | + if (handle_ascii(tty, vc, c)) | |
| 2569 | + return; | |
| 2570 | + | |
| 2571 | + switch(vc->vc_state) { | |
| 2572 | + case ESesc: /* ESC */ | |
| 2573 | + handle_esc(tty, vc, c); | |
| 2243 | 2574 | return; |
| 2244 | − case ESnonstd: | |
| 2245 | − if (c=='P') { /* palette escape sequence */ | |
| 2246 | − for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++) | |
| 2247 | − vc->vc_par[vc->vc_npar] = 0; | |
| 2248 | − vc->vc_npar = 0; | |
| 2575 | + case ESnonstd: /* ESC ] aka OSC */ | |
| 2576 | + switch (c) { | |
| 2577 | + case 'P': /* palette escape sequence */ | |
| 2578 | + vc_reset_params(vc); | |
| 2249 | 2579 | vc->vc_state = ESpalette; |
| 2250 | 2580 | return; |
| 2251 | − } else if (c=='R') { /* reset palette */ | |
| 2581 | + case 'R': /* reset palette */ | |
| 2252 | 2582 | reset_palette(vc); |
| 2253 | − vc->vc_state = ESnormal; | |
| 2254 | − } else if (c>='0' && c<='9') | |
| 2583 | + break; | |
| 2584 | + case '0' ... '9': | |
| 2255 | 2585 | vc->vc_state = ESosc; |
| 2256 | − else | |
| 2257 | − vc->vc_state = ESnormal; | |
| 2586 | + return; | |
| 2587 | + } | |
| 2588 | + vc->vc_state = ESnormal; | |
| 2258 | 2589 | return; |
| 2259 | − case ESpalette: | |
| 2590 | + case ESpalette: /* ESC ] P aka OSC P */ | |
| 2260 | 2591 | if (isxdigit(c)) { |
| 2261 | 2592 | vc->vc_par[vc->vc_npar++] = hex_to_bin(c); |
| 2262 | 2593 | if (vc->vc_npar == 7) { |
| @@ -2273,16 +2604,14 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 10 unmodified lines | ||
| 2273 | 2604 | } else |
| 2274 | 2605 | vc->vc_state = ESnormal; |
| 2275 | 2606 | return; |
| 2276 | − case ESsquare: | |
| 2277 | − for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++) | |
| 2278 | − vc->vc_par[vc->vc_npar] = 0; | |
| 2279 | − vc->vc_npar = 0; | |
| 2607 | + case ESsquare: /* ESC [ aka CSI, parameters or modifiers expected */ | |
| 2608 | + vc_reset_params(vc); | |
| 2609 | + | |
| 2280 | 2610 | vc->vc_state = ESgetpars; |
| 2281 | − if (c == '[') { /* Function key */ | |
| 2282 | − vc->vc_state=ESfunckey; | |
| 2283 | − return; | |
| 2284 | − } | |
| 2285 | 2611 | switch (c) { |
| 2612 | + case '[': /* Function key */ | |
| 2613 | + vc->vc_state = ESfunckey; | |
| 2614 | + return; | |
| 2286 | 2615 | case '?': |
| 2287 | 2616 | vc->vc_priv = EPdec; |
| 2288 | 2617 | return; |
| @@ -2298,182 +2627,44 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 9 unmodified lines | ||
| 2298 | 2627 | } |
| 2299 | 2628 | vc->vc_priv = EPecma; |
| 2300 | 2629 | fallthrough; |
| 2301 | − case ESgetpars: | |
| 2302 | − if (c == ';' && vc->vc_npar < NPAR - 1) { | |
| 2303 | − vc->vc_npar++; | |
| 2304 | − return; | |
| 2305 | − } else if (c>='0' && c<='9') { | |
| 2630 | + case ESgetpars: /* ESC [ aka CSI, parameters expected */ | |
| 2631 | + switch (c) { | |
| 2632 | + case ';': | |
| 2633 | + if (vc->vc_npar < NPAR - 1) { | |
| 2634 | + vc->vc_npar++; | |
| 2635 | + return; | |
| 2636 | + } | |
| 2637 | + break; | |
| 2638 | + case '0' ... '9': | |
| 2306 | 2639 | vc->vc_par[vc->vc_npar] *= 10; |
| 2307 | 2640 | vc->vc_par[vc->vc_npar] += c - '0'; |
| 2308 | 2641 | return; |
| 2309 | 2642 | } |
| 2310 | − if (c >= 0x20 && c <= 0x3f) { /* 0x2x, 0x3a and 0x3c - 0x3f */ | |
| 2643 | + if (c >= ASCII_CSI_IGNORE_FIRST && c <= ASCII_CSI_IGNORE_LAST) { | |
| 2311 | 2644 | vc->vc_state = EScsiignore; |
| 2312 | 2645 | return; |
| 2313 | 2646 | } |
| 2647 | + | |
| 2648 | + /* parameters done, handle the control char @c */ | |
| 2649 | + | |
| 2314 | 2650 | vc->vc_state = ESnormal; |
| 2315 | − switch(c) { | |
| 2316 | − case 'h': | |
| 2317 | − if (vc->vc_priv <= EPdec) | |
| 2318 | − set_mode(vc, 1); | |
| 2319 | − return; | |
| 2320 | − case 'l': | |
| 2321 | − if (vc->vc_priv <= EPdec) | |
| 2322 | − set_mode(vc, 0); | |
| 2323 | − return; | |
| 2324 | − case 'c': | |
| 2325 | − if (vc->vc_priv == EPdec) { | |
| 2326 | − if (vc->vc_par[0]) | |
| 2327 | − vc->vc_cursor_type = | |
| 2328 | − CUR_MAKE(vc->vc_par[0], | |
| 2329 | − vc->vc_par[1], | |
| 2330 | − vc->vc_par[2]); | |
| 2331 | − else | |
| 2332 | − vc->vc_cursor_type = cur_default; | |
| 2333 | − return; | |
| 2334 | − } | |
| 2335 | − break; | |
| 2336 | − case 'm': | |
| 2337 | − if (vc->vc_priv == EPdec) { | |
| 2338 | − clear_selection(); | |
| 2339 | − if (vc->vc_par[0]) | |
| 2340 | − vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1]; | |
| 2341 | − else | |
| 2342 | − vc->vc_complement_mask = vc->vc_s_complement_mask; | |
| 2343 | − return; | |
| 2344 | − } | |
| 2345 | − break; | |
| 2346 | − case 'n': | |
| 2347 | − if (vc->vc_priv == EPecma) { | |
| 2348 | − if (vc->vc_par[0] == 5) | |
| 2349 | − status_report(tty); | |
| 2350 | − else if (vc->vc_par[0] == 6) | |
| 2351 | − cursor_report(vc, tty); | |
| 2352 | − } | |
| 2353 | − return; | |
| 2354 | − } | |
| 2355 | − if (vc->vc_priv != EPecma) { | |
| 2356 | − vc->vc_priv = EPecma; | |
| 2357 | − return; | |
| 2358 | − } | |
| 2359 | − switch(c) { | |
| 2360 | − case 'G': case '`': | |
| 2361 | − if (vc->vc_par[0]) | |
| 2362 | − vc->vc_par[0]--; | |
| 2363 | − gotoxy(vc, vc->vc_par[0], vc->state.y); | |
| 2364 | − return; | |
| 2365 | − case 'A': | |
| 2366 | − if (!vc->vc_par[0]) | |
| 2367 | − vc->vc_par[0]++; | |
| 2368 | − gotoxy(vc, vc->state.x, vc->state.y - vc->vc_par[0]); | |
| 2369 | − return; | |
| 2370 | − case 'B': case 'e': | |
| 2371 | − if (!vc->vc_par[0]) | |
| 2372 | − vc->vc_par[0]++; | |
| 2373 | − gotoxy(vc, vc->state.x, vc->state.y + vc->vc_par[0]); | |
| 2374 | − return; | |
| 2375 | − case 'C': case 'a': | |
| 2376 | − if (!vc->vc_par[0]) | |
| 2377 | − vc->vc_par[0]++; | |
| 2378 | − gotoxy(vc, vc->state.x + vc->vc_par[0], vc->state.y); | |
| 2379 | − return; | |
| 2380 | − case 'D': | |
| 2381 | − if (!vc->vc_par[0]) | |
| 2382 | − vc->vc_par[0]++; | |
| 2383 | − gotoxy(vc, vc->state.x - vc->vc_par[0], vc->state.y); | |
| 2384 | − return; | |
| 2385 | − case 'E': | |
| 2386 | − if (!vc->vc_par[0]) | |
| 2387 | − vc->vc_par[0]++; | |
| 2388 | − gotoxy(vc, 0, vc->state.y + vc->vc_par[0]); | |
| 2389 | − return; | |
| 2390 | − case 'F': | |
| 2391 | − if (!vc->vc_par[0]) | |
| 2392 | − vc->vc_par[0]++; | |
| 2393 | − gotoxy(vc, 0, vc->state.y - vc->vc_par[0]); | |
| 2394 | − return; | |
| 2395 | − case 'd': | |
| 2396 | − if (vc->vc_par[0]) | |
| 2397 | − vc->vc_par[0]--; | |
| 2398 | − gotoxay(vc, vc->state.x ,vc->vc_par[0]); | |
| 2399 | − return; | |
| 2400 | − case 'H': case 'f': | |
| 2401 | − if (vc->vc_par[0]) | |
| 2402 | − vc->vc_par[0]--; | |
| 2403 | − if (vc->vc_par[1]) | |
| 2404 | − vc->vc_par[1]--; | |
| 2405 | − gotoxay(vc, vc->vc_par[1], vc->vc_par[0]); | |
| 2406 | − return; | |
| 2407 | − case 'J': | |
| 2408 | − csi_J(vc, vc->vc_par[0]); | |
| 2409 | − return; | |
| 2410 | − case 'K': | |
| 2411 | − csi_K(vc, vc->vc_par[0]); | |
| 2412 | − return; | |
| 2413 | − case 'L': | |
| 2414 | − csi_L(vc, vc->vc_par[0]); | |
| 2415 | − return; | |
| 2416 | − case 'M': | |
| 2417 | − csi_M(vc, vc->vc_par[0]); | |
| 2418 | − return; | |
| 2419 | − case 'P': | |
| 2420 | − csi_P(vc, vc->vc_par[0]); | |
| 2421 | − return; | |
| 2422 | − case 'c': | |
| 2423 | − if (!vc->vc_par[0]) | |
| 2424 | − respond_ID(tty); | |
| 2425 | − return; | |
| 2426 | − case 'g': | |
| 2427 | − if (!vc->vc_par[0] && vc->state.x < VC_TABSTOPS_COUNT) | |
| 2428 | − set_bit(vc->state.x, vc->vc_tab_stop); | |
| 2429 | − else if (vc->vc_par[0] == 3) | |
| 2430 | − bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT); | |
| 2431 | − return; | |
| 2432 | − case 'm': | |
| 2433 | − csi_m(vc); | |
| 2434 | − return; | |
| 2435 | − case 'q': /* DECLL - but only 3 leds */ | |
| 2436 | − /* map 0,1,2,3 to 0,1,2,4 */ | |
| 2437 | − if (vc->vc_par[0] < 4) | |
| 2438 | − vt_set_led_state(vc->vc_num, | |
| 2439 | − (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4); | |
| 2440 | − return; | |
| 2441 | − case 'r': | |
| 2442 | − if (!vc->vc_par[0]) | |
| 2443 | − vc->vc_par[0]++; | |
| 2444 | − if (!vc->vc_par[1]) | |
| 2445 | − vc->vc_par[1] = vc->vc_rows; | |
| 2446 | − /* Minimum allowed region is 2 lines */ | |
| 2447 | − if (vc->vc_par[0] < vc->vc_par[1] && | |
| 2448 | − vc->vc_par[1] <= vc->vc_rows) { | |
| 2449 | − vc->vc_top = vc->vc_par[0] - 1; | |
| 2450 | − vc->vc_bottom = vc->vc_par[1]; | |
| 2451 | − gotoxay(vc, 0, 0); | |
| 2452 | − } | |
| 2453 | − return; | |
| 2454 | − case 's': | |
| 2455 | − save_cur(vc); | |
| 2456 | − return; | |
| 2457 | − case 'u': | |
| 2458 | − restore_cur(vc); | |
| 2459 | − return; | |
| 2460 | − case 'X': | |
| 2461 | − csi_X(vc, vc->vc_par[0]); | |
| 2651 | + | |
| 2652 | + switch (vc->vc_priv) { | |
| 2653 | + case EPdec: | |
| 2654 | + csi_DEC(tty, vc, c); | |
| 2462 | 2655 | return; |
| 2463 | − case '@': | |
| 2464 | − csi_at(vc, vc->vc_par[0]); | |
| 2656 | + case EPecma: | |
| 2657 | + csi_ECMA(tty, vc, c); | |
| 2465 | 2658 | return; |
| 2466 | − case ']': /* setterm functions */ | |
| 2467 | − setterm_command(vc); | |
| 2659 | + default: | |
| 2468 | 2660 | return; |
| 2469 | 2661 | } |
| 2470 | − return; | |
| 2471 | 2662 | case EScsiignore: |
| 2472 | − if (c >= 20 && c <= 0x3f) | |
| 2663 | + if (c >= ASCII_CSI_IGNORE_FIRST && c <= ASCII_CSI_IGNORE_LAST) | |
| 2473 | 2664 | return; |
| 2474 | 2665 | vc->vc_state = ESnormal; |
| 2475 | 2666 | return; |
| 2476 | − case ESpercent: | |
| 2667 | + case ESpercent: /* ESC % */ | |
| 2477 | 2668 | vc->vc_state = ESnormal; |
| 2478 | 2669 | switch (c) { |
| 2479 | 2670 | case '@': /* defined in ISO 2022 */ |
| @@ -2485,36 +2676,36 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 5 unmodified lines | ||
| 2485 | 2676 | return; |
| 2486 | 2677 | } |
| 2487 | 2678 | return; |
| 2488 | − case ESfunckey: | |
| 2679 | + case ESfunckey: /* ESC [ [ aka CSI [ */ | |
| 2489 | 2680 | vc->vc_state = ESnormal; |
| 2490 | 2681 | return; |
| 2491 | − case EShash: | |
| 2682 | + case EShash: /* ESC # */ | |
| 2492 | 2683 | vc->vc_state = ESnormal; |
| 2493 | 2684 | if (c == '8') { |
| 2494 | 2685 | /* DEC screen alignment test. kludge :-) */ |
| 2495 | 2686 | vc->vc_video_erase_char = |
| 2496 | 2687 | (vc->vc_video_erase_char & 0xff00) | 'E'; |
| 2497 | − csi_J(vc, 2); | |
| 2688 | + csi_J(vc, CSI_J_VISIBLE); | |
| 2498 | 2689 | vc->vc_video_erase_char = |
| 2499 | 2690 | (vc->vc_video_erase_char & 0xff00) | ' '; |
| 2500 | 2691 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); |
| 2501 | 2692 | } |
| 2502 | 2693 | return; |
| 2503 | − case ESsetG0: | |
| 2694 | + case ESsetG0: /* ESC ( */ | |
| 2504 | 2695 | vc_setGx(vc, 0, c); |
| 2505 | 2696 | vc->vc_state = ESnormal; |
| 2506 | 2697 | return; |
| 2507 | − case ESsetG1: | |
| 2698 | + case ESsetG1: /* ESC ) */ | |
| 2508 | 2699 | vc_setGx(vc, 1, c); |
| 2509 | 2700 | vc->vc_state = ESnormal; |
| 2510 | 2701 | return; |
| 2511 | − case ESapc: | |
| 2702 | + case ESapc: /* ESC _ */ | |
| 2512 | 2703 | return; |
| 2513 | − case ESosc: | |
| 2704 | + case ESosc: /* ESC ] [0-9] aka OSC [0-9] */ | |
| 2514 | 2705 | return; |
| 2515 | − case ESpm: | |
| 2706 | + case ESpm: /* ESC ^ */ | |
| 2516 | 2707 | return; |
| 2517 | − case ESdcs: | |
| 2708 | + case ESdcs: /* ESC P */ | |
| 2518 | 2709 | return; |
| 2519 | 2710 | default: |
| 2520 | 2711 | vc->vc_state = ESnormal; |
| @@ -2588,33 +2779,39 @@ static inline int vc_translate_ascii(const struct vc_data *vc, int c) · 67 unmodified lines | ||
| 2588 | 2779 | |
| 2589 | 2780 | |
| 2590 | 2781 | /** |
| 2591 | − * vc_sanitize_unicode - Replace invalid Unicode code points with U+FFFD | |
| 2592 | − * @c: the received character, or U+FFFD for invalid sequences. | |
| 2782 | + * vc_sanitize_unicode - Replace invalid Unicode code points with ``U+FFFD`` | |
| 2783 | + * @c: the received code point | |
| 2593 | 2784 | */ |
| 2594 | 2785 | static inline int vc_sanitize_unicode(const int c) |
| 2595 | 2786 | { |
| 2596 | − if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) | |
| 2787 | + if (c >= 0xd800 && c <= 0xdfff) | |
| 2597 | 2788 | return 0xfffd; |
| 2598 | 2789 | |
| 2599 | 2790 | return c; |
| 2600 | 2791 | } |
| 2601 | 2792 | |
| 2602 | 2793 | /** |
| 2603 | − * vc_translate_unicode - Combine UTF-8 into Unicode in @vc_utf_char | |
| 2794 | + * vc_translate_unicode - Combine UTF-8 into Unicode in &vc_data.vc_utf_char | |
| 2604 | 2795 | * @vc: virtual console |
| 2605 | − * @c: character to translate | |
| 2606 | − * @rescan: we return true if we need more (continuation) data | |
| 2796 | + * @c: UTF-8 byte to translate | |
| 2797 | + * @rescan: set to true iff @c wasn't consumed here and needs to be re-processed | |
| 2798 | + * | |
| 2799 | + * * &vc_data.vc_utf_char is the being-constructed Unicode code point. | |
| 2800 | + * * &vc_data.vc_utf_count is the number of continuation bytes still expected to | |
| 2801 | + * arrive. | |
| 2802 | + * * &vc_data.vc_npar is the number of continuation bytes arrived so far. | |
| 2607 | 2803 | * |
| 2608 | − * @vc_utf_char is the being-constructed unicode character. | |
| 2609 | − * @vc_utf_count is the number of continuation bytes still expected to arrive. | |
| 2610 | − * @vc_npar is the number of continuation bytes arrived so far. | |
| 2804 | + * Return: | |
| 2805 | + * * %-1 - Input OK so far, @c consumed, further bytes expected. | |
| 2806 | + * * %0xFFFD - Possibility 1: input invalid, @c may have been consumed (see | |
| 2807 | + * desc. of @rescan). Possibility 2: input OK, @c consumed, | |
| 2808 | + * ``U+FFFD`` is the resulting code point. ``U+FFFD`` is valid, | |
| 2809 | + * ``REPLACEMENT CHARACTER``. | |
| 2810 | + * * otherwise - Input OK, @c consumed, resulting code point returned. | |
| 2611 | 2811 | */ |
| 2612 | 2812 | static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan) |
| 2613 | 2813 | { |
| 2614 | − static const u32 utf8_length_changes[] = { | |
| 2615 | − 0x0000007f, 0x000007ff, 0x0000ffff, | |
| 2616 | − 0x001fffff, 0x03ffffff, 0x7fffffff | |
| 2617 | − }; | |
| 2814 | + static const u32 utf8_length_changes[] = {0x7f, 0x7ff, 0xffff, 0x10ffff}; | |
| 2618 | 2815 | |
| 2619 | 2816 | /* Continuation byte received */ |
| 2620 | 2817 | if ((c & 0xc0) == 0x80) { |
| @@ -2660,14 +2857,7 @@ static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan) · 39 unmodified lines | ||
| 2660 | 2857 | } else if ((c & 0xf8) == 0xf0) { |
| 2661 | 2858 | vc->vc_utf_count = 3; |
| 2662 | 2859 | vc->vc_utf_char = (c & 0x07); |
| 2663 | − } else if ((c & 0xfc) == 0xf8) { | |
| 2664 | − vc->vc_utf_count = 4; | |
| 2665 | − vc->vc_utf_char = (c & 0x03); | |
| 2666 | − } else if ((c & 0xfe) == 0xfc) { | |
| 2667 | − vc->vc_utf_count = 5; | |
| 2668 | − vc->vc_utf_char = (c & 0x01); | |
| 2669 | 2860 | } else { |
| 2670 | − /* 254 and 255 are invalid */ | |
| 2671 | 2861 | return 0xfffd; |
| 2672 | 2862 | } |
| 2673 | 2863 | |
| @@ -2711,9 +2901,13 @@ static bool vc_is_control(struct vc_data *vc, int tc, int c) · 37 unmodified lines | ||
| 2711 | 2901 | * as cursor movement) and should not be displayed as a glyph unless |
| 2712 | 2902 | * the disp_ctrl mode is explicitly enabled. |
| 2713 | 2903 | */ |
| 2714 | − static const u32 CTRL_ACTION = 0x0d00ff81; | |
| 2904 | + static const u32 CTRL_ACTION = BIT(ASCII_NULL) | | |
| 2905 | + GENMASK(ASCII_SHIFTIN, ASCII_BELL) | BIT(ASCII_CANCEL) | | |
| 2906 | + BIT(ASCII_SUBSTITUTE) | BIT(ASCII_ESCAPE); | |
| 2715 | 2907 | /* Cannot be overridden by disp_ctrl */ |
| 2716 | − static const u32 CTRL_ALWAYS = 0x0800f501; | |
| 2908 | + static const u32 CTRL_ALWAYS = BIT(ASCII_NULL) | BIT(ASCII_BACKSPACE) | | |
| 2909 | + BIT(ASCII_LINEFEED) | BIT(ASCII_SHIFTIN) | BIT(ASCII_SHIFTOUT) | | |
| 2910 | + BIT(ASCII_CAR_RET) | BIT(ASCII_FORMFEED) | BIT(ASCII_ESCAPE); | |
| 2717 | 2911 | |
| 2718 | 2912 | if (vc->vc_state != ESnormal) |
| 2719 | 2913 | return true; |
| @@ -2730,17 +2924,17 @@ static bool vc_is_control(struct vc_data *vc, int tc, int c) · 10 unmodified lines | ||
| 2730 | 2924 | * useless without them; to display an arbitrary font position use the |
| 2731 | 2925 | * direct-to-font zone in UTF-8 mode. |
| 2732 | 2926 | */ |
| 2733 | − if (c < 32) { | |
| 2927 | + if (c < BITS_PER_TYPE(CTRL_ALWAYS)) { | |
| 2734 | 2928 | if (vc->vc_disp_ctrl) |
| 2735 | 2929 | return CTRL_ALWAYS & BIT(c); |
| 2736 | 2930 | else |
| 2737 | 2931 | return vc->vc_utf || (CTRL_ACTION & BIT(c)); |
| 2738 | 2932 | } |
| 2739 | 2933 | |
| 2740 | − if (c == 127 && !vc->vc_disp_ctrl) | |
| 2934 | + if (c == ASCII_DEL && !vc->vc_disp_ctrl) | |
| 2741 | 2935 | return true; |
| 2742 | 2936 | |
| 2743 | − if (c == 128 + 27) | |
| 2937 | + if (c == ASCII_EXT_CSI) | |
| 2744 | 2938 | return true; |
| 2745 | 2939 | |
| 2746 | 2940 | return false; |
| @@ -2852,7 +3046,7 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count) · 105 unmodified lines | ||
| 2852 | 3046 | }; |
| 2853 | 3047 | int c, tc, n = 0; |
| 2854 | 3048 | unsigned int currcons; |
| 2855 | − struct vc_data *vc; | |
| 3049 | + struct vc_data *vc = tty->driver_data; | |
| 2856 | 3050 | struct vt_notifier_param param; |
| 2857 | 3051 | bool rescan; |
| 2858 | 3052 | |
| @@ -2860,13 +3054,6 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count) · 1 unmodified line | ||
| 2860 | 3054 | return count; |
| 2861 | 3055 | |
| 2862 | 3056 | console_lock(); |
| 2863 | − vc = tty->driver_data; | |
| 2864 | − if (vc == NULL) { | |
| 2865 | − pr_err("vt: argh, driver_data is NULL !\n"); | |
| 2866 | − console_unlock(); | |
| 2867 | − return 0; | |
| 2868 | − } | |
| 2869 | − | |
| 2870 | 3057 | currcons = vc->vc_num; |
| 2871 | 3058 | if (!vc_cons_allocated(currcons)) { |
| 2872 | 3059 | /* could this happen? */ |
| @@ -2883,7 +3070,7 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count) · 10 unmodified lines | ||
| 2883 | 3070 | param.vc = vc; |
| 2884 | 3071 | |
| 2885 | 3072 | while (!tty->flow.stopped && count) { |
| 2886 | − int orig = *buf; | |
| 3073 | + u8 orig = *buf; | |
| 2887 | 3074 | buf++; |
| 2888 | 3075 | n++; |
| 2889 | 3076 | count--; |
| @@ -2992,16 +3179,16 @@ struct tty_driver *console_driver; · 102 unmodified lines | ||
| 2992 | 3179 | #ifdef CONFIG_VT_CONSOLE |
| 2993 | 3180 | |
| 2994 | 3181 | /** |
| 2995 | − * vt_kmsg_redirect() - Sets/gets the kernel message console | |
| 2996 | − * @new: The new virtual terminal number or -1 if the console should stay | |
| 2997 | − * unchanged | |
| 3182 | + * vt_kmsg_redirect() - sets/gets the kernel message console | |
| 3183 | + * @new: the new virtual terminal number or -1 if the console should stay | |
| 3184 | + * unchanged | |
| 2998 | 3185 | * |
| 2999 | 3186 | * By default, the kernel messages are always printed on the current virtual |
| 3000 | 3187 | * console. However, the user may modify that default with the |
| 3001 | − * TIOCL_SETKMSGREDIRECT ioctl call. | |
| 3188 | + * %TIOCL_SETKMSGREDIRECT ioctl call. | |
| 3002 | 3189 | * |
| 3003 | 3190 | * This function sets the kernel message console to be @new. It returns the old |
| 3004 | − * virtual console number. The virtual terminal number 0 (both as parameter and | |
| 3191 | + * virtual console number. The virtual terminal number %0 (both as parameter and | |
| 3005 | 3192 | * return value) means no redirection (i.e. always printed on the currently |
| 3006 | 3193 | * active console). |
| 3007 | 3194 | * |
| @@ -3009,8 +3196,8 @@ struct tty_driver *console_driver; · 1 unmodified line | ||
| 3009 | 3196 | * value is not modified. You may use the macro vt_get_kmsg_redirect() in that |
| 3010 | 3197 | * case to make the code more understandable. |
| 3011 | 3198 | * |
| 3012 | − * When the kernel is compiled without CONFIG_VT_CONSOLE, this function ignores | |
| 3013 | − * the parameter and always returns 0. | |
| 3199 | + * When the kernel is compiled without %CONFIG_VT_CONSOLE, this function ignores | |
| 3200 | + * the parameter and always returns %0. | |
| 3014 | 3201 | */ |
| 3015 | 3202 | int vt_kmsg_redirect(int new) |
| 3016 | 3203 | { |
| @@ -3065,22 +3252,23 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) · 48 unmodified lines | ||
| 3065 | 3252 | cnt = 0; |
| 3066 | 3253 | while (count--) { |
| 3067 | 3254 | c = *b++; |
| 3068 | − if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) { | |
| 3255 | + if (c == ASCII_LINEFEED || c == ASCII_CAR_RET || | |
| 3256 | + c == ASCII_BACKSPACE || vc->vc_need_wrap) { | |
| 3069 | 3257 | if (cnt && con_is_visible(vc)) |
| 3070 | 3258 | vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x); |
| 3071 | 3259 | cnt = 0; |
| 3072 | − if (c == 8) { /* backspace */ | |
| 3260 | + if (c == ASCII_BACKSPACE) { | |
| 3073 | 3261 | bs(vc); |
| 3074 | 3262 | start = (ushort *)vc->vc_pos; |
| 3075 | 3263 | start_x = vc->state.x; |
| 3076 | 3264 | continue; |
| 3077 | 3265 | } |
| 3078 | − if (c != 13) | |
| 3266 | + if (c != ASCII_CAR_RET) | |
| 3079 | 3267 | lf(vc); |
| 3080 | 3268 | cr(vc); |
| 3081 | 3269 | start = (ushort *)vc->vc_pos; |
| 3082 | 3270 | start_x = vc->state.x; |
| 3083 | − if (c == 10 || c == 13) | |
| 3271 | + if (c == ASCII_LINEFEED || c == ASCII_CAR_RET) | |
| 3084 | 3272 | continue; |
| 3085 | 3273 | } |
| 3086 | 3274 | vc_uniscr_putc(vc, c); |
| @@ -3144,6 +3332,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) · 57 unmodified lines | ||
| 3144 | 3332 | { |
| 3145 | 3333 | char type, data; |
| 3146 | 3334 | char __user *p = (char __user *)arg; |
| 3335 | + void __user *param_aligned32 = (u32 __user *)arg + 1; | |
| 3336 | + void __user *param = (void __user *)arg + 1; | |
| 3147 | 3337 | int lines; |
| 3148 | 3338 | int ret; |
| 3149 | 3339 | |
| @@ -3157,8 +3347,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) · 7 unmodified lines | ||
| 3157 | 3347 | case TIOCL_SETSEL: |
| 3158 | 3348 | if (!capable(CAP_SYS_ADMIN)) |
| 3159 | 3349 | return -EPERM; |
| 3160 | − return set_selection_user((struct tiocl_selection | |
| 3161 | − __user *)(p+1), tty); | |
| 3350 | + return set_selection_user(param, tty); | |
| 3162 | 3351 | case TIOCL_PASTESEL: |
| 3163 | 3352 | if (!capable(CAP_SYS_ADMIN)) |
| 3164 | 3353 | return -EPERM; |
| @@ -3171,10 +3360,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) · 6 unmodified lines | ||
| 3171 | 3360 | case TIOCL_SELLOADLUT: |
| 3172 | 3361 | if (!capable(CAP_SYS_ADMIN)) |
| 3173 | 3362 | return -EPERM; |
| 3174 | − console_lock(); | |
| 3175 | − ret = sel_loadlut(p); | |
| 3176 | − console_unlock(); | |
| 3177 | − break; | |
| 3363 | + return sel_loadlut(param_aligned32); | |
| 3178 | 3364 | case TIOCL_GETSHIFTSTATE: |
| 3179 | 3365 | /* |
| 3180 | 3366 | * Make it possible to react to Shift+Mousebutton. Note that |
| @@ -3190,10 +3376,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) · 9 unmodified lines | ||
| 3190 | 3376 | console_unlock(); |
| 3191 | 3377 | return put_user(data, p); |
| 3192 | 3378 | case TIOCL_SETVESABLANK: |
| 3193 | − console_lock(); | |
| 3194 | − ret = set_vesa_blanking(p); | |
| 3195 | − console_unlock(); | |
| 3196 | − break; | |
| 3379 | + return set_vesa_blanking(param); | |
| 3197 | 3380 | case TIOCL_GETKMSGREDIRECT: |
| 3198 | 3381 | data = vt_get_kmsg_redirect(); |
| 3199 | 3382 | return put_user(data, p); |
| @@ -3214,7 +3397,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) · 14 unmodified lines | ||
| 3214 | 3397 | */ |
| 3215 | 3398 | return fg_console; |
| 3216 | 3399 | case TIOCL_SCROLLCONSOLE: |
| 3217 | − if (get_user(lines, (s32 __user *)(p+4))) | |
| 3400 | + if (get_user(lines, (s32 __user *)param_aligned32)) | |
| 3218 | 3401 | return -EFAULT; |
| 3219 | 3402 | |
| 3220 | 3403 | /* |
| @@ -3312,16 +3495,13 @@ static void con_start(struct tty_struct *tty) · 91 unmodified lines | ||
| 3312 | 3495 | |
| 3313 | 3496 | static void con_flush_chars(struct tty_struct *tty) |
| 3314 | 3497 | { |
| 3315 | − struct vc_data *vc; | |
| 3498 | + struct vc_data *vc = tty->driver_data; | |
| 3316 | 3499 | |
| 3317 | 3500 | if (in_interrupt()) /* from flush_to_ldisc */ |
| 3318 | 3501 | return; |
| 3319 | 3502 | |
| 3320 | − /* if we race with con_close(), vt may be null */ | |
| 3321 | 3503 | console_lock(); |
| 3322 | − vc = tty->driver_data; | |
| 3323 | − if (vc) | |
| 3324 | − set_cursor(vc); | |
| 3504 | + set_cursor(vc); | |
| 3325 | 3505 | console_unlock(); |
| 3326 | 3506 | } |
| 3327 | 3507 | |
| @@ -3471,7 +3651,7 @@ static int __init con_init(void) · 143 unmodified lines | ||
| 3471 | 3651 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); |
| 3472 | 3652 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
| 3473 | 3653 | tty_port_init(&vc->port); |
| 3474 | − visual_init(vc, currcons, 1); | |
| 3654 | + visual_init(vc, currcons, true); | |
| 3475 | 3655 | /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */ |
| 3476 | 3656 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); |
| 3477 | 3657 | vc_init(vc, currcons || !vc->vc_sw->con_save_screen); |
| @@ -3481,7 +3661,7 @@ static int __init con_init(void) · 3 unmodified lines | ||
| 3481 | 3661 | set_origin(vc); |
| 3482 | 3662 | save_screen(vc); |
| 3483 | 3663 | gotoxy(vc, vc->state.x, vc->state.y); |
| 3484 | − csi_J(vc, 0); | |
| 3664 | + csi_J(vc, CSI_J_CURSOR_TO_END); | |
| 3485 | 3665 | update_screen(vc); |
| 3486 | 3666 | pr_info("Console: %s %s %dx%d\n", |
| 3487 | 3667 | 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, · 152 unmodified lines | ||
| 3640 | 3820 | old_was_color = vc->vc_can_do_color; |
| 3641 | 3821 | vc->vc_sw->con_deinit(vc); |
| 3642 | 3822 | vc->vc_origin = (unsigned long)vc->vc_screenbuf; |
| 3643 | − visual_init(vc, i, 0); | |
| 3823 | + visual_init(vc, i, false); | |
| 3644 | 3824 | set_origin(vc); |
| 3645 | 3825 | update_attr(vc); |
| 3646 | 3826 | |
| @@ -3930,7 +4110,7 @@ static void vtconsole_deinit_device(struct con_driver *con) · 283 unmodified lines | ||
| 3930 | 4110 | * RETURNS: zero if unbound, nonzero if bound |
| 3931 | 4111 | * |
| 3932 | 4112 | * Drivers can call this and if zero, they should release |
| 3933 | − * all resources allocated on con_startup() | |
| 4113 | + * all resources allocated on &consw.con_startup() | |
| 3934 | 4114 | */ |
| 3935 | 4115 | int con_is_bound(const struct consw *csw) |
| 3936 | 4116 | { |
| @@ -3970,15 +4150,9 @@ EXPORT_SYMBOL(con_is_visible); · 33 unmodified lines | ||
| 3970 | 4150 | * Called when the console is taken over by the kernel debugger, this |
| 3971 | 4151 | * function needs to save the current console state, then put the console |
| 3972 | 4152 | * into a state suitable for the kernel debugger. |
| 3973 | − * | |
| 3974 | − * RETURNS: | |
| 3975 | − * Zero on success, nonzero if a failure occurred when trying to prepare | |
| 3976 | − * the console for the debugger. | |
| 3977 | 4153 | */ |
| 3978 | −int con_debug_enter(struct vc_data *vc) | |
| 4154 | +void con_debug_enter(struct vc_data *vc) | |
| 3979 | 4155 | { |
| 3980 | − int ret = 0; | |
| 3981 | − | |
| 3982 | 4156 | saved_fg_console = fg_console; |
| 3983 | 4157 | saved_last_console = last_console; |
| 3984 | 4158 | saved_want_console = want_console; |
| @@ -3987,7 +4161,7 @@ int con_debug_enter(struct vc_data *vc) · 2 unmodified lines | ||
| 3987 | 4161 | vc->vc_mode = KD_TEXT; |
| 3988 | 4162 | console_blanked = 0; |
| 3989 | 4163 | if (vc->vc_sw->con_debug_enter) |
| 3990 | − ret = vc->vc_sw->con_debug_enter(vc); | |
| 4164 | + vc->vc_sw->con_debug_enter(vc); | |
| 3991 | 4165 | #ifdef CONFIG_KGDB_KDB |
| 3992 | 4166 | /* Set the initial LINES variable if it is not already set */ |
| 3993 | 4167 | if (vc->vc_rows < 999) { |
| @@ -4017,7 +4191,6 @@ int con_debug_enter(struct vc_data *vc) · 23 unmodified lines | ||
| 4017 | 4191 | } |
| 4018 | 4192 | } |
| 4019 | 4193 | #endif /* CONFIG_KGDB_KDB */ |
| 4020 | − return ret; | |
| 4021 | 4194 | } |
| 4022 | 4195 | EXPORT_SYMBOL_GPL(con_debug_enter); |
| 4023 | 4196 | |
| @@ -4026,15 +4199,10 @@ EXPORT_SYMBOL_GPL(con_debug_enter); · 2 unmodified lines | ||
| 4026 | 4199 | * |
| 4027 | 4200 | * Restore the console state to what it was before the kernel debugger |
| 4028 | 4201 | * was invoked. |
| 4029 | − * | |
| 4030 | − * RETURNS: | |
| 4031 | − * Zero on success, nonzero if a failure occurred when trying to restore | |
| 4032 | − * the console. | |
| 4033 | 4202 | */ |
| 4034 | −int con_debug_leave(void) | |
| 4203 | +void con_debug_leave(void) | |
| 4035 | 4204 | { |
| 4036 | 4205 | struct vc_data *vc; |
| 4037 | − int ret = 0; | |
| 4038 | 4206 | |
| 4039 | 4207 | fg_console = saved_fg_console; |
| 4040 | 4208 | last_console = saved_last_console; |
| @@ -4044,8 +4212,7 @@ int con_debug_leave(void) · 3 unmodified lines | ||
| 4044 | 4212 | |
| 4045 | 4213 | vc = vc_cons[fg_console].d; |
| 4046 | 4214 | if (vc->vc_sw->con_debug_leave) |
| 4047 | − ret = vc->vc_sw->con_debug_leave(vc); | |
| 4048 | − return ret; | |
| 4215 | + vc->vc_sw->con_debug_leave(vc); | |
| 4049 | 4216 | } |
| 4050 | 4217 | EXPORT_SYMBOL_GPL(con_debug_leave); |
| 4051 | 4218 | |
| @@ -4275,14 +4442,17 @@ postcore_initcall(vtconsole_class_init); · 223 unmodified lines | ||
| 4275 | 4442 | * Screen blanking |
| 4276 | 4443 | */ |
| 4277 | 4444 | |
| 4278 | −static int set_vesa_blanking(char __user *p) | |
| 4445 | +static int set_vesa_blanking(u8 __user *mode_user) | |
| 4279 | 4446 | { |
| 4280 | − unsigned int mode; | |
| 4447 | + u8 mode; | |
| 4281 | 4448 | |
| 4282 | − if (get_user(mode, p + 1)) | |
| 4449 | + if (get_user(mode, mode_user)) | |
| 4283 | 4450 | return -EFAULT; |
| 4284 | 4451 | |
| 4285 | − vesa_blank_mode = (mode < 4) ? mode : 0; | |
| 4452 | + console_lock(); | |
| 4453 | + vesa_blank_mode = (mode <= VESA_BLANK_MAX) ? mode : VESA_NO_BLANKING; | |
| 4454 | + console_unlock(); | |
| 4455 | + | |
| 4286 | 4456 | return 0; |
| 4287 | 4457 | } |
| 4288 | 4458 | |
| @@ -4307,7 +4477,7 @@ void do_blank_screen(int entering_gfx) · 18 unmodified lines | ||
| 4307 | 4477 | if (entering_gfx) { |
| 4308 | 4478 | hide_cursor(vc); |
| 4309 | 4479 | save_screen(vc); |
| 4310 | − vc->vc_sw->con_blank(vc, -1, 1); | |
| 4480 | + vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1); | |
| 4311 | 4481 | console_blanked = fg_console + 1; |
| 4312 | 4482 | blank_state = blank_off; |
| 4313 | 4483 | set_origin(vc); |
| @@ -4328,7 +4498,8 @@ void do_blank_screen(int entering_gfx) · 14 unmodified lines | ||
| 4328 | 4498 | |
| 4329 | 4499 | save_screen(vc); |
| 4330 | 4500 | /* In case we need to reset origin, blanking hook returns 1 */ |
| 4331 | − i = vc->vc_sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0); | |
| 4501 | + i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND : | |
| 4502 | + (vesa_blank_mode + 1), 0); | |
| 4332 | 4503 | console_blanked = fg_console + 1; |
| 4333 | 4504 | if (i) |
| 4334 | 4505 | set_origin(vc); |
| @@ -4379,7 +4550,7 @@ void do_unblank_screen(int leaving_gfx) · 44 unmodified lines | ||
| 4379 | 4550 | } |
| 4380 | 4551 | |
| 4381 | 4552 | console_blanked = 0; |
| 4382 | − if (vc->vc_sw->con_blank(vc, 0, leaving_gfx)) | |
| 4553 | + if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx)) | |
| 4383 | 4554 | /* Low-level driver cannot restore -> do it ourselves */ |
| 4384 | 4555 | update_screen(vc); |
| 4385 | 4556 | if (console_blank_hook) |
| @@ -4584,7 +4755,7 @@ out: · 198 unmodified lines | ||
| 4584 | 4755 | return rc; |
| 4585 | 4756 | } |
| 4586 | 4757 | |
| 4587 | −static int con_font_set(struct vc_data *vc, struct console_font_op *op) | |
| 4758 | +static int con_font_set(struct vc_data *vc, const struct console_font_op *op) | |
| 4588 | 4759 | { |
| 4589 | 4760 | struct console_font font; |
| 4590 | 4761 | int rc = -EINVAL; |
| @@ -4748,43 +4919,3 @@ void vcs_scr_updated(struct vc_data *vc) · 157 unmodified lines | ||
| 4748 | 4919 | { |
| 4749 | 4920 | notify_update(vc); |
| 4750 | 4921 | } |
| 4751 | − | |
| 4752 | −void vc_scrolldelta_helper(struct vc_data *c, int lines, | |
| 4753 | − unsigned int rolled_over, void *base, unsigned int size) | |
| 4754 | −{ | |
| 4755 | − unsigned long ubase = (unsigned long)base; | |
| 4756 | − ptrdiff_t scr_end = (void *)c->vc_scr_end - base; | |
| 4757 | − ptrdiff_t vorigin = (void *)c->vc_visible_origin - base; | |
| 4758 | − ptrdiff_t origin = (void *)c->vc_origin - base; | |
| 4759 | − int margin = c->vc_size_row * 4; | |
| 4760 | − int from, wrap, from_off, avail; | |
| 4761 | − | |
| 4762 | − /* Turn scrollback off */ | |
| 4763 | − if (!lines) { | |
| 4764 | − c->vc_visible_origin = c->vc_origin; | |
| 4765 | − return; | |
| 4766 | − } | |
| 4767 | − | |
| 4768 | − /* Do we have already enough to allow jumping from 0 to the end? */ | |
| 4769 | − if (rolled_over > scr_end + margin) { | |
| 4770 | − from = scr_end; | |
| 4771 | − wrap = rolled_over + c->vc_size_row; | |
| 4772 | − } else { | |
| 4773 | − from = 0; | |
| 4774 | − wrap = size; | |
| 4775 | − } | |
| 4776 | − | |
| 4777 | − from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row; | |
| 4778 | − avail = (origin - from + wrap) % wrap; | |
| 4779 | − | |
| 4780 | − /* Only a little piece would be left? Show all incl. the piece! */ | |
| 4781 | − if (avail < 2 * margin) | |
| 4782 | − margin = 0; | |
| 4783 | − if (from_off < margin) | |
| 4784 | − from_off = 0; | |
| 4785 | − if (from_off > avail - margin) | |
| 4786 | − from_off = avail; | |
| 4787 | − | |
| 4788 | − c->vc_visible_origin = ubase + (from + from_off) % wrap; | |
| 4789 | −} | |
| 4790 | −EXPORT_SYMBOL_GPL(vc_scrolldelta_helper); | |
| @@ -714,8 +714,7 @@ static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs) · 713 unmodified lines | ||
| 714 | 714 | vcp->vc_scan_lines = v.v_vlin; |
| 715 | 715 | if (v.v_clin) |
| 716 | 716 | vcp->vc_cell_height = v.v_clin; |
| 717 | − vcp->vc_resize_user = 1; | |
| 718 | − ret = vc_resize(vcp, v.v_cols, v.v_rows); | |
| 717 | + ret = __vc_resize(vcp, v.v_cols, v.v_rows, true); | |
| 719 | 718 | if (ret) { |
| 720 | 719 | vcp->vc_scan_lines = save_scan_lines; |
| 721 | 720 | vcp->vc_cell_height = save_cell_height; |
| @@ -923,9 +922,8 @@ int vt_ioctl(struct tty_struct *tty, · 201 unmodified lines | ||
| 923 | 922 | vc = vc_cons[i].d; |
| 924 | 923 | |
| 925 | 924 | if (vc) { |
| 926 | − vc->vc_resize_user = 1; | |
| 927 | 925 | /* FIXME: review v tty lock */ |
| 928 | − vc_resize(vc_cons[i].d, cc, ll); | |
| 926 | + __vc_resize(vc_cons[i].d, cc, ll, true); | |
| 929 | 927 | } |
| 930 | 928 | } |
| 931 | 929 | console_unlock(); |
| @@ -50,7 +50,8 @@ void dummycon_unregister_output_notifier(struct notifier_block *nb) · 49 unmodified lines | ||
| 50 | 50 | raw_notifier_chain_unregister(&dummycon_output_nh, nb); |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | −static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) | |
| 53 | +static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y, | |
| 54 | + unsigned int x) | |
| 54 | 55 | { |
| 55 | 56 | WARN_CONSOLE_UNLOCKED(); |
| 56 | 57 | |
| @@ -58,10 +59,10 @@ static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) · 1 unmodified line | ||
| 58 | 59 | raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); |
| 59 | 60 | } |
| 60 | 61 | |
| 61 | −static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, | |
| 62 | − int count, int ypos, int xpos) | |
| 62 | +static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, | |
| 63 | + unsigned int ypos, unsigned int xpos) | |
| 63 | 64 | { |
| 64 | − int i; | |
| 65 | + unsigned int i; | |
| 65 | 66 | |
| 66 | 67 | if (!dummycon_putc_called) { |
| 67 | 68 | /* Ignore erases */ |
| @@ -78,18 +79,21 @@ static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, · 10 unmodified lines | ||
| 78 | 79 | raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); |
| 79 | 80 | } |
| 80 | 81 | |
| 81 | −static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) | |
| 82 | +static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, | |
| 83 | + bool mode_switch) | |
| 82 | 84 | { |
| 83 | 85 | /* Redraw, so that we get putc(s) for output done while blanked */ |
| 84 | − return 1; | |
| 86 | + return true; | |
| 85 | 87 | } |
| 86 | 88 | #else |
| 87 | −static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } | |
| 88 | −static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, | |
| 89 | − int count, int ypos, int xpos) { } | |
| 90 | −static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) | |
| 89 | +static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y, | |
| 90 | + unsigned int x) { } | |
| 91 | +static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, | |
| 92 | + unsigned int ypos, unsigned int xpos) { } | |
| 93 | +static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, | |
| 94 | + bool mode_switch) | |
| 91 | 95 | { |
| 92 | − return 0; | |
| 96 | + return false; | |
| 93 | 97 | } |
| 94 | 98 | #endif |
| 95 | 99 | |
| @@ -98,7 +102,7 @@ static const char *dummycon_startup(void) · 2 unmodified lines | ||
| 98 | 102 | return "dummy device"; |
| 99 | 103 | } |
| 100 | 104 | |
| 101 | −static void dummycon_init(struct vc_data *vc, int init) | |
| 105 | +static void dummycon_init(struct vc_data *vc, bool init) | |
| 102 | 106 | { |
| 103 | 107 | vc->vc_can_do_color = 1; |
| 104 | 108 | if (init) { |
| @@ -109,9 +113,9 @@ static void dummycon_init(struct vc_data *vc, int init) · 4 unmodified lines | ||
| 109 | 113 | } |
| 110 | 114 | |
| 111 | 115 | static void dummycon_deinit(struct vc_data *vc) { } |
| 112 | −static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height, | |
| 113 | − int width) { } | |
| 114 | −static void dummycon_cursor(struct vc_data *vc, int mode) { } | |
| 116 | +static void dummycon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, | |
| 117 | + unsigned int width) { } | |
| 118 | +static void dummycon_cursor(struct vc_data *vc, bool enable) { } | |
| 115 | 119 | |
| 116 | 120 | static bool dummycon_scroll(struct vc_data *vc, unsigned int top, |
| 117 | 121 | unsigned int bottom, enum con_scroll dir, |
| @@ -120,9 +124,9 @@ static bool dummycon_scroll(struct vc_data *vc, unsigned int top, · 2 unmodified lines | ||
| 120 | 124 | return false; |
| 121 | 125 | } |
| 122 | 126 | |
| 123 | −static int dummycon_switch(struct vc_data *vc) | |
| 127 | +static bool dummycon_switch(struct vc_data *vc) | |
| 124 | 128 | { |
| 125 | − return 0; | |
| 129 | + return false; | |
| 126 | 130 | } |
| 127 | 131 | |
| 128 | 132 | /* |
| @@ -352,7 +352,7 @@ static const char *mdacon_startup(void) · 351 unmodified lines | ||
| 352 | 352 | return "MDA-2"; |
| 353 | 353 | } |
| 354 | 354 | |
| 355 | −static void mdacon_init(struct vc_data *c, int init) | |
| 355 | +static void mdacon_init(struct vc_data *c, bool init) | |
| 356 | 356 | { |
| 357 | 357 | c->vc_complement_mask = 0x0800; /* reverse video */ |
| 358 | 358 | c->vc_display_fg = &mda_display_fg; |
| @@ -427,13 +427,8 @@ static inline u16 *mda_addr(unsigned int x, unsigned int y) · 68 unmodified lines | ||
| 427 | 427 | return mda_vram_base + y * mda_num_columns + x; |
| 428 | 428 | } |
| 429 | 429 | |
| 430 | −static void mdacon_putc(struct vc_data *c, int ch, int y, int x) | |
| 431 | −{ | |
| 432 | − scr_writew(mda_convert_attr(ch), mda_addr(x, y)); | |
| 433 | −} | |
| 434 | − | |
| 435 | −static void mdacon_putcs(struct vc_data *c, const unsigned short *s, | |
| 436 | − int count, int y, int x) | |
| 430 | +static void mdacon_putcs(struct vc_data *c, const u16 *s, unsigned int count, | |
| 431 | + unsigned int y, unsigned int x) | |
| 437 | 432 | { |
| 438 | 433 | u16 *dest = mda_addr(x, y); |
| 439 | 434 | |
| @@ -442,29 +437,22 @@ static void mdacon_putcs(struct vc_data *c, const unsigned short *s, · 2 unmodified lines | ||
| 442 | 437 | } |
| 443 | 438 | } |
| 444 | 439 | |
| 445 | −static void mdacon_clear(struct vc_data *c, int y, int x, | |
| 446 | − int height, int width) | |
| 440 | +static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x, | |
| 441 | + unsigned int width) | |
| 447 | 442 | { |
| 448 | 443 | u16 *dest = mda_addr(x, y); |
| 449 | 444 | u16 eattr = mda_convert_attr(c->vc_video_erase_char); |
| 450 | 445 | |
| 451 | − if (width <= 0 || height <= 0) | |
| 452 | − return; | |
| 453 | − | |
| 454 | − if (x==0 && width==mda_num_columns) { | |
| 455 | − scr_memsetw(dest, eattr, height*width*2); | |
| 456 | − } else { | |
| 457 | − for (; height > 0; height--, dest+=mda_num_columns) | |
| 458 | − scr_memsetw(dest, eattr, width*2); | |
| 459 | − } | |
| 446 | + scr_memsetw(dest, eattr, width * 2); | |
| 460 | 447 | } |
| 461 | − | |
| 462 | −static int mdacon_switch(struct vc_data *c) | |
| 448 | + | |
| 449 | +static bool mdacon_switch(struct vc_data *c) | |
| 463 | 450 | { |
| 464 | − return 1; /* redrawing needed */ | |
| 451 | + return true; /* redrawing needed */ | |
| 465 | 452 | } |
| 466 | 453 | |
| 467 | −static int mdacon_blank(struct vc_data *c, int blank, int mode_switch) | |
| 454 | +static bool mdacon_blank(struct vc_data *c, enum vesa_blank_mode blank, | |
| 455 | + bool mode_switch) | |
| 468 | 456 | { |
| 469 | 457 | if (mda_type == TYPE_MDA) { |
| 470 | 458 | if (blank) |
| @@ -472,20 +460,20 @@ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch) · 1 unmodified line | ||
| 472 | 460 | mda_convert_attr(c->vc_video_erase_char), |
| 473 | 461 | c->vc_screenbuf_size); |
| 474 | 462 | /* Tell console.c that it has to restore the screen itself */ |
| 475 | − return 1; | |
| 463 | + return true; | |
| 476 | 464 | } else { |
| 477 | 465 | if (blank) |
| 478 | 466 | outb_p(0x00, mda_mode_port); /* disable video */ |
| 479 | 467 | else |
| 480 | 468 | outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, |
| 481 | 469 | mda_mode_port); |
| 482 | − return 0; | |
| 470 | + return false; | |
| 483 | 471 | } |
| 484 | 472 | } |
| 485 | 473 | |
| 486 | −static void mdacon_cursor(struct vc_data *c, int mode) | |
| 474 | +static void mdacon_cursor(struct vc_data *c, bool enable) | |
| 487 | 475 | { |
| 488 | − if (mode == CM_ERASE) { | |
| 476 | + if (!enable) { | |
| 489 | 477 | mda_set_cursor(mda_vram_len - 1); |
| 490 | 478 | return; |
| 491 | 479 | } |
| @@ -544,7 +532,6 @@ static const struct consw mda_con = { · 52 unmodified lines | ||
| 544 | 532 | .con_init = mdacon_init, |
| 545 | 533 | .con_deinit = mdacon_deinit, |
| 546 | 534 | .con_clear = mdacon_clear, |
| 547 | − .con_putc = mdacon_putc, | |
| 548 | 535 | .con_putcs = mdacon_putcs, |
| 549 | 536 | .con_cursor = mdacon_cursor, |
| 550 | 537 | .con_scroll = mdacon_scroll, |
| @@ -324,7 +324,7 @@ out_unmap: · 323 unmodified lines | ||
| 324 | 324 | return NULL; |
| 325 | 325 | } |
| 326 | 326 | |
| 327 | −static void newport_init(struct vc_data *vc, int init) | |
| 327 | +static void newport_init(struct vc_data *vc, bool init) | |
| 328 | 328 | { |
| 329 | 329 | int cols, rows; |
| 330 | 330 | |
| @@ -346,12 +346,12 @@ static void newport_deinit(struct vc_data *c) · 15 unmodified lines | ||
| 346 | 346 | } |
| 347 | 347 | } |
| 348 | 348 | |
| 349 | −static void newport_clear(struct vc_data *vc, int sy, int sx, int height, | |
| 350 | − int width) | |
| 349 | +static void newport_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, | |
| 350 | + unsigned int width) | |
| 351 | 351 | { |
| 352 | 352 | int xend = ((sx + width) << 3) - 1; |
| 353 | 353 | int ystart = ((sy << 4) + topscan) & 0x3ff; |
| 354 | − int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff; | |
| 354 | + int yend = (((sy + 1) << 4) + topscan - 1) & 0x3ff; | |
| 355 | 355 | |
| 356 | 356 | if (logo_active) |
| 357 | 357 | return; |
| @@ -367,8 +367,8 @@ static void newport_clear(struct vc_data *vc, int sy, int sx, int height, · 9 unmodified lines | ||
| 367 | 367 | } |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | −static void newport_putc(struct vc_data *vc, int charattr, int ypos, | |
| 371 | − int xpos) | |
| 370 | +static void newport_putc(struct vc_data *vc, u16 charattr, unsigned int ypos, | |
| 371 | + unsigned int xpos) | |
| 372 | 372 | { |
| 373 | 373 | unsigned char *p; |
| 374 | 374 | |
| @@ -396,12 +396,13 @@ static void newport_putc(struct vc_data *vc, int charattr, int ypos, · 21 unmodified lines | ||
| 396 | 396 | RENDER(npregs, p); |
| 397 | 397 | } |
| 398 | 398 | |
| 399 | −static void newport_putcs(struct vc_data *vc, const unsigned short *s, | |
| 400 | − int count, int ypos, int xpos) | |
| 399 | +static void newport_putcs(struct vc_data *vc, const u16 *s, | |
| 400 | + unsigned int count, unsigned int ypos, | |
| 401 | + unsigned int xpos) | |
| 401 | 402 | { |
| 402 | − int i; | |
| 403 | − int charattr; | |
| 404 | 403 | unsigned char *p; |
| 404 | + unsigned int i; | |
| 405 | + u16 charattr; | |
| 405 | 406 | |
| 406 | 407 | charattr = (scr_readw(s) >> 8) & 0xff; |
| 407 | 408 | |
| @@ -437,32 +438,28 @@ static void newport_putcs(struct vc_data *vc, const unsigned short *s, · 29 unmodified lines | ||
| 437 | 438 | } |
| 438 | 439 | } |
| 439 | 440 | |
| 440 | −static void newport_cursor(struct vc_data *vc, int mode) | |
| 441 | +static void newport_cursor(struct vc_data *vc, bool enable) | |
| 441 | 442 | { |
| 442 | 443 | unsigned short treg; |
| 443 | 444 | int xcurs, ycurs; |
| 444 | 445 | |
| 445 | − switch (mode) { | |
| 446 | − case CM_ERASE: | |
| 447 | − treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); | |
| 448 | − newport_vc2_set(npregs, VC2_IREG_CONTROL, | |
| 449 | − (treg & ~(VC2_CTRL_ECDISP))); | |
| 450 | − break; | |
| 446 | + treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); | |
| 451 | 447 | |
| 452 | − case CM_MOVE: | |
| 453 | − case CM_DRAW: | |
| 454 | − treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); | |
| 448 | + if (!enable) { | |
| 455 | 449 | newport_vc2_set(npregs, VC2_IREG_CONTROL, |
| 456 | − (treg | VC2_CTRL_ECDISP)); | |
| 457 | − xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2; | |
| 458 | − ycurs = ((xcurs / vc->vc_cols) << 4) + 31; | |
| 459 | − xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction; | |
| 460 | − newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs); | |
| 461 | − newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs); | |
| 450 | + (treg & ~(VC2_CTRL_ECDISP))); | |
| 451 | + return; | |
| 462 | 452 | } |
| 453 | + | |
| 454 | + newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP)); | |
| 455 | + xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2; | |
| 456 | + ycurs = ((xcurs / vc->vc_cols) << 4) + 31; | |
| 457 | + xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction; | |
| 458 | + newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs); | |
| 459 | + newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs); | |
| 463 | 460 | } |
| 464 | 461 | |
| 465 | −static int newport_switch(struct vc_data *vc) | |
| 462 | +static bool newport_switch(struct vc_data *vc) | |
| 466 | 463 | { |
| 467 | 464 | static int logo_drawn = 0; |
| 468 | 465 | |
| @@ -476,14 +473,15 @@ static int newport_switch(struct vc_data *vc) · 7 unmodified lines | ||
| 476 | 473 | } |
| 477 | 474 | } |
| 478 | 475 | |
| 479 | − return 1; | |
| 476 | + return true; | |
| 480 | 477 | } |
| 481 | 478 | |
| 482 | −static int newport_blank(struct vc_data *c, int blank, int mode_switch) | |
| 479 | +static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank, | |
| 480 | + bool mode_switch) | |
| 483 | 481 | { |
| 484 | 482 | unsigned short treg; |
| 485 | 483 | |
| 486 | − if (blank == 0) { | |
| 484 | + if (blank == VESA_NO_BLANKING) { | |
| 487 | 485 | /* unblank console */ |
| 488 | 486 | treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); |
| 489 | 487 | newport_vc2_set(npregs, VC2_IREG_CONTROL, |
| @@ -494,10 +492,12 @@ static int newport_blank(struct vc_data *c, int blank, int mode_switch) · 4 unmodified lines | ||
| 494 | 492 | newport_vc2_set(npregs, VC2_IREG_CONTROL, |
| 495 | 493 | (treg & ~(VC2_CTRL_EDISP))); |
| 496 | 494 | } |
| 497 | − return 1; | |
| 495 | + | |
| 496 | + return true; | |
| 498 | 497 | } |
| 499 | 498 | |
| 500 | −static int newport_set_font(int unit, struct console_font *op, unsigned int vpitch) | |
| 499 | +static int newport_set_font(int unit, const struct console_font *op, | |
| 500 | + unsigned int vpitch) | |
| 501 | 501 | { |
| 502 | 502 | int w = op->width; |
| 503 | 503 | int h = op->height; |
| @@ -564,12 +564,13 @@ static int newport_set_def_font(int unit, struct console_font *op) · 60 unmodified lines | ||
| 564 | 564 | return 0; |
| 565 | 565 | } |
| 566 | 566 | |
| 567 | −static int newport_font_default(struct vc_data *vc, struct console_font *op, char *name) | |
| 567 | +static int newport_font_default(struct vc_data *vc, struct console_font *op, | |
| 568 | + const char *name) | |
| 568 | 569 | { |
| 569 | 570 | return newport_set_def_font(vc->vc_num, op); |
| 570 | 571 | } |
| 571 | 572 | |
| 572 | −static int newport_font_set(struct vc_data *vc, struct console_font *font, | |
| 573 | +static int newport_font_set(struct vc_data *vc, const struct console_font *font, | |
| 573 | 574 | unsigned int vpitch, unsigned int flags) |
| 574 | 575 | { |
| 575 | 576 | return newport_set_font(vc->vc_num, font, vpitch); |
| @@ -71,19 +71,8 @@ static const char *sticon_startup(void) · 70 unmodified lines | ||
| 71 | 71 | return "STI console"; |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | −static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos) | |
| 75 | −{ | |
| 76 | − if (vga_is_gfx || console_blanked) | |
| 77 | − return; | |
| 78 | − | |
| 79 | − if (conp->vc_mode != KD_TEXT) | |
| 80 | − return; | |
| 81 | − | |
| 82 | − sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]); | |
| 83 | −} | |
| 84 | − | |
| 85 | −static void sticon_putcs(struct vc_data *conp, const unsigned short *s, | |
| 86 | − int count, int ypos, int xpos) | |
| 74 | +static void sticon_putcs(struct vc_data *conp, const u16 *s, unsigned int count, | |
| 75 | + unsigned int ypos, unsigned int xpos) | |
| 87 | 76 | { |
| 88 | 77 | if (vga_is_gfx || console_blanked) |
| 89 | 78 | return; |
| @@ -97,7 +86,7 @@ static void sticon_putcs(struct vc_data *conp, const unsigned short *s, · 7 unmodified lines | ||
| 97 | 86 | } |
| 98 | 87 | } |
| 99 | 88 | |
| 100 | −static void sticon_cursor(struct vc_data *conp, int mode) | |
| 89 | +static void sticon_cursor(struct vc_data *conp, bool enable) | |
| 101 | 90 | { |
| 102 | 91 | unsigned short car1; |
| 103 | 92 | |
| @@ -106,23 +95,20 @@ static void sticon_cursor(struct vc_data *conp, int mode) · 2 unmodified lines | ||
| 106 | 95 | return; |
| 107 | 96 | |
| 108 | 97 | car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; |
| 109 | − switch (mode) { | |
| 110 | − case CM_ERASE: | |
| 98 | + if (!enable) { | |
| 111 | 99 | sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, |
| 112 | 100 | font_data[conp->vc_num]); |
| 113 | − break; | |
| 114 | − case CM_MOVE: | |
| 115 | − case CM_DRAW: | |
| 116 | − switch (CUR_SIZE(conp->vc_cursor_type)) { | |
| 117 | − case CUR_UNDERLINE: | |
| 118 | − case CUR_LOWER_THIRD: | |
| 119 | − case CUR_LOWER_HALF: | |
| 120 | − case CUR_TWO_THIRDS: | |
| 121 | − case CUR_BLOCK: | |
| 122 | − sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), | |
| 123 | − conp->state.y, conp->state.x, font_data[conp->vc_num]); | |
| 124 | − break; | |
| 125 | − } | |
| 101 | + return; | |
| 102 | + } | |
| 103 | + | |
| 104 | + switch (CUR_SIZE(conp->vc_cursor_type)) { | |
| 105 | + case CUR_UNDERLINE: | |
| 106 | + case CUR_LOWER_THIRD: | |
| 107 | + case CUR_LOWER_HALF: | |
| 108 | + case CUR_TWO_THIRDS: | |
| 109 | + case CUR_BLOCK: | |
| 110 | + sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), | |
| 111 | + conp->state.y, conp->state.x, font_data[conp->vc_num]); | |
| 126 | 112 | break; |
| 127 | 113 | } |
| 128 | 114 | } |
| @@ -135,7 +121,7 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t, · 6 unmodified lines | ||
| 135 | 121 | if (vga_is_gfx) |
| 136 | 122 | return false; |
| 137 | 123 | |
| 138 | − sticon_cursor(conp, CM_ERASE); | |
| 124 | + sticon_cursor(conp, false); | |
| 139 | 125 | |
| 140 | 126 | switch (dir) { |
| 141 | 127 | case SM_UP: |
| @@ -167,7 +153,7 @@ static void sticon_set_def_font(int unit) · 25 unmodified lines | ||
| 167 | 153 | } |
| 168 | 154 | } |
| 169 | 155 | |
| 170 | −static int sticon_set_font(struct vc_data *vc, struct console_font *op, | |
| 156 | +static int sticon_set_font(struct vc_data *vc, const struct console_font *op, | |
| 171 | 157 | unsigned int vpitch) |
| 172 | 158 | { |
| 173 | 159 | struct sti_struct *sti = sticon_sti; |
| @@ -260,20 +246,21 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op, · 86 unmodified lines | ||
| 260 | 246 | return 0; |
| 261 | 247 | } |
| 262 | 248 | |
| 263 | −static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name) | |
| 249 | +static int sticon_font_default(struct vc_data *vc, struct console_font *op, | |
| 250 | + const char *name) | |
| 264 | 251 | { |
| 265 | 252 | sticon_set_def_font(vc->vc_num); |
| 266 | 253 | |
| 267 | 254 | return 0; |
| 268 | 255 | } |
| 269 | 256 | |
| 270 | −static int sticon_font_set(struct vc_data *vc, struct console_font *font, | |
| 257 | +static int sticon_font_set(struct vc_data *vc, const struct console_font *font, | |
| 271 | 258 | unsigned int vpitch, unsigned int flags) |
| 272 | 259 | { |
| 273 | 260 | return sticon_set_font(vc, font, vpitch); |
| 274 | 261 | } |
| 275 | 262 | |
| 276 | −static void sticon_init(struct vc_data *c, int init) | |
| 263 | +static void sticon_init(struct vc_data *c, bool init) | |
| 277 | 264 | { |
| 278 | 265 | struct sti_struct *sti = sticon_sti; |
| 279 | 266 | int vc_cols, vc_rows; |
| @@ -300,33 +287,32 @@ static void sticon_deinit(struct vc_data *c) · 20 unmodified lines | ||
| 300 | 287 | sticon_set_def_font(i); |
| 301 | 288 | } |
| 302 | 289 | |
| 303 | −static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, | |
| 304 | − int width) | |
| 290 | +static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx, | |
| 291 | + unsigned int width) | |
| 305 | 292 | { |
| 306 | − if (!height || !width) | |
| 307 | − return; | |
| 308 | − | |
| 309 | − sti_clear(sticon_sti, sy, sx, height, width, | |
| 293 | + sti_clear(sticon_sti, sy, sx, 1, width, | |
| 310 | 294 | conp->vc_video_erase_char, font_data[conp->vc_num]); |
| 311 | 295 | } |
| 312 | 296 | |
| 313 | −static int sticon_switch(struct vc_data *conp) | |
| 297 | +static bool sticon_switch(struct vc_data *conp) | |
| 314 | 298 | { |
| 315 | − return 1; /* needs refreshing */ | |
| 299 | + return true; /* needs refreshing */ | |
| 316 | 300 | } |
| 317 | 301 | |
| 318 | −static int sticon_blank(struct vc_data *c, int blank, int mode_switch) | |
| 302 | +static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank, | |
| 303 | + bool mode_switch) | |
| 319 | 304 | { |
| 320 | − if (blank == 0) { | |
| 305 | + if (blank == VESA_NO_BLANKING) { | |
| 321 | 306 | if (mode_switch) |
| 322 | 307 | vga_is_gfx = 0; |
| 323 | − return 1; | |
| 308 | + return true; | |
| 324 | 309 | } |
| 325 | 310 | sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, |
| 326 | 311 | font_data[c->vc_num]); |
| 327 | 312 | if (mode_switch) |
| 328 | 313 | vga_is_gfx = 1; |
| 329 | − return 1; | |
| 314 | + | |
| 315 | + return true; | |
| 330 | 316 | } |
| 331 | 317 | |
| 332 | 318 | static u8 sticon_build_attr(struct vc_data *conp, u8 color, |
| @@ -365,7 +351,6 @@ static const struct consw sti_con = { · 32 unmodified lines | ||
| 365 | 351 | .con_init = sticon_init, |
| 366 | 352 | .con_deinit = sticon_deinit, |
| 367 | 353 | .con_clear = sticon_clear, |
| 368 | − .con_putc = sticon_putc, | |
| 369 | 354 | .con_putcs = sticon_putcs, |
| 370 | 355 | .con_cursor = sticon_cursor, |
| 371 | 356 | .con_scroll = sticon_scroll, |
| @@ -65,7 +65,7 @@ static struct vgastate vgastate; · 64 unmodified lines | ||
| 65 | 65 | * Interface used by the world |
| 66 | 66 | */ |
| 67 | 67 | |
| 68 | −static int vgacon_set_origin(struct vc_data *c); | |
| 68 | +static bool vgacon_set_origin(struct vc_data *c); | |
| 69 | 69 | |
| 70 | 70 | static struct uni_pagedict *vgacon_uni_pagedir; |
| 71 | 71 | static int vgacon_refcount; |
| @@ -81,7 +81,7 @@ static unsigned int vga_video_num_lines; /* Number of text lines */ · 9 unmodified lines | ||
| 81 | 81 | static bool vga_can_do_color; /* Do we support colors? */ |
| 82 | 82 | static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ |
| 83 | 83 | static unsigned char vga_video_type __read_mostly; /* Card type */ |
| 84 | −static int vga_vesa_blanked; | |
| 84 | +static enum vesa_blank_mode vga_vesa_blanked; | |
| 85 | 85 | static bool vga_palette_blanked; |
| 86 | 86 | static bool vga_is_gfx; |
| 87 | 87 | static bool vga_512_chars; |
| @@ -138,8 +138,40 @@ static inline void vga_set_mem_top(struct vc_data *c) · 50 unmodified lines | ||
| 138 | 138 | |
| 139 | 139 | static void vgacon_scrolldelta(struct vc_data *c, int lines) |
| 140 | 140 | { |
| 141 | − vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base, | |
| 142 | − vga_vram_size); | |
| 141 | + unsigned long scr_end = c->vc_scr_end - vga_vram_base; | |
| 142 | + unsigned long vorigin = c->vc_visible_origin - vga_vram_base; | |
| 143 | + unsigned long origin = c->vc_origin - vga_vram_base; | |
| 144 | + int margin = c->vc_size_row * 4; | |
| 145 | + int from, wrap, from_off, avail; | |
| 146 | + | |
| 147 | + /* Turn scrollback off */ | |
| 148 | + if (!lines) { | |
| 149 | + c->vc_visible_origin = c->vc_origin; | |
| 150 | + return; | |
| 151 | + } | |
| 152 | + | |
| 153 | + /* Do we have already enough to allow jumping from 0 to the end? */ | |
| 154 | + if (vga_rolled_over > scr_end + margin) { | |
| 155 | + from = scr_end; | |
| 156 | + wrap = vga_rolled_over + c->vc_size_row; | |
| 157 | + } else { | |
| 158 | + from = 0; | |
| 159 | + wrap = vga_vram_size; | |
| 160 | + } | |
| 161 | + | |
| 162 | + from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row; | |
| 163 | + avail = (origin - from + wrap) % wrap; | |
| 164 | + | |
| 165 | + /* Only a little piece would be left? Show all incl. the piece! */ | |
| 166 | + if (avail < 2 * margin) | |
| 167 | + margin = 0; | |
| 168 | + if (from_off < margin) | |
| 169 | + from_off = 0; | |
| 170 | + if (from_off > avail - margin) | |
| 171 | + from_off = avail; | |
| 172 | + | |
| 173 | + c->vc_visible_origin = vga_vram_base + (from + from_off) % wrap; | |
| 174 | + | |
| 143 | 175 | vga_set_mem_top(c); |
| 144 | 176 | } |
| 145 | 177 | |
| @@ -335,7 +367,7 @@ static const char *vgacon_startup(void) · 189 unmodified lines | ||
| 335 | 367 | return display_desc; |
| 336 | 368 | } |
| 337 | 369 | |
| 338 | −static void vgacon_init(struct vc_data *c, int init) | |
| 370 | +static void vgacon_init(struct vc_data *c, bool init) | |
| 339 | 371 | { |
| 340 | 372 | struct uni_pagedict *p; |
| 341 | 373 | |
| @@ -352,7 +384,7 @@ static void vgacon_init(struct vc_data *c, int init) · 10 unmodified lines | ||
| 352 | 384 | c->vc_scan_lines = vga_scan_lines; |
| 353 | 385 | c->vc_font.height = c->vc_cell_height = vga_video_font_height; |
| 354 | 386 | |
| 355 | − /* set dimensions manually if init != 0 since vc_resize() will fail */ | |
| 387 | + /* set dimensions manually if init is true since vc_resize() will fail */ | |
| 356 | 388 | if (init) { |
| 357 | 389 | c->vc_cols = vga_video_num_columns; |
| 358 | 390 | c->vc_rows = vga_video_num_lines; |
| @@ -471,7 +503,7 @@ static void vgacon_set_cursor_size(int from, int to) · 112 unmodified lines | ||
| 471 | 503 | raw_spin_unlock_irqrestore(&vga_lock, flags); |
| 472 | 504 | } |
| 473 | 505 | |
| 474 | −static void vgacon_cursor(struct vc_data *c, int mode) | |
| 506 | +static void vgacon_cursor(struct vc_data *c, bool enable) | |
| 475 | 507 | { |
| 476 | 508 | unsigned int c_height; |
| 477 | 509 | |
| @@ -482,47 +514,41 @@ static void vgacon_cursor(struct vc_data *c, int mode) · 4 unmodified lines | ||
| 482 | 514 | |
| 483 | 515 | c_height = c->vc_cell_height; |
| 484 | 516 | |
| 485 | − switch (mode) { | |
| 486 | − case CM_ERASE: | |
| 487 | − write_vga(14, (c->vc_pos - vga_vram_base) / 2); | |
| 517 | + write_vga(14, (c->vc_pos - vga_vram_base) / 2); | |
| 518 | + | |
| 519 | + if (!enable) { | |
| 488 | 520 | if (vga_video_type >= VIDEO_TYPE_VGAC) |
| 489 | 521 | vgacon_set_cursor_size(31, 30); |
| 490 | 522 | else |
| 491 | 523 | vgacon_set_cursor_size(31, 31); |
| 492 | − break; | |
| 524 | + return; | |
| 525 | + } | |
| 493 | 526 | |
| 494 | − case CM_MOVE: | |
| 495 | − case CM_DRAW: | |
| 496 | − write_vga(14, (c->vc_pos - vga_vram_base) / 2); | |
| 497 | − switch (CUR_SIZE(c->vc_cursor_type)) { | |
| 498 | − case CUR_UNDERLINE: | |
| 499 | − vgacon_set_cursor_size(c_height - | |
| 500 | − (c_height < 10 ? 2 : 3), | |
| 501 | − c_height - | |
| 502 | − (c_height < 10 ? 1 : 2)); | |
| 503 | − break; | |
| 504 | − case CUR_TWO_THIRDS: | |
| 505 | − vgacon_set_cursor_size(c_height / 3, c_height - | |
| 506 | − (c_height < 10 ? 1 : 2)); | |
| 507 | − break; | |
| 508 | − case CUR_LOWER_THIRD: | |
| 509 | − vgacon_set_cursor_size(c_height * 2 / 3, c_height - | |
| 510 | − (c_height < 10 ? 1 : 2)); | |
| 511 | − break; | |
| 512 | − case CUR_LOWER_HALF: | |
| 513 | − vgacon_set_cursor_size(c_height / 2, c_height - | |
| 514 | − (c_height < 10 ? 1 : 2)); | |
| 515 | − break; | |
| 516 | − case CUR_NONE: | |
| 517 | − if (vga_video_type >= VIDEO_TYPE_VGAC) | |
| 518 | − vgacon_set_cursor_size(31, 30); | |
| 519 | − else | |
| 520 | − vgacon_set_cursor_size(31, 31); | |
| 521 | − break; | |
| 522 | − default: | |
| 523 | − vgacon_set_cursor_size(1, c_height); | |
| 524 | − break; | |
| 525 | − } | |
| 527 | + switch (CUR_SIZE(c->vc_cursor_type)) { | |
| 528 | + case CUR_UNDERLINE: | |
| 529 | + vgacon_set_cursor_size(c_height - (c_height < 10 ? 2 : 3), | |
| 530 | + c_height - (c_height < 10 ? 1 : 2)); | |
| 531 | + break; | |
| 532 | + case CUR_TWO_THIRDS: | |
| 533 | + vgacon_set_cursor_size(c_height / 3, | |
| 534 | + c_height - (c_height < 10 ? 1 : 2)); | |
| 535 | + break; | |
| 536 | + case CUR_LOWER_THIRD: | |
| 537 | + vgacon_set_cursor_size(c_height * 2 / 3, | |
| 538 | + c_height - (c_height < 10 ? 1 : 2)); | |
| 539 | + break; | |
| 540 | + case CUR_LOWER_HALF: | |
| 541 | + vgacon_set_cursor_size(c_height / 2, | |
| 542 | + c_height - (c_height < 10 ? 1 : 2)); | |
| 543 | + break; | |
| 544 | + case CUR_NONE: | |
| 545 | + if (vga_video_type >= VIDEO_TYPE_VGAC) | |
| 546 | + vgacon_set_cursor_size(31, 30); | |
| 547 | + else | |
| 548 | + vgacon_set_cursor_size(31, 31); | |
| 549 | + break; | |
| 550 | + default: | |
| 551 | + vgacon_set_cursor_size(1, c_height); | |
| 526 | 552 | break; |
| 527 | 553 | } |
| 528 | 554 | } |
| @@ -588,7 +614,7 @@ static void vgacon_doresize(struct vc_data *c, · 59 unmodified lines | ||
| 588 | 614 | raw_spin_unlock_irqrestore(&vga_lock, flags); |
| 589 | 615 | } |
| 590 | 616 | |
| 591 | −static int vgacon_switch(struct vc_data *c) | |
| 617 | +static bool vgacon_switch(struct vc_data *c) | |
| 592 | 618 | { |
| 593 | 619 | int x = c->vc_cols * VGA_FONTWIDTH; |
| 594 | 620 | int y = c->vc_rows * c->vc_cell_height; |
| @@ -617,7 +643,7 @@ static int vgacon_switch(struct vc_data *c) · 22 unmodified lines | ||
| 617 | 643 | vgacon_doresize(c, c->vc_cols, c->vc_rows); |
| 618 | 644 | } |
| 619 | 645 | |
| 620 | − return 0; /* Redrawing not needed */ | |
| 646 | + return false; /* Redrawing not needed */ | |
| 621 | 647 | } |
| 622 | 648 | |
| 623 | 649 | static void vga_set_palette(struct vc_data *vc, const unsigned char *table) |
| @@ -657,7 +683,7 @@ static struct { · 33 unmodified lines | ||
| 657 | 683 | unsigned char ClockingMode; /* Seq-Controller:01h */ |
| 658 | 684 | } vga_state; |
| 659 | 685 | |
| 660 | −static void vga_vesa_blank(struct vgastate *state, int mode) | |
| 686 | +static void vga_vesa_blank(struct vgastate *state, enum vesa_blank_mode mode) | |
| 661 | 687 | { |
| 662 | 688 | /* save original values of VGA controller registers */ |
| 663 | 689 | if (!vga_vesa_blanked) { |
| @@ -771,13 +797,14 @@ static void vga_pal_blank(struct vgastate *state) · 107 unmodified lines | ||
| 771 | 797 | } |
| 772 | 798 | } |
| 773 | 799 | |
| 774 | −static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) | |
| 800 | +static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank, | |
| 801 | + bool mode_switch) | |
| 775 | 802 | { |
| 776 | 803 | switch (blank) { |
| 777 | − case 0: /* Unblank */ | |
| 804 | + case VESA_NO_BLANKING: /* Unblank */ | |
| 778 | 805 | if (vga_vesa_blanked) { |
| 779 | 806 | vga_vesa_unblank(&vgastate); |
| 780 | − vga_vesa_blanked = 0; | |
| 807 | + vga_vesa_blanked = VESA_NO_BLANKING; | |
| 781 | 808 | } |
| 782 | 809 | if (vga_palette_blanked) { |
| 783 | 810 | vga_set_palette(c, color_table); |
| @@ -787,8 +814,7 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) · 3 unmodified lines | ||
| 787 | 814 | vga_is_gfx = false; |
| 788 | 815 | /* Tell console.c that it has to restore the screen itself */ |
| 789 | 816 | return 1; |
| 790 | − case 1: /* Normal blanking */ | |
| 791 | − case -1: /* Obsolete */ | |
| 817 | + case VESA_VSYNC_SUSPEND: /* Normal blanking */ | |
| 792 | 818 | if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { |
| 793 | 819 | vga_pal_blank(&vgastate); |
| 794 | 820 | vga_palette_blanked = true; |
| @@ -1004,7 +1030,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight) · 209 unmodified lines | ||
| 1004 | 1030 | /* void size to cause regs to be rewritten */ |
| 1005 | 1031 | cursor_size_lastfrom = 0; |
| 1006 | 1032 | cursor_size_lastto = 0; |
| 1007 | − c->vc_sw->con_cursor(c, CM_DRAW); | |
| 1033 | + c->vc_sw->con_cursor(c, true); | |
| 1008 | 1034 | } |
| 1009 | 1035 | c->vc_font.height = c->vc_cell_height = fontheight; |
| 1010 | 1036 | vc_resize(c, 0, rows); /* Adjust console size */ |
| @@ -1013,7 +1039,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight) · 2 unmodified lines | ||
| 1013 | 1039 | return 0; |
| 1014 | 1040 | } |
| 1015 | 1041 | |
| 1016 | −static int vgacon_font_set(struct vc_data *c, struct console_font *font, | |
| 1042 | +static int vgacon_font_set(struct vc_data *c, const struct console_font *font, | |
| 1017 | 1043 | unsigned int vpitch, unsigned int flags) |
| 1018 | 1044 | { |
| 1019 | 1045 | unsigned charcount = font->charcount; |
| @@ -1049,12 +1075,12 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font, unsigne · 29 unmodified lines | ||
| 1049 | 1075 | } |
| 1050 | 1076 | |
| 1051 | 1077 | static int vgacon_resize(struct vc_data *c, unsigned int width, |
| 1052 | − unsigned int height, unsigned int user) | |
| 1078 | + unsigned int height, bool from_user) | |
| 1053 | 1079 | { |
| 1054 | 1080 | if ((width << 1) * height > vga_vram_size) |
| 1055 | 1081 | return -EINVAL; |
| 1056 | 1082 | |
| 1057 | − if (user) { | |
| 1083 | + if (from_user) { | |
| 1058 | 1084 | /* |
| 1059 | 1085 | * Ho ho! Someone (svgatextmode, eh?) may have reprogrammed |
| 1060 | 1086 | * 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, · 13 unmodified lines | ||
| 1074 | 1100 | return 0; |
| 1075 | 1101 | } |
| 1076 | 1102 | |
| 1077 | −static int vgacon_set_origin(struct vc_data *c) | |
| 1103 | +static bool vgacon_set_origin(struct vc_data *c) | |
| 1078 | 1104 | { |
| 1079 | 1105 | if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ |
| 1080 | 1106 | (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */ |
| 1081 | − return 0; | |
| 1107 | + return false; | |
| 1082 | 1108 | c->vc_origin = c->vc_visible_origin = vga_vram_base; |
| 1083 | 1109 | vga_set_mem_top(c); |
| 1084 | 1110 | vga_rolled_over = 0; |
| 1085 | − return 1; | |
| 1111 | + return true; | |
| 1086 | 1112 | } |
| 1087 | 1113 | |
| 1088 | 1114 | 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, · 70 unmodified lines | ||
| 1159 | 1185 | * The console `switch' structure for the VGA based console |
| 1160 | 1186 | */ |
| 1161 | 1187 | |
| 1162 | −static void vgacon_clear(struct vc_data *vc, int sy, int sx, int height, | |
| 1163 | − int width) { } | |
| 1164 | −static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } | |
| 1165 | −static void vgacon_putcs(struct vc_data *vc, const unsigned short *s, | |
| 1166 | − int count, int ypos, int xpos) { } | |
| 1188 | +static void vgacon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, | |
| 1189 | + unsigned int width) { } | |
| 1190 | +static void vgacon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, | |
| 1191 | + unsigned int ypos, unsigned int xpos) { } | |
| 1167 | 1192 | |
| 1168 | 1193 | const struct consw vga_con = { |
| 1169 | 1194 | .owner = THIS_MODULE, |
| @@ -1171,7 +1196,6 @@ const struct consw vga_con = { · 1 unmodified line | ||
| 1171 | 1196 | .con_init = vgacon_init, |
| 1172 | 1197 | .con_deinit = vgacon_deinit, |
| 1173 | 1198 | .con_clear = vgacon_clear, |
| 1174 | − .con_putc = vgacon_putc, | |
| 1175 | 1199 | .con_putcs = vgacon_putcs, |
| 1176 | 1200 | .con_cursor = vgacon_cursor, |
| 1177 | 1201 | .con_scroll = vgacon_scroll, |
| @@ -233,7 +233,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, · 232 unmodified lines | ||
| 233 | 233 | } |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | −static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, | |
| 236 | +static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, | |
| 237 | 237 | int fg, int bg) |
| 238 | 238 | { |
| 239 | 239 | struct fb_cursor cursor; |
| @@ -348,16 +348,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 108 unmodified lines | ||
| 348 | 348 | mask[i++] = msk; |
| 349 | 349 | } |
| 350 | 350 | |
| 351 | − switch (mode) { | |
| 352 | − case CM_ERASE: | |
| 353 | − ops->cursor_state.enable = 0; | |
| 354 | − break; | |
| 355 | − case CM_DRAW: | |
| 356 | − case CM_MOVE: | |
| 357 | − default: | |
| 358 | − ops->cursor_state.enable = (use_sw) ? 0 : 1; | |
| 359 | − break; | |
| 360 | − } | |
| 351 | + ops->cursor_state.enable = enable && !use_sw; | |
| 361 | 352 | |
| 362 | 353 | cursor.image.data = src; |
| 363 | 354 | cursor.image.fg_color = ops->cursor_state.image.fg_color; |
| @@ -351,7 +351,7 @@ static void fb_flashcursor(struct work_struct *work) · 350 unmodified lines | ||
| 351 | 351 | struct fb_info *info; |
| 352 | 352 | struct vc_data *vc = NULL; |
| 353 | 353 | int c; |
| 354 | − int mode; | |
| 354 | + bool enable; | |
| 355 | 355 | int ret; |
| 356 | 356 | |
| 357 | 357 | /* FIXME: we should sort out the unbind locking instead */ |
| @@ -375,9 +375,8 @@ static void fb_flashcursor(struct work_struct *work) · 17 unmodified lines | ||
| 375 | 375 | } |
| 376 | 376 | |
| 377 | 377 | c = scr_readw((u16 *) vc->vc_pos); |
| 378 | − mode = (!ops->cursor_flash || ops->cursor_state.enable) ? | |
| 379 | − CM_ERASE : CM_DRAW; | |
| 380 | − ops->cursor(vc, info, mode, get_color(vc, info, c, 1), | |
| 378 | + enable = ops->cursor_flash && !ops->cursor_state.enable; | |
| 379 | + ops->cursor(vc, info, enable, get_color(vc, info, c, 1), | |
| 381 | 380 | get_color(vc, info, c, 0)); |
| 382 | 381 | console_unlock(); |
| 383 | 382 | |
| @@ -920,7 +919,7 @@ static void display_to_var(struct fb_var_screeninfo *var, · 536 unmodified lines | ||
| 920 | 919 | |
| 921 | 920 | static const char *fbcon_startup(void) |
| 922 | 921 | { |
| 923 | − const char *display_desc = "frame buffer device"; | |
| 922 | + static const char display_desc[] = "frame buffer device"; | |
| 924 | 923 | struct fbcon_display *p = &fb_display[fg_console]; |
| 925 | 924 | struct vc_data *vc = vc_cons[fg_console].d; |
| 926 | 925 | const struct font_desc *font = NULL; |
| @@ -987,7 +986,7 @@ static const char *fbcon_startup(void) · 60 unmodified lines | ||
| 987 | 986 | return display_desc; |
| 988 | 987 | } |
| 989 | 988 | |
| 990 | −static void fbcon_init(struct vc_data *vc, int init) | |
| 989 | +static void fbcon_init(struct vc_data *vc, bool init) | |
| 991 | 990 | { |
| 992 | 991 | struct fb_info *info; |
| 993 | 992 | struct fbcon_ops *ops; |
| @@ -1234,8 +1233,8 @@ finished: · 240 unmodified lines | ||
| 1234 | 1233 | * restriction is simplicity & efficiency at the moment. |
| 1235 | 1234 | */ |
| 1236 | 1235 | |
| 1237 | −static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, | |
| 1238 | − int width) | |
| 1236 | +static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, | |
| 1237 | + unsigned int height, unsigned int width) | |
| 1239 | 1238 | { |
| 1240 | 1239 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 1241 | 1240 | 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, · 30 unmodified lines | ||
| 1272 | 1271 | ops->clear(vc, info, real_y(p, sy), sx, height, width); |
| 1273 | 1272 | } |
| 1274 | 1273 | |
| 1275 | −static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, | |
| 1276 | − int count, int ypos, int xpos) | |
| 1274 | +static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, | |
| 1275 | + unsigned int width) | |
| 1276 | +{ | |
| 1277 | + __fbcon_clear(vc, sy, sx, 1, width); | |
| 1278 | +} | |
| 1279 | + | |
| 1280 | +static void fbcon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, | |
| 1281 | + unsigned int ypos, unsigned int xpos) | |
| 1277 | 1282 | { |
| 1278 | 1283 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 1279 | 1284 | 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, · 5 unmodified lines | ||
| 1285 | 1290 | get_color(vc, info, scr_readw(s), 0)); |
| 1286 | 1291 | } |
| 1287 | 1292 | |
| 1288 | −static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) | |
| 1289 | −{ | |
| 1290 | − unsigned short chr; | |
| 1291 | − | |
| 1292 | − scr_writew(c, &chr); | |
| 1293 | − fbcon_putcs(vc, &chr, 1, ypos, xpos); | |
| 1294 | −} | |
| 1295 | − | |
| 1296 | 1293 | static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) |
| 1297 | 1294 | { |
| 1298 | 1295 | 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) · 3 unmodified lines | ||
| 1302 | 1299 | ops->clear_margins(vc, info, margin_color, bottom_only); |
| 1303 | 1300 | } |
| 1304 | 1301 | |
| 1305 | −static void fbcon_cursor(struct vc_data *vc, int mode) | |
| 1302 | +static void fbcon_cursor(struct vc_data *vc, bool enable) | |
| 1306 | 1303 | { |
| 1307 | 1304 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 1308 | 1305 | struct fbcon_ops *ops = info->fbcon_par; |
| @@ -1318,12 +1315,12 @@ static void fbcon_cursor(struct vc_data *vc, int mode) · 9 unmodified lines | ||
| 1318 | 1315 | else |
| 1319 | 1316 | fbcon_add_cursor_work(info); |
| 1320 | 1317 | |
| 1321 | − ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1; | |
| 1318 | + ops->cursor_flash = enable; | |
| 1322 | 1319 | |
| 1323 | 1320 | if (!ops->cursor) |
| 1324 | 1321 | return; |
| 1325 | 1322 | |
| 1326 | − ops->cursor(vc, info, mode, get_color(vc, info, c, 1), | |
| 1323 | + ops->cursor(vc, info, enable, get_color(vc, info, c, 1), | |
| 1327 | 1324 | get_color(vc, info, c, 0)); |
| 1328 | 1325 | } |
| 1329 | 1326 | |
| @@ -1743,7 +1740,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 413 unmodified lines | ||
| 1743 | 1740 | if (fbcon_is_inactive(vc, info)) |
| 1744 | 1741 | return true; |
| 1745 | 1742 | |
| 1746 | − fbcon_cursor(vc, CM_ERASE); | |
| 1743 | + fbcon_cursor(vc, false); | |
| 1747 | 1744 | |
| 1748 | 1745 | /* |
| 1749 | 1746 | * ++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, · 9 unmodified lines | ||
| 1759 | 1756 | case SCROLL_MOVE: |
| 1760 | 1757 | fbcon_redraw_blit(vc, info, p, t, b - t - count, |
| 1761 | 1758 | count); |
| 1762 | − fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1759 | + __fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1763 | 1760 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1764 | 1761 | vc->vc_size_row * |
| 1765 | 1762 | (b - count)), |
| @@ -1782,7 +1779,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 16 unmodified lines | ||
| 1782 | 1779 | b - t - count, vc->vc_cols); |
| 1783 | 1780 | else |
| 1784 | 1781 | goto redraw_up; |
| 1785 | − fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1782 | + __fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1786 | 1783 | break; |
| 1787 | 1784 | |
| 1788 | 1785 | case SCROLL_PAN_REDRAW: |
| @@ -1800,7 +1797,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 11 unmodified lines | ||
| 1800 | 1797 | vc->vc_rows - b, b); |
| 1801 | 1798 | } else |
| 1802 | 1799 | fbcon_redraw_move(vc, p, t + count, b - t - count, t); |
| 1803 | − fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1800 | + __fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1804 | 1801 | break; |
| 1805 | 1802 | |
| 1806 | 1803 | case SCROLL_PAN_MOVE: |
| @@ -1823,14 +1820,14 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 16 unmodified lines | ||
| 1823 | 1820 | b - t - count, vc->vc_cols); |
| 1824 | 1821 | else |
| 1825 | 1822 | goto redraw_up; |
| 1826 | − fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1823 | + __fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1827 | 1824 | break; |
| 1828 | 1825 | |
| 1829 | 1826 | case SCROLL_REDRAW: |
| 1830 | 1827 | redraw_up: |
| 1831 | 1828 | fbcon_redraw(vc, t, b - t - count, |
| 1832 | 1829 | count * vc->vc_cols); |
| 1833 | − fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1830 | + __fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1834 | 1831 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1835 | 1832 | vc->vc_size_row * |
| 1836 | 1833 | (b - count)), |
| @@ -1847,7 +1844,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 10 unmodified lines | ||
| 1847 | 1844 | case SCROLL_MOVE: |
| 1848 | 1845 | fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, |
| 1849 | 1846 | -count); |
| 1850 | − fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1847 | + __fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1851 | 1848 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1852 | 1849 | vc->vc_size_row * |
| 1853 | 1850 | t), |
| @@ -1870,7 +1867,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 16 unmodified lines | ||
| 1870 | 1867 | b - t - count, vc->vc_cols); |
| 1871 | 1868 | else |
| 1872 | 1869 | goto redraw_down; |
| 1873 | − fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1870 | + __fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1874 | 1871 | break; |
| 1875 | 1872 | |
| 1876 | 1873 | case SCROLL_PAN_MOVE: |
| @@ -1892,7 +1889,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 15 unmodified lines | ||
| 1892 | 1889 | b - t - count, vc->vc_cols); |
| 1893 | 1890 | else |
| 1894 | 1891 | goto redraw_down; |
| 1895 | − fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1892 | + __fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1896 | 1893 | break; |
| 1897 | 1894 | |
| 1898 | 1895 | case SCROLL_PAN_REDRAW: |
| @@ -1909,14 +1906,14 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 10 unmodified lines | ||
| 1909 | 1906 | fbcon_redraw_move(vc, p, count, t, 0); |
| 1910 | 1907 | } else |
| 1911 | 1908 | fbcon_redraw_move(vc, p, t, b - t - count, t + count); |
| 1912 | − fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1909 | + __fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1913 | 1910 | break; |
| 1914 | 1911 | |
| 1915 | 1912 | case SCROLL_REDRAW: |
| 1916 | 1913 | redraw_down: |
| 1917 | 1914 | fbcon_redraw(vc, b - 1, b - t - count, |
| 1918 | 1915 | -count * vc->vc_cols); |
| 1919 | − fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1916 | + __fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1920 | 1917 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1921 | 1918 | vc->vc_size_row * |
| 1922 | 1919 | t), |
| @@ -1995,7 +1992,7 @@ static void updatescrollmode(struct fbcon_display *p, · 72 unmodified lines | ||
| 1995 | 1992 | #define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */ |
| 1996 | 1993 | |
| 1997 | 1994 | static int fbcon_resize(struct vc_data *vc, unsigned int width, |
| 1998 | − unsigned int height, unsigned int user) | |
| 1995 | + unsigned int height, bool from_user) | |
| 1999 | 1996 | { |
| 2000 | 1997 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2001 | 1998 | struct fbcon_ops *ops = info->fbcon_par; |
| @@ -2058,7 +2055,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, · 56 unmodified lines | ||
| 2058 | 2055 | return 0; |
| 2059 | 2056 | } |
| 2060 | 2057 | |
| 2061 | −static int fbcon_switch(struct vc_data *vc) | |
| 2058 | +static bool fbcon_switch(struct vc_data *vc) | |
| 2062 | 2059 | { |
| 2063 | 2060 | struct fb_info *info, *old_info = NULL; |
| 2064 | 2061 | struct fbcon_ops *ops; |
| @@ -2180,9 +2177,9 @@ static int fbcon_switch(struct vc_data *vc) · 115 unmodified lines | ||
| 2180 | 2177 | vc->vc_origin + vc->vc_size_row * vc->vc_top, |
| 2181 | 2178 | vc->vc_size_row * (vc->vc_bottom - |
| 2182 | 2179 | vc->vc_top) / 2); |
| 2183 | − return 0; | |
| 2180 | + return false; | |
| 2184 | 2181 | } |
| 2185 | − return 1; | |
| 2182 | + return true; | |
| 2186 | 2183 | } |
| 2187 | 2184 | |
| 2188 | 2185 | 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, · 6 unmodified lines | ||
| 2195 | 2192 | |
| 2196 | 2193 | oldc = vc->vc_video_erase_char; |
| 2197 | 2194 | vc->vc_video_erase_char &= charmask; |
| 2198 | − fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols); | |
| 2195 | + __fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols); | |
| 2199 | 2196 | vc->vc_video_erase_char = oldc; |
| 2200 | 2197 | } |
| 2201 | 2198 | } |
| 2202 | 2199 | |
| 2203 | −static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) | |
| 2200 | +static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank, | |
| 2201 | + bool mode_switch) | |
| 2204 | 2202 | { |
| 2205 | 2203 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2206 | 2204 | struct fbcon_ops *ops = info->fbcon_par; |
| @@ -2222,7 +2220,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) · 15 unmodified lines | ||
| 2222 | 2220 | if (!fbcon_is_inactive(vc, info)) { |
| 2223 | 2221 | if (ops->blank_state != blank) { |
| 2224 | 2222 | ops->blank_state = blank; |
| 2225 | − fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); | |
| 2223 | + fbcon_cursor(vc, !blank); | |
| 2226 | 2224 | ops->cursor_flash = (!blank); |
| 2227 | 2225 | |
| 2228 | 2226 | if (fb_blank(info, blank)) |
| @@ -2239,10 +2237,10 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) · 10 unmodified lines | ||
| 2239 | 2237 | else |
| 2240 | 2238 | fbcon_add_cursor_work(info); |
| 2241 | 2239 | |
| 2242 | − return 0; | |
| 2240 | + return false; | |
| 2243 | 2241 | } |
| 2244 | 2242 | |
| 2245 | −static int fbcon_debug_enter(struct vc_data *vc) | |
| 2243 | +static void fbcon_debug_enter(struct vc_data *vc) | |
| 2246 | 2244 | { |
| 2247 | 2245 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2248 | 2246 | struct fbcon_ops *ops = info->fbcon_par; |
| @@ -2252,10 +2250,9 @@ static int fbcon_debug_enter(struct vc_data *vc) · 3 unmodified lines | ||
| 2252 | 2250 | if (info->fbops->fb_debug_enter) |
| 2253 | 2251 | info->fbops->fb_debug_enter(info); |
| 2254 | 2252 | fbcon_set_palette(vc, color_table); |
| 2255 | − return 0; | |
| 2256 | 2253 | } |
| 2257 | 2254 | |
| 2258 | −static int fbcon_debug_leave(struct vc_data *vc) | |
| 2255 | +static void fbcon_debug_leave(struct vc_data *vc) | |
| 2259 | 2256 | { |
| 2260 | 2257 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2261 | 2258 | struct fbcon_ops *ops = info->fbcon_par; |
| @@ -2263,7 +2260,6 @@ static int fbcon_debug_leave(struct vc_data *vc) · 1 unmodified line | ||
| 2263 | 2260 | ops->graphics = ops->save_graphics; |
| 2264 | 2261 | if (info->fbops->fb_debug_leave) |
| 2265 | 2262 | info->fbops->fb_debug_leave(info); |
| 2266 | − return 0; | |
| 2267 | 2263 | } |
| 2268 | 2264 | |
| 2269 | 2265 | static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch) |
| @@ -2461,7 +2457,7 @@ err_out: · 191 unmodified lines | ||
| 2461 | 2457 | * but lets not assume that, since charcount of 512 is small for unicode support. |
| 2462 | 2458 | */ |
| 2463 | 2459 | |
| 2464 | −static int fbcon_set_font(struct vc_data *vc, struct console_font *font, | |
| 2460 | +static int fbcon_set_font(struct vc_data *vc, const struct console_font *font, | |
| 2465 | 2461 | unsigned int vpitch, unsigned int flags) |
| 2466 | 2462 | { |
| 2467 | 2463 | 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, · 66 unmodified lines | ||
| 2534 | 2530 | return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1); |
| 2535 | 2531 | } |
| 2536 | 2532 | |
| 2537 | −static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name) | |
| 2533 | +static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, | |
| 2534 | + const char *name) | |
| 2538 | 2535 | { |
| 2539 | 2536 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2540 | 2537 | const struct font_desc *f; |
| @@ -2593,35 +2590,6 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table) · 52 unmodified lines | ||
| 2593 | 2590 | fb_set_cmap(&palette_cmap, info); |
| 2594 | 2591 | } |
| 2595 | 2592 | |
| 2596 | −static u16 *fbcon_screen_pos(const struct vc_data *vc, int offset) | |
| 2597 | −{ | |
| 2598 | − return (u16 *) (vc->vc_origin + offset); | |
| 2599 | −} | |
| 2600 | − | |
| 2601 | −static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos, | |
| 2602 | − int *px, int *py) | |
| 2603 | −{ | |
| 2604 | − unsigned long ret; | |
| 2605 | − int x, y; | |
| 2606 | − | |
| 2607 | − if (pos >= vc->vc_origin && pos < vc->vc_scr_end) { | |
| 2608 | − unsigned long offset = (pos - vc->vc_origin) / 2; | |
| 2609 | − | |
| 2610 | − x = offset % vc->vc_cols; | |
| 2611 | − y = offset / vc->vc_cols; | |
| 2612 | − ret = pos + (vc->vc_cols - x) * 2; | |
| 2613 | − } else { | |
| 2614 | − /* Should not happen */ | |
| 2615 | − x = y = 0; | |
| 2616 | − ret = vc->vc_origin; | |
| 2617 | − } | |
| 2618 | − if (px) | |
| 2619 | − *px = x; | |
| 2620 | − if (py) | |
| 2621 | − *py = y; | |
| 2622 | − return ret; | |
| 2623 | −} | |
| 2624 | − | |
| 2625 | 2593 | /* As we might be inside of softback, we may work with non-contiguous buffer, |
| 2626 | 2594 | that's why we have to use a separate routine. */ |
| 2627 | 2595 | static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) |
| @@ -2650,7 +2618,7 @@ void fbcon_suspended(struct fb_info *info) · 22 unmodified lines | ||
| 2650 | 2618 | vc = vc_cons[ops->currcon].d; |
| 2651 | 2619 | |
| 2652 | 2620 | /* Clear cursor, restore saved data */ |
| 2653 | − fbcon_cursor(vc, CM_ERASE); | |
| 2621 | + fbcon_cursor(vc, false); | |
| 2654 | 2622 | } |
| 2655 | 2623 | |
| 2656 | 2624 | void fbcon_resumed(struct fb_info *info) |
| @@ -3152,7 +3120,6 @@ static const struct consw fb_con = { · 495 unmodified lines | ||
| 3152 | 3120 | .con_init = fbcon_init, |
| 3153 | 3121 | .con_deinit = fbcon_deinit, |
| 3154 | 3122 | .con_clear = fbcon_clear, |
| 3155 | − .con_putc = fbcon_putc, | |
| 3156 | 3123 | .con_putcs = fbcon_putcs, |
| 3157 | 3124 | .con_cursor = fbcon_cursor, |
| 3158 | 3125 | .con_scroll = fbcon_scroll, |
| @@ -3163,8 +3130,6 @@ static const struct consw fb_con = { · 4 unmodified lines | ||
| 3163 | 3130 | .con_font_default = fbcon_set_def_font, |
| 3164 | 3131 | .con_set_palette = fbcon_set_palette, |
| 3165 | 3132 | .con_invert_region = fbcon_invert_region, |
| 3166 | − .con_screen_pos = fbcon_screen_pos, | |
| 3167 | − .con_getxy = fbcon_getxy, | |
| 3168 | 3133 | .con_resize = fbcon_resize, |
| 3169 | 3134 | .con_debug_enter = fbcon_debug_enter, |
| 3170 | 3135 | .con_debug_leave = fbcon_debug_leave, |
| @@ -61,8 +61,8 @@ struct fbcon_ops { · 60 unmodified lines | ||
| 61 | 61 | int fg, int bg); |
| 62 | 62 | void (*clear_margins)(struct vc_data *vc, struct fb_info *info, |
| 63 | 63 | int color, int bottom_only); |
| 64 | − void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode, | |
| 65 | − int fg, int bg); | |
| 64 | + void (*cursor)(struct vc_data *vc, struct fb_info *info, | |
| 65 | + bool enable, int fg, int bg); | |
| 66 | 66 | int (*update_start)(struct fb_info *info); |
| 67 | 67 | int (*rotate_font)(struct fb_info *info, struct vc_data *vc); |
| 68 | 68 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ |
| @@ -218,7 +218,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, · 217 unmodified lines | ||
| 218 | 218 | } |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | −static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, | |
| 221 | +static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, | |
| 222 | 222 | int fg, int bg) |
| 223 | 223 | { |
| 224 | 224 | struct fb_cursor cursor; |
| @@ -349,16 +349,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 124 unmodified lines | ||
| 349 | 349 | kfree(tmp); |
| 350 | 350 | } |
| 351 | 351 | |
| 352 | − switch (mode) { | |
| 353 | − case CM_ERASE: | |
| 354 | − ops->cursor_state.enable = 0; | |
| 355 | − break; | |
| 356 | − case CM_DRAW: | |
| 357 | − case CM_MOVE: | |
| 358 | − default: | |
| 359 | − ops->cursor_state.enable = (use_sw) ? 0 : 1; | |
| 360 | − break; | |
| 361 | − } | |
| 352 | + ops->cursor_state.enable = enable && !use_sw; | |
| 362 | 353 | |
| 363 | 354 | cursor.image.data = src; |
| 364 | 355 | cursor.image.fg_color = ops->cursor_state.image.fg_color; |
| @@ -201,7 +201,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, · 200 unmodified lines | ||
| 201 | 201 | } |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | −static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, | |
| 204 | +static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, | |
| 205 | 205 | int fg, int bg) |
| 206 | 206 | { |
| 207 | 207 | struct fb_cursor cursor; |
| @@ -332,16 +332,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 124 unmodified lines | ||
| 332 | 332 | kfree(tmp); |
| 333 | 333 | } |
| 334 | 334 | |
| 335 | − switch (mode) { | |
| 336 | − case CM_ERASE: | |
| 337 | − ops->cursor_state.enable = 0; | |
| 338 | − break; | |
| 339 | − case CM_DRAW: | |
| 340 | − case CM_MOVE: | |
| 341 | − default: | |
| 342 | − ops->cursor_state.enable = (use_sw) ? 0 : 1; | |
| 343 | − break; | |
| 344 | − } | |
| 335 | + ops->cursor_state.enable = enable && !use_sw; | |
| 345 | 336 | |
| 346 | 337 | cursor.image.data = src; |
| 347 | 338 | cursor.image.fg_color = ops->cursor_state.image.fg_color; |
| @@ -248,7 +248,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, · 247 unmodified lines | ||
| 248 | 248 | } |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | −static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, | |
| 251 | +static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable, | |
| 252 | 252 | int fg, int bg) |
| 253 | 253 | { |
| 254 | 254 | struct fb_cursor cursor; |
| @@ -372,16 +372,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 117 unmodified lines | ||
| 372 | 372 | mask[i++] = ~msk; |
| 373 | 373 | } |
| 374 | 374 | |
| 375 | − switch (mode) { | |
| 376 | − case CM_ERASE: | |
| 377 | − ops->cursor_state.enable = 0; | |
| 378 | − break; | |
| 379 | − case CM_DRAW: | |
| 380 | − case CM_MOVE: | |
| 381 | − default: | |
| 382 | − ops->cursor_state.enable = (use_sw) ? 0 : 1; | |
| 383 | − break; | |
| 384 | − } | |
| 375 | + ops->cursor_state.enable = enable && !use_sw; | |
| 385 | 376 | |
| 386 | 377 | cursor.image.data = src; |
| 387 | 378 | cursor.image.fg_color = ops->cursor_state.image.fg_color; |
| @@ -79,7 +79,7 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info, · 78 unmodified lines | ||
| 79 | 79 | return; |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | −static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, | |
| 82 | +static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable, | |
| 83 | 83 | int fg, int bg) |
| 84 | 84 | { |
| 85 | 85 | struct fb_tilecursor cursor; |
| @@ -87,7 +87,7 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 1 unmodified line | ||
| 87 | 87 | |
| 88 | 88 | cursor.sx = vc->state.x; |
| 89 | 89 | cursor.sy = vc->state.y; |
| 90 | − cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1; | |
| 90 | + cursor.mode = enable && !use_sw; | |
| 91 | 91 | cursor.fg = fg; |
| 92 | 92 | cursor.bg = bg; |
| 93 | 93 | |
| @@ -380,7 +380,7 @@ tgafb_set_par(struct fb_info *info) · 379 unmodified lines | ||
| 380 | 380 | BT463_LOAD_ADDR(par, 0x0000); |
| 381 | 381 | TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG); |
| 382 | 382 | |
| 383 | −#ifdef CONFIG_HW_CONSOLE | |
| 383 | +#ifdef CONFIG_VT | |
| 384 | 384 | for (i = 0; i < 16; i++) { |
| 385 | 385 | int j = color_table[i]; |
| 386 | 386 | |
| @@ -78,5 +78,15 @@ config W1_MASTER_SGI · 77 unmodified lines | ||
| 78 | 78 | This support is also available as a module. If so, the module |
| 79 | 79 | will be called sgi_w1. |
| 80 | 80 | |
| 81 | +config W1_MASTER_UART | |
| 82 | + tristate "UART 1-wire driver" | |
| 83 | + depends on SERIAL_DEV_BUS | |
| 84 | + help | |
| 85 | + Say Y here if you want to communicate with your 1-wire devices using | |
| 86 | + UART interface. | |
| 87 | + | |
| 88 | + This support is also available as a module. If so, the module | |
| 89 | + will be called w1-uart. | |
| 90 | + | |
| 81 | 91 | endmenu |
| 82 | 92 | |
| @@ -12,3 +12,4 @@ obj-$(CONFIG_W1_MASTER_MXC) += mxc_w1.o · 11 unmodified lines | ||
| 12 | 12 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o |
| 13 | 13 | obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o |
| 14 | 14 | obj-$(CONFIG_W1_MASTER_SGI) += sgi_w1.o |
| 15 | +obj-$(CONFIG_W1_MASTER_UART) += w1-uart.o | |
| @@ -151,15 +151,13 @@ out_disable_clk: · 150 unmodified lines | ||
| 151 | 151 | /* |
| 152 | 152 | * disassociate the w1 device from the driver |
| 153 | 153 | */ |
| 154 | −static int mxc_w1_remove(struct platform_device *pdev) | |
| 154 | +static void mxc_w1_remove(struct platform_device *pdev) | |
| 155 | 155 | { |
| 156 | 156 | struct mxc_w1_device *mdev = platform_get_drvdata(pdev); |
| 157 | 157 | |
| 158 | 158 | w1_remove_master_device(&mdev->bus_master); |
| 159 | 159 | |
| 160 | 160 | clk_disable_unprepare(mdev->clk); |
| 161 | − | |
| 162 | − return 0; | |
| 163 | 161 | } |
| 164 | 162 | |
| 165 | 163 | static const struct of_device_id mxc_w1_dt_ids[] = { |
| @@ -174,7 +172,7 @@ static struct platform_driver mxc_w1_driver = { · 8 unmodified lines | ||
| 174 | 172 | .of_match_table = mxc_w1_dt_ids, |
| 175 | 173 | }, |
| 176 | 174 | .probe = mxc_w1_probe, |
| 177 | − .remove = mxc_w1_remove, | |
| 175 | + .remove_new = mxc_w1_remove, | |
| 178 | 176 | }; |
| 179 | 177 | module_platform_driver(mxc_w1_driver); |
| 180 | 178 | |
| @@ -647,7 +647,7 @@ err_w1: · 646 unmodified lines | ||
| 647 | 647 | return ret; |
| 648 | 648 | } |
| 649 | 649 | |
| 650 | −static int omap_hdq_remove(struct platform_device *pdev) | |
| 650 | +static void omap_hdq_remove(struct platform_device *pdev) | |
| 651 | 651 | { |
| 652 | 652 | int active; |
| 653 | 653 | |
| @@ -661,8 +661,6 @@ static int omap_hdq_remove(struct platform_device *pdev) · 7 unmodified lines | ||
| 661 | 661 | if (active >= 0) |
| 662 | 662 | pm_runtime_put_sync(&pdev->dev); |
| 663 | 663 | pm_runtime_disable(&pdev->dev); |
| 664 | − | |
| 665 | − return 0; | |
| 666 | 664 | } |
| 667 | 665 | |
| 668 | 666 | static const struct of_device_id omap_hdq_dt_ids[] = { |
| @@ -674,7 +672,7 @@ MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids); · 5 unmodified lines | ||
| 674 | 672 | |
| 675 | 673 | static struct platform_driver omap_hdq_driver = { |
| 676 | 674 | .probe = omap_hdq_probe, |
| 677 | − .remove = omap_hdq_remove, | |
| 675 | + .remove_new = omap_hdq_remove, | |
| 678 | 676 | .driver = { |
| 679 | 677 | .name = "omap_hdq", |
| 680 | 678 | .of_match_table = omap_hdq_dt_ids, |
| @@ -105,13 +105,11 @@ static int sgi_w1_probe(struct platform_device *pdev) · 104 unmodified lines | ||
| 105 | 105 | /* |
| 106 | 106 | * disassociate the w1 device from the driver |
| 107 | 107 | */ |
| 108 | −static int sgi_w1_remove(struct platform_device *pdev) | |
| 108 | +static void sgi_w1_remove(struct platform_device *pdev) | |
| 109 | 109 | { |
| 110 | 110 | struct sgi_w1_device *sdev = platform_get_drvdata(pdev); |
| 111 | 111 | |
| 112 | 112 | w1_remove_master_device(&sdev->bus_master); |
| 113 | − | |
| 114 | − return 0; | |
| 115 | 113 | } |
| 116 | 114 | |
| 117 | 115 | static struct platform_driver sgi_w1_driver = { |
| @@ -119,7 +117,7 @@ static struct platform_driver sgi_w1_driver = { · 1 unmodified line | ||
| 119 | 117 | .name = "sgi_w1", |
| 120 | 118 | }, |
| 121 | 119 | .probe = sgi_w1_probe, |
| 122 | − .remove = sgi_w1_remove, | |
| 120 | + .remove_new = sgi_w1_remove, | |
| 123 | 121 | }; |
| 124 | 122 | module_platform_driver(sgi_w1_driver); |
| 125 | 123 | |
| @@ -141,7 +141,7 @@ static int w1_gpio_probe(struct platform_device *pdev) · 140 unmodified lines | ||
| 141 | 141 | return 0; |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | −static int w1_gpio_remove(struct platform_device *pdev) | |
| 144 | +static void w1_gpio_remove(struct platform_device *pdev) | |
| 145 | 145 | { |
| 146 | 146 | struct w1_bus_master *master = platform_get_drvdata(pdev); |
| 147 | 147 | struct w1_gpio_ddata *ddata = master->data; |
| @@ -150,8 +150,6 @@ static int w1_gpio_remove(struct platform_device *pdev) · 2 unmodified lines | ||
| 150 | 150 | gpiod_set_value(ddata->pullup_gpiod, 0); |
| 151 | 151 | |
| 152 | 152 | w1_remove_master_device(master); |
| 153 | − | |
| 154 | − return 0; | |
| 155 | 153 | } |
| 156 | 154 | |
| 157 | 155 | static struct platform_driver w1_gpio_driver = { |
| @@ -160,7 +158,7 @@ static struct platform_driver w1_gpio_driver = { · 2 unmodified lines | ||
| 160 | 158 | .of_match_table = of_match_ptr(w1_gpio_dt_ids), |
| 161 | 159 | }, |
| 162 | 160 | .probe = w1_gpio_probe, |
| 163 | − .remove = w1_gpio_remove, | |
| 161 | + .remove_new = w1_gpio_remove, | |
| 164 | 162 | }; |
| 165 | 163 | |
| 166 | 164 | module_platform_driver(w1_gpio_driver); |
| @@ -0,0 +1,415 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | +/* | |
| 3 | + * w1-uart - UART 1-Wire bus driver | |
| 4 | + * | |
| 5 | + * Uses the UART interface (via Serial Device Bus) to create the 1-Wire | |
| 6 | + * timing patterns. Implements the following 1-Wire master interface: | |
| 7 | + * | |
| 8 | + * - reset_bus: requests baud-rate 9600 | |
| 9 | + * | |
| 10 | + * - touch_bit: requests baud-rate 115200 | |
| 11 | + * | |
| 12 | + * Author: Christoph Winklhofer <cj.winklhofer@gmail.com> | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#include <linux/completion.h> | |
| 16 | +#include <linux/delay.h> | |
| 17 | +#include <linux/jiffies.h> | |
| 18 | +#include <linux/module.h> | |
| 19 | +#include <linux/mutex.h> | |
| 20 | +#include <linux/of.h> | |
| 21 | +#include <linux/serdev.h> | |
| 22 | +#include <linux/w1.h> | |
| 23 | + | |
| 24 | +/* UART packet contains start and stop bit */ | |
| 25 | +#define W1_UART_BITS_PER_PACKET (BITS_PER_BYTE + 2) | |
| 26 | + | |
| 27 | +/* Timeout to wait for completion of serdev-receive */ | |
| 28 | +#define W1_UART_TIMEOUT msecs_to_jiffies(500) | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * struct w1_uart_config - configuration for 1-Wire operation | |
| 32 | + * @baudrate: baud-rate returned from serdev | |
| 33 | + * @delay_us: delay to complete a 1-Wire cycle (in us) | |
| 34 | + * @tx_byte: byte to generate 1-Wire timing pattern | |
| 35 | + */ | |
| 36 | +struct w1_uart_config { | |
| 37 | + unsigned int baudrate; | |
| 38 | + unsigned int delay_us; | |
| 39 | + u8 tx_byte; | |
| 40 | +}; | |
| 41 | + | |
| 42 | +/** | |
| 43 | + * struct w1_uart_device - 1-Wire UART device structure | |
| 44 | + * @serdev: serial device | |
| 45 | + * @bus: w1-bus master | |
| 46 | + * @cfg_reset: config for 1-Wire reset | |
| 47 | + * @cfg_touch_0: config for 1-Wire write-0 cycle | |
| 48 | + * @cfg_touch_1: config for 1-Wire write-1 and read cycle | |
| 49 | + * @rx_byte_received: completion for serdev receive | |
| 50 | + * @rx_mutex: mutex to protect rx_err and rx_byte | |
| 51 | + * @rx_err: indicates an error in serdev-receive | |
| 52 | + * @rx_byte: result byte from serdev-receive | |
| 53 | + */ | |
| 54 | +struct w1_uart_device { | |
| 55 | + struct serdev_device *serdev; | |
| 56 | + struct w1_bus_master bus; | |
| 57 | + | |
| 58 | + struct w1_uart_config cfg_reset; | |
| 59 | + struct w1_uart_config cfg_touch_0; | |
| 60 | + struct w1_uart_config cfg_touch_1; | |
| 61 | + | |
| 62 | + struct completion rx_byte_received; | |
| 63 | + /* | |
| 64 | + * protect rx_err and rx_byte from concurrent access in | |
| 65 | + * w1-callbacks and serdev-receive. | |
| 66 | + */ | |
| 67 | + struct mutex rx_mutex; | |
| 68 | + int rx_err; | |
| 69 | + u8 rx_byte; | |
| 70 | +}; | |
| 71 | + | |
| 72 | +/** | |
| 73 | + * struct w1_uart_limits - limits for 1-Wire operations | |
| 74 | + * @baudrate: Requested baud-rate to create 1-Wire timing pattern | |
| 75 | + * @bit_min_us: minimum time for a bit (in us) | |
| 76 | + * @bit_max_us: maximum time for a bit (in us) | |
| 77 | + * @sample_us: timespan to sample 1-Wire response | |
| 78 | + * @cycle_us: duration of the 1-Wire cycle | |
| 79 | + */ | |
| 80 | +struct w1_uart_limits { | |
| 81 | + unsigned int baudrate; | |
| 82 | + unsigned int bit_min_us; | |
| 83 | + unsigned int bit_max_us; | |
| 84 | + unsigned int sample_us; | |
| 85 | + unsigned int cycle_us; | |
| 86 | +}; | |
| 87 | + | |
| 88 | +static inline unsigned int baud_to_bit_ns(unsigned int baud) | |
| 89 | +{ | |
| 90 | + return NSEC_PER_SEC / baud; | |
| 91 | +} | |
| 92 | + | |
| 93 | +static inline unsigned int to_ns(unsigned int us) | |
| 94 | +{ | |
| 95 | + return us * NSEC_PER_USEC; | |
| 96 | +} | |
| 97 | + | |
| 98 | +/* | |
| 99 | + * Set baud-rate, delay and tx-byte to create a 1-Wire pulse and adapt | |
| 100 | + * the tx-byte according to the actual baud-rate. | |
| 101 | + * | |
| 102 | + * Reject when: | |
| 103 | + * - time for a bit outside min/max range | |
| 104 | + * - a 1-Wire response is not detectable for sent byte | |
| 105 | + */ | |
| 106 | +static int w1_uart_set_config(struct serdev_device *serdev, | |
| 107 | + const struct w1_uart_limits *limits, | |
| 108 | + struct w1_uart_config *w1cfg) | |
| 109 | +{ | |
| 110 | + unsigned int packet_ns; | |
| 111 | + unsigned int bits_low; | |
| 112 | + unsigned int bit_ns; | |
| 113 | + unsigned int low_ns; | |
| 114 | + | |
| 115 | + w1cfg->baudrate = serdev_device_set_baudrate(serdev, limits->baudrate); | |
| 116 | + if (w1cfg->baudrate == 0) | |
| 117 | + return -EINVAL; | |
| 118 | + | |
| 119 | + /* Compute in nanoseconds for accuracy */ | |
| 120 | + bit_ns = baud_to_bit_ns(w1cfg->baudrate); | |
| 121 | + bits_low = to_ns(limits->bit_min_us) / bit_ns; | |
| 122 | + /* start bit is always low */ | |
| 123 | + low_ns = bit_ns * (bits_low + 1); | |
| 124 | + | |
| 125 | + if (low_ns < to_ns(limits->bit_min_us)) | |
| 126 | + return -EINVAL; | |
| 127 | + | |
| 128 | + if (low_ns > to_ns(limits->bit_max_us)) | |
| 129 | + return -EINVAL; | |
| 130 | + | |
| 131 | + /* 1-Wire response detectable for sent byte */ | |
| 132 | + if (limits->sample_us > 0 && | |
| 133 | + bit_ns * BITS_PER_BYTE < low_ns + to_ns(limits->sample_us)) | |
| 134 | + return -EINVAL; | |
| 135 | + | |
| 136 | + /* delay: 1-Wire cycle takes longer than the UART packet */ | |
| 137 | + packet_ns = bit_ns * W1_UART_BITS_PER_PACKET; | |
| 138 | + w1cfg->delay_us = 0; | |
| 139 | + if (to_ns(limits->cycle_us) > packet_ns) | |
| 140 | + w1cfg->delay_us = | |
| 141 | + (to_ns(limits->cycle_us) - packet_ns) / NSEC_PER_USEC; | |
| 142 | + | |
| 143 | + /* byte to create 1-Wire pulse */ | |
| 144 | + w1cfg->tx_byte = 0xff << bits_low; | |
| 145 | + | |
| 146 | + return 0; | |
| 147 | +} | |
| 148 | + | |
| 149 | +/* | |
| 150 | + * Configuration for reset and presence detect | |
| 151 | + * - bit_min_us is 480us, add margin and use 485us | |
| 152 | + * - limits for sample time 60us-75us, use 65us | |
| 153 | + */ | |
| 154 | +static int w1_uart_set_config_reset(struct w1_uart_device *w1dev) | |
| 155 | +{ | |
| 156 | + struct serdev_device *serdev = w1dev->serdev; | |
| 157 | + struct device_node *np = serdev->dev.of_node; | |
| 158 | + | |
| 159 | + struct w1_uart_limits limits = { .baudrate = 9600, | |
| 160 | + .bit_min_us = 485, | |
| 161 | + .bit_max_us = 640, | |
| 162 | + .sample_us = 65, | |
| 163 | + .cycle_us = 960 }; | |
| 164 | + | |
| 165 | + of_property_read_u32(np, "reset-bps", &limits.baudrate); | |
| 166 | + | |
| 167 | + return w1_uart_set_config(serdev, &limits, &w1dev->cfg_reset); | |
| 168 | +} | |
| 169 | + | |
| 170 | +/* | |
| 171 | + * Configuration for write-0 cycle (touch bit 0) | |
| 172 | + * - bit_min_us is 60us, add margin and use 65us | |
| 173 | + * - no sampling required, sample_us = 0 | |
| 174 | + */ | |
| 175 | +static int w1_uart_set_config_touch_0(struct w1_uart_device *w1dev) | |
| 176 | +{ | |
| 177 | + struct serdev_device *serdev = w1dev->serdev; | |
| 178 | + struct device_node *np = serdev->dev.of_node; | |
| 179 | + | |
| 180 | + struct w1_uart_limits limits = { .baudrate = 115200, | |
| 181 | + .bit_min_us = 65, | |
| 182 | + .bit_max_us = 120, | |
| 183 | + .sample_us = 0, | |
| 184 | + .cycle_us = 70 }; | |
| 185 | + | |
| 186 | + of_property_read_u32(np, "write-0-bps", &limits.baudrate); | |
| 187 | + | |
| 188 | + return w1_uart_set_config(serdev, &limits, &w1dev->cfg_touch_0); | |
| 189 | +} | |
| 190 | + | |
| 191 | +/* | |
| 192 | + * Configuration for write-1 and read cycle (touch bit 1) | |
| 193 | + * - bit_min_us is 5us, add margin and use 6us | |
| 194 | + * - limits for sample time 5us-15us, use 15us | |
| 195 | + */ | |
| 196 | +static int w1_uart_set_config_touch_1(struct w1_uart_device *w1dev) | |
| 197 | +{ | |
| 198 | + struct serdev_device *serdev = w1dev->serdev; | |
| 199 | + struct device_node *np = serdev->dev.of_node; | |
| 200 | + | |
| 201 | + struct w1_uart_limits limits = { .baudrate = 115200, | |
| 202 | + .bit_min_us = 6, | |
| 203 | + .bit_max_us = 15, | |
| 204 | + .sample_us = 15, | |
| 205 | + .cycle_us = 70 }; | |
| 206 | + | |
| 207 | + of_property_read_u32(np, "write-1-bps", &limits.baudrate); | |
| 208 | + | |
| 209 | + return w1_uart_set_config(serdev, &limits, &w1dev->cfg_touch_1); | |
| 210 | +} | |
| 211 | + | |
| 212 | +/* | |
| 213 | + * Configure and open the serial device | |
| 214 | + */ | |
| 215 | +static int w1_uart_serdev_open(struct w1_uart_device *w1dev) | |
| 216 | +{ | |
| 217 | + struct serdev_device *serdev = w1dev->serdev; | |
| 218 | + struct device *dev = &serdev->dev; | |
| 219 | + int ret; | |
| 220 | + | |
| 221 | + ret = devm_serdev_device_open(dev, serdev); | |
| 222 | + if (ret < 0) | |
| 223 | + return ret; | |
| 224 | + | |
| 225 | + ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); | |
| 226 | + if (ret < 0) { | |
| 227 | + dev_err(dev, "set parity failed\n"); | |
| 228 | + return ret; | |
| 229 | + } | |
| 230 | + | |
| 231 | + ret = w1_uart_set_config_reset(w1dev); | |
| 232 | + if (ret < 0) { | |
| 233 | + dev_err(dev, "config for reset failed\n"); | |
| 234 | + return ret; | |
| 235 | + } | |
| 236 | + | |
| 237 | + ret = w1_uart_set_config_touch_0(w1dev); | |
| 238 | + if (ret < 0) { | |
| 239 | + dev_err(dev, "config for touch-0 failed\n"); | |
| 240 | + return ret; | |
| 241 | + } | |
| 242 | + | |
| 243 | + ret = w1_uart_set_config_touch_1(w1dev); | |
| 244 | + if (ret < 0) { | |
| 245 | + dev_err(dev, "config for touch-1 failed\n"); | |
| 246 | + return ret; | |
| 247 | + } | |
| 248 | + | |
| 249 | + serdev_device_set_flow_control(serdev, false); | |
| 250 | + | |
| 251 | + return 0; | |
| 252 | +} | |
| 253 | + | |
| 254 | +/* | |
| 255 | + * Send one byte (tx_byte) and read one byte (rx_byte) via serdev. | |
| 256 | + */ | |
| 257 | +static int w1_uart_serdev_tx_rx(struct w1_uart_device *w1dev, | |
| 258 | + const struct w1_uart_config *w1cfg, u8 *rx_byte) | |
| 259 | +{ | |
| 260 | + struct serdev_device *serdev = w1dev->serdev; | |
| 261 | + int ret; | |
| 262 | + | |
| 263 | + serdev_device_write_flush(serdev); | |
| 264 | + serdev_device_set_baudrate(serdev, w1cfg->baudrate); | |
| 265 | + | |
| 266 | + /* write and immediately read one byte */ | |
| 267 | + reinit_completion(&w1dev->rx_byte_received); | |
| 268 | + ret = serdev_device_write_buf(serdev, &w1cfg->tx_byte, 1); | |
| 269 | + if (ret != 1) | |
| 270 | + return -EIO; | |
| 271 | + ret = wait_for_completion_interruptible_timeout( | |
| 272 | + &w1dev->rx_byte_received, W1_UART_TIMEOUT); | |
| 273 | + if (ret <= 0) | |
| 274 | + return -EIO; | |
| 275 | + | |
| 276 | + /* locking could fail when serdev is unexpectedly receiving. */ | |
| 277 | + if (!mutex_trylock(&w1dev->rx_mutex)) | |
| 278 | + return -EIO; | |
| 279 | + | |
| 280 | + ret = w1dev->rx_err; | |
| 281 | + if (ret == 0) | |
| 282 | + *rx_byte = w1dev->rx_byte; | |
| 283 | + | |
| 284 | + mutex_unlock(&w1dev->rx_mutex); | |
| 285 | + | |
| 286 | + if (w1cfg->delay_us > 0) | |
| 287 | + fsleep(w1cfg->delay_us); | |
| 288 | + | |
| 289 | + return ret; | |
| 290 | +} | |
| 291 | + | |
| 292 | +static size_t w1_uart_serdev_receive_buf(struct serdev_device *serdev, | |
| 293 | + const u8 *buf, size_t count) | |
| 294 | +{ | |
| 295 | + struct w1_uart_device *w1dev = serdev_device_get_drvdata(serdev); | |
| 296 | + | |
| 297 | + mutex_lock(&w1dev->rx_mutex); | |
| 298 | + | |
| 299 | + /* sent a single byte and receive one single byte */ | |
| 300 | + if (count == 1) { | |
| 301 | + w1dev->rx_byte = buf[0]; | |
| 302 | + w1dev->rx_err = 0; | |
| 303 | + } else { | |
| 304 | + w1dev->rx_err = -EIO; | |
| 305 | + } | |
| 306 | + | |
| 307 | + mutex_unlock(&w1dev->rx_mutex); | |
| 308 | + complete(&w1dev->rx_byte_received); | |
| 309 | + | |
| 310 | + return count; | |
| 311 | +} | |
| 312 | + | |
| 313 | +static const struct serdev_device_ops w1_uart_serdev_ops = { | |
| 314 | + .receive_buf = w1_uart_serdev_receive_buf, | |
| 315 | + .write_wakeup = serdev_device_write_wakeup, | |
| 316 | +}; | |
| 317 | + | |
| 318 | +/* | |
| 319 | + * 1-wire reset and presence detect: A present slave will manipulate | |
| 320 | + * the received byte by pulling the 1-Wire low. | |
| 321 | + */ | |
| 322 | +static u8 w1_uart_reset_bus(void *data) | |
| 323 | +{ | |
| 324 | + struct w1_uart_device *w1dev = data; | |
| 325 | + const struct w1_uart_config *w1cfg = &w1dev->cfg_reset; | |
| 326 | + int ret; | |
| 327 | + u8 val; | |
| 328 | + | |
| 329 | + ret = w1_uart_serdev_tx_rx(w1dev, w1cfg, &val); | |
| 330 | + if (ret < 0) | |
| 331 | + return -1; | |
| 332 | + | |
| 333 | + /* Device present (0) or no device (1) */ | |
| 334 | + return val != w1cfg->tx_byte ? 0 : 1; | |
| 335 | +} | |
| 336 | + | |
| 337 | +/* | |
| 338 | + * 1-Wire read and write cycle: Only the read-0 manipulates the | |
| 339 | + * received byte, all others left the line untouched. | |
| 340 | + */ | |
| 341 | +static u8 w1_uart_touch_bit(void *data, u8 bit) | |
| 342 | +{ | |
| 343 | + struct w1_uart_device *w1dev = data; | |
| 344 | + const struct w1_uart_config *w1cfg = bit ? &w1dev->cfg_touch_1 : | |
| 345 | + &w1dev->cfg_touch_0; | |
| 346 | + int ret; | |
| 347 | + u8 val; | |
| 348 | + | |
| 349 | + ret = w1_uart_serdev_tx_rx(w1dev, w1cfg, &val); | |
| 350 | + | |
| 351 | + /* return inactive bus state on error */ | |
| 352 | + if (ret < 0) | |
| 353 | + return 1; | |
| 354 | + | |
| 355 | + return val == w1cfg->tx_byte ? 1 : 0; | |
| 356 | +} | |
| 357 | + | |
| 358 | +static int w1_uart_probe(struct serdev_device *serdev) | |
| 359 | +{ | |
| 360 | + struct device *dev = &serdev->dev; | |
| 361 | + struct w1_uart_device *w1dev; | |
| 362 | + int ret; | |
| 363 | + | |
| 364 | + w1dev = devm_kzalloc(dev, sizeof(*w1dev), GFP_KERNEL); | |
| 365 | + if (!w1dev) | |
| 366 | + return -ENOMEM; | |
| 367 | + w1dev->bus.data = w1dev; | |
| 368 | + w1dev->bus.reset_bus = w1_uart_reset_bus; | |
| 369 | + w1dev->bus.touch_bit = w1_uart_touch_bit; | |
| 370 | + w1dev->serdev = serdev; | |
| 371 | + | |
| 372 | + init_completion(&w1dev->rx_byte_received); | |
| 373 | + mutex_init(&w1dev->rx_mutex); | |
| 374 | + | |
| 375 | + ret = w1_uart_serdev_open(w1dev); | |
| 376 | + if (ret < 0) | |
| 377 | + return ret; | |
| 378 | + serdev_device_set_drvdata(serdev, w1dev); | |
| 379 | + serdev_device_set_client_ops(serdev, &w1_uart_serdev_ops); | |
| 380 | + | |
| 381 | + return w1_add_master_device(&w1dev->bus); | |
| 382 | +} | |
| 383 | + | |
| 384 | +static void w1_uart_remove(struct serdev_device *serdev) | |
| 385 | +{ | |
| 386 | + struct w1_uart_device *w1dev = serdev_device_get_drvdata(serdev); | |
| 387 | + | |
| 388 | + /* | |
| 389 | + * Waits until w1-uart callbacks are finished, serdev is closed | |
| 390 | + * and its device data released automatically by devres (waits | |
| 391 | + * until serdev-receive is finished). | |
| 392 | + */ | |
| 393 | + w1_remove_master_device(&w1dev->bus); | |
| 394 | +} | |
| 395 | + | |
| 396 | +static const struct of_device_id w1_uart_of_match[] = { | |
| 397 | + { .compatible = "w1-uart" }, | |
| 398 | + {}, | |
| 399 | +}; | |
| 400 | +MODULE_DEVICE_TABLE(of, w1_uart_of_match); | |
| 401 | + | |
| 402 | +static struct serdev_device_driver w1_uart_driver = { | |
| 403 | + .driver = { | |
| 404 | + .name = "w1-uart", | |
| 405 | + .of_match_table = w1_uart_of_match, | |
| 406 | + }, | |
| 407 | + .probe = w1_uart_probe, | |
| 408 | + .remove = w1_uart_remove, | |
| 409 | +}; | |
| 410 | + | |
| 411 | +module_serdev_device_driver(w1_uart_driver); | |
| 412 | + | |
| 413 | +MODULE_DESCRIPTION("UART w1 bus driver"); | |
| 414 | +MODULE_AUTHOR("Christoph Winklhofer <cj.winklhofer@gmail.com>"); | |
| 415 | +MODULE_LICENSE("GPL"); | |
| @@ -167,7 +167,7 @@ static struct w1_family w1_default_family = { · 166 unmodified lines | ||
| 167 | 167 | |
| 168 | 168 | static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env); |
| 169 | 169 | |
| 170 | −static struct bus_type w1_bus_type = { | |
| 170 | +static const struct bus_type w1_bus_type = { | |
| 171 | 171 | .name = "w1", |
| 172 | 172 | .uevent = w1_uevent, |
| 173 | 173 | }; |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/bits.h> |
| 19 | 19 | #include <linux/rculist.h> |
| 20 | 20 | #include <linux/types.h> |
| 21 | +#include <linux/vesa.h> | |
| 21 | 22 | |
| 22 | 23 | struct vc_data; |
| 23 | 24 | struct console_font_op; |
| @@ -36,63 +37,91 @@ enum vc_intensity; · 12 unmodified lines | ||
| 36 | 37 | /** |
| 37 | 38 | * struct consw - callbacks for consoles |
| 38 | 39 | * |
| 40 | + * @owner: the module to get references of when this console is used | |
| 41 | + * @con_startup: set up the console and return its name (like VGA, EGA, ...) | |
| 42 | + * @con_init: initialize the console on @vc. @init is true for the very first | |
| 43 | + * call on this @vc. | |
| 44 | + * @con_deinit: deinitialize the console from @vc. | |
| 45 | + * @con_clear: erase @count characters at [@x, @y] on @vc. @count >= 1. | |
| 46 | + * @con_putc: emit one character with attributes @ca to [@x, @y] on @vc. | |
| 47 | + * (optional -- @con_putcs would be called instead) | |
| 48 | + * @con_putcs: emit @count characters with attributes @s to [@x, @y] on @vc. | |
| 49 | + * @con_cursor: enable/disable cursor depending on @enable | |
| 39 | 50 | * @con_scroll: move lines from @top to @bottom in direction @dir by @lines. |
| 40 | 51 | * Return true if no generic handling should be done. |
| 41 | 52 | * Invoked by csi_M and printing to the console. |
| 42 | − * @con_set_palette: sets the palette of the console to @table (optional) | |
| 53 | + * @con_switch: notifier about the console switch; it is supposed to return | |
| 54 | + * true if a redraw is needed. | |
| 55 | + * @con_blank: blank/unblank the console. The target mode is passed in @blank. | |
| 56 | + * @mode_switch is set if changing from/to text/graphics. The hook | |
| 57 | + * is supposed to return true if a redraw is needed. | |
| 58 | + * @con_font_set: set console @vc font to @font with height @vpitch. @flags can | |
| 59 | + * be %KD_FONT_FLAG_DONT_RECALC. (optional) | |
| 60 | + * @con_font_get: fetch the current font on @vc of height @vpitch into @font. | |
| 61 | + * (optional) | |
| 62 | + * @con_font_default: set default font on @vc. @name can be %NULL or font name | |
| 63 | + * to search for. @font can be filled back. (optional) | |
| 64 | + * @con_resize: resize the @vc console to @width x @height. @from_user is true | |
| 65 | + * when this change comes from the user space. | |
| 66 | + * @con_set_palette: sets the palette of the console @vc to @table (optional) | |
| 43 | 67 | * @con_scrolldelta: the contents of the console should be scrolled by @lines. |
| 44 | 68 | * Invoked by user. (optional) |
| 69 | + * @con_set_origin: set origin (see &vc_data::vc_origin) of the @vc. If not | |
| 70 | + * provided or returns false, the origin is set to | |
| 71 | + * @vc->vc_screenbuf. (optional) | |
| 72 | + * @con_save_screen: save screen content into @vc->vc_screenbuf. Called e.g. | |
| 73 | + * upon entering graphics. (optional) | |
| 74 | + * @con_build_attr: build attributes based on @color, @intensity and other | |
| 75 | + * parameters. The result is used for both normal and erase | |
| 76 | + * characters. (optional) | |
| 77 | + * @con_invert_region: invert a region of length @count on @vc starting at @p. | |
| 78 | + * (optional) | |
| 79 | + * @con_debug_enter: prepare the console for the debugger. This includes, but | |
| 80 | + * is not limited to, unblanking the console, loading an | |
| 81 | + * appropriate palette, and allowing debugger generated output. | |
| 82 | + * (optional) | |
| 83 | + * @con_debug_leave: restore the console to its pre-debug state as closely as | |
| 84 | + * possible. (optional) | |
| 45 | 85 | */ |
| 46 | 86 | struct consw { |
| 47 | 87 | struct module *owner; |
| 48 | 88 | const char *(*con_startup)(void); |
| 49 | − void (*con_init)(struct vc_data *vc, int init); | |
| 89 | + void (*con_init)(struct vc_data *vc, bool init); | |
| 50 | 90 | void (*con_deinit)(struct vc_data *vc); |
| 51 | − void (*con_clear)(struct vc_data *vc, int sy, int sx, int height, | |
| 52 | − int width); | |
| 53 | − void (*con_putc)(struct vc_data *vc, int c, int ypos, int xpos); | |
| 54 | − void (*con_putcs)(struct vc_data *vc, const unsigned short *s, | |
| 55 | − int count, int ypos, int xpos); | |
| 56 | − void (*con_cursor)(struct vc_data *vc, int mode); | |
| 91 | + void (*con_clear)(struct vc_data *vc, unsigned int y, | |
| 92 | + unsigned int x, unsigned int count); | |
| 93 | + void (*con_putc)(struct vc_data *vc, u16 ca, unsigned int y, | |
| 94 | + unsigned int x); | |
| 95 | + void (*con_putcs)(struct vc_data *vc, const u16 *s, | |
| 96 | + unsigned int count, unsigned int ypos, | |
| 97 | + unsigned int xpos); | |
| 98 | + void (*con_cursor)(struct vc_data *vc, bool enable); | |
| 57 | 99 | bool (*con_scroll)(struct vc_data *vc, unsigned int top, |
| 58 | 100 | unsigned int bottom, enum con_scroll dir, |
| 59 | 101 | unsigned int lines); |
| 60 | − int (*con_switch)(struct vc_data *vc); | |
| 61 | − int (*con_blank)(struct vc_data *vc, int blank, int mode_switch); | |
| 62 | − int (*con_font_set)(struct vc_data *vc, struct console_font *font, | |
| 63 | − unsigned int vpitch, unsigned int flags); | |
| 102 | + bool (*con_switch)(struct vc_data *vc); | |
| 103 | + bool (*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank, | |
| 104 | + bool mode_switch); | |
| 105 | + int (*con_font_set)(struct vc_data *vc, | |
| 106 | + const struct console_font *font, | |
| 107 | + unsigned int vpitch, unsigned int flags); | |
| 64 | 108 | int (*con_font_get)(struct vc_data *vc, struct console_font *font, |
| 65 | 109 | unsigned int vpitch); |
| 66 | 110 | int (*con_font_default)(struct vc_data *vc, |
| 67 | − struct console_font *font, char *name); | |
| 111 | + struct console_font *font, const char *name); | |
| 68 | 112 | int (*con_resize)(struct vc_data *vc, unsigned int width, |
| 69 | − unsigned int height, unsigned int user); | |
| 113 | + unsigned int height, bool from_user); | |
| 70 | 114 | void (*con_set_palette)(struct vc_data *vc, |
| 71 | 115 | const unsigned char *table); |
| 72 | 116 | void (*con_scrolldelta)(struct vc_data *vc, int lines); |
| 73 | − int (*con_set_origin)(struct vc_data *vc); | |
| 117 | + bool (*con_set_origin)(struct vc_data *vc); | |
| 74 | 118 | void (*con_save_screen)(struct vc_data *vc); |
| 75 | 119 | u8 (*con_build_attr)(struct vc_data *vc, u8 color, |
| 76 | 120 | enum vc_intensity intensity, |
| 77 | 121 | bool blink, bool underline, bool reverse, bool italic); |
| 78 | 122 | void (*con_invert_region)(struct vc_data *vc, u16 *p, int count); |
| 79 | − u16 *(*con_screen_pos)(const struct vc_data *vc, int offset); | |
| 80 | − unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position, | |
| 81 | − int *px, int *py); | |
| 82 | − /* | |
| 83 | − * Flush the video console driver's scrollback buffer | |
| 84 | − */ | |
| 85 | − void (*con_flush_scrollback)(struct vc_data *vc); | |
| 86 | − /* | |
| 87 | − * Prepare the console for the debugger. This includes, but is not | |
| 88 | − * limited to, unblanking the console, loading an appropriate | |
| 89 | − * palette, and allowing debugger generated output. | |
| 90 | − */ | |
| 91 | − int (*con_debug_enter)(struct vc_data *vc); | |
| 92 | − /* | |
| 93 | − * Restore the console to its pre-debug state as closely as possible. | |
| 94 | − */ | |
| 95 | − int (*con_debug_leave)(struct vc_data *vc); | |
| 123 | + void (*con_debug_enter)(struct vc_data *vc); | |
| 124 | + void (*con_debug_leave)(struct vc_data *vc); | |
| 96 | 125 | }; |
| 97 | 126 | |
| 98 | 127 | extern const struct consw *conswitchp; |
| @@ -112,32 +141,21 @@ int con_is_bound(const struct consw *csw); · 13 unmodified lines | ||
| 112 | 141 | int do_unregister_con_driver(const struct consw *csw); |
| 113 | 142 | int do_take_over_console(const struct consw *sw, int first, int last, int deflt); |
| 114 | 143 | void give_up_console(const struct consw *sw); |
| 115 | −#ifdef CONFIG_HW_CONSOLE | |
| 116 | −int con_debug_enter(struct vc_data *vc); | |
| 117 | −int con_debug_leave(void); | |
| 144 | +#ifdef CONFIG_VT | |
| 145 | +void con_debug_enter(struct vc_data *vc); | |
| 146 | +void con_debug_leave(void); | |
| 118 | 147 | #else |
| 119 | −static inline int con_debug_enter(struct vc_data *vc) | |
| 120 | −{ | |
| 121 | − return 0; | |
| 122 | −} | |
| 123 | −static inline int con_debug_leave(void) | |
| 124 | −{ | |
| 125 | − return 0; | |
| 126 | −} | |
| 148 | +static inline void con_debug_enter(struct vc_data *vc) { } | |
| 149 | +static inline void con_debug_leave(void) { } | |
| 127 | 150 | #endif |
| 128 | 151 | |
| 129 | −/* cursor */ | |
| 130 | −#define CM_DRAW (1) | |
| 131 | −#define CM_ERASE (2) | |
| 132 | −#define CM_MOVE (3) | |
| 133 | − | |
| 134 | 152 | /* |
| 135 | 153 | * The interface for a console, or any other device that wants to capture |
| 136 | 154 | * console messages (printer driver?) |
| 137 | 155 | */ |
| 138 | 156 | |
| 139 | 157 | /** |
| 140 | − * cons_flags - General console flags | |
| 158 | + * enum cons_flags - General console flags | |
| 141 | 159 | * @CON_PRINTBUFFER: Used by newly registered consoles to avoid duplicate |
| 142 | 160 | * output of messages that were already shown by boot |
| 143 | 161 | * consoles or read by userspace via syslog() syscall. |
| @@ -218,7 +236,7 @@ struct nbcon_state { · 74 unmodified lines | ||
| 218 | 236 | static_assert(sizeof(struct nbcon_state) <= sizeof(int)); |
| 219 | 237 | |
| 220 | 238 | /** |
| 221 | − * nbcon_prio - console owner priority for nbcon consoles | |
| 239 | + * enum nbcon_prio - console owner priority for nbcon consoles | |
| 222 | 240 | * @NBCON_PRIO_NONE: Unused |
| 223 | 241 | * @NBCON_PRIO_NORMAL: Normal (non-emergency) usage |
| 224 | 242 | * @NBCON_PRIO_EMERGENCY: Emergency output (WARN/OOPS...) |
| @@ -450,7 +468,7 @@ static inline bool console_is_registered(const struct console *con) · 225 unmodified lines | ||
| 450 | 468 | * for_each_console() - Iterator over registered consoles |
| 451 | 469 | * @con: struct console pointer used as loop cursor |
| 452 | 470 | * |
| 453 | − * The console list and the console->flags are immutable while iterating. | |
| 471 | + * The console list and the &console.flags are immutable while iterating. | |
| 454 | 472 | * |
| 455 | 473 | * Requires console_list_lock to be held. |
| 456 | 474 | */ |
| @@ -520,12 +538,6 @@ void vcs_remove_sysfs(int index); · 63 unmodified lines | ||
| 520 | 538 | */ |
| 521 | 539 | extern atomic_t ignore_console_lock_warning; |
| 522 | 540 | |
| 523 | −/* VESA Blanking Levels */ | |
| 524 | −#define VESA_NO_BLANKING 0 | |
| 525 | −#define VESA_VSYNC_SUSPEND 1 | |
| 526 | −#define VESA_HSYNC_SUSPEND 2 | |
| 527 | −#define VESA_POWERDOWN 3 | |
| 528 | − | |
| 529 | 541 | extern void console_init(void); |
| 530 | 542 | |
| 531 | 543 | /* For deferred console takeover */ |
| @@ -151,7 +151,6 @@ struct vc_data { · 150 unmodified lines | ||
| 151 | 151 | DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */ |
| 152 | 152 | unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */ |
| 153 | 153 | unsigned short * vc_translate; |
| 154 | − unsigned int vc_resize_user; /* resize request from user */ | |
| 155 | 154 | unsigned int vc_bell_pitch; /* Console bell pitch */ |
| 156 | 155 | unsigned int vc_bell_duration; /* Console bell duration */ |
| 157 | 156 | unsigned short vc_cur_blink_ms; /* Cursor blink duration */ |
| @@ -14,17 +14,16 @@ · 13 unmodified lines | ||
| 14 | 14 | struct tty_struct; |
| 15 | 15 | struct vc_data; |
| 16 | 16 | |
| 17 | −extern void clear_selection(void); | |
| 18 | −extern int set_selection_user(const struct tiocl_selection __user *sel, | |
| 19 | − struct tty_struct *tty); | |
| 20 | −extern int set_selection_kernel(struct tiocl_selection *v, | |
| 21 | − struct tty_struct *tty); | |
| 22 | −extern int paste_selection(struct tty_struct *tty); | |
| 23 | −extern int sel_loadlut(char __user *p); | |
| 24 | −extern int mouse_reporting(void); | |
| 25 | −extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry); | |
| 26 | − | |
| 27 | −bool vc_is_sel(struct vc_data *vc); | |
| 17 | +void clear_selection(void); | |
| 18 | +int set_selection_user(const struct tiocl_selection __user *sel, | |
| 19 | + struct tty_struct *tty); | |
| 20 | +int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty); | |
| 21 | +int paste_selection(struct tty_struct *tty); | |
| 22 | +int sel_loadlut(u32 __user *lut); | |
| 23 | +int mouse_reporting(void); | |
| 24 | +void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry); | |
| 25 | + | |
| 26 | +bool vc_is_sel(const struct vc_data *vc); | |
| 28 | 27 | |
| 29 | 28 | extern int console_blanked; |
| 30 | 29 | |
| @@ -33,24 +32,21 @@ extern unsigned char default_red[]; · 2 unmodified lines | ||
| 33 | 32 | extern unsigned char default_grn[]; |
| 34 | 33 | extern unsigned char default_blu[]; |
| 35 | 34 | |
| 36 | −extern unsigned short *screen_pos(const struct vc_data *vc, int w_offset, | |
| 37 | − bool viewed); | |
| 38 | −extern u16 screen_glyph(const struct vc_data *vc, int offset); | |
| 39 | −extern u32 screen_glyph_unicode(const struct vc_data *vc, int offset); | |
| 40 | −extern void complement_pos(struct vc_data *vc, int offset); | |
| 41 | −extern void invert_screen(struct vc_data *vc, int offset, int count, bool viewed); | |
| 42 | − | |
| 43 | −extern void getconsxy(const struct vc_data *vc, unsigned char xy[static 2]); | |
| 44 | −extern void putconsxy(struct vc_data *vc, unsigned char xy[static const 2]); | |
| 45 | − | |
| 46 | −extern u16 vcs_scr_readw(const struct vc_data *vc, const u16 *org); | |
| 47 | −extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org); | |
| 48 | −extern void vcs_scr_updated(struct vc_data *vc); | |
| 49 | − | |
| 50 | −extern int vc_uniscr_check(struct vc_data *vc); | |
| 51 | −extern void vc_uniscr_copy_line(const struct vc_data *vc, void *dest, | |
| 52 | − bool viewed, | |
| 53 | − unsigned int row, unsigned int col, | |
| 54 | − unsigned int nr); | |
| 35 | +unsigned short *screen_pos(const struct vc_data *vc, int w_offset, bool viewed); | |
| 36 | +u16 screen_glyph(const struct vc_data *vc, int offset); | |
| 37 | +u32 screen_glyph_unicode(const struct vc_data *vc, int offset); | |
| 38 | +void complement_pos(struct vc_data *vc, int offset); | |
| 39 | +void invert_screen(struct vc_data *vc, int offset, int count, bool viewed); | |
| 40 | + | |
| 41 | +void getconsxy(const struct vc_data *vc, unsigned char xy[static 2]); | |
| 42 | +void putconsxy(struct vc_data *vc, unsigned char xy[static const 2]); | |
| 43 | + | |
| 44 | +u16 vcs_scr_readw(const struct vc_data *vc, const u16 *org); | |
| 45 | +void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org); | |
| 46 | +void vcs_scr_updated(struct vc_data *vc); | |
| 47 | + | |
| 48 | +int vc_uniscr_check(struct vc_data *vc); | |
| 49 | +void vc_uniscr_copy_line(const struct vc_data *vc, void *dest, bool viewed, | |
| 50 | + unsigned int row, unsigned int col, unsigned int nr); | |
| 55 | 51 | |
| 56 | 52 | #endif |
| @@ -27,7 +27,7 @@ struct serdev_device; · 26 unmodified lines | ||
| 27 | 27 | * not sleep. |
| 28 | 28 | */ |
| 29 | 29 | struct serdev_device_ops { |
| 30 | − ssize_t (*receive_buf)(struct serdev_device *, const u8 *, size_t); | |
| 30 | + size_t (*receive_buf)(struct serdev_device *, const u8 *, size_t); | |
| 31 | 31 | void (*write_wakeup)(struct serdev_device *); |
| 32 | 32 | }; |
| 33 | 33 | |
| @@ -185,9 +185,9 @@ static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl · 151 unmodified lines | ||
| 185 | 185 | serdev->ops->write_wakeup(serdev); |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | −static inline ssize_t serdev_controller_receive_buf(struct serdev_controller *ctrl, | |
| 189 | − const u8 *data, | |
| 190 | − size_t count) | |
| 188 | +static inline size_t serdev_controller_receive_buf(struct serdev_controller *ctrl, | |
| 189 | + const u8 *data, | |
| 190 | + size_t count) | |
| 191 | 191 | { |
| 192 | 192 | struct serdev_device *serdev = ctrl->serdev; |
| 193 | 193 | |
| @@ -210,6 +210,12 @@ int serial8250_console_exit(struct uart_port *port); · 209 unmodified lines | ||
| 210 | 210 | void serial8250_set_isa_configurator(void (*v)(int port, struct uart_port *up, |
| 211 | 211 | u32 *capabilities)); |
| 212 | 212 | |
| 213 | +#ifdef CONFIG_SERIAL_8250_CONSOLE | |
| 214 | +extern int hp300_setup_serial_console(void) __init; | |
| 215 | +#else | |
| 216 | +static inline int hp300_setup_serial_console(void) { return 0; } | |
| 217 | +#endif | |
| 218 | + | |
| 213 | 219 | #ifdef CONFIG_SERIAL_8250_RT288X |
| 214 | 220 | int rt288x_setup(struct uart_port *p); |
| 215 | 221 | int au_platform_setup(struct plat_serial8250_port *p); |
| @@ -467,9 +467,10 @@ struct uart_port { · 466 unmodified lines | ||
| 467 | 467 | unsigned int fifosize; /* tx fifo size */ |
| 468 | 468 | unsigned char x_char; /* xon/xoff char */ |
| 469 | 469 | unsigned char regshift; /* reg offset shift */ |
| 470 | + | |
| 470 | 471 | unsigned char iotype; /* io access style */ |
| 471 | − unsigned char quirks; /* internal quirks */ | |
| 472 | 472 | |
| 473 | +#define UPIO_UNKNOWN ((unsigned char)~0U) /* UCHAR_MAX */ | |
| 473 | 474 | #define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */ |
| 474 | 475 | #define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */ |
| 475 | 476 | #define UPIO_MEM (SERIAL_IO_MEM) /* driver-specific */ |
| @@ -479,7 +480,9 @@ struct uart_port { · 3 unmodified lines | ||
| 479 | 480 | #define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */ |
| 480 | 481 | #define UPIO_MEM16 (SERIAL_IO_MEM16) /* 16b little endian */ |
| 481 | 482 | |
| 482 | − /* quirks must be updated while holding port mutex */ | |
| 483 | + unsigned char quirks; /* internal quirks */ | |
| 484 | + | |
| 485 | + /* internal quirks must be updated while holding port mutex */ | |
| 483 | 486 | #define UPQ_NO_TXEN_TEST BIT(0) |
| 484 | 487 | |
| 485 | 488 | unsigned int read_status_mask; /* driver specific */ |
| @@ -786,7 +789,8 @@ enum UART_TX_FLAGS { · 300 unmodified lines | ||
| 786 | 789 | if (pending < WAKEUP_CHARS) { \ |
| 787 | 790 | uart_write_wakeup(__port); \ |
| 788 | 791 | \ |
| 789 | − if (!((flags) & UART_TX_NOSTOP) && pending == 0) \ | |
| 792 | + if (!((flags) & UART_TX_NOSTOP) && pending == 0 && \ | |
| 793 | + __port->ops->tx_empty(__port)) \ | |
| 790 | 794 | __port->ops->stop_tx(__port); \ |
| 791 | 795 | } \ |
| 792 | 796 | \ |
| @@ -959,6 +963,8 @@ int uart_register_driver(struct uart_driver *uart); · 166 unmodified lines | ||
| 959 | 963 | void uart_unregister_driver(struct uart_driver *uart); |
| 960 | 964 | int uart_add_one_port(struct uart_driver *reg, struct uart_port *port); |
| 961 | 965 | void uart_remove_one_port(struct uart_driver *reg, struct uart_port *port); |
| 966 | +int uart_read_port_properties(struct uart_port *port); | |
| 967 | +int uart_read_and_validate_port_properties(struct uart_port *port); | |
| 962 | 968 | bool uart_match_port(const struct uart_port *port1, |
| 963 | 969 | const struct uart_port *port2); |
| 964 | 970 | |
| @@ -178,6 +178,7 @@ struct geni_se { · 177 unmodified lines | ||
| 178 | 178 | #define M_GP_IRQ_3_EN BIT(12) |
| 179 | 179 | #define M_GP_IRQ_4_EN BIT(13) |
| 180 | 180 | #define M_GP_IRQ_5_EN BIT(14) |
| 181 | +#define M_TX_FIFO_NOT_EMPTY_EN BIT(21) | |
| 181 | 182 | #define M_IO_DATA_DEASSERT_EN BIT(22) |
| 182 | 183 | #define M_IO_DATA_ASSERT_EN BIT(23) |
| 183 | 184 | #define M_RX_FIFO_RD_ERR_EN BIT(24) |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/major.h> |
| 7 | 7 | #include <linux/termios.h> |
| 8 | 8 | #include <linux/workqueue.h> |
| 9 | −#include <linux/tty_buffer.h> | |
| 10 | 9 | #include <linux/tty_driver.h> |
| 11 | 10 | #include <linux/tty_ldisc.h> |
| 12 | 11 | #include <linux/tty_port.h> |
| @@ -25,7 +25,8 @@ extern int fg_console, last_console, want_console; · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | int vc_allocate(unsigned int console); |
| 27 | 27 | int vc_cons_allocated(unsigned int console); |
| 28 | −int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines); | |
| 28 | +int __vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines, | |
| 29 | + bool from_user); | |
| 29 | 30 | struct vc_data *vc_deallocate(unsigned int console); |
| 30 | 31 | void reset_palette(struct vc_data *vc); |
| 31 | 32 | void do_blank_screen(int entering_gfx); |
| @@ -42,6 +43,12 @@ void redraw_screen(struct vc_data *vc, int is_switch); · 10 unmodified lines | ||
| 42 | 43 | #define update_screen(x) redraw_screen(x, 0) |
| 43 | 44 | #define switch_screen(x) redraw_screen(x, 1) |
| 44 | 45 | |
| 46 | +static inline int vc_resize(struct vc_data *vc, unsigned int cols, | |
| 47 | + unsigned int lines) | |
| 48 | +{ | |
| 49 | + return __vc_resize(vc, cols, lines, false); | |
| 50 | +} | |
| 51 | + | |
| 45 | 52 | struct tty_struct; |
| 46 | 53 | int tioclinux(struct tty_struct *tty, unsigned long arg); |
| 47 | 54 | |
| @@ -168,7 +175,4 @@ void vt_set_led_state(unsigned int console, int leds); · 120 unmodified lines | ||
| 168 | 175 | void vt_kbd_con_start(unsigned int console); |
| 169 | 176 | void vt_kbd_con_stop(unsigned int console); |
| 170 | 177 | |
| 171 | −void vc_scrolldelta_helper(struct vc_data *c, int lines, | |
| 172 | − unsigned int rolled_over, void *_base, unsigned int size); | |
| 173 | − | |
| 174 | 178 | #endif /* _VT_KERN_H */ |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #include <linux/types.h> |
| 6 | 6 | #include <linux/i2c.h> |
| 7 | +#include <linux/vesa.h> | |
| 7 | 8 | |
| 8 | 9 | /* Definitions of frame buffers */ |
| 9 | 10 | |
| @@ -293,13 +294,6 @@ struct fb_con2fbmap { · 283 unmodified lines | ||
| 293 | 294 | __u32 framebuffer; |
| 294 | 295 | }; |
| 295 | 296 | |
| 296 | −/* VESA Blanking Levels */ | |
| 297 | −#define VESA_NO_BLANKING 0 | |
| 298 | −#define VESA_VSYNC_SUSPEND 1 | |
| 299 | −#define VESA_HSYNC_SUSPEND 2 | |
| 300 | −#define VESA_POWERDOWN 3 | |
| 301 | − | |
| 302 | − | |
| 303 | 297 | enum { |
| 304 | 298 | /* screen: unblanked, hsync: on, vsync: on */ |
| 305 | 299 | FB_BLANK_UNBLANK = VESA_NO_BLANKING, |
| @@ -0,0 +1,18 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ | |
| 2 | +#ifndef _UAPI_LINUX_VESA_H | |
| 3 | +#define _UAPI_LINUX_VESA_H | |
| 4 | + | |
| 5 | +/* VESA Blanking Levels */ | |
| 6 | +enum vesa_blank_mode { | |
| 7 | + VESA_NO_BLANKING = 0, | |
| 8 | +#define VESA_NO_BLANKING VESA_NO_BLANKING | |
| 9 | + VESA_VSYNC_SUSPEND = 1, | |
| 10 | +#define VESA_VSYNC_SUSPEND VESA_VSYNC_SUSPEND | |
| 11 | + VESA_HSYNC_SUSPEND = 2, | |
| 12 | +#define VESA_HSYNC_SUSPEND VESA_HSYNC_SUSPEND | |
| 13 | + VESA_POWERDOWN = VESA_VSYNC_SUSPEND | VESA_HSYNC_SUSPEND, | |
| 14 | +#define VESA_POWERDOWN VESA_POWERDOWN | |
| 15 | + VESA_BLANK_MAX = VESA_POWERDOWN, | |
| 16 | +}; | |
| 17 | + | |
| 18 | +#endif | |
| @@ -3269,6 +3269,21 @@ static int __init keep_bootcon_setup(char *str) · 3268 unmodified lines | ||
| 3269 | 3269 | |
| 3270 | 3270 | early_param("keep_bootcon", keep_bootcon_setup); |
| 3271 | 3271 | |
| 3272 | +static int console_call_setup(struct console *newcon, char *options) | |
| 3273 | +{ | |
| 3274 | + int err; | |
| 3275 | + | |
| 3276 | + if (!newcon->setup) | |
| 3277 | + return 0; | |
| 3278 | + | |
| 3279 | + /* Synchronize with possible boot console. */ | |
| 3280 | + console_lock(); | |
| 3281 | + err = newcon->setup(newcon, options); | |
| 3282 | + console_unlock(); | |
| 3283 | + | |
| 3284 | + return err; | |
| 3285 | +} | |
| 3286 | + | |
| 3272 | 3287 | /* |
| 3273 | 3288 | * This is called by register_console() to try to match |
| 3274 | 3289 | * the newly registered console with any of the ones selected |
| @@ -3304,8 +3319,8 @@ static int try_enable_preferred_console(struct console *newcon, · 29 unmodified lines | ||
| 3304 | 3319 | if (_braille_register_console(newcon, c)) |
| 3305 | 3320 | return 0; |
| 3306 | 3321 | |
| 3307 | − if (newcon->setup && | |
| 3308 | − (err = newcon->setup(newcon, c->options)) != 0) | |
| 3322 | + err = console_call_setup(newcon, c->options); | |
| 3323 | + if (err) | |
| 3309 | 3324 | return err; |
| 3310 | 3325 | } |
| 3311 | 3326 | newcon->flags |= CON_ENABLED; |
| @@ -3331,7 +3346,7 @@ static void try_enable_default_console(struct console *newcon) · 19 unmodified lines | ||
| 3331 | 3346 | if (newcon->index < 0) |
| 3332 | 3347 | newcon->index = 0; |
| 3333 | 3348 | |
| 3334 | − if (newcon->setup && newcon->setup(newcon, NULL) != 0) | |
| 3349 | + if (console_call_setup(newcon, NULL) != 0) | |
| 3335 | 3350 | return; |
| 3336 | 3351 | |
| 3337 | 3352 | newcon->flags |= CON_ENABLED; |
| @@ -43,7 +43,7 @@ config KGDB_SERIAL_CONSOLE · 42 unmodified lines | ||
| 43 | 43 | tristate "KGDB: use kgdb over the serial console" |
| 44 | 44 | select CONSOLE_POLL |
| 45 | 45 | select MAGIC_SYSRQ |
| 46 | − depends on TTY && HW_CONSOLE | |
| 46 | + depends on TTY && VT | |
| 47 | 47 | default y |
| 48 | 48 | help |
| 49 | 49 | Share a serial console with kgdb. Sysrq-g must be used |
| @@ -100,8 +100,8 @@ static void snd_serial_generic_write_wakeup(struct serdev_device *serdev) · 99 unmodified lines | ||
| 100 | 100 | snd_serial_generic_tx_wakeup(drvdata); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | −static ssize_t snd_serial_generic_receive_buf(struct serdev_device *serdev, | |
| 104 | − const u8 *buf, size_t count) | |
| 103 | +static size_t snd_serial_generic_receive_buf(struct serdev_device *serdev, | |
| 104 | + const u8 *buf, size_t count) | |
| 105 | 105 | { |
| 106 | 106 | int ret; |
| 107 | 107 | struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev); |