TTY/Serial patches for 5.5-rc1
Here is the "big" tty and serial driver patches for 5.5-rc1. It's a bit later in the merge window than normal as I wanted to make sure some last-minute patches applied to it were all sane. They seem to be :) There's a lot of little stuff in here, for the tty core, and for lots of serial drivers: - reverts of uartlite serial driver patches that were wrong - msm-serial driver fixes - serial core updates and fixes - tty core fixes - serial driver dma mapping api changes - lots of other tiny fixes and updates for serial drivers All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXebFIQ8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylnmACgjfMcfQWa7uC9Q6m2DaQaRMaW6QoAnjg+TgBB eW9EhvyXL2VbrsuUl+iH =Am9O -----END PGP SIGNATURE----- Merge tag 'tty-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial updates from Greg KH: "Here is the "big" tty and serial driver patches for 5.5-rc1. It's a bit later in the merge window than normal as I wanted to make sure some last-minute patches applied to it were all sane. They seem to be :) There's a lot of little stuff in here, for the tty core, and for lots of serial drivers: - reverts of uartlite serial driver patches that were wrong - msm-serial driver fixes - serial core updates and fixes - tty core fixes - serial driver dma mapping api changes - lots of other tiny fixes and updates for serial drivers All of these have been in linux-next for a while with no reported issues" * tag 'tty-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (58 commits) Revert "serial/8250: Add support for NI-Serial PXI/PXIe+485 devices" vcs: prevent write access to vcsu devices tty: vt: keyboard: reject invalid keycodes tty: don't crash in tty_init_dev when missing tty_port serial: stm32: fix clearing interrupt error flags tty: Fix Kconfig indentation, continued serial: serial_core: Perform NULL checks for break_ctl ops tty: remove unused argument from tty_open_by_driver() tty: Fix Kconfig indentation {tty: serial, nand: onenand}: samsung: rename to fix build warning serial: ifx6x60: add missed pm_runtime_disable serial: pl011: Fix DMA ->flush_buffer() Revert "serial-uartlite: Move the uart register" Revert "serial-uartlite: Add get serial id if not provided" Revert "serial-uartlite: Do not use static struct uart_driver out of probe()" Revert "serial-uartlite: Add runtime support" Revert "serial-uartlite: Change logic how console_port is setup" Revert "serial-uartlite: Use allocated structure instead of static ones" tty: serial: msm_serial: Use dma_request_chan() directly for channel request tty: serial: tegra: Use dma_request_chan() directly for channel request ...
This commit is contained in:
Коммит
537bd0a159
|
@ -6,10 +6,19 @@ Description: Configures which IO port the host side of the UART
|
||||||
Users: OpenBMC. Proposed changes should be mailed to
|
Users: OpenBMC. Proposed changes should be mailed to
|
||||||
openbmc@lists.ozlabs.org
|
openbmc@lists.ozlabs.org
|
||||||
|
|
||||||
What: /sys/bus/platform/drivers/aspeed-vuart*/sirq
|
What: /sys/bus/platform/drivers/aspeed-vuart/*/sirq
|
||||||
Date: April 2017
|
Date: April 2017
|
||||||
Contact: Jeremy Kerr <jk@ozlabs.org>
|
Contact: Jeremy Kerr <jk@ozlabs.org>
|
||||||
Description: Configures which interrupt number the host side of
|
Description: Configures which interrupt number the host side of
|
||||||
the UART will appear on the host <-> BMC LPC bus.
|
the UART will appear on the host <-> BMC LPC bus.
|
||||||
Users: OpenBMC. Proposed changes should be mailed to
|
Users: OpenBMC. Proposed changes should be mailed to
|
||||||
openbmc@lists.ozlabs.org
|
openbmc@lists.ozlabs.org
|
||||||
|
|
||||||
|
What: /sys/bus/platform/drivers/aspeed-vuart/*/sirq_polarity
|
||||||
|
Date: July 2019
|
||||||
|
Contact: Oskar Senft <osk@google.com>
|
||||||
|
Description: Configures the polarity of the serial interrupt to the
|
||||||
|
host via the BMC LPC bus.
|
||||||
|
Set to 0 for active-low or 1 for active-high.
|
||||||
|
Users: OpenBMC. Proposed changes should be mailed to
|
||||||
|
openbmc@lists.ozlabs.org
|
||||||
|
|
|
@ -1097,7 +1097,7 @@
|
||||||
mapped with the correct attributes.
|
mapped with the correct attributes.
|
||||||
|
|
||||||
linflex,<addr>
|
linflex,<addr>
|
||||||
Use early console provided by Freescale LinFlex UART
|
Use early console provided by Freescale LINFlexD UART
|
||||||
serial driver for NXP S32V234 SoCs. A valid base
|
serial driver for NXP S32V234 SoCs. A valid base
|
||||||
address must be provided, and the serial port must
|
address must be provided, and the serial port must
|
||||||
already be setup and configured.
|
already be setup and configured.
|
||||||
|
|
|
@ -56,6 +56,11 @@ Optional properties:
|
||||||
- {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD
|
- {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD
|
||||||
line respectively. It will use specified GPIO instead of the peripheral
|
line respectively. It will use specified GPIO instead of the peripheral
|
||||||
function pin for the UART feature. If unsure, don't specify this property.
|
function pin for the UART feature. If unsure, don't specify this property.
|
||||||
|
- aspeed,sirq-polarity-sense: Only applicable to aspeed,ast2500-vuart.
|
||||||
|
phandle to aspeed,ast2500-scu compatible syscon alongside register offset
|
||||||
|
and bit number to identify how the SIRQ polarity should be configured.
|
||||||
|
One possible data source is the LPC/eSPI mode bit.
|
||||||
|
Example: aspeed,sirq-polarity-sense = <&syscon 0x70 25>
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
* fsl,ns16550:
|
* fsl,ns16550:
|
||||||
|
|
|
@ -21,8 +21,7 @@ Required properties:
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- dmas: A list of two dma specifiers, one for each entry in dma-names.
|
- dmas: A list of two dma specifiers, one for each entry in dma-names.
|
||||||
- dma-names: should contain "tx" and "rx".
|
- dma-names: should contain "tx" and "rx".
|
||||||
- rs485-rts-delay, rs485-rts-active-low, rs485-rx-during-tx,
|
- rs485-rts-active-low, linux,rs485-enabled-at-boot-time: see rs485.txt
|
||||||
linux,rs485-enabled-at-boot-time: see rs485.txt
|
|
||||||
|
|
||||||
Note: Optional properties for DMA support. Write them both or both not.
|
Note: Optional properties for DMA support. Write them both or both not.
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,10 @@ Required properties:
|
||||||
- "renesas,hscif-r8a7794" for R8A7794 (R-Car E2) HSCIF compatible UART.
|
- "renesas,hscif-r8a7794" for R8A7794 (R-Car E2) HSCIF compatible UART.
|
||||||
- "renesas,scif-r8a7795" for R8A7795 (R-Car H3) SCIF compatible UART.
|
- "renesas,scif-r8a7795" for R8A7795 (R-Car H3) SCIF compatible UART.
|
||||||
- "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
|
- "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
|
||||||
- "renesas,scif-r8a7796" for R8A7796 (R-Car M3-W) SCIF compatible UART.
|
- "renesas,scif-r8a7796" for R8A77960 (R-Car M3-W) SCIF compatible UART.
|
||||||
- "renesas,hscif-r8a7796" for R8A7796 (R-Car M3-W) HSCIF compatible UART.
|
- "renesas,hscif-r8a7796" for R8A77960 (R-Car M3-W) HSCIF compatible UART.
|
||||||
|
- "renesas,scif-r8a77961" for R8A77961 (R-Car M3-W+) SCIF compatible UART.
|
||||||
|
- "renesas,hscif-r8a77961" for R8A77961 (R-Car M3-W+) HSCIF compatible UART.
|
||||||
- "renesas,scif-r8a77965" for R8A77965 (R-Car M3-N) SCIF compatible UART.
|
- "renesas,scif-r8a77965" for R8A77965 (R-Car M3-N) SCIF compatible UART.
|
||||||
- "renesas,hscif-r8a77965" for R8A77965 (R-Car M3-N) HSCIF compatible UART.
|
- "renesas,hscif-r8a77965" for R8A77965 (R-Car M3-N) HSCIF compatible UART.
|
||||||
- "renesas,scif-r8a77970" for R8A77970 (R-Car V3M) SCIF compatible UART.
|
- "renesas,scif-r8a77970" for R8A77970 (R-Car V3M) SCIF compatible UART.
|
||||||
|
|
|
@ -81,7 +81,6 @@ FF_MAGIC 0x4646 fc_info ``drivers/net/ip
|
||||||
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
|
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
|
||||||
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
|
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
|
||||||
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
|
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
|
||||||
SERIAL_MAGIC 0x5301 async_struct ``include/linux/serial.h``
|
|
||||||
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
|
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
|
||||||
SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
|
SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
|
||||||
STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
|
STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
|
||||||
|
|
|
@ -87,7 +87,6 @@ FF_MAGIC 0x4646 fc_info ``drivers/net/ip
|
||||||
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
|
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
|
||||||
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
|
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
|
||||||
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
|
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
|
||||||
SERIAL_MAGIC 0x5301 async_struct ``include/linux/serial.h``
|
|
||||||
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
|
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
|
||||||
SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
|
SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
|
||||||
STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
|
STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
|
||||||
|
|
|
@ -70,7 +70,6 @@ FF_MAGIC 0x4646 fc_info ``drivers/net/ip
|
||||||
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
|
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
|
||||||
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
|
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
|
||||||
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
|
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
|
||||||
SERIAL_MAGIC 0x5301 async_struct ``include/linux/serial.h``
|
|
||||||
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
|
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
|
||||||
SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
|
SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
|
||||||
STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
|
STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
|
||||||
|
|
|
@ -379,6 +379,7 @@
|
||||||
interrupts = <8>;
|
interrupts = <8>;
|
||||||
clocks = <&syscon ASPEED_CLK_APB>;
|
clocks = <&syscon ASPEED_CLK_APB>;
|
||||||
no-loopback-test;
|
no-loopback-test;
|
||||||
|
aspeed,sirq-polarity-sense = <&syscon 0x70 25>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,6 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o
|
||||||
# Board specific.
|
# Board specific.
|
||||||
obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
|
obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
|
||||||
obj-$(CONFIG_MTD_ONENAND_OMAP2) += omap2.o
|
obj-$(CONFIG_MTD_ONENAND_OMAP2) += omap2.o
|
||||||
obj-$(CONFIG_MTD_ONENAND_SAMSUNG) += samsung.o
|
obj-$(CONFIG_MTD_ONENAND_SAMSUNG) += samsung_mtd.o
|
||||||
|
|
||||||
onenand-objs = onenand_base.o onenand_bbt.o
|
onenand-objs = onenand_base.o onenand_bbt.o
|
||||||
|
|
|
@ -421,8 +421,6 @@ extern struct z8530_irqhandler z8530_sync, z8530_async, z8530_nop;
|
||||||
* Asynchronous Interfacing
|
* Asynchronous Interfacing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SERIAL_MAGIC 0x5301
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The size of the serial xmit buffer is 1 page, or 4096 bytes
|
* The size of the serial xmit buffer is 1 page, or 4096 bytes
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -82,20 +82,20 @@ config HW_CONSOLE
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config VT_HW_CONSOLE_BINDING
|
config VT_HW_CONSOLE_BINDING
|
||||||
bool "Support for binding and unbinding console drivers"
|
bool "Support for binding and unbinding console drivers"
|
||||||
depends on HW_CONSOLE
|
depends on HW_CONSOLE
|
||||||
---help---
|
---help---
|
||||||
The virtual terminal is the device that interacts with the physical
|
The virtual terminal is the device that interacts with the physical
|
||||||
terminal through console drivers. On these systems, at least one
|
terminal through console drivers. On these systems, at least one
|
||||||
console driver is loaded. In other configurations, additional console
|
console driver is loaded. In other configurations, additional console
|
||||||
drivers may be enabled, such as the framebuffer console. If more than
|
drivers may be enabled, such as the framebuffer console. If more than
|
||||||
1 console driver is enabled, setting this to 'y' will allow you to
|
1 console driver is enabled, setting this to 'y' will allow you to
|
||||||
select the console driver that will serve as the backend for the
|
select the console driver that will serve as the backend for the
|
||||||
virtual terminals.
|
virtual terminals.
|
||||||
|
|
||||||
See <file:Documentation/driver-api/console.rst> for more
|
See <file:Documentation/driver-api/console.rst> for more
|
||||||
information. For framebuffer console users, please refer to
|
information. For framebuffer console users, please refer to
|
||||||
<file:Documentation/fb/fbcon.rst>.
|
<file:Documentation/fb/fbcon.rst>.
|
||||||
|
|
||||||
config UNIX98_PTYS
|
config UNIX98_PTYS
|
||||||
bool "Unix98 PTY support" if EXPERT
|
bool "Unix98 PTY support" if EXPERT
|
||||||
|
@ -173,15 +173,15 @@ config ROCKETPORT
|
||||||
depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
|
depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
|
||||||
help
|
help
|
||||||
This driver supports Comtrol RocketPort and RocketModem PCI boards.
|
This driver supports Comtrol RocketPort and RocketModem PCI boards.
|
||||||
These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
|
These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
|
||||||
modems. For information about the RocketPort/RocketModem boards
|
modems. For information about the RocketPort/RocketModem boards
|
||||||
and this driver read <file:Documentation/driver-api/serial/rocket.rst>.
|
and this driver read <file:Documentation/driver-api/serial/rocket.rst>.
|
||||||
|
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called rocket.
|
module will be called rocket.
|
||||||
|
|
||||||
If you want to compile this driver into the kernel, say Y here. If
|
If you want to compile this driver into the kernel, say Y here. If
|
||||||
you don't have a Comtrol RocketPort/RocketModem card installed, say N.
|
you don't have a Comtrol RocketPort/RocketModem card installed, say N.
|
||||||
|
|
||||||
config CYCLADES
|
config CYCLADES
|
||||||
tristate "Cyclades async mux support"
|
tristate "Cyclades async mux support"
|
||||||
|
@ -437,8 +437,8 @@ config MIPS_EJTAG_FDC_KGDB
|
||||||
depends on MIPS_EJTAG_FDC_TTY && KGDB
|
depends on MIPS_EJTAG_FDC_TTY && KGDB
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
This enables the use of KGDB over an FDC channel, allowing KGDB to be
|
This enables the use of KGDB over an FDC channel, allowing KGDB to be
|
||||||
used remotely or when a serial port isn't available.
|
used remotely or when a serial port isn't available.
|
||||||
|
|
||||||
config MIPS_EJTAG_FDC_KGDB_CHAN
|
config MIPS_EJTAG_FDC_KGDB_CHAN
|
||||||
int "KGDB FDC channel"
|
int "KGDB FDC channel"
|
||||||
|
|
|
@ -22,18 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Serial driver configuration section. Here are the various options:
|
|
||||||
*
|
|
||||||
* SERIAL_PARANOIA_CHECK
|
|
||||||
* Check the magic number for the async_structure where
|
|
||||||
* ever possible.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#undef SERIAL_PARANOIA_CHECK
|
|
||||||
|
|
||||||
/* Set of debugging defines */
|
/* Set of debugging defines */
|
||||||
|
|
||||||
#undef SERIAL_DEBUG_INTR
|
#undef SERIAL_DEBUG_INTR
|
||||||
|
@ -132,28 +122,6 @@ static struct serial_state rs_table[1];
|
||||||
|
|
||||||
#define serial_isroot() (capable(CAP_SYS_ADMIN))
|
#define serial_isroot() (capable(CAP_SYS_ADMIN))
|
||||||
|
|
||||||
|
|
||||||
static inline int serial_paranoia_check(struct serial_state *info,
|
|
||||||
char *name, const char *routine)
|
|
||||||
{
|
|
||||||
#ifdef SERIAL_PARANOIA_CHECK
|
|
||||||
static const char *badmagic =
|
|
||||||
"Warning: bad magic number for serial struct (%s) in %s\n";
|
|
||||||
static const char *badinfo =
|
|
||||||
"Warning: null async_struct for (%s) in %s\n";
|
|
||||||
|
|
||||||
if (!info) {
|
|
||||||
printk(badinfo, name, routine);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (info->magic != SERIAL_MAGIC) {
|
|
||||||
printk(badmagic, name, routine);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* some serial hardware definitions */
|
/* some serial hardware definitions */
|
||||||
#define SDR_OVRUN (1<<15)
|
#define SDR_OVRUN (1<<15)
|
||||||
#define SDR_RBF (1<<14)
|
#define SDR_RBF (1<<14)
|
||||||
|
@ -189,9 +157,6 @@ static void rs_stop(struct tty_struct *tty)
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_stop"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
if (info->IER & UART_IER_THRI) {
|
if (info->IER & UART_IER_THRI) {
|
||||||
info->IER &= ~UART_IER_THRI;
|
info->IER &= ~UART_IER_THRI;
|
||||||
|
@ -209,9 +174,6 @@ static void rs_start(struct tty_struct *tty)
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_start"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
if (info->xmit.head != info->xmit.tail
|
if (info->xmit.head != info->xmit.tail
|
||||||
&& info->xmit.buf
|
&& info->xmit.buf
|
||||||
|
@ -783,9 +745,6 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)
|
||||||
|
|
||||||
info = tty->driver_data;
|
info = tty->driver_data;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_put_char"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!info->xmit.buf)
|
if (!info->xmit.buf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -808,9 +767,6 @@ static void rs_flush_chars(struct tty_struct *tty)
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (info->xmit.head == info->xmit.tail
|
if (info->xmit.head == info->xmit.tail
|
||||||
|| tty->stopped
|
|| tty->stopped
|
||||||
|| tty->hw_stopped
|
|| tty->hw_stopped
|
||||||
|
@ -833,9 +789,6 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_write"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!info->xmit.buf)
|
if (!info->xmit.buf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -878,8 +831,6 @@ static int rs_write_room(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_write_room"))
|
|
||||||
return 0;
|
|
||||||
return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
|
return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,8 +838,6 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
|
|
||||||
return 0;
|
|
||||||
return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
|
return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,8 +846,6 @@ static void rs_flush_buffer(struct tty_struct *tty)
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
|
|
||||||
return;
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
info->xmit.head = info->xmit.tail = 0;
|
info->xmit.head = info->xmit.tail = 0;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
@ -914,9 +861,6 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_send_xchar"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
info->x_char = ch;
|
info->x_char = ch;
|
||||||
if (ch) {
|
if (ch) {
|
||||||
/* Make sure transmit interrupts are on */
|
/* Make sure transmit interrupts are on */
|
||||||
|
@ -952,9 +896,6 @@ static void rs_throttle(struct tty_struct * tty)
|
||||||
printk("throttle %s ....\n", tty_name(tty));
|
printk("throttle %s ....\n", tty_name(tty));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_throttle"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (I_IXOFF(tty))
|
if (I_IXOFF(tty))
|
||||||
rs_send_xchar(tty, STOP_CHAR(tty));
|
rs_send_xchar(tty, STOP_CHAR(tty));
|
||||||
|
|
||||||
|
@ -974,9 +915,6 @@ static void rs_unthrottle(struct tty_struct * tty)
|
||||||
printk("unthrottle %s ....\n", tty_name(tty));
|
printk("unthrottle %s ....\n", tty_name(tty));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (I_IXOFF(tty)) {
|
if (I_IXOFF(tty)) {
|
||||||
if (info->x_char)
|
if (info->x_char)
|
||||||
info->x_char = 0;
|
info->x_char = 0;
|
||||||
|
@ -1109,8 +1047,6 @@ static int rs_tiocmget(struct tty_struct *tty)
|
||||||
unsigned char control, status;
|
unsigned char control, status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
|
|
||||||
return -ENODEV;
|
|
||||||
if (tty_io_error(tty))
|
if (tty_io_error(tty))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
@ -1131,8 +1067,6 @@ static int rs_tiocmset(struct tty_struct *tty, unsigned int set,
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
|
|
||||||
return -ENODEV;
|
|
||||||
if (tty_io_error(tty))
|
if (tty_io_error(tty))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
@ -1155,12 +1089,8 @@ static int rs_tiocmset(struct tty_struct *tty, unsigned int set,
|
||||||
*/
|
*/
|
||||||
static int rs_break(struct tty_struct *tty, int break_state)
|
static int rs_break(struct tty_struct *tty, int break_state)
|
||||||
{
|
{
|
||||||
struct serial_state *info = tty->driver_data;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_break"))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
if (break_state == -1)
|
if (break_state == -1)
|
||||||
custom.adkcon = AC_SETCLR | AC_UARTBRK;
|
custom.adkcon = AC_SETCLR | AC_UARTBRK;
|
||||||
|
@ -1212,9 +1142,6 @@ static int rs_ioctl(struct tty_struct *tty,
|
||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if ((cmd != TIOCSERCONFIG) &&
|
if ((cmd != TIOCSERCONFIG) &&
|
||||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
||||||
if (tty_io_error(tty))
|
if (tty_io_error(tty))
|
||||||
|
@ -1333,9 +1260,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
|
||||||
struct serial_state *state = tty->driver_data;
|
struct serial_state *state = tty->driver_data;
|
||||||
struct tty_port *port = &state->tport;
|
struct tty_port *port = &state->tport;
|
||||||
|
|
||||||
if (serial_paranoia_check(state, tty->name, "rs_close"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tty_port_close_start(port, tty, filp) == 0)
|
if (tty_port_close_start(port, tty, filp) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1379,9 +1303,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||||
unsigned long orig_jiffies, char_time;
|
unsigned long orig_jiffies, char_time;
|
||||||
int lsr;
|
int lsr;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (info->xmit_fifo_size == 0)
|
if (info->xmit_fifo_size == 0)
|
||||||
return; /* Just in case.... */
|
return; /* Just in case.... */
|
||||||
|
|
||||||
|
@ -1440,9 +1361,6 @@ static void rs_hangup(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct serial_state *info = tty->driver_data;
|
struct serial_state *info = tty->driver_data;
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_hangup"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
rs_flush_buffer(tty);
|
rs_flush_buffer(tty);
|
||||||
shutdown(tty, info);
|
shutdown(tty, info);
|
||||||
info->tport.count = 0;
|
info->tport.count = 0;
|
||||||
|
@ -1467,8 +1385,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
|
||||||
port->tty = tty;
|
port->tty = tty;
|
||||||
tty->driver_data = info;
|
tty->driver_data = info;
|
||||||
tty->port = port;
|
tty->port = port;
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_open"))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
||||||
|
|
||||||
|
|
|
@ -70,22 +70,22 @@ config HVC_XEN_FRONTEND
|
||||||
Xen driver for secondary virtual consoles
|
Xen driver for secondary virtual consoles
|
||||||
|
|
||||||
config HVC_UDBG
|
config HVC_UDBG
|
||||||
bool "udbg based fake hypervisor console"
|
bool "udbg based fake hypervisor console"
|
||||||
depends on PPC
|
depends on PPC
|
||||||
select HVC_DRIVER
|
select HVC_DRIVER
|
||||||
help
|
help
|
||||||
This is meant to be used during HW bring up or debugging when
|
This is meant to be used during HW bring up or debugging when
|
||||||
no other console mechanism exist but udbg, to get you a quick
|
no other console mechanism exist but udbg, to get you a quick
|
||||||
console for userspace. Do NOT enable in production kernels.
|
console for userspace. Do NOT enable in production kernels.
|
||||||
|
|
||||||
config HVC_DCC
|
config HVC_DCC
|
||||||
bool "ARM JTAG DCC console"
|
bool "ARM JTAG DCC console"
|
||||||
depends on ARM || ARM64
|
depends on ARM || ARM64
|
||||||
select HVC_DRIVER
|
select HVC_DRIVER
|
||||||
help
|
help
|
||||||
This console uses the JTAG DCC on ARM to create a console under the HVC
|
This console uses the JTAG DCC on ARM to create a console under the HVC
|
||||||
driver. This console is used through a JTAG only on ARM. If you don't have
|
driver. This console is used through a JTAG only on ARM. If you don't have
|
||||||
a JTAG then you probably don't want this option.
|
a JTAG then you probably don't want this option.
|
||||||
|
|
||||||
config HVC_RISCV_SBI
|
config HVC_RISCV_SBI
|
||||||
bool "RISC-V SBI console support"
|
bool "RISC-V SBI console support"
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/* Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. */
|
/* Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. */
|
||||||
|
|
||||||
|
#include <linux/console.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
#include <linux/serial_core.h>
|
||||||
|
|
||||||
#include <asm/dcc.h>
|
#include <asm/dcc.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
@ -12,6 +15,31 @@
|
||||||
#define DCC_STATUS_RX (1 << 30)
|
#define DCC_STATUS_RX (1 << 30)
|
||||||
#define DCC_STATUS_TX (1 << 29)
|
#define DCC_STATUS_TX (1 << 29)
|
||||||
|
|
||||||
|
static void dcc_uart_console_putchar(struct uart_port *port, int ch)
|
||||||
|
{
|
||||||
|
while (__dcc_getstatus() & DCC_STATUS_TX)
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
__dcc_putchar(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcc_early_write(struct console *con, const char *s, unsigned n)
|
||||||
|
{
|
||||||
|
struct earlycon_device *dev = con->data;
|
||||||
|
|
||||||
|
uart_console_write(&dev->port, s, n, dcc_uart_console_putchar);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init dcc_early_console_setup(struct earlycon_device *device,
|
||||||
|
const char *opt)
|
||||||
|
{
|
||||||
|
device->con->write = dcc_early_write;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EARLYCON_DECLARE(dcc, dcc_early_console_setup);
|
||||||
|
|
||||||
static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
|
static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -1222,22 +1222,28 @@ static int set_config(struct tty_struct *tty, struct r_port *info,
|
||||||
*/
|
*/
|
||||||
static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
|
static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
|
||||||
{
|
{
|
||||||
struct rocket_ports tmp;
|
struct rocket_ports *tmp;
|
||||||
int board;
|
int board, ret = 0;
|
||||||
|
|
||||||
memset(&tmp, 0, sizeof (tmp));
|
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
||||||
tmp.tty_major = rocket_driver->major;
|
if (!tmp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
tmp->tty_major = rocket_driver->major;
|
||||||
|
|
||||||
for (board = 0; board < 4; board++) {
|
for (board = 0; board < 4; board++) {
|
||||||
tmp.rocketModel[board].model = rocketModel[board].model;
|
tmp->rocketModel[board].model = rocketModel[board].model;
|
||||||
strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString);
|
strcpy(tmp->rocketModel[board].modelString,
|
||||||
tmp.rocketModel[board].numPorts = rocketModel[board].numPorts;
|
rocketModel[board].modelString);
|
||||||
tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
|
tmp->rocketModel[board].numPorts = rocketModel[board].numPorts;
|
||||||
tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber;
|
tmp->rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
|
||||||
|
tmp->rocketModel[board].startingPortNumber =
|
||||||
|
rocketModel[board].startingPortNumber;
|
||||||
}
|
}
|
||||||
if (copy_to_user(retports, &tmp, sizeof (*retports)))
|
if (copy_to_user(retports, tmp, sizeof(*retports)))
|
||||||
return -EFAULT;
|
ret = -EFAULT;
|
||||||
return 0;
|
kfree(tmp);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reset_rm2(struct r_port *info, void __user *arg)
|
static int reset_rm2(struct r_port *info, void __user *arg)
|
||||||
|
|
|
@ -552,15 +552,96 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl,
|
|
||||||
struct acpi_device *adev)
|
|
||||||
{
|
|
||||||
struct serdev_device *serdev = NULL;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (acpi_bus_get_status(adev) || !adev->status.present ||
|
#define SERDEV_ACPI_MAX_SCAN_DEPTH 32
|
||||||
acpi_device_enumerated(adev))
|
|
||||||
return AE_OK;
|
struct acpi_serdev_lookup {
|
||||||
|
acpi_handle device_handle;
|
||||||
|
acpi_handle controller_handle;
|
||||||
|
int n;
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
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);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: Ideally, we would also want to retreive other properties here,
|
||||||
|
* once setting them before opening the device is supported by serdev.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int acpi_serdev_do_lookup(struct acpi_device *adev,
|
||||||
|
struct acpi_serdev_lookup *lookup)
|
||||||
|
{
|
||||||
|
struct list_head resource_list;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
lookup->device_handle = acpi_device_handle(adev);
|
||||||
|
lookup->controller_handle = NULL;
|
||||||
|
lookup->n = 0;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&resource_list);
|
||||||
|
ret = acpi_dev_get_resources(adev, &resource_list,
|
||||||
|
acpi_serdev_parse_resource, lookup);
|
||||||
|
acpi_dev_free_resource_list(&resource_list);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int acpi_serdev_check_resources(struct serdev_controller *ctrl,
|
||||||
|
struct acpi_device *adev)
|
||||||
|
{
|
||||||
|
struct acpi_serdev_lookup lookup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (acpi_bus_get_status(adev) || !adev->status.present)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Look for UARTSerialBusV2 resource */
|
||||||
|
lookup.index = -1; // we only care for the last device
|
||||||
|
|
||||||
|
ret = acpi_serdev_do_lookup(adev, &lookup);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Make sure controller and ResourceSource handle match */
|
||||||
|
if (ACPI_HANDLE(ctrl->dev.parent) != lookup.controller_handle)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl,
|
||||||
|
struct acpi_device *adev)
|
||||||
|
{
|
||||||
|
struct serdev_device *serdev;
|
||||||
|
int err;
|
||||||
|
|
||||||
serdev = serdev_device_alloc(ctrl);
|
serdev = serdev_device_alloc(ctrl);
|
||||||
if (!serdev) {
|
if (!serdev) {
|
||||||
|
@ -583,7 +664,7 @@ static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
|
static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
|
||||||
void *data, void **return_value)
|
void *data, void **return_value)
|
||||||
{
|
{
|
||||||
struct serdev_controller *ctrl = data;
|
struct serdev_controller *ctrl = data;
|
||||||
struct acpi_device *adev;
|
struct acpi_device *adev;
|
||||||
|
@ -591,22 +672,28 @@ static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
|
||||||
if (acpi_bus_get_device(handle, &adev))
|
if (acpi_bus_get_device(handle, &adev))
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
|
|
||||||
|
if (acpi_device_enumerated(adev))
|
||||||
|
return AE_OK;
|
||||||
|
|
||||||
|
if (acpi_serdev_check_resources(ctrl, adev))
|
||||||
|
return AE_OK;
|
||||||
|
|
||||||
return acpi_serdev_register_device(ctrl, adev);
|
return acpi_serdev_register_device(ctrl, adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int acpi_serdev_register_devices(struct serdev_controller *ctrl)
|
static int acpi_serdev_register_devices(struct serdev_controller *ctrl)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
acpi_handle handle;
|
|
||||||
|
|
||||||
handle = ACPI_HANDLE(ctrl->dev.parent);
|
if (!has_acpi_companion(ctrl->dev.parent))
|
||||||
if (!handle)
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
|
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||||
|
SERDEV_ACPI_MAX_SCAN_DEPTH,
|
||||||
acpi_serdev_add_device, NULL, ctrl, NULL);
|
acpi_serdev_add_device, NULL, ctrl, NULL);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
dev_dbg(&ctrl->dev, "failed to enumerate serdev slaves\n");
|
dev_warn(&ctrl->dev, "failed to enumerate serdev slaves\n");
|
||||||
|
|
||||||
if (!ctrl->serdev)
|
if (!ctrl->serdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/mfd/syscon.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
@ -22,6 +24,7 @@
|
||||||
|
|
||||||
#define ASPEED_VUART_GCRA 0x20
|
#define ASPEED_VUART_GCRA 0x20
|
||||||
#define ASPEED_VUART_GCRA_VUART_EN BIT(0)
|
#define ASPEED_VUART_GCRA_VUART_EN BIT(0)
|
||||||
|
#define ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY BIT(1)
|
||||||
#define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5)
|
#define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5)
|
||||||
#define ASPEED_VUART_GCRB 0x24
|
#define ASPEED_VUART_GCRB 0x24
|
||||||
#define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4)
|
#define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4)
|
||||||
|
@ -131,8 +134,53 @@ static ssize_t sirq_store(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
static DEVICE_ATTR_RW(sirq);
|
static DEVICE_ATTR_RW(sirq);
|
||||||
|
|
||||||
|
static ssize_t sirq_polarity_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
|
||||||
|
u8 reg;
|
||||||
|
|
||||||
|
reg = readb(vuart->regs + ASPEED_VUART_GCRA);
|
||||||
|
reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart,
|
||||||
|
bool polarity)
|
||||||
|
{
|
||||||
|
u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
|
||||||
|
|
||||||
|
if (polarity)
|
||||||
|
reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
|
||||||
|
else
|
||||||
|
reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
|
||||||
|
|
||||||
|
writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t sirq_polarity_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
|
||||||
|
unsigned long val;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = kstrtoul(buf, 0, &val);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
aspeed_vuart_set_sirq_polarity(vuart, val != 0);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_RW(sirq_polarity);
|
||||||
|
|
||||||
static struct attribute *aspeed_vuart_attrs[] = {
|
static struct attribute *aspeed_vuart_attrs[] = {
|
||||||
&dev_attr_sirq.attr,
|
&dev_attr_sirq.attr,
|
||||||
|
&dev_attr_sirq_polarity.attr,
|
||||||
&dev_attr_lpc_address.attr,
|
&dev_attr_lpc_address.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
@ -302,8 +350,30 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void aspeed_vuart_auto_configure_sirq_polarity(
|
||||||
|
struct aspeed_vuart *vuart, struct device_node *syscon_np,
|
||||||
|
u32 reg_offset, u32 reg_mask)
|
||||||
|
{
|
||||||
|
struct regmap *regmap;
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
regmap = syscon_node_to_regmap(syscon_np);
|
||||||
|
if (IS_ERR(regmap)) {
|
||||||
|
dev_warn(vuart->dev,
|
||||||
|
"could not get regmap for aspeed,sirq-polarity-sense\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (regmap_read(regmap, reg_offset, &value)) {
|
||||||
|
dev_warn(vuart->dev, "could not read hw strap table\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int aspeed_vuart_probe(struct platform_device *pdev)
|
static int aspeed_vuart_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct of_phandle_args sirq_polarity_sense_args;
|
||||||
struct uart_8250_port port;
|
struct uart_8250_port port;
|
||||||
struct aspeed_vuart *vuart;
|
struct aspeed_vuart *vuart;
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
@ -402,6 +472,20 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
vuart->line = rc;
|
vuart->line = rc;
|
||||||
|
|
||||||
|
rc = of_parse_phandle_with_fixed_args(
|
||||||
|
np, "aspeed,sirq-polarity-sense", 2, 0,
|
||||||
|
&sirq_polarity_sense_args);
|
||||||
|
if (rc < 0) {
|
||||||
|
dev_dbg(&pdev->dev,
|
||||||
|
"aspeed,sirq-polarity-sense property not found\n");
|
||||||
|
} else {
|
||||||
|
aspeed_vuart_auto_configure_sirq_polarity(
|
||||||
|
vuart, sirq_polarity_sense_args.np,
|
||||||
|
sirq_polarity_sense_args.args[0],
|
||||||
|
BIT(sirq_polarity_sense_args.args[1]));
|
||||||
|
of_node_put(sirq_polarity_sense_args.np);
|
||||||
|
}
|
||||||
|
|
||||||
aspeed_vuart_set_enabled(vuart, true);
|
aspeed_vuart_set_enabled(vuart, true);
|
||||||
aspeed_vuart_set_host_tx_discard(vuart, true);
|
aspeed_vuart_set_host_tx_discard(vuart, true);
|
||||||
platform_set_drvdata(pdev, vuart);
|
platform_set_drvdata(pdev, vuart);
|
||||||
|
|
|
@ -280,9 +280,6 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||||
long rate;
|
long rate;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (IS_ERR(d->clk))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
clk_disable_unprepare(d->clk);
|
clk_disable_unprepare(d->clk);
|
||||||
rate = clk_round_rate(d->clk, baud * 16);
|
rate = clk_round_rate(d->clk, baud * 16);
|
||||||
if (rate < 0)
|
if (rate < 0)
|
||||||
|
@ -293,8 +290,10 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||||
ret = clk_set_rate(d->clk, rate);
|
ret = clk_set_rate(d->clk, rate);
|
||||||
clk_prepare_enable(d->clk);
|
clk_prepare_enable(d->clk);
|
||||||
|
|
||||||
if (!ret)
|
if (ret)
|
||||||
p->uartclk = rate;
|
goto out;
|
||||||
|
|
||||||
|
p->uartclk = rate;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
p->status &= ~UPSTAT_AUTOCTS;
|
p->status &= ~UPSTAT_AUTOCTS;
|
||||||
|
@ -386,10 +385,10 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct uart_8250_port uart = {}, *up = &uart;
|
struct uart_8250_port uart = {}, *up = &uart;
|
||||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
int irq = platform_get_irq(pdev, 0);
|
|
||||||
struct uart_port *p = &up->port;
|
struct uart_port *p = &up->port;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct dw8250_data *data;
|
struct dw8250_data *data;
|
||||||
|
int irq;
|
||||||
int err;
|
int err;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
|
@ -398,11 +397,9 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irq < 0) {
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq != -EPROBE_DEFER)
|
if (irq < 0)
|
||||||
dev_err(dev, "cannot get irq\n");
|
|
||||||
return irq;
|
return irq;
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_init(&p->lock);
|
spin_lock_init(&p->lock);
|
||||||
p->mapbase = regs->start;
|
p->mapbase = regs->start;
|
||||||
|
@ -472,19 +469,18 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||||
device_property_read_u32(dev, "clock-frequency", &p->uartclk);
|
device_property_read_u32(dev, "clock-frequency", &p->uartclk);
|
||||||
|
|
||||||
/* If there is separate baudclk, get the rate from it. */
|
/* If there is separate baudclk, get the rate from it. */
|
||||||
data->clk = devm_clk_get(dev, "baudclk");
|
data->clk = devm_clk_get_optional(dev, "baudclk");
|
||||||
if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER)
|
if (data->clk == NULL)
|
||||||
data->clk = devm_clk_get(dev, NULL);
|
data->clk = devm_clk_get_optional(dev, NULL);
|
||||||
if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER)
|
if (IS_ERR(data->clk))
|
||||||
return -EPROBE_DEFER;
|
return PTR_ERR(data->clk);
|
||||||
if (!IS_ERR_OR_NULL(data->clk)) {
|
|
||||||
err = clk_prepare_enable(data->clk);
|
err = clk_prepare_enable(data->clk);
|
||||||
if (err)
|
if (err)
|
||||||
dev_warn(dev, "could not enable optional baudclk: %d\n",
|
dev_warn(dev, "could not enable optional baudclk: %d\n", err);
|
||||||
err);
|
|
||||||
else
|
if (data->clk)
|
||||||
p->uartclk = clk_get_rate(data->clk);
|
p->uartclk = clk_get_rate(data->clk);
|
||||||
}
|
|
||||||
|
|
||||||
/* If no clock rate is defined, fail. */
|
/* If no clock rate is defined, fail. */
|
||||||
if (!p->uartclk) {
|
if (!p->uartclk) {
|
||||||
|
@ -493,17 +489,16 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||||
goto err_clk;
|
goto err_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->pclk = devm_clk_get(dev, "apb_pclk");
|
data->pclk = devm_clk_get_optional(dev, "apb_pclk");
|
||||||
if (IS_ERR(data->pclk) && PTR_ERR(data->pclk) == -EPROBE_DEFER) {
|
if (IS_ERR(data->pclk)) {
|
||||||
err = -EPROBE_DEFER;
|
err = PTR_ERR(data->pclk);
|
||||||
goto err_clk;
|
goto err_clk;
|
||||||
}
|
}
|
||||||
if (!IS_ERR(data->pclk)) {
|
|
||||||
err = clk_prepare_enable(data->pclk);
|
err = clk_prepare_enable(data->pclk);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(dev, "could not enable apb_pclk\n");
|
dev_err(dev, "could not enable apb_pclk\n");
|
||||||
goto err_clk;
|
goto err_clk;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
|
data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
|
||||||
|
@ -546,12 +541,10 @@ err_reset:
|
||||||
reset_control_assert(data->rst);
|
reset_control_assert(data->rst);
|
||||||
|
|
||||||
err_pclk:
|
err_pclk:
|
||||||
if (!IS_ERR(data->pclk))
|
clk_disable_unprepare(data->pclk);
|
||||||
clk_disable_unprepare(data->pclk);
|
|
||||||
|
|
||||||
err_clk:
|
err_clk:
|
||||||
if (!IS_ERR(data->clk))
|
clk_disable_unprepare(data->clk);
|
||||||
clk_disable_unprepare(data->clk);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -567,11 +560,9 @@ static int dw8250_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
reset_control_assert(data->rst);
|
reset_control_assert(data->rst);
|
||||||
|
|
||||||
if (!IS_ERR(data->pclk))
|
clk_disable_unprepare(data->pclk);
|
||||||
clk_disable_unprepare(data->pclk);
|
|
||||||
|
|
||||||
if (!IS_ERR(data->clk))
|
clk_disable_unprepare(data->clk);
|
||||||
clk_disable_unprepare(data->clk);
|
|
||||||
|
|
||||||
pm_runtime_disable(dev);
|
pm_runtime_disable(dev);
|
||||||
pm_runtime_put_noidle(dev);
|
pm_runtime_put_noidle(dev);
|
||||||
|
@ -604,11 +595,9 @@ static int dw8250_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct dw8250_data *data = dev_get_drvdata(dev);
|
struct dw8250_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (!IS_ERR(data->clk))
|
clk_disable_unprepare(data->clk);
|
||||||
clk_disable_unprepare(data->clk);
|
|
||||||
|
|
||||||
if (!IS_ERR(data->pclk))
|
clk_disable_unprepare(data->pclk);
|
||||||
clk_disable_unprepare(data->pclk);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -617,11 +606,9 @@ static int dw8250_runtime_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct dw8250_data *data = dev_get_drvdata(dev);
|
struct dw8250_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (!IS_ERR(data->pclk))
|
clk_prepare_enable(data->pclk);
|
||||||
clk_prepare_enable(data->pclk);
|
|
||||||
|
|
||||||
if (!IS_ERR(data->clk))
|
clk_prepare_enable(data->clk);
|
||||||
clk_prepare_enable(data->clk);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,23 @@ static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud,
|
||||||
serial_port_out(p, 0x2, quot_frac);
|
serial_port_out(p, 0x2, quot_frac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xr17v35x_startup(struct uart_port *port)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* First enable access to IER [7:5], ISR [5:4], FCR [5:4],
|
||||||
|
* MCR [7:5] and MSR [7:0]
|
||||||
|
*/
|
||||||
|
serial_port_out(port, UART_XR_EFR, UART_EFR_ECB);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure all interrups are masked until initialization is
|
||||||
|
* complete and the FIFOs are cleared
|
||||||
|
*/
|
||||||
|
serial_port_out(port, UART_IER, 0);
|
||||||
|
|
||||||
|
return serial8250_do_startup(port);
|
||||||
|
}
|
||||||
|
|
||||||
static void exar_shutdown(struct uart_port *port)
|
static void exar_shutdown(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned char lsr;
|
unsigned char lsr;
|
||||||
|
@ -212,6 +229,8 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,
|
||||||
|
|
||||||
port->port.get_divisor = xr17v35x_get_divisor;
|
port->port.get_divisor = xr17v35x_get_divisor;
|
||||||
port->port.set_divisor = xr17v35x_set_divisor;
|
port->port.set_divisor = xr17v35x_set_divisor;
|
||||||
|
|
||||||
|
port->port.startup = xr17v35x_startup;
|
||||||
} else {
|
} else {
|
||||||
port->port.type = PORT_XR17D15X;
|
port->port.type = PORT_XR17D15X;
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,17 +221,6 @@ static void qrk_serial_exit_dma(struct lpss8250 *lpss) {}
|
||||||
|
|
||||||
static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
|
static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(port->dev);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
pci_set_master(pdev);
|
|
||||||
|
|
||||||
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
port->irq = pci_irq_vector(pdev, 0);
|
|
||||||
|
|
||||||
qrk_serial_setup_dma(lpss, port);
|
qrk_serial_setup_dma(lpss, port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -293,16 +282,22 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
pci_set_master(pdev);
|
||||||
|
|
||||||
lpss = devm_kzalloc(&pdev->dev, sizeof(*lpss), GFP_KERNEL);
|
lpss = devm_kzalloc(&pdev->dev, sizeof(*lpss), GFP_KERNEL);
|
||||||
if (!lpss)
|
if (!lpss)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
lpss->board = (struct lpss8250_board *)id->driver_data;
|
lpss->board = (struct lpss8250_board *)id->driver_data;
|
||||||
|
|
||||||
memset(&uart, 0, sizeof(struct uart_8250_port));
|
memset(&uart, 0, sizeof(struct uart_8250_port));
|
||||||
|
|
||||||
uart.port.dev = &pdev->dev;
|
uart.port.dev = &pdev->dev;
|
||||||
uart.port.irq = pdev->irq;
|
uart.port.irq = pci_irq_vector(pdev, 0);
|
||||||
uart.port.private_data = &lpss->data;
|
uart.port.private_data = &lpss->data;
|
||||||
uart.port.type = PORT_16550A;
|
uart.port.type = PORT_16550A;
|
||||||
uart.port.iotype = UPIO_MEM;
|
uart.port.iotype = UPIO_MEM;
|
||||||
|
@ -337,6 +332,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
err_exit:
|
err_exit:
|
||||||
if (lpss->board->exit)
|
if (lpss->board->exit)
|
||||||
lpss->board->exit(lpss);
|
lpss->board->exit(lpss);
|
||||||
|
pci_free_irq_vectors(pdev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,6 +344,7 @@ static void lpss8250_remove(struct pci_dev *pdev)
|
||||||
|
|
||||||
if (lpss->board->exit)
|
if (lpss->board->exit)
|
||||||
lpss->board->exit(lpss);
|
lpss->board->exit(lpss);
|
||||||
|
pci_free_irq_vectors(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct lpss8250_board byt_board = {
|
static const struct lpss8250_board byt_board = {
|
||||||
|
|
|
@ -544,7 +544,7 @@ static int mtk8250_probe(struct platform_device *pdev)
|
||||||
pm_runtime_set_active(&pdev->dev);
|
pm_runtime_set_active(&pdev->dev);
|
||||||
pm_runtime_enable(&pdev->dev);
|
pm_runtime_enable(&pdev->dev);
|
||||||
|
|
||||||
data->rx_wakeup_irq = platform_get_irq(pdev, 1);
|
data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,36 @@ static inline void tegra_serial_handle_break(struct uart_port *port)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int of_8250_rs485_config(struct uart_port *port,
|
||||||
|
struct serial_rs485 *rs485)
|
||||||
|
{
|
||||||
|
struct uart_8250_port *up = up_to_u8250p(port);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
port->rs485 = *rs485;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Both serial8250_em485_init and serial8250_em485_destroy
|
||||||
|
* are idempotent
|
||||||
|
*/
|
||||||
|
if (rs485->flags & SER_RS485_ENABLED) {
|
||||||
|
int ret = serial8250_em485_init(up);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
rs485->flags &= ~SER_RS485_ENABLED;
|
||||||
|
port->rs485.flags &= ~SER_RS485_ENABLED;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
serial8250_em485_destroy(up);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill a struct uart_port for a given device node
|
* Fill a struct uart_port for a given device node
|
||||||
*/
|
*/
|
||||||
|
@ -178,6 +208,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
||||||
port->flags |= UPF_SKIP_TEST;
|
port->flags |= UPF_SKIP_TEST;
|
||||||
|
|
||||||
port->dev = &ofdev->dev;
|
port->dev = &ofdev->dev;
|
||||||
|
port->rs485_config = of_8250_rs485_config;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PORT_TEGRA:
|
case PORT_TEGRA:
|
||||||
|
|
|
@ -743,16 +743,8 @@ static int pci_ni8430_init(struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UART Port Control Register */
|
/* UART Port Control Register */
|
||||||
#define NI16550_PCR_OFFSET 0x0f
|
#define NI8430_PORTCON 0x0f
|
||||||
#define NI16550_PCR_RS422 0x00
|
#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
|
||||||
#define NI16550_PCR_ECHO_RS485 0x01
|
|
||||||
#define NI16550_PCR_DTR_RS485 0x02
|
|
||||||
#define NI16550_PCR_AUTO_RS485 0x03
|
|
||||||
#define NI16550_PCR_WIRE_MODE_MASK 0x03
|
|
||||||
#define NI16550_PCR_TXVR_ENABLE_BIT BIT(3)
|
|
||||||
#define NI16550_PCR_RS485_TERMINATION_BIT BIT(6)
|
|
||||||
#define NI16550_ACR_DTR_AUTO_DTR (0x2 << 3)
|
|
||||||
#define NI16550_ACR_DTR_MANUAL_DTR (0x0 << 3)
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pci_ni8430_setup(struct serial_private *priv,
|
pci_ni8430_setup(struct serial_private *priv,
|
||||||
|
@ -774,117 +766,14 @@ pci_ni8430_setup(struct serial_private *priv,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* enable the transceiver */
|
/* enable the transceiver */
|
||||||
writeb(readb(p + offset + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT,
|
writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
|
||||||
p + offset + NI16550_PCR_OFFSET);
|
p + offset + NI8430_PORTCON);
|
||||||
|
|
||||||
iounmap(p);
|
iounmap(p);
|
||||||
|
|
||||||
return setup_port(priv, port, bar, offset, board->reg_shift);
|
return setup_port(priv, port, bar, offset, board->reg_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_ni8431_config_rs485(struct uart_port *port,
|
|
||||||
struct serial_rs485 *rs485)
|
|
||||||
{
|
|
||||||
u8 pcr, acr;
|
|
||||||
struct uart_8250_port *up;
|
|
||||||
|
|
||||||
up = container_of(port, struct uart_8250_port, port);
|
|
||||||
acr = up->acr;
|
|
||||||
pcr = port->serial_in(port, NI16550_PCR_OFFSET);
|
|
||||||
pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
|
|
||||||
|
|
||||||
if (rs485->flags & SER_RS485_ENABLED) {
|
|
||||||
/* RS-485 */
|
|
||||||
if ((rs485->flags & SER_RS485_RX_DURING_TX) &&
|
|
||||||
(rs485->flags & SER_RS485_RTS_ON_SEND)) {
|
|
||||||
dev_dbg(port->dev, "Invalid 2-wire mode\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rs485->flags & SER_RS485_RX_DURING_TX) {
|
|
||||||
/* Echo */
|
|
||||||
dev_vdbg(port->dev, "2-wire DTR with echo\n");
|
|
||||||
pcr |= NI16550_PCR_ECHO_RS485;
|
|
||||||
acr |= NI16550_ACR_DTR_MANUAL_DTR;
|
|
||||||
} else {
|
|
||||||
/* Auto or DTR */
|
|
||||||
if (rs485->flags & SER_RS485_RTS_ON_SEND) {
|
|
||||||
/* Auto */
|
|
||||||
dev_vdbg(port->dev, "2-wire Auto\n");
|
|
||||||
pcr |= NI16550_PCR_AUTO_RS485;
|
|
||||||
acr |= NI16550_ACR_DTR_AUTO_DTR;
|
|
||||||
} else {
|
|
||||||
/* DTR-controlled */
|
|
||||||
/* No Echo */
|
|
||||||
dev_vdbg(port->dev, "2-wire DTR no echo\n");
|
|
||||||
pcr |= NI16550_PCR_DTR_RS485;
|
|
||||||
acr |= NI16550_ACR_DTR_MANUAL_DTR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* RS-422 */
|
|
||||||
dev_vdbg(port->dev, "4-wire\n");
|
|
||||||
pcr |= NI16550_PCR_RS422;
|
|
||||||
acr |= NI16550_ACR_DTR_MANUAL_DTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr);
|
|
||||||
port->serial_out(port, NI16550_PCR_OFFSET, pcr);
|
|
||||||
|
|
||||||
up->acr = acr;
|
|
||||||
port->serial_out(port, UART_SCR, UART_ACR);
|
|
||||||
port->serial_out(port, UART_ICR, up->acr);
|
|
||||||
|
|
||||||
/* Update the cache. */
|
|
||||||
port->rs485 = *rs485;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pci_ni8431_setup(struct serial_private *priv,
|
|
||||||
const struct pciserial_board *board,
|
|
||||||
struct uart_8250_port *uart, int idx)
|
|
||||||
{
|
|
||||||
u8 pcr, acr;
|
|
||||||
struct pci_dev *dev = priv->dev;
|
|
||||||
void __iomem *addr;
|
|
||||||
unsigned int bar, offset = board->first_offset;
|
|
||||||
|
|
||||||
if (idx >= board->num_ports)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
bar = FL_GET_BASE(board->flags);
|
|
||||||
offset += idx * board->uart_offset;
|
|
||||||
|
|
||||||
addr = pci_ioremap_bar(dev, bar);
|
|
||||||
if (!addr)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* enable the transceiver */
|
|
||||||
writeb(readb(addr + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT,
|
|
||||||
addr + NI16550_PCR_OFFSET);
|
|
||||||
|
|
||||||
pcr = readb(addr + NI16550_PCR_OFFSET);
|
|
||||||
pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
|
|
||||||
|
|
||||||
/* set wire mode to default RS-422 */
|
|
||||||
pcr |= NI16550_PCR_RS422;
|
|
||||||
acr = NI16550_ACR_DTR_MANUAL_DTR;
|
|
||||||
|
|
||||||
/* write port configuration to register */
|
|
||||||
writeb(pcr, addr + NI16550_PCR_OFFSET);
|
|
||||||
|
|
||||||
/* access and write to UART acr register */
|
|
||||||
writeb(UART_ACR, addr + UART_SCR);
|
|
||||||
writeb(acr, addr + UART_ICR);
|
|
||||||
|
|
||||||
uart->port.rs485_config = &pci_ni8431_config_rs485;
|
|
||||||
|
|
||||||
iounmap(addr);
|
|
||||||
|
|
||||||
return setup_port(priv, uart, bar, offset, board->reg_shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pci_netmos_9900_setup(struct serial_private *priv,
|
static int pci_netmos_9900_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_8250_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
|
@ -2021,15 +1910,6 @@ pci_moxa_setup(struct serial_private *priv,
|
||||||
#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9
|
#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9
|
||||||
#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8
|
#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8
|
||||||
|
|
||||||
#define PCIE_DEVICE_ID_NI_PXIE8430_2328 0x74C2
|
|
||||||
#define PCIE_DEVICE_ID_NI_PXIE8430_23216 0x74C1
|
|
||||||
#define PCI_DEVICE_ID_NI_PXI8431_4852 0x7081
|
|
||||||
#define PCI_DEVICE_ID_NI_PXI8431_4854 0x70DE
|
|
||||||
#define PCI_DEVICE_ID_NI_PXI8431_4858 0x70E3
|
|
||||||
#define PCI_DEVICE_ID_NI_PXI8433_4852 0x70E9
|
|
||||||
#define PCI_DEVICE_ID_NI_PXI8433_4854 0x70ED
|
|
||||||
#define PCIE_DEVICE_ID_NI_PXIE8431_4858 0x74C4
|
|
||||||
#define PCIE_DEVICE_ID_NI_PXIE8431_48516 0x74C3
|
|
||||||
|
|
||||||
#define PCI_DEVICE_ID_MOXA_CP102E 0x1024
|
#define PCI_DEVICE_ID_MOXA_CP102E 0x1024
|
||||||
#define PCI_DEVICE_ID_MOXA_CP102EL 0x1025
|
#define PCI_DEVICE_ID_MOXA_CP102EL 0x1025
|
||||||
|
@ -2267,87 +2147,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||||
.setup = pci_ni8430_setup,
|
.setup = pci_ni8430_setup,
|
||||||
.exit = pci_ni8430_exit,
|
.exit = pci_ni8430_exit,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCIE_DEVICE_ID_NI_PXIE8430_2328,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8430_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCIE_DEVICE_ID_NI_PXIE8430_23216,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8430_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCI_DEVICE_ID_NI_PXI8431_4852,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8431_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCI_DEVICE_ID_NI_PXI8431_4854,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8431_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCI_DEVICE_ID_NI_PXI8431_4858,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8431_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCI_DEVICE_ID_NI_PXI8433_4852,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8431_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCI_DEVICE_ID_NI_PXI8433_4854,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8431_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCIE_DEVICE_ID_NI_PXIE8431_4858,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8431_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.vendor = PCI_VENDOR_ID_NI,
|
|
||||||
.device = PCIE_DEVICE_ID_NI_PXIE8431_48516,
|
|
||||||
.subvendor = PCI_ANY_ID,
|
|
||||||
.subdevice = PCI_ANY_ID,
|
|
||||||
.init = pci_ni8430_init,
|
|
||||||
.setup = pci_ni8431_setup,
|
|
||||||
.exit = pci_ni8430_exit,
|
|
||||||
},
|
|
||||||
/* Quatech */
|
/* Quatech */
|
||||||
{
|
{
|
||||||
.vendor = PCI_VENDOR_ID_QUATECH,
|
.vendor = PCI_VENDOR_ID_QUATECH,
|
||||||
|
@ -3104,13 +2903,6 @@ enum pci_board_num_t {
|
||||||
pbn_ni8430_4,
|
pbn_ni8430_4,
|
||||||
pbn_ni8430_8,
|
pbn_ni8430_8,
|
||||||
pbn_ni8430_16,
|
pbn_ni8430_16,
|
||||||
pbn_ni8430_pxie_8,
|
|
||||||
pbn_ni8430_pxie_16,
|
|
||||||
pbn_ni8431_2,
|
|
||||||
pbn_ni8431_4,
|
|
||||||
pbn_ni8431_8,
|
|
||||||
pbn_ni8431_pxie_8,
|
|
||||||
pbn_ni8431_pxie_16,
|
|
||||||
pbn_ADDIDATA_PCIe_1_3906250,
|
pbn_ADDIDATA_PCIe_1_3906250,
|
||||||
pbn_ADDIDATA_PCIe_2_3906250,
|
pbn_ADDIDATA_PCIe_2_3906250,
|
||||||
pbn_ADDIDATA_PCIe_4_3906250,
|
pbn_ADDIDATA_PCIe_4_3906250,
|
||||||
|
@ -3763,55 +3555,6 @@ static struct pciserial_board pci_boards[] = {
|
||||||
.uart_offset = 0x10,
|
.uart_offset = 0x10,
|
||||||
.first_offset = 0x800,
|
.first_offset = 0x800,
|
||||||
},
|
},
|
||||||
[pbn_ni8430_pxie_16] = {
|
|
||||||
.flags = FL_BASE0,
|
|
||||||
.num_ports = 16,
|
|
||||||
.base_baud = 3125000,
|
|
||||||
.uart_offset = 0x10,
|
|
||||||
.first_offset = 0x800,
|
|
||||||
},
|
|
||||||
[pbn_ni8430_pxie_8] = {
|
|
||||||
.flags = FL_BASE0,
|
|
||||||
.num_ports = 8,
|
|
||||||
.base_baud = 3125000,
|
|
||||||
.uart_offset = 0x10,
|
|
||||||
.first_offset = 0x800,
|
|
||||||
},
|
|
||||||
[pbn_ni8431_8] = {
|
|
||||||
.flags = FL_BASE0,
|
|
||||||
.num_ports = 8,
|
|
||||||
.base_baud = 3686400,
|
|
||||||
.uart_offset = 0x10,
|
|
||||||
.first_offset = 0x800,
|
|
||||||
},
|
|
||||||
[pbn_ni8431_4] = {
|
|
||||||
.flags = FL_BASE0,
|
|
||||||
.num_ports = 4,
|
|
||||||
.base_baud = 3686400,
|
|
||||||
.uart_offset = 0x10,
|
|
||||||
.first_offset = 0x800,
|
|
||||||
},
|
|
||||||
[pbn_ni8431_2] = {
|
|
||||||
.flags = FL_BASE0,
|
|
||||||
.num_ports = 2,
|
|
||||||
.base_baud = 3686400,
|
|
||||||
.uart_offset = 0x10,
|
|
||||||
.first_offset = 0x800,
|
|
||||||
},
|
|
||||||
[pbn_ni8431_pxie_16] = {
|
|
||||||
.flags = FL_BASE0,
|
|
||||||
.num_ports = 16,
|
|
||||||
.base_baud = 3125000,
|
|
||||||
.uart_offset = 0x10,
|
|
||||||
.first_offset = 0x800,
|
|
||||||
},
|
|
||||||
[pbn_ni8431_pxie_8] = {
|
|
||||||
.flags = FL_BASE0,
|
|
||||||
.num_ports = 8,
|
|
||||||
.base_baud = 3125000,
|
|
||||||
.uart_offset = 0x10,
|
|
||||||
.first_offset = 0x800,
|
|
||||||
},
|
|
||||||
/*
|
/*
|
||||||
* ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
|
* ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
|
||||||
*/
|
*/
|
||||||
|
@ -5565,33 +5308,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
|
||||||
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
|
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||||
pbn_ni8430_4 },
|
pbn_ni8430_4 },
|
||||||
{ PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_2328,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8430_pxie_8 },
|
|
||||||
{ PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_23216,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8430_pxie_16 },
|
|
||||||
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4852,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8431_2 },
|
|
||||||
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4854,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8431_4 },
|
|
||||||
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4858,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8431_8 },
|
|
||||||
{ PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_4858,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8431_pxie_8 },
|
|
||||||
{ PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_48516,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8431_pxie_16 },
|
|
||||||
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4852,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8431_2 },
|
|
||||||
{ PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4854,
|
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
pbn_ni8431_4 },
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MOXA
|
* MOXA
|
||||||
|
|
|
@ -2114,20 +2114,6 @@ int serial8250_do_startup(struct uart_port *port)
|
||||||
enable_rsa(up);
|
enable_rsa(up);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (port->type == PORT_XR17V35X) {
|
|
||||||
/*
|
|
||||||
* First enable access to IER [7:5], ISR [5:4], FCR [5:4],
|
|
||||||
* MCR [7:5] and MSR [7:0]
|
|
||||||
*/
|
|
||||||
serial_port_out(port, UART_XR_EFR, UART_EFR_ECB);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure all interrups are masked until initialization is
|
|
||||||
* complete and the FIFOs are cleared
|
|
||||||
*/
|
|
||||||
serial_port_out(port, UART_IER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the FIFO buffers and disable them.
|
* Clear the FIFO buffers and disable them.
|
||||||
* (they will be reenabled in set_termios())
|
* (they will be reenabled in set_termios())
|
||||||
|
|
|
@ -243,6 +243,7 @@ config SERIAL_8250_ASPEED_VUART
|
||||||
tristate "Aspeed Virtual UART"
|
tristate "Aspeed Virtual UART"
|
||||||
depends on SERIAL_8250
|
depends on SERIAL_8250
|
||||||
depends on OF
|
depends on OF
|
||||||
|
depends on REGMAP && MFD_SYSCON
|
||||||
help
|
help
|
||||||
If you want to use the virtual UART (VUART) device on Aspeed
|
If you want to use the virtual UART (VUART) device on Aspeed
|
||||||
BMC platforms, enable this option. This enables the 16550A-
|
BMC platforms, enable this option. This enables the 16550A-
|
||||||
|
@ -334,7 +335,7 @@ config SERIAL_8250_BCM2835AUX
|
||||||
|
|
||||||
Features and limitations of the UART are
|
Features and limitations of the UART are
|
||||||
Registers are similar to 16650 registers,
|
Registers are similar to 16650 registers,
|
||||||
set bits in the control registers that are unsupported
|
set bits in the control registers that are unsupported
|
||||||
are ignored and read back as 0
|
are ignored and read back as 0
|
||||||
7/8 bit operation with 1 start and 1 stop bit
|
7/8 bit operation with 1 start and 1 stop bit
|
||||||
8 symbols deep fifo for rx and tx
|
8 symbols deep fifo for rx and tx
|
||||||
|
|
|
@ -287,26 +287,26 @@ config SERIAL_SAMSUNG_CONSOLE
|
||||||
boot time.)
|
boot time.)
|
||||||
|
|
||||||
config SERIAL_SIRFSOC
|
config SERIAL_SIRFSOC
|
||||||
tristate "SiRF SoC Platform Serial port support"
|
tristate "SiRF SoC Platform Serial port support"
|
||||||
depends on ARCH_SIRF
|
depends on ARCH_SIRF
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
help
|
help
|
||||||
Support for the on-chip UART on the CSR SiRFprimaII series,
|
Support for the on-chip UART on the CSR SiRFprimaII series,
|
||||||
providing /dev/ttySiRF0, 1 and 2 (note, some machines may not
|
providing /dev/ttySiRF0, 1 and 2 (note, some machines may not
|
||||||
provide all of these ports, depending on how the serial port
|
provide all of these ports, depending on how the serial port
|
||||||
pins are configured).
|
pins are configured).
|
||||||
|
|
||||||
config SERIAL_SIRFSOC_CONSOLE
|
config SERIAL_SIRFSOC_CONSOLE
|
||||||
bool "Support for console on SiRF SoC serial port"
|
bool "Support for console on SiRF SoC serial port"
|
||||||
depends on SERIAL_SIRFSOC=y
|
depends on SERIAL_SIRFSOC=y
|
||||||
select SERIAL_CORE_CONSOLE
|
select SERIAL_CORE_CONSOLE
|
||||||
help
|
help
|
||||||
Even if you say Y here, the currently visible virtual console
|
Even if you say Y here, the currently visible virtual console
|
||||||
(/dev/tty0) will still be used as the system console by default, but
|
(/dev/tty0) will still be used as the system console by default, but
|
||||||
you can alter that using a kernel command line option such as
|
you can alter that using a kernel command line option such as
|
||||||
"console=ttySiRFx". (Try "man bootparam" or see the documentation of
|
"console=ttySiRFx". (Try "man bootparam" or see the documentation of
|
||||||
your boot loader about how to pass options to the kernel at
|
your boot loader about how to pass options to the kernel at
|
||||||
boot time.)
|
boot time.)
|
||||||
|
|
||||||
config SERIAL_TEGRA
|
config SERIAL_TEGRA
|
||||||
tristate "NVIDIA Tegra20/30 SoC serial controller"
|
tristate "NVIDIA Tegra20/30 SoC serial controller"
|
||||||
|
@ -1078,41 +1078,41 @@ config SERIAL_SCCNXP_CONSOLE
|
||||||
Support for console on SCCNXP serial ports.
|
Support for console on SCCNXP serial ports.
|
||||||
|
|
||||||
config SERIAL_SC16IS7XX_CORE
|
config SERIAL_SC16IS7XX_CORE
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
config SERIAL_SC16IS7XX
|
config SERIAL_SC16IS7XX
|
||||||
tristate "SC16IS7xx serial support"
|
tristate "SC16IS7xx serial support"
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
depends on (SPI_MASTER && !I2C) || I2C
|
depends on (SPI_MASTER && !I2C) || I2C
|
||||||
help
|
help
|
||||||
This selects support for SC16IS7xx serial ports.
|
This selects support for SC16IS7xx serial ports.
|
||||||
Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752,
|
Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752,
|
||||||
SC16IS760 and SC16IS762. Select supported buses using options below.
|
SC16IS760 and SC16IS762. Select supported buses using options below.
|
||||||
|
|
||||||
config SERIAL_SC16IS7XX_I2C
|
config SERIAL_SC16IS7XX_I2C
|
||||||
bool "SC16IS7xx for I2C interface"
|
bool "SC16IS7xx for I2C interface"
|
||||||
depends on SERIAL_SC16IS7XX
|
depends on SERIAL_SC16IS7XX
|
||||||
depends on I2C
|
depends on I2C
|
||||||
select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX
|
select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX
|
||||||
select REGMAP_I2C if I2C
|
select REGMAP_I2C if I2C
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Enable SC16IS7xx driver on I2C bus,
|
Enable SC16IS7xx driver on I2C bus,
|
||||||
If required say y, and say n to i2c if not required,
|
If required say y, and say n to i2c if not required,
|
||||||
Enabled by default to support oldconfig.
|
Enabled by default to support oldconfig.
|
||||||
You must select at least one bus for the driver to be built.
|
You must select at least one bus for the driver to be built.
|
||||||
|
|
||||||
config SERIAL_SC16IS7XX_SPI
|
config SERIAL_SC16IS7XX_SPI
|
||||||
bool "SC16IS7xx for spi interface"
|
bool "SC16IS7xx for spi interface"
|
||||||
depends on SERIAL_SC16IS7XX
|
depends on SERIAL_SC16IS7XX
|
||||||
depends on SPI_MASTER
|
depends on SPI_MASTER
|
||||||
select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX
|
select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX
|
||||||
select REGMAP_SPI if SPI_MASTER
|
select REGMAP_SPI if SPI_MASTER
|
||||||
help
|
help
|
||||||
Enable SC16IS7xx driver on SPI bus,
|
Enable SC16IS7xx driver on SPI bus,
|
||||||
If required say y, and say n to spi if not required,
|
If required say y, and say n to spi if not required,
|
||||||
This is additional support to exsisting driver.
|
This is additional support to exsisting driver.
|
||||||
You must select at least one bus for the driver to be built.
|
You must select at least one bus for the driver to be built.
|
||||||
|
|
||||||
config SERIAL_TIMBERDALE
|
config SERIAL_TIMBERDALE
|
||||||
tristate "Support for timberdale UART"
|
tristate "Support for timberdale UART"
|
||||||
|
@ -1212,7 +1212,7 @@ config SERIAL_ALTERA_UART_CONSOLE
|
||||||
Enable a Altera UART port to be the system console.
|
Enable a Altera UART port to be the system console.
|
||||||
|
|
||||||
config SERIAL_IFX6X60
|
config SERIAL_IFX6X60
|
||||||
tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
|
tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
|
||||||
depends on GPIOLIB || COMPILE_TEST
|
depends on GPIOLIB || COMPILE_TEST
|
||||||
depends on SPI && HAS_DMA
|
depends on SPI && HAS_DMA
|
||||||
help
|
help
|
||||||
|
@ -1392,19 +1392,19 @@ config SERIAL_FSL_LPUART_CONSOLE
|
||||||
you can make it the console by answering Y to this option.
|
you can make it the console by answering Y to this option.
|
||||||
|
|
||||||
config SERIAL_FSL_LINFLEXUART
|
config SERIAL_FSL_LINFLEXUART
|
||||||
tristate "Freescale linflexuart serial port support"
|
tristate "Freescale LINFlexD UART serial port support"
|
||||||
depends on PRINTK
|
depends on PRINTK
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
help
|
help
|
||||||
Support for the on-chip linflexuart on some Freescale SOCs.
|
Support for the on-chip LINFlexD UART on some Freescale SOCs.
|
||||||
|
|
||||||
config SERIAL_FSL_LINFLEXUART_CONSOLE
|
config SERIAL_FSL_LINFLEXUART_CONSOLE
|
||||||
bool "Console on Freescale linflexuart serial port"
|
bool "Console on Freescale LINFlexD UART serial port"
|
||||||
depends on SERIAL_FSL_LINFLEXUART=y
|
depends on SERIAL_FSL_LINFLEXUART=y
|
||||||
select SERIAL_CORE_CONSOLE
|
select SERIAL_CORE_CONSOLE
|
||||||
select SERIAL_EARLYCON
|
select SERIAL_EARLYCON
|
||||||
help
|
help
|
||||||
If you have enabled the linflexuart serial port on the Freescale
|
If you have enabled the LINFlexD UART serial port on the Freescale
|
||||||
SoCs, you can make it the console by answering Y to this option.
|
SoCs, you can make it the console by answering Y to this option.
|
||||||
|
|
||||||
config SERIAL_CONEXANT_DIGICOLOR
|
config SERIAL_CONEXANT_DIGICOLOR
|
||||||
|
|
|
@ -30,7 +30,7 @@ obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
|
||||||
obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
|
obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
|
||||||
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
|
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
|
||||||
obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
|
obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
|
||||||
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
|
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung_tty.o
|
||||||
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
|
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
|
||||||
obj-$(CONFIG_SERIAL_MAX310X) += max310x.o
|
obj-$(CONFIG_SERIAL_MAX310X) += max310x.o
|
||||||
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
|
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
|
||||||
|
|
|
@ -414,7 +414,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
|
||||||
dma_cap_mask_t mask;
|
dma_cap_mask_t mask;
|
||||||
|
|
||||||
uap->dma_probed = true;
|
uap->dma_probed = true;
|
||||||
chan = dma_request_slave_channel_reason(dev, "tx");
|
chan = dma_request_chan(dev, "tx");
|
||||||
if (IS_ERR(chan)) {
|
if (IS_ERR(chan)) {
|
||||||
if (PTR_ERR(chan) == -EPROBE_DEFER) {
|
if (PTR_ERR(chan) == -EPROBE_DEFER) {
|
||||||
uap->dma_probed = false;
|
uap->dma_probed = false;
|
||||||
|
@ -813,10 +813,8 @@ __acquires(&uap->port.lock)
|
||||||
if (!uap->using_tx_dma)
|
if (!uap->using_tx_dma)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Avoid deadlock with the DMA engine callback */
|
dmaengine_terminate_async(uap->dmatx.chan);
|
||||||
spin_unlock(&uap->port.lock);
|
|
||||||
dmaengine_terminate_all(uap->dmatx.chan);
|
|
||||||
spin_lock(&uap->port.lock);
|
|
||||||
if (uap->dmatx.queued) {
|
if (uap->dmatx.queued) {
|
||||||
dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
|
dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
|
@ -1236,10 +1234,6 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* Blank functions if the DMA engine is not available */
|
/* Blank functions if the DMA engine is not available */
|
||||||
static inline void pl011_dma_probe(struct uart_amba_port *uap)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void pl011_dma_remove(struct uart_amba_port *uap)
|
static inline void pl011_dma_remove(struct uart_amba_port *uap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* Freescale linflexuart serial port driver
|
* Freescale LINFlexD UART serial port driver
|
||||||
*
|
*
|
||||||
* Copyright 2012-2016 Freescale Semiconductor, Inc.
|
* Copyright 2012-2016 Freescale Semiconductor, Inc.
|
||||||
* Copyright 2017-2019 NXP
|
* Copyright 2017-2019 NXP
|
||||||
|
@ -940,5 +940,5 @@ static void __exit linflex_serial_exit(void)
|
||||||
module_init(linflex_serial_init);
|
module_init(linflex_serial_init);
|
||||||
module_exit(linflex_serial_exit);
|
module_exit(linflex_serial_exit);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Freescale linflex serial port driver");
|
MODULE_DESCRIPTION("Freescale LINFlexD serial port driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
|
@ -437,8 +437,8 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
|
||||||
}
|
}
|
||||||
|
|
||||||
sport->dma_tx_desc = dmaengine_prep_slave_sg(sport->dma_tx_chan, sgl,
|
sport->dma_tx_desc = dmaengine_prep_slave_sg(sport->dma_tx_chan, sgl,
|
||||||
sport->dma_tx_nents,
|
ret, DMA_MEM_TO_DEV,
|
||||||
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
|
DMA_PREP_INTERRUPT);
|
||||||
if (!sport->dma_tx_desc) {
|
if (!sport->dma_tx_desc) {
|
||||||
dma_unmap_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
|
dma_unmap_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
|
||||||
dev_err(dev, "Cannot prepare TX slave DMA!\n");
|
dev_err(dev, "Cannot prepare TX slave DMA!\n");
|
||||||
|
@ -1280,6 +1280,57 @@ static int lpuart_config_rs485(struct uart_port *port,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lpuart32_config_rs485(struct uart_port *port,
|
||||||
|
struct serial_rs485 *rs485)
|
||||||
|
{
|
||||||
|
struct lpuart_port *sport = container_of(port,
|
||||||
|
struct lpuart_port, port);
|
||||||
|
|
||||||
|
unsigned long modem = lpuart32_read(&sport->port, UARTMODIR)
|
||||||
|
& ~(UARTMODEM_TXRTSPOL | UARTMODEM_TXRTSE);
|
||||||
|
lpuart32_write(&sport->port, modem, UARTMODIR);
|
||||||
|
|
||||||
|
/* clear unsupported configurations */
|
||||||
|
rs485->delay_rts_before_send = 0;
|
||||||
|
rs485->delay_rts_after_send = 0;
|
||||||
|
rs485->flags &= ~SER_RS485_RX_DURING_TX;
|
||||||
|
|
||||||
|
if (rs485->flags & SER_RS485_ENABLED) {
|
||||||
|
/* Enable auto RS-485 RTS mode */
|
||||||
|
modem |= UARTMODEM_TXRTSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RTS needs to be logic HIGH either during transer _or_ after
|
||||||
|
* transfer, other variants are not supported by the hardware.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
|
||||||
|
SER_RS485_RTS_AFTER_SEND)))
|
||||||
|
rs485->flags |= SER_RS485_RTS_ON_SEND;
|
||||||
|
|
||||||
|
if (rs485->flags & SER_RS485_RTS_ON_SEND &&
|
||||||
|
rs485->flags & SER_RS485_RTS_AFTER_SEND)
|
||||||
|
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The hardware defaults to RTS logic HIGH while transfer.
|
||||||
|
* Switch polarity in case RTS shall be logic HIGH
|
||||||
|
* after transfer.
|
||||||
|
* Note: UART is assumed to be active high.
|
||||||
|
*/
|
||||||
|
if (rs485->flags & SER_RS485_RTS_ON_SEND)
|
||||||
|
modem &= ~UARTMODEM_TXRTSPOL;
|
||||||
|
else if (rs485->flags & SER_RS485_RTS_AFTER_SEND)
|
||||||
|
modem |= UARTMODEM_TXRTSPOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the new configuration */
|
||||||
|
sport->port.rs485 = *rs485;
|
||||||
|
|
||||||
|
lpuart32_write(&sport->port, modem, UARTMODIR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int lpuart_get_mctrl(struct uart_port *port)
|
static unsigned int lpuart_get_mctrl(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned int temp = 0;
|
unsigned int temp = 0;
|
||||||
|
@ -1333,18 +1384,7 @@ static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
|
|
||||||
static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
{
|
{
|
||||||
unsigned long temp;
|
|
||||||
|
|
||||||
temp = lpuart32_read(port, UARTMODIR) &
|
|
||||||
~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
|
||||||
|
|
||||||
if (mctrl & TIOCM_RTS)
|
|
||||||
temp |= UARTMODIR_RXRTSE;
|
|
||||||
|
|
||||||
if (mctrl & TIOCM_CTS)
|
|
||||||
temp |= UARTMODIR_TXCTSE;
|
|
||||||
|
|
||||||
lpuart32_write(port, temp, UARTMODIR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lpuart_break_ctl(struct uart_port *port, int break_state)
|
static void lpuart_break_ctl(struct uart_port *port, int break_state)
|
||||||
|
@ -1889,11 +1929,18 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
ctrl |= UARTCTRL_M;
|
ctrl |= UARTCTRL_M;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When auto RS-485 RTS mode is enabled,
|
||||||
|
* hardware flow control need to be disabled.
|
||||||
|
*/
|
||||||
|
if (sport->port.rs485.flags & SER_RS485_ENABLED)
|
||||||
|
termios->c_cflag &= ~CRTSCTS;
|
||||||
|
|
||||||
if (termios->c_cflag & CRTSCTS) {
|
if (termios->c_cflag & CRTSCTS) {
|
||||||
modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE;
|
modem |= (UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
||||||
} else {
|
} else {
|
||||||
termios->c_cflag &= ~CRTSCTS;
|
termios->c_cflag &= ~CRTSCTS;
|
||||||
modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
|
modem &= ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (termios->c_cflag & CSTOPB)
|
if (termios->c_cflag & CSTOPB)
|
||||||
|
@ -2416,7 +2463,10 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||||
sport->port.ops = &lpuart_pops;
|
sport->port.ops = &lpuart_pops;
|
||||||
sport->port.flags = UPF_BOOT_AUTOCONF;
|
sport->port.flags = UPF_BOOT_AUTOCONF;
|
||||||
|
|
||||||
sport->port.rs485_config = lpuart_config_rs485;
|
if (lpuart_is_32(sport))
|
||||||
|
sport->port.rs485_config = lpuart32_config_rs485;
|
||||||
|
else
|
||||||
|
sport->port.rs485_config = lpuart_config_rs485;
|
||||||
|
|
||||||
sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
|
sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
|
||||||
if (IS_ERR(sport->ipg_clk)) {
|
if (IS_ERR(sport->ipg_clk)) {
|
||||||
|
@ -2470,7 +2520,7 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||||
sport->port.rs485.delay_rts_after_send)
|
sport->port.rs485.delay_rts_after_send)
|
||||||
dev_err(&pdev->dev, "driver doesn't support RTS delays\n");
|
dev_err(&pdev->dev, "driver doesn't support RTS delays\n");
|
||||||
|
|
||||||
lpuart_config_rs485(&sport->port, &sport->port.rs485);
|
sport->port.rs485_config(&sport->port, &sport->port.rs485);
|
||||||
|
|
||||||
sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
|
sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
|
||||||
if (!sport->dma_tx_chan)
|
if (!sport->dma_tx_chan)
|
||||||
|
|
|
@ -1230,6 +1230,9 @@ static int ifx_spi_spi_remove(struct spi_device *spi)
|
||||||
struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
|
struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
|
||||||
/* stop activity */
|
/* stop activity */
|
||||||
tasklet_kill(&ifx_dev->io_work_tasklet);
|
tasklet_kill(&ifx_dev->io_work_tasklet);
|
||||||
|
|
||||||
|
pm_runtime_disable(&spi->dev);
|
||||||
|
|
||||||
/* free irq */
|
/* free irq */
|
||||||
free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev);
|
free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev);
|
||||||
free_irq(gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev);
|
free_irq(gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev);
|
||||||
|
|
|
@ -619,7 +619,7 @@ static void imx_uart_dma_tx(struct imx_port *sport)
|
||||||
dev_err(dev, "DMA mapping error for TX.\n");
|
dev_err(dev, "DMA mapping error for TX.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents,
|
desc = dmaengine_prep_slave_sg(chan, sgl, ret,
|
||||||
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
|
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
dma_unmap_sg(dev, sgl, sport->dma_tx_nents,
|
dma_unmap_sg(dev, sgl, sport->dma_tx_nents,
|
||||||
|
@ -1034,8 +1034,6 @@ static void imx_uart_timeout(struct timer_list *t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RX_BUF_SIZE (PAGE_SIZE)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are two kinds of RX DMA interrupts(such as in the MX6Q):
|
* There are two kinds of RX DMA interrupts(such as in the MX6Q):
|
||||||
* [1] the RX DMA buffer is full.
|
* [1] the RX DMA buffer is full.
|
||||||
|
@ -1118,7 +1116,8 @@ static void imx_uart_dma_rx_callback(void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RX DMA buffer periods */
|
/* RX DMA buffer periods */
|
||||||
#define RX_DMA_PERIODS 4
|
#define RX_DMA_PERIODS 16
|
||||||
|
#define RX_BUF_SIZE (RX_DMA_PERIODS * PAGE_SIZE / 4)
|
||||||
|
|
||||||
static int imx_uart_start_rx_dma(struct imx_port *sport)
|
static int imx_uart_start_rx_dma(struct imx_port *sport)
|
||||||
{
|
{
|
||||||
|
|
|
@ -301,7 +301,7 @@ static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base)
|
||||||
dma = &msm_port->tx_dma;
|
dma = &msm_port->tx_dma;
|
||||||
|
|
||||||
/* allocate DMA resources, if available */
|
/* allocate DMA resources, if available */
|
||||||
dma->chan = dma_request_slave_channel_reason(dev, "tx");
|
dma->chan = dma_request_chan(dev, "tx");
|
||||||
if (IS_ERR(dma->chan))
|
if (IS_ERR(dma->chan))
|
||||||
goto no_tx;
|
goto no_tx;
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
|
||||||
dma = &msm_port->rx_dma;
|
dma = &msm_port->rx_dma;
|
||||||
|
|
||||||
/* allocate DMA resources, if available */
|
/* allocate DMA resources, if available */
|
||||||
dma->chan = dma_request_slave_channel_reason(dev, "rx");
|
dma->chan = dma_request_chan(dev, "rx");
|
||||||
if (IS_ERR(dma->chan))
|
if (IS_ERR(dma->chan))
|
||||||
goto no_rx;
|
goto no_rx;
|
||||||
|
|
||||||
|
@ -980,6 +980,7 @@ static unsigned int msm_get_mctrl(struct uart_port *port)
|
||||||
static void msm_reset(struct uart_port *port)
|
static void msm_reset(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct msm_port *msm_port = UART_TO_MSM(port);
|
struct msm_port *msm_port = UART_TO_MSM(port);
|
||||||
|
unsigned int mr;
|
||||||
|
|
||||||
/* reset everything */
|
/* reset everything */
|
||||||
msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
|
||||||
|
@ -987,7 +988,10 @@ static void msm_reset(struct uart_port *port)
|
||||||
msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
|
||||||
msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
|
||||||
msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
|
||||||
msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
|
msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR);
|
||||||
|
mr = msm_read(port, UART_MR1);
|
||||||
|
mr &= ~UART_MR1_RX_RDY_CTL;
|
||||||
|
msm_write(port, mr, UART_MR1);
|
||||||
|
|
||||||
/* Disable DM modes */
|
/* Disable DM modes */
|
||||||
if (msm_port->is_uartdm)
|
if (msm_port->is_uartdm)
|
||||||
|
|
|
@ -233,6 +233,7 @@ struct eg20t_port {
|
||||||
struct dma_chan *chan_rx;
|
struct dma_chan *chan_rx;
|
||||||
struct scatterlist *sg_tx_p;
|
struct scatterlist *sg_tx_p;
|
||||||
int nent;
|
int nent;
|
||||||
|
int orig_nent;
|
||||||
struct scatterlist sg_rx;
|
struct scatterlist sg_rx;
|
||||||
int tx_dma_use;
|
int tx_dma_use;
|
||||||
void *rx_buf_virt;
|
void *rx_buf_virt;
|
||||||
|
@ -787,9 +788,10 @@ static void pch_dma_tx_complete(void *arg)
|
||||||
}
|
}
|
||||||
xmit->tail &= UART_XMIT_SIZE - 1;
|
xmit->tail &= UART_XMIT_SIZE - 1;
|
||||||
async_tx_ack(priv->desc_tx);
|
async_tx_ack(priv->desc_tx);
|
||||||
dma_unmap_sg(port->dev, sg, priv->nent, DMA_TO_DEVICE);
|
dma_unmap_sg(port->dev, sg, priv->orig_nent, DMA_TO_DEVICE);
|
||||||
priv->tx_dma_use = 0;
|
priv->tx_dma_use = 0;
|
||||||
priv->nent = 0;
|
priv->nent = 0;
|
||||||
|
priv->orig_nent = 0;
|
||||||
kfree(priv->sg_tx_p);
|
kfree(priv->sg_tx_p);
|
||||||
pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
|
pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
|
||||||
}
|
}
|
||||||
|
@ -1010,6 +1012,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
|
||||||
dev_err(priv->port.dev, "%s:dma_map_sg Failed\n", __func__);
|
dev_err(priv->port.dev, "%s:dma_map_sg Failed\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
priv->orig_nent = num;
|
||||||
priv->nent = nent;
|
priv->nent = nent;
|
||||||
|
|
||||||
for (i = 0; i < nent; i++, sg++) {
|
for (i = 0; i < nent; i++, sg++) {
|
||||||
|
|
|
@ -9,10 +9,12 @@
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_wakeirq.h>
|
||||||
#include <linux/qcom-geni-se.h>
|
#include <linux/qcom-geni-se.h>
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
@ -115,6 +117,7 @@ struct qcom_geni_serial_port {
|
||||||
bool brk;
|
bool brk;
|
||||||
|
|
||||||
unsigned int tx_remaining;
|
unsigned int tx_remaining;
|
||||||
|
int wakeup_irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct uart_ops qcom_geni_console_pops;
|
static const struct uart_ops qcom_geni_console_pops;
|
||||||
|
@ -754,6 +757,15 @@ out_write_wakeup:
|
||||||
uart_write_wakeup(uport);
|
uart_write_wakeup(uport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static irqreturn_t qcom_geni_serial_wakeup_isr(int isr, void *dev)
|
||||||
|
{
|
||||||
|
struct uart_port *uport = dev;
|
||||||
|
|
||||||
|
pm_wakeup_event(uport->dev, 2000);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
|
static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
|
||||||
{
|
{
|
||||||
u32 m_irq_en;
|
u32 m_irq_en;
|
||||||
|
@ -830,7 +842,7 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)
|
||||||
if (uart_console(uport))
|
if (uart_console(uport))
|
||||||
console_stop(uport->cons);
|
console_stop(uport->cons);
|
||||||
|
|
||||||
free_irq(uport->irq, uport);
|
disable_irq(uport->irq);
|
||||||
spin_lock_irqsave(&uport->lock, flags);
|
spin_lock_irqsave(&uport->lock, flags);
|
||||||
qcom_geni_serial_stop_tx(uport);
|
qcom_geni_serial_stop_tx(uport);
|
||||||
qcom_geni_serial_stop_rx(uport);
|
qcom_geni_serial_stop_rx(uport);
|
||||||
|
@ -890,21 +902,14 @@ static int qcom_geni_serial_startup(struct uart_port *uport)
|
||||||
int ret;
|
int ret;
|
||||||
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
|
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
|
||||||
|
|
||||||
scnprintf(port->name, sizeof(port->name),
|
|
||||||
"qcom_serial_%s%d",
|
|
||||||
(uart_console(uport) ? "console" : "uart"), uport->line);
|
|
||||||
|
|
||||||
if (!port->setup) {
|
if (!port->setup) {
|
||||||
ret = qcom_geni_serial_port_setup(uport);
|
ret = qcom_geni_serial_port_setup(uport);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
enable_irq(uport->irq);
|
||||||
|
|
||||||
ret = request_irq(uport->irq, qcom_geni_serial_isr, IRQF_TRIGGER_HIGH,
|
return 0;
|
||||||
port->name, uport);
|
|
||||||
if (ret)
|
|
||||||
dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long get_clk_cfg(unsigned long clk_freq)
|
static unsigned long get_clk_cfg(unsigned long clk_freq)
|
||||||
|
@ -1297,11 +1302,44 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
|
||||||
port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
|
port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
|
||||||
port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
|
port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
|
||||||
|
|
||||||
|
scnprintf(port->name, sizeof(port->name), "qcom_geni_serial_%s%d",
|
||||||
|
(uart_console(uport) ? "console" : "uart"), uport->line);
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
return irq;
|
return irq;
|
||||||
uport->irq = irq;
|
uport->irq = irq;
|
||||||
|
|
||||||
|
irq_set_status_flags(uport->irq, IRQ_NOAUTOEN);
|
||||||
|
ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr,
|
||||||
|
IRQF_TRIGGER_HIGH, port->name, uport);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!console) {
|
||||||
|
port->wakeup_irq = platform_get_irq(pdev, 1);
|
||||||
|
if (port->wakeup_irq < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to get wakeup IRQ %d\n",
|
||||||
|
port->wakeup_irq);
|
||||||
|
} else {
|
||||||
|
irq_set_status_flags(port->wakeup_irq, IRQ_NOAUTOEN);
|
||||||
|
ret = devm_request_irq(uport->dev, port->wakeup_irq,
|
||||||
|
qcom_geni_serial_wakeup_isr,
|
||||||
|
IRQF_TRIGGER_FALLING, "uart_wakeup", uport);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(uport->dev, "Failed to register wakeup IRQ ret %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_init_wakeup(&pdev->dev, true);
|
||||||
|
ret = dev_pm_set_wake_irq(&pdev->dev, port->wakeup_irq);
|
||||||
|
if (unlikely(ret))
|
||||||
|
dev_err(uport->dev, "%s:Failed to set IRQ wake:%d\n",
|
||||||
|
__func__, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
uport->private_data = drv;
|
uport->private_data = drv;
|
||||||
platform_set_drvdata(pdev, port);
|
platform_set_drvdata(pdev, port);
|
||||||
port->handle_rx = console ? handle_rx_console : handle_rx_uart;
|
port->handle_rx = console ? handle_rx_console : handle_rx_uart;
|
||||||
|
@ -1324,7 +1362,12 @@ static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev)
|
||||||
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
|
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
|
||||||
struct uart_port *uport = &port->uport;
|
struct uart_port *uport = &port->uport;
|
||||||
|
|
||||||
return uart_suspend_port(uport->private_data, uport);
|
uart_suspend_port(uport->private_data, uport);
|
||||||
|
|
||||||
|
if (port->wakeup_irq > 0)
|
||||||
|
enable_irq(port->wakeup_irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
|
static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
|
||||||
|
@ -1332,6 +1375,9 @@ static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
|
||||||
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
|
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
|
||||||
struct uart_port *uport = &port->uport;
|
struct uart_port *uport = &port->uport;
|
||||||
|
|
||||||
|
if (port->wakeup_irq > 0)
|
||||||
|
disable_irq(port->wakeup_irq);
|
||||||
|
|
||||||
return uart_resume_port(uport->private_data, uport);
|
return uart_resume_port(uport->private_data, uport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1122,8 +1122,7 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
|
||||||
int ret;
|
int ret;
|
||||||
struct dma_slave_config dma_sconfig;
|
struct dma_slave_config dma_sconfig;
|
||||||
|
|
||||||
dma_chan = dma_request_slave_channel_reason(tup->uport.dev,
|
dma_chan = dma_request_chan(tup->uport.dev, dma_to_memory ? "rx" : "tx");
|
||||||
dma_to_memory ? "rx" : "tx");
|
|
||||||
if (IS_ERR(dma_chan)) {
|
if (IS_ERR(dma_chan)) {
|
||||||
ret = PTR_ERR(dma_chan);
|
ret = PTR_ERR(dma_chan);
|
||||||
dev_err(tup->uport.dev,
|
dev_err(tup->uport.dev,
|
||||||
|
|
|
@ -1111,7 +1111,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state)
|
||||||
if (!uport)
|
if (!uport)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (uport->type != PORT_UNKNOWN)
|
if (uport->type != PORT_UNKNOWN && uport->ops->break_ctl)
|
||||||
uport->ops->break_ctl(uport, break_state);
|
uport->ops->break_ctl(uport, break_state);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -120,7 +120,8 @@ static u32 uart_usp_ff_empty_mask(struct uart_port *port)
|
||||||
empty_bit = ilog2(port->fifosize) + 1;
|
empty_bit = ilog2(port->fifosize) + 1;
|
||||||
return (1 << empty_bit);
|
return (1 << empty_bit);
|
||||||
}
|
}
|
||||||
struct sirfsoc_uart_register sirfsoc_usp = {
|
|
||||||
|
static struct sirfsoc_uart_register sirfsoc_usp = {
|
||||||
.uart_reg = {
|
.uart_reg = {
|
||||||
.sirfsoc_mode1 = 0x0000,
|
.sirfsoc_mode1 = 0x0000,
|
||||||
.sirfsoc_mode2 = 0x0004,
|
.sirfsoc_mode2 = 0x0004,
|
||||||
|
@ -186,7 +187,7 @@ struct sirfsoc_uart_register sirfsoc_usp = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sirfsoc_uart_register sirfsoc_uart = {
|
static struct sirfsoc_uart_register sirfsoc_uart = {
|
||||||
.uart_reg = {
|
.uart_reg = {
|
||||||
.sirfsoc_line_ctrl = 0x0040,
|
.sirfsoc_line_ctrl = 0x0040,
|
||||||
.sirfsoc_tx_rx_en = 0x004c,
|
.sirfsoc_tx_rx_en = 0x004c,
|
||||||
|
|
|
@ -919,6 +919,34 @@ static void sprd_pm(struct uart_port *port, unsigned int state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
static int sprd_poll_init(struct uart_port *port)
|
||||||
|
{
|
||||||
|
if (port->state->pm_state != UART_PM_STATE_ON) {
|
||||||
|
sprd_pm(port, UART_PM_STATE_ON, 0);
|
||||||
|
port->state->pm_state = UART_PM_STATE_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sprd_poll_get_char(struct uart_port *port)
|
||||||
|
{
|
||||||
|
while (!(serial_in(port, SPRD_STS1) & SPRD_RX_FIFO_CNT_MASK))
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
return serial_in(port, SPRD_RXD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sprd_poll_put_char(struct uart_port *port, unsigned char ch)
|
||||||
|
{
|
||||||
|
while (serial_in(port, SPRD_STS1) & SPRD_TX_FIFO_CNT_MASK)
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
serial_out(port, SPRD_TXD, ch);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct uart_ops serial_sprd_ops = {
|
static const struct uart_ops serial_sprd_ops = {
|
||||||
.tx_empty = sprd_tx_empty,
|
.tx_empty = sprd_tx_empty,
|
||||||
.get_mctrl = sprd_get_mctrl,
|
.get_mctrl = sprd_get_mctrl,
|
||||||
|
@ -936,6 +964,11 @@ static const struct uart_ops serial_sprd_ops = {
|
||||||
.config_port = sprd_config_port,
|
.config_port = sprd_config_port,
|
||||||
.verify_port = sprd_verify_port,
|
.verify_port = sprd_verify_port,
|
||||||
.pm = sprd_pm,
|
.pm = sprd_pm,
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
.poll_init = sprd_poll_init,
|
||||||
|
.poll_get_char = sprd_poll_get_char,
|
||||||
|
.poll_put_char = sprd_poll_put_char,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_SPRD_CONSOLE
|
#ifdef CONFIG_SERIAL_SPRD_CONSOLE
|
||||||
|
|
|
@ -240,8 +240,8 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded)
|
||||||
* cleared by the sequence [read SR - read DR].
|
* cleared by the sequence [read SR - read DR].
|
||||||
*/
|
*/
|
||||||
if ((sr & USART_SR_ERR_MASK) && ofs->icr != UNDEF_REG)
|
if ((sr & USART_SR_ERR_MASK) && ofs->icr != UNDEF_REG)
|
||||||
stm32_clr_bits(port, ofs->icr, USART_ICR_ORECF |
|
writel_relaxed(sr & USART_SR_ERR_MASK,
|
||||||
USART_ICR_PECF | USART_ICR_FECF);
|
port->membase + ofs->icr);
|
||||||
|
|
||||||
c = stm32_get_char(port, &sr, &stm32_port->last_res);
|
c = stm32_get_char(port, &sr, &stm32_port->last_res);
|
||||||
port->icount.rx++;
|
port->icount.rx++;
|
||||||
|
@ -435,7 +435,7 @@ static void stm32_transmit_chars(struct uart_port *port)
|
||||||
if (ofs->icr == UNDEF_REG)
|
if (ofs->icr == UNDEF_REG)
|
||||||
stm32_clr_bits(port, ofs->isr, USART_SR_TC);
|
stm32_clr_bits(port, ofs->isr, USART_SR_TC);
|
||||||
else
|
else
|
||||||
stm32_set_bits(port, ofs->icr, USART_ICR_TCCF);
|
writel_relaxed(USART_ICR_TCCF, port->membase + ofs->icr);
|
||||||
|
|
||||||
if (stm32_port->tx_ch)
|
if (stm32_port->tx_ch)
|
||||||
stm32_transmit_chars_dma(port);
|
stm32_transmit_chars_dma(port);
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/pm_runtime.h>
|
|
||||||
|
|
||||||
#define ULITE_NAME "ttyUL"
|
#define ULITE_NAME "ttyUL"
|
||||||
#define ULITE_MAJOR 204
|
#define ULITE_MAJOR 204
|
||||||
|
@ -55,7 +54,6 @@
|
||||||
#define ULITE_CONTROL_RST_TX 0x01
|
#define ULITE_CONTROL_RST_TX 0x01
|
||||||
#define ULITE_CONTROL_RST_RX 0x02
|
#define ULITE_CONTROL_RST_RX 0x02
|
||||||
#define ULITE_CONTROL_IE 0x10
|
#define ULITE_CONTROL_IE 0x10
|
||||||
#define UART_AUTOSUSPEND_TIMEOUT 3000
|
|
||||||
|
|
||||||
/* Static pointer to console port */
|
/* Static pointer to console port */
|
||||||
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
|
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
|
||||||
|
@ -65,7 +63,6 @@ static struct uart_port *console_port;
|
||||||
struct uartlite_data {
|
struct uartlite_data {
|
||||||
const struct uartlite_reg_ops *reg_ops;
|
const struct uartlite_reg_ops *reg_ops;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct uart_driver *ulite_uart_driver;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uartlite_reg_ops {
|
struct uartlite_reg_ops {
|
||||||
|
@ -393,12 +390,12 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||||
static void ulite_pm(struct uart_port *port, unsigned int state,
|
static void ulite_pm(struct uart_port *port, unsigned int state,
|
||||||
unsigned int oldstate)
|
unsigned int oldstate)
|
||||||
{
|
{
|
||||||
if (!state) {
|
struct uartlite_data *pdata = port->private_data;
|
||||||
pm_runtime_get_sync(port->dev);
|
|
||||||
} else {
|
if (!state)
|
||||||
pm_runtime_mark_last_busy(port->dev);
|
clk_enable(pdata->clk);
|
||||||
pm_runtime_put_autosuspend(port->dev);
|
else
|
||||||
}
|
clk_disable(pdata->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
@ -697,9 +694,7 @@ static int ulite_release(struct device *dev)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (port) {
|
if (port) {
|
||||||
struct uartlite_data *pdata = port->private_data;
|
rc = uart_remove_one_port(&ulite_uart_driver, port);
|
||||||
|
|
||||||
rc = uart_remove_one_port(pdata->ulite_uart_driver, port);
|
|
||||||
dev_set_drvdata(dev, NULL);
|
dev_set_drvdata(dev, NULL);
|
||||||
port->mapbase = 0;
|
port->mapbase = 0;
|
||||||
}
|
}
|
||||||
|
@ -717,11 +712,8 @@ static int __maybe_unused ulite_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct uart_port *port = dev_get_drvdata(dev);
|
struct uart_port *port = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (port) {
|
if (port)
|
||||||
struct uartlite_data *pdata = port->private_data;
|
uart_suspend_port(&ulite_uart_driver, port);
|
||||||
|
|
||||||
uart_suspend_port(pdata->ulite_uart_driver, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -736,41 +728,17 @@ static int __maybe_unused ulite_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct uart_port *port = dev_get_drvdata(dev);
|
struct uart_port *port = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (port) {
|
if (port)
|
||||||
struct uartlite_data *pdata = port->private_data;
|
uart_resume_port(&ulite_uart_driver, port);
|
||||||
|
|
||||||
uart_resume_port(pdata->ulite_uart_driver, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
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;
|
|
||||||
|
|
||||||
clk_enable(pdata->clk);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
* Platform bus binding
|
* Platform bus binding
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const struct dev_pm_ops ulite_pm_ops = {
|
static SIMPLE_DEV_PM_OPS(ulite_pm_ops, ulite_suspend, ulite_resume);
|
||||||
SET_SYSTEM_SLEEP_PM_OPS(ulite_suspend, ulite_resume)
|
|
||||||
SET_RUNTIME_PM_OPS(ulite_runtime_suspend,
|
|
||||||
ulite_runtime_resume, NULL)
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(CONFIG_OF)
|
#if defined(CONFIG_OF)
|
||||||
/* Match table for of_platform binding */
|
/* Match table for of_platform binding */
|
||||||
|
@ -795,22 +763,6 @@ static int ulite_probe(struct platform_device *pdev)
|
||||||
if (prop)
|
if (prop)
|
||||||
id = be32_to_cpup(prop);
|
id = be32_to_cpup(prop);
|
||||||
#endif
|
#endif
|
||||||
if (id < 0) {
|
|
||||||
/* Look for a serialN alias */
|
|
||||||
id = of_alias_get_id(pdev->dev.of_node, "serial");
|
|
||||||
if (id < 0)
|
|
||||||
id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data),
|
pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!pdata)
|
if (!pdata)
|
||||||
|
@ -836,22 +788,24 @@ static int ulite_probe(struct platform_device *pdev)
|
||||||
pdata->clk = NULL;
|
pdata->clk = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdata->ulite_uart_driver = &ulite_uart_driver;
|
|
||||||
ret = clk_prepare_enable(pdata->clk);
|
ret = clk_prepare_enable(pdata->clk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to prepare clock\n");
|
dev_err(&pdev->dev, "Failed to prepare clock\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_runtime_use_autosuspend(&pdev->dev);
|
if (!ulite_uart_driver.state) {
|
||||||
pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
|
dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
|
||||||
pm_runtime_set_active(&pdev->dev);
|
ret = uart_register_driver(&ulite_uart_driver);
|
||||||
pm_runtime_enable(&pdev->dev);
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to register driver\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
|
ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
|
||||||
|
|
||||||
pm_runtime_mark_last_busy(&pdev->dev);
|
clk_disable(pdata->clk);
|
||||||
pm_runtime_put_autosuspend(&pdev->dev);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -860,14 +814,9 @@ static int ulite_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct uart_port *port = dev_get_drvdata(&pdev->dev);
|
struct uart_port *port = dev_get_drvdata(&pdev->dev);
|
||||||
struct uartlite_data *pdata = port->private_data;
|
struct uartlite_data *pdata = port->private_data;
|
||||||
int rc;
|
|
||||||
|
|
||||||
clk_unprepare(pdata->clk);
|
clk_disable_unprepare(pdata->clk);
|
||||||
rc = ulite_release(&pdev->dev);
|
return 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 */
|
/* work with hotplug and coldplug */
|
||||||
|
|
|
@ -1345,9 +1345,12 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
|
||||||
if (!tty->port)
|
if (!tty->port)
|
||||||
tty->port = driver->ports[idx];
|
tty->port = driver->ports[idx];
|
||||||
|
|
||||||
WARN_RATELIMIT(!tty->port,
|
if (WARN_RATELIMIT(!tty->port,
|
||||||
"%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",
|
"%s: %s driver does not set tty->port. This would crash the kernel. Fix the driver!\n",
|
||||||
__func__, tty->driver->name);
|
__func__, tty->driver->name)) {
|
||||||
|
retval = -EINVAL;
|
||||||
|
goto err_release_lock;
|
||||||
|
}
|
||||||
|
|
||||||
retval = tty_ldisc_lock(tty, 5 * HZ);
|
retval = tty_ldisc_lock(tty, 5 * HZ);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -1925,7 +1928,6 @@ EXPORT_SYMBOL_GPL(tty_kopen);
|
||||||
/**
|
/**
|
||||||
* tty_open_by_driver - open a tty device
|
* tty_open_by_driver - open a tty device
|
||||||
* @device: dev_t of device to open
|
* @device: dev_t of device to open
|
||||||
* @inode: inode of device file
|
|
||||||
* @filp: file pointer to tty
|
* @filp: file pointer to tty
|
||||||
*
|
*
|
||||||
* Performs the driver lookup, checks for a reopen, or otherwise
|
* Performs the driver lookup, checks for a reopen, or otherwise
|
||||||
|
@ -1938,7 +1940,7 @@ EXPORT_SYMBOL_GPL(tty_kopen);
|
||||||
* - concurrent tty driver removal w/ lookup
|
* - concurrent tty driver removal w/ lookup
|
||||||
* - concurrent tty removal from driver table
|
* - concurrent tty removal from driver table
|
||||||
*/
|
*/
|
||||||
static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
|
static struct tty_struct *tty_open_by_driver(dev_t device,
|
||||||
struct file *filp)
|
struct file *filp)
|
||||||
{
|
{
|
||||||
struct tty_struct *tty;
|
struct tty_struct *tty;
|
||||||
|
@ -2030,7 +2032,7 @@ retry_open:
|
||||||
|
|
||||||
tty = tty_open_current_tty(device, filp);
|
tty = tty_open_current_tty(device, filp);
|
||||||
if (!tty)
|
if (!tty)
|
||||||
tty = tty_open_by_driver(device, inode, filp);
|
tty = tty_open_by_driver(device, filp);
|
||||||
|
|
||||||
if (IS_ERR(tty)) {
|
if (IS_ERR(tty)) {
|
||||||
tty_free_file(filp);
|
tty_free_file(filp);
|
||||||
|
|
|
@ -156,12 +156,7 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
|
||||||
* takes tty_ldiscs_lock to guard against ldisc races
|
* takes tty_ldiscs_lock to guard against ldisc races
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(CONFIG_LDISC_AUTOLOAD)
|
static int tty_ldisc_autoload = IS_BUILTIN(CONFIG_LDISC_AUTOLOAD);
|
||||||
#define INITIAL_AUTOLOAD_STATE 1
|
|
||||||
#else
|
|
||||||
#define INITIAL_AUTOLOAD_STATE 0
|
|
||||||
#endif
|
|
||||||
static int tty_ldisc_autoload = INITIAL_AUTOLOAD_STATE;
|
|
||||||
|
|
||||||
static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
|
static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1491,7 +1491,7 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
|
||||||
|
|
||||||
if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
|
if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
|
||||||
kbd_rawcode(value);
|
kbd_rawcode(value);
|
||||||
if (event_type == EV_KEY)
|
if (event_type == EV_KEY && event_code <= KEY_MAX)
|
||||||
kbd_keycode(event_code, value, HW_RAW(handle->dev));
|
kbd_keycode(event_code, value, HW_RAW(handle->dev));
|
||||||
|
|
||||||
spin_unlock(&kbd_event_lock);
|
spin_unlock(&kbd_event_lock);
|
||||||
|
|
|
@ -456,6 +456,9 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||||
size_t ret;
|
size_t ret;
|
||||||
char *con_buf;
|
char *con_buf;
|
||||||
|
|
||||||
|
if (use_unicode(inode))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
con_buf = (char *) __get_free_page(GFP_KERNEL);
|
con_buf = (char *) __get_free_page(GFP_KERNEL);
|
||||||
if (!con_buf)
|
if (!con_buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -290,7 +290,7 @@
|
||||||
/* Sunix UART */
|
/* Sunix UART */
|
||||||
#define PORT_SUNIX 121
|
#define PORT_SUNIX 121
|
||||||
|
|
||||||
/* Freescale Linflex UART */
|
/* Freescale LINFlexD UART */
|
||||||
#define PORT_LINFLEXUART 122
|
#define PORT_LINFLEXUART 122
|
||||||
|
|
||||||
#endif /* _UAPILINUX_SERIAL_CORE_H */
|
#endif /* _UAPILINUX_SERIAL_CORE_H */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче