Merge tag 'tty-6.0-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 and serial driver changes for 6.0-rc1.

  It was delayed from last week as I wanted to make sure the last commit
  here got some good testing in linux-next and elsewhere as it seemed to
  show up only late in testing for some reason.

  Nothing major here, just lots of cleanups from Jiri and Ilpo to make
  the tty core cleaner (Jiri) and the rs485 code simpler to use (Ilpo).

  Also included in here is the obligatory n_gsm updates from Daniel
  Starke and lots of tiny driver updates and minor fixes and tweaks for
  other smaller serial drivers.

  All of these have been in linux-next for a while with no reported
  problems"

* tag 'tty-6.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (186 commits)
  tty: serial: qcom-geni-serial: Fix %lu -> %u in print statements
  tty: amiserial: Fix comment typo
  tty: serial: document uart_get_console()
  tty: serial: serial_core, reformat kernel-doc for functions
  Documentation: serial: link uart_ops properly
  Documentation: serial: move GPIO kernel-doc to the functions
  Documentation: serial: dedup kernel-doc for uart functions
  Documentation: serial: move uart_ops documentation to the struct
  dt-bindings: serial: snps-dw-apb-uart: Document Rockchip RV1126
  serial: mvebu-uart: uart2 error bits clearing
  tty: serial: fsl_lpuart: correct the count of break characters
  serial: stm32: make info structs static to avoid sparse warnings
  serial: fsl_lpuart: zero out parity bit in CS7 mode
  tty: serial: qcom-geni-serial: Fix get_clk_div_rate() which otherwise could return a sub-optimal clock rate.
  serial: 8250_bcm2835aux: Add missing clk_disable_unprepare()
  tty: vt: initialize unicode screen buffer
  serial: remove VR41XX serial driver
  serial: 8250: lpc18xx: Remove redundant sanity check for RS485 flags
  serial: 8250_dwlib: remove redundant sanity check for RS485 flags
  dt_bindings: rs485: Correct delay values
  ...
This commit is contained in:
Linus Torvalds
2022-08-08 11:31:40 -07:00
97 changed files with 3344 additions and 3188 deletions

View File

@@ -62,6 +62,7 @@ properties:
- const: mrvl,pxa-uart
- const: nuvoton,wpcm450-uart
- const: nuvoton,npcm750-uart
- const: nuvoton,npcm845-uart
- const: nvidia,tegra20-uart
- const: nxp,lpc3220-uart
- items:

View File

@@ -0,0 +1,120 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/serial/mediatek,uart.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek Universal Asynchronous Receiver/Transmitter (UART)
maintainers:
- Matthias Brugger <matthias.bgg@gmail.com>
allOf:
- $ref: serial.yaml#
description: |
The MediaTek UART is based on the basic 8250 UART and compatible
with 16550A, with enhancements for high speed baud rates and
support for DMA.
properties:
compatible:
oneOf:
- const: mediatek,mt6577-uart
- items:
- enum:
- mediatek,mt2701-uart
- mediatek,mt2712-uart
- mediatek,mt6580-uart
- mediatek,mt6582-uart
- mediatek,mt6589-uart
- mediatek,mt6755-uart
- mediatek,mt6765-uart
- mediatek,mt6779-uart
- mediatek,mt6795-uart
- mediatek,mt6797-uart
- mediatek,mt7622-uart
- mediatek,mt7623-uart
- mediatek,mt7629-uart
- mediatek,mt7986-uart
- mediatek,mt8127-uart
- mediatek,mt8135-uart
- mediatek,mt8173-uart
- mediatek,mt8183-uart
- mediatek,mt8186-uart
- mediatek,mt8192-uart
- mediatek,mt8195-uart
- mediatek,mt8516-uart
- const: mediatek,mt6577-uart
reg:
description: The base address of the UART register bank
maxItems: 1
clocks:
minItems: 1
items:
- description: The clock the baudrate is derived from
- description: The bus clock for register accesses
clock-names:
minItems: 1
items:
- const: baud
- const: bus
dmas:
items:
- description: phandle to TX DMA
- description: phandle to RX DMA
dma-names:
items:
- const: tx
- const: rx
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
description:
The UART interrupt and optionally the RX in-band wakeup interrupt.
minItems: 1
items:
- const: uart
- const: wakeup
pinctrl-0: true
pinctrl-1: true
pinctrl-names:
minItems: 1
items:
- const: default
- const: sleep
required:
- compatible
- reg
- clocks
- interrupts
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
serial@11006000 {
compatible = "mediatek,mt6589-uart", "mediatek,mt6577-uart";
reg = <0x11006000 0x400>;
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>,
<GIC_SPI 52 IRQ_TYPE_EDGE_FALLING>;
interrupt-names = "uart", "wakeup";
clocks = <&uart_clk>, <&bus_clk>;
clock-names = "baud", "bus";
pinctrl-0 = <&uart_pin>;
pinctrl-1 = <&uart_pin_sleep>;
pinctrl-names = "default", "sleep";
};

View File

@@ -1,59 +0,0 @@
* MediaTek Universal Asynchronous Receiver/Transmitter (UART)
Required properties:
- compatible should contain:
* "mediatek,mt2701-uart" for MT2701 compatible UARTS
* "mediatek,mt2712-uart" for MT2712 compatible UARTS
* "mediatek,mt6580-uart" for MT6580 compatible UARTS
* "mediatek,mt6582-uart" for MT6582 compatible UARTS
* "mediatek,mt6589-uart" for MT6589 compatible UARTS
* "mediatek,mt6755-uart" for MT6755 compatible UARTS
* "mediatek,mt6765-uart" for MT6765 compatible UARTS
* "mediatek,mt6779-uart" for MT6779 compatible UARTS
* "mediatek,mt6795-uart" for MT6795 compatible UARTS
* "mediatek,mt6797-uart" for MT6797 compatible UARTS
* "mediatek,mt7622-uart" for MT7622 compatible UARTS
* "mediatek,mt7623-uart" for MT7623 compatible UARTS
* "mediatek,mt7629-uart" for MT7629 compatible UARTS
* "mediatek,mt7986-uart", "mediatek,mt6577-uart" for MT7986 compatible UARTS
* "mediatek,mt8127-uart" for MT8127 compatible UARTS
* "mediatek,mt8135-uart" for MT8135 compatible UARTS
* "mediatek,mt8173-uart" for MT8173 compatible UARTS
* "mediatek,mt8183-uart", "mediatek,mt6577-uart" for MT8183 compatible UARTS
* "mediatek,mt8186-uart", "mediatek,mt6577-uart" for MT8183 compatible UARTS
* "mediatek,mt8192-uart", "mediatek,mt6577-uart" for MT8192 compatible UARTS
* "mediatek,mt8195-uart", "mediatek,mt6577-uart" for MT8195 compatible UARTS
* "mediatek,mt8516-uart" for MT8516 compatible UARTS
* "mediatek,mt6577-uart" for MT6577 and all of the above
- reg: The base address of the UART register bank.
- interrupts:
index 0: an interrupt specifier for the UART controller itself
index 1: optional, an interrupt specifier with edge sensitivity on Rx pin to
support Rx in-band wake up. If one would like to use this feature,
one must create an addtional pinctrl to reconfigure Rx pin to normal
GPIO before suspend.
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names:
- "baud": The clock the baudrate is derived from
- "bus": The bus clock for register accesses (optional)
For compatibility with older device trees an unnamed clock is used for the
baud clock if the baudclk does not exist. Do not use this for new designs.
Example:
uart0: serial@11006000 {
compatible = "mediatek,mt6589-uart", "mediatek,mt6577-uart";
reg = <0x11006000 0x400>;
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>,
<GIC_SPI 52 IRQ_TYPE_EDGE_FALLING>;
clocks = <&uart_clk>, <&bus_clk>;
clock-names = "baud", "bus";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart_pin>;
pinctrl-1 = <&uart_pin_sleep>;
};

View File

@@ -57,6 +57,7 @@ properties:
- items:
- enum:
- renesas,hscif-r8a779a0 # R-Car V3U
- renesas,hscif-r8a779f0 # R-Car S4-8
- renesas,hscif-r8a779g0 # R-Car V4H
- const: renesas,rcar-gen4-hscif # R-Car Gen4
- const: renesas,hscif # generic HSCIF compatible UART

View File

@@ -22,12 +22,12 @@ properties:
- description: Delay between rts signal and beginning of data sent in
milliseconds. It corresponds to the delay before sending data.
default: 0
maximum: 1000
maximum: 100
- description: Delay between end of data sent and rts signal in milliseconds.
It corresponds to the delay after sending data and actual release
of the line.
default: 0
maximum: 1000
maximum: 100
rs485-rts-active-low:
description: drive RTS low when sending (default is high).

View File

@@ -33,7 +33,9 @@ properties:
- rockchip,rk3368-uart
- rockchip,rk3399-uart
- rockchip,rk3568-uart
- rockchip,rk3588-uart
- rockchip,rv1108-uart
- rockchip,rv1126-uart
- const: snps,dw-apb-uart
- items:
- enum:

File diff suppressed because it is too large Load Diff

View File

@@ -38,10 +38,14 @@ RS485 Serial Communications
the values given by the device tree.
Any driver for devices capable of working both as RS232 and RS485 should
implement the rs485_config callback in the uart_port structure. The
serial_core calls rs485_config to do the device specific part in response
to TIOCSRS485 and TIOCGRS485 ioctls (see below). The rs485_config callback
receives a pointer to struct serial_rs485.
implement the rs485_config callback and provide rs485_supported in the
uart_port structure. The serial core calls rs485_config to do the device
specific part in response to TIOCSRS485 ioctl (see below). The rs485_config
callback receives a pointer to a sanitizated serial_rs485 structure. The
serial_rs485 userspace provides is sanitized before calling rs485_config
using rs485_supported that indicates what RS485 features the driver supports
for the uart_port. TIOCGRS485 ioctl can be used to read back the
serial_rs485 structure matching to the current configuration.
4. Usage from user-level
========================
@@ -95,7 +99,31 @@ RS485 Serial Communications
/* Error handling. See errno. */
}
5. References
5. Multipoint Addressing
========================
The Linux kernel provides addressing mode for multipoint RS-485 serial
communications line. The addressing mode is enabled with SER_RS485_ADDRB
flag in serial_rs485. Struct serial_rs485 has two additional flags and
fields for enabling receive and destination addresses.
Address mode flags:
- SER_RS485_ADDRB: Enabled addressing mode (sets also ADDRB in termios).
- SER_RS485_ADDR_RECV: Receive (filter) address enabled.
- SER_RS485_ADDR_DEST: Set destination address.
Address fields (enabled with corresponding SER_RS485_ADDR_* flag):
- addr_recv: Receive address.
- addr_dest: Destination address.
Once a receive address is set, the communication can occur only with the
particular device and other peers are filtered out. It is left up to the
receiver side to enforce the filtering. Receive address will be cleared
if SER_RS485_ADDR_RECV is not set.
Note: not all devices supporting RS485 support multipoint addressing.
6. References
=============
[1] include/uapi/linux/serial.h

View File

@@ -19622,8 +19622,9 @@ F: Documentation/devicetree/bindings/gpio/snps,creg-gpio.txt
F: drivers/gpio/gpio-creg-snps.c
SYNOPSYS DESIGNWARE 8250 UART DRIVER
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
S: Maintained
S: Supported
F: drivers/tty/serial/8250/8250_dw.c
F: drivers/tty/serial/8250/8250_dwlib.*
F: drivers/tty/serial/8250/8250_lpss.c

View File

@@ -8,6 +8,7 @@
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <asm/addrspace.h>
#include <asm/setup.h>
@@ -18,38 +19,34 @@
static void (*_prom_putchar)(char);
static inline void prom_putchar_wait(void __iomem *reg, u32 mask, u32 val)
static inline void prom_putchar_wait(void __iomem *reg, u32 val)
{
u32 t;
do {
t = __raw_readl(reg);
if ((t & mask) == val)
if ((t & val) == val)
break;
} while (1);
}
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
static void prom_putchar_ar71xx(char ch)
{
void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
prom_putchar_wait(base + UART_LSR * 4, UART_LSR_BOTH_EMPTY);
__raw_writel((unsigned char)ch, base + UART_TX * 4);
prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
prom_putchar_wait(base + UART_LSR * 4, UART_LSR_BOTH_EMPTY);
}
static void prom_putchar_ar933x(char ch)
{
void __iomem *base = (void __iomem *)(KSEG1ADDR(AR933X_UART_BASE));
prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR,
AR933X_UART_DATA_TX_CSR);
prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR);
__raw_writel(AR933X_UART_DATA_TX_CSR | (unsigned char)ch,
base + AR933X_UART_DATA_REG);
prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR,
AR933X_UART_DATA_TX_CSR);
prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR);
}
static void prom_putchar_dummy(char ch)

View File

@@ -131,7 +131,7 @@ static void vc_refresh(struct vc_data *vc)
for (i = 0; i < WIDTH; i++) {
u16 glyph = screen_glyph(vc,
2 * (vc_x + i) + vc_y * vc->vc_size_row);
buf[i] = inverse_translate(vc, glyph, 1);
buf[i] = inverse_translate(vc, glyph, true);
}
braille_write(buf);
}

View File

@@ -470,7 +470,7 @@ static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs)
c |= 0x100;
}
ch = inverse_translate(vc, c, 1);
ch = inverse_translate(vc, c, true);
*attribs = (w & 0xff00) >> 8;
}
return ch;

View File

