TTY / Serial patches for 5.15-rc1
Here is the "big" set of tty/serial driver patches for 5.15-rc1 Nothing major in here at all, just some driver updates and more cleanups on old tty apis and code that needed it that includes: - tty.h cleanup of things that didn't belong in it - other tty cleanups by Jiri - driver cleanups - rs485 support added to amba-pl011 driver - dts updates - stm32 serial driver updates - other minor fixes and driver updates All have been in linux-next for a while with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYS9/lg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylZNwCggKViEViSGqJFIafAZZjmI3Nt6tUAoMkRlhcd n1MS3snS0Sq+7BdJs37M =GyxP -----END PGP SIGNATURE----- Merge tag 'tty-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty / serial updates from Greg KH: "Here is the "big" set of tty/serial driver patches for 5.15-rc1 Nothing major in here at all, just some driver updates and more cleanups on old tty apis and code that needed it that includes: - tty.h cleanup of things that didn't belong in it - other tty cleanups by Jiri - driver cleanups - rs485 support added to amba-pl011 driver - dts updates - stm32 serial driver updates - other minor fixes and driver updates All have been in linux-next for a while with no reported problems" * tag 'tty-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (83 commits) tty: serial: uartlite: Use read_poll_timeout for a polling loop tty: serial: uartlite: Use constants in early_uartlite_putc tty: Fix data race between tiocsti() and flush_to_ldisc() serial: vt8500: Use of_device_get_match_data serial: tegra: Use of_device_get_match_data serial: 8250_ingenic: Use of_device_get_match_data tty: serial: linflexuart: Remove redundant check to simplify the code tty: serial: fsl_lpuart: do software reset for imx7ulp and imx8qxp tty: serial: fsl_lpuart: enable two stop bits for lpuart32 tty: serial: fsl_lpuart: fix the wrong mapbase value mxser: use semi-colons instead of commas tty: moxa: use semi-colons instead of commas tty: serial: fsl_lpuart: check dma_tx_in_progress in tx dma callback tty: replace in_irq() with in_hardirq() serial: sh-sci: fix break handling for sysrq serial: stm32: use devm_platform_get_and_ioremap_resource() serial: stm32: use the defined variable to simplify code Revert "arm pl011 serial: support multi-irq request" tty: serial: samsung: Add Exynos850 SoC data tty: serial: samsung: Fix driver data macros style ...
This commit is contained in:
commit
7c314bdfb6
|
@ -64,6 +64,12 @@ properties:
|
|||
- const: nuvoton,npcm750-uart
|
||||
- const: nvidia,tegra20-uart
|
||||
- const: nxp,lpc3220-uart
|
||||
- items:
|
||||
- enum:
|
||||
- exar,xr16l2552
|
||||
- exar,xr16l2551
|
||||
- exar,xr16l2550
|
||||
- const: ns8250
|
||||
- items:
|
||||
- enum:
|
||||
- altr,16550-FIFO32
|
||||
|
|
|
@ -79,6 +79,7 @@ properties:
|
|||
power-domains: true
|
||||
clock-frequency: true
|
||||
current-speed: true
|
||||
overrun-throttle-ms: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
Binding for Cadence UART Controller
|
||||
|
||||
Required properties:
|
||||
- compatible :
|
||||
Use "xlnx,xuartps","cdns,uart-r1p8" for Zynq-7xxx SoC.
|
||||
Use "xlnx,zynqmp-uart","cdns,uart-r1p12" for Zynq Ultrascale+ MPSoC.
|
||||
- reg: Should contain UART controller registers location and length.
|
||||
- interrupts: Should contain UART controller interrupts.
|
||||
- clocks: Must contain phandles to the UART clocks
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
- clock-names: Tuple to identify input clocks, must contain "uart_clk" and "pclk"
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
|
||||
|
||||
Optional properties:
|
||||
- cts-override : Override the CTS modem status signal. This signal will
|
||||
always be reported as active instead of being obtained from the modem status
|
||||
register. Define this if your serial port does not use this pin
|
||||
|
||||
Example:
|
||||
uart@e0000000 {
|
||||
compatible = "cdns,uart-r1p8";
|
||||
clocks = <&clkc 23>, <&clkc 40>;
|
||||
clock-names = "uart_clk", "pclk";
|
||||
reg = <0xE0000000 0x1000>;
|
||||
interrupts = <0 27 4>;
|
||||
};
|
|
@ -0,0 +1,66 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/serial/cdns,uart.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cadence UART Controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Michal Simek <michal.simek@xilinx.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/serial.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: UART controller for Zynq-7xxx SoC
|
||||
items:
|
||||
- const: xlnx,xuartps
|
||||
- const: cdns,uart-r1p8
|
||||
- description: UART controller for Zynq Ultrascale+ MPSoC
|
||||
items:
|
||||
- const: xlnx,zynqmp-uart
|
||||
- const: cdns,uart-r1p12
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: uart_clk
|
||||
- const: pclk
|
||||
|
||||
cts-override:
|
||||
description: |
|
||||
Override the CTS modem status signal. This signal will
|
||||
always be reported as active instead of being obtained
|
||||
from the modem status register. Define this if your serial
|
||||
port does not use this pin.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
uart0: serial@e0000000 {
|
||||
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
|
||||
clocks = <&clkc 23>, <&clkc 40>;
|
||||
clock-names = "uart_clk", "pclk";
|
||||
reg = <0xE0000000 0x1000>;
|
||||
interrupts = <0 27 4>;
|
||||
};
|
|
@ -15,6 +15,7 @@ Required properties:
|
|||
* "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
|
||||
|
|
|
@ -204,9 +204,9 @@ srmcons_init(void)
|
|||
struct tty_driver *driver;
|
||||
int err;
|
||||
|
||||
driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES);
|
||||
if (!driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(MAX_SRM_CONSOLE_DEVICES, 0);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
tty_port_init(&srmcons_singleton.port);
|
||||
|
||||
|
@ -221,7 +221,7 @@ srmcons_init(void)
|
|||
tty_port_link_device(&srmcons_singleton.port, driver, 0);
|
||||
err = tty_register_driver(driver);
|
||||
if (err) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
tty_port_destroy(&srmcons_singleton.port);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -120,35 +120,37 @@ early_param("debug", nf_debug_setup);
|
|||
|
||||
static int __init nfcon_init(void)
|
||||
{
|
||||
struct tty_driver *driver;
|
||||
int res;
|
||||
|
||||
stderr_id = nf_get_id("NF_STDERR");
|
||||
if (!stderr_id)
|
||||
return -ENODEV;
|
||||
|
||||
nfcon_tty_driver = alloc_tty_driver(1);
|
||||
if (!nfcon_tty_driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
tty_port_init(&nfcon_tty_port);
|
||||
|
||||
nfcon_tty_driver->driver_name = "nfcon";
|
||||
nfcon_tty_driver->name = "nfcon";
|
||||
nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY;
|
||||
nfcon_tty_driver->init_termios = tty_std_termios;
|
||||
nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
driver->driver_name = "nfcon";
|
||||
driver->name = "nfcon";
|
||||
driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
driver->subtype = SYSTEM_TYPE_TTY;
|
||||
driver->init_termios = tty_std_termios;
|
||||
|
||||
tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
|
||||
tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0);
|
||||
res = tty_register_driver(nfcon_tty_driver);
|
||||
tty_set_operations(driver, &nfcon_tty_ops);
|
||||
tty_port_link_device(&nfcon_tty_port, driver, 0);
|
||||
res = tty_register_driver(driver);
|
||||
if (res) {
|
||||
pr_err("failed to register nfcon tty driver\n");
|
||||
put_tty_driver(nfcon_tty_driver);
|
||||
tty_driver_kref_put(driver);
|
||||
tty_port_destroy(&nfcon_tty_port);
|
||||
return res;
|
||||
}
|
||||
|
||||
nfcon_tty_driver = driver;
|
||||
|
||||
if (!(nf_console.flags & CON_ENABLED))
|
||||
register_console(&nf_console);
|
||||
|
||||
|
@ -159,7 +161,7 @@ static void __exit nfcon_exit(void)
|
|||
{
|
||||
unregister_console(&nf_console);
|
||||
tty_unregister_driver(nfcon_tty_driver);
|
||||
put_tty_driver(nfcon_tty_driver);
|
||||
tty_driver_kref_put(nfcon_tty_driver);
|
||||
tty_port_destroy(&nfcon_tty_port);
|
||||
}
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ static struct tty_driver *pdc_console_tty_driver;
|
|||
|
||||
static int __init pdc_console_tty_driver_init(void)
|
||||
{
|
||||
struct tty_driver *driver;
|
||||
int err;
|
||||
|
||||
/* Check if the console driver is still registered.
|
||||
|
@ -160,31 +161,32 @@ static int __init pdc_console_tty_driver_init(void)
|
|||
printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
|
||||
pdc_cons.flags &= ~CON_BOOT;
|
||||
|
||||
pdc_console_tty_driver = alloc_tty_driver(1);
|
||||
|
||||
if (!pdc_console_tty_driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_RESET_TERMIOS);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
tty_port_init(&tty_port);
|
||||
|
||||
pdc_console_tty_driver->driver_name = "pdc_cons";
|
||||
pdc_console_tty_driver->name = "ttyB";
|
||||
pdc_console_tty_driver->major = MUX_MAJOR;
|
||||
pdc_console_tty_driver->minor_start = 0;
|
||||
pdc_console_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
pdc_console_tty_driver->init_termios = tty_std_termios;
|
||||
pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_RESET_TERMIOS;
|
||||
tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops);
|
||||
tty_port_link_device(&tty_port, pdc_console_tty_driver, 0);
|
||||
driver->driver_name = "pdc_cons";
|
||||
driver->name = "ttyB";
|
||||
driver->major = MUX_MAJOR;
|
||||
driver->minor_start = 0;
|
||||
driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
driver->init_termios = tty_std_termios;
|
||||
tty_set_operations(driver, &pdc_console_tty_ops);
|
||||
tty_port_link_device(&tty_port, driver, 0);
|
||||
|
||||
err = tty_register_driver(pdc_console_tty_driver);
|
||||
err = tty_register_driver(driver);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
|
||||
tty_port_destroy(&tty_port);
|
||||
tty_driver_kref_put(driver);
|
||||
return err;
|
||||
}
|
||||
|
||||
pdc_console_tty_driver = driver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(pdc_console_tty_driver_init);
|
||||
|
|
|
@ -538,12 +538,14 @@ int register_lines(struct line_driver *line_driver,
|
|||
const struct tty_operations *ops,
|
||||
struct line *lines, int nlines)
|
||||
{
|
||||
struct tty_driver *driver = alloc_tty_driver(nlines);
|
||||
struct tty_driver *driver;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
if (!driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(nlines, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
driver->driver_name = line_driver->name;
|
||||
driver->name = line_driver->device_name;
|
||||
|
@ -551,9 +553,8 @@ int register_lines(struct line_driver *line_driver,
|
|||
driver->minor_start = line_driver->minor_start;
|
||||
driver->type = line_driver->type;
|
||||
driver->subtype = line_driver->subtype;
|
||||
driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
driver->init_termios = tty_std_termios;
|
||||
|
||||
|
||||
for (i = 0; i < nlines; i++) {
|
||||
tty_port_init(&lines[i].port);
|
||||
lines[i].port.ops = &line_port_ops;
|
||||
|
@ -567,7 +568,7 @@ int register_lines(struct line_driver *line_driver,
|
|||
if (err) {
|
||||
printk(KERN_ERR "register_lines : can't register %s driver\n",
|
||||
line_driver->name);
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
for (i = 0; i < nlines; i++)
|
||||
tty_port_destroy(&lines[i].port);
|
||||
return err;
|
||||
|
|
|
@ -136,28 +136,41 @@ static const struct tty_operations serial_ops = {
|
|||
|
||||
static int __init rs_init(void)
|
||||
{
|
||||
tty_port_init(&serial_port);
|
||||
struct tty_driver *driver;
|
||||
int ret;
|
||||
|
||||
serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES);
|
||||
driver = tty_alloc_driver(SERIAL_MAX_NUM_LINES, TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
tty_port_init(&serial_port);
|
||||
|
||||
/* Initialize the tty_driver structure */
|
||||
|
||||
serial_driver->driver_name = "iss_serial";
|
||||
serial_driver->name = "ttyS";
|
||||
serial_driver->major = TTY_MAJOR;
|
||||
serial_driver->minor_start = 64;
|
||||
serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
serial_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
serial_driver->init_termios = tty_std_termios;
|
||||
serial_driver->init_termios.c_cflag =
|
||||
driver->driver_name = "iss_serial";
|
||||
driver->name = "ttyS";
|
||||
driver->major = TTY_MAJOR;
|
||||
driver->minor_start = 64;
|
||||
driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
driver->init_termios = tty_std_termios;
|
||||
driver->init_termios.c_cflag =
|
||||
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
serial_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
|
||||
tty_set_operations(serial_driver, &serial_ops);
|
||||
tty_port_link_device(&serial_port, serial_driver, 0);
|
||||
tty_set_operations(driver, &serial_ops);
|
||||
tty_port_link_device(&serial_port, driver, 0);
|
||||
|
||||
ret = tty_register_driver(driver);
|
||||
if (ret) {
|
||||
pr_err("Couldn't register serial driver\n");
|
||||
tty_driver_kref_put(driver);
|
||||
tty_port_destroy(&serial_port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
serial_driver = driver;
|
||||
|
||||
if (tty_register_driver(serial_driver))
|
||||
panic("Couldn't register serial driver\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -165,7 +178,7 @@ static int __init rs_init(void)
|
|||
static __exit void rs_exit(void)
|
||||
{
|
||||
tty_unregister_driver(serial_driver);
|
||||
put_tty_driver(serial_driver);
|
||||
tty_driver_kref_put(serial_driver);
|
||||
tty_port_destroy(&serial_port);
|
||||
}
|
||||
|
||||
|
|
|
@ -2841,7 +2841,7 @@ static int __init synclink_cs_init(void)
|
|||
err_unreg_tty:
|
||||
tty_unregister_driver(serial_driver);
|
||||
err_put_tty:
|
||||
put_tty_driver(serial_driver);
|
||||
tty_driver_kref_put(serial_driver);
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
@ -2850,7 +2850,7 @@ static void __exit synclink_cs_exit(void)
|
|||
{
|
||||
pcmcia_unregister_driver(&mgslpc_driver);
|
||||
tty_unregister_driver(serial_driver);
|
||||
put_tty_driver(serial_driver);
|
||||
tty_driver_kref_put(serial_driver);
|
||||
}
|
||||
|
||||
module_init(synclink_cs_init);
|
||||
|
|
|
@ -198,7 +198,7 @@ static int __init ttyprintk_init(void)
|
|||
return 0;
|
||||
|
||||
error:
|
||||
put_tty_driver(ttyprintk_driver);
|
||||
tty_driver_kref_put(ttyprintk_driver);
|
||||
tty_port_destroy(&tpk_port.port);
|
||||
return ret;
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ error:
|
|||
static void __exit ttyprintk_exit(void)
|
||||
{
|
||||
tty_unregister_driver(ttyprintk_driver);
|
||||
put_tty_driver(ttyprintk_driver);
|
||||
tty_driver_kref_put(ttyprintk_driver);
|
||||
tty_port_destroy(&tpk_port.port);
|
||||
}
|
||||
|
||||
|
|
|
@ -347,10 +347,10 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|||
/* Register the TTY device */
|
||||
|
||||
/* Each IP-OCTAL channel is a TTY port */
|
||||
tty = alloc_tty_driver(NR_CHANNELS);
|
||||
|
||||
if (!tty)
|
||||
return -ENOMEM;
|
||||
tty = tty_alloc_driver(NR_CHANNELS, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(tty))
|
||||
return PTR_ERR(tty);
|
||||
|
||||
/* Fill struct tty_driver with ipoctal data */
|
||||
tty->owner = THIS_MODULE;
|
||||
|
@ -362,7 +362,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|||
tty->minor_start = 0;
|
||||
tty->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
tty->subtype = SERIAL_TYPE_NORMAL;
|
||||
tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty->init_termios = tty_std_termios;
|
||||
tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
tty->init_termios.c_ispeed = 9600;
|
||||
|
@ -372,7 +371,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|||
res = tty_register_driver(tty);
|
||||
if (res) {
|
||||
dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
|
||||
put_tty_driver(tty);
|
||||
tty_driver_kref_put(tty);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -697,7 +696,7 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
|
|||
}
|
||||
|
||||
tty_unregister_driver(ipoctal->tty_drv);
|
||||
put_tty_driver(ipoctal->tty_drv);
|
||||
tty_driver_kref_put(ipoctal->tty_drv);
|
||||
kfree(ipoctal);
|
||||
}
|
||||
|
||||
|
|
|
@ -1269,10 +1269,11 @@ static int __init capinc_tty_init(void)
|
|||
if (!capiminors)
|
||||
return -ENOMEM;
|
||||
|
||||
drv = alloc_tty_driver(capi_ttyminors);
|
||||
if (!drv) {
|
||||
drv = tty_alloc_driver(capi_ttyminors, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(drv)) {
|
||||
kfree(capiminors);
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(drv);
|
||||
}
|
||||
drv->driver_name = "capi_nc";
|
||||
drv->name = "capi!";
|
||||
|
@ -1285,14 +1286,11 @@ static int __init capinc_tty_init(void)
|
|||
drv->init_termios.c_oflag = OPOST | ONLCR;
|
||||
drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
drv->init_termios.c_lflag = 0;
|
||||
drv->flags =
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS |
|
||||
TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_set_operations(drv, &capinc_ops);
|
||||
|
||||
err = tty_register_driver(drv);
|
||||
if (err) {
|
||||
put_tty_driver(drv);
|
||||
tty_driver_kref_put(drv);
|
||||
kfree(capiminors);
|
||||
printk(KERN_ERR "Couldn't register capi_nc driver\n");
|
||||
return err;
|
||||
|
@ -1304,7 +1302,7 @@ static int __init capinc_tty_init(void)
|
|||
static void __exit capinc_tty_exit(void)
|
||||
{
|
||||
tty_unregister_driver(capinc_tty_driver);
|
||||
put_tty_driver(capinc_tty_driver);
|
||||
tty_driver_kref_put(capinc_tty_driver);
|
||||
kfree(capiminors);
|
||||
}
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ int bcm_vk_tty_init(struct bcm_vk *vk, char *name)
|
|||
tty_drv->name = kstrdup(name, GFP_KERNEL);
|
||||
if (!tty_drv->name) {
|
||||
err = -ENOMEM;
|
||||
goto err_put_tty_driver;
|
||||
goto err_tty_driver_kref_put;
|
||||
}
|
||||
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
tty_drv->subtype = SERIAL_TYPE_NORMAL;
|
||||
|
@ -295,8 +295,8 @@ err_kfree_tty_name:
|
|||
kfree(tty_drv->name);
|
||||
tty_drv->name = NULL;
|
||||
|
||||
err_put_tty_driver:
|
||||
put_tty_driver(tty_drv);
|
||||
err_tty_driver_kref_put:
|
||||
tty_driver_kref_put(tty_drv);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ void bcm_vk_tty_exit(struct bcm_vk *vk)
|
|||
kfree(vk->tty_drv->name);
|
||||
vk->tty_drv->name = NULL;
|
||||
|
||||
put_tty_driver(vk->tty_drv);
|
||||
tty_driver_kref_put(vk->tty_drv);
|
||||
}
|
||||
|
||||
void bcm_vk_tty_terminate_tty_user(struct bcm_vk *vk)
|
||||
|
|
|
@ -1135,9 +1135,10 @@ static int __init sdio_uart_init(void)
|
|||
int ret;
|
||||
struct tty_driver *tty_drv;
|
||||
|
||||
sdio_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);
|
||||
if (!tty_drv)
|
||||
return -ENOMEM;
|
||||
sdio_uart_tty_driver = tty_drv = tty_alloc_driver(UART_NR,
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(tty_drv))
|
||||
return PTR_ERR(tty_drv);
|
||||
|
||||
tty_drv->driver_name = "sdio_uart";
|
||||
tty_drv->name = "ttySDIO";
|
||||
|
@ -1145,7 +1146,6 @@ static int __init sdio_uart_init(void)
|
|||
tty_drv->minor_start = 0;
|
||||
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
tty_drv->subtype = SERIAL_TYPE_NORMAL;
|
||||
tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_drv->init_termios = tty_std_termios;
|
||||
tty_drv->init_termios.c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
tty_drv->init_termios.c_ispeed = 4800;
|
||||
|
@ -1165,7 +1165,7 @@ static int __init sdio_uart_init(void)
|
|||
err2:
|
||||
tty_unregister_driver(tty_drv);
|
||||
err1:
|
||||
put_tty_driver(tty_drv);
|
||||
tty_driver_kref_put(tty_drv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1173,7 +1173,7 @@ static void __exit sdio_uart_exit(void)
|
|||
{
|
||||
sdio_unregister_driver(&sdio_uart_driver);
|
||||
tty_unregister_driver(sdio_uart_tty_driver);
|
||||
put_tty_driver(sdio_uart_tty_driver);
|
||||
tty_driver_kref_put(sdio_uart_tty_driver);
|
||||
}
|
||||
|
||||
module_init(sdio_uart_init);
|
||||
|
|
|
@ -3241,9 +3241,10 @@ static int __init hso_init(void)
|
|||
serial_table[i] = NULL;
|
||||
|
||||
/* allocate our driver using the proper amount of supported minors */
|
||||
tty_drv = alloc_tty_driver(HSO_SERIAL_TTY_MINORS);
|
||||
if (!tty_drv)
|
||||
return -ENOMEM;
|
||||
tty_drv = tty_alloc_driver(HSO_SERIAL_TTY_MINORS, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(tty_drv))
|
||||
return PTR_ERR(tty_drv);
|
||||
|
||||
/* fill in all needed values */
|
||||
tty_drv->driver_name = driver_name;
|
||||
|
@ -3256,7 +3257,6 @@ static int __init hso_init(void)
|
|||
tty_drv->minor_start = 0;
|
||||
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
tty_drv->subtype = SERIAL_TYPE_NORMAL;
|
||||
tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_drv->init_termios = tty_std_termios;
|
||||
hso_init_termios(&tty_drv->init_termios);
|
||||
tty_set_operations(tty_drv, &hso_serial_ops);
|
||||
|
@ -3281,7 +3281,7 @@ static int __init hso_init(void)
|
|||
err_unreg_tty:
|
||||
tty_unregister_driver(tty_drv);
|
||||
err_free_tty:
|
||||
put_tty_driver(tty_drv);
|
||||
tty_driver_kref_put(tty_drv);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -3292,7 +3292,7 @@ static void __exit hso_exit(void)
|
|||
tty_unregister_driver(tty_drv);
|
||||
/* deregister the usb driver */
|
||||
usb_deregister(&hso_driver);
|
||||
put_tty_driver(tty_drv);
|
||||
tty_driver_kref_put(tty_drv);
|
||||
}
|
||||
|
||||
/* Module definitions */
|
||||
|
|
|
@ -301,20 +301,13 @@ static acpi_status ssam_serdev_setup_via_acpi_crs(struct acpi_resource *rsc,
|
|||
void *ctx)
|
||||
{
|
||||
struct serdev_device *serdev = ctx;
|
||||
struct acpi_resource_common_serialbus *serial;
|
||||
struct acpi_resource_uart_serialbus *uart;
|
||||
bool flow_control;
|
||||
int status = 0;
|
||||
|
||||
if (rsc->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
|
||||
if (!serdev_acpi_get_uart_resource(rsc, &uart))
|
||||
return AE_OK;
|
||||
|
||||
serial = &rsc->data.common_serial_bus;
|
||||
if (serial->type != ACPI_RESOURCE_SERIAL_TYPE_UART)
|
||||
return AE_OK;
|
||||
|
||||
uart = &rsc->data.uart_serial_bus;
|
||||
|
||||
/* Set up serdev device. */
|
||||
serdev_device_set_baudrate(serdev, uart->default_baud_rate);
|
||||
|
||||
|
|
|
@ -1076,13 +1076,13 @@ static int __init tty3215_init(void)
|
|||
if (!CONSOLE_IS_3215)
|
||||
return 0;
|
||||
|
||||
driver = alloc_tty_driver(NR_3215);
|
||||
if (!driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(NR_3215, TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
ret = ccw_driver_register(&raw3215_ccw_driver);
|
||||
if (ret) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
|
@ -1101,11 +1101,10 @@ static int __init tty3215_init(void)
|
|||
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
|
||||
driver->init_termios.c_oflag = ONLCR;
|
||||
driver->init_termios.c_lflag = ISIG;
|
||||
driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
tty_set_operations(driver, &tty3215_ops);
|
||||
ret = tty_register_driver(driver);
|
||||
if (ret) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
return ret;
|
||||
}
|
||||
tty3215_driver = driver;
|
||||
|
|
|
@ -503,20 +503,20 @@ sclp_tty_init(void)
|
|||
return 0;
|
||||
if (!sclp.has_linemode)
|
||||
return 0;
|
||||
driver = alloc_tty_driver(1);
|
||||
if (!driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
rc = sclp_rw_init();
|
||||
if (rc) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
return rc;
|
||||
}
|
||||
/* Allocate pages for output buffering */
|
||||
for (i = 0; i < MAX_KMEM_PAGES; i++) {
|
||||
page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (page == NULL) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
return -ENOMEM;
|
||||
}
|
||||
list_add_tail((struct list_head *) page, &sclp_tty_pages);
|
||||
|
@ -532,7 +532,7 @@ sclp_tty_init(void)
|
|||
|
||||
rc = sclp_register(&sclp_input_event);
|
||||
if (rc) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -548,12 +548,11 @@ sclp_tty_init(void)
|
|||
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
|
||||
driver->init_termios.c_oflag = ONLCR;
|
||||
driver->init_termios.c_lflag = ISIG | ECHO;
|
||||
driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
tty_set_operations(driver, &sclp_ops);
|
||||
tty_port_link_device(&sclp_port, driver, 0);
|
||||
rc = tty_register_driver(driver);
|
||||
if (rc) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
tty_port_destroy(&sclp_port);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -732,9 +732,9 @@ static int __init sclp_vt220_tty_init(void)
|
|||
|
||||
/* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
|
||||
* symmetry between VM and LPAR systems regarding ttyS1. */
|
||||
driver = alloc_tty_driver(1);
|
||||
if (!driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
rc = __sclp_vt220_init(MAX_KMEM_PAGES);
|
||||
if (rc)
|
||||
goto out_driver;
|
||||
|
@ -746,7 +746,6 @@ static int __init sclp_vt220_tty_init(void)
|
|||
driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
driver->subtype = SYSTEM_TYPE_TTY;
|
||||
driver->init_termios = tty_std_termios;
|
||||
driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
tty_set_operations(driver, &sclp_vt220_ops);
|
||||
tty_port_link_device(&sclp_vt220_port, driver, 0);
|
||||
|
||||
|
@ -764,7 +763,7 @@ out_reg:
|
|||
out_init:
|
||||
__sclp_vt220_cleanup();
|
||||
out_driver:
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
return rc;
|
||||
}
|
||||
__initcall(sclp_vt220_tty_init);
|
||||
|
|
|
@ -1935,7 +1935,7 @@ static int __init tty3270_init(void)
|
|||
tty_set_operations(driver, &tty3270_ops);
|
||||
ret = tty_register_driver(driver);
|
||||
if (ret) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
return ret;
|
||||
}
|
||||
tty3270_driver = driver;
|
||||
|
@ -1952,7 +1952,7 @@ tty3270_exit(void)
|
|||
driver = tty3270_driver;
|
||||
tty3270_driver = NULL;
|
||||
tty_unregister_driver(driver);
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
tty3270_del_views();
|
||||
}
|
||||
|
||||
|
|
|
@ -2852,11 +2852,11 @@ unregister_loop:
|
|||
tty_unregister_driver(fwloop_driver);
|
||||
put_loop:
|
||||
if (create_loop_dev)
|
||||
put_tty_driver(fwloop_driver);
|
||||
tty_driver_kref_put(fwloop_driver);
|
||||
unregister_driver:
|
||||
tty_unregister_driver(fwtty_driver);
|
||||
put_tty:
|
||||
put_tty_driver(fwtty_driver);
|
||||
tty_driver_kref_put(fwtty_driver);
|
||||
remove_debugfs:
|
||||
debugfs_remove_recursive(fwserial_debugfs);
|
||||
|
||||
|
@ -2871,10 +2871,10 @@ static void __exit fwserial_exit(void)
|
|||
kmem_cache_destroy(fwtty_txn_cache);
|
||||
if (create_loop_dev) {
|
||||
tty_unregister_driver(fwloop_driver);
|
||||
put_tty_driver(fwloop_driver);
|
||||
tty_driver_kref_put(fwloop_driver);
|
||||
}
|
||||
tty_unregister_driver(fwtty_driver);
|
||||
put_tty_driver(fwtty_driver);
|
||||
tty_driver_kref_put(fwtty_driver);
|
||||
debugfs_remove_recursive(fwserial_debugfs);
|
||||
}
|
||||
|
||||
|
|
|
@ -281,9 +281,10 @@ int register_lte_tty_driver(void)
|
|||
int ret;
|
||||
|
||||
for (i = 0; i < TTY_MAX_COUNT; i++) {
|
||||
tty_driver = alloc_tty_driver(GDM_TTY_MINOR);
|
||||
if (!tty_driver)
|
||||
return -ENOMEM;
|
||||
tty_driver = tty_alloc_driver(GDM_TTY_MINOR,
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(tty_driver))
|
||||
return PTR_ERR(tty_driver);
|
||||
|
||||
tty_driver->owner = THIS_MODULE;
|
||||
tty_driver->driver_name = DRIVER_STRING[i];
|
||||
|
@ -291,8 +292,6 @@ int register_lte_tty_driver(void)
|
|||
tty_driver->major = GDM_TTY_MAJOR;
|
||||
tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
tty_driver->flags = TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_driver->init_termios = tty_std_termios;
|
||||
tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
|
||||
tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
|
||||
|
@ -300,7 +299,7 @@ int register_lte_tty_driver(void)
|
|||
|
||||
ret = tty_register_driver(tty_driver);
|
||||
if (ret) {
|
||||
put_tty_driver(tty_driver);
|
||||
tty_driver_kref_put(tty_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -319,7 +318,7 @@ void unregister_lte_tty_driver(void)
|
|||
tty_driver = gdm_driver[i];
|
||||
if (tty_driver) {
|
||||
tty_unregister_driver(tty_driver);
|
||||
put_tty_driver(tty_driver);
|
||||
tty_driver_kref_put(tty_driver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -973,7 +973,7 @@ static int gb_tty_init(void)
|
|||
return 0;
|
||||
|
||||
fail_put_gb_tty:
|
||||
put_tty_driver(gb_tty_driver);
|
||||
tty_driver_kref_put(gb_tty_driver);
|
||||
fail_unregister_dev:
|
||||
return retval;
|
||||
}
|
||||
|
@ -981,7 +981,7 @@ fail_unregister_dev:
|
|||
static void gb_tty_exit(void)
|
||||
{
|
||||
tty_unregister_driver(gb_tty_driver);
|
||||
put_tty_driver(gb_tty_driver);
|
||||
tty_driver_kref_put(gb_tty_driver);
|
||||
idr_destroy(&tty_minors);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
/* Set of debugging defines */
|
||||
|
||||
#undef SERIAL_DEBUG_INTR
|
||||
|
@ -31,55 +29,42 @@
|
|||
#undef SERIAL_DEBUG_FLOW
|
||||
#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
|
||||
#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
|
||||
tty->name, (info->tport.flags), serial_driver->refcount,info->count,tty->count,s)
|
||||
#else
|
||||
#define DBG_CNT(s)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* End of serial driver configuration section.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_reg.h>
|
||||
static char *serial_version = "4.30";
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/amigahw.h>
|
||||
#include <asm/amigaints.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
struct serial_state {
|
||||
struct tty_port tport;
|
||||
|
@ -88,7 +73,6 @@ struct serial_state {
|
|||
|
||||
unsigned long port;
|
||||
int baud_base;
|
||||
int xmit_fifo_size;
|
||||
int custom_divisor;
|
||||
int read_status_mask;
|
||||
int ignore_status_mask;
|
||||
|
@ -99,14 +83,13 @@ struct serial_state {
|
|||
int x_char; /* xon/xoff character */
|
||||
};
|
||||
|
||||
#define custom amiga_custom
|
||||
static char *serial_name = "Amiga-builtin serial driver";
|
||||
|
||||
static struct tty_driver *serial_driver;
|
||||
|
||||
/* number of characters left in xmit buffer before we ask for more */
|
||||
#define WAKEUP_CHARS 256
|
||||
|
||||
#define XMIT_FIFO_SIZE 1
|
||||
|
||||
static unsigned char current_ctl_bits;
|
||||
|
||||
static void change_speed(struct tty_struct *tty, struct serial_state *info,
|
||||
|
@ -114,13 +97,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
|
|||
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
|
||||
|
||||
|
||||
static struct serial_state rs_table[1];
|
||||
|
||||
#define NR_PORTS ARRAY_SIZE(rs_table)
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define serial_isroot() (capable(CAP_SYS_ADMIN))
|
||||
static struct serial_state serial_state;
|
||||
|
||||
/* some serial hardware definitions */
|
||||
#define SDR_OVRUN (1<<15)
|
||||
|
@ -161,9 +138,9 @@ static void rs_stop(struct tty_struct *tty)
|
|||
if (info->IER & UART_IER_THRI) {
|
||||
info->IER &= ~UART_IER_THRI;
|
||||
/* disable Tx interrupt and remove any pending interrupts */
|
||||
custom.intena = IF_TBE;
|
||||
amiga_custom.intena = IF_TBE;
|
||||
mb();
|
||||
custom.intreq = IF_TBE;
|
||||
amiga_custom.intreq = IF_TBE;
|
||||
mb();
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
@ -179,10 +156,10 @@ static void rs_start(struct tty_struct *tty)
|
|||
&& info->xmit.buf
|
||||
&& !(info->IER & UART_IER_THRI)) {
|
||||
info->IER |= UART_IER_THRI;
|
||||
custom.intena = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intena = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
/* set a pending Tx Interrupt, transmitter should restart now */
|
||||
custom.intreq = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intreq = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
@ -191,21 +168,8 @@ static void rs_start(struct tty_struct *tty)
|
|||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Here starts the interrupt handling routines. All of the following
|
||||
* subroutines are declared as inline and are folded into
|
||||
* rs_interrupt(). They were separated out for readability's sake.
|
||||
* Here start the interrupt handling routines.
|
||||
*
|
||||
* Note: rs_interrupt() is a "fast" interrupt, which means that it
|
||||
* runs with interrupts turned off. People who may want to modify
|
||||
* rs_interrupt() should try to keep the interrupt handler as fast as
|
||||
* possible. After you are done making modifications, it is not a bad
|
||||
* idea to do:
|
||||
*
|
||||
* gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
|
||||
*
|
||||
* and look at the resulting assemble code in serial.s.
|
||||
*
|
||||
* - Ted Ts'o (tytso@mit.edu), 7-Mar-93
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -220,9 +184,9 @@ static void receive_chars(struct serial_state *info)
|
|||
icount = &info->icount;
|
||||
|
||||
status = UART_LSR_DR; /* We obviously have a character! */
|
||||
serdatr = custom.serdatr;
|
||||
serdatr = amiga_custom.serdatr;
|
||||
mb();
|
||||
custom.intreq = IF_RBF;
|
||||
amiga_custom.intreq = IF_RBF;
|
||||
mb();
|
||||
|
||||
if((serdatr & 0x1ff) == 0)
|
||||
|
@ -299,10 +263,10 @@ out:
|
|||
|
||||
static void transmit_chars(struct serial_state *info)
|
||||
{
|
||||
custom.intreq = IF_TBE;
|
||||
amiga_custom.intreq = IF_TBE;
|
||||
mb();
|
||||
if (info->x_char) {
|
||||
custom.serdat = info->x_char | 0x100;
|
||||
amiga_custom.serdat = info->x_char | 0x100;
|
||||
mb();
|
||||
info->icount.tx++;
|
||||
info->x_char = 0;
|
||||
|
@ -312,12 +276,12 @@ static void transmit_chars(struct serial_state *info)
|
|||
|| info->tport.tty->flow.stopped
|
||||
|| info->tport.tty->hw_stopped) {
|
||||
info->IER &= ~UART_IER_THRI;
|
||||
custom.intena = IF_TBE;
|
||||
amiga_custom.intena = IF_TBE;
|
||||
mb();
|
||||
return;
|
||||
}
|
||||
|
||||
custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
|
||||
amiga_custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
|
||||
mb();
|
||||
info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
|
||||
info->icount.tx++;
|
||||
|
@ -331,7 +295,7 @@ static void transmit_chars(struct serial_state *info)
|
|||
printk("THRE...");
|
||||
#endif
|
||||
if (info->xmit.head == info->xmit.tail) {
|
||||
custom.intena = IF_TBE;
|
||||
amiga_custom.intena = IF_TBE;
|
||||
mb();
|
||||
info->IER &= ~UART_IER_THRI;
|
||||
}
|
||||
|
@ -384,10 +348,10 @@ static void check_modem_status(struct serial_state *info)
|
|||
#endif
|
||||
port->tty->hw_stopped = 0;
|
||||
info->IER |= UART_IER_THRI;
|
||||
custom.intena = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intena = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
/* set a pending Tx Interrupt, transmitter should restart now */
|
||||
custom.intreq = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intreq = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
tty_wakeup(port->tty);
|
||||
return;
|
||||
|
@ -400,9 +364,9 @@ static void check_modem_status(struct serial_state *info)
|
|||
port->tty->hw_stopped = 1;
|
||||
info->IER &= ~UART_IER_THRI;
|
||||
/* disable Tx interrupt and remove any pending interrupts */
|
||||
custom.intena = IF_TBE;
|
||||
amiga_custom.intena = IF_TBE;
|
||||
mb();
|
||||
custom.intreq = IF_TBE;
|
||||
amiga_custom.intreq = IF_TBE;
|
||||
mb();
|
||||
}
|
||||
}
|
||||
|
@ -444,7 +408,7 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id)
|
|||
{
|
||||
struct serial_state *info = dev_id;
|
||||
|
||||
if (custom.serdatr & SDR_TBE) {
|
||||
if (amiga_custom.serdatr & SDR_TBE) {
|
||||
#ifdef SERIAL_DEBUG_INTR
|
||||
printk("ser_tx_int...");
|
||||
#endif
|
||||
|
@ -504,20 +468,20 @@ static int startup(struct tty_struct *tty, struct serial_state *info)
|
|||
|
||||
/* Clear anything in the input buffer */
|
||||
|
||||
custom.intreq = IF_RBF;
|
||||
amiga_custom.intreq = IF_RBF;
|
||||
mb();
|
||||
|
||||
retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info);
|
||||
if (retval) {
|
||||
if (serial_isroot()) {
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
retval = 0;
|
||||
}
|
||||
goto errout;
|
||||
if (capable(CAP_SYS_ADMIN)) {
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
retval = 0;
|
||||
}
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* enable both Rx and Tx interrupts */
|
||||
custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
|
||||
amiga_custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
|
||||
mb();
|
||||
info->IER = UART_IER_MSI;
|
||||
|
||||
|
@ -553,13 +517,10 @@ errout:
|
|||
static void shutdown(struct tty_struct *tty, struct serial_state *info)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct serial_state *state;
|
||||
|
||||
if (!tty_port_initialized(&info->tport))
|
||||
return;
|
||||
|
||||
state = info;
|
||||
|
||||
#ifdef SERIAL_DEBUG_OPEN
|
||||
printk("Shutting down serial port %d ....\n", info->line);
|
||||
#endif
|
||||
|
@ -583,11 +544,11 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info)
|
|||
}
|
||||
|
||||
info->IER = 0;
|
||||
custom.intena = IF_RBF | IF_TBE;
|
||||
amiga_custom.intena = IF_RBF | IF_TBE;
|
||||
mb();
|
||||
|
||||
/* disable break condition */
|
||||
custom.adkcon = AC_UARTBRK;
|
||||
amiga_custom.adkcon = AC_UARTBRK;
|
||||
mb();
|
||||
|
||||
if (C_HUPCL(tty))
|
||||
|
@ -671,7 +632,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
|
|||
if (!quot)
|
||||
quot = baud_base / 9600;
|
||||
info->quot = quot;
|
||||
info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
|
||||
info->timeout = (XMIT_FIFO_SIZE*HZ*bits*quot) / baud_base;
|
||||
info->timeout += HZ/50; /* Add .02 seconds of slop */
|
||||
|
||||
/* CTS flow control flag and modem status interrupts */
|
||||
|
@ -731,7 +692,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
|
|||
if(cval & UART_LCR_PARITY)
|
||||
serper |= (SERPER_PARENB);
|
||||
|
||||
custom.serper = serper;
|
||||
amiga_custom.serper = serper;
|
||||
mb();
|
||||
}
|
||||
|
||||
|
@ -775,10 +736,10 @@ static void rs_flush_chars(struct tty_struct *tty)
|
|||
|
||||
local_irq_save(flags);
|
||||
info->IER |= UART_IER_THRI;
|
||||
custom.intena = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intena = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
/* set a pending Tx Interrupt, transmitter should restart now */
|
||||
custom.intreq = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intreq = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
@ -817,10 +778,10 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
|
|||
&& !(info->IER & UART_IER_THRI)) {
|
||||
info->IER |= UART_IER_THRI;
|
||||
local_irq_disable();
|
||||
custom.intena = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intena = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
/* set a pending Tx Interrupt, transmitter should restart now */
|
||||
custom.intreq = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intreq = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
@ -867,11 +828,11 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
|
|||
|
||||
/* Check this ! */
|
||||
local_irq_save(flags);
|
||||
if(!(custom.intenar & IF_TBE)) {
|
||||
custom.intena = IF_SETCLR | IF_TBE;
|
||||
if(!(amiga_custom.intenar & IF_TBE)) {
|
||||
amiga_custom.intena = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
/* set a pending Tx Interrupt, transmitter should restart now */
|
||||
custom.intreq = IF_SETCLR | IF_TBE;
|
||||
amiga_custom.intreq = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
@ -948,7 +909,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
|
|||
ss->line = tty->index;
|
||||
ss->port = state->port;
|
||||
ss->flags = state->tport.flags;
|
||||
ss->xmit_fifo_size = state->xmit_fifo_size;
|
||||
ss->xmit_fifo_size = XMIT_FIFO_SIZE;
|
||||
ss->baud_base = state->baud_base;
|
||||
ss->close_delay = close_delay;
|
||||
ss->closing_wait = closing_wait;
|
||||
|
@ -969,7 +930,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
|
|||
change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) ||
|
||||
ss->custom_divisor != state->custom_divisor;
|
||||
if (ss->irq || ss->port != state->port ||
|
||||
ss->xmit_fifo_size != state->xmit_fifo_size) {
|
||||
ss->xmit_fifo_size != XMIT_FIFO_SIZE) {
|
||||
tty_unlock(tty);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -979,11 +940,10 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
|
|||
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
|
||||
closing_wait = msecs_to_jiffies(closing_wait * 10);
|
||||
|
||||
if (!serial_isroot()) {
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
if ((ss->baud_base != state->baud_base) ||
|
||||
(close_delay != port->close_delay) ||
|
||||
(closing_wait != port->closing_wait) ||
|
||||
(ss->xmit_fifo_size != state->xmit_fifo_size) ||
|
||||
((ss->flags & ~ASYNC_USR_MASK) !=
|
||||
(port->flags & ~ASYNC_USR_MASK))) {
|
||||
tty_unlock(tty);
|
||||
|
@ -1043,7 +1003,7 @@ static int get_lsr_info(struct serial_state *info, unsigned int __user *value)
|
|||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
status = custom.serdatr;
|
||||
status = amiga_custom.serdatr;
|
||||
mb();
|
||||
local_irq_restore(flags);
|
||||
result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0);
|
||||
|
@ -1105,9 +1065,9 @@ static int rs_break(struct tty_struct *tty, int break_state)
|
|||
|
||||
local_irq_save(flags);
|
||||
if (break_state == -1)
|
||||
custom.adkcon = AC_SETCLR | AC_UARTBRK;
|
||||
amiga_custom.adkcon = AC_SETCLR | AC_UARTBRK;
|
||||
else
|
||||
custom.adkcon = AC_UARTBRK;
|
||||
amiga_custom.adkcon = AC_UARTBRK;
|
||||
mb();
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
|
@ -1284,10 +1244,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
|
|||
state->read_status_mask &= ~UART_LSR_DR;
|
||||
if (tty_port_initialized(port)) {
|
||||
/* disable receive interrupts */
|
||||
custom.intena = IF_RBF;
|
||||
amiga_custom.intena = IF_RBF;
|
||||
mb();
|
||||
/* clear any pending receive interrupt */
|
||||
custom.intreq = IF_RBF;
|
||||
amiga_custom.intreq = IF_RBF;
|
||||
mb();
|
||||
|
||||
/*
|
||||
|
@ -1315,9 +1275,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
|
|||
unsigned long orig_jiffies, char_time;
|
||||
int lsr;
|
||||
|
||||
if (info->xmit_fifo_size == 0)
|
||||
return; /* Just in case.... */
|
||||
|
||||
orig_jiffies = jiffies;
|
||||
|
||||
/*
|
||||
|
@ -1328,7 +1285,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
|
|||
* Note: we have to use pretty tight timings here to satisfy
|
||||
* the NIST-PCTS.
|
||||
*/
|
||||
char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
|
||||
char_time = (info->timeout - HZ/50) / XMIT_FIFO_SIZE;
|
||||
char_time = char_time / 5;
|
||||
if (char_time == 0)
|
||||
char_time = 1;
|
||||
|
@ -1349,7 +1306,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
|
|||
printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
|
||||
printk("jiff=%lu...", jiffies);
|
||||
#endif
|
||||
while(!((lsr = custom.serdatr) & SDR_TSRE)) {
|
||||
while(!((lsr = amiga_custom.serdatr) & SDR_TSRE)) {
|
||||
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
|
||||
printk("serdatr = %d (jiff=%lu)...", lsr, jiffies);
|
||||
#endif
|
||||
|
@ -1389,14 +1346,14 @@ static void rs_hangup(struct tty_struct *tty)
|
|||
*/
|
||||
static int rs_open(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
struct serial_state *info = rs_table + tty->index;
|
||||
struct tty_port *port = &info->tport;
|
||||
struct tty_port *port = tty->port;
|
||||
struct serial_state *info = container_of(port, struct serial_state,
|
||||
tport);
|
||||
int retval;
|
||||
|
||||
port->count++;
|
||||
port->tty = tty;
|
||||
tty->driver_data = info;
|
||||
tty->port = port;
|
||||
|
||||
retval = startup(tty, info);
|
||||
if (retval) {
|
||||
|
@ -1461,8 +1418,8 @@ static inline void line_info(struct seq_file *m, int line,
|
|||
|
||||
static int rs_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
|
||||
line_info(m, 0, &rs_table[0]);
|
||||
seq_printf(m, "serinfo:1.0 driver:4.30\n");
|
||||
line_info(m, 0, &serial_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1474,17 +1431,6 @@ static int rs_proc_show(struct seq_file *m, void *v)
|
|||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* This routine prints out the appropriate serial driver version
|
||||
* number, and identifies which options were configured into this
|
||||
* driver.
|
||||
*/
|
||||
static void show_serial_version(void)
|
||||
{
|
||||
printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
|
||||
}
|
||||
|
||||
|
||||
static const struct tty_operations serial_ops = {
|
||||
.open = rs_open,
|
||||
.close = rs_close,
|
||||
|
@ -1543,52 +1489,43 @@ static const struct tty_port_operations amiga_port_ops = {
|
|||
*/
|
||||
static int __init amiga_serial_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct serial_state *state = &serial_state;
|
||||
struct tty_driver *driver;
|
||||
unsigned long flags;
|
||||
struct serial_state * state;
|
||||
int error;
|
||||
|
||||
serial_driver = alloc_tty_driver(NR_PORTS);
|
||||
if (!serial_driver)
|
||||
return -ENOMEM;
|
||||
|
||||
show_serial_version();
|
||||
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
/* Initialize the tty_driver structure */
|
||||
|
||||
serial_driver->driver_name = "amiserial";
|
||||
serial_driver->name = "ttyS";
|
||||
serial_driver->major = TTY_MAJOR;
|
||||
serial_driver->minor_start = 64;
|
||||
serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
serial_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
serial_driver->init_termios = tty_std_termios;
|
||||
serial_driver->init_termios.c_cflag =
|
||||
driver->driver_name = "amiserial";
|
||||
driver->name = "ttyS";
|
||||
driver->major = TTY_MAJOR;
|
||||
driver->minor_start = 64;
|
||||
driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
driver->init_termios = tty_std_termios;
|
||||
driver->init_termios.c_cflag =
|
||||
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
serial_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
tty_set_operations(serial_driver, &serial_ops);
|
||||
tty_set_operations(driver, &serial_ops);
|
||||
|
||||
state = rs_table;
|
||||
state->port = (int)&custom.serdatr; /* Just to give it a value */
|
||||
state->custom_divisor = 0;
|
||||
state->icount.cts = state->icount.dsr =
|
||||
state->icount.rng = state->icount.dcd = 0;
|
||||
state->icount.rx = state->icount.tx = 0;
|
||||
state->icount.frame = state->icount.parity = 0;
|
||||
state->icount.overrun = state->icount.brk = 0;
|
||||
memset(state, 0, sizeof(*state));
|
||||
state->port = (int)&amiga_custom.serdatr; /* Just to give it a value */
|
||||
tty_port_init(&state->tport);
|
||||
state->tport.ops = &amiga_port_ops;
|
||||
tty_port_link_device(&state->tport, serial_driver, 0);
|
||||
tty_port_link_device(&state->tport, driver, 0);
|
||||
|
||||
error = tty_register_driver(serial_driver);
|
||||
error = tty_register_driver(driver);
|
||||
if (error)
|
||||
goto fail_put_tty_driver;
|
||||
goto fail_tty_driver_kref_put;
|
||||
|
||||
printk(KERN_INFO "ttyS0 is the amiga builtin serial port\n");
|
||||
|
||||
/* Hardware set up */
|
||||
|
||||
state->baud_base = amiga_colorclock;
|
||||
state->xmit_fifo_size = 1;
|
||||
|
||||
/* set ISRs, and then disable the rx interrupts */
|
||||
error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
|
||||
|
@ -1603,11 +1540,11 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
|
|||
local_irq_save(flags);
|
||||
|
||||
/* turn off Rx and Tx interrupts */
|
||||
custom.intena = IF_RBF | IF_TBE;
|
||||
amiga_custom.intena = IF_RBF | IF_TBE;
|
||||
mb();
|
||||
|
||||
/* clear any pending interrupt */
|
||||
custom.intreq = IF_RBF | IF_TBE;
|
||||
amiga_custom.intreq = IF_RBF | IF_TBE;
|
||||
mb();
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
@ -1621,15 +1558,17 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, state);
|
||||
|
||||
serial_driver = driver;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_irq:
|
||||
free_irq(IRQ_AMIGA_TBE, state);
|
||||
fail_unregister:
|
||||
tty_unregister_driver(serial_driver);
|
||||
fail_put_tty_driver:
|
||||
tty_unregister_driver(driver);
|
||||
fail_tty_driver_kref_put:
|
||||
tty_port_destroy(&state->tport);
|
||||
put_tty_driver(serial_driver);
|
||||
tty_driver_kref_put(driver);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1637,9 +1576,8 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct serial_state *state = platform_get_drvdata(pdev);
|
||||
|
||||
/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
|
||||
tty_unregister_driver(serial_driver);
|
||||
put_tty_driver(serial_driver);
|
||||
tty_driver_kref_put(serial_driver);
|
||||
tty_port_destroy(&state->tport);
|
||||
|
||||
free_irq(IRQ_AMIGA_TBE, state);
|
||||
|
@ -1668,8 +1606,8 @@ module_platform_driver_probe(amiga_serial_driver, amiga_serial_probe);
|
|||
|
||||
static void amiga_serial_putc(char c)
|
||||
{
|
||||
custom.serdat = (unsigned char)c | 0x100;
|
||||
while (!(custom.serdatr & 0x2000))
|
||||
amiga_custom.serdat = (unsigned char)c | 0x100;
|
||||
while (!(amiga_custom.serdatr & 0x2000))
|
||||
barrier();
|
||||
}
|
||||
|
||||
|
@ -1682,9 +1620,9 @@ static void amiga_serial_putc(char c)
|
|||
static void serial_console_write(struct console *co, const char *s,
|
||||
unsigned count)
|
||||
{
|
||||
unsigned short intena = custom.intenar;
|
||||
unsigned short intena = amiga_custom.intenar;
|
||||
|
||||
custom.intena = IF_TBE;
|
||||
amiga_custom.intena = IF_TBE;
|
||||
|
||||
while (count--) {
|
||||
if (*s == '\n')
|
||||
|
@ -1692,7 +1630,7 @@ static void serial_console_write(struct console *co, const char *s,
|
|||
amiga_serial_putc(*s++);
|
||||
}
|
||||
|
||||
custom.intena = IF_SETCLR | (intena & IF_TBE);
|
||||
amiga_custom.intena = IF_SETCLR | (intena & IF_TBE);
|
||||
}
|
||||
|
||||
static struct tty_driver *serial_console_device(struct console *c, int *index)
|
||||
|
|
|
@ -751,6 +751,7 @@ static struct platform_driver ehv_bc_tty_driver = {
|
|||
*/
|
||||
static int __init ehv_bc_init(void)
|
||||
{
|
||||
struct tty_driver *driver;
|
||||
struct device_node *np;
|
||||
unsigned int count = 0; /* Number of elements in bcs[] */
|
||||
int ret;
|
||||
|
@ -773,26 +774,28 @@ static int __init ehv_bc_init(void)
|
|||
if (!bcs)
|
||||
return -ENOMEM;
|
||||
|
||||
ehv_bc_driver = alloc_tty_driver(count);
|
||||
if (!ehv_bc_driver) {
|
||||
ret = -ENOMEM;
|
||||
driver = tty_alloc_driver(count, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(driver)) {
|
||||
ret = PTR_ERR(driver);
|
||||
goto err_free_bcs;
|
||||
}
|
||||
|
||||
ehv_bc_driver->driver_name = "ehv-bc";
|
||||
ehv_bc_driver->name = ehv_bc_console.name;
|
||||
ehv_bc_driver->type = TTY_DRIVER_TYPE_CONSOLE;
|
||||
ehv_bc_driver->subtype = SYSTEM_TYPE_CONSOLE;
|
||||
ehv_bc_driver->init_termios = tty_std_termios;
|
||||
ehv_bc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_set_operations(ehv_bc_driver, &ehv_bc_ops);
|
||||
driver->driver_name = "ehv-bc";
|
||||
driver->name = ehv_bc_console.name;
|
||||
driver->type = TTY_DRIVER_TYPE_CONSOLE;
|
||||
driver->subtype = SYSTEM_TYPE_CONSOLE;
|
||||
driver->init_termios = tty_std_termios;
|
||||
tty_set_operations(driver, &ehv_bc_ops);
|
||||
|
||||
ret = tty_register_driver(ehv_bc_driver);
|
||||
ret = tty_register_driver(driver);
|
||||
if (ret) {
|
||||
pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
|
||||
goto err_put_tty_driver;
|
||||
goto err_tty_driver_kref_put;
|
||||
}
|
||||
|
||||
ehv_bc_driver = driver;
|
||||
|
||||
ret = platform_driver_register(&ehv_bc_tty_driver);
|
||||
if (ret) {
|
||||
pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
|
||||
|
@ -803,9 +806,10 @@ static int __init ehv_bc_init(void)
|
|||
return 0;
|
||||
|
||||
err_deregister_tty_driver:
|
||||
tty_unregister_driver(ehv_bc_driver);
|
||||
err_put_tty_driver:
|
||||
put_tty_driver(ehv_bc_driver);
|
||||
ehv_bc_driver = NULL;
|
||||
tty_unregister_driver(driver);
|
||||
err_tty_driver_kref_put:
|
||||
tty_driver_kref_put(driver);
|
||||
err_free_bcs:
|
||||
kfree(bcs);
|
||||
|
||||
|
|
|
@ -253,18 +253,18 @@ static int goldfish_tty_create_driver(void)
|
|||
ret = -ENOMEM;
|
||||
goto err_alloc_goldfish_ttys_failed;
|
||||
}
|
||||
tty = alloc_tty_driver(goldfish_tty_line_count);
|
||||
if (tty == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_tty_driver_failed;
|
||||
tty = tty_alloc_driver(goldfish_tty_line_count,
|
||||
TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(tty)) {
|
||||
ret = PTR_ERR(tty);
|
||||
goto err_tty_alloc_driver_failed;
|
||||
}
|
||||
tty->driver_name = "goldfish";
|
||||
tty->name = "ttyGF";
|
||||
tty->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
tty->subtype = SERIAL_TYPE_NORMAL;
|
||||
tty->init_termios = tty_std_termios;
|
||||
tty->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_set_operations(tty, &goldfish_tty_ops);
|
||||
ret = tty_register_driver(tty);
|
||||
if (ret)
|
||||
|
@ -274,8 +274,8 @@ static int goldfish_tty_create_driver(void)
|
|||
return 0;
|
||||
|
||||
err_tty_register_driver_failed:
|
||||
put_tty_driver(tty);
|
||||
err_alloc_tty_driver_failed:
|
||||
tty_driver_kref_put(tty);
|
||||
err_tty_alloc_driver_failed:
|
||||
kfree(goldfish_ttys);
|
||||
goldfish_ttys = NULL;
|
||||
err_alloc_goldfish_ttys_failed:
|
||||
|
@ -285,7 +285,7 @@ err_alloc_goldfish_ttys_failed:
|
|||
static void goldfish_tty_delete_driver(void)
|
||||
{
|
||||
tty_unregister_driver(goldfish_tty_driver);
|
||||
put_tty_driver(goldfish_tty_driver);
|
||||
tty_driver_kref_put(goldfish_tty_driver);
|
||||
goldfish_tty_driver = NULL;
|
||||
kfree(goldfish_ttys);
|
||||
goldfish_ttys = NULL;
|
||||
|
|
|
@ -1021,9 +1021,10 @@ static int hvc_init(void)
|
|||
int err;
|
||||
|
||||
/* We need more than hvc_count adapters due to hotplug additions. */
|
||||
drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
|
||||
if (!drv) {
|
||||
err = -ENOMEM;
|
||||
drv = tty_alloc_driver(HVC_ALLOC_TTY_ADAPTERS, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_RESET_TERMIOS);
|
||||
if (IS_ERR(drv)) {
|
||||
err = PTR_ERR(drv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1033,7 +1034,6 @@ static int hvc_init(void)
|
|||
drv->minor_start = HVC_MINOR;
|
||||
drv->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
drv->init_termios = tty_std_termios;
|
||||
drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
|
||||
tty_set_operations(drv, &hvc_ops);
|
||||
|
||||
/* Always start the kthread because there can be hotplug vty adapters
|
||||
|
@ -1063,7 +1063,7 @@ stop_thread:
|
|||
kthread_stop(hvc_task);
|
||||
hvc_task = NULL;
|
||||
put_tty:
|
||||
put_tty_driver(drv);
|
||||
tty_driver_kref_put(drv);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -86,7 +86,11 @@ static int __write_console(struct xencons_info *xencons,
|
|||
cons = intf->out_cons;
|
||||
prod = intf->out_prod;
|
||||
mb(); /* update queue values before going on */
|
||||
BUG_ON((prod - cons) > sizeof(intf->out));
|
||||
|
||||
if ((prod - cons) > sizeof(intf->out)) {
|
||||
pr_err_once("xencons: Illegal ring page indices");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
|
||||
intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
|
||||
|
@ -114,7 +118,10 @@ static int domU_write_console(uint32_t vtermno, const char *data, int len)
|
|||
*/
|
||||
while (len) {
|
||||
int sent = __write_console(cons, data, len);
|
||||
|
||||
|
||||
if (sent < 0)
|
||||
return sent;
|
||||
|
||||
data += sent;
|
||||
len -= sent;
|
||||
|
||||
|
@ -138,7 +145,11 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
|
|||
cons = intf->in_cons;
|
||||
prod = intf->in_prod;
|
||||
mb(); /* get pointers before reading ring */
|
||||
BUG_ON((prod - cons) > sizeof(intf->in));
|
||||
|
||||
if ((prod - cons) > sizeof(intf->in)) {
|
||||
pr_err_once("xencons: Illegal ring page indices");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (cons != prod && recv < len)
|
||||
buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
|
||||
|
|
|
@ -1445,10 +1445,11 @@ static int hvcs_initialize(void)
|
|||
} else
|
||||
num_ttys_to_alloc = hvcs_parm_num_devs;
|
||||
|
||||
hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
|
||||
if (!hvcs_tty_driver) {
|
||||
hvcs_tty_driver = tty_alloc_driver(num_ttys_to_alloc,
|
||||
TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(hvcs_tty_driver)) {
|
||||
mutex_unlock(&hvcs_init_mutex);
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(hvcs_tty_driver);
|
||||
}
|
||||
|
||||
if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
|
||||
|
@ -1473,7 +1474,6 @@ static int hvcs_initialize(void)
|
|||
* throw us into a horrible recursive echo-echo-echo loop.
|
||||
*/
|
||||
hvcs_tty_driver->init_termios = hvcs_tty_termios;
|
||||
hvcs_tty_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
|
||||
tty_set_operations(hvcs_tty_driver, &hvcs_ops);
|
||||
|
||||
|
@ -1509,7 +1509,7 @@ buff_alloc_fail:
|
|||
register_fail:
|
||||
hvcs_free_index_list();
|
||||
index_fail:
|
||||
put_tty_driver(hvcs_tty_driver);
|
||||
tty_driver_kref_put(hvcs_tty_driver);
|
||||
hvcs_tty_driver = NULL;
|
||||
mutex_unlock(&hvcs_init_mutex);
|
||||
return rc;
|
||||
|
@ -1562,7 +1562,7 @@ static void __exit hvcs_module_exit(void)
|
|||
|
||||
hvcs_free_index_list();
|
||||
|
||||
put_tty_driver(hvcs_tty_driver);
|
||||
tty_driver_kref_put(hvcs_tty_driver);
|
||||
|
||||
printk(KERN_INFO "HVCS: driver module removed.\n");
|
||||
}
|
||||
|
|
|
@ -1038,29 +1038,29 @@ static const struct tty_operations hvsi_ops = {
|
|||
|
||||
static int __init hvsi_init(void)
|
||||
{
|
||||
int i;
|
||||
struct tty_driver *driver;
|
||||
int i, ret;
|
||||
|
||||
hvsi_driver = alloc_tty_driver(hvsi_count);
|
||||
if (!hvsi_driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(hvsi_count, TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
hvsi_driver->driver_name = "hvsi";
|
||||
hvsi_driver->name = "hvsi";
|
||||
hvsi_driver->major = HVSI_MAJOR;
|
||||
hvsi_driver->minor_start = HVSI_MINOR;
|
||||
hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
hvsi_driver->init_termios = tty_std_termios;
|
||||
hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
|
||||
hvsi_driver->init_termios.c_ispeed = 9600;
|
||||
hvsi_driver->init_termios.c_ospeed = 9600;
|
||||
hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
tty_set_operations(hvsi_driver, &hvsi_ops);
|
||||
driver->driver_name = "hvsi";
|
||||
driver->name = "hvsi";
|
||||
driver->major = HVSI_MAJOR;
|
||||
driver->minor_start = HVSI_MINOR;
|
||||
driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
driver->init_termios = tty_std_termios;
|
||||
driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
|
||||
driver->init_termios.c_ispeed = 9600;
|
||||
driver->init_termios.c_ospeed = 9600;
|
||||
tty_set_operations(driver, &hvsi_ops);
|
||||
|
||||
for (i=0; i < hvsi_count; i++) {
|
||||
struct hvsi_struct *hp = &hvsi_ports[i];
|
||||
int ret = 1;
|
||||
|
||||
tty_port_link_device(&hp->port, hvsi_driver, i);
|
||||
tty_port_link_device(&hp->port, driver, i);
|
||||
|
||||
ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
|
||||
if (ret)
|
||||
|
@ -1069,12 +1069,27 @@ static int __init hvsi_init(void)
|
|||
}
|
||||
hvsi_wait = wait_for_state; /* irqs active now */
|
||||
|
||||
if (tty_register_driver(hvsi_driver))
|
||||
panic("Couldn't register hvsi console driver\n");
|
||||
ret = tty_register_driver(driver);
|
||||
if (ret) {
|
||||
pr_err("Couldn't register hvsi console driver\n");
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
hvsi_driver = driver;
|
||||
|
||||
printk(KERN_DEBUG "HVSI: registered %i devices\n", hvsi_count);
|
||||
|
||||
return 0;
|
||||
err_free_irq:
|
||||
hvsi_wait = poll_for_state;
|
||||
for (i = 0; i < hvsi_count; i++) {
|
||||
struct hvsi_struct *hp = &hvsi_ports[i];
|
||||
|
||||
free_irq(hp->virq, hp);
|
||||
}
|
||||
tty_driver_kref_put(driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
device_initcall(hvsi_init);
|
||||
|
||||
|
|
|
@ -564,9 +564,10 @@ int ipwireless_tty_init(void)
|
|||
{
|
||||
int result;
|
||||
|
||||
ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
|
||||
if (!ipw_tty_driver)
|
||||
return -ENOMEM;
|
||||
ipw_tty_driver = tty_alloc_driver(IPWIRELESS_PCMCIA_MINORS,
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(ipw_tty_driver))
|
||||
return PTR_ERR(ipw_tty_driver);
|
||||
|
||||
ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
|
||||
ipw_tty_driver->name = "ttyIPWp";
|
||||
|
@ -574,7 +575,6 @@ int ipwireless_tty_init(void)
|
|||
ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
|
||||
ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
ipw_tty_driver->init_termios = tty_std_termios;
|
||||
ipw_tty_driver->init_termios.c_cflag =
|
||||
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
|
@ -585,7 +585,7 @@ int ipwireless_tty_init(void)
|
|||
if (result) {
|
||||
printk(KERN_ERR IPWIRELESS_PCCARD_NAME
|
||||
": failed to register tty driver\n");
|
||||
put_tty_driver(ipw_tty_driver);
|
||||
tty_driver_kref_put(ipw_tty_driver);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -595,7 +595,7 @@ int ipwireless_tty_init(void)
|
|||
void ipwireless_tty_release(void)
|
||||
{
|
||||
tty_unregister_driver(ipw_tty_driver);
|
||||
put_tty_driver(ipw_tty_driver);
|
||||
tty_driver_kref_put(ipw_tty_driver);
|
||||
}
|
||||
|
||||
int ipwireless_tty_is_modem(struct ipw_tty *tty)
|
||||
|
|
|
@ -1042,7 +1042,7 @@ err_destroy_ports:
|
|||
dport = &priv->ports[nport];
|
||||
tty_port_destroy(&dport->port);
|
||||
}
|
||||
put_tty_driver(priv->driver);
|
||||
tty_driver_kref_put(priv->driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1053,7 +1053,7 @@ static int __init moxa_init(void)
|
|||
|
||||
if (tty_register_driver(moxaDriver)) {
|
||||
printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
|
||||
put_tty_driver(moxaDriver);
|
||||
tty_driver_kref_put(moxaDriver);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1119,7 +1119,7 @@ static void __exit moxa_exit(void)
|
|||
del_timer_sync(&moxaTimer);
|
||||
|
||||
tty_unregister_driver(moxaDriver);
|
||||
put_tty_driver(moxaDriver);
|
||||
tty_driver_kref_put(moxaDriver);
|
||||
}
|
||||
|
||||
module_init(moxa_init);
|
||||
|
@ -2034,10 +2034,10 @@ static int moxa_get_serial_info(struct tty_struct *tty,
|
|||
if (!info)
|
||||
return -ENODEV;
|
||||
mutex_lock(&info->port.mutex);
|
||||
ss->type = info->type,
|
||||
ss->line = info->port.tty->index,
|
||||
ss->flags = info->port.flags,
|
||||
ss->baud_base = 921600,
|
||||
ss->type = info->type;
|
||||
ss->line = info->port.tty->index;
|
||||
ss->flags = info->port.flags;
|
||||
ss->baud_base = 921600;
|
||||
ss->close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
|
||||
mutex_unlock(&info->port.mutex);
|
||||
return 0;
|
||||
|
|
|
@ -1039,12 +1039,12 @@ static int mxser_get_serial_info(struct tty_struct *tty,
|
|||
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
|
||||
closing_wait = jiffies_to_msecs(closing_wait) / 10;
|
||||
|
||||
ss->type = info->type,
|
||||
ss->line = tty->index,
|
||||
ss->port = info->ioaddr,
|
||||
ss->irq = info->board->irq,
|
||||
ss->flags = info->port.flags,
|
||||
ss->baud_base = MXSER_BAUD_BASE,
|
||||
ss->type = info->type;
|
||||
ss->line = tty->index;
|
||||
ss->port = info->ioaddr;
|
||||
ss->irq = info->board->irq;
|
||||
ss->flags = info->port.flags;
|
||||
ss->baud_base = MXSER_BAUD_BASE;
|
||||
ss->close_delay = close_delay;
|
||||
ss->closing_wait = closing_wait;
|
||||
ss->custom_divisor = MXSER_CUSTOM_DIVISOR,
|
||||
|
@ -1976,9 +1976,10 @@ static int __init mxser_module_init(void)
|
|||
{
|
||||
int retval;
|
||||
|
||||
mxvar_sdriver = alloc_tty_driver(MXSER_PORTS);
|
||||
if (!mxvar_sdriver)
|
||||
return -ENOMEM;
|
||||
mxvar_sdriver = tty_alloc_driver(MXSER_PORTS, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(mxvar_sdriver))
|
||||
return PTR_ERR(mxvar_sdriver);
|
||||
|
||||
/* Initialize the tty_driver structure */
|
||||
mxvar_sdriver->name = "ttyMI";
|
||||
|
@ -1988,7 +1989,6 @@ static int __init mxser_module_init(void)
|
|||
mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
|
||||
mxvar_sdriver->init_termios = tty_std_termios;
|
||||
mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
|
||||
mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_set_operations(mxvar_sdriver, &mxser_ops);
|
||||
|
||||
retval = tty_register_driver(mxvar_sdriver);
|
||||
|
@ -2008,7 +2008,7 @@ static int __init mxser_module_init(void)
|
|||
err_unr:
|
||||
tty_unregister_driver(mxvar_sdriver);
|
||||
err_put:
|
||||
put_tty_driver(mxvar_sdriver);
|
||||
tty_driver_kref_put(mxvar_sdriver);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -2016,7 +2016,7 @@ static void __exit mxser_module_exit(void)
|
|||
{
|
||||
pci_unregister_driver(&mxser_driver);
|
||||
tty_unregister_driver(mxvar_sdriver);
|
||||
put_tty_driver(mxvar_sdriver);
|
||||
tty_driver_kref_put(mxvar_sdriver);
|
||||
}
|
||||
|
||||
module_init(mxser_module_init);
|
||||
|
|
|
@ -3252,10 +3252,11 @@ static int __init gsm_init(void)
|
|||
return status;
|
||||
}
|
||||
|
||||
gsm_tty_driver = alloc_tty_driver(256);
|
||||
if (!gsm_tty_driver) {
|
||||
gsm_tty_driver = tty_alloc_driver(256, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
|
||||
if (IS_ERR(gsm_tty_driver)) {
|
||||
pr_err("gsm_init: tty allocation failed.\n");
|
||||
status = -ENOMEM;
|
||||
status = PTR_ERR(gsm_tty_driver);
|
||||
goto err_unreg_ldisc;
|
||||
}
|
||||
gsm_tty_driver->driver_name = "gsmtty";
|
||||
|
@ -3264,8 +3265,6 @@ static int __init gsm_init(void)
|
|||
gsm_tty_driver->minor_start = 0;
|
||||
gsm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
gsm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
gsm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV
|
||||
| TTY_DRIVER_HARDWARE_BREAK;
|
||||
gsm_tty_driver->init_termios = tty_std_termios;
|
||||
/* Fixme */
|
||||
gsm_tty_driver->init_termios.c_lflag &= ~ECHO;
|
||||
|
@ -3280,7 +3279,7 @@ static int __init gsm_init(void)
|
|||
gsm_tty_driver->major, gsm_tty_driver->minor_start);
|
||||
return 0;
|
||||
err_put_driver:
|
||||
put_tty_driver(gsm_tty_driver);
|
||||
tty_driver_kref_put(gsm_tty_driver);
|
||||
err_unreg_ldisc:
|
||||
tty_unregister_ldisc(&tty_ldisc_packet);
|
||||
return status;
|
||||
|
@ -3290,7 +3289,7 @@ static void __exit gsm_exit(void)
|
|||
{
|
||||
tty_unregister_ldisc(&tty_ldisc_packet);
|
||||
tty_unregister_driver(gsm_tty_driver);
|
||||
put_tty_driver(gsm_tty_driver);
|
||||
tty_driver_kref_put(gsm_tty_driver);
|
||||
}
|
||||
|
||||
module_init(gsm_init);
|
||||
|
|
|
@ -1824,16 +1824,16 @@ static __init int nozomi_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
|
||||
if (!ntty_driver)
|
||||
return -ENOMEM;
|
||||
ntty_driver = tty_alloc_driver(NTTY_TTY_MAXMINORS, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(ntty_driver))
|
||||
return PTR_ERR(ntty_driver);
|
||||
|
||||
ntty_driver->driver_name = NOZOMI_NAME_TTY;
|
||||
ntty_driver->name = "noz";
|
||||
ntty_driver->major = 0;
|
||||
ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
ntty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
ntty_driver->init_termios = tty_std_termios;
|
||||
ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \
|
||||
HUPCL | CLOCAL;
|
||||
|
@ -1857,7 +1857,7 @@ static __init int nozomi_init(void)
|
|||
unr_tty:
|
||||
tty_unregister_driver(ntty_driver);
|
||||
free_tty:
|
||||
put_tty_driver(ntty_driver);
|
||||
tty_driver_kref_put(ntty_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1865,7 +1865,7 @@ static __exit void nozomi_exit(void)
|
|||
{
|
||||
pci_unregister_driver(&nozomi_driver);
|
||||
tty_unregister_driver(ntty_driver);
|
||||
put_tty_driver(ntty_driver);
|
||||
tty_driver_kref_put(ntty_driver);
|
||||
}
|
||||
|
||||
module_init(nozomi_init);
|
||||
|
|
|
@ -562,23 +562,45 @@ struct acpi_serdev_lookup {
|
|||
int index;
|
||||
};
|
||||
|
||||
/**
|
||||
* serdev_acpi_get_uart_resource - Gets UARTSerialBus resource if type matches
|
||||
* @ares: ACPI resource
|
||||
* @uart: Pointer to UARTSerialBus resource will be returned here
|
||||
*
|
||||
* Checks if the given ACPI resource is of type UARTSerialBus.
|
||||
* In this case, returns a pointer to it to the caller.
|
||||
*
|
||||
* Return: True if resource type is of UARTSerialBus, otherwise false.
|
||||
*/
|
||||
bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
|
||||
struct acpi_resource_uart_serialbus **uart)
|
||||
{
|
||||
struct acpi_resource_uart_serialbus *sb;
|
||||
|
||||
if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
|
||||
return false;
|
||||
|
||||
sb = &ares->data.uart_serial_bus;
|
||||
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_UART)
|
||||
return false;
|
||||
|
||||
*uart = sb;
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serdev_acpi_get_uart_resource);
|
||||
|
||||
static int acpi_serdev_parse_resource(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
struct acpi_serdev_lookup *lookup = data;
|
||||
struct acpi_resource_uart_serialbus *sb;
|
||||
acpi_status status;
|
||||
|
||||
if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
|
||||
return 1;
|
||||
|
||||
if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
|
||||
if (!serdev_acpi_get_uart_resource(ares, &sb))
|
||||
return 1;
|
||||
|
||||
if (lookup->index != -1 && lookup->n++ != lookup->index)
|
||||
return 1;
|
||||
|
||||
sb = &ares->data.uart_serial_bus;
|
||||
|
||||
status = acpi_get_handle(lookup->device_handle,
|
||||
sb->resource_source.string_ptr,
|
||||
&lookup->controller_handle);
|
||||
|
@ -586,7 +608,7 @@ static int acpi_serdev_parse_resource(struct acpi_resource *ares, void *data)
|
|||
return 1;
|
||||
|
||||
/*
|
||||
* NOTE: Ideally, we would also want to retreive other properties here,
|
||||
* NOTE: Ideally, we would also want to retrieve other properties here,
|
||||
* once setting them before opening the device is supported by serdev.
|
||||
*/
|
||||
|
||||
|
|
|
@ -941,7 +941,7 @@ static int brcmuart_probe(struct platform_device *pdev)
|
|||
struct clk *baud_mux_clk;
|
||||
struct uart_8250_port up;
|
||||
struct resource *irq;
|
||||
void __iomem *membase = 0;
|
||||
void __iomem *membase = NULL;
|
||||
resource_size_t mapbase = 0;
|
||||
u32 clk_rate = 0;
|
||||
int ret;
|
||||
|
|
|
@ -114,6 +114,7 @@ struct exar8250;
|
|||
struct exar8250_platform {
|
||||
int (*rs485_config)(struct uart_port *, struct serial_rs485 *);
|
||||
int (*register_gpio)(struct pci_dev *, struct uart_8250_port *);
|
||||
void (*unregister_gpio)(struct uart_8250_port *);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -352,9 +353,8 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
|
|||
writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
|
||||
}
|
||||
|
||||
static void *
|
||||
__xr17v35x_register_gpio(struct pci_dev *pcidev,
|
||||
const struct software_node *node)
|
||||
static struct platform_device *__xr17v35x_register_gpio(struct pci_dev *pcidev,
|
||||
const struct software_node *node)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
|
||||
|
@ -374,6 +374,12 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev,
|
|||
return pdev;
|
||||
}
|
||||
|
||||
static void __xr17v35x_unregister_gpio(struct platform_device *pdev)
|
||||
{
|
||||
device_remove_software_node(&pdev->dev);
|
||||
platform_device_unregister(pdev);
|
||||
}
|
||||
|
||||
static const struct property_entry exar_gpio_properties[] = {
|
||||
PROPERTY_ENTRY_U32("exar,first-pin", 0),
|
||||
PROPERTY_ENTRY_U32("ngpios", 16),
|
||||
|
@ -384,8 +390,7 @@ static const struct software_node exar_gpio_node = {
|
|||
.properties = exar_gpio_properties,
|
||||
};
|
||||
|
||||
static int xr17v35x_register_gpio(struct pci_dev *pcidev,
|
||||
struct uart_8250_port *port)
|
||||
static int xr17v35x_register_gpio(struct pci_dev *pcidev, struct uart_8250_port *port)
|
||||
{
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_EXAR)
|
||||
port->port.private_data =
|
||||
|
@ -394,6 +399,15 @@ static int xr17v35x_register_gpio(struct pci_dev *pcidev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void xr17v35x_unregister_gpio(struct uart_8250_port *port)
|
||||
{
|
||||
if (!port->port.private_data)
|
||||
return;
|
||||
|
||||
__xr17v35x_unregister_gpio(port->port.private_data);
|
||||
port->port.private_data = NULL;
|
||||
}
|
||||
|
||||
static int generic_rs485_config(struct uart_port *port,
|
||||
struct serial_rs485 *rs485)
|
||||
{
|
||||
|
@ -419,6 +433,7 @@ static int generic_rs485_config(struct uart_port *port,
|
|||
|
||||
static const struct exar8250_platform exar8250_default_platform = {
|
||||
.register_gpio = xr17v35x_register_gpio,
|
||||
.unregister_gpio = xr17v35x_unregister_gpio,
|
||||
.rs485_config = generic_rs485_config,
|
||||
};
|
||||
|
||||
|
@ -484,6 +499,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev,
|
|||
static const struct exar8250_platform iot2040_platform = {
|
||||
.rs485_config = iot2040_rs485_config,
|
||||
.register_gpio = iot2040_register_gpio,
|
||||
.unregister_gpio = xr17v35x_unregister_gpio,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -555,17 +571,11 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
|
|||
|
||||
static void pci_xr17v35x_exit(struct pci_dev *pcidev)
|
||||
{
|
||||
const struct exar8250_platform *platform = exar_get_platform();
|
||||
struct exar8250 *priv = pci_get_drvdata(pcidev);
|
||||
struct uart_8250_port *port = serial8250_get_port(priv->line[0]);
|
||||
struct platform_device *pdev;
|
||||
|
||||
pdev = port->port.private_data;
|
||||
if (!pdev)
|
||||
return;
|
||||
|
||||
device_remove_software_node(&pdev->dev);
|
||||
platform_device_unregister(pdev);
|
||||
port->port.private_data = NULL;
|
||||
platform->unregister_gpio(port);
|
||||
}
|
||||
|
||||
static inline void exar_misc_clear(struct exar8250 *priv)
|
||||
|
|
|
@ -209,16 +209,14 @@ static int ingenic_uart_probe(struct platform_device *pdev)
|
|||
struct uart_8250_port uart = {};
|
||||
struct ingenic_uart_data *data;
|
||||
const struct ingenic_uart_config *cdata;
|
||||
const struct of_device_id *match;
|
||||
struct resource *regs;
|
||||
int irq, err, line;
|
||||
|
||||
match = of_match_device(of_match, &pdev->dev);
|
||||
if (!match) {
|
||||
cdata = of_device_get_match_data(&pdev->dev);
|
||||
if (!cdata) {
|
||||
dev_err(&pdev->dev, "Error: No device match found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
cdata = match->data;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
|
|
|
@ -158,6 +158,16 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
|
|||
|
||||
static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
|
||||
{
|
||||
struct uart_8250_dma *dma = &lpss->data.dma;
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
|
||||
/*
|
||||
* This simply makes the checks in the 8250_port to try the DMA
|
||||
* channel request which in turn uses the magic of ACPI tables
|
||||
* parsing (see drivers/dma/acpi-dma.c for the details) and
|
||||
* matching with the registered General Purpose DMA controllers.
|
||||
*/
|
||||
up->dma = dma;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -538,7 +538,7 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state,
|
|||
static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
|
||||
struct omap8250_priv *priv)
|
||||
{
|
||||
const struct soc_device_attribute k3_soc_devices[] = {
|
||||
static const struct soc_device_attribute k3_soc_devices[] = {
|
||||
{ .family = "AM65X", },
|
||||
{ .family = "J721E", .revision = "SR1.0" },
|
||||
{ /* sentinel */ }
|
||||
|
@ -617,7 +617,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
|
|||
struct uart_port *port = dev_id;
|
||||
struct omap8250_priv *priv = port->private_data;
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
unsigned int iir;
|
||||
unsigned int iir, lsr;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_DMA
|
||||
|
@ -628,6 +628,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
|
|||
#endif
|
||||
|
||||
serial8250_rpm_get(up);
|
||||
lsr = serial_port_in(port, UART_LSR);
|
||||
iir = serial_port_in(port, UART_IIR);
|
||||
ret = serial8250_handle_irq(port, iir);
|
||||
|
||||
|
@ -642,6 +643,24 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
|
|||
serial_port_in(port, UART_RX);
|
||||
}
|
||||
|
||||
/* Stop processing interrupts on input overrun */
|
||||
if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) {
|
||||
unsigned long delay;
|
||||
|
||||
up->ier = port->serial_in(port, UART_IER);
|
||||
if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
|
||||
port->ops->stop_rx(port);
|
||||
} else {
|
||||
/* Keep restarting the timer until
|
||||
* the input overrun subsides.
|
||||
*/
|
||||
cancel_delayed_work(&up->overrun_backoff);
|
||||
}
|
||||
|
||||
delay = msecs_to_jiffies(up->overrun_backoff_time_ms);
|
||||
schedule_delayed_work(&up->overrun_backoff, delay);
|
||||
}
|
||||
|
||||
serial8250_rpm_put(up);
|
||||
|
||||
return IRQ_RETVAL(ret);
|
||||
|
@ -1353,6 +1372,10 @@ static int omap8250_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "overrun-throttle-ms",
|
||||
&up.overrun_backoff_time_ms) != 0)
|
||||
up.overrun_backoff_time_ms = 0;
|
||||
|
||||
priv->wakeirq = irq_of_parse_and_map(np, 1);
|
||||
|
||||
pdata = of_device_get_match_data(&pdev->dev);
|
||||
|
|
|
@ -87,7 +87,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
|
|||
|
||||
static int
|
||||
setup_port(struct serial_private *priv, struct uart_8250_port *port,
|
||||
int bar, int offset, int regshift)
|
||||
u8 bar, unsigned int offset, int regshift)
|
||||
{
|
||||
struct pci_dev *dev = priv->dev;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/pnp.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
|
@ -475,6 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
|||
if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
|
||||
uart.port.flags |= UPF_SHARE_IRQ;
|
||||
uart.port.uartclk = 1843200;
|
||||
device_property_read_u32(&dev->dev, "clock-frequency", &uart.port.uartclk);
|
||||
uart.port.dev = &dev->dev;
|
||||
|
||||
line = serial8250_register_8250_port(&uart);
|
||||
|
|
|
@ -122,7 +122,8 @@ static const struct serial8250_config uart_config[] = {
|
|||
.name = "16C950/954",
|
||||
.fifo_size = 128,
|
||||
.tx_loadsz = 128,
|
||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
|
||||
.rxtrig_bytes = {16, 32, 112, 120},
|
||||
/* UART_CAP_EFR breaks billionon CF bluetooth card. */
|
||||
.flags = UART_CAP_FIFO | UART_CAP_SLEEP,
|
||||
},
|
||||
|
|
|
@ -363,7 +363,7 @@ config SERIAL_8250_BCM2835AUX
|
|||
config SERIAL_8250_FSL
|
||||
bool
|
||||
depends on SERIAL_8250_CONSOLE
|
||||
default PPC || ARM || ARM64
|
||||
default PPC || ARM || ARM64 || COMPILE_TEST
|
||||
|
||||
config SERIAL_8250_DW
|
||||
tristate "Support for Synopsys DesignWare 8250 quirks"
|
||||
|
@ -375,7 +375,8 @@ config SERIAL_8250_DW
|
|||
|
||||
config SERIAL_8250_EM
|
||||
tristate "Support for Emma Mobile integrated serial port"
|
||||
depends on SERIAL_8250 && ARM && HAVE_CLK
|
||||
depends on SERIAL_8250 && HAVE_CLK
|
||||
depends on ARM || COMPILE_TEST
|
||||
help
|
||||
Selecting this option will add support for the integrated serial
|
||||
port hardware found on the Emma Mobile line of processors.
|
||||
|
@ -383,7 +384,8 @@ config SERIAL_8250_EM
|
|||
|
||||
config SERIAL_8250_IOC3
|
||||
tristate "SGI IOC3 8250 UART support"
|
||||
depends on SGI_MFD_IOC3 && SERIAL_8250
|
||||
depends on SERIAL_8250
|
||||
depends on SGI_MFD_IOC3 || COMPILE_TEST
|
||||
select SERIAL_8250_EXTENDED
|
||||
select SERIAL_8250_SHARE_IRQ
|
||||
help
|
||||
|
@ -495,7 +497,7 @@ config SERIAL_8250_MID
|
|||
config SERIAL_8250_PXA
|
||||
tristate "PXA serial port support"
|
||||
depends on SERIAL_8250
|
||||
depends on ARCH_PXA || ARCH_MMP
|
||||
depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST
|
||||
help
|
||||
If you have a machine based on an Intel XScale PXA2xx CPU you can
|
||||
enable its onboard serial ports by enabling this option. The option is
|
||||
|
|
|
@ -959,7 +959,7 @@ config SERIAL_VT8500_CONSOLE
|
|||
|
||||
config SERIAL_OMAP
|
||||
tristate "OMAP serial port support"
|
||||
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||
depends on (ARCH_OMAP2PLUS && !SERIAL_8250_OMAP) || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a machine based on an Texas Instruments OMAP CPU you
|
||||
|
@ -1382,7 +1382,7 @@ config SERIAL_ST_ASC
|
|||
select SERIAL_CORE
|
||||
depends on ARM || COMPILE_TEST
|
||||
help
|
||||
This driver is for the on-chip Asychronous Serial Controller on
|
||||
This driver is for the on-chip Asynchronous Serial Controller on
|
||||
STMicroelectronics STi SoCs.
|
||||
ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
|
||||
It support all industry standard baud rates.
|
||||
|
|
|
@ -265,6 +265,8 @@ struct uart_amba_port {
|
|||
unsigned int old_cr; /* state during shutdown */
|
||||
unsigned int fixed_baud; /* vendor-set fixed baud rate */
|
||||
char type[12];
|
||||
bool rs485_tx_started;
|
||||
unsigned int rs485_tx_drain_interval; /* usecs */
|
||||
#ifdef CONFIG_DMA_ENGINE
|
||||
/* DMA stuff */
|
||||
bool using_tx_dma;
|
||||
|
@ -275,6 +277,8 @@ struct uart_amba_port {
|
|||
#endif
|
||||
};
|
||||
|
||||
static unsigned int pl011_tx_empty(struct uart_port *port);
|
||||
|
||||
static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
|
||||
unsigned int reg)
|
||||
{
|
||||
|
@ -1282,6 +1286,42 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
|
|||
#define pl011_dma_flush_buffer NULL
|
||||
#endif
|
||||
|
||||
static void pl011_rs485_tx_stop(struct uart_amba_port *uap)
|
||||
{
|
||||
struct uart_port *port = &uap->port;
|
||||
int i = 0;
|
||||
u32 cr;
|
||||
|
||||
/* Wait until hardware tx queue is empty */
|
||||
while (!pl011_tx_empty(port)) {
|
||||
if (i == port->fifosize) {
|
||||
dev_warn(port->dev,
|
||||
"timeout while draining hardware tx queue\n");
|
||||
break;
|
||||
}
|
||||
|
||||
udelay(uap->rs485_tx_drain_interval);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (port->rs485.delay_rts_after_send)
|
||||
mdelay(port->rs485.delay_rts_after_send);
|
||||
|
||||
cr = pl011_read(uap, REG_CR);
|
||||
|
||||
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
cr &= ~UART011_CR_RTS;
|
||||
else
|
||||
cr |= UART011_CR_RTS;
|
||||
|
||||
/* Disable the transmitter and reenable the transceiver */
|
||||
cr &= ~UART011_CR_TXE;
|
||||
cr |= UART011_CR_RXE;
|
||||
pl011_write(cr, uap, REG_CR);
|
||||
|
||||
uap->rs485_tx_started = false;
|
||||
}
|
||||
|
||||
static void pl011_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap =
|
||||
|
@ -1290,6 +1330,9 @@ static void pl011_stop_tx(struct uart_port *port)
|
|||
uap->im &= ~UART011_TXIM;
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
pl011_dma_tx_stop(uap);
|
||||
|
||||
if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
|
||||
pl011_rs485_tx_stop(uap);
|
||||
}
|
||||
|
||||
static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
|
||||
|
@ -1380,6 +1423,32 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void pl011_rs485_tx_start(struct uart_amba_port *uap)
|
||||
{
|
||||
struct uart_port *port = &uap->port;
|
||||
u32 cr;
|
||||
|
||||
/* Enable transmitter */
|
||||
cr = pl011_read(uap, REG_CR);
|
||||
cr |= UART011_CR_TXE;
|
||||
|
||||
/* Disable receiver if half-duplex */
|
||||
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
|
||||
cr &= ~UART011_CR_RXE;
|
||||
|
||||
if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
|
||||
cr &= ~UART011_CR_RTS;
|
||||
else
|
||||
cr |= UART011_CR_RTS;
|
||||
|
||||
pl011_write(cr, uap, REG_CR);
|
||||
|
||||
if (port->rs485.delay_rts_before_send)
|
||||
mdelay(port->rs485.delay_rts_before_send);
|
||||
|
||||
uap->rs485_tx_started = true;
|
||||
}
|
||||
|
||||
/* Returns true if tx interrupts have to be (kept) enabled */
|
||||
static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
|
||||
{
|
||||
|
@ -1397,6 +1466,10 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
|
||||
!uap->rs485_tx_started)
|
||||
pl011_rs485_tx_start(uap);
|
||||
|
||||
/* If we are using DMA mode, try to send some characters. */
|
||||
if (pl011_dma_tx_irq(uap))
|
||||
return true;
|
||||
|
@ -1542,6 +1615,9 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
container_of(port, struct uart_amba_port, port);
|
||||
unsigned int cr;
|
||||
|
||||
if (port->rs485.flags & SER_RS485_ENABLED)
|
||||
mctrl &= ~TIOCM_RTS;
|
||||
|
||||
cr = pl011_read(uap, REG_CR);
|
||||
|
||||
#define TIOCMBIT(tiocmbit, uartbit) \
|
||||
|
@ -1763,7 +1839,17 @@ static int pl011_startup(struct uart_port *port)
|
|||
|
||||
/* restore RTS and DTR */
|
||||
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
|
||||
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
|
||||
cr |= UART01x_CR_UARTEN | UART011_CR_RXE;
|
||||
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
cr &= ~UART011_CR_RTS;
|
||||
else
|
||||
cr |= UART011_CR_RTS;
|
||||
} else {
|
||||
cr |= UART011_CR_TXE;
|
||||
}
|
||||
|
||||
pl011_write(cr, uap, REG_CR);
|
||||
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
|
@ -1864,6 +1950,9 @@ static void pl011_shutdown(struct uart_port *port)
|
|||
|
||||
pl011_dma_shutdown(uap);
|
||||
|
||||
if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
|
||||
pl011_rs485_tx_stop(uap);
|
||||
|
||||
free_irq(uap->port.irq, uap);
|
||||
|
||||
pl011_disable_uart(uap);
|
||||
|
@ -1941,6 +2030,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
unsigned int lcr_h, old_cr;
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot, clkdiv;
|
||||
unsigned int bits;
|
||||
|
||||
if (uap->vendor->oversampling)
|
||||
clkdiv = 8;
|
||||
|
@ -1991,6 +2081,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
if (uap->fifosize > 1)
|
||||
lcr_h |= UART01x_LCRH_FEN;
|
||||
|
||||
bits = tty_get_frame_size(termios->c_cflag);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/*
|
||||
|
@ -1998,11 +2090,21 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
/*
|
||||
* Calculate the approximated time it takes to transmit one character
|
||||
* with the given baud rate. We use this as the poll interval when we
|
||||
* wait for the tx queue to empty.
|
||||
*/
|
||||
uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud;
|
||||
|
||||
pl011_setup_status_masks(port, termios);
|
||||
|
||||
if (UART_ENABLE_MS(port, termios->c_cflag))
|
||||
pl011_enable_ms(port);
|
||||
|
||||
if (port->rs485.flags & SER_RS485_ENABLED)
|
||||
termios->c_cflag &= ~CRTSCTS;
|
||||
|
||||
/* first, disable everything */
|
||||
old_cr = pl011_read(uap, REG_CR);
|
||||
pl011_write(0, uap, REG_CR);
|
||||
|
@ -2124,6 +2226,41 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int pl011_rs485_config(struct uart_port *port,
|
||||
struct serial_rs485 *rs485)
|
||||
{
|
||||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
|
||||
/* pick sane settings if the user hasn't */
|
||||
if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
|
||||
!(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
|
||||
rs485->flags |= SER_RS485_RTS_ON_SEND;
|
||||
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
/* clamp the delays to [0, 100ms] */
|
||||
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
|
||||
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
|
||||
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||
|
||||
if (port->rs485.flags & SER_RS485_ENABLED)
|
||||
pl011_rs485_tx_stop(uap);
|
||||
|
||||
/* Set new configuration */
|
||||
port->rs485 = *rs485;
|
||||
|
||||
/* Make sure auto RTS is disabled */
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
u32 cr = pl011_read(uap, REG_CR);
|
||||
|
||||
cr &= ~UART011_CR_RTSEN;
|
||||
pl011_write(cr, uap, REG_CR);
|
||||
port->status &= ~UPSTAT_AUTORTS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct uart_ops amba_pl011_pops = {
|
||||
.tx_empty = pl011_tx_empty,
|
||||
.set_mctrl = pl011_set_mctrl,
|
||||
|
@ -2588,10 +2725,28 @@ static int pl011_find_free_port(void)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int pl011_get_rs485_mode(struct uart_amba_port *uap)
|
||||
{
|
||||
struct uart_port *port = &uap->port;
|
||||
struct serial_rs485 *rs485 = &port->rs485;
|
||||
int ret;
|
||||
|
||||
ret = uart_get_rs485_mode(port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* clamp the delays to [0, 100ms] */
|
||||
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
|
||||
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
|
||||
struct resource *mmiobase, int index)
|
||||
{
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
base = devm_ioremap_resource(dev, mmiobase);
|
||||
if (IS_ERR(base))
|
||||
|
@ -2608,6 +2763,10 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
|
|||
uap->port.flags = UPF_BOOT_AUTOCONF;
|
||||
uap->port.line = index;
|
||||
|
||||
ret = pl011_get_rs485_mode(uap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
amba_ports[index] = uap;
|
||||
|
||||
return 0;
|
||||
|
@ -2665,7 +2824,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM;
|
||||
uap->port.irq = dev->irq[0];
|
||||
uap->port.ops = &amba_pl011_pops;
|
||||
|
||||
uap->port.rs485_config = pl011_rs485_config;
|
||||
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
|
||||
|
||||
ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr);
|
||||
|
|
|
@ -861,11 +861,7 @@ static int linflex_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, sport);
|
||||
|
||||
ret = uart_add_one_port(&linflex_reg, sport);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return uart_add_one_port(&linflex_reg, sport);
|
||||
}
|
||||
|
||||
static int linflex_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dmapool.h>
|
||||
|
@ -109,6 +110,11 @@
|
|||
#define UARTSFIFO_TXOF 0x02
|
||||
#define UARTSFIFO_RXUF 0x01
|
||||
|
||||
/* 32-bit global registers only for i.MX7ULP/i.MX8x
|
||||
* Used to reset all internal logic and registers, except the Global Register.
|
||||
*/
|
||||
#define UART_GLOBAL 0x8
|
||||
|
||||
/* 32-bit register definition */
|
||||
#define UARTBAUD 0x00
|
||||
#define UARTSTAT 0x04
|
||||
|
@ -219,6 +225,10 @@
|
|||
#define UARTWATER_TXWATER_OFF 0
|
||||
#define UARTWATER_RXWATER_OFF 16
|
||||
|
||||
#define UART_GLOBAL_RST 0x2
|
||||
#define GLOBAL_RST_MIN_US 20
|
||||
#define GLOBAL_RST_MAX_US 40
|
||||
|
||||
/* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
|
||||
#define DMA_RX_TIMEOUT (10)
|
||||
|
||||
|
@ -320,6 +330,11 @@ static inline bool is_layerscape_lpuart(struct lpuart_port *sport)
|
|||
sport->devtype == LS1028A_LPUART);
|
||||
}
|
||||
|
||||
static inline bool is_imx7ulp_lpuart(struct lpuart_port *sport)
|
||||
{
|
||||
return sport->devtype == IMX7ULP_LPUART;
|
||||
}
|
||||
|
||||
static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
|
||||
{
|
||||
return sport->devtype == IMX8QXP_LPUART;
|
||||
|
@ -383,6 +398,33 @@ static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport)
|
|||
#define lpuart_enable_clks(x) __lpuart_enable_clks(x, true)
|
||||
#define lpuart_disable_clks(x) __lpuart_enable_clks(x, false)
|
||||
|
||||
static int lpuart_global_reset(struct lpuart_port *sport)
|
||||
{
|
||||
struct uart_port *port = &sport->port;
|
||||
void __iomem *global_addr;
|
||||
int ret;
|
||||
|
||||
if (uart_console(port))
|
||||
return 0;
|
||||
|
||||
ret = clk_prepare_enable(sport->ipg_clk);
|
||||
if (ret) {
|
||||
dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (is_imx7ulp_lpuart(sport) || is_imx8qxp_lpuart(sport)) {
|
||||
global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF;
|
||||
writel(UART_GLOBAL_RST, global_addr);
|
||||
usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
|
||||
writel(0, global_addr);
|
||||
usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(sport->ipg_clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lpuart_stop_tx(struct uart_port *port)
|
||||
{
|
||||
unsigned char temp;
|
||||
|
@ -479,6 +521,10 @@ static void lpuart_dma_tx_complete(void *arg)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
if (!sport->dma_tx_in_progress) {
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents,
|
||||
DMA_TO_DEVICE);
|
||||
|
@ -2045,11 +2091,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
{
|
||||
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
|
||||
unsigned long flags;
|
||||
unsigned long ctrl, old_ctrl, modem;
|
||||
unsigned long ctrl, old_ctrl, bd, modem;
|
||||
unsigned int baud;
|
||||
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
|
||||
|
||||
ctrl = old_ctrl = lpuart32_read(&sport->port, UARTCTRL);
|
||||
bd = lpuart32_read(&sport->port, UARTBAUD);
|
||||
modem = lpuart32_read(&sport->port, UARTMODIR);
|
||||
/*
|
||||
* only support CS8 and CS7, and for CS7 must enable PE.
|
||||
|
@ -2093,7 +2140,9 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
}
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
termios->c_cflag &= ~CSTOPB;
|
||||
bd |= UARTBAUD_SBNS;
|
||||
else
|
||||
bd &= ~UARTBAUD_SBNS;
|
||||
|
||||
/* parity must be enabled when CS7 to match 8-bits format */
|
||||
if ((termios->c_cflag & CSIZE) == CS7)
|
||||
|
@ -2163,6 +2212,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
|
||||
UARTCTRL);
|
||||
|
||||
lpuart32_write(&sport->port, bd, UARTBAUD);
|
||||
lpuart32_serial_setbrg(sport, baud);
|
||||
lpuart32_write(&sport->port, modem, UARTMODIR);
|
||||
lpuart32_write(&sport->port, ctrl, UARTCTRL);
|
||||
|
@ -2611,7 +2661,7 @@ static int lpuart_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(sport->port.membase);
|
||||
|
||||
sport->port.membase += sdata->reg_off;
|
||||
sport->port.mapbase = res->start;
|
||||
sport->port.mapbase = res->start + sdata->reg_off;
|
||||
sport->port.dev = &pdev->dev;
|
||||
sport->port.type = PORT_LPUART;
|
||||
sport->devtype = sdata->devtype;
|
||||
|
@ -2691,6 +2741,10 @@ static int lpuart_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto failed_attach_port;
|
||||
|
||||
ret = lpuart_global_reset(sport);
|
||||
if (ret)
|
||||
goto failed_reset;
|
||||
|
||||
ret = uart_get_rs485_mode(&sport->port);
|
||||
if (ret)
|
||||
goto failed_get_rs485;
|
||||
|
@ -2707,6 +2761,8 @@ static int lpuart_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
failed_get_rs485:
|
||||
failed_reset:
|
||||
uart_remove_one_port(&lpuart_reg, &sport->port);
|
||||
failed_attach_port:
|
||||
failed_irq_request:
|
||||
lpuart_disable_clks(sport);
|
||||
|
|
|
@ -815,7 +815,9 @@ static void neo_parse_isr(struct jsm_board *brd, u32 port)
|
|||
/* Parse any modem signal changes */
|
||||
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
|
||||
"MOD_STAT: sending to parse_modem_sigs\n");
|
||||
spin_lock_irqsave(&ch->uart_port.lock, lock_flags);
|
||||
neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
|
||||
spin_unlock_irqrestore(&ch->uart_port.lock, lock_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -187,6 +187,7 @@ static void jsm_tty_break(struct uart_port *port, int break_state)
|
|||
|
||||
static int jsm_tty_open(struct uart_port *port)
|
||||
{
|
||||
unsigned long lock_flags;
|
||||
struct jsm_board *brd;
|
||||
struct jsm_channel *channel =
|
||||
container_of(port, struct jsm_channel, uart_port);
|
||||
|
@ -240,6 +241,7 @@ static int jsm_tty_open(struct uart_port *port)
|
|||
channel->ch_cached_lsr = 0;
|
||||
channel->ch_stops_sent = 0;
|
||||
|
||||
spin_lock_irqsave(&port->lock, lock_flags);
|
||||
termios = &port->state->port.tty->termios;
|
||||
channel->ch_c_cflag = termios->c_cflag;
|
||||
channel->ch_c_iflag = termios->c_iflag;
|
||||
|
@ -259,6 +261,7 @@ static int jsm_tty_open(struct uart_port *port)
|
|||
jsm_carrier(channel);
|
||||
|
||||
channel->ch_open_count++;
|
||||
spin_unlock_irqrestore(&port->lock, lock_flags);
|
||||
|
||||
jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n");
|
||||
return 0;
|
||||
|
|
|
@ -330,17 +330,16 @@ int kgdb_register_nmi_console(void)
|
|||
if (!arch_kgdb_ops.enable_nmi)
|
||||
return 0;
|
||||
|
||||
kgdb_nmi_tty_driver = alloc_tty_driver(1);
|
||||
if (!kgdb_nmi_tty_driver) {
|
||||
kgdb_nmi_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
|
||||
if (IS_ERR(kgdb_nmi_tty_driver)) {
|
||||
pr_err("%s: cannot allocate tty\n", __func__);
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(kgdb_nmi_tty_driver);
|
||||
}
|
||||
kgdb_nmi_tty_driver->driver_name = "ttyNMI";
|
||||
kgdb_nmi_tty_driver->name = "ttyNMI";
|
||||
kgdb_nmi_tty_driver->num = 1;
|
||||
kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
kgdb_nmi_tty_driver->init_termios = tty_std_termios;
|
||||
tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios,
|
||||
KGDB_NMI_BAUD, KGDB_NMI_BAUD);
|
||||
|
@ -356,7 +355,7 @@ int kgdb_register_nmi_console(void)
|
|||
|
||||
return 0;
|
||||
err_drv_reg:
|
||||
put_tty_driver(kgdb_nmi_tty_driver);
|
||||
tty_driver_kref_put(kgdb_nmi_tty_driver);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kgdb_register_nmi_console);
|
||||
|
@ -374,7 +373,7 @@ int kgdb_unregister_nmi_console(void)
|
|||
return ret;
|
||||
|
||||
tty_unregister_driver(kgdb_nmi_tty_driver);
|
||||
put_tty_driver(kgdb_nmi_tty_driver);
|
||||
tty_driver_kref_put(kgdb_nmi_tty_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1271,18 +1271,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
|||
/* Always ask for fixed clock rate from a property. */
|
||||
device_property_read_u32(dev, "clock-frequency", &uartclk);
|
||||
|
||||
s->clk = devm_clk_get_optional(dev, "osc");
|
||||
xtal = device_property_match_string(dev, "clock-names", "osc") < 0;
|
||||
if (xtal)
|
||||
s->clk = devm_clk_get_optional(dev, "xtal");
|
||||
else
|
||||
s->clk = devm_clk_get_optional(dev, "osc");
|
||||
if (IS_ERR(s->clk))
|
||||
return PTR_ERR(s->clk);
|
||||
if (s->clk) {
|
||||
xtal = false;
|
||||
} else {
|
||||
s->clk = devm_clk_get_optional(dev, "xtal");
|
||||
if (IS_ERR(s->clk))
|
||||
return PTR_ERR(s->clk);
|
||||
|
||||
xtal = true;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(s->clk);
|
||||
if (ret)
|
||||
|
|
|
@ -276,11 +276,8 @@ static void serial_omap_enable_ms(struct uart_port *port)
|
|||
|
||||
dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line);
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
up->ier |= UART_IER_MSI;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static void serial_omap_stop_tx(struct uart_port *port)
|
||||
|
@ -288,8 +285,6 @@ static void serial_omap_stop_tx(struct uart_port *port)
|
|||
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||
int res;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
|
||||
/* Handle RS-485 */
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
if (up->scr & OMAP_UART_SCR_TX_EMPTY) {
|
||||
|
@ -330,21 +325,15 @@ static void serial_omap_stop_tx(struct uart_port *port)
|
|||
up->ier &= ~UART_IER_THRI;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static void serial_omap_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
|
||||
up->port.read_status_mask &= ~UART_LSR_DR;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
|
||||
|
@ -399,8 +388,6 @@ static void serial_omap_start_tx(struct uart_port *port)
|
|||
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||
int res;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
|
||||
/* Handle RS-485 */
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
/* Fire THR interrupts when FIFO is below trigger level */
|
||||
|
@ -421,8 +408,6 @@ static void serial_omap_start_tx(struct uart_port *port)
|
|||
up->rs485_tx_filter_count = 0;
|
||||
|
||||
serial_omap_enable_ier_thri(up);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static void serial_omap_throttle(struct uart_port *port)
|
||||
|
@ -430,13 +415,10 @@ static void serial_omap_throttle(struct uart_port *port)
|
|||
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||
unsigned long flags;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static void serial_omap_unthrottle(struct uart_port *port)
|
||||
|
@ -444,13 +426,10 @@ static void serial_omap_unthrottle(struct uart_port *port)
|
|||
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||
unsigned long flags;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
up->ier |= UART_IER_RLSI | UART_IER_RDI;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static unsigned int check_modem_status(struct uart_omap_port *up)
|
||||
|
@ -576,7 +555,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
|
|||
int max_count = 256;
|
||||
|
||||
spin_lock(&up->port.lock);
|
||||
pm_runtime_get_sync(up->dev);
|
||||
|
||||
do {
|
||||
iir = serial_in(up, UART_IIR);
|
||||
|
@ -616,8 +594,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
|
|||
|
||||
tty_flip_buffer_push(&up->port.state->port);
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
up->port_activity = jiffies;
|
||||
|
||||
return ret;
|
||||
|
@ -629,13 +605,11 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
|
|||
unsigned long flags;
|
||||
unsigned int ret = 0;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line);
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -645,10 +619,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
|
|||
unsigned int status;
|
||||
unsigned int ret = 0;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
status = check_modem_status(up);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
|
||||
dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line);
|
||||
|
||||
|
@ -680,7 +651,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
if (mctrl & TIOCM_LOOP)
|
||||
mcr |= UART_MCR_LOOP;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
old_mcr = serial_in(up, UART_MCR);
|
||||
old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 |
|
||||
UART_MCR_DTR | UART_MCR_RTS);
|
||||
|
@ -696,9 +666,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
up->efr &= ~UART_EFR_RTS;
|
||||
serial_out(up, UART_EFR, up->efr);
|
||||
serial_out(up, UART_LCR, lcr);
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
|
||||
|
@ -707,7 +674,6 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
|
|||
unsigned long flags;
|
||||
|
||||
dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
|
||||
pm_runtime_get_sync(up->dev);
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
if (break_state == -1)
|
||||
up->lcr |= UART_LCR_SBC;
|
||||
|
@ -715,8 +681,6 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
|
|||
up->lcr &= ~UART_LCR_SBC;
|
||||
serial_out(up, UART_LCR, up->lcr);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static int serial_omap_startup(struct uart_port *port)
|
||||
|
@ -788,8 +752,6 @@ static int serial_omap_startup(struct uart_port *port)
|
|||
|
||||
serial_out(up, UART_OMAP_WER, up->wer);
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
up->port_activity = jiffies;
|
||||
return 0;
|
||||
}
|
||||
|
@ -801,7 +763,6 @@ static void serial_omap_shutdown(struct uart_port *port)
|
|||
|
||||
dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line);
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
/*
|
||||
* Disable interrupts from this port
|
||||
*/
|
||||
|
@ -825,8 +786,7 @@ static void serial_omap_shutdown(struct uart_port *port)
|
|||
if (serial_in(up, UART_LSR) & UART_LSR_DR)
|
||||
(void) serial_in(up, UART_RX);
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
pm_runtime_put_sync(up->dev);
|
||||
free_irq(up->port.irq, up);
|
||||
dev_pm_clear_wake_irq(up->dev);
|
||||
}
|
||||
|
@ -896,7 +856,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
* Ok, we're now changing the port state. Do it with
|
||||
* interrupts disabled.
|
||||
*/
|
||||
pm_runtime_get_sync(up->dev);
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
|
||||
/*
|
||||
|
@ -1096,8 +1055,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
serial_omap_set_mctrl(&up->port, up->port.mctrl);
|
||||
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
|
||||
}
|
||||
|
||||
|
@ -1110,7 +1067,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
|
|||
|
||||
dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line);
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
efr = serial_in(up, UART_EFR);
|
||||
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
|
||||
|
@ -1120,9 +1076,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
|
|||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
serial_out(up, UART_EFR, efr);
|
||||
serial_out(up, UART_LCR, 0);
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static void serial_omap_release_port(struct uart_port *port)
|
||||
|
@ -1202,11 +1155,8 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
|
|||
{
|
||||
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
wait_for_xmitr(up);
|
||||
serial_out(up, UART_TX, ch);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
}
|
||||
|
||||
static int serial_omap_poll_get_char(struct uart_port *port)
|
||||
|
@ -1214,7 +1164,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
|
|||
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||
unsigned int status;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
status = serial_in(up, UART_LSR);
|
||||
if (!(status & UART_LSR_DR)) {
|
||||
status = NO_POLL_CHAR;
|
||||
|
@ -1224,9 +1173,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
|
|||
status = serial_in(up, UART_RX);
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1309,8 +1255,6 @@ serial_omap_console_write(struct console *co, const char *s,
|
|||
unsigned int ier;
|
||||
int locked = 1;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
|
||||
local_irq_save(flags);
|
||||
if (up->port.sysrq)
|
||||
locked = 0;
|
||||
|
@ -1343,8 +1287,6 @@ serial_omap_console_write(struct console *co, const char *s,
|
|||
if (up->msr_saved_flags)
|
||||
check_modem_status(up);
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
if (locked)
|
||||
spin_unlock(&up->port.lock);
|
||||
local_irq_restore(flags);
|
||||
|
@ -1403,8 +1345,6 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
|
|||
unsigned int mode;
|
||||
int val;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
|
||||
/* Disable interrupts from this port */
|
||||
mode = up->ier;
|
||||
up->ier = 0;
|
||||
|
@ -1438,9 +1378,6 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
|
|||
serial_out(up, UART_OMAP_SCR, up->scr);
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1737,11 +1674,7 @@ static int serial_omap_probe(struct platform_device *pdev)
|
|||
omap_up_info->autosuspend_timeout = -1;
|
||||
|
||||
device_init_wakeup(up->dev, true);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev,
|
||||
omap_up_info->autosuspend_timeout);
|
||||
|
||||
pm_runtime_irq_safe(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
@ -1755,12 +1688,9 @@ static int serial_omap_probe(struct platform_device *pdev)
|
|||
if (ret != 0)
|
||||
goto err_add_port;
|
||||
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
return 0;
|
||||
|
||||
err_add_port:
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
cpu_latency_qos_remove_request(&up->pm_qos_request);
|
||||
|
@ -1778,7 +1708,6 @@ static int serial_omap_remove(struct platform_device *dev)
|
|||
|
||||
uart_remove_one_port(&serial_omap_reg, &up->port);
|
||||
|
||||
pm_runtime_dont_use_autosuspend(up->dev);
|
||||
pm_runtime_put_sync(up->dev);
|
||||
pm_runtime_disable(up->dev);
|
||||
cpu_latency_qos_remove_request(&up->pm_qos_request);
|
||||
|
|
|
@ -65,6 +65,7 @@ enum s3c24xx_port_type {
|
|||
struct s3c24xx_uart_info {
|
||||
char *name;
|
||||
enum s3c24xx_port_type type;
|
||||
unsigned int has_usi;
|
||||
unsigned int port_type;
|
||||
unsigned int fifosize;
|
||||
unsigned long rx_fifomask;
|
||||
|
@ -305,8 +306,9 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
|
|||
dmaengine_pause(dma->tx_chan);
|
||||
dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
|
||||
dmaengine_terminate_all(dma->tx_chan);
|
||||
dma_sync_single_for_cpu(ourport->port.dev,
|
||||
dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE);
|
||||
dma_sync_single_for_cpu(dma->tx_chan->device->dev,
|
||||
dma->tx_transfer_addr, dma->tx_size,
|
||||
DMA_TO_DEVICE);
|
||||
async_tx_ack(dma->tx_desc);
|
||||
count = dma->tx_bytes_requested - state.residue;
|
||||
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
|
||||
|
@ -338,8 +340,9 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
|
|||
count = dma->tx_bytes_requested - state.residue;
|
||||
async_tx_ack(dma->tx_desc);
|
||||
|
||||
dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr,
|
||||
dma->tx_size, DMA_TO_DEVICE);
|
||||
dma_sync_single_for_cpu(dma->tx_chan->device->dev,
|
||||
dma->tx_transfer_addr, dma->tx_size,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
|
@ -443,8 +446,9 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
|
|||
dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
|
||||
dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
|
||||
|
||||
dma_sync_single_for_device(ourport->port.dev, dma->tx_transfer_addr,
|
||||
dma->tx_size, DMA_TO_DEVICE);
|
||||
dma_sync_single_for_device(dma->tx_chan->device->dev,
|
||||
dma->tx_transfer_addr, dma->tx_size,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan,
|
||||
dma->tx_transfer_addr, dma->tx_size,
|
||||
|
@ -515,7 +519,7 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport,
|
|||
if (!count)
|
||||
return;
|
||||
|
||||
dma_sync_single_for_cpu(ourport->port.dev, dma->rx_addr,
|
||||
dma_sync_single_for_cpu(dma->rx_chan->device->dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
|
||||
ourport->port.icount.rx += count;
|
||||
|
@ -636,8 +640,8 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
|
|||
{
|
||||
struct s3c24xx_uart_dma *dma = ourport->dma;
|
||||
|
||||
dma_sync_single_for_device(ourport->port.dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_device(dma->rx_chan->device->dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
|
||||
dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan,
|
||||
dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM,
|
||||
|
@ -1102,18 +1106,19 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
|
|||
goto err_release_tx;
|
||||
}
|
||||
|
||||
dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(p->port.dev, dma->rx_addr)) {
|
||||
dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(dma->rx_chan->device->dev, dma->rx_addr)) {
|
||||
reason = "DMA mapping error for RX buffer";
|
||||
ret = -EIO;
|
||||
goto err_free_rx;
|
||||
}
|
||||
|
||||
/* TX buffer */
|
||||
dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf,
|
||||
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(p->port.dev, dma->tx_addr)) {
|
||||
dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
|
||||
p->port.state->xmit.buf, UART_XMIT_SIZE,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) {
|
||||
reason = "DMA mapping error for TX buffer";
|
||||
ret = -EIO;
|
||||
goto err_unmap_rx;
|
||||
|
@ -1122,8 +1127,8 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
|
|||
return 0;
|
||||
|
||||
err_unmap_rx:
|
||||
dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
err_free_rx:
|
||||
kfree(dma->rx_buf);
|
||||
err_release_tx:
|
||||
|
@ -1142,8 +1147,8 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
|
|||
|
||||
if (dma->rx_chan) {
|
||||
dmaengine_terminate_all(dma->rx_chan);
|
||||
dma_unmap_single(p->port.dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
kfree(dma->rx_buf);
|
||||
dma_release_channel(dma->rx_chan);
|
||||
dma->rx_chan = NULL;
|
||||
|
@ -1151,8 +1156,8 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
|
|||
|
||||
if (dma->tx_chan) {
|
||||
dmaengine_terminate_all(dma->tx_chan);
|
||||
dma_unmap_single(p->port.dev, dma->tx_addr,
|
||||
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
||||
dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
|
||||
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
||||
dma_release_channel(dma->tx_chan);
|
||||
dma->tx_chan = NULL;
|
||||
}
|
||||
|
@ -1352,6 +1357,28 @@ static int apple_s5l_serial_startup(struct uart_port *port)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void exynos_usi_init(struct uart_port *port)
|
||||
{
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
struct s3c24xx_uart_info *info = ourport->info;
|
||||
unsigned int val;
|
||||
|
||||
if (!info->has_usi)
|
||||
return;
|
||||
|
||||
/* Clear the software reset of USI block (it's set at startup) */
|
||||
val = rd_regl(port, USI_CON);
|
||||
val &= ~USI_CON_RESET_MASK;
|
||||
wr_regl(port, USI_CON, val);
|
||||
udelay(1);
|
||||
|
||||
/* Continuously provide the clock to USI IP w/o gating (for Rx mode) */
|
||||
val = rd_regl(port, USI_OPTION);
|
||||
val &= ~USI_OPTION_HWACG_MASK;
|
||||
val |= USI_OPTION_HWACG_CLKREQ_ON;
|
||||
wr_regl(port, USI_OPTION, val);
|
||||
}
|
||||
|
||||
/* power power management control */
|
||||
|
||||
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
|
||||
|
@ -1379,6 +1406,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
|
|||
if (!IS_ERR(ourport->baudclk))
|
||||
clk_prepare_enable(ourport->baudclk);
|
||||
|
||||
exynos_usi_init(port);
|
||||
break;
|
||||
default:
|
||||
dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
|
||||
|
@ -2102,6 +2130,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
|||
if (ret)
|
||||
pr_warn("uart: failed to enable baudclk\n");
|
||||
|
||||
exynos_usi_init(port);
|
||||
|
||||
/* Keep all interrupts masked and cleared */
|
||||
switch (ourport->info->type) {
|
||||
case TYPE_S3C6400:
|
||||
|
@ -2750,10 +2780,11 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
|
|||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_EXYNOS)
|
||||
#define EXYNOS_COMMON_SERIAL_DRV_DATA \
|
||||
#define EXYNOS_COMMON_SERIAL_DRV_DATA_USI(_has_usi) \
|
||||
.info = &(struct s3c24xx_uart_info) { \
|
||||
.name = "Samsung Exynos UART", \
|
||||
.type = TYPE_S3C6400, \
|
||||
.has_usi = _has_usi, \
|
||||
.port_type = PORT_S3C6400, \
|
||||
.has_divslot = 1, \
|
||||
.rx_fifomask = S5PV210_UFSTAT_RXMASK, \
|
||||
|
@ -2773,6 +2804,9 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
|
|||
.has_fracval = 1, \
|
||||
} \
|
||||
|
||||
#define EXYNOS_COMMON_SERIAL_DRV_DATA \
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA_USI(0)
|
||||
|
||||
static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA,
|
||||
.fifosize = { 256, 64, 16, 16 },
|
||||
|
@ -2783,11 +2817,19 @@ static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
|
|||
.fifosize = { 64, 256, 16, 256 },
|
||||
};
|
||||
|
||||
static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
|
||||
EXYNOS_COMMON_SERIAL_DRV_DATA_USI(1),
|
||||
.fifosize = { 256, 64, 64, 64 },
|
||||
};
|
||||
|
||||
#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
|
||||
#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos5433_serial_drv_data)
|
||||
#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos850_serial_drv_data)
|
||||
|
||||
#else
|
||||
#define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
|
||||
#define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL
|
||||
#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
|
||||
#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
|
||||
#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_APPLE
|
||||
|
@ -2843,6 +2885,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
|
|||
}, {
|
||||
.name = "s5l-uart",
|
||||
.driver_data = S5L_SERIAL_DRV_DATA,
|
||||
}, {
|
||||
.name = "exynos850-uart",
|
||||
.driver_data = EXYNOS850_SERIAL_DRV_DATA,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
@ -2866,6 +2911,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
|
|||
.data = (void *)EXYNOS5433_SERIAL_DRV_DATA },
|
||||
{ .compatible = "apple,s5l-uart",
|
||||
.data = (void *)S5L_SERIAL_DRV_DATA },
|
||||
{ .compatible = "samsung,exynos850-uart",
|
||||
.data = (void *)EXYNOS850_SERIAL_DRV_DATA },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
|
||||
|
|
|
@ -1568,14 +1568,12 @@ static int tegra_uart_probe(struct platform_device *pdev)
|
|||
struct resource *resource;
|
||||
int ret;
|
||||
const struct tegra_uart_chip_data *cdata;
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_device(tegra_uart_of_match, &pdev->dev);
|
||||
if (!match) {
|
||||
cdata = of_device_get_match_data(&pdev->dev);
|
||||
if (!cdata) {
|
||||
dev_err(&pdev->dev, "Error: No device match found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
cdata = match->data;
|
||||
|
||||
tup = devm_kzalloc(&pdev->dev, sizeof(*tup), GFP_KERNEL);
|
||||
if (!tup) {
|
||||
|
|
|
@ -2314,6 +2314,14 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
|
|||
port->dev ? ": " : "",
|
||||
port->name,
|
||||
address, port->irq, port->uartclk / 16, uart_type(port));
|
||||
|
||||
/* The magic multiplier feature is a bit obscure, so report it too. */
|
||||
if (port->flags & UPF_MAGIC_MULTIPLIER)
|
||||
pr_info("%s%s%s extra baud rates supported: %d, %d",
|
||||
port->dev ? dev_name(port->dev) : "",
|
||||
port->dev ? ": " : "",
|
||||
port->name,
|
||||
port->uartclk / 8, port->uartclk / 4);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2522,9 +2530,12 @@ int uart_register_driver(struct uart_driver *drv)
|
|||
if (!drv->state)
|
||||
goto out;
|
||||
|
||||
normal = alloc_tty_driver(drv->nr);
|
||||
if (!normal)
|
||||
normal = tty_alloc_driver(drv->nr, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(normal)) {
|
||||
retval = PTR_ERR(normal);
|
||||
goto out_kfree;
|
||||
}
|
||||
|
||||
drv->tty_driver = normal;
|
||||
|
||||
|
@ -2537,7 +2548,6 @@ int uart_register_driver(struct uart_driver *drv)
|
|||
normal->init_termios = tty_std_termios;
|
||||
normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
|
||||
normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
normal->driver_state = drv;
|
||||
tty_set_operations(normal, &uart_ops);
|
||||
|
||||
|
@ -2558,7 +2568,7 @@ int uart_register_driver(struct uart_driver *drv)
|
|||
|
||||
for (i = 0; i < drv->nr; i++)
|
||||
tty_port_destroy(&drv->state[i].port);
|
||||
put_tty_driver(normal);
|
||||
tty_driver_kref_put(normal);
|
||||
out_kfree:
|
||||
kfree(drv->state);
|
||||
out:
|
||||
|
@ -2580,7 +2590,7 @@ void uart_unregister_driver(struct uart_driver *drv)
|
|||
unsigned int i;
|
||||
|
||||
tty_unregister_driver(p);
|
||||
put_tty_driver(p);
|
||||
tty_driver_kref_put(p);
|
||||
for (i = 0; i < drv->nr; i++)
|
||||
tty_port_destroy(&drv->state[i].port);
|
||||
kfree(drv->state);
|
||||
|
|
|
@ -1758,6 +1758,10 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
|
|||
|
||||
/* Handle BREAKs */
|
||||
sci_handle_breaks(port);
|
||||
|
||||
/* drop invalid character received before break was detected */
|
||||
serial_port_in(port, SCxRDR);
|
||||
|
||||
sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -1837,7 +1841,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
|
|||
ret = sci_er_interrupt(irq, ptr);
|
||||
|
||||
/* Break Interrupt */
|
||||
if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
|
||||
if (s->irqs[SCIx_ERI_IRQ] != s->irqs[SCIx_BRI_IRQ] &&
|
||||
(ssr_status & SCxSR_BRK(port)) && err_enabled)
|
||||
ret = sci_br_interrupt(irq, ptr);
|
||||
|
||||
/* Overrun Interrupt */
|
||||
|
|
|
@ -1034,8 +1034,8 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
|
|||
int ret, irq;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0)
|
||||
return irq ? : -ENODEV;
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
port->iotype = UPIO_MEM;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
|
@ -1064,8 +1064,7 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
|
|||
&stm32port->txftcfg);
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
port->membase = devm_ioremap_resource(&pdev->dev, res);
|
||||
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(port->membase))
|
||||
return PTR_ERR(port->membase);
|
||||
port->mapbase = res->start;
|
||||
|
@ -1177,7 +1176,7 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
|
|||
if (uart_console(port))
|
||||
return -ENODEV;
|
||||
|
||||
stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L,
|
||||
stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L,
|
||||
&stm32port->rx_dma_buf,
|
||||
GFP_KERNEL);
|
||||
if (!stm32port->rx_buf)
|
||||
|
@ -1243,7 +1242,7 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port,
|
|||
|
||||
stm32port->tx_dma_busy = false;
|
||||
|
||||
stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L,
|
||||
stm32port->tx_buf = dma_alloc_coherent(dev, TX_BUF_L,
|
||||
&stm32port->tx_dma_buf,
|
||||
GFP_KERNEL);
|
||||
if (!stm32port->tx_buf)
|
||||
|
|
|
@ -17,11 +17,13 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#define ULITE_NAME "ttyUL"
|
||||
#define ULITE_MAJOR 204
|
||||
|
@ -54,6 +56,7 @@
|
|||
#define ULITE_CONTROL_RST_TX 0x01
|
||||
#define ULITE_CONTROL_RST_RX 0x02
|
||||
#define ULITE_CONTROL_IE 0x10
|
||||
#define UART_AUTOSUSPEND_TIMEOUT 3000 /* ms */
|
||||
|
||||
/* Static pointer to console port */
|
||||
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
|
||||
|
@ -390,12 +393,16 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
|
|||
static void ulite_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
{
|
||||
struct uartlite_data *pdata = port->private_data;
|
||||
int ret;
|
||||
|
||||
if (!state)
|
||||
clk_enable(pdata->clk);
|
||||
else
|
||||
clk_disable(pdata->clk);
|
||||
if (!state) {
|
||||
ret = pm_runtime_get_sync(port->dev);
|
||||
if (ret < 0)
|
||||
dev_err(port->dev, "Failed to enable clocks\n");
|
||||
} else {
|
||||
pm_runtime_mark_last_busy(port->dev);
|
||||
pm_runtime_put_autosuspend(port->dev);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
|
@ -448,24 +455,15 @@ static const struct uart_ops ulite_ops = {
|
|||
static void ulite_console_wait_tx(struct uart_port *port)
|
||||
{
|
||||
u8 val;
|
||||
unsigned long timeout;
|
||||
|
||||
/*
|
||||
* Spin waiting for TX fifo to have space available.
|
||||
* When using the Microblaze Debug Module this can take up to 1s
|
||||
*/
|
||||
timeout = jiffies + msecs_to_jiffies(1000);
|
||||
while (1) {
|
||||
val = uart_in32(ULITE_STATUS, port);
|
||||
if ((val & ULITE_STATUS_TXFULL) == 0)
|
||||
break;
|
||||
if (time_after(jiffies, timeout)) {
|
||||
dev_warn(port->dev,
|
||||
"timeout waiting for TX buffer empty\n");
|
||||
break;
|
||||
}
|
||||
cpu_relax();
|
||||
}
|
||||
if (read_poll_timeout_atomic(uart_in32, val, !(val & ULITE_STATUS_TXFULL),
|
||||
0, 1000000, false, ULITE_STATUS, port))
|
||||
dev_warn(port->dev,
|
||||
"timeout waiting for TX buffer empty\n");
|
||||
}
|
||||
|
||||
static void ulite_console_putchar(struct uart_port *port, int ch)
|
||||
|
@ -555,16 +553,15 @@ static void early_uartlite_putc(struct uart_port *port, int c)
|
|||
* This limit is pretty arbitrary, unless we are at about 10 baud
|
||||
* we'll never timeout on a working UART.
|
||||
*/
|
||||
|
||||
unsigned retries = 1000000;
|
||||
/* read status bit - 0x8 offset */
|
||||
while (--retries && (readl(port->membase + 8) & (1 << 3)))
|
||||
|
||||
while (--retries &&
|
||||
(readl(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL))
|
||||
;
|
||||
|
||||
/* Only attempt the iowrite if we didn't timeout */
|
||||
/* write to TX_FIFO - 0x4 offset */
|
||||
if (retries)
|
||||
writel(c & 0xff, port->membase + 4);
|
||||
writel(c & 0xff, port->membase + ULITE_TX);
|
||||
}
|
||||
|
||||
static void early_uartlite_write(struct console *console,
|
||||
|
@ -719,11 +716,38 @@ static int __maybe_unused ulite_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused ulite_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct uart_port *port = dev_get_drvdata(dev);
|
||||
struct uartlite_data *pdata = port->private_data;
|
||||
|
||||
clk_disable(pdata->clk);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int __maybe_unused ulite_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct uart_port *port = dev_get_drvdata(dev);
|
||||
struct uartlite_data *pdata = port->private_data;
|
||||
int ret;
|
||||
|
||||
ret = clk_enable(pdata->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Cannot enable clock.\n");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Platform bus binding
|
||||
*/
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ulite_pm_ops, ulite_suspend, ulite_resume);
|
||||
static const struct dev_pm_ops ulite_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(ulite_suspend, ulite_resume)
|
||||
SET_RUNTIME_PM_OPS(ulite_runtime_suspend,
|
||||
ulite_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
/* Match table for of_platform binding */
|
||||
|
@ -779,18 +803,25 @@ static int ulite_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
if (!ulite_uart_driver.state) {
|
||||
dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
|
||||
ret = uart_register_driver(&ulite_uart_driver);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to register driver\n");
|
||||
clk_disable_unprepare(pdata->clk);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
|
||||
|
||||
clk_disable(pdata->clk);
|
||||
pm_runtime_mark_last_busy(&pdev->dev);
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -799,9 +830,14 @@ static int ulite_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct uart_port *port = dev_get_drvdata(&pdev->dev);
|
||||
struct uartlite_data *pdata = port->private_data;
|
||||
int rc;
|
||||
|
||||
clk_disable_unprepare(pdata->clk);
|
||||
return ulite_release(&pdev->dev);
|
||||
rc = ulite_release(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
|
|
|
@ -623,17 +623,14 @@ static int vt8500_serial_probe(struct platform_device *pdev)
|
|||
struct vt8500_port *vt8500_port;
|
||||
struct resource *mmres, *irqres;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
const unsigned int *flags;
|
||||
int ret;
|
||||
int port;
|
||||
|
||||
match = of_match_device(wmt_dt_ids, &pdev->dev);
|
||||
if (!match)
|
||||
flags = of_device_get_match_data(&pdev->dev);
|
||||
if (!flags)
|
||||
return -EINVAL;
|
||||
|
||||
flags = match->data;
|
||||
|
||||
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!mmres || !irqres)
|
||||
|
|
|
@ -3647,7 +3647,7 @@ static void slgt_cleanup(void)
|
|||
for (info=slgt_device_list ; info != NULL ; info=info->next_device)
|
||||
tty_unregister_device(serial_driver, info->line);
|
||||
tty_unregister_driver(serial_driver);
|
||||
put_tty_driver(serial_driver);
|
||||
tty_driver_kref_put(serial_driver);
|
||||
}
|
||||
|
||||
/* reset devices */
|
||||
|
@ -3686,10 +3686,11 @@ static int __init slgt_init(void)
|
|||
|
||||
printk(KERN_INFO "%s\n", driver_name);
|
||||
|
||||
serial_driver = alloc_tty_driver(MAX_DEVICES);
|
||||
if (!serial_driver) {
|
||||
serial_driver = tty_alloc_driver(MAX_DEVICES, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(serial_driver)) {
|
||||
printk("%s can't allocate tty driver\n", driver_name);
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(serial_driver);
|
||||
}
|
||||
|
||||
/* Initialize the tty_driver structure */
|
||||
|
@ -3705,11 +3706,10 @@ static int __init slgt_init(void)
|
|||
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
serial_driver->init_termios.c_ispeed = 9600;
|
||||
serial_driver->init_termios.c_ospeed = 9600;
|
||||
serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_set_operations(serial_driver, &ops);
|
||||
if ((rc = tty_register_driver(serial_driver)) < 0) {
|
||||
DBGERR(("%s can't register serial driver\n", driver_name));
|
||||
put_tty_driver(serial_driver);
|
||||
tty_driver_kref_put(serial_driver);
|
||||
serial_driver = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -258,7 +258,7 @@ static void sysrq_handle_showallcpus(int key)
|
|||
if (!trigger_all_cpu_backtrace()) {
|
||||
struct pt_regs *regs = NULL;
|
||||
|
||||
if (in_irq())
|
||||
if (in_hardirq())
|
||||
regs = get_irq_regs();
|
||||
if (regs) {
|
||||
pr_info("CPU%d:\n", smp_processor_id());
|
||||
|
@ -280,7 +280,7 @@ static void sysrq_handle_showregs(int key)
|
|||
{
|
||||
struct pt_regs *regs = NULL;
|
||||
|
||||
if (in_irq())
|
||||
if (in_hardirq())
|
||||
regs = get_irq_regs();
|
||||
if (regs)
|
||||
show_regs(regs);
|
||||
|
|
|
@ -2290,8 +2290,6 @@ static int tty_fasync(int fd, struct file *filp, int on)
|
|||
* Locking:
|
||||
* Called functions take tty_ldiscs_lock
|
||||
* current->signal->tty check is safe without locks
|
||||
*
|
||||
* FIXME: may race normal receive processing
|
||||
*/
|
||||
|
||||
static int tiocsti(struct tty_struct *tty, char __user *p)
|
||||
|
@ -2307,8 +2305,10 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
|
|||
ld = tty_ldisc_ref_wait(tty);
|
||||
if (!ld)
|
||||
return -EIO;
|
||||
tty_buffer_lock_exclusive(tty->port);
|
||||
if (ld->ops->receive_buf)
|
||||
ld->ops->receive_buf(tty, &ch, &mbz, 1);
|
||||
tty_buffer_unlock_exclusive(tty->port);
|
||||
tty_ldisc_deref(ld);
|
||||
return 0;
|
||||
}
|
||||
|
@ -3438,19 +3438,6 @@ void tty_driver_kref_put(struct tty_driver *driver)
|
|||
}
|
||||
EXPORT_SYMBOL(tty_driver_kref_put);
|
||||
|
||||
void tty_set_operations(struct tty_driver *driver,
|
||||
const struct tty_operations *op)
|
||||
{
|
||||
driver->ops = op;
|
||||
};
|
||||
EXPORT_SYMBOL(tty_set_operations);
|
||||
|
||||
void put_tty_driver(struct tty_driver *d)
|
||||
{
|
||||
tty_driver_kref_put(d);
|
||||
}
|
||||
EXPORT_SYMBOL(put_tty_driver);
|
||||
|
||||
/*
|
||||
* Called by a tty driver to register itself.
|
||||
*/
|
||||
|
|
|
@ -84,7 +84,7 @@ static int __init ttynull_init(void)
|
|||
|
||||
ret = tty_register_driver(driver);
|
||||
if (ret < 0) {
|
||||
put_tty_driver(driver);
|
||||
tty_driver_kref_put(driver);
|
||||
tty_port_destroy(&ttynull_port);
|
||||
return ret;
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ static void __exit ttynull_exit(void)
|
|||
{
|
||||
unregister_console(&ttynull_console);
|
||||
tty_unregister_driver(ttynull_driver);
|
||||
put_tty_driver(ttynull_driver);
|
||||
tty_driver_kref_put(ttynull_driver);
|
||||
tty_port_destroy(&ttynull_port);
|
||||
}
|
||||
|
||||
|
|
|
@ -1028,7 +1028,7 @@ static int vcc_tty_init(void)
|
|||
rv = tty_register_driver(vcc_tty_driver);
|
||||
if (rv) {
|
||||
pr_err("VCC: TTY driver registration failed\n");
|
||||
put_tty_driver(vcc_tty_driver);
|
||||
tty_driver_kref_put(vcc_tty_driver);
|
||||
vcc_tty_driver = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
@ -1041,7 +1041,7 @@ static int vcc_tty_init(void)
|
|||
static void vcc_tty_exit(void)
|
||||
{
|
||||
tty_unregister_driver(vcc_tty_driver);
|
||||
put_tty_driver(vcc_tty_driver);
|
||||
tty_driver_kref_put(vcc_tty_driver);
|
||||
vccdbg("VCC: TTY driver unregistered\n");
|
||||
|
||||
vcc_tty_driver = NULL;
|
||||
|
|
|
@ -1171,9 +1171,9 @@ static inline unsigned char getleds(void)
|
|||
*
|
||||
* Check the status of a keyboard led flag and report it back
|
||||
*/
|
||||
int vt_get_leds(int console, int flag)
|
||||
int vt_get_leds(unsigned int console, int flag)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -1193,9 +1193,9 @@ EXPORT_SYMBOL_GPL(vt_get_leds);
|
|||
* Set the LEDs on a console. This is a wrapper for the VT layer
|
||||
* so that we can keep kbd knowledge internal
|
||||
*/
|
||||
void vt_set_led_state(int console, int leds)
|
||||
void vt_set_led_state(unsigned int console, int leds)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
setledstate(kb, leds);
|
||||
}
|
||||
|
||||
|
@ -1212,9 +1212,9 @@ void vt_set_led_state(int console, int leds)
|
|||
* don't hold the lock. We probably need to split out an LED lock
|
||||
* but not during an -rc release!
|
||||
*/
|
||||
void vt_kbd_con_start(int console)
|
||||
void vt_kbd_con_start(unsigned int console)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&led_lock, flags);
|
||||
clr_vc_kbd_led(kb, VC_SCROLLOCK);
|
||||
|
@ -1229,9 +1229,9 @@ void vt_kbd_con_start(int console)
|
|||
* Handle console stop. This is a wrapper for the VT layer
|
||||
* so that we can keep kbd knowledge internal
|
||||
*/
|
||||
void vt_kbd_con_stop(int console)
|
||||
void vt_kbd_con_stop(unsigned int console)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&led_lock, flags);
|
||||
set_vc_kbd_led(kb, VC_SCROLLOCK);
|
||||
|
@ -1377,7 +1377,7 @@ static void kbd_rawcode(unsigned char data)
|
|||
{
|
||||
struct vc_data *vc = vc_cons[fg_console].d;
|
||||
|
||||
kbd = kbd_table + vc->vc_num;
|
||||
kbd = &kbd_table[vc->vc_num];
|
||||
if (kbd->kbdmode == VC_RAW)
|
||||
put_queue(vc, data);
|
||||
}
|
||||
|
@ -1400,7 +1400,7 @@ static void kbd_keycode(unsigned int keycode, int down, bool hw_raw)
|
|||
tty->driver_data = vc;
|
||||
}
|
||||
|
||||
kbd = kbd_table + vc->vc_num;
|
||||
kbd = &kbd_table[vc->vc_num];
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
if (keycode == KEY_STOP)
|
||||
|
@ -1825,9 +1825,9 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
|||
* Update the keyboard mode bits while holding the correct locks.
|
||||
* Return 0 for success or an error code.
|
||||
*/
|
||||
int vt_do_kdskbmode(int console, unsigned int arg)
|
||||
int vt_do_kdskbmode(unsigned int console, unsigned int arg)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -1865,9 +1865,9 @@ int vt_do_kdskbmode(int console, unsigned int arg)
|
|||
* Update the keyboard meta bits while holding the correct locks.
|
||||
* Return 0 for success or an error code.
|
||||
*/
|
||||
int vt_do_kdskbmeta(int console, unsigned int arg)
|
||||
int vt_do_kdskbmeta(unsigned int console, unsigned int arg)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -2008,9 +2008,9 @@ out:
|
|||
}
|
||||
|
||||
int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
|
||||
int console)
|
||||
unsigned int console)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
struct kbentry kbe;
|
||||
|
||||
if (copy_from_user(&kbe, user_kbe, sizeof(struct kbentry)))
|
||||
|
@ -2097,9 +2097,9 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
|
||||
int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
unsigned long flags;
|
||||
unsigned char ucval;
|
||||
|
||||
|
@ -2139,9 +2139,9 @@ int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
|
|||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
int vt_do_kdgkbmode(int console)
|
||||
int vt_do_kdgkbmode(unsigned int console)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
/* This is a spot read so needs no locking */
|
||||
switch (kb->kbdmode) {
|
||||
case VC_RAW:
|
||||
|
@ -2163,9 +2163,9 @@ int vt_do_kdgkbmode(int console)
|
|||
*
|
||||
* Report the meta flag status of this console
|
||||
*/
|
||||
int vt_do_kdgkbmeta(int console)
|
||||
int vt_do_kdgkbmeta(unsigned int console)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
/* Again a spot read so no locking */
|
||||
return vc_kbd_mode(kb, VC_META) ? K_ESCPREFIX : K_METABIT;
|
||||
}
|
||||
|
@ -2176,7 +2176,7 @@ int vt_do_kdgkbmeta(int console)
|
|||
*
|
||||
* Restore the unicode console state to its default
|
||||
*/
|
||||
void vt_reset_unicode(int console)
|
||||
void vt_reset_unicode(unsigned int console)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -2204,9 +2204,9 @@ int vt_get_shift_state(void)
|
|||
* Reset the keyboard bits for a console as part of a general console
|
||||
* reset event
|
||||
*/
|
||||
void vt_reset_keyboard(int console)
|
||||
void vt_reset_keyboard(unsigned int console)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&kbd_event_lock, flags);
|
||||
|
@ -2234,9 +2234,9 @@ void vt_reset_keyboard(int console)
|
|||
* caller must be sure that there are no synchronization needs
|
||||
*/
|
||||
|
||||
int vt_get_kbd_mode_bit(int console, int bit)
|
||||
int vt_get_kbd_mode_bit(unsigned int console, int bit)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
return vc_kbd_mode(kb, bit);
|
||||
}
|
||||
|
||||
|
@ -2249,9 +2249,9 @@ int vt_get_kbd_mode_bit(int console, int bit)
|
|||
* caller must be sure that there are no synchronization needs
|
||||
*/
|
||||
|
||||
void vt_set_kbd_mode_bit(int console, int bit)
|
||||
void vt_set_kbd_mode_bit(unsigned int console, int bit)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&kbd_event_lock, flags);
|
||||
|
@ -2268,9 +2268,9 @@ void vt_set_kbd_mode_bit(int console, int bit)
|
|||
* caller must be sure that there are no synchronization needs
|
||||
*/
|
||||
|
||||
void vt_clr_kbd_mode_bit(int console, int bit)
|
||||
void vt_clr_kbd_mode_bit(unsigned int console, int bit)
|
||||
{
|
||||
struct kbd_struct *kb = kbd_table + console;
|
||||
struct kbd_struct *kb = &kbd_table[console];
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&kbd_event_lock, flags);
|
||||
|
|
|
@ -1219,8 +1219,25 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
|
|||
new_row_size = new_cols << 1;
|
||||
new_screen_size = new_row_size * new_rows;
|
||||
|
||||
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
|
||||
return 0;
|
||||
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) {
|
||||
/*
|
||||
* This function is being called here to cover the case
|
||||
* where the userspace calls the FBIOPUT_VSCREENINFO twice,
|
||||
* passing the same fb_var_screeninfo containing the fields
|
||||
* yres/xres equal to a number non-multiple of vc_font.height
|
||||
* and yres_virtual/xres_virtual equal to number lesser than the
|
||||
* vc_font.height and yres/xres.
|
||||
* In the second call, the struct fb_var_screeninfo isn't
|
||||
* being modified by the underlying driver because of the
|
||||
* if above, and this causes the fbcon_display->vrows to become
|
||||
* negative and it eventually leads to out-of-bound
|
||||
* access by the imageblit function.
|
||||
* To give the correct values to the struct and to not have
|
||||
* to deal with possible errors from the code below, we call
|
||||
* the resize_screen here as well.
|
||||
*/
|
||||
return resize_screen(vc, new_cols, new_rows, user);
|
||||
}
|
||||
|
||||
if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
|
||||
return -EINVAL;
|
||||
|
@ -3582,8 +3599,9 @@ int __init vty_init(const struct file_operations *console_fops)
|
|||
|
||||
vcs_init();
|
||||
|
||||
console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
|
||||
if (!console_driver)
|
||||
console_driver = tty_alloc_driver(MAX_NR_CONSOLES, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_RESET_TERMIOS);
|
||||
if (IS_ERR(console_driver))
|
||||
panic("Couldn't allocate console driver\n");
|
||||
|
||||
console_driver->name = "tty";
|
||||
|
@ -3594,7 +3612,6 @@ int __init vty_init(const struct file_operations *console_fops)
|
|||
console_driver->init_termios = tty_std_termios;
|
||||
if (default_utf8)
|
||||
console_driver->init_termios.c_iflag |= IUTF8;
|
||||
console_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
|
||||
tty_set_operations(console_driver, &con_ops);
|
||||
if (tty_register_driver(console_driver))
|
||||
panic("Couldn't register console driver\n");
|
||||
|
|
|
@ -2027,16 +2027,16 @@ static const struct tty_operations acm_ops = {
|
|||
static int __init acm_init(void)
|
||||
{
|
||||
int retval;
|
||||
acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS);
|
||||
if (!acm_tty_driver)
|
||||
return -ENOMEM;
|
||||
acm_tty_driver = tty_alloc_driver(ACM_TTY_MINORS, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(acm_tty_driver))
|
||||
return PTR_ERR(acm_tty_driver);
|
||||
acm_tty_driver->driver_name = "acm",
|
||||
acm_tty_driver->name = "ttyACM",
|
||||
acm_tty_driver->major = ACM_TTY_MAJOR,
|
||||
acm_tty_driver->minor_start = 0,
|
||||
acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
|
||||
acm_tty_driver->subtype = SERIAL_TYPE_NORMAL,
|
||||
acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
acm_tty_driver->init_termios = tty_std_termios;
|
||||
acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD |
|
||||
HUPCL | CLOCAL;
|
||||
|
@ -2044,14 +2044,14 @@ static int __init acm_init(void)
|
|||
|
||||
retval = tty_register_driver(acm_tty_driver);
|
||||
if (retval) {
|
||||
put_tty_driver(acm_tty_driver);
|
||||
tty_driver_kref_put(acm_tty_driver);
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = usb_register(&acm_driver);
|
||||
if (retval) {
|
||||
tty_unregister_driver(acm_tty_driver);
|
||||
put_tty_driver(acm_tty_driver);
|
||||
tty_driver_kref_put(acm_tty_driver);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -2064,7 +2064,7 @@ static void __exit acm_exit(void)
|
|||
{
|
||||
usb_deregister(&acm_driver);
|
||||
tty_unregister_driver(acm_tty_driver);
|
||||
put_tty_driver(acm_tty_driver);
|
||||
tty_driver_kref_put(acm_tty_driver);
|
||||
idr_destroy(&acm_minors);
|
||||
}
|
||||
|
||||
|
|
|
@ -1445,51 +1445,53 @@ EXPORT_SYMBOL_GPL(gserial_resume);
|
|||
|
||||
static int userial_init(void)
|
||||
{
|
||||
struct tty_driver *driver;
|
||||
unsigned i;
|
||||
int status;
|
||||
|
||||
gs_tty_driver = alloc_tty_driver(MAX_U_SERIAL_PORTS);
|
||||
if (!gs_tty_driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(MAX_U_SERIAL_PORTS, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
gs_tty_driver->driver_name = "g_serial";
|
||||
gs_tty_driver->name = "ttyGS";
|
||||
driver->driver_name = "g_serial";
|
||||
driver->name = "ttyGS";
|
||||
/* uses dynamically assigned dev_t values */
|
||||
|
||||
gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
gs_tty_driver->init_termios = tty_std_termios;
|
||||
driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
driver->init_termios = tty_std_termios;
|
||||
|
||||
/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
|
||||
* MS-Windows. Otherwise, most of these flags shouldn't affect
|
||||
* anything unless we were to actually hook up to a serial line.
|
||||
*/
|
||||
gs_tty_driver->init_termios.c_cflag =
|
||||
driver->init_termios.c_cflag =
|
||||
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
gs_tty_driver->init_termios.c_ispeed = 9600;
|
||||
gs_tty_driver->init_termios.c_ospeed = 9600;
|
||||
driver->init_termios.c_ispeed = 9600;
|
||||
driver->init_termios.c_ospeed = 9600;
|
||||
|
||||
tty_set_operations(gs_tty_driver, &gs_tty_ops);
|
||||
tty_set_operations(driver, &gs_tty_ops);
|
||||
for (i = 0; i < MAX_U_SERIAL_PORTS; i++)
|
||||
mutex_init(&ports[i].lock);
|
||||
|
||||
/* export the driver ... */
|
||||
status = tty_register_driver(gs_tty_driver);
|
||||
status = tty_register_driver(driver);
|
||||
if (status) {
|
||||
pr_err("%s: cannot register, err %d\n",
|
||||
__func__, status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gs_tty_driver = driver;
|
||||
|
||||
pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
|
||||
MAX_U_SERIAL_PORTS,
|
||||
(MAX_U_SERIAL_PORTS == 1) ? "" : "s");
|
||||
|
||||
return status;
|
||||
fail:
|
||||
put_tty_driver(gs_tty_driver);
|
||||
gs_tty_driver = NULL;
|
||||
tty_driver_kref_put(driver);
|
||||
return status;
|
||||
}
|
||||
module_init(userial_init);
|
||||
|
@ -1497,7 +1499,7 @@ module_init(userial_init);
|
|||
static void userial_cleanup(void)
|
||||
{
|
||||
tty_unregister_driver(gs_tty_driver);
|
||||
put_tty_driver(gs_tty_driver);
|
||||
tty_driver_kref_put(gs_tty_driver);
|
||||
gs_tty_driver = NULL;
|
||||
}
|
||||
module_exit(userial_cleanup);
|
||||
|
|
|
@ -541,7 +541,7 @@ static int dbc_tty_init(void)
|
|||
ret = tty_register_driver(dbc_tty_driver);
|
||||
if (ret) {
|
||||
pr_err("Can't register dbc tty driver\n");
|
||||
put_tty_driver(dbc_tty_driver);
|
||||
tty_driver_kref_put(dbc_tty_driver);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ static void dbc_tty_exit(void)
|
|||
{
|
||||
if (dbc_tty_driver) {
|
||||
tty_unregister_driver(dbc_tty_driver);
|
||||
put_tty_driver(dbc_tty_driver);
|
||||
tty_driver_kref_put(dbc_tty_driver);
|
||||
dbc_tty_driver = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1319,9 +1319,10 @@ static int __init usb_serial_init(void)
|
|||
{
|
||||
int result;
|
||||
|
||||
usb_serial_tty_driver = alloc_tty_driver(USB_SERIAL_TTY_MINORS);
|
||||
if (!usb_serial_tty_driver)
|
||||
return -ENOMEM;
|
||||
usb_serial_tty_driver = tty_alloc_driver(USB_SERIAL_TTY_MINORS,
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(usb_serial_tty_driver))
|
||||
return PTR_ERR(usb_serial_tty_driver);
|
||||
|
||||
/* Initialize our global data */
|
||||
result = bus_register(&usb_serial_bus_type);
|
||||
|
@ -1336,8 +1337,6 @@ static int __init usb_serial_init(void)
|
|||
usb_serial_tty_driver->minor_start = 0;
|
||||
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV;
|
||||
usb_serial_tty_driver->init_termios = tty_std_termios;
|
||||
usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
|
||||
| HUPCL | CLOCAL;
|
||||
|
@ -1367,7 +1366,7 @@ exit_reg_driver:
|
|||
|
||||
exit_bus:
|
||||
pr_err("%s - returning with error %d\n", __func__, result);
|
||||
put_tty_driver(usb_serial_tty_driver);
|
||||
tty_driver_kref_put(usb_serial_tty_driver);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1379,7 +1378,7 @@ static void __exit usb_serial_exit(void)
|
|||
usb_serial_generic_deregister();
|
||||
|
||||
tty_unregister_driver(usb_serial_tty_driver);
|
||||
put_tty_driver(usb_serial_tty_driver);
|
||||
tty_driver_kref_put(usb_serial_tty_driver);
|
||||
bus_unregister(&usb_serial_bus_type);
|
||||
idr_destroy(&serial_minors);
|
||||
}
|
||||
|
|
|
@ -327,4 +327,18 @@ static inline int serdev_tty_port_unregister(struct tty_port *port)
|
|||
}
|
||||
#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
|
||||
|
||||
struct acpi_resource;
|
||||
struct acpi_resource_uart_serialbus;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
|
||||
struct acpi_resource_uart_serialbus **uart);
|
||||
#else
|
||||
static inline bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
|
||||
struct acpi_resource_uart_serialbus **uart)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#endif /*_LINUX_SERDEV_H */
|
||||
|
|
|
@ -27,6 +27,15 @@
|
|||
#define S3C2410_UERSTAT (0x14)
|
||||
#define S3C2410_UFSTAT (0x18)
|
||||
#define S3C2410_UMSTAT (0x1C)
|
||||
#define USI_CON (0xC4)
|
||||
#define USI_OPTION (0xC8)
|
||||
|
||||
#define USI_CON_RESET (1<<0)
|
||||
#define USI_CON_RESET_MASK (1<<0)
|
||||
|
||||
#define USI_OPTION_HWACG_CLKREQ_ON (1<<1)
|
||||
#define USI_OPTION_HWACG_CLKSTOP_ON (1<<2)
|
||||
#define USI_OPTION_HWACG_MASK (3<<1)
|
||||
|
||||
#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))
|
||||
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
#include <linux/major.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/tty_buffer.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_ldisc.h>
|
||||
#include <linux/tty_port.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/tty_flags.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <uapi/linux/tty.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/llist.h>
|
||||
|
@ -31,54 +32,6 @@
|
|||
*/
|
||||
#define __DISABLED_CHAR '\0'
|
||||
|
||||
struct tty_buffer {
|
||||
union {
|
||||
struct tty_buffer *next;
|
||||
struct llist_node free;
|
||||
};
|
||||
int used;
|
||||
int size;
|
||||
int commit;
|
||||
int read;
|
||||
int flags;
|
||||
/* Data points here */
|
||||
unsigned long data[];
|
||||
};
|
||||
|
||||
/* Values for .flags field of tty_buffer */
|
||||
#define TTYB_NORMAL 1 /* buffer has no flags buffer */
|
||||
|
||||
static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs)
|
||||
{
|
||||
return ((unsigned char *)b->data) + ofs;
|
||||
}
|
||||
|
||||
static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs)
|
||||
{
|
||||
return (char *)char_buf_ptr(b, ofs) + b->size;
|
||||
}
|
||||
|
||||
struct tty_bufhead {
|
||||
struct tty_buffer *head; /* Queue head */
|
||||
struct work_struct work;
|
||||
struct mutex lock;
|
||||
atomic_t priority;
|
||||
struct tty_buffer sentinel;
|
||||
struct llist_head free; /* Free queue head */
|
||||
atomic_t mem_used; /* In-use buffers excluding free list */
|
||||
int mem_limit;
|
||||
struct tty_buffer *tail; /* Active buffer */
|
||||
};
|
||||
/*
|
||||
* When a break, frame error, or parity error happens, these codes are
|
||||
* stuffed into the flags buffer.
|
||||
*/
|
||||
#define TTY_NORMAL 0
|
||||
#define TTY_BREAK 1
|
||||
#define TTY_FRAME 2
|
||||
#define TTY_PARITY 3
|
||||
#define TTY_OVERRUN 4
|
||||
|
||||
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
|
||||
#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
|
||||
#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
|
||||
|
@ -164,85 +117,6 @@ struct tty_bufhead {
|
|||
|
||||
struct device;
|
||||
struct signal_struct;
|
||||
|
||||
/*
|
||||
* Port level information. Each device keeps its own port level information
|
||||
* so provide a common structure for those ports wanting to use common support
|
||||
* routines.
|
||||
*
|
||||
* The tty port has a different lifetime to the tty so must be kept apart.
|
||||
* In addition be careful as tty -> port mappings are valid for the life
|
||||
* of the tty object but in many cases port -> tty mappings are valid only
|
||||
* until a hangup so don't use the wrong path.
|
||||
*/
|
||||
|
||||
struct tty_port;
|
||||
|
||||
struct tty_port_operations {
|
||||
/* Return 1 if the carrier is raised */
|
||||
int (*carrier_raised)(struct tty_port *port);
|
||||
/* Control the DTR line */
|
||||
void (*dtr_rts)(struct tty_port *port, int raise);
|
||||
/* Called when the last close completes or a hangup finishes
|
||||
IFF the port was initialized. Do not use to free resources. Called
|
||||
under the port mutex to serialize against activate/shutdowns */
|
||||
void (*shutdown)(struct tty_port *port);
|
||||
/* Called under the port mutex from tty_port_open, serialized using
|
||||
the port mutex */
|
||||
/* FIXME: long term getting the tty argument *out* of this would be
|
||||
good for consoles */
|
||||
int (*activate)(struct tty_port *port, struct tty_struct *tty);
|
||||
/* Called on the final put of a port */
|
||||
void (*destruct)(struct tty_port *port);
|
||||
};
|
||||
|
||||
struct tty_port_client_operations {
|
||||
int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t);
|
||||
void (*write_wakeup)(struct tty_port *port);
|
||||
};
|
||||
|
||||
extern const struct tty_port_client_operations tty_port_default_client_ops;
|
||||
|
||||
struct tty_port {
|
||||
struct tty_bufhead buf; /* Locked internally */
|
||||
struct tty_struct *tty; /* Back pointer */
|
||||
struct tty_struct *itty; /* internal back ptr */
|
||||
const struct tty_port_operations *ops; /* Port operations */
|
||||
const struct tty_port_client_operations *client_ops; /* Port client operations */
|
||||
spinlock_t lock; /* Lock protecting tty field */
|
||||
int blocked_open; /* Waiting to open */
|
||||
int count; /* Usage count */
|
||||
wait_queue_head_t open_wait; /* Open waiters */
|
||||
wait_queue_head_t delta_msr_wait; /* Modem status change */
|
||||
unsigned long flags; /* User TTY flags ASYNC_ */
|
||||
unsigned long iflags; /* Internal flags TTY_PORT_ */
|
||||
unsigned char console:1; /* port is a console */
|
||||
struct mutex mutex; /* Locking */
|
||||
struct mutex buf_mutex; /* Buffer alloc lock */
|
||||
unsigned char *xmit_buf; /* Optional buffer */
|
||||
unsigned int close_delay; /* Close port delay */
|
||||
unsigned int closing_wait; /* Delay for output */
|
||||
int drain_delay; /* Set to zero if no pure time
|
||||
based drain is needed else
|
||||
set to size of fifo */
|
||||
struct kref kref; /* Ref counter */
|
||||
void *client_data;
|
||||
};
|
||||
|
||||
/* tty_port::iflags bits -- use atomic bit ops */
|
||||
#define TTY_PORT_INITIALIZED 0 /* device is initialized */
|
||||
#define TTY_PORT_SUSPENDED 1 /* device is suspended */
|
||||
#define TTY_PORT_ACTIVE 2 /* device is open */
|
||||
|
||||
/*
|
||||
* uart drivers: use the uart_port::status field and the UPSTAT_* defines
|
||||
* for s/w-based flow control steering and carrier detection status
|
||||
*/
|
||||
#define TTY_PORT_CTS_FLOW 3 /* h/w flow control enabled */
|
||||
#define TTY_PORT_CHECK_CD 4 /* carrier detect enabled */
|
||||
#define TTY_PORT_KOPENED 5 /* device exclusively opened by
|
||||
kernel */
|
||||
|
||||
struct tty_operations;
|
||||
|
||||
/**
|
||||
|
@ -446,15 +320,6 @@ extern const char *tty_driver_name(const struct tty_struct *tty);
|
|||
extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
|
||||
extern void stop_tty(struct tty_struct *tty);
|
||||
extern void start_tty(struct tty_struct *tty);
|
||||
extern int tty_register_driver(struct tty_driver *driver);
|
||||
extern void tty_unregister_driver(struct tty_driver *driver);
|
||||
extern struct device *tty_register_device(struct tty_driver *driver,
|
||||
unsigned index, struct device *dev);
|
||||
extern struct device *tty_register_device_attr(struct tty_driver *driver,
|
||||
unsigned index, struct device *device,
|
||||
void *drvdata,
|
||||
const struct attribute_group **attr_grp);
|
||||
extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
|
||||
extern void tty_write_message(struct tty_struct *tty, char *msg);
|
||||
extern int tty_send_xchar(struct tty_struct *tty, char ch);
|
||||
extern int tty_put_char(struct tty_struct *tty, unsigned char c);
|
||||
|
@ -502,13 +367,7 @@ extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
|
|||
extern int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b);
|
||||
extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
|
||||
|
||||
extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
|
||||
extern void tty_ldisc_deref(struct tty_ldisc *);
|
||||
extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
|
||||
extern const struct seq_operations tty_ldiscs_seq_ops;
|
||||
|
||||
extern void tty_wakeup(struct tty_struct *tty);
|
||||
extern void tty_ldisc_flush(struct tty_struct *tty);
|
||||
|
||||
extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
@ -522,128 +381,6 @@ extern int tty_standard_install(struct tty_driver *driver,
|
|||
|
||||
extern struct mutex tty_mutex;
|
||||
|
||||
extern void tty_port_init(struct tty_port *port);
|
||||
extern void tty_port_link_device(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index);
|
||||
extern struct device *tty_port_register_device(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device);
|
||||
extern struct device *tty_port_register_device_attr(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device, void *drvdata,
|
||||
const struct attribute_group **attr_grp);
|
||||
extern struct device *tty_port_register_device_serdev(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device);
|
||||
extern struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device, void *drvdata,
|
||||
const struct attribute_group **attr_grp);
|
||||
extern void tty_port_unregister_device(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index);
|
||||
extern int tty_port_alloc_xmit_buf(struct tty_port *port);
|
||||
extern void tty_port_free_xmit_buf(struct tty_port *port);
|
||||
extern void tty_port_destroy(struct tty_port *port);
|
||||
extern void tty_port_put(struct tty_port *port);
|
||||
|
||||
static inline struct tty_port *tty_port_get(struct tty_port *port)
|
||||
{
|
||||
if (port && kref_get_unless_zero(&port->kref))
|
||||
return port;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the cts flow control is enabled, return true. */
|
||||
static inline bool tty_port_cts_enabled(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_CTS_FLOW, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_cts_flow(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_CTS_FLOW, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_active(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_ACTIVE, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_active(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_ACTIVE, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_check_carrier(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_CHECK_CD, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_check_carrier(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_CHECK_CD, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_suspended(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_SUSPENDED, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_suspended(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_SUSPENDED, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_initialized(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_INITIALIZED, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_initialized(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_INITIALIZED, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_kopened(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_KOPENED, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_kopened(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_KOPENED, &port->iflags, val);
|
||||
}
|
||||
|
||||
extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
|
||||
extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
|
||||
extern int tty_port_carrier_raised(struct tty_port *port);
|
||||
extern void tty_port_raise_dtr_rts(struct tty_port *port);
|
||||
extern void tty_port_lower_dtr_rts(struct tty_port *port);
|
||||
extern void tty_port_hangup(struct tty_port *port);
|
||||
extern void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
|
||||
extern void tty_port_tty_wakeup(struct tty_port *port);
|
||||
extern int tty_port_block_til_ready(struct tty_port *port,
|
||||
struct tty_struct *tty, struct file *filp);
|
||||
extern int tty_port_close_start(struct tty_port *port,
|
||||
struct tty_struct *tty, struct file *filp);
|
||||
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
|
||||
extern void tty_port_close(struct tty_port *port,
|
||||
struct tty_struct *tty, struct file *filp);
|
||||
extern int tty_port_install(struct tty_port *port, struct tty_driver *driver,
|
||||
struct tty_struct *tty);
|
||||
extern int tty_port_open(struct tty_port *port,
|
||||
struct tty_struct *tty, struct file *filp);
|
||||
static inline int tty_port_users(struct tty_port *port)
|
||||
{
|
||||
return port->count + port->blocked_open;
|
||||
}
|
||||
|
||||
extern int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc);
|
||||
extern void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc);
|
||||
extern int tty_set_ldisc(struct tty_struct *tty, int disc);
|
||||
extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
|
||||
const char *f, int count);
|
||||
|
||||
/* n_tty.c */
|
||||
extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
|
||||
#ifdef CONFIG_TTY
|
||||
|
@ -691,12 +428,4 @@ extern void tty_lock_slave(struct tty_struct *tty);
|
|||
extern void tty_unlock_slave(struct tty_struct *tty);
|
||||
extern void tty_set_lock_subclass(struct tty_struct *tty);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
extern void proc_tty_register_driver(struct tty_driver *);
|
||||
extern void proc_tty_unregister_driver(struct tty_driver *);
|
||||
#else
|
||||
static inline void proc_tty_register_driver(struct tty_driver *d) {}
|
||||
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_TTY_BUFFER_H
|
||||
#define _LINUX_TTY_BUFFER_H
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/llist.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct tty_buffer {
|
||||
union {
|
||||
struct tty_buffer *next;
|
||||
struct llist_node free;
|
||||
};
|
||||
int used;
|
||||
int size;
|
||||
int commit;
|
||||
int read;
|
||||
int flags;
|
||||
/* Data points here */
|
||||
unsigned long data[];
|
||||
};
|
||||
|
||||
/* Values for .flags field of tty_buffer */
|
||||
#define TTYB_NORMAL 1 /* buffer has no flags buffer */
|
||||
|
||||
static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs)
|
||||
{
|
||||
return ((unsigned char *)b->data) + ofs;
|
||||
}
|
||||
|
||||
static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs)
|
||||
{
|
||||
return (char *)char_buf_ptr(b, ofs) + b->size;
|
||||
}
|
||||
|
||||
struct tty_bufhead {
|
||||
struct tty_buffer *head; /* Queue head */
|
||||
struct work_struct work;
|
||||
struct mutex lock;
|
||||
atomic_t priority;
|
||||
struct tty_buffer sentinel;
|
||||
struct llist_head free; /* Free queue head */
|
||||
atomic_t mem_used; /* In-use buffers excluding free list */
|
||||
int mem_limit;
|
||||
struct tty_buffer *tail; /* Active buffer */
|
||||
};
|
||||
|
||||
/*
|
||||
* When a break, frame error, or parity error happens, these codes are
|
||||
* stuffed into the flags buffer.
|
||||
*/
|
||||
#define TTY_NORMAL 0
|
||||
#define TTY_BREAK 1
|
||||
#define TTY_FRAME 2
|
||||
#define TTY_PARITY 3
|
||||
#define TTY_OVERRUN 4
|
||||
|
||||
#endif
|
|
@ -233,6 +233,7 @@
|
|||
|
||||
#include <linux/export.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/termios.h>
|
||||
|
@ -328,9 +329,6 @@ extern struct list_head tty_drivers;
|
|||
|
||||
extern struct tty_driver *__tty_alloc_driver(unsigned int lines,
|
||||
struct module *owner, unsigned long flags);
|
||||
extern void put_tty_driver(struct tty_driver *driver);
|
||||
extern void tty_set_operations(struct tty_driver *driver,
|
||||
const struct tty_operations *op);
|
||||
extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
|
||||
|
||||
extern void tty_driver_kref_put(struct tty_driver *driver);
|
||||
|
@ -339,24 +337,18 @@ extern void tty_driver_kref_put(struct tty_driver *driver);
|
|||
#define tty_alloc_driver(lines, flags) \
|
||||
__tty_alloc_driver(lines, THIS_MODULE, flags)
|
||||
|
||||
/*
|
||||
* DEPRECATED Do not use this in new code, use tty_alloc_driver instead.
|
||||
* (And change the return value checks.)
|
||||
*/
|
||||
static inline struct tty_driver *alloc_tty_driver(unsigned int lines)
|
||||
{
|
||||
struct tty_driver *ret = tty_alloc_driver(lines, 0);
|
||||
if (IS_ERR(ret))
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
|
||||
{
|
||||
kref_get(&d->kref);
|
||||
return d;
|
||||
}
|
||||
|
||||
static inline void tty_set_operations(struct tty_driver *driver,
|
||||
const struct tty_operations *op)
|
||||
{
|
||||
driver->ops = op;
|
||||
}
|
||||
|
||||
/* tty driver magic number */
|
||||
#define TTY_DRIVER_MAGIC 0x5402
|
||||
|
||||
|
@ -434,4 +426,21 @@ static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
|
|||
/* serial subtype definitions */
|
||||
#define SERIAL_TYPE_NORMAL 1
|
||||
|
||||
int tty_register_driver(struct tty_driver *driver);
|
||||
void tty_unregister_driver(struct tty_driver *driver);
|
||||
struct device *tty_register_device(struct tty_driver *driver, unsigned index,
|
||||
struct device *dev);
|
||||
struct device *tty_register_device_attr(struct tty_driver *driver,
|
||||
unsigned index, struct device *device, void *drvdata,
|
||||
const struct attribute_group **attr_grp);
|
||||
void tty_unregister_device(struct tty_driver *driver, unsigned index);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
void proc_tty_register_driver(struct tty_driver *);
|
||||
void proc_tty_unregister_driver(struct tty_driver *);
|
||||
#else
|
||||
static inline void proc_tty_register_driver(struct tty_driver *d) {}
|
||||
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
|
||||
#endif
|
||||
|
||||
#endif /* #ifdef _LINUX_TTY_DRIVER_H */
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
#ifndef _LINUX_TTY_FLIP_H
|
||||
#define _LINUX_TTY_FLIP_H
|
||||
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_buffer.h>
|
||||
#include <linux/tty_port.h>
|
||||
|
||||
struct tty_ldisc;
|
||||
|
||||
extern int tty_buffer_set_limit(struct tty_port *port, int limit);
|
||||
extern unsigned int tty_buffer_space_avail(struct tty_port *port);
|
||||
|
@ -39,6 +42,9 @@ static inline int tty_insert_flip_string(struct tty_port *port,
|
|||
return tty_insert_flip_string_fixed_flag(port, chars, TTY_NORMAL, size);
|
||||
}
|
||||
|
||||
int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
|
||||
const char *f, int count);
|
||||
|
||||
extern void tty_buffer_lock_exclusive(struct tty_port *port);
|
||||
extern void tty_buffer_unlock_exclusive(struct tty_port *port);
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#ifndef _LINUX_TTY_LDISC_H
|
||||
#define _LINUX_TTY_LDISC_H
|
||||
|
||||
struct tty_struct;
|
||||
|
||||
/*
|
||||
* This structure defines the interface between the tty line discipline
|
||||
* implementation and the tty routines. The following routines can be
|
||||
|
@ -126,6 +128,9 @@
|
|||
#include <linux/fs.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
/*
|
||||
* the semaphore definition
|
||||
|
@ -220,4 +225,16 @@ struct tty_ldisc {
|
|||
#define MODULE_ALIAS_LDISC(ldisc) \
|
||||
MODULE_ALIAS("tty-ldisc-" __stringify(ldisc))
|
||||
|
||||
extern const struct seq_operations tty_ldiscs_seq_ops;
|
||||
|
||||
struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
|
||||
void tty_ldisc_deref(struct tty_ldisc *);
|
||||
struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
|
||||
|
||||
void tty_ldisc_flush(struct tty_struct *tty);
|
||||
|
||||
int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc);
|
||||
void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc);
|
||||
int tty_set_ldisc(struct tty_struct *tty, int disc);
|
||||
|
||||
#endif /* _LINUX_TTY_LDISC_H */
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_TTY_PORT_H
|
||||
#define _LINUX_TTY_PORT_H
|
||||
|
||||
#include <linux/kref.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/tty_buffer.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
/*
|
||||
* Port level information. Each device keeps its own port level information
|
||||
* so provide a common structure for those ports wanting to use common support
|
||||
* routines.
|
||||
*
|
||||
* The tty port has a different lifetime to the tty so must be kept apart.
|
||||
* In addition be careful as tty -> port mappings are valid for the life
|
||||
* of the tty object but in many cases port -> tty mappings are valid only
|
||||
* until a hangup so don't use the wrong path.
|
||||
*/
|
||||
|
||||
struct attribute_group;
|
||||
struct tty_driver;
|
||||
struct tty_port;
|
||||
struct tty_struct;
|
||||
|
||||
struct tty_port_operations {
|
||||
/* Return 1 if the carrier is raised */
|
||||
int (*carrier_raised)(struct tty_port *port);
|
||||
/* Control the DTR line */
|
||||
void (*dtr_rts)(struct tty_port *port, int raise);
|
||||
/* Called when the last close completes or a hangup finishes
|
||||
IFF the port was initialized. Do not use to free resources. Called
|
||||
under the port mutex to serialize against activate/shutdowns */
|
||||
void (*shutdown)(struct tty_port *port);
|
||||
/* Called under the port mutex from tty_port_open, serialized using
|
||||
the port mutex */
|
||||
/* FIXME: long term getting the tty argument *out* of this would be
|
||||
good for consoles */
|
||||
int (*activate)(struct tty_port *port, struct tty_struct *tty);
|
||||
/* Called on the final put of a port */
|
||||
void (*destruct)(struct tty_port *port);
|
||||
};
|
||||
|
||||
struct tty_port_client_operations {
|
||||
int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t);
|
||||
void (*write_wakeup)(struct tty_port *port);
|
||||
};
|
||||
|
||||
extern const struct tty_port_client_operations tty_port_default_client_ops;
|
||||
|
||||
struct tty_port {
|
||||
struct tty_bufhead buf; /* Locked internally */
|
||||
struct tty_struct *tty; /* Back pointer */
|
||||
struct tty_struct *itty; /* internal back ptr */
|
||||
const struct tty_port_operations *ops; /* Port operations */
|
||||
const struct tty_port_client_operations *client_ops; /* Port client operations */
|
||||
spinlock_t lock; /* Lock protecting tty field */
|
||||
int blocked_open; /* Waiting to open */
|
||||
int count; /* Usage count */
|
||||
wait_queue_head_t open_wait; /* Open waiters */
|
||||
wait_queue_head_t delta_msr_wait; /* Modem status change */
|
||||
unsigned long flags; /* User TTY flags ASYNC_ */
|
||||
unsigned long iflags; /* Internal flags TTY_PORT_ */
|
||||
unsigned char console:1; /* port is a console */
|
||||
struct mutex mutex; /* Locking */
|
||||
struct mutex buf_mutex; /* Buffer alloc lock */
|
||||
unsigned char *xmit_buf; /* Optional buffer */
|
||||
unsigned int close_delay; /* Close port delay */
|
||||
unsigned int closing_wait; /* Delay for output */
|
||||
int drain_delay; /* Set to zero if no pure time
|
||||
based drain is needed else
|
||||
set to size of fifo */
|
||||
struct kref kref; /* Ref counter */
|
||||
void *client_data;
|
||||
};
|
||||
|
||||
/* tty_port::iflags bits -- use atomic bit ops */
|
||||
#define TTY_PORT_INITIALIZED 0 /* device is initialized */
|
||||
#define TTY_PORT_SUSPENDED 1 /* device is suspended */
|
||||
#define TTY_PORT_ACTIVE 2 /* device is open */
|
||||
|
||||
/*
|
||||
* uart drivers: use the uart_port::status field and the UPSTAT_* defines
|
||||
* for s/w-based flow control steering and carrier detection status
|
||||
*/
|
||||
#define TTY_PORT_CTS_FLOW 3 /* h/w flow control enabled */
|
||||
#define TTY_PORT_CHECK_CD 4 /* carrier detect enabled */
|
||||
#define TTY_PORT_KOPENED 5 /* device exclusively opened by
|
||||
kernel */
|
||||
|
||||
void tty_port_init(struct tty_port *port);
|
||||
void tty_port_link_device(struct tty_port *port, struct tty_driver *driver,
|
||||
unsigned index);
|
||||
struct device *tty_port_register_device(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device);
|
||||
struct device *tty_port_register_device_attr(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device, void *drvdata,
|
||||
const struct attribute_group **attr_grp);
|
||||
struct device *tty_port_register_device_serdev(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device);
|
||||
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device, void *drvdata,
|
||||
const struct attribute_group **attr_grp);
|
||||
void tty_port_unregister_device(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index);
|
||||
int tty_port_alloc_xmit_buf(struct tty_port *port);
|
||||
void tty_port_free_xmit_buf(struct tty_port *port);
|
||||
void tty_port_destroy(struct tty_port *port);
|
||||
void tty_port_put(struct tty_port *port);
|
||||
|
||||
static inline struct tty_port *tty_port_get(struct tty_port *port)
|
||||
{
|
||||
if (port && kref_get_unless_zero(&port->kref))
|
||||
return port;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the cts flow control is enabled, return true. */
|
||||
static inline bool tty_port_cts_enabled(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_CTS_FLOW, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_cts_flow(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_CTS_FLOW, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_active(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_ACTIVE, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_active(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_ACTIVE, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_check_carrier(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_CHECK_CD, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_check_carrier(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_CHECK_CD, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_suspended(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_SUSPENDED, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_suspended(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_SUSPENDED, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_initialized(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_INITIALIZED, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_initialized(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_INITIALIZED, &port->iflags, val);
|
||||
}
|
||||
|
||||
static inline bool tty_port_kopened(const struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_KOPENED, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_kopened(struct tty_port *port, bool val)
|
||||
{
|
||||
assign_bit(TTY_PORT_KOPENED, &port->iflags, val);
|
||||
}
|
||||
|
||||
struct tty_struct *tty_port_tty_get(struct tty_port *port);
|
||||
void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
|
||||
int tty_port_carrier_raised(struct tty_port *port);
|
||||
void tty_port_raise_dtr_rts(struct tty_port *port);
|
||||
void tty_port_lower_dtr_rts(struct tty_port *port);
|
||||
void tty_port_hangup(struct tty_port *port);
|
||||
void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
|
||||
void tty_port_tty_wakeup(struct tty_port *port);
|
||||
int tty_port_block_til_ready(struct tty_port *port, struct tty_struct *tty,
|
||||
struct file *filp);
|
||||
int tty_port_close_start(struct tty_port *port, struct tty_struct *tty,
|
||||
struct file *filp);
|
||||
void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
|
||||
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
|
||||
struct file *filp);
|
||||
int tty_port_install(struct tty_port *port, struct tty_driver *driver,
|
||||
struct tty_struct *tty);
|
||||
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
|
||||
struct file *filp);
|
||||
|
||||
static inline int tty_port_users(struct tty_port *port)
|
||||
{
|
||||
return port->count + port->blocked_open;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -148,26 +148,26 @@ void hide_boot_cursor(bool hide);
|
|||
|
||||
/* keyboard provided interfaces */
|
||||
int vt_do_diacrit(unsigned int cmd, void __user *up, int eperm);
|
||||
int vt_do_kdskbmode(int console, unsigned int arg);
|
||||
int vt_do_kdskbmeta(int console, unsigned int arg);
|
||||
int vt_do_kdskbmode(unsigned int console, unsigned int arg);
|
||||
int vt_do_kdskbmeta(unsigned int console, unsigned int arg);
|
||||
int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
|
||||
int perm);
|
||||
int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
|
||||
int console);
|
||||
unsigned int console);
|
||||
int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm);
|
||||
int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm);
|
||||
int vt_do_kdgkbmode(int console);
|
||||
int vt_do_kdgkbmeta(int console);
|
||||
void vt_reset_unicode(int console);
|
||||
int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm);
|
||||
int vt_do_kdgkbmode(unsigned int console);
|
||||
int vt_do_kdgkbmeta(unsigned int console);
|
||||
void vt_reset_unicode(unsigned int console);
|
||||
int vt_get_shift_state(void);
|
||||
void vt_reset_keyboard(int console);
|
||||
int vt_get_leds(int console, int flag);
|
||||
int vt_get_kbd_mode_bit(int console, int bit);
|
||||
void vt_set_kbd_mode_bit(int console, int bit);
|
||||
void vt_clr_kbd_mode_bit(int console, int bit);
|
||||
void vt_set_led_state(int console, int leds);
|
||||
void vt_kbd_con_start(int console);
|
||||
void vt_kbd_con_stop(int console);
|
||||
void vt_reset_keyboard(unsigned int console);
|
||||
int vt_get_leds(unsigned int console, int flag);
|
||||
int vt_get_kbd_mode_bit(unsigned int console, int bit);
|
||||
void vt_set_kbd_mode_bit(unsigned int console, int bit);
|
||||
void vt_clr_kbd_mode_bit(unsigned int console, int bit);
|
||||
void vt_set_led_state(unsigned int console, int leds);
|
||||
void vt_kbd_con_start(unsigned int console);
|
||||
void vt_kbd_con_stop(unsigned int console);
|
||||
|
||||
void vc_scrolldelta_helper(struct vc_data *c, int lines,
|
||||
unsigned int rolled_over, void *_base, unsigned int size);
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
* ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
|
||||
* TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
|
||||
* TI16C752: 8 16 56 60 8 16 32 56
|
||||
* OX16C950: 16 32 112 120 16 32 64 112 PORT_16C950
|
||||
* Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
|
||||
*/
|
||||
#define UART_FCR_R_TRIG_00 0x00
|
||||
|
|
|
@ -1127,9 +1127,10 @@ int __init rfcomm_init_ttys(void)
|
|||
{
|
||||
int error;
|
||||
|
||||
rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
|
||||
if (!rfcomm_tty_driver)
|
||||
return -ENOMEM;
|
||||
rfcomm_tty_driver = tty_alloc_driver(RFCOMM_TTY_PORTS,
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
|
||||
if (IS_ERR(rfcomm_tty_driver))
|
||||
return PTR_ERR(rfcomm_tty_driver);
|
||||
|
||||
rfcomm_tty_driver->driver_name = "rfcomm";
|
||||
rfcomm_tty_driver->name = "rfcomm";
|
||||
|
@ -1137,7 +1138,6 @@ int __init rfcomm_init_ttys(void)
|
|||
rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR;
|
||||
rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
rfcomm_tty_driver->init_termios = tty_std_termios;
|
||||
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
|
||||
rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
|
||||
|
@ -1146,7 +1146,7 @@ int __init rfcomm_init_ttys(void)
|
|||
error = tty_register_driver(rfcomm_tty_driver);
|
||||
if (error) {
|
||||
BT_ERR("Can't register RFCOMM TTY driver");
|
||||
put_tty_driver(rfcomm_tty_driver);
|
||||
tty_driver_kref_put(rfcomm_tty_driver);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1158,5 +1158,5 @@ int __init rfcomm_init_ttys(void)
|
|||
void rfcomm_cleanup_ttys(void)
|
||||
{
|
||||
tty_unregister_driver(rfcomm_tty_driver);
|
||||
put_tty_driver(rfcomm_tty_driver);
|
||||
tty_driver_kref_put(rfcomm_tty_driver);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue