OpenCloudOS-Kernel/include/linux/serial_core.h

595 lines
18 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* linux/drivers/char/serial_core.h
*
* Copyright (C) 2000 Deep Blue Solutions Ltd.
*/
#ifndef LINUX_SERIAL_CORE_H
#define LINUX_SERIAL_CORE_H
#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/console.h>
#include <linux/interrupt.h>
#include <linux/circ_buf.h>
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/mutex.h>
#include <linux/sysrq.h>
#include <uapi/linux/serial_core.h>
#ifdef CONFIG_SERIAL_CORE_CONSOLE
#define uart_console(port) \
((port)->cons && (port)->cons->index == (port)->line)
#else
#define uart_console(port) ({ (void)port; 0; })
#endif
struct uart_port;
struct serial_struct;
struct device;
struct gpio_desc;
/*
* This structure describes all the operations that can be done on the
* physical hardware. See Documentation/driver-api/serial/driver.rst for details.
*/
struct uart_ops {
unsigned int (*tx_empty)(struct uart_port *);
void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
unsigned int (*get_mctrl)(struct uart_port *);
void (*stop_tx)(struct uart_port *);
void (*start_tx)(struct uart_port *);
void (*throttle)(struct uart_port *);
void (*unthrottle)(struct uart_port *);
void (*send_xchar)(struct uart_port *, char ch);
void (*stop_rx)(struct uart_port *);
void (*enable_ms)(struct uart_port *);
void (*break_ctl)(struct uart_port *, int ctl);
int (*startup)(struct uart_port *);
void (*shutdown)(struct uart_port *);
void (*flush_buffer)(struct uart_port *);
void (*set_termios)(struct uart_port *, struct ktermios *new,
struct ktermios *old);
void (*set_ldisc)(struct uart_port *, struct ktermios *);
void (*pm)(struct uart_port *, unsigned int state,
unsigned int oldstate);
/*
* Return a string describing the type of the port
*/
const char *(*type)(struct uart_port *);
/*
* Release IO and memory resources used by the port.
* This includes iounmap if necessary.
*/
void (*release_port)(struct uart_port *);
/*
* Request IO and memory resources used by the port.
* This includes iomapping the port if necessary.
*/
int (*request_port)(struct uart_port *);
void (*config_port)(struct uart_port *, int);
int (*verify_port)(struct uart_port *, struct serial_struct *);
int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL
int (*poll_init)(struct uart_port *);
void (*poll_put_char)(struct uart_port *, unsigned char);
int (*poll_get_char)(struct uart_port *);
#endif
};
#define NO_POLL_CHAR 0x00ff0000
#define UART_CONFIG_TYPE (1 << 0)
#define UART_CONFIG_IRQ (1 << 1)
struct uart_icount {
__u32 cts;
__u32 dsr;
__u32 rng;
__u32 dcd;
__u32 rx;
__u32 tx;
__u32 frame;
__u32 overrun;
__u32 parity;
__u32 brk;
__u32 buf_overrun;
};
typedef unsigned int __bitwise upf_t;
typedef unsigned int __bitwise upstat_t;
struct uart_port {
spinlock_t lock; /* port lock */
unsigned long iobase; /* in/out[bwl] */
unsigned char __iomem *membase; /* read/write[bwl] */
unsigned int (*serial_in)(struct uart_port *, int);
void (*serial_out)(struct uart_port *, int, int);
void (*set_termios)(struct uart_port *,
struct ktermios *new,
struct ktermios *old);
void (*set_ldisc)(struct uart_port *,
struct ktermios *);
unsigned int (*get_mctrl)(struct uart_port *);
void (*set_mctrl)(struct uart_port *, unsigned int);
unsigned int (*get_divisor)(struct uart_port *,
unsigned int baud,
unsigned int *frac);
void (*set_divisor)(struct uart_port *,
unsigned int baud,
unsigned int quot,
unsigned int quot_frac);
int (*startup)(struct uart_port *port);
void (*shutdown)(struct uart_port *port);
void (*throttle)(struct uart_port *port);
void (*unthrottle)(struct uart_port *port);
int (*handle_irq)(struct uart_port *);
void (*pm)(struct uart_port *, unsigned int state,
unsigned int old);
void (*handle_break)(struct uart_port *);
int (*rs485_config)(struct uart_port *,
struct serial_rs485 *rs485);
int (*iso7816_config)(struct uart_port *,
struct serial_iso7816 *iso7816);
unsigned int irq; /* irq number */
unsigned long irqflags; /* irq flags */
unsigned int uartclk; /* base uart clock */
unsigned int fifosize; /* tx fifo size */
unsigned char x_char; /* xon/xoff char */
unsigned char regshift; /* reg offset shift */
unsigned char iotype; /* io access style */
unsigned char quirks; /* internal quirks */
#define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */
#define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */
#define UPIO_MEM (SERIAL_IO_MEM) /* driver-specific */
#define UPIO_MEM32 (SERIAL_IO_MEM32) /* 32b little endian */
#define UPIO_AU (SERIAL_IO_AU) /* Au1x00 and RT288x type IO */
#define UPIO_TSI (SERIAL_IO_TSI) /* Tsi108/109 type IO */
#define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */
#define UPIO_MEM16 (SERIAL_IO_MEM16) /* 16b little endian */
/* quirks must be updated while holding port mutex */
#define UPQ_NO_TXEN_TEST BIT(0)
unsigned int read_status_mask; /* driver specific */
unsigned int ignore_status_mask; /* driver specific */
struct uart_state *state; /* pointer to parent state */
struct uart_icount icount; /* statistics */
struct console *cons; /* struct console, if any */
/* flags must be updated while holding port mutex */
upf_t flags;
/*
* These flags must be equivalent to the flags defined in
* include/uapi/linux/tty_flags.h which are the userspace definitions
* assigned from the serial_struct flags in uart_set_info()
* [for bit definitions in the UPF_CHANGE_MASK]
*
* Bits [0..ASYNCB_LAST_USER] are userspace defined/visible/changeable
* The remaining bits are serial-core specific and not modifiable by
* userspace.
*/
#define UPF_FOURPORT ((__force upf_t) ASYNC_FOURPORT /* 1 */ )
#define UPF_SAK ((__force upf_t) ASYNC_SAK /* 2 */ )
#define UPF_SPD_HI ((__force upf_t) ASYNC_SPD_HI /* 4 */ )
#define UPF_SPD_VHI ((__force upf_t) ASYNC_SPD_VHI /* 5 */ )
#define UPF_SPD_CUST ((__force upf_t) ASYNC_SPD_CUST /* 0x0030 */ )
#define UPF_SPD_WARP ((__force upf_t) ASYNC_SPD_WARP /* 0x1010 */ )
#define UPF_SPD_MASK ((__force upf_t) ASYNC_SPD_MASK /* 0x1030 */ )
#define UPF_SKIP_TEST ((__force upf_t) ASYNC_SKIP_TEST /* 6 */ )
#define UPF_AUTO_IRQ ((__force upf_t) ASYNC_AUTO_IRQ /* 7 */ )
#define UPF_HARDPPS_CD ((__force upf_t) ASYNC_HARDPPS_CD /* 11 */ )
#define UPF_SPD_SHI ((__force upf_t) ASYNC_SPD_SHI /* 12 */ )
#define UPF_LOW_LATENCY ((__force upf_t) ASYNC_LOW_LATENCY /* 13 */ )
#define UPF_BUGGY_UART ((__force upf_t) ASYNC_BUGGY_UART /* 14 */ )
#define UPF_MAGIC_MULTIPLIER ((__force upf_t) ASYNC_MAGIC_MULTIPLIER /* 16 */ )
#define UPF_NO_THRE_TEST ((__force upf_t) (1 << 19))
serial: core: Rework hw-assisted flow control support hw-assisted flow control support was added to the serial core in v3.8 with commits, dba05832cbe4f ("SERIAL: core: add hardware assisted h/w flow control support") 2cbacafd7af0f ("SERIAL: core: add hardware assisted s/w flow control support") 9aba8d5b01119 ("SERIAL: core: add throttle/unthrottle callbacks for hardware assisted flow control") Since then, additional requirements for serial core support have arisen. Specifically, 1. Separate tx and rx flow control settings for UARTs which only support tx flow control (ie., autoCTS). 2. Disable sw-assisted CTS flow control in autoCTS mode 3. Support for RTS flow control by serial core and userspace in autoRTS mode Distinguish mode from capability; introduce UPSTAT_AUTORTS, UPSTAT_AUTOCTS and UPSTAT_AUTOXOFF which, when set by the uart driver, enable serial core support for hw-assisted rx, hw-assisted tx and hw-assisted in-band/IXOFF rx flow control, respectively. [Note: hw-assisted in-band/IXON tx flow control does not require serial core support/intervention and can be enabled by the uart driver when required.] These modes must be set/reset in the driver's set_termios() method, based on termios settings, and thus can be safely queried in any context in which one of the port lock, port mutex or termios rwsem are held. Set these modes in the 2 in-tree drivers, omap-serial and 8250_omap, which currently use UPF_HARD_FLOW/UPF_SOFT_FLOW support. Retain UPF_HARD_FLOW and UPF_SOFT_FLOW as capabilities; re-define UPF_HARD_FLOW as both UPF_AUTO_RTS and UPF_AUTO_CTS to allow for distinct and separate rx and tx flow control capabilities. Disable sw-assisted CTS flow control when UPSTAT_AUTOCTS is enabled. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2015-01-26 03:44:51 +08:00
/* Port has hardware-assisted h/w flow control */
#define UPF_AUTO_CTS ((__force upf_t) (1 << 20))
#define UPF_AUTO_RTS ((__force upf_t) (1 << 21))
#define UPF_HARD_FLOW ((__force upf_t) (UPF_AUTO_CTS | UPF_AUTO_RTS))
/* Port has hardware-assisted s/w flow control */
#define UPF_SOFT_FLOW ((__force upf_t) (1 << 22))
#define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
#define UPF_EXAR_EFR ((__force upf_t) (1 << 25))
#define UPF_BUG_THRE ((__force upf_t) (1 << 26))
/* The exact UART type is known and should not be probed. */
#define UPF_FIXED_TYPE ((__force upf_t) (1 << 27))
#define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT ((__force upf_t) (1 << 29))
#define UPF_DEAD ((__force upf_t) (1 << 30))
#define UPF_IOREMAP ((__force upf_t) (1 << 31))
#define __UPF_CHANGE_MASK 0x17fff
#define UPF_CHANGE_MASK ((__force upf_t) __UPF_CHANGE_MASK)
#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
#if __UPF_CHANGE_MASK > ASYNC_FLAGS
#error Change mask not equivalent to userspace-visible bit defines
#endif
serial: core: Rework hw-assisted flow control support hw-assisted flow control support was added to the serial core in v3.8 with commits, dba05832cbe4f ("SERIAL: core: add hardware assisted h/w flow control support") 2cbacafd7af0f ("SERIAL: core: add hardware assisted s/w flow control support") 9aba8d5b01119 ("SERIAL: core: add throttle/unthrottle callbacks for hardware assisted flow control") Since then, additional requirements for serial core support have arisen. Specifically, 1. Separate tx and rx flow control settings for UARTs which only support tx flow control (ie., autoCTS). 2. Disable sw-assisted CTS flow control in autoCTS mode 3. Support for RTS flow control by serial core and userspace in autoRTS mode Distinguish mode from capability; introduce UPSTAT_AUTORTS, UPSTAT_AUTOCTS and UPSTAT_AUTOXOFF which, when set by the uart driver, enable serial core support for hw-assisted rx, hw-assisted tx and hw-assisted in-band/IXOFF rx flow control, respectively. [Note: hw-assisted in-band/IXON tx flow control does not require serial core support/intervention and can be enabled by the uart driver when required.] These modes must be set/reset in the driver's set_termios() method, based on termios settings, and thus can be safely queried in any context in which one of the port lock, port mutex or termios rwsem are held. Set these modes in the 2 in-tree drivers, omap-serial and 8250_omap, which currently use UPF_HARD_FLOW/UPF_SOFT_FLOW support. Retain UPF_HARD_FLOW and UPF_SOFT_FLOW as capabilities; re-define UPF_HARD_FLOW as both UPF_AUTO_RTS and UPF_AUTO_CTS to allow for distinct and separate rx and tx flow control capabilities. Disable sw-assisted CTS flow control when UPSTAT_AUTOCTS is enabled. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2015-01-26 03:44:51 +08:00
/*
* Must hold termios_rwsem, port mutex and port lock to change;
* can hold any one lock to read.
*/
upstat_t status;
#define UPSTAT_CTS_ENABLE ((__force upstat_t) (1 << 0))
#define UPSTAT_DCD_ENABLE ((__force upstat_t) (1 << 1))
serial: core: Rework hw-assisted flow control support hw-assisted flow control support was added to the serial core in v3.8 with commits, dba05832cbe4f ("SERIAL: core: add hardware assisted h/w flow control support") 2cbacafd7af0f ("SERIAL: core: add hardware assisted s/w flow control support") 9aba8d5b01119 ("SERIAL: core: add throttle/unthrottle callbacks for hardware assisted flow control") Since then, additional requirements for serial core support have arisen. Specifically, 1. Separate tx and rx flow control settings for UARTs which only support tx flow control (ie., autoCTS). 2. Disable sw-assisted CTS flow control in autoCTS mode 3. Support for RTS flow control by serial core and userspace in autoRTS mode Distinguish mode from capability; introduce UPSTAT_AUTORTS, UPSTAT_AUTOCTS and UPSTAT_AUTOXOFF which, when set by the uart driver, enable serial core support for hw-assisted rx, hw-assisted tx and hw-assisted in-band/IXOFF rx flow control, respectively. [Note: hw-assisted in-band/IXON tx flow control does not require serial core support/intervention and can be enabled by the uart driver when required.] These modes must be set/reset in the driver's set_termios() method, based on termios settings, and thus can be safely queried in any context in which one of the port lock, port mutex or termios rwsem are held. Set these modes in the 2 in-tree drivers, omap-serial and 8250_omap, which currently use UPF_HARD_FLOW/UPF_SOFT_FLOW support. Retain UPF_HARD_FLOW and UPF_SOFT_FLOW as capabilities; re-define UPF_HARD_FLOW as both UPF_AUTO_RTS and UPF_AUTO_CTS to allow for distinct and separate rx and tx flow control capabilities. Disable sw-assisted CTS flow control when UPSTAT_AUTOCTS is enabled. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2015-01-26 03:44:51 +08:00
#define UPSTAT_AUTORTS ((__force upstat_t) (1 << 2))
#define UPSTAT_AUTOCTS ((__force upstat_t) (1 << 3))
#define UPSTAT_AUTOXOFF ((__force upstat_t) (1 << 4))
#define UPSTAT_SYNC_FIFO ((__force upstat_t) (1 << 5))
int hw_stopped; /* sw-assisted CTS flow state */
unsigned int mctrl; /* current modem ctrl settings */
unsigned int timeout; /* character-based timeout */
unsigned int type; /* port type */
const struct uart_ops *ops;
unsigned int custom_divisor;
unsigned int line; /* port index */
unsigned int minor;
resource_size_t mapbase; /* for ioremap */
resource_size_t mapsize;
struct device *dev; /* parent device */
unsigned long sysrq; /* sysrq timeout */
unsigned int sysrq_ch; /* char for sysrq */
unsigned char has_sysrq;
unsigned char sysrq_seq; /* index in sysrq_toggle_seq */
unsigned char hub6; /* this should be in the 8250 driver */
unsigned char suspended;
serial: core: fix console port-lock regression Fix the port-lock initialisation regression introduced by commit a3cb39d258ef ("serial: core: Allow detach and attach serial device for console") by making sure that the lock is again initialised during console setup. The console may be registered before the serial controller has been probed in which case the port lock needs to be initialised during console setup by a call to uart_set_options(). The console-detach changes introduced a regression in several drivers by effectively removing that initialisation by not initialising the lock when the port is used as a console (which is always the case during console setup). Add back the early lock initialisation and instead use a new console-reinit flag to handle the case where a console is being re-attached through sysfs. The question whether the console-detach interface should have been added in the first place is left for another discussion. Note that the console-enabled check in uart_set_options() is not redundant because of kgdboc, which can end up reinitialising an already enabled console (see commit 42b6a1baa3ec ("serial_core: Don't re-initialize a previously initialized spinlock.")). Fixes: a3cb39d258ef ("serial: core: Allow detach and attach serial device for console") Cc: stable <stable@vger.kernel.org> # 5.7 Signed-off-by: Johan Hovold <johan@kernel.org> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20200909143101.15389-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-09-09 22:31:01 +08:00
unsigned char console_reinit;
const char *name; /* port name */
struct attribute_group *attr_group; /* port specific attributes */
const struct attribute_group **tty_groups; /* all attributes (serial core use only) */
struct serial_rs485 rs485;
struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */
struct serial_iso7816 iso7816;
void *private_data; /* generic platform data pointer */
};
static inline int serial_port_in(struct uart_port *up, int offset)
{
return up->serial_in(up, offset);
}
static inline void serial_port_out(struct uart_port *up, int offset, int value)
{
up->serial_out(up, offset, value);
}
/**
* enum uart_pm_state - power states for UARTs
* @UART_PM_STATE_ON: UART is powered, up and operational
* @UART_PM_STATE_OFF: UART is powered off
* @UART_PM_STATE_UNDEFINED: sentinel
*/
enum uart_pm_state {
UART_PM_STATE_ON = 0,
UART_PM_STATE_OFF = 3, /* number taken from ACPI */
UART_PM_STATE_UNDEFINED,
};
/*
* This is the state information which is persistent across opens.
*/
struct uart_state {
struct tty_port port;
enum uart_pm_state pm_state;
struct circ_buf xmit;
atomic_t refcount;
wait_queue_head_t remove_wait;
struct uart_port *uart_port;
};
#define UART_XMIT_SIZE PAGE_SIZE
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
struct module;
struct tty_driver;
struct uart_driver {
struct module *owner;
const char *driver_name;
const char *dev_name;
int major;
int minor;
int nr;
struct console *cons;
/*
* these are private; the low level driver should not
* touch these; they should be initialised to NULL
*/
struct uart_state *state;
struct tty_driver *tty_driver;
};
void uart_write_wakeup(struct uart_port *port);
/*
* Baud rate helpers.
*/
void uart_update_timeout(struct uart_port *port, unsigned int cflag,
unsigned int baud);
unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
struct ktermios *old, unsigned int min,
unsigned int max);
unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
/* Base timer interval for polling */
static inline int uart_poll_timeout(struct uart_port *port)
{
int timeout = port->timeout;
return timeout > 6 ? (timeout / 2 - 2) : 1;
}
/*
* Console helpers.
*/
struct earlycon_device {
struct console *con;
struct uart_port port;
char options[16]; /* e.g., 115200n8 */
unsigned int baud;
};
struct earlycon_id {
char name[15];
char name_term; /* In case compiler didn't '\0' term name */
char compatible[128];
int (*setup)(struct earlycon_device *, const char *options);
earlycon: Use a pointer table to fix __earlycon_table stride Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix __earlycon_table stride by forcing the earlycon_id struct alignment to 32 and asking the linker to 32-byte align the __earlycon_table symbol. This fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker defined symbols") which tried a similar fix for the tracing subsystem. However, this fix doesn't quite work because there is no guarantee that gcc will place structures packed into an array format. In fact, gcc 4.9 chooses to 64-byte align these structs by inserting additional padding between the entries because it has no clue that they are supposed to be in an array. If we are unlucky, the linker will assign symbol "__earlycon_table" to a 32-byte aligned address which does not correspond to the 64-byte aligned contents of section "__earlycon_table". To address this same problem, the fix to the tracing system was subsequently re-implemented using a more robust table of pointers approach by commits: 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer array") 654986462939 ("tracepoints: Fix section alignment using pointer array") e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array") Let's use this same "array of pointers to structs" approach for EARLYCON_TABLE. Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride") Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> Suggested-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Rob Herring <robh@kernel.org> Tested-by: Guenter Roeck <groeck@chromium.org> Reviewed-by: Guenter Roeck <groeck@chromium.org> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-04-07 07:21:53 +08:00
};
extern const struct earlycon_id __earlycon_table[];
extern const struct earlycon_id __earlycon_table_end[];
#if defined(CONFIG_SERIAL_EARLYCON) && !defined(MODULE)
#define EARLYCON_USED_OR_UNUSED __used
#else
#define EARLYCON_USED_OR_UNUSED __maybe_unused
#endif
#define OF_EARLYCON_DECLARE(_name, compat, fn) \
static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \
EARLYCON_USED_OR_UNUSED __section("__earlycon_table") \
__aligned(__alignof__(struct earlycon_id)) \
= { .name = __stringify(_name), \
.compatible = compat, \
.setup = fn }
#define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn)
extern int of_setup_earlycon(const struct earlycon_id *match,
unsigned long node,
const char *options);
#ifdef CONFIG_SERIAL_EARLYCON
extern bool earlycon_acpi_spcr_enable __initdata;
int setup_earlycon(char *buf);
#else
static const bool earlycon_acpi_spcr_enable EARLYCON_USED_OR_UNUSED;
static inline int setup_earlycon(char *buf) { return 0; }
#endif
struct uart_port *uart_get_console(struct uart_port *ports, int nr,
struct console *c);
int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr,
char **options);
void uart_parse_options(const char *options, int *baud, int *parity, int *bits,
int *flow);
int uart_set_options(struct uart_port *port, struct console *co, int baud,
int parity, int bits, int flow);
struct tty_driver *uart_console_device(struct console *co, int *index);
void uart_console_write(struct uart_port *port, const char *s,
unsigned int count,
serial: make uart_console_write->putchar()'s character an unsigned char Currently, uart_console_write->putchar's second parameter (the character) is of type int. It makes little sense, provided uart_console_write() accepts the input string as "const char *s" and passes its content -- the characters -- to putchar(). So switch the character's type to unsigned char. We don't use char as that is signed on some platforms. That would cause troubles for drivers which (implicitly) cast the char to u16 when writing to the device. Sign extension would happen in that case and the value written would be completely different to the provided char. DZ is an example of such a driver -- on MIPS, it uses u16 for dz_out in dz_console_putchar(). Note we do the char -> uchar conversion implicitly in uart_console_write(). Provided we do not change size of the data type, sign extension does not happen there, so the problem is void. This makes the types consistent and unified with the rest of the uart layer, which uses unsigned char in most places already. One exception is xmit_buf, but that is going to be converted later. Cc: Paul Cercueil <paul@crapouillou.net> Cc: Tobias Klauser <tklauser@distanz.ch> Cc: Russell King <linux@armlinux.org.uk> Cc: Vineet Gupta <vgupta@kernel.org> Cc: Nicolas Ferre <nicolas.ferre@microchip.com> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com> Cc: Ludovic Desroches <ludovic.desroches@microchip.com> Cc: Florian Fainelli <f.fainelli@gmail.com> Cc: bcm-kernel-feedback-list@broadcom.com Cc: Alexander Shiyan <shc_work@mail.ru> Cc: Baruch Siach <baruch@tkos.co.il> Cc: "Maciej W. Rozycki" <macro@orcam.me.uk> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: Shawn Guo <shawnguo@kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Pengutronix Kernel Team <kernel@pengutronix.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: NXP Linux Team <linux-imx@nxp.com> Cc: Karol Gugala <kgugala@antmicro.com> Cc: Mateusz Holenko <mholenko@antmicro.com> Cc: Vladimir Zapolskiy <vz@mleia.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Kevin Hilman <khilman@baylibre.com> Cc: Jerome Brunet <jbrunet@baylibre.com> Cc: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Cc: Taichi Sugaya <sugaya.taichi@socionext.com> Cc: Takao Orito <orito.takao@socionext.com> Cc: Liviu Dudau <liviu.dudau@arm.com> Cc: Sudeep Holla <sudeep.holla@arm.com> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Cc: "Andreas Färber" <afaerber@suse.de> Cc: Manivannan Sadhasivam <mani@kernel.org> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Andy Gross <agross@kernel.org> Cc: Bjorn Andersson <bjorn.andersson@linaro.org> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> Cc: Orson Zhai <orsonzhai@gmail.com> Cc: Baolin Wang <baolin.wang7@gmail.com> Cc: Chunyan Zhang <zhang.lyra@gmail.com> Cc: Patrice Chotard <patrice.chotard@foss.st.com> Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com> Cc: Alexandre Torgue <alexandre.torgue@foss.st.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: Peter Korsgaard <peter@korsgaard.com> Cc: Michal Simek <michal.simek@xilinx.com> Acked-by: Richard Genoud <richard.genoud@gmail.com> [atmel_serial] Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Acked-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Neil Armstrong <narmstrong@baylibre.com> # meson_serial Signed-off-by: Jiri Slaby <jslaby@suse.cz> Link: https://lore.kernel.org/r/20220303080831.21783-1-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-03-03 16:08:31 +08:00
void (*putchar)(struct uart_port *, unsigned char));
/*
* Port/driver registration/removal
*/
int uart_register_driver(struct uart_driver *uart);
void uart_unregister_driver(struct uart_driver *uart);
int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
bool uart_match_port(const struct uart_port *port1,
const struct uart_port *port2);
/*
* Power Management
*/
int uart_suspend_port(struct uart_driver *reg, struct uart_port *port);
int uart_resume_port(struct uart_driver *reg, struct uart_port *port);
#define uart_circ_empty(circ) ((circ)->head == (circ)->tail)
#define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0)
#define uart_circ_chars_pending(circ) \
(CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
#define uart_circ_chars_free(circ) \
(CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
static inline int uart_tx_stopped(struct uart_port *port)
{
struct tty_struct *tty = port->state->port.tty;
tty: cumulate and document tty_struct::flow* members Group the flow flags under a single struct called flow. The new struct contains 'stopped' and 'tco_stopped' bools which used to be bits in a bitfield. The struct also contains the lock protecting them to potentially share the same cache line. Note that commit c545b66c6922b (tty: Serialize tcflow() with other tty flow control changes) added a padding to the original bitfield. It was for the bitfield to occupy a whole 64b word to avoid interferring stores on Alpha (cannot we evaporate this arch with weird implications to C code yet?). But it doesn't work as expected as the padding (tty_struct::unused) is aligned to a 8B boundary too and occupies some bytes from the next word. So make it reliable by: 1) setting __aligned of the struct -- that aligns the start, and 2) making 'unsigned long unused[0]' as the last member of the struct -- pads the end. This is also the perfect time to start the documentation of tty_struct where all this lives. So we start by documenting what these bools actually serve for. And why we do all the alignment dances. Only the few up-to-date information from the Theodore's comment made it into this new Kerneldoc comment. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Cc: "David S. Miller" <davem@davemloft.net> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Ulf Hansson <ulf.hansson@linaro.org> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Cc: Christian Borntraeger <borntraeger@de.ibm.com> Cc: Shawn Guo <shawnguo@kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Vineet Gupta <vgupta@synopsys.com> Cc: "Maciej W. Rozycki" <macro@orcam.me.uk> Link: https://lore.kernel.org/r/20210505091928.22010-13-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2021-05-05 17:19:05 +08:00
if ((tty && tty->flow.stopped) || port->hw_stopped)
return 1;
return 0;
}
static inline bool uart_cts_enabled(struct uart_port *uport)
{
return !!(uport->status & UPSTAT_CTS_ENABLE);
}
serial: core: Rework hw-assisted flow control support hw-assisted flow control support was added to the serial core in v3.8 with commits, dba05832cbe4f ("SERIAL: core: add hardware assisted h/w flow control support") 2cbacafd7af0f ("SERIAL: core: add hardware assisted s/w flow control support") 9aba8d5b01119 ("SERIAL: core: add throttle/unthrottle callbacks for hardware assisted flow control") Since then, additional requirements for serial core support have arisen. Specifically, 1. Separate tx and rx flow control settings for UARTs which only support tx flow control (ie., autoCTS). 2. Disable sw-assisted CTS flow control in autoCTS mode 3. Support for RTS flow control by serial core and userspace in autoRTS mode Distinguish mode from capability; introduce UPSTAT_AUTORTS, UPSTAT_AUTOCTS and UPSTAT_AUTOXOFF which, when set by the uart driver, enable serial core support for hw-assisted rx, hw-assisted tx and hw-assisted in-band/IXOFF rx flow control, respectively. [Note: hw-assisted in-band/IXON tx flow control does not require serial core support/intervention and can be enabled by the uart driver when required.] These modes must be set/reset in the driver's set_termios() method, based on termios settings, and thus can be safely queried in any context in which one of the port lock, port mutex or termios rwsem are held. Set these modes in the 2 in-tree drivers, omap-serial and 8250_omap, which currently use UPF_HARD_FLOW/UPF_SOFT_FLOW support. Retain UPF_HARD_FLOW and UPF_SOFT_FLOW as capabilities; re-define UPF_HARD_FLOW as both UPF_AUTO_RTS and UPF_AUTO_CTS to allow for distinct and separate rx and tx flow control capabilities. Disable sw-assisted CTS flow control when UPSTAT_AUTOCTS is enabled. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2015-01-26 03:44:51 +08:00
static inline bool uart_softcts_mode(struct uart_port *uport)
{
upstat_t mask = UPSTAT_CTS_ENABLE | UPSTAT_AUTOCTS;
return ((uport->status & mask) == UPSTAT_CTS_ENABLE);
}
/*
* The following are helper functions for the low level drivers.
*/
extern void uart_handle_dcd_change(struct uart_port *uport,
unsigned int status);
extern void uart_handle_cts_change(struct uart_port *uport,
unsigned int status);
extern void uart_insert_char(struct uart_port *port, unsigned int status,
unsigned int overrun, unsigned int ch, unsigned int flag);
void uart_xchar_out(struct uart_port *uport, int offset);
#ifdef CONFIG_MAGIC_SYSRQ_SERIAL
#define SYSRQ_TIMEOUT (HZ * 5)
bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch);
static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
{
if (!port->sysrq)
return 0;
if (ch && time_before(jiffies, port->sysrq)) {
if (sysrq_mask()) {
handle_sysrq(ch);
port->sysrq = 0;
return 1;
}
if (uart_try_toggle_sysrq(port, ch))
return 1;
}
port->sysrq = 0;
return 0;
}
static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
{
if (!port->sysrq)
return 0;
if (ch && time_before(jiffies, port->sysrq)) {
if (sysrq_mask()) {
port->sysrq_ch = ch;
port->sysrq = 0;
return 1;
}
if (uart_try_toggle_sysrq(port, ch))
return 1;
}
port->sysrq = 0;
return 0;
}
static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
{
int sysrq_ch;
if (!port->has_sysrq) {
spin_unlock(&port->lock);
return;
}
sysrq_ch = port->sysrq_ch;
port->sysrq_ch = 0;
spin_unlock(&port->lock);
if (sysrq_ch)
handle_sysrq(sysrq_ch);
}
static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port,
unsigned long flags)
{
int sysrq_ch;
if (!port->has_sysrq) {
spin_unlock_irqrestore(&port->lock, flags);
return;
}
sysrq_ch = port->sysrq_ch;
port->sysrq_ch = 0;
spin_unlock_irqrestore(&port->lock, flags);
if (sysrq_ch)
handle_sysrq(sysrq_ch);
}
#else /* CONFIG_MAGIC_SYSRQ_SERIAL */
static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
{
return 0;
}
static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
{
return 0;
}
static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
{
spin_unlock(&port->lock);
}
static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port,
unsigned long flags)
{
spin_unlock_irqrestore(&port->lock, flags);
}
#endif /* CONFIG_MAGIC_SYSRQ_SERIAL */
/*
* We do the SysRQ and SAK checking like this...
*/
static inline int uart_handle_break(struct uart_port *port)
{
struct uart_state *state = port->state;
if (port->handle_break)
port->handle_break(port);
#ifdef CONFIG_MAGIC_SYSRQ_SERIAL
if (port->has_sysrq && uart_console(port)) {
if (!port->sysrq) {
port->sysrq = jiffies + SYSRQ_TIMEOUT;
return 1;
}
port->sysrq = 0;
}
#endif
if (port->flags & UPF_SAK)
do_SAK(state->port.tty);
return 0;
}
/*
* UART_ENABLE_MS - determine if port should enable modem status irqs
*/
#define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \
(cflag) & CRTSCTS || \
!((cflag) & CLOCAL))
int uart_get_rs485_mode(struct uart_port *port);
#endif /* LINUX_SERIAL_CORE_H */