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 | allOf: | 56 | allOf: |
| 57 | - $ref: serial.yaml# | 57 | - $ref: serial.yaml# |
| 58 | - $ref: rs485.yaml# | ||
| 58 | - if: | 59 | - if: |
| 59 | properties: | 60 | properties: |
| 60 | compatible: | 61 | compatible: |
| @@ -30,6 +30,7 @@ properties: · 29 unmodified lines | |||
| 30 | - items: | 30 | - items: |
| 31 | - enum: | 31 | - enum: |
| 32 | - fsl,imx93-lpuart | 32 | - fsl,imx93-lpuart |
| 33 | - fsl,imx95-lpuart | ||
| 33 | - const: fsl,imx8ulp-lpuart | 34 | - const: fsl,imx8ulp-lpuart |
| 34 | - const: fsl,imx7ulp-lpuart | 35 | - const: fsl,imx7ulp-lpuart |
| 35 | - items: | 36 | - items: |
| @@ -59,6 +59,7 @@ properties: · 58 unmodified lines | |||
| 59 | - renesas,hscif-r8a779a0 # R-Car V3U | 59 | - renesas,hscif-r8a779a0 # R-Car V3U |
| 60 | - renesas,hscif-r8a779f0 # R-Car S4-8 | 60 | - renesas,hscif-r8a779f0 # R-Car S4-8 |
| 61 | - renesas,hscif-r8a779g0 # R-Car V4H | 61 | - renesas,hscif-r8a779g0 # R-Car V4H |
| 62 | - renesas,hscif-r8a779h0 # R-Car V4M | ||
| 62 | - const: renesas,rcar-gen4-hscif # R-Car Gen4 | 63 | - const: renesas,rcar-gen4-hscif # R-Car Gen4 |
| 63 | - const: renesas,hscif # generic HSCIF compatible UART | 64 | - const: renesas,hscif # generic HSCIF compatible UART |
| 64 | 65 | ||
| @@ -143,6 +143,8 @@ allOf: · 142 unmodified lines | |||
| 143 | then: | 143 | then: |
| 144 | required: | 144 | required: |
| 145 | - samsung,uart-fifosize | 145 | - samsung,uart-fifosize |
| 146 | properties: | ||
| 147 | reg-io-width: false | ||
| 146 | 148 | ||
| 147 | unevaluatedProperties: false | 149 | unevaluatedProperties: false |
| 148 | 150 | ||
| @@ -88,7 +88,7 @@ properties: · 87 unmodified lines | |||
| 88 | TX FIFO threshold configuration (in bytes). | 88 | TX FIFO threshold configuration (in bytes). |
| 89 | 89 | ||
| 90 | patternProperties: | 90 | patternProperties: |
| 91 | "^(bluetooth|bluetooth-gnss|gnss|gps|mcu)$": | 91 | "^(bluetooth|bluetooth-gnss|gnss|gps|mcu|onewire)$": |
| 92 | if: | 92 | if: |
| 93 | type: object | 93 | type: object |
| 94 | then: | 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 | wakeup-source: true | 59 | wakeup-source: true |
| 60 | 60 | ||
| 61 | power-domains: | ||
| 62 | maxItems: 1 | ||
| 63 | |||
| 61 | rx-threshold: | 64 | rx-threshold: |
| 62 | description: | 65 | description: |
| 63 | If value is set to 1, RX FIFO threshold is disabled. | 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 | tty_buffer | 38 | tty_buffer |
| 39 | tty_ioctl | 39 | tty_ioctl |
| 40 | tty_internals | 40 | tty_internals |
| 41 | console | ||
| 41 | 42 | ||
| 42 | Writing TTY Driver | 43 | Writing TTY Driver |
| 43 | ================== | 44 | ================== |
| @@ -12,3 +12,4 @@ · 11 unmodified lines | |||
| 12 | mxc-w1 | 12 | mxc-w1 |
| 13 | omap-hdq | 13 | omap-hdq |
| 14 | w1-gpio | 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 | * The Amiga keyboard driver needs key_maps, but we cannot export it in | 846 | * The Amiga keyboard driver needs key_maps, but we cannot export it in |
| 847 | * drivers/char/defkeymap.c, as it is autogenerated | 847 | * drivers/char/defkeymap.c, as it is autogenerated |
| 848 | */ | 848 | */ |
| 849 | #ifdef CONFIG_HW_CONSOLE | 849 | #ifdef CONFIG_VT |
| 850 | EXPORT_SYMBOL_GPL(key_maps); | 850 | EXPORT_SYMBOL_GPL(key_maps); |
| 851 | #endif | 851 | #endif |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/serial_8250.h> | ||
| 13 | #include <linux/string.h> | 14 | #include <linux/string.h> |
| 14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 15 | #include <linux/console.h> | 16 | #include <linux/console.h> |
| @@ -67,9 +68,6 @@ static char *hp300_models[] __initdata = { · 51 unmodified lines | |||
| 67 | static char hp300_model_name[13] = "HP9000/"; | 68 | static char hp300_model_name[13] = "HP9000/"; |
| 68 | 69 | ||
| 69 | extern void hp300_reset(void); | 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 | int __init hp300_parse_bootinfo(const struct bi_record *record) | 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 | } else { | 261 | } else { |
| 264 | panic("Unknown HP9000 Model"); | 262 | panic("Unknown HP9000 Model"); |
| 265 | } | 263 | } |
| 266 | #ifdef CONFIG_SERIAL_8250_CONSOLE | ||
| 267 | hp300_setup_serial_console(); | 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, | 386 | static size_t btmtkuart_receive_buf(struct serdev_device *serdev, |
| 387 | const u8 *data, size_t count) | 387 | const u8 *data, size_t count) |
| 388 | { | 388 | { |
| 389 | struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); | 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 | { NXP_RECV_FW_REQ_V3, .recv = nxp_recv_fw_req_v3 }, | 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, | 1288 | static size_t btnxpuart_receive_buf(struct serdev_device *serdev, |
| 1289 | const u8 *data, size_t count) | 1289 | const u8 *data, size_t count) |
| 1290 | { | 1290 | { |
| 1291 | struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev); | 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 | * Return: number of processed bytes | 272 | * Return: number of processed bytes |
| 273 | */ | 273 | */ |
| 274 | static ssize_t hci_uart_receive_buf(struct serdev_device *serdev, | 274 | static size_t hci_uart_receive_buf(struct serdev_device *serdev, |
| 275 | const u8 *data, size_t count) | 275 | const u8 *data, size_t count) |
| 276 | { | 276 | { |
| 277 | struct hci_uart *hu = serdev_device_get_drvdata(serdev); | 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 | .write_raw = gnss_serial_write_raw, | 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 | const u8 *buf, size_t count) | 84 | const u8 *buf, size_t count) |
| 85 | { | 85 | { |
| 86 | struct gnss_serial *gserial = serdev_device_get_drvdata(serdev); | 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 | .write_raw = sirf_write_raw, | 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 | const u8 *buf, size_t count) | 164 | const u8 *buf, size_t count) |
| 165 | { | 165 | { |
| 166 | struct sirf_data *data = serdev_device_get_drvdata(serdev); | 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 | size_t i; | 276 | size_t i; |
| 277 | u8 c; | 277 | u8 c; |
| @@ -331,8 +331,8 @@ static void hdlc_deinit(struct gb_beagleplay *bg) · 53 unmodified lines | |||
| 331 | flush_work(&bg->tx_work); | 331 | flush_work(&bg->tx_work); |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static ssize_t gb_tty_receive(struct serdev_device *sd, const u8 *data, | 334 | static size_t gb_tty_receive(struct serdev_device *sd, const u8 *data, |
| 335 | size_t count) | 335 | size_t count) |
| 336 | { | 336 | { |
| 337 | struct gb_beagleplay *bg = serdev_device_get_drvdata(sd); | 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 | return checksum == pms7003_calc_checksum(frame); | 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, | 214 | static size_t pms7003_receive_buf(struct serdev_device *serdev, const u8 *buf, |
| 215 | size_t size) | 215 | size_t size) |
| 216 | { | 216 | { |
| 217 | struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev); | 217 | struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev); |
| 218 | struct pms7003_state *state = iio_priv(indio_dev); | 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 | return 0; | 174 | return 0; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static ssize_t scd30_serdev_receive_buf(struct serdev_device *serdev, | 177 | static size_t scd30_serdev_receive_buf(struct serdev_device *serdev, |
| 178 | const u8 *buf, size_t size) | 178 | const u8 *buf, size_t size) |
| 179 | { | 179 | { |
| 180 | struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev); | 180 | struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev); |
| 181 | struct scd30_serdev_priv *priv; | 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 | return rsp_size; | 210 | return rsp_size; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | static ssize_t sps30_serial_receive_buf(struct serdev_device *serdev, | 213 | static size_t sps30_serial_receive_buf(struct serdev_device *serdev, |
| 214 | const u8 *buf, size_t size) | 214 | const u8 *buf, size_t size) |
| 215 | { | 215 | { |
| 216 | struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev); | 216 | struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev); |
| 217 | struct sps30_serial_priv *priv; | 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 | * Also, we assume to RX one pkt per time (i.e. the HW doesn't send anything | 378 | * Also, we assume to RX one pkt per time (i.e. the HW doesn't send anything |
| 379 | * unless we require to AND we don't queue more than one request per time). | 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, | 381 | static size_t bno055_ser_receive_buf(struct serdev_device *serdev, |
| 382 | const u8 *buf, size_t size) | 382 | const u8 *buf, size_t size) |
| 383 | { | 383 | { |
| 384 | int status; | 384 | int status; |
| 385 | struct bno055_ser_priv *priv = serdev_device_get_drvdata(serdev); | 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 | MODULE_DESCRIPTION("Amiga keyboard driver"); | 26 | MODULE_DESCRIPTION("Amiga keyboard driver"); |
| 27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
| 28 | 28 | ||
| 29 | #ifdef CONFIG_HW_CONSOLE | 29 | #ifdef CONFIG_VT |
| 30 | static unsigned char amikbd_keycode[0x78] __initdata = { | 30 | static unsigned char amikbd_keycode[0x78] __initdata = { |
| 31 | [0] = KEY_GRAVE, | 31 | [0] = KEY_GRAVE, |
| 32 | [1] = KEY_1, | 32 | [1] = KEY_1, |
| @@ -148,9 +148,9 @@ static void __init amikbd_init_console_keymaps(void) · 115 unmodified lines | |||
| 148 | memcpy(key_maps[i], temp_map, sizeof(temp_map)); | 148 | memcpy(key_maps[i], temp_map, sizeof(temp_map)); |
| 149 | } | 149 | } |
| 150 | } | 150 | } |
| 151 | #else /* !CONFIG_HW_CONSOLE */ | 151 | #else /* !CONFIG_VT */ |
| 152 | static inline void amikbd_init_console_keymaps(void) {} | 152 | static inline void amikbd_init_console_keymaps(void) {} |
| 153 | #endif /* !CONFIG_HW_CONSOLE */ | 153 | #endif /* !CONFIG_VT */ |
| 154 | 154 | ||
| 155 | static const char *amikbd_messages[8] = { | 155 | static const char *amikbd_messages[8] = { |
| 156 | [0] = KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n", | 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 | rave_sp_receive_reply(sp, data, length); | 471 | rave_sp_receive_reply(sp, data, length); |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | static ssize_t rave_sp_receive_buf(struct serdev_device *serdev, | 474 | static size_t rave_sp_receive_buf(struct serdev_device *serdev, |
| 475 | const u8 *buf, size_t size) | 475 | const u8 *buf, size_t size) |
| 476 | { | 476 | { |
| 477 | struct device *dev = &serdev->dev; | 477 | struct device *dev = &serdev->dev; |
| 478 | struct rave_sp *sp = dev_get_drvdata(dev); | 478 | struct rave_sp *sp = dev_get_drvdata(dev); |
| @@ -45,7 +45,7 @@ struct qcauart { · 44 unmodified lines | |||
| 45 | unsigned char *tx_buffer; | 45 | unsigned char *tx_buffer; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | static ssize_t | 48 | static size_t |
| 49 | qca_tty_receive(struct serdev_device *serdev, const u8 *data, size_t count) | 49 | qca_tty_receive(struct serdev_device *serdev, const u8 *data, size_t count) |
| 50 | { | 50 | { |
| 51 | struct qcauart *qca = serdev_device_get_drvdata(serdev); | 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 | return 0; | 203 | return 0; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | static ssize_t pn532_receive_buf(struct serdev_device *serdev, | 206 | static size_t pn532_receive_buf(struct serdev_device *serdev, |
| 207 | const u8 *data, size_t count) | 207 | const u8 *data, size_t count) |
| 208 | { | 208 | { |
| 209 | struct pn532_uart_phy *dev = serdev_device_get_drvdata(serdev); | 209 | struct pn532_uart_phy *dev = serdev_device_get_drvdata(serdev); |
| 210 | size_t i; | 210 | size_t i; |
| @@ -51,8 +51,8 @@ static const struct s3fwrn5_phy_ops uart_phy_ops = { · 50 unmodified lines | |||
| 51 | .write = s3fwrn82_uart_write, | 51 | .write = s3fwrn82_uart_write, |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static ssize_t s3fwrn82_uart_read(struct serdev_device *serdev, | 54 | static size_t s3fwrn82_uart_read(struct serdev_device *serdev, |
| 55 | const u8 *data, size_t count) | 55 | const u8 *data, size_t count) |
| 56 | { | 56 | { |
| 57 | struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev); | 57 | struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev); |
| 58 | size_t i; | 58 | size_t i; |
| @@ -81,8 +81,8 @@ struct cros_ec_uart { · 80 unmodified lines | |||
| 81 | struct response_info response; | 81 | struct response_info response; |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | static ssize_t cros_ec_uart_rx_bytes(struct serdev_device *serdev, | 84 | static size_t cros_ec_uart_rx_bytes(struct serdev_device *serdev, |
| 85 | const u8 *data, size_t count) | 85 | const u8 *data, size_t count) |
| 86 | { | 86 | { |
| 87 | struct ec_host_response *host_response; | 87 | struct ec_host_response *host_response; |
| 88 | struct cros_ec_device *ec_dev = serdev_device_get_drvdata(serdev); | 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 | /* -- Glue layer (serdev_device -> ssam_controller). ------------------------ */ | 228 | /* -- Glue layer (serdev_device -> ssam_controller). ------------------------ */ |
| 229 | 229 | ||
| 230 | static ssize_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf, | 230 | static size_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf, |
| 231 | size_t n) | 231 | size_t n) |
| 232 | { | 232 | { |
| 233 | struct ssam_controller *ctrl; | 233 | struct ssam_controller *ctrl; |
| 234 | int ret; | 234 | int ret; |
| @@ -75,14 +75,9 @@ config VT_CONSOLE_SLEEP · 74 unmodified lines | |||
| 75 | def_bool y | 75 | def_bool y |
| 76 | depends on VT_CONSOLE && PM_SLEEP | 76 | depends on VT_CONSOLE && PM_SLEEP |
| 77 | 77 | ||
| 78 | config HW_CONSOLE | ||
| 79 | bool | ||
| 80 | depends on VT | ||
| 81 | default y | ||
| 82 | |||
| 83 | config VT_HW_CONSOLE_BINDING | 78 | config VT_HW_CONSOLE_BINDING |
| 84 | bool "Support for binding and unbinding console drivers" | 79 | bool "Support for binding and unbinding console drivers" |
| 85 | depends on HW_CONSOLE | 80 | depends on VT |
| 86 | help | 81 | help |
| 87 | The virtual terminal is the device that interacts with the physical | 82 | The virtual terminal is the device that interacts with the physical |
| 88 | terminal through console drivers. On these systems, at least one | 83 | terminal through console drivers. On these systems, at least one |
| @@ -1566,7 +1566,7 @@ fail_tty_driver_kref_put: · 1565 unmodified lines | |||
| 1566 | return error; | 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 | struct serial_state *state = platform_get_drvdata(pdev); | 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 | free_irq(IRQ_AMIGA_TBE, state); | 1577 | free_irq(IRQ_AMIGA_TBE, state); |
| 1578 | free_irq(IRQ_AMIGA_RBF, state); | 1578 | free_irq(IRQ_AMIGA_RBF, state); |
| 1579 | |||
| 1580 | return 0; | ||
| 1581 | } | 1579 | } |
| 1582 | 1580 | ||
| 1583 | static struct platform_driver amiga_serial_driver = { | 1581 | static struct platform_driver amiga_serial_driver = { |
| 1584 | .remove = __exit_p(amiga_serial_remove), | 1582 | .remove_new = __exit_p(amiga_serial_remove), |
| 1585 | .driver = { | 1583 | .driver = { |
| 1586 | .name = "amiga-serial", | 1584 | .name = "amiga-serial", |
| 1587 | }, | 1585 | }, |
| @@ -408,7 +408,7 @@ err_unmap: · 407 unmodified lines | |||
| 408 | return ret; | 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 | struct goldfish_tty *qtty = platform_get_drvdata(pdev); | 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 | if (goldfish_tty_current_line_count == 0) | 424 | if (goldfish_tty_current_line_count == 0) |
| 425 | goldfish_tty_delete_driver(); | 425 | goldfish_tty_delete_driver(); |
| 426 | mutex_unlock(&goldfish_tty_lock); | 426 | mutex_unlock(&goldfish_tty_lock); |
| 427 | return 0; | ||
| 428 | } | 427 | } |
| 429 | 428 | ||
| 430 | #ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE | 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 | static struct platform_driver goldfish_tty_platform_driver = { | 462 | static struct platform_driver goldfish_tty_platform_driver = { |
| 464 | .probe = goldfish_tty_probe, | 463 | .probe = goldfish_tty_probe, |
| 465 | .remove = goldfish_tty_remove, | 464 | .remove_new = goldfish_tty_remove, |
| 466 | .driver = { | 465 | .driver = { |
| 467 | .name = "goldfish_tty", | 466 | .name = "goldfish_tty", |
| 468 | .of_match_table = goldfish_tty_of_match, | 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 | NULL, | 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 | * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance | 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 | priv->dev->bus = &iucv_bus; | 1101 | priv->dev->bus = &iucv_bus; |
| 1098 | priv->dev->parent = iucv_root; | 1102 | priv->dev->parent = iucv_root; |
| 1099 | priv->dev->groups = hvc_iucv_dev_attr_groups; | 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 | rc = device_register(priv->dev); | 1105 | rc = device_register(priv->dev); |
| 1102 | if (rc) { | 1106 | if (rc) { |
| 1103 | put_device(priv->dev); | 1107 | put_device(priv->dev); |
| @@ -431,7 +431,7 @@ static void serdev_drv_remove(struct device *dev) · 430 unmodified lines | |||
| 431 | dev_pm_domain_detach(dev, true); | 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 | .name = "serial", | 435 | .name = "serial", |
| 436 | .match = serdev_device_match, | 436 | .match = serdev_device_match, |
| 437 | .probe = serdev_drv_probe, | 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 | struct serdev_controller *ctrl = port->client_data; | 28 | struct serdev_controller *ctrl = port->client_data; |
| 29 | struct serport *serport = serdev_controller_get_drvdata(ctrl); | 29 | struct serport *serport = serdev_controller_get_drvdata(ctrl); |
| 30 | int ret; | 30 | size_t ret; |
| 31 | 31 | ||
| 32 | if (!test_bit(SERPORT_ACTIVE, &serport->flags)) | 32 | if (!test_bit(SERPORT_ACTIVE, &serport->flags)) |
| 33 | return 0; | 33 | return 0; |
| 34 | 34 | ||
| 35 | ret = serdev_controller_receive_buf(ctrl, cp, count); | 35 | ret = serdev_controller_receive_buf(ctrl, cp, count); |
| 36 | 36 | ||
| 37 | dev_WARN_ONCE(&ctrl->dev, ret < 0 || ret > count, | 37 | dev_WARN_ONCE(&ctrl->dev, ret > count, |
| 38 | "receive_buf returns %d (count = %zu)\n", | 38 | "receive_buf returns %zu (count = %zu)\n", |
| 39 | ret, count); | 39 | ret, count); |
| 40 | if (ret < 0) | 40 | if (ret > count) |
| 41 | return 0; | ||
| 42 | else if (ret > count) | ||
| 43 | return count; | 41 | return count; |
| 44 | 42 | ||
| 45 | return ret; | 43 | return ret; |
| @@ -419,8 +419,8 @@ static int aspeed_vuart_probe(struct platform_device *pdev) · 418 unmodified lines | |||
| 419 | struct aspeed_vuart *vuart; | 419 | struct aspeed_vuart *vuart; |
| 420 | struct device_node *np; | 420 | struct device_node *np; |
| 421 | struct resource *res; | 421 | struct resource *res; |
| 422 | u32 clk, prop, sirq[2]; | ||
| 423 | int rc, sirq_polarity; | 422 | int rc, sirq_polarity; |
| 423 | u32 prop, sirq[2]; | ||
| 424 | struct clk *vclk; | 424 | struct clk *vclk; |
| 425 | 425 | ||
| 426 | np = pdev->dev.of_node; | 426 | np = pdev->dev.of_node; |
| @@ -447,53 +447,35 @@ static int aspeed_vuart_probe(struct platform_device *pdev) · 20 unmodified lines | |||
| 447 | port.port.status = UPSTAT_SYNC_FIFO; | 447 | port.port.status = UPSTAT_SYNC_FIFO; |
| 448 | port.port.dev = &pdev->dev; | 448 | port.port.dev = &pdev->dev; |
| 449 | port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); | 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 | port.bugs |= UART_BUG_TXRACE; | 452 | port.bugs |= UART_BUG_TXRACE; |
| 451 | 453 | ||
| 452 | rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); | 454 | rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); |
| 453 | if (rc < 0) | 455 | if (rc < 0) |
| 454 | return rc; | 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 | vclk = devm_clk_get_enabled(dev, NULL); | 464 | vclk = devm_clk_get_enabled(dev, NULL); |
| 458 | if (IS_ERR(vclk)) { | 465 | if (IS_ERR(vclk)) { |
| 459 | rc = dev_err_probe(dev, PTR_ERR(vclk), "clk or clock-frequency not defined\n"); | 466 | rc = dev_err_probe(dev, PTR_ERR(vclk), "clk or clock-frequency not defined\n"); |
| 460 | goto err_sysfs_remove; | 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 | /* If current-speed was set, then try not to change it. */ | 473 | /* If current-speed was set, then try not to change it. */ |
| 467 | if (of_property_read_u32(np, "current-speed", &prop) == 0) | 474 | if (of_property_read_u32(np, "current-speed", &prop) == 0) |
| 468 | port.port.custom_divisor = clk / (16 * prop); | 475 | port.port.custom_divisor = port.port.uartclk / (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; | ||
| 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 | port.port.handle_irq = aspeed_vuart_handle_irq; | 477 | port.port.handle_irq = aspeed_vuart_handle_irq; |
| 489 | port.port.iotype = UPIO_MEM; | ||
| 490 | port.port.type = PORT_ASPEED_VUART; | 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 | if (port.port.fifosize) | 480 | if (port.port.fifosize) |
| 499 | port.capabilities = UART_CAP_FIFO; | 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 | rc = serial8250_register_8250_port(&port); | 486 | rc = serial8250_register_8250_port(&port); |
| 505 | if (rc < 0) | 487 | if (rc < 0) |
| 506 | goto err_clk_disable; | 488 | goto err_sysfs_remove; |
| 507 | 489 | ||
| 508 | vuart->line = rc; | 490 | vuart->line = rc; |
| 509 | vuart->port = serial8250_get_port(vuart->line); | 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 | rc = aspeed_vuart_set_lpc_address(vuart, prop); | 511 | rc = aspeed_vuart_set_lpc_address(vuart, prop); |
| 530 | if (rc < 0) { | 512 | if (rc < 0) { |
| 531 | dev_err_probe(dev, rc, "invalid value in aspeed,lpc-io-reg property\n"); | 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 | rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", sirq, 2); | 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 | rc = aspeed_vuart_set_sirq(vuart, sirq[0]); | 523 | rc = aspeed_vuart_set_sirq(vuart, sirq[0]); |
| 542 | if (rc < 0) { | 524 | if (rc < 0) { |
| 543 | dev_err_probe(dev, rc, "invalid sirq number in aspeed,lpc-interrupts property\n"); | 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 | sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]); | 529 | sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]); |
| 548 | if (sirq_polarity < 0) { | 530 | if (sirq_polarity < 0) { |
| 549 | rc = dev_err_probe(dev, sirq_polarity, | 531 | rc = dev_err_probe(dev, sirq_polarity, |
| 550 | "invalid sirq polarity in aspeed,lpc-interrupts property\n"); | 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 | aspeed_vuart_set_sirq_polarity(vuart, sirq_polarity); | 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 | return 0; | 542 | return 0; |
| 561 | 543 | ||
| 562 | err_clk_disable: | ||
| 563 | irq_dispose_mapping(port.port.irq); | ||
| 564 | err_sysfs_remove: | 544 | err_sysfs_remove: |
| 565 | sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); | 545 | sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); |
| 566 | return rc; | 546 | return rc; |
| @@ -45,10 +45,6 @@ struct bcm2835aux_data { · 44 unmodified lines | |||
| 45 | u32 cntl; | 45 | u32 cntl; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | struct bcm2835_aux_serial_driver_data { | ||
| 49 | resource_size_t offset; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) | 48 | static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) |
| 53 | { | 49 | { |
| 54 | if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { | 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 | static int bcm2835aux_serial_probe(struct platform_device *pdev) | 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 | struct uart_8250_port up = { }; | 85 | struct uart_8250_port up = { }; |
| 90 | struct bcm2835aux_data *data; | 86 | struct bcm2835aux_data *data; |
| 91 | resource_size_t offset = 0; | ||
| 92 | struct resource *res; | 87 | struct resource *res; |
| 93 | unsigned int uartclk; | 88 | unsigned int uartclk; |
| 94 | int ret; | 89 | int ret; |
| @@ -101,12 +96,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 101 | /* initialize data */ | 96 | /* initialize data */ |
| 102 | up.capabilities = UART_CAP_FIFO | UART_CAP_MINI; | 97 | up.capabilities = UART_CAP_FIFO | UART_CAP_MINI; |
| 103 | up.port.dev = &pdev->dev; | 98 | up.port.dev = &pdev->dev; |
| 104 | up.port.regshift = 2; | ||
| 105 | up.port.type = PORT_16550; | 99 | up.port.type = PORT_16550; |
| 106 | up.port.iotype = UPIO_MEM; | 100 | up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_IOREMAP; |
| 107 | up.port.fifosize = 8; | ||
| 108 | up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE | | ||
| 109 | UPF_SKIP_TEST | UPF_IOREMAP; | ||
| 110 | up.port.rs485_config = serial8250_em485_config; | 101 | up.port.rs485_config = serial8250_em485_config; |
| 111 | up.port.rs485_supported = serial8250_em485_supported; | 102 | up.port.rs485_supported = serial8250_em485_supported; |
| 112 | up.rs485_start_tx = bcm2835aux_rs485_start_tx; | 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 | if (IS_ERR(data->clk)) | 113 | if (IS_ERR(data->clk)) |
| 123 | return dev_err_probe(&pdev->dev, PTR_ERR(data->clk), "could not get clk\n"); | 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 | /* map the main registers */ | 116 | /* map the main registers */ |
| 132 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 117 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 133 | if (!res) { | 118 | if (!res) { |
| @@ -135,52 +120,40 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 135 | return -EINVAL; | 120 | return -EINVAL; |
| 136 | } | 121 | } |
| 137 | 122 | ||
| 138 | bcm_data = device_get_match_data(&pdev->dev); | 123 | up.port.mapbase = res->start; |
| 139 | 124 | up.port.mapsize = resource_size(res); | |
| 140 | /* Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi) | 125 | |
| 141 | * describe the miniuart with a base address that encompasses the auxiliary | 126 | bcm2835_swnode = device_get_match_data(&pdev->dev); |
| 142 | * registers shared between the miniuart and spi. | 127 | if (bcm2835_swnode) { |
| 143 | * | 128 | ret = device_add_software_node(&pdev->dev, bcm2835_swnode); |
| 144 | * This is due to historical reasons, see discussion here : | 129 | if (ret) |
| 145 | * https://edk2.groups.io/g/devel/topic/87501357#84349 | 130 | return ret; |
| 146 | * | 131 | } |
| 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; | ||
| 152 | 132 | ||
| 153 | up.port.mapbase = res->start + offset; | 133 | ret = uart_read_port_properties(&up.port); |
| 154 | up.port.mapsize = resource_size(res) - offset; | 134 | if (ret) |
| 135 | goto rm_swnode; | ||
| 155 | 136 | ||
| 156 | /* Check for a fixed line number */ | 137 | up.port.regshift = 2; |
| 157 | ret = of_alias_get_id(pdev->dev.of_node, "serial"); | 138 | up.port.fifosize = 8; |
| 158 | if (ret >= 0) | ||
| 159 | up.port.line = ret; | ||
| 160 | 139 | ||
| 161 | /* enable the clock as a last step */ | 140 | /* enable the clock as a last step */ |
| 162 | ret = clk_prepare_enable(data->clk); | 141 | ret = clk_prepare_enable(data->clk); |
| 163 | if (ret) { | 142 | if (ret) { |
| 164 | dev_err(&pdev->dev, "unable to enable uart clock - %d\n", | 143 | dev_err_probe(&pdev->dev, ret, "unable to enable uart clock\n"); |
| 165 | ret); | 144 | goto rm_swnode; |
| 166 | return ret; | ||
| 167 | } | 145 | } |
| 168 | 146 | ||
| 169 | uartclk = clk_get_rate(data->clk); | 147 | uartclk = clk_get_rate(data->clk); |
| 170 | if (!uartclk) { | 148 | if (uartclk) |
| 171 | ret = device_property_read_u32(&pdev->dev, "clock-frequency", &uartclk); | 149 | up.port.uartclk = uartclk; |
| 172 | if (ret) { | ||
| 173 | dev_err_probe(&pdev->dev, ret, "could not get clk rate\n"); | ||
| 174 | goto dis_clk; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | 150 | ||
| 178 | /* the HW-clock divider for bcm2835aux is 8, | 151 | /* the HW-clock divider for bcm2835aux is 8, |
| 179 | * but 8250 expects a divider of 16, | 152 | * but 8250 expects a divider of 16, |
| 180 | * so we have to multiply the actual clock by 2 | 153 | * so we have to multiply the actual clock by 2 |
| 181 | * to get identical baudrates. | 154 | * to get identical baudrates. |
| 182 | */ | 155 | */ |
| 183 | up.port.uartclk = uartclk * 2; | 156 | up.port.uartclk *= 2; |
| 184 | 157 | ||
| 185 | /* register the port */ | 158 | /* register the port */ |
| 186 | ret = serial8250_register_8250_port(&up); | 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 | dis_clk: | 168 | dis_clk: |
| 196 | clk_disable_unprepare(data->clk); | 169 | clk_disable_unprepare(data->clk); |
| 170 | rm_swnode: | ||
| 171 | device_remove_software_node(&pdev->dev); | ||
| 197 | return ret; | 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 | serial8250_unregister_port(data->line); | 179 | serial8250_unregister_port(data->line); |
| 205 | clk_disable_unprepare(data->clk); | 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 = { | 184 | /* |
| 209 | .offset = 0x40, | 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 | static const struct of_device_id bcm2835aux_serial_match[] = { | 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 | MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match); | 208 | MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match); |
| 217 | 209 | ||
| 218 | static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = { | 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 | MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match); | 214 | MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match); |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | |||
| 22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
| 24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
| 25 | #include <linux/units.h> | ||
| 25 | 26 | ||
| 26 | #include "8250.h" | 27 | #include "8250.h" |
| 27 | 28 | ||
| @@ -187,21 +188,19 @@ · 159 unmodified lines | |||
| 187 | #define TX_BUF_SIZE 4096 | 188 | #define TX_BUF_SIZE 4096 |
| 188 | #define RX_BUF_SIZE 4096 | 189 | #define RX_BUF_SIZE 4096 |
| 189 | #define RX_BUFS_COUNT 2 | 190 | #define RX_BUFS_COUNT 2 |
| 190 | #define KHZ 1000 | ||
| 191 | #define MHZ(x) ((x) * KHZ * KHZ) | ||
| 192 | 191 | ||
| 193 | static const u32 brcmstb_rate_table[] = { | 192 | static const u32 brcmstb_rate_table[] = { |
| 194 | MHZ(81), | 193 | 81 * HZ_PER_MHZ, |
| 195 | MHZ(108), | 194 | 108 * HZ_PER_MHZ, |
| 196 | MHZ(64), /* Actually 64285715 for some chips */ | 195 | 64 * HZ_PER_MHZ, /* Actually 64285715 for some chips */ |
| 197 | MHZ(48), | 196 | 48 * HZ_PER_MHZ, |
| 198 | }; | 197 | }; |
| 199 | 198 | ||
| 200 | static const u32 brcmstb_rate_table_7278[] = { | 199 | static const u32 brcmstb_rate_table_7278[] = { |
| 201 | MHZ(81), | 200 | 81 * HZ_PER_MHZ, |
| 202 | MHZ(108), | 201 | 108 * HZ_PER_MHZ, |
| 203 | 0, | 202 | 0, |
| 204 | MHZ(48), | 203 | 48 * HZ_PER_MHZ, |
| 205 | }; | 204 | }; |
| 206 | 205 | ||
| 207 | struct brcmuart_priv { | 206 | struct brcmuart_priv { |
| @@ -936,17 +935,14 @@ static void brcmuart_init_debugfs(struct brcmuart_priv *priv, · 728 unmodified lines | |||
| 936 | static int brcmuart_probe(struct platform_device *pdev) | 935 | static int brcmuart_probe(struct platform_device *pdev) |
| 937 | { | 936 | { |
| 938 | struct resource *regs; | 937 | struct resource *regs; |
| 939 | struct device_node *np = pdev->dev.of_node; | ||
| 940 | const struct of_device_id *of_id = NULL; | 938 | const struct of_device_id *of_id = NULL; |
| 941 | struct uart_8250_port *new_port; | 939 | struct uart_8250_port *new_port; |
| 942 | struct device *dev = &pdev->dev; | 940 | struct device *dev = &pdev->dev; |
| 943 | struct brcmuart_priv *priv; | 941 | struct brcmuart_priv *priv; |
| 944 | struct clk *baud_mux_clk; | 942 | struct clk *baud_mux_clk; |
| 945 | struct uart_8250_port up; | 943 | struct uart_8250_port up; |
| 946 | int irq; | ||
| 947 | void __iomem *membase = NULL; | 944 | void __iomem *membase = NULL; |
| 948 | resource_size_t mapbase = 0; | 945 | resource_size_t mapbase = 0; |
| 949 | u32 clk_rate = 0; | ||
| 950 | int ret; | 946 | int ret; |
| 951 | int x; | 947 | int x; |
| 952 | int dma_irq; | 948 | int dma_irq; |
| @@ -954,15 +950,12 @@ static int brcmuart_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 954 | "uart", "dma_rx", "dma_tx", "dma_intr2", "dma_arb" | 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 | priv = devm_kzalloc(dev, sizeof(struct brcmuart_priv), | 953 | priv = devm_kzalloc(dev, sizeof(struct brcmuart_priv), |
| 961 | GFP_KERNEL); | 954 | GFP_KERNEL); |
| 962 | if (!priv) | 955 | if (!priv) |
| 963 | return -ENOMEM; | 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 | if (!of_id || !of_id->data) | 959 | if (!of_id || !of_id->data) |
| 967 | priv->rate_table = brcmstb_rate_table; | 960 | priv->rate_table = brcmstb_rate_table; |
| 968 | else | 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 | /* See if a Baud clock has been specified */ | 1026 | /* See if a Baud clock has been specified */ |
| 1018 | baud_mux_clk = devm_clk_get_optional_enabled(dev, "sw_baud"); | 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 | priv->baud_mux_clk = baud_mux_clk; | 1034 | priv->baud_mux_clk = baud_mux_clk; |
| 1026 | init_real_clk_rates(dev, priv); | 1035 | init_real_clk_rates(dev, priv); |
| 1027 | clk_rate = priv->default_mux_rate; | 1036 | up.port.uartclk = priv->default_mux_rate; |
| 1028 | } else { | 1037 | } else { |
| 1029 | dev_dbg(dev, "BAUD MUX clock not specified\n"); | 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 | /* setup HR timer */ | 1041 | /* setup HR timer */ |
| 1061 | hrtimer_init(&priv->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 1042 | hrtimer_init(&priv->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
| 1062 | priv->hrt.function = brcmuart_hrtimer_func; | 1043 | priv->hrt.function = brcmuart_hrtimer_func; |
| @@ -9,7 +9,6 @@ · 8 unmodified lines | |||
| 9 | * LCR is written whilst busy. If it is, then a busy detect interrupt is | 9 | * LCR is written whilst busy. If it is, then a busy detect interrupt is |
| 10 | * raised, the LCR needs to be rewritten and the uart status register read. | 10 | * raised, the LCR needs to be rewritten and the uart status register read. |
| 11 | */ | 11 | */ |
| 12 | #include <linux/acpi.h> | ||
| 13 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
| 14 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| 15 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| @@ -17,7 +16,6 @@ · 1 unmodified line | |||
| 17 | #include <linux/mod_devicetable.h> | 16 | #include <linux/mod_devicetable.h> |
| 18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 19 | #include <linux/notifier.h> | 18 | #include <linux/notifier.h> |
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 22 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
| 23 | #include <linux/property.h> | 21 | #include <linux/property.h> |
| @@ -56,6 +54,7 @@ · 32 unmodified lines | |||
| 56 | #define DW_UART_QUIRK_ARMADA_38X BIT(1) | 54 | #define DW_UART_QUIRK_ARMADA_38X BIT(1) |
| 57 | #define DW_UART_QUIRK_SKIP_SET_RATE BIT(2) | 55 | #define DW_UART_QUIRK_SKIP_SET_RATE BIT(2) |
| 58 | #define DW_UART_QUIRK_IS_DMA_FC BIT(3) | 56 | #define DW_UART_QUIRK_IS_DMA_FC BIT(3) |
| 57 | #define DW_UART_QUIRK_APMC0D08 BIT(4) | ||
| 59 | 58 | ||
| 60 | static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb) | 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 | static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) | 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 | #ifdef CONFIG_64BIT | 449 | #ifdef CONFIG_64BIT |
| 459 | if (quirks & DW_UART_QUIRK_OCTEON) { | 450 | if (quirks & DW_UART_QUIRK_OCTEON) { |
| 460 | p->serial_in = dw8250_serial_inq; | 451 | p->serial_in = dw8250_serial_inq; |
| 461 | p->serial_out = dw8250_serial_outq; | 452 | p->serial_out = dw8250_serial_outq; |
| 462 | p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; | 453 | p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; |
| 463 | p->type = PORT_OCTEON; | 454 | p->type = PORT_OCTEON; |
| 464 | data->skip_autocfg = true; | 455 | data->skip_autocfg = true; |
| 465 | } | 456 | } |
| 466 | #endif | 457 | #endif |
| 467 | 458 | ||
| 468 | if (of_device_is_big_endian(np)) { | 459 | if (quirks & DW_UART_QUIRK_ARMADA_38X) |
| 469 | p->iotype = UPIO_MEM32BE; | 460 | p->serial_out = dw8250_serial_out38x; |
| 470 | p->serial_in = dw8250_serial_in32be; | 461 | if (quirks & DW_UART_QUIRK_SKIP_SET_RATE) |
| 471 | p->serial_out = dw8250_serial_out32be; | 462 | p->set_termios = dw8250_do_set_termios; |
| 472 | } | 463 | if (quirks & DW_UART_QUIRK_IS_DMA_FC) { |
| 473 | 464 | data->data.dma.txconf.device_fc = 1; | |
| 474 | if (quirks & DW_UART_QUIRK_ARMADA_38X) | 465 | data->data.dma.rxconf.device_fc = 1; |
| 475 | p->serial_out = dw8250_serial_out38x; | 466 | data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma; |
| 476 | if (quirks & DW_UART_QUIRK_SKIP_SET_RATE) | 467 | data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma; |
| 477 | p->set_termios = dw8250_do_set_termios; | 468 | } |
| 478 | if (quirks & DW_UART_QUIRK_IS_DMA_FC) { | 469 | if (quirks & DW_UART_QUIRK_APMC0D08) { |
| 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)) { | ||
| 486 | p->iotype = UPIO_MEM32; | 470 | p->iotype = UPIO_MEM32; |
| 487 | p->regshift = 2; | 471 | p->regshift = 2; |
| 488 | p->serial_in = dw8250_serial_in32; | 472 | p->serial_in = dw8250_serial_in32; |
| @@ -510,39 +494,21 @@ static int dw8250_probe(struct platform_device *pdev) · 21 unmodified lines | |||
| 510 | struct device *dev = &pdev->dev; | 494 | struct device *dev = &pdev->dev; |
| 511 | struct dw8250_data *data; | 495 | struct dw8250_data *data; |
| 512 | struct resource *regs; | 496 | struct resource *regs; |
| 513 | int irq; | ||
| 514 | int err; | 497 | int err; |
| 515 | u32 val; | ||
| 516 | 498 | ||
| 517 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 499 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 518 | if (!regs) | 500 | if (!regs) |
| 519 | return dev_err_probe(dev, -EINVAL, "no registers defined\n"); | 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 | spin_lock_init(&p->lock); | 503 | spin_lock_init(&p->lock); |
| 529 | p->mapbase = regs->start; | ||
| 530 | p->irq = irq; | ||
| 531 | p->handle_irq = dw8250_handle_irq; | 504 | p->handle_irq = dw8250_handle_irq; |
| 532 | p->pm = dw8250_do_pm; | 505 | p->pm = dw8250_do_pm; |
| 533 | p->type = PORT_8250; | 506 | p->type = PORT_8250; |
| 534 | p->flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; | 507 | p->flags = UPF_FIXED_PORT; |
| 535 | p->dev = dev; | 508 | p->dev = dev; |
| 536 | p->iotype = UPIO_MEM; | ||
| 537 | p->serial_in = dw8250_serial_in; | ||
| 538 | p->serial_out = dw8250_serial_out; | ||
| 539 | p->set_ldisc = dw8250_set_ldisc; | 509 | p->set_ldisc = dw8250_set_ldisc; |
| 540 | p->set_termios = dw8250_set_termios; | 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 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | 512 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
| 547 | if (!data) | 513 | if (!data) |
| 548 | return -ENOMEM; | 514 | return -ENOMEM; |
| @@ -554,15 +520,35 @@ static int dw8250_probe(struct platform_device *pdev) · 5 unmodified lines | |||
| 554 | data->uart_16550_compatible = device_property_read_bool(dev, | 520 | data->uart_16550_compatible = device_property_read_bool(dev, |
| 555 | "snps,uart-16550-compatible"); | 521 | "snps,uart-16550-compatible"); |
| 556 | 522 | ||
| 557 | err = device_property_read_u32(dev, "reg-shift", &val); | 523 | p->mapbase = regs->start; |
| 558 | if (!err) | 524 | p->mapsize = resource_size(regs); |
| 559 | p->regshift = val; | ||
| 560 | 525 | ||
| 561 | err = device_property_read_u32(dev, "reg-io-width", &val); | 526 | p->membase = devm_ioremap(dev, p->mapbase, p->mapsize); |
| 562 | if (!err && val == 4) { | 527 | if (!p->membase) |
| 563 | p->iotype = UPIO_MEM32; | 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 | p->serial_in = dw8250_serial_in32; | 543 | p->serial_in = dw8250_serial_in32; |
| 565 | p->serial_out = dw8250_serial_out32; | 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 | if (device_property_read_bool(dev, "dcd-override")) { | 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 | data->msr_mask_off |= UART_MSR_TERI; | 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 | /* If there is separate baudclk, get the rate from it. */ | 578 | /* If there is separate baudclk, get the rate from it. */ |
| 596 | data->clk = devm_clk_get_optional_enabled(dev, "baudclk"); | 579 | data->clk = devm_clk_get_optional_enabled(dev, "baudclk"); |
| 597 | if (data->clk == NULL) | 580 | if (data->clk == NULL) |
| 598 | data->clk = devm_clk_get_optional_enabled(dev, NULL); | 581 | data->clk = devm_clk_get_optional_enabled(dev, NULL); |
| 599 | if (IS_ERR(data->clk)) | 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 | INIT_WORK(&data->clk_work, dw8250_clk_work_cb); | 586 | INIT_WORK(&data->clk_work, dw8250_clk_work_cb); |
| 603 | data->clk_notifier.notifier_call = dw8250_clk_notifier_cb; | 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 | MODULE_DEVICE_TABLE(of, dw8250_of_match); | 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 | static const struct acpi_device_id dw8250_acpi_match[] = { | 754 | static const struct acpi_device_id dw8250_acpi_match[] = { |
| 766 | { "80860F0A", (kernel_ulong_t)&dw8250_dw_apb }, | 755 | { "80860F0A", (kernel_ulong_t)&dw8250_dw_apb }, |
| 767 | { "8086228A", (kernel_ulong_t)&dw8250_dw_apb }, | 756 | { "8086228A", (kernel_ulong_t)&dw8250_dw_apb }, |
| 768 | { "AMD0020", (kernel_ulong_t)&dw8250_dw_apb }, | 757 | { "AMD0020", (kernel_ulong_t)&dw8250_dw_apb }, |
| 769 | { "AMDI0020", (kernel_ulong_t)&dw8250_dw_apb }, | 758 | { "AMDI0020", (kernel_ulong_t)&dw8250_dw_apb }, |
| 770 | { "AMDI0022", (kernel_ulong_t)&dw8250_dw_apb }, | 759 | { "AMDI0022", (kernel_ulong_t)&dw8250_dw_apb }, |
| 771 | { "APMC0D08", (kernel_ulong_t)&dw8250_dw_apb}, | 760 | { "APMC0D08", (kernel_ulong_t)&dw8250_apmc0d08 }, |
| 772 | { "BRCM2032", (kernel_ulong_t)&dw8250_dw_apb }, | 761 | { "BRCM2032", (kernel_ulong_t)&dw8250_dw_apb }, |
| 773 | { "HISI0031", (kernel_ulong_t)&dw8250_dw_apb }, | 762 | { "HISI0031", (kernel_ulong_t)&dw8250_dw_apb }, |
| 774 | { "INT33C4", (kernel_ulong_t)&dw8250_dw_apb }, | 763 | { "INT33C4", (kernel_ulong_t)&dw8250_dw_apb }, |
| @@ -6,23 +6,29 @@ · 5 unmodified lines | |||
| 6 | * | 6 | * |
| 7 | * Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved. | 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 | #include <linux/dmi.h> | 12 | #include <linux/dmi.h> |
| 13 | #include <linux/interrupt.h> | ||
| 11 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 12 | #include <linux/kernel.h> | 15 | #include <linux/math.h> |
| 13 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 14 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/pm.h> | ||
| 15 | #include <linux/property.h> | 20 | #include <linux/property.h> |
| 21 | #include <linux/string.h> | ||
| 22 | #include <linux/types.h> | ||
| 23 | |||
| 24 | #include <linux/serial_8250.h> | ||
| 16 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
| 17 | #include <linux/serial_reg.h> | 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 | #include <asm/byteorder.h> | 28 | #include <asm/byteorder.h> |
| 24 | 29 | ||
| 25 | #include "8250.h" | 30 | #include "8250.h" |
| 31 | #include "8250_pcilib.h" | ||
| 26 | 32 | ||
| 27 | #define PCI_DEVICE_ID_ACCESSIO_COM_2S 0x1052 | 33 | #define PCI_DEVICE_ID_ACCESSIO_COM_2S 0x1052 |
| 28 | #define PCI_DEVICE_ID_ACCESSIO_COM_4S 0x105d | 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 | struct uart_8250_port *port) | 235 | struct uart_8250_port *port) |
| 230 | { | 236 | { |
| 231 | const struct exar8250_board *board = priv->board; | 237 | const struct exar8250_board *board = priv->board; |
| 232 | unsigned int bar = 0; | ||
| 233 | unsigned char status; | 238 | unsigned char status; |
| 239 | int err; | ||
| 234 | 240 | ||
| 235 | port->port.iotype = UPIO_MEM; | 241 | err = serial8250_pci_setup_port(pcidev, port, 0, offset, board->reg_shift); |
| 236 | port->port.mapbase = pci_resource_start(pcidev, bar) + offset; | 242 | if (err) |
| 237 | port->port.membase = priv->virt + offset; | 243 | return err; |
| 238 | port->port.regshift = board->reg_shift; | ||
| 239 | 244 | ||
| 240 | /* | 245 | /* |
| 241 | * XR17V35x UARTs have an extra divisor register, DLD that gets enabled | 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 | return NULL; | 380 | return NULL; |
| 376 | 381 | ||
| 377 | pdev->dev.parent = &pcidev->dev; | 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 | if (device_add_software_node(&pdev->dev, node) < 0 || | 385 | if (device_add_software_node(&pdev->dev, node) < 0 || |
| 381 | platform_device_add(pdev) < 0) { | 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 | uart.port.irq = pci_irq_vector(pcidev, 0); | 718 | uart.port.irq = pci_irq_vector(pcidev, 0); |
| 714 | uart.port.dev = &pcidev->dev; | 719 | uart.port.dev = &pcidev->dev; |
| 715 | 720 | ||
| 721 | /* Clear interrupts */ | ||
| 722 | exar_misc_clear(priv); | ||
| 723 | |||
| 716 | rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler, | 724 | rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler, |
| 717 | IRQF_SHARED, "exar_uart", priv); | 725 | IRQF_SHARED, "exar_uart", priv); |
| 718 | if (rc) | 726 | if (rc) |
| 719 | return rc; | 727 | return rc; |
| 720 | 728 | ||
| 721 | /* Clear interrupts */ | ||
| 722 | exar_misc_clear(priv); | ||
| 723 | |||
| 724 | for (i = 0; i < nr_ports && i < maxnr; i++) { | 729 | for (i = 0; i < nr_ports && i < maxnr; i++) { |
| 725 | rc = board->setup(priv, pcidev, &uart, i); | 730 | rc = board->setup(priv, pcidev, &uart, i); |
| 726 | if (rc) { | 731 | if (rc) { |
| @@ -753,28 +758,24 @@ static void exar_pci_remove(struct pci_dev *pcidev) · 26 unmodified lines | |||
| 753 | for (i = 0; i < priv->nr; i++) | 758 | for (i = 0; i < priv->nr; i++) |
| 754 | serial8250_unregister_port(priv->line[i]); | 759 | serial8250_unregister_port(priv->line[i]); |
| 755 | 760 | ||
| 761 | /* Ensure that every init quirk is properly torn down */ | ||
| 756 | if (priv->board->exit) | 762 | if (priv->board->exit) |
| 757 | priv->board->exit(pcidev); | 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); | 768 | struct exar8250 *priv = dev_get_drvdata(dev); |
| 763 | struct exar8250 *priv = pci_get_drvdata(pcidev); | ||
| 764 | unsigned int i; | 769 | unsigned int i; |
| 765 | 770 | ||
| 766 | for (i = 0; i < priv->nr; i++) | 771 | for (i = 0; i < priv->nr; i++) |
| 767 | if (priv->line[i] >= 0) | 772 | if (priv->line[i] >= 0) |
| 768 | serial8250_suspend_port(priv->line[i]); | 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 | return 0; | 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 | struct exar8250 *priv = dev_get_drvdata(dev); | 780 | struct exar8250 *priv = dev_get_drvdata(dev); |
| 780 | unsigned int i; | 781 | unsigned int i; |
| @@ -788,7 +789,7 @@ static int __maybe_unused exar_resume(struct device *dev) · 7 unmodified lines | |||
| 788 | return 0; | 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 | static const struct exar8250_board pbn_fastcom335_2 = { | 794 | static const struct exar8250_board pbn_fastcom335_2 = { |
| 794 | .num_ports = 2, | 795 | .num_ports = 2, |
| @@ -938,12 +939,13 @@ static struct pci_driver exar_pci_driver = { · 143 unmodified lines | |||
| 938 | .probe = exar_pci_probe, | 939 | .probe = exar_pci_probe, |
| 939 | .remove = exar_pci_remove, | 940 | .remove = exar_pci_remove, |
| 940 | .driver = { | 941 | .driver = { |
| 941 | .pm = &exar_pci_pm, | 942 | .pm = pm_sleep_ptr(&exar_pci_pm), |
| 942 | }, | 943 | }, |
| 943 | .id_table = exar_pci_tbl, | 944 | .id_table = exar_pci_tbl, |
| 944 | }; | 945 | }; |
| 945 | module_pci_driver(exar_pci_driver); | 946 | module_pci_driver(exar_pci_driver); |
| 946 | 947 | ||
| 948 | MODULE_IMPORT_NS(SERIAL_8250_PCI); | ||
| 947 | MODULE_LICENSE("GPL"); | 949 | MODULE_LICENSE("GPL"); |
| 948 | MODULE_DESCRIPTION("Exar Serial Driver"); | 950 | MODULE_DESCRIPTION("Exar Serial Driver"); |
| 949 | MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>"); | 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 | struct ingenic_uart_data *data; | 234 | struct ingenic_uart_data *data; |
| 235 | const struct ingenic_uart_config *cdata; | 235 | const struct ingenic_uart_config *cdata; |
| 236 | struct resource *regs; | 236 | struct resource *regs; |
| 237 | int irq, err, line; | 237 | int err; |
| 238 | 238 | ||
| 239 | cdata = of_device_get_match_data(&pdev->dev); | 239 | cdata = of_device_get_match_data(&pdev->dev); |
| 240 | if (!cdata) { | 240 | if (!cdata) { |
| @@ -242,10 +242,6 @@ static int ingenic_uart_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 242 | return -ENODEV; | 242 | return -ENODEV; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | irq = platform_get_irq(pdev, 0); | ||
| 246 | if (irq < 0) | ||
| 247 | return irq; | ||
| 248 | |||
| 249 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 245 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 250 | if (!regs) { | 246 | if (!regs) { |
| 251 | dev_err(&pdev->dev, "no registers defined\n"); | 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 | spin_lock_init(&uart.port.lock); | 255 | spin_lock_init(&uart.port.lock); |
| 260 | uart.port.type = PORT_16550A; | 256 | uart.port.type = PORT_16550A; |
| 261 | uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE; | 257 | uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE; |
| 262 | uart.port.iotype = UPIO_MEM; | ||
| 263 | uart.port.mapbase = regs->start; | 258 | uart.port.mapbase = regs->start; |
| 264 | uart.port.regshift = 2; | ||
| 265 | uart.port.serial_out = ingenic_uart_serial_out; | 259 | uart.port.serial_out = ingenic_uart_serial_out; |
| 266 | uart.port.serial_in = ingenic_uart_serial_in; | 260 | uart.port.serial_in = ingenic_uart_serial_in; |
| 267 | uart.port.irq = irq; | ||
| 268 | uart.port.dev = &pdev->dev; | 261 | uart.port.dev = &pdev->dev; |
| 269 | uart.port.fifosize = cdata->fifosize; | ||
| 270 | uart.tx_loadsz = cdata->tx_loadsz; | 262 | uart.tx_loadsz = cdata->tx_loadsz; |
| 271 | uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE; | 263 | uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE; |
| 272 | 264 | ||
| 273 | /* Check for a fixed line number */ | 265 | err = uart_read_port_properties(&uart.port); |
| 274 | line = of_alias_get_id(pdev->dev.of_node, "serial"); | 266 | if (err) |
| 275 | if (line >= 0) | 267 | return err; |
| 276 | uart.port.line = line; | 268 | |
| 269 | uart.port.regshift = 2; | ||
| 270 | uart.port.fifosize = cdata->fifosize; | ||
| 277 | 271 | ||
| 278 | uart.port.membase = devm_ioremap(&pdev->dev, regs->start, | 272 | uart.port.membase = devm_ioremap(&pdev->dev, regs->start, |
| 279 | resource_size(regs)); | 273 | resource_size(regs)); |
| @@ -92,11 +92,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) · 91 unmodified lines | |||
| 92 | struct lpc18xx_uart_data *data; | 92 | struct lpc18xx_uart_data *data; |
| 93 | struct uart_8250_port uart; | 93 | struct uart_8250_port uart; |
| 94 | struct resource *res; | 94 | struct resource *res; |
| 95 | int irq, ret; | 95 | int ret; |
| 96 | |||
| 97 | irq = platform_get_irq(pdev, 0); | ||
| 98 | if (irq < 0) | ||
| 99 | return irq; | ||
| 100 | 96 | ||
| 101 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 97 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 102 | if (!res) { | 98 | if (!res) { |
| @@ -139,19 +135,12 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) · 36 unmodified lines | |||
| 139 | goto dis_clk_reg; | 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 | data->dma.rx_param = data; | 138 | data->dma.rx_param = data; |
| 147 | data->dma.tx_param = data; | 139 | data->dma.tx_param = data; |
| 148 | 140 | ||
| 149 | spin_lock_init(&uart.port.lock); | 141 | spin_lock_init(&uart.port.lock); |
| 150 | uart.port.dev = &pdev->dev; | 142 | uart.port.dev = &pdev->dev; |
| 151 | uart.port.irq = irq; | ||
| 152 | uart.port.iotype = UPIO_MEM32; | ||
| 153 | uart.port.mapbase = res->start; | 143 | uart.port.mapbase = res->start; |
| 154 | uart.port.regshift = 2; | ||
| 155 | uart.port.type = PORT_16550A; | 144 | uart.port.type = PORT_16550A; |
| 156 | uart.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST; | 145 | uart.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST; |
| 157 | uart.port.uartclk = clk_get_rate(data->clk_uart); | 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 | uart.port.rs485_supported = lpc18xx_rs485_supported; | 149 | uart.port.rs485_supported = lpc18xx_rs485_supported; |
| 161 | uart.port.serial_out = lpc18xx_uart_serial_out; | 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 | uart.dma = &data->dma; | 159 | uart.dma = &data->dma; |
| 164 | uart.dma->rxconf.src_maxburst = 1; | 160 | uart.dma->rxconf.src_maxburst = 1; |
| 165 | uart.dma->txconf.dst_maxburst = 1; | 161 | uart.dma->txconf.dst_maxburst = 1; |
| @@ -4,7 +4,10 @@ · 3 unmodified lines | |||
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp. | 5 | * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp. |
| 6 | */ | 6 | */ |
| 7 | |||
| 8 | #include <linux/bits.h> | ||
| 7 | #include <linux/console.h> | 9 | #include <linux/console.h> |
| 10 | #include <linux/math.h> | ||
| 8 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 9 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 10 | #include <linux/serial_core.h> | 13 | #include <linux/serial_core.h> |
| @@ -25,6 +28,36 @@ struct of_serial_info { · 14 unmodified lines | |||
| 25 | int line; | 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 | * Fill a struct uart_port for a given device node | 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 | struct device *dev = &ofdev->dev; | 69 | struct device *dev = &ofdev->dev; |
| 37 | struct device_node *np = dev->of_node; | 70 | struct device_node *np = dev->of_node; |
| 38 | struct uart_port *port = &up->port; | 71 | struct uart_port *port = &up->port; |
| 39 | u32 clk, spd, prop; | 72 | u32 spd; |
| 40 | int ret, irq; | 73 | int ret; |
| 41 | 74 | ||
| 42 | memset(port, 0, sizeof *port); | 75 | memset(port, 0, sizeof *port); |
| 43 | 76 | ||
| 44 | pm_runtime_enable(&ofdev->dev); | 77 | pm_runtime_enable(&ofdev->dev); |
| 45 | pm_runtime_get_sync(&ofdev->dev); | 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 | ret = of_address_to_resource(np, 0, &resource); | 80 | ret = of_address_to_resource(np, 0, &resource); |
| 63 | if (ret) { | 81 | if (ret) { |
| 64 | dev_err_probe(dev, ret, "invalid address\n"); | 82 | dev_err_probe(dev, ret, "invalid address\n"); |
| 65 | goto err_pmruntime; | 83 | goto err_pmruntime; |
| 66 | } | 84 | } |
| 67 | 85 | ||
| 68 | port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | | 86 | port->dev = &ofdev->dev; |
| 69 | UPF_FIXED_TYPE; | 87 | port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE; |
| 70 | spin_lock_init(&port->lock); | 88 | spin_lock_init(&port->lock); |
| 71 | 89 | ||
| 72 | if (resource_type(&resource) == IORESOURCE_IO) { | 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 | } else { | 93 | } else { |
| 76 | port->mapbase = resource.start; | 94 | port->mapbase = resource.start; |
| 77 | port->mapsize = resource_size(&resource); | 95 | port->mapsize = resource_size(&resource); |
| 96 | port->flags |= UPF_IOREMAP; | ||
| 97 | } | ||
| 78 | 98 | ||
| 79 | /* Check for shifted address mapping */ | 99 | ret = uart_read_and_validate_port_properties(port); |
| 80 | if (of_property_read_u32(np, "reg-offset", &prop) == 0) { | 100 | if (ret) |
| 81 | if (prop >= port->mapsize) { | 101 | goto err_pmruntime; |
| 82 | ret = dev_err_probe(dev, -EINVAL, "reg-offset %u exceeds region size %pa\n", | ||
| 83 | prop, &port->mapsize); | ||
| 84 | goto err_pmruntime; | ||
| 85 | } | ||
| 86 | 102 | ||
| 87 | port->mapbase += prop; | 103 | /* Get clk rate through clk driver if present */ |
| 88 | port->mapsize -= prop; | 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; | 111 | port->uartclk = clk_get_rate(info->clk); |
| 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 | } | 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 | /* Compatibility with the deprecated pxa driver and 8250_pxa drivers. */ | 117 | /* Compatibility with the deprecated pxa driver and 8250_pxa drivers. */ |
| 114 | if (of_device_is_compatible(np, "mrvl,mmp-uart")) | 118 | if (of_device_is_compatible(np, "mrvl,mmp-uart")) |
| 115 | port->regshift = 2; | 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 | info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL); | 121 | info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL); |
| 143 | if (IS_ERR(info->rst)) { | 122 | if (IS_ERR(info->rst)) { |
| 144 | ret = PTR_ERR(info->rst); | 123 | ret = PTR_ERR(info->rst); |
| @@ -150,12 +129,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev, · 5 unmodified lines | |||
| 150 | goto err_pmruntime; | 129 | goto err_pmruntime; |
| 151 | 130 | ||
| 152 | port->type = type; | 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 | port->rs485_config = serial8250_em485_config; | 132 | port->rs485_config = serial8250_em485_config; |
| 160 | port->rs485_supported = serial8250_em485_supported; | 133 | port->rs485_supported = serial8250_em485_supported; |
| 161 | up->rs485_start_tx = serial8250_em485_start_tx; | 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 | switch (type) { | 137 | switch (type) { |
| 165 | case PORT_RT2880: | 138 | case PORT_RT2880: |
| 166 | ret = rt288x_setup(port); | 139 | ret = rt288x_setup(port); |
| 167 | if (ret) | 140 | break; |
| 168 | goto err_pmruntime; | 141 | case PORT_NPCM: |
| 142 | ret = npcm_setup(port); | ||
| 143 | break; | ||
| 144 | default: | ||
| 145 | /* Nothing to do */ | ||
| 146 | ret = 0; | ||
| 169 | break; | 147 | break; |
| 170 | } | 148 | } |
| 149 | if (ret) | ||
| 150 | goto err_pmruntime; | ||
| 171 | 151 | ||
| 172 | if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL) && | 152 | if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL) && |
| 173 | (of_device_is_compatible(np, "fsl,ns16550") || | 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 | platform_set_drvdata(ofdev, info); | 220 | platform_set_drvdata(ofdev, info); |
| 241 | return 0; | 221 | return 0; |
| 242 | err_dispose: | 222 | err_dispose: |
| 243 | irq_dispose_mapping(port8250.port.irq); | ||
| 244 | pm_runtime_put_sync(&ofdev->dev); | 223 | pm_runtime_put_sync(&ofdev->dev); |
| 245 | pm_runtime_disable(&ofdev->dev); | 224 | pm_runtime_disable(&ofdev->dev); |
| 246 | err_free: | 225 | err_free: |
| @@ -1394,11 +1394,7 @@ static int omap8250_probe(struct platform_device *pdev) · 1393 unmodified lines | |||
| 1394 | struct uart_8250_port up; | 1394 | struct uart_8250_port up; |
| 1395 | struct resource *regs; | 1395 | struct resource *regs; |
| 1396 | void __iomem *membase; | 1396 | void __iomem *membase; |
| 1397 | int irq, ret; | 1397 | int ret; |
| 1398 | |||
| 1399 | irq = platform_get_irq(pdev, 0); | ||
| 1400 | if (irq < 0) | ||
| 1401 | return irq; | ||
| 1402 | 1398 | ||
| 1403 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1399 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1404 | if (!regs) { | 1400 | if (!regs) { |
| @@ -1419,7 +1415,6 @@ static int omap8250_probe(struct platform_device *pdev) · 14 unmodified lines | |||
| 1419 | up.port.dev = &pdev->dev; | 1415 | up.port.dev = &pdev->dev; |
| 1420 | up.port.mapbase = regs->start; | 1416 | up.port.mapbase = regs->start; |
| 1421 | up.port.membase = membase; | 1417 | up.port.membase = membase; |
| 1422 | up.port.irq = irq; | ||
| 1423 | /* | 1418 | /* |
| 1424 | * It claims to be 16C750 compatible however it is a little different. | 1419 | * It claims to be 16C750 compatible however it is a little different. |
| 1425 | * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to | 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 | * or pm callback. | 1424 | * or pm callback. |
| 1430 | */ | 1425 | */ |
| 1431 | up.port.type = PORT_8250; | 1426 | up.port.type = PORT_8250; |
| 1432 | up.port.iotype = UPIO_MEM; | 1427 | up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | UPF_HARD_FLOW; |
| 1433 | up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | | ||
| 1434 | UPF_HARD_FLOW; | ||
| 1435 | up.port.private_data = priv; | 1428 | up.port.private_data = priv; |
| 1436 | 1429 | ||
| 1437 | up.port.regshift = OMAP_UART_REGSHIFT; | ||
| 1438 | up.port.fifosize = 64; | ||
| 1439 | up.tx_loadsz = 64; | 1430 | up.tx_loadsz = 64; |
| 1440 | up.capabilities = UART_CAP_FIFO; | 1431 | up.capabilities = UART_CAP_FIFO; |
| 1441 | #ifdef CONFIG_PM | 1432 | #ifdef CONFIG_PM |
| @@ -1461,14 +1452,14 @@ static int omap8250_probe(struct platform_device *pdev) · 19 unmodified lines | |||
| 1461 | up.rs485_stop_tx = serial8250_em485_stop_tx; | 1452 | up.rs485_stop_tx = serial8250_em485_stop_tx; |
| 1462 | up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); | 1453 | up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); |
| 1463 | 1454 | ||
| 1464 | ret = of_alias_get_id(np, "serial"); | 1455 | ret = uart_read_port_properties(&up.port); |
| 1465 | if (ret < 0) { | 1456 | if (ret) |
| 1466 | dev_err(&pdev->dev, "failed to get alias\n"); | ||
| 1467 | return ret; | 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 | struct clk *clk; | 1463 | struct clk *clk; |
| 1473 | 1464 | ||
| 1474 | clk = devm_clk_get(&pdev->dev, NULL); | 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 | #endif | 1552 | #endif |
| 1562 | 1553 | ||
| 1563 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | 1554 | irq_set_status_flags(up.port.irq, IRQ_NOAUTOEN); |
| 1564 | ret = devm_request_irq(&pdev->dev, irq, omap8250_irq, 0, | 1555 | ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0, |
| 1565 | dev_name(&pdev->dev), priv); | 1556 | dev_name(&pdev->dev), priv); |
| 1566 | if (ret < 0) | 1557 | if (ret < 0) |
| 1567 | return ret; | 1558 | return ret; |
| @@ -7,23 +7,31 @@ · 6 unmodified lines | |||
| 7 | * Copyright (C) 2022 Microchip Technology Inc., All Rights Reserved. | 7 | * Copyright (C) 2022 Microchip Technology Inc., All Rights Reserved. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/array_size.h> | ||
| 10 | #include <linux/bitfield.h> | 11 | #include <linux/bitfield.h> |
| 11 | #include <linux/bitops.h> | 12 | #include <linux/bits.h> |
| 12 | #include <linux/delay.h> | 13 | #include <linux/circ_buf.h> |
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/gfp_types.h> | ||
| 13 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 14 | #include <linux/iopoll.h> | 18 | #include <linux/iopoll.h> |
| 15 | #include <linux/kernel.h> | 19 | #include <linux/minmax.h> |
| 16 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/mutex.h> | ||
| 22 | #include <linux/overflow.h> | ||
| 17 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| 24 | #include <linux/pm.h> | ||
| 18 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
| 19 | #include <linux/serial_reg.h> | 26 | #include <linux/serial_reg.h> |
| 20 | #include <linux/serial_8250.h> | 27 | #include <linux/serial_8250.h> |
| 21 | #include <linux/slab.h> | 28 | #include <linux/spinlock.h> |
| 22 | #include <linux/string.h> | 29 | #include <linux/string.h> |
| 23 | #include <linux/units.h> | 30 | #include <linux/time.h> |
| 24 | #include <linux/tty.h> | 31 | #include <linux/tty.h> |
| 25 | #include <linux/tty_flip.h> | 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 | #include <asm/byteorder.h> | 36 | #include <asm/byteorder.h> |
| 29 | 37 | ||
| @@ -67,6 +75,7 @@ · 37 unmodified lines | |||
| 67 | #define SYSLOCK_RETRY_CNT 1000 | 75 | #define SYSLOCK_RETRY_CNT 1000 |
| 68 | 76 | ||
| 69 | #define UART_RX_BYTE_FIFO 0x00 | 77 | #define UART_RX_BYTE_FIFO 0x00 |
| 78 | #define UART_TX_BYTE_FIFO 0x00 | ||
| 70 | #define UART_FIFO_CTL 0x02 | 79 | #define UART_FIFO_CTL 0x02 |
| 71 | 80 | ||
| 72 | #define UART_ACTV_REG 0x11 | 81 | #define UART_ACTV_REG 0x11 |
| @@ -81,10 +90,10 @@ · 8 unmodified lines | |||
| 81 | #define ADCL_CFG_PIN_SEL BIT(1) | 90 | #define ADCL_CFG_PIN_SEL BIT(1) |
| 82 | #define ADCL_CFG_EN BIT(0) | 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 | #define BAUD_CLOCK_DIV_INT_MSK GENMASK(31, 8) | 95 | #define BAUD_CLOCK_DIV_INT_MSK GENMASK(31, 8) |
| 86 | #define ADCL_CFG_RTS_DELAY_MASK GENMASK(11, 8) | 96 | #define ADCL_CFG_RTS_DELAY_MASK GENMASK(11, 8) |
| 87 | #define UART_CLOCK_DEFAULT (62500 * HZ_PER_KHZ) | ||
| 88 | 97 | ||
| 89 | #define UART_WAKE_REG 0x8C | 98 | #define UART_WAKE_REG 0x8C |
| 90 | #define UART_WAKE_MASK_REG 0x90 | 99 | #define UART_WAKE_MASK_REG 0x90 |
| @@ -95,13 +104,19 @@ · 4 unmodified lines | |||
| 95 | (UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT) | 104 | (UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT) |
| 96 | 105 | ||
| 97 | #define UART_BAUD_CLK_DIVISOR_REG 0x54 | 106 | #define UART_BAUD_CLK_DIVISOR_REG 0x54 |
| 107 | #define FRAC_DIV_CFG_REG 0x58 | ||
| 98 | 108 | ||
| 99 | #define UART_RESET_REG 0x94 | 109 | #define UART_RESET_REG 0x94 |
| 100 | #define UART_RESET_D3_RESET_DISABLE BIT(16) | 110 | #define UART_RESET_D3_RESET_DISABLE BIT(16) |
| 101 | 111 | ||
| 102 | #define UART_BURST_STATUS_REG 0x9C | 112 | #define UART_BURST_STATUS_REG 0x9C |
| 113 | #define UART_TX_BURST_FIFO 0xA0 | ||
| 103 | #define UART_RX_BURST_FIFO 0xA4 | 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 | #define MAX_PORTS 4 | 120 | #define MAX_PORTS 4 |
| 106 | #define PORT_OFFSET 0x100 | 121 | #define PORT_OFFSET 0x100 |
| 107 | #define RX_BUF_SIZE 512 | 122 | #define RX_BUF_SIZE 512 |
| @@ -109,6 +124,7 @@ · 1 unmodified line | |||
| 109 | #define UART_BURST_SIZE 4 | 124 | #define UART_BURST_SIZE 4 |
| 110 | 125 | ||
| 111 | #define UART_BST_STAT_RX_COUNT_MASK 0x00FF | 126 | #define UART_BST_STAT_RX_COUNT_MASK 0x00FF |
| 127 | #define UART_BST_STAT_TX_COUNT_MASK 0xFF00 | ||
| 112 | #define UART_BST_STAT_IIR_INT_PEND 0x100000 | 128 | #define UART_BST_STAT_IIR_INT_PEND 0x100000 |
| 113 | #define UART_LSR_OVERRUN_ERR_CLR 0x43 | 129 | #define UART_LSR_OVERRUN_ERR_CLR 0x43 |
| 114 | #define UART_BST_STAT_LSR_RX_MASK 0x9F000000 | 130 | #define UART_BST_STAT_LSR_RX_MASK 0x9F000000 |
| @@ -116,6 +132,7 @@ · 1 unmodified line | |||
| 116 | #define UART_BST_STAT_LSR_OVERRUN_ERR 0x2000000 | 132 | #define UART_BST_STAT_LSR_OVERRUN_ERR 0x2000000 |
| 117 | #define UART_BST_STAT_LSR_PARITY_ERR 0x4000000 | 133 | #define UART_BST_STAT_LSR_PARITY_ERR 0x4000000 |
| 118 | #define UART_BST_STAT_LSR_FRAME_ERR 0x8000000 | 134 | #define UART_BST_STAT_LSR_FRAME_ERR 0x8000000 |
| 135 | #define UART_BST_STAT_LSR_THRE 0x20000000 | ||
| 119 | 136 | ||
| 120 | struct pci1xxxx_8250 { | 137 | struct pci1xxxx_8250 { |
| 121 | unsigned int nr; | 138 | unsigned int nr; |
| @@ -206,15 +223,21 @@ static int pci1xxxx_get_num_ports(struct pci_dev *dev) · 84 unmodified lines | |||
| 206 | static unsigned int pci1xxxx_get_divisor(struct uart_port *port, | 223 | static unsigned int pci1xxxx_get_divisor(struct uart_port *port, |
| 207 | unsigned int baud, unsigned int *frac) | 224 | unsigned int baud, unsigned int *frac) |
| 208 | { | 225 | { |
| 226 | unsigned int uart_sample_cnt; | ||
| 209 | unsigned int quot; | 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 | * Calculate baud rate sampling period in nanoseconds. | 235 | * Calculate baud rate sampling period in nanoseconds. |
| 213 | * Fractional part x denotes x/255 parts of a nanosecond. | 236 | * Fractional part x denotes x/255 parts of a nanosecond. |
| 214 | */ | 237 | */ |
| 215 | quot = NSEC_PER_SEC / (baud * UART_BIT_SAMPLE_CNT); | 238 | quot = NSEC_PER_SEC / (baud * uart_sample_cnt); |
| 216 | *frac = (NSEC_PER_SEC - quot * baud * UART_BIT_SAMPLE_CNT) * | 239 | *frac = (NSEC_PER_SEC - quot * baud * uart_sample_cnt) * |
| 217 | 255 / UART_BIT_SAMPLE_CNT / baud; | 240 | 255 / uart_sample_cnt / baud; |
| 218 | 241 | ||
| 219 | return quot; | 242 | return quot; |
| 220 | } | 243 | } |
| @@ -222,6 +245,11 @@ static unsigned int pci1xxxx_get_divisor(struct uart_port *port, · 1 unmodified line | |||
| 222 | static void pci1xxxx_set_divisor(struct uart_port *port, unsigned int baud, | 245 | static void pci1xxxx_set_divisor(struct uart_port *port, unsigned int baud, |
| 223 | unsigned int quot, unsigned int frac) | 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 | writel(FIELD_PREP(BAUD_CLOCK_DIV_INT_MSK, quot) | frac, | 253 | writel(FIELD_PREP(BAUD_CLOCK_DIV_INT_MSK, quot) | frac, |
| 226 | port->membase + UART_BAUD_CLK_DIVISOR_REG); | 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 | u32 delay_in_baud_periods; | 261 | u32 delay_in_baud_periods; |
| 234 | u32 baud_period_in_ns; | 262 | u32 baud_period_in_ns; |
| 235 | u32 mode_cfg = 0; | 263 | u32 mode_cfg = 0; |
| 264 | u32 sample_cnt; | ||
| 236 | u32 clock_div; | 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 | * pci1xxxx's uart hardware supports only RTS delay after | 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 | clock_div = readl(port->membase + UART_BAUD_CLK_DIVISOR_REG); | 286 | clock_div = readl(port->membase + UART_BAUD_CLK_DIVISOR_REG); |
| 250 | baud_period_in_ns = | 287 | baud_period_in_ns = |
| 251 | FIELD_GET(BAUD_CLOCK_DIV_INT_MSK, clock_div) * | 288 | FIELD_GET(BAUD_CLOCK_DIV_INT_MSK, clock_div) * |
| 252 | UART_BIT_SAMPLE_CNT; | 289 | sample_cnt; |
| 253 | delay_in_baud_periods = | 290 | delay_in_baud_periods = |
| 254 | rs485->delay_rts_after_send * NSEC_PER_MSEC / | 291 | rs485->delay_rts_after_send * NSEC_PER_MSEC / |
| 255 | baud_period_in_ns; | 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 | static int pci1xxxx_handle_irq(struct uart_port *port) | 483 | static int pci1xxxx_handle_irq(struct uart_port *port) |
| 348 | { | 484 | { |
| 349 | unsigned long flags; | 485 | unsigned long flags; |
| @@ -359,6 +495,9 @@ static int pci1xxxx_handle_irq(struct uart_port *port) · 9 unmodified lines | |||
| 359 | if (status & UART_BST_STAT_LSR_RX_MASK) | 495 | if (status & UART_BST_STAT_LSR_RX_MASK) |
| 360 | pci1xxxx_rx_burst(port, status); | 496 | pci1xxxx_rx_burst(port, status); |
| 361 | 497 | ||
| 498 | if (status & UART_BST_STAT_LSR_THRE) | ||
| 499 | pci1xxxx_tx_burst(port, status); | ||
| 500 | |||
| 362 | spin_unlock_irqrestore(&port->lock, flags); | 501 | spin_unlock_irqrestore(&port->lock, flags); |
| 363 | 502 | ||
| 364 | return 1; | 503 | return 1; |
| @@ -481,6 +620,17 @@ static int pci1xxxx_setup(struct pci_dev *pdev, · 116 unmodified lines | |||
| 481 | 620 | ||
| 482 | port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST; | 621 | port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST; |
| 483 | port->port.type = PORT_MCHP16550A; | 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 | port->port.set_termios = serial8250_do_set_termios; | 634 | port->port.set_termios = serial8250_do_set_termios; |
| 485 | port->port.get_divisor = pci1xxxx_get_divisor; | 635 | port->port.get_divisor = pci1xxxx_get_divisor; |
| 486 | port->port.set_divisor = pci1xxxx_set_divisor; | 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 | memset(&uart, 0, sizeof(uart)); | 745 | memset(&uart, 0, sizeof(uart)); |
| 596 | uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; | 746 | uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; |
| 597 | uart.port.uartclk = UART_CLOCK_DEFAULT; | ||
| 598 | uart.port.dev = dev; | 747 | uart.port.dev = dev; |
| 599 | 748 | ||
| 600 | if (num_vectors == max_vec_reqd) | 749 | if (num_vectors == max_vec_reqd) |
| @@ -38,10 +38,6 @@ · 37 unmodified lines | |||
| 38 | 38 | ||
| 39 | #include "8250.h" | 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 | * Debugging. | 42 | * Debugging. |
| 47 | */ | 43 | */ |
| @@ -1329,9 +1325,6 @@ static void autoconfig_irq(struct uart_8250_port *up) · 1281 unmodified lines | |||
| 1329 | inb_p(ICP); | 1325 | inb_p(ICP); |
| 1330 | } | 1326 | } |
| 1331 | 1327 | ||
| 1332 | if (uart_console(port)) | ||
| 1333 | console_lock(); | ||
| 1334 | |||
| 1335 | /* forget possible initially masked and pending IRQ */ | 1328 | /* forget possible initially masked and pending IRQ */ |
| 1336 | probe_irq_off(probe_irq_on()); | 1329 | probe_irq_off(probe_irq_on()); |
| 1337 | save_mcr = serial8250_in_MCR(up); | 1330 | save_mcr = serial8250_in_MCR(up); |
| @@ -1371,9 +1364,6 @@ static void autoconfig_irq(struct uart_8250_port *up) · 33 unmodified lines | |||
| 1371 | if (port->flags & UPF_FOURPORT) | 1364 | if (port->flags & UPF_FOURPORT) |
| 1372 | outb_p(save_ICP, ICP); | 1365 | outb_p(save_ICP, ICP); |
| 1373 | 1366 | ||
| 1374 | if (uart_console(port)) | ||
| 1375 | console_unlock(); | ||
| 1376 | |||
| 1377 | port->irq = (irq > 0) ? irq : 0; | 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 | UART_DA830_PWREMU_MGMT_FREE); | 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 | #ifdef CONFIG_SERIAL_8250_RSA | 2228 | #ifdef CONFIG_SERIAL_8250_RSA |
| 2248 | /* | 2229 | /* |
| 2249 | * If this is an RSA port, see if we can kick it up to the | 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 | serial8250_do_shutdown(port); | 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 | static unsigned int serial8250_do_get_divisor(struct uart_port *port, | 2529 | static unsigned int serial8250_do_get_divisor(struct uart_port *port, |
| 2558 | unsigned int baud, | 2530 | unsigned int baud, |
| 2559 | unsigned int *frac) | 2531 | unsigned int *frac) |
| @@ -2598,8 +2570,6 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port, · 38 unmodified lines | |||
| 2598 | quot = 0x8001; | 2570 | quot = 0x8001; |
| 2599 | else if (magic_multiplier && baud >= port->uartclk / 12) | 2571 | else if (magic_multiplier && baud >= port->uartclk / 12) |
| 2600 | quot = 0x8002; | 2572 | quot = 0x8002; |
| 2601 | else if (up->port.type == PORT_NPCM) | ||
| 2602 | quot = npcm_get_divisor(up, baud); | ||
| 2603 | else | 2573 | else |
| 2604 | quot = uart_get_divisor(port, baud); | 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 | void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) | 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 | struct tty_port *tport = &port->state->port; | 2687 | struct tty_port *tport = &port->state->port; |
| 2719 | unsigned int baud, quot, frac = 0; | ||
| 2720 | struct ktermios *termios; | ||
| 2721 | struct tty_struct *tty; | 2688 | struct tty_struct *tty; |
| 2722 | unsigned long flags; | ||
| 2723 | 2689 | ||
| 2724 | tty = tty_port_tty_get(tport); | 2690 | tty = tty_port_tty_get(tport); |
| 2725 | if (!tty) { | 2691 | if (!tty) { |
| @@ -2740,21 +2706,7 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) · 14 unmodified lines | |||
| 2740 | if (!tty_port_initialized(tport)) | 2706 | if (!tty_port_initialized(tport)) |
| 2741 | goto out_unlock; | 2707 | goto out_unlock; |
| 2742 | 2708 | ||
| 2743 | termios = &tty->termios; | 2709 | serial8250_do_set_termios(port, &tty->termios, NULL); |
| 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); | ||
| 2758 | 2710 | ||
| 2759 | out_unlock: | 2711 | out_unlock: |
| 2760 | mutex_unlock(&tport->mutex); | 2712 | mutex_unlock(&tport->mutex); |
| @@ -92,11 +92,7 @@ static int serial_pxa_probe(struct platform_device *pdev) · 91 unmodified lines | |||
| 92 | struct uart_8250_port uart = {}; | 92 | struct uart_8250_port uart = {}; |
| 93 | struct pxa8250_data *data; | 93 | struct pxa8250_data *data; |
| 94 | struct resource *mmres; | 94 | struct resource *mmres; |
| 95 | int irq, ret; | 95 | int ret; |
| 96 | |||
| 97 | irq = platform_get_irq(pdev, 0); | ||
| 98 | if (irq < 0) | ||
| 99 | return irq; | ||
| 100 | 96 | ||
| 101 | mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 97 | mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 102 | if (!mmres) | 98 | if (!mmres) |
| @@ -114,21 +110,21 @@ static int serial_pxa_probe(struct platform_device *pdev) · 11 unmodified lines | |||
| 114 | if (ret) | 110 | if (ret) |
| 115 | return ret; | 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 | uart.port.type = PORT_XSCALE; | 113 | uart.port.type = PORT_XSCALE; |
| 122 | uart.port.iotype = UPIO_MEM32; | ||
| 123 | uart.port.mapbase = mmres->start; | 114 | uart.port.mapbase = mmres->start; |
| 124 | uart.port.regshift = 2; | ||
| 125 | uart.port.irq = irq; | ||
| 126 | uart.port.fifosize = 64; | ||
| 127 | uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE; | 115 | uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE; |
| 128 | uart.port.dev = &pdev->dev; | 116 | uart.port.dev = &pdev->dev; |
| 129 | uart.port.uartclk = clk_get_rate(data->clk); | 117 | uart.port.uartclk = clk_get_rate(data->clk); |
| 130 | uart.port.pm = serial_pxa_pm; | 118 | uart.port.pm = serial_pxa_pm; |
| 131 | uart.port.private_data = data; | 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 | uart.dl_write = serial_pxa_dl_write; | 128 | uart.dl_write = serial_pxa_dl_write; |
| 133 | 129 | ||
| 134 | ret = serial8250_register_8250_port(&uart); | 130 | ret = serial8250_register_8250_port(&uart); |
| @@ -57,25 +57,11 @@ static int tegra_uart_probe(struct platform_device *pdev) · 56 unmodified lines | |||
| 57 | port = &port8250.port; | 57 | port = &port8250.port; |
| 58 | spin_lock_init(&port->lock); | 58 | spin_lock_init(&port->lock); |
| 59 | 59 | ||
| 60 | port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | | 60 | port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE; |
| 61 | UPF_FIXED_TYPE; | ||
| 62 | port->iotype = UPIO_MEM32; | ||
| 63 | port->regshift = 2; | ||
| 64 | port->type = PORT_TEGRA; | 61 | port->type = PORT_TEGRA; |
| 65 | port->irqflags |= IRQF_SHARED; | ||
| 66 | port->dev = &pdev->dev; | 62 | port->dev = &pdev->dev; |
| 67 | port->handle_break = tegra_uart_handle_break; | 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 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 65 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 80 | if (!res) | 66 | if (!res) |
| 81 | return -ENODEV; | 67 | return -ENODEV; |
| @@ -88,12 +74,18 @@ static int tegra_uart_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 88 | port->mapbase = res->start; | 74 | port->mapbase = res->start; |
| 89 | port->mapsize = resource_size(res); | 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 | uart->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); | 84 | uart->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); |
| 92 | if (IS_ERR(uart->rst)) | 85 | if (IS_ERR(uart->rst)) |
| 93 | return PTR_ERR(uart->rst); | 86 | return PTR_ERR(uart->rst); |
| 94 | 87 | ||
| 95 | if (device_property_read_u32(&pdev->dev, "clock-frequency", | 88 | if (!port->uartclk) { |
| 96 | &port->uartclk)) { | ||
| 97 | uart->clk = devm_clk_get(&pdev->dev, NULL); | 89 | uart->clk = devm_clk_get(&pdev->dev, NULL); |
| 98 | if (IS_ERR(uart->clk)) { | 90 | if (IS_ERR(uart->clk)) { |
| 99 | dev_err(&pdev->dev, "failed to get clock!\n"); | 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 | struct uniphier8250_priv *priv; | 162 | struct uniphier8250_priv *priv; |
| 163 | struct resource *regs; | 163 | struct resource *regs; |
| 164 | void __iomem *membase; | 164 | void __iomem *membase; |
| 165 | int irq; | ||
| 166 | int ret; | 165 | int ret; |
| 167 | 166 | ||
| 168 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 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 | if (!membase) | 174 | if (!membase) |
| 176 | return -ENOMEM; | 175 | return -ENOMEM; |
| 177 | 176 | ||
| 178 | irq = platform_get_irq(pdev, 0); | ||
| 179 | if (irq < 0) | ||
| 180 | return irq; | ||
| 181 | |||
| 182 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 177 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
| 183 | if (!priv) | 178 | if (!priv) |
| 184 | return -ENOMEM; | 179 | return -ENOMEM; |
| 185 | 180 | ||
| 186 | memset(&up, 0, sizeof(up)); | 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 | priv->clk = devm_clk_get(dev, NULL); | 183 | priv->clk = devm_clk_get(dev, NULL); |
| 196 | if (IS_ERR(priv->clk)) { | 184 | if (IS_ERR(priv->clk)) { |
| 197 | dev_err(dev, "failed to get clock\n"); | 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 | up.port.mapbase = regs->start; | 199 | up.port.mapbase = regs->start; |
| 212 | up.port.mapsize = resource_size(regs); | 200 | up.port.mapsize = resource_size(regs); |
| 213 | up.port.membase = membase; | 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 | up.port.type = PORT_16550A; | 207 | up.port.type = PORT_16550A; |
| 217 | up.port.iotype = UPIO_MEM32; | 208 | up.port.iotype = UPIO_MEM32; |
| @@ -149,6 +149,7 @@ config SERIAL_8250_PCI · 148 unmodified lines | |||
| 149 | config SERIAL_8250_EXAR | 149 | config SERIAL_8250_EXAR |
| 150 | tristate "8250/16550 Exar/Commtech PCI/PCIe device support" | 150 | tristate "8250/16550 Exar/Commtech PCI/PCIe device support" |
| 151 | depends on SERIAL_8250 && PCI | 151 | depends on SERIAL_8250 && PCI |
| 152 | select SERIAL_8250_PCILIB | ||
| 152 | default SERIAL_8250 | 153 | default SERIAL_8250 |
| 153 | help | 154 | help |
| 154 | This builds support for XR17C1xx, XR17V3xx and some Commtech | 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 | flag = TTY_FRAME; | 348 | flag = TTY_FRAME; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | uart_port_unlock(&uap->port); | 351 | sysrq = uart_prepare_sysrq_char(&uap->port, ch & 255); |
| 352 | sysrq = uart_handle_sysrq_char(&uap->port, ch & 255); | ||
| 353 | uart_port_lock(&uap->port); | ||
| 354 | |||
| 355 | if (!sysrq) | 352 | if (!sysrq) |
| 356 | uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); | 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 | ret = pl011_dma_rx_trigger_dma(uap); | 1014 | ret = pl011_dma_rx_trigger_dma(uap); |
| 1018 | 1015 | ||
| 1019 | pl011_dma_rx_chars(uap, pending, lastbuf, false); | 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 | * Do this check after we picked the DMA chars so we don't | 1019 | * Do this check after we picked the DMA chars so we don't |
| 1023 | * get some IRQ immediately from RX. | 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 | static irqreturn_t pl011_int(int irq, void *dev_id) | 1537 | static irqreturn_t pl011_int(int irq, void *dev_id) |
| 1541 | { | 1538 | { |
| 1542 | struct uart_amba_port *uap = dev_id; | 1539 | struct uart_amba_port *uap = dev_id; |
| 1543 | unsigned long flags; | ||
| 1544 | unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; | 1540 | unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; |
| 1545 | int handled = 0; | 1541 | int handled = 0; |
| 1546 | 1542 | ||
| 1547 | uart_port_lock_irqsave(&uap->port, &flags); | 1543 | uart_port_lock(&uap->port); |
| 1548 | status = pl011_read(uap, REG_RIS) & uap->im; | 1544 | status = pl011_read(uap, REG_RIS) & uap->im; |
| 1549 | if (status) { | 1545 | if (status) { |
| 1550 | do { | 1546 | do { |
| @@ -1573,7 +1569,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) · 22 unmodified lines | |||
| 1573 | handled = 1; | 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 | return IRQ_RETVAL(handled); | 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 | clk_enable(uap->clk); | 2319 | clk_enable(uap->clk); |
| 2324 | 2320 | ||
| 2325 | local_irq_save(flags); | 2321 | if (oops_in_progress) |
| 2326 | if (uap->port.sysrq) | 2322 | locked = uart_port_trylock_irqsave(&uap->port, &flags); |
| 2327 | locked = 0; | ||
| 2328 | else if (oops_in_progress) | ||
| 2329 | locked = uart_port_trylock(&uap->port); | ||
| 2330 | else | 2323 | else |
| 2331 | uart_port_lock(&uap->port); | 2324 | uart_port_lock_irqsave(&uap->port, &flags); |
| 2332 | 2325 | ||
| 2333 | /* | 2326 | /* |
| 2334 | * First save the CR then disable the interrupts | 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 | pl011_write(old_cr, uap, REG_CR); | 2347 | pl011_write(old_cr, uap, REG_CR); |
| 2355 | 2348 | ||
| 2356 | if (locked) | 2349 | if (locked) |
| 2357 | uart_port_unlock(&uap->port); | 2350 | uart_port_unlock_irqrestore(&uap->port, flags); |
| 2358 | local_irq_restore(flags); | ||
| 2359 | 2351 | ||
| 2360 | clk_disable(uap->clk); | 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 | up->port.icount.rx++; | 378 | up->port.icount.rx++; |
| 379 | ch = rdata & AR933X_UART_DATA_TX_RX_MASK; | 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 | continue; | 382 | continue; |
| 383 | 383 | ||
| 384 | if ((up->port.ignore_status_mask & AR933X_DUMMY_STATUS_RD) == 0) | 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 | ar933x_uart_tx_chars(up); | 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 | return IRQ_HANDLED; | 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 | unsigned int int_en; | 627 | unsigned int int_en; |
| 628 | int locked = 1; | 628 | int locked = 1; |
| 629 | 629 | ||
| 630 | local_irq_save(flags); | 630 | if (oops_in_progress) |
| 631 | 631 | locked = uart_port_trylock_irqsave(&up->port, &flags); | |
| 632 | if (up->port.sysrq) | ||
| 633 | locked = 0; | ||
| 634 | else if (oops_in_progress) | ||
| 635 | locked = uart_port_trylock(&up->port); | ||
| 636 | else | 632 | else |
| 637 | uart_port_lock(&up->port); | 633 | uart_port_lock_irqsave(&up->port, &flags); |
| 638 | 634 | ||
| 639 | /* | 635 | /* |
| 640 | * First save the IER then disable the interrupts | 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 | ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS); | 650 | ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS); |
| 655 | 651 | ||
| 656 | if (locked) | 652 | if (locked) |
| 657 | uart_port_unlock(&up->port); | 653 | uart_port_unlock_irqrestore(&up->port, flags); |
| 658 | |||
| 659 | local_irq_restore(flags); | ||
| 660 | } | 654 | } |
| 661 | 655 | ||
| 662 | static int ar933x_uart_console_setup(struct console *co, char *options) | 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 | flag = TTY_PARITY; | 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 | continue; | 289 | continue; |
| 290 | 290 | ||
| 291 | |||
| 292 | if ((cstat & port->ignore_status_mask) == 0) | 291 | if ((cstat & port->ignore_status_mask) == 0) |
| 293 | tty_insert_flip_char(tty_port, c, flag); | 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 | estat & UART_EXTINP_DCD_MASK); | 352 | estat & UART_EXTINP_DCD_MASK); |
| 354 | } | 353 | } |
| 355 | 354 | ||
| 356 | uart_port_unlock(port); | 355 | uart_unlock_and_check_sysrq(port); |
| 357 | return IRQ_HANDLED; | 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 | struct uart_port *port; | 703 | struct uart_port *port; |
| 705 | unsigned long flags; | 704 | unsigned long flags; |
| 706 | int locked; | 705 | int locked = 1; |
| 707 | 706 | ||
| 708 | port = &ports[co->index]; | 707 | port = &ports[co->index]; |
| 709 | 708 | ||
| 710 | local_irq_save(flags); | 709 | if (oops_in_progress) |
| 711 | if (port->sysrq) { | 710 | locked = uart_port_trylock_irqsave(port, &flags); |
| 712 | /* bcm_uart_interrupt() already took the lock */ | 711 | else |
| 713 | locked = 0; | 712 | uart_port_lock_irqsave(port, &flags); |
| 714 | } else if (oops_in_progress) { | ||
| 715 | locked = uart_port_trylock(port); | ||
| 716 | } else { | ||
| 717 | uart_port_lock(port); | ||
| 718 | locked = 1; | ||
| 719 | } | ||
| 720 | 713 | ||
| 721 | /* call helper to deal with \r\n */ | 714 | /* call helper to deal with \r\n */ |
| 722 | uart_console_write(port, s, count, bcm_console_putchar); | 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 | wait_for_xmitr(port); | 718 | wait_for_xmitr(port); |
| 726 | 719 | ||
| 727 | if (locked) | 720 | if (locked) |
| 728 | uart_port_unlock(port); | 721 | uart_port_unlock_irqrestore(port, flags); |
| 729 | local_irq_restore(flags); | ||
| 730 | } | 722 | } |
| 731 | 723 | ||
| 732 | /* | 724 | /* |
| @@ -837,7 +837,6 @@ static int linflex_probe(struct platform_device *pdev) · 836 unmodified lines | |||
| 837 | return ret; | 837 | return ret; |
| 838 | 838 | ||
| 839 | sport->dev = &pdev->dev; | 839 | sport->dev = &pdev->dev; |
| 840 | sport->type = PORT_LINFLEXUART; | ||
| 841 | sport->iotype = UPIO_MEM; | 840 | sport->iotype = UPIO_MEM; |
| 842 | sport->irq = ret; | 841 | sport->irq = ret; |
| 843 | sport->ops = &linflex_pops; | 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 | * which in this case is the break signal. | 395 | * which in this case is the break signal. |
| 396 | */ | 396 | */ |
| 397 | if (linestatus & error_mask) { | 397 | if (linestatus & error_mask) { |
| 398 | linestatus = 0; | ||
| 399 | readb(&ch->ch_cls_uart->txrx); | 398 | readb(&ch->ch_cls_uart->txrx); |
| 400 | continue; | 399 | continue; |
| 401 | } | 400 | } |
| @@ -136,20 +136,16 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s, · 135 unmodified lines | |||
| 136 | int locked = 1; | 136 | int locked = 1; |
| 137 | 137 | ||
| 138 | touch_nmi_watchdog(); | 138 | touch_nmi_watchdog(); |
| 139 | local_irq_save(flags); | 139 | if (oops_in_progress) |
| 140 | if (up->port.sysrq) | 140 | locked = uart_port_trylock_irqsave(&up->port, &flags); |
| 141 | locked = 0; | ||
| 142 | else if (oops_in_progress) | ||
| 143 | locked = uart_port_trylock(&up->port); | ||
| 144 | else | 141 | else |
| 145 | uart_port_lock(&up->port); | 142 | uart_port_lock_irqsave(&up->port, &flags); |
| 146 | 143 | ||
| 147 | uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar); | 144 | uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar); |
| 148 | wait_for_xmit_empty(&up->port); | 145 | wait_for_xmit_empty(&up->port); |
| 149 | 146 | ||
| 150 | if (locked) | 147 | if (locked) |
| 151 | uart_port_unlock(&up->port); | 148 | uart_port_unlock_irqrestore(&up->port, flags); |
| 152 | local_irq_restore(flags); | ||
| 153 | } | 149 | } |
| 154 | 150 | ||
| 155 | static int __init lpc32xx_hsuart_console_setup(struct console *co, | 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 | hsu_rate++; | 230 | hsu_rate++; |
| 235 | } | 231 | } |
| 236 | if (hsu_rate > 0xFF) | ||
| 237 | hsu_rate = 0xFF; | ||
| 238 | 232 | ||
| 239 | return goodrate; | 233 | return goodrate; |
| 240 | } | 234 | } |
| @@ -268,7 +262,8 @@ static void __serial_lpc32xx_rx(struct uart_port *port) · 27 unmodified lines | |||
| 268 | tty_insert_flip_char(tport, 0, TTY_FRAME); | 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 | tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); | 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 | __serial_lpc32xx_tx(port); | 328 | __serial_lpc32xx_tx(port); |
| 334 | } | 329 | } |
| 335 | 330 | ||
| 336 | uart_port_unlock(port); | 331 | uart_unlock_and_check_sysrq(port); |
| 337 | 332 | ||
| 338 | return IRQ_HANDLED; | 333 | return IRQ_HANDLED; |
| 339 | } | 334 | } |
| @@ -30,6 +30,7 @@ · 29 unmodified lines | |||
| 30 | #define MAX310X_MAJOR 204 | 30 | #define MAX310X_MAJOR 204 |
| 31 | #define MAX310X_MINOR 209 | 31 | #define MAX310X_MINOR 209 |
| 32 | #define MAX310X_UART_NRMAX 16 | 32 | #define MAX310X_UART_NRMAX 16 |
| 33 | #define MAX310X_MAX_PORTS 4 /* Maximum number of UART ports per IC. */ | ||
| 33 | 34 | ||
| 34 | /* MAX310X register definitions */ | 35 | /* MAX310X register definitions */ |
| 35 | #define MAX310X_RHR_REG (0x00) /* RX FIFO */ | 36 | #define MAX310X_RHR_REG (0x00) /* RX FIFO */ |
| @@ -66,6 +67,7 @@ · 30 unmodified lines | |||
| 66 | #define MAX310X_BRGDIVMSB_REG (0x1d) /* Baud rate divisor MSB */ | 67 | #define MAX310X_BRGDIVMSB_REG (0x1d) /* Baud rate divisor MSB */ |
| 67 | #define MAX310X_CLKSRC_REG (0x1e) /* Clock source */ | 68 | #define MAX310X_CLKSRC_REG (0x1e) /* Clock source */ |
| 68 | #define MAX310X_REG_1F (0x1f) | 69 | #define MAX310X_REG_1F (0x1f) |
| 70 | #define MAX310X_EXTREG_START (0x20) /* Only relevant in SPI mode. */ | ||
| 69 | 71 | ||
| 70 | #define MAX310X_REVID_REG MAX310X_REG_1F /* Revision ID */ | 72 | #define MAX310X_REVID_REG MAX310X_REG_1F /* Revision ID */ |
| 71 | 73 | ||
| @@ -73,9 +75,9 @@ · 1 unmodified line | |||
| 73 | #define MAX310X_GLOBALCMD_REG MAX310X_REG_1F /* Global Command (WO) */ | 75 | #define MAX310X_GLOBALCMD_REG MAX310X_REG_1F /* Global Command (WO) */ |
| 74 | 76 | ||
| 75 | /* Extended registers */ | 77 | /* Extended registers */ |
| 76 | #define MAX310X_SPI_REVID_EXTREG MAX310X_REG_05 /* Revision ID */ | 78 | #define MAX310X_REVID_EXTREG (0x25) /* Revision ID |
| 77 | #define MAX310X_I2C_REVID_EXTREG (0x25) /* Revision ID */ | 79 | * (extended addressing space) |
| 78 | 80 | */ | |
| 79 | /* IRQ register bits */ | 81 | /* IRQ register bits */ |
| 80 | #define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ | 82 | #define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ |
| 81 | #define MAX310X_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */ | 83 | #define MAX310X_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */ |
| @@ -160,14 +162,14 @@ · 78 unmodified lines | |||
| 160 | #define MAX310X_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */ | 162 | #define MAX310X_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */ |
| 161 | 163 | ||
| 162 | /* Flow control trigger level register masks */ | 164 | /* Flow control trigger level register masks */ |
| 163 | #define MAX310X_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */ | 165 | #define MAX310X_FLOWLVL_HALT_MASK GENMASK(3, 0) /* Flow control halt level */ |
| 164 | #define MAX310X_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */ | 166 | #define MAX310X_FLOWLVL_RES_MASK GENMASK(7, 4) /* Flow control resume level */ |
| 165 | #define MAX310X_FLOWLVL_HALT(words) ((words / 8) & 0x0f) | 167 | #define MAX310X_FLOWLVL_HALT(words) ((words / 8) & 0x0f) |
| 166 | #define MAX310X_FLOWLVL_RES(words) (((words / 8) & 0x0f) << 4) | 168 | #define MAX310X_FLOWLVL_RES(words) (((words / 8) & 0x0f) << 4) |
| 167 | 169 | ||
| 168 | /* FIFO interrupt trigger level register masks */ | 170 | /* FIFO interrupt trigger level register masks */ |
| 169 | #define MAX310X_FIFOTRIGLVL_TX_MASK (0x0f) /* TX FIFO trigger level */ | 171 | #define MAX310X_FIFOTRIGLVL_TX_MASK GENMASK(3, 0) /* TX FIFO trigger level */ |
| 170 | #define MAX310X_FIFOTRIGLVL_RX_MASK (0xf0) /* RX FIFO trigger level */ | 172 | #define MAX310X_FIFOTRIGLVL_RX_MASK GENMASK(7, 4) /* RX FIFO trigger level */ |
| 171 | #define MAX310X_FIFOTRIGLVL_TX(words) ((words / 8) & 0x0f) | 173 | #define MAX310X_FIFOTRIGLVL_TX(words) ((words / 8) & 0x0f) |
| 172 | #define MAX310X_FIFOTRIGLVL_RX(words) (((words / 8) & 0x0f) << 4) | 174 | #define MAX310X_FIFOTRIGLVL_RX(words) (((words / 8) & 0x0f) << 4) |
| 173 | 175 | ||
| @@ -177,7 +179,8 @@ · 3 unmodified lines | |||
| 177 | #define MAX310X_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs | 179 | #define MAX310X_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs |
| 178 | * are used in conjunction with | 180 | * are used in conjunction with |
| 179 | * XOFF2 for definition of | 181 | * XOFF2 for definition of |
| 180 | * special character */ | 182 | * special character |
| 183 | */ | ||
| 181 | #define MAX310X_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */ | 184 | #define MAX310X_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */ |
| 182 | #define MAX310X_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */ | 185 | #define MAX310X_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */ |
| 183 | #define MAX310X_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1 | 186 | #define MAX310X_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1 |
| @@ -214,8 +217,8 @@ · 30 unmodified lines | |||
| 214 | */ | 217 | */ |
| 215 | 218 | ||
| 216 | /* PLL configuration register masks */ | 219 | /* PLL configuration register masks */ |
| 217 | #define MAX310X_PLLCFG_PREDIV_MASK (0x3f) /* PLL predivision value */ | 220 | #define MAX310X_PLLCFG_PREDIV_MASK GENMASK(5, 0) /* PLL predivision value */ |
| 218 | #define MAX310X_PLLCFG_PLLFACTOR_MASK (0xc0) /* PLL multiplication factor */ | 221 | #define MAX310X_PLLCFG_PLLFACTOR_MASK GENMASK(7, 6) /* PLL multiplication factor */ |
| 219 | 222 | ||
| 220 | /* Baud rate generator configuration register bits */ | 223 | /* Baud rate generator configuration register bits */ |
| 221 | #define MAX310X_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */ | 224 | #define MAX310X_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */ |
| @@ -234,7 +237,7 @@ · 12 unmodified lines | |||
| 234 | 237 | ||
| 235 | /* Misc definitions */ | 238 | /* Misc definitions */ |
| 236 | #define MAX310X_FIFO_SIZE (128) | 239 | #define MAX310X_FIFO_SIZE (128) |
| 237 | #define MAX310x_REV_MASK (0xf8) | 240 | #define MAX310x_REV_MASK GENMASK(7, 3) |
| 238 | #define MAX310X_WRITE_BIT 0x80 | 241 | #define MAX310X_WRITE_BIT 0x80 |
| 239 | 242 | ||
| 240 | /* Port startup definitions */ | 243 | /* Port startup definitions */ |
| @@ -257,20 +260,21 @@ · 16 unmodified lines | |||
| 257 | 260 | ||
| 258 | struct max310x_if_cfg { | 261 | struct max310x_if_cfg { |
| 259 | int (*extended_reg_enable)(struct device *dev, bool enable); | 262 | int (*extended_reg_enable)(struct device *dev, bool enable); |
| 260 | 263 | u8 rev_id_offset; | |
| 261 | unsigned int rev_id_reg; | ||
| 262 | }; | 264 | }; |
| 263 | 265 | ||
| 264 | struct max310x_devtype { | 266 | struct max310x_devtype { |
| 265 | struct { | 267 | struct { |
| 266 | unsigned short min; | 268 | unsigned short min; |
| 267 | unsigned short max; | 269 | unsigned short max; |
| 268 | } slave_addr; | 270 | } slave_addr; /* Relevant only in I2C mode. */ |
| 269 | char name[9]; | ||
| 270 | int nr; | 271 | int nr; |
| 272 | char name[9]; | ||
| 271 | u8 mode1; | 273 | u8 mode1; |
| 272 | int (*detect)(struct device *); | 274 | u8 rev_id_val; |
| 273 | void (*power)(struct uart_port *, int); | 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 | struct max310x_one { | 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 | regmap_update_bits(one->regmap, reg, mask, val); | 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 | struct max310x_port *s = dev_get_drvdata(dev); | 340 | struct max310x_port *s = dev_get_drvdata(dev); |
| 337 | unsigned int val = 0; | 341 | unsigned int val = 0; |
| 338 | int ret; | 342 | int ret; |
| 339 | 343 | ||
| 340 | ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val); | 344 | /* Check if variant supports REV ID register: */ |
| 341 | if (ret) | 345 | if (s->devtype->rev_id_val) { |
| 342 | return ret; | 346 | u8 rev_id_reg = s->devtype->rev_id_reg; |
| 343 | 347 | ||
| 344 | if (((val & MAX310x_REV_MASK) != MAX3107_REV_ID)) { | 348 | /* Check if REV ID is in extended addressing space: */ |
| 345 | dev_err(dev, | 349 | if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) { |
| 346 | "%s ID 0x%02x does not match\n", s->devtype->name, val); | 350 | ret = s->if_cfg->extended_reg_enable(dev, true); |
| 347 | return -ENODEV; | 351 | if (ret) |
| 348 | } | 352 | return ret; |
| 349 | |||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | 353 | ||
| 353 | static int max3108_detect(struct device *dev) | 354 | /* Adjust REV ID extended addressing space address: */ |
| 354 | { | 355 | if (s->if_cfg->rev_id_offset) |
| 355 | struct max310x_port *s = dev_get_drvdata(dev); | 356 | rev_id_reg -= s->if_cfg->rev_id_offset; |
| 356 | unsigned int val = 0; | 357 | } |
| 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 | } | ||
| 370 | 358 | ||
| 371 | return 0; | 359 | regmap_read(s->regmap, rev_id_reg, &val); |
| 372 | } | ||
| 373 | 360 | ||
| 374 | static int max3109_detect(struct device *dev) | 361 | if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) { |
| 375 | { | 362 | ret = s->if_cfg->extended_reg_enable(dev, false); |
| 376 | struct max310x_port *s = dev_get_drvdata(dev); | 363 | if (ret) |
| 377 | unsigned int val = 0; | 364 | return ret; |
| 378 | int ret; | 365 | } |
| 379 | |||
| 380 | ret = s->if_cfg->extended_reg_enable(dev, true); | ||
| 381 | if (ret) | ||
| 382 | return ret; | ||
| 383 | 366 | ||
| 384 | regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val); | 367 | if (((val & MAX310x_REV_MASK) != s->devtype->rev_id_val)) |
| 385 | s->if_cfg->extended_reg_enable(dev, false); | 368 | return dev_err_probe(dev, -ENODEV, |
| 386 | if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) { | 369 | "%s ID 0x%02x does not match\n", |
| 387 | dev_err(dev, | 370 | s->devtype->name, val); |
| 388 | "%s ID 0x%02x does not match\n", s->devtype->name, val); | 371 | } else { |
| 389 | return -ENODEV; | 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 | return 0; | 386 | return 0; |
| @@ -394,39 +388,10 @@ static int max3109_detect(struct device *dev) · 1 unmodified line | |||
| 394 | 388 | ||
| 395 | static void max310x_power(struct uart_port *port, int on) | 389 | static void max310x_power(struct uart_port *port, int on) |
| 396 | { | 390 | { |
| 397 | max310x_port_update(port, MAX310X_MODE1_REG, | 391 | struct max310x_port *s = dev_get_drvdata(port->dev); |
| 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 | } | ||
| 424 | 392 | ||
| 425 | static void max14830_power(struct uart_port *port, int on) | 393 | max310x_port_update(port, s->devtype->power_reg, s->devtype->power_bit, |
| 426 | { | 394 | on ? 0 : s->devtype->power_bit); |
| 427 | max310x_port_update(port, MAX310X_BRGCFG_REG, | ||
| 428 | MAX14830_BRGCFG_CLKDIS_BIT, | ||
| 429 | on ? 0 : MAX14830_BRGCFG_CLKDIS_BIT); | ||
| 430 | if (on) | 395 | if (on) |
| 431 | msleep(50); | 396 | msleep(50); |
| 432 | } | 397 | } |
| @@ -435,8 +400,10 @@ static const struct max310x_devtype max3107_devtype = { · 2 unmodified lines | |||
| 435 | .name = "MAX3107", | 400 | .name = "MAX3107", |
| 436 | .nr = 1, | 401 | .nr = 1, |
| 437 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT, | 402 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT, |
| 438 | .detect = max3107_detect, | 403 | .rev_id_val = MAX3107_REV_ID, |
| 439 | .power = max310x_power, | 404 | .rev_id_reg = MAX310X_REVID_REG, |
| 405 | .power_reg = MAX310X_MODE1_REG, | ||
| 406 | .power_bit = MAX310X_MODE1_FORCESLEEP_BIT, | ||
| 440 | .slave_addr = { | 407 | .slave_addr = { |
| 441 | .min = 0x2c, | 408 | .min = 0x2c, |
| 442 | .max = 0x2f, | 409 | .max = 0x2f, |
| @@ -447,8 +414,10 @@ static const struct max310x_devtype max3108_devtype = { · 4 unmodified lines | |||
| 447 | .name = "MAX3108", | 414 | .name = "MAX3108", |
| 448 | .nr = 1, | 415 | .nr = 1, |
| 449 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, | 416 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, |
| 450 | .detect = max3108_detect, | 417 | .rev_id_val = 0, /* Unsupported. */ |
| 451 | .power = max310x_power, | 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 | .slave_addr = { | 421 | .slave_addr = { |
| 453 | .min = 0x60, | 422 | .min = 0x60, |
| 454 | .max = 0x6f, | 423 | .max = 0x6f, |
| @@ -459,8 +428,10 @@ static const struct max310x_devtype max3109_devtype = { · 4 unmodified lines | |||
| 459 | .name = "MAX3109", | 428 | .name = "MAX3109", |
| 460 | .nr = 2, | 429 | .nr = 2, |
| 461 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, | 430 | .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, |
| 462 | .detect = max3109_detect, | 431 | .rev_id_val = MAX3109_REV_ID, |
| 463 | .power = max310x_power, | 432 | .rev_id_reg = MAX310X_REVID_EXTREG, |
| 433 | .power_reg = MAX310X_MODE1_REG, | ||
| 434 | .power_bit = MAX310X_MODE1_FORCESLEEP_BIT, | ||
| 464 | .slave_addr = { | 435 | .slave_addr = { |
| 465 | .min = 0x60, | 436 | .min = 0x60, |
| 466 | .max = 0x6f, | 437 | .max = 0x6f, |
| @@ -471,8 +442,10 @@ static const struct max310x_devtype max14830_devtype = { · 4 unmodified lines | |||
| 471 | .name = "MAX14830", | 442 | .name = "MAX14830", |
| 472 | .nr = 4, | 443 | .nr = 4, |
| 473 | .mode1 = MAX310X_MODE1_IRQSEL_BIT, | 444 | .mode1 = MAX310X_MODE1_IRQSEL_BIT, |
| 474 | .detect = max14830_detect, | 445 | .rev_id_val = MAX14830_REV_ID, |
| 475 | .power = max14830_power, | 446 | .rev_id_reg = MAX310X_REVID_EXTREG, |
| 447 | .power_reg = MAX310X_BRGCFG_REG, | ||
| 448 | .power_bit = MAX14830_BRGCFG_CLKDIS_BIT, | ||
| 476 | .slave_addr = { | 449 | .slave_addr = { |
| 477 | .min = 0x60, | 450 | .min = 0x60, |
| 478 | .max = 0x6f, | 451 | .max = 0x6f, |
| @@ -490,10 +463,8 @@ static bool max310x_reg_writeable(struct device *dev, unsigned int reg) · 11 unmodified lines | |||
| 490 | case MAX310X_RXFIFOLVL_REG: | 463 | case MAX310X_RXFIFOLVL_REG: |
| 491 | return false; | 464 | return false; |
| 492 | default: | 465 | default: |
| 493 | break; | 466 | return true; |
| 494 | } | 467 | } |
| 495 | |||
| 496 | return true; | ||
| 497 | } | 468 | } |
| 498 | 469 | ||
| 499 | static bool max310x_reg_volatile(struct device *dev, unsigned int reg) | 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 | case MAX310X_REG_1F: | 483 | case MAX310X_REG_1F: |
| 513 | return true; | 484 | return true; |
| 514 | default: | 485 | default: |
| 515 | break; | 486 | return false; |
| 516 | } | 487 | } |
| 517 | |||
| 518 | return false; | ||
| 519 | } | 488 | } |
| 520 | 489 | ||
| 521 | static bool max310x_reg_precious(struct device *dev, unsigned int reg) | 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 | case MAX310X_STS_IRQSTS_REG: | 496 | case MAX310X_STS_IRQSTS_REG: |
| 528 | return true; | 497 | return true; |
| 529 | default: | 498 | default: |
| 530 | break; | 499 | return false; |
| 531 | } | 500 | } |
| 532 | |||
| 533 | return false; | ||
| 534 | } | 501 | } |
| 535 | 502 | ||
| 536 | static bool max310x_reg_noinc(struct device *dev, unsigned int reg) | 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 | u8 ch, flag; | 656 | u8 ch, flag; |
| 690 | 657 | ||
| 691 | if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) { | 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 | * Break condition, parity checking, framing errors -- they | 661 | * Break condition, parity checking, framing errors -- they |
| 694 | * are all ignored. That means that we can do a batch-read. | 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 | * that the LSR register applies to the "current" character. | 666 | * that the LSR register applies to the "current" character. |
| 699 | * That's also the reason why we cannot do batched reads when | 667 | * That's also the reason why we cannot do batched reads when |
| 700 | * asked to check the individual statuses. | 668 | * asked to check the individual statuses. |
| 701 | * */ | 669 | */ |
| 702 | 670 | ||
| 703 | sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); | 671 | sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); |
| 704 | max310x_batch_read(port, one->rx_buf, rxlen); | 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 | to_send = (to_send > txlen) ? txlen : to_send; | 770 | to_send = (to_send > txlen) ? txlen : to_send; |
| 803 | 771 | ||
| 804 | if (until_end < to_send) { | 772 | if (until_end < to_send) { |
| 805 | /* It's a circ buffer -- wrap around. | 773 | /* |
| 806 | * We could do that in one SPI transaction, but meh. */ | 774 | * It's a circ buffer -- wrap around. |
| 775 | * We could do that in one SPI transaction, but meh. | ||
| 776 | */ | ||
| 807 | max310x_batch_write(port, xmit->buf + xmit->tail, until_end); | 777 | max310x_batch_write(port, xmit->buf + xmit->tail, until_end); |
| 808 | max310x_batch_write(port, xmit->buf, to_send - until_end); | 778 | max310x_batch_write(port, xmit->buf, to_send - until_end); |
| 809 | } else { | 779 | } else { |
| @@ -848,6 +818,7 @@ static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno) · 38 unmodified lines | |||
| 848 | if (ists & MAX310X_IRQ_TXEMPTY_BIT) | 818 | if (ists & MAX310X_IRQ_TXEMPTY_BIT) |
| 849 | max310x_start_tx(port); | 819 | max310x_start_tx(port); |
| 850 | } while (1); | 820 | } while (1); |
| 821 | |||
| 851 | return res; | 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 | static unsigned int max310x_get_mctrl(struct uart_port *port) | 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 | * so just indicate DSR and CAR asserted | 868 | * so just indicate DSR and CAR asserted |
| 897 | */ | 869 | */ |
| 898 | return TIOCM_DSR | TIOCM_CAR; | 870 | return TIOCM_DSR | TIOCM_CAR; |
| @@ -984,7 +956,8 @@ static void max310x_set_termios(struct uart_port *port, · 85 unmodified lines | |||
| 984 | max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]); | 956 | max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]); |
| 985 | max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]); | 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 | * flow control | 961 | * flow control |
| 989 | */ | 962 | */ |
| 990 | if (termios->c_cflag & CRTSCTS || termios->c_iflag & IXOFF) { | 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 | max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow); | 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 | * flow control | 989 | * flow control |
| 1016 | */ | 990 | */ |
| 1017 | if (!(termios->c_cflag & CRTSCTS) && !(termios->c_iflag & IXOFF)) { | 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 | static int max310x_startup(struct uart_port *port) | 1047 | static int max310x_startup(struct uart_port *port) |
| 1074 | { | 1048 | { |
| 1075 | struct max310x_port *s = dev_get_drvdata(port->dev); | ||
| 1076 | unsigned int val; | 1049 | unsigned int val; |
| 1077 | 1050 | ||
| 1078 | s->devtype->power(port, 1); | 1051 | max310x_power(port, 1); |
| 1079 | 1052 | ||
| 1080 | /* Configure MODE1 register */ | 1053 | /* Configure MODE1 register */ |
| 1081 | max310x_port_update(port, MAX310X_MODE1_REG, | 1054 | max310x_port_update(port, MAX310X_MODE1_REG, |
| @@ -1103,8 +1076,11 @@ static int max310x_startup(struct uart_port *port) · 21 unmodified lines | |||
| 1103 | MAX310X_MODE2_ECHOSUPR_BIT); | 1076 | MAX310X_MODE2_ECHOSUPR_BIT); |
| 1104 | } | 1077 | } |
| 1105 | 1078 | ||
| 1106 | /* Configure flow control levels */ | 1079 | /* |
| 1107 | /* Flow control halt level 96, resume level 48 */ | 1080 | * Configure flow control levels: |
| 1081 | * resume: 48 | ||
| 1082 | * halt: 96 | ||
| 1083 | */ | ||
| 1108 | max310x_port_write(port, MAX310X_FLOWLVL_REG, | 1084 | max310x_port_write(port, MAX310X_FLOWLVL_REG, |
| 1109 | MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96)); | 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 | static void max310x_shutdown(struct uart_port *port) | 1097 | static void max310x_shutdown(struct uart_port *port) |
| 1122 | { | 1098 | { |
| 1123 | struct max310x_port *s = dev_get_drvdata(port->dev); | ||
| 1124 | |||
| 1125 | /* Disable all interrupts */ | 1099 | /* Disable all interrupts */ |
| 1126 | max310x_port_write(port, MAX310X_IRQEN_REG, 0); | 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 | static const char *max310x_type(struct uart_port *port) | 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 | for (i = 0; i < s->devtype->nr; i++) { | 1162 | for (i = 0; i < s->devtype->nr; i++) { |
| 1189 | uart_suspend_port(&max310x_uart, &s->p[i].port); | 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 | return 0; | 1167 | return 0; |
| @@ -1199,7 +1173,7 @@ static int __maybe_unused max310x_resume(struct device *dev) · 5 unmodified lines | |||
| 1199 | int i; | 1173 | int i; |
| 1200 | 1174 | ||
| 1201 | for (i = 0; i < s->devtype->nr; i++) { | 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 | uart_resume_port(&max310x_uart, &s->p[i].port); | 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 | static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); | 1183 | static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); |
| 1210 | 1184 | ||
| 1211 | #ifdef CONFIG_GPIOLIB | 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 | unsigned int val; | 1188 | unsigned int val; |
| 1215 | struct max310x_port *s = gpiochip_get_data(chip); | 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 | return !!((val >> 4) & (1 << (offset % 4))); | 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 | struct max310x_port *s = gpiochip_get_data(chip); | 1199 | struct max310x_port *s = gpiochip_get_data(chip); |
| 1226 | struct uart_port *port = &s->p[offset / 4].port; | 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 | value ? 1 << (offset % 4) : 0); | 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 | struct max310x_port *s = gpiochip_get_data(chip); | 1208 | struct max310x_port *s = gpiochip_get_data(chip); |
| 1235 | struct uart_port *port = &s->p[offset / 4].port; | 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 | static int max310x_gpio_direction_output(struct gpio_chip *chip, | 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 | struct max310x_port *s = gpiochip_get_data(chip); | 1219 | struct max310x_port *s = gpiochip_get_data(chip); |
| 1246 | struct uart_port *port = &s->p[offset / 4].port; | 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 | /* Alloc port structure */ | 1271 | /* Alloc port structure */ |
| 1298 | s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL); | 1272 | s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL); |
| 1299 | if (!s) { | 1273 | if (!s) |
| 1300 | dev_err(dev, "Error allocating port structure\n"); | 1274 | return dev_err_probe(dev, -ENOMEM, |
| 1301 | return -ENOMEM; | 1275 | "Error allocating port structure\n"); |
| 1302 | } | ||
| 1303 | 1276 | ||
| 1304 | /* Always ask for fixed clock rate from a property. */ | 1277 | /* Always ask for fixed clock rate from a property. */ |
| 1305 | device_property_read_u32(dev, "clock-frequency", &uartclk); | 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 | if (freq == 0) | 1293 | if (freq == 0) |
| 1321 | freq = uartclk; | 1294 | freq = uartclk; |
| 1322 | if (freq == 0) { | 1295 | if (freq == 0) { |
| 1323 | dev_err(dev, "Cannot get clock rate\n"); | 1296 | ret = dev_err_probe(dev, -EINVAL, "Cannot get clock rate\n"); |
| 1324 | ret = -EINVAL; | ||
| 1325 | goto out_clk; | 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 | dev_set_drvdata(dev, s); | 1317 | dev_set_drvdata(dev, s); |
| 1346 | 1318 | ||
| 1347 | /* Check device to ensure we are talking to what we expect */ | 1319 | /* Check device to ensure we are talking to what we expect */ |
| 1348 | ret = devtype->detect(dev); | 1320 | ret = max310x_detect(dev); |
| 1349 | if (ret) | 1321 | if (ret) |
| 1350 | goto out_clk; | 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 | /* Register port */ | 1400 | /* Register port */ |
| 1429 | ret = uart_add_one_port(&max310x_uart, &s->p[i].port); | 1401 | ret = uart_add_one_port(&max310x_uart, &s->p[i].port); |
| 1430 | if (ret) { | 1402 | if (ret) |
| 1431 | s->p[i].port.dev = NULL; | ||
| 1432 | goto out_uart; | 1403 | goto out_uart; |
| 1433 | } | 1404 | |
| 1434 | set_bit(line, max310x_lines); | 1405 | set_bit(line, max310x_lines); |
| 1435 | 1406 | ||
| 1436 | /* Go to suspend mode */ | 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 | #ifdef CONFIG_GPIOLIB | 1411 | #ifdef CONFIG_GPIOLIB |
| @@ -1461,14 +1432,12 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty · 20 unmodified lines | |||
| 1461 | if (!ret) | 1432 | if (!ret) |
| 1462 | return 0; | 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 | out_uart: | 1437 | out_uart: |
| 1467 | for (i = 0; i < devtype->nr; i++) { | 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 | uart_remove_one_port(&max310x_uart, &s->p[i].port); | 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 | out_clk: | 1443 | out_clk: |
| @@ -1486,9 +1455,11 @@ static void max310x_remove(struct device *dev) · 11 unmodified lines | |||
| 1486 | cancel_work_sync(&s->p[i].tx_work); | 1455 | cancel_work_sync(&s->p[i].tx_work); |
| 1487 | cancel_work_sync(&s->p[i].md_work); | 1456 | cancel_work_sync(&s->p[i].md_work); |
| 1488 | cancel_work_sync(&s->p[i].rs_work); | 1457 | cancel_work_sync(&s->p[i].rs_work); |
| 1489 | uart_remove_one_port(&max310x_uart, &s->p[i].port); | 1458 | |
| 1490 | clear_bit(s->p[i].port.line, max310x_lines); | 1459 | if (test_and_clear_bit(s->p[i].port.line, max310x_lines)) |
| 1491 | s->devtype->power(&s->p[i].port, 0); | 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 | clk_disable_unprepare(s->clk); | 1465 | clk_disable_unprepare(s->clk); |
| @@ -1518,6 +1489,19 @@ static struct regmap_config regcfg = { · 23 unmodified lines | |||
| 1518 | .max_raw_write = MAX310X_FIFO_SIZE, | 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 | #ifdef CONFIG_SPI_MASTER | 1505 | #ifdef CONFIG_SPI_MASTER |
| 1522 | static int max310x_spi_extended_reg_enable(struct device *dev, bool enable) | 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 | static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = { | 1514 | static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = { |
| 1531 | .extended_reg_enable = max310x_spi_extended_reg_enable, | 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 | static int max310x_spi_probe(struct spi_device *spi) | 1519 | static int max310x_spi_probe(struct spi_device *spi) |
| 1536 | { | 1520 | { |
| 1537 | const struct max310x_devtype *devtype; | 1521 | const struct max310x_devtype *devtype; |
| 1538 | struct regmap *regmaps[4]; | 1522 | struct regmap *regmaps[MAX310X_MAX_PORTS]; |
| 1539 | unsigned int i; | 1523 | unsigned int i; |
| 1540 | int ret; | 1524 | int ret; |
| 1541 | 1525 | ||
| @@ -1547,12 +1531,14 @@ static int max310x_spi_probe(struct spi_device *spi) · 5 unmodified lines | |||
| 1547 | if (ret) | 1531 | if (ret) |
| 1548 | return ret; | 1532 | return ret; |
| 1549 | 1533 | ||
| 1550 | devtype = device_get_match_data(&spi->dev); | 1534 | devtype = spi_get_device_match_data(spi); |
| 1551 | if (!devtype) | 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 | for (i = 0; i < devtype->nr; i++) { | 1538 | for (i = 0; i < devtype->nr; i++) { |
| 1555 | u8 port_mask = i * 0x20; | 1539 | u8 port_mask = i * 0x20; |
| 1540 | |||
| 1541 | regcfg.name = max310x_regmap_name(i); | ||
| 1556 | regcfg.read_flag_mask = port_mask; | 1542 | regcfg.read_flag_mask = port_mask; |
| 1557 | regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT; | 1543 | regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT; |
| 1558 | regmaps[i] = devm_regmap_init_spi(spi, ®cfg); | 1544 | regmaps[i] = devm_regmap_init_spi(spi, ®cfg); |
| @@ -1600,7 +1586,7 @@ static struct regmap_config regcfg_i2c = { · 41 unmodified lines | |||
| 1600 | .writeable_reg = max310x_reg_writeable, | 1586 | .writeable_reg = max310x_reg_writeable, |
| 1601 | .volatile_reg = max310x_reg_volatile, | 1587 | .volatile_reg = max310x_reg_volatile, |
| 1602 | .precious_reg = max310x_reg_precious, | 1588 | .precious_reg = max310x_reg_precious, |
| 1603 | .max_register = MAX310X_I2C_REVID_EXTREG, | 1589 | .max_register = MAX310X_REVID_EXTREG, |
| 1604 | .writeable_noinc_reg = max310x_reg_noinc, | 1590 | .writeable_noinc_reg = max310x_reg_noinc, |
| 1605 | .readable_noinc_reg = max310x_reg_noinc, | 1591 | .readable_noinc_reg = max310x_reg_noinc, |
| 1606 | .max_raw_read = MAX310X_FIFO_SIZE, | 1592 | .max_raw_read = MAX310X_FIFO_SIZE, |
| @@ -1609,7 +1595,7 @@ static struct regmap_config regcfg_i2c = { · 2 unmodified lines | |||
| 1609 | 1595 | ||
| 1610 | static const struct max310x_if_cfg max310x_i2c_if_cfg = { | 1596 | static const struct max310x_if_cfg max310x_i2c_if_cfg = { |
| 1611 | .extended_reg_enable = max310x_i2c_extended_reg_enable, | 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 | static unsigned short max310x_i2c_slave_addr(unsigned short addr, | 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 | * For MAX14830 and MAX3109, the slave address depends on what the | 1605 | * For MAX14830 and MAX3109, the slave address depends on what the |
| 1620 | * A0 and A1 pins are tied to. | 1606 | * A0 and A1 pins are tied to. |
| 1621 | * See Table I2C Address Map of the datasheet. | 1607 | * See Table I2C Address Map of the datasheet. |
| 1622 | * Based on that table, the following formulas were determined. | 1608 | * Based on that table, the following formulas were determined: |
| 1623 | * UART1 - UART0 = 0x10 | 1609 | * UART1 - UART0 = 0x10 |
| 1624 | * UART2 - UART1 = 0x20 + 0x10 | 1610 | * UART2 - UART1 = 0x20 + 0x10 |
| 1625 | * UART3 - UART2 = 0x10 | 1611 | * UART3 - UART2 = 0x10 |
| 1626 | */ | 1612 | */ |
| 1627 | 1613 | ||
| 1628 | addr -= nr * 0x10; | 1614 | addr -= nr * 0x10; |
| @@ -1635,20 +1621,24 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr, · 6 unmodified lines | |||
| 1635 | 1621 | ||
| 1636 | static int max310x_i2c_probe(struct i2c_client *client) | 1622 | static int max310x_i2c_probe(struct i2c_client *client) |
| 1637 | { | 1623 | { |
| 1638 | const struct max310x_devtype *devtype = | 1624 | const struct max310x_devtype *devtype; |
| 1639 | device_get_match_data(&client->dev); | ||
| 1640 | struct i2c_client *port_client; | 1625 | struct i2c_client *port_client; |
| 1641 | struct regmap *regmaps[4]; | 1626 | struct regmap *regmaps[MAX310X_MAX_PORTS]; |
| 1642 | unsigned int i; | 1627 | unsigned int i; |
| 1643 | u8 port_addr; | 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 | if (client->addr < devtype->slave_addr.min || | 1634 | if (client->addr < devtype->slave_addr.min || |
| 1646 | client->addr > devtype->slave_addr.max) | 1635 | client->addr > devtype->slave_addr.max) |
| 1647 | return dev_err_probe(&client->dev, -EINVAL, | 1636 | return dev_err_probe(&client->dev, -EINVAL, |
| 1648 | "Slave addr 0x%x outside of range [0x%x, 0x%x]\n", | 1637 | "Slave addr 0x%x outside of range [0x%x, 0x%x]\n", |
| 1649 | client->addr, devtype->slave_addr.min, | 1638 | client->addr, devtype->slave_addr.min, |
| 1650 | devtype->slave_addr.max); | 1639 | devtype->slave_addr.max); |
| 1651 | 1640 | ||
| 1641 | regcfg_i2c.name = max310x_regmap_name(0); | ||
| 1652 | regmaps[0] = devm_regmap_init_i2c(client, ®cfg_i2c); | 1642 | regmaps[0] = devm_regmap_init_i2c(client, ®cfg_i2c); |
| 1653 | 1643 | ||
| 1654 | for (i = 1; i < devtype->nr; i++) { | 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 | client->adapter, | 1647 | client->adapter, |
| 1658 | port_addr); | 1648 | port_addr); |
| 1659 | 1649 | ||
| 1650 | regcfg_i2c.name = max310x_regmap_name(i); | ||
| 1660 | regmaps[i] = devm_regmap_init_i2c(port_client, ®cfg_i2c); | 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 | max310x_remove(&client->dev); | 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 | static struct i2c_driver max310x_i2c_driver = { | 1672 | static struct i2c_driver max310x_i2c_driver = { |
| 1673 | .driver = { | 1673 | .driver = { |
| 1674 | .name = MAX310X_NAME, | 1674 | .name = MAX310X_NAME, |
| @@ -1677,6 +1677,7 @@ static struct i2c_driver max310x_i2c_driver = { · 2 unmodified lines | |||
| 1677 | }, | 1677 | }, |
| 1678 | .probe = max310x_i2c_probe, | 1678 | .probe = max310x_i2c_probe, |
| 1679 | .remove = max310x_i2c_remove, | 1679 | .remove = max310x_i2c_remove, |
| 1680 | .id_table = max310x_i2c_id_table, | ||
| 1680 | }; | 1681 | }; |
| 1681 | #endif | 1682 | #endif |
| 1682 | 1683 | ||
| @@ -470,33 +470,6 @@ static struct mcf_uart mcf_ports[4]; · 469 unmodified lines | |||
| 470 | #if defined(CONFIG_SERIAL_MCF_CONSOLE) | 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 | static void mcf_console_putc(struct console *co, const char c) | 473 | static void mcf_console_putc(struct console *co, const char c) |
| 501 | { | 474 | { |
| 502 | struct uart_port *port = &(mcf_ports + co->index)->port; | 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 | continue; | 220 | continue; |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | if (uart_handle_sysrq_char(port, ch)) | 223 | if (uart_prepare_sysrq_char(port, ch)) |
| 224 | continue; | 224 | continue; |
| 225 | 225 | ||
| 226 | if ((status & port->ignore_status_mask) == 0) | 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 | meson_uart_start_tx(port); | 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 | return IRQ_HANDLED; | 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 | u_int count) | 556 | u_int count) |
| 557 | { | 557 | { |
| 558 | unsigned long flags; | 558 | unsigned long flags; |
| 559 | int locked; | 559 | int locked = 1; |
| 560 | u32 val, tmp; | 560 | u32 val, tmp; |
| 561 | 561 | ||
| 562 | local_irq_save(flags); | 562 | if (oops_in_progress) |
| 563 | if (port->sysrq) { | 563 | locked = uart_port_trylock_irqsave(port, &flags); |
| 564 | locked = 0; | 564 | else |
| 565 | } else if (oops_in_progress) { | 565 | uart_port_lock_irqsave(port, &flags); |
| 566 | locked = uart_port_trylock(port); | ||
| 567 | } else { | ||
| 568 | uart_port_lock(port); | ||
| 569 | locked = 1; | ||
| 570 | } | ||
| 571 | 566 | ||
| 572 | val = readl(port->membase + AML_UART_CONTROL); | 567 | val = readl(port->membase + AML_UART_CONTROL); |
| 573 | tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN); | 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 | writel(val, port->membase + AML_UART_CONTROL); | 572 | writel(val, port->membase + AML_UART_CONTROL); |
| 578 | 573 | ||
| 579 | if (locked) | 574 | if (locked) |
| 580 | uart_port_unlock(port); | 575 | uart_port_unlock_irqrestore(port, flags); |
| 581 | local_irq_restore(flags); | ||
| 582 | } | 576 | } |
| 583 | 577 | ||
| 584 | static void meson_serial_console_write(struct console *co, const char *s, | 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 | if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) | 588 | if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) |
| 589 | flag = TTY_NORMAL; | 589 | flag = TTY_NORMAL; |
| 590 | 590 | ||
| 591 | uart_port_unlock_irqrestore(port, flags); | 591 | sysrq = uart_prepare_sysrq_char(port, dma->virt[i]); |
| 592 | sysrq = uart_handle_sysrq_char(port, dma->virt[i]); | ||
| 593 | uart_port_lock_irqsave(port, &flags); | ||
| 594 | if (!sysrq) | 592 | if (!sysrq) |
| 595 | tty_insert_flip_char(tport, dma->virt[i], flag); | 593 | tty_insert_flip_char(tport, dma->virt[i], flag); |
| 596 | } | 594 | } |
| 597 | 595 | ||
| 598 | msm_start_rx_dma(msm_port); | 596 | msm_start_rx_dma(msm_port); |
| 599 | done: | 597 | done: |
| 600 | uart_port_unlock_irqrestore(port, flags); | 598 | uart_unlock_and_check_sysrq_irqrestore(port, flags); |
| 601 | 599 | ||
| 602 | if (count) | 600 | if (count) |
| 603 | tty_flip_buffer_push(tport); | 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 | if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) | 761 | if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) |
| 764 | flag = TTY_NORMAL; | 762 | flag = TTY_NORMAL; |
| 765 | 763 | ||
| 766 | uart_port_unlock(port); | 764 | sysrq = uart_prepare_sysrq_char(port, buf[i]); |
| 767 | sysrq = uart_handle_sysrq_char(port, buf[i]); | ||
| 768 | uart_port_lock(port); | ||
| 769 | if (!sysrq) | 765 | if (!sysrq) |
| 770 | tty_insert_flip_char(tport, buf[i], flag); | 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 | else if (sr & MSM_UART_SR_PAR_FRAME_ERR) | 821 | else if (sr & MSM_UART_SR_PAR_FRAME_ERR) |
| 826 | flag = TTY_FRAME; | 822 | flag = TTY_FRAME; |
| 827 | 823 | ||
| 828 | uart_port_unlock(port); | 824 | sysrq = uart_prepare_sysrq_char(port, c); |
| 829 | sysrq = uart_handle_sysrq_char(port, c); | ||
| 830 | uart_port_lock(port); | ||
| 831 | if (!sysrq) | 825 | if (!sysrq) |
| 832 | tty_insert_flip_char(tport, c, flag); | 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 | struct uart_port *port = dev_id; | 942 | struct uart_port *port = dev_id; |
| 949 | struct msm_port *msm_port = to_msm_port(port); | 943 | struct msm_port *msm_port = to_msm_port(port); |
| 950 | struct msm_dma *dma = &msm_port->rx_dma; | 944 | struct msm_dma *dma = &msm_port->rx_dma; |
| 951 | unsigned long flags; | ||
| 952 | unsigned int misr; | 945 | unsigned int misr; |
| 953 | u32 val; | 946 | u32 val; |
| 954 | 947 | ||
| 955 | uart_port_lock_irqsave(port, &flags); | 948 | uart_port_lock(port); |
| 956 | misr = msm_read(port, MSM_UART_MISR); | 949 | misr = msm_read(port, MSM_UART_MISR); |
| 957 | msm_write(port, 0, MSM_UART_IMR); /* disable interrupt */ | 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 | msm_handle_delta_cts(port); | 977 | msm_handle_delta_cts(port); |
| 985 | 978 | ||
| 986 | msm_write(port, msm_port->imr, MSM_UART_IMR); /* restore interrupt */ | 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 | return IRQ_HANDLED; | 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 | num_newlines++; | 1614 | num_newlines++; |
| 1622 | count += num_newlines; | 1615 | count += num_newlines; |
| 1623 | 1616 | ||
| 1624 | local_irq_save(flags); | 1617 | if (oops_in_progress) |
| 1625 | 1618 | locked = uart_port_trylock_irqsave(port, &flags); | |
| 1626 | if (port->sysrq) | ||
| 1627 | locked = 0; | ||
| 1628 | else if (oops_in_progress) | ||
| 1629 | locked = uart_port_trylock(port); | ||
| 1630 | else | 1619 | else |
| 1631 | uart_port_lock(port); | 1620 | uart_port_lock_irqsave(port, &flags); |
| 1632 | 1621 | ||
| 1633 | if (is_uartdm) | 1622 | if (is_uartdm) |
| 1634 | msm_reset_dm_count(port, count); | 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 | if (locked) | 1658 | if (locked) |
| 1670 | uart_port_unlock(port); | 1659 | uart_port_unlock_irqrestore(port, flags); |
| 1671 | |||
| 1672 | local_irq_restore(flags); | ||
| 1673 | } | 1660 | } |
| 1674 | 1661 | ||
| 1675 | static void msm_console_write(struct console *co, const char *s, | 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 | up->port.icount.rx++; | 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 | return; | 512 | return; |
| 513 | 513 | ||
| 514 | uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, TTY_NORMAL); | 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 | } while (max_count--); | 564 | } while (max_count--); |
| 565 | 565 | ||
| 566 | uart_port_unlock(&up->port); | 566 | uart_unlock_and_check_sysrq(&up->port); |
| 567 | 567 | ||
| 568 | tty_flip_buffer_push(&up->port.state->port); | 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 | unsigned int ier; | 1212 | unsigned int ier; |
| 1213 | int locked = 1; | 1213 | int locked = 1; |
| 1214 | 1214 | ||
| 1215 | local_irq_save(flags); | 1215 | if (oops_in_progress) |
| 1216 | if (up->port.sysrq) | 1216 | locked = uart_port_trylock_irqsave(&up->port, &flags); |
| 1217 | locked = 0; | ||
| 1218 | else if (oops_in_progress) | ||
| 1219 | locked = uart_port_trylock(&up->port); | ||
| 1220 | else | 1217 | else |
| 1221 | uart_port_lock(&up->port); | 1218 | uart_port_lock_irqsave(&up->port, &flags); |
| 1222 | 1219 | ||
| 1223 | /* | 1220 | /* |
| 1224 | * First save the IER then disable the interrupts | 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 | check_modem_status(up); | 1242 | check_modem_status(up); |
| 1246 | 1243 | ||
| 1247 | if (locked) | 1244 | if (locked) |
| 1248 | uart_port_unlock(&up->port); | 1245 | uart_port_unlock_irqrestore(&up->port, flags); |
| 1249 | local_irq_restore(flags); | ||
| 1250 | } | 1246 | } |
| 1251 | 1247 | ||
| 1252 | static int __init | 1248 | static int __init |
| @@ -199,6 +199,7 @@ static void owl_uart_receive_chars(struct uart_port *port) · 198 unmodified lines | |||
| 199 | stat = owl_uart_read(port, OWL_UART_STAT); | 199 | stat = owl_uart_read(port, OWL_UART_STAT); |
| 200 | while (!(stat & OWL_UART_STAT_RFEM)) { | 200 | while (!(stat & OWL_UART_STAT_RFEM)) { |
| 201 | char flag = TTY_NORMAL; | 201 | char flag = TTY_NORMAL; |
| 202 | bool sysrq; | ||
| 202 | 203 | ||
| 203 | if (stat & OWL_UART_STAT_RXER) | 204 | if (stat & OWL_UART_STAT_RXER) |
| 204 | port->icount.overrun++; | 205 | port->icount.overrun++; |
| @@ -217,7 +218,9 @@ static void owl_uart_receive_chars(struct uart_port *port) · 12 unmodified lines | |||
| 217 | val = owl_uart_read(port, OWL_UART_RXDAT); | 218 | val = owl_uart_read(port, OWL_UART_RXDAT); |
| 218 | val &= 0xff; | 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 | tty_insert_flip_char(&port->state->port, val, flag); | 224 | tty_insert_flip_char(&port->state->port, val, flag); |
| 222 | 225 | ||
| 223 | stat = owl_uart_read(port, OWL_UART_STAT); | 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 | static irqreturn_t owl_uart_irq(int irq, void *dev_id) | 232 | static irqreturn_t owl_uart_irq(int irq, void *dev_id) |
| 230 | { | 233 | { |
| 231 | struct uart_port *port = dev_id; | 234 | struct uart_port *port = dev_id; |
| 232 | unsigned long flags; | ||
| 233 | u32 stat; | 235 | u32 stat; |
| 234 | 236 | ||
| 235 | uart_port_lock_irqsave(port, &flags); | 237 | uart_port_lock(port); |
| 236 | 238 | ||
| 237 | stat = owl_uart_read(port, OWL_UART_STAT); | 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 | stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP; | 248 | stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP; |
| 247 | owl_uart_write(port, stat, OWL_UART_STAT); | 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 | return IRQ_HANDLED; | 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 | u32 old_ctl, val; | 511 | u32 old_ctl, val; |
| 510 | unsigned long flags; | 512 | unsigned long flags; |
| 511 | int locked; | 513 | int locked = 1; |
| 512 | 514 | ||
| 513 | local_irq_save(flags); | 515 | if (oops_in_progress) |
| 514 | 516 | locked = uart_port_trylock_irqsave(port, &flags); | |
| 515 | if (port->sysrq) | 517 | else |
| 516 | locked = 0; | 518 | uart_port_lock_irqsave(port, &flags); |
| 517 | else if (oops_in_progress) | ||
| 518 | locked = uart_port_trylock(port); | ||
| 519 | else { | ||
| 520 | uart_port_lock(port); | ||
| 521 | locked = 1; | ||
| 522 | } | ||
| 523 | 519 | ||
| 524 | old_ctl = owl_uart_read(port, OWL_UART_CTL); | 520 | old_ctl = owl_uart_read(port, OWL_UART_CTL); |
| 525 | val = old_ctl | OWL_UART_CTL_TRFS_TX; | 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 | owl_uart_write(port, old_ctl, OWL_UART_CTL); | 537 | owl_uart_write(port, old_ctl, OWL_UART_CTL); |
| 542 | 538 | ||
| 543 | if (locked) | 539 | if (locked) |
| 544 | uart_port_unlock(port); | 540 | uart_port_unlock_irqrestore(port, flags); |
| 545 | |||
| 546 | local_irq_restore(flags); | ||
| 547 | } | 541 | } |
| 548 | 542 | ||
| 549 | static void owl_uart_console_write(struct console *co, const char *s, | 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 | #define IRQ_NAME_SIZE 17 | 238 | #define IRQ_NAME_SIZE 17 |
| 239 | char irq_name[IRQ_NAME_SIZE]; | 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 | if (uart_handle_break(port)) | 564 | if (uart_handle_break(port)) |
| 568 | continue; | 565 | continue; |
| 569 | } | 566 | } |
| 570 | if (uart_handle_sysrq_char(port, rbr)) | 567 | if (uart_prepare_sysrq_char(port, rbr)) |
| 571 | continue; | 568 | continue; |
| 572 | 569 | ||
| 573 | buf[i++] = rbr; | 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 | iowrite8(lcr, priv->membase + UART_LCR); | 596 | iowrite8(lcr, priv->membase + UART_LCR); |
| 600 | } | 597 | } |
| 601 | 598 | ||
| 602 | static int push_rx(struct eg20t_port *priv, const unsigned char *buf, | 599 | static void push_rx(struct eg20t_port *priv, const unsigned char *buf, |
| 603 | int size) | 600 | int size) |
| 604 | { | 601 | { |
| 605 | struct uart_port *port = &priv->port; | 602 | struct uart_port *port = &priv->port; |
| 606 | struct tty_port *tport = &port->state->port; | 603 | struct tty_port *tport = &port->state->port; |
| 607 | 604 | ||
| 608 | tty_insert_flip_string(tport, buf, size); | 605 | tty_insert_flip_string(tport, buf, size); |
| 609 | tty_flip_buffer_push(tport); | 606 | tty_flip_buffer_push(tport); |
| 610 | |||
| 611 | return 0; | ||
| 612 | } | 607 | } |
| 613 | 608 | ||
| 614 | static int dma_push_rx(struct eg20t_port *priv, int size) | 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 | struct pch_uart_buffer *buf; | 757 | struct pch_uart_buffer *buf; |
| 763 | int rx_size; | 758 | int rx_size; |
| 764 | int ret; | 759 | |
| 765 | if (!priv->start_rx) { | 760 | if (!priv->start_rx) { |
| 766 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | | 761 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | |
| 767 | PCH_UART_HAL_RX_ERR_INT); | 762 | PCH_UART_HAL_RX_ERR_INT); |
| @@ -770,19 +765,12 @@ static int handle_rx_to(struct eg20t_port *priv) · 2 unmodified lines | |||
| 770 | buf = &priv->rxbuf; | 765 | buf = &priv->rxbuf; |
| 771 | do { | 766 | do { |
| 772 | rx_size = pch_uart_hal_read(priv, buf->buf, buf->size); | 767 | rx_size = pch_uart_hal_read(priv, buf->buf, buf->size); |
| 773 | ret = push_rx(priv, buf->buf, rx_size); | 768 | push_rx(priv, buf->buf, rx_size); |
| 774 | if (ret) | ||
| 775 | return 0; | ||
| 776 | } while (rx_size == buf->size); | 769 | } while (rx_size == buf->size); |
| 777 | 770 | ||
| 778 | return PCH_UART_HANDLED_RX_INT; | 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 | static int dma_handle_rx(struct eg20t_port *priv) | 774 | static int dma_handle_rx(struct eg20t_port *priv) |
| 787 | { | 775 | { |
| 788 | struct uart_port *port = &priv->port; | 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 | u8 lsr; | 1007 | u8 lsr; |
| 1020 | int ret = 0; | 1008 | int ret = 0; |
| 1021 | unsigned char iid; | 1009 | unsigned char iid; |
| 1022 | unsigned long flags; | ||
| 1023 | int next = 1; | 1010 | int next = 1; |
| 1024 | u8 msr; | 1011 | u8 msr; |
| 1025 | 1012 | ||
| 1026 | spin_lock_irqsave(&priv->lock, flags); | 1013 | uart_port_lock(&priv->port); |
| 1027 | handled = 0; | 1014 | handled = 0; |
| 1028 | while (next) { | 1015 | while (next) { |
| 1029 | iid = pch_uart_hal_get_iid(priv); | 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 | PCH_UART_HAL_RX_INT | | 1038 | PCH_UART_HAL_RX_INT | |
| 1052 | PCH_UART_HAL_RX_ERR_INT); | 1039 | PCH_UART_HAL_RX_ERR_INT); |
| 1053 | } else { | 1040 | } else { |
| 1054 | ret = handle_rx(priv); | 1041 | ret = handle_rx_to(priv); |
| 1055 | } | 1042 | } |
| 1056 | break; | 1043 | break; |
| 1057 | case PCH_UART_IID_RDR_TO: /* Received Data Ready | 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 | handled |= (unsigned int)ret; | 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 | return IRQ_RETVAL(handled); | 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 | unsigned long flags; | 1181 | unsigned long flags; |
| 1195 | 1182 | ||
| 1196 | priv = container_of(port, struct eg20t_port, port); | 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 | pch_uart_hal_set_break(priv, ctl); | 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 | /* Grab any interrupt resources and initialise any low level driver state. */ | 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 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); | 1334 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); |
| 1348 | 1335 | ||
| 1349 | spin_lock_irqsave(&priv->lock, flags); | 1336 | uart_port_lock_irqsave(port, &flags); |
| 1350 | uart_port_lock(port); | ||
| 1351 | 1337 | ||
| 1352 | uart_update_timeout(port, termios->c_cflag, baud); | 1338 | uart_update_timeout(port, termios->c_cflag, baud); |
| 1353 | rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb); | 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 | tty_termios_encode_baud_rate(termios, baud, baud); | 1346 | tty_termios_encode_baud_rate(termios, baud, baud); |
| 1361 | 1347 | ||
| 1362 | out: | 1348 | out: |
| 1363 | uart_port_unlock(port); | 1349 | uart_port_unlock_irqrestore(port, flags); |
| 1364 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 1365 | } | 1350 | } |
| 1366 | 1351 | ||
| 1367 | static const char *pch_uart_type(struct uart_port *port) | 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 | struct eg20t_port *priv; | 1551 | struct eg20t_port *priv; |
| 1567 | unsigned long flags; | 1552 | unsigned long flags; |
| 1568 | int priv_locked = 1; | 1553 | int locked = 1; |
| 1569 | int port_locked = 1; | ||
| 1570 | u8 ier; | 1554 | u8 ier; |
| 1571 | 1555 | ||
| 1572 | priv = pch_uart_ports[co->index]; | 1556 | priv = pch_uart_ports[co->index]; |
| 1573 | 1557 | ||
| 1574 | touch_nmi_watchdog(); | 1558 | touch_nmi_watchdog(); |
| 1575 | 1559 | ||
| 1576 | local_irq_save(flags); | 1560 | if (oops_in_progress) |
| 1577 | if (priv->port.sysrq) { | 1561 | locked = uart_port_trylock_irqsave(&priv->port, &flags); |
| 1578 | /* call to uart_handle_sysrq_char already took the priv lock */ | 1562 | else |
| 1579 | priv_locked = 0; | 1563 | uart_port_lock_irqsave(&priv->port, &flags); |
| 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 | } | ||
| 1589 | 1564 | ||
| 1590 | /* | 1565 | /* |
| 1591 | * First save the IER then disable the interrupts | 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 | wait_for_xmitr(priv, UART_LSR_BOTH_EMPTY); | 1578 | wait_for_xmitr(priv, UART_LSR_BOTH_EMPTY); |
| 1604 | iowrite8(ier, priv->membase + UART_IER); | 1579 | iowrite8(ier, priv->membase + UART_IER); |
| 1605 | 1580 | ||
| 1606 | if (port_locked) | 1581 | if (locked) |
| 1607 | uart_port_unlock(&priv->port); | 1582 | uart_port_unlock_irqrestore(&priv->port, flags); |
| 1608 | if (priv_locked) | ||
| 1609 | spin_unlock(&priv->lock); | ||
| 1610 | local_irq_restore(flags); | ||
| 1611 | } | 1583 | } |
| 1612 | 1584 | ||
| 1613 | static int __init pch_console_setup(struct console *co, char *options) | 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 | pci_enable_msi(pdev); | 1676 | pci_enable_msi(pdev); |
| 1705 | pci_set_master(pdev); | 1677 | pci_set_master(pdev); |
| 1706 | 1678 | ||
| 1707 | spin_lock_init(&priv->lock); | ||
| 1708 | |||
| 1709 | iobase = pci_resource_start(pdev, 0); | 1679 | iobase = pci_resource_start(pdev, 0); |
| 1710 | mapbase = pci_resource_start(pdev, 1); | 1680 | mapbase = pci_resource_start(pdev, 1); |
| 1711 | priv->mapbase = mapbase; | 1681 | priv->mapbase = mapbase; |
| @@ -1735,8 +1705,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, · 23 unmodified lines | |||
| 1735 | KBUILD_MODNAME ":" PCH_UART_DRIVER_DEVICE "%d", | 1705 | KBUILD_MODNAME ":" PCH_UART_DRIVER_DEVICE "%d", |
| 1736 | priv->port.line); | 1706 | priv->port.line); |
| 1737 | 1707 | ||
| 1738 | spin_lock_init(&priv->port.lock); | ||
| 1739 | |||
| 1740 | pci_set_drvdata(pdev, priv); | 1708 | pci_set_drvdata(pdev, priv); |
| 1741 | priv->trigger_level = 1; | 1709 | priv->trigger_level = 1; |
| 1742 | priv->fcr = 0; | 1710 | priv->fcr = 0; |
| @@ -1714,18 +1714,13 @@ static int __init pmz_attach(struct platform_device *pdev) · 1713 unmodified lines | |||
| 1714 | return uart_add_one_port(&pmz_uart_reg, &uap->port); | 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 | struct uart_pmac_port *uap = platform_get_drvdata(pdev); | 1719 | struct uart_pmac_port *uap = platform_get_drvdata(pdev); |
| 1720 | 1720 | ||
| 1721 | if (!uap) | ||
| 1722 | return -ENODEV; | ||
| 1723 | |||
| 1724 | uart_remove_one_port(&pmz_uart_reg, &uap->port); | 1721 | uart_remove_one_port(&pmz_uart_reg, &uap->port); |
| 1725 | 1722 | ||
| 1726 | uap->port.dev = NULL; | 1723 | uap->port.dev = NULL; |
| 1727 | |||
| 1728 | return 0; | ||
| 1729 | } | 1724 | } |
| 1730 | 1725 | ||
| 1731 | #endif /* !CONFIG_PPC_PMAC */ | 1726 | #endif /* !CONFIG_PPC_PMAC */ |
| @@ -1794,7 +1789,7 @@ static struct macio_driver pmz_driver = { · 62 unmodified lines | |||
| 1794 | #else | 1789 | #else |
| 1795 | 1790 | ||
| 1796 | static struct platform_driver pmz_driver = { | 1791 | static struct platform_driver pmz_driver = { |
| 1797 | .remove = __exit_p(pmz_detach), | 1792 | .remove_new = __exit_p(pmz_detach), |
| 1798 | .driver = { | 1793 | .driver = { |
| 1799 | .name = "scc", | 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 | flag = TTY_FRAME; | 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 | goto ignore_char; | 155 | goto ignore_char; |
| 156 | 156 | ||
| 157 | uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); | 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 | check_modem_status(up); | 232 | check_modem_status(up); |
| 233 | if (lsr & UART_LSR_THRE) | 233 | if (lsr & UART_LSR_THRE) |
| 234 | transmit_chars(up); | 234 | transmit_chars(up); |
| 235 | uart_port_unlock(&up->port); | 235 | uart_unlock_and_check_sysrq(&up->port); |
| 236 | return IRQ_HANDLED; | 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 | int locked = 1; | 604 | int locked = 1; |
| 605 | 605 | ||
| 606 | clk_enable(up->clk); | 606 | clk_enable(up->clk); |
| 607 | local_irq_save(flags); | 607 | if (oops_in_progress) |
| 608 | if (up->port.sysrq) | 608 | locked = uart_port_trylock_irqsave(&up->port, &flags); |
| 609 | locked = 0; | ||
| 610 | else if (oops_in_progress) | ||
| 611 | locked = uart_port_trylock(&up->port); | ||
| 612 | else | 609 | else |
| 613 | uart_port_lock(&up->port); | 610 | uart_port_lock_irqsave(&up->port, &flags); |
| 614 | 611 | ||
| 615 | /* | 612 | /* |
| 616 | * First save the IER then disable the interrupts | 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 | serial_out(up, UART_IER, ier); | 625 | serial_out(up, UART_IER, ier); |
| 629 | 626 | ||
| 630 | if (locked) | 627 | if (locked) |
| 631 | uart_port_unlock(&up->port); | 628 | uart_port_unlock_irqrestore(&up->port, flags); |
| 632 | local_irq_restore(flags); | ||
| 633 | clk_disable(up->clk); | 629 | clk_disable(up->clk); |
| 634 | |||
| 635 | } | 630 | } |
| 636 | 631 | ||
| 637 | #ifdef CONFIG_CONSOLE_POLL | 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 | geni_status = readl(uport->membase + SE_GENI_STATUS); | 489 | geni_status = readl(uport->membase + SE_GENI_STATUS); |
| 490 | 490 | ||
| 491 | /* Cancel the current write to log the fault */ | ||
| 492 | if (!locked) { | 491 | if (!locked) { |
| 493 | geni_se_cancel_m_cmd(&port->se); | 492 | /* |
| 494 | if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, | 493 | * We can only get here if an oops is in progress then we were |
| 495 | M_CMD_CANCEL_EN, true)) { | 494 | * unable to get the lock. This means we can't safely access |
| 496 | geni_se_abort_m_cmd(&port->se); | 495 | * our state variables like tx_remaining. About the best we |
| 497 | qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, | 496 | * can do is wait for the FIFO to be empty before we start our |
| 498 | M_CMD_ABORT_EN, true); | 497 | * transfer, so we'll do that. |
| 499 | writel(M_CMD_ABORT_EN, uport->membase + | 498 | */ |
| 500 | SE_GENI_M_IRQ_CLEAR); | 499 | qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, |
| 501 | } | 500 | M_TX_FIFO_NOT_EMPTY_EN, false); |
| 502 | writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); | ||
| 503 | } else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) { | 501 | } else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) { |
| 504 | /* | 502 | /* |
| 505 | * It seems we can't interrupt existing transfers if all data | 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 | __qcom_geni_serial_console_write(uport, s, count); | 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 | uart_port_unlock_irqrestore(uport, flags); | 521 | uart_port_unlock_irqrestore(uport, flags); |
| 522 | } | ||
| 524 | } | 523 | } |
| 525 | 524 | ||
| 526 | static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop) | 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 | val &= 0xff; | 394 | val &= 0xff; |
| 395 | 395 | ||
| 396 | port->icount.rx++; | 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 | status = rda_uart_read(port, RDA_UART_STATUS); | 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 | static irqreturn_t rda_interrupt(int irq, void *dev_id) | 406 | static irqreturn_t rda_interrupt(int irq, void *dev_id) |
| 406 | { | 407 | { |
| 407 | struct uart_port *port = dev_id; | 408 | struct uart_port *port = dev_id; |
| 408 | unsigned long flags; | ||
| 409 | u32 val, irq_mask; | 409 | u32 val, irq_mask; |
| 410 | 410 | ||
| 411 | uart_port_lock_irqsave(port, &flags); | 411 | uart_port_lock(port); |
| 412 | 412 | ||
| 413 | /* Clear IRQ cause */ | 413 | /* Clear IRQ cause */ |
| 414 | val = rda_uart_read(port, RDA_UART_IRQ_CAUSE); | 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 | rda_uart_send_chars(port); | 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 | return IRQ_HANDLED; | 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 | u32 old_irq_mask; | 591 | u32 old_irq_mask; |
| 592 | unsigned long flags; | 592 | unsigned long flags; |
| 593 | int locked; | 593 | int locked = 1; |
| 594 | |||
| 595 | local_irq_save(flags); | ||
| 596 | 594 | ||
| 597 | if (port->sysrq) { | 595 | if (oops_in_progress) |
| 598 | locked = 0; | 596 | locked = uart_port_trylock_irqsave(port, &flags); |
| 599 | } else if (oops_in_progress) { | 597 | else |
| 600 | locked = uart_port_trylock(port); | 598 | uart_port_lock_irqsave(port, &flags); |
| 601 | } else { | ||
| 602 | uart_port_lock(port); | ||
| 603 | locked = 1; | ||
| 604 | } | ||
| 605 | 599 | ||
| 606 | old_irq_mask = rda_uart_read(port, RDA_UART_IRQ_MASK); | 600 | old_irq_mask = rda_uart_read(port, RDA_UART_IRQ_MASK); |
| 607 | rda_uart_write(port, 0, RDA_UART_IRQ_MASK); | 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 | rda_uart_write(port, old_irq_mask, RDA_UART_IRQ_MASK); | 609 | rda_uart_write(port, old_irq_mask, RDA_UART_IRQ_MASK); |
| 616 | 610 | ||
| 617 | if (locked) | 611 | if (locked) |
| 618 | uart_port_unlock(port); | 612 | uart_port_unlock_irqrestore(port, flags); |
| 619 | |||
| 620 | local_irq_restore(flags); | ||
| 621 | } | 613 | } |
| 622 | 614 | ||
| 623 | static void rda_uart_console_write(struct console *co, const char *s, | 615 | static void rda_uart_console_write(struct console *co, const char *s, |
| @@ -21,26 +21,28 @@ · 20 unmodified lines | |||
| 21 | * BJD, 04-Nov-2004 | 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 | #include <linux/dma-mapping.h> | 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 | #include <linux/math.h> | 33 | #include <linux/math.h> |
| 28 | #include <linux/module.h> | 34 | #include <linux/module.h> |
| 29 | #include <linux/ioport.h> | 35 | #include <linux/of.h> |
| 30 | #include <linux/io.h> | ||
| 31 | #include <linux/platform_device.h> | 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 | #include <linux/sysrq.h> | 41 | #include <linux/sysrq.h> |
| 34 | #include <linux/console.h> | ||
| 35 | #include <linux/tty.h> | 42 | #include <linux/tty.h> |
| 36 | #include <linux/tty_flip.h> | 43 | #include <linux/tty_flip.h> |
| 37 | #include <linux/serial_core.h> | 44 | #include <linux/types.h> |
| 38 | #include <linux/serial.h> | 45 | |
| 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 <asm/irq.h> | 46 | #include <asm/irq.h> |
| 45 | 47 | ||
| 46 | /* UART name and device definitions */ | 48 | /* UART name and device definitions */ |
| @@ -73,21 +75,21 @@ struct s3c24xx_uart_info { · 26 unmodified lines | |||
| 73 | enum s3c24xx_port_type type; | 75 | enum s3c24xx_port_type type; |
| 74 | unsigned int port_type; | 76 | unsigned int port_type; |
| 75 | unsigned int fifosize; | 77 | unsigned int fifosize; |
| 76 | unsigned long rx_fifomask; | 78 | u32 rx_fifomask; |
| 77 | unsigned long rx_fifoshift; | 79 | u32 rx_fifoshift; |
| 78 | unsigned long rx_fifofull; | 80 | u32 rx_fifofull; |
| 79 | unsigned long tx_fifomask; | 81 | u32 tx_fifomask; |
| 80 | unsigned long tx_fifoshift; | 82 | u32 tx_fifoshift; |
| 81 | unsigned long tx_fifofull; | 83 | u32 tx_fifofull; |
| 82 | unsigned int def_clk_sel; | 84 | u32 clksel_mask; |
| 83 | unsigned long num_clks; | 85 | u32 clksel_shift; |
| 84 | unsigned long clksel_mask; | 86 | u32 ucon_mask; |
| 85 | unsigned long clksel_shift; | 87 | u8 def_clk_sel; |
| 86 | unsigned long ucon_mask; | 88 | u8 num_clks; |
| 89 | u8 iotype; | ||
| 87 | 90 | ||
| 88 | /* uart port features */ | 91 | /* uart port features */ |
| 89 | 92 | bool has_divslot; | |
| 90 | unsigned int has_divslot:1; | ||
| 91 | }; | 93 | }; |
| 92 | 94 | ||
| 93 | struct s3c24xx_serial_drv_data { | 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 | /* Byte-order aware bit setting/clearing functions. */ | 198 | /* Byte-order aware bit setting/clearing functions. */ |
| 197 | 199 | ||
| 198 | static inline void s3c24xx_set_bit(const struct uart_port *port, int idx, | 200 | static inline void s3c24xx_set_bit(const struct uart_port *port, int idx, |
| 199 | unsigned int reg) | 201 | u32 reg) |
| 200 | { | 202 | { |
| 201 | unsigned long flags; | 203 | unsigned long flags; |
| 202 | u32 val; | 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 | static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx, | 213 | static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx, |
| 212 | unsigned int reg) | 214 | u32 reg) |
| 213 | { | 215 | { |
| 214 | unsigned long flags; | 216 | unsigned long flags; |
| 215 | u32 val; | 217 | u32 val; |
| @@ -233,7 +235,7 @@ static inline const char *s3c24xx_serial_portname(const struct uart_port *port) · 17 unmodified lines | |||
| 233 | return to_platform_device(port->dev)->name; | 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 | return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE; | 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 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 245 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 244 | unsigned long flags; | 246 | unsigned long flags; |
| 245 | unsigned int ucon, ufcon; | ||
| 246 | int count = 10000; | 247 | int count = 10000; |
| 248 | u32 ucon, ufcon; | ||
| 247 | 249 | ||
| 248 | uart_port_lock_irqsave(port, &flags); | 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 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 269 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 268 | unsigned long flags; | 270 | unsigned long flags; |
| 269 | unsigned int ucon; | 271 | u32 ucon; |
| 270 | 272 | ||
| 271 | uart_port_lock_irqsave(port, &flags); | 273 | uart_port_lock_irqsave(port, &flags); |
| 272 | 274 | ||
| @@ -587,8 +589,8 @@ static inline const struct s3c2410_uartcfg · 314 unmodified lines | |||
| 587 | return ourport->cfg; | 589 | return ourport->cfg; |
| 588 | } | 590 | } |
| 589 | 591 | ||
| 590 | static int s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport, | 592 | static unsigned int |
| 591 | unsigned long ufstat) | 593 | s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport, u32 ufstat) |
| 592 | { | 594 | { |
| 593 | const struct s3c24xx_uart_info *info = ourport->info; | 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 | static void enable_rx_dma(struct s3c24xx_uart_port *ourport) | 662 | static void enable_rx_dma(struct s3c24xx_uart_port *ourport) |
| 661 | { | 663 | { |
| 662 | struct uart_port *port = &ourport->port; | 664 | struct uart_port *port = &ourport->port; |
| 663 | unsigned int ucon; | 665 | u32 ucon; |
| 664 | 666 | ||
| 665 | /* set Rx mode to DMA mode */ | 667 | /* set Rx mode to DMA mode */ |
| 666 | ucon = rd_regl(port, S3C2410_UCON); | 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 | static void enable_rx_pio(struct s3c24xx_uart_port *ourport) | 685 | static void enable_rx_pio(struct s3c24xx_uart_port *ourport) |
| 684 | { | 686 | { |
| 685 | struct uart_port *port = &ourport->port; | 687 | struct uart_port *port = &ourport->port; |
| 686 | unsigned int ucon; | 688 | u32 ucon; |
| 687 | 689 | ||
| 688 | /* set Rx mode to DMA mode */ | 690 | /* set Rx mode to DMA mode */ |
| 689 | ucon = rd_regl(port, S3C2410_UCON); | 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 | static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) | 711 | static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) |
| 710 | { | 712 | { |
| 711 | unsigned int utrstat, received; | ||
| 712 | struct s3c24xx_uart_port *ourport = dev_id; | 713 | struct s3c24xx_uart_port *ourport = dev_id; |
| 713 | struct uart_port *port = &ourport->port; | 714 | struct uart_port *port = &ourport->port; |
| 714 | struct s3c24xx_uart_dma *dma = ourport->dma; | 715 | struct s3c24xx_uart_dma *dma = ourport->dma; |
| 715 | struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port); | 716 | struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port); |
| 716 | struct tty_port *t = &port->state->port; | 717 | struct tty_port *t = &port->state->port; |
| 717 | struct dma_tx_state state; | 718 | struct dma_tx_state state; |
| 719 | unsigned int received; | ||
| 720 | u32 utrstat; | ||
| 718 | 721 | ||
| 719 | utrstat = rd_regl(port, S3C2410_UTRSTAT); | 722 | utrstat = rd_regl(port, S3C2410_UTRSTAT); |
| 720 | rd_regl(port, S3C2410_UFSTAT); | 723 | rd_regl(port, S3C2410_UFSTAT); |
| @@ -756,9 +759,9 @@ finish: · 35 unmodified lines | |||
| 756 | static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) | 759 | static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) |
| 757 | { | 760 | { |
| 758 | struct uart_port *port = &ourport->port; | 761 | struct uart_port *port = &ourport->port; |
| 759 | unsigned int ufcon, ufstat, uerstat; | 762 | unsigned int max_count = port->fifosize; |
| 760 | unsigned int fifocnt = 0; | 763 | unsigned int fifocnt = 0; |
| 761 | int max_count = port->fifosize; | 764 | u32 ufcon, ufstat, uerstat; |
| 762 | u8 ch, flag; | 765 | u8 ch, flag; |
| 763 | 766 | ||
| 764 | while (max_count-- > 0) { | 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 | ch = rd_reg(port, S3C2410_URXH); | 781 | ch = rd_reg(port, S3C2410_URXH); |
| 779 | 782 | ||
| 780 | if (port->flags & UPF_CONS_FLOW) { | 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 | if (ourport->rx_enabled) { | 786 | if (ourport->rx_enabled) { |
| 784 | if (!txe) { | 787 | if (!txe) { |
| @@ -942,7 +945,7 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) · 157 unmodified lines | |||
| 942 | { | 945 | { |
| 943 | const struct s3c24xx_uart_port *ourport = id; | 946 | const struct s3c24xx_uart_port *ourport = id; |
| 944 | const struct uart_port *port = &ourport->port; | 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 | irqreturn_t ret = IRQ_HANDLED; | 949 | irqreturn_t ret = IRQ_HANDLED; |
| 947 | 950 | ||
| 948 | if (pend & S3C64XX_UINTM_RXD_MSK) { | 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 | const struct s3c24xx_uart_port *ourport = id; | 965 | const struct s3c24xx_uart_port *ourport = id; |
| 963 | const struct uart_port *port = &ourport->port; | 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 | irqreturn_t ret = IRQ_NONE; | 968 | irqreturn_t ret = IRQ_NONE; |
| 966 | 969 | ||
| 967 | if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) { | 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 | static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) | 983 | static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) |
| 981 | { | 984 | { |
| 982 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | 985 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 983 | unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT); | 986 | u32 ufstat = rd_regl(port, S3C2410_UFSTAT); |
| 984 | unsigned long ufcon = rd_regl(port, S3C2410_UFCON); | 987 | u32 ufcon = rd_regl(port, S3C2410_UFCON); |
| 985 | 988 | ||
| 986 | if (ufcon & S3C2410_UFCON_FIFOMODE) { | 989 | if (ufcon & S3C2410_UFCON_FIFOMODE) { |
| 987 | if ((ufstat & info->tx_fifomask) != 0 || | 990 | if ((ufstat & info->tx_fifomask) || |
| 988 | (ufstat & info->tx_fifofull)) | 991 | (ufstat & info->tx_fifofull)) |
| 989 | return 0; | 992 | return 0; |
| 990 | 993 | return TIOCSER_TEMT; | |
| 991 | return 1; | ||
| 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 | /* no modem control lines */ | 999 | /* no modem control lines */ |
| 998 | static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) | 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 | if (umstat & S3C2410_UMSTAT_CTS) | 1004 | if (umstat & S3C2410_UMSTAT_CTS) |
| 1003 | return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; | 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 | static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) | 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); | 1012 | u32 umcon = rd_regl(port, S3C2410_UMCON); |
| 1011 | unsigned int ucon = rd_regl(port, S3C2410_UCON); | 1013 | u32 ucon = rd_regl(port, S3C2410_UCON); |
| 1012 | 1014 | ||
| 1013 | if (mctrl & TIOCM_RTS) | 1015 | if (mctrl & TIOCM_RTS) |
| 1014 | umcon |= S3C2410_UMCOM_RTS_LOW; | 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 | static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) | 1030 | static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) |
| 1029 | { | 1031 | { |
| 1030 | unsigned long flags; | 1032 | unsigned long flags; |
| 1031 | unsigned int ucon; | 1033 | u32 ucon; |
| 1032 | 1034 | ||
| 1033 | uart_port_lock_irqsave(port, &flags); | 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 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 1189 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 1188 | 1190 | ||
| 1189 | unsigned int ucon; | 1191 | u32 ucon; |
| 1190 | 1192 | ||
| 1191 | ucon = rd_regl(port, S3C2410_UCON); | 1193 | ucon = rd_regl(port, S3C2410_UCON); |
| 1192 | ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK | | 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 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 1215 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 1214 | unsigned long flags; | 1216 | unsigned long flags; |
| 1215 | unsigned int ufcon; | 1217 | u32 ufcon; |
| 1216 | int ret; | 1218 | int ret; |
| 1217 | 1219 | ||
| 1218 | wr_regl(port, S3C64XX_UINTM, 0xf); | 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 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 1260 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 1259 | unsigned long flags; | 1261 | unsigned long flags; |
| 1260 | unsigned int ufcon; | 1262 | u32 ufcon; |
| 1261 | int ret; | 1263 | int ret; |
| 1262 | 1264 | ||
| 1263 | wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS); | 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 | return ret; | 1294 | return ret; |
| 1293 | } | 1295 | } |
| 1294 | 1296 | ||
| 1295 | /* power power management control */ | ||
| 1296 | |||
| 1297 | static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, | 1297 | static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, |
| 1298 | unsigned int old) | 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 | #define MAX_CLK_NAME_LENGTH 15 | 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 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | 1344 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 1345 | unsigned int ucon; | 1345 | u32 ucon; |
| 1346 | 1346 | ||
| 1347 | if (info->num_clks == 1) | 1347 | if (info->num_clks == 1) |
| 1348 | return 0; | 1348 | return 0; |
| @@ -1352,11 +1352,10 @@ static inline int s3c24xx_serial_getsource(struct uart_port *port) · 3 unmodified lines | |||
| 1352 | return ucon >> info->clksel_shift; | 1352 | return ucon >> info->clksel_shift; |
| 1353 | } | 1353 | } |
| 1354 | 1354 | ||
| 1355 | static void s3c24xx_serial_setsource(struct uart_port *port, | 1355 | static void s3c24xx_serial_setsource(struct uart_port *port, u8 clk_sel) |
| 1356 | unsigned int clk_sel) | ||
| 1357 | { | 1356 | { |
| 1358 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | 1357 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 1359 | unsigned int ucon; | 1358 | u32 ucon; |
| 1360 | 1359 | ||
| 1361 | if (info->num_clks == 1) | 1360 | if (info->num_clks == 1) |
| 1362 | return; | 1361 | return; |
| @@ -1372,14 +1371,15 @@ static void s3c24xx_serial_setsource(struct uart_port *port, · 9 unmodified lines | |||
| 1372 | 1371 | ||
| 1373 | static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, | 1372 | static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, |
| 1374 | unsigned int req_baud, struct clk **best_clk, | 1373 | unsigned int req_baud, struct clk **best_clk, |
| 1375 | unsigned int *clk_num) | 1374 | u8 *clk_num) |
| 1376 | { | 1375 | { |
| 1377 | const struct s3c24xx_uart_info *info = ourport->info; | 1376 | const struct s3c24xx_uart_info *info = ourport->info; |
| 1378 | struct clk *clk; | 1377 | struct clk *clk; |
| 1379 | unsigned long rate; | 1378 | unsigned long rate; |
| 1380 | unsigned int cnt, baud, quot, best_quot = 0; | 1379 | unsigned int baud, quot, best_quot = 0; |
| 1381 | char clkname[MAX_CLK_NAME_LENGTH]; | 1380 | char clkname[MAX_CLK_NAME_LENGTH]; |
| 1382 | int calc_deviation, deviation = (1 << 30) - 1; | 1381 | int calc_deviation, deviation = (1 << 30) - 1; |
| 1382 | u8 cnt; | ||
| 1383 | 1383 | ||
| 1384 | for (cnt = 0; cnt < info->num_clks; cnt++) { | 1384 | for (cnt = 0; cnt < info->num_clks; cnt++) { |
| 1385 | /* Keep selected clock if provided */ | 1385 | /* Keep selected clock if provided */ |
| @@ -1472,10 +1472,10 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, · 86 unmodified lines | |||
| 1472 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 1472 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 1473 | struct clk *clk = ERR_PTR(-EINVAL); | 1473 | struct clk *clk = ERR_PTR(-EINVAL); |
| 1474 | unsigned long flags; | 1474 | unsigned long flags; |
| 1475 | unsigned int baud, quot, clk_sel = 0; | 1475 | unsigned int baud, quot; |
| 1476 | unsigned int ulcon; | ||
| 1477 | unsigned int umcon; | ||
| 1478 | unsigned int udivslot = 0; | 1476 | unsigned int udivslot = 0; |
| 1477 | u32 ulcon, umcon; | ||
| 1478 | u8 clk_sel = 0; | ||
| 1479 | 1479 | ||
| 1480 | /* | 1480 | /* |
| 1481 | * We don't support modem control lines. | 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 | static struct s3c24xx_uart_port s3c24xx_serial_ports[UART_NR]; | 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 | struct uart_port *port = &s3c24xx_serial_ports[index].port; | 1742 | struct uart_port *port = &s3c24xx_serial_ports[index].port; |
| 1742 | 1743 | ||
| 1743 | spin_lock_init(&port->lock); | 1744 | spin_lock_init(&port->lock); |
| 1744 | 1745 | ||
| 1745 | port->iotype = UPIO_MEM; | ||
| 1746 | port->uartclk = 0; | 1746 | port->uartclk = 0; |
| 1747 | port->fifosize = 16; | 1747 | port->fifosize = 16; |
| 1748 | port->flags = UPF_BOOT_AUTOCONF; | 1748 | port->flags = UPF_BOOT_AUTOCONF; |
| @@ -1758,7 +1758,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port, · 9 unmodified lines | |||
| 1758 | const struct s3c2410_uartcfg *cfg) | 1758 | const struct s3c2410_uartcfg *cfg) |
| 1759 | { | 1759 | { |
| 1760 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | 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 | ucon &= (info->clksel_mask | info->ucon_mask); | 1763 | ucon &= (info->clksel_mask | info->ucon_mask); |
| 1764 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | 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 | struct device *dev = ourport->port.dev; | 1776 | struct device *dev = ourport->port.dev; |
| 1777 | const struct s3c24xx_uart_info *info = ourport->info; | 1777 | const struct s3c24xx_uart_info *info = ourport->info; |
| 1778 | char clk_name[MAX_CLK_NAME_LENGTH]; | 1778 | char clk_name[MAX_CLK_NAME_LENGTH]; |
| 1779 | unsigned int clk_sel; | ||
| 1780 | struct clk *clk; | 1779 | struct clk *clk; |
| 1781 | int clk_num; | ||
| 1782 | int ret; | 1780 | int ret; |
| 1781 | u8 clk_sel, clk_num; | ||
| 1783 | 1782 | ||
| 1784 | clk_sel = ourport->cfg->clk_sel ? : info->def_clk_sel; | 1783 | clk_sel = ourport->cfg->clk_sel ? : info->def_clk_sel; |
| 1785 | for (clk_num = 0; clk_num < info->num_clks; clk_num++) { | 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 | wr_regl(port, S3C64XX_UINTSP, 0xf); | 1903 | wr_regl(port, S3C64XX_UINTSP, 0xf); |
| 1905 | break; | 1904 | break; |
| 1906 | case TYPE_APPLE_S5L: { | 1905 | case TYPE_APPLE_S5L: { |
| 1907 | unsigned int ucon; | 1906 | u32 ucon; |
| 1908 | 1907 | ||
| 1909 | ucon = rd_regl(port, S3C2410_UCON); | 1908 | ucon = rd_regl(port, S3C2410_UCON); |
| 1910 | ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK | | 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 | struct device_node *np = pdev->dev.of_node; | 1951 | struct device_node *np = pdev->dev.of_node; |
| 1953 | struct s3c24xx_uart_port *ourport; | 1952 | struct s3c24xx_uart_port *ourport; |
| 1954 | int index = probe_index; | 1953 | int index = probe_index; |
| 1955 | int ret, prop = 0; | 1954 | int ret, prop = 0, fifosize_prop = 1; |
| 1956 | 1955 | ||
| 1957 | if (np) { | 1956 | if (np) { |
| 1958 | ret = of_alias_get_id(np, "serial"); | 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 | break; | 1988 | break; |
| 1990 | } | 1989 | } |
| 1991 | 1990 | ||
| 1991 | ourport->port.iotype = ourport->info->iotype; | ||
| 1992 | |||
| 1992 | if (np) { | 1993 | if (np) { |
| 1993 | of_property_read_u32(np, | 1994 | fifosize_prop = of_property_read_u32(np, "samsung,uart-fifosize", |
| 1994 | "samsung,uart-fifosize", &ourport->port.fifosize); | 1995 | &ourport->port.fifosize); |
| 1995 | 1996 | ||
| 1996 | if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { | 1997 | if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { |
| 1997 | switch (prop) { | 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 | if (fifosize_prop) { |
| 2013 | ourport->port.fifosize = ourport->drv_data->fifosize[index]; | 2014 | if (ourport->drv_data->fifosize[index]) |
| 2014 | else if (ourport->info->fifosize) | 2015 | ourport->port.fifosize = ourport->drv_data->fifosize[index]; |
| 2015 | ourport->port.fifosize = ourport->info->fifosize; | 2016 | else if (ourport->info->fifosize) |
| 2017 | ourport->port.fifosize = ourport->info->fifosize; | ||
| 2018 | } | ||
| 2019 | |||
| 2016 | ourport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SAMSUNG_CONSOLE); | 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 | struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); | 2063 | struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); |
| 2060 | 2064 | ||
| 2061 | if (port) { | 2065 | if (port) |
| 2062 | uart_remove_one_port(&s3c24xx_uart_drv, port); | 2066 | uart_remove_one_port(&s3c24xx_uart_drv, port); |
| 2063 | } | ||
| 2064 | 2067 | ||
| 2065 | uart_unregister_driver(&s3c24xx_uart_drv); | 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 | /* restore IRQ mask */ | 2109 | /* restore IRQ mask */ |
| 2107 | switch (ourport->info->type) { | 2110 | switch (ourport->info->type) { |
| 2108 | case TYPE_S3C6400: { | 2111 | case TYPE_S3C6400: { |
| 2109 | unsigned int uintm = 0xf; | 2112 | u32 uintm = 0xf; |
| 2110 | 2113 | ||
| 2111 | if (ourport->tx_enabled) | 2114 | if (ourport->tx_enabled) |
| 2112 | uintm &= ~S3C64XX_UINTM_TXD_MSK; | 2115 | uintm &= ~S3C64XX_UINTM_TXD_MSK; |
| @@ -2122,7 +2125,7 @@ static int s3c24xx_serial_resume_noirq(struct device *dev) · 9 unmodified lines | |||
| 2122 | break; | 2125 | break; |
| 2123 | } | 2126 | } |
| 2124 | case TYPE_APPLE_S5L: { | 2127 | case TYPE_APPLE_S5L: { |
| 2125 | unsigned int ucon; | 2128 | u32 ucon; |
| 2126 | int ret; | 2129 | int ret; |
| 2127 | 2130 | ||
| 2128 | ret = clk_prepare_enable(ourport->clk); | 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 | static struct uart_port *cons_uart; | 2187 | static struct uart_port *cons_uart; |
| 2185 | 2188 | ||
| 2186 | static int | 2189 | static bool |
| 2187 | s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) | 2190 | s3c24xx_serial_console_txrdy(struct uart_port *port, u32 ufcon) |
| 2188 | { | 2191 | { |
| 2189 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | 2192 | const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| 2190 | unsigned long ufstat, utrstat; | 2193 | u32 ufstat, utrstat; |
| 2191 | 2194 | ||
| 2192 | if (ufcon & S3C2410_UFCON_FIFOMODE) { | 2195 | if (ufcon & S3C2410_UFCON_FIFOMODE) { |
| 2193 | /* fifo mode - check amount of data in fifo registers... */ | 2196 | /* fifo mode - check amount of data in fifo registers... */ |
| 2194 | 2197 | ||
| 2195 | ufstat = rd_regl(port, S3C2410_UFSTAT); | 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 | /* in non-fifo mode, we go and use the tx buffer empty */ | 2202 | /* in non-fifo mode, we go and use the tx buffer empty */ |
| 2200 | 2203 | ||
| 2201 | utrstat = rd_regl(port, S3C2410_UTRSTAT); | 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 | static bool | 2208 | static bool |
| 2206 | s3c24xx_port_configured(unsigned int ucon) | 2209 | s3c24xx_port_configured(u32 ucon) |
| 2207 | { | 2210 | { |
| 2208 | /* consider the serial port configured if the tx/rx mode set */ | 2211 | /* consider the serial port configured if the tx/rx mode set */ |
| 2209 | return (ucon & 0xf) != 0; | 2212 | return (ucon & 0xf) != 0; |
| @@ -2218,7 +2221,7 @@ s3c24xx_port_configured(unsigned int ucon) · 8 unmodified lines | |||
| 2218 | static int s3c24xx_serial_get_poll_char(struct uart_port *port) | 2221 | static int s3c24xx_serial_get_poll_char(struct uart_port *port) |
| 2219 | { | 2222 | { |
| 2220 | const struct s3c24xx_uart_port *ourport = to_ourport(port); | 2223 | const struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 2221 | unsigned int ufstat; | 2224 | u32 ufstat; |
| 2222 | 2225 | ||
| 2223 | ufstat = rd_regl(port, S3C2410_UFSTAT); | 2226 | ufstat = rd_regl(port, S3C2410_UFSTAT); |
| 2224 | if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) | 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 | static void s3c24xx_serial_put_poll_char(struct uart_port *port, | 2233 | static void s3c24xx_serial_put_poll_char(struct uart_port *port, |
| 2231 | unsigned char c) | 2234 | unsigned char c) |
| 2232 | { | 2235 | { |
| 2233 | unsigned int ufcon = rd_regl(port, S3C2410_UFCON); | 2236 | u32 ufcon = rd_regl(port, S3C2410_UFCON); |
| 2234 | unsigned int ucon = rd_regl(port, S3C2410_UCON); | 2237 | u32 ucon = rd_regl(port, S3C2410_UCON); |
| 2235 | 2238 | ||
| 2236 | /* not possible to xmit on unconfigured port */ | 2239 | /* not possible to xmit on unconfigured port */ |
| 2237 | if (!s3c24xx_port_configured(ucon)) | 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 | static void | 2250 | static void |
| 2248 | s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch) | 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 | while (!s3c24xx_serial_console_txrdy(port, ufcon)) | 2255 | while (!s3c24xx_serial_console_txrdy(port, ufcon)) |
| 2253 | cpu_relax(); | 2256 | cpu_relax(); |
| @@ -2258,7 +2261,7 @@ static void · 4 unmodified lines | |||
| 2258 | s3c24xx_serial_console_write(struct console *co, const char *s, | 2261 | s3c24xx_serial_console_write(struct console *co, const char *s, |
| 2259 | unsigned int count) | 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 | unsigned long flags; | 2265 | unsigned long flags; |
| 2263 | bool locked = true; | 2266 | bool locked = true; |
| 2264 | 2267 | ||
| @@ -2285,12 +2288,10 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, · 20 unmodified lines | |||
| 2285 | int *parity, int *bits) | 2288 | int *parity, int *bits) |
| 2286 | { | 2289 | { |
| 2287 | struct clk *clk; | 2290 | struct clk *clk; |
| 2288 | unsigned int ulcon; | ||
| 2289 | unsigned int ucon; | ||
| 2290 | unsigned int ubrdiv; | ||
| 2291 | unsigned long rate; | 2291 | unsigned long rate; |
| 2292 | unsigned int clk_sel; | 2292 | u32 ulcon, ucon, ubrdiv; |
| 2293 | char clk_name[MAX_CLK_NAME_LENGTH]; | 2293 | char clk_name[MAX_CLK_NAME_LENGTH]; |
| 2294 | u8 clk_sel; | ||
| 2294 | 2295 | ||
| 2295 | ulcon = rd_regl(port, S3C2410_ULCON); | 2296 | ulcon = rd_regl(port, S3C2410_ULCON); |
| 2296 | ucon = rd_regl(port, S3C2410_UCON); | 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 | .name = "Samsung S3C6400 UART", | 2400 | .name = "Samsung S3C6400 UART", |
| 2400 | .type = TYPE_S3C6400, | 2401 | .type = TYPE_S3C6400, |
| 2401 | .port_type = PORT_S3C6400, | 2402 | .port_type = PORT_S3C6400, |
| 2403 | .iotype = UPIO_MEM, | ||
| 2402 | .fifosize = 64, | 2404 | .fifosize = 64, |
| 2403 | .has_divslot = 1, | 2405 | .has_divslot = true, |
| 2404 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, | 2406 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, |
| 2405 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, | 2407 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, |
| 2406 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, | 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 | .name = "Samsung S5PV210 UART", | 2430 | .name = "Samsung S5PV210 UART", |
| 2429 | .type = TYPE_S3C6400, | 2431 | .type = TYPE_S3C6400, |
| 2430 | .port_type = PORT_S3C6400, | 2432 | .port_type = PORT_S3C6400, |
| 2431 | .has_divslot = 1, | 2433 | .iotype = UPIO_MEM, |
| 2434 | .has_divslot = true, | ||
| 2432 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, | 2435 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, |
| 2433 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, | 2436 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, |
| 2434 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, | 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 | #endif | 2455 | #endif |
| 2453 | 2456 | ||
| 2454 | #if defined(CONFIG_ARCH_EXYNOS) | 2457 | #if defined(CONFIG_ARCH_EXYNOS) |
| 2455 | #define EXYNOS_COMMON_SERIAL_DRV_DATA() \ | 2458 | #define EXYNOS_COMMON_SERIAL_DRV_DATA \ |
| 2456 | .info = { \ | 2459 | .info = { \ |
| 2457 | .name = "Samsung Exynos UART", \ | 2460 | .name = "Samsung Exynos UART", \ |
| 2458 | .type = TYPE_S3C6400, \ | 2461 | .type = TYPE_S3C6400, \ |
| 2459 | .port_type = PORT_S3C6400, \ | 2462 | .port_type = PORT_S3C6400, \ |
| 2460 | .has_divslot = 1, \ | 2463 | .iotype = UPIO_MEM, \ |
| 2464 | .has_divslot = true, \ | ||
| 2461 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ | 2465 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ |
| 2462 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \ | 2466 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \ |
| 2463 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, \ | 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 | static const struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = { | 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 | .fifosize = { 256, 64, 16, 16 }, | 2484 | .fifosize = { 256, 64, 16, 16 }, |
| 2481 | }; | 2485 | }; |
| 2482 | 2486 | ||
| 2483 | static const struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = { | 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 | .fifosize = { 64, 256, 16, 256 }, | 2489 | .fifosize = { 64, 256, 16, 256 }, |
| 2486 | }; | 2490 | }; |
| 2487 | 2491 | ||
| 2488 | static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = { | 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 | .fifosize = { 256, 64, 64, 64 }, | 2494 | .fifosize = { 256, 64, 64, 64 }, |
| 2491 | }; | 2495 | }; |
| 2492 | 2496 | ||
| 2493 | /* | 2497 | static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = { |
| 2494 | * Common drv_data struct for platforms that specify samsung,uart-fifosize in | 2498 | .info = { |
| 2495 | * device tree. | 2499 | .name = "Google GS101 UART", |
| 2496 | */ | 2500 | .type = TYPE_S3C6400, |
| 2497 | static const struct s3c24xx_serial_drv_data exynos_fifoszdt_serial_drv_data = { | 2501 | .port_type = PORT_S3C6400, |
| 2498 | EXYNOS_COMMON_SERIAL_DRV_DATA(), | 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 | .fifosize = { 0 }, | 2521 | .fifosize = { 0 }, |
| 2500 | }; | 2522 | }; |
| 2501 | 2523 | ||
| 2502 | #define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data) | 2524 | #define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data) |
| 2503 | #define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data) | 2525 | #define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data) |
| 2504 | #define EXYNOS850_SERIAL_DRV_DATA (&exynos850_serial_drv_data) | 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 | #else | 2529 | #else |
| 2508 | #define EXYNOS4210_SERIAL_DRV_DATA NULL | 2530 | #define EXYNOS4210_SERIAL_DRV_DATA NULL |
| 2509 | #define EXYNOS5433_SERIAL_DRV_DATA NULL | 2531 | #define EXYNOS5433_SERIAL_DRV_DATA NULL |
| 2510 | #define EXYNOS850_SERIAL_DRV_DATA NULL | 2532 | #define EXYNOS850_SERIAL_DRV_DATA NULL |
| 2511 | #define EXYNOS_FIFOSZDT_DRV_DATA NULL | 2533 | #define GS101_SERIAL_DRV_DATA NULL |
| 2512 | #endif | 2534 | #endif |
| 2513 | 2535 | ||
| 2514 | #ifdef CONFIG_ARCH_APPLE | 2536 | #ifdef CONFIG_ARCH_APPLE |
| @@ -2517,6 +2539,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = { · 2 unmodified lines | |||
| 2517 | .name = "Apple S5L UART", | 2539 | .name = "Apple S5L UART", |
| 2518 | .type = TYPE_APPLE_S5L, | 2540 | .type = TYPE_APPLE_S5L, |
| 2519 | .port_type = PORT_8250, | 2541 | .port_type = PORT_8250, |
| 2542 | .iotype = UPIO_MEM, | ||
| 2520 | .fifosize = 16, | 2543 | .fifosize = 16, |
| 2521 | .rx_fifomask = S3C2410_UFSTAT_RXMASK, | 2544 | .rx_fifomask = S3C2410_UFSTAT_RXMASK, |
| 2522 | .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, | 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 | .name = "Axis ARTPEC-8 UART", | 2569 | .name = "Axis ARTPEC-8 UART", |
| 2547 | .type = TYPE_S3C6400, | 2570 | .type = TYPE_S3C6400, |
| 2548 | .port_type = PORT_S3C6400, | 2571 | .port_type = PORT_S3C6400, |
| 2572 | .iotype = UPIO_MEM, | ||
| 2549 | .fifosize = 64, | 2573 | .fifosize = 64, |
| 2550 | .has_divslot = 1, | 2574 | .has_divslot = true, |
| 2551 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, | 2575 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, |
| 2552 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, | 2576 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, |
| 2553 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, | 2577 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, |
| @@ -2594,7 +2618,7 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = { · 40 unmodified lines | |||
| 2594 | .driver_data = (kernel_ulong_t)ARTPEC8_SERIAL_DRV_DATA, | 2618 | .driver_data = (kernel_ulong_t)ARTPEC8_SERIAL_DRV_DATA, |
| 2595 | }, { | 2619 | }, { |
| 2596 | .name = "gs101-uart", | 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 | { .compatible = "axis,artpec8-uart", | 2641 | { .compatible = "axis,artpec8-uart", |
| 2618 | .data = ARTPEC8_SERIAL_DRV_DATA }, | 2642 | .data = ARTPEC8_SERIAL_DRV_DATA }, |
| 2619 | { .compatible = "google,gs101-uart", | 2643 | { .compatible = "google,gs101-uart", |
| 2620 | .data = EXYNOS_FIFOSZDT_DRV_DATA }, | 2644 | .data = GS101_SERIAL_DRV_DATA }, |
| 2621 | {}, | 2645 | {}, |
| 2622 | }; | 2646 | }; |
| 2623 | MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match); | 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 | struct earlycon_device *dev = con->data; | 2741 | struct earlycon_device *dev = con->data; |
| 2718 | const struct samsung_early_console_data *data = dev->port.private_data; | 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 | while (num_read < n) { | 2746 | while (num_read < n) { |
| 2722 | ufstat = rd_regl(&dev->port, S3C2410_UFSTAT); | 2747 | ufstat = rd_regl(&dev->port, S3C2410_UFSTAT); |
| @@ -2785,6 +2810,17 @@ OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", · 62 unmodified lines | |||
| 2785 | OF_EARLYCON_DECLARE(artpec8, "axis,artpec8-uart", | 2810 | OF_EARLYCON_DECLARE(artpec8, "axis,artpec8-uart", |
| 2786 | s5pv210_early_console_setup); | 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 | /* Apple S5L */ | 2824 | /* Apple S5L */ |
| 2789 | static int __init apple_s5l_early_console_setup(struct earlycon_device *device, | 2825 | static int __init apple_s5l_early_console_setup(struct earlycon_device *device, |
| 2790 | const char *opt) | 2826 | const char *opt) |
| @@ -41,7 +41,7 @@ static int serial_base_match(struct device *dev, struct device_driver *drv) · 40 unmodified lines | |||
| 41 | return 0; | 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 | .name = "serial-base", | 45 | .name = "serial-base", |
| 46 | .match = serial_base_match, | 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 | port->type = PORT_UNKNOWN; | 2608 | port->type = PORT_UNKNOWN; |
| 2609 | flags |= UART_CONFIG_TYPE; | 2609 | flags |= UART_CONFIG_TYPE; |
| 2610 | } | 2610 | } |
| 2611 | /* Synchronize with possible boot console. */ | ||
| 2612 | if (uart_console(port)) | ||
| 2613 | console_lock(); | ||
| 2611 | port->ops->config_port(port, flags); | 2614 | port->ops->config_port(port, flags); |
| 2615 | if (uart_console(port)) | ||
| 2616 | console_unlock(); | ||
| 2612 | } | 2617 | } |
| 2613 | 2618 | ||
| 2614 | if (port->type != PORT_UNKNOWN) { | 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 | uart_report_port(drv, port); | 2622 | uart_report_port(drv, port); |
| 2618 | 2623 | ||
| 2624 | /* Synchronize with possible boot console. */ | ||
| 2625 | if (uart_console(port)) | ||
| 2626 | console_lock(); | ||
| 2627 | |||
| 2619 | /* Power up port for set_mctrl() */ | 2628 | /* Power up port for set_mctrl() */ |
| 2620 | uart_change_pm(state, UART_PM_STATE_ON); | 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 | uart_rs485_config(port); | 2642 | uart_rs485_config(port); |
| 2634 | 2643 | ||
| 2644 | if (uart_console(port)) | ||
| 2645 | console_unlock(); | ||
| 2646 | |||
| 2635 | /* | 2647 | /* |
| 2636 | * If this driver supports console, and it hasn't been | 2648 | * If this driver supports console, and it hasn't been |
| 2637 | * successfully registered yet, try to re-register it. | 2649 | * successfully registered yet, try to re-register it. |
| @@ -8,7 +8,10 @@ · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | #include <linux/device.h> | 9 | #include <linux/device.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/of.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/pm_runtime.h> | 13 | #include <linux/pm_runtime.h> |
| 14 | #include <linux/property.h> | ||
| 12 | #include <linux/serial_core.h> | 15 | #include <linux/serial_core.h> |
| 13 | #include <linux/spinlock.h> | 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 | EXPORT_SYMBOL(uart_remove_one_port); | 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 | static struct device_driver serial_port_driver = { | 253 | static struct device_driver serial_port_driver = { |
| 109 | .name = "port", | 254 | .name = "port", |
| 110 | .suppress_bind_attrs = true, | 255 | .suppress_bind_attrs = true, |
| @@ -23,9 +23,10 @@ · 22 unmodified lines | |||
| 23 | #include <linux/serial.h> | 23 | #include <linux/serial.h> |
| 24 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
| 25 | #include <linux/tty_flip.h> | 25 | #include <linux/tty_flip.h> |
| 26 | |||
| 27 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 28 | 27 | ||
| 28 | #include <asm/txx9/generic.h> | ||
| 29 | |||
| 29 | #define PASS_LIMIT 256 | 30 | #define PASS_LIMIT 256 |
| 30 | 31 | ||
| 31 | #if !defined(CONFIG_SERIAL_TXX9_STDSERIAL) | 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 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 577 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 578 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 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 | if (s->chan_tx) | 580 | if (s->chan_tx) |
| 581 | new = scr | SCSCR_TDRQE; | 581 | new = scr | SCSCR_TDRQE; |
| 582 | else | 582 | else |
| 583 | new = scr & ~SCSCR_TDRQE; | 583 | new = scr & ~SCSCR_TDRQE; |
| 584 | if (new != scr) | 584 | if (new != scr) |
| 585 | serial_port_out(port, SCSCR, new); | 585 | sci_serial_out(port, SCSCR, new); |
| 586 | } | 586 | } |
| 587 | 587 | ||
| 588 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && | 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 | if (!s->chan_tx || s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE || | 599 | if (!s->chan_tx || s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE || |
| 600 | port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 600 | port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 601 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 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 | * For SCI, TE (transmit enable) must be set after setting TIE | 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 | if (port->type == PORT_SCI) | 609 | if (port->type == PORT_SCI) |
| 610 | ctrl |= SCSCR_TE; | 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 | unsigned short ctrl; | 618 | unsigned short ctrl; |
| 619 | 619 | ||
| 620 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ | 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 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 623 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
| 624 | ctrl &= ~SCSCR_TDRQE; | 624 | ctrl &= ~SCSCR_TDRQE; |
| 625 | 625 | ||
| 626 | ctrl &= ~SCSCR_TIE; | 626 | ctrl &= ~SCSCR_TIE; |
| 627 | 627 | ||
| 628 | serial_port_out(port, SCSCR, ctrl); | 628 | sci_serial_out(port, SCSCR, ctrl); |
| 629 | 629 | ||
| 630 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 630 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 631 | if (to_sci_port(port)->chan_tx && | 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 | unsigned short ctrl; | 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 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 645 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
| 646 | ctrl &= ~SCSCR_RDRQE; | 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 | static void sci_stop_rx(struct uart_port *port) | 651 | static void sci_stop_rx(struct uart_port *port) |
| 652 | { | 652 | { |
| 653 | unsigned short ctrl; | 653 | unsigned short ctrl; |
| 654 | 654 | ||
| 655 | ctrl = serial_port_in(port, SCSCR); | 655 | ctrl = sci_serial_in(port, SCSCR); |
| 656 | 656 | ||
| 657 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 657 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
| 658 | ctrl &= ~SCSCR_RDRQE; | 658 | ctrl &= ~SCSCR_RDRQE; |
| 659 | 659 | ||
| 660 | ctrl &= ~port_rx_irq_mask(port); | 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 | static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask) | 665 | static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask) |
| 666 | { | 666 | { |
| 667 | if (port->type == PORT_SCI) { | 667 | if (port->type == PORT_SCI) { |
| 668 | /* Just store the mask */ | 668 | /* Just store the mask */ |
| 669 | serial_port_out(port, SCxSR, mask); | 669 | sci_serial_out(port, SCxSR, mask); |
| 670 | } else if (to_sci_port(port)->params->overrun_mask == SCIFA_ORER) { | 670 | } else if (to_sci_port(port)->params->overrun_mask == SCIFA_ORER) { |
| 671 | /* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */ | 671 | /* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */ |
| 672 | /* Only clear the status bits we want to clear */ | 672 | /* Only clear the status bits we want to clear */ |
| 673 | serial_port_out(port, SCxSR, | 673 | sci_serial_out(port, SCxSR, sci_serial_in(port, SCxSR) & mask); |
| 674 | serial_port_in(port, SCxSR) & mask); | ||
| 675 | } else { | 674 | } else { |
| 676 | /* Store the mask, clear parity/framing errors */ | 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 | int c; | 687 | int c; |
| 689 | 688 | ||
| 690 | do { | 689 | do { |
| 691 | status = serial_port_in(port, SCxSR); | 690 | status = sci_serial_in(port, SCxSR); |
| 692 | if (status & SCxSR_ERRORS(port)) { | 691 | if (status & SCxSR_ERRORS(port)) { |
| 693 | sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port)); | 692 | sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port)); |
| 694 | continue; | 693 | continue; |
| @@ -699,10 +698,10 @@ static int sci_poll_get_char(struct uart_port *port) · 4 unmodified lines | |||
| 699 | if (!(status & SCxSR_RDxF(port))) | 698 | if (!(status & SCxSR_RDxF(port))) |
| 700 | return NO_POLL_CHAR; | 699 | return NO_POLL_CHAR; |
| 701 | 700 | ||
| 702 | c = serial_port_in(port, SCxRDR); | 701 | c = sci_serial_in(port, SCxRDR); |
| 703 | 702 | ||
| 704 | /* Dummy read */ | 703 | /* Dummy read */ |
| 705 | serial_port_in(port, SCxSR); | 704 | sci_serial_in(port, SCxSR); |
| 706 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); | 705 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); |
| 707 | 706 | ||
| 708 | return c; | 707 | return c; |
| @@ -714,10 +713,10 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) · 5 unmodified lines | |||
| 714 | unsigned short status; | 713 | unsigned short status; |
| 715 | 714 | ||
| 716 | do { | 715 | do { |
| 717 | status = serial_port_in(port, SCxSR); | 716 | status = sci_serial_in(port, SCxSR); |
| 718 | } while (!(status & SCxSR_TDxE(port))); | 717 | } while (!(status & SCxSR_TDxE(port))); |
| 719 | 718 | ||
| 720 | serial_port_out(port, SCxTDR, c); | 719 | sci_serial_out(port, SCxTDR, c); |
| 721 | sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); | 720 | sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); |
| 722 | } | 721 | } |
| 723 | #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE || | 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 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 737 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 739 | u16 data = serial_port_in(port, SCPDR); | 738 | u16 data = sci_serial_in(port, SCPDR); |
| 740 | u16 ctrl = serial_port_in(port, SCPCR); | 739 | u16 ctrl = sci_serial_in(port, SCPCR); |
| 741 | 740 | ||
| 742 | /* Enable RXD and TXD pin functions */ | 741 | /* Enable RXD and TXD pin functions */ |
| 743 | ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC); | 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 | /* Enable CTS# pin function */ | 755 | /* Enable CTS# pin function */ |
| 757 | ctrl &= ~SCPCR_CTSC; | 756 | ctrl &= ~SCPCR_CTSC; |
| 758 | } | 757 | } |
| 759 | serial_port_out(port, SCPDR, data); | 758 | sci_serial_out(port, SCPDR, data); |
| 760 | serial_port_out(port, SCPCR, ctrl); | 759 | sci_serial_out(port, SCPCR, ctrl); |
| 761 | } else if (sci_getreg(port, SCSPTR)->size) { | 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 | /* RTS# is always output; and active low, unless autorts */ | 763 | /* RTS# is always output; and active low, unless autorts */ |
| 765 | status |= SCSPTR_RTSIO; | 764 | status |= SCSPTR_RTSIO; |
| @@ -769,7 +768,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) · 3 unmodified lines | |||
| 769 | status &= ~SCSPTR_RTSDT; | 768 | status &= ~SCSPTR_RTSDT; |
| 770 | /* CTS# and SCK are inputs */ | 769 | /* CTS# and SCK are inputs */ |
| 771 | status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO); | 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 | reg = sci_getreg(port, SCTFDR); | 781 | reg = sci_getreg(port, SCTFDR); |
| 783 | if (reg->size) | 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 | reg = sci_getreg(port, SCFDR); | 785 | reg = sci_getreg(port, SCFDR); |
| 787 | if (reg->size) | 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 | static int sci_txroom(struct uart_port *port) | 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 | reg = sci_getreg(port, SCRFDR); | 803 | reg = sci_getreg(port, SCRFDR); |
| 805 | if (reg->size) | 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 | reg = sci_getreg(port, SCFDR); | 807 | reg = sci_getreg(port, SCFDR); |
| 809 | if (reg->size) | 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 | unsigned short ctrl; | 823 | unsigned short ctrl; |
| 825 | int count; | 824 | int count; |
| 826 | 825 | ||
| 827 | status = serial_port_in(port, SCxSR); | 826 | status = sci_serial_in(port, SCxSR); |
| 828 | if (!(status & SCxSR_TDxE(port))) { | 827 | if (!(status & SCxSR_TDxE(port))) { |
| 829 | ctrl = serial_port_in(port, SCSCR); | 828 | ctrl = sci_serial_in(port, SCSCR); |
| 830 | if (uart_circ_empty(xmit)) | 829 | if (uart_circ_empty(xmit)) |
| 831 | ctrl &= ~SCSCR_TIE; | 830 | ctrl &= ~SCSCR_TIE; |
| 832 | else | 831 | else |
| 833 | ctrl |= SCSCR_TIE; | 832 | ctrl |= SCSCR_TIE; |
| 834 | serial_port_out(port, SCSCR, ctrl); | 833 | sci_serial_out(port, SCSCR, ctrl); |
| 835 | return; | 834 | return; |
| 836 | } | 835 | } |
| 837 | 836 | ||
| @@ -847,15 +846,15 @@ static void sci_transmit_chars(struct uart_port *port) · 9 unmodified lines | |||
| 847 | c = xmit->buf[xmit->tail]; | 846 | c = xmit->buf[xmit->tail]; |
| 848 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 847 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| 849 | } else if (port->type == PORT_SCI && uart_circ_empty(xmit)) { | 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 | ctrl &= ~SCSCR_TE; | 850 | ctrl &= ~SCSCR_TE; |
| 852 | serial_port_out(port, SCSCR, ctrl); | 851 | sci_serial_out(port, SCSCR, ctrl); |
| 853 | return; | 852 | return; |
| 854 | } else { | 853 | } else { |
| 855 | break; | 854 | break; |
| 856 | } | 855 | } |
| 857 | 856 | ||
| 858 | serial_port_out(port, SCxTDR, c); | 857 | sci_serial_out(port, SCxTDR, c); |
| 859 | 858 | ||
| 860 | port->icount.tx++; | 859 | port->icount.tx++; |
| 861 | } while (--count > 0); | 860 | } while (--count > 0); |
| @@ -866,10 +865,10 @@ static void sci_transmit_chars(struct uart_port *port) · 4 unmodified lines | |||
| 866 | uart_write_wakeup(port); | 865 | uart_write_wakeup(port); |
| 867 | if (uart_circ_empty(xmit)) { | 866 | if (uart_circ_empty(xmit)) { |
| 868 | if (port->type == PORT_SCI) { | 867 | if (port->type == PORT_SCI) { |
| 869 | ctrl = serial_port_in(port, SCSCR); | 868 | ctrl = sci_serial_in(port, SCSCR); |
| 870 | ctrl &= ~SCSCR_TIE; | 869 | ctrl &= ~SCSCR_TIE; |
| 871 | ctrl |= SCSCR_TEIE; | 870 | ctrl |= SCSCR_TEIE; |
| 872 | serial_port_out(port, SCSCR, ctrl); | 871 | sci_serial_out(port, SCSCR, ctrl); |
| 873 | } | 872 | } |
| 874 | 873 | ||
| 875 | sci_stop_tx(port); | 874 | sci_stop_tx(port); |
| @@ -883,7 +882,7 @@ static void sci_receive_chars(struct uart_port *port) · 7 unmodified lines | |||
| 883 | unsigned short status; | 882 | unsigned short status; |
| 884 | unsigned char flag; | 883 | unsigned char flag; |
| 885 | 884 | ||
| 886 | status = serial_port_in(port, SCxSR); | 885 | status = sci_serial_in(port, SCxSR); |
| 887 | if (!(status & SCxSR_RDxF(port))) | 886 | if (!(status & SCxSR_RDxF(port))) |
| 888 | return; | 887 | return; |
| 889 | 888 | ||
| @@ -896,7 +895,7 @@ static void sci_receive_chars(struct uart_port *port) · 6 unmodified lines | |||
| 896 | break; | 895 | break; |
| 897 | 896 | ||
| 898 | if (port->type == PORT_SCI) { | 897 | if (port->type == PORT_SCI) { |
| 899 | char c = serial_port_in(port, SCxRDR); | 898 | char c = sci_serial_in(port, SCxRDR); |
| 900 | if (uart_handle_sysrq_char(port, c)) | 899 | if (uart_handle_sysrq_char(port, c)) |
| 901 | count = 0; | 900 | count = 0; |
| 902 | else | 901 | else |
| @@ -907,11 +906,11 @@ static void sci_receive_chars(struct uart_port *port) · 4 unmodified lines | |||
| 907 | 906 | ||
| 908 | if (port->type == PORT_SCIF || | 907 | if (port->type == PORT_SCIF || |
| 909 | port->type == PORT_HSCIF) { | 908 | port->type == PORT_HSCIF) { |
| 910 | status = serial_port_in(port, SCxSR); | 909 | status = sci_serial_in(port, SCxSR); |
| 911 | c = serial_port_in(port, SCxRDR); | 910 | c = sci_serial_in(port, SCxRDR); |
| 912 | } else { | 911 | } else { |
| 913 | c = serial_port_in(port, SCxRDR); | 912 | c = sci_serial_in(port, SCxRDR); |
| 914 | status = serial_port_in(port, SCxSR); | 913 | status = sci_serial_in(port, SCxSR); |
| 915 | } | 914 | } |
| 916 | if (uart_handle_sysrq_char(port, c)) { | 915 | if (uart_handle_sysrq_char(port, c)) { |
| 917 | count--; i--; | 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 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); | 935 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); |
| 937 | 936 | ||
| 938 | copied += count; | 937 | copied += count; |
| @@ -944,8 +943,8 @@ static void sci_receive_chars(struct uart_port *port) · 5 unmodified lines | |||
| 944 | tty_flip_buffer_push(tport); | 943 | tty_flip_buffer_push(tport); |
| 945 | } else { | 944 | } else { |
| 946 | /* TTY buffers full; read from RX reg to prevent lockup */ | 945 | /* TTY buffers full; read from RX reg to prevent lockup */ |
| 947 | serial_port_in(port, SCxRDR); | 946 | sci_serial_in(port, SCxRDR); |
| 948 | serial_port_in(port, SCxSR); /* dummy read */ | 947 | sci_serial_in(port, SCxSR); /* dummy read */ |
| 949 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); | 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 | static int sci_handle_errors(struct uart_port *port) | 952 | static int sci_handle_errors(struct uart_port *port) |
| 954 | { | 953 | { |
| 955 | int copied = 0; | 954 | int copied = 0; |
| 956 | unsigned short status = serial_port_in(port, SCxSR); | 955 | unsigned short status = sci_serial_in(port, SCxSR); |
| 957 | struct tty_port *tport = &port->state->port; | 956 | struct tty_port *tport = &port->state->port; |
| 958 | struct sci_port *s = to_sci_port(port); | 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 | if (!reg->size) | 999 | if (!reg->size) |
| 1001 | return 0; | 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 | if (status & s->params->overrun_mask) { | 1003 | if (status & s->params->overrun_mask) { |
| 1005 | status &= ~s->params->overrun_mask; | 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 | port->icount.overrun++; | 1007 | port->icount.overrun++; |
| 1009 | 1008 | ||
| @@ -1018,7 +1017,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port) · 8 unmodified lines | |||
| 1018 | static int sci_handle_breaks(struct uart_port *port) | 1017 | static int sci_handle_breaks(struct uart_port *port) |
| 1019 | { | 1018 | { |
| 1020 | int copied = 0; | 1019 | int copied = 0; |
| 1021 | unsigned short status = serial_port_in(port, SCxSR); | 1020 | unsigned short status = sci_serial_in(port, SCxSR); |
| 1022 | struct tty_port *tport = &port->state->port; | 1021 | struct tty_port *tport = &port->state->port; |
| 1023 | 1022 | ||
| 1024 | if (uart_handle_break(port)) | 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 | /* HSCIF can be set to an arbitrary level. */ | 1051 | /* HSCIF can be set to an arbitrary level. */ |
| 1053 | if (sci_getreg(port, HSRTRGR)->size) { | 1052 | if (sci_getreg(port, HSRTRGR)->size) { |
| 1054 | serial_port_out(port, HSRTRGR, rx_trig); | 1053 | sci_serial_out(port, HSRTRGR, rx_trig); |
| 1055 | return rx_trig; | 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 | return 1; | 1091 | return 1; |
| 1093 | } | 1092 | } |
| 1094 | 1093 | ||
| 1095 | serial_port_out(port, SCFCR, | 1094 | sci_serial_out(port, SCFCR, |
| 1096 | (serial_port_in(port, SCFCR) & | 1095 | (sci_serial_in(port, SCFCR) & |
| 1097 | ~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits); | 1096 | ~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits); |
| 1098 | 1097 | ||
| 1099 | return rx_trig; | 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 | static int scif_rtrg_enabled(struct uart_port *port) | 1101 | static int scif_rtrg_enabled(struct uart_port *port) |
| 1103 | { | 1102 | { |
| 1104 | if (sci_getreg(port, HSRTRGR)->size) | 1103 | if (sci_getreg(port, HSRTRGR)->size) |
| 1105 | return serial_port_in(port, HSRTRGR) != 0; | 1104 | return sci_serial_in(port, HSRTRGR) != 0; |
| 1106 | else | 1105 | else |
| 1107 | return (serial_port_in(port, SCFCR) & | 1106 | return (sci_serial_in(port, SCFCR) & |
| 1108 | (SCFCR_RTRG0 | SCFCR_RTRG1)) != 0; | 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 | s->cookie_tx = -EINVAL; | 1218 | s->cookie_tx = -EINVAL; |
| 1220 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || | 1219 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || |
| 1221 | s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { | 1220 | s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { |
| 1222 | u16 ctrl = serial_port_in(port, SCSCR); | 1221 | u16 ctrl = sci_serial_in(port, SCSCR); |
| 1223 | serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE); | 1222 | sci_serial_out(port, SCSCR, ctrl & ~SCSCR_TIE); |
| 1224 | if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { | 1223 | if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { |
| 1225 | /* Switch irq from DMA to SCIF */ | 1224 | /* Switch irq from DMA to SCIF */ |
| 1226 | dmaengine_pause(s->chan_tx_saved); | 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 | u16 scr; | 1295 | u16 scr; |
| 1297 | 1296 | ||
| 1298 | /* Direct new serial port interrupts back to CPU */ | 1297 | /* Direct new serial port interrupts back to CPU */ |
| 1299 | scr = serial_port_in(port, SCSCR); | 1298 | scr = sci_serial_in(port, SCSCR); |
| 1300 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || | 1299 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || |
| 1301 | s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { | 1300 | s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { |
| 1302 | enable_irq(s->irqs[SCIx_RXI_IRQ]); | 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 | else | 1304 | else |
| 1306 | scr &= ~SCSCR_RDRQE; | 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 | static void sci_dma_rx_complete(void *arg) | 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 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1714 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 1716 | if (s->chan_rx) { | 1715 | if (s->chan_rx) { |
| 1717 | u16 scr = serial_port_in(port, SCSCR); | 1716 | u16 scr = sci_serial_in(port, SCSCR); |
| 1718 | u16 ssr = serial_port_in(port, SCxSR); | 1717 | u16 ssr = sci_serial_in(port, SCxSR); |
| 1719 | 1718 | ||
| 1720 | /* Disable future Rx interrupts */ | 1719 | /* Disable future Rx interrupts */ |
| 1721 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || | 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 | scr &= ~SCSCR_RIE; | 1733 | scr &= ~SCSCR_RIE; |
| 1735 | } | 1734 | } |
| 1736 | serial_port_out(port, SCSCR, scr); | 1735 | sci_serial_out(port, SCSCR, scr); |
| 1737 | /* Clear current interrupt */ | 1736 | /* Clear current interrupt */ |
| 1738 | serial_port_out(port, SCxSR, | 1737 | sci_serial_out(port, SCxSR, |
| 1739 | ssr & ~(SCIF_DR | SCxSR_RDxF(port))); | 1738 | ssr & ~(SCIF_DR | SCxSR_RDxF(port))); |
| 1740 | dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u us\n", | 1739 | dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u us\n", |
| 1741 | jiffies, s->rx_timeout); | 1740 | jiffies, s->rx_timeout); |
| 1742 | start_hrtimer_us(&s->rx_timer, s->rx_timeout); | 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 | return sci_tx_interrupt(irq, ptr); | 1785 | return sci_tx_interrupt(irq, ptr); |
| 1787 | 1786 | ||
| 1788 | uart_port_lock_irqsave(port, &flags); | 1787 | uart_port_lock_irqsave(port, &flags); |
| 1789 | ctrl = serial_port_in(port, SCSCR); | 1788 | ctrl = sci_serial_in(port, SCSCR); |
| 1790 | ctrl &= ~(SCSCR_TE | SCSCR_TEIE); | 1789 | ctrl &= ~(SCSCR_TE | SCSCR_TEIE); |
| 1791 | serial_port_out(port, SCSCR, ctrl); | 1790 | sci_serial_out(port, SCSCR, ctrl); |
| 1792 | uart_port_unlock_irqrestore(port, flags); | 1791 | uart_port_unlock_irqrestore(port, flags); |
| 1793 | 1792 | ||
| 1794 | return IRQ_HANDLED; | 1793 | return IRQ_HANDLED; |
| @@ -1802,7 +1801,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) · 7 unmodified lines | |||
| 1802 | sci_handle_breaks(port); | 1801 | sci_handle_breaks(port); |
| 1803 | 1802 | ||
| 1804 | /* drop invalid character received before break was detected */ | 1803 | /* drop invalid character received before break was detected */ |
| 1805 | serial_port_in(port, SCxRDR); | 1804 | sci_serial_in(port, SCxRDR); |
| 1806 | 1805 | ||
| 1807 | sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port)); | 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 | if (s->irqs[SCIx_ERI_IRQ] == s->irqs[SCIx_BRI_IRQ]) { | 1816 | if (s->irqs[SCIx_ERI_IRQ] == s->irqs[SCIx_BRI_IRQ]) { |
| 1818 | /* Break and Error interrupts are muxed */ | 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 | /* Break Interrupt */ | 1820 | /* Break Interrupt */ |
| 1822 | if (ssr_status & SCxSR_BRK(port)) | 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 | if (port->type == PORT_SCI) { | 1830 | if (port->type == PORT_SCI) { |
| 1832 | if (sci_handle_errors(port)) { | 1831 | if (sci_handle_errors(port)) { |
| 1833 | /* discard character in rx buffer */ | 1832 | /* discard character in rx buffer */ |
| 1834 | serial_port_in(port, SCxSR); | 1833 | sci_serial_in(port, SCxSR); |
| 1835 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); | 1834 | sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port)); |
| 1836 | } | 1835 | } |
| 1837 | } else { | 1836 | } else { |
| @@ -1856,12 +1855,12 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) · 18 unmodified lines | |||
| 1856 | struct sci_port *s = to_sci_port(port); | 1855 | struct sci_port *s = to_sci_port(port); |
| 1857 | irqreturn_t ret = IRQ_NONE; | 1856 | irqreturn_t ret = IRQ_NONE; |
| 1858 | 1857 | ||
| 1859 | ssr_status = serial_port_in(port, SCxSR); | 1858 | ssr_status = sci_serial_in(port, SCxSR); |
| 1860 | scr_status = serial_port_in(port, SCSCR); | 1859 | scr_status = sci_serial_in(port, SCSCR); |
| 1861 | if (s->params->overrun_reg == SCxSR) | 1860 | if (s->params->overrun_reg == SCxSR) |
| 1862 | orer_status = ssr_status; | 1861 | orer_status = ssr_status; |
| 1863 | else if (sci_getreg(port, s->params->overrun_reg)->size) | 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 | err_enabled = scr_status & port_rx_irq_mask(port); | 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 | static unsigned int sci_tx_empty(struct uart_port *port) | 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 | unsigned short in_tx_fifo = sci_txfill(port); | 2041 | unsigned short in_tx_fifo = sci_txfill(port); |
| 2043 | 2042 | ||
| 2044 | return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0; | 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 | static void sci_set_rts(struct uart_port *port, bool state) | 2046 | static void sci_set_rts(struct uart_port *port, bool state) |
| 2048 | { | 2047 | { |
| 2049 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 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 | /* Active low */ | 2051 | /* Active low */ |
| 2053 | if (state) | 2052 | if (state) |
| 2054 | data &= ~SCPDR_RTSD; | 2053 | data &= ~SCPDR_RTSD; |
| 2055 | else | 2054 | else |
| 2056 | data |= SCPDR_RTSD; | 2055 | data |= SCPDR_RTSD; |
| 2057 | serial_port_out(port, SCPDR, data); | 2056 | sci_serial_out(port, SCPDR, data); |
| 2058 | 2057 | ||
| 2059 | /* RTS# is output */ | 2058 | /* RTS# is output */ |
| 2060 | serial_port_out(port, SCPCR, | 2059 | sci_serial_out(port, SCPCR, |
| 2061 | serial_port_in(port, SCPCR) | SCPCR_RTSC); | 2060 | sci_serial_in(port, SCPCR) | SCPCR_RTSC); |
| 2062 | } else if (sci_getreg(port, SCSPTR)->size) { | 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 | /* Active low */ | 2064 | /* Active low */ |
| 2066 | if (state) | 2065 | if (state) |
| 2067 | ctrl &= ~SCSPTR_RTSDT; | 2066 | ctrl &= ~SCSPTR_RTSDT; |
| 2068 | else | 2067 | else |
| 2069 | ctrl |= SCSPTR_RTSDT; | 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 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 2075 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 2077 | /* Active low */ | 2076 | /* Active low */ |
| 2078 | return !(serial_port_in(port, SCPDR) & SCPDR_CTSD); | 2077 | return !(sci_serial_in(port, SCPDR) & SCPDR_CTSD); |
| 2079 | } else if (sci_getreg(port, SCSPTR)->size) { | 2078 | } else if (sci_getreg(port, SCSPTR)->size) { |
| 2080 | /* Active low */ | 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 | return true; | 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 | reg = sci_getreg(port, SCFCR); | 2108 | reg = sci_getreg(port, SCFCR); |
| 2110 | if (reg->size) | 2109 | if (reg->size) |
| 2111 | serial_port_out(port, SCFCR, | 2110 | sci_serial_out(port, SCFCR, |
| 2112 | serial_port_in(port, SCFCR) | | 2111 | sci_serial_in(port, SCFCR) | SCFCR_LOOP); |
| 2113 | SCFCR_LOOP); | ||
| 2114 | } | 2112 | } |
| 2115 | 2113 | ||
| 2116 | mctrl_gpio_set(s->gpios, mctrl); | 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 | if (!(mctrl & TIOCM_RTS)) { | 2119 | if (!(mctrl & TIOCM_RTS)) { |
| 2122 | /* Disable Auto RTS */ | 2120 | /* Disable Auto RTS */ |
| 2123 | serial_port_out(port, SCFCR, | 2121 | sci_serial_out(port, SCFCR, |
| 2124 | serial_port_in(port, SCFCR) & ~SCFCR_MCE); | 2122 | sci_serial_in(port, SCFCR) & ~SCFCR_MCE); |
| 2125 | 2123 | ||
| 2126 | /* Clear RTS */ | 2124 | /* Clear RTS */ |
| 2127 | sci_set_rts(port, 0); | 2125 | sci_set_rts(port, 0); |
| 2128 | } else if (s->autorts) { | 2126 | } else if (s->autorts) { |
| 2129 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 2127 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
| 2130 | /* Enable RTS# pin function */ | 2128 | /* Enable RTS# pin function */ |
| 2131 | serial_port_out(port, SCPCR, | 2129 | sci_serial_out(port, SCPCR, |
| 2132 | serial_port_in(port, SCPCR) & ~SCPCR_RTSC); | 2130 | sci_serial_in(port, SCPCR) & ~SCPCR_RTSC); |
| 2133 | } | 2131 | } |
| 2134 | 2132 | ||
| 2135 | /* Enable Auto RTS */ | 2133 | /* Enable Auto RTS */ |
| 2136 | serial_port_out(port, SCFCR, | 2134 | sci_serial_out(port, SCFCR, |
| 2137 | serial_port_in(port, SCFCR) | SCFCR_MCE); | 2135 | sci_serial_in(port, SCFCR) | SCFCR_MCE); |
| 2138 | } else { | 2136 | } else { |
| 2139 | /* Set RTS */ | 2137 | /* Set RTS */ |
| 2140 | sci_set_rts(port, 1); | 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 | uart_port_lock_irqsave(port, &flags); | 2187 | uart_port_lock_irqsave(port, &flags); |
| 2190 | scsptr = serial_port_in(port, SCSPTR); | 2188 | scsptr = sci_serial_in(port, SCSPTR); |
| 2191 | scscr = serial_port_in(port, SCSCR); | 2189 | scscr = sci_serial_in(port, SCSCR); |
| 2192 | 2190 | ||
| 2193 | if (break_state == -1) { | 2191 | if (break_state == -1) { |
| 2194 | scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT; | 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 | scscr |= SCSCR_TE; | 2196 | scscr |= SCSCR_TE; |
| 2199 | } | 2197 | } |
| 2200 | 2198 | ||
| 2201 | serial_port_out(port, SCSPTR, scsptr); | 2199 | sci_serial_out(port, SCSPTR, scsptr); |
| 2202 | serial_port_out(port, SCSCR, scscr); | 2200 | sci_serial_out(port, SCSCR, scscr); |
| 2203 | uart_port_unlock_irqrestore(port, flags); | 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 | * Stop RX and TX, disable related interrupts, keep clock source | 2237 | * Stop RX and TX, disable related interrupts, keep clock source |
| 2240 | * and HSCIF TOT bits | 2238 | * and HSCIF TOT bits |
| 2241 | */ | 2239 | */ |
| 2242 | scr = serial_port_in(port, SCSCR); | 2240 | scr = sci_serial_in(port, SCSCR); |
| 2243 | serial_port_out(port, SCSCR, scr & | 2241 | sci_serial_out(port, SCSCR, |
| 2244 | (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot)); | 2242 | scr & (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot)); |
| 2245 | uart_port_unlock_irqrestore(port, flags); | 2243 | uart_port_unlock_irqrestore(port, flags); |
| 2246 | 2244 | ||
| 2247 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 2245 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| @@ -2390,19 +2388,19 @@ static void sci_reset(struct uart_port *port) · 142 unmodified lines | |||
| 2390 | unsigned int status; | 2388 | unsigned int status; |
| 2391 | struct sci_port *s = to_sci_port(port); | 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 | reg = sci_getreg(port, SCFCR); | 2393 | reg = sci_getreg(port, SCFCR); |
| 2396 | if (reg->size) | 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 | sci_clear_SCxSR(port, | 2397 | sci_clear_SCxSR(port, |
| 2400 | SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) & | 2398 | SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) & |
| 2401 | SCxSR_BREAK_CLEAR(port)); | 2399 | SCxSR_BREAK_CLEAR(port)); |
| 2402 | if (sci_getreg(port, SCLSR)->size) { | 2400 | if (sci_getreg(port, SCLSR)->size) { |
| 2403 | status = serial_port_in(port, SCLSR); | 2401 | status = sci_serial_in(port, SCLSR); |
| 2404 | status &= ~(SCLSR_TO | SCLSR_ORER); | 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 | if (s->rx_trigger > 1) { | 2406 | if (s->rx_trigger > 1) { |
| @@ -2540,8 +2538,8 @@ done: · 131 unmodified lines | |||
| 2540 | * It controls the mux to select (H)SCK or frequency divided clock. | 2538 | * It controls the mux to select (H)SCK or frequency divided clock. |
| 2541 | */ | 2539 | */ |
| 2542 | if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) { | 2540 | if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) { |
| 2543 | serial_port_out(port, SCDL, dl); | 2541 | sci_serial_out(port, SCDL, dl); |
| 2544 | serial_port_out(port, SCCKS, sccks); | 2542 | sci_serial_out(port, SCCKS, sccks); |
| 2545 | } | 2543 | } |
| 2546 | 2544 | ||
| 2547 | uart_port_lock_irqsave(port, &flags); | 2545 | uart_port_lock_irqsave(port, &flags); |
| @@ -2554,7 +2552,7 @@ done: · 6 unmodified lines | |||
| 2554 | bits = tty_get_frame_size(termios->c_cflag); | 2552 | bits = tty_get_frame_size(termios->c_cflag); |
| 2555 | 2553 | ||
| 2556 | if (sci_getreg(port, SEMR)->size) | 2554 | if (sci_getreg(port, SEMR)->size) |
| 2557 | serial_port_out(port, SEMR, 0); | 2555 | sci_serial_out(port, SEMR, 0); |
| 2558 | 2556 | ||
| 2559 | if (best_clk >= 0) { | 2557 | if (best_clk >= 0) { |
| 2560 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 2558 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
| @@ -2569,9 +2567,9 @@ done: · 8 unmodified lines | |||
| 2569 | case 27: smr_val |= SCSMR_SRC_27; break; | 2567 | case 27: smr_val |= SCSMR_SRC_27; break; |
| 2570 | } | 2568 | } |
| 2571 | smr_val |= cks; | 2569 | smr_val |= cks; |
| 2572 | serial_port_out(port, SCSCR, scr_val | s->hscif_tot); | 2570 | sci_serial_out(port, SCSCR, scr_val | s->hscif_tot); |
| 2573 | serial_port_out(port, SCSMR, smr_val); | 2571 | sci_serial_out(port, SCSMR, smr_val); |
| 2574 | serial_port_out(port, SCBRR, brr); | 2572 | sci_serial_out(port, SCBRR, brr); |
| 2575 | if (sci_getreg(port, HSSRR)->size) { | 2573 | if (sci_getreg(port, HSSRR)->size) { |
| 2576 | unsigned int hssrr = srr | HSCIF_SRE; | 2574 | unsigned int hssrr = srr | HSCIF_SRE; |
| 2577 | /* Calculate deviation from intended rate at the | 2575 | /* Calculate deviation from intended rate at the |
| @@ -2593,7 +2591,7 @@ done: · 15 unmodified lines | |||
| 2593 | HSCIF_SRHP_MASK; | 2591 | HSCIF_SRHP_MASK; |
| 2594 | hssrr |= HSCIF_SRDE; | 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 | /* Wait one bit interval */ | 2597 | /* Wait one bit interval */ |
| @@ -2601,10 +2599,10 @@ done: · 1 unmodified line | |||
| 2601 | } else { | 2599 | } else { |
| 2602 | /* Don't touch the bit rate configuration */ | 2600 | /* Don't touch the bit rate configuration */ |
| 2603 | scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0); | 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 | (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS); | 2603 | (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS); |
| 2606 | serial_port_out(port, SCSCR, scr_val | s->hscif_tot); | 2604 | sci_serial_out(port, SCSCR, scr_val | s->hscif_tot); |
| 2607 | serial_port_out(port, SCSMR, smr_val); | 2605 | sci_serial_out(port, SCSMR, smr_val); |
| 2608 | } | 2606 | } |
| 2609 | 2607 | ||
| 2610 | sci_init_pins(port, termios->c_cflag); | 2608 | sci_init_pins(port, termios->c_cflag); |
| @@ -2613,7 +2611,7 @@ done: · 2 unmodified lines | |||
| 2613 | s->autorts = false; | 2611 | s->autorts = false; |
| 2614 | reg = sci_getreg(port, SCFCR); | 2612 | reg = sci_getreg(port, SCFCR); |
| 2615 | if (reg->size) { | 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 | if ((port->flags & UPF_HARD_FLOW) && | 2616 | if ((port->flags & UPF_HARD_FLOW) && |
| 2619 | (termios->c_cflag & CRTSCTS)) { | 2617 | (termios->c_cflag & CRTSCTS)) { |
| @@ -2630,7 +2628,7 @@ done: · 10 unmodified lines | |||
| 2630 | */ | 2628 | */ |
| 2631 | ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST); | 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 | if (port->flags & UPF_HARD_FLOW) { | 2633 | if (port->flags & UPF_HARD_FLOW) { |
| 2636 | /* Refresh (Auto) RTS */ | 2634 | /* Refresh (Auto) RTS */ |
| @@ -2645,7 +2643,7 @@ done: · 8 unmodified lines | |||
| 2645 | if (port->type != PORT_SCI) | 2643 | if (port->type != PORT_SCI) |
| 2646 | scr_val |= SCSCR_TE; | 2644 | scr_val |= SCSCR_TE; |
| 2647 | scr_val |= SCSCR_RE | (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)); | 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 | if ((srr + 1 == 5) && | 2647 | if ((srr + 1 == 5) && |
| 2650 | (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) { | 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 | port->irq = sci_port->irqs[SCIx_RXI_IRQ]; | 3015 | port->irq = sci_port->irqs[SCIx_RXI_IRQ]; |
| 3018 | port->irqflags = 0; | 3016 | port->irqflags = 0; |
| 3019 | 3017 | ||
| 3020 | port->serial_in = sci_serial_in; | ||
| 3021 | port->serial_out = sci_serial_out; | ||
| 3022 | |||
| 3023 | return 0; | 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 | uart_port_lock_irqsave(port, &flags); | 3051 | uart_port_lock_irqsave(port, &flags); |
| 3057 | 3052 | ||
| 3058 | /* first save SCSCR then disable interrupts, keep clock source */ | 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 | ctrl_temp = SCSCR_RE | SCSCR_TE | | 3055 | ctrl_temp = SCSCR_RE | SCSCR_TE | |
| 3061 | (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | | 3056 | (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | |
| 3062 | (ctrl & (SCSCR_CKE1 | SCSCR_CKE0)); | 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 | uart_console_write(port, s, count, serial_console_putchar); | 3060 | uart_console_write(port, s, count, serial_console_putchar); |
| 3066 | 3061 | ||
| 3067 | /* wait until fifo is empty and last bit has been transmitted */ | 3062 | /* wait until fifo is empty and last bit has been transmitted */ |
| 3068 | bits = SCxSR_TDxE(port) | SCxSR_TEND(port); | 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 | cpu_relax(); | 3065 | cpu_relax(); |
| 3071 | 3066 | ||
| 3072 | /* restore the SCSCR */ | 3067 | /* restore the SCSCR */ |
| 3073 | serial_port_out(port, SCSCR, ctrl); | 3068 | sci_serial_out(port, SCSCR, ctrl); |
| 3074 | 3069 | ||
| 3075 | if (locked) | 3070 | if (locked) |
| 3076 | uart_port_unlock_irqrestore(port, flags); | 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 | if (!device->port.membase) | 3498 | if (!device->port.membase) |
| 3504 | return -ENODEV; | 3499 | return -ENODEV; |
| 3505 | 3500 | ||
| 3506 | device->port.serial_in = sci_serial_in; | ||
| 3507 | device->port.serial_out = sci_serial_out; | ||
| 3508 | device->port.type = type; | 3501 | device->port.type = type; |
| 3509 | memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port)); | 3502 | memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port)); |
| 3510 | port_cfg.type = type; | 3503 | port_cfg.type = type; |
| @@ -412,7 +412,8 @@ static void __ssp_receive_chars(struct sifive_serial_port *ssp) · 411 unmodified lines | |||
| 412 | break; | 412 | break; |
| 413 | 413 | ||
| 414 | ssp->port.icount.rx++; | 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 | tty_flip_buffer_push(&ssp->port.state->port); | 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 | if (ip & SIFIVE_SERIAL_IP_TXWM_MASK) | 535 | if (ip & SIFIVE_SERIAL_IP_TXWM_MASK) |
| 535 | __ssp_transmit_chars(ssp); | 536 | __ssp_transmit_chars(ssp); |
| 536 | 537 | ||
| 537 | uart_port_unlock(&ssp->port); | 538 | uart_unlock_and_check_sysrq(&ssp->port); |
| 538 | 539 | ||
| 539 | return IRQ_HANDLED; | 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 | if (!ssp) | 792 | if (!ssp) |
| 792 | return; | 793 | return; |
| 793 | 794 | ||
| 794 | local_irq_save(flags); | 795 | if (oops_in_progress) |
| 795 | if (ssp->port.sysrq) | 796 | locked = uart_port_trylock_irqsave(&ssp->port, &flags); |
| 796 | locked = 0; | ||
| 797 | else if (oops_in_progress) | ||
| 798 | locked = uart_port_trylock(&ssp->port); | ||
| 799 | else | 797 | else |
| 800 | uart_port_lock(&ssp->port); | 798 | uart_port_lock_irqsave(&ssp->port, &flags); |
| 801 | 799 | ||
| 802 | ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS); | 800 | ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS); |
| 803 | __ssp_writel(0, SIFIVE_SERIAL_IE_OFFS, ssp); | 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 | __ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp); | 805 | __ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp); |
| 808 | 806 | ||
| 809 | if (locked) | 807 | if (locked) |
| 810 | uart_port_unlock(&ssp->port); | 808 | uart_port_unlock_irqrestore(&ssp->port, flags); |
| 811 | local_irq_restore(flags); | ||
| 812 | } | 809 | } |
| 813 | 810 | ||
| 814 | static int sifive_serial_console_setup(struct console *co, char *options) | 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 | const struct ktermios *old) | 465 | const struct ktermios *old) |
| 466 | { | 466 | { |
| 467 | struct asc_port *ascport = to_asc_port(port); | 467 | struct asc_port *ascport = to_asc_port(port); |
| 468 | bool manual_rts, toggle_rts = false; | ||
| 468 | struct gpio_desc *gpiod; | 469 | struct gpio_desc *gpiod; |
| 469 | unsigned int baud; | 470 | unsigned int baud; |
| 470 | u32 ctrl_val; | 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 | /* If flow-control selected, stop handling RTS manually */ | 520 | /* If flow-control selected, stop handling RTS manually */ |
| 520 | if (ascport->rts) { | 521 | if (ascport->rts) { |
| 521 | devm_gpiod_put(port->dev, ascport->rts); | 522 | toggle_rts = true; |
| 522 | ascport->rts = NULL; | 523 | manual_rts = false; |
| 523 | |||
| 524 | pinctrl_select_state(ascport->pinctrl, | ||
| 525 | ascport->states[DEFAULT]); | ||
| 526 | } | 524 | } |
| 527 | } else { | 525 | } else { |
| 528 | /* If flow-control disabled, it's safe to handle RTS manually */ | 526 | /* If flow-control disabled, it's safe to handle RTS manually */ |
| 529 | if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) { | 527 | if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) |
| 530 | pinctrl_select_state(ascport->pinctrl, | 528 | manual_rts = toggle_rts = true; |
| 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 | } | ||
| 540 | } | 529 | } |
| 541 | 530 | ||
| 542 | if ((baud < 19200) && !ascport->force_m1) { | 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 | asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN)); | 584 | asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN)); |
| 596 | 585 | ||
| 597 | uart_port_unlock_irqrestore(port, flags); | 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 | static const char *asc_type(struct uart_port *port) | 608 | static const char *asc_type(struct uart_port *port) |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | * Inspired by st-asc.c from STMicroelectronics (c) | 9 | * Inspired by st-asc.c from STMicroelectronics (c) |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/bitfield.h> | ||
| 12 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
| 13 | #include <linux/console.h> | 14 | #include <linux/console.h> |
| 14 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| @@ -39,60 +40,64 @@ · 24 unmodified lines | |||
| 39 | /* Register offsets */ | 40 | /* Register offsets */ |
| 40 | static struct stm32_usart_info __maybe_unused stm32f4_info = { | 41 | static struct stm32_usart_info __maybe_unused stm32f4_info = { |
| 41 | .ofs = { | 42 | .ofs = { |
| 42 | .isr = 0x00, | 43 | .isr = 0x00, |
| 43 | .rdr = 0x04, | 44 | .rdr = 0x04, |
| 44 | .tdr = 0x04, | 45 | .tdr = 0x04, |
| 45 | .brr = 0x08, | 46 | .brr = 0x08, |
| 46 | .cr1 = 0x0c, | 47 | .cr1 = 0x0c, |
| 47 | .cr2 = 0x10, | 48 | .cr2 = 0x10, |
| 48 | .cr3 = 0x14, | 49 | .cr3 = 0x14, |
| 49 | .gtpr = 0x18, | 50 | .gtpr = 0x18, |
| 50 | .rtor = UNDEF_REG, | 51 | .rtor = UNDEF_REG, |
| 51 | .rqr = UNDEF_REG, | 52 | .rqr = UNDEF_REG, |
| 52 | .icr = UNDEF_REG, | 53 | .icr = UNDEF_REG, |
| 54 | .presc = UNDEF_REG, | ||
| 55 | .hwcfgr1 = UNDEF_REG, | ||
| 53 | }, | 56 | }, |
| 54 | .cfg = { | 57 | .cfg = { |
| 55 | .uart_enable_bit = 13, | 58 | .uart_enable_bit = 13, |
| 56 | .has_7bits_data = false, | 59 | .has_7bits_data = false, |
| 57 | .fifosize = 1, | ||
| 58 | } | 60 | } |
| 59 | }; | 61 | }; |
| 60 | 62 | ||
| 61 | static struct stm32_usart_info __maybe_unused stm32f7_info = { | 63 | static struct stm32_usart_info __maybe_unused stm32f7_info = { |
| 62 | .ofs = { | 64 | .ofs = { |
| 63 | .cr1 = 0x00, | 65 | .cr1 = 0x00, |
| 64 | .cr2 = 0x04, | 66 | .cr2 = 0x04, |
| 65 | .cr3 = 0x08, | 67 | .cr3 = 0x08, |
| 66 | .brr = 0x0c, | 68 | .brr = 0x0c, |
| 67 | .gtpr = 0x10, | 69 | .gtpr = 0x10, |
| 68 | .rtor = 0x14, | 70 | .rtor = 0x14, |
| 69 | .rqr = 0x18, | 71 | .rqr = 0x18, |
| 70 | .isr = 0x1c, | 72 | .isr = 0x1c, |
| 71 | .icr = 0x20, | 73 | .icr = 0x20, |
| 72 | .rdr = 0x24, | 74 | .rdr = 0x24, |
| 73 | .tdr = 0x28, | 75 | .tdr = 0x28, |
| 76 | .presc = UNDEF_REG, | ||
| 77 | .hwcfgr1 = UNDEF_REG, | ||
| 74 | }, | 78 | }, |
| 75 | .cfg = { | 79 | .cfg = { |
| 76 | .uart_enable_bit = 0, | 80 | .uart_enable_bit = 0, |
| 77 | .has_7bits_data = true, | 81 | .has_7bits_data = true, |
| 78 | .has_swap = true, | 82 | .has_swap = true, |
| 79 | .fifosize = 1, | ||
| 80 | } | 83 | } |
| 81 | }; | 84 | }; |
| 82 | 85 | ||
| 83 | static struct stm32_usart_info __maybe_unused stm32h7_info = { | 86 | static struct stm32_usart_info __maybe_unused stm32h7_info = { |
| 84 | .ofs = { | 87 | .ofs = { |
| 85 | .cr1 = 0x00, | 88 | .cr1 = 0x00, |
| 86 | .cr2 = 0x04, | 89 | .cr2 = 0x04, |
| 87 | .cr3 = 0x08, | 90 | .cr3 = 0x08, |
| 88 | .brr = 0x0c, | 91 | .brr = 0x0c, |
| 89 | .gtpr = 0x10, | 92 | .gtpr = 0x10, |
| 90 | .rtor = 0x14, | 93 | .rtor = 0x14, |
| 91 | .rqr = 0x18, | 94 | .rqr = 0x18, |
| 92 | .isr = 0x1c, | 95 | .isr = 0x1c, |
| 93 | .icr = 0x20, | 96 | .icr = 0x20, |
| 94 | .rdr = 0x24, | 97 | .rdr = 0x24, |
| 95 | .tdr = 0x28, | 98 | .tdr = 0x28, |
| 99 | .presc = 0x2c, | ||
| 100 | .hwcfgr1 = 0x3f0, | ||
| 96 | }, | 101 | }, |
| 97 | .cfg = { | 102 | .cfg = { |
| 98 | .uart_enable_bit = 0, | 103 | .uart_enable_bit = 0, |
| @@ -100,7 +105,6 @@ static struct stm32_usart_info __maybe_unused stm32h7_info = { · 1 unmodified line | |||
| 100 | .has_swap = true, | 105 | .has_swap = true, |
| 101 | .has_wakeup = true, | 106 | .has_wakeup = true, |
| 102 | .has_fifo = true, | 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 | free_irq(port->irq, port); | 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 | static void stm32_usart_set_termios(struct uart_port *port, | 1156 | static void stm32_usart_set_termios(struct uart_port *port, |
| 1151 | struct ktermios *termios, | 1157 | struct ktermios *termios, |
| 1152 | const struct ktermios *old) | 1158 | const struct ktermios *old) |
| @@ -1155,17 +1161,19 @@ static void stm32_usart_set_termios(struct uart_port *port, · 2 unmodified lines | |||
| 1155 | const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 1161 | const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| 1156 | const struct stm32_usart_config *cfg = &stm32_port->info->cfg; | 1162 | const struct stm32_usart_config *cfg = &stm32_port->info->cfg; |
| 1157 | struct serial_rs485 *rs485conf = &port->rs485; | 1163 | struct serial_rs485 *rs485conf = &port->rs485; |
| 1158 | unsigned int baud, bits; | 1164 | unsigned int baud, bits, uart_clk, uart_clk_pres; |
| 1159 | u32 usartdiv, mantissa, fraction, oversampling; | 1165 | u32 usartdiv, mantissa, fraction, oversampling; |
| 1160 | tcflag_t cflag = termios->c_cflag; | 1166 | tcflag_t cflag = termios->c_cflag; |
| 1161 | u32 cr1, cr2, cr3, isr; | 1167 | u32 cr1, cr2, cr3, isr, brr, presc; |
| 1162 | unsigned long flags; | 1168 | unsigned long flags; |
| 1163 | int ret; | 1169 | int ret; |
| 1164 | 1170 | ||
| 1165 | if (!stm32_port->hw_flow_control) | 1171 | if (!stm32_port->hw_flow_control) |
| 1166 | cflag &= ~CRTSCTS; | 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 | uart_port_lock_irqsave(port, &flags); | 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 | cr3 |= USART_CR3_CTSE | USART_CR3_RTSE; | 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 | /* | 1282 | /* |
| 1273 | * The USART supports 16 or 8 times oversampling. | 1283 | * The USART supports 16 or 8 times oversampling. |
| 1274 | * By default we prefer 16 times oversampling, so that the receiver | 1284 | * By default we prefer 16 times oversampling, so that the receiver |
| 1275 | * has a better tolerance to clock deviations. | 1285 | * has a better tolerance to clock deviations. |
| 1276 | * 8 times oversampling is only used to achieve higher speeds. | 1286 | * 8 times oversampling is only used to achieve higher speeds. |
| 1277 | */ | 1287 | */ |
| 1278 | if (usartdiv < 16) { | 1288 | if (usartdiv < 16) { |
| 1279 | oversampling = 8; | 1289 | oversampling = 8; |
| 1280 | cr1 |= USART_CR1_OVER8; | 1290 | cr1 |= USART_CR1_OVER8; |
| 1281 | stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8); | 1291 | stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8); |
| 1282 | } else { | 1292 | } else { |
| 1283 | oversampling = 16; | 1293 | oversampling = 16; |
| 1284 | cr1 &= ~USART_CR1_OVER8; | 1294 | cr1 &= ~USART_CR1_OVER8; |
| 1285 | stm32_usart_clr_bits(port, ofs->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; | 1319 | writel_relaxed(brr, port->membase + ofs->brr); |
| 1289 | fraction = usartdiv % oversampling; | ||
| 1290 | writel_relaxed(mantissa | fraction, port->membase + ofs->brr); | ||
| 1291 | 1320 | ||
| 1292 | uart_update_timeout(port, cflag, baud); | 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 | #endif /* CONFIG_CONSOLE_POLL */ | 1500 | #endif /* CONFIG_CONSOLE_POLL */ |
| 1472 | }; | 1501 | }; |
| 1473 | 1502 | ||
| 1474 | /* | 1503 | struct stm32_usart_thresh_ratio { |
| 1475 | * STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG) | 1504 | int mul; |
| 1476 | * Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case, | 1505 | int div; |
| 1477 | * RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE. | 1506 | }; |
| 1478 | * So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1. | 1507 | |
| 1479 | */ | 1508 | static const struct stm32_usart_thresh_ratio stm32h7_usart_fifo_thresh_cfg[] = { |
| 1480 | static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 }; | 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, | 1517 | static int stm32_usart_get_ftcfg(struct platform_device *pdev, struct stm32_port *stm32port, |
| 1483 | int *ftcfg) | 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 | if (of_property_read_u32(pdev->dev.of_node, p, &bytes)) | 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++) | 1537 | if (bytes < stm32_usart_get_thresh_value(fifo_size, 0)) { |
| 1492 | if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes) | 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 | break; | 1544 | break; |
| 1545 | } | ||
| 1494 | if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg)) | 1546 | if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg)) |
| 1495 | i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1; | 1547 | i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1; |
| 1496 | 1548 | ||
| 1497 | dev_dbg(&pdev->dev, "%s set to %d bytes\n", p, | 1549 | dev_dbg(&pdev->dev, "%s set to %d/%d bytes\n", p, |
| 1498 | stm32h7_usart_fifo_thresh_cfg[i]); | 1550 | stm32_usart_get_thresh_value(fifo_size, i), fifo_size); |
| 1499 | 1551 | ||
| 1500 | /* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */ | 1552 | *ftcfg = i; |
| 1501 | if (i) | 1553 | return fifo_size; |
| 1502 | *ftcfg = i - 1; | ||
| 1503 | else | ||
| 1504 | *ftcfg = -EINVAL; | ||
| 1505 | } | 1554 | } |
| 1506 | 1555 | ||
| 1507 | static void stm32_usart_deinit_port(struct stm32_port *stm32port) | 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 | port->flags = UPF_BOOT_AUTOCONF; | 1580 | port->flags = UPF_BOOT_AUTOCONF; |
| 1532 | port->ops = &stm32_uart_ops; | 1581 | port->ops = &stm32_uart_ops; |
| 1533 | port->dev = &pdev->dev; | 1582 | port->dev = &pdev->dev; |
| 1534 | port->fifosize = stm32port->info->cfg.fifosize; | ||
| 1535 | port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); | 1583 | port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); |
| 1536 | port->irq = irq; | 1584 | port->irq = irq; |
| 1537 | port->rs485_config = stm32_usart_config_rs485; | 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 | stm32port->swap = stm32port->info->cfg.has_swap && | 1595 | stm32port->swap = stm32port->info->cfg.has_swap && |
| 1548 | of_property_read_bool(pdev->dev.of_node, "rx-tx-swap"); | 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 | port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); | 1598 | port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); |
| 1559 | if (IS_ERR(port->membase)) | 1599 | if (IS_ERR(port->membase)) |
| 1560 | return PTR_ERR(port->membase); | 1600 | return PTR_ERR(port->membase); |
| @@ -1577,6 +1617,15 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, · 16 unmodified lines | |||
| 1577 | goto err_clk; | 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 | stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0); | 1629 | stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0); |
| 1581 | if (IS_ERR(stm32port->gpios)) { | 1630 | if (IS_ERR(stm32port->gpios)) { |
| 1582 | ret = PTR_ERR(stm32port->gpios); | 1631 | ret = PTR_ERR(stm32port->gpios); |
| @@ -9,17 +9,19 @@ · 8 unmodified lines | |||
| 9 | #define DRIVER_NAME "stm32-usart" | 9 | #define DRIVER_NAME "stm32-usart" |
| 10 | 10 | ||
| 11 | struct stm32_usart_offsets { | 11 | struct stm32_usart_offsets { |
| 12 | u8 cr1; | 12 | u16 cr1; |
| 13 | u8 cr2; | 13 | u16 cr2; |
| 14 | u8 cr3; | 14 | u16 cr3; |
| 15 | u8 brr; | 15 | u16 brr; |
| 16 | u8 gtpr; | 16 | u16 gtpr; |
| 17 | u8 rtor; | 17 | u16 rtor; |
| 18 | u8 rqr; | 18 | u16 rqr; |
| 19 | u8 isr; | 19 | u16 isr; |
| 20 | u8 icr; | 20 | u16 icr; |
| 21 | u8 rdr; | 21 | u16 rdr; |
| 22 | u8 tdr; | 22 | u16 tdr; |
| 23 | u16 presc; | ||
| 24 | u16 hwcfgr1; | ||
| 23 | }; | 25 | }; |
| 24 | 26 | ||
| 25 | struct stm32_usart_config { | 27 | struct stm32_usart_config { |
| @@ -28,7 +30,6 @@ struct stm32_usart_config { · 2 unmodified lines | |||
| 28 | bool has_swap; | 30 | bool has_swap; |
| 29 | bool has_wakeup; | 31 | bool has_wakeup; |
| 30 | bool has_fifo; | 32 | bool has_fifo; |
| 31 | int fifosize; | ||
| 32 | }; | 33 | }; |
| 33 | 34 | ||
| 34 | struct stm32_usart_info { | 35 | struct stm32_usart_info { |
| @@ -36,7 +37,7 @@ struct stm32_usart_info { · 1 unmodified line | |||
| 36 | struct stm32_usart_config cfg; | 37 | struct stm32_usart_config cfg; |
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| 39 | #define UNDEF_REG 0xff | 40 | #define UNDEF_REG 0xffff |
| 40 | 41 | ||
| 41 | /* USART_SR (F4) / USART_ISR (F7) */ | 42 | /* USART_SR (F4) / USART_ISR (F7) */ |
| 42 | #define USART_SR_PE BIT(0) | 43 | #define USART_SR_PE BIT(0) |
| @@ -71,6 +72,7 @@ struct stm32_usart_info { · 28 unmodified lines | |||
| 71 | #define USART_BRR_DIV_M_MASK GENMASK(15, 4) | 72 | #define USART_BRR_DIV_M_MASK GENMASK(15, 4) |
| 72 | #define USART_BRR_DIV_M_SHIFT 4 | 73 | #define USART_BRR_DIV_M_SHIFT 4 |
| 73 | #define USART_BRR_04_R_SHIFT 1 | 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 | /* USART_CR1 */ | 77 | /* USART_CR1 */ |
| 76 | #define USART_CR1_SBK BIT(0) | 78 | #define USART_CR1_SBK BIT(0) |
| @@ -176,8 +178,16 @@ struct stm32_usart_info { · 99 unmodified lines | |||
| 176 | #define USART_ICR_CMCF BIT(17) /* F7 */ | 178 | #define USART_ICR_CMCF BIT(17) /* F7 */ |
| 177 | #define USART_ICR_WUCF BIT(20) /* H7 */ | 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 | #define STM32_SERIAL_NAME "ttySTM" | 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 | #define RX_BUF_L 4096 /* dma rx buffer length */ | 192 | #define RX_BUF_L 4096 /* dma rx buffer length */ |
| 183 | #define RX_BUF_P (RX_BUF_L / 2) /* dma rx buffer period */ | 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 | if (port->ignore_status_mask & SUP_DUMMY_READ) | 260 | if (port->ignore_status_mask & SUP_DUMMY_READ) |
| 261 | goto ignore_char; | 261 | goto ignore_char; |
| 262 | 262 | ||
| 263 | if (uart_handle_sysrq_char(port, ch)) | 263 | if (uart_prepare_sysrq_char(port, ch)) |
| 264 | goto ignore_char; | 264 | goto ignore_char; |
| 265 | 265 | ||
| 266 | uart_insert_char(port, lsr, SUP_UART_LSR_OE, ch, flag); | 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 | if (isc & SUP_UART_ISC_TX) | 287 | if (isc & SUP_UART_ISC_TX) |
| 288 | transmit_chars(port); | 288 | transmit_chars(port); |
| 289 | 289 | ||
| 290 | uart_port_unlock(port); | 290 | uart_unlock_and_check_sysrq(port); |
| 291 | 291 | ||
| 292 | return IRQ_HANDLED; | 292 | return IRQ_HANDLED; |
| 293 | } | 293 | } |
| @@ -512,22 +512,16 @@ static void sunplus_console_write(struct console *co, · 218 unmodified lines | |||
| 512 | unsigned long flags; | 512 | unsigned long flags; |
| 513 | int locked = 1; | 513 | int locked = 1; |
| 514 | 514 | ||
| 515 | local_irq_save(flags); | 515 | if (oops_in_progress) |
| 516 | 516 | locked = uart_port_trylock_irqsave(&sunplus_console_ports[co->index]->port, &flags); | |
| 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); | ||
| 521 | else | 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 | uart_console_write(&sunplus_console_ports[co->index]->port, s, count, | 520 | uart_console_write(&sunplus_console_ports[co->index]->port, s, count, |
| 525 | sunplus_uart_console_putchar); | 521 | sunplus_uart_console_putchar); |
| 526 | 522 | ||
| 527 | if (locked) | 523 | if (locked) |
| 528 | uart_port_unlock(&sunplus_console_ports[co->index]->port); | 524 | uart_port_unlock_irqrestore(&sunplus_console_ports[co->index]->port, flags); |
| 529 | |||
| 530 | local_irq_restore(flags); | ||
| 531 | } | 525 | } |
| 532 | 526 | ||
| 533 | static int __init sunplus_console_setup(struct console *co, char *options) | 527 | static int __init sunplus_console_setup(struct console *co, char *options) |
| @@ -22,7 +22,9 @@ · 21 unmodified lines | |||
| 22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/pm_runtime.h> | 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 | #define CDNS_UART_TTY_NAME "ttyPS" | 29 | #define CDNS_UART_TTY_NAME "ttyPS" |
| 28 | #define CDNS_UART_NAME "xuartps" | 30 | #define CDNS_UART_NAME "xuartps" |
| @@ -193,6 +195,9 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); · 164 unmodified lines | |||
| 193 | * @clk_rate_change_nb: Notifier block for clock changes | 195 | * @clk_rate_change_nb: Notifier block for clock changes |
| 194 | * @quirks: Flags for RXBS support. | 196 | * @quirks: Flags for RXBS support. |
| 195 | * @cts_override: Modem control state override | 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 | struct cdns_uart { | 202 | struct cdns_uart { |
| 198 | struct uart_port *port; | 203 | struct uart_port *port; |
| @@ -203,10 +208,21 @@ struct cdns_uart { · 4 unmodified lines | |||
| 203 | struct notifier_block clk_rate_change_nb; | 208 | struct notifier_block clk_rate_change_nb; |
| 204 | u32 quirks; | 209 | u32 quirks; |
| 205 | bool cts_override; | 210 | bool cts_override; |
| 211 | struct gpio_desc *gpiod_rts; | ||
| 212 | bool rs485_tx_started; | ||
| 213 | struct hrtimer tx_timer; | ||
| 206 | }; | 214 | }; |
| 207 | struct cdns_platform_data { | 215 | struct cdns_platform_data { |
| 208 | u32 quirks; | 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 | #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ | 226 | #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ |
| 211 | clk_rate_change_nb) | 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 | * @dev_id: Id of the UART port | 421 | * @dev_id: Id of the UART port |
| 311 | * Return: None | 422 | * Return: None |
| 312 | */ | 423 | */ |
| 313 | static void cdns_uart_handle_tx(void *dev_id) | 424 | static void cdns_uart_handle_tx(void *dev_id) |
| 314 | { | 425 | { |
| 315 | struct uart_port *port = (struct uart_port *)dev_id; | 426 | struct uart_port *port = (struct uart_port *)dev_id; |
| 427 | struct cdns_uart *cdns_uart = port->private_data; | ||
| 316 | struct circ_buf *xmit = &port->state->xmit; | 428 | struct circ_buf *xmit = &port->state->xmit; |
| 317 | unsigned int numbytes; | 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 | writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR); | 433 | writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR); |
| 321 | return; | 434 | return; |
| 322 | } | 435 | } |
| @@ -332,6 +445,16 @@ static void cdns_uart_handle_tx(void *dev_id) · 9 unmodified lines | |||
| 332 | 445 | ||
| 333 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 446 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| 334 | uart_write_wakeup(port); | 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 | #endif | 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 | * cdns_uart_start_tx - Start transmitting bytes | 706 | * cdns_uart_start_tx - Start transmitting bytes |
| 569 | * @port: Handle to the uart port structure | 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 | static void cdns_uart_start_tx(struct uart_port *port) | 709 | static void cdns_uart_start_tx(struct uart_port *port) |
| 572 | { | 710 | { |
| 573 | unsigned int status; | 711 | unsigned int status; |
| 712 | struct cdns_uart *cdns_uart = port->private_data; | ||
| 574 | 713 | ||
| 575 | if (uart_tx_stopped(port)) | 714 | if (uart_tx_stopped(port)) |
| 576 | return; | 715 | return; |
| @@ -587,12 +726,19 @@ static void cdns_uart_start_tx(struct uart_port *port) · 10 unmodified lines | |||
| 587 | if (uart_circ_empty(&port->state->xmit)) | 726 | if (uart_circ_empty(&port->state->xmit)) |
| 588 | return; | 727 | return; |
| 589 | 728 | ||
| 729 | /* Clear the TX Empty interrupt */ | ||
| 590 | writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); | 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 | cdns_uart_handle_tx(port); | 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 | static void cdns_uart_stop_tx(struct uart_port *port) | 748 | static void cdns_uart_stop_tx(struct uart_port *port) |
| 603 | { | 749 | { |
| 604 | unsigned int regval; | 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 | regval = readl(port->membase + CDNS_UART_CR); | 756 | regval = readl(port->membase + CDNS_UART_CR); |
| 607 | regval |= CDNS_UART_CR_TX_DIS; | 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 | writel(regval, port->membase + CDNS_UART_CR); | 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 | * cdns_uart_break_ctl - Based on the input ctl we have to start or stop | 780 | * cdns_uart_break_ctl - Based on the input ctl we have to start or stop |
| 646 | * transmitting char breaks | 781 | * transmitting char breaks |
| @@ -829,6 +964,9 @@ static int cdns_uart_startup(struct uart_port *port) · 182 unmodified lines | |||
| 829 | (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) | 964 | (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) |
| 830 | cpu_relax(); | 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 | * Clear the RX disable bit and then set the RX enable bit to enable | 971 | * Clear the RX disable bit and then set the RX enable bit to enable |
| 834 | * the receiver. | 972 | * the receiver. |
| @@ -888,6 +1026,10 @@ static void cdns_uart_shutdown(struct uart_port *port) · 53 unmodified lines | |||
| 888 | { | 1026 | { |
| 889 | int status; | 1027 | int status; |
| 890 | unsigned long flags; | 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 | uart_port_lock_irqsave(port, &flags); | 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 | if (mctrl & TIOCM_RTS) | 1176 | if (mctrl & TIOCM_RTS) |
| 1035 | val |= CDNS_UART_MODEMCR_RTS; | 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 | if (mctrl & TIOCM_DTR) | 1180 | if (mctrl & TIOCM_DTR) |
| 1037 | val |= CDNS_UART_MODEMCR_DTR; | 1181 | val |= CDNS_UART_MODEMCR_DTR; |
| 1038 | if (mctrl & TIOCM_LOOP) | 1182 | if (mctrl & TIOCM_LOOP) |
| @@ -1455,6 +1599,39 @@ MODULE_DEVICE_TABLE(of, cdns_uart_of_match); · 416 unmodified lines | |||
| 1455 | /* Temporary variable for storing number of instances */ | 1599 | /* Temporary variable for storing number of instances */ |
| 1456 | static int instances; | 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 | * cdns_uart_probe - Platform driver probe | 1636 | * cdns_uart_probe - Platform driver probe |
| 1460 | * @pdev: Pointer to the platform device structure | 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 | port->private_data = cdns_uart_data; | 1774 | port->private_data = cdns_uart_data; |
| 1598 | port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG | | 1775 | port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG | |
| 1599 | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT; | 1776 | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT; |
| 1777 | port->rs485_config = cdns_rs485_config; | ||
| 1778 | port->rs485_supported = cdns_rs485_supported; | ||
| 1600 | cdns_uart_data->port = port; | 1779 | cdns_uart_data->port = port; |
| 1601 | platform_set_drvdata(pdev, port); | 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 | pm_runtime_use_autosuspend(&pdev->dev); | 1794 | pm_runtime_use_autosuspend(&pdev->dev); |
| 1604 | pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); | 1795 | pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); |
| 1605 | pm_runtime_set_active(&pdev->dev); | 1796 | pm_runtime_set_active(&pdev->dev); |
| @@ -1618,6 +1809,8 @@ static int cdns_uart_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 1618 | console_port = port; | 1809 | console_port = port; |
| 1619 | } | 1810 | } |
| 1620 | #endif | 1811 | #endif |
| 1812 | if (cdns_uart_data->port->rs485.flags & SER_RS485_ENABLED) | ||
| 1813 | cdns_rs485_rx_setup(cdns_uart_data); | ||
| 1621 | 1814 | ||
| 1622 | rc = uart_add_one_port(&cdns_uart_uart_driver, port); | 1815 | rc = uart_add_one_port(&cdns_uart_uart_driver, port); |
| 1623 | if (rc) { | 1816 | if (rc) { |
| @@ -1646,6 +1839,7 @@ err_out_pm_disable: · 22 unmodified lines | |||
| 1646 | pm_runtime_disable(&pdev->dev); | 1839 | pm_runtime_disable(&pdev->dev); |
| 1647 | pm_runtime_set_suspended(&pdev->dev); | 1840 | pm_runtime_set_suspended(&pdev->dev); |
| 1648 | pm_runtime_dont_use_autosuspend(&pdev->dev); | 1841 | pm_runtime_dont_use_autosuspend(&pdev->dev); |
| 1842 | err_out_clk_notifier: | ||
| 1649 | #ifdef CONFIG_COMMON_CLK | 1843 | #ifdef CONFIG_COMMON_CLK |
| 1650 | clk_notifier_unregister(cdns_uart_data->uartclk, | 1844 | clk_notifier_unregister(cdns_uart_data->uartclk, |
| 1651 | &cdns_uart_data->clk_rate_change_nb); | 1845 | &cdns_uart_data->clk_rate_change_nb); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/errno.h> | 7 | #include <linux/errno.h> |
| 8 | #include <linux/minmax.h> | 8 | #include <linux/minmax.h> |
| 9 | #include <linux/tty.h> | 9 | #include <linux/tty.h> |
| 10 | #include <linux/tty_buffer.h> | ||
| 10 | #include <linux/tty_driver.h> | 11 | #include <linux/tty_driver.h> |
| 11 | #include <linux/tty_flip.h> | 12 | #include <linux/tty_flip.h> |
| 12 | #include <linux/timer.h> | 13 | #include <linux/timer.h> |
| @@ -5,9 +5,9 @@ · 4 unmodified lines | |||
| 5 | FONTMAPFILE = cp437.uni | 5 | FONTMAPFILE = cp437.uni |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \ | 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 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o | 10 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o |
| 10 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | ||
| 11 | 11 | ||
| 12 | # Files generated that shall be removed upon make clean | 12 | # Files generated that shall be removed upon make clean |
| 13 | clean-files := consolemap_deftbl.c defkeymap.c | 13 | clean-files := consolemap_deftbl.c defkeymap.c |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | |||
| 7 | * 'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)' | 7 | * 'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)' |
| 8 | * 'void clear_selection(void)' | 8 | * 'void clear_selection(void)' |
| 9 | * 'int paste_selection(struct tty_struct *)' | 9 | * 'int paste_selection(struct tty_struct *)' |
| 10 | * 'int sel_loadlut(char __user *)' | 10 | * 'int sel_loadlut(u32 __user *)' |
| 11 | * | 11 | * |
| 12 | * Now that /dev/vcs exists, most of this can disappear again. | 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 | 78 | * Remove the current selection highlight, if any from the console holding the |
| 79 | * holding the selection. The caller must hold the console lock. | 79 | * selection. |
| 80 | * | ||
| 81 | * Locking: The caller must hold the console lock. | ||
| 80 | */ | 82 | */ |
| 81 | void clear_selection(void) | 83 | void clear_selection(void) |
| 82 | { | 84 | { |
| @@ -88,7 +90,7 @@ void clear_selection(void) · 5 unmodified lines | |||
| 88 | } | 90 | } |
| 89 | EXPORT_SYMBOL_GPL(clear_selection); | 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 | return vc == vc_sel.cons; | 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 | 115 | * sel_loadlut() - load the LUT table |
| 114 | * @p: user 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 | 121 | * Locking: The console lock is acquired. |
| 117 | * lock. Make a temporary copy so a partial update doesn't make a mess. | ||
| 118 | */ | 122 | */ |
| 119 | int sel_loadlut(char __user *p) | 123 | int sel_loadlut(u32 __user *lut) |
| 120 | { | 124 | { |
| 121 | u32 tmplut[ARRAY_SIZE(inwordLut)]; | 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 | return -EFAULT; | 128 | return -EFAULT; |
| 129 | |||
| 130 | console_lock(); | ||
| 124 | memcpy(inwordLut, tmplut, sizeof(inwordLut)); | 131 | memcpy(inwordLut, tmplut, sizeof(inwordLut)); |
| 132 | console_unlock(); | ||
| 133 | |||
| 125 | return 0; | 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. | 178 | * set_selection_user - set the current selection. |
| 170 | * @sel: user selection info | 179 | * @sel: user selection info |
| 171 | * @tty: the console tty | 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 | 184 | * Locking: The entire selection process is managed under the console_lock. |
| 176 | * a lot under the lock but its hardly a performance path | 185 | * It's a lot under the lock but its hardly a performance path. |
| 177 | */ | 186 | */ |
| 178 | int set_selection_user(const struct tiocl_selection __user *sel, | 187 | int set_selection_user(const struct tiocl_selection __user *sel, |
| 179 | struct tty_struct *tty) | 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 | static void save_cur(struct vc_data *vc); | 145 | static void save_cur(struct vc_data *vc); |
| 146 | static void reset_terminal(struct vc_data *vc, int do_clear); | 146 | static void reset_terminal(struct vc_data *vc, int do_clear); |
| 147 | static void con_flush_chars(struct tty_struct *tty); | 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 | static void set_cursor(struct vc_data *vc); | 149 | static void set_cursor(struct vc_data *vc); |
| 150 | static void hide_cursor(struct vc_data *vc); | 150 | static void hide_cursor(struct vc_data *vc); |
| 151 | static void console_callback(struct work_struct *ignored); | 151 | static void console_callback(struct work_struct *ignored); |
| @@ -175,7 +175,7 @@ int do_poke_blanked_console; · 23 unmodified lines | |||
| 175 | int console_blanked; | 175 | int console_blanked; |
| 176 | EXPORT_SYMBOL(console_blanked); | 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 | static int vesa_off_interval; | 179 | static int vesa_off_interval; |
| 180 | static int blankinterval; | 180 | static int blankinterval; |
| 181 | core_param(consoleblank, blankinterval, int, 0444); | 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 | return con_is_visible(vc) && !console_blanked; | 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, | 289 | static inline u16 *screenpos(const struct vc_data *vc, unsigned int offset, |
| 290 | bool viewed) | 290 | bool viewed) |
| 291 | { | 291 | { |
| 292 | unsigned short *p; | 292 | unsigned long origin = viewed ? vc->vc_visible_origin : vc->vc_origin; |
| 293 | 293 | ||
| 294 | if (!viewed) | 294 | return (u16 *)(origin + offset); |
| 295 | p = (unsigned short *)(vc->vc_origin + offset); | 295 | } |
| 296 | else if (!vc->vc_sw->con_screen_pos) | 296 | |
| 297 | p = (unsigned short *)(vc->vc_visible_origin + offset); | 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 | else | 301 | else |
| 299 | p = vc->vc_sw->con_screen_pos(vc, offset); | 302 | vc->vc_sw->con_putcs(vc, &ca, 1, y, x); |
| 300 | return p; | ||
| 301 | } | 303 | } |
| 302 | 304 | ||
| 303 | /* Called from the keyboard irq path.. */ | 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 | static void do_update_region(struct vc_data *vc, unsigned long start, int count) | 593 | static void do_update_region(struct vc_data *vc, unsigned long start, int count) |
| 592 | { | 594 | { |
| 593 | unsigned int xx, yy, offset; | 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 | for(;;) { | 602 | for(;;) { |
| 607 | u16 attrib = scr_readw(p) & 0xff00; | 603 | u16 attrib = scr_readw(p) & 0xff00; |
| 608 | int startx = xx; | 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 | break; | 621 | break; |
| 626 | xx = 0; | 622 | xx = 0; |
| 627 | yy++; | 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 | /* Note: inverting the screen twice should revert to the original state */ | 695 | /* Note: inverting the screen twice should revert to the original state */ |
| 704 | void invert_screen(struct vc_data *vc, int offset, int count, bool viewed) | 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 | WARN_CONSOLE_UNLOCKED(); | 700 | WARN_CONSOLE_UNLOCKED(); |
| 709 | 701 | ||
| @@ -762,7 +754,7 @@ void complement_pos(struct vc_data *vc, int offset) · 52 unmodified lines | |||
| 762 | old_offset < vc->vc_screenbuf_size) { | 754 | old_offset < vc->vc_screenbuf_size) { |
| 763 | scr_writew(old, screenpos(vc, old_offset, true)); | 755 | scr_writew(old, screenpos(vc, old_offset, true)); |
| 764 | if (con_should_update(vc)) | 756 | if (con_should_update(vc)) |
| 765 | vc->vc_sw->con_putc(vc, old, oldy, oldx); | 757 | con_putc(vc, old, oldy, oldx); |
| 766 | notify_update(vc); | 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 | if (offset != -1 && offset >= 0 && | 763 | if (offset != -1 && offset >= 0 && |
| 772 | offset < vc->vc_screenbuf_size) { | 764 | offset < vc->vc_screenbuf_size) { |
| 773 | unsigned short new; | 765 | unsigned short new; |
| 774 | unsigned short *p; | 766 | u16 *p = screenpos(vc, offset, true); |
| 775 | p = screenpos(vc, offset, true); | ||
| 776 | old = scr_readw(p); | 767 | old = scr_readw(p); |
| 777 | new = old ^ vc->vc_complement_mask; | 768 | new = old ^ vc->vc_complement_mask; |
| 778 | scr_writew(new, p); | 769 | scr_writew(new, p); |
| 779 | if (con_should_update(vc)) { | 770 | if (con_should_update(vc)) { |
| 780 | oldx = (offset >> 1) % vc->vc_cols; | 771 | oldx = (offset >> 1) % vc->vc_cols; |
| 781 | oldy = (offset >> 1) / vc->vc_cols; | 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 | notify_update(vc); | 775 | notify_update(vc); |
| 785 | } | 776 | } |
| @@ -833,7 +824,7 @@ static void add_softcursor(struct vc_data *vc) · 47 unmodified lines | |||
| 833 | i ^= CUR_FG; | 824 | i ^= CUR_FG; |
| 834 | scr_writew(i, (u16 *)vc->vc_pos); | 825 | scr_writew(i, (u16 *)vc->vc_pos); |
| 835 | if (con_should_update(vc)) | 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 | static void hide_softcursor(struct vc_data *vc) | 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 | if (softcursor_original != -1) { | 832 | if (softcursor_original != -1) { |
| 842 | scr_writew(softcursor_original, (u16 *)vc->vc_pos); | 833 | scr_writew(softcursor_original, (u16 *)vc->vc_pos); |
| 843 | if (con_should_update(vc)) | 834 | if (con_should_update(vc)) |
| 844 | vc->vc_sw->con_putc(vc, softcursor_original, | 835 | con_putc(vc, softcursor_original, vc->state.y, |
| 845 | vc->state.y, vc->state.x); | 836 | vc->state.x); |
| 846 | softcursor_original = -1; | 837 | softcursor_original = -1; |
| 847 | } | 838 | } |
| 848 | } | 839 | } |
| @@ -852,7 +843,7 @@ static void hide_cursor(struct vc_data *vc) · 3 unmodified lines | |||
| 852 | if (vc_is_sel(vc)) | 843 | if (vc_is_sel(vc)) |
| 853 | clear_selection(); | 844 | clear_selection(); |
| 854 | 845 | ||
| 855 | vc->vc_sw->con_cursor(vc, CM_ERASE); | 846 | vc->vc_sw->con_cursor(vc, false); |
| 856 | hide_softcursor(vc); | 847 | hide_softcursor(vc); |
| 857 | } | 848 | } |
| 858 | 849 | ||
| @@ -865,7 +856,7 @@ static void set_cursor(struct vc_data *vc) · 6 unmodified lines | |||
| 865 | clear_selection(); | 856 | clear_selection(); |
| 866 | add_softcursor(vc); | 857 | add_softcursor(vc); |
| 867 | if (CUR_SIZE(vc->vc_cursor_type) != CUR_NONE) | 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 | } else | 860 | } else |
| 870 | hide_cursor(vc); | 861 | hide_cursor(vc); |
| 871 | } | 862 | } |
| @@ -897,21 +888,18 @@ static void flush_scrollback(struct vc_data *vc) · 25 unmodified lines | |||
| 897 | WARN_CONSOLE_UNLOCKED(); | 888 | WARN_CONSOLE_UNLOCKED(); |
| 898 | 889 | ||
| 899 | set_origin(vc); | 890 | set_origin(vc); |
| 900 | if (vc->vc_sw->con_flush_scrollback) { | 891 | if (!con_is_visible(vc)) |
| 901 | vc->vc_sw->con_flush_scrollback(vc); | 892 | return; |
| 902 | } else if (con_is_visible(vc)) { | 893 | |
| 903 | /* | 894 | /* |
| 904 | * When no con_flush_scrollback method is provided then the | 895 | * The legacy way for flushing the scrollback buffer is to use a side |
| 905 | * legacy way for flushing the scrollback buffer is to use | 896 | * effect of the con_switch method. We do it only on the foreground |
| 906 | * a side effect of the con_switch method. We do it only on | 897 | * console as background consoles have no scrollback buffers in that |
| 907 | * the foreground console as background consoles have no | 898 | * case and we obviously don't want to switch to them. |
| 908 | * scrollback buffers in that case and we obviously don't | 899 | */ |
| 909 | * want to switch to them. | 900 | hide_cursor(vc); |
| 910 | */ | 901 | vc->vc_sw->con_switch(vc); |
| 911 | hide_cursor(vc); | 902 | set_cursor(vc); |
| 912 | vc->vc_sw->con_switch(vc); | ||
| 913 | set_cursor(vc); | ||
| 914 | } | ||
| 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 | if (redraw) { | 952 | if (redraw) { |
| 965 | int update; | 953 | bool update; |
| 966 | int old_was_color = vc->vc_can_do_color; | 954 | int old_was_color = vc->vc_can_do_color; |
| 967 | 955 | ||
| 968 | set_origin(vc); | 956 | set_origin(vc); |
| @@ -999,7 +987,7 @@ int vc_cons_allocated(unsigned int i) · 30 unmodified lines | |||
| 999 | return (i < MAX_NR_CONSOLES && vc_cons[i].d); | 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 | /* ++Geert: vc->vc_sw->con_init determines console size */ | 992 | /* ++Geert: vc->vc_sw->con_init determines console size */ |
| 1005 | if (vc->vc_sw) | 993 | if (vc->vc_sw) |
| @@ -1083,7 +1071,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ · 77 unmodified lines | |||
| 1083 | vc->port.ops = &vc_port_ops; | 1071 | vc->port.ops = &vc_port_ops; |
| 1084 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 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 | if (!*vc->uni_pagedict_loc) | 1076 | if (!*vc->uni_pagedict_loc) |
| 1089 | con_set_default_unimap(vc); | 1077 | con_set_default_unimap(vc); |
| @@ -1115,51 +1103,44 @@ err_free: · 25 unmodified lines | |||
| 1115 | } | 1103 | } |
| 1116 | 1104 | ||
| 1117 | static inline int resize_screen(struct vc_data *vc, int width, int height, | 1105 | static inline int resize_screen(struct vc_data *vc, int width, int height, |
| 1118 | int user) | 1106 | bool from_user) |
| 1119 | { | 1107 | { |
| 1120 | /* Resizes the resolution of the display adapater */ | 1108 | /* Resizes the resolution of the display adapater */ |
| 1121 | int err = 0; | 1109 | int err = 0; |
| 1122 | 1110 | ||
| 1123 | if (vc->vc_sw->con_resize) | 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 | return err; | 1114 | return err; |
| 1127 | } | 1115 | } |
| 1128 | 1116 | ||
| 1129 | /** | 1117 | /** |
| 1130 | * vc_do_resize - resizing method for the tty | 1118 | * vc_do_resize - resizing method for the tty |
| 1131 | * @tty: tty being resized | 1119 | * @tty: tty being resized |
| 1132 | * @vc: virtual console private data | 1120 | * @vc: virtual console private data |
| 1133 | * @cols: columns | 1121 | * @cols: columns |
| 1134 | * @lines: lines | 1122 | * @lines: lines |
| 1123 | * @from_user: invoked by a user? | ||
| 1135 | * | 1124 | * |
| 1136 | * Resize a virtual console, clipping according to the actual constraints. | 1125 | * Resize a virtual console, clipping according to the actual constraints. If |
| 1137 | * If the caller passes a tty structure then update the termios winsize | 1126 | * the caller passes a tty structure then update the termios winsize |
| 1138 | * information and perform any necessary signal handling. | 1127 | * information and perform any necessary signal handling. |
| 1139 | * | 1128 | * |
| 1140 | * Caller must hold the console semaphore. Takes the termios rwsem and | 1129 | * Locking: Caller must hold the console semaphore. Takes the termios rwsem and |
| 1141 | * ctrl.lock of the tty IFF a tty is passed. | 1130 | * ctrl.lock of the tty IFF a tty is passed. |
| 1142 | */ | 1131 | */ |
| 1143 | |||
| 1144 | static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | 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 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; | 1135 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
| 1148 | unsigned long end; | 1136 | unsigned long end; |
| 1149 | unsigned int old_rows, old_row_size, first_copied_row; | 1137 | unsigned int old_rows, old_row_size, first_copied_row; |
| 1150 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; | 1138 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; |
| 1151 | unsigned int user; | ||
| 1152 | unsigned short *oldscreen, *newscreen; | 1139 | unsigned short *oldscreen, *newscreen; |
| 1153 | u32 **new_uniscr = NULL; | 1140 | u32 **new_uniscr = NULL; |
| 1154 | 1141 | ||
| 1155 | WARN_CONSOLE_UNLOCKED(); | 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 | if (cols > VC_MAXCOL || lines > VC_MAXROW) | 1144 | if (cols > VC_MAXCOL || lines > VC_MAXROW) |
| 1164 | return -EINVAL; | 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 | * to deal with possible errors from the code below, we call | 1166 | * to deal with possible errors from the code below, we call |
| 1186 | * the resize_screen here as well. | 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 | if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size) | 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 | old_rows = vc->vc_rows; | 1189 | old_rows = vc->vc_rows; |
| 1209 | old_row_size = vc->vc_size_row; | 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 | if (err) { | 1193 | if (err) { |
| 1213 | kfree(newscreen); | 1194 | kfree(newscreen); |
| 1214 | vc_uniscr_free(new_uniscr); | 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 | 1279 | * __vc_resize - resize a VT |
| 1299 | * @vc: virtual console | 1280 | * @vc: virtual console |
| 1300 | * @cols: columns | 1281 | * @cols: columns |
| 1301 | * @rows: rows | 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 | 1288 | * Locking: The caller must hold the console sem to protect console internals |
| 1304 | * use the common vc_do_resize methods to update the structures. The | 1289 | * and @vc->port.tty. |
| 1305 | * caller must hold the console sem to protect console internals and | ||
| 1306 | * vc->port.tty | ||
| 1307 | */ | 1290 | */ |
| 1308 | 1291 | int __vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows, | |
| 1309 | 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 | 1299 | * vt_resize - resize a VT |
| 1317 | * @tty: tty to resize | 1300 | * @tty: tty to resize |
| 1318 | * @ws: winsize attributes | 1301 | * @ws: winsize attributes |
| 1319 | * | 1302 | * |
| 1320 | * Resize a virtual terminal. This is called by the tty layer as we | 1303 | * Resize a virtual terminal. This is called by the tty layer as we register |
| 1321 | * register our own handler for resizing. The mutual helper does all | 1304 | * our own handler for resizing. The mutual helper does all the actual work. |
| 1322 | * the actual work. | ||
| 1323 | * | 1305 | * |
| 1324 | * Takes the console sem and the called methods then take the tty | 1306 | * Locking: Takes the console sem and the called methods then take the tty |
| 1325 | * termios_rwsem and the tty ctrl.lock in that order. | 1307 | * termios_rwsem and the tty ctrl.lock in that order. |
| 1326 | */ | 1308 | */ |
| 1327 | static int vt_resize(struct tty_struct *tty, struct winsize *ws) | 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 | int ret; | 1312 | int ret; |
| 1331 | 1313 | ||
| 1332 | console_lock(); | 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 | console_unlock(); | 1316 | console_unlock(); |
| 1335 | return ret; | 1317 | return ret; |
| 1336 | } | 1318 | } |
| @@ -1503,36 +1485,43 @@ static inline void del(struct vc_data *vc) · 166 unmodified lines | |||
| 1503 | /* ignored */ | 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 | unsigned int count; | 1498 | unsigned int count; |
| 1509 | unsigned short * start; | ||
| 1510 | 1499 | ||
| 1511 | switch (vpar) { | 1500 | switch (vpar) { |
| 1512 | case 0: /* erase from cursor to end of display */ | 1501 | case CSI_J_CURSOR_TO_END: |
| 1513 | vc_uniscr_clear_line(vc, vc->state.x, | 1502 | vc_uniscr_clear_line(vc, vc->state.x, |
| 1514 | vc->vc_cols - vc->state.x); | 1503 | vc->vc_cols - vc->state.x); |
| 1515 | vc_uniscr_clear_lines(vc, vc->state.y + 1, | 1504 | vc_uniscr_clear_lines(vc, vc->state.y + 1, |
| 1516 | vc->vc_rows - vc->state.y - 1); | 1505 | vc->vc_rows - vc->state.y - 1); |
| 1517 | count = (vc->vc_scr_end - vc->vc_pos) >> 1; | 1506 | count = (vc->vc_scr_end - vc->vc_pos) >> 1; |
| 1518 | start = (unsigned short *)vc->vc_pos; | 1507 | start = (unsigned short *)vc->vc_pos; |
| 1519 | break; | 1508 | break; |
| 1520 | case 1: /* erase from start to cursor */ | 1509 | case CSI_J_START_TO_CURSOR: |
| 1521 | vc_uniscr_clear_line(vc, 0, vc->state.x + 1); | 1510 | vc_uniscr_clear_line(vc, 0, vc->state.x + 1); |
| 1522 | vc_uniscr_clear_lines(vc, 0, vc->state.y); | 1511 | vc_uniscr_clear_lines(vc, 0, vc->state.y); |
| 1523 | count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; | 1512 | count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; |
| 1524 | start = (unsigned short *)vc->vc_origin; | 1513 | start = (unsigned short *)vc->vc_origin; |
| 1525 | break; | 1514 | break; |
| 1526 | case 3: /* include scrollback */ | 1515 | case CSI_J_FULL: |
| 1527 | flush_scrollback(vc); | 1516 | flush_scrollback(vc); |
| 1528 | fallthrough; | 1517 | fallthrough; |
| 1529 | case 2: /* erase whole display */ | 1518 | case CSI_J_VISIBLE: |
| 1530 | vc_uniscr_clear_lines(vc, 0, vc->vc_rows); | 1519 | vc_uniscr_clear_lines(vc, 0, vc->vc_rows); |
| 1531 | count = vc->vc_cols * vc->vc_rows; | 1520 | count = vc->vc_cols * vc->vc_rows; |
| 1532 | start = (unsigned short *)vc->vc_origin; | 1521 | start = (unsigned short *)vc->vc_origin; |
| 1533 | break; | 1522 | break; |
| 1534 | default: | 1523 | default: |
| 1535 | return; | 1524 | return; |
| 1536 | } | 1525 | } |
| 1537 | scr_memsetw(start, vc->vc_video_erase_char, 2 * count); | 1526 | scr_memsetw(start, vc->vc_video_erase_char, 2 * count); |
| 1538 | if (con_should_update(vc)) | 1527 | if (con_should_update(vc)) |
| @@ -1540,27 +1529,33 @@ static void csi_J(struct vc_data *vc, int vpar) · 1 unmodified line | |||
| 1540 | vc->vc_need_wrap = 0; | 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 | unsigned int count; | 1540 | unsigned int count; |
| 1546 | unsigned short *start = (unsigned short *)vc->vc_pos; | 1541 | unsigned short *start = (unsigned short *)vc->vc_pos; |
| 1547 | int offset; | 1542 | int offset; |
| 1548 | 1543 | ||
| 1549 | switch (vpar) { | 1544 | switch (vc->vc_par[0]) { |
| 1550 | case 0: /* erase from cursor to end of line */ | 1545 | case CSI_K_CURSOR_TO_LINEEND: |
| 1551 | offset = 0; | 1546 | offset = 0; |
| 1552 | count = vc->vc_cols - vc->state.x; | 1547 | count = vc->vc_cols - vc->state.x; |
| 1553 | break; | 1548 | break; |
| 1554 | case 1: /* erase from start of line to cursor */ | 1549 | case CSI_K_LINESTART_TO_CURSOR: |
| 1555 | offset = -vc->state.x; | 1550 | offset = -vc->state.x; |
| 1556 | count = vc->state.x + 1; | 1551 | count = vc->state.x + 1; |
| 1557 | break; | 1552 | break; |
| 1558 | case 2: /* erase whole line */ | 1553 | case CSI_K_LINE: |
| 1559 | offset = -vc->state.x; | 1554 | offset = -vc->state.x; |
| 1560 | count = vc->vc_cols; | 1555 | count = vc->vc_cols; |
| 1561 | break; | 1556 | break; |
| 1562 | default: | 1557 | default: |
| 1563 | return; | 1558 | return; |
| 1564 | } | 1559 | } |
| 1565 | vc_uniscr_clear_line(vc, vc->state.x + offset, count); | 1560 | vc_uniscr_clear_line(vc, vc->state.x + offset, count); |
| 1566 | scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count); | 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 | do_update_region(vc, (unsigned long)(start + offset), count); | 1564 | do_update_region(vc, (unsigned long)(start + offset), count); |
| 1570 | } | 1565 | } |
| 1571 | 1566 | ||
| 1572 | /* erase the following vpar positions */ | 1567 | /* erase the following count positions */ |
| 1573 | static void csi_X(struct vc_data *vc, unsigned int vpar) | 1568 | static void csi_X(struct vc_data *vc) |
| 1574 | { /* not vt100? */ | 1569 | { /* not vt100? */ |
| 1575 | unsigned int count; | 1570 | unsigned int count = clamp(vc->vc_par[0], 1, vc->vc_cols - vc->state.x); |
| 1576 | |||
| 1577 | if (!vpar) | ||
| 1578 | vpar++; | ||
| 1579 | |||
| 1580 | count = min(vpar, vc->vc_cols - vc->state.x); | ||
| 1581 | 1571 | ||
| 1582 | vc_uniscr_clear_line(vc, vc->state.x, count); | 1572 | vc_uniscr_clear_line(vc, vc->state.x, count); |
| 1583 | scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); | 1573 | scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); |
| 1584 | if (con_should_update(vc)) | 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 | vc->vc_need_wrap = 0; | 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 | struct rgb { u8 r; u8 g; u8 b; }; | 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 | if (i < 8) { /* Standard colours. */ | 1593 | if (i < 8) { /* Standard colours. */ |
| 1604 | c->r = i&1 ? 0xaa : 0x00; | 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 | c->g = i&2 ? 0xff : 0x55; | 1599 | c->g = i&2 ? 0xff : 0x55; |
| 1610 | c->b = i&4 ? 0xff : 0x55; | 1600 | c->b = i&4 ? 0xff : 0x55; |
| 1611 | } else if (i < 232) { /* 6x6x6 colour cube. */ | 1601 | } else if (i < 232) { /* 6x6x6 colour cube. */ |
| 1612 | c->r = (i - 16) / 36 * 85 / 2; | 1602 | i -= 16; |
| 1613 | c->g = (i - 16) / 6 % 6 * 85 / 2; | 1603 | c->b = i % 6 * 255 / 6; |
| 1614 | c->b = (i - 16) % 6 * 85 / 2; | 1604 | i /= 6; |
| 1605 | c->g = i % 6 * 255 / 6; | ||
| 1606 | i /= 6; | ||
| 1607 | c->r = i * 255 / 6; | ||
| 1615 | } else /* Grayscale ramp. */ | 1608 | } else /* Grayscale ramp. */ |
| 1616 | c->r = c->g = c->b = i * 10 - 2312; | 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 | return i; | 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 | /* console_lock is held */ | 1710 | /* console_lock is held */ |
| 1685 | static void csi_m(struct vc_data *vc) | 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 | for (i = 0; i <= vc->vc_npar; i++) | 1715 | for (i = 0; i <= vc->vc_npar; i++) |
| 1690 | switch (vc->vc_par[i]) { | 1716 | switch (vc->vc_par[i]) { |
| 1691 | case 0: /* all attributes off */ | 1717 | case CSI_m_DEFAULT: /* all attributes off */ |
| 1692 | default_attr(vc); | 1718 | default_attr(vc); |
| 1693 | break; | 1719 | break; |
| 1694 | case 1: | 1720 | case CSI_m_BOLD: |
| 1695 | vc->state.intensity = VCI_BOLD; | 1721 | vc->state.intensity = VCI_BOLD; |
| 1696 | break; | 1722 | break; |
| 1697 | case 2: | 1723 | case CSI_m_HALF_BRIGHT: |
| 1698 | vc->state.intensity = VCI_HALF_BRIGHT; | 1724 | vc->state.intensity = VCI_HALF_BRIGHT; |
| 1699 | break; | 1725 | break; |
| 1700 | case 3: | 1726 | case CSI_m_ITALIC: |
| 1701 | vc->state.italic = true; | 1727 | vc->state.italic = true; |
| 1702 | break; | 1728 | break; |
| 1703 | case 21: | 1729 | case CSI_m_DOUBLE_UNDERLINE: |
| 1704 | /* | 1730 | /* |
| 1705 | * No console drivers support double underline, so | 1731 | * No console drivers support double underline, so |
| 1706 | * convert it to a single underline. | 1732 | * convert it to a single underline. |
| 1707 | */ | 1733 | */ |
| 1708 | case 4: | 1734 | case CSI_m_UNDERLINE: |
| 1709 | vc->state.underline = true; | 1735 | vc->state.underline = true; |
| 1710 | break; | 1736 | break; |
| 1711 | case 5: | 1737 | case CSI_m_BLINK: |
| 1712 | vc->state.blink = true; | 1738 | vc->state.blink = true; |
| 1713 | break; | 1739 | break; |
| 1714 | case 7: | 1740 | case CSI_m_REVERSE: |
| 1715 | vc->state.reverse = true; | 1741 | vc->state.reverse = true; |
| 1716 | break; | 1742 | break; |
| 1717 | case 10: /* ANSI X3.64-1979 (SCO-ish?) | 1743 | case CSI_m_PRI_FONT: /* ANSI X3.64-1979 (SCO-ish?) |
| 1718 | * Select primary font, don't display control chars if | 1744 | * Select primary font, don't display control chars if |
| 1719 | * defined, don't set bit 8 on output. | 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 | vc->vc_disp_ctrl = 0; | 1748 | vc->vc_disp_ctrl = 0; |
| 1723 | vc->vc_toggle_meta = 0; | 1749 | vc->vc_toggle_meta = 0; |
| 1724 | break; | 1750 | break; |
| 1725 | case 11: /* ANSI X3.64-1979 (SCO-ish?) | 1751 | case CSI_m_ALT_FONT1: /* ANSI X3.64-1979 (SCO-ish?) |
| 1726 | * Select first alternate font, lets chars < 32 be | 1752 | * Select first alternate font, lets chars < 32 be |
| 1727 | * displayed as ROM chars. | 1753 | * displayed as ROM chars. |
| 1728 | */ | 1754 | */ |
| @@ -1730,7 +1756,7 @@ static void csi_m(struct vc_data *vc) · 1 unmodified line | |||
| 1730 | vc->vc_disp_ctrl = 1; | 1756 | vc->vc_disp_ctrl = 1; |
| 1731 | vc->vc_toggle_meta = 0; | 1757 | vc->vc_toggle_meta = 0; |
| 1732 | break; | 1758 | break; |
| 1733 | case 12: /* ANSI X3.64-1979 (SCO-ish?) | 1759 | case CSI_m_ALT_FONT2: /* ANSI X3.64-1979 (SCO-ish?) |
| 1734 | * Select second alternate font, toggle high bit | 1760 | * Select second alternate font, toggle high bit |
| 1735 | * before displaying as ROM char. | 1761 | * before displaying as ROM char. |
| 1736 | */ | 1762 | */ |
| @@ -1738,47 +1764,51 @@ static void csi_m(struct vc_data *vc) · 1 unmodified line | |||
| 1738 | vc->vc_disp_ctrl = 1; | 1764 | vc->vc_disp_ctrl = 1; |
| 1739 | vc->vc_toggle_meta = 1; | 1765 | vc->vc_toggle_meta = 1; |
| 1740 | break; | 1766 | break; |
| 1741 | case 22: | 1767 | case CSI_m_NORMAL_INTENSITY: |
| 1742 | vc->state.intensity = VCI_NORMAL; | 1768 | vc->state.intensity = VCI_NORMAL; |
| 1743 | break; | 1769 | break; |
| 1744 | case 23: | 1770 | case CSI_m_NO_ITALIC: |
| 1745 | vc->state.italic = false; | 1771 | vc->state.italic = false; |
| 1746 | break; | 1772 | break; |
| 1747 | case 24: | 1773 | case CSI_m_NO_UNDERLINE: |
| 1748 | vc->state.underline = false; | 1774 | vc->state.underline = false; |
| 1749 | break; | 1775 | break; |
| 1750 | case 25: | 1776 | case CSI_m_NO_BLINK: |
| 1751 | vc->state.blink = false; | 1777 | vc->state.blink = false; |
| 1752 | break; | 1778 | break; |
| 1753 | case 27: | 1779 | case CSI_m_NO_REVERSE: |
| 1754 | vc->state.reverse = false; | 1780 | vc->state.reverse = false; |
| 1755 | break; | 1781 | break; |
| 1756 | case 38: | 1782 | case CSI_m_FG_COLOR: |
| 1757 | i = vc_t416_color(vc, i, rgb_foreground); | 1783 | i = vc_t416_color(vc, i, rgb_foreground); |
| 1758 | break; | 1784 | break; |
| 1759 | case 48: | 1785 | case CSI_m_BG_COLOR: |
| 1760 | i = vc_t416_color(vc, i, rgb_background); | 1786 | i = vc_t416_color(vc, i, rgb_background); |
| 1761 | break; | 1787 | break; |
| 1762 | case 39: | 1788 | case CSI_m_DEFAULT_FG_COLOR: |
| 1763 | vc->state.color = (vc->vc_def_color & 0x0f) | | 1789 | vc->state.color = (vc->vc_def_color & 0x0f) | |
| 1764 | (vc->state.color & 0xf0); | 1790 | (vc->state.color & 0xf0); |
| 1765 | break; | 1791 | break; |
| 1766 | case 49: | 1792 | case CSI_m_DEFAULT_BG_COLOR: |
| 1767 | vc->state.color = (vc->vc_def_color & 0xf0) | | 1793 | vc->state.color = (vc->vc_def_color & 0xf0) | |
| 1768 | (vc->state.color & 0x0f); | 1794 | (vc->state.color & 0x0f); |
| 1769 | break; | 1795 | break; |
| 1770 | default: | 1796 | case CSI_m_BRIGHT_FG_COLOR_BEG ... CSI_m_BRIGHT_FG_COLOR_END: |
| 1771 | if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) { | 1797 | vc->state.intensity = VCI_BOLD; |
| 1772 | if (vc->vc_par[i] < 100) | 1798 | vc->vc_par[i] -= CSI_m_BRIGHT_FG_COLOR_OFF; |
| 1773 | vc->state.intensity = VCI_BOLD; | 1799 | fallthrough; |
| 1774 | vc->vc_par[i] -= 60; | 1800 | case CSI_m_FG_COLOR_BEG ... CSI_m_FG_COLOR_END: |
| 1775 | } | 1801 | vc->vc_par[i] -= CSI_m_FG_COLOR_BEG; |
| 1776 | if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37) | 1802 | vc->state.color = color_table[vc->vc_par[i]] | |
| 1777 | vc->state.color = color_table[vc->vc_par[i] - 30] | 1803 | (vc->state.color & 0xf0); |
| 1778 | | (vc->state.color & 0xf0); | 1804 | break; |
| 1779 | else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47) | 1805 | case CSI_m_BRIGHT_BG_COLOR_BEG ... CSI_m_BRIGHT_BG_COLOR_END: |
| 1780 | vc->state.color = (color_table[vc->vc_par[i] - 40] << 4) | 1806 | vc->vc_par[i] -= CSI_m_BRIGHT_BG_COLOR_OFF; |
| 1781 | | (vc->state.color & 0x0f); | 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 | break; | 1812 | break; |
| 1783 | } | 1813 | } |
| 1784 | update_attr(vc); | 1814 | update_attr(vc); |
| @@ -1832,133 +1862,175 @@ int mouse_reporting(void) · 47 unmodified lines | |||
| 1832 | return vc_cons[fg_console].d->vc_report_mouse; | 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 | /* console_lock is held */ | 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 | for (i = 0; i <= vc->vc_npar; i++) | 1882 | for (i = 0; i <= vc->vc_npar; i++) |
| 1841 | if (vc->vc_priv == EPdec) { | 1883 | switch (vc->vc_par[i]) { |
| 1842 | switch(vc->vc_par[i]) { /* DEC private modes set/reset */ | 1884 | case CSI_DEC_hl_CURSOR_KEYS: |
| 1843 | case 1: /* Cursor keys send ^[Ox/^[[x */ | 1885 | if (on_off) |
| 1844 | if (on_off) | 1886 | set_kbd(vc, decckm); |
| 1845 | set_kbd(vc, decckm); | 1887 | else |
| 1846 | else | 1888 | clr_kbd(vc, decckm); |
| 1847 | clr_kbd(vc, decckm); | 1889 | break; |
| 1848 | break; | 1890 | case CSI_DEC_hl_132_COLUMNS: /* unimplemented */ |
| 1849 | case 3: /* 80/132 mode switch unimplemented */ | ||
| 1850 | #if 0 | 1891 | #if 0 |
| 1851 | vc_resize(deccolm ? 132 : 80, vc->vc_rows); | 1892 | vc_resize(deccolm ? 132 : 80, vc->vc_rows); |
| 1852 | /* this alone does not suffice; some user mode | 1893 | /* this alone does not suffice; some user mode |
| 1853 | utility has to change the hardware regs */ | 1894 | utility has to change the hardware regs */ |
| 1854 | #endif | 1895 | #endif |
| 1855 | break; | 1896 | break; |
| 1856 | case 5: /* Inverted screen on/off */ | 1897 | case CSI_DEC_hl_REVERSE_VIDEO: |
| 1857 | if (vc->vc_decscnm != on_off) { | 1898 | if (vc->vc_decscnm != on_off) { |
| 1858 | vc->vc_decscnm = on_off; | 1899 | vc->vc_decscnm = on_off; |
| 1859 | invert_screen(vc, 0, | 1900 | invert_screen(vc, 0, vc->vc_screenbuf_size, |
| 1860 | vc->vc_screenbuf_size, | 1901 | false); |
| 1861 | false); | 1902 | update_attr(vc); |
| 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; | ||
| 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 | /* console_lock is held */ | 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 | switch (vc->vc_par[0]) { | 1981 | switch (vc->vc_par[0]) { |
| 1910 | case 1: /* set color for underline mode */ | 1982 | case CSI_RSB_COLOR_FOR_UNDERLINE: |
| 1911 | if (vc->vc_can_do_color && vc->vc_par[1] < 16) { | 1983 | if (vc->vc_can_do_color && vc->vc_par[1] < 16) { |
| 1912 | vc->vc_ulcolor = color_table[vc->vc_par[1]]; | 1984 | vc->vc_ulcolor = color_table[vc->vc_par[1]]; |
| 1913 | if (vc->state.underline) | 1985 | if (vc->state.underline) |
| 1914 | update_attr(vc); | 1986 | update_attr(vc); |
| 1915 | } | 1987 | } |
| 1916 | break; | 1988 | break; |
| 1917 | case 2: /* set color for half intensity mode */ | 1989 | case CSI_RSB_COLOR_FOR_HALF_BRIGHT: |
| 1918 | if (vc->vc_can_do_color && vc->vc_par[1] < 16) { | 1990 | if (vc->vc_can_do_color && vc->vc_par[1] < 16) { |
| 1919 | vc->vc_halfcolor = color_table[vc->vc_par[1]]; | 1991 | vc->vc_halfcolor = color_table[vc->vc_par[1]]; |
| 1920 | if (vc->state.intensity == VCI_HALF_BRIGHT) | 1992 | if (vc->state.intensity == VCI_HALF_BRIGHT) |
| 1921 | update_attr(vc); | 1993 | update_attr(vc); |
| 1922 | } | 1994 | } |
| 1923 | break; | 1995 | break; |
| 1924 | case 8: /* store colors as defaults */ | 1996 | case CSI_RSB_MAKE_CUR_COLOR_DEFAULT: |
| 1925 | vc->vc_def_color = vc->vc_attr; | 1997 | vc->vc_def_color = vc->vc_attr; |
| 1926 | if (vc->vc_hi_font_mask == 0x100) | 1998 | if (vc->vc_hi_font_mask == 0x100) |
| 1927 | vc->vc_def_color >>= 1; | 1999 | vc->vc_def_color >>= 1; |
| 1928 | default_attr(vc); | 2000 | default_attr(vc); |
| 1929 | update_attr(vc); | 2001 | update_attr(vc); |
| 1930 | break; | 2002 | break; |
| 1931 | case 9: /* set blanking interval */ | 2003 | case CSI_RSB_BLANKING_INTERVAL: |
| 1932 | blankinterval = min(vc->vc_par[1], 60U) * 60; | 2004 | blankinterval = min(vc->vc_par[1], 60U) * 60; |
| 1933 | poke_blanked_console(); | 2005 | poke_blanked_console(); |
| 1934 | break; | 2006 | break; |
| 1935 | case 10: /* set bell frequency in Hz */ | 2007 | case CSI_RSB_BELL_FREQUENCY: |
| 1936 | if (vc->vc_npar >= 1) | 2008 | if (vc->vc_npar >= 1) |
| 1937 | vc->vc_bell_pitch = vc->vc_par[1]; | 2009 | vc->vc_bell_pitch = vc->vc_par[1]; |
| 1938 | else | 2010 | else |
| 1939 | vc->vc_bell_pitch = DEFAULT_BELL_PITCH; | 2011 | vc->vc_bell_pitch = DEFAULT_BELL_PITCH; |
| 1940 | break; | 2012 | break; |
| 1941 | case 11: /* set bell duration in msec */ | 2013 | case CSI_RSB_BELL_DURATION: |
| 1942 | if (vc->vc_npar >= 1) | 2014 | if (vc->vc_npar >= 1) |
| 1943 | vc->vc_bell_duration = (vc->vc_par[1] < 2000) ? | 2015 | vc->vc_bell_duration = (vc->vc_par[1] < 2000) ? |
| 1944 | msecs_to_jiffies(vc->vc_par[1]) : 0; | 2016 | msecs_to_jiffies(vc->vc_par[1]) : 0; |
| 1945 | else | 2017 | else |
| 1946 | vc->vc_bell_duration = DEFAULT_BELL_DURATION; | 2018 | vc->vc_bell_duration = DEFAULT_BELL_DURATION; |
| 1947 | break; | 2019 | break; |
| 1948 | case 12: /* bring specified console to the front */ | 2020 | case CSI_RSB_BRING_CONSOLE_TO_FRONT: |
| 1949 | if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1)) | 2021 | if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1)) |
| 1950 | set_console(vc->vc_par[1] - 1); | 2022 | set_console(vc->vc_par[1] - 1); |
| 1951 | break; | 2023 | break; |
| 1952 | case 13: /* unblank the screen */ | 2024 | case CSI_RSB_UNBLANK: |
| 1953 | poke_blanked_console(); | 2025 | poke_blanked_console(); |
| 1954 | break; | 2026 | break; |
| 1955 | case 14: /* set vesa powerdown interval */ | 2027 | case CSI_RSB_VESA_OFF_INTERVAL: |
| 1956 | vesa_off_interval = min(vc->vc_par[1], 60U) * 60 * HZ; | 2028 | vesa_off_interval = min(vc->vc_par[1], 60U) * 60 * HZ; |
| 1957 | break; | 2029 | break; |
| 1958 | case 15: /* activate the previous console */ | 2030 | case CSI_RSB_BRING_PREV_CONSOLE_TO_FRONT: |
| 1959 | set_console(last_console); | 2031 | set_console(last_console); |
| 1960 | break; | 2032 | break; |
| 1961 | case 16: /* set cursor blink duration in msec */ | 2033 | case CSI_RSB_CURSOR_BLINK_INTERVAL: |
| 1962 | if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 && | 2034 | if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 && |
| 1963 | vc->vc_par[1] <= USHRT_MAX) | 2035 | vc->vc_par[1] <= USHRT_MAX) |
| 1964 | vc->vc_cur_blink_ms = vc->vc_par[1]; | 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 | /* console_lock is held */ | 2043 | /* console_lock is held */ |
| 1972 | static void csi_at(struct vc_data *vc, unsigned int nr) | 2044 | static void csi_at(struct vc_data *vc, unsigned int nr) |
| 1973 | { | 2045 | { |
| 1974 | if (nr > vc->vc_cols - vc->state.x) | 2046 | nr = clamp(nr, 1, vc->vc_cols - vc->state.x); |
| 1975 | nr = vc->vc_cols - vc->state.x; | ||
| 1976 | else if (!nr) | ||
| 1977 | nr = 1; | ||
| 1978 | insert_char(vc, nr); | 2047 | insert_char(vc, nr); |
| 1979 | } | 2048 | } |
| 1980 | 2049 | ||
| 1981 | /* console_lock is held */ | 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) | 2053 | unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_rows - vc->state.y); |
| 1985 | nr = vc->vc_rows - vc->state.y; | 2054 | |
| 1986 | else if (!nr) | ||
| 1987 | nr = 1; | ||
| 1988 | con_scroll(vc, vc->state.y, vc->vc_bottom, SM_DOWN, nr); | 2055 | con_scroll(vc, vc->state.y, vc->vc_bottom, SM_DOWN, nr); |
| 1989 | vc->vc_need_wrap = 0; | 2056 | vc->vc_need_wrap = 0; |
| 1990 | } | 2057 | } |
| 1991 | 2058 | ||
| 1992 | /* console_lock is held */ | 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) | 2062 | unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_cols - vc->state.x); |
| 1996 | nr = vc->vc_cols - vc->state.x; | 2063 | |
| 1997 | else if (!nr) | ||
| 1998 | nr = 1; | ||
| 1999 | delete_char(vc, nr); | 2064 | delete_char(vc, nr); |
| 2000 | } | 2065 | } |
| 2001 | 2066 | ||
| 2002 | /* console_lock is held */ | 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) | 2070 | unsigned int nr = clamp(vc->vc_par[0], 1, vc->vc_rows - vc->state.y); |
| 2006 | nr = vc->vc_rows - vc->state.y; | 2071 | |
| 2007 | else if (!nr) | ||
| 2008 | nr=1; | ||
| 2009 | con_scroll(vc, vc->state.y, vc->vc_bottom, SM_UP, nr); | 2072 | con_scroll(vc, vc->state.y, vc->vc_bottom, SM_UP, nr); |
| 2010 | vc->vc_need_wrap = 0; | 2073 | vc->vc_need_wrap = 0; |
| 2011 | } | 2074 | } |
| @@ -2028,9 +2091,48 @@ static void restore_cur(struct vc_data *vc) · 16 unmodified lines | |||
| 2028 | vc->vc_need_wrap = 0; | 2091 | vc->vc_need_wrap = 0; |
| 2029 | } | 2092 | } |
| 2030 | 2093 | ||
| 2031 | enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, | 2094 | /** |
| 2032 | EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd, | 2095 | * enum vc_ctl_state - control characters state of a vt |
| 2033 | ESpalette, ESosc, ESapc, ESpm, ESdcs }; | 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 | /* console_lock is held (except via vc_init()) */ | 2137 | /* console_lock is held (except via vc_init()) */ |
| 2036 | static void reset_terminal(struct vc_data *vc, int do_clear) | 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 | gotoxy(vc, 0, 0); | 2180 | gotoxy(vc, 0, 0); |
| 2079 | save_cur(vc); | 2181 | save_cur(vc); |
| 2080 | if (do_clear) | 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 | unsigned char *charset = &vc->state.Gx_charset[which]; | 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 | vc->vc_translate = set_translate(*charset, vc); | 2206 | vc->vc_translate = set_translate(*charset, vc); |
| 2105 | } | 2207 | } |
| 2106 | 2208 | ||
| 2107 | /* is this state an ANSI control string? */ | 2209 | static bool ansi_control_string(enum vc_ctl_state state) |
| 2108 | static bool ansi_control_string(unsigned int state) | ||
| 2109 | { | 2210 | { |
| 2110 | if (state == ESosc || state == ESapc || state == ESpm || state == ESdcs) | 2211 | return state >= ESANSI_first && state <= ESANSI_last; |
| 2111 | return true; | ||
| 2112 | return false; | ||
| 2113 | } | 2212 | } |
| 2114 | 2213 | ||
| 2115 | /* console_lock is held */ | 2214 | enum { |
| 2116 | static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | 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 | switch (c) { | 2244 | switch (c) { |
| 2125 | case 0: | 2245 | case ASCII_NULL: |
| 2126 | return; | 2246 | return true; |
| 2127 | case 7: | 2247 | case ASCII_BELL: |
| 2128 | if (ansi_control_string(vc->vc_state)) | 2248 | if (ansi_control_string(vc->vc_state)) |
| 2129 | vc->vc_state = ESnormal; | 2249 | vc->vc_state = ESnormal; |
| 2130 | else if (vc->vc_bell_duration) | 2250 | else if (vc->vc_bell_duration) |
| 2131 | kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration); | 2251 | kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration); |
| 2132 | return; | 2252 | return true; |
| 2133 | case 8: | 2253 | case ASCII_BACKSPACE: |
| 2134 | bs(vc); | 2254 | bs(vc); |
| 2135 | return; | 2255 | return true; |
| 2136 | case 9: | 2256 | case ASCII_HTAB: |
| 2137 | vc->vc_pos -= (vc->state.x << 1); | 2257 | vc->vc_pos -= (vc->state.x << 1); |
| 2138 | 2258 | ||
| 2139 | vc->state.x = find_next_bit(vc->vc_tab_stop, | 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 | vc->vc_pos += (vc->state.x << 1); | 2265 | vc->vc_pos += (vc->state.x << 1); |
| 2146 | notify_write(vc, '\t'); | 2266 | notify_write(vc, '\t'); |
| 2147 | return; | 2267 | return true; |
| 2148 | case 10: case 11: case 12: | 2268 | case ASCII_LINEFEED: |
| 2269 | case ASCII_VTAB: | ||
| 2270 | case ASCII_FORMFEED: | ||
| 2149 | lf(vc); | 2271 | lf(vc); |
| 2150 | if (!is_kbd(vc, lnm)) | 2272 | if (!is_kbd(vc, lnm)) |
| 2151 | return; | 2273 | return true; |
| 2152 | fallthrough; | 2274 | fallthrough; |
| 2153 | case 13: | 2275 | case ASCII_CAR_RET: |
| 2154 | cr(vc); | 2276 | cr(vc); |
| 2155 | return; | 2277 | return true; |
| 2156 | case 14: | 2278 | case ASCII_SHIFTOUT: |
| 2157 | vc->state.charset = 1; | 2279 | vc->state.charset = 1; |
| 2158 | vc->vc_translate = set_translate(vc->state.Gx_charset[1], vc); | 2280 | vc->vc_translate = set_translate(vc->state.Gx_charset[1], vc); |
| 2159 | vc->vc_disp_ctrl = 1; | 2281 | vc->vc_disp_ctrl = 1; |
| 2160 | return; | 2282 | return true; |
| 2161 | case 15: | 2283 | case ASCII_SHIFTIN: |
| 2162 | vc->state.charset = 0; | 2284 | vc->state.charset = 0; |
| 2163 | vc->vc_translate = set_translate(vc->state.Gx_charset[0], vc); | 2285 | vc->vc_translate = set_translate(vc->state.Gx_charset[0], vc); |
| 2164 | vc->vc_disp_ctrl = 0; | 2286 | vc->vc_disp_ctrl = 0; |
| 2165 | return; | 2287 | return true; |
| 2166 | case 24: case 26: | 2288 | case ASCII_CANCEL: |
| 2289 | case ASCII_SUBSTITUTE: | ||
| 2167 | vc->vc_state = ESnormal; | 2290 | vc->vc_state = ESnormal; |
| 2168 | return; | 2291 | return true; |
| 2169 | case 27: | 2292 | case ASCII_ESCAPE: |
| 2170 | vc->vc_state = ESesc; | 2293 | vc->vc_state = ESesc; |
| 2171 | return; | 2294 | return true; |
| 2172 | case 127: | 2295 | case ASCII_DEL: |
| 2173 | del(vc); | 2296 | del(vc); |
| 2174 | return; | 2297 | return true; |
| 2175 | case 128+27: | 2298 | case ASCII_EXT_CSI: |
| 2176 | vc->vc_state = ESsquare; | 2299 | vc->vc_state = ESsquare; |
| 2177 | return; | 2300 | return true; |
| 2178 | } | 2301 | } |
| 2179 | switch(vc->vc_state) { | 2302 | |
| 2180 | case ESesc: | 2303 | return false; |
| 2181 | vc->vc_state = ESnormal; | 2304 | } |
| 2182 | switch (c) { | 2305 | |
| 2183 | case '[': | 2306 | /* |
| 2184 | vc->vc_state = ESsquare; | 2307 | * Handle a character (@c) following an ESC (when @vc is in the ESesc state). |
| 2185 | return; | 2308 | * E.g. previous ESC with @c == '[' here yields the ESsquare state (that is: |
| 2186 | case ']': | 2309 | * CSI). |
| 2187 | vc->vc_state = ESnonstd; | 2310 | */ |
| 2188 | return; | 2311 | static void handle_esc(struct tty_struct *tty, struct vc_data *vc, u8 c) |
| 2189 | case '_': | 2312 | { |
| 2190 | vc->vc_state = ESapc; | 2313 | vc->vc_state = ESnormal; |
| 2191 | return; | 2314 | switch (c) { |
| 2192 | case '^': | 2315 | case '[': |
| 2193 | vc->vc_state = ESpm; | 2316 | vc->vc_state = ESsquare; |
| 2194 | return; | 2317 | break; |
| 2195 | case '%': | 2318 | case ']': |
| 2196 | vc->vc_state = ESpercent; | 2319 | vc->vc_state = ESnonstd; |
| 2197 | return; | 2320 | break; |
| 2198 | case 'E': | 2321 | case '_': |
| 2199 | cr(vc); | 2322 | vc->vc_state = ESapc; |
| 2200 | lf(vc); | 2323 | break; |
| 2201 | return; | 2324 | case '^': |
| 2202 | case 'M': | 2325 | vc->vc_state = ESpm; |
| 2203 | ri(vc); | 2326 | break; |
| 2204 | return; | 2327 | case '%': |
| 2205 | case 'D': | 2328 | vc->vc_state = ESpercent; |
| 2206 | lf(vc); | 2329 | break; |
| 2207 | return; | 2330 | case 'E': |
| 2208 | case 'H': | 2331 | cr(vc); |
| 2209 | if (vc->state.x < VC_TABSTOPS_COUNT) | 2332 | lf(vc); |
| 2210 | set_bit(vc->state.x, vc->vc_tab_stop); | 2333 | break; |
| 2211 | return; | 2334 | case 'M': |
| 2212 | case 'P': | 2335 | ri(vc); |
| 2213 | vc->vc_state = ESdcs; | 2336 | break; |
| 2214 | return; | 2337 | case 'D': |
| 2215 | case 'Z': | 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 | respond_ID(tty); | 2490 | respond_ID(tty); |
| 2217 | return; | 2491 | break; |
| 2218 | case '7': | 2492 | case 'g': |
| 2219 | save_cur(vc); | 2493 | if (!vc->vc_par[0] && vc->state.x < VC_TABSTOPS_COUNT) |
| 2220 | return; | 2494 | set_bit(vc->state.x, vc->vc_tab_stop); |
| 2221 | case '8': | 2495 | else if (vc->vc_par[0] == 3) |
| 2222 | restore_cur(vc); | 2496 | bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT); |
| 2223 | return; | 2497 | break; |
| 2224 | case '(': | 2498 | case 'h': |
| 2225 | vc->vc_state = ESsetG0; | 2499 | csi_hl(vc, true); |
| 2226 | return; | 2500 | break; |
| 2227 | case ')': | 2501 | case 'l': |
| 2228 | vc->vc_state = ESsetG1; | 2502 | csi_hl(vc, false); |
| 2229 | return; | 2503 | break; |
| 2230 | case '#': | 2504 | case 'm': |
| 2231 | vc->vc_state = EShash; | 2505 | csi_m(vc); |
| 2232 | return; | 2506 | break; |
| 2233 | case 'c': | 2507 | case 'n': |
| 2234 | reset_terminal(vc, 1); | 2508 | if (vc->vc_par[0] == 5) |
| 2235 | return; | 2509 | status_report(tty); |
| 2236 | case '>': /* Numeric keypad */ | 2510 | else if (vc->vc_par[0] == 6) |
| 2237 | clr_kbd(vc, kbdapplic); | 2511 | cursor_report(vc, tty); |
| 2238 | return; | 2512 | break; |
| 2239 | case '=': /* Appl. keypad */ | 2513 | case 'q': /* DECLL - but only 3 leds */ |
| 2240 | set_kbd(vc, kbdapplic); | 2514 | /* map 0,1,2,3 to 0,1,2,4 */ |
| 2241 | return; | 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 | return; | 2574 | return; |
| 2244 | case ESnonstd: | 2575 | case ESnonstd: /* ESC ] aka OSC */ |
| 2245 | if (c=='P') { /* palette escape sequence */ | 2576 | switch (c) { |
| 2246 | for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++) | 2577 | case 'P': /* palette escape sequence */ |
| 2247 | vc->vc_par[vc->vc_npar] = 0; | 2578 | vc_reset_params(vc); |
| 2248 | vc->vc_npar = 0; | ||
| 2249 | vc->vc_state = ESpalette; | 2579 | vc->vc_state = ESpalette; |
| 2250 | return; | 2580 | return; |
| 2251 | } else if (c=='R') { /* reset palette */ | 2581 | case 'R': /* reset palette */ |
| 2252 | reset_palette(vc); | 2582 | reset_palette(vc); |
| 2253 | vc->vc_state = ESnormal; | 2583 | break; |
| 2254 | } else if (c>='0' && c<='9') | 2584 | case '0' ... '9': |
| 2255 | vc->vc_state = ESosc; | 2585 | vc->vc_state = ESosc; |
| 2256 | else | 2586 | return; |
| 2257 | vc->vc_state = ESnormal; | 2587 | } |
| 2588 | vc->vc_state = ESnormal; | ||
| 2258 | return; | 2589 | return; |
| 2259 | case ESpalette: | 2590 | case ESpalette: /* ESC ] P aka OSC P */ |
| 2260 | if (isxdigit(c)) { | 2591 | if (isxdigit(c)) { |
| 2261 | vc->vc_par[vc->vc_npar++] = hex_to_bin(c); | 2592 | vc->vc_par[vc->vc_npar++] = hex_to_bin(c); |
| 2262 | if (vc->vc_npar == 7) { | 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 | } else | 2604 | } else |
| 2274 | vc->vc_state = ESnormal; | 2605 | vc->vc_state = ESnormal; |
| 2275 | return; | 2606 | return; |
| 2276 | case ESsquare: | 2607 | case ESsquare: /* ESC [ aka CSI, parameters or modifiers expected */ |
| 2277 | for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++) | 2608 | vc_reset_params(vc); |
| 2278 | vc->vc_par[vc->vc_npar] = 0; | 2609 | |
| 2279 | vc->vc_npar = 0; | ||
| 2280 | vc->vc_state = ESgetpars; | 2610 | vc->vc_state = ESgetpars; |
| 2281 | if (c == '[') { /* Function key */ | ||
| 2282 | vc->vc_state=ESfunckey; | ||
| 2283 | return; | ||
| 2284 | } | ||
| 2285 | switch (c) { | 2611 | switch (c) { |
| 2612 | case '[': /* Function key */ | ||
| 2613 | vc->vc_state = ESfunckey; | ||
| 2614 | return; | ||
| 2286 | case '?': | 2615 | case '?': |
| 2287 | vc->vc_priv = EPdec; | 2616 | vc->vc_priv = EPdec; |
| 2288 | return; | 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 | vc->vc_priv = EPecma; | 2628 | vc->vc_priv = EPecma; |
| 2300 | fallthrough; | 2629 | fallthrough; |
| 2301 | case ESgetpars: | 2630 | case ESgetpars: /* ESC [ aka CSI, parameters expected */ |
| 2302 | if (c == ';' && vc->vc_npar < NPAR - 1) { | 2631 | switch (c) { |
| 2303 | vc->vc_npar++; | 2632 | case ';': |
| 2304 | return; | 2633 | if (vc->vc_npar < NPAR - 1) { |
| 2305 | } else if (c>='0' && c<='9') { | 2634 | vc->vc_npar++; |
| 2635 | return; | ||
| 2636 | } | ||
| 2637 | break; | ||
| 2638 | case '0' ... '9': | ||
| 2306 | vc->vc_par[vc->vc_npar] *= 10; | 2639 | vc->vc_par[vc->vc_npar] *= 10; |
| 2307 | vc->vc_par[vc->vc_npar] += c - '0'; | 2640 | vc->vc_par[vc->vc_npar] += c - '0'; |
| 2308 | return; | 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 | vc->vc_state = EScsiignore; | 2644 | vc->vc_state = EScsiignore; |
| 2312 | return; | 2645 | return; |
| 2313 | } | 2646 | } |
| 2647 | |||
| 2648 | /* parameters done, handle the control char @c */ | ||
| 2649 | |||
| 2314 | vc->vc_state = ESnormal; | 2650 | vc->vc_state = ESnormal; |
| 2315 | switch(c) { | 2651 | |
| 2316 | case 'h': | 2652 | switch (vc->vc_priv) { |
| 2317 | if (vc->vc_priv <= EPdec) | 2653 | case EPdec: |
| 2318 | set_mode(vc, 1); | 2654 | csi_DEC(tty, vc, c); |
| 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]); | ||
| 2462 | return; | 2655 | return; |
| 2463 | case '@': | 2656 | case EPecma: |
| 2464 | csi_at(vc, vc->vc_par[0]); | 2657 | csi_ECMA(tty, vc, c); |
| 2465 | return; | 2658 | return; |
| 2466 | case ']': /* setterm functions */ | 2659 | default: |
| 2467 | setterm_command(vc); | ||
| 2468 | return; | 2660 | return; |
| 2469 | } | 2661 | } |
| 2470 | return; | ||
| 2471 | case EScsiignore: | 2662 | case EScsiignore: |
| 2472 | if (c >= 20 && c <= 0x3f) | 2663 | if (c >= ASCII_CSI_IGNORE_FIRST && c <= ASCII_CSI_IGNORE_LAST) |
| 2473 | return; | 2664 | return; |
| 2474 | vc->vc_state = ESnormal; | 2665 | vc->vc_state = ESnormal; |
| 2475 | return; | 2666 | return; |
| 2476 | case ESpercent: | 2667 | case ESpercent: /* ESC % */ |
| 2477 | vc->vc_state = ESnormal; | 2668 | vc->vc_state = ESnormal; |
| 2478 | switch (c) { | 2669 | switch (c) { |
| 2479 | case '@': /* defined in ISO 2022 */ | 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 | return; | 2676 | return; |
| 2486 | } | 2677 | } |
| 2487 | return; | 2678 | return; |
| 2488 | case ESfunckey: | 2679 | case ESfunckey: /* ESC [ [ aka CSI [ */ |
| 2489 | vc->vc_state = ESnormal; | 2680 | vc->vc_state = ESnormal; |
| 2490 | return; | 2681 | return; |
| 2491 | case EShash: | 2682 | case EShash: /* ESC # */ |
| 2492 | vc->vc_state = ESnormal; | 2683 | vc->vc_state = ESnormal; |
| 2493 | if (c == '8') { | 2684 | if (c == '8') { |
| 2494 | /* DEC screen alignment test. kludge :-) */ | 2685 | /* DEC screen alignment test. kludge :-) */ |
| 2495 | vc->vc_video_erase_char = | 2686 | vc->vc_video_erase_char = |
| 2496 | (vc->vc_video_erase_char & 0xff00) | 'E'; | 2687 | (vc->vc_video_erase_char & 0xff00) | 'E'; |
| 2497 | csi_J(vc, 2); | 2688 | csi_J(vc, CSI_J_VISIBLE); |
| 2498 | vc->vc_video_erase_char = | 2689 | vc->vc_video_erase_char = |
| 2499 | (vc->vc_video_erase_char & 0xff00) | ' '; | 2690 | (vc->vc_video_erase_char & 0xff00) | ' '; |
| 2500 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); | 2691 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); |
| 2501 | } | 2692 | } |
| 2502 | return; | 2693 | return; |
| 2503 | case ESsetG0: | 2694 | case ESsetG0: /* ESC ( */ |
| 2504 | vc_setGx(vc, 0, c); | 2695 | vc_setGx(vc, 0, c); |
| 2505 | vc->vc_state = ESnormal; | 2696 | vc->vc_state = ESnormal; |
| 2506 | return; | 2697 | return; |
| 2507 | case ESsetG1: | 2698 | case ESsetG1: /* ESC ) */ |
| 2508 | vc_setGx(vc, 1, c); | 2699 | vc_setGx(vc, 1, c); |
| 2509 | vc->vc_state = ESnormal; | 2700 | vc->vc_state = ESnormal; |
| 2510 | return; | 2701 | return; |
| 2511 | case ESapc: | 2702 | case ESapc: /* ESC _ */ |
| 2512 | return; | 2703 | return; |
| 2513 | case ESosc: | 2704 | case ESosc: /* ESC ] [0-9] aka OSC [0-9] */ |
| 2514 | return; | 2705 | return; |
| 2515 | case ESpm: | 2706 | case ESpm: /* ESC ^ */ |
| 2516 | return; | 2707 | return; |
| 2517 | case ESdcs: | 2708 | case ESdcs: /* ESC P */ |
| 2518 | return; | 2709 | return; |
| 2519 | default: | 2710 | default: |
| 2520 | vc->vc_state = ESnormal; | 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 | 2782 | * vc_sanitize_unicode - Replace invalid Unicode code points with ``U+FFFD`` |
| 2592 | * @c: the received character, or U+FFFD for invalid sequences. | 2783 | * @c: the received code point |
| 2593 | */ | 2784 | */ |
| 2594 | static inline int vc_sanitize_unicode(const int c) | 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 | return 0xfffd; | 2788 | return 0xfffd; |
| 2598 | 2789 | ||
| 2599 | return c; | 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 | * @vc: virtual console | 2795 | * @vc: virtual console |
| 2605 | * @c: character to translate | 2796 | * @c: UTF-8 byte to translate |
| 2606 | * @rescan: we return true if we need more (continuation) data | 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. | 2804 | * Return: |
| 2609 | * @vc_utf_count is the number of continuation bytes still expected to arrive. | 2805 | * * %-1 - Input OK so far, @c consumed, further bytes expected. |
| 2610 | * @vc_npar is the number of continuation bytes arrived so far. | 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 | static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan) | 2812 | static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan) |
| 2613 | { | 2813 | { |
| 2614 | static const u32 utf8_length_changes[] = { | 2814 | static const u32 utf8_length_changes[] = {0x7f, 0x7ff, 0xffff, 0x10ffff}; |
| 2615 | 0x0000007f, 0x000007ff, 0x0000ffff, | ||
| 2616 | 0x001fffff, 0x03ffffff, 0x7fffffff | ||
| 2617 | }; | ||
| 2618 | 2815 | ||
| 2619 | /* Continuation byte received */ | 2816 | /* Continuation byte received */ |
| 2620 | if ((c & 0xc0) == 0x80) { | 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 | } else if ((c & 0xf8) == 0xf0) { | 2857 | } else if ((c & 0xf8) == 0xf0) { |
| 2661 | vc->vc_utf_count = 3; | 2858 | vc->vc_utf_count = 3; |
| 2662 | vc->vc_utf_char = (c & 0x07); | 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 | } else { | 2860 | } else { |
| 2670 | /* 254 and 255 are invalid */ | ||
| 2671 | return 0xfffd; | 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 | * as cursor movement) and should not be displayed as a glyph unless | 2901 | * as cursor movement) and should not be displayed as a glyph unless |
| 2712 | * the disp_ctrl mode is explicitly enabled. | 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 | /* Cannot be overridden by disp_ctrl */ | 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 | if (vc->vc_state != ESnormal) | 2912 | if (vc->vc_state != ESnormal) |
| 2719 | return true; | 2913 | return true; |
| @@ -2730,17 +2924,17 @@ static bool vc_is_control(struct vc_data *vc, int tc, int c) · 10 unmodified lines | |||
| 2730 | * useless without them; to display an arbitrary font position use the | 2924 | * useless without them; to display an arbitrary font position use the |
| 2731 | * direct-to-font zone in UTF-8 mode. | 2925 | * direct-to-font zone in UTF-8 mode. |
| 2732 | */ | 2926 | */ |
| 2733 | if (c < 32) { | 2927 | if (c < BITS_PER_TYPE(CTRL_ALWAYS)) { |
| 2734 | if (vc->vc_disp_ctrl) | 2928 | if (vc->vc_disp_ctrl) |
| 2735 | return CTRL_ALWAYS & BIT(c); | 2929 | return CTRL_ALWAYS & BIT(c); |
| 2736 | else | 2930 | else |
| 2737 | return vc->vc_utf || (CTRL_ACTION & BIT(c)); | 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 | return true; | 2935 | return true; |
| 2742 | 2936 | ||
| 2743 | if (c == 128 + 27) | 2937 | if (c == ASCII_EXT_CSI) |
| 2744 | return true; | 2938 | return true; |
| 2745 | 2939 | ||
| 2746 | return false; | 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 | int c, tc, n = 0; | 3047 | int c, tc, n = 0; |
| 2854 | unsigned int currcons; | 3048 | unsigned int currcons; |
| 2855 | struct vc_data *vc; | 3049 | struct vc_data *vc = tty->driver_data; |
| 2856 | struct vt_notifier_param param; | 3050 | struct vt_notifier_param param; |
| 2857 | bool rescan; | 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 | return count; | 3054 | return count; |
| 2861 | 3055 | ||
| 2862 | console_lock(); | 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 | currcons = vc->vc_num; | 3057 | currcons = vc->vc_num; |
| 2871 | if (!vc_cons_allocated(currcons)) { | 3058 | if (!vc_cons_allocated(currcons)) { |
| 2872 | /* could this happen? */ | 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 | param.vc = vc; | 3070 | param.vc = vc; |
| 2884 | 3071 | ||
| 2885 | while (!tty->flow.stopped && count) { | 3072 | while (!tty->flow.stopped && count) { |
| 2886 | int orig = *buf; | 3073 | u8 orig = *buf; |
| 2887 | buf++; | 3074 | buf++; |
| 2888 | n++; | 3075 | n++; |
| 2889 | count--; | 3076 | count--; |
| @@ -2992,16 +3179,16 @@ struct tty_driver *console_driver; · 102 unmodified lines | |||
| 2992 | #ifdef CONFIG_VT_CONSOLE | 3179 | #ifdef CONFIG_VT_CONSOLE |
| 2993 | 3180 | ||
| 2994 | /** | 3181 | /** |
| 2995 | * vt_kmsg_redirect() - Sets/gets the kernel message console | 3182 | * vt_kmsg_redirect() - sets/gets the kernel message console |
| 2996 | * @new: The new virtual terminal number or -1 if the console should stay | 3183 | * @new: the new virtual terminal number or -1 if the console should stay |
| 2997 | * unchanged | 3184 | * unchanged |
| 2998 | * | 3185 | * |
| 2999 | * By default, the kernel messages are always printed on the current virtual | 3186 | * By default, the kernel messages are always printed on the current virtual |
| 3000 | * console. However, the user may modify that default with the | 3187 | * console. However, the user may modify that default with the |
| 3001 | * TIOCL_SETKMSGREDIRECT ioctl call. | 3188 | * %TIOCL_SETKMSGREDIRECT ioctl call. |
| 3002 | * | 3189 | * |
| 3003 | * This function sets the kernel message console to be @new. It returns the old | 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 | * return value) means no redirection (i.e. always printed on the currently | 3192 | * return value) means no redirection (i.e. always printed on the currently |
| 3006 | * active console). | 3193 | * active console). |
| 3007 | * | 3194 | * |
| @@ -3009,8 +3196,8 @@ struct tty_driver *console_driver; · 1 unmodified line | |||
| 3009 | * value is not modified. You may use the macro vt_get_kmsg_redirect() in that | 3196 | * value is not modified. You may use the macro vt_get_kmsg_redirect() in that |
| 3010 | * case to make the code more understandable. | 3197 | * case to make the code more understandable. |
| 3011 | * | 3198 | * |
| 3012 | * When the kernel is compiled without CONFIG_VT_CONSOLE, this function ignores | 3199 | * When the kernel is compiled without %CONFIG_VT_CONSOLE, this function ignores |
| 3013 | * the parameter and always returns 0. | 3200 | * the parameter and always returns %0. |
| 3014 | */ | 3201 | */ |
| 3015 | int vt_kmsg_redirect(int new) | 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 | cnt = 0; | 3252 | cnt = 0; |
| 3066 | while (count--) { | 3253 | while (count--) { |
| 3067 | c = *b++; | 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 | if (cnt && con_is_visible(vc)) | 3257 | if (cnt && con_is_visible(vc)) |
| 3070 | vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x); | 3258 | vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x); |
| 3071 | cnt = 0; | 3259 | cnt = 0; |
| 3072 | if (c == 8) { /* backspace */ | 3260 | if (c == ASCII_BACKSPACE) { |
| 3073 | bs(vc); | 3261 | bs(vc); |
| 3074 | start = (ushort *)vc->vc_pos; | 3262 | start = (ushort *)vc->vc_pos; |
| 3075 | start_x = vc->state.x; | 3263 | start_x = vc->state.x; |
| 3076 | continue; | 3264 | continue; |
| 3077 | } | 3265 | } |
| 3078 | if (c != 13) | 3266 | if (c != ASCII_CAR_RET) |
| 3079 | lf(vc); | 3267 | lf(vc); |
| 3080 | cr(vc); | 3268 | cr(vc); |
| 3081 | start = (ushort *)vc->vc_pos; | 3269 | start = (ushort *)vc->vc_pos; |
| 3082 | start_x = vc->state.x; | 3270 | start_x = vc->state.x; |
| 3083 | if (c == 10 || c == 13) | 3271 | if (c == ASCII_LINEFEED || c == ASCII_CAR_RET) |
| 3084 | continue; | 3272 | continue; |
| 3085 | } | 3273 | } |
| 3086 | vc_uniscr_putc(vc, c); | 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 | char type, data; | 3333 | char type, data; |
| 3146 | char __user *p = (char __user *)arg; | 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 | int lines; | 3337 | int lines; |
| 3148 | int ret; | 3338 | int ret; |
| 3149 | 3339 | ||
| @@ -3157,8 +3347,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) · 7 unmodified lines | |||
| 3157 | case TIOCL_SETSEL: | 3347 | case TIOCL_SETSEL: |
| 3158 | if (!capable(CAP_SYS_ADMIN)) | 3348 | if (!capable(CAP_SYS_ADMIN)) |
| 3159 | return -EPERM; | 3349 | return -EPERM; |
| 3160 | return set_selection_user((struct tiocl_selection | 3350 | return set_selection_user(param, tty); |
| 3161 | __user *)(p+1), tty); | ||
| 3162 | case TIOCL_PASTESEL: | 3351 | case TIOCL_PASTESEL: |
| 3163 | if (!capable(CAP_SYS_ADMIN)) | 3352 | if (!capable(CAP_SYS_ADMIN)) |
| 3164 | return -EPERM; | 3353 | return -EPERM; |
| @@ -3171,10 +3360,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) · 6 unmodified lines | |||
| 3171 | case TIOCL_SELLOADLUT: | 3360 | case TIOCL_SELLOADLUT: |
| 3172 | if (!capable(CAP_SYS_ADMIN)) | 3361 | if (!capable(CAP_SYS_ADMIN)) |
| 3173 | return -EPERM; | 3362 | return -EPERM; |
| 3174 | console_lock(); | 3363 | return sel_loadlut(param_aligned32); |
| 3175 | ret = sel_loadlut(p); | ||
| 3176 | console_unlock(); | ||
| 3177 | break; | ||
| 3178 | case TIOCL_GETSHIFTSTATE: | 3364 | case TIOCL_GETSHIFTSTATE: |
| 3179 | /* | 3365 | /* |
| 3180 | * Make it possible to react to Shift+Mousebutton. Note that | 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 | console_unlock(); | 3376 | console_unlock(); |
| 3191 | return put_user(data, p); | 3377 | return put_user(data, p); |
| 3192 | case TIOCL_SETVESABLANK: | 3378 | case TIOCL_SETVESABLANK: |
| 3193 | console_lock(); | 3379 | return set_vesa_blanking(param); |
| 3194 | ret = set_vesa_blanking(p); | ||
| 3195 | console_unlock(); | ||
| 3196 | break; | ||
| 3197 | case TIOCL_GETKMSGREDIRECT: | 3380 | case TIOCL_GETKMSGREDIRECT: |
| 3198 | data = vt_get_kmsg_redirect(); | 3381 | data = vt_get_kmsg_redirect(); |
| 3199 | return put_user(data, p); | 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 | return fg_console; | 3398 | return fg_console; |
| 3216 | case TIOCL_SCROLLCONSOLE: | 3399 | case TIOCL_SCROLLCONSOLE: |
| 3217 | if (get_user(lines, (s32 __user *)(p+4))) | 3400 | if (get_user(lines, (s32 __user *)param_aligned32)) |
| 3218 | return -EFAULT; | 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 | static void con_flush_chars(struct tty_struct *tty) | 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 | if (in_interrupt()) /* from flush_to_ldisc */ | 3500 | if (in_interrupt()) /* from flush_to_ldisc */ |
| 3318 | return; | 3501 | return; |
| 3319 | 3502 | ||
| 3320 | /* if we race with con_close(), vt may be null */ | ||
| 3321 | console_lock(); | 3503 | console_lock(); |
| 3322 | vc = tty->driver_data; | 3504 | set_cursor(vc); |
| 3323 | if (vc) | ||
| 3324 | set_cursor(vc); | ||
| 3325 | console_unlock(); | 3505 | console_unlock(); |
| 3326 | } | 3506 | } |
| 3327 | 3507 | ||
| @@ -3471,7 +3651,7 @@ static int __init con_init(void) · 143 unmodified lines | |||
| 3471 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); | 3651 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); |
| 3472 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 3652 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
| 3473 | tty_port_init(&vc->port); | 3653 | tty_port_init(&vc->port); |
| 3474 | visual_init(vc, currcons, 1); | 3654 | visual_init(vc, currcons, true); |
| 3475 | /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */ | 3655 | /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */ |
| 3476 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); | 3656 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); |
| 3477 | vc_init(vc, currcons || !vc->vc_sw->con_save_screen); | 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 | set_origin(vc); | 3661 | set_origin(vc); |
| 3482 | save_screen(vc); | 3662 | save_screen(vc); |
| 3483 | gotoxy(vc, vc->state.x, vc->state.y); | 3663 | gotoxy(vc, vc->state.x, vc->state.y); |
| 3484 | csi_J(vc, 0); | 3664 | csi_J(vc, CSI_J_CURSOR_TO_END); |
| 3485 | update_screen(vc); | 3665 | update_screen(vc); |
| 3486 | pr_info("Console: %s %s %dx%d\n", | 3666 | pr_info("Console: %s %s %dx%d\n", |
| 3487 | vc->vc_can_do_color ? "colour" : "mono", | 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 | old_was_color = vc->vc_can_do_color; | 3820 | old_was_color = vc->vc_can_do_color; |
| 3641 | vc->vc_sw->con_deinit(vc); | 3821 | vc->vc_sw->con_deinit(vc); |
| 3642 | vc->vc_origin = (unsigned long)vc->vc_screenbuf; | 3822 | vc->vc_origin = (unsigned long)vc->vc_screenbuf; |
| 3643 | visual_init(vc, i, 0); | 3823 | visual_init(vc, i, false); |
| 3644 | set_origin(vc); | 3824 | set_origin(vc); |
| 3645 | update_attr(vc); | 3825 | update_attr(vc); |
| 3646 | 3826 | ||
| @@ -3930,7 +4110,7 @@ static void vtconsole_deinit_device(struct con_driver *con) · 283 unmodified lines | |||
| 3930 | * RETURNS: zero if unbound, nonzero if bound | 4110 | * RETURNS: zero if unbound, nonzero if bound |
| 3931 | * | 4111 | * |
| 3932 | * Drivers can call this and if zero, they should release | 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 | int con_is_bound(const struct consw *csw) | 4115 | int con_is_bound(const struct consw *csw) |
| 3936 | { | 4116 | { |
| @@ -3970,15 +4150,9 @@ EXPORT_SYMBOL(con_is_visible); · 33 unmodified lines | |||
| 3970 | * Called when the console is taken over by the kernel debugger, this | 4150 | * Called when the console is taken over by the kernel debugger, this |
| 3971 | * function needs to save the current console state, then put the console | 4151 | * function needs to save the current console state, then put the console |
| 3972 | * into a state suitable for the kernel debugger. | 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 | saved_fg_console = fg_console; | 4156 | saved_fg_console = fg_console; |
| 3983 | saved_last_console = last_console; | 4157 | saved_last_console = last_console; |
| 3984 | saved_want_console = want_console; | 4158 | saved_want_console = want_console; |
| @@ -3987,7 +4161,7 @@ int con_debug_enter(struct vc_data *vc) · 2 unmodified lines | |||
| 3987 | vc->vc_mode = KD_TEXT; | 4161 | vc->vc_mode = KD_TEXT; |
| 3988 | console_blanked = 0; | 4162 | console_blanked = 0; |
| 3989 | if (vc->vc_sw->con_debug_enter) | 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 | #ifdef CONFIG_KGDB_KDB | 4165 | #ifdef CONFIG_KGDB_KDB |
| 3992 | /* Set the initial LINES variable if it is not already set */ | 4166 | /* Set the initial LINES variable if it is not already set */ |
| 3993 | if (vc->vc_rows < 999) { | 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 | #endif /* CONFIG_KGDB_KDB */ | 4193 | #endif /* CONFIG_KGDB_KDB */ |
| 4020 | return ret; | ||
| 4021 | } | 4194 | } |
| 4022 | EXPORT_SYMBOL_GPL(con_debug_enter); | 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 | * Restore the console state to what it was before the kernel debugger | 4200 | * Restore the console state to what it was before the kernel debugger |
| 4028 | * was invoked. | 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 | struct vc_data *vc; | 4205 | struct vc_data *vc; |
| 4037 | int ret = 0; | ||
| 4038 | 4206 | ||
| 4039 | fg_console = saved_fg_console; | 4207 | fg_console = saved_fg_console; |
| 4040 | last_console = saved_last_console; | 4208 | last_console = saved_last_console; |
| @@ -4044,8 +4212,7 @@ int con_debug_leave(void) · 3 unmodified lines | |||
| 4044 | 4212 | ||
| 4045 | vc = vc_cons[fg_console].d; | 4213 | vc = vc_cons[fg_console].d; |
| 4046 | if (vc->vc_sw->con_debug_leave) | 4214 | if (vc->vc_sw->con_debug_leave) |
| 4047 | ret = vc->vc_sw->con_debug_leave(vc); | 4215 | vc->vc_sw->con_debug_leave(vc); |
| 4048 | return ret; | ||
| 4049 | } | 4216 | } |
| 4050 | EXPORT_SYMBOL_GPL(con_debug_leave); | 4217 | EXPORT_SYMBOL_GPL(con_debug_leave); |
| 4051 | 4218 | ||
| @@ -4275,14 +4442,17 @@ postcore_initcall(vtconsole_class_init); · 223 unmodified lines | |||
| 4275 | * Screen blanking | 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 | return -EFAULT; | 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 | return 0; | 4456 | return 0; |
| 4287 | } | 4457 | } |
| 4288 | 4458 | ||
| @@ -4307,7 +4477,7 @@ void do_blank_screen(int entering_gfx) · 18 unmodified lines | |||
| 4307 | if (entering_gfx) { | 4477 | if (entering_gfx) { |
| 4308 | hide_cursor(vc); | 4478 | hide_cursor(vc); |
| 4309 | save_screen(vc); | 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 | console_blanked = fg_console + 1; | 4481 | console_blanked = fg_console + 1; |
| 4312 | blank_state = blank_off; | 4482 | blank_state = blank_off; |
| 4313 | set_origin(vc); | 4483 | set_origin(vc); |
| @@ -4328,7 +4498,8 @@ void do_blank_screen(int entering_gfx) · 14 unmodified lines | |||
| 4328 | 4498 | ||
| 4329 | save_screen(vc); | 4499 | save_screen(vc); |
| 4330 | /* In case we need to reset origin, blanking hook returns 1 */ | 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 | console_blanked = fg_console + 1; | 4503 | console_blanked = fg_console + 1; |
| 4333 | if (i) | 4504 | if (i) |
| 4334 | set_origin(vc); | 4505 | set_origin(vc); |
| @@ -4379,7 +4550,7 @@ void do_unblank_screen(int leaving_gfx) · 44 unmodified lines | |||
| 4379 | } | 4550 | } |
| 4380 | 4551 | ||
| 4381 | console_blanked = 0; | 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 | /* Low-level driver cannot restore -> do it ourselves */ | 4554 | /* Low-level driver cannot restore -> do it ourselves */ |
| 4384 | update_screen(vc); | 4555 | update_screen(vc); |
| 4385 | if (console_blank_hook) | 4556 | if (console_blank_hook) |
| @@ -4584,7 +4755,7 @@ out: · 198 unmodified lines | |||
| 4584 | return rc; | 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 | struct console_font font; | 4760 | struct console_font font; |
| 4590 | int rc = -EINVAL; | 4761 | int rc = -EINVAL; |
| @@ -4748,43 +4919,3 @@ void vcs_scr_updated(struct vc_data *vc) · 157 unmodified lines | |||
| 4748 | { | 4919 | { |
| 4749 | notify_update(vc); | 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 | vcp->vc_scan_lines = v.v_vlin; | 714 | vcp->vc_scan_lines = v.v_vlin; |
| 715 | if (v.v_clin) | 715 | if (v.v_clin) |
| 716 | vcp->vc_cell_height = v.v_clin; | 716 | vcp->vc_cell_height = v.v_clin; |
| 717 | vcp->vc_resize_user = 1; | 717 | ret = __vc_resize(vcp, v.v_cols, v.v_rows, true); |
| 718 | ret = vc_resize(vcp, v.v_cols, v.v_rows); | ||
| 719 | if (ret) { | 718 | if (ret) { |
| 720 | vcp->vc_scan_lines = save_scan_lines; | 719 | vcp->vc_scan_lines = save_scan_lines; |
| 721 | vcp->vc_cell_height = save_cell_height; | 720 | vcp->vc_cell_height = save_cell_height; |
| @@ -923,9 +922,8 @@ int vt_ioctl(struct tty_struct *tty, · 201 unmodified lines | |||
| 923 | vc = vc_cons[i].d; | 922 | vc = vc_cons[i].d; |
| 924 | 923 | ||
| 925 | if (vc) { | 924 | if (vc) { |
| 926 | vc->vc_resize_user = 1; | ||
| 927 | /* FIXME: review v tty lock */ | 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 | console_unlock(); | 929 | console_unlock(); |
| @@ -50,7 +50,8 @@ void dummycon_unregister_output_notifier(struct notifier_block *nb) · 49 unmodified lines | |||
| 50 | raw_notifier_chain_unregister(&dummycon_output_nh, nb); | 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 | WARN_CONSOLE_UNLOCKED(); | 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 | raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); | 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 | static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, |
| 62 | int count, int ypos, int xpos) | 63 | unsigned int ypos, unsigned int xpos) |
| 63 | { | 64 | { |
| 64 | int i; | 65 | unsigned int i; |
| 65 | 66 | ||
| 66 | if (!dummycon_putc_called) { | 67 | if (!dummycon_putc_called) { |
| 67 | /* Ignore erases */ | 68 | /* Ignore erases */ |
| @@ -78,18 +79,21 @@ static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, · 10 unmodified lines | |||
| 78 | raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); | 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 | /* Redraw, so that we get putc(s) for output done while blanked */ | 85 | /* Redraw, so that we get putc(s) for output done while blanked */ |
| 84 | return 1; | 86 | return true; |
| 85 | } | 87 | } |
| 86 | #else | 88 | #else |
| 87 | static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } | 89 | static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y, |
| 88 | static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, | 90 | unsigned int x) { } |
| 89 | int count, int ypos, int xpos) { } | 91 | static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, |
| 90 | static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) | 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 | #endif | 98 | #endif |
| 95 | 99 | ||
| @@ -98,7 +102,7 @@ static const char *dummycon_startup(void) · 2 unmodified lines | |||
| 98 | return "dummy device"; | 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 | vc->vc_can_do_color = 1; | 107 | vc->vc_can_do_color = 1; |
| 104 | if (init) { | 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 | static void dummycon_deinit(struct vc_data *vc) { } | 115 | static void dummycon_deinit(struct vc_data *vc) { } |
| 112 | static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height, | 116 | static void dummycon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, |
| 113 | int width) { } | 117 | unsigned int width) { } |
| 114 | static void dummycon_cursor(struct vc_data *vc, int mode) { } | 118 | static void dummycon_cursor(struct vc_data *vc, bool enable) { } |
| 115 | 119 | ||
| 116 | static bool dummycon_scroll(struct vc_data *vc, unsigned int top, | 120 | static bool dummycon_scroll(struct vc_data *vc, unsigned int top, |
| 117 | unsigned int bottom, enum con_scroll dir, | 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 | return false; | 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 | return "MDA-2"; | 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 | c->vc_complement_mask = 0x0800; /* reverse video */ | 357 | c->vc_complement_mask = 0x0800; /* reverse video */ |
| 358 | c->vc_display_fg = &mda_display_fg; | 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 | return mda_vram_base + y * mda_num_columns + x; | 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) | 430 | static void mdacon_putcs(struct vc_data *c, const u16 *s, unsigned int count, |
| 431 | { | 431 | unsigned int y, unsigned int x) |
| 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) | ||
| 437 | { | 432 | { |
| 438 | u16 *dest = mda_addr(x, y); | 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, | 440 | static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x, |
| 446 | int height, int width) | 441 | unsigned int width) |
| 447 | { | 442 | { |
| 448 | u16 *dest = mda_addr(x, y); | 443 | u16 *dest = mda_addr(x, y); |
| 449 | u16 eattr = mda_convert_attr(c->vc_video_erase_char); | 444 | u16 eattr = mda_convert_attr(c->vc_video_erase_char); |
| 450 | 445 | ||
| 451 | if (width <= 0 || height <= 0) | 446 | scr_memsetw(dest, eattr, width * 2); |
| 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 | } | ||
| 460 | } | 447 | } |
| 461 | 448 | ||
| 462 | static int mdacon_switch(struct vc_data *c) | 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 | if (mda_type == TYPE_MDA) { | 457 | if (mda_type == TYPE_MDA) { |
| 470 | if (blank) | 458 | if (blank) |
| @@ -472,20 +460,20 @@ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch) · 1 unmodified line | |||
| 472 | mda_convert_attr(c->vc_video_erase_char), | 460 | mda_convert_attr(c->vc_video_erase_char), |
| 473 | c->vc_screenbuf_size); | 461 | c->vc_screenbuf_size); |
| 474 | /* Tell console.c that it has to restore the screen itself */ | 462 | /* Tell console.c that it has to restore the screen itself */ |
| 475 | return 1; | 463 | return true; |
| 476 | } else { | 464 | } else { |
| 477 | if (blank) | 465 | if (blank) |
| 478 | outb_p(0x00, mda_mode_port); /* disable video */ | 466 | outb_p(0x00, mda_mode_port); /* disable video */ |
| 479 | else | 467 | else |
| 480 | outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, | 468 | outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, |
| 481 | mda_mode_port); | 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 | mda_set_cursor(mda_vram_len - 1); | 477 | mda_set_cursor(mda_vram_len - 1); |
| 490 | return; | 478 | return; |
| 491 | } | 479 | } |
| @@ -544,7 +532,6 @@ static const struct consw mda_con = { · 52 unmodified lines | |||
| 544 | .con_init = mdacon_init, | 532 | .con_init = mdacon_init, |
| 545 | .con_deinit = mdacon_deinit, | 533 | .con_deinit = mdacon_deinit, |
| 546 | .con_clear = mdacon_clear, | 534 | .con_clear = mdacon_clear, |
| 547 | .con_putc = mdacon_putc, | ||
| 548 | .con_putcs = mdacon_putcs, | 535 | .con_putcs = mdacon_putcs, |
| 549 | .con_cursor = mdacon_cursor, | 536 | .con_cursor = mdacon_cursor, |
| 550 | .con_scroll = mdacon_scroll, | 537 | .con_scroll = mdacon_scroll, |
| @@ -324,7 +324,7 @@ out_unmap: · 323 unmodified lines | |||
| 324 | return NULL; | 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 | int cols, rows; | 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, | 349 | static void newport_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, |
| 350 | int width) | 350 | unsigned int width) |
| 351 | { | 351 | { |
| 352 | int xend = ((sx + width) << 3) - 1; | 352 | int xend = ((sx + width) << 3) - 1; |
| 353 | int ystart = ((sy << 4) + topscan) & 0x3ff; | 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 | if (logo_active) | 356 | if (logo_active) |
| 357 | return; | 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, | 370 | static void newport_putc(struct vc_data *vc, u16 charattr, unsigned int ypos, |
| 371 | int xpos) | 371 | unsigned int xpos) |
| 372 | { | 372 | { |
| 373 | unsigned char *p; | 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 | RENDER(npregs, p); | 396 | RENDER(npregs, p); |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | static void newport_putcs(struct vc_data *vc, const unsigned short *s, | 399 | static void newport_putcs(struct vc_data *vc, const u16 *s, |
| 400 | int count, int ypos, int xpos) | 400 | unsigned int count, unsigned int ypos, |
| 401 | unsigned int xpos) | ||
| 401 | { | 402 | { |
| 402 | int i; | ||
| 403 | int charattr; | ||
| 404 | unsigned char *p; | 403 | unsigned char *p; |
| 404 | unsigned int i; | ||
| 405 | u16 charattr; | ||
| 405 | 406 | ||
| 406 | charattr = (scr_readw(s) >> 8) & 0xff; | 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 | unsigned short treg; | 443 | unsigned short treg; |
| 443 | int xcurs, ycurs; | 444 | int xcurs, ycurs; |
| 444 | 445 | ||
| 445 | switch (mode) { | 446 | treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); |
| 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; | ||
| 451 | 447 | ||
| 452 | case CM_MOVE: | 448 | if (!enable) { |
| 453 | case CM_DRAW: | ||
| 454 | treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); | ||
| 455 | newport_vc2_set(npregs, VC2_IREG_CONTROL, | 449 | newport_vc2_set(npregs, VC2_IREG_CONTROL, |
| 456 | (treg | VC2_CTRL_ECDISP)); | 450 | (treg & ~(VC2_CTRL_ECDISP))); |
| 457 | xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2; | 451 | return; |
| 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); | ||
| 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 | static int logo_drawn = 0; | 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 | unsigned short treg; | 482 | unsigned short treg; |
| 485 | 483 | ||
| 486 | if (blank == 0) { | 484 | if (blank == VESA_NO_BLANKING) { |
| 487 | /* unblank console */ | 485 | /* unblank console */ |
| 488 | treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); | 486 | treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); |
| 489 | newport_vc2_set(npregs, VC2_IREG_CONTROL, | 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 | newport_vc2_set(npregs, VC2_IREG_CONTROL, | 492 | newport_vc2_set(npregs, VC2_IREG_CONTROL, |
| 495 | (treg & ~(VC2_CTRL_EDISP))); | 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 | int w = op->width; | 502 | int w = op->width; |
| 503 | int h = op->height; | 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 | return 0; | 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 | return newport_set_def_font(vc->vc_num, op); | 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 | unsigned int vpitch, unsigned int flags) | 574 | unsigned int vpitch, unsigned int flags) |
| 574 | { | 575 | { |
| 575 | return newport_set_font(vc->vc_num, font, vpitch); | 576 | return newport_set_font(vc->vc_num, font, vpitch); |
| @@ -71,19 +71,8 @@ static const char *sticon_startup(void) · 70 unmodified lines | |||
| 71 | return "STI console"; | 71 | return "STI console"; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos) | 74 | static void sticon_putcs(struct vc_data *conp, const u16 *s, unsigned int count, |
| 75 | { | 75 | unsigned int ypos, unsigned int xpos) |
| 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) | ||
| 87 | { | 76 | { |
| 88 | if (vga_is_gfx || console_blanked) | 77 | if (vga_is_gfx || console_blanked) |
| 89 | return; | 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 | unsigned short car1; | 91 | unsigned short car1; |
| 103 | 92 | ||
| @@ -106,23 +95,20 @@ static void sticon_cursor(struct vc_data *conp, int mode) · 2 unmodified lines | |||
| 106 | return; | 95 | return; |
| 107 | 96 | ||
| 108 | car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; | 97 | car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; |
| 109 | switch (mode) { | 98 | if (!enable) { |
| 110 | case CM_ERASE: | ||
| 111 | sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, | 99 | sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, |
| 112 | font_data[conp->vc_num]); | 100 | font_data[conp->vc_num]); |
| 113 | break; | 101 | return; |
| 114 | case CM_MOVE: | 102 | } |
| 115 | case CM_DRAW: | 103 | |
| 116 | switch (CUR_SIZE(conp->vc_cursor_type)) { | 104 | switch (CUR_SIZE(conp->vc_cursor_type)) { |
| 117 | case CUR_UNDERLINE: | 105 | case CUR_UNDERLINE: |
| 118 | case CUR_LOWER_THIRD: | 106 | case CUR_LOWER_THIRD: |
| 119 | case CUR_LOWER_HALF: | 107 | case CUR_LOWER_HALF: |
| 120 | case CUR_TWO_THIRDS: | 108 | case CUR_TWO_THIRDS: |
| 121 | case CUR_BLOCK: | 109 | case CUR_BLOCK: |
| 122 | sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), | 110 | sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), |
| 123 | conp->state.y, conp->state.x, font_data[conp->vc_num]); | 111 | conp->state.y, conp->state.x, font_data[conp->vc_num]); |
| 124 | break; | ||
| 125 | } | ||
| 126 | break; | 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 | if (vga_is_gfx) | 121 | if (vga_is_gfx) |
| 136 | return false; | 122 | return false; |
| 137 | 123 | ||
| 138 | sticon_cursor(conp, CM_ERASE); | 124 | sticon_cursor(conp, false); |
| 139 | 125 | ||
| 140 | switch (dir) { | 126 | switch (dir) { |
| 141 | case SM_UP: | 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 | unsigned int vpitch) | 157 | unsigned int vpitch) |
| 172 | { | 158 | { |
| 173 | struct sti_struct *sti = sticon_sti; | 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 | return 0; | 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 | sticon_set_def_font(vc->vc_num); | 252 | sticon_set_def_font(vc->vc_num); |
| 266 | 253 | ||
| 267 | return 0; | 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 | unsigned int vpitch, unsigned int flags) | 258 | unsigned int vpitch, unsigned int flags) |
| 272 | { | 259 | { |
| 273 | return sticon_set_font(vc, font, vpitch); | 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 | struct sti_struct *sti = sticon_sti; | 265 | struct sti_struct *sti = sticon_sti; |
| 279 | int vc_cols, vc_rows; | 266 | int vc_cols, vc_rows; |
| @@ -300,33 +287,32 @@ static void sticon_deinit(struct vc_data *c) · 20 unmodified lines | |||
| 300 | sticon_set_def_font(i); | 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, | 290 | static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx, |
| 304 | int width) | 291 | unsigned int width) |
| 305 | { | 292 | { |
| 306 | if (!height || !width) | 293 | sti_clear(sticon_sti, sy, sx, 1, width, |
| 307 | return; | ||
| 308 | |||
| 309 | sti_clear(sticon_sti, sy, sx, height, width, | ||
| 310 | conp->vc_video_erase_char, font_data[conp->vc_num]); | 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 | if (mode_switch) | 306 | if (mode_switch) |
| 322 | vga_is_gfx = 0; | 307 | vga_is_gfx = 0; |
| 323 | return 1; | 308 | return true; |
| 324 | } | 309 | } |
| 325 | sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, | 310 | sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, |
| 326 | font_data[c->vc_num]); | 311 | font_data[c->vc_num]); |
| 327 | if (mode_switch) | 312 | if (mode_switch) |
| 328 | vga_is_gfx = 1; | 313 | vga_is_gfx = 1; |
| 329 | return 1; | 314 | |
| 315 | return true; | ||
| 330 | } | 316 | } |
| 331 | 317 | ||
| 332 | static u8 sticon_build_attr(struct vc_data *conp, u8 color, | 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 | .con_init = sticon_init, | 351 | .con_init = sticon_init, |
| 366 | .con_deinit = sticon_deinit, | 352 | .con_deinit = sticon_deinit, |
| 367 | .con_clear = sticon_clear, | 353 | .con_clear = sticon_clear, |
| 368 | .con_putc = sticon_putc, | ||
| 369 | .con_putcs = sticon_putcs, | 354 | .con_putcs = sticon_putcs, |
| 370 | .con_cursor = sticon_cursor, | 355 | .con_cursor = sticon_cursor, |
| 371 | .con_scroll = sticon_scroll, | 356 | .con_scroll = sticon_scroll, |
| @@ -65,7 +65,7 @@ static struct vgastate vgastate; · 64 unmodified lines | |||
| 65 | * Interface used by the world | 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 | static struct uni_pagedict *vgacon_uni_pagedir; | 70 | static struct uni_pagedict *vgacon_uni_pagedir; |
| 71 | static int vgacon_refcount; | 71 | static int vgacon_refcount; |
| @@ -81,7 +81,7 @@ static unsigned int vga_video_num_lines; /* Number of text lines */ · 9 unmodified lines | |||
| 81 | static bool vga_can_do_color; /* Do we support colors? */ | 81 | static bool vga_can_do_color; /* Do we support colors? */ |
| 82 | static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ | 82 | static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ |
| 83 | static unsigned char vga_video_type __read_mostly; /* Card type */ | 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 | static bool vga_palette_blanked; | 85 | static bool vga_palette_blanked; |
| 86 | static bool vga_is_gfx; | 86 | static bool vga_is_gfx; |
| 87 | static bool vga_512_chars; | 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 | static void vgacon_scrolldelta(struct vc_data *c, int lines) | 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, | 141 | unsigned long scr_end = c->vc_scr_end - vga_vram_base; |
| 142 | vga_vram_size); | 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 | vga_set_mem_top(c); | 175 | vga_set_mem_top(c); |
| 144 | } | 176 | } |
| 145 | 177 | ||
| @@ -335,7 +367,7 @@ static const char *vgacon_startup(void) · 189 unmodified lines | |||
| 335 | return display_desc; | 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 | struct uni_pagedict *p; | 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 | c->vc_scan_lines = vga_scan_lines; | 384 | c->vc_scan_lines = vga_scan_lines; |
| 353 | c->vc_font.height = c->vc_cell_height = vga_video_font_height; | 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 | if (init) { | 388 | if (init) { |
| 357 | c->vc_cols = vga_video_num_columns; | 389 | c->vc_cols = vga_video_num_columns; |
| 358 | c->vc_rows = vga_video_num_lines; | 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 | raw_spin_unlock_irqrestore(&vga_lock, flags); | 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 | unsigned int c_height; | 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 | c_height = c->vc_cell_height; | 515 | c_height = c->vc_cell_height; |
| 484 | 516 | ||
| 485 | switch (mode) { | 517 | write_vga(14, (c->vc_pos - vga_vram_base) / 2); |
| 486 | case CM_ERASE: | 518 | |
| 487 | write_vga(14, (c->vc_pos - vga_vram_base) / 2); | 519 | if (!enable) { |
| 488 | if (vga_video_type >= VIDEO_TYPE_VGAC) | 520 | if (vga_video_type >= VIDEO_TYPE_VGAC) |
| 489 | vgacon_set_cursor_size(31, 30); | 521 | vgacon_set_cursor_size(31, 30); |
| 490 | else | 522 | else |
| 491 | vgacon_set_cursor_size(31, 31); | 523 | vgacon_set_cursor_size(31, 31); |
| 492 | break; | 524 | return; |
| 525 | } | ||
| 493 | 526 | ||
| 494 | case CM_MOVE: | 527 | switch (CUR_SIZE(c->vc_cursor_type)) { |
| 495 | case CM_DRAW: | 528 | case CUR_UNDERLINE: |
| 496 | write_vga(14, (c->vc_pos - vga_vram_base) / 2); | 529 | vgacon_set_cursor_size(c_height - (c_height < 10 ? 2 : 3), |
| 497 | switch (CUR_SIZE(c->vc_cursor_type)) { | 530 | c_height - (c_height < 10 ? 1 : 2)); |
| 498 | case CUR_UNDERLINE: | 531 | break; |
| 499 | vgacon_set_cursor_size(c_height - | 532 | case CUR_TWO_THIRDS: |
| 500 | (c_height < 10 ? 2 : 3), | 533 | vgacon_set_cursor_size(c_height / 3, |
| 501 | c_height - | 534 | c_height - (c_height < 10 ? 1 : 2)); |
| 502 | (c_height < 10 ? 1 : 2)); | 535 | break; |
| 503 | break; | 536 | case CUR_LOWER_THIRD: |
| 504 | case CUR_TWO_THIRDS: | 537 | vgacon_set_cursor_size(c_height * 2 / 3, |
| 505 | vgacon_set_cursor_size(c_height / 3, c_height - | 538 | c_height - (c_height < 10 ? 1 : 2)); |
| 506 | (c_height < 10 ? 1 : 2)); | 539 | break; |
| 507 | break; | 540 | case CUR_LOWER_HALF: |
| 508 | case CUR_LOWER_THIRD: | 541 | vgacon_set_cursor_size(c_height / 2, |
| 509 | vgacon_set_cursor_size(c_height * 2 / 3, c_height - | 542 | c_height - (c_height < 10 ? 1 : 2)); |
| 510 | (c_height < 10 ? 1 : 2)); | 543 | break; |
| 511 | break; | 544 | case CUR_NONE: |
| 512 | case CUR_LOWER_HALF: | 545 | if (vga_video_type >= VIDEO_TYPE_VGAC) |
| 513 | vgacon_set_cursor_size(c_height / 2, c_height - | 546 | vgacon_set_cursor_size(31, 30); |
| 514 | (c_height < 10 ? 1 : 2)); | 547 | else |
| 515 | break; | 548 | vgacon_set_cursor_size(31, 31); |
| 516 | case CUR_NONE: | 549 | break; |
| 517 | if (vga_video_type >= VIDEO_TYPE_VGAC) | 550 | default: |
| 518 | vgacon_set_cursor_size(31, 30); | 551 | vgacon_set_cursor_size(1, c_height); |
| 519 | else | ||
| 520 | vgacon_set_cursor_size(31, 31); | ||
| 521 | break; | ||
| 522 | default: | ||
| 523 | vgacon_set_cursor_size(1, c_height); | ||
| 524 | break; | ||
| 525 | } | ||
| 526 | break; | 552 | break; |
| 527 | } | 553 | } |
| 528 | } | 554 | } |
| @@ -588,7 +614,7 @@ static void vgacon_doresize(struct vc_data *c, · 59 unmodified lines | |||
| 588 | raw_spin_unlock_irqrestore(&vga_lock, flags); | 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 | int x = c->vc_cols * VGA_FONTWIDTH; | 619 | int x = c->vc_cols * VGA_FONTWIDTH; |
| 594 | int y = c->vc_rows * c->vc_cell_height; | 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 | vgacon_doresize(c, c->vc_cols, c->vc_rows); | 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 | static void vga_set_palette(struct vc_data *vc, const unsigned char *table) | 649 | static void vga_set_palette(struct vc_data *vc, const unsigned char *table) |
| @@ -657,7 +683,7 @@ static struct { · 33 unmodified lines | |||
| 657 | unsigned char ClockingMode; /* Seq-Controller:01h */ | 683 | unsigned char ClockingMode; /* Seq-Controller:01h */ |
| 658 | } vga_state; | 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 | /* save original values of VGA controller registers */ | 688 | /* save original values of VGA controller registers */ |
| 663 | if (!vga_vesa_blanked) { | 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 | switch (blank) { | 803 | switch (blank) { |
| 777 | case 0: /* Unblank */ | 804 | case VESA_NO_BLANKING: /* Unblank */ |
| 778 | if (vga_vesa_blanked) { | 805 | if (vga_vesa_blanked) { |
| 779 | vga_vesa_unblank(&vgastate); | 806 | vga_vesa_unblank(&vgastate); |
| 780 | vga_vesa_blanked = 0; | 807 | vga_vesa_blanked = VESA_NO_BLANKING; |
| 781 | } | 808 | } |
| 782 | if (vga_palette_blanked) { | 809 | if (vga_palette_blanked) { |
| 783 | vga_set_palette(c, color_table); | 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 | vga_is_gfx = false; | 814 | vga_is_gfx = false; |
| 788 | /* Tell console.c that it has to restore the screen itself */ | 815 | /* Tell console.c that it has to restore the screen itself */ |
| 789 | return 1; | 816 | return 1; |
| 790 | case 1: /* Normal blanking */ | 817 | case VESA_VSYNC_SUSPEND: /* Normal blanking */ |
| 791 | case -1: /* Obsolete */ | ||
| 792 | if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { | 818 | if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { |
| 793 | vga_pal_blank(&vgastate); | 819 | vga_pal_blank(&vgastate); |
| 794 | vga_palette_blanked = true; | 820 | vga_palette_blanked = true; |
| @@ -1004,7 +1030,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight) · 209 unmodified lines | |||
| 1004 | /* void size to cause regs to be rewritten */ | 1030 | /* void size to cause regs to be rewritten */ |
| 1005 | cursor_size_lastfrom = 0; | 1031 | cursor_size_lastfrom = 0; |
| 1006 | cursor_size_lastto = 0; | 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 | c->vc_font.height = c->vc_cell_height = fontheight; | 1035 | c->vc_font.height = c->vc_cell_height = fontheight; |
| 1010 | vc_resize(c, 0, rows); /* Adjust console size */ | 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 | return 0; | 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 | unsigned int vpitch, unsigned int flags) | 1043 | unsigned int vpitch, unsigned int flags) |
| 1018 | { | 1044 | { |
| 1019 | unsigned charcount = font->charcount; | 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 | static int vgacon_resize(struct vc_data *c, unsigned int width, | 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 | if ((width << 1) * height > vga_vram_size) | 1080 | if ((width << 1) * height > vga_vram_size) |
| 1055 | return -EINVAL; | 1081 | return -EINVAL; |
| 1056 | 1082 | ||
| 1057 | if (user) { | 1083 | if (from_user) { |
| 1058 | /* | 1084 | /* |
| 1059 | * Ho ho! Someone (svgatextmode, eh?) may have reprogrammed | 1085 | * Ho ho! Someone (svgatextmode, eh?) may have reprogrammed |
| 1060 | * the video mode! Set the new defaults then and go away. | 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 | return 0; | 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 | if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ | 1105 | if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ |
| 1080 | (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */ | 1106 | (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */ |
| 1081 | return 0; | 1107 | return false; |
| 1082 | c->vc_origin = c->vc_visible_origin = vga_vram_base; | 1108 | c->vc_origin = c->vc_visible_origin = vga_vram_base; |
| 1083 | vga_set_mem_top(c); | 1109 | vga_set_mem_top(c); |
| 1084 | vga_rolled_over = 0; | 1110 | vga_rolled_over = 0; |
| 1085 | return 1; | 1111 | return true; |
| 1086 | } | 1112 | } |
| 1087 | 1113 | ||
| 1088 | static void vgacon_save_screen(struct vc_data *c) | 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 | * The console `switch' structure for the VGA based console | 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, | 1188 | static void vgacon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, |
| 1163 | int width) { } | 1189 | unsigned int width) { } |
| 1164 | static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } | 1190 | static void vgacon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, |
| 1165 | static void vgacon_putcs(struct vc_data *vc, const unsigned short *s, | 1191 | unsigned int ypos, unsigned int xpos) { } |
| 1166 | int count, int ypos, int xpos) { } | ||
| 1167 | 1192 | ||
| 1168 | const struct consw vga_con = { | 1193 | const struct consw vga_con = { |
| 1169 | .owner = THIS_MODULE, | 1194 | .owner = THIS_MODULE, |
| @@ -1171,7 +1196,6 @@ const struct consw vga_con = { · 1 unmodified line | |||
| 1171 | .con_init = vgacon_init, | 1196 | .con_init = vgacon_init, |
| 1172 | .con_deinit = vgacon_deinit, | 1197 | .con_deinit = vgacon_deinit, |
| 1173 | .con_clear = vgacon_clear, | 1198 | .con_clear = vgacon_clear, |
| 1174 | .con_putc = vgacon_putc, | ||
| 1175 | .con_putcs = vgacon_putcs, | 1199 | .con_putcs = vgacon_putcs, |
| 1176 | .con_cursor = vgacon_cursor, | 1200 | .con_cursor = vgacon_cursor, |
| 1177 | .con_scroll = vgacon_scroll, | 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 | int fg, int bg) | 237 | int fg, int bg) |
| 238 | { | 238 | { |
| 239 | struct fb_cursor cursor; | 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 | mask[i++] = msk; | 348 | mask[i++] = msk; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | switch (mode) { | 351 | ops->cursor_state.enable = enable && !use_sw; |
| 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 | } | ||
| 361 | 352 | ||
| 362 | cursor.image.data = src; | 353 | cursor.image.data = src; |
| 363 | cursor.image.fg_color = ops->cursor_state.image.fg_color; | 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 | struct fb_info *info; | 351 | struct fb_info *info; |
| 352 | struct vc_data *vc = NULL; | 352 | struct vc_data *vc = NULL; |
| 353 | int c; | 353 | int c; |
| 354 | int mode; | 354 | bool enable; |
| 355 | int ret; | 355 | int ret; |
| 356 | 356 | ||
| 357 | /* FIXME: we should sort out the unbind locking instead */ | 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 | c = scr_readw((u16 *) vc->vc_pos); | 377 | c = scr_readw((u16 *) vc->vc_pos); |
| 378 | mode = (!ops->cursor_flash || ops->cursor_state.enable) ? | 378 | enable = ops->cursor_flash && !ops->cursor_state.enable; |
| 379 | CM_ERASE : CM_DRAW; | 379 | ops->cursor(vc, info, enable, get_color(vc, info, c, 1), |
| 380 | ops->cursor(vc, info, mode, get_color(vc, info, c, 1), | ||
| 381 | get_color(vc, info, c, 0)); | 380 | get_color(vc, info, c, 0)); |
| 382 | console_unlock(); | 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 | static const char *fbcon_startup(void) | 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 | struct fbcon_display *p = &fb_display[fg_console]; | 923 | struct fbcon_display *p = &fb_display[fg_console]; |
| 925 | struct vc_data *vc = vc_cons[fg_console].d; | 924 | struct vc_data *vc = vc_cons[fg_console].d; |
| 926 | const struct font_desc *font = NULL; | 925 | const struct font_desc *font = NULL; |
| @@ -987,7 +986,7 @@ static const char *fbcon_startup(void) · 60 unmodified lines | |||
| 987 | return display_desc; | 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 | struct fb_info *info; | 991 | struct fb_info *info; |
| 993 | struct fbcon_ops *ops; | 992 | struct fbcon_ops *ops; |
| @@ -1234,8 +1233,8 @@ finished: · 240 unmodified lines | |||
| 1234 | * restriction is simplicity & efficiency at the moment. | 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, | 1236 | static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, |
| 1238 | int width) | 1237 | unsigned int height, unsigned int width) |
| 1239 | { | 1238 | { |
| 1240 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 1239 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 1241 | struct fbcon_ops *ops = info->fbcon_par; | 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 | ops->clear(vc, info, real_y(p, sy), sx, height, width); | 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, | 1274 | static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, |
| 1276 | int count, int ypos, int xpos) | 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 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 1283 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 1279 | struct fbcon_display *p = &fb_display[vc->vc_num]; | 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 | get_color(vc, info, scr_readw(s), 0)); | 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 | static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) | 1293 | static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) |
| 1297 | { | 1294 | { |
| 1298 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 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 | ops->clear_margins(vc, info, margin_color, bottom_only); | 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 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 1304 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 1308 | struct fbcon_ops *ops = info->fbcon_par; | 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 | else | 1315 | else |
| 1319 | fbcon_add_cursor_work(info); | 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 | if (!ops->cursor) | 1320 | if (!ops->cursor) |
| 1324 | return; | 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 | get_color(vc, info, c, 0)); | 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 | if (fbcon_is_inactive(vc, info)) | 1740 | if (fbcon_is_inactive(vc, info)) |
| 1744 | return true; | 1741 | return true; |
| 1745 | 1742 | ||
| 1746 | fbcon_cursor(vc, CM_ERASE); | 1743 | fbcon_cursor(vc, false); |
| 1747 | 1744 | ||
| 1748 | /* | 1745 | /* |
| 1749 | * ++Geert: Only use ywrap/ypan if the console is in text mode | 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 | case SCROLL_MOVE: | 1756 | case SCROLL_MOVE: |
| 1760 | fbcon_redraw_blit(vc, info, p, t, b - t - count, | 1757 | fbcon_redraw_blit(vc, info, p, t, b - t - count, |
| 1761 | count); | 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 | scr_memsetw((unsigned short *) (vc->vc_origin + | 1760 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1764 | vc->vc_size_row * | 1761 | vc->vc_size_row * |
| 1765 | (b - count)), | 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 | b - t - count, vc->vc_cols); | 1779 | b - t - count, vc->vc_cols); |
| 1783 | else | 1780 | else |
| 1784 | goto redraw_up; | 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 | break; | 1783 | break; |
| 1787 | 1784 | ||
| 1788 | case SCROLL_PAN_REDRAW: | 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 | vc->vc_rows - b, b); | 1797 | vc->vc_rows - b, b); |
| 1801 | } else | 1798 | } else |
| 1802 | fbcon_redraw_move(vc, p, t + count, b - t - count, t); | 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 | break; | 1801 | break; |
| 1805 | 1802 | ||
| 1806 | case SCROLL_PAN_MOVE: | 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 | b - t - count, vc->vc_cols); | 1820 | b - t - count, vc->vc_cols); |
| 1824 | else | 1821 | else |
| 1825 | goto redraw_up; | 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 | break; | 1824 | break; |
| 1828 | 1825 | ||
| 1829 | case SCROLL_REDRAW: | 1826 | case SCROLL_REDRAW: |
| 1830 | redraw_up: | 1827 | redraw_up: |
| 1831 | fbcon_redraw(vc, t, b - t - count, | 1828 | fbcon_redraw(vc, t, b - t - count, |
| 1832 | count * vc->vc_cols); | 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 | scr_memsetw((unsigned short *) (vc->vc_origin + | 1831 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1835 | vc->vc_size_row * | 1832 | vc->vc_size_row * |
| 1836 | (b - count)), | 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 | case SCROLL_MOVE: | 1844 | case SCROLL_MOVE: |
| 1848 | fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, | 1845 | fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, |
| 1849 | -count); | 1846 | -count); |
| 1850 | fbcon_clear(vc, t, 0, count, vc->vc_cols); | 1847 | __fbcon_clear(vc, t, 0, count, vc->vc_cols); |
| 1851 | scr_memsetw((unsigned short *) (vc->vc_origin + | 1848 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1852 | vc->vc_size_row * | 1849 | vc->vc_size_row * |
| 1853 | t), | 1850 | t), |
| @@ -1870,7 +1867,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 16 unmodified lines | |||
| 1870 | b - t - count, vc->vc_cols); | 1867 | b - t - count, vc->vc_cols); |
| 1871 | else | 1868 | else |
| 1872 | goto redraw_down; | 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 | break; | 1871 | break; |
| 1875 | 1872 | ||
| 1876 | case SCROLL_PAN_MOVE: | 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 | b - t - count, vc->vc_cols); | 1889 | b - t - count, vc->vc_cols); |
| 1893 | else | 1890 | else |
| 1894 | goto redraw_down; | 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 | break; | 1893 | break; |
| 1897 | 1894 | ||
| 1898 | case SCROLL_PAN_REDRAW: | 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 | fbcon_redraw_move(vc, p, count, t, 0); | 1906 | fbcon_redraw_move(vc, p, count, t, 0); |
| 1910 | } else | 1907 | } else |
| 1911 | fbcon_redraw_move(vc, p, t, b - t - count, t + count); | 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 | break; | 1910 | break; |
| 1914 | 1911 | ||
| 1915 | case SCROLL_REDRAW: | 1912 | case SCROLL_REDRAW: |
| 1916 | redraw_down: | 1913 | redraw_down: |
| 1917 | fbcon_redraw(vc, b - 1, b - t - count, | 1914 | fbcon_redraw(vc, b - 1, b - t - count, |
| 1918 | -count * vc->vc_cols); | 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 | scr_memsetw((unsigned short *) (vc->vc_origin + | 1917 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1921 | vc->vc_size_row * | 1918 | vc->vc_size_row * |
| 1922 | t), | 1919 | t), |
| @@ -1995,7 +1992,7 @@ static void updatescrollmode(struct fbcon_display *p, · 72 unmodified lines | |||
| 1995 | #define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */ | 1992 | #define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */ |
| 1996 | 1993 | ||
| 1997 | static int fbcon_resize(struct vc_data *vc, unsigned int width, | 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 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 1997 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2001 | struct fbcon_ops *ops = info->fbcon_par; | 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 | return 0; | 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 | struct fb_info *info, *old_info = NULL; | 2060 | struct fb_info *info, *old_info = NULL; |
| 2064 | struct fbcon_ops *ops; | 2061 | struct fbcon_ops *ops; |
| @@ -2180,9 +2177,9 @@ static int fbcon_switch(struct vc_data *vc) · 115 unmodified lines | |||
| 2180 | vc->vc_origin + vc->vc_size_row * vc->vc_top, | 2177 | vc->vc_origin + vc->vc_size_row * vc->vc_top, |
| 2181 | vc->vc_size_row * (vc->vc_bottom - | 2178 | vc->vc_size_row * (vc->vc_bottom - |
| 2182 | vc->vc_top) / 2); | 2179 | vc->vc_top) / 2); |
| 2183 | return 0; | 2180 | return false; |
| 2184 | } | 2181 | } |
| 2185 | return 1; | 2182 | return true; |
| 2186 | } | 2183 | } |
| 2187 | 2184 | ||
| 2188 | static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, | 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 | oldc = vc->vc_video_erase_char; | 2193 | oldc = vc->vc_video_erase_char; |
| 2197 | vc->vc_video_erase_char &= charmask; | 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 | vc->vc_video_erase_char = oldc; | 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 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 2203 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2206 | struct fbcon_ops *ops = info->fbcon_par; | 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 | if (!fbcon_is_inactive(vc, info)) { | 2220 | if (!fbcon_is_inactive(vc, info)) { |
| 2223 | if (ops->blank_state != blank) { | 2221 | if (ops->blank_state != blank) { |
| 2224 | ops->blank_state = blank; | 2222 | ops->blank_state = blank; |
| 2225 | fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); | 2223 | fbcon_cursor(vc, !blank); |
| 2226 | ops->cursor_flash = (!blank); | 2224 | ops->cursor_flash = (!blank); |
| 2227 | 2225 | ||
| 2228 | if (fb_blank(info, blank)) | 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 | else | 2237 | else |
| 2240 | fbcon_add_cursor_work(info); | 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 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 2245 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2248 | struct fbcon_ops *ops = info->fbcon_par; | 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 | if (info->fbops->fb_debug_enter) | 2250 | if (info->fbops->fb_debug_enter) |
| 2253 | info->fbops->fb_debug_enter(info); | 2251 | info->fbops->fb_debug_enter(info); |
| 2254 | fbcon_set_palette(vc, color_table); | 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 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 2257 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2261 | struct fbcon_ops *ops = info->fbcon_par; | 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 | ops->graphics = ops->save_graphics; | 2260 | ops->graphics = ops->save_graphics; |
| 2264 | if (info->fbops->fb_debug_leave) | 2261 | if (info->fbops->fb_debug_leave) |
| 2265 | info->fbops->fb_debug_leave(info); | 2262 | info->fbops->fb_debug_leave(info); |
| 2266 | return 0; | ||
| 2267 | } | 2263 | } |
| 2268 | 2264 | ||
| 2269 | static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch) | 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 | * but lets not assume that, since charcount of 512 is small for unicode support. | 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 | unsigned int vpitch, unsigned int flags) | 2461 | unsigned int vpitch, unsigned int flags) |
| 2466 | { | 2462 | { |
| 2467 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 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 | return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1); | 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 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); | 2536 | struct fb_info *info = fbcon_info_from_console(vc->vc_num); |
| 2540 | const struct font_desc *f; | 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 | fb_set_cmap(&palette_cmap, info); | 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 | /* As we might be inside of softback, we may work with non-contiguous buffer, | 2593 | /* As we might be inside of softback, we may work with non-contiguous buffer, |
| 2626 | that's why we have to use a separate routine. */ | 2594 | that's why we have to use a separate routine. */ |
| 2627 | static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) | 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 | vc = vc_cons[ops->currcon].d; | 2618 | vc = vc_cons[ops->currcon].d; |
| 2651 | 2619 | ||
| 2652 | /* Clear cursor, restore saved data */ | 2620 | /* Clear cursor, restore saved data */ |
| 2653 | fbcon_cursor(vc, CM_ERASE); | 2621 | fbcon_cursor(vc, false); |
| 2654 | } | 2622 | } |
| 2655 | 2623 | ||
| 2656 | void fbcon_resumed(struct fb_info *info) | 2624 | void fbcon_resumed(struct fb_info *info) |
| @@ -3152,7 +3120,6 @@ static const struct consw fb_con = { · 495 unmodified lines | |||
| 3152 | .con_init = fbcon_init, | 3120 | .con_init = fbcon_init, |
| 3153 | .con_deinit = fbcon_deinit, | 3121 | .con_deinit = fbcon_deinit, |
| 3154 | .con_clear = fbcon_clear, | 3122 | .con_clear = fbcon_clear, |
| 3155 | .con_putc = fbcon_putc, | ||
| 3156 | .con_putcs = fbcon_putcs, | 3123 | .con_putcs = fbcon_putcs, |
| 3157 | .con_cursor = fbcon_cursor, | 3124 | .con_cursor = fbcon_cursor, |
| 3158 | .con_scroll = fbcon_scroll, | 3125 | .con_scroll = fbcon_scroll, |
| @@ -3163,8 +3130,6 @@ static const struct consw fb_con = { · 4 unmodified lines | |||
| 3163 | .con_font_default = fbcon_set_def_font, | 3130 | .con_font_default = fbcon_set_def_font, |
| 3164 | .con_set_palette = fbcon_set_palette, | 3131 | .con_set_palette = fbcon_set_palette, |
| 3165 | .con_invert_region = fbcon_invert_region, | 3132 | .con_invert_region = fbcon_invert_region, |
| 3166 | .con_screen_pos = fbcon_screen_pos, | ||
| 3167 | .con_getxy = fbcon_getxy, | ||
| 3168 | .con_resize = fbcon_resize, | 3133 | .con_resize = fbcon_resize, |
| 3169 | .con_debug_enter = fbcon_debug_enter, | 3134 | .con_debug_enter = fbcon_debug_enter, |
| 3170 | .con_debug_leave = fbcon_debug_leave, | 3135 | .con_debug_leave = fbcon_debug_leave, |
| @@ -61,8 +61,8 @@ struct fbcon_ops { · 60 unmodified lines | |||
| 61 | int fg, int bg); | 61 | int fg, int bg); |
| 62 | void (*clear_margins)(struct vc_data *vc, struct fb_info *info, | 62 | void (*clear_margins)(struct vc_data *vc, struct fb_info *info, |
| 63 | int color, int bottom_only); | 63 | int color, int bottom_only); |
| 64 | void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode, | 64 | void (*cursor)(struct vc_data *vc, struct fb_info *info, |
| 65 | int fg, int bg); | 65 | bool enable, int fg, int bg); |
| 66 | int (*update_start)(struct fb_info *info); | 66 | int (*update_start)(struct fb_info *info); |
| 67 | int (*rotate_font)(struct fb_info *info, struct vc_data *vc); | 67 | int (*rotate_font)(struct fb_info *info, struct vc_data *vc); |
| 68 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ | 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 | int fg, int bg) | 222 | int fg, int bg) |
| 223 | { | 223 | { |
| 224 | struct fb_cursor cursor; | 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 | kfree(tmp); | 349 | kfree(tmp); |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | switch (mode) { | 352 | ops->cursor_state.enable = enable && !use_sw; |
| 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 | } | ||
| 362 | 353 | ||
| 363 | cursor.image.data = src; | 354 | cursor.image.data = src; |
| 364 | cursor.image.fg_color = ops->cursor_state.image.fg_color; | 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 | int fg, int bg) | 205 | int fg, int bg) |
| 206 | { | 206 | { |
| 207 | struct fb_cursor cursor; | 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 | kfree(tmp); | 332 | kfree(tmp); |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | switch (mode) { | 335 | ops->cursor_state.enable = enable && !use_sw; |
| 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 | } | ||
| 345 | 336 | ||
| 346 | cursor.image.data = src; | 337 | cursor.image.data = src; |
| 347 | cursor.image.fg_color = ops->cursor_state.image.fg_color; | 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 | int fg, int bg) | 252 | int fg, int bg) |
| 253 | { | 253 | { |
| 254 | struct fb_cursor cursor; | 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 | mask[i++] = ~msk; | 372 | mask[i++] = ~msk; |
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | switch (mode) { | 375 | ops->cursor_state.enable = enable && !use_sw; |
| 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 | } | ||
| 385 | 376 | ||
| 386 | cursor.image.data = src; | 377 | cursor.image.data = src; |
| 387 | cursor.image.fg_color = ops->cursor_state.image.fg_color; | 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 | return; | 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 | int fg, int bg) | 83 | int fg, int bg) |
| 84 | { | 84 | { |
| 85 | struct fb_tilecursor cursor; | 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 | cursor.sx = vc->state.x; | 88 | cursor.sx = vc->state.x; |
| 89 | cursor.sy = vc->state.y; | 89 | cursor.sy = vc->state.y; |
| 90 | cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1; | 90 | cursor.mode = enable && !use_sw; |
| 91 | cursor.fg = fg; | 91 | cursor.fg = fg; |
| 92 | cursor.bg = bg; | 92 | cursor.bg = bg; |
| 93 | 93 | ||
| @@ -380,7 +380,7 @@ tgafb_set_par(struct fb_info *info) · 379 unmodified lines | |||
| 380 | BT463_LOAD_ADDR(par, 0x0000); | 380 | BT463_LOAD_ADDR(par, 0x0000); |
| 381 | TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG); | 381 | TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG); |
| 382 | 382 | ||
| 383 | #ifdef CONFIG_HW_CONSOLE | 383 | #ifdef CONFIG_VT |
| 384 | for (i = 0; i < 16; i++) { | 384 | for (i = 0; i < 16; i++) { |
| 385 | int j = color_table[i]; | 385 | int j = color_table[i]; |
| 386 | 386 | ||
| @@ -78,5 +78,15 @@ config W1_MASTER_SGI · 77 unmodified lines | |||
| 78 | This support is also available as a module. If so, the module | 78 | This support is also available as a module. If so, the module |
| 79 | will be called sgi_w1. | 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 | endmenu | 91 | endmenu |
| 82 | 92 | ||
| @@ -12,3 +12,4 @@ obj-$(CONFIG_W1_MASTER_MXC) += mxc_w1.o · 11 unmodified lines | |||
| 12 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o | 12 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o |
| 13 | obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o | 13 | obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o |
| 14 | obj-$(CONFIG_W1_MASTER_SGI) += sgi_w1.o | 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 | * disassociate the w1 device from the driver | 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 | struct mxc_w1_device *mdev = platform_get_drvdata(pdev); | 156 | struct mxc_w1_device *mdev = platform_get_drvdata(pdev); |
| 157 | 157 | ||
| 158 | w1_remove_master_device(&mdev->bus_master); | 158 | w1_remove_master_device(&mdev->bus_master); |
| 159 | 159 | ||
| 160 | clk_disable_unprepare(mdev->clk); | 160 | clk_disable_unprepare(mdev->clk); |
| 161 | |||
| 162 | return 0; | ||
| 163 | } | 161 | } |
| 164 | 162 | ||
| 165 | static const struct of_device_id mxc_w1_dt_ids[] = { | 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 | .of_match_table = mxc_w1_dt_ids, | 172 | .of_match_table = mxc_w1_dt_ids, |
| 175 | }, | 173 | }, |
| 176 | .probe = mxc_w1_probe, | 174 | .probe = mxc_w1_probe, |
| 177 | .remove = mxc_w1_remove, | 175 | .remove_new = mxc_w1_remove, |
| 178 | }; | 176 | }; |
| 179 | module_platform_driver(mxc_w1_driver); | 177 | module_platform_driver(mxc_w1_driver); |
| 180 | 178 | ||
| @@ -647,7 +647,7 @@ err_w1: · 646 unmodified lines | |||
| 647 | return ret; | 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 | int active; | 652 | int active; |
| 653 | 653 | ||
| @@ -661,8 +661,6 @@ static int omap_hdq_remove(struct platform_device *pdev) · 7 unmodified lines | |||
| 661 | if (active >= 0) | 661 | if (active >= 0) |
| 662 | pm_runtime_put_sync(&pdev->dev); | 662 | pm_runtime_put_sync(&pdev->dev); |
| 663 | pm_runtime_disable(&pdev->dev); | 663 | pm_runtime_disable(&pdev->dev); |
| 664 | |||
| 665 | return 0; | ||
| 666 | } | 664 | } |
| 667 | 665 | ||
| 668 | static const struct of_device_id omap_hdq_dt_ids[] = { | 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 | static struct platform_driver omap_hdq_driver = { | 673 | static struct platform_driver omap_hdq_driver = { |
| 676 | .probe = omap_hdq_probe, | 674 | .probe = omap_hdq_probe, |
| 677 | .remove = omap_hdq_remove, | 675 | .remove_new = omap_hdq_remove, |
| 678 | .driver = { | 676 | .driver = { |
| 679 | .name = "omap_hdq", | 677 | .name = "omap_hdq", |
| 680 | .of_match_table = omap_hdq_dt_ids, | 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 | * disassociate the w1 device from the driver | 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 | struct sgi_w1_device *sdev = platform_get_drvdata(pdev); | 110 | struct sgi_w1_device *sdev = platform_get_drvdata(pdev); |
| 111 | 111 | ||
| 112 | w1_remove_master_device(&sdev->bus_master); | 112 | w1_remove_master_device(&sdev->bus_master); |
| 113 | |||
| 114 | return 0; | ||
| 115 | } | 113 | } |
| 116 | 114 | ||
| 117 | static struct platform_driver sgi_w1_driver = { | 115 | static struct platform_driver sgi_w1_driver = { |
| @@ -119,7 +117,7 @@ static struct platform_driver sgi_w1_driver = { · 1 unmodified line | |||
| 119 | .name = "sgi_w1", | 117 | .name = "sgi_w1", |
| 120 | }, | 118 | }, |
| 121 | .probe = sgi_w1_probe, | 119 | .probe = sgi_w1_probe, |
| 122 | .remove = sgi_w1_remove, | 120 | .remove_new = sgi_w1_remove, |
| 123 | }; | 121 | }; |
| 124 | module_platform_driver(sgi_w1_driver); | 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 | return 0; | 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 | struct w1_bus_master *master = platform_get_drvdata(pdev); | 146 | struct w1_bus_master *master = platform_get_drvdata(pdev); |
| 147 | struct w1_gpio_ddata *ddata = master->data; | 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 | gpiod_set_value(ddata->pullup_gpiod, 0); | 150 | gpiod_set_value(ddata->pullup_gpiod, 0); |
| 151 | 151 | ||
| 152 | w1_remove_master_device(master); | 152 | w1_remove_master_device(master); |
| 153 | |||
| 154 | return 0; | ||
| 155 | } | 153 | } |
| 156 | 154 | ||
| 157 | static struct platform_driver w1_gpio_driver = { | 155 | static struct platform_driver w1_gpio_driver = { |
| @@ -160,7 +158,7 @@ static struct platform_driver w1_gpio_driver = { · 2 unmodified lines | |||
| 160 | .of_match_table = of_match_ptr(w1_gpio_dt_ids), | 158 | .of_match_table = of_match_ptr(w1_gpio_dt_ids), |
| 161 | }, | 159 | }, |
| 162 | .probe = w1_gpio_probe, | 160 | .probe = w1_gpio_probe, |
| 163 | .remove = w1_gpio_remove, | 161 | .remove_new = w1_gpio_remove, |
| 164 | }; | 162 | }; |
| 165 | 163 | ||
| 166 | module_platform_driver(w1_gpio_driver); | 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 | static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env); | 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 | .name = "w1", | 171 | .name = "w1", |
| 172 | .uevent = w1_uevent, | 172 | .uevent = w1_uevent, |
| 173 | }; | 173 | }; |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <linux/bits.h> | 18 | #include <linux/bits.h> |
| 19 | #include <linux/rculist.h> | 19 | #include <linux/rculist.h> |
| 20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
| 21 | #include <linux/vesa.h> | ||
| 21 | 22 | ||
| 22 | struct vc_data; | 23 | struct vc_data; |
| 23 | struct console_font_op; | 24 | struct console_font_op; |
| @@ -36,63 +37,91 @@ enum vc_intensity; · 12 unmodified lines | |||
| 36 | /** | 37 | /** |
| 37 | * struct consw - callbacks for consoles | 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 | * @con_scroll: move lines from @top to @bottom in direction @dir by @lines. | 50 | * @con_scroll: move lines from @top to @bottom in direction @dir by @lines. |
| 40 | * Return true if no generic handling should be done. | 51 | * Return true if no generic handling should be done. |
| 41 | * Invoked by csi_M and printing to the console. | 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 | * @con_scrolldelta: the contents of the console should be scrolled by @lines. | 67 | * @con_scrolldelta: the contents of the console should be scrolled by @lines. |
| 44 | * Invoked by user. (optional) | 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 | struct consw { | 86 | struct consw { |
| 47 | struct module *owner; | 87 | struct module *owner; |
| 48 | const char *(*con_startup)(void); | 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 | void (*con_deinit)(struct vc_data *vc); | 90 | void (*con_deinit)(struct vc_data *vc); |
| 51 | void (*con_clear)(struct vc_data *vc, int sy, int sx, int height, | 91 | void (*con_clear)(struct vc_data *vc, unsigned int y, |
| 52 | int width); | 92 | unsigned int x, unsigned int count); |
| 53 | void (*con_putc)(struct vc_data *vc, int c, int ypos, int xpos); | 93 | void (*con_putc)(struct vc_data *vc, u16 ca, unsigned int y, |
| 54 | void (*con_putcs)(struct vc_data *vc, const unsigned short *s, | 94 | unsigned int x); |
| 55 | int count, int ypos, int xpos); | 95 | void (*con_putcs)(struct vc_data *vc, const u16 *s, |
| 56 | void (*con_cursor)(struct vc_data *vc, int mode); | 96 | unsigned int count, unsigned int ypos, |
| 97 | unsigned int xpos); | ||
| 98 | void (*con_cursor)(struct vc_data *vc, bool enable); | ||
| 57 | bool (*con_scroll)(struct vc_data *vc, unsigned int top, | 99 | bool (*con_scroll)(struct vc_data *vc, unsigned int top, |
| 58 | unsigned int bottom, enum con_scroll dir, | 100 | unsigned int bottom, enum con_scroll dir, |
| 59 | unsigned int lines); | 101 | unsigned int lines); |
| 60 | int (*con_switch)(struct vc_data *vc); | 102 | bool (*con_switch)(struct vc_data *vc); |
| 61 | int (*con_blank)(struct vc_data *vc, int blank, int mode_switch); | 103 | bool (*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank, |
| 62 | int (*con_font_set)(struct vc_data *vc, struct console_font *font, | 104 | bool mode_switch); |
| 63 | unsigned int vpitch, unsigned int flags); | 105 | int (*con_font_set)(struct vc_data *vc, |
| 106 | const struct console_font *font, | ||
| 107 | unsigned int vpitch, unsigned int flags); | ||
| 64 | int (*con_font_get)(struct vc_data *vc, struct console_font *font, | 108 | int (*con_font_get)(struct vc_data *vc, struct console_font *font, |
| 65 | unsigned int vpitch); | 109 | unsigned int vpitch); |
| 66 | int (*con_font_default)(struct vc_data *vc, | 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 | int (*con_resize)(struct vc_data *vc, unsigned int width, | 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 | void (*con_set_palette)(struct vc_data *vc, | 114 | void (*con_set_palette)(struct vc_data *vc, |
| 71 | const unsigned char *table); | 115 | const unsigned char *table); |
| 72 | void (*con_scrolldelta)(struct vc_data *vc, int lines); | 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 | void (*con_save_screen)(struct vc_data *vc); | 118 | void (*con_save_screen)(struct vc_data *vc); |
| 75 | u8 (*con_build_attr)(struct vc_data *vc, u8 color, | 119 | u8 (*con_build_attr)(struct vc_data *vc, u8 color, |
| 76 | enum vc_intensity intensity, | 120 | enum vc_intensity intensity, |
| 77 | bool blink, bool underline, bool reverse, bool italic); | 121 | bool blink, bool underline, bool reverse, bool italic); |
| 78 | void (*con_invert_region)(struct vc_data *vc, u16 *p, int count); | 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); | 123 | void (*con_debug_enter)(struct vc_data *vc); |
| 80 | unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position, | 124 | void (*con_debug_leave)(struct vc_data *vc); |
| 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); | ||
| 96 | }; | 125 | }; |
| 97 | 126 | ||
| 98 | extern const struct consw *conswitchp; | 127 | extern const struct consw *conswitchp; |
| @@ -112,32 +141,21 @@ int con_is_bound(const struct consw *csw); · 13 unmodified lines | |||
| 112 | int do_unregister_con_driver(const struct consw *csw); | 141 | int do_unregister_con_driver(const struct consw *csw); |
| 113 | int do_take_over_console(const struct consw *sw, int first, int last, int deflt); | 142 | int do_take_over_console(const struct consw *sw, int first, int last, int deflt); |
| 114 | void give_up_console(const struct consw *sw); | 143 | void give_up_console(const struct consw *sw); |
| 115 | #ifdef CONFIG_HW_CONSOLE | 144 | #ifdef CONFIG_VT |
| 116 | int con_debug_enter(struct vc_data *vc); | 145 | void con_debug_enter(struct vc_data *vc); |
| 117 | int con_debug_leave(void); | 146 | void con_debug_leave(void); |
| 118 | #else | 147 | #else |
| 119 | static inline int con_debug_enter(struct vc_data *vc) | 148 | static inline void con_debug_enter(struct vc_data *vc) { } |
| 120 | { | 149 | static inline void con_debug_leave(void) { } |
| 121 | return 0; | ||
| 122 | } | ||
| 123 | static inline int con_debug_leave(void) | ||
| 124 | { | ||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | #endif | 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 | * The interface for a console, or any other device that wants to capture | 153 | * The interface for a console, or any other device that wants to capture |
| 136 | * console messages (printer driver?) | 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 | * @CON_PRINTBUFFER: Used by newly registered consoles to avoid duplicate | 159 | * @CON_PRINTBUFFER: Used by newly registered consoles to avoid duplicate |
| 142 | * output of messages that were already shown by boot | 160 | * output of messages that were already shown by boot |
| 143 | * consoles or read by userspace via syslog() syscall. | 161 | * consoles or read by userspace via syslog() syscall. |
| @@ -218,7 +236,7 @@ struct nbcon_state { · 74 unmodified lines | |||
| 218 | static_assert(sizeof(struct nbcon_state) <= sizeof(int)); | 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 | * @NBCON_PRIO_NONE: Unused | 240 | * @NBCON_PRIO_NONE: Unused |
| 223 | * @NBCON_PRIO_NORMAL: Normal (non-emergency) usage | 241 | * @NBCON_PRIO_NORMAL: Normal (non-emergency) usage |
| 224 | * @NBCON_PRIO_EMERGENCY: Emergency output (WARN/OOPS...) | 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 | * for_each_console() - Iterator over registered consoles | 468 | * for_each_console() - Iterator over registered consoles |
| 451 | * @con: struct console pointer used as loop cursor | 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 | * Requires console_list_lock to be held. | 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 | extern atomic_t ignore_console_lock_warning; | 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 | extern void console_init(void); | 541 | extern void console_init(void); |
| 530 | 542 | ||
| 531 | /* For deferred console takeover */ | 543 | /* For deferred console takeover */ |
| @@ -151,7 +151,6 @@ struct vc_data { · 150 unmodified lines | |||
| 151 | DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */ | 151 | DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */ |
| 152 | unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */ | 152 | unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */ |
| 153 | unsigned short * vc_translate; | 153 | unsigned short * vc_translate; |
| 154 | unsigned int vc_resize_user; /* resize request from user */ | ||
| 155 | unsigned int vc_bell_pitch; /* Console bell pitch */ | 154 | unsigned int vc_bell_pitch; /* Console bell pitch */ |
| 156 | unsigned int vc_bell_duration; /* Console bell duration */ | 155 | unsigned int vc_bell_duration; /* Console bell duration */ |
| 157 | unsigned short vc_cur_blink_ms; /* Cursor blink duration */ | 156 | unsigned short vc_cur_blink_ms; /* Cursor blink duration */ |
| @@ -14,17 +14,16 @@ · 13 unmodified lines | |||
| 14 | struct tty_struct; | 14 | struct tty_struct; |
| 15 | struct vc_data; | 15 | struct vc_data; |
| 16 | 16 | ||
| 17 | extern void clear_selection(void); | 17 | void clear_selection(void); |
| 18 | extern int set_selection_user(const struct tiocl_selection __user *sel, | 18 | int set_selection_user(const struct tiocl_selection __user *sel, |
| 19 | struct tty_struct *tty); | 19 | struct tty_struct *tty); |
| 20 | extern int set_selection_kernel(struct tiocl_selection *v, | 20 | int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty); |
| 21 | struct tty_struct *tty); | 21 | int paste_selection(struct tty_struct *tty); |
| 22 | extern int paste_selection(struct tty_struct *tty); | 22 | int sel_loadlut(u32 __user *lut); |
| 23 | extern int sel_loadlut(char __user *p); | 23 | int mouse_reporting(void); |
| 24 | extern int mouse_reporting(void); | 24 | void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry); |
| 25 | extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry); | 25 | |
| 26 | 26 | bool vc_is_sel(const struct vc_data *vc); | |
| 27 | bool vc_is_sel(struct vc_data *vc); | ||
| 28 | 27 | ||
| 29 | extern int console_blanked; | 28 | extern int console_blanked; |
| 30 | 29 | ||
| @@ -33,24 +32,21 @@ extern unsigned char default_red[]; · 2 unmodified lines | |||
| 33 | extern unsigned char default_grn[]; | 32 | extern unsigned char default_grn[]; |
| 34 | extern unsigned char default_blu[]; | 33 | extern unsigned char default_blu[]; |
| 35 | 34 | ||
| 36 | extern unsigned short *screen_pos(const struct vc_data *vc, int w_offset, | 35 | unsigned short *screen_pos(const struct vc_data *vc, int w_offset, bool viewed); |
| 37 | bool viewed); | 36 | u16 screen_glyph(const struct vc_data *vc, int offset); |
| 38 | extern u16 screen_glyph(const struct vc_data *vc, int offset); | 37 | u32 screen_glyph_unicode(const struct vc_data *vc, int offset); |
| 39 | extern u32 screen_glyph_unicode(const struct vc_data *vc, int offset); | 38 | void complement_pos(struct vc_data *vc, int offset); |
| 40 | extern void complement_pos(struct vc_data *vc, int offset); | 39 | void invert_screen(struct vc_data *vc, int offset, int count, bool viewed); |
| 41 | extern void invert_screen(struct vc_data *vc, int offset, int count, bool viewed); | 40 | |
| 42 | 41 | void getconsxy(const struct vc_data *vc, unsigned char xy[static 2]); | |
| 43 | extern 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]); |
| 44 | extern void putconsxy(struct vc_data *vc, unsigned char xy[static const 2]); | 43 | |
| 45 | 44 | u16 vcs_scr_readw(const struct vc_data *vc, const u16 *org); | |
| 46 | extern 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); |
| 47 | extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org); | 46 | void vcs_scr_updated(struct vc_data *vc); |
| 48 | extern void vcs_scr_updated(struct vc_data *vc); | 47 | |
| 49 | 48 | int vc_uniscr_check(struct vc_data *vc); | |
| 50 | extern int vc_uniscr_check(struct vc_data *vc); | 49 | void vc_uniscr_copy_line(const struct vc_data *vc, void *dest, bool viewed, |
| 51 | extern void vc_uniscr_copy_line(const struct vc_data *vc, void *dest, | 50 | unsigned int row, unsigned int col, unsigned int nr); |
| 52 | bool viewed, | ||
| 53 | unsigned int row, unsigned int col, | ||
| 54 | unsigned int nr); | ||
| 55 | 51 | ||
| 56 | #endif | 52 | #endif |
| @@ -27,7 +27,7 @@ struct serdev_device; · 26 unmodified lines | |||
| 27 | * not sleep. | 27 | * not sleep. |
| 28 | */ | 28 | */ |
| 29 | struct serdev_device_ops { | 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 | void (*write_wakeup)(struct serdev_device *); | 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 | serdev->ops->write_wakeup(serdev); | 185 | serdev->ops->write_wakeup(serdev); |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | static inline ssize_t serdev_controller_receive_buf(struct serdev_controller *ctrl, | 188 | static inline size_t serdev_controller_receive_buf(struct serdev_controller *ctrl, |
| 189 | const u8 *data, | 189 | const u8 *data, |
| 190 | size_t count) | 190 | size_t count) |
| 191 | { | 191 | { |
| 192 | struct serdev_device *serdev = ctrl->serdev; | 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 | void serial8250_set_isa_configurator(void (*v)(int port, struct uart_port *up, | 210 | void serial8250_set_isa_configurator(void (*v)(int port, struct uart_port *up, |
| 211 | u32 *capabilities)); | 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 | #ifdef CONFIG_SERIAL_8250_RT288X | 219 | #ifdef CONFIG_SERIAL_8250_RT288X |
| 214 | int rt288x_setup(struct uart_port *p); | 220 | int rt288x_setup(struct uart_port *p); |
| 215 | int au_platform_setup(struct plat_serial8250_port *p); | 221 | int au_platform_setup(struct plat_serial8250_port *p); |
| @@ -467,9 +467,10 @@ struct uart_port { · 466 unmodified lines | |||
| 467 | unsigned int fifosize; /* tx fifo size */ | 467 | unsigned int fifosize; /* tx fifo size */ |
| 468 | unsigned char x_char; /* xon/xoff char */ | 468 | unsigned char x_char; /* xon/xoff char */ |
| 469 | unsigned char regshift; /* reg offset shift */ | 469 | unsigned char regshift; /* reg offset shift */ |
| 470 | |||
| 470 | unsigned char iotype; /* io access style */ | 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 | #define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */ | 474 | #define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */ |
| 474 | #define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */ | 475 | #define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */ |
| 475 | #define UPIO_MEM (SERIAL_IO_MEM) /* driver-specific */ | 476 | #define UPIO_MEM (SERIAL_IO_MEM) /* driver-specific */ |
| @@ -479,7 +480,9 @@ struct uart_port { · 3 unmodified lines | |||
| 479 | #define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */ | 480 | #define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */ |
| 480 | #define UPIO_MEM16 (SERIAL_IO_MEM16) /* 16b little endian */ | 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 | #define UPQ_NO_TXEN_TEST BIT(0) | 486 | #define UPQ_NO_TXEN_TEST BIT(0) |
| 484 | 487 | ||
| 485 | unsigned int read_status_mask; /* driver specific */ | 488 | unsigned int read_status_mask; /* driver specific */ |
| @@ -786,7 +789,8 @@ enum UART_TX_FLAGS { · 300 unmodified lines | |||
| 786 | if (pending < WAKEUP_CHARS) { \ | 789 | if (pending < WAKEUP_CHARS) { \ |
| 787 | uart_write_wakeup(__port); \ | 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 | __port->ops->stop_tx(__port); \ | 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 | void uart_unregister_driver(struct uart_driver *uart); | 963 | void uart_unregister_driver(struct uart_driver *uart); |
| 960 | int uart_add_one_port(struct uart_driver *reg, struct uart_port *port); | 964 | int uart_add_one_port(struct uart_driver *reg, struct uart_port *port); |
| 961 | void uart_remove_one_port(struct uart_driver *reg, struct uart_port *port); | 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 | bool uart_match_port(const struct uart_port *port1, | 968 | bool uart_match_port(const struct uart_port *port1, |
| 963 | const struct uart_port *port2); | 969 | const struct uart_port *port2); |
| 964 | 970 | ||
| @@ -178,6 +178,7 @@ struct geni_se { · 177 unmodified lines | |||
| 178 | #define M_GP_IRQ_3_EN BIT(12) | 178 | #define M_GP_IRQ_3_EN BIT(12) |
| 179 | #define M_GP_IRQ_4_EN BIT(13) | 179 | #define M_GP_IRQ_4_EN BIT(13) |
| 180 | #define M_GP_IRQ_5_EN BIT(14) | 180 | #define M_GP_IRQ_5_EN BIT(14) |
| 181 | #define M_TX_FIFO_NOT_EMPTY_EN BIT(21) | ||
| 181 | #define M_IO_DATA_DEASSERT_EN BIT(22) | 182 | #define M_IO_DATA_DEASSERT_EN BIT(22) |
| 182 | #define M_IO_DATA_ASSERT_EN BIT(23) | 183 | #define M_IO_DATA_ASSERT_EN BIT(23) |
| 183 | #define M_RX_FIFO_RD_ERR_EN BIT(24) | 184 | #define M_RX_FIFO_RD_ERR_EN BIT(24) |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | |||
| 6 | #include <linux/major.h> | 6 | #include <linux/major.h> |
| 7 | #include <linux/termios.h> | 7 | #include <linux/termios.h> |
| 8 | #include <linux/workqueue.h> | 8 | #include <linux/workqueue.h> |
| 9 | #include <linux/tty_buffer.h> | ||
| 10 | #include <linux/tty_driver.h> | 9 | #include <linux/tty_driver.h> |
| 11 | #include <linux/tty_ldisc.h> | 10 | #include <linux/tty_ldisc.h> |
| 12 | #include <linux/tty_port.h> | 11 | #include <linux/tty_port.h> |
| @@ -25,7 +25,8 @@ extern int fg_console, last_console, want_console; · 24 unmodified lines | |||
| 25 | 25 | ||
| 26 | int vc_allocate(unsigned int console); | 26 | int vc_allocate(unsigned int console); |
| 27 | int vc_cons_allocated(unsigned int console); | 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 | struct vc_data *vc_deallocate(unsigned int console); | 30 | struct vc_data *vc_deallocate(unsigned int console); |
| 30 | void reset_palette(struct vc_data *vc); | 31 | void reset_palette(struct vc_data *vc); |
| 31 | void do_blank_screen(int entering_gfx); | 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 | #define update_screen(x) redraw_screen(x, 0) | 43 | #define update_screen(x) redraw_screen(x, 0) |
| 43 | #define switch_screen(x) redraw_screen(x, 1) | 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 | struct tty_struct; | 52 | struct tty_struct; |
| 46 | int tioclinux(struct tty_struct *tty, unsigned long arg); | 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 | void vt_kbd_con_start(unsigned int console); | 175 | void vt_kbd_con_start(unsigned int console); |
| 169 | void vt_kbd_con_stop(unsigned int console); | 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 | #endif /* _VT_KERN_H */ | 178 | #endif /* _VT_KERN_H */ |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | #include <linux/i2c.h> | 6 | #include <linux/i2c.h> |
| 7 | #include <linux/vesa.h> | ||
| 7 | 8 | ||
| 8 | /* Definitions of frame buffers */ | 9 | /* Definitions of frame buffers */ |
| 9 | 10 | ||
| @@ -293,13 +294,6 @@ struct fb_con2fbmap { · 283 unmodified lines | |||
| 293 | __u32 framebuffer; | 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 | enum { | 297 | enum { |
| 304 | /* screen: unblanked, hsync: on, vsync: on */ | 298 | /* screen: unblanked, hsync: on, vsync: on */ |
| 305 | FB_BLANK_UNBLANK = VESA_NO_BLANKING, | 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 | early_param("keep_bootcon", keep_bootcon_setup); | 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 | * This is called by register_console() to try to match | 3288 | * This is called by register_console() to try to match |
| 3274 | * the newly registered console with any of the ones selected | 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 | if (_braille_register_console(newcon, c)) | 3319 | if (_braille_register_console(newcon, c)) |
| 3305 | return 0; | 3320 | return 0; |
| 3306 | 3321 | ||
| 3307 | if (newcon->setup && | 3322 | err = console_call_setup(newcon, c->options); |
| 3308 | (err = newcon->setup(newcon, c->options)) != 0) | 3323 | if (err) |
| 3309 | return err; | 3324 | return err; |
| 3310 | } | 3325 | } |
| 3311 | newcon->flags |= CON_ENABLED; | 3326 | newcon->flags |= CON_ENABLED; |
| @@ -3331,7 +3346,7 @@ static void try_enable_default_console(struct console *newcon) · 19 unmodified lines | |||
| 3331 | if (newcon->index < 0) | 3346 | if (newcon->index < 0) |
| 3332 | newcon->index = 0; | 3347 | newcon->index = 0; |
| 3333 | 3348 | ||
| 3334 | if (newcon->setup && newcon->setup(newcon, NULL) != 0) | 3349 | if (console_call_setup(newcon, NULL) != 0) |
| 3335 | return; | 3350 | return; |
| 3336 | 3351 | ||
| 3337 | newcon->flags |= CON_ENABLED; | 3352 | newcon->flags |= CON_ENABLED; |
| @@ -43,7 +43,7 @@ config KGDB_SERIAL_CONSOLE · 42 unmodified lines | |||
| 43 | tristate "KGDB: use kgdb over the serial console" | 43 | tristate "KGDB: use kgdb over the serial console" |
| 44 | select CONSOLE_POLL | 44 | select CONSOLE_POLL |
| 45 | select MAGIC_SYSRQ | 45 | select MAGIC_SYSRQ |
| 46 | depends on TTY && HW_CONSOLE | 46 | depends on TTY && VT |
| 47 | default y | 47 | default y |
| 48 | help | 48 | help |
| 49 | Share a serial console with kgdb. Sysrq-g must be used | 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 | snd_serial_generic_tx_wakeup(drvdata); | 100 | snd_serial_generic_tx_wakeup(drvdata); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | static ssize_t snd_serial_generic_receive_buf(struct serdev_device *serdev, | 103 | static size_t snd_serial_generic_receive_buf(struct serdev_device *serdev, |
| 104 | const u8 *buf, size_t count) | 104 | const u8 *buf, size_t count) |
| 105 | { | 105 | { |
| 106 | int ret; | 106 | int ret; |
| 107 | struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev); | 107 | struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev); |