@@ -33,9 +33,8 @@ struct old_serial_port {
#define NUM_DISABLE_TIMEOUTS 3
/* buffer timeout in ms */
#define SPK_TIMEOUT 100
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
#define spk_serial_tx_busy() \
((inb(speakup_info.port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY)
(!uart_lsr_tx_empty(inb(speakup_info.port_tts + UART_LSR)))
#endif

View File

@@ -1024,6 +1024,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int l;
const struct earlycon_id *match;
const void *fdt = initial_boot_params;
int ret;
offset = fdt_path_offset(fdt, "/chosen");
if (offset < 0)
@@ -1056,7 +1057,8 @@ int __init early_init_dt_scan_chosen_stdout(void)
if (fdt_node_check_compatible(fdt, offset, match->compatible))
continue;
if (of_setup_earlycon(match, offset, options) == 0)
ret = of_setup_earlycon(match, offset, options);
if (!ret || ret == -EALREADY)
return 0;
}
return -ENODEV;

View File

@@ -12,7 +12,7 @@
* (non hardware specific) changes to serial.c.
*
* The port is registered with the tty driver as minor device 64, and
* therefore other ports should should only use 65 upwards.
* therefore other ports should only use 65 upwards.
*
* Richard Lucock 28/12/99
*
@@ -51,6 +51,7 @@
#include <linux/seq_file.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <linux/serial_core.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/slab.h>
@@ -283,12 +284,12 @@ static void transmit_chars(struct serial_state *info)
amiga_custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
mb();
info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
info->xmit.tail = info->xmit.tail & (UART_XMIT_SIZE - 1);
info->icount.tx++;
if (CIRC_CNT(info->xmit.head,
info->xmit.tail,
SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
UART_XMIT_SIZE) < WAKEUP_CHARS)
tty_wakeup(info->tport.tty);
#ifdef SERIAL_DEBUG_INTR
@@ -708,13 +709,13 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)
local_irq_save(flags);
if (CIRC_SPACE(info->xmit.head,
info->xmit.tail,
SERIAL_XMIT_SIZE) == 0) {
UART_XMIT_SIZE) == 0) {
local_irq_restore(flags);
return 0;
}
info->xmit.buf[info->xmit.head++] = ch;
info->xmit.head &= SERIAL_XMIT_SIZE-1;
info->xmit.head &= UART_XMIT_SIZE - 1;
local_irq_restore(flags);
return 1;
}
@@ -753,15 +754,14 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
while (1) {
c = CIRC_SPACE_TO_END(info->xmit.head,
info->xmit.tail,
SERIAL_XMIT_SIZE);
UART_XMIT_SIZE);
if (count < c)
c = count;
if (c <= 0) {
break;
}
memcpy(info->xmit.buf + info->xmit.head, buf, c);
info->xmit.head = ((info->xmit.head + c) &
(SERIAL_XMIT_SIZE-1));
info->xmit.head = (info->xmit.head + c) & (UART_XMIT_SIZE - 1);
buf += c;
count -= c;
ret += c;
@@ -788,14 +788,14 @@ static unsigned int rs_write_room(struct tty_struct *tty)
{
struct serial_state *info = tty->driver_data;
return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
return CIRC_SPACE(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE);
}
static unsigned int rs_chars_in_buffer(struct tty_struct *tty)
{
struct serial_state *info = tty->driver_data;
return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
return CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE);
}
static void rs_flush_buffer(struct tty_struct *tty)

View File

@@ -916,7 +916,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev)
mips_ejtag_fdc_write(priv, REG_FDCFG, cfg);
/* Make each port's xmit FIFO big enough to fill FDC TX FIFO */
priv->xmit_size = min(tx_fifo * 4, (unsigned int)SERIAL_XMIT_SIZE);
priv->xmit_size = min(tx_fifo * 4, (unsigned int)UART_XMIT_SIZE);
driver = tty_alloc_driver(NUM_TTY_CHANNELS, TTY_DRIVER_REAL_RAW);
if (IS_ERR(driver))
@@ -1222,7 +1222,7 @@ static void kgdbfdc_push_one(void)
/* Construct a word from any data in buffer */
word = mips_ejtag_fdc_encode(bufs, &kgdbfdc_wbuflen, 1);
/* Relocate any remaining data to beginnning of buffer */
/* Relocate any remaining data to beginning of buffer */
kgdbfdc_wbuflen -= word.bytes;
for (i = 0; i < kgdbfdc_wbuflen; ++i)
kgdbfdc_wbuf[i] = kgdbfdc_wbuf[i + word.bytes];

File diff suppressed because it is too large Load Diff

View File

