TTY/Serial driver update for 6.9-rc1
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZfwqow8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ynNegCffxTbsnbMGjWhVrQ326IJx/DFvNMAoI9csigv m+G3RzefzZLRx8nAma0c =GMfc -----END PGP SIGNATURE----- Merge tag 'tty-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty 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(). ...
This commit is contained in:
commit
3bcb0bf65c
|
@ -55,6 +55,7 @@ required:
|
|||
|
||||
allOf:
|
||||
- $ref: serial.yaml#
|
||||
- $ref: rs485.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
@ -30,6 +30,7 @@ properties:
|
|||
- items:
|
||||
- enum:
|
||||
- fsl,imx93-lpuart
|
||||
- fsl,imx95-lpuart
|
||||
- const: fsl,imx8ulp-lpuart
|
||||
- const: fsl,imx7ulp-lpuart
|
||||
- items:
|
||||
|
|
|
@ -59,6 +59,7 @@ properties:
|
|||
- renesas,hscif-r8a779a0 # R-Car V3U
|
||||
- renesas,hscif-r8a779f0 # R-Car S4-8
|
||||
- renesas,hscif-r8a779g0 # R-Car V4H
|
||||
- renesas,hscif-r8a779h0 # R-Car V4M
|
||||
- const: renesas,rcar-gen4-hscif # R-Car Gen4
|
||||
- const: renesas,hscif # generic HSCIF compatible UART
|
||||
|
||||
|
|
|
@ -143,6 +143,8 @@ allOf:
|
|||
then:
|
||||
required:
|
||||
- samsung,uart-fifosize
|
||||
properties:
|
||||
reg-io-width: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ properties:
|
|||
TX FIFO threshold configuration (in bytes).
|
||||
|
||||
patternProperties:
|
||||
"^(bluetooth|bluetooth-gnss|gnss|gps|mcu)$":
|
||||
"^(bluetooth|bluetooth-gnss|gnss|gps|mcu|onewire)$":
|
||||
if:
|
||||
type: object
|
||||
then:
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/serial/st,asc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: STMicroelectronics STi SoCs Serial Port
|
||||
|
||||
maintainers:
|
||||
- Patrice Chotard <patrice.chotard@foss.st.com>
|
||||
|
||||
allOf:
|
||||
- $ref: serial.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: st,asc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
st,hw-flow-ctrl:
|
||||
description: When set, enable hardware flow control.
|
||||
type: boolean
|
||||
|
||||
st,force-m1:
|
||||
description: When set, force asc to be in Mode-1. This is recommended for
|
||||
high bit rates above 19.2K.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/stih407-clks.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
serial@9830000 {
|
||||
compatible = "st,asc";
|
||||
reg = <0x9830000 0x2c>;
|
||||
interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
|
||||
};
|
||||
...
|
|
@ -58,6 +58,9 @@ properties:
|
|||
|
||||
wakeup-source: true
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
rx-threshold:
|
||||
description:
|
||||
If value is set to 1, RX FIFO threshold is disabled.
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
*st-asc(Serial Port)
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "st,asc".
|
||||
- reg, reg-names, interrupts, interrupt-names : Standard way to define device
|
||||
resources with names. look in
|
||||
Documentation/devicetree/bindings/resource-names.txt
|
||||
|
||||
Optional properties:
|
||||
- st,hw-flow-ctrl bool flag to enable hardware flow control.
|
||||
- st,force-m1 bool flat to force asc to be in Mode-1 recommended
|
||||
for high bit rates (above 19.2K)
|
||||
Example:
|
||||
serial@fe440000{
|
||||
compatible = "st,asc";
|
||||
reg = <0xfe440000 0x2c>;
|
||||
interrupts = <0 209 0>;
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/w1/w1-uart.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: UART 1-Wire Bus
|
||||
|
||||
maintainers:
|
||||
- Christoph Winklhofer <cj.winklhofer@gmail.com>
|
||||
|
||||
description: |
|
||||
UART 1-wire bus. Utilizes the UART interface via the Serial Device Bus
|
||||
to create the 1-Wire timing patterns.
|
||||
|
||||
The UART peripheral must support full-duplex and operate in open-drain
|
||||
mode. The timing patterns are generated by a specific combination of
|
||||
baud-rate and transmitted byte, which corresponds to a 1-Wire read bit,
|
||||
write bit or reset pulse.
|
||||
|
||||
The default baud-rate for reset and presence detection is 9600 and for
|
||||
a 1-Wire read or write operation 115200. In case the actual baud-rate
|
||||
is different from the requested one, the transmitted byte is adapted
|
||||
to generate the 1-Wire timing patterns.
|
||||
|
||||
https://www.analog.com/en/technical-articles/using-a-uart-to-implement-a-1wire-bus-master.html
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: w1-uart
|
||||
|
||||
reset-bps:
|
||||
default: 9600
|
||||
description:
|
||||
The baud rate for the 1-Wire reset and presence detect.
|
||||
|
||||
write-0-bps:
|
||||
default: 115200
|
||||
description:
|
||||
The baud rate for the 1-Wire write-0 cycle.
|
||||
|
||||
write-1-bps:
|
||||
default: 115200
|
||||
description:
|
||||
The baud rate for the 1-Wire write-1 and read cycle.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties:
|
||||
type: object
|
||||
|
||||
examples:
|
||||
- |
|
||||
serial {
|
||||
onewire {
|
||||
compatible = "w1-uart";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,45 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======
|
||||
Console
|
||||
=======
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Struct Console
|
||||
==============
|
||||
|
||||
.. kernel-doc:: include/linux/console.h
|
||||
:identifiers: console cons_flags
|
||||
|
||||
Internals
|
||||
---------
|
||||
|
||||
.. kernel-doc:: include/linux/console.h
|
||||
:identifiers: nbcon_state nbcon_prio nbcon_context nbcon_write_context
|
||||
|
||||
Struct Consw
|
||||
============
|
||||
|
||||
.. kernel-doc:: include/linux/console.h
|
||||
:identifiers: consw
|
||||
|
||||
Console functions
|
||||
=================
|
||||
|
||||
.. kernel-doc:: include/linux/console.h
|
||||
:identifiers: console_srcu_read_flags console_srcu_write_flags
|
||||
console_is_registered for_each_console_srcu for_each_console
|
||||
|
||||
.. kernel-doc:: drivers/tty/vt/selection.c
|
||||
:export:
|
||||
.. kernel-doc:: drivers/tty/vt/vt.c
|
||||
:export:
|
||||
|
||||
Internals
|
||||
---------
|
||||
|
||||
.. kernel-doc:: drivers/tty/vt/selection.c
|
||||
:internal:
|
||||
.. kernel-doc:: drivers/tty/vt/vt.c
|
||||
:internal:
|
|
@ -38,6 +38,7 @@ In-detail description of the named TTY structures is in separate documents:
|
|||
tty_buffer
|
||||
tty_ioctl
|
||||
tty_internals
|
||||
console
|
||||
|
||||
Writing TTY Driver
|
||||
==================
|
||||
|
|
|
@ -12,3 +12,4 @@
|
|||
mxc-w1
|
||||
omap-hdq
|
||||
w1-gpio
|
||||
w1-uart
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
=====================
|
||||
Kernel driver w1-uart
|
||||
=====================
|
||||
|
||||
Author: Christoph Winklhofer <cj.winklhofer@gmail.com>
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
UART 1-Wire bus driver. The driver utilizes the UART interface via the
|
||||
Serial Device Bus to create the 1-Wire timing patterns as described in
|
||||
the document `"Using a UART to Implement a 1-Wire Bus Master"`_.
|
||||
|
||||
.. _"Using a UART to Implement a 1-Wire Bus Master": https://www.analog.com/en/technical-articles/using-a-uart-to-implement-a-1wire-bus-master.html
|
||||
|
||||
In short, the UART peripheral must support full-duplex and operate in
|
||||
open-drain mode. The timing patterns are generated by a specific
|
||||
combination of baud-rate and transmitted byte, which corresponds to a
|
||||
1-Wire read bit, write bit or reset pulse.
|
||||
|
||||
For instance the timing pattern for a 1-Wire reset and presence detect uses
|
||||
the baud-rate 9600, i.e. 104.2 us per bit. The transmitted byte 0xf0 over
|
||||
UART (least significant bit first, start-bit low) sets the reset low time
|
||||
for 1-Wire to 521 us. A present 1-Wire device changes the received byte by
|
||||
pulling the line low, which is used by the driver to evaluate the result of
|
||||
the 1-Wire operation.
|
||||
|
||||
Similar for a 1-Wire read bit or write bit, which uses the baud-rate
|
||||
115200, i.e. 8.7 us per bit. The transmitted byte 0x80 is used for a
|
||||
Write-0 operation (low time 69.6us) and the byte 0xff for Read-0, Read-1
|
||||
and Write-1 (low time 8.7us).
|
||||
|
||||
The default baud-rate for reset and presence detection is 9600 and for
|
||||
a 1-Wire read or write operation 115200. In case the actual baud-rate
|
||||
is different from the requested one, the transmitted byte is adapted
|
||||
to generate the 1-Wire timing patterns.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Specify the UART 1-wire bus in the device tree by adding the single child
|
||||
onewire to the serial node (e.g. uart0). For example:
|
||||
::
|
||||
|
||||
@uart0 {
|
||||
...
|
||||
onewire {
|
||||
compatible = "w1-uart";
|
||||
};
|
||||
};
|
|
@ -846,6 +846,6 @@ static void amiga_get_hardware_list(struct seq_file *m)
|
|||
* The Amiga keyboard driver needs key_maps, but we cannot export it in
|
||||
* drivers/char/defkeymap.c, as it is autogenerated
|
||||
*/
|
||||
#ifdef CONFIG_HW_CONSOLE
|
||||
#ifdef CONFIG_VT
|
||||
EXPORT_SYMBOL_GPL(key_maps);
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/console.h>
|
||||
|
@ -67,9 +68,6 @@ static char *hp300_models[] __initdata = {
|
|||
static char hp300_model_name[13] = "HP9000/";
|
||||
|
||||
extern void hp300_reset(void);
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
extern int hp300_setup_serial_console(void) __init;
|
||||
#endif
|
||||
|
||||
int __init hp300_parse_bootinfo(const struct bi_record *record)
|
||||
{
|
||||
|
@ -263,7 +261,5 @@ void __init config_hp300(void)
|
|||
} else {
|
||||
panic("Unknown HP9000 Model");
|
||||
}
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
hp300_setup_serial_console();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -383,8 +383,8 @@ static void btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count)
|
|||
}
|
||||
}
|
||||
|
||||
static ssize_t btmtkuart_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
static size_t btmtkuart_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
{
|
||||
struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
|
||||
|
||||
|
|
|
@ -1285,8 +1285,8 @@ static const struct h4_recv_pkt nxp_recv_pkts[] = {
|
|||
{ NXP_RECV_FW_REQ_V3, .recv = nxp_recv_fw_req_v3 },
|
||||
};
|
||||
|
||||
static ssize_t btnxpuart_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
static size_t btnxpuart_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
{
|
||||
struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
|
||||
|
||||
|
|
|
@ -271,8 +271,8 @@ static void hci_uart_write_wakeup(struct serdev_device *serdev)
|
|||
*
|
||||
* Return: number of processed bytes
|
||||
*/
|
||||
static ssize_t hci_uart_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
static size_t hci_uart_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
{
|
||||
struct hci_uart *hu = serdev_device_get_drvdata(serdev);
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ static const struct gnss_operations gnss_serial_gnss_ops = {
|
|||
.write_raw = gnss_serial_write_raw,
|
||||
};
|
||||
|
||||
static ssize_t gnss_serial_receive_buf(struct serdev_device *serdev,
|
||||
static size_t gnss_serial_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t count)
|
||||
{
|
||||
struct gnss_serial *gserial = serdev_device_get_drvdata(serdev);
|
||||
|
|
|
@ -160,7 +160,7 @@ static const struct gnss_operations sirf_gnss_ops = {
|
|||
.write_raw = sirf_write_raw,
|
||||
};
|
||||
|
||||
static ssize_t sirf_receive_buf(struct serdev_device *serdev,
|
||||
static size_t sirf_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t count)
|
||||
{
|
||||
struct sirf_data *data = serdev_device_get_drvdata(serdev);
|
||||
|
|
|
@ -271,7 +271,7 @@ static void hdlc_rx_frame(struct gb_beagleplay *bg)
|
|||
}
|
||||
}
|
||||
|
||||
static ssize_t hdlc_rx(struct gb_beagleplay *bg, const u8 *data, size_t count)
|
||||
static size_t hdlc_rx(struct gb_beagleplay *bg, const u8 *data, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
u8 c;
|
||||
|
@ -331,8 +331,8 @@ static void hdlc_deinit(struct gb_beagleplay *bg)
|
|||
flush_work(&bg->tx_work);
|
||||
}
|
||||
|
||||
static ssize_t gb_tty_receive(struct serdev_device *sd, const u8 *data,
|
||||
size_t count)
|
||||
static size_t gb_tty_receive(struct serdev_device *sd, const u8 *data,
|
||||
size_t count)
|
||||
{
|
||||
struct gb_beagleplay *bg = serdev_device_get_drvdata(sd);
|
||||
|
||||
|
|
|
@ -211,8 +211,8 @@ static bool pms7003_frame_is_okay(struct pms7003_frame *frame)
|
|||
return checksum == pms7003_calc_checksum(frame);
|
||||
}
|
||||
|
||||
static ssize_t pms7003_receive_buf(struct serdev_device *serdev, const u8 *buf,
|
||||
size_t size)
|
||||
static size_t pms7003_receive_buf(struct serdev_device *serdev, const u8 *buf,
|
||||
size_t size)
|
||||
{
|
||||
struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev);
|
||||
struct pms7003_state *state = iio_priv(indio_dev);
|
||||
|
|
|
@ -174,8 +174,8 @@ static int scd30_serdev_command(struct scd30_state *state, enum scd30_cmd cmd, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t scd30_serdev_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t size)
|
||||
static size_t scd30_serdev_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t size)
|
||||
{
|
||||
struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev);
|
||||
struct scd30_serdev_priv *priv;
|
||||
|
|
|
@ -210,8 +210,8 @@ static int sps30_serial_command(struct sps30_state *state, unsigned char cmd,
|
|||
return rsp_size;
|
||||
}
|
||||
|
||||
static ssize_t sps30_serial_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t size)
|
||||
static size_t sps30_serial_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t size)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev);
|
||||
struct sps30_serial_priv *priv;
|
||||
|
|
|
@ -378,8 +378,8 @@ static void bno055_ser_handle_rx(struct bno055_ser_priv *priv, int status)
|
|||
* Also, we assume to RX one pkt per time (i.e. the HW doesn't send anything
|
||||
* unless we require to AND we don't queue more than one request per time).
|
||||
*/
|
||||
static ssize_t bno055_ser_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t size)
|
||||
static size_t bno055_ser_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t size)
|
||||
{
|
||||
int status;
|
||||
struct bno055_ser_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
|
|
|
@ -26,7 +26,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
|||
MODULE_DESCRIPTION("Amiga keyboard driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifdef CONFIG_HW_CONSOLE
|
||||
#ifdef CONFIG_VT
|
||||
static unsigned char amikbd_keycode[0x78] __initdata = {
|
||||
[0] = KEY_GRAVE,
|
||||
[1] = KEY_1,
|
||||
|
@ -148,9 +148,9 @@ static void __init amikbd_init_console_keymaps(void)
|
|||
memcpy(key_maps[i], temp_map, sizeof(temp_map));
|
||||
}
|
||||
}
|
||||
#else /* !CONFIG_HW_CONSOLE */
|
||||
#else /* !CONFIG_VT */
|
||||
static inline void amikbd_init_console_keymaps(void) {}
|
||||
#endif /* !CONFIG_HW_CONSOLE */
|
||||
#endif /* !CONFIG_VT */
|
||||
|
||||
static const char *amikbd_messages[8] = {
|
||||
[0] = KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n",
|
||||
|
|
|
@ -471,8 +471,8 @@ static void rave_sp_receive_frame(struct rave_sp *sp,
|
|||
rave_sp_receive_reply(sp, data, length);
|
||||
}
|
||||
|
||||
static ssize_t rave_sp_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t size)
|
||||
static size_t rave_sp_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *buf, size_t size)
|
||||
{
|
||||
struct device *dev = &serdev->dev;
|
||||
struct rave_sp *sp = dev_get_drvdata(dev);
|
||||
|
|
|
@ -45,7 +45,7 @@ struct qcauart {
|
|||
unsigned char *tx_buffer;
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
static size_t
|
||||
qca_tty_receive(struct serdev_device *serdev, const u8 *data, size_t count)
|
||||
{
|
||||
struct qcauart *qca = serdev_device_get_drvdata(serdev);
|
||||
|
|
|
@ -203,8 +203,8 @@ static int pn532_uart_rx_is_frame(struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t pn532_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
static size_t pn532_receive_buf(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
{
|
||||
struct pn532_uart_phy *dev = serdev_device_get_drvdata(serdev);
|
||||
size_t i;
|
||||
|
|
|
@ -51,8 +51,8 @@ static const struct s3fwrn5_phy_ops uart_phy_ops = {
|
|||
.write = s3fwrn82_uart_write,
|
||||
};
|
||||
|
||||
static ssize_t s3fwrn82_uart_read(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
static size_t s3fwrn82_uart_read(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
{
|
||||
struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
|
||||
size_t i;
|
||||
|
|
|
@ -81,8 +81,8 @@ struct cros_ec_uart {
|
|||
struct response_info response;
|
||||
};
|
||||
|
||||
static ssize_t cros_ec_uart_rx_bytes(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
static size_t cros_ec_uart_rx_bytes(struct serdev_device *serdev,
|
||||
const u8 *data, size_t count)
|
||||
{
|
||||
struct ec_host_response *host_response;
|
||||
struct cros_ec_device *ec_dev = serdev_device_get_drvdata(serdev);
|
||||
|
|
|
@ -227,8 +227,8 @@ EXPORT_SYMBOL_GPL(ssam_client_bind);
|
|||
|
||||
/* -- Glue layer (serdev_device -> ssam_controller). ------------------------ */
|
||||
|
||||
static ssize_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf,
|
||||
size_t n)
|
||||
static size_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf,
|
||||
size_t n)
|
||||
{
|
||||
struct ssam_controller *ctrl;
|
||||
int ret;
|
||||
|
|
|
@ -75,14 +75,9 @@ config VT_CONSOLE_SLEEP
|
|||
def_bool y
|
||||
depends on VT_CONSOLE && PM_SLEEP
|
||||
|
||||
config HW_CONSOLE
|
||||
bool
|
||||
depends on VT
|
||||
default y
|
||||
|
||||
config VT_HW_CONSOLE_BINDING
|
||||
bool "Support for binding and unbinding console drivers"
|
||||
depends on HW_CONSOLE
|
||||
depends on VT
|
||||
help
|
||||
The virtual terminal is the device that interacts with the physical
|
||||
terminal through console drivers. On these systems, at least one
|
||||
|
|
|
@ -1566,7 +1566,7 @@ fail_tty_driver_kref_put:
|
|||
return error;
|
||||
}
|
||||
|
||||
static int __exit amiga_serial_remove(struct platform_device *pdev)
|
||||
static void __exit amiga_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct serial_state *state = platform_get_drvdata(pdev);
|
||||
|
||||
|
@ -1576,12 +1576,10 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
|
|||
|
||||
free_irq(IRQ_AMIGA_TBE, state);
|
||||
free_irq(IRQ_AMIGA_RBF, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver amiga_serial_driver = {
|
||||
.remove = __exit_p(amiga_serial_remove),
|
||||
.remove_new = __exit_p(amiga_serial_remove),
|
||||
.driver = {
|
||||
.name = "amiga-serial",
|
||||
},
|
||||
|
|
|
@ -408,7 +408,7 @@ err_unmap:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int goldfish_tty_remove(struct platform_device *pdev)
|
||||
static void goldfish_tty_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct goldfish_tty *qtty = platform_get_drvdata(pdev);
|
||||
|
||||
|
@ -424,7 +424,6 @@ static int goldfish_tty_remove(struct platform_device *pdev)
|
|||
if (goldfish_tty_current_line_count == 0)
|
||||
goldfish_tty_delete_driver();
|
||||
mutex_unlock(&goldfish_tty_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE
|
||||
|
@ -462,7 +461,7 @@ MODULE_DEVICE_TABLE(of, goldfish_tty_of_match);
|
|||
|
||||
static struct platform_driver goldfish_tty_platform_driver = {
|
||||
.probe = goldfish_tty_probe,
|
||||
.remove = goldfish_tty_remove,
|
||||
.remove_new = goldfish_tty_remove,
|
||||
.driver = {
|
||||
.name = "goldfish_tty",
|
||||
.of_match_table = goldfish_tty_of_match,
|
||||
|
|
|
@ -1035,6 +1035,10 @@ static const struct attribute_group *hvc_iucv_dev_attr_groups[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static void hvc_iucv_free(struct device *data)
|
||||
{
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
|
||||
|
@ -1097,7 +1101,7 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console)
|
|||
priv->dev->bus = &iucv_bus;
|
||||
priv->dev->parent = iucv_root;
|
||||
priv->dev->groups = hvc_iucv_dev_attr_groups;
|
||||
priv->dev->release = (void (*)(struct device *)) kfree;
|
||||
priv->dev->release = hvc_iucv_free;
|
||||
rc = device_register(priv->dev);
|
||||
if (rc) {
|
||||
put_device(priv->dev);
|
||||
|
|
|
@ -431,7 +431,7 @@ static void serdev_drv_remove(struct device *dev)
|
|||
dev_pm_domain_detach(dev, true);
|
||||
}
|
||||
|
||||
static struct bus_type serdev_bus_type = {
|
||||
static const struct bus_type serdev_bus_type = {
|
||||
.name = "serial",
|
||||
.match = serdev_device_match,
|
||||
.probe = serdev_drv_probe,
|
||||
|
|
|
@ -27,19 +27,17 @@ static size_t ttyport_receive_buf(struct tty_port *port, const u8 *cp,
|
|||
{
|
||||
struct serdev_controller *ctrl = port->client_data;
|
||||
struct serport *serport = serdev_controller_get_drvdata(ctrl);
|
||||
int ret;
|
||||
size_t ret;
|
||||
|
||||
if (!test_bit(SERPORT_ACTIVE, &serport->flags))
|
||||
return 0;
|
||||
|
||||
ret = serdev_controller_receive_buf(ctrl, cp, count);
|
||||
|
||||
dev_WARN_ONCE(&ctrl->dev, ret < 0 || ret > count,
|
||||
"receive_buf returns %d (count = %zu)\n",
|
||||
dev_WARN_ONCE(&ctrl->dev, ret > count,
|
||||
"receive_buf returns %zu (count = %zu)\n",
|
||||
ret, count);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
else if (ret > count)
|
||||
if (ret > count)
|
||||
return count;
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -419,8 +419,8 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
|||
struct aspeed_vuart *vuart;
|
||||
struct device_node *np;
|
||||
struct resource *res;
|
||||
u32 clk, prop, sirq[2];
|
||||
int rc, sirq_polarity;
|
||||
u32 prop, sirq[2];
|
||||
struct clk *vclk;
|
||||
|
||||
np = pdev->dev.of_node;
|
||||
|
@ -447,53 +447,35 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
|||
port.port.status = UPSTAT_SYNC_FIFO;
|
||||
port.port.dev = &pdev->dev;
|
||||
port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
|
||||
port.port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE |
|
||||
UPF_NO_THRE_TEST;
|
||||
port.bugs |= UART_BUG_TXRACE;
|
||||
|
||||
rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (of_property_read_u32(np, "clock-frequency", &clk)) {
|
||||
rc = uart_read_port_properties(&port.port);
|
||||
if (rc)
|
||||
goto err_sysfs_remove;
|
||||
|
||||
/* Get clk rate through clk driver if present */
|
||||
if (!port.port.uartclk) {
|
||||
vclk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(vclk)) {
|
||||
rc = dev_err_probe(dev, PTR_ERR(vclk), "clk or clock-frequency not defined\n");
|
||||
goto err_sysfs_remove;
|
||||
}
|
||||
|
||||
clk = clk_get_rate(vclk);
|
||||
port.port.uartclk = clk_get_rate(vclk);
|
||||
}
|
||||
|
||||
/* If current-speed was set, then try not to change it. */
|
||||
if (of_property_read_u32(np, "current-speed", &prop) == 0)
|
||||
port.port.custom_divisor = clk / (16 * prop);
|
||||
port.port.custom_divisor = port.port.uartclk / (16 * prop);
|
||||
|
||||
/* Check for shifted address mapping */
|
||||
if (of_property_read_u32(np, "reg-offset", &prop) == 0)
|
||||
port.port.mapbase += prop;
|
||||
|
||||
/* Check for registers offset within the devices address range */
|
||||
if (of_property_read_u32(np, "reg-shift", &prop) == 0)
|
||||
port.port.regshift = prop;
|
||||
|
||||
/* Check for fifo size */
|
||||
if (of_property_read_u32(np, "fifo-size", &prop) == 0)
|
||||
port.port.fifosize = prop;
|
||||
|
||||
/* Check for a fixed line number */
|
||||
rc = of_alias_get_id(np, "serial");
|
||||
if (rc >= 0)
|
||||
port.port.line = rc;
|
||||
|
||||
port.port.irq = irq_of_parse_and_map(np, 0);
|
||||
port.port.handle_irq = aspeed_vuart_handle_irq;
|
||||
port.port.iotype = UPIO_MEM;
|
||||
port.port.type = PORT_ASPEED_VUART;
|
||||
port.port.uartclk = clk;
|
||||
port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
|
||||
| UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
|
||||
|
||||
if (of_property_read_bool(np, "no-loopback-test"))
|
||||
port.port.flags |= UPF_SKIP_TEST;
|
||||
|
||||
if (port.port.fifosize)
|
||||
port.capabilities = UART_CAP_FIFO;
|
||||
|
@ -503,7 +485,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
|||
|
||||
rc = serial8250_register_8250_port(&port);
|
||||
if (rc < 0)
|
||||
goto err_clk_disable;
|
||||
goto err_sysfs_remove;
|
||||
|
||||
vuart->line = rc;
|
||||
vuart->port = serial8250_get_port(vuart->line);
|
||||
|
@ -529,7 +511,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
|||
rc = aspeed_vuart_set_lpc_address(vuart, prop);
|
||||
if (rc < 0) {
|
||||
dev_err_probe(dev, rc, "invalid value in aspeed,lpc-io-reg property\n");
|
||||
goto err_clk_disable;
|
||||
goto err_sysfs_remove;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", sirq, 2);
|
||||
|
@ -541,14 +523,14 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
|||
rc = aspeed_vuart_set_sirq(vuart, sirq[0]);
|
||||
if (rc < 0) {
|
||||
dev_err_probe(dev, rc, "invalid sirq number in aspeed,lpc-interrupts property\n");
|
||||
goto err_clk_disable;
|
||||
goto err_sysfs_remove;
|
||||
}
|
||||
|
||||
sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]);
|
||||
if (sirq_polarity < 0) {
|
||||
rc = dev_err_probe(dev, sirq_polarity,
|
||||
"invalid sirq polarity in aspeed,lpc-interrupts property\n");
|
||||
goto err_clk_disable;
|
||||
goto err_sysfs_remove;
|
||||
}
|
||||
|
||||
aspeed_vuart_set_sirq_polarity(vuart, sirq_polarity);
|
||||
|
@ -559,8 +541,6 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
|
||||
err_clk_disable:
|
||||
irq_dispose_mapping(port.port.irq);
|
||||
err_sysfs_remove:
|
||||
sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
|
||||
return rc;
|
||||
|
|
|
@ -45,10 +45,6 @@ struct bcm2835aux_data {
|
|||
u32 cntl;
|
||||
};
|
||||
|
||||
struct bcm2835_aux_serial_driver_data {
|
||||
resource_size_t offset;
|
||||
};
|
||||
|
||||
static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up)
|
||||
{
|
||||
if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
|
||||
|
@ -85,10 +81,9 @@ static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up)
|
|||
|
||||
static int bcm2835aux_serial_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct bcm2835_aux_serial_driver_data *bcm_data;
|
||||
const struct software_node *bcm2835_swnode;
|
||||
struct uart_8250_port up = { };
|
||||
struct bcm2835aux_data *data;
|
||||
resource_size_t offset = 0;
|
||||
struct resource *res;
|
||||
unsigned int uartclk;
|
||||
int ret;
|
||||
|
@ -101,12 +96,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
|
|||
/* initialize data */
|
||||
up.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
|
||||
up.port.dev = &pdev->dev;
|
||||
up.port.regshift = 2;
|
||||
up.port.type = PORT_16550;
|
||||
up.port.iotype = UPIO_MEM;
|
||||
up.port.fifosize = 8;
|
||||
up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE |
|
||||
UPF_SKIP_TEST | UPF_IOREMAP;
|
||||
up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_IOREMAP;
|
||||
up.port.rs485_config = serial8250_em485_config;
|
||||
up.port.rs485_supported = serial8250_em485_supported;
|
||||
up.rs485_start_tx = bcm2835aux_rs485_start_tx;
|
||||
|
@ -122,12 +113,6 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(data->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(data->clk), "could not get clk\n");
|
||||
|
||||
/* get the interrupt */
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
up.port.irq = ret;
|
||||
|
||||
/* map the main registers */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
|
@ -135,52 +120,40 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bcm_data = device_get_match_data(&pdev->dev);
|
||||
up.port.mapbase = res->start;
|
||||
up.port.mapsize = resource_size(res);
|
||||
|
||||
/* Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi)
|
||||
* describe the miniuart with a base address that encompasses the auxiliary
|
||||
* registers shared between the miniuart and spi.
|
||||
*
|
||||
* This is due to historical reasons, see discussion here :
|
||||
* https://edk2.groups.io/g/devel/topic/87501357#84349
|
||||
*
|
||||
* We need to add the offset between the miniuart and auxiliary
|
||||
* registers to get the real miniuart base address.
|
||||
*/
|
||||
if (bcm_data)
|
||||
offset = bcm_data->offset;
|
||||
bcm2835_swnode = device_get_match_data(&pdev->dev);
|
||||
if (bcm2835_swnode) {
|
||||
ret = device_add_software_node(&pdev->dev, bcm2835_swnode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
up.port.mapbase = res->start + offset;
|
||||
up.port.mapsize = resource_size(res) - offset;
|
||||
ret = uart_read_port_properties(&up.port);
|
||||
if (ret)
|
||||
goto rm_swnode;
|
||||
|
||||
/* Check for a fixed line number */
|
||||
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
if (ret >= 0)
|
||||
up.port.line = ret;
|
||||
up.port.regshift = 2;
|
||||
up.port.fifosize = 8;
|
||||
|
||||
/* enable the clock as a last step */
|
||||
ret = clk_prepare_enable(data->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to enable uart clock - %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
dev_err_probe(&pdev->dev, ret, "unable to enable uart clock\n");
|
||||
goto rm_swnode;
|
||||
}
|
||||
|
||||
uartclk = clk_get_rate(data->clk);
|
||||
if (!uartclk) {
|
||||
ret = device_property_read_u32(&pdev->dev, "clock-frequency", &uartclk);
|
||||
if (ret) {
|
||||
dev_err_probe(&pdev->dev, ret, "could not get clk rate\n");
|
||||
goto dis_clk;
|
||||
}
|
||||
}
|
||||
if (uartclk)
|
||||
up.port.uartclk = uartclk;
|
||||
|
||||
/* the HW-clock divider for bcm2835aux is 8,
|
||||
* but 8250 expects a divider of 16,
|
||||
* so we have to multiply the actual clock by 2
|
||||
* to get identical baudrates.
|
||||
*/
|
||||
up.port.uartclk = uartclk * 2;
|
||||
up.port.uartclk *= 2;
|
||||
|
||||
/* register the port */
|
||||
ret = serial8250_register_8250_port(&up);
|
||||
|
@ -194,6 +167,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
|
|||
|
||||
dis_clk:
|
||||
clk_disable_unprepare(data->clk);
|
||||
rm_swnode:
|
||||
device_remove_software_node(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -203,10 +178,27 @@ static void bcm2835aux_serial_remove(struct platform_device *pdev)
|
|||
|
||||
serial8250_unregister_port(data->line);
|
||||
clk_disable_unprepare(data->clk);
|
||||
device_remove_software_node(&pdev->dev);
|
||||
}
|
||||
|
||||
static const struct bcm2835_aux_serial_driver_data bcm2835_acpi_data = {
|
||||
.offset = 0x40,
|
||||
/*
|
||||
* Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi)
|
||||
* describe the miniuart with a base address that encompasses the auxiliary
|
||||
* registers shared between the miniuart and spi.
|
||||
*
|
||||
* This is due to historical reasons, see discussion here:
|
||||
* https://edk2.groups.io/g/devel/topic/87501357#84349
|
||||
*
|
||||
* We need to add the offset between the miniuart and auxiliary registers
|
||||
* to get the real miniuart base address.
|
||||
*/
|
||||
static const struct property_entry bcm2835_acpi_properties[] = {
|
||||
PROPERTY_ENTRY_U32("reg-offset", 0x40),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct software_node bcm2835_acpi_node = {
|
||||
.properties = bcm2835_acpi_properties,
|
||||
};
|
||||
|
||||
static const struct of_device_id bcm2835aux_serial_match[] = {
|
||||
|
@ -216,7 +208,7 @@ static const struct of_device_id bcm2835aux_serial_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match);
|
||||
|
||||
static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = {
|
||||
{ "BCM2836", (kernel_ulong_t)&bcm2835_acpi_data },
|
||||
{ "BCM2836", (kernel_ulong_t)&bcm2835_acpi_node },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
|
@ -187,21 +188,19 @@
|
|||
#define TX_BUF_SIZE 4096
|
||||
#define RX_BUF_SIZE 4096
|
||||
#define RX_BUFS_COUNT 2
|
||||
#define KHZ 1000
|
||||
#define MHZ(x) ((x) * KHZ * KHZ)
|
||||
|
||||
static const u32 brcmstb_rate_table[] = {
|
||||
MHZ(81),
|
||||
MHZ(108),
|
||||
MHZ(64), /* Actually 64285715 for some chips */
|
||||
MHZ(48),
|
||||
81 * HZ_PER_MHZ,
|
||||
108 * HZ_PER_MHZ,
|
||||
64 * HZ_PER_MHZ, /* Actually 64285715 for some chips */
|
||||
48 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const u32 brcmstb_rate_table_7278[] = {
|
||||
MHZ(81),
|
||||
MHZ(108),
|
||||
81 * HZ_PER_MHZ,
|
||||
108 * HZ_PER_MHZ,
|
||||
0,
|
||||
MHZ(48),
|
||||
48 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
struct brcmuart_priv {
|
||||
|
@ -936,17 +935,14 @@ static void brcmuart_init_debugfs(struct brcmuart_priv *priv,
|
|||
static int brcmuart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *regs;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id = NULL;
|
||||
struct uart_8250_port *new_port;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct brcmuart_priv *priv;
|
||||
struct clk *baud_mux_clk;
|
||||
struct uart_8250_port up;
|
||||
int irq;
|
||||
void __iomem *membase = NULL;
|
||||
resource_size_t mapbase = 0;
|
||||
u32 clk_rate = 0;
|
||||
int ret;
|
||||
int x;
|
||||
int dma_irq;
|
||||
|
@ -954,15 +950,12 @@ static int brcmuart_probe(struct platform_device *pdev)
|
|||
"uart", "dma_rx", "dma_tx", "dma_intr2", "dma_arb"
|
||||
};
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
priv = devm_kzalloc(dev, sizeof(struct brcmuart_priv),
|
||||
GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
of_id = of_match_node(brcmuart_dt_ids, np);
|
||||
of_id = of_match_node(brcmuart_dt_ids, dev->of_node);
|
||||
if (!of_id || !of_id->data)
|
||||
priv->rate_table = brcmstb_rate_table;
|
||||
else
|
||||
|
@ -1012,7 +1005,23 @@ static int brcmuart_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
of_property_read_u32(np, "clock-frequency", &clk_rate);
|
||||
dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
|
||||
|
||||
memset(&up, 0, sizeof(up));
|
||||
up.port.type = PORT_BCM7271;
|
||||
up.port.dev = dev;
|
||||
up.port.mapbase = mapbase;
|
||||
up.port.membase = membase;
|
||||
up.port.handle_irq = brcmuart_handle_irq;
|
||||
up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||
up.port.private_data = priv;
|
||||
|
||||
ret = uart_read_port_properties(&up.port);
|
||||
if (ret)
|
||||
goto release_dma;
|
||||
|
||||
up.port.regshift = 2;
|
||||
up.port.iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32;
|
||||
|
||||
/* See if a Baud clock has been specified */
|
||||
baud_mux_clk = devm_clk_get_optional_enabled(dev, "sw_baud");
|
||||
|
@ -1024,39 +1033,11 @@ static int brcmuart_probe(struct platform_device *pdev)
|
|||
|
||||
priv->baud_mux_clk = baud_mux_clk;
|
||||
init_real_clk_rates(dev, priv);
|
||||
clk_rate = priv->default_mux_rate;
|
||||
up.port.uartclk = priv->default_mux_rate;
|
||||
} else {
|
||||
dev_dbg(dev, "BAUD MUX clock not specified\n");
|
||||
}
|
||||
|
||||
if (clk_rate == 0) {
|
||||
ret = dev_err_probe(dev, -EINVAL, "clock-frequency or clk not defined\n");
|
||||
goto release_dma;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
|
||||
|
||||
memset(&up, 0, sizeof(up));
|
||||
up.port.type = PORT_BCM7271;
|
||||
up.port.uartclk = clk_rate;
|
||||
up.port.dev = dev;
|
||||
up.port.mapbase = mapbase;
|
||||
up.port.membase = membase;
|
||||
up.port.irq = irq;
|
||||
up.port.handle_irq = brcmuart_handle_irq;
|
||||
up.port.regshift = 2;
|
||||
up.port.iotype = of_device_is_big_endian(np) ?
|
||||
UPIO_MEM32BE : UPIO_MEM32;
|
||||
up.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
|
||||
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||
up.port.dev = dev;
|
||||
up.port.private_data = priv;
|
||||
|
||||
/* Check for a fixed line number */
|
||||
ret = of_alias_get_id(np, "serial");
|
||||
if (ret >= 0)
|
||||
up.port.line = ret;
|
||||
|
||||
/* setup HR timer */
|
||||
hrtimer_init(&priv->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
|
||||
priv->hrt.function = brcmuart_hrtimer_func;
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
* LCR is written whilst busy. If it is, then a busy detect interrupt is
|
||||
* raised, the LCR needs to be rewritten and the uart status register read.
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
|
@ -17,7 +16,6 @@
|
|||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
|
@ -56,6 +54,7 @@
|
|||
#define DW_UART_QUIRK_ARMADA_38X BIT(1)
|
||||
#define DW_UART_QUIRK_SKIP_SET_RATE BIT(2)
|
||||
#define DW_UART_QUIRK_IS_DMA_FC BIT(3)
|
||||
#define DW_UART_QUIRK_APMC0D08 BIT(4)
|
||||
|
||||
static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
|
||||
{
|
||||
|
@ -445,44 +444,29 @@ static void dw8250_prepare_rx_dma(struct uart_8250_port *p)
|
|||
|
||||
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
|
||||
{
|
||||
struct device_node *np = p->dev->of_node;
|
||||
unsigned int quirks = data->pdata ? data->pdata->quirks : 0;
|
||||
|
||||
if (np) {
|
||||
unsigned int quirks = data->pdata->quirks;
|
||||
int id;
|
||||
|
||||
/* get index of serial line, if found in DT aliases */
|
||||
id = of_alias_get_id(np, "serial");
|
||||
if (id >= 0)
|
||||
p->line = id;
|
||||
#ifdef CONFIG_64BIT
|
||||
if (quirks & DW_UART_QUIRK_OCTEON) {
|
||||
p->serial_in = dw8250_serial_inq;
|
||||
p->serial_out = dw8250_serial_outq;
|
||||
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
||||
p->type = PORT_OCTEON;
|
||||
data->skip_autocfg = true;
|
||||
}
|
||||
if (quirks & DW_UART_QUIRK_OCTEON) {
|
||||
p->serial_in = dw8250_serial_inq;
|
||||
p->serial_out = dw8250_serial_outq;
|
||||
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
||||
p->type = PORT_OCTEON;
|
||||
data->skip_autocfg = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (of_device_is_big_endian(np)) {
|
||||
p->iotype = UPIO_MEM32BE;
|
||||
p->serial_in = dw8250_serial_in32be;
|
||||
p->serial_out = dw8250_serial_out32be;
|
||||
}
|
||||
|
||||
if (quirks & DW_UART_QUIRK_ARMADA_38X)
|
||||
p->serial_out = dw8250_serial_out38x;
|
||||
if (quirks & DW_UART_QUIRK_SKIP_SET_RATE)
|
||||
p->set_termios = dw8250_do_set_termios;
|
||||
if (quirks & DW_UART_QUIRK_IS_DMA_FC) {
|
||||
data->data.dma.txconf.device_fc = 1;
|
||||
data->data.dma.rxconf.device_fc = 1;
|
||||
data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma;
|
||||
data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma;
|
||||
}
|
||||
|
||||
} else if (acpi_dev_present("APMC0D08", NULL, -1)) {
|
||||
if (quirks & DW_UART_QUIRK_ARMADA_38X)
|
||||
p->serial_out = dw8250_serial_out38x;
|
||||
if (quirks & DW_UART_QUIRK_SKIP_SET_RATE)
|
||||
p->set_termios = dw8250_do_set_termios;
|
||||
if (quirks & DW_UART_QUIRK_IS_DMA_FC) {
|
||||
data->data.dma.txconf.device_fc = 1;
|
||||
data->data.dma.rxconf.device_fc = 1;
|
||||
data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma;
|
||||
data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma;
|
||||
}
|
||||
if (quirks & DW_UART_QUIRK_APMC0D08) {
|
||||
p->iotype = UPIO_MEM32;
|
||||
p->regshift = 2;
|
||||
p->serial_in = dw8250_serial_in32;
|
||||
|
@ -510,39 +494,21 @@ static int dw8250_probe(struct platform_device *pdev)
|
|||
struct device *dev = &pdev->dev;
|
||||
struct dw8250_data *data;
|
||||
struct resource *regs;
|
||||
int irq;
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs)
|
||||
return dev_err_probe(dev, -EINVAL, "no registers defined\n");
|
||||
|
||||
irq = platform_get_irq_optional(pdev, 0);
|
||||
/* no interrupt -> fall back to polling */
|
||||
if (irq == -ENXIO)
|
||||
irq = 0;
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
spin_lock_init(&p->lock);
|
||||
p->mapbase = regs->start;
|
||||
p->irq = irq;
|
||||
p->handle_irq = dw8250_handle_irq;
|
||||
p->pm = dw8250_do_pm;
|
||||
p->type = PORT_8250;
|
||||
p->flags = UPF_SHARE_IRQ | UPF_FIXED_PORT;
|
||||
p->flags = UPF_FIXED_PORT;
|
||||
p->dev = dev;
|
||||
p->iotype = UPIO_MEM;
|
||||
p->serial_in = dw8250_serial_in;
|
||||
p->serial_out = dw8250_serial_out;
|
||||
p->set_ldisc = dw8250_set_ldisc;
|
||||
p->set_termios = dw8250_set_termios;
|
||||
|
||||
p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
|
||||
if (!p->membase)
|
||||
return -ENOMEM;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
@ -554,15 +520,35 @@ static int dw8250_probe(struct platform_device *pdev)
|
|||
data->uart_16550_compatible = device_property_read_bool(dev,
|
||||
"snps,uart-16550-compatible");
|
||||
|
||||
err = device_property_read_u32(dev, "reg-shift", &val);
|
||||
if (!err)
|
||||
p->regshift = val;
|
||||
p->mapbase = regs->start;
|
||||
p->mapsize = resource_size(regs);
|
||||
|
||||
err = device_property_read_u32(dev, "reg-io-width", &val);
|
||||
if (!err && val == 4) {
|
||||
p->iotype = UPIO_MEM32;
|
||||
p->membase = devm_ioremap(dev, p->mapbase, p->mapsize);
|
||||
if (!p->membase)
|
||||
return -ENOMEM;
|
||||
|
||||
err = uart_read_port_properties(p);
|
||||
/* no interrupt -> fall back to polling */
|
||||
if (err == -ENXIO)
|
||||
err = 0;
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (p->iotype) {
|
||||
case UPIO_MEM:
|
||||
p->serial_in = dw8250_serial_in;
|
||||
p->serial_out = dw8250_serial_out;
|
||||
break;
|
||||
case UPIO_MEM32:
|
||||
p->serial_in = dw8250_serial_in32;
|
||||
p->serial_out = dw8250_serial_out32;
|
||||
break;
|
||||
case UPIO_MEM32BE:
|
||||
p->serial_in = dw8250_serial_in32be;
|
||||
p->serial_out = dw8250_serial_out32be;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (device_property_read_bool(dev, "dcd-override")) {
|
||||
|
@ -589,15 +575,13 @@ static int dw8250_probe(struct platform_device *pdev)
|
|||
data->msr_mask_off |= UART_MSR_TERI;
|
||||
}
|
||||
|
||||
/* Always ask for fixed clock rate from a property. */
|
||||
device_property_read_u32(dev, "clock-frequency", &p->uartclk);
|
||||
|
||||
/* If there is separate baudclk, get the rate from it. */
|
||||
data->clk = devm_clk_get_optional_enabled(dev, "baudclk");
|
||||
if (data->clk == NULL)
|
||||
data->clk = devm_clk_get_optional_enabled(dev, NULL);
|
||||
if (IS_ERR(data->clk))
|
||||
return PTR_ERR(data->clk);
|
||||
return dev_err_probe(dev, PTR_ERR(data->clk),
|
||||
"failed to get baudclk\n");
|
||||
|
||||
INIT_WORK(&data->clk_work, dw8250_clk_work_cb);
|
||||
data->clk_notifier.notifier_call = dw8250_clk_notifier_cb;
|
||||
|
@ -762,13 +746,18 @@ static const struct of_device_id dw8250_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
||||
|
||||
static const struct dw8250_platform_data dw8250_apmc0d08 = {
|
||||
.usr_reg = DW_UART_USR,
|
||||
.quirks = DW_UART_QUIRK_APMC0D08,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id dw8250_acpi_match[] = {
|
||||
{ "80860F0A", (kernel_ulong_t)&dw8250_dw_apb },
|
||||
{ "8086228A", (kernel_ulong_t)&dw8250_dw_apb },
|
||||
{ "AMD0020", (kernel_ulong_t)&dw8250_dw_apb },
|
||||
{ "AMDI0020", (kernel_ulong_t)&dw8250_dw_apb },
|
||||
{ "AMDI0022", (kernel_ulong_t)&dw8250_dw_apb },
|
||||
{ "APMC0D08", (kernel_ulong_t)&dw8250_dw_apb},
|
||||
{ "APMC0D08", (kernel_ulong_t)&dw8250_apmc0d08 },
|
||||
{ "BRCM2032", (kernel_ulong_t)&dw8250_dw_apb },
|
||||
{ "HISI0031", (kernel_ulong_t)&dw8250_dw_apb },
|
||||
{ "INT33C4", (kernel_ulong_t)&dw8250_dw_apb },
|
||||
|
|
|
@ -6,23 +6,29 @@
|
|||
*
|
||||
* Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved.
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "8250.h"
|
||||
#include "8250_pcilib.h"
|
||||
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM_2S 0x1052
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM_4S 0x105d
|
||||
|
@ -229,13 +235,12 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,
|
|||
struct uart_8250_port *port)
|
||||
{
|
||||
const struct exar8250_board *board = priv->board;
|
||||
unsigned int bar = 0;
|
||||
unsigned char status;
|
||||
int err;
|
||||
|
||||
port->port.iotype = UPIO_MEM;
|
||||
port->port.mapbase = pci_resource_start(pcidev, bar) + offset;
|
||||
port->port.membase = priv->virt + offset;
|
||||
port->port.regshift = board->reg_shift;
|
||||
err = serial8250_pci_setup_port(pcidev, port, 0, offset, board->reg_shift);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* XR17V35x UARTs have an extra divisor register, DLD that gets enabled
|
||||
|
@ -375,7 +380,7 @@ static struct platform_device *__xr17v35x_register_gpio(struct pci_dev *pcidev,
|
|||
return NULL;
|
||||
|
||||
pdev->dev.parent = &pcidev->dev;
|
||||
ACPI_COMPANION_SET(&pdev->dev, ACPI_COMPANION(&pcidev->dev));
|
||||
device_set_node(&pdev->dev, dev_fwnode(&pcidev->dev));
|
||||
|
||||
if (device_add_software_node(&pdev->dev, node) < 0 ||
|
||||
platform_device_add(pdev) < 0) {
|
||||
|
@ -713,14 +718,14 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
|
|||
uart.port.irq = pci_irq_vector(pcidev, 0);
|
||||
uart.port.dev = &pcidev->dev;
|
||||
|
||||
/* Clear interrupts */
|
||||
exar_misc_clear(priv);
|
||||
|
||||
rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler,
|
||||
IRQF_SHARED, "exar_uart", priv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Clear interrupts */
|
||||
exar_misc_clear(priv);
|
||||
|
||||
for (i = 0; i < nr_ports && i < maxnr; i++) {
|
||||
rc = board->setup(priv, pcidev, &uart, i);
|
||||
if (rc) {
|
||||
|
@ -753,28 +758,24 @@ static void exar_pci_remove(struct pci_dev *pcidev)
|
|||
for (i = 0; i < priv->nr; i++)
|
||||
serial8250_unregister_port(priv->line[i]);
|
||||
|
||||
/* Ensure that every init quirk is properly torn down */
|
||||
if (priv->board->exit)
|
||||
priv->board->exit(pcidev);
|
||||
}
|
||||
|
||||
static int __maybe_unused exar_suspend(struct device *dev)
|
||||
static int exar_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pcidev = to_pci_dev(dev);
|
||||
struct exar8250 *priv = pci_get_drvdata(pcidev);
|
||||
struct exar8250 *priv = dev_get_drvdata(dev);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < priv->nr; i++)
|
||||
if (priv->line[i] >= 0)
|
||||
serial8250_suspend_port(priv->line[i]);
|
||||
|
||||
/* Ensure that every init quirk is properly torn down */
|
||||
if (priv->board->exit)
|
||||
priv->board->exit(pcidev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused exar_resume(struct device *dev)
|
||||
static int exar_resume(struct device *dev)
|
||||
{
|
||||
struct exar8250 *priv = dev_get_drvdata(dev);
|
||||
unsigned int i;
|
||||
|
@ -788,7 +789,7 @@ static int __maybe_unused exar_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
|
||||
|
||||
static const struct exar8250_board pbn_fastcom335_2 = {
|
||||
.num_ports = 2,
|
||||
|
@ -938,12 +939,13 @@ static struct pci_driver exar_pci_driver = {
|
|||
.probe = exar_pci_probe,
|
||||
.remove = exar_pci_remove,
|
||||
.driver = {
|
||||
.pm = &exar_pci_pm,
|
||||
.pm = pm_sleep_ptr(&exar_pci_pm),
|
||||
},
|
||||
.id_table = exar_pci_tbl,
|
||||
};
|
||||
module_pci_driver(exar_pci_driver);
|
||||
|
||||
MODULE_IMPORT_NS(SERIAL_8250_PCI);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Exar Serial Driver");
|
||||
MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
|
||||
|
|
|
@ -234,7 +234,7 @@ static int ingenic_uart_probe(struct platform_device *pdev)
|
|||
struct ingenic_uart_data *data;
|
||||
const struct ingenic_uart_config *cdata;
|
||||
struct resource *regs;
|
||||
int irq, err, line;
|
||||
int err;
|
||||
|
||||
cdata = of_device_get_match_data(&pdev->dev);
|
||||
if (!cdata) {
|
||||
|
@ -242,10 +242,6 @@ static int ingenic_uart_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "no registers defined\n");
|
||||
|
@ -259,21 +255,19 @@ static int ingenic_uart_probe(struct platform_device *pdev)
|
|||
spin_lock_init(&uart.port.lock);
|
||||
uart.port.type = PORT_16550A;
|
||||
uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
|
||||
uart.port.iotype = UPIO_MEM;
|
||||
uart.port.mapbase = regs->start;
|
||||
uart.port.regshift = 2;
|
||||
uart.port.serial_out = ingenic_uart_serial_out;
|
||||
uart.port.serial_in = ingenic_uart_serial_in;
|
||||
uart.port.irq = irq;
|
||||
uart.port.dev = &pdev->dev;
|
||||
uart.port.fifosize = cdata->fifosize;
|
||||
uart.tx_loadsz = cdata->tx_loadsz;
|
||||
uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE;
|
||||
|
||||
/* Check for a fixed line number */
|
||||
line = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
if (line >= 0)
|
||||
uart.port.line = line;
|
||||
err = uart_read_port_properties(&uart.port);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
uart.port.regshift = 2;
|
||||
uart.port.fifosize = cdata->fifosize;
|
||||
|
||||
uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
|
||||
resource_size(regs));
|
||||
|
|
|
@ -92,11 +92,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
|
|||
struct lpc18xx_uart_data *data;
|
||||
struct uart_8250_port uart;
|
||||
struct resource *res;
|
||||
int irq, ret;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
int ret;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
|
@ -139,19 +135,12 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
|
|||
goto dis_clk_reg;
|
||||
}
|
||||
|
||||
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
if (ret >= 0)
|
||||
uart.port.line = ret;
|
||||
|
||||
data->dma.rx_param = data;
|
||||
data->dma.tx_param = data;
|
||||
|
||||
spin_lock_init(&uart.port.lock);
|
||||
uart.port.dev = &pdev->dev;
|
||||
uart.port.irq = irq;
|
||||
uart.port.iotype = UPIO_MEM32;
|
||||
uart.port.mapbase = res->start;
|
||||
uart.port.regshift = 2;
|
||||
uart.port.type = PORT_16550A;
|
||||
uart.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST;
|
||||
uart.port.uartclk = clk_get_rate(data->clk_uart);
|
||||
|
@ -160,6 +149,13 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
|
|||
uart.port.rs485_supported = lpc18xx_rs485_supported;
|
||||
uart.port.serial_out = lpc18xx_uart_serial_out;
|
||||
|
||||
ret = uart_read_port_properties(&uart.port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
uart.port.iotype = UPIO_MEM32;
|
||||
uart.port.regshift = 2;
|
||||
|
||||
uart.dma = &data->dma;
|
||||
uart.dma->rxconf.src_maxburst = 1;
|
||||
uart.dma->txconf.dst_maxburst = 1;
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
*
|
||||
* Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
@ -25,6 +28,36 @@ struct of_serial_info {
|
|||
int line;
|
||||
};
|
||||
|
||||
/* Nuvoton NPCM timeout register */
|
||||
#define UART_NPCM_TOR 7
|
||||
#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */
|
||||
|
||||
static int npcm_startup(struct uart_port *port)
|
||||
{
|
||||
/*
|
||||
* Nuvoton calls the scratch register 'UART_TOR' (timeout
|
||||
* register). Enable it, and set TIOC (timeout interrupt
|
||||
* comparator) to be 0x20 for correct operation.
|
||||
*/
|
||||
serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20);
|
||||
|
||||
return serial8250_do_startup(port);
|
||||
}
|
||||
|
||||
/* Nuvoton NPCM UARTs have a custom divisor calculation */
|
||||
static unsigned int npcm_get_divisor(struct uart_port *port, unsigned int baud,
|
||||
unsigned int *frac)
|
||||
{
|
||||
return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2;
|
||||
}
|
||||
|
||||
static int npcm_setup(struct uart_port *port)
|
||||
{
|
||||
port->get_divisor = npcm_get_divisor;
|
||||
port->startup = npcm_startup;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill a struct uart_port for a given device node
|
||||
*/
|
||||
|
@ -36,37 +69,22 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
|||
struct device *dev = &ofdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct uart_port *port = &up->port;
|
||||
u32 clk, spd, prop;
|
||||
int ret, irq;
|
||||
u32 spd;
|
||||
int ret;
|
||||
|
||||
memset(port, 0, sizeof *port);
|
||||
|
||||
pm_runtime_enable(&ofdev->dev);
|
||||
pm_runtime_get_sync(&ofdev->dev);
|
||||
|
||||
if (of_property_read_u32(np, "clock-frequency", &clk)) {
|
||||
|
||||
/* Get clk rate through clk driver if present */
|
||||
info->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(info->clk)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(info->clk), "failed to get clock\n");
|
||||
goto err_pmruntime;
|
||||
}
|
||||
|
||||
clk = clk_get_rate(info->clk);
|
||||
}
|
||||
/* If current-speed was set, then try not to change it. */
|
||||
if (of_property_read_u32(np, "current-speed", &spd) == 0)
|
||||
port->custom_divisor = clk / (16 * spd);
|
||||
|
||||
ret = of_address_to_resource(np, 0, &resource);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "invalid address\n");
|
||||
goto err_pmruntime;
|
||||
}
|
||||
|
||||
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT |
|
||||
UPF_FIXED_TYPE;
|
||||
port->dev = &ofdev->dev;
|
||||
port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||
spin_lock_init(&port->lock);
|
||||
|
||||
if (resource_type(&resource) == IORESOURCE_IO) {
|
||||
|
@ -75,70 +93,31 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
|||
} else {
|
||||
port->mapbase = resource.start;
|
||||
port->mapsize = resource_size(&resource);
|
||||
|
||||
/* Check for shifted address mapping */
|
||||
if (of_property_read_u32(np, "reg-offset", &prop) == 0) {
|
||||
if (prop >= port->mapsize) {
|
||||
ret = dev_err_probe(dev, -EINVAL, "reg-offset %u exceeds region size %pa\n",
|
||||
prop, &port->mapsize);
|
||||
goto err_pmruntime;
|
||||
}
|
||||
|
||||
port->mapbase += prop;
|
||||
port->mapsize -= prop;
|
||||
}
|
||||
|
||||
port->iotype = UPIO_MEM;
|
||||
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
|
||||
switch (prop) {
|
||||
case 1:
|
||||
port->iotype = UPIO_MEM;
|
||||
break;
|
||||
case 2:
|
||||
port->iotype = UPIO_MEM16;
|
||||
break;
|
||||
case 4:
|
||||
port->iotype = of_device_is_big_endian(np) ?
|
||||
UPIO_MEM32BE : UPIO_MEM32;
|
||||
break;
|
||||
default:
|
||||
ret = dev_err_probe(dev, -EINVAL, "unsupported reg-io-width (%u)\n",
|
||||
prop);
|
||||
goto err_pmruntime;
|
||||
}
|
||||
}
|
||||
port->flags |= UPF_IOREMAP;
|
||||
}
|
||||
|
||||
ret = uart_read_and_validate_port_properties(port);
|
||||
if (ret)
|
||||
goto err_pmruntime;
|
||||
|
||||
/* Get clk rate through clk driver if present */
|
||||
if (!port->uartclk) {
|
||||
info->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(info->clk)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(info->clk), "failed to get clock\n");
|
||||
goto err_pmruntime;
|
||||
}
|
||||
|
||||
port->uartclk = clk_get_rate(info->clk);
|
||||
}
|
||||
/* If current-speed was set, then try not to change it. */
|
||||
if (of_property_read_u32(np, "current-speed", &spd) == 0)
|
||||
port->custom_divisor = port->uartclk / (16 * spd);
|
||||
|
||||
/* Compatibility with the deprecated pxa driver and 8250_pxa drivers. */
|
||||
if (of_device_is_compatible(np, "mrvl,mmp-uart"))
|
||||
port->regshift = 2;
|
||||
|
||||
/* Check for registers offset within the devices address range */
|
||||
if (of_property_read_u32(np, "reg-shift", &prop) == 0)
|
||||
port->regshift = prop;
|
||||
|
||||
/* Check for fifo size */
|
||||
if (of_property_read_u32(np, "fifo-size", &prop) == 0)
|
||||
port->fifosize = prop;
|
||||
|
||||
/* Check for a fixed line number */
|
||||
ret = of_alias_get_id(np, "serial");
|
||||
if (ret >= 0)
|
||||
port->line = ret;
|
||||
|
||||
irq = of_irq_get(np, 0);
|
||||
if (irq < 0) {
|
||||
if (irq == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err_pmruntime;
|
||||
}
|
||||
/* IRQ support not mandatory */
|
||||
irq = 0;
|
||||
}
|
||||
|
||||
port->irq = irq;
|
||||
|
||||
info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL);
|
||||
if (IS_ERR(info->rst)) {
|
||||
ret = PTR_ERR(info->rst);
|
||||
|
@ -150,12 +129,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
|||
goto err_pmruntime;
|
||||
|
||||
port->type = type;
|
||||
port->uartclk = clk;
|
||||
|
||||
if (of_property_read_bool(np, "no-loopback-test"))
|
||||
port->flags |= UPF_SKIP_TEST;
|
||||
|
||||
port->dev = &ofdev->dev;
|
||||
port->rs485_config = serial8250_em485_config;
|
||||
port->rs485_supported = serial8250_em485_supported;
|
||||
up->rs485_start_tx = serial8250_em485_start_tx;
|
||||
|
@ -164,10 +137,17 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
|||
switch (type) {
|
||||
case PORT_RT2880:
|
||||
ret = rt288x_setup(port);
|
||||
if (ret)
|
||||
goto err_pmruntime;
|
||||
break;
|
||||
case PORT_NPCM:
|
||||
ret = npcm_setup(port);
|
||||
break;
|
||||
default:
|
||||
/* Nothing to do */
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
goto err_pmruntime;
|
||||
|
||||
if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL) &&
|
||||
(of_device_is_compatible(np, "fsl,ns16550") ||
|
||||
|
@ -240,7 +220,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
|
|||
platform_set_drvdata(ofdev, info);
|
||||
return 0;
|
||||
err_dispose:
|
||||
irq_dispose_mapping(port8250.port.irq);
|
||||
pm_runtime_put_sync(&ofdev->dev);
|
||||
pm_runtime_disable(&ofdev->dev);
|
||||
err_free:
|
||||
|
|
|
@ -1394,11 +1394,7 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||
struct uart_8250_port up;
|
||||
struct resource *regs;
|
||||
void __iomem *membase;
|
||||
int irq, ret;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
int ret;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
|
@ -1419,7 +1415,6 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||
up.port.dev = &pdev->dev;
|
||||
up.port.mapbase = regs->start;
|
||||
up.port.membase = membase;
|
||||
up.port.irq = irq;
|
||||
/*
|
||||
* It claims to be 16C750 compatible however it is a little different.
|
||||
* It has EFR and has no FCR7_64byte bit. The AFE (which it claims to
|
||||
|
@ -1429,13 +1424,9 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||
* or pm callback.
|
||||
*/
|
||||
up.port.type = PORT_8250;
|
||||
up.port.iotype = UPIO_MEM;
|
||||
up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW |
|
||||
UPF_HARD_FLOW;
|
||||
up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | UPF_HARD_FLOW;
|
||||
up.port.private_data = priv;
|
||||
|
||||
up.port.regshift = OMAP_UART_REGSHIFT;
|
||||
up.port.fifosize = 64;
|
||||
up.tx_loadsz = 64;
|
||||
up.capabilities = UART_CAP_FIFO;
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -1461,14 +1452,14 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||
up.rs485_stop_tx = serial8250_em485_stop_tx;
|
||||
up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
|
||||
|
||||
ret = of_alias_get_id(np, "serial");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to get alias\n");
|
||||
ret = uart_read_port_properties(&up.port);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
up.port.line = ret;
|
||||
|
||||
if (of_property_read_u32(np, "clock-frequency", &up.port.uartclk)) {
|
||||
up.port.regshift = OMAP_UART_REGSHIFT;
|
||||
up.port.fifosize = 64;
|
||||
|
||||
if (!up.port.uartclk) {
|
||||
struct clk *clk;
|
||||
|
||||
clk = devm_clk_get(&pdev->dev, NULL);
|
||||
|
@ -1560,8 +1551,8 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||
}
|
||||
#endif
|
||||
|
||||
irq_set_status_flags(irq, IRQ_NOAUTOEN);
|
||||
ret = devm_request_irq(&pdev->dev, irq, omap8250_irq, 0,
|
||||
irq_set_status_flags(up.port.irq, IRQ_NOAUTOEN);
|
||||
ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0,
|
||||
dev_name(&pdev->dev), priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
@ -7,23 +7,31 @@
|
|||
* Copyright (C) 2022 Microchip Technology Inc., All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gfp_types.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/units.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/8250_pci.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
|
@ -67,6 +75,7 @@
|
|||
#define SYSLOCK_RETRY_CNT 1000
|
||||
|
||||
#define UART_RX_BYTE_FIFO 0x00
|
||||
#define UART_TX_BYTE_FIFO 0x00
|
||||
#define UART_FIFO_CTL 0x02
|
||||
|
||||
#define UART_ACTV_REG 0x11
|
||||
|
@ -81,10 +90,10 @@
|
|||
#define ADCL_CFG_PIN_SEL BIT(1)
|
||||
#define ADCL_CFG_EN BIT(0)
|
||||
|
||||
#define UART_BIT_SAMPLE_CNT 16
|
||||
#define UART_BIT_SAMPLE_CNT_8 8
|
||||
#define UART_BIT_SAMPLE_CNT_16 16
|
||||
#define BAUD_CLOCK_DIV_INT_MSK GENMASK(31, 8)
|
||||
#define ADCL_CFG_RTS_DELAY_MASK GENMASK(11, 8)
|
||||
#define UART_CLOCK_DEFAULT (62500 * HZ_PER_KHZ)
|
||||
|
||||
#define UART_WAKE_REG 0x8C
|
||||
#define UART_WAKE_MASK_REG 0x90
|
||||
|
@ -95,13 +104,19 @@
|
|||
(UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT)
|
||||
|
||||
#define UART_BAUD_CLK_DIVISOR_REG 0x54
|
||||
#define FRAC_DIV_CFG_REG 0x58
|
||||
|
||||
#define UART_RESET_REG 0x94
|
||||
#define UART_RESET_D3_RESET_DISABLE BIT(16)
|
||||
|
||||
#define UART_BURST_STATUS_REG 0x9C
|
||||
#define UART_TX_BURST_FIFO 0xA0
|
||||
#define UART_RX_BURST_FIFO 0xA4
|
||||
|
||||
#define UART_BIT_DIVISOR_8 0x26731000
|
||||
#define UART_BIT_DIVISOR_16 0x6ef71000
|
||||
#define UART_BAUD_4MBPS 4000000
|
||||
|
||||
#define MAX_PORTS 4
|
||||
#define PORT_OFFSET 0x100
|
||||
#define RX_BUF_SIZE 512
|
||||
|
@ -109,6 +124,7 @@
|
|||
#define UART_BURST_SIZE 4
|
||||
|
||||
#define UART_BST_STAT_RX_COUNT_MASK 0x00FF
|
||||
#define UART_BST_STAT_TX_COUNT_MASK 0xFF00
|
||||
#define UART_BST_STAT_IIR_INT_PEND 0x100000
|
||||
#define UART_LSR_OVERRUN_ERR_CLR 0x43
|
||||
#define UART_BST_STAT_LSR_RX_MASK 0x9F000000
|
||||
|
@ -116,6 +132,7 @@
|
|||
#define UART_BST_STAT_LSR_OVERRUN_ERR 0x2000000
|
||||
#define UART_BST_STAT_LSR_PARITY_ERR 0x4000000
|
||||
#define UART_BST_STAT_LSR_FRAME_ERR 0x8000000
|
||||
#define UART_BST_STAT_LSR_THRE 0x20000000
|
||||
|
||||
struct pci1xxxx_8250 {
|
||||
unsigned int nr;
|
||||
|
@ -206,15 +223,21 @@ static int pci1xxxx_get_num_ports(struct pci_dev *dev)
|
|||
static unsigned int pci1xxxx_get_divisor(struct uart_port *port,
|
||||
unsigned int baud, unsigned int *frac)
|
||||
{
|
||||
unsigned int uart_sample_cnt;
|
||||
unsigned int quot;
|
||||
|
||||
if (baud >= UART_BAUD_4MBPS)
|
||||
uart_sample_cnt = UART_BIT_SAMPLE_CNT_8;
|
||||
else
|
||||
uart_sample_cnt = UART_BIT_SAMPLE_CNT_16;
|
||||
|
||||
/*
|
||||
* Calculate baud rate sampling period in nanoseconds.
|
||||
* Fractional part x denotes x/255 parts of a nanosecond.
|
||||
*/
|
||||
quot = NSEC_PER_SEC / (baud * UART_BIT_SAMPLE_CNT);
|
||||
*frac = (NSEC_PER_SEC - quot * baud * UART_BIT_SAMPLE_CNT) *
|
||||
255 / UART_BIT_SAMPLE_CNT / baud;
|
||||
quot = NSEC_PER_SEC / (baud * uart_sample_cnt);
|
||||
*frac = (NSEC_PER_SEC - quot * baud * uart_sample_cnt) *
|
||||
255 / uart_sample_cnt / baud;
|
||||
|
||||
return quot;
|
||||
}
|
||||
|
@ -222,6 +245,11 @@ static unsigned int pci1xxxx_get_divisor(struct uart_port *port,
|
|||
static void pci1xxxx_set_divisor(struct uart_port *port, unsigned int baud,
|
||||
unsigned int quot, unsigned int frac)
|
||||
{
|
||||
if (baud >= UART_BAUD_4MBPS)
|
||||
writel(UART_BIT_DIVISOR_8, port->membase + FRAC_DIV_CFG_REG);
|
||||
else
|
||||
writel(UART_BIT_DIVISOR_16, port->membase + FRAC_DIV_CFG_REG);
|
||||
|
||||
writel(FIELD_PREP(BAUD_CLOCK_DIV_INT_MSK, quot) | frac,
|
||||
port->membase + UART_BAUD_CLK_DIVISOR_REG);
|
||||
}
|
||||
|
@ -233,7 +261,16 @@ static int pci1xxxx_rs485_config(struct uart_port *port,
|
|||
u32 delay_in_baud_periods;
|
||||
u32 baud_period_in_ns;
|
||||
u32 mode_cfg = 0;
|
||||
u32 sample_cnt;
|
||||
u32 clock_div;
|
||||
u32 frac_div;
|
||||
|
||||
frac_div = readl(port->membase + FRAC_DIV_CFG_REG);
|
||||
|
||||
if (frac_div == UART_BIT_DIVISOR_16)
|
||||
sample_cnt = UART_BIT_SAMPLE_CNT_16;
|
||||
else
|
||||
sample_cnt = UART_BIT_SAMPLE_CNT_8;
|
||||
|
||||
/*
|
||||
* pci1xxxx's uart hardware supports only RTS delay after
|
||||
|
@ -249,7 +286,7 @@ static int pci1xxxx_rs485_config(struct uart_port *port,
|
|||
clock_div = readl(port->membase + UART_BAUD_CLK_DIVISOR_REG);
|
||||
baud_period_in_ns =
|
||||
FIELD_GET(BAUD_CLOCK_DIV_INT_MSK, clock_div) *
|
||||
UART_BIT_SAMPLE_CNT;
|
||||
sample_cnt;
|
||||
delay_in_baud_periods =
|
||||
rs485->delay_rts_after_send * NSEC_PER_MSEC /
|
||||
baud_period_in_ns;
|
||||
|
@ -344,6 +381,105 @@ static void pci1xxxx_rx_burst(struct uart_port *port, u32 uart_status)
|
|||
}
|
||||
}
|
||||
|
||||
static void pci1xxxx_process_write_data(struct uart_port *port,
|
||||
struct circ_buf *xmit,
|
||||
int *data_empty_count,
|
||||
u32 *valid_byte_count)
|
||||
{
|
||||
u32 valid_burst_count = *valid_byte_count / UART_BURST_SIZE;
|
||||
|
||||
/*
|
||||
* Each transaction transfers data in DWORDs. If there are less than
|
||||
* four remaining valid_byte_count to transfer or if the circular
|
||||
* buffer has insufficient space for a DWORD, the data is transferred
|
||||
* one byte at a time.
|
||||
*/
|
||||
while (valid_burst_count) {
|
||||
if (*data_empty_count - UART_BURST_SIZE < 0)
|
||||
break;
|
||||
if (xmit->tail > (UART_XMIT_SIZE - UART_BURST_SIZE))
|
||||
break;
|
||||
writel(*(unsigned int *)&xmit->buf[xmit->tail],
|
||||
port->membase + UART_TX_BURST_FIFO);
|
||||
*valid_byte_count -= UART_BURST_SIZE;
|
||||
*data_empty_count -= UART_BURST_SIZE;
|
||||
valid_burst_count -= UART_BYTE_SIZE;
|
||||
|
||||
xmit->tail = (xmit->tail + UART_BURST_SIZE) &
|
||||
(UART_XMIT_SIZE - 1);
|
||||
}
|
||||
|
||||
while (*valid_byte_count) {
|
||||
if (*data_empty_count - UART_BYTE_SIZE < 0)
|
||||
break;
|
||||
writeb(xmit->buf[xmit->tail], port->membase +
|
||||
UART_TX_BYTE_FIFO);
|
||||
*data_empty_count -= UART_BYTE_SIZE;
|
||||
*valid_byte_count -= UART_BYTE_SIZE;
|
||||
|
||||
/*
|
||||
* When the tail of the circular buffer is reached, the next
|
||||
* byte is transferred to the beginning of the buffer.
|
||||
*/
|
||||
xmit->tail = (xmit->tail + UART_BYTE_SIZE) &
|
||||
(UART_XMIT_SIZE - 1);
|
||||
|
||||
/*
|
||||
* If there are any pending burst count, data is handled by
|
||||
* transmitting DWORDs at a time.
|
||||
*/
|
||||
if (valid_burst_count && (xmit->tail <
|
||||
(UART_XMIT_SIZE - UART_BURST_SIZE)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pci1xxxx_tx_burst(struct uart_port *port, u32 uart_status)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
u32 valid_byte_count;
|
||||
int data_empty_count;
|
||||
struct circ_buf *xmit;
|
||||
|
||||
xmit = &port->state->xmit;
|
||||
|
||||
if (port->x_char) {
|
||||
writeb(port->x_char, port->membase + UART_TX);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((uart_tx_stopped(port)) || (uart_circ_empty(xmit))) {
|
||||
port->ops->stop_tx(port);
|
||||
} else {
|
||||
data_empty_count = (pci1xxxx_read_burst_status(port) &
|
||||
UART_BST_STAT_TX_COUNT_MASK) >> 8;
|
||||
do {
|
||||
valid_byte_count = uart_circ_chars_pending(xmit);
|
||||
|
||||
pci1xxxx_process_write_data(port, xmit,
|
||||
&data_empty_count,
|
||||
&valid_byte_count);
|
||||
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (data_empty_count && valid_byte_count);
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
/*
|
||||
* With RPM enabled, we have to wait until the FIFO is empty before
|
||||
* the HW can go idle. So we get here once again with empty FIFO and
|
||||
* disable the interrupt and RPM in __stop_tx()
|
||||
*/
|
||||
if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
|
||||
port->ops->stop_tx(port);
|
||||
}
|
||||
|
||||
static int pci1xxxx_handle_irq(struct uart_port *port)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -359,6 +495,9 @@ static int pci1xxxx_handle_irq(struct uart_port *port)
|
|||
if (status & UART_BST_STAT_LSR_RX_MASK)
|
||||
pci1xxxx_rx_burst(port, status);
|
||||
|
||||
if (status & UART_BST_STAT_LSR_THRE)
|
||||
pci1xxxx_tx_burst(port, status);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
return 1;
|
||||
|
@ -481,6 +620,17 @@ static int pci1xxxx_setup(struct pci_dev *pdev,
|
|||
|
||||
port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST;
|
||||
port->port.type = PORT_MCHP16550A;
|
||||
/*
|
||||
* 8250 core considers prescaller value to be always 16.
|
||||
* The MCHP ports support downscaled mode and hence the
|
||||
* functional UART clock can be lower, i.e. 62.5MHz, than
|
||||
* software expects in order to support higher baud rates.
|
||||
* Assign here 64MHz to support 4Mbps.
|
||||
*
|
||||
* The value itself is not really used anywhere except baud
|
||||
* rate calculations, so we can mangle it as we wish.
|
||||
*/
|
||||
port->port.uartclk = 64 * HZ_PER_MHZ;
|
||||
port->port.set_termios = serial8250_do_set_termios;
|
||||
port->port.get_divisor = pci1xxxx_get_divisor;
|
||||
port->port.set_divisor = pci1xxxx_set_divisor;
|
||||
|
@ -594,7 +744,6 @@ static int pci1xxxx_serial_probe(struct pci_dev *pdev,
|
|||
|
||||
memset(&uart, 0, sizeof(uart));
|
||||
uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT;
|
||||
uart.port.uartclk = UART_CLOCK_DEFAULT;
|
||||
uart.port.dev = dev;
|
||||
|
||||
if (num_vectors == max_vec_reqd)
|
||||
|
|
|
@ -38,10 +38,6 @@
|
|||
|
||||
#include "8250.h"
|
||||
|
||||
/* Nuvoton NPCM timeout register */
|
||||
#define UART_NPCM_TOR 7
|
||||
#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */
|
||||
|
||||
/*
|
||||
* Debugging.
|
||||
*/
|
||||
|
@ -1329,9 +1325,6 @@ static void autoconfig_irq(struct uart_8250_port *up)
|
|||
inb_p(ICP);
|
||||
}
|
||||
|
||||
if (uart_console(port))
|
||||
console_lock();
|
||||
|
||||
/* forget possible initially masked and pending IRQ */
|
||||
probe_irq_off(probe_irq_on());
|
||||
save_mcr = serial8250_in_MCR(up);
|
||||
|
@ -1371,9 +1364,6 @@ static void autoconfig_irq(struct uart_8250_port *up)
|
|||
if (port->flags & UPF_FOURPORT)
|
||||
outb_p(save_ICP, ICP);
|
||||
|
||||
if (uart_console(port))
|
||||
console_unlock();
|
||||
|
||||
port->irq = (irq > 0) ? irq : 0;
|
||||
}
|
||||
|
||||
|
@ -2235,15 +2225,6 @@ int serial8250_do_startup(struct uart_port *port)
|
|||
UART_DA830_PWREMU_MGMT_FREE);
|
||||
}
|
||||
|
||||
if (port->type == PORT_NPCM) {
|
||||
/*
|
||||
* Nuvoton calls the scratch register 'UART_TOR' (timeout
|
||||
* register). Enable it, and set TIOC (timeout interrupt
|
||||
* comparator) to be 0x20 for correct operation.
|
||||
*/
|
||||
serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_RSA
|
||||
/*
|
||||
* If this is an RSA port, see if we can kick it up to the
|
||||
|
@ -2545,15 +2526,6 @@ static void serial8250_shutdown(struct uart_port *port)
|
|||
serial8250_do_shutdown(port);
|
||||
}
|
||||
|
||||
/* Nuvoton NPCM UARTs have a custom divisor calculation */
|
||||
static unsigned int npcm_get_divisor(struct uart_8250_port *up,
|
||||
unsigned int baud)
|
||||
{
|
||||
struct uart_port *port = &up->port;
|
||||
|
||||
return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2;
|
||||
}
|
||||
|
||||
static unsigned int serial8250_do_get_divisor(struct uart_port *port,
|
||||
unsigned int baud,
|
||||
unsigned int *frac)
|
||||
|
@ -2598,8 +2570,6 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port,
|
|||
quot = 0x8001;
|
||||
else if (magic_multiplier && baud >= port->uartclk / 12)
|
||||
quot = 0x8002;
|
||||
else if (up->port.type == PORT_NPCM)
|
||||
quot = npcm_get_divisor(up, baud);
|
||||
else
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
|
@ -2714,12 +2684,8 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
|
|||
*/
|
||||
void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
struct tty_port *tport = &port->state->port;
|
||||
unsigned int baud, quot, frac = 0;
|
||||
struct ktermios *termios;
|
||||
struct tty_struct *tty;
|
||||
unsigned long flags;
|
||||
|
||||
tty = tty_port_tty_get(tport);
|
||||
if (!tty) {
|
||||
|
@ -2740,21 +2706,7 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
|
|||
if (!tty_port_initialized(tport))
|
||||
goto out_unlock;
|
||||
|
||||
termios = &tty->termios;
|
||||
|
||||
baud = serial8250_get_baud_rate(port, termios, NULL);
|
||||
quot = serial8250_get_divisor(port, baud, &frac);
|
||||
|
||||
serial8250_rpm_get(up);
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
serial8250_set_divisor(port, baud, quot, frac);
|
||||
serial_port_out(port, UART_LCR, up->lcr);
|
||||
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
serial8250_rpm_put(up);
|
||||
serial8250_do_set_termios(port, &tty->termios, NULL);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&tport->mutex);
|
||||
|
|
|
@ -92,11 +92,7 @@ static int serial_pxa_probe(struct platform_device *pdev)
|
|||
struct uart_8250_port uart = {};
|
||||
struct pxa8250_data *data;
|
||||
struct resource *mmres;
|
||||
int irq, ret;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
int ret;
|
||||
|
||||
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!mmres)
|
||||
|
@ -114,21 +110,21 @@ static int serial_pxa_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
if (ret >= 0)
|
||||
uart.port.line = ret;
|
||||
|
||||
uart.port.type = PORT_XSCALE;
|
||||
uart.port.iotype = UPIO_MEM32;
|
||||
uart.port.mapbase = mmres->start;
|
||||
uart.port.regshift = 2;
|
||||
uart.port.irq = irq;
|
||||
uart.port.fifosize = 64;
|
||||
uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE;
|
||||
uart.port.dev = &pdev->dev;
|
||||
uart.port.uartclk = clk_get_rate(data->clk);
|
||||
uart.port.pm = serial_pxa_pm;
|
||||
uart.port.private_data = data;
|
||||
|
||||
ret = uart_read_port_properties(&uart.port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
uart.port.iotype = UPIO_MEM32;
|
||||
uart.port.regshift = 2;
|
||||
uart.port.fifosize = 64;
|
||||
uart.dl_write = serial_pxa_dl_write;
|
||||
|
||||
ret = serial8250_register_8250_port(&uart);
|
||||
|
|
|
@ -57,25 +57,11 @@ static int tegra_uart_probe(struct platform_device *pdev)
|
|||
port = &port8250.port;
|
||||
spin_lock_init(&port->lock);
|
||||
|
||||
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT |
|
||||
UPF_FIXED_TYPE;
|
||||
port->iotype = UPIO_MEM32;
|
||||
port->regshift = 2;
|
||||
port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||
port->type = PORT_TEGRA;
|
||||
port->irqflags |= IRQF_SHARED;
|
||||
port->dev = &pdev->dev;
|
||||
port->handle_break = tegra_uart_handle_break;
|
||||
|
||||
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
if (ret >= 0)
|
||||
port->line = ret;
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
port->irq = ret;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
@ -88,12 +74,18 @@ static int tegra_uart_probe(struct platform_device *pdev)
|
|||
port->mapbase = res->start;
|
||||
port->mapsize = resource_size(res);
|
||||
|
||||
ret = uart_read_port_properties(port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
port->iotype = UPIO_MEM32;
|
||||
port->regshift = 2;
|
||||
|
||||
uart->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
|
||||
if (IS_ERR(uart->rst))
|
||||
return PTR_ERR(uart->rst);
|
||||
|
||||
if (device_property_read_u32(&pdev->dev, "clock-frequency",
|
||||
&port->uartclk)) {
|
||||
if (!port->uartclk) {
|
||||
uart->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(uart->clk)) {
|
||||
dev_err(&pdev->dev, "failed to get clock!\n");
|
||||
|
|
|
@ -162,7 +162,6 @@ static int uniphier_uart_probe(struct platform_device *pdev)
|
|||
struct uniphier8250_priv *priv;
|
||||
struct resource *regs;
|
||||
void __iomem *membase;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
@ -175,23 +174,12 @@ static int uniphier_uart_probe(struct platform_device *pdev)
|
|||
if (!membase)
|
||||
return -ENOMEM;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&up, 0, sizeof(up));
|
||||
|
||||
ret = of_alias_get_id(dev->of_node, "serial");
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get alias id\n");
|
||||
return ret;
|
||||
}
|
||||
up.port.line = ret;
|
||||
|
||||
priv->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(dev, "failed to get clock\n");
|
||||
|
@ -211,7 +199,10 @@ static int uniphier_uart_probe(struct platform_device *pdev)
|
|||
up.port.mapbase = regs->start;
|
||||
up.port.mapsize = resource_size(regs);
|
||||
up.port.membase = membase;
|
||||
up.port.irq = irq;
|
||||
|
||||
ret = uart_read_port_properties(&up.port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
up.port.type = PORT_16550A;
|
||||
up.port.iotype = UPIO_MEM32;
|
||||
|
|
|
@ -149,6 +149,7 @@ config SERIAL_8250_PCI
|
|||
config SERIAL_8250_EXAR
|
||||
tristate "8250/16550 Exar/Commtech PCI/PCIe device support"
|
||||
depends on SERIAL_8250 && PCI
|
||||
select SERIAL_8250_PCILIB
|
||||
default SERIAL_8250
|
||||
help
|
||||
This builds support for XR17C1xx, XR17V3xx and some Commtech
|
||||
|
|
|
@ -348,10 +348,7 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
|
|||
flag = TTY_FRAME;
|
||||
}
|
||||
|
||||
uart_port_unlock(&uap->port);
|
||||
sysrq = uart_handle_sysrq_char(&uap->port, ch & 255);
|
||||
uart_port_lock(&uap->port);
|
||||
|
||||
sysrq = uart_prepare_sysrq_char(&uap->port, ch & 255);
|
||||
if (!sysrq)
|
||||
uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
|
||||
}
|
||||
|
@ -1017,7 +1014,7 @@ static void pl011_dma_rx_callback(void *data)
|
|||
ret = pl011_dma_rx_trigger_dma(uap);
|
||||
|
||||
pl011_dma_rx_chars(uap, pending, lastbuf, false);
|
||||
uart_port_unlock_irq(&uap->port);
|
||||
uart_unlock_and_check_sysrq(&uap->port);
|
||||
/*
|
||||
* Do this check after we picked the DMA chars so we don't
|
||||
* get some IRQ immediately from RX.
|
||||
|
@ -1540,11 +1537,10 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
|
|||
static irqreturn_t pl011_int(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_amba_port *uap = dev_id;
|
||||
unsigned long flags;
|
||||
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
|
||||
int handled = 0;
|
||||
|
||||
uart_port_lock_irqsave(&uap->port, &flags);
|
||||
uart_port_lock(&uap->port);
|
||||
status = pl011_read(uap, REG_RIS) & uap->im;
|
||||
if (status) {
|
||||
do {
|
||||
|
@ -1573,7 +1569,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
|
|||
handled = 1;
|
||||
}
|
||||
|
||||
uart_port_unlock_irqrestore(&uap->port, flags);
|
||||
uart_unlock_and_check_sysrq(&uap->port);
|
||||
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
@ -2322,13 +2318,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
|
|||
|
||||
clk_enable(uap->clk);
|
||||
|
||||
local_irq_save(flags);
|
||||
if (uap->port.sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(&uap->port);
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(&uap->port, &flags);
|
||||
else
|
||||
uart_port_lock(&uap->port);
|
||||
uart_port_lock_irqsave(&uap->port, &flags);
|
||||
|
||||
/*
|
||||
* First save the CR then disable the interrupts
|
||||
|
@ -2354,8 +2347,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
|
|||
pl011_write(old_cr, uap, REG_CR);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(&uap->port);
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(&uap->port, flags);
|
||||
|
||||
clk_disable(uap->clk);
|
||||
}
|
||||
|
|
|
@ -378,7 +378,7 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)
|
|||
up->port.icount.rx++;
|
||||
ch = rdata & AR933X_UART_DATA_TX_RX_MASK;
|
||||
|
||||
if (uart_handle_sysrq_char(&up->port, ch))
|
||||
if (uart_prepare_sysrq_char(&up->port, ch))
|
||||
continue;
|
||||
|
||||
if ((up->port.ignore_status_mask & AR933X_DUMMY_STATUS_RD) == 0)
|
||||
|
@ -468,7 +468,7 @@ static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id)
|
|||
ar933x_uart_tx_chars(up);
|
||||
}
|
||||
|
||||
uart_port_unlock(&up->port);
|
||||
uart_unlock_and_check_sysrq(&up->port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -627,14 +627,10 @@ static void ar933x_uart_console_write(struct console *co, const char *s,
|
|||
unsigned int int_en;
|
||||
int locked = 1;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (up->port.sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(&up->port);
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(&up->port, &flags);
|
||||
else
|
||||
uart_port_lock(&up->port);
|
||||
uart_port_lock_irqsave(&up->port, &flags);
|
||||
|
||||
/*
|
||||
* First save the IER then disable the interrupts
|
||||
|
@ -654,9 +650,7 @@ static void ar933x_uart_console_write(struct console *co, const char *s,
|
|||
ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(&up->port);
|
||||
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(&up->port, flags);
|
||||
}
|
||||
|
||||
static int ar933x_uart_console_setup(struct console *co, char *options)
|
||||
|
|
|
@ -285,10 +285,9 @@ static void bcm_uart_do_rx(struct uart_port *port)
|
|||
flag = TTY_PARITY;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(port, c))
|
||||
if (uart_prepare_sysrq_char(port, c))
|
||||
continue;
|
||||
|
||||
|
||||
if ((cstat & port->ignore_status_mask) == 0)
|
||||
tty_insert_flip_char(tty_port, c, flag);
|
||||
|
||||
|
@ -353,7 +352,7 @@ static irqreturn_t bcm_uart_interrupt(int irq, void *dev_id)
|
|||
estat & UART_EXTINP_DCD_MASK);
|
||||
}
|
||||
|
||||
uart_port_unlock(port);
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -703,20 +702,14 @@ static void bcm_console_write(struct console *co, const char *s,
|
|||
{
|
||||
struct uart_port *port;
|
||||
unsigned long flags;
|
||||
int locked;
|
||||
int locked = 1;
|
||||
|
||||
port = &ports[co->index];
|
||||
|
||||
local_irq_save(flags);
|
||||
if (port->sysrq) {
|
||||
/* bcm_uart_interrupt() already took the lock */
|
||||
locked = 0;
|
||||
} else if (oops_in_progress) {
|
||||
locked = uart_port_trylock(port);
|
||||
} else {
|
||||
uart_port_lock(port);
|
||||
locked = 1;
|
||||
}
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(port, &flags);
|
||||
else
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
/* call helper to deal with \r\n */
|
||||
uart_console_write(port, s, count, bcm_console_putchar);
|
||||
|
@ -725,8 +718,7 @@ static void bcm_console_write(struct console *co, const char *s,
|
|||
wait_for_xmitr(port);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(port);
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -837,7 +837,6 @@ static int linflex_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
|
||||
sport->dev = &pdev->dev;
|
||||
sport->type = PORT_LINFLEXUART;
|
||||
sport->iotype = UPIO_MEM;
|
||||
sport->irq = ret;
|
||||
sport->ops = &linflex_pops;
|
||||
|
|
|
@ -395,7 +395,6 @@ static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch)
|
|||
* which in this case is the break signal.
|
||||
*/
|
||||
if (linestatus & error_mask) {
|
||||
linestatus = 0;
|
||||
readb(&ch->ch_cls_uart->txrx);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -136,20 +136,16 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
|
|||
int locked = 1;
|
||||
|
||||
touch_nmi_watchdog();
|
||||
local_irq_save(flags);
|
||||
if (up->port.sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(&up->port);
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(&up->port, &flags);
|
||||
else
|
||||
uart_port_lock(&up->port);
|
||||
uart_port_lock_irqsave(&up->port, &flags);
|
||||
|
||||
uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar);
|
||||
wait_for_xmit_empty(&up->port);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(&up->port);
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(&up->port, flags);
|
||||
}
|
||||
|
||||
static int __init lpc32xx_hsuart_console_setup(struct console *co,
|
||||
|
@ -233,8 +229,6 @@ static unsigned int __serial_get_clock_div(unsigned long uartclk,
|
|||
|
||||
hsu_rate++;
|
||||
}
|
||||
if (hsu_rate > 0xFF)
|
||||
hsu_rate = 0xFF;
|
||||
|
||||
return goodrate;
|
||||
}
|
||||
|
@ -268,7 +262,8 @@ static void __serial_lpc32xx_rx(struct uart_port *port)
|
|||
tty_insert_flip_char(tport, 0, TTY_FRAME);
|
||||
}
|
||||
|
||||
tty_insert_flip_char(tport, (tmp & 0xFF), flag);
|
||||
if (!uart_prepare_sysrq_char(port, tmp & 0xff))
|
||||
tty_insert_flip_char(tport, (tmp & 0xFF), flag);
|
||||
|
||||
tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
|
||||
}
|
||||
|
@ -333,7 +328,7 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
|
|||
__serial_lpc32xx_tx(port);
|
||||
}
|
||||
|
||||
uart_port_unlock(port);
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define MAX310X_MAJOR 204
|
||||
#define MAX310X_MINOR 209
|
||||
#define MAX310X_UART_NRMAX 16
|
||||
#define MAX310X_MAX_PORTS 4 /* Maximum number of UART ports per IC. */
|
||||
|
||||
/* MAX310X register definitions */
|
||||
#define MAX310X_RHR_REG (0x00) /* RX FIFO */
|
||||
|
@ -66,6 +67,7 @@
|
|||
#define MAX310X_BRGDIVMSB_REG (0x1d) /* Baud rate divisor MSB */
|
||||
#define MAX310X_CLKSRC_REG (0x1e) /* Clock source */
|
||||
#define MAX310X_REG_1F (0x1f)
|
||||
#define MAX310X_EXTREG_START (0x20) /* Only relevant in SPI mode. */
|
||||
|
||||
#define MAX310X_REVID_REG MAX310X_REG_1F /* Revision ID */
|
||||
|
||||
|
@ -73,9 +75,9 @@
|
|||
#define MAX310X_GLOBALCMD_REG MAX310X_REG_1F /* Global Command (WO) */
|
||||
|
||||
/* Extended registers */
|
||||
#define MAX310X_SPI_REVID_EXTREG MAX310X_REG_05 /* Revision ID */
|
||||
#define MAX310X_I2C_REVID_EXTREG (0x25) /* Revision ID */
|
||||
|
||||
#define MAX310X_REVID_EXTREG (0x25) /* Revision ID
|
||||
* (extended addressing space)
|
||||
*/
|
||||
/* IRQ register bits */
|
||||
#define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */
|
||||
#define MAX310X_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */
|
||||
|
@ -160,14 +162,14 @@
|
|||
#define MAX310X_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */
|
||||
|
||||
/* Flow control trigger level register masks */
|
||||
#define MAX310X_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */
|
||||
#define MAX310X_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */
|
||||
#define MAX310X_FLOWLVL_HALT_MASK GENMASK(3, 0) /* Flow control halt level */
|
||||
#define MAX310X_FLOWLVL_RES_MASK GENMASK(7, 4) /* Flow control resume level */
|
||||
#define MAX310X_FLOWLVL_HALT(words) ((words / 8) & 0x0f)
|
||||
#define MAX310X_FLOWLVL_RES(words) (((words / 8) & 0x0f) << 4)
|
||||
|
||||
/* FIFO interrupt trigger level register masks */
|
||||
#define MAX310X_FIFOTRIGLVL_TX_MASK (0x0f) /* TX FIFO trigger level */
|
||||
#define MAX310X_FIFOTRIGLVL_RX_MASK (0xf0) /* RX FIFO trigger level */
|
||||
#define MAX310X_FIFOTRIGLVL_TX_MASK GENMASK(3, 0) /* TX FIFO trigger level */
|
||||
#define MAX310X_FIFOTRIGLVL_RX_MASK GENMASK(7, 4) /* RX FIFO trigger level */
|
||||
#define MAX310X_FIFOTRIGLVL_TX(words) ((words / 8) & 0x0f)
|
||||
#define MAX310X_FIFOTRIGLVL_RX(words) (((words / 8) & 0x0f) << 4)
|
||||
|
||||
|
@ -177,7 +179,8 @@
|
|||
#define MAX310X_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs
|
||||
* are used in conjunction with
|
||||
* XOFF2 for definition of
|
||||
* special character */
|
||||
* special character
|
||||
*/
|
||||
#define MAX310X_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */
|
||||
#define MAX310X_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */
|
||||
#define MAX310X_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1
|
||||
|
@ -214,8 +217,8 @@
|
|||
*/
|
||||
|
||||
/* PLL configuration register masks */
|
||||
#define MAX310X_PLLCFG_PREDIV_MASK (0x3f) /* PLL predivision value */
|
||||
#define MAX310X_PLLCFG_PLLFACTOR_MASK (0xc0) /* PLL multiplication factor */
|
||||
#define MAX310X_PLLCFG_PREDIV_MASK GENMASK(5, 0) /* PLL predivision value */
|
||||
#define MAX310X_PLLCFG_PLLFACTOR_MASK GENMASK(7, 6) /* PLL multiplication factor */
|
||||
|
||||
/* Baud rate generator configuration register bits */
|
||||
#define MAX310X_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */
|
||||
|
@ -234,7 +237,7 @@
|
|||
|
||||
/* Misc definitions */
|
||||
#define MAX310X_FIFO_SIZE (128)
|
||||
#define MAX310x_REV_MASK (0xf8)
|
||||
#define MAX310x_REV_MASK GENMASK(7, 3)
|
||||
#define MAX310X_WRITE_BIT 0x80
|
||||
|
||||
/* Port startup definitions */
|
||||
|
@ -257,20 +260,21 @@
|
|||
|
||||
struct max310x_if_cfg {
|
||||
int (*extended_reg_enable)(struct device *dev, bool enable);
|
||||
|
||||
unsigned int rev_id_reg;
|
||||
u8 rev_id_offset;
|
||||
};
|
||||
|
||||
struct max310x_devtype {
|
||||
struct {
|
||||
unsigned short min;
|
||||
unsigned short max;
|
||||
} slave_addr;
|
||||
char name[9];
|
||||
} slave_addr; /* Relevant only in I2C mode. */
|
||||
int nr;
|
||||
char name[9];
|
||||
u8 mode1;
|
||||
int (*detect)(struct device *);
|
||||
void (*power)(struct uart_port *, int);
|
||||
u8 rev_id_val;
|
||||
u8 rev_id_reg; /* Relevant only if rev_id_val is defined. */
|
||||
u8 power_reg; /* Register address for power/sleep control. */
|
||||
u8 power_bit; /* Bit for sleep or power-off mode (active high). */
|
||||
};
|
||||
|
||||
struct max310x_one {
|
||||
|
@ -331,62 +335,52 @@ static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val)
|
|||
regmap_update_bits(one->regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
static int max3107_detect(struct device *dev)
|
||||
static int max310x_detect(struct device *dev)
|
||||
{
|
||||
struct max310x_port *s = dev_get_drvdata(dev);
|
||||
unsigned int val = 0;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Check if variant supports REV ID register: */
|
||||
if (s->devtype->rev_id_val) {
|
||||
u8 rev_id_reg = s->devtype->rev_id_reg;
|
||||
|
||||
if (((val & MAX310x_REV_MASK) != MAX3107_REV_ID)) {
|
||||
dev_err(dev,
|
||||
"%s ID 0x%02x does not match\n", s->devtype->name, val);
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Check if REV ID is in extended addressing space: */
|
||||
if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) {
|
||||
ret = s->if_cfg->extended_reg_enable(dev, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Adjust REV ID extended addressing space address: */
|
||||
if (s->if_cfg->rev_id_offset)
|
||||
rev_id_reg -= s->if_cfg->rev_id_offset;
|
||||
}
|
||||
|
||||
static int max3108_detect(struct device *dev)
|
||||
{
|
||||
struct max310x_port *s = dev_get_drvdata(dev);
|
||||
unsigned int val = 0;
|
||||
int ret;
|
||||
regmap_read(s->regmap, rev_id_reg, &val);
|
||||
|
||||
/* MAX3108 have not REV ID register, we just check default value
|
||||
* from clocksource register to make sure everything works.
|
||||
*/
|
||||
ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) {
|
||||
ret = s->if_cfg->extended_reg_enable(dev, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT)) {
|
||||
dev_err(dev, "%s not present\n", s->devtype->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (((val & MAX310x_REV_MASK) != s->devtype->rev_id_val))
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
"%s ID 0x%02x does not match\n",
|
||||
s->devtype->name, val);
|
||||
} else {
|
||||
/*
|
||||
* For variant without REV ID register, just check default value
|
||||
* from clocksource register to make sure everything works.
|
||||
*/
|
||||
ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max3109_detect(struct device *dev)
|
||||
{
|
||||
struct max310x_port *s = dev_get_drvdata(dev);
|
||||
unsigned int val = 0;
|
||||
int ret;
|
||||
|
||||
ret = s->if_cfg->extended_reg_enable(dev, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
|
||||
s->if_cfg->extended_reg_enable(dev, false);
|
||||
if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) {
|
||||
dev_err(dev,
|
||||
"%s ID 0x%02x does not match\n", s->devtype->name, val);
|
||||
return -ENODEV;
|
||||
if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT))
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
"%s not present\n",
|
||||
s->devtype->name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -394,39 +388,10 @@ static int max3109_detect(struct device *dev)
|
|||
|
||||
static void max310x_power(struct uart_port *port, int on)
|
||||
{
|
||||
max310x_port_update(port, MAX310X_MODE1_REG,
|
||||
MAX310X_MODE1_FORCESLEEP_BIT,
|
||||
on ? 0 : MAX310X_MODE1_FORCESLEEP_BIT);
|
||||
if (on)
|
||||
msleep(50);
|
||||
}
|
||||
struct max310x_port *s = dev_get_drvdata(port->dev);
|
||||
|
||||
static int max14830_detect(struct device *dev)
|
||||
{
|
||||
struct max310x_port *s = dev_get_drvdata(dev);
|
||||
unsigned int val = 0;
|
||||
int ret;
|
||||
|
||||
ret = s->if_cfg->extended_reg_enable(dev, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
|
||||
s->if_cfg->extended_reg_enable(dev, false);
|
||||
if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) {
|
||||
dev_err(dev,
|
||||
"%s ID 0x%02x does not match\n", s->devtype->name, val);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void max14830_power(struct uart_port *port, int on)
|
||||
{
|
||||
max310x_port_update(port, MAX310X_BRGCFG_REG,
|
||||
MAX14830_BRGCFG_CLKDIS_BIT,
|
||||
on ? 0 : MAX14830_BRGCFG_CLKDIS_BIT);
|
||||
max310x_port_update(port, s->devtype->power_reg, s->devtype->power_bit,
|
||||
on ? 0 : s->devtype->power_bit);
|
||||
if (on)
|
||||
msleep(50);
|
||||
}
|
||||
|
@ -435,8 +400,10 @@ static const struct max310x_devtype max3107_devtype = {
|
|||
.name = "MAX3107",
|
||||
.nr = 1,
|
||||
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT,
|
||||
.detect = max3107_detect,
|
||||
.power = max310x_power,
|
||||
.rev_id_val = MAX3107_REV_ID,
|
||||
.rev_id_reg = MAX310X_REVID_REG,
|
||||
.power_reg = MAX310X_MODE1_REG,
|
||||
.power_bit = MAX310X_MODE1_FORCESLEEP_BIT,
|
||||
.slave_addr = {
|
||||
.min = 0x2c,
|
||||
.max = 0x2f,
|
||||
|
@ -447,8 +414,10 @@ static const struct max310x_devtype max3108_devtype = {
|
|||
.name = "MAX3108",
|
||||
.nr = 1,
|
||||
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT,
|
||||
.detect = max3108_detect,
|
||||
.power = max310x_power,
|
||||
.rev_id_val = 0, /* Unsupported. */
|
||||
.rev_id_reg = 0, /* Irrelevant when rev_id_val is not defined. */
|
||||
.power_reg = MAX310X_MODE1_REG,
|
||||
.power_bit = MAX310X_MODE1_FORCESLEEP_BIT,
|
||||
.slave_addr = {
|
||||
.min = 0x60,
|
||||
.max = 0x6f,
|
||||
|
@ -459,8 +428,10 @@ static const struct max310x_devtype max3109_devtype = {
|
|||
.name = "MAX3109",
|
||||
.nr = 2,
|
||||
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT,
|
||||
.detect = max3109_detect,
|
||||
.power = max310x_power,
|
||||
.rev_id_val = MAX3109_REV_ID,
|
||||
.rev_id_reg = MAX310X_REVID_EXTREG,
|
||||
.power_reg = MAX310X_MODE1_REG,
|
||||
.power_bit = MAX310X_MODE1_FORCESLEEP_BIT,
|
||||
.slave_addr = {
|
||||
.min = 0x60,
|
||||
.max = 0x6f,
|
||||
|
@ -471,8 +442,10 @@ static const struct max310x_devtype max14830_devtype = {
|
|||
.name = "MAX14830",
|
||||
.nr = 4,
|
||||
.mode1 = MAX310X_MODE1_IRQSEL_BIT,
|
||||
.detect = max14830_detect,
|
||||
.power = max14830_power,
|
||||
.rev_id_val = MAX14830_REV_ID,
|
||||
.rev_id_reg = MAX310X_REVID_EXTREG,
|
||||
.power_reg = MAX310X_BRGCFG_REG,
|
||||
.power_bit = MAX14830_BRGCFG_CLKDIS_BIT,
|
||||
.slave_addr = {
|
||||
.min = 0x60,
|
||||
.max = 0x6f,
|
||||
|
@ -490,10 +463,8 @@ static bool max310x_reg_writeable(struct device *dev, unsigned int reg)
|
|||
case MAX310X_RXFIFOLVL_REG:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
|
||||
|
@ -512,10 +483,8 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
|
|||
case MAX310X_REG_1F:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool max310x_reg_precious(struct device *dev, unsigned int reg)
|
||||
|
@ -527,10 +496,8 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
|
|||
case MAX310X_STS_IRQSTS_REG:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool max310x_reg_noinc(struct device *dev, unsigned int reg)
|
||||
|
@ -689,7 +656,8 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
|||
u8 ch, flag;
|
||||
|
||||
if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) {
|
||||
/* We are just reading, happily ignoring any error conditions.
|
||||
/*
|
||||
* We are just reading, happily ignoring any error conditions.
|
||||
* Break condition, parity checking, framing errors -- they
|
||||
* are all ignored. That means that we can do a batch-read.
|
||||
*
|
||||
|
@ -698,7 +666,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
|||
* that the LSR register applies to the "current" character.
|
||||
* That's also the reason why we cannot do batched reads when
|
||||
* asked to check the individual statuses.
|
||||
* */
|
||||
*/
|
||||
|
||||
sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
||||
max310x_batch_read(port, one->rx_buf, rxlen);
|
||||
|
@ -802,8 +770,10 @@ static void max310x_handle_tx(struct uart_port *port)
|
|||
to_send = (to_send > txlen) ? txlen : to_send;
|
||||
|
||||
if (until_end < to_send) {
|
||||
/* It's a circ buffer -- wrap around.
|
||||
* We could do that in one SPI transaction, but meh. */
|
||||
/*
|
||||
* It's a circ buffer -- wrap around.
|
||||
* We could do that in one SPI transaction, but meh.
|
||||
*/
|
||||
max310x_batch_write(port, xmit->buf + xmit->tail, until_end);
|
||||
max310x_batch_write(port, xmit->buf, to_send - until_end);
|
||||
} else {
|
||||
|
@ -848,6 +818,7 @@ static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno)
|
|||
if (ists & MAX310X_IRQ_TXEMPTY_BIT)
|
||||
max310x_start_tx(port);
|
||||
} while (1);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -892,7 +863,8 @@ static unsigned int max310x_tx_empty(struct uart_port *port)
|
|||
|
||||
static unsigned int max310x_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
/* DCD and DSR are not wired and CTS/RTS is handled automatically
|
||||
/*
|
||||
* DCD and DSR are not wired and CTS/RTS is handled automatically
|
||||
* so just indicate DSR and CAR asserted
|
||||
*/
|
||||
return TIOCM_DSR | TIOCM_CAR;
|
||||
|
@ -984,7 +956,8 @@ static void max310x_set_termios(struct uart_port *port,
|
|||
max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]);
|
||||
max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]);
|
||||
|
||||
/* Disable transmitter before enabling AutoCTS or auto transmitter
|
||||
/*
|
||||
* Disable transmitter before enabling AutoCTS or auto transmitter
|
||||
* flow control
|
||||
*/
|
||||
if (termios->c_cflag & CRTSCTS || termios->c_iflag & IXOFF) {
|
||||
|
@ -1011,7 +984,8 @@ static void max310x_set_termios(struct uart_port *port,
|
|||
}
|
||||
max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow);
|
||||
|
||||
/* Enable transmitter after disabling AutoCTS and auto transmitter
|
||||
/*
|
||||
* Enable transmitter after disabling AutoCTS and auto transmitter
|
||||
* flow control
|
||||
*/
|
||||
if (!(termios->c_cflag & CRTSCTS) && !(termios->c_iflag & IXOFF)) {
|
||||
|
@ -1072,10 +1046,9 @@ static int max310x_rs485_config(struct uart_port *port, struct ktermios *termios
|
|||
|
||||
static int max310x_startup(struct uart_port *port)
|
||||
{
|
||||
struct max310x_port *s = dev_get_drvdata(port->dev);
|
||||
unsigned int val;
|
||||
|
||||
s->devtype->power(port, 1);
|
||||
max310x_power(port, 1);
|
||||
|
||||
/* Configure MODE1 register */
|
||||
max310x_port_update(port, MAX310X_MODE1_REG,
|
||||
|
@ -1103,8 +1076,11 @@ static int max310x_startup(struct uart_port *port)
|
|||
MAX310X_MODE2_ECHOSUPR_BIT);
|
||||
}
|
||||
|
||||
/* Configure flow control levels */
|
||||
/* Flow control halt level 96, resume level 48 */
|
||||
/*
|
||||
* Configure flow control levels:
|
||||
* resume: 48
|
||||
* halt: 96
|
||||
*/
|
||||
max310x_port_write(port, MAX310X_FLOWLVL_REG,
|
||||
MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96));
|
||||
|
||||
|
@ -1120,12 +1096,10 @@ static int max310x_startup(struct uart_port *port)
|
|||
|
||||
static void max310x_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct max310x_port *s = dev_get_drvdata(port->dev);
|
||||
|
||||
/* Disable all interrupts */
|
||||
max310x_port_write(port, MAX310X_IRQEN_REG, 0);
|
||||
|
||||
s->devtype->power(port, 0);
|
||||
max310x_power(port, 0);
|
||||
}
|
||||
|
||||
static const char *max310x_type(struct uart_port *port)
|
||||
|
@ -1187,7 +1161,7 @@ static int __maybe_unused max310x_suspend(struct device *dev)
|
|||
|
||||
for (i = 0; i < s->devtype->nr; i++) {
|
||||
uart_suspend_port(&max310x_uart, &s->p[i].port);
|
||||
s->devtype->power(&s->p[i].port, 0);
|
||||
max310x_power(&s->p[i].port, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1199,7 +1173,7 @@ static int __maybe_unused max310x_resume(struct device *dev)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < s->devtype->nr; i++) {
|
||||
s->devtype->power(&s->p[i].port, 1);
|
||||
max310x_power(&s->p[i].port, 1);
|
||||
uart_resume_port(&max310x_uart, &s->p[i].port);
|
||||
}
|
||||
|
||||
|
@ -1209,7 +1183,7 @@ static int __maybe_unused max310x_resume(struct device *dev)
|
|||
static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
static int max310x_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
unsigned int val;
|
||||
struct max310x_port *s = gpiochip_get_data(chip);
|
||||
|
@ -1220,7 +1194,7 @@ static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
|
|||
return !!((val >> 4) & (1 << (offset % 4)));
|
||||
}
|
||||
|
||||
static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
static void max310x_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
{
|
||||
struct max310x_port *s = gpiochip_get_data(chip);
|
||||
struct uart_port *port = &s->p[offset / 4].port;
|
||||
|
@ -1229,7 +1203,7 @@ static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
|||
value ? 1 << (offset % 4) : 0);
|
||||
}
|
||||
|
||||
static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct max310x_port *s = gpiochip_get_data(chip);
|
||||
struct uart_port *port = &s->p[offset / 4].port;
|
||||
|
@ -1240,7 +1214,7 @@ static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
|||
}
|
||||
|
||||
static int max310x_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
struct max310x_port *s = gpiochip_get_data(chip);
|
||||
struct uart_port *port = &s->p[offset / 4].port;
|
||||
|
@ -1296,10 +1270,9 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
|||
|
||||
/* Alloc port structure */
|
||||
s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL);
|
||||
if (!s) {
|
||||
dev_err(dev, "Error allocating port structure\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!s)
|
||||
return dev_err_probe(dev, -ENOMEM,
|
||||
"Error allocating port structure\n");
|
||||
|
||||
/* Always ask for fixed clock rate from a property. */
|
||||
device_property_read_u32(dev, "clock-frequency", &uartclk);
|
||||
|
@ -1320,8 +1293,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
|||
if (freq == 0)
|
||||
freq = uartclk;
|
||||
if (freq == 0) {
|
||||
dev_err(dev, "Cannot get clock rate\n");
|
||||
ret = -EINVAL;
|
||||
ret = dev_err_probe(dev, -EINVAL, "Cannot get clock rate\n");
|
||||
goto out_clk;
|
||||
}
|
||||
|
||||
|
@ -1345,7 +1317,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
|||
dev_set_drvdata(dev, s);
|
||||
|
||||
/* Check device to ensure we are talking to what we expect */
|
||||
ret = devtype->detect(dev);
|
||||
ret = max310x_detect(dev);
|
||||
if (ret)
|
||||
goto out_clk;
|
||||
|
||||
|
@ -1427,14 +1399,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
|||
|
||||
/* Register port */
|
||||
ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
|
||||
if (ret) {
|
||||
s->p[i].port.dev = NULL;
|
||||
if (ret)
|
||||
goto out_uart;
|
||||
}
|
||||
|
||||
set_bit(line, max310x_lines);
|
||||
|
||||
/* Go to suspend mode */
|
||||
devtype->power(&s->p[i].port, 0);
|
||||
max310x_power(&s->p[i].port, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
|
@ -1461,14 +1432,12 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
|||
if (!ret)
|
||||
return 0;
|
||||
|
||||
dev_err(dev, "Unable to reguest IRQ %i\n", irq);
|
||||
dev_err(dev, "Unable to request IRQ %i\n", irq);
|
||||
|
||||
out_uart:
|
||||
for (i = 0; i < devtype->nr; i++) {
|
||||
if (s->p[i].port.dev) {
|
||||
if (test_and_clear_bit(s->p[i].port.line, max310x_lines))
|
||||
uart_remove_one_port(&max310x_uart, &s->p[i].port);
|
||||
clear_bit(s->p[i].port.line, max310x_lines);
|
||||
}
|
||||
}
|
||||
|
||||
out_clk:
|
||||
|
@ -1486,9 +1455,11 @@ static void max310x_remove(struct device *dev)
|
|||
cancel_work_sync(&s->p[i].tx_work);
|
||||
cancel_work_sync(&s->p[i].md_work);
|
||||
cancel_work_sync(&s->p[i].rs_work);
|
||||
uart_remove_one_port(&max310x_uart, &s->p[i].port);
|
||||
clear_bit(s->p[i].port.line, max310x_lines);
|
||||
s->devtype->power(&s->p[i].port, 0);
|
||||
|
||||
if (test_and_clear_bit(s->p[i].port.line, max310x_lines))
|
||||
uart_remove_one_port(&max310x_uart, &s->p[i].port);
|
||||
|
||||
max310x_power(&s->p[i].port, 0);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(s->clk);
|
||||
|
@ -1518,6 +1489,19 @@ static struct regmap_config regcfg = {
|
|||
.max_raw_write = MAX310X_FIFO_SIZE,
|
||||
};
|
||||
|
||||
static const char *max310x_regmap_name(u8 port_id)
|
||||
{
|
||||
switch (port_id) {
|
||||
case 0: return "port0";
|
||||
case 1: return "port1";
|
||||
case 2: return "port2";
|
||||
case 3: return "port3";
|
||||
default:
|
||||
WARN_ON(true);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_MASTER
|
||||
static int max310x_spi_extended_reg_enable(struct device *dev, bool enable)
|
||||
{
|
||||
|
@ -1529,13 +1513,13 @@ static int max310x_spi_extended_reg_enable(struct device *dev, bool enable)
|
|||
|
||||
static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = {
|
||||
.extended_reg_enable = max310x_spi_extended_reg_enable,
|
||||
.rev_id_reg = MAX310X_SPI_REVID_EXTREG,
|
||||
.rev_id_offset = MAX310X_EXTREG_START,
|
||||
};
|
||||
|
||||
static int max310x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct max310x_devtype *devtype;
|
||||
struct regmap *regmaps[4];
|
||||
struct regmap *regmaps[MAX310X_MAX_PORTS];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
|
@ -1547,12 +1531,14 @@ static int max310x_spi_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
devtype = device_get_match_data(&spi->dev);
|
||||
devtype = spi_get_device_match_data(spi);
|
||||
if (!devtype)
|
||||
devtype = (struct max310x_devtype *)spi_get_device_id(spi)->driver_data;
|
||||
return dev_err_probe(&spi->dev, -ENODEV, "Failed to match device\n");
|
||||
|
||||
for (i = 0; i < devtype->nr; i++) {
|
||||
u8 port_mask = i * 0x20;
|
||||
|
||||
regcfg.name = max310x_regmap_name(i);
|
||||
regcfg.read_flag_mask = port_mask;
|
||||
regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT;
|
||||
regmaps[i] = devm_regmap_init_spi(spi, ®cfg);
|
||||
|
@ -1600,7 +1586,7 @@ static struct regmap_config regcfg_i2c = {
|
|||
.writeable_reg = max310x_reg_writeable,
|
||||
.volatile_reg = max310x_reg_volatile,
|
||||
.precious_reg = max310x_reg_precious,
|
||||
.max_register = MAX310X_I2C_REVID_EXTREG,
|
||||
.max_register = MAX310X_REVID_EXTREG,
|
||||
.writeable_noinc_reg = max310x_reg_noinc,
|
||||
.readable_noinc_reg = max310x_reg_noinc,
|
||||
.max_raw_read = MAX310X_FIFO_SIZE,
|
||||
|
@ -1609,7 +1595,7 @@ static struct regmap_config regcfg_i2c = {
|
|||
|
||||
static const struct max310x_if_cfg max310x_i2c_if_cfg = {
|
||||
.extended_reg_enable = max310x_i2c_extended_reg_enable,
|
||||
.rev_id_reg = MAX310X_I2C_REVID_EXTREG,
|
||||
.rev_id_offset = 0, /* No offset in I2C mode. */
|
||||
};
|
||||
|
||||
static unsigned short max310x_i2c_slave_addr(unsigned short addr,
|
||||
|
@ -1619,10 +1605,10 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr,
|
|||
* For MAX14830 and MAX3109, the slave address depends on what the
|
||||
* A0 and A1 pins are tied to.
|
||||
* See Table I2C Address Map of the datasheet.
|
||||
* Based on that table, the following formulas were determined.
|
||||
* UART1 - UART0 = 0x10
|
||||
* UART2 - UART1 = 0x20 + 0x10
|
||||
* UART3 - UART2 = 0x10
|
||||
* Based on that table, the following formulas were determined:
|
||||
* UART1 - UART0 = 0x10
|
||||
* UART2 - UART1 = 0x20 + 0x10
|
||||
* UART3 - UART2 = 0x10
|
||||
*/
|
||||
|
||||
addr -= nr * 0x10;
|
||||
|
@ -1635,20 +1621,24 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr,
|
|||
|
||||
static int max310x_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct max310x_devtype *devtype =
|
||||
device_get_match_data(&client->dev);
|
||||
const struct max310x_devtype *devtype;
|
||||
struct i2c_client *port_client;
|
||||
struct regmap *regmaps[4];
|
||||
struct regmap *regmaps[MAX310X_MAX_PORTS];
|
||||
unsigned int i;
|
||||
u8 port_addr;
|
||||
|
||||
devtype = i2c_get_match_data(client);
|
||||
if (!devtype)
|
||||
return dev_err_probe(&client->dev, -ENODEV, "Failed to match device\n");
|
||||
|
||||
if (client->addr < devtype->slave_addr.min ||
|
||||
client->addr > devtype->slave_addr.max)
|
||||
client->addr > devtype->slave_addr.max)
|
||||
return dev_err_probe(&client->dev, -EINVAL,
|
||||
"Slave addr 0x%x outside of range [0x%x, 0x%x]\n",
|
||||
client->addr, devtype->slave_addr.min,
|
||||
devtype->slave_addr.max);
|
||||
|
||||
regcfg_i2c.name = max310x_regmap_name(0);
|
||||
regmaps[0] = devm_regmap_init_i2c(client, ®cfg_i2c);
|
||||
|
||||
for (i = 1; i < devtype->nr; i++) {
|
||||
|
@ -1657,6 +1647,7 @@ static int max310x_i2c_probe(struct i2c_client *client)
|
|||
client->adapter,
|
||||
port_addr);
|
||||
|
||||
regcfg_i2c.name = max310x_regmap_name(i);
|
||||
regmaps[i] = devm_regmap_init_i2c(port_client, ®cfg_i2c);
|
||||
}
|
||||
|
||||
|
@ -1669,6 +1660,15 @@ static void max310x_i2c_remove(struct i2c_client *client)
|
|||
max310x_remove(&client->dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max310x_i2c_id_table[] = {
|
||||
{ "max3107", (kernel_ulong_t)&max3107_devtype, },
|
||||
{ "max3108", (kernel_ulong_t)&max3108_devtype, },
|
||||
{ "max3109", (kernel_ulong_t)&max3109_devtype, },
|
||||
{ "max14830", (kernel_ulong_t)&max14830_devtype, },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max310x_i2c_id_table);
|
||||
|
||||
static struct i2c_driver max310x_i2c_driver = {
|
||||
.driver = {
|
||||
.name = MAX310X_NAME,
|
||||
|
@ -1677,6 +1677,7 @@ static struct i2c_driver max310x_i2c_driver = {
|
|||
},
|
||||
.probe = max310x_i2c_probe,
|
||||
.remove = max310x_i2c_remove,
|
||||
.id_table = max310x_i2c_id_table,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -470,33 +470,6 @@ static struct mcf_uart mcf_ports[4];
|
|||
#if defined(CONFIG_SERIAL_MCF_CONSOLE)
|
||||
/****************************************************************************/
|
||||
|
||||
int __init early_mcf_setup(struct mcf_platform_uart *platp)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int i;
|
||||
|
||||
for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
|
||||
port = &mcf_ports[i].port;
|
||||
|
||||
port->line = i;
|
||||
port->type = PORT_MCF;
|
||||
port->mapbase = platp[i].mapbase;
|
||||
port->membase = (platp[i].membase) ? platp[i].membase :
|
||||
(unsigned char __iomem *) port->mapbase;
|
||||
port->iotype = SERIAL_IO_MEM;
|
||||
port->irq = platp[i].irq;
|
||||
port->uartclk = MCF_BUSCLK;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->rs485_config = mcf_config_rs485;
|
||||
port->rs485_supported = mcf_rs485_supported;
|
||||
port->ops = &mcf_uart_ops;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void mcf_console_putc(struct console *co, const char c)
|
||||
{
|
||||
struct uart_port *port = &(mcf_ports + co->index)->port;
|
||||
|
|
|
@ -220,7 +220,7 @@ static void meson_receive_chars(struct uart_port *port)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(port, ch))
|
||||
if (uart_prepare_sysrq_char(port, ch))
|
||||
continue;
|
||||
|
||||
if ((status & port->ignore_status_mask) == 0)
|
||||
|
@ -248,7 +248,7 @@ static irqreturn_t meson_uart_interrupt(int irq, void *dev_id)
|
|||
meson_uart_start_tx(port);
|
||||
}
|
||||
|
||||
uart_port_unlock(port);
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -556,18 +556,13 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
|
|||
u_int count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int locked;
|
||||
int locked = 1;
|
||||
u32 val, tmp;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (port->sysrq) {
|
||||
locked = 0;
|
||||
} else if (oops_in_progress) {
|
||||
locked = uart_port_trylock(port);
|
||||
} else {
|
||||
uart_port_lock(port);
|
||||
locked = 1;
|
||||
}
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(port, &flags);
|
||||
else
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN);
|
||||
|
@ -577,8 +572,7 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
|
|||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(port);
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
static void meson_serial_console_write(struct console *co, const char *s,
|
||||
|
|
|
@ -588,16 +588,14 @@ static void msm_complete_rx_dma(void *args)
|
|||
if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK))
|
||||
flag = TTY_NORMAL;
|
||||
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
sysrq = uart_handle_sysrq_char(port, dma->virt[i]);
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
sysrq = uart_prepare_sysrq_char(port, dma->virt[i]);
|
||||
if (!sysrq)
|
||||
tty_insert_flip_char(tport, dma->virt[i], flag);
|
||||
}
|
||||
|
||||
msm_start_rx_dma(msm_port);
|
||||
done:
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
uart_unlock_and_check_sysrq_irqrestore(port, flags);
|
||||
|
||||
if (count)
|
||||
tty_flip_buffer_push(tport);
|
||||
|
@ -763,9 +761,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
|
|||
if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK))
|
||||
flag = TTY_NORMAL;
|
||||
|
||||
uart_port_unlock(port);
|
||||
sysrq = uart_handle_sysrq_char(port, buf[i]);
|
||||
uart_port_lock(port);
|
||||
sysrq = uart_prepare_sysrq_char(port, buf[i]);
|
||||
if (!sysrq)
|
||||
tty_insert_flip_char(tport, buf[i], flag);
|
||||
}
|
||||
|
@ -825,9 +821,7 @@ static void msm_handle_rx(struct uart_port *port)
|
|||
else if (sr & MSM_UART_SR_PAR_FRAME_ERR)
|
||||
flag = TTY_FRAME;
|
||||
|
||||
uart_port_unlock(port);
|
||||
sysrq = uart_handle_sysrq_char(port, c);
|
||||
uart_port_lock(port);
|
||||
sysrq = uart_prepare_sysrq_char(port, c);
|
||||
if (!sysrq)
|
||||
tty_insert_flip_char(tport, c, flag);
|
||||
}
|
||||
|
@ -948,11 +942,10 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id)
|
|||
struct uart_port *port = dev_id;
|
||||
struct msm_port *msm_port = to_msm_port(port);
|
||||
struct msm_dma *dma = &msm_port->rx_dma;
|
||||
unsigned long flags;
|
||||
unsigned int misr;
|
||||
u32 val;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
uart_port_lock(port);
|
||||
misr = msm_read(port, MSM_UART_MISR);
|
||||
msm_write(port, 0, MSM_UART_IMR); /* disable interrupt */
|
||||
|
||||
|
@ -984,7 +977,7 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id)
|
|||
msm_handle_delta_cts(port);
|
||||
|
||||
msm_write(port, msm_port->imr, MSM_UART_IMR); /* restore interrupt */
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -1621,14 +1614,10 @@ static void __msm_console_write(struct uart_port *port, const char *s,
|
|||
num_newlines++;
|
||||
count += num_newlines;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (port->sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(port);
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(port, &flags);
|
||||
else
|
||||
uart_port_lock(port);
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
if (is_uartdm)
|
||||
msm_reset_dm_count(port, count);
|
||||
|
@ -1667,9 +1656,7 @@ static void __msm_console_write(struct uart_port *port, const char *s,
|
|||
}
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(port);
|
||||
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
static void msm_console_write(struct console *co, const char *s,
|
||||
|
|
|
@ -508,7 +508,7 @@ static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)
|
|||
|
||||
up->port.icount.rx++;
|
||||
|
||||
if (uart_handle_sysrq_char(&up->port, ch))
|
||||
if (uart_prepare_sysrq_char(&up->port, ch))
|
||||
return;
|
||||
|
||||
uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, TTY_NORMAL);
|
||||
|
@ -563,7 +563,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
|
|||
}
|
||||
} while (max_count--);
|
||||
|
||||
uart_port_unlock(&up->port);
|
||||
uart_unlock_and_check_sysrq(&up->port);
|
||||
|
||||
tty_flip_buffer_push(&up->port.state->port);
|
||||
|
||||
|
@ -1212,13 +1212,10 @@ serial_omap_console_write(struct console *co, const char *s,
|
|||
unsigned int ier;
|
||||
int locked = 1;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (up->port.sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(&up->port);
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(&up->port, &flags);
|
||||
else
|
||||
uart_port_lock(&up->port);
|
||||
uart_port_lock_irqsave(&up->port, &flags);
|
||||
|
||||
/*
|
||||
* First save the IER then disable the interrupts
|
||||
|
@ -1245,8 +1242,7 @@ serial_omap_console_write(struct console *co, const char *s,
|
|||
check_modem_status(up);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(&up->port);
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(&up->port, flags);
|
||||
}
|
||||
|
||||
static int __init
|
||||
|
|
|
@ -199,6 +199,7 @@ static void owl_uart_receive_chars(struct uart_port *port)
|
|||
stat = owl_uart_read(port, OWL_UART_STAT);
|
||||
while (!(stat & OWL_UART_STAT_RFEM)) {
|
||||
char flag = TTY_NORMAL;
|
||||
bool sysrq;
|
||||
|
||||
if (stat & OWL_UART_STAT_RXER)
|
||||
port->icount.overrun++;
|
||||
|
@ -217,7 +218,9 @@ static void owl_uart_receive_chars(struct uart_port *port)
|
|||
val = owl_uart_read(port, OWL_UART_RXDAT);
|
||||
val &= 0xff;
|
||||
|
||||
if ((stat & port->ignore_status_mask) == 0)
|
||||
sysrq = uart_prepare_sysrq_char(port, val);
|
||||
|
||||
if (!sysrq && (stat & port->ignore_status_mask) == 0)
|
||||
tty_insert_flip_char(&port->state->port, val, flag);
|
||||
|
||||
stat = owl_uart_read(port, OWL_UART_STAT);
|
||||
|
@ -229,10 +232,9 @@ static void owl_uart_receive_chars(struct uart_port *port)
|
|||
static irqreturn_t owl_uart_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
unsigned long flags;
|
||||
u32 stat;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
uart_port_lock(port);
|
||||
|
||||
stat = owl_uart_read(port, OWL_UART_STAT);
|
||||
|
||||
|
@ -246,7 +248,7 @@ static irqreturn_t owl_uart_irq(int irq, void *dev_id)
|
|||
stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP;
|
||||
owl_uart_write(port, stat, OWL_UART_STAT);
|
||||
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -508,18 +510,12 @@ static void owl_uart_port_write(struct uart_port *port, const char *s,
|
|||
{
|
||||
u32 old_ctl, val;
|
||||
unsigned long flags;
|
||||
int locked;
|
||||
int locked = 1;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (port->sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(port);
|
||||
else {
|
||||
uart_port_lock(port);
|
||||
locked = 1;
|
||||
}
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(port, &flags);
|
||||
else
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
old_ctl = owl_uart_read(port, OWL_UART_CTL);
|
||||
val = old_ctl | OWL_UART_CTL_TRFS_TX;
|
||||
|
@ -541,9 +537,7 @@ static void owl_uart_port_write(struct uart_port *port, const char *s,
|
|||
owl_uart_write(port, old_ctl, OWL_UART_CTL);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(port);
|
||||
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
static void owl_uart_console_write(struct console *co, const char *s,
|
||||
|
|
|
@ -237,9 +237,6 @@ struct eg20t_port {
|
|||
|
||||
#define IRQ_NAME_SIZE 17
|
||||
char irq_name[IRQ_NAME_SIZE];
|
||||
|
||||
/* protect the eg20t_port private structure and io access to membase */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -567,7 +564,7 @@ static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
|
|||
if (uart_handle_break(port))
|
||||
continue;
|
||||
}
|
||||
if (uart_handle_sysrq_char(port, rbr))
|
||||
if (uart_prepare_sysrq_char(port, rbr))
|
||||
continue;
|
||||
|
||||
buf[i++] = rbr;
|
||||
|
@ -599,16 +596,14 @@ static void pch_uart_hal_set_break(struct eg20t_port *priv, int on)
|
|||
iowrite8(lcr, priv->membase + UART_LCR);
|
||||
}
|
||||
|
||||
static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
|
||||
int size)
|
||||
static void push_rx(struct eg20t_port *priv, const unsigned char *buf,
|
||||
int size)
|
||||
{
|
||||
struct uart_port *port = &priv->port;
|
||||
struct tty_port *tport = &port->state->port;
|
||||
|
||||
tty_insert_flip_string(tport, buf, size);
|
||||
tty_flip_buffer_push(tport);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dma_push_rx(struct eg20t_port *priv, int size)
|
||||
|
@ -761,7 +756,7 @@ static int handle_rx_to(struct eg20t_port *priv)
|
|||
{
|
||||
struct pch_uart_buffer *buf;
|
||||
int rx_size;
|
||||
int ret;
|
||||
|
||||
if (!priv->start_rx) {
|
||||
pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT |
|
||||
PCH_UART_HAL_RX_ERR_INT);
|
||||
|
@ -770,19 +765,12 @@ static int handle_rx_to(struct eg20t_port *priv)
|
|||
buf = &priv->rxbuf;
|
||||
do {
|
||||
rx_size = pch_uart_hal_read(priv, buf->buf, buf->size);
|
||||
ret = push_rx(priv, buf->buf, rx_size);
|
||||
if (ret)
|
||||
return 0;
|
||||
push_rx(priv, buf->buf, rx_size);
|
||||
} while (rx_size == buf->size);
|
||||
|
||||
return PCH_UART_HANDLED_RX_INT;
|
||||
}
|
||||
|
||||
static int handle_rx(struct eg20t_port *priv)
|
||||
{
|
||||
return handle_rx_to(priv);
|
||||
}
|
||||
|
||||
static int dma_handle_rx(struct eg20t_port *priv)
|
||||
{
|
||||
struct uart_port *port = &priv->port;
|
||||
|
@ -1019,11 +1007,10 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
|
|||
u8 lsr;
|
||||
int ret = 0;
|
||||
unsigned char iid;
|
||||
unsigned long flags;
|
||||
int next = 1;
|
||||
u8 msr;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
uart_port_lock(&priv->port);
|
||||
handled = 0;
|
||||
while (next) {
|
||||
iid = pch_uart_hal_get_iid(priv);
|
||||
|
@ -1051,7 +1038,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
|
|||
PCH_UART_HAL_RX_INT |
|
||||
PCH_UART_HAL_RX_ERR_INT);
|
||||
} else {
|
||||
ret = handle_rx(priv);
|
||||
ret = handle_rx_to(priv);
|
||||
}
|
||||
break;
|
||||
case PCH_UART_IID_RDR_TO: /* Received Data Ready
|
||||
|
@ -1083,7 +1070,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
|
|||
handled |= (unsigned int)ret;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
uart_unlock_and_check_sysrq(&priv->port);
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
|
@ -1194,9 +1181,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl)
|
|||
unsigned long flags;
|
||||
|
||||
priv = container_of(port, struct eg20t_port, port);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
uart_port_lock_irqsave(&priv->port, &flags);
|
||||
pch_uart_hal_set_break(priv, ctl);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
uart_port_unlock_irqrestore(&priv->port, flags);
|
||||
}
|
||||
|
||||
/* Grab any interrupt resources and initialise any low level driver state. */
|
||||
|
@ -1346,8 +1333,7 @@ static void pch_uart_set_termios(struct uart_port *port,
|
|||
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
uart_port_lock(port);
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb);
|
||||
|
@ -1360,8 +1346,7 @@ static void pch_uart_set_termios(struct uart_port *port,
|
|||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
|
||||
out:
|
||||
uart_port_unlock(port);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
static const char *pch_uart_type(struct uart_port *port)
|
||||
|
@ -1565,27 +1550,17 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
|
|||
{
|
||||
struct eg20t_port *priv;
|
||||
unsigned long flags;
|
||||
int priv_locked = 1;
|
||||
int port_locked = 1;
|
||||
int locked = 1;
|
||||
u8 ier;
|
||||
|
||||
priv = pch_uart_ports[co->index];
|
||||
|
||||
touch_nmi_watchdog();
|
||||
|
||||
local_irq_save(flags);
|
||||
if (priv->port.sysrq) {
|
||||
/* call to uart_handle_sysrq_char already took the priv lock */
|
||||
priv_locked = 0;
|
||||
/* serial8250_handle_port() already took the port lock */
|
||||
port_locked = 0;
|
||||
} else if (oops_in_progress) {
|
||||
priv_locked = spin_trylock(&priv->lock);
|
||||
port_locked = uart_port_trylock(&priv->port);
|
||||
} else {
|
||||
spin_lock(&priv->lock);
|
||||
uart_port_lock(&priv->port);
|
||||
}
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(&priv->port, &flags);
|
||||
else
|
||||
uart_port_lock_irqsave(&priv->port, &flags);
|
||||
|
||||
/*
|
||||
* First save the IER then disable the interrupts
|
||||
|
@ -1603,11 +1578,8 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
|
|||
wait_for_xmitr(priv, UART_LSR_BOTH_EMPTY);
|
||||
iowrite8(ier, priv->membase + UART_IER);
|
||||
|
||||
if (port_locked)
|
||||
uart_port_unlock(&priv->port);
|
||||
if (priv_locked)
|
||||
spin_unlock(&priv->lock);
|
||||
local_irq_restore(flags);
|
||||
if (locked)
|
||||
uart_port_unlock_irqrestore(&priv->port, flags);
|
||||
}
|
||||
|
||||
static int __init pch_console_setup(struct console *co, char *options)
|
||||
|
@ -1704,8 +1676,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
|
|||
pci_enable_msi(pdev);
|
||||
pci_set_master(pdev);
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
iobase = pci_resource_start(pdev, 0);
|
||||
mapbase = pci_resource_start(pdev, 1);
|
||||
priv->mapbase = mapbase;
|
||||
|
@ -1735,8 +1705,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
|
|||
KBUILD_MODNAME ":" PCH_UART_DRIVER_DEVICE "%d",
|
||||
priv->port.line);
|
||||
|
||||
spin_lock_init(&priv->port.lock);
|
||||
|
||||
pci_set_drvdata(pdev, priv);
|
||||
priv->trigger_level = 1;
|
||||
priv->fcr = 0;
|
||||
|
|
|
@ -1714,18 +1714,13 @@ static int __init pmz_attach(struct platform_device *pdev)
|
|||
return uart_add_one_port(&pmz_uart_reg, &uap->port);
|
||||
}
|
||||
|
||||
static int __exit pmz_detach(struct platform_device *pdev)
|
||||
static void __exit pmz_detach(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_pmac_port *uap = platform_get_drvdata(pdev);
|
||||
|
||||
if (!uap)
|
||||
return -ENODEV;
|
||||
|
||||
uart_remove_one_port(&pmz_uart_reg, &uap->port);
|
||||
|
||||
uap->port.dev = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_PPC_PMAC */
|
||||
|
@ -1794,7 +1789,7 @@ static struct macio_driver pmz_driver = {
|
|||
#else
|
||||
|
||||
static struct platform_driver pmz_driver = {
|
||||
.remove = __exit_p(pmz_detach),
|
||||
.remove_new = __exit_p(pmz_detach),
|
||||
.driver = {
|
||||
.name = "scc",
|
||||
},
|
||||
|
|
|
@ -151,7 +151,7 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status)
|
|||
flag = TTY_FRAME;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(&up->port, ch))
|
||||
if (uart_prepare_sysrq_char(&up->port, ch))
|
||||
goto ignore_char;
|
||||
|
||||
uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
|
||||
|
@ -232,7 +232,7 @@ static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
|
|||
check_modem_status(up);
|
||||
if (lsr & UART_LSR_THRE)
|
||||
transmit_chars(up);
|
||||
uart_port_unlock(&up->port);
|
||||
uart_unlock_and_check_sysrq(&up->port);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -604,13 +604,10 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
|
|||
int locked = 1;
|
||||
|
||||
clk_enable(up->clk);
|
||||
local_irq_save(flags);
|
||||
if (up->port.sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(&up->port);
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(&up->port, &flags);
|
||||
else
|
||||
uart_port_lock(&up->port);
|
||||
uart_port_lock_irqsave(&up->port, &flags);
|
||||
|
||||
/*
|
||||
* First save the IER then disable the interrupts
|
||||
|
@ -628,10 +625,8 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
|
|||
serial_out(up, UART_IER, ier);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(&up->port);
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(&up->port, flags);
|
||||
clk_disable(up->clk);
|
||||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
|
|
|
@ -488,18 +488,16 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
|
|||
|
||||
geni_status = readl(uport->membase + SE_GENI_STATUS);
|
||||
|
||||
/* Cancel the current write to log the fault */
|
||||
if (!locked) {
|
||||
geni_se_cancel_m_cmd(&port->se);
|
||||
if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
|
||||
M_CMD_CANCEL_EN, true)) {
|
||||
geni_se_abort_m_cmd(&port->se);
|
||||
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
|
||||
M_CMD_ABORT_EN, true);
|
||||
writel(M_CMD_ABORT_EN, uport->membase +
|
||||
SE_GENI_M_IRQ_CLEAR);
|
||||
}
|
||||
writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
|
||||
/*
|
||||
* We can only get here if an oops is in progress then we were
|
||||
* unable to get the lock. This means we can't safely access
|
||||
* our state variables like tx_remaining. About the best we
|
||||
* can do is wait for the FIFO to be empty before we start our
|
||||
* transfer, so we'll do that.
|
||||
*/
|
||||
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
|
||||
M_TX_FIFO_NOT_EMPTY_EN, false);
|
||||
} else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) {
|
||||
/*
|
||||
* It seems we can't interrupt existing transfers if all data
|
||||
|
@ -516,11 +514,12 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
|
|||
|
||||
__qcom_geni_serial_console_write(uport, s, count);
|
||||
|
||||
if (port->tx_remaining)
|
||||
qcom_geni_serial_setup_tx(uport, port->tx_remaining);
|
||||
|
||||
if (locked)
|
||||
if (locked) {
|
||||
if (port->tx_remaining)
|
||||
qcom_geni_serial_setup_tx(uport, port->tx_remaining);
|
||||
uart_port_unlock_irqrestore(uport, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
|
||||
|
|
|
@ -394,7 +394,8 @@ static void rda_uart_receive_chars(struct uart_port *port)
|
|||
val &= 0xff;
|
||||
|
||||
port->icount.rx++;
|
||||
tty_insert_flip_char(&port->state->port, val, flag);
|
||||
if (!uart_prepare_sysrq_char(port, val))
|
||||
tty_insert_flip_char(&port->state->port, val, flag);
|
||||
|
||||
status = rda_uart_read(port, RDA_UART_STATUS);
|
||||
}
|
||||
|
@ -405,10 +406,9 @@ static void rda_uart_receive_chars(struct uart_port *port)
|
|||
static irqreturn_t rda_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
unsigned long flags;
|
||||
u32 val, irq_mask;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
uart_port_lock(port);
|
||||
|
||||
/* Clear IRQ cause */
|
||||
val = rda_uart_read(port, RDA_UART_IRQ_CAUSE);
|
||||
|
@ -425,7 +425,7 @@ static irqreturn_t rda_interrupt(int irq, void *dev_id)
|
|||
rda_uart_send_chars(port);
|
||||
}
|
||||
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -590,18 +590,12 @@ static void rda_uart_port_write(struct uart_port *port, const char *s,
|
|||
{
|
||||
u32 old_irq_mask;
|
||||
unsigned long flags;
|
||||
int locked;
|
||||
int locked = 1;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (port->sysrq) {
|
||||
locked = 0;
|
||||
} else if (oops_in_progress) {
|
||||
locked = uart_port_trylock(port);
|
||||
} else {
|
||||
uart_port_lock(port);
|
||||
locked = 1;
|
||||
}
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(port, &flags);
|
||||
else
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
old_irq_mask = rda_uart_read(port, RDA_UART_IRQ_MASK);
|
||||
rda_uart_write(port, 0, RDA_UART_IRQ_MASK);
|
||||
|
@ -615,9 +609,7 @@ static void rda_uart_port_write(struct uart_port *port, const char *s,
|
|||
rda_uart_write(port, old_irq_mask, RDA_UART_IRQ_MASK);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(port);
|
||||
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
static void rda_uart_console_write(struct console *co, const char *s,
|
||||
|
|
|
@ -21,26 +21,28 @@
|
|||
* BJD, 04-Nov-2004
|
||||
*/
|
||||
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_s3c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_s3c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
/* UART name and device definitions */
|
||||
|
@ -73,21 +75,21 @@ struct s3c24xx_uart_info {
|
|||
enum s3c24xx_port_type type;
|
||||
unsigned int port_type;
|
||||
unsigned int fifosize;
|
||||
unsigned long rx_fifomask;
|
||||
unsigned long rx_fifoshift;
|
||||
unsigned long rx_fifofull;
|
||||
unsigned long tx_fifomask;
|
||||
unsigned long tx_fifoshift;
|
||||
unsigned long tx_fifofull;
|
||||
unsigned int def_clk_sel;
|
||||
unsigned long num_clks;
|
||||
unsigned long clksel_mask;
|
||||
unsigned long clksel_shift;
|
||||
unsigned long ucon_mask;
|
||||
u32 rx_fifomask;
|
||||
u32 rx_fifoshift;
|
||||
u32 rx_fifofull;
|
||||
u32 tx_fifomask;
|
||||
u32 tx_fifoshift;
|
||||
u32 tx_fifofull;
|
||||
u32 clksel_mask;
|
||||
u32 clksel_shift;
|
||||
u32 ucon_mask;
|
||||
u8 def_clk_sel;
|
||||
u8 num_clks;
|
||||
u8 iotype;
|
||||
|
||||
/* uart port features */
|
||||
|
||||
unsigned int has_divslot:1;
|
||||
bool has_divslot;
|
||||
};
|
||||
|
||||
struct s3c24xx_serial_drv_data {
|
||||
|
@ -196,7 +198,7 @@ static void wr_reg(const struct uart_port *port, u32 reg, u32 val)
|
|||
/* Byte-order aware bit setting/clearing functions. */
|
||||
|
||||
static inline void s3c24xx_set_bit(const struct uart_port *port, int idx,
|
||||
unsigned int reg)
|
||||
u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
@ -209,7 +211,7 @@ static inline void s3c24xx_set_bit(const struct uart_port *port, int idx,
|
|||
}
|
||||
|
||||
static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx,
|
||||
unsigned int reg)
|
||||
u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
@ -233,7 +235,7 @@ static inline const char *s3c24xx_serial_portname(const struct uart_port *port)
|
|||
return to_platform_device(port->dev)->name;
|
||||
}
|
||||
|
||||
static int s3c24xx_serial_txempty_nofifo(const struct uart_port *port)
|
||||
static bool s3c24xx_serial_txempty_nofifo(const struct uart_port *port)
|
||||
{
|
||||
return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
|
||||
}
|
||||
|
@ -242,8 +244,8 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port)
|
|||
{
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
unsigned long flags;
|
||||
unsigned int ucon, ufcon;
|
||||
int count = 10000;
|
||||
u32 ucon, ufcon;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
|
@ -266,7 +268,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port)
|
|||
{
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
unsigned long flags;
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
|
@ -587,8 +589,8 @@ static inline const struct s3c2410_uartcfg
|
|||
return ourport->cfg;
|
||||
}
|
||||
|
||||
static int s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport,
|
||||
unsigned long ufstat)
|
||||
static unsigned int
|
||||
s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport, u32 ufstat)
|
||||
{
|
||||
const struct s3c24xx_uart_info *info = ourport->info;
|
||||
|
||||
|
@ -660,7 +662,7 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
|
|||
static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
|
||||
{
|
||||
struct uart_port *port = &ourport->port;
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
|
||||
/* set Rx mode to DMA mode */
|
||||
ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
@ -683,7 +685,7 @@ static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
|
|||
static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
|
||||
{
|
||||
struct uart_port *port = &ourport->port;
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
|
||||
/* set Rx mode to DMA mode */
|
||||
ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
@ -708,13 +710,14 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);
|
|||
|
||||
static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
|
||||
{
|
||||
unsigned int utrstat, received;
|
||||
struct s3c24xx_uart_port *ourport = dev_id;
|
||||
struct uart_port *port = &ourport->port;
|
||||
struct s3c24xx_uart_dma *dma = ourport->dma;
|
||||
struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
|
||||
struct tty_port *t = &port->state->port;
|
||||
struct dma_tx_state state;
|
||||
unsigned int received;
|
||||
u32 utrstat;
|
||||
|
||||
utrstat = rd_regl(port, S3C2410_UTRSTAT);
|
||||
rd_regl(port, S3C2410_UFSTAT);
|
||||
|
@ -756,9 +759,9 @@ finish:
|
|||
static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
|
||||
{
|
||||
struct uart_port *port = &ourport->port;
|
||||
unsigned int ufcon, ufstat, uerstat;
|
||||
unsigned int max_count = port->fifosize;
|
||||
unsigned int fifocnt = 0;
|
||||
int max_count = port->fifosize;
|
||||
u32 ufcon, ufstat, uerstat;
|
||||
u8 ch, flag;
|
||||
|
||||
while (max_count-- > 0) {
|
||||
|
@ -778,7 +781,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
|
|||
ch = rd_reg(port, S3C2410_URXH);
|
||||
|
||||
if (port->flags & UPF_CONS_FLOW) {
|
||||
int txe = s3c24xx_serial_txempty_nofifo(port);
|
||||
bool txe = s3c24xx_serial_txempty_nofifo(port);
|
||||
|
||||
if (ourport->rx_enabled) {
|
||||
if (!txe) {
|
||||
|
@ -942,7 +945,7 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
|
|||
{
|
||||
const struct s3c24xx_uart_port *ourport = id;
|
||||
const struct uart_port *port = &ourport->port;
|
||||
unsigned int pend = rd_regl(port, S3C64XX_UINTP);
|
||||
u32 pend = rd_regl(port, S3C64XX_UINTP);
|
||||
irqreturn_t ret = IRQ_HANDLED;
|
||||
|
||||
if (pend & S3C64XX_UINTM_RXD_MSK) {
|
||||
|
@ -961,7 +964,7 @@ static irqreturn_t apple_serial_handle_irq(int irq, void *id)
|
|||
{
|
||||
const struct s3c24xx_uart_port *ourport = id;
|
||||
const struct uart_port *port = &ourport->port;
|
||||
unsigned int pend = rd_regl(port, S3C2410_UTRSTAT);
|
||||
u32 pend = rd_regl(port, S3C2410_UTRSTAT);
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) {
|
||||
|
@ -980,24 +983,23 @@ static irqreturn_t apple_serial_handle_irq(int irq, void *id)
|
|||
static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
|
||||
{
|
||||
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
|
||||
unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
|
||||
unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
|
||||
u32 ufstat = rd_regl(port, S3C2410_UFSTAT);
|
||||
u32 ufcon = rd_regl(port, S3C2410_UFCON);
|
||||
|
||||
if (ufcon & S3C2410_UFCON_FIFOMODE) {
|
||||
if ((ufstat & info->tx_fifomask) != 0 ||
|
||||
if ((ufstat & info->tx_fifomask) ||
|
||||
(ufstat & info->tx_fifofull))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
return s3c24xx_serial_txempty_nofifo(port);
|
||||
return s3c24xx_serial_txempty_nofifo(port) ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
/* no modem control lines */
|
||||
static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
unsigned int umstat = rd_reg(port, S3C2410_UMSTAT);
|
||||
u32 umstat = rd_reg(port, S3C2410_UMSTAT);
|
||||
|
||||
if (umstat & S3C2410_UMSTAT_CTS)
|
||||
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
|
@ -1007,8 +1009,8 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
|
|||
|
||||
static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
unsigned int umcon = rd_regl(port, S3C2410_UMCON);
|
||||
unsigned int ucon = rd_regl(port, S3C2410_UCON);
|
||||
u32 umcon = rd_regl(port, S3C2410_UMCON);
|
||||
u32 ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
umcon |= S3C2410_UMCOM_RTS_LOW;
|
||||
|
@ -1028,7 +1030,7 @@ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
|
@ -1186,7 +1188,7 @@ static void apple_s5l_serial_shutdown(struct uart_port *port)
|
|||
{
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
|
||||
ucon = rd_regl(port, S3C2410_UCON);
|
||||
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
|
||||
|
@ -1212,7 +1214,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
|
|||
{
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
unsigned long flags;
|
||||
unsigned int ufcon;
|
||||
u32 ufcon;
|
||||
int ret;
|
||||
|
||||
wr_regl(port, S3C64XX_UINTM, 0xf);
|
||||
|
@ -1257,7 +1259,7 @@ static int apple_s5l_serial_startup(struct uart_port *port)
|
|||
{
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
unsigned long flags;
|
||||
unsigned int ufcon;
|
||||
u32 ufcon;
|
||||
int ret;
|
||||
|
||||
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
|
||||
|
@ -1292,8 +1294,6 @@ static int apple_s5l_serial_startup(struct uart_port *port)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* power power management control */
|
||||
|
||||
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
|
||||
unsigned int old)
|
||||
{
|
||||
|
@ -1339,10 +1339,10 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
|
|||
|
||||
#define MAX_CLK_NAME_LENGTH 15
|
||||
|
||||
static inline int s3c24xx_serial_getsource(struct uart_port *port)
|
||||
static inline u8 s3c24xx_serial_getsource(struct uart_port *port)
|
||||
{
|
||||
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
|
||||
if (info->num_clks == 1)
|
||||
return 0;
|
||||
|
@ -1352,11 +1352,10 @@ static inline int s3c24xx_serial_getsource(struct uart_port *port)
|
|||
return ucon >> info->clksel_shift;
|
||||
}
|
||||
|
||||
static void s3c24xx_serial_setsource(struct uart_port *port,
|
||||
unsigned int clk_sel)
|
||||
static void s3c24xx_serial_setsource(struct uart_port *port, u8 clk_sel)
|
||||
{
|
||||
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
|
||||
if (info->num_clks == 1)
|
||||
return;
|
||||
|
@ -1372,14 +1371,15 @@ static void s3c24xx_serial_setsource(struct uart_port *port,
|
|||
|
||||
static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
|
||||
unsigned int req_baud, struct clk **best_clk,
|
||||
unsigned int *clk_num)
|
||||
u8 *clk_num)
|
||||
{
|
||||
const struct s3c24xx_uart_info *info = ourport->info;
|
||||
struct clk *clk;
|
||||
unsigned long rate;
|
||||
unsigned int cnt, baud, quot, best_quot = 0;
|
||||
unsigned int baud, quot, best_quot = 0;
|
||||
char clkname[MAX_CLK_NAME_LENGTH];
|
||||
int calc_deviation, deviation = (1 << 30) - 1;
|
||||
u8 cnt;
|
||||
|
||||
for (cnt = 0; cnt < info->num_clks; cnt++) {
|
||||
/* Keep selected clock if provided */
|
||||
|
@ -1472,10 +1472,10 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
|
|||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
struct clk *clk = ERR_PTR(-EINVAL);
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot, clk_sel = 0;
|
||||
unsigned int ulcon;
|
||||
unsigned int umcon;
|
||||
unsigned int baud, quot;
|
||||
unsigned int udivslot = 0;
|
||||
u32 ulcon, umcon;
|
||||
u8 clk_sel = 0;
|
||||
|
||||
/*
|
||||
* We don't support modem control lines.
|
||||
|
@ -1737,12 +1737,12 @@ static struct uart_driver s3c24xx_uart_drv = {
|
|||
|
||||
static struct s3c24xx_uart_port s3c24xx_serial_ports[UART_NR];
|
||||
|
||||
static void s3c24xx_serial_init_port_default(int index) {
|
||||
static void s3c24xx_serial_init_port_default(int index)
|
||||
{
|
||||
struct uart_port *port = &s3c24xx_serial_ports[index].port;
|
||||
|
||||
spin_lock_init(&port->lock);
|
||||
|
||||
port->iotype = UPIO_MEM;
|
||||
port->uartclk = 0;
|
||||
port->fifosize = 16;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
|
@ -1758,7 +1758,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
|
|||
const struct s3c2410_uartcfg *cfg)
|
||||
{
|
||||
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
|
||||
unsigned long ucon = rd_regl(port, S3C2410_UCON);
|
||||
u32 ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
||||
ucon &= (info->clksel_mask | info->ucon_mask);
|
||||
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
|
||||
|
@ -1776,10 +1776,9 @@ static int s3c24xx_serial_enable_baudclk(struct s3c24xx_uart_port *ourport)
|
|||
struct device *dev = ourport->port.dev;
|
||||
const struct s3c24xx_uart_info *info = ourport->info;
|
||||
char clk_name[MAX_CLK_NAME_LENGTH];
|
||||
unsigned int clk_sel;
|
||||
struct clk *clk;
|
||||
int clk_num;
|
||||
int ret;
|
||||
u8 clk_sel, clk_num;
|
||||
|
||||
clk_sel = ourport->cfg->clk_sel ? : info->def_clk_sel;
|
||||
for (clk_num = 0; clk_num < info->num_clks; clk_num++) {
|
||||
|
@ -1904,7 +1903,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
|||
wr_regl(port, S3C64XX_UINTSP, 0xf);
|
||||
break;
|
||||
case TYPE_APPLE_S5L: {
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
|
||||
ucon = rd_regl(port, S3C2410_UCON);
|
||||
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
|
||||
|
@ -1952,7 +1951,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
|||
struct device_node *np = pdev->dev.of_node;
|
||||
struct s3c24xx_uart_port *ourport;
|
||||
int index = probe_index;
|
||||
int ret, prop = 0;
|
||||
int ret, prop = 0, fifosize_prop = 1;
|
||||
|
||||
if (np) {
|
||||
ret = of_alias_get_id(np, "serial");
|
||||
|
@ -1989,9 +1988,11 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
|||
break;
|
||||
}
|
||||
|
||||
ourport->port.iotype = ourport->info->iotype;
|
||||
|
||||
if (np) {
|
||||
of_property_read_u32(np,
|
||||
"samsung,uart-fifosize", &ourport->port.fifosize);
|
||||
fifosize_prop = of_property_read_u32(np, "samsung,uart-fifosize",
|
||||
&ourport->port.fifosize);
|
||||
|
||||
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
|
||||
switch (prop) {
|
||||
|
@ -2009,10 +2010,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
if (ourport->drv_data->fifosize[index])
|
||||
ourport->port.fifosize = ourport->drv_data->fifosize[index];
|
||||
else if (ourport->info->fifosize)
|
||||
ourport->port.fifosize = ourport->info->fifosize;
|
||||
if (fifosize_prop) {
|
||||
if (ourport->drv_data->fifosize[index])
|
||||
ourport->port.fifosize = ourport->drv_data->fifosize[index];
|
||||
else if (ourport->info->fifosize)
|
||||
ourport->port.fifosize = ourport->info->fifosize;
|
||||
}
|
||||
|
||||
ourport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SAMSUNG_CONSOLE);
|
||||
|
||||
/*
|
||||
|
@ -2058,9 +2062,8 @@ static void s3c24xx_serial_remove(struct platform_device *dev)
|
|||
{
|
||||
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
|
||||
|
||||
if (port) {
|
||||
if (port)
|
||||
uart_remove_one_port(&s3c24xx_uart_drv, port);
|
||||
}
|
||||
|
||||
uart_unregister_driver(&s3c24xx_uart_drv);
|
||||
}
|
||||
|
@ -2106,7 +2109,7 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
|
|||
/* restore IRQ mask */
|
||||
switch (ourport->info->type) {
|
||||
case TYPE_S3C6400: {
|
||||
unsigned int uintm = 0xf;
|
||||
u32 uintm = 0xf;
|
||||
|
||||
if (ourport->tx_enabled)
|
||||
uintm &= ~S3C64XX_UINTM_TXD_MSK;
|
||||
|
@ -2122,7 +2125,7 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
|
|||
break;
|
||||
}
|
||||
case TYPE_APPLE_S5L: {
|
||||
unsigned int ucon;
|
||||
u32 ucon;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(ourport->clk);
|
||||
|
@ -2183,27 +2186,27 @@ static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
|
|||
|
||||
static struct uart_port *cons_uart;
|
||||
|
||||
static int
|
||||
s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
|
||||
static bool
|
||||
s3c24xx_serial_console_txrdy(struct uart_port *port, u32 ufcon)
|
||||
{
|
||||
const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
|
||||
unsigned long ufstat, utrstat;
|
||||
u32 ufstat, utrstat;
|
||||
|
||||
if (ufcon & S3C2410_UFCON_FIFOMODE) {
|
||||
/* fifo mode - check amount of data in fifo registers... */
|
||||
|
||||
ufstat = rd_regl(port, S3C2410_UFSTAT);
|
||||
return (ufstat & info->tx_fifofull) ? 0 : 1;
|
||||
return !(ufstat & info->tx_fifofull);
|
||||
}
|
||||
|
||||
/* in non-fifo mode, we go and use the tx buffer empty */
|
||||
|
||||
utrstat = rd_regl(port, S3C2410_UTRSTAT);
|
||||
return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
|
||||
return utrstat & S3C2410_UTRSTAT_TXE;
|
||||
}
|
||||
|
||||
static bool
|
||||
s3c24xx_port_configured(unsigned int ucon)
|
||||
s3c24xx_port_configured(u32 ucon)
|
||||
{
|
||||
/* consider the serial port configured if the tx/rx mode set */
|
||||
return (ucon & 0xf) != 0;
|
||||
|
@ -2218,7 +2221,7 @@ s3c24xx_port_configured(unsigned int ucon)
|
|||
static int s3c24xx_serial_get_poll_char(struct uart_port *port)
|
||||
{
|
||||
const struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
unsigned int ufstat;
|
||||
u32 ufstat;
|
||||
|
||||
ufstat = rd_regl(port, S3C2410_UFSTAT);
|
||||
if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
|
||||
|
@ -2230,8 +2233,8 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port)
|
|||
static void s3c24xx_serial_put_poll_char(struct uart_port *port,
|
||||
unsigned char c)
|
||||
{
|
||||
unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
|
||||
unsigned int ucon = rd_regl(port, S3C2410_UCON);
|
||||
u32 ufcon = rd_regl(port, S3C2410_UFCON);
|
||||
u32 ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
||||
/* not possible to xmit on unconfigured port */
|
||||
if (!s3c24xx_port_configured(ucon))
|
||||
|
@ -2247,7 +2250,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
|
|||
static void
|
||||
s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch)
|
||||
{
|
||||
unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
|
||||
u32 ufcon = rd_regl(port, S3C2410_UFCON);
|
||||
|
||||
while (!s3c24xx_serial_console_txrdy(port, ufcon))
|
||||
cpu_relax();
|
||||
|
@ -2258,7 +2261,7 @@ static void
|
|||
s3c24xx_serial_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
|
||||
u32 ucon = rd_regl(cons_uart, S3C2410_UCON);
|
||||
unsigned long flags;
|
||||
bool locked = true;
|
||||
|
||||
|
@ -2285,12 +2288,10 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
|
|||
int *parity, int *bits)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int ulcon;
|
||||
unsigned int ucon;
|
||||
unsigned int ubrdiv;
|
||||
unsigned long rate;
|
||||
unsigned int clk_sel;
|
||||
u32 ulcon, ucon, ubrdiv;
|
||||
char clk_name[MAX_CLK_NAME_LENGTH];
|
||||
u8 clk_sel;
|
||||
|
||||
ulcon = rd_regl(port, S3C2410_ULCON);
|
||||
ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
@ -2399,8 +2400,9 @@ static const struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
|
|||
.name = "Samsung S3C6400 UART",
|
||||
.type = TYPE_S3C6400,
|
||||
.port_type = PORT_S3C6400,
|
||||
.iotype = UPIO_MEM,
|
||||
.fifosize = 64,
|
||||
.has_divslot = 1,
|
||||
.has_divslot = true,
|
||||
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
|
||||
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
|
||||
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
|
||||
|
@ -2428,7 +2430,8 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
|
|||
.name = "Samsung S5PV210 UART",
|
||||
.type = TYPE_S3C6400,
|
||||
.port_type = PORT_S3C6400,
|
||||
.has_divslot = 1,
|
||||
.iotype = UPIO_MEM,
|
||||
.has_divslot = true,
|
||||
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
|
||||
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
|
||||
.rx_fifofull = S5PV210_UFSTAT_RXFULL,
|
||||
|
@ -2452,12 +2455,13 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
|
|||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_EXYNOS)
|
||||
#define EXYNOS_COMMON_SERIAL_DRV_DATA() \
|
||||
#define EXYNOS_COMMON_SERIAL_DRV_DATA \
|
||||
.info = { \
|
||||
.name = "Samsung Exynos UART", \
|
||||
.type = TYPE_S3C6400, \
|
||||
.port_type = PORT_S3C6400, \
|
||||
.has_divslot = 1, \
|
||||
.iotype = UPIO_MEM, \
|
||||
.has_divslot = true, \
|
||||
.rx_fifomask = S5PV210_UFSTAT_RXMASK, \
|
||||
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \
|
||||
.rx_fifofull = S5PV210_UFSTAT_RXFULL, \
|
||||
|
@ -2476,39 +2480,57 @@ static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
|
|||
} \
|
||||
|
||||
static const struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA(),
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA,
|
||||
.fifosize = { 256, 64, 16, 16 },
|
||||
};
|
||||
|
||||
static const struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA(),
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA,
|
||||
.fifosize = { 64, 256, 16, 256 },
|
||||
};
|
||||
|
||||
static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA(),
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA,
|
||||
.fifosize = { 256, 64, 64, 64 },
|
||||
};
|
||||
|
||||
/*
|
||||
* Common drv_data struct for platforms that specify samsung,uart-fifosize in
|
||||
* device tree.
|
||||
*/
|
||||
static const struct s3c24xx_serial_drv_data exynos_fifoszdt_serial_drv_data = {
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA(),
|
||||
static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = {
|
||||
.info = {
|
||||
.name = "Google GS101 UART",
|
||||
.type = TYPE_S3C6400,
|
||||
.port_type = PORT_S3C6400,
|
||||
.iotype = UPIO_MEM32,
|
||||
.has_divslot = true,
|
||||
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
|
||||
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
|
||||
.rx_fifofull = S5PV210_UFSTAT_RXFULL,
|
||||
.tx_fifofull = S5PV210_UFSTAT_TXFULL,
|
||||
.tx_fifomask = S5PV210_UFSTAT_TXMASK,
|
||||
.tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
|
||||
.def_clk_sel = S3C2410_UCON_CLKSEL0,
|
||||
.num_clks = 1,
|
||||
.clksel_mask = 0,
|
||||
.clksel_shift = 0,
|
||||
},
|
||||
.def_cfg = {
|
||||
.ucon = S5PV210_UCON_DEFAULT,
|
||||
.ufcon = S5PV210_UFCON_DEFAULT,
|
||||
.has_fracval = 1,
|
||||
},
|
||||
/* samsung,uart-fifosize must be specified in the device tree. */
|
||||
.fifosize = { 0 },
|
||||
};
|
||||
|
||||
#define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data)
|
||||
#define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data)
|
||||
#define EXYNOS850_SERIAL_DRV_DATA (&exynos850_serial_drv_data)
|
||||
#define EXYNOS_FIFOSZDT_DRV_DATA (&exynos_fifoszdt_serial_drv_data)
|
||||
#define GS101_SERIAL_DRV_DATA (&gs101_serial_drv_data)
|
||||
|
||||
#else
|
||||
#define EXYNOS4210_SERIAL_DRV_DATA NULL
|
||||
#define EXYNOS5433_SERIAL_DRV_DATA NULL
|
||||
#define EXYNOS850_SERIAL_DRV_DATA NULL
|
||||
#define EXYNOS_FIFOSZDT_DRV_DATA NULL
|
||||
#define GS101_SERIAL_DRV_DATA NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_APPLE
|
||||
|
@ -2517,6 +2539,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
|
|||
.name = "Apple S5L UART",
|
||||
.type = TYPE_APPLE_S5L,
|
||||
.port_type = PORT_8250,
|
||||
.iotype = UPIO_MEM,
|
||||
.fifosize = 16,
|
||||
.rx_fifomask = S3C2410_UFSTAT_RXMASK,
|
||||
.rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
|
||||
|
@ -2546,8 +2569,9 @@ static const struct s3c24xx_serial_drv_data artpec8_serial_drv_data = {
|
|||
.name = "Axis ARTPEC-8 UART",
|
||||
.type = TYPE_S3C6400,
|
||||
.port_type = PORT_S3C6400,
|
||||
.iotype = UPIO_MEM,
|
||||
.fifosize = 64,
|
||||
.has_divslot = 1,
|
||||
.has_divslot = true,
|
||||
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
|
||||
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
|
||||
.rx_fifofull = S5PV210_UFSTAT_RXFULL,
|
||||
|
@ -2594,7 +2618,7 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
|
|||
.driver_data = (kernel_ulong_t)ARTPEC8_SERIAL_DRV_DATA,
|
||||
}, {
|
||||
.name = "gs101-uart",
|
||||
.driver_data = (kernel_ulong_t)EXYNOS_FIFOSZDT_DRV_DATA,
|
||||
.driver_data = (kernel_ulong_t)GS101_SERIAL_DRV_DATA,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
@ -2617,7 +2641,7 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
|
|||
{ .compatible = "axis,artpec8-uart",
|
||||
.data = ARTPEC8_SERIAL_DRV_DATA },
|
||||
{ .compatible = "google,gs101-uart",
|
||||
.data = EXYNOS_FIFOSZDT_DRV_DATA },
|
||||
.data = GS101_SERIAL_DRV_DATA },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
|
||||
|
@ -2716,7 +2740,8 @@ static int samsung_early_read(struct console *con, char *s, unsigned int n)
|
|||
{
|
||||
struct earlycon_device *dev = con->data;
|
||||
const struct samsung_early_console_data *data = dev->port.private_data;
|
||||
int ch, ufstat, num_read = 0;
|
||||
int num_read = 0;
|
||||
u32 ch, ufstat;
|
||||
|
||||
while (num_read < n) {
|
||||
ufstat = rd_regl(&dev->port, S3C2410_UFSTAT);
|
||||
|
@ -2785,6 +2810,17 @@ OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
|
|||
OF_EARLYCON_DECLARE(artpec8, "axis,artpec8-uart",
|
||||
s5pv210_early_console_setup);
|
||||
|
||||
static int __init gs101_early_console_setup(struct earlycon_device *device,
|
||||
const char *opt)
|
||||
{
|
||||
/* gs101 always expects MMIO32 register accesses. */
|
||||
device->port.iotype = UPIO_MEM32;
|
||||
|
||||
return s5pv210_early_console_setup(device, opt);
|
||||
}
|
||||
|
||||
OF_EARLYCON_DECLARE(gs101, "google,gs101-uart", gs101_early_console_setup);
|
||||
|
||||
/* Apple S5L */
|
||||
static int __init apple_s5l_early_console_setup(struct earlycon_device *device,
|
||||
const char *opt)
|
||||
|
|
|
@ -41,7 +41,7 @@ static int serial_base_match(struct device *dev, struct device_driver *drv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct bus_type serial_base_bus_type = {
|
||||
static const struct bus_type serial_base_bus_type = {
|
||||
.name = "serial-base",
|
||||
.match = serial_base_match,
|
||||
};
|
||||
|
|
|
@ -2608,7 +2608,12 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
|
|||
port->type = PORT_UNKNOWN;
|
||||
flags |= UART_CONFIG_TYPE;
|
||||
}
|
||||
/* Synchronize with possible boot console. */
|
||||
if (uart_console(port))
|
||||
console_lock();
|
||||
port->ops->config_port(port, flags);
|
||||
if (uart_console(port))
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
if (port->type != PORT_UNKNOWN) {
|
||||
|
@ -2616,6 +2621,10 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
|
|||
|
||||
uart_report_port(drv, port);
|
||||
|
||||
/* Synchronize with possible boot console. */
|
||||
if (uart_console(port))
|
||||
console_lock();
|
||||
|
||||
/* Power up port for set_mctrl() */
|
||||
uart_change_pm(state, UART_PM_STATE_ON);
|
||||
|
||||
|
@ -2632,6 +2641,9 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
|
|||
|
||||
uart_rs485_config(port);
|
||||
|
||||
if (uart_console(port))
|
||||
console_unlock();
|
||||
|
||||
/*
|
||||
* If this driver supports console, and it hasn't been
|
||||
* successfully registered yet, try to re-register it.
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
|
@ -105,6 +108,148 @@ void uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
|
|||
}
|
||||
EXPORT_SYMBOL(uart_remove_one_port);
|
||||
|
||||
/**
|
||||
* __uart_read_properties - read firmware properties of the given UART port
|
||||
* @port: corresponding port
|
||||
* @use_defaults: apply defaults (when %true) or validate the values (when %false)
|
||||
*
|
||||
* The following device properties are supported:
|
||||
* - clock-frequency (optional)
|
||||
* - fifo-size (optional)
|
||||
* - no-loopback-test (optional)
|
||||
* - reg-shift (defaults may apply)
|
||||
* - reg-offset (value may be validated)
|
||||
* - reg-io-width (defaults may apply or value may be validated)
|
||||
* - interrupts (OF only)
|
||||
* - serial [alias ID] (OF only)
|
||||
*
|
||||
* If the port->dev is of struct platform_device type the interrupt line
|
||||
* will be retrieved via platform_get_irq() call against that device.
|
||||
* Otherwise it will be assigned by fwnode_irq_get() call. In both cases
|
||||
* the index 0 of the resource is used.
|
||||
*
|
||||
* The caller is responsible to initialize the following fields of the @port
|
||||
* ->dev (must be valid)
|
||||
* ->flags
|
||||
* ->mapbase
|
||||
* ->mapsize
|
||||
* ->regshift (if @use_defaults is false)
|
||||
* before calling this function. Alternatively the above mentioned fields
|
||||
* may be zeroed, in such case the only ones, that have associated properties
|
||||
* found, will be set to the respective values.
|
||||
*
|
||||
* If no error happened, the ->irq, ->mapbase, ->mapsize will be altered.
|
||||
* The ->iotype is always altered.
|
||||
*
|
||||
* When @use_defaults is true and the respective property is not found
|
||||
* the following values will be applied:
|
||||
* ->regshift = 0
|
||||
* In this case IRQ must be provided, otherwise an error will be returned.
|
||||
*
|
||||
* When @use_defaults is false and the respective property is found
|
||||
* the following values will be validated:
|
||||
* - reg-io-width (->iotype)
|
||||
* - reg-offset (->mapsize against ->mapbase)
|
||||
*
|
||||
* Returns: 0 on success or negative errno on failure
|
||||
*/
|
||||
static int __uart_read_properties(struct uart_port *port, bool use_defaults)
|
||||
{
|
||||
struct device *dev = port->dev;
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
/* Read optional UART functional clock frequency */
|
||||
device_property_read_u32(dev, "clock-frequency", &port->uartclk);
|
||||
|
||||
/* Read the registers alignment (default: 8-bit) */
|
||||
ret = device_property_read_u32(dev, "reg-shift", &value);
|
||||
if (ret)
|
||||
port->regshift = use_defaults ? 0 : port->regshift;
|
||||
else
|
||||
port->regshift = value;
|
||||
|
||||
/* Read the registers I/O access type (default: MMIO 8-bit) */
|
||||
ret = device_property_read_u32(dev, "reg-io-width", &value);
|
||||
if (ret) {
|
||||
port->iotype = UPIO_MEM;
|
||||
} else {
|
||||
switch (value) {
|
||||
case 1:
|
||||
port->iotype = UPIO_MEM;
|
||||
break;
|
||||
case 2:
|
||||
port->iotype = UPIO_MEM16;
|
||||
break;
|
||||
case 4:
|
||||
port->iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32;
|
||||
break;
|
||||
default:
|
||||
if (!use_defaults) {
|
||||
dev_err(dev, "Unsupported reg-io-width (%u)\n", value);
|
||||
return -EINVAL;
|
||||
}
|
||||
port->iotype = UPIO_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the address mapping base offset (default: no offset) */
|
||||
ret = device_property_read_u32(dev, "reg-offset", &value);
|
||||
if (ret)
|
||||
value = 0;
|
||||
|
||||
/* Check for shifted address mapping overflow */
|
||||
if (!use_defaults && port->mapsize < value) {
|
||||
dev_err(dev, "reg-offset %u exceeds region size %pa\n", value, &port->mapsize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
port->mapbase += value;
|
||||
port->mapsize -= value;
|
||||
|
||||
/* Read optional FIFO size */
|
||||
device_property_read_u32(dev, "fifo-size", &port->fifosize);
|
||||
|
||||
if (device_property_read_bool(dev, "no-loopback-test"))
|
||||
port->flags |= UPF_SKIP_TEST;
|
||||
|
||||
/* Get index of serial line, if found in DT aliases */
|
||||
ret = of_alias_get_id(dev_of_node(dev), "serial");
|
||||
if (ret >= 0)
|
||||
port->line = ret;
|
||||
|
||||
if (dev_is_platform(dev))
|
||||
ret = platform_get_irq(to_platform_device(dev), 0);
|
||||
else
|
||||
ret = fwnode_irq_get(dev_fwnode(dev), 0);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
if (ret > 0)
|
||||
port->irq = ret;
|
||||
else if (use_defaults)
|
||||
/* By default IRQ support is mandatory */
|
||||
return ret;
|
||||
else
|
||||
port->irq = 0;
|
||||
|
||||
port->flags |= UPF_SHARE_IRQ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_read_port_properties(struct uart_port *port)
|
||||
{
|
||||
return __uart_read_properties(port, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(uart_read_port_properties);
|
||||
|
||||
int uart_read_and_validate_port_properties(struct uart_port *port)
|
||||
{
|
||||
return __uart_read_properties(port, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(uart_read_and_validate_port_properties);
|
||||
|
||||
static struct device_driver serial_port_driver = {
|
||||
.name = "port",
|
||||
.suppress_bind_attrs = true,
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
#include <linux/serial.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/txx9/generic.h>
|
||||
|
||||
#define PASS_LIMIT 256
|
||||
|
||||
#if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
|
||||
|
|
|
@ -576,13 +576,13 @@ static void sci_start_tx(struct uart_port *port)
|
|||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
u16 new, scr = serial_port_in(port, SCSCR);
|
||||
u16 new, scr = sci_serial_in(port, SCSCR);
|
||||
if (s->chan_tx)
|
||||
new = scr | SCSCR_TDRQE;
|
||||
else
|
||||
new = scr & ~SCSCR_TDRQE;
|
||||
if (new != scr)
|
||||
serial_port_out(port, SCSCR, new);
|
||||
sci_serial_out(port, SCSCR, new);
|
||||
}
|
||||
|
||||
if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
|
||||
|
@ -599,7 +599,7 @@ static void sci_start_tx(struct uart_port *port)
|
|||
if (!s->chan_tx || s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE ||
|
||||
port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl = sci_serial_in(port, SCSCR);
|
||||
|
||||
/*
|
||||
* For SCI, TE (transmit enable) must be set after setting TIE
|
||||
|
@ -609,7 +609,7 @@ static void sci_start_tx(struct uart_port *port)
|
|||
if (port->type == PORT_SCI)
|
||||
ctrl |= SCSCR_TE;
|
||||
|
||||
serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
|
||||
sci_serial_out(port, SCSCR, ctrl | SCSCR_TIE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -618,14 +618,14 @@ static void sci_stop_tx(struct uart_port *port)
|
|||
unsigned short ctrl;
|
||||
|
||||
/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl = sci_serial_in(port, SCSCR);
|
||||
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||
ctrl &= ~SCSCR_TDRQE;
|
||||
|
||||
ctrl &= ~SCSCR_TIE;
|
||||
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
sci_serial_out(port, SCSCR, ctrl);
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
if (to_sci_port(port)->chan_tx &&
|
||||
|
@ -640,41 +640,40 @@ static void sci_start_rx(struct uart_port *port)
|
|||
{
|
||||
unsigned short ctrl;
|
||||
|
||||
ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
|
||||
ctrl = sci_serial_in(port, SCSCR) | port_rx_irq_mask(port);
|
||||
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||
ctrl &= ~SCSCR_RDRQE;
|
||||
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
sci_serial_out(port, SCSCR, ctrl);
|
||||
}
|
||||
|
||||
static void sci_stop_rx(struct uart_port *port)
|
||||
{
|
||||
unsigned short ctrl;
|
||||
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl = sci_serial_in(port, SCSCR);
|
||||
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||
ctrl &= ~SCSCR_RDRQE;
|
||||
|
||||
ctrl &= ~port_rx_irq_mask(port);
|
||||
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
sci_serial_out(port, SCSCR, ctrl);
|
||||
}
|
||||
|
||||
static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask)
|
||||
{
|
||||
if (port->type == PORT_SCI) {
|
||||
/* Just store the mask */
|
||||
serial_port_out(port, SCxSR, mask);
|
||||
sci_serial_out(port, SCxSR, mask);
|
||||
} else if (to_sci_port(port)->params->overrun_mask == SCIFA_ORER) {
|
||||
/* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */
|
||||
/* Only clear the status bits we want to clear */
|
||||
serial_port_out(port, SCxSR,
|
||||
serial_port_in(port, SCxSR) & mask);
|
||||
sci_serial_out(port, SCxSR, sci_serial_in(port, SCxSR) & mask);
|
||||
} else {
|
||||
/* Store the mask, clear parity/framing errors */
|
||||
serial_port_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC));
|
||||
sci_serial_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -688,7 +687,7 @@ static int sci_poll_get_char(struct uart_port *port)
|
|||
int c;
|
||||
|
||||
do {
|
||||
status = serial_port_in(port, SCxSR);
|
||||
status = sci_serial_in(port, SCxSR);
|
||||
if (status & SCxSR_ERRORS(port)) {
|
||||
sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
|
||||
continue;
|
||||
|
@ -699,10 +698,10 @@ static int sci_poll_get_char(struct uart_port *port)
|
|||
if (!(status & SCxSR_RDxF(port)))
|
||||
return NO_POLL_CHAR;
|
||||
|
||||
c = serial_port_in(port, SCxRDR);
|
||||
c = sci_serial_in(port, SCxRDR);
|
||||
|
||||
/* Dummy read */
|
||||
serial_port_in(port, SCxSR);
|
||||
sci_serial_in(port, SCxSR);
|
||||
sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
|
||||
|
||||
return c;
|
||||
|
@ -714,10 +713,10 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
|
|||
unsigned short status;
|
||||
|
||||
do {
|
||||
status = serial_port_in(port, SCxSR);
|
||||
status = sci_serial_in(port, SCxSR);
|
||||
} while (!(status & SCxSR_TDxE(port)));
|
||||
|
||||
serial_port_out(port, SCxTDR, c);
|
||||
sci_serial_out(port, SCxTDR, c);
|
||||
sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
|
||||
}
|
||||
#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE ||
|
||||
|
@ -736,8 +735,8 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
|||
}
|
||||
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
u16 data = serial_port_in(port, SCPDR);
|
||||
u16 ctrl = serial_port_in(port, SCPCR);
|
||||
u16 data = sci_serial_in(port, SCPDR);
|
||||
u16 ctrl = sci_serial_in(port, SCPCR);
|
||||
|
||||
/* Enable RXD and TXD pin functions */
|
||||
ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
|
||||
|
@ -756,10 +755,10 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
|||
/* Enable CTS# pin function */
|
||||
ctrl &= ~SCPCR_CTSC;
|
||||
}
|
||||
serial_port_out(port, SCPDR, data);
|
||||
serial_port_out(port, SCPCR, ctrl);
|
||||
sci_serial_out(port, SCPDR, data);
|
||||
sci_serial_out(port, SCPCR, ctrl);
|
||||
} else if (sci_getreg(port, SCSPTR)->size) {
|
||||
u16 status = serial_port_in(port, SCSPTR);
|
||||
u16 status = sci_serial_in(port, SCSPTR);
|
||||
|
||||
/* RTS# is always output; and active low, unless autorts */
|
||||
status |= SCSPTR_RTSIO;
|
||||
|
@ -769,7 +768,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
|||
status &= ~SCSPTR_RTSDT;
|
||||
/* CTS# and SCK are inputs */
|
||||
status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO);
|
||||
serial_port_out(port, SCSPTR, status);
|
||||
sci_serial_out(port, SCSPTR, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -781,13 +780,13 @@ static int sci_txfill(struct uart_port *port)
|
|||
|
||||
reg = sci_getreg(port, SCTFDR);
|
||||
if (reg->size)
|
||||
return serial_port_in(port, SCTFDR) & fifo_mask;
|
||||
return sci_serial_in(port, SCTFDR) & fifo_mask;
|
||||
|
||||
reg = sci_getreg(port, SCFDR);
|
||||
if (reg->size)
|
||||
return serial_port_in(port, SCFDR) >> 8;
|
||||
return sci_serial_in(port, SCFDR) >> 8;
|
||||
|
||||
return !(serial_port_in(port, SCxSR) & SCI_TDRE);
|
||||
return !(sci_serial_in(port, SCxSR) & SCI_TDRE);
|
||||
}
|
||||
|
||||
static int sci_txroom(struct uart_port *port)
|
||||
|
@ -803,13 +802,13 @@ static int sci_rxfill(struct uart_port *port)
|
|||
|
||||
reg = sci_getreg(port, SCRFDR);
|
||||
if (reg->size)
|
||||
return serial_port_in(port, SCRFDR) & fifo_mask;
|
||||
return sci_serial_in(port, SCRFDR) & fifo_mask;
|
||||
|
||||
reg = sci_getreg(port, SCFDR);
|
||||
if (reg->size)
|
||||
return serial_port_in(port, SCFDR) & fifo_mask;
|
||||
return sci_serial_in(port, SCFDR) & fifo_mask;
|
||||
|
||||
return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
|
||||
return (sci_serial_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
|
||||
}
|
||||
|
||||
/* ********************************************************************** *
|
||||
|
@ -824,14 +823,14 @@ static void sci_transmit_chars(struct uart_port *port)
|
|||
unsigned short ctrl;
|
||||
int count;
|
||||
|
||||
status = serial_port_in(port, SCxSR);
|
||||
status = sci_serial_in(port, SCxSR);
|
||||
if (!(status & SCxSR_TDxE(port))) {
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl = sci_serial_in(port, SCSCR);
|
||||
if (uart_circ_empty(xmit))
|
||||
ctrl &= ~SCSCR_TIE;
|
||||
else
|
||||
ctrl |= SCSCR_TIE;
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
sci_serial_out(port, SCSCR, ctrl);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -847,15 +846,15 @@ static void sci_transmit_chars(struct uart_port *port)
|
|||
c = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
} else if (port->type == PORT_SCI && uart_circ_empty(xmit)) {
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl = sci_serial_in(port, SCSCR);
|
||||
ctrl &= ~SCSCR_TE;
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
sci_serial_out(port, SCSCR, ctrl);
|
||||
return;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
serial_port_out(port, SCxTDR, c);
|
||||
sci_serial_out(port, SCxTDR, c);
|
||||
|
||||
port->icount.tx++;
|
||||
} while (--count > 0);
|
||||
|
@ -866,10 +865,10 @@ static void sci_transmit_chars(struct uart_port *port)
|
|||
uart_write_wakeup(port);
|
||||
if (uart_circ_empty(xmit)) {
|
||||
if (port->type == PORT_SCI) {
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl = sci_serial_in(port, SCSCR);
|
||||
ctrl &= ~SCSCR_TIE;
|
||||
ctrl |= SCSCR_TEIE;
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
sci_serial_out(port, SCSCR, ctrl);
|
||||
}
|
||||
|
||||
sci_stop_tx(port);
|
||||
|
@ -883,7 +882,7 @@ static void sci_receive_chars(struct uart_port *port)
|
|||
unsigned short status;
|
||||
unsigned char flag;
|
||||
|
||||
status = serial_port_in(port, SCxSR);
|
||||
status = sci_serial_in(port, SCxSR);
|
||||
if (!(status & SCxSR_RDxF(port)))
|
||||
return;
|
||||
|
||||
|
@ -896,7 +895,7 @@ static void sci_receive_chars(struct uart_port *port)
|
|||
break;
|
||||
|
||||
if (port->type == PORT_SCI) {
|
||||
char c = serial_port_in(port, SCxRDR);
|
||||
char c = sci_serial_in(port, SCxRDR);
|
||||
if (uart_handle_sysrq_char(port, c))
|
||||
count = 0;
|
||||
else
|
||||
|
@ -907,11 +906,11 @@ static void sci_receive_chars(struct uart_port *port)
|
|||
|
||||
if (port->type == PORT_SCIF ||
|
||||
port->type == PORT_HSCIF) {
|
||||
status = serial_port_in(port, SCxSR);
|
||||
c = serial_port_in(port, SCxRDR);
|
||||
status = sci_serial_in(port, SCxSR);
|
||||
c = sci_serial_in(port, SCxRDR);
|
||||
} else {
|
||||
c = serial_port_in(port, SCxRDR);
|
||||
status = serial_port_in(port, SCxSR);
|
||||
c = sci_serial_in(port, SCxRDR);
|
||||
status = sci_serial_in(port, SCxSR);
|
||||
}
|
||||
if (uart_handle_sysrq_char(port, c)) {
|
||||
count--; i--;
|
||||
|
@ -932,7 +931,7 @@ static void sci_receive_chars(struct uart_port *port)
|
|||
}
|
||||
}
|
||||
|
||||
serial_port_in(port, SCxSR); /* dummy read */
|
||||
sci_serial_in(port, SCxSR); /* dummy read */
|
||||
sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
|
||||
|
||||
copied += count;
|
||||
|
@ -944,8 +943,8 @@ static void sci_receive_chars(struct uart_port *port)
|
|||
tty_flip_buffer_push(tport);
|
||||
} else {
|
||||
/* TTY buffers full; read from RX reg to prevent lockup */
|
||||
serial_port_in(port, SCxRDR);
|
||||
serial_port_in(port, SCxSR); /* dummy read */
|
||||
sci_serial_in(port, SCxRDR);
|
||||
sci_serial_in(port, SCxSR); /* dummy read */
|
||||
sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
|
||||
}
|
||||
}
|
||||
|
@ -953,7 +952,7 @@ static void sci_receive_chars(struct uart_port *port)
|
|||
static int sci_handle_errors(struct uart_port *port)
|
||||
{
|
||||
int copied = 0;
|
||||
unsigned short status = serial_port_in(port, SCxSR);
|
||||
unsigned short status = sci_serial_in(port, SCxSR);
|
||||
struct tty_port *tport = &port->state->port;
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
|
||||
|
@ -1000,10 +999,10 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
|
|||
if (!reg->size)
|
||||
return 0;
|
||||
|
||||
status = serial_port_in(port, s->params->overrun_reg);
|
||||
status = sci_serial_in(port, s->params->overrun_reg);
|
||||
if (status & s->params->overrun_mask) {
|
||||
status &= ~s->params->overrun_mask;
|
||||
serial_port_out(port, s->params->overrun_reg, status);
|
||||
sci_serial_out(port, s->params->overrun_reg, status);
|
||||
|
||||
port->icount.overrun++;
|
||||
|
||||
|
@ -1018,7 +1017,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
|
|||
static int sci_handle_breaks(struct uart_port *port)
|
||||
{
|
||||
int copied = 0;
|
||||
unsigned short status = serial_port_in(port, SCxSR);
|
||||
unsigned short status = sci_serial_in(port, SCxSR);
|
||||
struct tty_port *tport = &port->state->port;
|
||||
|
||||
if (uart_handle_break(port))
|
||||
|
@ -1051,7 +1050,7 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig)
|
|||
|
||||
/* HSCIF can be set to an arbitrary level. */
|
||||
if (sci_getreg(port, HSRTRGR)->size) {
|
||||
serial_port_out(port, HSRTRGR, rx_trig);
|
||||
sci_serial_out(port, HSRTRGR, rx_trig);
|
||||
return rx_trig;
|
||||
}
|
||||
|
||||
|
@ -1092,9 +1091,9 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig)
|
|||
return 1;
|
||||
}
|
||||
|
||||
serial_port_out(port, SCFCR,
|
||||
(serial_port_in(port, SCFCR) &
|
||||
~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits);
|
||||
sci_serial_out(port, SCFCR,
|
||||
(sci_serial_in(port, SCFCR) &
|
||||
~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits);
|
||||
|
||||
return rx_trig;
|
||||
}
|
||||
|
@ -1102,9 +1101,9 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig)
|
|||
static int scif_rtrg_enabled(struct uart_port *port)
|
||||
{
|
||||
if (sci_getreg(port, HSRTRGR)->size)
|
||||
return serial_port_in(port, HSRTRGR) != 0;
|
||||
return sci_serial_in(port, HSRTRGR) != 0;
|
||||
else
|
||||
return (serial_port_in(port, SCFCR) &
|
||||
return (sci_serial_in(port, SCFCR) &
|
||||
(SCFCR_RTRG0 | SCFCR_RTRG1)) != 0;
|
||||
}
|
||||
|
||||
|
@ -1219,8 +1218,8 @@ static void sci_dma_tx_complete(void *arg)
|
|||
s->cookie_tx = -EINVAL;
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
|
||||
s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
|
||||
u16 ctrl = serial_port_in(port, SCSCR);
|
||||
serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
|
||||
u16 ctrl = sci_serial_in(port, SCSCR);
|
||||
sci_serial_out(port, SCSCR, ctrl & ~SCSCR_TIE);
|
||||
if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
|
||||
/* Switch irq from DMA to SCIF */
|
||||
dmaengine_pause(s->chan_tx_saved);
|
||||
|
@ -1296,7 +1295,7 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s)
|
|||
u16 scr;
|
||||
|
||||
/* Direct new serial port interrupts back to CPU */
|
||||
scr = serial_port_in(port, SCSCR);
|
||||
scr = sci_serial_in(port, SCSCR);
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
|
||||
s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
|
||||
enable_irq(s->irqs[SCIx_RXI_IRQ]);
|
||||
|
@ -1305,7 +1304,7 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s)
|
|||
else
|
||||
scr &= ~SCSCR_RDRQE;
|
||||
}
|
||||
serial_port_out(port, SCSCR, scr | SCSCR_RIE);
|
||||
sci_serial_out(port, SCSCR, scr | SCSCR_RIE);
|
||||
}
|
||||
|
||||
static void sci_dma_rx_complete(void *arg)
|
||||
|
@ -1714,8 +1713,8 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
|
|||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
if (s->chan_rx) {
|
||||
u16 scr = serial_port_in(port, SCSCR);
|
||||
u16 ssr = serial_port_in(port, SCxSR);
|
||||
u16 scr = sci_serial_in(port, SCSCR);
|
||||
u16 ssr = sci_serial_in(port, SCxSR);
|
||||
|
||||
/* Disable future Rx interrupts */
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
|
||||
|
@ -1733,10 +1732,10 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
|
|||
|
||||
scr &= ~SCSCR_RIE;
|
||||
}
|
||||
serial_port_out(port, SCSCR, scr);
|
||||
sci_serial_out(port, SCSCR, scr);
|
||||
/* Clear current interrupt */
|
||||
serial_port_out(port, SCxSR,
|
||||
ssr & ~(SCIF_DR | SCxSR_RDxF(port)));
|
||||
sci_serial_out(port, SCxSR,
|
||||
ssr & ~(SCIF_DR | SCxSR_RDxF(port)));
|
||||
dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u us\n",
|
||||
jiffies, s->rx_timeout);
|
||||
start_hrtimer_us(&s->rx_timer, s->rx_timeout);
|
||||
|
@ -1786,9 +1785,9 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
|
|||
return sci_tx_interrupt(irq, ptr);
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl = sci_serial_in(port, SCSCR);
|
||||
ctrl &= ~(SCSCR_TE | SCSCR_TEIE);
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
sci_serial_out(port, SCSCR, ctrl);
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -1802,7 +1801,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
|
|||
sci_handle_breaks(port);
|
||||
|
||||
/* drop invalid character received before break was detected */
|
||||
serial_port_in(port, SCxRDR);
|
||||
sci_serial_in(port, SCxRDR);
|
||||
|
||||
sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
|
||||
|
||||
|
@ -1816,7 +1815,7 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr)
|
|||
|
||||
if (s->irqs[SCIx_ERI_IRQ] == s->irqs[SCIx_BRI_IRQ]) {
|
||||
/* Break and Error interrupts are muxed */
|
||||
unsigned short ssr_status = serial_port_in(port, SCxSR);
|
||||
unsigned short ssr_status = sci_serial_in(port, SCxSR);
|
||||
|
||||
/* Break Interrupt */
|
||||
if (ssr_status & SCxSR_BRK(port))
|
||||
|
@ -1831,7 +1830,7 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr)
|
|||
if (port->type == PORT_SCI) {
|
||||
if (sci_handle_errors(port)) {
|
||||
/* discard character in rx buffer */
|
||||
serial_port_in(port, SCxSR);
|
||||
sci_serial_in(port, SCxSR);
|
||||
sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
|
||||
}
|
||||
} else {
|
||||
|
@ -1856,12 +1855,12 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
|
|||
struct sci_port *s = to_sci_port(port);
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
ssr_status = serial_port_in(port, SCxSR);
|
||||
scr_status = serial_port_in(port, SCSCR);
|
||||
ssr_status = sci_serial_in(port, SCxSR);
|
||||
scr_status = sci_serial_in(port, SCSCR);
|
||||
if (s->params->overrun_reg == SCxSR)
|
||||
orer_status = ssr_status;
|
||||
else if (sci_getreg(port, s->params->overrun_reg)->size)
|
||||
orer_status = serial_port_in(port, s->params->overrun_reg);
|
||||
orer_status = sci_serial_in(port, s->params->overrun_reg);
|
||||
|
||||
err_enabled = scr_status & port_rx_irq_mask(port);
|
||||
|
||||
|
@ -2038,7 +2037,7 @@ static void sci_free_irq(struct sci_port *port)
|
|||
|
||||
static unsigned int sci_tx_empty(struct uart_port *port)
|
||||
{
|
||||
unsigned short status = serial_port_in(port, SCxSR);
|
||||
unsigned short status = sci_serial_in(port, SCxSR);
|
||||
unsigned short in_tx_fifo = sci_txfill(port);
|
||||
|
||||
return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
|
||||
|
@ -2047,27 +2046,27 @@ static unsigned int sci_tx_empty(struct uart_port *port)
|
|||
static void sci_set_rts(struct uart_port *port, bool state)
|
||||
{
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
u16 data = serial_port_in(port, SCPDR);
|
||||
u16 data = sci_serial_in(port, SCPDR);
|
||||
|
||||
/* Active low */
|
||||
if (state)
|
||||
data &= ~SCPDR_RTSD;
|
||||
else
|
||||
data |= SCPDR_RTSD;
|
||||
serial_port_out(port, SCPDR, data);
|
||||
sci_serial_out(port, SCPDR, data);
|
||||
|
||||
/* RTS# is output */
|
||||
serial_port_out(port, SCPCR,
|
||||
serial_port_in(port, SCPCR) | SCPCR_RTSC);
|
||||
sci_serial_out(port, SCPCR,
|
||||
sci_serial_in(port, SCPCR) | SCPCR_RTSC);
|
||||
} else if (sci_getreg(port, SCSPTR)->size) {
|
||||
u16 ctrl = serial_port_in(port, SCSPTR);
|
||||
u16 ctrl = sci_serial_in(port, SCSPTR);
|
||||
|
||||
/* Active low */
|
||||
if (state)
|
||||
ctrl &= ~SCSPTR_RTSDT;
|
||||
else
|
||||
ctrl |= SCSPTR_RTSDT;
|
||||
serial_port_out(port, SCSPTR, ctrl);
|
||||
sci_serial_out(port, SCSPTR, ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2075,10 +2074,10 @@ static bool sci_get_cts(struct uart_port *port)
|
|||
{
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
/* Active low */
|
||||
return !(serial_port_in(port, SCPDR) & SCPDR_CTSD);
|
||||
return !(sci_serial_in(port, SCPDR) & SCPDR_CTSD);
|
||||
} else if (sci_getreg(port, SCSPTR)->size) {
|
||||
/* Active low */
|
||||
return !(serial_port_in(port, SCSPTR) & SCSPTR_CTSDT);
|
||||
return !(sci_serial_in(port, SCSPTR) & SCSPTR_CTSDT);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2108,9 +2107,8 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
*/
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size)
|
||||
serial_port_out(port, SCFCR,
|
||||
serial_port_in(port, SCFCR) |
|
||||
SCFCR_LOOP);
|
||||
sci_serial_out(port, SCFCR,
|
||||
sci_serial_in(port, SCFCR) | SCFCR_LOOP);
|
||||
}
|
||||
|
||||
mctrl_gpio_set(s->gpios, mctrl);
|
||||
|
@ -2120,21 +2118,21 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
|
||||
if (!(mctrl & TIOCM_RTS)) {
|
||||
/* Disable Auto RTS */
|
||||
serial_port_out(port, SCFCR,
|
||||
serial_port_in(port, SCFCR) & ~SCFCR_MCE);
|
||||
sci_serial_out(port, SCFCR,
|
||||
sci_serial_in(port, SCFCR) & ~SCFCR_MCE);
|
||||
|
||||
/* Clear RTS */
|
||||
sci_set_rts(port, 0);
|
||||
} else if (s->autorts) {
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
/* Enable RTS# pin function */
|
||||
serial_port_out(port, SCPCR,
|
||||
serial_port_in(port, SCPCR) & ~SCPCR_RTSC);
|
||||
sci_serial_out(port, SCPCR,
|
||||
sci_serial_in(port, SCPCR) & ~SCPCR_RTSC);
|
||||
}
|
||||
|
||||
/* Enable Auto RTS */
|
||||
serial_port_out(port, SCFCR,
|
||||
serial_port_in(port, SCFCR) | SCFCR_MCE);
|
||||
sci_serial_out(port, SCFCR,
|
||||
sci_serial_in(port, SCFCR) | SCFCR_MCE);
|
||||
} else {
|
||||
/* Set RTS */
|
||||
sci_set_rts(port, 1);
|
||||
|
@ -2187,8 +2185,8 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
|
|||
}
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
scsptr = serial_port_in(port, SCSPTR);
|
||||
scscr = serial_port_in(port, SCSCR);
|
||||
scsptr = sci_serial_in(port, SCSPTR);
|
||||
scscr = sci_serial_in(port, SCSCR);
|
||||
|
||||
if (break_state == -1) {
|
||||
scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
|
||||
|
@ -2198,8 +2196,8 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
|
|||
scscr |= SCSCR_TE;
|
||||
}
|
||||
|
||||
serial_port_out(port, SCSPTR, scsptr);
|
||||
serial_port_out(port, SCSCR, scscr);
|
||||
sci_serial_out(port, SCSPTR, scsptr);
|
||||
sci_serial_out(port, SCSCR, scscr);
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
|
@ -2239,9 +2237,9 @@ static void sci_shutdown(struct uart_port *port)
|
|||
* Stop RX and TX, disable related interrupts, keep clock source
|
||||
* and HSCIF TOT bits
|
||||
*/
|
||||
scr = serial_port_in(port, SCSCR);
|
||||
serial_port_out(port, SCSCR, scr &
|
||||
(SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot));
|
||||
scr = sci_serial_in(port, SCSCR);
|
||||
sci_serial_out(port, SCSCR,
|
||||
scr & (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot));
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
|
@ -2390,19 +2388,19 @@ static void sci_reset(struct uart_port *port)
|
|||
unsigned int status;
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
|
||||
serial_port_out(port, SCSCR, s->hscif_tot); /* TE=0, RE=0, CKE1=0 */
|
||||
sci_serial_out(port, SCSCR, s->hscif_tot); /* TE=0, RE=0, CKE1=0 */
|
||||
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size)
|
||||
serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
|
||||
sci_serial_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
|
||||
|
||||
sci_clear_SCxSR(port,
|
||||
SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) &
|
||||
SCxSR_BREAK_CLEAR(port));
|
||||
if (sci_getreg(port, SCLSR)->size) {
|
||||
status = serial_port_in(port, SCLSR);
|
||||
status = sci_serial_in(port, SCLSR);
|
||||
status &= ~(SCLSR_TO | SCLSR_ORER);
|
||||
serial_port_out(port, SCLSR, status);
|
||||
sci_serial_out(port, SCLSR, status);
|
||||
}
|
||||
|
||||
if (s->rx_trigger > 1) {
|
||||
|
@ -2540,8 +2538,8 @@ done:
|
|||
* It controls the mux to select (H)SCK or frequency divided clock.
|
||||
*/
|
||||
if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) {
|
||||
serial_port_out(port, SCDL, dl);
|
||||
serial_port_out(port, SCCKS, sccks);
|
||||
sci_serial_out(port, SCDL, dl);
|
||||
sci_serial_out(port, SCCKS, sccks);
|
||||
}
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
@ -2554,7 +2552,7 @@ done:
|
|||
bits = tty_get_frame_size(termios->c_cflag);
|
||||
|
||||
if (sci_getreg(port, SEMR)->size)
|
||||
serial_port_out(port, SEMR, 0);
|
||||
sci_serial_out(port, SEMR, 0);
|
||||
|
||||
if (best_clk >= 0) {
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||
|
@ -2569,9 +2567,9 @@ done:
|
|||
case 27: smr_val |= SCSMR_SRC_27; break;
|
||||
}
|
||||
smr_val |= cks;
|
||||
serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
|
||||
serial_port_out(port, SCSMR, smr_val);
|
||||
serial_port_out(port, SCBRR, brr);
|
||||
sci_serial_out(port, SCSCR, scr_val | s->hscif_tot);
|
||||
sci_serial_out(port, SCSMR, smr_val);
|
||||
sci_serial_out(port, SCBRR, brr);
|
||||
if (sci_getreg(port, HSSRR)->size) {
|
||||
unsigned int hssrr = srr | HSCIF_SRE;
|
||||
/* Calculate deviation from intended rate at the
|
||||
|
@ -2593,7 +2591,7 @@ done:
|
|||
HSCIF_SRHP_MASK;
|
||||
hssrr |= HSCIF_SRDE;
|
||||
}
|
||||
serial_port_out(port, HSSRR, hssrr);
|
||||
sci_serial_out(port, HSSRR, hssrr);
|
||||
}
|
||||
|
||||
/* Wait one bit interval */
|
||||
|
@ -2601,10 +2599,10 @@ done:
|
|||
} else {
|
||||
/* Don't touch the bit rate configuration */
|
||||
scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0);
|
||||
smr_val |= serial_port_in(port, SCSMR) &
|
||||
smr_val |= sci_serial_in(port, SCSMR) &
|
||||
(SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS);
|
||||
serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
|
||||
serial_port_out(port, SCSMR, smr_val);
|
||||
sci_serial_out(port, SCSCR, scr_val | s->hscif_tot);
|
||||
sci_serial_out(port, SCSMR, smr_val);
|
||||
}
|
||||
|
||||
sci_init_pins(port, termios->c_cflag);
|
||||
|
@ -2613,7 +2611,7 @@ done:
|
|||
s->autorts = false;
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size) {
|
||||
unsigned short ctrl = serial_port_in(port, SCFCR);
|
||||
unsigned short ctrl = sci_serial_in(port, SCFCR);
|
||||
|
||||
if ((port->flags & UPF_HARD_FLOW) &&
|
||||
(termios->c_cflag & CRTSCTS)) {
|
||||
|
@ -2630,7 +2628,7 @@ done:
|
|||
*/
|
||||
ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);
|
||||
|
||||
serial_port_out(port, SCFCR, ctrl);
|
||||
sci_serial_out(port, SCFCR, ctrl);
|
||||
}
|
||||
if (port->flags & UPF_HARD_FLOW) {
|
||||
/* Refresh (Auto) RTS */
|
||||
|
@ -2645,7 +2643,7 @@ done:
|
|||
if (port->type != PORT_SCI)
|
||||
scr_val |= SCSCR_TE;
|
||||
scr_val |= SCSCR_RE | (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
|
||||
serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
|
||||
sci_serial_out(port, SCSCR, scr_val | s->hscif_tot);
|
||||
if ((srr + 1 == 5) &&
|
||||
(port->type == PORT_SCIFA || port->type == PORT_SCIFB)) {
|
||||
/*
|
||||
|
@ -3017,9 +3015,6 @@ static int sci_init_single(struct platform_device *dev,
|
|||
port->irq = sci_port->irqs[SCIx_RXI_IRQ];
|
||||
port->irqflags = 0;
|
||||
|
||||
port->serial_in = sci_serial_in;
|
||||
port->serial_out = sci_serial_out;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3056,21 +3051,21 @@ static void serial_console_write(struct console *co, const char *s,
|
|||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
/* first save SCSCR then disable interrupts, keep clock source */
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl = sci_serial_in(port, SCSCR);
|
||||
ctrl_temp = SCSCR_RE | SCSCR_TE |
|
||||
(sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) |
|
||||
(ctrl & (SCSCR_CKE1 | SCSCR_CKE0));
|
||||
serial_port_out(port, SCSCR, ctrl_temp | sci_port->hscif_tot);
|
||||
sci_serial_out(port, SCSCR, ctrl_temp | sci_port->hscif_tot);
|
||||
|
||||
uart_console_write(port, s, count, serial_console_putchar);
|
||||
|
||||
/* wait until fifo is empty and last bit has been transmitted */
|
||||
bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
|
||||
while ((serial_port_in(port, SCxSR) & bits) != bits)
|
||||
while ((sci_serial_in(port, SCxSR) & bits) != bits)
|
||||
cpu_relax();
|
||||
|
||||
/* restore the SCSCR */
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
sci_serial_out(port, SCSCR, ctrl);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
|
@ -3503,8 +3498,6 @@ static int __init early_console_setup(struct earlycon_device *device,
|
|||
if (!device->port.membase)
|
||||
return -ENODEV;
|
||||
|
||||
device->port.serial_in = sci_serial_in;
|
||||
device->port.serial_out = sci_serial_out;
|
||||
device->port.type = type;
|
||||
memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port));
|
||||
port_cfg.type = type;
|
||||
|
|
|
@ -412,7 +412,8 @@ static void __ssp_receive_chars(struct sifive_serial_port *ssp)
|
|||
break;
|
||||
|
||||
ssp->port.icount.rx++;
|
||||
uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL);
|
||||
if (!uart_prepare_sysrq_char(&ssp->port, ch))
|
||||
uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL);
|
||||
}
|
||||
|
||||
tty_flip_buffer_push(&ssp->port.state->port);
|
||||
|
@ -534,7 +535,7 @@ static irqreturn_t sifive_serial_irq(int irq, void *dev_id)
|
|||
if (ip & SIFIVE_SERIAL_IP_TXWM_MASK)
|
||||
__ssp_transmit_chars(ssp);
|
||||
|
||||
uart_port_unlock(&ssp->port);
|
||||
uart_unlock_and_check_sysrq(&ssp->port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -791,13 +792,10 @@ static void sifive_serial_console_write(struct console *co, const char *s,
|
|||
if (!ssp)
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (ssp->port.sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(&ssp->port);
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(&ssp->port, &flags);
|
||||
else
|
||||
uart_port_lock(&ssp->port);
|
||||
uart_port_lock_irqsave(&ssp->port, &flags);
|
||||
|
||||
ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS);
|
||||
__ssp_writel(0, SIFIVE_SERIAL_IE_OFFS, ssp);
|
||||
|
@ -807,8 +805,7 @@ static void sifive_serial_console_write(struct console *co, const char *s,
|
|||
__ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(&ssp->port);
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(&ssp->port, flags);
|
||||
}
|
||||
|
||||
static int sifive_serial_console_setup(struct console *co, char *options)
|
||||
|
|
|
@ -465,6 +465,7 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
const struct ktermios *old)
|
||||
{
|
||||
struct asc_port *ascport = to_asc_port(port);
|
||||
bool manual_rts, toggle_rts = false;
|
||||
struct gpio_desc *gpiod;
|
||||
unsigned int baud;
|
||||
u32 ctrl_val;
|
||||
|
@ -518,25 +519,13 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
|
||||
/* If flow-control selected, stop handling RTS manually */
|
||||
if (ascport->rts) {
|
||||
devm_gpiod_put(port->dev, ascport->rts);
|
||||
ascport->rts = NULL;
|
||||
|
||||
pinctrl_select_state(ascport->pinctrl,
|
||||
ascport->states[DEFAULT]);
|
||||
toggle_rts = true;
|
||||
manual_rts = false;
|
||||
}
|
||||
} else {
|
||||
/* If flow-control disabled, it's safe to handle RTS manually */
|
||||
if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) {
|
||||
pinctrl_select_state(ascport->pinctrl,
|
||||
ascport->states[NO_HW_FLOWCTRL]);
|
||||
|
||||
gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW);
|
||||
if (!IS_ERR(gpiod)) {
|
||||
gpiod_set_consumer_name(gpiod,
|
||||
port->dev->of_node->name);
|
||||
ascport->rts = gpiod;
|
||||
}
|
||||
}
|
||||
if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL])
|
||||
manual_rts = toggle_rts = true;
|
||||
}
|
||||
|
||||
if ((baud < 19200) && !ascport->force_m1) {
|
||||
|
@ -595,6 +584,25 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN));
|
||||
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
|
||||
if (toggle_rts) {
|
||||
if (manual_rts) {
|
||||
pinctrl_select_state(ascport->pinctrl,
|
||||
ascport->states[NO_HW_FLOWCTRL]);
|
||||
|
||||
gpiod = devm_gpiod_get(port->dev, "rts", GPIOD_OUT_LOW);
|
||||
if (!IS_ERR(gpiod)) {
|
||||
gpiod_set_consumer_name(gpiod,
|
||||
port->dev->of_node->name);
|
||||
ascport->rts = gpiod;
|
||||
}
|
||||
} else {
|
||||
devm_gpiod_put(port->dev, ascport->rts);
|
||||
ascport->rts = NULL;
|
||||
pinctrl_select_state(ascport->pinctrl,
|
||||
ascport->states[DEFAULT]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *asc_type(struct uart_port *port)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* Inspired by st-asc.c from STMicroelectronics (c)
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -39,60 +40,64 @@
|
|||
/* Register offsets */
|
||||
static struct stm32_usart_info __maybe_unused stm32f4_info = {
|
||||
.ofs = {
|
||||
.isr = 0x00,
|
||||
.rdr = 0x04,
|
||||
.tdr = 0x04,
|
||||
.brr = 0x08,
|
||||
.cr1 = 0x0c,
|
||||
.cr2 = 0x10,
|
||||
.cr3 = 0x14,
|
||||
.gtpr = 0x18,
|
||||
.rtor = UNDEF_REG,
|
||||
.rqr = UNDEF_REG,
|
||||
.icr = UNDEF_REG,
|
||||
.isr = 0x00,
|
||||
.rdr = 0x04,
|
||||
.tdr = 0x04,
|
||||
.brr = 0x08,
|
||||
.cr1 = 0x0c,
|
||||
.cr2 = 0x10,
|
||||
.cr3 = 0x14,
|
||||
.gtpr = 0x18,
|
||||
.rtor = UNDEF_REG,
|
||||
.rqr = UNDEF_REG,
|
||||
.icr = UNDEF_REG,
|
||||
.presc = UNDEF_REG,
|
||||
.hwcfgr1 = UNDEF_REG,
|
||||
},
|
||||
.cfg = {
|
||||
.uart_enable_bit = 13,
|
||||
.has_7bits_data = false,
|
||||
.fifosize = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static struct stm32_usart_info __maybe_unused stm32f7_info = {
|
||||
.ofs = {
|
||||
.cr1 = 0x00,
|
||||
.cr2 = 0x04,
|
||||
.cr3 = 0x08,
|
||||
.brr = 0x0c,
|
||||
.gtpr = 0x10,
|
||||
.rtor = 0x14,
|
||||
.rqr = 0x18,
|
||||
.isr = 0x1c,
|
||||
.icr = 0x20,
|
||||
.rdr = 0x24,
|
||||
.tdr = 0x28,
|
||||
.cr1 = 0x00,
|
||||
.cr2 = 0x04,
|
||||
.cr3 = 0x08,
|
||||
.brr = 0x0c,
|
||||
.gtpr = 0x10,
|
||||
.rtor = 0x14,
|
||||
.rqr = 0x18,
|
||||
.isr = 0x1c,
|
||||
.icr = 0x20,
|
||||
.rdr = 0x24,
|
||||
.tdr = 0x28,
|
||||
.presc = UNDEF_REG,
|
||||
.hwcfgr1 = UNDEF_REG,
|
||||
},
|
||||
.cfg = {
|
||||
.uart_enable_bit = 0,
|
||||
.has_7bits_data = true,
|
||||
.has_swap = true,
|
||||
.fifosize = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static struct stm32_usart_info __maybe_unused stm32h7_info = {
|
||||
.ofs = {
|
||||
.cr1 = 0x00,
|
||||
.cr2 = 0x04,
|
||||
.cr3 = 0x08,
|
||||
.brr = 0x0c,
|
||||
.gtpr = 0x10,
|
||||
.rtor = 0x14,
|
||||
.rqr = 0x18,
|
||||
.isr = 0x1c,
|
||||
.icr = 0x20,
|
||||
.rdr = 0x24,
|
||||
.tdr = 0x28,
|
||||
.cr1 = 0x00,
|
||||
.cr2 = 0x04,
|
||||
.cr3 = 0x08,
|
||||
.brr = 0x0c,
|
||||
.gtpr = 0x10,
|
||||
.rtor = 0x14,
|
||||
.rqr = 0x18,
|
||||
.isr = 0x1c,
|
||||
.icr = 0x20,
|
||||
.rdr = 0x24,
|
||||
.tdr = 0x28,
|
||||
.presc = 0x2c,
|
||||
.hwcfgr1 = 0x3f0,
|
||||
},
|
||||
.cfg = {
|
||||
.uart_enable_bit = 0,
|
||||
|
@ -100,7 +105,6 @@ static struct stm32_usart_info __maybe_unused stm32h7_info = {
|
|||
.has_swap = true,
|
||||
.has_wakeup = true,
|
||||
.has_fifo = true,
|
||||
.fifosize = 16,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1147,6 +1151,8 @@ static void stm32_usart_shutdown(struct uart_port *port)
|
|||
free_irq(port->irq, port);
|
||||
}
|
||||
|
||||
static const unsigned int stm32_usart_presc_val[] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256};
|
||||
|
||||
static void stm32_usart_set_termios(struct uart_port *port,
|
||||
struct ktermios *termios,
|
||||
const struct ktermios *old)
|
||||
|
@ -1155,17 +1161,19 @@ static void stm32_usart_set_termios(struct uart_port *port,
|
|||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
|
||||
struct serial_rs485 *rs485conf = &port->rs485;
|
||||
unsigned int baud, bits;
|
||||
unsigned int baud, bits, uart_clk, uart_clk_pres;
|
||||
u32 usartdiv, mantissa, fraction, oversampling;
|
||||
tcflag_t cflag = termios->c_cflag;
|
||||
u32 cr1, cr2, cr3, isr;
|
||||
u32 cr1, cr2, cr3, isr, brr, presc;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!stm32_port->hw_flow_control)
|
||||
cflag &= ~CRTSCTS;
|
||||
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 8);
|
||||
uart_clk = clk_get_rate(stm32_port->clk);
|
||||
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, uart_clk / 8);
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
|
@ -1267,27 +1275,48 @@ static void stm32_usart_set_termios(struct uart_port *port,
|
|||
cr3 |= USART_CR3_CTSE | USART_CR3_RTSE;
|
||||
}
|
||||
|
||||
usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
|
||||
for (presc = 0; presc <= USART_PRESC_MAX; presc++) {
|
||||
uart_clk_pres = DIV_ROUND_CLOSEST(uart_clk, stm32_usart_presc_val[presc]);
|
||||
usartdiv = DIV_ROUND_CLOSEST(uart_clk_pres, baud);
|
||||
|
||||
/*
|
||||
* The USART supports 16 or 8 times oversampling.
|
||||
* By default we prefer 16 times oversampling, so that the receiver
|
||||
* has a better tolerance to clock deviations.
|
||||
* 8 times oversampling is only used to achieve higher speeds.
|
||||
*/
|
||||
if (usartdiv < 16) {
|
||||
oversampling = 8;
|
||||
cr1 |= USART_CR1_OVER8;
|
||||
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8);
|
||||
} else {
|
||||
oversampling = 16;
|
||||
cr1 &= ~USART_CR1_OVER8;
|
||||
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_OVER8);
|
||||
/*
|
||||
* The USART supports 16 or 8 times oversampling.
|
||||
* By default we prefer 16 times oversampling, so that the receiver
|
||||
* has a better tolerance to clock deviations.
|
||||
* 8 times oversampling is only used to achieve higher speeds.
|
||||
*/
|
||||
if (usartdiv < 16) {
|
||||
oversampling = 8;
|
||||
cr1 |= USART_CR1_OVER8;
|
||||
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8);
|
||||
} else {
|
||||
oversampling = 16;
|
||||
cr1 &= ~USART_CR1_OVER8;
|
||||
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_OVER8);
|
||||
}
|
||||
|
||||
mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT;
|
||||
fraction = usartdiv % oversampling;
|
||||
brr = mantissa | fraction;
|
||||
|
||||
if (FIELD_FIT(USART_BRR_MASK, brr)) {
|
||||
if (ofs->presc != UNDEF_REG) {
|
||||
port->uartclk = uart_clk_pres;
|
||||
writel_relaxed(presc, port->membase + ofs->presc);
|
||||
} else if (presc) {
|
||||
/* We need a prescaler but we don't have it (STM32F4, STM32F7) */
|
||||
dev_err(port->dev,
|
||||
"unable to set baudrate, input clock is too high");
|
||||
}
|
||||
break;
|
||||
} else if (presc == USART_PRESC_MAX) {
|
||||
/* Even with prescaler and brr at max value we can't set baudrate */
|
||||
dev_err(port->dev, "unable to set baudrate, input clock is too high");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT;
|
||||
fraction = usartdiv % oversampling;
|
||||
writel_relaxed(mantissa | fraction, port->membase + ofs->brr);
|
||||
writel_relaxed(brr, port->membase + ofs->brr);
|
||||
|
||||
uart_update_timeout(port, cflag, baud);
|
||||
|
||||
|
@ -1471,37 +1500,57 @@ static const struct uart_ops stm32_uart_ops = {
|
|||
#endif /* CONFIG_CONSOLE_POLL */
|
||||
};
|
||||
|
||||
/*
|
||||
* STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG)
|
||||
* Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case,
|
||||
* RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE.
|
||||
* So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1.
|
||||
*/
|
||||
static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 };
|
||||
struct stm32_usart_thresh_ratio {
|
||||
int mul;
|
||||
int div;
|
||||
};
|
||||
|
||||
static void stm32_usart_get_ftcfg(struct platform_device *pdev, const char *p,
|
||||
int *ftcfg)
|
||||
static const struct stm32_usart_thresh_ratio stm32h7_usart_fifo_thresh_cfg[] = {
|
||||
{1, 8}, {1, 4}, {1, 2}, {3, 4}, {7, 8}, {1, 1} };
|
||||
|
||||
static int stm32_usart_get_thresh_value(u32 fifo_size, int index)
|
||||
{
|
||||
u32 bytes, i;
|
||||
return fifo_size * stm32h7_usart_fifo_thresh_cfg[index].mul /
|
||||
stm32h7_usart_fifo_thresh_cfg[index].div;
|
||||
}
|
||||
|
||||
/* DT option to get RX & TX FIFO threshold (default to 8 bytes) */
|
||||
static int stm32_usart_get_ftcfg(struct platform_device *pdev, struct stm32_port *stm32port,
|
||||
const char *p, int *ftcfg)
|
||||
{
|
||||
const struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
|
||||
u32 bytes, i, cfg8;
|
||||
int fifo_size;
|
||||
|
||||
if (WARN_ON(ofs->hwcfgr1 == UNDEF_REG))
|
||||
return 1;
|
||||
|
||||
cfg8 = FIELD_GET(USART_HWCFGR1_CFG8,
|
||||
readl_relaxed(stm32port->port.membase + ofs->hwcfgr1));
|
||||
|
||||
/* On STM32H7, hwcfgr is not present, so returned value will be 0 */
|
||||
fifo_size = cfg8 ? 1 << cfg8 : STM32H7_USART_FIFO_SIZE;
|
||||
|
||||
/* DT option to get RX & TX FIFO threshold (default to half fifo size) */
|
||||
if (of_property_read_u32(pdev->dev.of_node, p, &bytes))
|
||||
bytes = 8;
|
||||
bytes = fifo_size / 2;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++)
|
||||
if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes)
|
||||
if (bytes < stm32_usart_get_thresh_value(fifo_size, 0)) {
|
||||
*ftcfg = -EINVAL;
|
||||
return fifo_size;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++) {
|
||||
if (stm32_usart_get_thresh_value(fifo_size, i) >= bytes)
|
||||
break;
|
||||
}
|
||||
if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg))
|
||||
i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1;
|
||||
|
||||
dev_dbg(&pdev->dev, "%s set to %d bytes\n", p,
|
||||
stm32h7_usart_fifo_thresh_cfg[i]);
|
||||
dev_dbg(&pdev->dev, "%s set to %d/%d bytes\n", p,
|
||||
stm32_usart_get_thresh_value(fifo_size, i), fifo_size);
|
||||
|
||||
/* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */
|
||||
if (i)
|
||||
*ftcfg = i - 1;
|
||||
else
|
||||
*ftcfg = -EINVAL;
|
||||
*ftcfg = i;
|
||||
return fifo_size;
|
||||
}
|
||||
|
||||
static void stm32_usart_deinit_port(struct stm32_port *stm32port)
|
||||
|
@ -1531,7 +1580,6 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
|
|||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->ops = &stm32_uart_ops;
|
||||
port->dev = &pdev->dev;
|
||||
port->fifosize = stm32port->info->cfg.fifosize;
|
||||
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE);
|
||||
port->irq = irq;
|
||||
port->rs485_config = stm32_usart_config_rs485;
|
||||
|
@ -1547,14 +1595,6 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
|
|||
stm32port->swap = stm32port->info->cfg.has_swap &&
|
||||
of_property_read_bool(pdev->dev.of_node, "rx-tx-swap");
|
||||
|
||||
stm32port->fifoen = stm32port->info->cfg.has_fifo;
|
||||
if (stm32port->fifoen) {
|
||||
stm32_usart_get_ftcfg(pdev, "rx-threshold",
|
||||
&stm32port->rxftcfg);
|
||||
stm32_usart_get_ftcfg(pdev, "tx-threshold",
|
||||
&stm32port->txftcfg);
|
||||
}
|
||||
|
||||
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(port->membase))
|
||||
return PTR_ERR(port->membase);
|
||||
|
@ -1577,6 +1617,15 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
|
|||
goto err_clk;
|
||||
}
|
||||
|
||||
stm32port->fifoen = stm32port->info->cfg.has_fifo;
|
||||
if (stm32port->fifoen) {
|
||||
stm32_usart_get_ftcfg(pdev, stm32port, "rx-threshold", &stm32port->rxftcfg);
|
||||
port->fifosize = stm32_usart_get_ftcfg(pdev, stm32port, "tx-threshold",
|
||||
&stm32port->txftcfg);
|
||||
} else {
|
||||
port->fifosize = 1;
|
||||
}
|
||||
|
||||
stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0);
|
||||
if (IS_ERR(stm32port->gpios)) {
|
||||
ret = PTR_ERR(stm32port->gpios);
|
||||
|
|
|
@ -9,17 +9,19 @@
|
|||
#define DRIVER_NAME "stm32-usart"
|
||||
|
||||
struct stm32_usart_offsets {
|
||||
u8 cr1;
|
||||
u8 cr2;
|
||||
u8 cr3;
|
||||
u8 brr;
|
||||
u8 gtpr;
|
||||
u8 rtor;
|
||||
u8 rqr;
|
||||
u8 isr;
|
||||
u8 icr;
|
||||
u8 rdr;
|
||||
u8 tdr;
|
||||
u16 cr1;
|
||||
u16 cr2;
|
||||
u16 cr3;
|
||||
u16 brr;
|
||||
u16 gtpr;
|
||||
u16 rtor;
|
||||
u16 rqr;
|
||||
u16 isr;
|
||||
u16 icr;
|
||||
u16 rdr;
|
||||
u16 tdr;
|
||||
u16 presc;
|
||||
u16 hwcfgr1;
|
||||
};
|
||||
|
||||
struct stm32_usart_config {
|
||||
|
@ -28,7 +30,6 @@ struct stm32_usart_config {
|
|||
bool has_swap;
|
||||
bool has_wakeup;
|
||||
bool has_fifo;
|
||||
int fifosize;
|
||||
};
|
||||
|
||||
struct stm32_usart_info {
|
||||
|
@ -36,7 +37,7 @@ struct stm32_usart_info {
|
|||
struct stm32_usart_config cfg;
|
||||
};
|
||||
|
||||
#define UNDEF_REG 0xff
|
||||
#define UNDEF_REG 0xffff
|
||||
|
||||
/* USART_SR (F4) / USART_ISR (F7) */
|
||||
#define USART_SR_PE BIT(0)
|
||||
|
@ -71,6 +72,7 @@ struct stm32_usart_info {
|
|||
#define USART_BRR_DIV_M_MASK GENMASK(15, 4)
|
||||
#define USART_BRR_DIV_M_SHIFT 4
|
||||
#define USART_BRR_04_R_SHIFT 1
|
||||
#define USART_BRR_MASK (USART_BRR_DIV_M_MASK | USART_BRR_DIV_F_MASK)
|
||||
|
||||
/* USART_CR1 */
|
||||
#define USART_CR1_SBK BIT(0)
|
||||
|
@ -176,8 +178,16 @@ struct stm32_usart_info {
|
|||
#define USART_ICR_CMCF BIT(17) /* F7 */
|
||||
#define USART_ICR_WUCF BIT(20) /* H7 */
|
||||
|
||||
/* USART_PRESC */
|
||||
#define USART_PRESC GENMASK(3, 0) /* H7 */
|
||||
#define USART_PRESC_MAX 0b1011
|
||||
|
||||
/* USART_HWCFCR1 */
|
||||
#define USART_HWCFGR1_CFG8 GENMASK(31, 28) /* MP1 */
|
||||
|
||||
#define STM32_SERIAL_NAME "ttySTM"
|
||||
#define STM32_MAX_PORTS 8
|
||||
#define STM32_MAX_PORTS 9
|
||||
#define STM32H7_USART_FIFO_SIZE 16
|
||||
|
||||
#define RX_BUF_L 4096 /* dma rx buffer length */
|
||||
#define RX_BUF_P (RX_BUF_L / 2) /* dma rx buffer period */
|
||||
|
|
|
@ -260,7 +260,7 @@ static void receive_chars(struct uart_port *port)
|
|||
if (port->ignore_status_mask & SUP_DUMMY_READ)
|
||||
goto ignore_char;
|
||||
|
||||
if (uart_handle_sysrq_char(port, ch))
|
||||
if (uart_prepare_sysrq_char(port, ch))
|
||||
goto ignore_char;
|
||||
|
||||
uart_insert_char(port, lsr, SUP_UART_LSR_OE, ch, flag);
|
||||
|
@ -287,7 +287,7 @@ static irqreturn_t sunplus_uart_irq(int irq, void *args)
|
|||
if (isc & SUP_UART_ISC_TX)
|
||||
transmit_chars(port);
|
||||
|
||||
uart_port_unlock(port);
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -512,22 +512,16 @@ static void sunplus_console_write(struct console *co,
|
|||
unsigned long flags;
|
||||
int locked = 1;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (sunplus_console_ports[co->index]->port.sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
locked = uart_port_trylock(&sunplus_console_ports[co->index]->port);
|
||||
if (oops_in_progress)
|
||||
locked = uart_port_trylock_irqsave(&sunplus_console_ports[co->index]->port, &flags);
|
||||
else
|
||||
uart_port_lock(&sunplus_console_ports[co->index]->port);
|
||||
uart_port_lock_irqsave(&sunplus_console_ports[co->index]->port, &flags);
|
||||
|
||||
uart_console_write(&sunplus_console_ports[co->index]->port, s, count,
|
||||
sunplus_uart_console_putchar);
|
||||
|
||||
if (locked)
|
||||
uart_port_unlock(&sunplus_console_ports[co->index]->port);
|
||||
|
||||
local_irq_restore(flags);
|
||||
uart_port_unlock_irqrestore(&sunplus_console_ports[co->index]->port, flags);
|
||||
}
|
||||
|
||||
static int __init sunplus_console_setup(struct console *co, char *options)
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define CDNS_UART_TTY_NAME "ttyPS"
|
||||
#define CDNS_UART_NAME "xuartps"
|
||||
|
@ -193,6 +195,9 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255");
|
|||
* @clk_rate_change_nb: Notifier block for clock changes
|
||||
* @quirks: Flags for RXBS support.
|
||||
* @cts_override: Modem control state override
|
||||
* @gpiod_rts: Pointer to the gpio descriptor
|
||||
* @rs485_tx_started: RS485 tx state
|
||||
* @tx_timer: Timer for tx
|
||||
*/
|
||||
struct cdns_uart {
|
||||
struct uart_port *port;
|
||||
|
@ -203,10 +208,21 @@ struct cdns_uart {
|
|||
struct notifier_block clk_rate_change_nb;
|
||||
u32 quirks;
|
||||
bool cts_override;
|
||||
struct gpio_desc *gpiod_rts;
|
||||
bool rs485_tx_started;
|
||||
struct hrtimer tx_timer;
|
||||
};
|
||||
struct cdns_platform_data {
|
||||
u32 quirks;
|
||||
};
|
||||
|
||||
struct serial_rs485 cdns_rs485_supported = {
|
||||
.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND |
|
||||
SER_RS485_RTS_AFTER_SEND,
|
||||
.delay_rts_before_send = 1,
|
||||
.delay_rts_after_send = 1,
|
||||
};
|
||||
|
||||
#define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \
|
||||
clk_rate_change_nb)
|
||||
|
||||
|
@ -306,17 +322,114 @@ static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus)
|
|||
}
|
||||
|
||||
/**
|
||||
* cdns_uart_handle_tx - Handle the bytes to be Txed.
|
||||
* cdns_rts_gpio_enable - Configure RTS/GPIO to high/low
|
||||
* @cdns_uart: Handle to the cdns_uart
|
||||
* @enable: Value to be set to RTS/GPIO
|
||||
*/
|
||||
static void cdns_rts_gpio_enable(struct cdns_uart *cdns_uart, bool enable)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (cdns_uart->gpiod_rts) {
|
||||
gpiod_set_value(cdns_uart->gpiod_rts, enable);
|
||||
} else {
|
||||
val = readl(cdns_uart->port->membase + CDNS_UART_MODEMCR);
|
||||
if (enable)
|
||||
val |= CDNS_UART_MODEMCR_RTS;
|
||||
else
|
||||
val &= ~CDNS_UART_MODEMCR_RTS;
|
||||
writel(val, cdns_uart->port->membase + CDNS_UART_MODEMCR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_rs485_tx_setup - Tx setup specific to rs485
|
||||
* @cdns_uart: Handle to the cdns_uart
|
||||
*/
|
||||
static void cdns_rs485_tx_setup(struct cdns_uart *cdns_uart)
|
||||
{
|
||||
bool enable;
|
||||
|
||||
enable = cdns_uart->port->rs485.flags & SER_RS485_RTS_ON_SEND;
|
||||
cdns_rts_gpio_enable(cdns_uart, enable);
|
||||
|
||||
cdns_uart->rs485_tx_started = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_rs485_rx_setup - Rx setup specific to rs485
|
||||
* @cdns_uart: Handle to the cdns_uart
|
||||
*/
|
||||
static void cdns_rs485_rx_setup(struct cdns_uart *cdns_uart)
|
||||
{
|
||||
bool enable;
|
||||
|
||||
enable = cdns_uart->port->rs485.flags & SER_RS485_RTS_AFTER_SEND;
|
||||
cdns_rts_gpio_enable(cdns_uart, enable);
|
||||
|
||||
cdns_uart->rs485_tx_started = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_uart_tx_empty - Check whether TX is empty
|
||||
* @port: Handle to the uart port structure
|
||||
*
|
||||
* Return: TIOCSER_TEMT on success, 0 otherwise
|
||||
*/
|
||||
static unsigned int cdns_uart_tx_empty(struct uart_port *port)
|
||||
{
|
||||
unsigned int status;
|
||||
|
||||
status = readl(port->membase + CDNS_UART_SR);
|
||||
status &= (CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE);
|
||||
return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_rs485_rx_callback - Timer rx callback handler for rs485.
|
||||
* @t: Handle to the hrtimer structure
|
||||
*/
|
||||
static enum hrtimer_restart cdns_rs485_rx_callback(struct hrtimer *t)
|
||||
{
|
||||
struct cdns_uart *cdns_uart = container_of(t, struct cdns_uart, tx_timer);
|
||||
|
||||
/*
|
||||
* Default Rx should be setup, because Rx signaling path
|
||||
* need to enable to receive data.
|
||||
*/
|
||||
cdns_rs485_rx_setup(cdns_uart);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_calc_after_tx_delay - calculate delay required for after tx.
|
||||
* @cdns_uart: Handle to the cdns_uart
|
||||
*/
|
||||
static u64 cdns_calc_after_tx_delay(struct cdns_uart *cdns_uart)
|
||||
{
|
||||
/*
|
||||
* Frame time + stop bit time + rs485.delay_rts_after_send
|
||||
*/
|
||||
return cdns_uart->port->frame_time
|
||||
+ DIV_ROUND_UP(cdns_uart->port->frame_time, 7)
|
||||
+ (u64)cdns_uart->port->rs485.delay_rts_after_send * NSEC_PER_MSEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_uart_handle_tx - Handle the bytes to be transmitted.
|
||||
* @dev_id: Id of the UART port
|
||||
* Return: None
|
||||
*/
|
||||
static void cdns_uart_handle_tx(void *dev_id)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *)dev_id;
|
||||
struct cdns_uart *cdns_uart = port->private_data;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
unsigned int numbytes;
|
||||
|
||||
if (uart_circ_empty(xmit)) {
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
/* Disable the TX Empty interrupt */
|
||||
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR);
|
||||
return;
|
||||
}
|
||||
|
@ -332,6 +445,16 @@ static void cdns_uart_handle_tx(void *dev_id)
|
|||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
/* Enable the TX Empty interrupt */
|
||||
writel(CDNS_UART_IXR_TXEMPTY, cdns_uart->port->membase + CDNS_UART_IER);
|
||||
|
||||
if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED &&
|
||||
(uart_circ_empty(xmit) || uart_tx_stopped(port))) {
|
||||
cdns_uart->tx_timer.function = &cdns_rs485_rx_callback;
|
||||
hrtimer_start(&cdns_uart->tx_timer,
|
||||
ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart)), HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -564,6 +687,21 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cdns_rs485_tx_callback - Timer tx callback handler for rs485.
|
||||
* @t: Handle to the hrtimer structure
|
||||
*/
|
||||
static enum hrtimer_restart cdns_rs485_tx_callback(struct hrtimer *t)
|
||||
{
|
||||
struct cdns_uart *cdns_uart = container_of(t, struct cdns_uart, tx_timer);
|
||||
|
||||
uart_port_lock(cdns_uart->port);
|
||||
cdns_uart_handle_tx(cdns_uart->port);
|
||||
uart_port_unlock(cdns_uart->port);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_uart_start_tx - Start transmitting bytes
|
||||
* @port: Handle to the uart port structure
|
||||
|
@ -571,6 +709,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
|
|||
static void cdns_uart_start_tx(struct uart_port *port)
|
||||
{
|
||||
unsigned int status;
|
||||
struct cdns_uart *cdns_uart = port->private_data;
|
||||
|
||||
if (uart_tx_stopped(port))
|
||||
return;
|
||||
|
@ -587,12 +726,19 @@ static void cdns_uart_start_tx(struct uart_port *port)
|
|||
if (uart_circ_empty(&port->state->xmit))
|
||||
return;
|
||||
|
||||
/* Clear the TX Empty interrupt */
|
||||
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR);
|
||||
|
||||
if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) {
|
||||
if (!cdns_uart->rs485_tx_started) {
|
||||
cdns_uart->tx_timer.function = &cdns_rs485_tx_callback;
|
||||
cdns_rs485_tx_setup(cdns_uart);
|
||||
return hrtimer_start(&cdns_uart->tx_timer,
|
||||
ms_to_ktime(port->rs485.delay_rts_before_send),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
cdns_uart_handle_tx(port);
|
||||
|
||||
/* Enable the TX Empty interrupt */
|
||||
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -602,6 +748,10 @@ static void cdns_uart_start_tx(struct uart_port *port)
|
|||
static void cdns_uart_stop_tx(struct uart_port *port)
|
||||
{
|
||||
unsigned int regval;
|
||||
struct cdns_uart *cdns_uart = port->private_data;
|
||||
|
||||
if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED)
|
||||
cdns_rs485_rx_setup(cdns_uart);
|
||||
|
||||
regval = readl(port->membase + CDNS_UART_CR);
|
||||
regval |= CDNS_UART_CR_TX_DIS;
|
||||
|
@ -626,21 +776,6 @@ static void cdns_uart_stop_rx(struct uart_port *port)
|
|||
writel(regval, port->membase + CDNS_UART_CR);
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_uart_tx_empty - Check whether TX is empty
|
||||
* @port: Handle to the uart port structure
|
||||
*
|
||||
* Return: TIOCSER_TEMT on success, 0 otherwise
|
||||
*/
|
||||
static unsigned int cdns_uart_tx_empty(struct uart_port *port)
|
||||
{
|
||||
unsigned int status;
|
||||
|
||||
status = readl(port->membase + CDNS_UART_SR) &
|
||||
(CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE);
|
||||
return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_uart_break_ctl - Based on the input ctl we have to start or stop
|
||||
* transmitting char breaks
|
||||
|
@ -829,6 +964,9 @@ static int cdns_uart_startup(struct uart_port *port)
|
|||
(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST))
|
||||
cpu_relax();
|
||||
|
||||
if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED)
|
||||
cdns_rs485_rx_setup(cdns_uart);
|
||||
|
||||
/*
|
||||
* Clear the RX disable bit and then set the RX enable bit to enable
|
||||
* the receiver.
|
||||
|
@ -888,6 +1026,10 @@ static void cdns_uart_shutdown(struct uart_port *port)
|
|||
{
|
||||
int status;
|
||||
unsigned long flags;
|
||||
struct cdns_uart *cdns_uart = port->private_data;
|
||||
|
||||
if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED)
|
||||
hrtimer_cancel(&cdns_uart->tx_timer);
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
|
@ -1033,6 +1175,8 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
val |= CDNS_UART_MODEMCR_RTS;
|
||||
if (cdns_uart_data->gpiod_rts)
|
||||
gpiod_set_value(cdns_uart_data->gpiod_rts, !(mctrl & TIOCM_RTS));
|
||||
if (mctrl & TIOCM_DTR)
|
||||
val |= CDNS_UART_MODEMCR_DTR;
|
||||
if (mctrl & TIOCM_LOOP)
|
||||
|
@ -1455,6 +1599,39 @@ MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
|
|||
/* Temporary variable for storing number of instances */
|
||||
static int instances;
|
||||
|
||||
/**
|
||||
* cdns_rs485_config - Called when an application calls TIOCSRS485 ioctl.
|
||||
* @port: Pointer to the uart_port structure
|
||||
* @termios: Pointer to the ktermios structure
|
||||
* @rs485: Pointer to the serial_rs485 structure
|
||||
*
|
||||
* Return: 0
|
||||
*/
|
||||
static int cdns_rs485_config(struct uart_port *port, struct ktermios *termios,
|
||||
struct serial_rs485 *rs485)
|
||||
{
|
||||
u32 val;
|
||||
struct cdns_uart *cdns_uart = port->private_data;
|
||||
|
||||
if (rs485->flags & SER_RS485_ENABLED) {
|
||||
dev_dbg(port->dev, "Setting UART to RS485\n");
|
||||
/* Make sure auto RTS is disabled */
|
||||
val = readl(port->membase + CDNS_UART_MODEMCR);
|
||||
val &= ~CDNS_UART_MODEMCR_FCM;
|
||||
writel(val, port->membase + CDNS_UART_MODEMCR);
|
||||
|
||||
/* Timer setup */
|
||||
hrtimer_init(&cdns_uart->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
cdns_uart->tx_timer.function = &cdns_rs485_tx_callback;
|
||||
|
||||
/* Disable transmitter and make Rx setup*/
|
||||
cdns_uart_stop_tx(port);
|
||||
} else {
|
||||
hrtimer_cancel(&cdns_uart->tx_timer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns_uart_probe - Platform driver probe
|
||||
* @pdev: Pointer to the platform device structure
|
||||
|
@ -1597,9 +1774,23 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
|||
port->private_data = cdns_uart_data;
|
||||
port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG |
|
||||
CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT;
|
||||
port->rs485_config = cdns_rs485_config;
|
||||
port->rs485_supported = cdns_rs485_supported;
|
||||
cdns_uart_data->port = port;
|
||||
platform_set_drvdata(pdev, port);
|
||||
|
||||
rc = uart_get_rs485_mode(port);
|
||||
if (rc)
|
||||
goto err_out_clk_notifier;
|
||||
|
||||
cdns_uart_data->gpiod_rts = devm_gpiod_get_optional(&pdev->dev, "rts",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(cdns_uart_data->gpiod_rts)) {
|
||||
rc = PTR_ERR(cdns_uart_data->gpiod_rts);
|
||||
dev_err(port->dev, "xuartps: devm_gpiod_get_optional failed\n");
|
||||
goto err_out_clk_notifier;
|
||||
}
|
||||
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
|
@ -1618,6 +1809,8 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
|||
console_port = port;
|
||||
}
|
||||
#endif
|
||||
if (cdns_uart_data->port->rs485.flags & SER_RS485_ENABLED)
|
||||
cdns_rs485_rx_setup(cdns_uart_data);
|
||||
|
||||
rc = uart_add_one_port(&cdns_uart_uart_driver, port);
|
||||
if (rc) {
|
||||
|
@ -1646,6 +1839,7 @@ err_out_pm_disable:
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
err_out_clk_notifier:
|
||||
#ifdef CONFIG_COMMON_CLK
|
||||
clk_notifier_unregister(cdns_uart_data->uartclk,
|
||||
&cdns_uart_data->clk_rate_change_nb);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_buffer.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/timer.h>
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
FONTMAPFILE = cp437.uni
|
||||
|
||||
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \
|
||||
selection.o keyboard.o
|
||||
selection.o keyboard.o \
|
||||
vt.o defkeymap.o
|
||||
obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
|
||||
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
clean-files := consolemap_deftbl.c defkeymap.c
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* 'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)'
|
||||
* 'void clear_selection(void)'
|
||||
* 'int paste_selection(struct tty_struct *)'
|
||||
* 'int sel_loadlut(char __user *)'
|
||||
* 'int sel_loadlut(u32 __user *)'
|
||||
*
|
||||
* Now that /dev/vcs exists, most of this can disappear again.
|
||||
*/
|
||||
|
@ -73,10 +73,12 @@ sel_pos(int n, bool unicode)
|
|||
}
|
||||
|
||||
/**
|
||||
* clear_selection - remove current selection
|
||||
* clear_selection - remove current selection
|
||||
*
|
||||
* Remove the current selection highlight, if any from the console
|
||||
* holding the selection. The caller must hold the console lock.
|
||||
* Remove the current selection highlight, if any from the console holding the
|
||||
* selection.
|
||||
*
|
||||
* Locking: The caller must hold the console lock.
|
||||
*/
|
||||
void clear_selection(void)
|
||||
{
|
||||
|
@ -88,7 +90,7 @@ void clear_selection(void)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(clear_selection);
|
||||
|
||||
bool vc_is_sel(struct vc_data *vc)
|
||||
bool vc_is_sel(const struct vc_data *vc)
|
||||
{
|
||||
return vc == vc_sel.cons;
|
||||
}
|
||||
|
@ -110,18 +112,25 @@ static inline int inword(const u32 c)
|
|||
}
|
||||
|
||||
/**
|
||||
* sel_loadlut() - load the LUT table
|
||||
* @p: user table
|
||||
* sel_loadlut() - load the LUT table
|
||||
* @lut: user table
|
||||
*
|
||||
* Load the LUT table from user space. The caller must hold the console
|
||||
* lock. Make a temporary copy so a partial update doesn't make a mess.
|
||||
* Load the LUT table from user space. Make a temporary copy so a partial
|
||||
* update doesn't make a mess.
|
||||
*
|
||||
* Locking: The console lock is acquired.
|
||||
*/
|
||||
int sel_loadlut(char __user *p)
|
||||
int sel_loadlut(u32 __user *lut)
|
||||
{
|
||||
u32 tmplut[ARRAY_SIZE(inwordLut)];
|
||||
if (copy_from_user(tmplut, (u32 __user *)(p+4), sizeof(inwordLut)))
|
||||
|
||||
if (copy_from_user(tmplut, lut, sizeof(inwordLut)))
|
||||
return -EFAULT;
|
||||
|
||||
console_lock();
|
||||
memcpy(inwordLut, tmplut, sizeof(inwordLut));
|
||||
console_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -166,14 +175,14 @@ static int store_utf8(u32 c, char *p)
|
|||
}
|
||||
|
||||
/**
|
||||
* set_selection_user - set the current selection.
|
||||
* @sel: user selection info
|
||||
* @tty: the console tty
|
||||
* set_selection_user - set the current selection.
|
||||
* @sel: user selection info
|
||||
* @tty: the console tty
|
||||
*
|
||||
* Invoked by the ioctl handle for the vt layer.
|
||||
* Invoked by the ioctl handle for the vt layer.
|
||||
*
|
||||
* The entire selection process is managed under the console_lock. It's
|
||||
* a lot under the lock but its hardly a performance path
|
||||
* Locking: The entire selection process is managed under the console_lock.
|
||||
* It's a lot under the lock but its hardly a performance path.
|
||||
*/
|
||||
int set_selection_user(const struct tiocl_selection __user *sel,
|
||||
struct tty_struct *tty)
|
||||
|
|
1531
drivers/tty/vt/vt.c
1531
drivers/tty/vt/vt.c
File diff suppressed because it is too large
Load Diff
|
@ -714,8 +714,7 @@ static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
|
|||
vcp->vc_scan_lines = v.v_vlin;
|
||||
if (v.v_clin)
|
||||
vcp->vc_cell_height = v.v_clin;
|
||||
vcp->vc_resize_user = 1;
|
||||
ret = vc_resize(vcp, v.v_cols, v.v_rows);
|
||||
ret = __vc_resize(vcp, v.v_cols, v.v_rows, true);
|
||||
if (ret) {
|
||||
vcp->vc_scan_lines = save_scan_lines;
|
||||
vcp->vc_cell_height = save_cell_height;
|
||||
|
@ -923,9 +922,8 @@ int vt_ioctl(struct tty_struct *tty,
|
|||
vc = vc_cons[i].d;
|
||||
|
||||
if (vc) {
|
||||
vc->vc_resize_user = 1;
|
||||
/* FIXME: review v tty lock */
|
||||
vc_resize(vc_cons[i].d, cc, ll);
|
||||
__vc_resize(vc_cons[i].d, cc, ll, true);
|
||||
}
|
||||
}
|
||||
console_unlock();
|
||||
|
|
|
@ -50,7 +50,8 @@ void dummycon_unregister_output_notifier(struct notifier_block *nb)
|
|||
raw_notifier_chain_unregister(&dummycon_output_nh, nb);
|
||||
}
|
||||
|
||||
static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos)
|
||||
static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y,
|
||||
unsigned int x)
|
||||
{
|
||||
WARN_CONSOLE_UNLOCKED();
|
||||
|
||||
|
@ -58,10 +59,10 @@ static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos)
|
|||
raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
|
||||
}
|
||||
|
||||
static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
|
||||
int count, int ypos, int xpos)
|
||||
static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
|
||||
unsigned int ypos, unsigned int xpos)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
if (!dummycon_putc_called) {
|
||||
/* Ignore erases */
|
||||
|
@ -78,18 +79,21 @@ static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
|
|||
raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
|
||||
}
|
||||
|
||||
static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch)
|
||||
static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
|
||||
bool mode_switch)
|
||||
{
|
||||
/* Redraw, so that we get putc(s) for output done while blanked */
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
|
||||
static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
|
||||
int count, int ypos, int xpos) { }
|
||||
static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch)
|
||||
static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y,
|
||||
unsigned int x) { }
|
||||
static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
|
||||
unsigned int ypos, unsigned int xpos) { }
|
||||
static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
|
||||
bool mode_switch)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -98,7 +102,7 @@ static const char *dummycon_startup(void)
|
|||
return "dummy device";
|
||||
}
|
||||
|
||||
static void dummycon_init(struct vc_data *vc, int init)
|
||||
static void dummycon_init(struct vc_data *vc, bool init)
|
||||
{
|
||||
vc->vc_can_do_color = 1;
|
||||
if (init) {
|
||||
|
@ -109,9 +113,9 @@ static void dummycon_init(struct vc_data *vc, int init)
|
|||
}
|
||||
|
||||
static void dummycon_deinit(struct vc_data *vc) { }
|
||||
static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height,
|
||||
int width) { }
|
||||
static void dummycon_cursor(struct vc_data *vc, int mode) { }
|
||||
static void dummycon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
|
||||
unsigned int width) { }
|
||||
static void dummycon_cursor(struct vc_data *vc, bool enable) { }
|
||||
|
||||
static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
|
||||
unsigned int bottom, enum con_scroll dir,
|
||||
|
@ -120,9 +124,9 @@ static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
|
|||
return false;
|
||||
}
|
||||
|
||||
static int dummycon_switch(struct vc_data *vc)
|
||||
static bool dummycon_switch(struct vc_data *vc)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -352,7 +352,7 @@ static const char *mdacon_startup(void)
|
|||
return "MDA-2";
|
||||
}
|
||||
|
||||
static void mdacon_init(struct vc_data *c, int init)
|
||||
static void mdacon_init(struct vc_data *c, bool init)
|
||||
{
|
||||
c->vc_complement_mask = 0x0800; /* reverse video */
|
||||
c->vc_display_fg = &mda_display_fg;
|
||||
|
@ -427,13 +427,8 @@ static inline u16 *mda_addr(unsigned int x, unsigned int y)
|
|||
return mda_vram_base + y * mda_num_columns + x;
|
||||
}
|
||||
|
||||
static void mdacon_putc(struct vc_data *c, int ch, int y, int x)
|
||||
{
|
||||
scr_writew(mda_convert_attr(ch), mda_addr(x, y));
|
||||
}
|
||||
|
||||
static void mdacon_putcs(struct vc_data *c, const unsigned short *s,
|
||||
int count, int y, int x)
|
||||
static void mdacon_putcs(struct vc_data *c, const u16 *s, unsigned int count,
|
||||
unsigned int y, unsigned int x)
|
||||
{
|
||||
u16 *dest = mda_addr(x, y);
|
||||
|
||||
|
@ -442,29 +437,22 @@ static void mdacon_putcs(struct vc_data *c, const unsigned short *s,
|
|||
}
|
||||
}
|
||||
|
||||
static void mdacon_clear(struct vc_data *c, int y, int x,
|
||||
int height, int width)
|
||||
static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x,
|
||||
unsigned int width)
|
||||
{
|
||||
u16 *dest = mda_addr(x, y);
|
||||
u16 eattr = mda_convert_attr(c->vc_video_erase_char);
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
if (x==0 && width==mda_num_columns) {
|
||||
scr_memsetw(dest, eattr, height*width*2);
|
||||
} else {
|
||||
for (; height > 0; height--, dest+=mda_num_columns)
|
||||
scr_memsetw(dest, eattr, width*2);
|
||||
}
|
||||
scr_memsetw(dest, eattr, width * 2);
|
||||
}
|
||||
|
||||
static int mdacon_switch(struct vc_data *c)
|
||||
|
||||
static bool mdacon_switch(struct vc_data *c)
|
||||
{
|
||||
return 1; /* redrawing needed */
|
||||
return true; /* redrawing needed */
|
||||
}
|
||||
|
||||
static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
static bool mdacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
|
||||
bool mode_switch)
|
||||
{
|
||||
if (mda_type == TYPE_MDA) {
|
||||
if (blank)
|
||||
|
@ -472,20 +460,20 @@ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
|
|||
mda_convert_attr(c->vc_video_erase_char),
|
||||
c->vc_screenbuf_size);
|
||||
/* Tell console.c that it has to restore the screen itself */
|
||||
return 1;
|
||||
return true;
|
||||
} else {
|
||||
if (blank)
|
||||
outb_p(0x00, mda_mode_port); /* disable video */
|
||||
else
|
||||
outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN,
|
||||
mda_mode_port);
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void mdacon_cursor(struct vc_data *c, int mode)
|
||||
static void mdacon_cursor(struct vc_data *c, bool enable)
|
||||
{
|
||||
if (mode == CM_ERASE) {
|
||||
if (!enable) {
|
||||
mda_set_cursor(mda_vram_len - 1);
|
||||
return;
|
||||
}
|
||||
|
@ -544,7 +532,6 @@ static const struct consw mda_con = {
|
|||
.con_init = mdacon_init,
|
||||
.con_deinit = mdacon_deinit,
|
||||
.con_clear = mdacon_clear,
|
||||
.con_putc = mdacon_putc,
|
||||
.con_putcs = mdacon_putcs,
|
||||
.con_cursor = mdacon_cursor,
|
||||
.con_scroll = mdacon_scroll,
|
||||
|
|
|
@ -324,7 +324,7 @@ out_unmap:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void newport_init(struct vc_data *vc, int init)
|
||||
static void newport_init(struct vc_data *vc, bool init)
|
||||
{
|
||||
int cols, rows;
|
||||
|
||||
|
@ -346,12 +346,12 @@ static void newport_deinit(struct vc_data *c)
|
|||
}
|
||||
}
|
||||
|
||||
static void newport_clear(struct vc_data *vc, int sy, int sx, int height,
|
||||
int width)
|
||||
static void newport_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
|
||||
unsigned int width)
|
||||
{
|
||||
int xend = ((sx + width) << 3) - 1;
|
||||
int ystart = ((sy << 4) + topscan) & 0x3ff;
|
||||
int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff;
|
||||
int yend = (((sy + 1) << 4) + topscan - 1) & 0x3ff;
|
||||
|
||||
if (logo_active)
|
||||
return;
|
||||
|
@ -367,8 +367,8 @@ static void newport_clear(struct vc_data *vc, int sy, int sx, int height,
|
|||
}
|
||||
}
|
||||
|
||||
static void newport_putc(struct vc_data *vc, int charattr, int ypos,
|
||||
int xpos)
|
||||
static void newport_putc(struct vc_data *vc, u16 charattr, unsigned int ypos,
|
||||
unsigned int xpos)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
|
@ -396,12 +396,13 @@ static void newport_putc(struct vc_data *vc, int charattr, int ypos,
|
|||
RENDER(npregs, p);
|
||||
}
|
||||
|
||||
static void newport_putcs(struct vc_data *vc, const unsigned short *s,
|
||||
int count, int ypos, int xpos)
|
||||
static void newport_putcs(struct vc_data *vc, const u16 *s,
|
||||
unsigned int count, unsigned int ypos,
|
||||
unsigned int xpos)
|
||||
{
|
||||
int i;
|
||||
int charattr;
|
||||
unsigned char *p;
|
||||
unsigned int i;
|
||||
u16 charattr;
|
||||
|
||||
charattr = (scr_readw(s) >> 8) & 0xff;
|
||||
|
||||
|
@ -437,32 +438,28 @@ static void newport_putcs(struct vc_data *vc, const unsigned short *s,
|
|||
}
|
||||
}
|
||||
|
||||
static void newport_cursor(struct vc_data *vc, int mode)
|
||||
static void newport_cursor(struct vc_data *vc, bool enable)
|
||||
{
|
||||
unsigned short treg;
|
||||
int xcurs, ycurs;
|
||||
|
||||
switch (mode) {
|
||||
case CM_ERASE:
|
||||
treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
|
||||
treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
|
||||
|
||||
if (!enable) {
|
||||
newport_vc2_set(npregs, VC2_IREG_CONTROL,
|
||||
(treg & ~(VC2_CTRL_ECDISP)));
|
||||
break;
|
||||
|
||||
case CM_MOVE:
|
||||
case CM_DRAW:
|
||||
treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
|
||||
newport_vc2_set(npregs, VC2_IREG_CONTROL,
|
||||
(treg | VC2_CTRL_ECDISP));
|
||||
xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2;
|
||||
ycurs = ((xcurs / vc->vc_cols) << 4) + 31;
|
||||
xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction;
|
||||
newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs);
|
||||
newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs);
|
||||
return;
|
||||
}
|
||||
|
||||
newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP));
|
||||
xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2;
|
||||
ycurs = ((xcurs / vc->vc_cols) << 4) + 31;
|
||||
xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction;
|
||||
newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs);
|
||||
newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs);
|
||||
}
|
||||
|
||||
static int newport_switch(struct vc_data *vc)
|
||||
static bool newport_switch(struct vc_data *vc)
|
||||
{
|
||||
static int logo_drawn = 0;
|
||||
|
||||
|
@ -476,14 +473,15 @@ static int newport_switch(struct vc_data *vc)
|
|||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int newport_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank,
|
||||
bool mode_switch)
|
||||
{
|
||||
unsigned short treg;
|
||||
|
||||
if (blank == 0) {
|
||||
if (blank == VESA_NO_BLANKING) {
|
||||
/* unblank console */
|
||||
treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
|
||||
newport_vc2_set(npregs, VC2_IREG_CONTROL,
|
||||
|
@ -494,10 +492,12 @@ static int newport_blank(struct vc_data *c, int blank, int mode_switch)
|
|||
newport_vc2_set(npregs, VC2_IREG_CONTROL,
|
||||
(treg & ~(VC2_CTRL_EDISP)));
|
||||
}
|
||||
return 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int newport_set_font(int unit, struct console_font *op, unsigned int vpitch)
|
||||
static int newport_set_font(int unit, const struct console_font *op,
|
||||
unsigned int vpitch)
|
||||
{
|
||||
int w = op->width;
|
||||
int h = op->height;
|
||||
|
@ -564,12 +564,13 @@ static int newport_set_def_font(int unit, struct console_font *op)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int newport_font_default(struct vc_data *vc, struct console_font *op, char *name)
|
||||
static int newport_font_default(struct vc_data *vc, struct console_font *op,
|
||||
const char *name)
|
||||
{
|
||||
return newport_set_def_font(vc->vc_num, op);
|
||||
}
|
||||
|
||||
static int newport_font_set(struct vc_data *vc, struct console_font *font,
|
||||
static int newport_font_set(struct vc_data *vc, const struct console_font *font,
|
||||
unsigned int vpitch, unsigned int flags)
|
||||
{
|
||||
return newport_set_font(vc->vc_num, font, vpitch);
|
||||
|
|
|
@ -71,19 +71,8 @@ static const char *sticon_startup(void)
|
|||
return "STI console";
|
||||
}
|
||||
|
||||
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
|
||||
{
|
||||
if (vga_is_gfx || console_blanked)
|
||||
return;
|
||||
|
||||
if (conp->vc_mode != KD_TEXT)
|
||||
return;
|
||||
|
||||
sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]);
|
||||
}
|
||||
|
||||
static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
|
||||
int count, int ypos, int xpos)
|
||||
static void sticon_putcs(struct vc_data *conp, const u16 *s, unsigned int count,
|
||||
unsigned int ypos, unsigned int xpos)
|
||||
{
|
||||
if (vga_is_gfx || console_blanked)
|
||||
return;
|
||||
|
@ -97,7 +86,7 @@ static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
|
|||
}
|
||||
}
|
||||
|
||||
static void sticon_cursor(struct vc_data *conp, int mode)
|
||||
static void sticon_cursor(struct vc_data *conp, bool enable)
|
||||
{
|
||||
unsigned short car1;
|
||||
|
||||
|
@ -106,23 +95,20 @@ static void sticon_cursor(struct vc_data *conp, int mode)
|
|||
return;
|
||||
|
||||
car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
|
||||
switch (mode) {
|
||||
case CM_ERASE:
|
||||
if (!enable) {
|
||||
sti_putc(sticon_sti, car1, conp->state.y, conp->state.x,
|
||||
font_data[conp->vc_num]);
|
||||
break;
|
||||
case CM_MOVE:
|
||||
case CM_DRAW:
|
||||
switch (CUR_SIZE(conp->vc_cursor_type)) {
|
||||
case CUR_UNDERLINE:
|
||||
case CUR_LOWER_THIRD:
|
||||
case CUR_LOWER_HALF:
|
||||
case CUR_TWO_THIRDS:
|
||||
case CUR_BLOCK:
|
||||
sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
|
||||
conp->state.y, conp->state.x, font_data[conp->vc_num]);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (CUR_SIZE(conp->vc_cursor_type)) {
|
||||
case CUR_UNDERLINE:
|
||||
case CUR_LOWER_THIRD:
|
||||
case CUR_LOWER_HALF:
|
||||
case CUR_TWO_THIRDS:
|
||||
case CUR_BLOCK:
|
||||
sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
|
||||
conp->state.y, conp->state.x, font_data[conp->vc_num]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +121,7 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t,
|
|||
if (vga_is_gfx)
|
||||
return false;
|
||||
|
||||
sticon_cursor(conp, CM_ERASE);
|
||||
sticon_cursor(conp, false);
|
||||
|
||||
switch (dir) {
|
||||
case SM_UP:
|
||||
|
@ -167,7 +153,7 @@ static void sticon_set_def_font(int unit)
|
|||
}
|
||||
}
|
||||
|
||||
static int sticon_set_font(struct vc_data *vc, struct console_font *op,
|
||||
static int sticon_set_font(struct vc_data *vc, const struct console_font *op,
|
||||
unsigned int vpitch)
|
||||
{
|
||||
struct sti_struct *sti = sticon_sti;
|
||||
|
@ -260,20 +246,21 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name)
|
||||
static int sticon_font_default(struct vc_data *vc, struct console_font *op,
|
||||
const char *name)
|
||||
{
|
||||
sticon_set_def_font(vc->vc_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sticon_font_set(struct vc_data *vc, struct console_font *font,
|
||||
static int sticon_font_set(struct vc_data *vc, const struct console_font *font,
|
||||
unsigned int vpitch, unsigned int flags)
|
||||
{
|
||||
return sticon_set_font(vc, font, vpitch);
|
||||
}
|
||||
|
||||
static void sticon_init(struct vc_data *c, int init)
|
||||
static void sticon_init(struct vc_data *c, bool init)
|
||||
{
|
||||
struct sti_struct *sti = sticon_sti;
|
||||
int vc_cols, vc_rows;
|
||||
|
@ -300,33 +287,32 @@ static void sticon_deinit(struct vc_data *c)
|
|||
sticon_set_def_font(i);
|
||||
}
|
||||
|
||||
static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
|
||||
int width)
|
||||
static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx,
|
||||
unsigned int width)
|
||||
{
|
||||
if (!height || !width)
|
||||
return;
|
||||
|
||||
sti_clear(sticon_sti, sy, sx, height, width,
|
||||
sti_clear(sticon_sti, sy, sx, 1, width,
|
||||
conp->vc_video_erase_char, font_data[conp->vc_num]);
|
||||
}
|
||||
|
||||
static int sticon_switch(struct vc_data *conp)
|
||||
static bool sticon_switch(struct vc_data *conp)
|
||||
{
|
||||
return 1; /* needs refreshing */
|
||||
return true; /* needs refreshing */
|
||||
}
|
||||
|
||||
static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank,
|
||||
bool mode_switch)
|
||||
{
|
||||
if (blank == 0) {
|
||||
if (blank == VESA_NO_BLANKING) {
|
||||
if (mode_switch)
|
||||
vga_is_gfx = 0;
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK,
|
||||
font_data[c->vc_num]);
|
||||
if (mode_switch)
|
||||
vga_is_gfx = 1;
|
||||
return 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u8 sticon_build_attr(struct vc_data *conp, u8 color,
|
||||
|
@ -365,7 +351,6 @@ static const struct consw sti_con = {
|
|||
.con_init = sticon_init,
|
||||
.con_deinit = sticon_deinit,
|
||||
.con_clear = sticon_clear,
|
||||
.con_putc = sticon_putc,
|
||||
.con_putcs = sticon_putcs,
|
||||
.con_cursor = sticon_cursor,
|
||||
.con_scroll = sticon_scroll,
|
||||
|
|
|
@ -65,7 +65,7 @@ static struct vgastate vgastate;
|
|||
* Interface used by the world
|
||||
*/
|
||||
|
||||
static int vgacon_set_origin(struct vc_data *c);
|
||||
static bool vgacon_set_origin(struct vc_data *c);
|
||||
|
||||
static struct uni_pagedict *vgacon_uni_pagedir;
|
||||
static int vgacon_refcount;
|
||||
|
@ -81,7 +81,7 @@ static unsigned int vga_video_num_lines; /* Number of text lines */
|
|||
static bool vga_can_do_color; /* Do we support colors? */
|
||||
static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */
|
||||
static unsigned char vga_video_type __read_mostly; /* Card type */
|
||||
static int vga_vesa_blanked;
|
||||
static enum vesa_blank_mode vga_vesa_blanked;
|
||||
static bool vga_palette_blanked;
|
||||
static bool vga_is_gfx;
|
||||
static bool vga_512_chars;
|
||||
|
@ -138,8 +138,40 @@ static inline void vga_set_mem_top(struct vc_data *c)
|
|||
|
||||
static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||
{
|
||||
vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
|
||||
vga_vram_size);
|
||||
unsigned long scr_end = c->vc_scr_end - vga_vram_base;
|
||||
unsigned long vorigin = c->vc_visible_origin - vga_vram_base;
|
||||
unsigned long origin = c->vc_origin - vga_vram_base;
|
||||
int margin = c->vc_size_row * 4;
|
||||
int from, wrap, from_off, avail;
|
||||
|
||||
/* Turn scrollback off */
|
||||
if (!lines) {
|
||||
c->vc_visible_origin = c->vc_origin;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do we have already enough to allow jumping from 0 to the end? */
|
||||
if (vga_rolled_over > scr_end + margin) {
|
||||
from = scr_end;
|
||||
wrap = vga_rolled_over + c->vc_size_row;
|
||||
} else {
|
||||
from = 0;
|
||||
wrap = vga_vram_size;
|
||||
}
|
||||
|
||||
from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row;
|
||||
avail = (origin - from + wrap) % wrap;
|
||||
|
||||
/* Only a little piece would be left? Show all incl. the piece! */
|
||||
if (avail < 2 * margin)
|
||||
margin = 0;
|
||||
if (from_off < margin)
|
||||
from_off = 0;
|
||||
if (from_off > avail - margin)
|
||||
from_off = avail;
|
||||
|
||||
c->vc_visible_origin = vga_vram_base + (from + from_off) % wrap;
|
||||
|
||||
vga_set_mem_top(c);
|
||||
}
|
||||
|
||||
|
@ -335,7 +367,7 @@ static const char *vgacon_startup(void)
|
|||
return display_desc;
|
||||
}
|
||||
|
||||
static void vgacon_init(struct vc_data *c, int init)
|
||||
static void vgacon_init(struct vc_data *c, bool init)
|
||||
{
|
||||
struct uni_pagedict *p;
|
||||
|
||||
|
@ -352,7 +384,7 @@ static void vgacon_init(struct vc_data *c, int init)
|
|||
c->vc_scan_lines = vga_scan_lines;
|
||||
c->vc_font.height = c->vc_cell_height = vga_video_font_height;
|
||||
|
||||
/* set dimensions manually if init != 0 since vc_resize() will fail */
|
||||
/* set dimensions manually if init is true since vc_resize() will fail */
|
||||
if (init) {
|
||||
c->vc_cols = vga_video_num_columns;
|
||||
c->vc_rows = vga_video_num_lines;
|
||||
|
@ -471,7 +503,7 @@ static void vgacon_set_cursor_size(int from, int to)
|
|||
raw_spin_unlock_irqrestore(&vga_lock, flags);
|
||||
}
|
||||
|
||||
static void vgacon_cursor(struct vc_data *c, int mode)
|
||||
static void vgacon_cursor(struct vc_data *c, bool enable)
|
||||
{
|
||||
unsigned int c_height;
|
||||
|
||||
|
@ -482,47 +514,41 @@ static void vgacon_cursor(struct vc_data *c, int mode)
|
|||
|
||||
c_height = c->vc_cell_height;
|
||||
|
||||
switch (mode) {
|
||||
case CM_ERASE:
|
||||
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
|
||||
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
|
||||
|
||||
if (!enable) {
|
||||
if (vga_video_type >= VIDEO_TYPE_VGAC)
|
||||
vgacon_set_cursor_size(31, 30);
|
||||
else
|
||||
vgacon_set_cursor_size(31, 31);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
case CM_MOVE:
|
||||
case CM_DRAW:
|
||||
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
|
||||
switch (CUR_SIZE(c->vc_cursor_type)) {
|
||||
case CUR_UNDERLINE:
|
||||
vgacon_set_cursor_size(c_height -
|
||||
(c_height < 10 ? 2 : 3),
|
||||
c_height -
|
||||
(c_height < 10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_TWO_THIRDS:
|
||||
vgacon_set_cursor_size(c_height / 3, c_height -
|
||||
(c_height < 10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_LOWER_THIRD:
|
||||
vgacon_set_cursor_size(c_height * 2 / 3, c_height -
|
||||
(c_height < 10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_LOWER_HALF:
|
||||
vgacon_set_cursor_size(c_height / 2, c_height -
|
||||
(c_height < 10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_NONE:
|
||||
if (vga_video_type >= VIDEO_TYPE_VGAC)
|
||||
vgacon_set_cursor_size(31, 30);
|
||||
else
|
||||
vgacon_set_cursor_size(31, 31);
|
||||
break;
|
||||
default:
|
||||
vgacon_set_cursor_size(1, c_height);
|
||||
break;
|
||||
}
|
||||
switch (CUR_SIZE(c->vc_cursor_type)) {
|
||||
case CUR_UNDERLINE:
|
||||
vgacon_set_cursor_size(c_height - (c_height < 10 ? 2 : 3),
|
||||
c_height - (c_height < 10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_TWO_THIRDS:
|
||||
vgacon_set_cursor_size(c_height / 3,
|
||||
c_height - (c_height < 10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_LOWER_THIRD:
|
||||
vgacon_set_cursor_size(c_height * 2 / 3,
|
||||
c_height - (c_height < 10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_LOWER_HALF:
|
||||
vgacon_set_cursor_size(c_height / 2,
|
||||
c_height - (c_height < 10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_NONE:
|
||||
if (vga_video_type >= VIDEO_TYPE_VGAC)
|
||||
vgacon_set_cursor_size(31, 30);
|
||||
else
|
||||
vgacon_set_cursor_size(31, 31);
|
||||
break;
|
||||
default:
|
||||
vgacon_set_cursor_size(1, c_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -588,7 +614,7 @@ static void vgacon_doresize(struct vc_data *c,
|
|||
raw_spin_unlock_irqrestore(&vga_lock, flags);
|
||||
}
|
||||
|
||||
static int vgacon_switch(struct vc_data *c)
|
||||
static bool vgacon_switch(struct vc_data *c)
|
||||
{
|
||||
int x = c->vc_cols * VGA_FONTWIDTH;
|
||||
int y = c->vc_rows * c->vc_cell_height;
|
||||
|
@ -617,7 +643,7 @@ static int vgacon_switch(struct vc_data *c)
|
|||
vgacon_doresize(c, c->vc_cols, c->vc_rows);
|
||||
}
|
||||
|
||||
return 0; /* Redrawing not needed */
|
||||
return false; /* Redrawing not needed */
|
||||
}
|
||||
|
||||
static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
|
||||
|
@ -657,7 +683,7 @@ static struct {
|
|||
unsigned char ClockingMode; /* Seq-Controller:01h */
|
||||
} vga_state;
|
||||
|
||||
static void vga_vesa_blank(struct vgastate *state, int mode)
|
||||
static void vga_vesa_blank(struct vgastate *state, enum vesa_blank_mode mode)
|
||||
{
|
||||
/* save original values of VGA controller registers */
|
||||
if (!vga_vesa_blanked) {
|
||||
|
@ -771,13 +797,14 @@ static void vga_pal_blank(struct vgastate *state)
|
|||
}
|
||||
}
|
||||
|
||||
static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
|
||||
bool mode_switch)
|
||||
{
|
||||
switch (blank) {
|
||||
case 0: /* Unblank */
|
||||
case VESA_NO_BLANKING: /* Unblank */
|
||||
if (vga_vesa_blanked) {
|
||||
vga_vesa_unblank(&vgastate);
|
||||
vga_vesa_blanked = 0;
|
||||
vga_vesa_blanked = VESA_NO_BLANKING;
|
||||
}
|
||||
if (vga_palette_blanked) {
|
||||
vga_set_palette(c, color_table);
|
||||
|
@ -787,8 +814,7 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
|
|||
vga_is_gfx = false;
|
||||
/* Tell console.c that it has to restore the screen itself */
|
||||
return 1;
|
||||
case 1: /* Normal blanking */
|
||||
case -1: /* Obsolete */
|
||||
case VESA_VSYNC_SUSPEND: /* Normal blanking */
|
||||
if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
|
||||
vga_pal_blank(&vgastate);
|
||||
vga_palette_blanked = true;
|
||||
|
@ -1004,7 +1030,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
|
|||
/* void size to cause regs to be rewritten */
|
||||
cursor_size_lastfrom = 0;
|
||||
cursor_size_lastto = 0;
|
||||
c->vc_sw->con_cursor(c, CM_DRAW);
|
||||
c->vc_sw->con_cursor(c, true);
|
||||
}
|
||||
c->vc_font.height = c->vc_cell_height = fontheight;
|
||||
vc_resize(c, 0, rows); /* Adjust console size */
|
||||
|
@ -1013,7 +1039,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vgacon_font_set(struct vc_data *c, struct console_font *font,
|
||||
static int vgacon_font_set(struct vc_data *c, const struct console_font *font,
|
||||
unsigned int vpitch, unsigned int flags)
|
||||
{
|
||||
unsigned charcount = font->charcount;
|
||||
|
@ -1049,12 +1075,12 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font, unsigne
|
|||
}
|
||||
|
||||
static int vgacon_resize(struct vc_data *c, unsigned int width,
|
||||
unsigned int height, unsigned int user)
|
||||
unsigned int height, bool from_user)
|
||||
{
|
||||
if ((width << 1) * height > vga_vram_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (user) {
|
||||
if (from_user) {
|
||||
/*
|
||||
* Ho ho! Someone (svgatextmode, eh?) may have reprogrammed
|
||||
* the video mode! Set the new defaults then and go away.
|
||||
|
@ -1074,15 +1100,15 @@ static int vgacon_resize(struct vc_data *c, unsigned int width,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vgacon_set_origin(struct vc_data *c)
|
||||
static bool vgacon_set_origin(struct vc_data *c)
|
||||
{
|
||||
if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
|
||||
(console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */
|
||||
return 0;
|
||||
return false;
|
||||
c->vc_origin = c->vc_visible_origin = vga_vram_base;
|
||||
vga_set_mem_top(c);
|
||||
vga_rolled_over = 0;
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vgacon_save_screen(struct vc_data *c)
|
||||
|
@ -1159,11 +1185,10 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
|
|||
* The console `switch' structure for the VGA based console
|
||||
*/
|
||||
|
||||
static void vgacon_clear(struct vc_data *vc, int sy, int sx, int height,
|
||||
int width) { }
|
||||
static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
|
||||
static void vgacon_putcs(struct vc_data *vc, const unsigned short *s,
|
||||
int count, int ypos, int xpos) { }
|
||||
static void vgacon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
|
||||
unsigned int width) { }
|
||||
static void vgacon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
|
||||
unsigned int ypos, unsigned int xpos) { }
|
||||
|
||||
const struct consw vga_con = {
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -1171,7 +1196,6 @@ const struct consw vga_con = {
|
|||
.con_init = vgacon_init,
|
||||
.con_deinit = vgacon_deinit,
|
||||
.con_clear = vgacon_clear,
|
||||
.con_putc = vgacon_putc,
|
||||
.con_putcs = vgacon_putcs,
|
||||
.con_cursor = vgacon_cursor,
|
||||
.con_scroll = vgacon_scroll,
|
||||
|
|
|
@ -233,7 +233,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
}
|
||||
}
|
||||
|
||||
static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
|
||||
int fg, int bg)
|
||||
{
|
||||
struct fb_cursor cursor;
|
||||
|
@ -348,16 +348,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
mask[i++] = msk;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CM_ERASE:
|
||||
ops->cursor_state.enable = 0;
|
||||
break;
|
||||
case CM_DRAW:
|
||||
case CM_MOVE:
|
||||
default:
|
||||
ops->cursor_state.enable = (use_sw) ? 0 : 1;
|
||||
break;
|
||||
}
|
||||
ops->cursor_state.enable = enable && !use_sw;
|
||||
|
||||
cursor.image.data = src;
|
||||
cursor.image.fg_color = ops->cursor_state.image.fg_color;
|
||||
|
|
|
@ -351,7 +351,7 @@ static void fb_flashcursor(struct work_struct *work)
|
|||
struct fb_info *info;
|
||||
struct vc_data *vc = NULL;
|
||||
int c;
|
||||
int mode;
|
||||
bool enable;
|
||||
int ret;
|
||||
|
||||
/* FIXME: we should sort out the unbind locking instead */
|
||||
|
@ -375,9 +375,8 @@ static void fb_flashcursor(struct work_struct *work)
|
|||
}
|
||||
|
||||
c = scr_readw((u16 *) vc->vc_pos);
|
||||
mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
|
||||
CM_ERASE : CM_DRAW;
|
||||
ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
|
||||
enable = ops->cursor_flash && !ops->cursor_state.enable;
|
||||
ops->cursor(vc, info, enable, get_color(vc, info, c, 1),
|
||||
get_color(vc, info, c, 0));
|
||||
console_unlock();
|
||||
|
||||
|
@ -920,7 +919,7 @@ static void display_to_var(struct fb_var_screeninfo *var,
|
|||
|
||||
static const char *fbcon_startup(void)
|
||||
{
|
||||
const char *display_desc = "frame buffer device";
|
||||
static const char display_desc[] = "frame buffer device";
|
||||
struct fbcon_display *p = &fb_display[fg_console];
|
||||
struct vc_data *vc = vc_cons[fg_console].d;
|
||||
const struct font_desc *font = NULL;
|
||||
|
@ -987,7 +986,7 @@ static const char *fbcon_startup(void)
|
|||
return display_desc;
|
||||
}
|
||||
|
||||
static void fbcon_init(struct vc_data *vc, int init)
|
||||
static void fbcon_init(struct vc_data *vc, bool init)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct fbcon_ops *ops;
|
||||
|
@ -1234,8 +1233,8 @@ finished:
|
|||
* restriction is simplicity & efficiency at the moment.
|
||||
*/
|
||||
|
||||
static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
|
||||
int width)
|
||||
static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
|
||||
unsigned int height, unsigned int width)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
@ -1272,8 +1271,14 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
|
|||
ops->clear(vc, info, real_y(p, sy), sx, height, width);
|
||||
}
|
||||
|
||||
static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
|
||||
int count, int ypos, int xpos)
|
||||
static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
|
||||
unsigned int width)
|
||||
{
|
||||
__fbcon_clear(vc, sy, sx, 1, width);
|
||||
}
|
||||
|
||||
static void fbcon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
|
||||
unsigned int ypos, unsigned int xpos)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
struct fbcon_display *p = &fb_display[vc->vc_num];
|
||||
|
@ -1285,14 +1290,6 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
|
|||
get_color(vc, info, scr_readw(s), 0));
|
||||
}
|
||||
|
||||
static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
|
||||
{
|
||||
unsigned short chr;
|
||||
|
||||
scr_writew(c, &chr);
|
||||
fbcon_putcs(vc, &chr, 1, ypos, xpos);
|
||||
}
|
||||
|
||||
static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
|
@ -1302,7 +1299,7 @@ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
|
|||
ops->clear_margins(vc, info, margin_color, bottom_only);
|
||||
}
|
||||
|
||||
static void fbcon_cursor(struct vc_data *vc, int mode)
|
||||
static void fbcon_cursor(struct vc_data *vc, bool enable)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
@ -1318,12 +1315,12 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
|
|||
else
|
||||
fbcon_add_cursor_work(info);
|
||||
|
||||
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
|
||||
ops->cursor_flash = enable;
|
||||
|
||||
if (!ops->cursor)
|
||||
return;
|
||||
|
||||
ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
|
||||
ops->cursor(vc, info, enable, get_color(vc, info, c, 1),
|
||||
get_color(vc, info, c, 0));
|
||||
}
|
||||
|
||||
|
@ -1743,7 +1740,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
if (fbcon_is_inactive(vc, info))
|
||||
return true;
|
||||
|
||||
fbcon_cursor(vc, CM_ERASE);
|
||||
fbcon_cursor(vc, false);
|
||||
|
||||
/*
|
||||
* ++Geert: Only use ywrap/ypan if the console is in text mode
|
||||
|
@ -1759,7 +1756,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
case SCROLL_MOVE:
|
||||
fbcon_redraw_blit(vc, info, p, t, b - t - count,
|
||||
count);
|
||||
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
scr_memsetw((unsigned short *) (vc->vc_origin +
|
||||
vc->vc_size_row *
|
||||
(b - count)),
|
||||
|
@ -1782,7 +1779,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
b - t - count, vc->vc_cols);
|
||||
else
|
||||
goto redraw_up;
|
||||
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
break;
|
||||
|
||||
case SCROLL_PAN_REDRAW:
|
||||
|
@ -1800,7 +1797,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
vc->vc_rows - b, b);
|
||||
} else
|
||||
fbcon_redraw_move(vc, p, t + count, b - t - count, t);
|
||||
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
break;
|
||||
|
||||
case SCROLL_PAN_MOVE:
|
||||
|
@ -1823,14 +1820,14 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
b - t - count, vc->vc_cols);
|
||||
else
|
||||
goto redraw_up;
|
||||
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
break;
|
||||
|
||||
case SCROLL_REDRAW:
|
||||
redraw_up:
|
||||
fbcon_redraw(vc, t, b - t - count,
|
||||
count * vc->vc_cols);
|
||||
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
|
||||
scr_memsetw((unsigned short *) (vc->vc_origin +
|
||||
vc->vc_size_row *
|
||||
(b - count)),
|
||||
|
@ -1847,7 +1844,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
case SCROLL_MOVE:
|
||||
fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
|
||||
-count);
|
||||
fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
scr_memsetw((unsigned short *) (vc->vc_origin +
|
||||
vc->vc_size_row *
|
||||
t),
|
||||
|
@ -1870,7 +1867,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
b - t - count, vc->vc_cols);
|
||||
else
|
||||
goto redraw_down;
|
||||
fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
break;
|
||||
|
||||
case SCROLL_PAN_MOVE:
|
||||
|
@ -1892,7 +1889,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
b - t - count, vc->vc_cols);
|
||||
else
|
||||
goto redraw_down;
|
||||
fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
break;
|
||||
|
||||
case SCROLL_PAN_REDRAW:
|
||||
|
@ -1909,14 +1906,14 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
fbcon_redraw_move(vc, p, count, t, 0);
|
||||
} else
|
||||
fbcon_redraw_move(vc, p, t, b - t - count, t + count);
|
||||
fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
break;
|
||||
|
||||
case SCROLL_REDRAW:
|
||||
redraw_down:
|
||||
fbcon_redraw(vc, b - 1, b - t - count,
|
||||
-count * vc->vc_cols);
|
||||
fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
__fbcon_clear(vc, t, 0, count, vc->vc_cols);
|
||||
scr_memsetw((unsigned short *) (vc->vc_origin +
|
||||
vc->vc_size_row *
|
||||
t),
|
||||
|
@ -1995,7 +1992,7 @@ static void updatescrollmode(struct fbcon_display *p,
|
|||
#define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */
|
||||
|
||||
static int fbcon_resize(struct vc_data *vc, unsigned int width,
|
||||
unsigned int height, unsigned int user)
|
||||
unsigned int height, bool from_user)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
@ -2058,7 +2055,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fbcon_switch(struct vc_data *vc)
|
||||
static bool fbcon_switch(struct vc_data *vc)
|
||||
{
|
||||
struct fb_info *info, *old_info = NULL;
|
||||
struct fbcon_ops *ops;
|
||||
|
@ -2180,9 +2177,9 @@ static int fbcon_switch(struct vc_data *vc)
|
|||
vc->vc_origin + vc->vc_size_row * vc->vc_top,
|
||||
vc->vc_size_row * (vc->vc_bottom -
|
||||
vc->vc_top) / 2);
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
|
||||
|
@ -2195,12 +2192,13 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
|
|||
|
||||
oldc = vc->vc_video_erase_char;
|
||||
vc->vc_video_erase_char &= charmask;
|
||||
fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
|
||||
__fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
|
||||
vc->vc_video_erase_char = oldc;
|
||||
}
|
||||
}
|
||||
|
||||
static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
|
||||
static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
|
||||
bool mode_switch)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
@ -2222,7 +2220,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
|
|||
if (!fbcon_is_inactive(vc, info)) {
|
||||
if (ops->blank_state != blank) {
|
||||
ops->blank_state = blank;
|
||||
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
|
||||
fbcon_cursor(vc, !blank);
|
||||
ops->cursor_flash = (!blank);
|
||||
|
||||
if (fb_blank(info, blank))
|
||||
|
@ -2239,10 +2237,10 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
|
|||
else
|
||||
fbcon_add_cursor_work(info);
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int fbcon_debug_enter(struct vc_data *vc)
|
||||
static void fbcon_debug_enter(struct vc_data *vc)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
@ -2252,10 +2250,9 @@ static int fbcon_debug_enter(struct vc_data *vc)
|
|||
if (info->fbops->fb_debug_enter)
|
||||
info->fbops->fb_debug_enter(info);
|
||||
fbcon_set_palette(vc, color_table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fbcon_debug_leave(struct vc_data *vc)
|
||||
static void fbcon_debug_leave(struct vc_data *vc)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
@ -2263,7 +2260,6 @@ static int fbcon_debug_leave(struct vc_data *vc)
|
|||
ops->graphics = ops->save_graphics;
|
||||
if (info->fbops->fb_debug_leave)
|
||||
info->fbops->fb_debug_leave(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch)
|
||||
|
@ -2461,7 +2457,7 @@ err_out:
|
|||
* but lets not assume that, since charcount of 512 is small for unicode support.
|
||||
*/
|
||||
|
||||
static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
|
||||
static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
|
||||
unsigned int vpitch, unsigned int flags)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
|
@ -2534,7 +2530,8 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
|
|||
return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1);
|
||||
}
|
||||
|
||||
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
|
||||
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font,
|
||||
const char *name)
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
const struct font_desc *f;
|
||||
|
@ -2593,35 +2590,6 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
|
|||
fb_set_cmap(&palette_cmap, info);
|
||||
}
|
||||
|
||||
static u16 *fbcon_screen_pos(const struct vc_data *vc, int offset)
|
||||
{
|
||||
return (u16 *) (vc->vc_origin + offset);
|
||||
}
|
||||
|
||||
static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
|
||||
int *px, int *py)
|
||||
{
|
||||
unsigned long ret;
|
||||
int x, y;
|
||||
|
||||
if (pos >= vc->vc_origin && pos < vc->vc_scr_end) {
|
||||
unsigned long offset = (pos - vc->vc_origin) / 2;
|
||||
|
||||
x = offset % vc->vc_cols;
|
||||
y = offset / vc->vc_cols;
|
||||
ret = pos + (vc->vc_cols - x) * 2;
|
||||
} else {
|
||||
/* Should not happen */
|
||||
x = y = 0;
|
||||
ret = vc->vc_origin;
|
||||
}
|
||||
if (px)
|
||||
*px = x;
|
||||
if (py)
|
||||
*py = y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* As we might be inside of softback, we may work with non-contiguous buffer,
|
||||
that's why we have to use a separate routine. */
|
||||
static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
|
||||
|
@ -2650,7 +2618,7 @@ void fbcon_suspended(struct fb_info *info)
|
|||
vc = vc_cons[ops->currcon].d;
|
||||
|
||||
/* Clear cursor, restore saved data */
|
||||
fbcon_cursor(vc, CM_ERASE);
|
||||
fbcon_cursor(vc, false);
|
||||
}
|
||||
|
||||
void fbcon_resumed(struct fb_info *info)
|
||||
|
@ -3152,7 +3120,6 @@ static const struct consw fb_con = {
|
|||
.con_init = fbcon_init,
|
||||
.con_deinit = fbcon_deinit,
|
||||
.con_clear = fbcon_clear,
|
||||
.con_putc = fbcon_putc,
|
||||
.con_putcs = fbcon_putcs,
|
||||
.con_cursor = fbcon_cursor,
|
||||
.con_scroll = fbcon_scroll,
|
||||
|
@ -3163,8 +3130,6 @@ static const struct consw fb_con = {
|
|||
.con_font_default = fbcon_set_def_font,
|
||||
.con_set_palette = fbcon_set_palette,
|
||||
.con_invert_region = fbcon_invert_region,
|
||||
.con_screen_pos = fbcon_screen_pos,
|
||||
.con_getxy = fbcon_getxy,
|
||||
.con_resize = fbcon_resize,
|
||||
.con_debug_enter = fbcon_debug_enter,
|
||||
.con_debug_leave = fbcon_debug_leave,
|
||||
|
|
|
@ -61,8 +61,8 @@ struct fbcon_ops {
|
|||
int fg, int bg);
|
||||
void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
|
||||
int color, int bottom_only);
|
||||
void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
int fg, int bg);
|
||||
void (*cursor)(struct vc_data *vc, struct fb_info *info,
|
||||
bool enable, int fg, int bg);
|
||||
int (*update_start)(struct fb_info *info);
|
||||
int (*rotate_font)(struct fb_info *info, struct vc_data *vc);
|
||||
struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */
|
||||
|
|
|
@ -218,7 +218,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
}
|
||||
}
|
||||
|
||||
static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
|
||||
int fg, int bg)
|
||||
{
|
||||
struct fb_cursor cursor;
|
||||
|
@ -349,16 +349,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
kfree(tmp);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CM_ERASE:
|
||||
ops->cursor_state.enable = 0;
|
||||
break;
|
||||
case CM_DRAW:
|
||||
case CM_MOVE:
|
||||
default:
|
||||
ops->cursor_state.enable = (use_sw) ? 0 : 1;
|
||||
break;
|
||||
}
|
||||
ops->cursor_state.enable = enable && !use_sw;
|
||||
|
||||
cursor.image.data = src;
|
||||
cursor.image.fg_color = ops->cursor_state.image.fg_color;
|
||||
|
|
|
@ -201,7 +201,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
}
|
||||
}
|
||||
|
||||
static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
|
||||
int fg, int bg)
|
||||
{
|
||||
struct fb_cursor cursor;
|
||||
|
@ -332,16 +332,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
kfree(tmp);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CM_ERASE:
|
||||
ops->cursor_state.enable = 0;
|
||||
break;
|
||||
case CM_DRAW:
|
||||
case CM_MOVE:
|
||||
default:
|
||||
ops->cursor_state.enable = (use_sw) ? 0 : 1;
|
||||
break;
|
||||
}
|
||||
ops->cursor_state.enable = enable && !use_sw;
|
||||
|
||||
cursor.image.data = src;
|
||||
cursor.image.fg_color = ops->cursor_state.image.fg_color;
|
||||
|
|
|
@ -248,7 +248,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
}
|
||||
}
|
||||
|
||||
static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
|
||||
int fg, int bg)
|
||||
{
|
||||
struct fb_cursor cursor;
|
||||
|
@ -372,16 +372,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
mask[i++] = ~msk;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CM_ERASE:
|
||||
ops->cursor_state.enable = 0;
|
||||
break;
|
||||
case CM_DRAW:
|
||||
case CM_MOVE:
|
||||
default:
|
||||
ops->cursor_state.enable = (use_sw) ? 0 : 1;
|
||||
break;
|
||||
}
|
||||
ops->cursor_state.enable = enable && !use_sw;
|
||||
|
||||
cursor.image.data = src;
|
||||
cursor.image.fg_color = ops->cursor_state.image.fg_color;
|
||||
|
|
|
@ -79,7 +79,7 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
return;
|
||||
}
|
||||
|
||||
static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
|
||||
int fg, int bg)
|
||||
{
|
||||
struct fb_tilecursor cursor;
|
||||
|
@ -87,7 +87,7 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
|
||||
cursor.sx = vc->state.x;
|
||||
cursor.sy = vc->state.y;
|
||||
cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1;
|
||||
cursor.mode = enable && !use_sw;
|
||||
cursor.fg = fg;
|
||||
cursor.bg = bg;
|
||||
|
||||
|
|
|
@ -380,7 +380,7 @@ tgafb_set_par(struct fb_info *info)
|
|||
BT463_LOAD_ADDR(par, 0x0000);
|
||||
TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
|
||||
|
||||
#ifdef CONFIG_HW_CONSOLE
|
||||
#ifdef CONFIG_VT
|
||||
for (i = 0; i < 16; i++) {
|
||||
int j = color_table[i];
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue