TTY / Serial driver updates for 7.0-rc1

Here is the small amount of tty and serial driver updates for 7.0-rc1.
 Nothing major in here at all, just some driver updates and minor tweaks
 and cleanups including:
   - sh-sci serial driver updates
   - 8250 driver updates
   - attempt to make the tty ports have their own workqueue, but was
     reverted after testing found it to have problems on some platforms.
     This will probably come back for 7.1 after it has been reworked and
     resubmitted
   - other tiny tty driver changes
 
 All of these have been in linux-next for a while with no reported
 problems.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCaZR1VQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ykfsACghiyMgr0XKVDFEpV7/fPzocKH+o0An3v8knSi
 kLz/f6LstVsISqCxeT+9
 =uozB
 -----END PGP SIGNATURE-----

Merge tag 'tty-7.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 small amount of tty and serial driver updates for 7.0-rc1.
  Nothing major in here at all, just some driver updates and minor
  tweaks and cleanups including:

   - sh-sci serial driver updates

   - 8250 driver updates

   - attempt to make the tty ports have their own workqueue, but was
     reverted after testing found it to have problems on some platforms.

     This will probably come back for 7.1 after it has been reworked and
     resubmitted

   - other tiny tty driver changes

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

* tag 'tty-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (49 commits)
  Revert "tty: tty_port: add workqueue to flip TTY buffer"
  tty: tty_port: add workqueue to flip TTY buffer
  serial: 8250_pci: Remove custom deprecated baud setting routine
  serial: 8250_omap: Remove custom deprecated baud setting routine
  dt-bindings: serial: renesas,scif: Document RZ/G3L SoC
  serial: 8250: omap: set out-of-band wakeup if wakeup pinctrl exists
  tty: hvc-iucv: Remove KMSG_COMPONENT macro
  dt-bindings: serial: google,goldfish-tty: Convert to DT schema
  dt-bindings: serial: sh-sci: Fold single-entry compatibles into enum
  serial: 8250: 8250_omap.c: Clear DMA RX running status only after DMA termination is done
  serial: 8250: 8250_omap.c: Add support for handling UART error conditions
  serial: SH_SCI: improve "DMA support" prompt
  serial: Kconfig: fix ordering of entries for menu display
  serial: 8250: fix ordering of entries for menu display
  serial: imx: change SERIAL_IMX_CONSOLE to bool
  8250_men_mcb: drop unneeded MODULE_ALIAS
  serial: men_z135_uart: drop unneeded MODULE_ALIAS
  dt-bindings: serial: renesas,rsci: Document RZ/V2H(P) and RZ/V2N SoCs
  serial: rsci: Convert to FIELD_MODIFY()
  dt-bindings: serial: 8250: add SpacemiT K3 UART compatible
  ...
This commit is contained in:
Linus Torvalds 2026-02-17 09:30:52 -08:00
commit 3ad7945754
26 changed files with 801 additions and 419 deletions

View file

@ -1,17 +0,0 @@
Android Goldfish TTY
Android goldfish tty device generated by android emulator.
Required properties:
- compatible : should contain "google,goldfish-tty" to match emulator
- reg : <registers mapping>
- interrupts : <interrupt mapping>
Example:
goldfish_tty@1f004000 {
compatible = "google,goldfish-tty";
reg = <0x1f004000 0x1000>;
interrupts = <0xc>;
};

View file

@ -160,6 +160,7 @@ properties:
- enum:
- mrvl,mmp-uart
- spacemit,k1-uart
- spacemit,k3-uart
- const: intel,xscale-uart
- items:
- enum:

View file

@ -0,0 +1,41 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/serial/google,goldfish-tty.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Google Goldfish TTY
maintainers:
- Kuan-Wei Chiu <visitorckw@gmail.com>
allOf:
- $ref: /schemas/serial/serial.yaml#
description:
Android goldfish TTY device generated by Android emulator.
properties:
compatible:
const: google,goldfish-tty
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
examples:
- |
serial@1f004000 {
compatible = "google,goldfish-tty";
reg = <0x1f004000 0x1000>;
interrupts = <12>;
};

View file

@ -10,47 +10,79 @@ maintainers:
- Geert Uytterhoeven <geert+renesas@glider.be>
- Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
allOf:
- $ref: serial.yaml#
properties:
compatible:
oneOf:
- items:
- const: renesas,r9a09g087-rsci # RZ/N2H
- const: renesas,r9a09g077-rsci # RZ/T2H
- enum:
- renesas,r9a09g047-rsci # RZ/G3E
- renesas,r9a09g077-rsci # RZ/T2H
- items:
- enum:
- renesas,r9a09g056-rsci # RZ/V2N
- renesas,r9a09g057-rsci # RZ/V2H(P)
- const: renesas,r9a09g047-rsci
- items:
- const: renesas,r9a09g087-rsci # RZ/N2H
- const: renesas,r9a09g077-rsci # RZ/T2H
reg:
maxItems: 1
interrupts:
minItems: 4
items:
- description: Error interrupt
- description: Receive buffer full interrupt
- description: Transmit buffer empty interrupt
- description: Transmit end interrupt
- description: Active edge detection interrupt
- description: Break field detection interrupt
interrupt-names:
minItems: 4
items:
- const: eri
- const: rxi
- const: txi
- const: tei
- const: aed
- const: bfd
clocks:
minItems: 2
maxItems: 3
maxItems: 6
clock-names:
minItems: 2
items:
oneOf:
- items:
- const: operation
- const: bus
- const: sck # optional external clock input
minItems: 2
- items:
- const: pclk
- const: tclk
- const: tclk_div4
- const: tclk_div16
- const: tclk_div64
- const: sck # optional external clock input
minItems: 5
resets:
items:
- description: Input for resetting the APB clock
- description: Input for resetting TCLK
reset-names:
items:
- const: presetn
- const: tresetn
power-domains:
maxItems: 1
@ -62,6 +94,57 @@ required:
- clock-names
- power-domains
allOf:
- $ref: serial.yaml#
- if:
properties:
compatible:
contains:
const: renesas,r9a09g077-rsci
then:
properties:
interrupts:
maxItems: 4
interrupt-names:
maxItems: 4
clocks:
minItems: 2
maxItems: 3
clock-names:
minItems: 2
maxItems: 3
resets: false
- if:
properties:
compatible:
contains:
const: renesas,r9a09g047-rsci
then:
properties:
interrupts:
minItems: 6
interrupt-names:
minItems: 6
clocks:
minItems: 5
maxItems: 6
clock-names:
minItems: 5
maxItems: 6
required:
- resets
- reset-names
unevaluatedProperties: false
examples:

View file

@ -12,15 +12,16 @@ maintainers:
properties:
compatible:
oneOf:
- enum:
- renesas,scif-r7s9210 # RZ/A2
- renesas,scif-r9a07g044 # RZ/G2{L,LC}
- renesas,scif-r9a09g057 # RZ/V2H(P)
- items:
- enum:
- renesas,scif-r7s72100 # RZ/A1H
- const: renesas,scif # generic SCIF compatible UART
- items:
- enum:
- renesas,scif-r7s9210 # RZ/A2
- items:
- enum:
- renesas,scif-r8a7778 # R-Car M1
@ -76,19 +77,14 @@ properties:
- const: renesas,rcar-gen5-scif # R-Car Gen5
- const: renesas,scif # generic SCIF compatible UART
- items:
- enum:
- renesas,scif-r9a07g044 # RZ/G2{L,LC}
- items:
- enum:
- renesas,scif-r9a07g043 # RZ/G2UL and RZ/Five
- renesas,scif-r9a07g054 # RZ/V2L
- renesas,scif-r9a08g045 # RZ/G3S
- renesas,scif-r9a08g046 # RZ/G3L
- const: renesas,scif-r9a07g044 # RZ/G2{L,LC} fallback
- const: renesas,scif-r9a09g057 # RZ/V2H(P)
- items:
- enum:
- renesas,scif-r9a09g047 # RZ/G3E

View file

@ -89,31 +89,7 @@ With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX
limitation imposed by ``serial8250_get_baud_rate`` standard baud rates
below 300bps become unavailable in the regular way, e.g. the rate of
200bps requires the baud base to be divided by 78125 and that is beyond
the unsigned 16-bit range. The historic spd_cust feature can still be
used by encoding the values for, the prescaler, the oversampling rate
and the clock divisor (DLM/DLL) as follows to obtain such rates if so
required:
::
31 29 28 20 19 16 15 0
+-----+-----------------+-------+-------------------------------+
|0 0 0| CPR2:CPR | TCR | DLM:DLL |
+-----+-----------------+-------+-------------------------------+
Use a value such encoded for the ``custom_divisor`` field along with the
ASYNC_SPD_CUST flag set in the ``flags`` field in ``struct serial_struct``
passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8)
utility and its ``divisor`` and ``spd_cust`` parameters, and then select
the baud rate of 38400bps. Note that the value of 0 in TCR sets the
oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are
clamped by the driver to 1.
For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL
respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value,
the oversampling rate and the clock divisor of 62.500, 16 and 1250
respectively. These parameters will set the baud rate for the serial
port to 62500000 / 62.500 / 1250 / 16 = 50bps.
the unsigned 16-bit range.
Maciej W. Rozycki <macro@orcam.me.uk>

View file

@ -677,13 +677,6 @@ static const struct hci_uart_proto aml_hci_proto = {
.dequeue = aml_dequeue,
};
static void aml_device_driver_shutdown(struct device *dev)
{
struct aml_serdev *amldev = dev_get_drvdata(dev);
aml_power_off(amldev);
}
static int aml_serdev_probe(struct serdev_device *serdev)
{
struct aml_serdev *amldev;
@ -714,6 +707,13 @@ static void aml_serdev_remove(struct serdev_device *serdev)
hci_uart_unregister_device(&amldev->serdev_hu);
}
static void aml_serdev_shutdown(struct serdev_device *serdev)
{
struct aml_serdev *amldev = serdev_device_get_drvdata(serdev);
aml_power_off(amldev);
}
static const struct aml_device_data data_w155s2 = {
.iccm_offset = 256 * 1024,
};
@ -732,10 +732,10 @@ MODULE_DEVICE_TABLE(of, aml_bluetooth_of_match);
static struct serdev_device_driver aml_serdev_driver = {
.probe = aml_serdev_probe,
.remove = aml_serdev_remove,
.shutdown = aml_serdev_shutdown,
.driver = {
.name = "hci_uart_aml",
.of_match_table = aml_bluetooth_of_match,
.shutdown = aml_device_driver_shutdown,
},
};

View file

@ -2570,11 +2570,10 @@ static void qca_serdev_remove(struct serdev_device *serdev)
hci_uart_unregister_device(&qcadev->serdev_hu);
}
static void qca_serdev_shutdown(struct device *dev)
static void qca_serdev_shutdown(struct serdev_device *serdev)
{
int ret;
int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
struct serdev_device *serdev = to_serdev_device(dev);
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
struct hci_uart *hu = &qcadev->serdev_hu;
struct hci_dev *hdev = hu->hdev;
@ -2796,11 +2795,11 @@ static void hciqca_coredump(struct device *dev)
static struct serdev_device_driver qca_serdev_driver = {
.probe = qca_serdev_probe,
.remove = qca_serdev_remove,
.shutdown = qca_serdev_shutdown,
.driver = {
.name = "hci_uart_qca",
.of_match_table = of_match_ptr(qca_bluetooth_of_match),
.acpi_match_table = ACPI_PTR(qca_bluetooth_acpi_match),
.shutdown = qca_serdev_shutdown,
.pm = &qca_pm_ops,
#ifdef CONFIG_DEV_COREDUMP
.coredump = hciqca_coredump,

View file

@ -380,9 +380,9 @@ static int ssam_serdev_setup(struct acpi_device *ssh, struct serdev_device *serd
/* -- Power management. ----------------------------------------------------- */
static void ssam_serial_hub_shutdown(struct device *dev)
static void ssam_serial_hub_shutdown(struct serdev_device *serdev)
{
struct ssam_controller *c = dev_get_drvdata(dev);
struct ssam_controller *c = dev_get_drvdata(&serdev->dev);
int status;
/*
@ -834,12 +834,12 @@ MODULE_DEVICE_TABLE(of, ssam_serial_hub_of_match);
static struct serdev_device_driver ssam_serial_hub = {
.probe = ssam_serial_hub_probe,
.remove = ssam_serial_hub_remove,
.shutdown = ssam_serial_hub_shutdown,
.driver = {
.name = "surface_serial_hub",
.acpi_match_table = ACPI_PTR(ssam_serial_hub_acpi_match),
.of_match_table = of_match_ptr(ssam_serial_hub_of_match),
.pm = &ssam_serial_hub_pm_ops,
.shutdown = ssam_serial_hub_shutdown,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};

View file

@ -9,8 +9,7 @@
*
* Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
*/
#define KMSG_COMPONENT "hvc_iucv"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#define pr_fmt(fmt) "hvc_iucv: " fmt
#include <linux/types.h>
#include <linux/slab.h>
@ -1344,7 +1343,7 @@ static int __init hvc_iucv_init(void)
}
}
hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT,
hvc_iucv_buffer_cache = kmem_cache_create("hvc_iucv",
sizeof(struct iucv_tty_buffer),
0, 0, NULL);
if (!hvc_iucv_buffer_cache) {

View file

@ -127,6 +127,8 @@ struct n_hdlc_buf_list {
* @rx_buf_list: list of received frame buffers
* @tx_free_buf_list: list unused transmit frame buffers
* @rx_free_buf_list: list unused received frame buffers
* @write_work: work struct for deferred frame transmission
* @tty_for_write_work: pointer to tty instance used by the @write_work
*/
struct n_hdlc {
bool tbusy;

View file

@ -414,11 +414,21 @@ static void serdev_drv_remove(struct device *dev)
sdrv->remove(to_serdev_device(dev));
}
static void serdev_drv_shutdown(struct device *dev)
{
const struct serdev_device_driver *sdrv =
to_serdev_device_driver(dev->driver);
if (dev->driver && sdrv->shutdown)
sdrv->shutdown(to_serdev_device(dev));
}
static const struct bus_type serdev_bus_type = {
.name = "serial",
.match = serdev_device_match,
.probe = serdev_drv_probe,
.remove = serdev_drv_remove,
.shutdown = serdev_drv_shutdown,
};
/**
@ -814,6 +824,14 @@ void serdev_controller_remove(struct serdev_controller *ctrl)
}
EXPORT_SYMBOL_GPL(serdev_controller_remove);
static void serdev_legacy_shutdown(struct serdev_device *serdev)
{
struct device *dev = &serdev->dev;
struct device_driver *driver = dev->driver;
driver->shutdown(dev);
}
/**
* __serdev_device_driver_register() - Register client driver with serdev core
* @sdrv: client driver to be associated with client-device.
@ -830,6 +848,9 @@ int __serdev_device_driver_register(struct serdev_device_driver *sdrv, struct mo
/* force drivers to async probe so I/O is possible in probe */
sdrv->driver.probe_type = PROBE_PREFER_ASYNCHRONOUS;
if (!sdrv->shutdown && sdrv->driver.shutdown)
sdrv->shutdown = serdev_legacy_shutdown;
return driver_register(&sdrv->driver);
}
EXPORT_SYMBOL_GPL(__serdev_device_driver_register);

View file

@ -643,6 +643,10 @@ static int dw8250_probe(struct platform_device *pdev)
if (err)
return err;
err = pm_runtime_set_active(dev);
if (err)
return dev_err_probe(dev, err, "Failed to set the runtime suspend as active\n");
data->uart_16550_compatible = device_property_read_bool(dev, "snps,uart-16550-compatible");
data->pdata = device_get_match_data(p->dev);
@ -685,7 +689,6 @@ static int dw8250_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return 0;
@ -741,19 +744,25 @@ static int dw8250_runtime_suspend(struct device *dev)
static int dw8250_runtime_resume(struct device *dev)
{
int ret;
struct dw8250_data *data = dev_get_drvdata(dev);
clk_prepare_enable(data->pclk);
ret = clk_prepare_enable(data->pclk);
if (ret)
return ret;
clk_prepare_enable(data->clk);
ret = clk_prepare_enable(data->clk);
if (ret) {
clk_disable_unprepare(data->pclk);
return ret;
}
return 0;
}
static const struct dev_pm_ops dw8250_pm_ops = {
SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume)
RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
};
static _DEFINE_DEV_PM_OPS(dw8250_pm_ops, dw8250_suspend, dw8250_resume,
dw8250_runtime_suspend, dw8250_runtime_resume,
NULL);
static const struct dw8250_platform_data dw8250_dw_apb = {
.usr_reg = DW_UART_USR,

View file

@ -6,10 +6,18 @@
*/
#include <linux/auxiliary_bus.h>
#include <linux/device.h>
#include <linux/bits.h>
#include <linux/container_of.h>
#include <linux/dev_printk.h>
#include <linux/device/devres.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/misc/keba.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/serial_core.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include "8250.h"
@ -43,6 +51,10 @@ enum kuart_mode {
#define KUART_CAPABILITY_RS232 BIT(KUART_MODE_RS232)
#define KUART_CAPABILITY_MASK GENMASK(3, 0)
/* registers for Indexed Control Register access in enhanced mode */
#define KUART_EMODE_ICR_OFFSET UART_SCR
#define KUART_EMODE_ICR_VALUE UART_LSR
/* Additional Control Register DTR line configuration */
#define UART_ACR_DTRLC_MASK 0x18
#define UART_ACR_DTRLC_COMPAT 0x00
@ -90,13 +102,13 @@ static void kuart_dtr_line_config(struct uart_8250_port *up, u8 dtrlc)
u8 acr;
/* set index register to 0 to access ACR register */
serial_out(up, UART_SCR, UART_ACR);
serial_out(up, KUART_EMODE_ICR_OFFSET, UART_ACR);
/* set value register to 0x10 writing DTR mode (1,0) */
acr = serial_in(up, UART_LSR);
acr = serial_in(up, KUART_EMODE_ICR_VALUE);
acr &= ~UART_ACR_DTRLC_MASK;
acr |= dtrlc;
serial_out(up, UART_LSR, acr);
serial_out(up, KUART_EMODE_ICR_VALUE, acr);
}
static int kuart_rs485_config(struct uart_port *port, struct ktermios *termios,
@ -240,10 +252,9 @@ static int kuart_probe(struct auxiliary_device *auxdev,
}
retval = serial8250_register_8250_port(&uart);
if (retval < 0) {
dev_err(&auxdev->dev, "UART registration failed!\n");
return retval;
}
if (retval < 0)
return dev_err_probe(&auxdev->dev, retval,
"UART registration failed!\n");
kuart->line = retval;
return 0;

View file

@ -28,8 +28,6 @@
#define MEN_UART3_MASK 0x04
#define MEN_UART4_MASK 0x08
#define MEN_Z125_UARTS_AVAILABLE 0x01
#define MEN_Z025_MAX_UARTS 4
#define MEN_UART_MEM_SIZE 0x10
#define MEM_UART_REGISTER_SIZE 0x01
@ -42,12 +40,10 @@
#define MEN_READ_REGISTER(addr) readb(addr)
#define MAX_PORTS 4
struct serial_8250_men_mcb_data {
int num_ports;
int line[MAX_PORTS];
unsigned int offset[MAX_PORTS];
int line[MEN_Z025_MAX_UARTS];
unsigned int offset[MEN_Z025_MAX_UARTS];
};
/*
@ -126,7 +122,7 @@ static int read_serial_data(struct mcb_device *mdev,
if (res < 0)
return res;
for (i = 0; i < MAX_PORTS; i++) {
for (i = 0; i < MEN_Z025_MAX_UARTS; i++) {
mask = 0x1 << i;
switch (uarts_available & mask) {
case MEN_UART1_MASK:
@ -150,7 +146,7 @@ static int read_serial_data(struct mcb_device *mdev,
}
}
if (count <= 0 || count > MAX_PORTS) {
if (count <= 0 || count > MEN_Z025_MAX_UARTS) {
dev_err(&mdev->dev, "unexpected number of ports: %u\n",
count);
return -ENODEV;
@ -268,7 +264,4 @@ module_mcb_driver(mcb_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MEN 8250 UART driver");
MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
MODULE_ALIAS("mcb:16z125");
MODULE_ALIAS("mcb:16z025");
MODULE_ALIAS("mcb:16z057");
MODULE_IMPORT_NS("MCB");

View file

@ -100,6 +100,9 @@
#define OMAP_UART_REV_52 0x0502
#define OMAP_UART_REV_63 0x0603
/* Resume register */
#define UART_OMAP_RESUME 0x0B
/* Interrupt Enable Register 2 */
#define UART_OMAP_IER2 0x1B
#define UART_OMAP_IER2_RHR_IT_DIS BIT(2)
@ -119,7 +122,6 @@
/* Timeout low and High */
#define UART_OMAP_TO_L 0x26
#define UART_OMAP_TO_H 0x27
struct omap8250_priv {
void __iomem *membase;
int line;
@ -241,22 +243,6 @@ static void omap_8250_get_divisor(struct uart_port *port, unsigned int baud,
unsigned int div_13, div_16;
unsigned int abs_d13, abs_d16;
/*
* Old custom speed handling.
*/
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
priv->quot = port->custom_divisor & UART_DIV_MAX;
/*
* I assume that nobody is using this. But hey, if somebody
* would like to specify the divisor _and_ the mode then the
* driver is ready and waiting for it.
*/
if (port->custom_divisor & (1 << 16))
priv->mdr1 = UART_OMAP_MDR1_13X_MODE;
else
priv->mdr1 = UART_OMAP_MDR1_16X_MODE;
return;
}
div_13 = DIV_ROUND_CLOSEST(uartclk, 13 * baud);
div_16 = DIV_ROUND_CLOSEST(uartclk, 16 * baud);
@ -929,7 +915,6 @@ static void __dma_rx_do_complete(struct uart_8250_port *p)
goto out;
cookie = dma->rx_cookie;
dma->rx_running = 0;
/* Re-enable RX FIFO interrupt now that transfer is complete */
if (priv->habit & UART_HAS_RHR_IT_DIS) {
@ -963,6 +948,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p)
goto out;
ret = tty_insert_flip_string(tty_port, dma->rx_buf, count);
dma->rx_running = 0;
p->port.icount.rx += ret;
p->port.icount.buf_overrun += count - ret;
out:
@ -1256,6 +1242,20 @@ static u16 omap_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, u16 status
return status;
}
static void am654_8250_handle_uart_errors(struct uart_8250_port *up, u8 iir, u16 status)
{
if (status & UART_LSR_OE) {
serial8250_clear_and_reinit_fifos(up);
serial_in(up, UART_LSR);
serial_in(up, UART_OMAP_RESUME);
} else {
if (status & (UART_LSR_FE | UART_LSR_PE | UART_LSR_BI))
serial_in(up, UART_RX);
if (iir & UART_IIR_XOFF)
serial_in(up, UART_IIR);
}
}
static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
u16 status)
{
@ -1266,7 +1266,8 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
* Queue a new transfer if FIFO has data.
*/
if ((status & (UART_LSR_DR | UART_LSR_BI)) &&
(up->ier & UART_IER_RDI)) {
(up->ier & UART_IER_RDI) && !(status & UART_LSR_OE)) {
am654_8250_handle_uart_errors(up, iir, status);
omap_8250_rx_dma(up);
serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE);
} else if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) {
@ -1282,6 +1283,8 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
serial_out(up, UART_OMAP_EFR2, 0x0);
up->ier |= UART_IER_RLSI | UART_IER_RDI;
serial_out(up, UART_IER, up->ier);
} else {
am654_8250_handle_uart_errors(up, iir, status);
}
}
@ -1363,6 +1366,8 @@ static int omap8250_select_wakeup_pinctrl(struct device *dev,
if (!device_may_wakeup(dev))
return 0;
device_set_out_band_wakeup(dev);
return pinctrl_select_state(priv->pinctrl, priv->pinctrl_wakeup);
}

View file

@ -1205,16 +1205,6 @@ static unsigned int pci_oxsemi_tornado_get_divisor(struct uart_port *port,
u8 tcr;
int i;
/* Old custom speed handling. */
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
unsigned int cust_div = port->custom_divisor;
quot = cust_div & UART_DIV_MAX;
tcr = (cust_div >> 16) & OXSEMI_TORNADO_TCR_MASK;
cpr = (cust_div >> 20) & OXSEMI_TORNADO_CPR_MASK;
if (cpr < OXSEMI_TORNADO_CPR_MIN)
cpr = OXSEMI_TORNADO_CPR_DEF;
} else {
best_squot = quot_scale;
for (i = 0; i < ARRAY_SIZE(p); i++) {
unsigned int spre;
@ -1260,7 +1250,6 @@ static unsigned int pci_oxsemi_tornado_get_divisor(struct uart_port *port,
cpr = OXSEMI_TORNADO_CPR_MASK;
}
}
}
*frac = (cpr << 8) | (tcr & OXSEMI_TORNADO_TCR_MASK);
return quot;

View file

@ -116,6 +116,7 @@ config SERIAL_8250_DMA
config SERIAL_8250_PCILIB
bool
depends on SERIAL_8250 && PCI
config SERIAL_8250_PCI
tristate "8250/16550 PCI device support"
@ -205,6 +206,37 @@ config SERIAL_8250_EXTENDED
kernel: saying N will just cause the configurator to skip all
the questions about serial driver options. If unsure, say N.
config SERIAL_8250_SHARE_IRQ
bool "Support for sharing serial interrupts"
depends on SERIAL_8250_EXTENDED
help
Some serial boards have hardware support which allows multiple dumb
serial ports on the same board to share a single IRQ. To enable
support for this in the serial driver, say Y here.
config SERIAL_8250_DETECT_IRQ
bool "Autodetect IRQ on standard ports (unsafe)"
depends on SERIAL_8250_EXTENDED
help
Say Y here if you want the kernel to try to guess which IRQ
to use for your serial port.
This is considered unsafe; it is far better to configure the IRQ in
a boot script using the setserial command.
If unsure, say N.
config SERIAL_8250_RSA
bool "Support RSA serial ports"
depends on SERIAL_8250_EXTENDED
help
Say Y here if you have a IODATA RSA-DV II/S ISA card and
would like to use its >115kbps speeds.
You will need to provide module parameter "probe_rsa", or boot-time
parameter 8250.probe_rsa with I/O addresses of this card then.
If you don't have such card, or if unsure, say N.
config SERIAL_8250_MANY_PORTS
bool "Support more than 4 legacy serial ports"
depends on SERIAL_8250_EXTENDED
@ -240,19 +272,6 @@ config SERIAL_8250_ACCENT
To compile this driver as a module, choose M here: the module
will be called 8250_accent.
config SERIAL_8250_ASPEED_VUART
tristate "Aspeed Virtual UART"
depends on SERIAL_8250
depends on OF
depends on MFD_SYSCON
depends on ARCH_ASPEED || COMPILE_TEST
select REGMAP
help
If you want to use the virtual UART (VUART) device on Aspeed
BMC platforms, enable this option. This enables the 16550A-
compatible device on the local LPC bus, giving a UART device
with no physical RS232 connections.
config SERIAL_8250_BOCA
tristate "Support Boca cards"
depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
@ -293,44 +312,23 @@ config SERIAL_8250_PCI1XXXX
serial driver for the serial interface. This driver support
will ensure to support baud rates upto 1.5Mpbs.
config SERIAL_8250_ASPEED_VUART
tristate "Aspeed Virtual UART"
depends on SERIAL_8250
depends on OF
depends on MFD_SYSCON
depends on ARCH_ASPEED || COMPILE_TEST
select REGMAP
help
If you want to use the virtual UART (VUART) device on Aspeed
BMC platforms, enable this option. This enables the 16550A-
compatible device on the local LPC bus, giving a UART device
with no physical RS232 connections.
#
# Misc. options/drivers.
#
config SERIAL_8250_SHARE_IRQ
bool "Support for sharing serial interrupts"
depends on SERIAL_8250_EXTENDED
help
Some serial boards have hardware support which allows multiple dumb
serial ports on the same board to share a single IRQ. To enable
support for this in the serial driver, say Y here.
config SERIAL_8250_DETECT_IRQ
bool "Autodetect IRQ on standard ports (unsafe)"
depends on SERIAL_8250_EXTENDED
help
Say Y here if you want the kernel to try to guess which IRQ
to use for your serial port.
This is considered unsafe; it is far better to configure the IRQ in
a boot script using the setserial command.
If unsure, say N.
config SERIAL_8250_RSA
bool "Support RSA serial ports"
depends on SERIAL_8250_EXTENDED
help
Say Y here if you have a IODATA RSA-DV II/S ISA card and
would like to use its >115kbps speeds.
You will need to provide module parameter "probe_rsa", or boot-time
parameter 8250.probe_rsa with I/O addresses of this card then.
If you don't have such card, or if unsure, say N.
config SERIAL_8250_DWLIB
bool
config SERIAL_8250_ACORN
tristate "Acorn expansion card serial port support"
depends on ARCH_ACORN && SERIAL_8250
@ -596,3 +594,6 @@ config SERIAL_OF_PLATFORM
are probed through devicetree, including Open Firmware based
PowerPC systems and embedded systems on architectures using the
flattened device tree format.
config SERIAL_8250_DWLIB
bool

View file

@ -413,6 +413,10 @@ config SERIAL_21285_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
config SERIAL_PXA_NON8250
bool
depends on !SERIAL_8250 || COMPILE_TEST
config SERIAL_PXA
bool "PXA serial port support (DEPRECATED)"
depends on ARCH_PXA || ARCH_MMP
@ -426,10 +430,6 @@ config SERIAL_PXA
Unless you have a specific need, you should use SERIAL_8250_PXA
instead of this.
config SERIAL_PXA_NON8250
bool
depends on !SERIAL_8250 || COMPILE_TEST
config SERIAL_PXA_CONSOLE
bool "Console on PXA serial port (DEPRECATED)"
depends on SERIAL_PXA
@ -486,14 +486,14 @@ config SERIAL_IMX
can enable its onboard serial port by enabling this option.
config SERIAL_IMX_CONSOLE
tristate "Console on IMX serial port"
bool "Console on IMX serial port"
depends on SERIAL_IMX
select SERIAL_CORE_CONSOLE
help
If you have enabled the serial port on the Freescale IMX
CPU you can make it the console by answering Y/M to this option.
CPU you can make it the console by answering Y to this option.
Even if you say Y/M here, the currently visible virtual console
Even if you say Y here, the currently visible virtual console
(/dev/tty0) will still be used as the system console by default, but
you can alter that using a kernel command line option such as
"console=ttymxc0". (Try "man bootparam" or see the documentation of
@ -671,7 +671,7 @@ config SERIAL_SH_SCI_EARLYCON
default ARCH_RENESAS
config SERIAL_SH_SCI_DMA
bool "DMA support" if EXPERT
bool "Support for DMA on SuperH SCI(F)" if EXPERT
depends on SERIAL_SH_SCI && DMA_ENGINE
default ARCH_RENESAS
@ -863,15 +863,15 @@ config SERIAL_ICOM
This driver can also be built as a module. If so, the module
will be called icom.
config HAS_TXX9_SERIAL
bool
config SERIAL_TXX9
bool "TMPTX39XX/49XX SIO support"
depends on HAS_TXX9_SERIAL
select SERIAL_CORE
default y
config HAS_TXX9_SERIAL
bool
config SERIAL_TXX9_NR_UARTS
int "Maximum number of TMPTX39XX/49XX SIO ports"
depends on SERIAL_TXX9
@ -1251,12 +1251,6 @@ config SERIAL_AR933X_NR_UARTS
Set this to the number of serial ports you want the driver
to support.
config SERIAL_MPS2_UART_CONSOLE
bool "MPS2 UART console support"
depends on SERIAL_MPS2_UART
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
config SERIAL_MPS2_UART
bool "MPS2 UART port"
depends on ARCH_MPS2 || COMPILE_TEST
@ -1264,6 +1258,12 @@ config SERIAL_MPS2_UART
help
This driver support the UART ports on ARM MPS2.
config SERIAL_MPS2_UART_CONSOLE
bool "MPS2 UART console support"
depends on SERIAL_MPS2_UART
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
config SERIAL_ARC
tristate "ARC UART driver support"
select SERIAL_CORE

View file

@ -919,5 +919,4 @@ module_exit(men_z135_exit);
MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MEN 16z135 High Speed UART");
MODULE_ALIAS("mcb:16z135");
MODULE_IMPORT_NS("MCB");

View file

@ -11,6 +11,8 @@
#include <linux/serial_core.h>
#include <linux/serial_sci.h>
#include <linux/tty_flip.h>
#include "serial_mctrl_gpio.h"
#include "rsci.h"
MODULE_IMPORT_NS("SH_SCI");
@ -24,7 +26,6 @@ MODULE_IMPORT_NS("SH_SCI");
#define CCR3 0x14
#define CCR4 0x18
#define FCR 0x24
#define DCR 0x30
#define CSR 0x48
#define FRSR 0x50
#define FTSR 0x54
@ -36,12 +37,6 @@ MODULE_IMPORT_NS("SH_SCI");
#define RDR_FPER BIT(11) /* FIFO Parity Error */
#define RDR_RDAT_MSK GENMASK(8, 0)
/* TDR (Transmit Data Register) */
#define TDR_MPBT BIT(9) /* Multiprocessor Transfer */
#define TDR_TDAT_9BIT_LSHIFT 0
#define TDR_TDAT_9BIT_VAL 0x1FF
#define TDR_TDAT_9BIT_MSK (TDR_TDAT_9BIT_VAL << TDR_TDAT_9BIT_LSHIFT)
/* CCR0 (Common Control Register 0) */
#define CCR0_SSE BIT(24) /* SSn# Pin Function Enable */
#define CCR0_TEIE BIT(21) /* Transmit End Interrupt Enable */
@ -66,6 +61,41 @@ MODULE_IMPORT_NS("SH_SCI");
#define CCR1_CTSPEN BIT(1) /* CTS External Pin Enable */
#define CCR1_CTSE BIT(0) /* CTS Enable */
/* CCR2 (Common Control Register 2) */
#define CCR2_INIT 0xFF000004
#define CCR2_CKS_TCLK (0) /* TCLK clock */
#define CCR2_CKS_TCLK_DIV4 BIT(20) /* TCLK/4 clock */
#define CCR2_CKS_TCLK_DIV16 BIT(21) /* TCLK16 clock */
#define CCR2_CKS_TCLK_DIV64 (BIT(21) | BIT(20)) /* TCLK/64 clock */
#define CCR2_BRME BIT(16) /* Bitrate Modulation Enable */
#define CCR2_ABCSE BIT(6) /* Asynchronous Mode Extended Base Clock Select */
#define CCR2_ABCS BIT(5) /* Asynchronous Mode Base Clock Select */
#define CCR2_BGDM BIT(4) /* Baud Rate Generator Double-Speed Mode Select */
/* CCR3 (Common Control Register 3) */
#define CCR3_INIT 0x1203
#define CCR3_BLK BIT(29) /* Block Transfer Mode */
#define CCR3_GM BIT(28) /* GSM Mode */
#define CCR3_CKE1 BIT(25) /* Clock Enable 1 */
#define CCR3_CKE0 BIT(24) /* Clock Enable 0 */
#define CCR3_DEN BIT(21) /* Driver Enabled */
#define CCR3_FM BIT(20) /* FIFO Mode Select */
#define CCR3_MP BIT(19) /* Multi-Processor Mode */
#define CCR3_MOD_ASYNC 0 /* Asynchronous mode (Multi-processor mode) */
#define CCR3_MOD_IRDA BIT(16) /* Smart card interface mode */
#define CCR3_MOD_CLK_SYNC BIT(17) /* Clock synchronous mode */
#define CCR3_MOD_SPI (BIT(17) | BIT(16)) /* Simple SPI mode */
#define CCR3_MOD_I2C BIT(18) /* Simple I2C mode */
#define CCR3_RXDESEL BIT(15) /* Asynchronous Start Bit Edge Detection Select */
#define CCR3_STP BIT(14) /* Stop bit Length */
#define CCR3_SINV BIT(13) /* Transmitted/Received Data Invert */
#define CCR3_LSBF BIT(12) /* LSB First select */
#define CCR3_CHR1 BIT(9) /* Character Length */
#define CCR3_CHR0 BIT(8) /* Character Length */
#define CCR3_BPEN BIT(7) /* Synchronizer Bypass Enable */
#define CCR3_CPOL BIT(1) /* Clock Polarity Select */
#define CCR3_CPHA BIT(0) /* Clock Phase Select */
/* FCR (FIFO Control Register) */
#define FCR_RFRST BIT(23) /* Receive FIFO Data Register Reset */
#define FCR_TFRST BIT(15) /* Transmit FIFO Data Register Reset */
@ -119,8 +149,6 @@ MODULE_IMPORT_NS("SH_SCI");
/* FFCLR (FIFO Flag CLear Register) */
#define FFCLR_DRC BIT(0) /* DR Clear */
#define DCR_DEPOL BIT(0)
static u32 rsci_serial_in(struct uart_port *p, int offset)
{
return readl(p->membase + offset);
@ -137,10 +165,6 @@ static void rsci_clear_DRxC(struct uart_port *port)
rsci_serial_out(port, FFCLR, FFCLR_DRC);
}
static void rsci_clear_SCxSR(struct uart_port *port, unsigned int mask)
{
rsci_serial_out(port, CFCLR, mask);
}
static void rsci_start_rx(struct uart_port *port)
{
@ -151,21 +175,160 @@ static void rsci_start_rx(struct uart_port *port)
rsci_serial_out(port, CCR0, ctrl);
}
static void rsci_enable_ms(struct uart_port *port)
{
mctrl_gpio_enable_ms(to_sci_port(port)->gpios);
}
static void rsci_init_pins(struct uart_port *port, unsigned int cflag)
{
struct sci_port *s = to_sci_port(port);
/* Use port-specific handler if provided */
if (s->cfg->ops && s->cfg->ops->init_pins) {
s->cfg->ops->init_pins(port, cflag);
return;
}
if (!s->has_rtscts)
return;
if (s->autorts)
rsci_serial_out(port, CCR1, rsci_serial_in(port, CCR1) |
CCR1_CTSE | CCR1_CTSPEN);
}
static int rsci_scif_set_rtrg(struct uart_port *port, int rx_trig)
{
u32 fcr = rsci_serial_in(port, FCR);
if (rx_trig >= port->fifosize)
rx_trig = port->fifosize - 1;
else if (rx_trig < 1)
rx_trig = 0;
FIELD_MODIFY(FCR_RTRG4_0, &fcr, rx_trig);
rsci_serial_out(port, FCR, fcr);
return rx_trig;
}
static void rsci_set_termios(struct uart_port *port, struct ktermios *termios,
const struct ktermios *old)
{
unsigned int ccr2_val = CCR2_INIT, ccr3_val = CCR3_INIT;
unsigned int ccr0_val = 0, ccr1_val = 0, ccr4_val = 0;
unsigned int brr1 = 255, cks1 = 0, srr1 = 15;
struct sci_port *s = to_sci_port(port);
unsigned int brr = 255, cks = 0;
int min_err = INT_MAX, err;
unsigned long max_freq = 0;
unsigned int baud, i;
unsigned long flags;
unsigned int ctrl;
int best_clk = -1;
if ((termios->c_cflag & CSIZE) == CS7) {
ccr3_val |= CCR3_CHR0;
} else {
termios->c_cflag &= ~CSIZE;
termios->c_cflag |= CS8;
}
if (termios->c_cflag & PARENB)
ccr1_val |= CCR1_PE;
if (termios->c_cflag & PARODD)
ccr1_val |= (CCR1_PE | CCR1_PM);
if (termios->c_cflag & CSTOPB)
ccr3_val |= CCR3_STP;
/* Enable noise filter function */
ccr1_val |= CCR1_NFEN;
/*
* earlyprintk comes here early on with port->uartclk set to zero.
* the clock framework is not up and running at this point so here
* we assume that 115200 is the maximum baud rate. please note that
* the baud rate is not programmed during earlyprintk - it is assumed
* that the previous boot loader has enabled required clocks and
* setup the baud rate generator hardware for us already.
*/
if (!port->uartclk) {
max_freq = 115200;
} else {
for (i = 0; i < SCI_NUM_CLKS; i++)
max_freq = max(max_freq, s->clk_rates[i]);
max_freq /= min_sr(s);
}
baud = uart_get_baud_rate(port, termios, old, 0, max_freq);
if (!baud)
goto done;
/* Divided Functional Clock using standard Bit Rate Register */
err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1);
if (abs(err) < abs(min_err)) {
best_clk = SCI_FCK;
ccr0_val = 0;
min_err = err;
brr = brr1;
cks = cks1;
}
done:
if (best_clk >= 0)
dev_dbg(port->dev, "Using clk %pC for %u%+d bps\n",
s->clks[best_clk], baud, min_err);
sci_port_enable(s);
uart_port_lock_irqsave(port, &flags);
/* For now, only RX enabling is supported */
if (termios->c_cflag & CREAD)
uart_update_timeout(port, termios->c_cflag, baud);
rsci_serial_out(port, CCR0, ccr0_val);
ccr3_val |= CCR3_FM;
rsci_serial_out(port, CCR3, ccr3_val);
ccr2_val |= (cks << 20) | (brr << 8);
rsci_serial_out(port, CCR2, ccr2_val);
rsci_serial_out(port, CCR1, ccr1_val);
rsci_serial_out(port, CCR4, ccr4_val);
ctrl = rsci_serial_in(port, FCR);
ctrl |= (FCR_RFRST | FCR_TFRST);
rsci_serial_out(port, FCR, ctrl);
if (s->rx_trigger > 1)
rsci_scif_set_rtrg(port, s->rx_trigger);
port->status &= ~UPSTAT_AUTOCTS;
s->autorts = false;
if ((port->flags & UPF_HARD_FLOW) && (termios->c_cflag & CRTSCTS)) {
port->status |= UPSTAT_AUTOCTS;
s->autorts = true;
}
rsci_init_pins(port, termios->c_cflag);
rsci_serial_out(port, CFCLR, CFCLR_CLRFLAG);
rsci_serial_out(port, FFCLR, FFCLR_DRC);
ccr0_val |= CCR0_RE;
rsci_serial_out(port, CCR0, ccr0_val);
if ((termios->c_cflag & CREAD) != 0)
rsci_start_rx(port);
uart_port_unlock_irqrestore(port, flags);
sci_port_disable(s);
if (UART_ENABLE_MS(port, termios->c_cflag))
rsci_enable_ms(port);
}
static int rsci_txfill(struct uart_port *port)
@ -190,13 +353,34 @@ static unsigned int rsci_tx_empty(struct uart_port *port)
static void rsci_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
/* Not supported yet */
if (mctrl & TIOCM_LOOP) {
/* Standard loopback mode */
rsci_serial_out(port, CCR1, rsci_serial_in(port, CCR1) | CCR1_SPLP);
}
}
static unsigned int rsci_get_mctrl(struct uart_port *port)
{
/* Not supported yet */
return 0;
struct sci_port *s = to_sci_port(port);
struct mctrl_gpios *gpios = s->gpios;
unsigned int mctrl = 0;
mctrl_gpio_get(gpios, &mctrl);
/*
* CTS/RTS is handled in hardware when supported, while nothing
* else is wired up.
*/
if (!mctrl_gpio_to_gpiod(gpios, UART_GPIO_CTS))
mctrl |= TIOCM_CTS;
if (!mctrl_gpio_to_gpiod(gpios, UART_GPIO_DSR))
mctrl |= TIOCM_DSR;
if (!mctrl_gpio_to_gpiod(gpios, UART_GPIO_DCD))
mctrl |= TIOCM_CAR;
return mctrl;
}
static void rsci_clear_CFC(struct uart_port *port, unsigned int mask)
@ -326,7 +510,8 @@ static void rsci_receive_chars(struct uart_port *port)
continue;
}
/* Store data and status.
/*
* Store data and status.
* Non FIFO mode is not supported
*/
if (rdat & RDR_FFER) {
@ -360,6 +545,28 @@ static void rsci_receive_chars(struct uart_port *port)
}
}
static void rsci_break_ctl(struct uart_port *port, int break_state)
{
unsigned short ccr0_val, ccr1_val;
unsigned long flags;
uart_port_lock_irqsave(port, &flags);
ccr1_val = rsci_serial_in(port, CCR1);
ccr0_val = rsci_serial_in(port, CCR0);
if (break_state == -1) {
ccr1_val = (ccr1_val | CCR1_SPB2IO) & ~CCR1_SPB2DT;
ccr0_val &= ~CCR0_TE;
} else {
ccr1_val = (ccr1_val | CCR1_SPB2DT) & ~CCR1_SPB2IO;
ccr0_val |= CCR0_TE;
}
rsci_serial_out(port, CCR1, ccr1_val);
rsci_serial_out(port, CCR0, ccr0_val);
uart_port_unlock_irqrestore(port, flags);
}
static void rsci_poll_put_char(struct uart_port *port, unsigned char c)
{
u32 status;
@ -375,18 +582,27 @@ static void rsci_poll_put_char(struct uart_port *port, unsigned char c)
}
rsci_serial_out(port, TDR, c);
done:
rsci_clear_SCxSR(port, CFCLR_TDREC);
rsci_clear_CFC(port, CFCLR_TDREC);
}
static void rsci_prepare_console_write(struct uart_port *port, u32 ctrl)
{
struct sci_port *s = to_sci_port(port);
u32 ctrl_temp =
s->params->param_bits->rxtx_enable | CCR0_TIE |
s->hscif_tot;
u32 ctrl_temp = s->params->param_bits->rxtx_enable;
if (s->type == RSCI_PORT_SCIF16)
ctrl_temp |= CCR0_TIE | s->hscif_tot;
rsci_serial_out(port, CCR0, ctrl_temp);
}
static void rsci_finish_console_write(struct uart_port *port, u32 ctrl)
{
/* First set TE = 0 and then restore the CCR0 value */
rsci_serial_out(port, CCR0, ctrl & ~CCR0_TE);
rsci_serial_out(port, CCR0, ctrl);
}
static const char *rsci_type(struct uart_port *port)
{
return "rsci";
@ -416,7 +632,18 @@ static const struct sci_port_params_bits rsci_port_param_bits = {
.poll_sent_bits = CSR_TDRE | CSR_TEND,
};
static const struct sci_port_params rsci_port_params = {
static const struct sci_port_params rsci_rzg3e_port_params = {
.fifosize = 32,
.overrun_reg = CSR,
.overrun_mask = CSR_ORER,
.sampling_rate_mask = SCI_SR(32),
.error_mask = RSCI_DEFAULT_ERROR_MASK,
.error_clear = RSCI_ERROR_CLEAR,
.param_bits = &rsci_port_param_bits,
.common_regs = &rsci_common_regs,
};
static const struct sci_port_params rsci_rzt2h_port_params = {
.fifosize = 16,
.overrun_reg = CSR,
.overrun_mask = CSR_ORER,
@ -434,6 +661,8 @@ static const struct uart_ops rsci_uart_ops = {
.start_tx = rsci_start_tx,
.stop_tx = rsci_stop_tx,
.stop_rx = rsci_stop_rx,
.enable_ms = rsci_enable_ms,
.break_ctl = rsci_break_ctl,
.startup = sci_startup,
.shutdown = sci_shutdown,
.set_termios = rsci_set_termios,
@ -448,31 +677,47 @@ static const struct uart_ops rsci_uart_ops = {
static const struct sci_port_ops rsci_port_ops = {
.read_reg = rsci_serial_in,
.write_reg = rsci_serial_out,
.clear_SCxSR = rsci_clear_SCxSR,
.clear_SCxSR = rsci_clear_CFC,
.transmit_chars = rsci_transmit_chars,
.receive_chars = rsci_receive_chars,
.poll_put_char = rsci_poll_put_char,
.prepare_console_write = rsci_prepare_console_write,
.finish_console_write = rsci_finish_console_write,
.suspend_regs_size = rsci_suspend_regs_size,
.set_rtrg = rsci_scif_set_rtrg,
.shutdown_complete = rsci_shutdown_complete,
};
struct sci_of_data of_sci_rsci_data = {
.type = SCI_PORT_RSCI,
struct sci_of_data of_rsci_rzg3e_data = {
.type = RSCI_PORT_SCIF32,
.ops = &rsci_port_ops,
.uart_ops = &rsci_uart_ops,
.params = &rsci_port_params,
.params = &rsci_rzg3e_port_params,
};
struct sci_of_data of_rsci_rzt2h_data = {
.type = RSCI_PORT_SCIF16,
.ops = &rsci_port_ops,
.uart_ops = &rsci_uart_ops,
.params = &rsci_rzt2h_port_params,
};
#ifdef CONFIG_SERIAL_SH_SCI_EARLYCON
static int __init rsci_early_console_setup(struct earlycon_device *device,
static int __init rsci_rzg3e_early_console_setup(struct earlycon_device *device,
const char *opt)
{
return scix_early_console_setup(device, &of_sci_rsci_data);
return scix_early_console_setup(device, &of_rsci_rzg3e_data);
}
OF_EARLYCON_DECLARE(rsci, "renesas,r9a09g077-rsci", rsci_early_console_setup);
static int __init rsci_rzt2h_early_console_setup(struct earlycon_device *device,
const char *opt)
{
return scix_early_console_setup(device, &of_rsci_rzt2h_data);
}
OF_EARLYCON_DECLARE(rsci, "renesas,r9a09g047-rsci", rsci_rzg3e_early_console_setup);
OF_EARLYCON_DECLARE(rsci, "renesas,r9a09g077-rsci", rsci_rzt2h_early_console_setup);
#endif /* CONFIG_SERIAL_SH_SCI_EARLYCON */

View file

@ -5,6 +5,7 @@
#include "sh-sci-common.h"
extern struct sci_of_data of_sci_rsci_data;
extern struct sci_of_data of_rsci_rzg3e_data;
extern struct sci_of_data of_rsci_rzt2h_data;
#endif /* __RSCI_H__ */

View file

@ -7,7 +7,8 @@
/* Private port IDs */
enum SCI_PORT_TYPE {
SCI_PORT_RSCI = BIT(7) | 0,
RSCI_PORT_SCIF16 = BIT(7) | 0,
RSCI_PORT_SCIF32 = BIT(7) | 1,
};
enum SCI_CLKS {
@ -15,6 +16,9 @@ enum SCI_CLKS {
SCI_SCK, /* Optional External Clock */
SCI_BRG_INT, /* Optional BRG Internal Clock Source */
SCI_SCIF_CLK, /* Optional BRG External Clock Source */
SCI_FCK_DIV4, /* Optional Functional Clock frequency-divided by 4 */
SCI_FCK_DIV16, /* Optional Functional Clock frequency-divided by 16 */
SCI_FCK_DIV64, /* Optional Functional Clock frequency-divided by 64 */
SCI_NUM_CLKS
};
@ -89,6 +93,7 @@ struct sci_port_ops {
void (*shutdown_complete)(struct uart_port *port);
void (*prepare_console_write)(struct uart_port *port, u32 ctrl);
void (*finish_console_write)(struct uart_port *port, u32 ctrl);
void (*console_save)(struct uart_port *port);
void (*console_restore)(struct uart_port *port);
size_t (*suspend_regs_size)(void);
@ -165,6 +170,9 @@ void sci_port_enable(struct sci_port *sci_port);
int sci_startup(struct uart_port *port);
void sci_shutdown(struct uart_port *port);
int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr,
unsigned int *srr, unsigned int *cks);
#define min_sr(_port) ffs((_port)->sampling_rate_mask)
#define max_sr(_port) fls((_port)->sampling_rate_mask)

View file

@ -1182,6 +1182,11 @@ static int sci_handle_errors(struct uart_port *port)
return copied;
}
static bool sci_is_rsci_type(u8 type)
{
return (type == RSCI_PORT_SCIF16 || type == RSCI_PORT_SCIF32);
}
static int sci_handle_fifo_overrun(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
@ -1190,7 +1195,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
int copied = 0;
u32 status;
if (s->type != SCI_PORT_RSCI) {
if (!sci_is_rsci_type(s->type)) {
reg = sci_getreg(port, s->params->overrun_reg);
if (!reg->size)
return 0;
@ -1198,7 +1203,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
status = s->ops->read_reg(port, s->params->overrun_reg);
if (status & s->params->overrun_mask) {
if (s->type == SCI_PORT_RSCI) {
if (sci_is_rsci_type(s->type)) {
/*
* All of the CFCLR_*C clearing bits match the corresponding
* CSR_*status bits. So, reuse the overrun mask for clearing.
@ -2015,7 +2020,7 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
unsigned long flags;
u32 ctrl;
if (s->type != PORT_SCI && s->type != SCI_PORT_RSCI)
if (s->type != PORT_SCI && !sci_is_rsci_type(s->type))
return sci_tx_interrupt(irq, ptr);
uart_port_lock_irqsave(port, &flags);
@ -2568,9 +2573,8 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps,
}
/* calculate sample rate, BRR, and clock select */
static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
unsigned int *brr, unsigned int *srr,
unsigned int *cks)
int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr,
unsigned int *srr, unsigned int *cks)
{
unsigned long freq = s->clk_rates[SCI_FCK];
unsigned int sr, br, prediv, scrate, c;
@ -2634,6 +2638,7 @@ found:
min_err, *brr, *srr + 1, *cks);
return min_err;
}
EXPORT_SYMBOL_NS_GPL(sci_scbrr_calc, "SH_SCI");
static void sci_reset(struct uart_port *port)
{
@ -3167,15 +3172,21 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
[SCI_SCK] = "sck",
[SCI_BRG_INT] = "brg_int",
[SCI_SCIF_CLK] = "scif_clk",
[SCI_FCK_DIV4] = "tclk_div4",
[SCI_FCK_DIV16] = "tclk_div16",
[SCI_FCK_DIV64] = "tclk_div64",
};
struct clk *clk;
unsigned int i;
if (sci_port->type == PORT_HSCIF) {
clk_names[SCI_SCK] = "hsck";
} else if (sci_port->type == SCI_PORT_RSCI) {
} else if (sci_port->type == RSCI_PORT_SCIF16) {
clk_names[SCI_FCK] = "operation";
clk_names[SCI_BRG_INT] = "bus";
} else if (sci_port->type == RSCI_PORT_SCIF32) {
clk_names[SCI_FCK] = "tclk";
clk_names[SCI_BRG_INT] = "pclk";
}
for (i = 0; i < SCI_NUM_CLKS; i++) {
@ -3185,12 +3196,13 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
if (IS_ERR(clk))
return PTR_ERR(clk);
if (!clk && sci_port->type == SCI_PORT_RSCI &&
(i == SCI_FCK || i == SCI_BRG_INT)) {
return dev_err_probe(dev, -ENODEV,
"failed to get %s\n",
name);
}
if (!clk && sci_port->type == RSCI_PORT_SCIF16 &&
(i == SCI_FCK || i == SCI_BRG_INT))
return dev_err_probe(dev, -ENODEV, "failed to get %s\n", name);
if (!clk && sci_port->type == RSCI_PORT_SCIF32 &&
(i != SCI_SCK && i != SCI_SCIF_CLK))
return dev_err_probe(dev, -ENODEV, "failed to get %s\n", name);
if (!clk && i == SCI_FCK) {
/*
@ -3200,16 +3212,13 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
*/
clk = devm_clk_get(dev, "peripheral_clk");
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk),
"failed to get %s\n",
name);
return dev_err_probe(dev, PTR_ERR(clk), "failed to get %s\n", name);
}
if (!clk)
dev_dbg(dev, "failed to get %s\n", name);
else
dev_dbg(dev, "clk %s is %pC rate %lu\n", name,
clk, clk_get_rate(clk));
dev_dbg(dev, "clk %s is %pC rate %lu\n", name, clk, clk_get_rate(clk));
sci_port->clks[i] = clk;
}
return 0;
@ -3295,7 +3304,7 @@ static int sci_init_single(struct platform_device *dev,
* The fourth interrupt on SCI and RSCI port is transmit end interrupt, so
* shuffle the interrupts.
*/
if (p->type == PORT_SCI || p->type == SCI_PORT_RSCI)
if (p->type == PORT_SCI || sci_is_rsci_type(p->type))
swap(sci_port->irqs[SCIx_BRI_IRQ], sci_port->irqs[SCIx_TEI_IRQ]);
/* The SCI generates several interrupts. They can be muxed together or
@ -3320,6 +3329,7 @@ static int sci_init_single(struct platform_device *dev,
sci_port->rx_trigger = 64;
break;
case PORT_SCIFA:
case RSCI_PORT_SCIF32:
sci_port->rx_trigger = 32;
break;
case PORT_SCIF:
@ -3329,8 +3339,8 @@ static int sci_init_single(struct platform_device *dev,
else
sci_port->rx_trigger = 8;
break;
case SCI_PORT_RSCI:
sci_port->rx_trigger = 15;
case RSCI_PORT_SCIF16:
sci_port->rx_trigger = 16;
break;
default:
sci_port->rx_trigger = 1;
@ -3422,6 +3432,9 @@ static void serial_console_write(struct console *co, const char *s,
cpu_relax();
/* restore the SCSCR */
if (sci_port->ops->finish_console_write)
sci_port->ops->finish_console_write(port, ctrl);
else
sci_port->ops->write_reg(port, regs->control, ctrl);
if (locked)
@ -3549,16 +3562,14 @@ static struct uart_driver sci_uart_driver = {
static void sci_remove(struct platform_device *dev)
{
struct sci_port *s = platform_get_drvdata(dev);
unsigned int type = s->type; /* uart_remove_... clears it */
sci_ports_in_use &= ~BIT(s->port.line);
uart_remove_one_port(&sci_uart_driver, &s->port);
if (s->port.fifosize > 1)
if (s->port.fifosize > 1) {
device_remove_file(&dev->dev, &dev_attr_rx_fifo_trigger);
if (type == PORT_SCIFA || type == PORT_SCIFB || type == PORT_HSCIF ||
type == SCI_PORT_RSCI)
device_remove_file(&dev->dev, &dev_attr_rx_fifo_timeout);
}
}
static const struct sci_of_data of_sci_scif_sh2 = {
@ -3652,9 +3663,13 @@ static const struct of_device_id of_sci_match[] __maybe_unused = {
.data = &of_sci_scif_rzv2h,
},
#ifdef CONFIG_SERIAL_RSCI
{
.compatible = "renesas,r9a09g047-rsci",
.data = &of_rsci_rzg3e_data,
},
{
.compatible = "renesas,r9a09g077-rsci",
.data = &of_sci_rsci_data,
.data = &of_rsci_rzt2h_data,
},
#endif /* CONFIG_SERIAL_RSCI */
/* Family-specific types */
@ -3716,7 +3731,7 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
data = of_device_get_match_data(&pdev->dev);
rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
rstc = devm_reset_control_array_get_optional_exclusive(&pdev->dev);
if (IS_ERR(rstc))
return ERR_PTR(dev_err_probe(&pdev->dev, PTR_ERR(rstc),
"failed to get reset ctrl\n"));
@ -3917,15 +3932,10 @@ static int sci_probe(struct platform_device *dev)
ret = device_create_file(&dev->dev, &dev_attr_rx_fifo_trigger);
if (ret)
return ret;
}
if (sp->type == PORT_SCIFA || sp->type == PORT_SCIFB ||
sp->type == PORT_HSCIF || sp->type == SCI_PORT_RSCI) {
ret = device_create_file(&dev->dev, &dev_attr_rx_fifo_timeout);
if (ret) {
if (sp->port.fifosize > 1) {
device_remove_file(&dev->dev,
&dev_attr_rx_fifo_trigger);
}
device_remove_file(&dev->dev, &dev_attr_rx_fifo_trigger);
return ret;
}
}

View file

@ -1649,24 +1649,10 @@ int __init kbd_init(void)
/* Ioctl support code */
/**
* vt_do_diacrit - diacritical table updates
* @cmd: ioctl request
* @udp: pointer to user data for ioctl
* @perm: permissions check computed by caller
*
* Update the diacritical tables atomically and safely. Lock them
* against simultaneous keypresses
*/
int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
static int vt_do_kdgkbdiacr(void __user *udp)
{
int asize;
switch (cmd) {
case KDGKBDIACR:
{
struct kbdiacrs __user *a = udp;
int i;
int i, asize;
struct kbdiacr __free(kfree) *dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
GFP_KERNEL);
@ -1689,10 +1675,12 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
if (copy_to_user(a->kbdiacr, dia, asize * sizeof(struct kbdiacr)))
return -EFAULT;
return 0;
}
case KDGKBDIACRUC:
{
}
static int vt_do_kdgkbdiacruc(void __user *udp)
{
struct kbdiacrsuc __user *a = udp;
int asize;
void __free(kfree) *buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
GFP_KERNEL);
@ -1712,10 +1700,10 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
return -EFAULT;
return 0;
}
}
case KDSKBDIACR:
{
static int vt_do_kdskbdiacr(void __user *udp, int perm)
{
struct kbdiacrs __user *a = udp;
struct kbdiacr __free(kfree) *dia = NULL;
unsigned int ct;
@ -1747,10 +1735,10 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
}
return 0;
}
}
case KDSKBDIACRUC:
{
static int vt_do_kdskbdiacruc(void __user *udp, int perm)
{
struct kbdiacrsuc __user *a = udp;
unsigned int ct;
void __free(kfree) *buf = NULL;
@ -1776,7 +1764,28 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
ct * sizeof(struct kbdiacruc));
accent_table_size = ct;
return 0;
}
}
/**
* vt_do_diacrit - diacritical table updates
* @cmd: ioctl request
* @udp: pointer to user data for ioctl
* @perm: permissions check computed by caller
*
* Update the diacritical tables atomically and safely. Lock them
* against simultaneous keypresses
*/
int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
{
switch (cmd) {
case KDGKBDIACR:
return vt_do_kdgkbdiacr(udp);
case KDGKBDIACRUC:
return vt_do_kdgkbdiacruc(udp);
case KDSKBDIACR:
return vt_do_kdskbdiacr(udp, perm);
case KDSKBDIACRUC:
return vt_do_kdskbdiacruc(udp, perm);
}
return 0;
}

View file

@ -65,6 +65,7 @@ struct serdev_device_driver {
struct device_driver driver;
int (*probe)(struct serdev_device *);
void (*remove)(struct serdev_device *);
void (*shutdown)(struct serdev_device *);
};
static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d)