@@ -118,6 +118,9 @@ struct n_tty_data {
size_t read_tail;
size_t line_start;
/* # of chars looked ahead (to find software flow control chars) */
size_t lookahead_count;
/* protected by output lock */
unsigned int column;
unsigned int canon_column;
@@ -333,6 +336,8 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
ldata->erasing = 0;
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
ldata->push = 0;
ldata->lookahead_count = 0;
}
static void n_tty_packet_mode_flush(struct tty_struct *tty)
@@ -1225,12 +1230,30 @@ static bool n_tty_is_char_flow_ctrl(struct tty_struct *tty, unsigned char c)
return c == START_CHAR(tty) || c == STOP_CHAR(tty);
}
/* Returns true if c is consumed as flow-control character */
static bool n_tty_receive_char_flow_ctrl(struct tty_struct *tty, unsigned char c)
/**
* n_tty_receive_char_flow_ctrl - receive flow control chars
* @tty: terminal device
* @c: character
* @lookahead_done: lookahead has processed this character already
*
* Receive and process flow control character actions.
*
* In case lookahead for flow control chars already handled the character in
* advance to the normal receive, the actions are skipped during normal
* receive.
*
* Returns true if @c is consumed as flow-control character, the character
* must not be treated as normal character.
*/
static bool n_tty_receive_char_flow_ctrl(struct tty_struct *tty, unsigned char c,
bool lookahead_done)
{
if (!n_tty_is_char_flow_ctrl(tty, c))
return false;
if (lookahead_done)
return true;
if (c == START_CHAR(tty)) {
start_tty(tty);
process_echoes(tty);
@@ -1242,11 +1265,12 @@ static bool n_tty_receive_char_flow_ctrl(struct tty_struct *tty, unsigned char c
return true;
}
static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c,
bool lookahead_done)
{
struct n_tty_data *ldata = tty->disc_data;
if (I_IXON(tty) && n_tty_receive_char_flow_ctrl(tty, c))
if (I_IXON(tty) && n_tty_receive_char_flow_ctrl(tty, c, lookahead_done))
return;
if (L_ISIG(tty)) {
@@ -1401,7 +1425,8 @@ static void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
put_tty_queue(c, ldata);
}
static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c)
static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c,
bool lookahead_done)
{
if (I_ISTRIP(tty))
c &= 0x7f;
@@ -1409,12 +1434,10 @@ static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c)
c = tolower(c);
if (I_IXON(tty)) {
if (c == STOP_CHAR(tty))
stop_tty(tty);
else if (c == START_CHAR(tty) ||
(tty->flow.stopped && !tty->flow.tco_stopped && I_IXANY(tty) &&
c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) &&
c != SUSP_CHAR(tty))) {
if (!n_tty_receive_char_flow_ctrl(tty, c, lookahead_done) &&
tty->flow.stopped && !tty->flow.tco_stopped && I_IXANY(tty) &&
c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) &&
c != SUSP_CHAR(tty)) {
start_tty(tty);
process_echoes(tty);
}
@@ -1457,6 +1480,27 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag)
n_tty_receive_char_flagged(tty, c, flag);
}
/* Caller must ensure count > 0 */
static void n_tty_lookahead_flow_ctrl(struct tty_struct *tty, const unsigned char *cp,
const unsigned char *fp, unsigned int count)
{
struct n_tty_data *ldata = tty->disc_data;
unsigned char flag = TTY_NORMAL;
ldata->lookahead_count += count;
if (!I_IXON(tty))
return;
while (count--) {
if (fp)
flag = *fp++;
if (likely(flag == TTY_NORMAL))
n_tty_receive_char_flow_ctrl(tty, *cp, false);
cp++;
}
}
static void
n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp,
const char *fp, int count)
@@ -1496,7 +1540,7 @@ n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp,
static void
n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp,
const char *fp, int count)
const char *fp, int count, bool lookahead_done)
{
char flag = TTY_NORMAL;
@@ -1504,12 +1548,12 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp,
if (fp)
flag = *fp++;
if (likely(flag == TTY_NORMAL))
n_tty_receive_char_closing(tty, *cp++);
n_tty_receive_char_closing(tty, *cp++, lookahead_done);
}
}
static void n_tty_receive_buf_standard(struct tty_struct *tty,
const unsigned char *cp, const char *fp, int count)
const unsigned char *cp, const char *fp, int count, bool lookahead_done)
{
struct n_tty_data *ldata = tty->disc_data;
char flag = TTY_NORMAL;
@@ -1540,7 +1584,7 @@ static void n_tty_receive_buf_standard(struct tty_struct *tty,
}
if (test_bit(c, ldata->char_map))
n_tty_receive_char_special(tty, c);
n_tty_receive_char_special(tty, c, lookahead_done);
else
n_tty_receive_char(tty, c);
}
@@ -1551,21 +1595,30 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
{
struct n_tty_data *ldata = tty->disc_data;
bool preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty));
size_t la_count = min_t(size_t, ldata->lookahead_count, count);
if (ldata->real_raw)
n_tty_receive_buf_real_raw(tty, cp, fp, count);
else if (ldata->raw || (L_EXTPROC(tty) && !preops))
n_tty_receive_buf_raw(tty, cp, fp, count);
else if (tty->closing && !L_EXTPROC(tty))
n_tty_receive_buf_closing(tty, cp, fp, count);
else {
n_tty_receive_buf_standard(tty, cp, fp, count);
else if (tty->closing && !L_EXTPROC(tty)) {
if (la_count > 0)
n_tty_receive_buf_closing(tty, cp, fp, la_count, true);
if (count > la_count)
n_tty_receive_buf_closing(tty, cp, fp, count - la_count, false);
} else {
if (la_count > 0)
n_tty_receive_buf_standard(tty, cp, fp, la_count, true);
if (count > la_count)
n_tty_receive_buf_standard(tty, cp, fp, count - la_count, false);
flush_echoes(tty);
if (tty->ops->flush_chars)
tty->ops->flush_chars(tty);
}
ldata->lookahead_count -= la_count;
if (ldata->icanon && !L_EXTPROC(tty))
return;
@@ -2446,6 +2499,7 @@ static struct tty_ldisc_ops n_tty_ops = {
.receive_buf = n_tty_receive_buf,
.write_wakeup = n_tty_write_wakeup,
.receive_buf2 = n_tty_receive_buf2,
.lookahead_buf = n_tty_lookahead_flow_ctrl,
};
/**

View File

@@ -123,6 +123,26 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value)
up->port.serial_out(&up->port, offset, value);
}
/**
* serial_lsr_in - Read LSR register and preserve flags across reads
* @up: uart 8250 port
*
* Read LSR register and handle saving non-preserved flags across reads.
* The flags that are not preserved across reads are stored into
* up->lsr_saved_flags.
*
* Returns LSR value or'ed with the preserved flags (if any).
*/
static inline u16 serial_lsr_in(struct uart_8250_port *up)
{
u16 lsr = up->lsr_saved_flags;
lsr |= serial_in(up, UART_LSR);
up->lsr_saved_flags = lsr & up->lsr_save_mask;
return lsr;
}
/*
* For the 16C950
*/
@@ -183,10 +203,12 @@ void serial8250_rpm_put(struct uart_8250_port *p);
void serial8250_rpm_get_tx(struct uart_8250_port *p);
void serial8250_rpm_put_tx(struct uart_8250_port *p);
int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485);
int serial8250_em485_config(struct uart_port *port, struct ktermios *termios,
struct serial_rs485 *rs485);
void serial8250_em485_start_tx(struct uart_8250_port *p);
void serial8250_em485_stop_tx(struct uart_8250_port *p);
void serial8250_em485_destroy(struct uart_8250_port *p);
extern struct serial_rs485 serial8250_em485_supported;
/* MCR <-> TIOCM conversion */
static inline int serial8250_TIOCM_to_MCR(int tiocm)

View File

@@ -108,6 +108,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
up.port.flags = UPF_SHARE_IRQ | 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;
up.rs485_stop_tx = bcm2835aux_rs485_stop_tx;
@@ -166,8 +167,10 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
uartclk = clk_get_rate(data->clk);
if (!uartclk) {
ret = device_property_read_u32(&pdev->dev, "clock-frequency", &uartclk);
if (ret)
return dev_err_probe(&pdev->dev, ret, "could not get clk rate\n");
if (ret) {
dev_err_probe(&pdev->dev, ret, "could not get clk rate\n");
goto dis_clk;
}
}
/* the HW-clock divider for bcm2835aux is 8,

Some files were not shown because too many files have changed in this diff Show More