TTY/Serial driver updates for 5.13-rc1

Here is the big set of tty and serial driver updates for 5.13-rc1.
 
 Actually busy this release, with a number of cleanups happening:
 	- much needed core tty cleanups by Jiri Slaby
 	- removal of unused and orphaned old-style serial drivers.  If
 	  anyone shows up with this hardware, it is trivial to restore
 	  these but we really do not think they are in use anymore.
 	- fixes and cleanups from Johan Hovold on a number of termios
 	  setting corner cases that loads of drivers got wrong as well
 	  as removing unneeded code due to tty core changes from long
 	  ago that were never propagated out to the drivers
 	- loads of platform-specific serial port driver updates and
 	  fixes
 	- coding style cleanups and other small fixes and updates all
 	  over the tty/serial tree.
 
 All of these have been in linux-next for a while now with no reported
 issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYIa3NQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ykMXgCfX3FZgKveI4l94ChXSy4OyKwycHUAn00BzrMC
 /7BwA1FnjQnC4zSzuHnm
 =bAas
 -----END PGP SIGNATURE-----

Merge tag 'tty-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty and serial driver updates from Greg KH:
 "Here is the big set of tty and serial driver updates for 5.13-rc1.

  Actually busy this release, with a number of cleanups happening:

   - much needed core tty cleanups by Jiri Slaby

   - removal of unused and orphaned old-style serial drivers. If anyone
     shows up with this hardware, it is trivial to restore these but we
     really do not think they are in use anymore.

   - fixes and cleanups from Johan Hovold on a number of termios setting
     corner cases that loads of drivers got wrong as well as removing
     unneeded code due to tty core changes from long ago that were never
     propagated out to the drivers

   - loads of platform-specific serial port driver updates and fixes

   - coding style cleanups and other small fixes and updates all over
     the tty/serial tree.

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

* tag 'tty-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (186 commits)
  serial: extend compile-test coverage
  serial: stm32: add FIFO threshold configuration
  dt-bindings: serial: 8250: update TX FIFO trigger level
  dt-bindings: serial: stm32: override FIFO threshold properties
  dt-bindings: serial: add RX and TX FIFO properties
  serial: xilinx_uartps: drop low-latency workaround
  serial: vt8500: drop low-latency workaround
  serial: timbuart: drop low-latency workaround
  serial: sunsu: drop low-latency workaround
  serial: sifive: drop low-latency workaround
  serial: txx9: drop low-latency workaround
  serial: sa1100: drop low-latency workaround
  serial: rp2: drop low-latency workaround
  serial: rda: drop low-latency workaround
  serial: owl: drop low-latency workaround
  serial: msm_serial: drop low-latency workaround
  serial: mpc52xx_uart: drop low-latency workaround
  serial: meson: drop low-latency workaround
  serial: mcf: drop low-latency workaround
  serial: lpc32xx_hs: drop low-latency workaround
  ...
This commit is contained in:
Linus Torvalds 2021-04-26 11:20:10 -07:00
commit d08410d8c9
139 changed files with 2734 additions and 12736 deletions

View File

@ -289,7 +289,7 @@
152 = /dev/kpoll Kernel Poll Driver
153 = /dev/mergemem Memory merge device
154 = /dev/pmu Macintosh PowerBook power manager
155 = /dev/isictl MultiTech ISICom serial control
155 =
156 = /dev/lcd Front panel LCD display
157 = /dev/ac Applicom Intl Profibus card
158 = /dev/nwbutton Netwinder external button
@ -477,11 +477,6 @@
18 block Sanyo CD-ROM
0 = /dev/sjcd Sanyo CD-ROM
19 char Cyclades serial card
0 = /dev/ttyC0 First Cyclades port
...
31 = /dev/ttyC31 32nd Cyclades port
19 block "Double" compressed disk
0 = /dev/double0 First compressed disk
...
@ -493,11 +488,6 @@
See the Double documentation for the meaning of the
mirror devices.
20 char Cyclades serial card - alternate devices
0 = /dev/cub0 Callout device for ttyC0
...
31 = /dev/cub31 Callout device for ttyC31
20 block Hitachi CD-ROM (under development)
0 = /dev/hitcd Hitachi CD-ROM

View File

@ -12,8 +12,13 @@ maintainers:
allOf:
- $ref: /schemas/serial.yaml#
- if:
required:
- aspeed,sirq-polarity-sense
anyOf:
- required:
- aspeed,lpc-io-reg
- required:
- aspeed,lpc-interrupts
- required:
- aspeed,sirq-polarity-sense
then:
properties:
compatible:
@ -55,6 +60,7 @@ properties:
- const: aspeed,ast2500-vuart
- const: intel,xscale-uart
- const: mrvl,pxa-uart
- const: nuvoton,wpcm450-uart
- const: nuvoton,npcm750-uart
- const: nvidia,tegra20-uart
- const: nxp,lpc3220-uart
@ -165,7 +171,6 @@ properties:
property.
tx-threshold:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Specify the TX FIFO low water indication for parts with programmable
TX FIFO thresholds.
@ -188,6 +193,21 @@ properties:
offset and bit number to identify how the SIRQ polarity should be
configured. One possible data source is the LPC/eSPI mode bit. Only
applicable to aspeed,ast2500-vuart.
deprecated: true
aspeed,lpc-io-reg:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: |
The VUART LPC address. Only applicable to aspeed,ast2500-vuart.
aspeed,lpc-interrupts:
$ref: "/schemas/types.yaml#/definitions/uint32-array"
minItems: 2
maxItems: 2
description: |
A 2-cell property describing the VUART SIRQ number and SIRQ
polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
applicable to aspeed,ast2500-vuart.
required:
- reg
@ -220,6 +240,7 @@ examples:
};
- |
#include <dt-bindings/clock/aspeed-clock.h>
#include <dt-bindings/interrupt-controller/irq.h>
serial@1e787000 {
compatible = "aspeed,ast2500-vuart";
reg = <0x1e787000 0x40>;
@ -227,7 +248,8 @@ examples:
interrupts = <8>;
clocks = <&syscon ASPEED_CLK_APB>;
no-loopback-test;
aspeed,sirq-polarity-sense = <&syscon 0x70 25>;
aspeed,lpc-io-reg = <0x3f8>;
aspeed,lpc-interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
};
...

View File

@ -0,0 +1,95 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/serial/brcm,bcm7271-uart.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom 8250 based serial port devicetree bindings
maintainers:
- Al Cooper <alcooperx@gmail.com>
allOf:
- $ref: /schemas/serial.yaml#
description: |+
The Broadcom UART is based on the basic 8250 UART but with
enhancements for more accurate high speed baud rates and support
for DMA.
properties:
compatible:
items:
- enum:
- brcm,bcm7271-uart
- brcm,bcm7278-uart
reg:
minItems: 1
maxItems: 5
reg-names:
description: The UART register block and optionally the DMA register blocks.
oneOf:
- items:
- const: uart
- items:
- const: uart
- const: dma_arb
- const: dma_rx
- const: dma_tx
- const: dma_intr2
clocks:
minItems: 1
clock-names:
const: sw_baud
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
description: The UART interrupt and optionally the DMA interrupt.
minItems: 1
items:
- const: uart
- const: dma
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- interrupts
- interrupt-names
unevaluatedProperties: false
examples:
- |
serial@840d000 {
compatible = "brcm,bcm7271-uart";
reg = <0x840d000 0x20>;
reg-names = "uart";
interrupts = <0x0 0x62 0x4>;
interrupt-names = "uart";
clocks = <&scmi_clk 190>;
clock-names = "sw_baud";
};
serial@840e000 {
compatible = "brcm,bcm7271-uart";
reg = <0x840e000 0x20>,
<0x840e080 0x8>,
<0x840e100 0xa8>,
<0x840e200 0x4c>,
<0x840e300 0x30>;
reg-names = "uart", "dma_arb", "dma_rx", "dma_tx", "dma_intr2";
interrupts = <0x0 0x62 0x4>, <0x0 0x75 0x4>;
interrupt-names = "uart", "dma";
clocks = <&scmi_clk 190>;
clock-names = "sw_baud";
};

View File

@ -20,6 +20,7 @@ Required properties:
* "mediatek,mt8173-uart" for MT8173 compatible UARTS
* "mediatek,mt8183-uart", "mediatek,mt6577-uart" for MT8183 compatible UARTS
* "mediatek,mt8192-uart", "mediatek,mt6577-uart" for MT8192 compatible UARTS
* "mediatek,mt8195-uart", "mediatek,mt6577-uart" for MT8195 compatible UARTS
* "mediatek,mt8516-uart" for MT8516 compatible UARTS
* "mediatek,mt6577-uart" for MT6577 and all of the above

View File

@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/serial/samsung_uart.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S3C, S5P and Exynos SoC UART Controller
title: Samsung S3C, S5P, Exynos, and S5L (Apple SoC) SoC UART Controller
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
@ -19,6 +19,7 @@ properties:
compatible:
items:
- enum:
- apple,s5l-uart
- samsung,s3c2410-uart
- samsung,s3c2412-uart
- samsung,s3c2440-uart
@ -51,6 +52,16 @@ properties:
- pattern: '^clk_uart_baud[0-3]$'
- pattern: '^clk_uart_baud[0-3]$'
dmas:
items:
- description: DMA controller phandle and request line for RX
- description: DMA controller phandle and request line for TX
dma-names:
items:
- const: rx
- const: tx
interrupts:
description: RX interrupt and optionally TX interrupt.
minItems: 1
@ -68,9 +79,11 @@ required:
- interrupts
- reg
additionalProperties: false
unevaluatedProperties: false
allOf:
- $ref: /schemas/serial.yaml#
- if:
properties:
compatible:
@ -96,6 +109,7 @@ allOf:
compatible:
contains:
enum:
- apple,s5l-uart
- samsung,exynos4210-uart
then:
properties:

View File

@ -75,6 +75,16 @@ properties:
type: boolean
description: CTS and RTS pins are swapped.
rx-threshold:
$ref: /schemas/types.yaml#/definitions/uint32
description:
RX FIFO threshold configuration (in bytes).
tx-threshold:
$ref: /schemas/types.yaml#/definitions/uint32
description:
TX FIFO threshold configuration (in bytes).
if:
required:
- uart-has-rtscts

View File

@ -9,9 +9,6 @@ maintainers:
title: STMicroelectronics STM32 USART bindings
allOf:
- $ref: rs485.yaml
properties:
compatible:
enum:
@ -40,6 +37,8 @@ properties:
uart-has-rtscts: true
rx-tx-swap: true
dmas:
minItems: 1
maxItems: 2
@ -66,13 +65,46 @@ properties:
linux,rs485-enabled-at-boot-time: true
rs485-rx-during-tx: true
if:
required:
- st,hw-flow-ctrl
then:
properties:
cts-gpios: false
rts-gpios: false
rx-threshold:
description:
If value is set to 1, RX FIFO threshold is disabled.
enum: [1, 2, 4, 8, 12, 14, 16]
default: 8
tx-threshold:
description:
If value is set to 1, TX FIFO threshold is disabled.
enum: [1, 2, 4, 8, 12, 14, 16]
default: 8
allOf:
- $ref: rs485.yaml#
- $ref: serial.yaml#
- if:
required:
- st,hw-flow-ctrl
then:
properties:
cts-gpios: false
rts-gpios: false
- if:
properties:
compatible:
const: st,stm32-uart
then:
properties:
rx-tx-swap: false
- if:
properties:
compatible:
contains:
enum:
- st,stm32-uart
- st,stm32f7-uart
then:
properties:
rx-threshold: false
tx-threshold: false
required:
- compatible
@ -80,19 +112,22 @@ required:
- interrupts
- clocks
additionalProperties: false
additionalProperties:
type: object
examples:
- |
#include <dt-bindings/clock/stm32mp1-clks.h>
usart1: serial@40011000 {
compatible = "st,stm32-uart";
compatible = "st,stm32h7-uart";
reg = <0x40011000 0x400>;
interrupts = <37>;
clocks = <&rcc 0 164>;
dmas = <&dma2 2 4 0x414 0x0>,
<&dma2 7 4 0x414 0x0>;
dma-names = "rx", "tx";
rx-threshold = <4>;
tx-threshold = <4>;
rs485-rts-active-low;
};

View File

@ -1,11 +0,0 @@
================
Cyclades-Z notes
================
The Cyclades-Z must have firmware loaded onto the card before it will
operate. This operation should be performed during system startup,
The firmware, loader program and the latest device driver code are
available from Cyclades at
ftp://ftp.cyclades.com/pub/cyclades/cyclades-z/linux/

View File

@ -17,7 +17,6 @@ Serial drivers
.. toctree::
:maxdepth: 1
cyclades_z
moxa-smartio
n_gsm
rocket

View File

@ -1,185 +0,0 @@
================================================
Comtrol(tm) RocketPort(R)/RocketModem(TM) Series
================================================
Device Driver for the Linux Operating System
============================================
Product overview
----------------
This driver provides a loadable kernel driver for the Comtrol RocketPort
and RocketModem PCI boards. These boards provide, 2, 4, 8, 16, or 32
high-speed serial ports or modems. This driver supports up to a combination
of four RocketPort or RocketModems boards in one machine simultaneously.
This file assumes that you are using the RocketPort driver which is
integrated into the kernel sources.
The driver can also be installed as an external module using the usual
"make;make install" routine. This external module driver, obtainable
from the Comtrol website listed below, is useful for updating the driver
or installing it into kernels which do not have the driver configured
into them. Installations instructions for the external module
are in the included README and HW_INSTALL files.
RocketPort ISA and RocketModem II PCI boards currently are only supported by
this driver in module form.
The RocketPort ISA board requires I/O ports to be configured by the DIP
switches on the board. See the section "ISA Rocketport Boards" below for
information on how to set the DIP switches.
You pass the I/O port to the driver using the following module parameters:
board1:
I/O port for the first ISA board
board2:
I/O port for the second ISA board
board3:
I/O port for the third ISA board
board4:
I/O port for the fourth ISA board
There is a set of utilities and scripts provided with the external driver
(downloadable from http://www.comtrol.com) that ease the configuration and
setup of the ISA cards.
The RocketModem II PCI boards require firmware to be loaded into the card
before it will function. The driver has only been tested as a module for this
board.
Installation Procedures
-----------------------
RocketPort/RocketModem PCI cards require no driver configuration, they are
automatically detected and configured.
The RocketPort driver can be installed as a module (recommended) or built
into the kernel. This is selected, as for other drivers, through the `make config`
command from the root of the Linux source tree during the kernel build process.
The RocketPort/RocketModem serial ports installed by this driver are assigned
device major number 46, and will be named /dev/ttyRx, where x is the port number
starting at zero (ex. /dev/ttyR0, /devttyR1, ...). If you have multiple cards
installed in the system, the mapping of port names to serial ports is displayed
in the system log at /var/log/messages.
If installed as a module, the module must be loaded. This can be done
manually by entering "modprobe rocket". To have the module loaded automatically
upon system boot, edit a `/etc/modprobe.d/*.conf` file and add the line
"alias char-major-46 rocket".
In order to use the ports, their device names (nodes) must be created with mknod.
This is only required once, the system will retain the names once created. To
create the RocketPort/RocketModem device names, use the command
"mknod /dev/ttyRx c 46 x" where x is the port number starting at zero.
For example::
> mknod /dev/ttyR0 c 46 0
> mknod /dev/ttyR1 c 46 1
> mknod /dev/ttyR2 c 46 2
The Linux script MAKEDEV will create the first 16 ttyRx device names (nodes)
for you::
>/dev/MAKEDEV ttyR
ISA Rocketport Boards
---------------------
You must assign and configure the I/O addresses used by the ISA Rocketport
card before installing and using it. This is done by setting a set of DIP
switches on the Rocketport board.
Setting the I/O address
-----------------------
Before installing RocketPort(R) or RocketPort RA boards, you must find
a range of I/O addresses for it to use. The first RocketPort card
requires a 68-byte contiguous block of I/O addresses, starting at one
of the following: 0x100h, 0x140h, 0x180h, 0x200h, 0x240h, 0x280h,
0x300h, 0x340h, 0x380h. This I/O address must be reflected in the DIP
switches of *all* of the Rocketport cards.
The second, third, and fourth RocketPort cards require a 64-byte
contiguous block of I/O addresses, starting at one of the following
I/O addresses: 0x100h, 0x140h, 0x180h, 0x1C0h, 0x200h, 0x240h, 0x280h,
0x2C0h, 0x300h, 0x340h, 0x380h, 0x3C0h. The I/O address used by the
second, third, and fourth Rocketport cards (if present) are set via
software control. The DIP switch settings for the I/O address must be
set to the value of the first Rocketport cards.
In order to distinguish each of the card from the others, each card
must have a unique board ID set on the dip switches. The first
Rocketport board must be set with the DIP switches corresponding to
the first board, the second board must be set with the DIP switches
corresponding to the second board, etc. IMPORTANT: The board ID is
the only place where the DIP switch settings should differ between the
various Rocketport boards in a system.
The I/O address range used by any of the RocketPort cards must not
conflict with any other cards in the system, including other
RocketPort cards. Below, you will find a list of commonly used I/O
address ranges which may be in use by other devices in your system.
On a Linux system, "cat /proc/ioports" will also be helpful in
identifying what I/O addresses are being used by devices on your
system.
Remember, the FIRST RocketPort uses 68 I/O addresses. So, if you set it
for 0x100, it will occupy 0x100 to 0x143. This would mean that you
CAN NOT set the second, third or fourth board for address 0x140 since
the first 4 bytes of that range are used by the first board. You would
need to set the second, third, or fourth board to one of the next available
blocks such as 0x180.
RocketPort and RocketPort RA SW1 Settings::
+-------------------------------+
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+-------+-------+---------------+
| Unused| Card | I/O Port Block|
+-------------------------------+
DIP Switches DIP Switches
7 8 6 5
=================== ===================
On On UNUSED, MUST BE ON. On On First Card <==== Default
On Off Second Card
Off On Third Card
Off Off Fourth Card
DIP Switches I/O Address Range
4 3 2 1 Used by the First Card
=====================================
On Off On Off 100-143
On Off Off On 140-183
On Off Off Off 180-1C3 <==== Default
Off On On Off 200-243
Off On Off On 240-283
Off On Off Off 280-2C3
Off Off On Off 300-343
Off Off Off On 340-383
Off Off Off Off 380-3C3
Reporting Bugs
--------------
For technical support, please provide the following
information: Driver version, kernel release, distribution of
kernel, and type of board you are using. Error messages and log
printouts port configuration details are especially helpful.
USA:
:Phone: (612) 494-4100
:FAX: (612) 494-4199
:email: support@comtrol.com
Comtrol Europe:
:Phone: +44 (0) 1 869 323-220
:FAX: +44 (0) 1 869 323-211
:email: support@comtrol.co.uk
Web: http://www.comtrol.com
FTP: ftp.comtrol.com

View File

@ -73,12 +73,10 @@ CMAGIC 0x0111 user ``include/linux/
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h``
DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
@ -90,14 +88,12 @@ TTY_MAGIC 0x5401 tty_struct ``include/linux/
MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h``
USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h``
LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``
NBD_REQUEST_MAGIC 0x12560953 nbd_request ``include/linux/nbd.h``

View File

@ -79,12 +79,10 @@ CMAGIC 0x0111 user ``include/linux/
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h``
DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
@ -96,14 +94,12 @@ TTY_MAGIC 0x5401 tty_struct ``include/linux/
MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h``
USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h``
LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str ``drivers/scsi/gdth_ioctl.h``
RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``

View File

@ -62,12 +62,10 @@ CMAGIC 0x0111 user ``include/linux/
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h``
DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
@ -79,14 +77,12 @@ TTY_MAGIC 0x5401 tty_struct ``include/linux/
MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h``
USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h``
LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str ``drivers/scsi/gdth_ioctl.h``
RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``

View File

@ -209,7 +209,6 @@ Code Seq# Include File Comments
linux/fs.h,
'X' all fs/ocfs2/ocfs_fs.h conflict!
'X' 01 linux/pktcdvd.h conflict!
'Y' all linux/cyclades.h
'Z' 14-15 drivers/message/fusion/mptctl.h
'[' 00-3F linux/usb/tmc.h USB Test and Measurement Devices
<mailto:gregkh@linuxfoundation.org>

View File

@ -3578,6 +3578,14 @@ S: Supported
F: Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml
F: drivers/i2c/busses/i2c-brcmstb.c
BROADCOM BRCMSTB UART DRIVER
M: Al Cooper <alcooperx@gmail.com>
L: linux-serial@vger.kernel.org
L: bcm-kernel-feedback-list@broadcom.com
S: Maintained
F: Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml
F: drivers/tty/serial/8250/8250_bcm7271.c
BROADCOM BRCMSTB USB EHCI DRIVER
M: Al Cooper <alcooperx@gmail.com>
L: linux-usb@vger.kernel.org
@ -4902,16 +4910,8 @@ S: Maintained
W: http://www.armlinux.org.uk/
F: drivers/video/fbdev/cyber2000fb.*
CYCLADES ASYNC MUX DRIVER
S: Orphan
W: http://www.cyclades.com/
F: drivers/tty/cyclades.c
F: include/linux/cyclades.h
F: include/uapi/linux/cyclades.h
CYCLADES PC300 DRIVER
S: Orphan
W: http://www.cyclades.com/
F: drivers/net/wan/pc300*
CYPRESS_FIRMWARE MEDIA DRIVER
@ -12167,8 +12167,7 @@ F: drivers/media/pci/meye/
F: include/uapi/linux/meye.h
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
M: Jiri Slaby <jirislaby@kernel.org>
S: Maintained
S: Orphan
F: Documentation/driver-api/serial/moxa-smartio.rst
F: drivers/tty/mxser.*
@ -12312,11 +12311,6 @@ F: drivers/mux/
F: include/dt-bindings/mux/
F: include/linux/mux/
MULTITECH MULTIPORT CARD (ISICOM)
S: Orphan
F: drivers/tty/isicom.c
F: include/linux/isicom.h
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
M: Bin Liu <b-liu@ti.com>
L: linux-usb@vger.kernel.org
@ -15493,12 +15487,6 @@ L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/rocker/
ROCKETPORT DRIVER
S: Maintained
W: http://www.comtrol.com
F: Documentation/driver-api/serial/rocket.rst
F: drivers/tty/rocket*
ROCKETPORT EXPRESS/INFINITY DRIVER
M: Kevin Cernekee <cernekee@gmail.com>
L: linux-serial@vger.kernel.org

View File

@ -452,32 +452,36 @@
usart2: serial@4000e000 {
compatible = "st,stm32h7-uart";
reg = <0x4000e000 0x400>;
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART2_K>;
wakeup-source;
status = "disabled";
};
usart3: serial@4000f000 {
compatible = "st,stm32h7-uart";
reg = <0x4000f000 0x400>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART3_K>;
wakeup-source;
status = "disabled";
};
uart4: serial@40010000 {
compatible = "st,stm32h7-uart";
reg = <0x40010000 0x400>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART4_K>;
wakeup-source;
status = "disabled";
};
uart5: serial@40011000 {
compatible = "st,stm32h7-uart";
reg = <0x40011000 0x400>;
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART5_K>;
wakeup-source;
status = "disabled";
};
@ -577,16 +581,18 @@
uart7: serial@40018000 {
compatible = "st,stm32h7-uart";
reg = <0x40018000 0x400>;
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART7_K>;
wakeup-source;
status = "disabled";
};
uart8: serial@40019000 {
compatible = "st,stm32h7-uart";
reg = <0x40019000 0x400>;
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART8_K>;
wakeup-source;
status = "disabled";
};
@ -665,8 +671,9 @@
usart6: serial@44003000 {
compatible = "st,stm32h7-uart";
reg = <0x44003000 0x400>;
interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART6_K>;
wakeup-source;
status = "disabled";
};
@ -1505,8 +1512,9 @@
usart1: serial@5c000000 {
compatible = "st,stm32h7-uart";
reg = <0x5c000000 0x400>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART1_K>;
wakeup-source;
status = "disabled";
};

View File

@ -595,7 +595,6 @@ CONFIG_GAMEPORT_FM801=m
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_NONSTANDARD=y
CONFIG_ROCKETPORT=m
CONFIG_CYCLADES=m
CONFIG_SYNCLINK_GT=m
CONFIG_NOZOMI=m
CONFIG_N_HDLC=m

View File

@ -31,48 +31,23 @@
#define SERIAL_MAX_NUM_LINES 1
#define SERIAL_TIMER_VALUE (HZ / 10)
static void rs_poll(struct timer_list *);
static struct tty_driver *serial_driver;
static struct tty_port serial_port;
static struct timer_list serial_timer;
static DEFINE_TIMER(serial_timer, rs_poll);
static DEFINE_SPINLOCK(timer_lock);
static char *serial_version = "0.1";
static char *serial_name = "ISS serial driver";
/*
* This routine is called whenever a serial port is opened. It
* enables interrupts for a serial port, linking in its async structure into
* the IRQ chain. It also performs the serial-specific
* initialization for the tty structure.
*/
static void rs_poll(struct timer_list *);
static int rs_open(struct tty_struct *tty, struct file * filp)
{
tty->port = &serial_port;
spin_lock_bh(&timer_lock);
if (tty->count == 1) {
timer_setup(&serial_timer, rs_poll, 0);
if (tty->count == 1)
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
}
spin_unlock_bh(&timer_lock);
return 0;
}
/*
* ------------------------------------------------------------
* iss_serial_close()
*
* This routine is called when the serial port gets closed. First, we
* wait for the last remaining data to be sent. Then, we unlink its
* async structure from the interrupt chain if necessary, and we free
* that IRQ if nothing is left in the chain.
* ------------------------------------------------------------
*/
static void rs_close(struct tty_struct *tty, struct file * filp)
{
spin_lock_bh(&timer_lock);
@ -149,7 +124,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
static int rs_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
seq_printf(m, "serinfo:1.0 driver:0.1\n");
return 0;
}
@ -166,14 +141,12 @@ static const struct tty_operations serial_ops = {
.proc_show = rs_proc_show,
};
int __init rs_init(void)
static int __init rs_init(void)
{
tty_port_init(&serial_port);
serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES);
pr_info("%s %s\n", serial_name, serial_version);
/* Initialize the tty_driver structure */
serial_driver->driver_name = "iss_serial";
@ -198,11 +171,7 @@ int __init rs_init(void)
static __exit void rs_exit(void)
{
int error;
if ((error = tty_unregister_driver(serial_driver)))
pr_err("ISS_SERIAL: failed to unregister serial driver (%d)\n",
error);
tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
tty_port_destroy(&serial_port);
}

View File

@ -104,7 +104,6 @@ static int spk_ttyio_receive_buf2(struct tty_struct *tty,
static struct tty_ldisc_ops spk_ttyio_ldisc_ops = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "speakup_ldisc",
.open = spk_ttyio_ldisc_open,
.close = spk_ttyio_ldisc_close,

View File

@ -821,7 +821,6 @@ static __poll_t hci_uart_tty_poll(struct tty_struct *tty,
static struct tty_ldisc_ops hci_uart_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "n_hci",
.open = hci_uart_tty_open,
.close = hci_uart_tty_close,

View File

@ -530,8 +530,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
info->port.ops = &mgslpc_port_ops;
INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096;
info->port.close_delay = 5*HZ/10;
info->port.closing_wait = 30*HZ;
init_waitqueue_head(&info->status_event_wait_q);
init_waitqueue_head(&info->event_wait_q);
spin_lock_init(&info->lock);

View File

@ -158,12 +158,23 @@ static int tpk_ioctl(struct tty_struct *tty,
return 0;
}
/*
* TTY operations hangup function.
*/
static void tpk_hangup(struct tty_struct *tty)
{
struct ttyprintk_port *tpkp = tty->driver_data;
tty_port_hangup(&tpkp->port);
}
static const struct tty_operations ttyprintk_ops = {
.open = tpk_open,
.close = tpk_close,
.write = tpk_write,
.write_room = tpk_write_room,
.ioctl = tpk_ioctl,
.hangup = tpk_hangup,
};
static const struct tty_port_operations null_ops = { };

View File

@ -845,7 +845,6 @@ static void st_tty_flush_buffer(struct tty_struct *tty)
}
static struct tty_ldisc_ops st_ldisc_ops = {
.magic = TTY_LDISC_MAGIC,
.name = "n_st",
.open = st_tty_open,
.close = st_tty_close,

View File

@ -382,7 +382,6 @@ static void ldisc_close(struct tty_struct *tty)
/* The line discipline structure. */
static struct tty_ldisc_ops caif_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "n_caif",
.open = ldisc_open,
.close = ldisc_close,
@ -390,18 +389,6 @@ static struct tty_ldisc_ops caif_ldisc = {
.write_wakeup = ldisc_tx_wakeup
};
static int register_ldisc(void)
{
int result;
result = tty_register_ldisc(N_CAIF, &caif_ldisc);
if (result < 0) {
pr_err("cannot register CAIF ldisc=%d err=%d\n", N_CAIF,
result);
return result;
}
return result;
}
static const struct net_device_ops netdev_ops = {
.ndo_open = caif_net_open,
.ndo_stop = caif_net_close,
@ -444,7 +431,10 @@ static int __init caif_ser_init(void)
{
int ret;
ret = register_ldisc();
ret = tty_register_ldisc(N_CAIF, &caif_ldisc);
if (ret < 0)
pr_err("cannot register CAIF ldisc=%d err=%d\n", N_CAIF, ret);
debugfsdir = debugfs_create_dir("caif_serial", NULL);
return ret;
}

View File

@ -697,7 +697,6 @@ static int slcan_ioctl(struct tty_struct *tty, struct file *file,
static struct tty_ldisc_ops slc_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "slcan",
.open = slcan_open,
.close = slcan_close,

View File

@ -744,7 +744,6 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
static struct tty_ldisc_ops sp_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "6pack",
.open = sixpack_open,
.close = sixpack_close,

View File

@ -933,7 +933,6 @@ out:
static struct tty_ldisc_ops ax_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "mkiss",
.open = mkiss_open,
.close = mkiss_close,

View File

@ -372,7 +372,6 @@ ppp_asynctty_wakeup(struct tty_struct *tty)
static struct tty_ldisc_ops ppp_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "ppp",
.open = ppp_asynctty_open,
.close = ppp_asynctty_close,

View File

@ -365,7 +365,6 @@ ppp_sync_wakeup(struct tty_struct *tty)
static struct tty_ldisc_ops ppp_sync_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "pppsync",
.open = ppp_sync_open,
.close = ppp_sync_close,

View File

@ -1263,7 +1263,6 @@ static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static struct tty_ldisc_ops sl_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "slip",
.open = slip_open,
.close = slip_close,

View File

@ -13,8 +13,6 @@
#include <linux/pps_kernel.h>
#include <linux/bug.h>
#define PPS_TTY_MAGIC 0x0001
static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status)
{
struct pps_device *pps;
@ -114,7 +112,6 @@ static int __init pps_tty_init(void)
/* Init PPS_TTY data */
pps_ldisc_ops.owner = THIS_MODULE;
pps_ldisc_ops.magic = PPS_TTY_MAGIC;
pps_ldisc_ops.name = "pps_tty";
pps_ldisc_ops.dcd_change = pps_tty_dcd_change;
pps_ldisc_ops.open = pps_tty_open;

View File

@ -85,7 +85,6 @@ struct raw3215_info {
int written; /* number of bytes in write requests */
struct raw3215_req *queued_read; /* pointer to queued read requests */
struct raw3215_req *queued_write;/* pointer to queued write requests */
struct tasklet_struct tlet; /* tasklet to invoke tty_wakeup */
wait_queue_head_t empty_wait; /* wait queue for flushing */
struct timer_list timer; /* timer for delayed output */
int line_pos; /* position on the line (for tabs) */
@ -329,21 +328,6 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
}
}
/*
* Call tty_wakeup from tasklet context
*/
static void raw3215_wakeup(unsigned long data)
{
struct raw3215_info *raw = (struct raw3215_info *) data;
struct tty_struct *tty;
tty = tty_port_tty_get(&raw->port);
if (tty) {
tty_wakeup(tty);
tty_kref_put(tty);
}
}
/*
* Try to start the next IO and wake up processes waiting on the tty.
*/
@ -352,7 +336,7 @@ static void raw3215_next_io(struct raw3215_info *raw, struct tty_struct *tty)
raw3215_mk_write_req(raw);
raw3215_try_io(raw);
if (tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE)
tasklet_schedule(&raw->tlet);
tty_wakeup(tty);
}
/*
@ -644,7 +628,6 @@ static struct raw3215_info *raw3215_alloc_info(void)
timer_setup(&info->timer, raw3215_timeout, 0);
init_waitqueue_head(&info->empty_wait);
tasklet_init(&info->tlet, raw3215_wakeup, (unsigned long)info);
tty_port_init(&info->port);
return info;
@ -928,15 +911,13 @@ static int tty3215_open(struct tty_struct *tty, struct file * filp)
*/
static void tty3215_close(struct tty_struct *tty, struct file * filp)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
raw = (struct raw3215_info *) tty->driver_data;
if (raw == NULL || tty->count > 1)
return;
tty->closing = 1;
/* Shutdown the terminal */
raw3215_shutdown(raw);
tasklet_kill(&raw->tlet);
tty->closing = 0;
tty_port_tty_set(&raw->port, NULL);
}
@ -946,9 +927,7 @@ static void tty3215_close(struct tty_struct *tty, struct file * filp)
*/
static int tty3215_write_room(struct tty_struct *tty)
{
struct raw3215_info *raw;
raw = (struct raw3215_info *) tty->driver_data;
struct raw3215_info *raw = tty->driver_data;
/* Subtract TAB_STOP_SIZE to allow for a tab, 8 <<< 64K */
if ((RAW3215_BUFFER_SIZE - raw->count - TAB_STOP_SIZE) >= 0)
@ -963,12 +942,9 @@ static int tty3215_write_room(struct tty_struct *tty)
static int tty3215_write(struct tty_struct * tty,
const unsigned char *buf, int count)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
int i, written;
if (!tty)
return 0;
raw = (struct raw3215_info *) tty->driver_data;
written = count;
while (count > 0) {
for (i = 0; i < count; i++)
@ -991,12 +967,10 @@ static int tty3215_write(struct tty_struct * tty,
*/
static int tty3215_put_char(struct tty_struct *tty, unsigned char ch)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
if (!tty)
return 0;
raw = (struct raw3215_info *) tty->driver_data;
raw3215_putchar(raw, ch);
return 1;
}
@ -1009,17 +983,15 @@ static void tty3215_flush_chars(struct tty_struct *tty)
*/
static int tty3215_chars_in_buffer(struct tty_struct *tty)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
raw = (struct raw3215_info *) tty->driver_data;
return raw->count;
}
static void tty3215_flush_buffer(struct tty_struct *tty)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
raw = (struct raw3215_info *) tty->driver_data;
raw3215_flush_buffer(raw);
tty_wakeup(tty);
}
@ -1029,9 +1001,8 @@ static void tty3215_flush_buffer(struct tty_struct *tty)
*/
static void tty3215_throttle(struct tty_struct * tty)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
raw = (struct raw3215_info *) tty->driver_data;
raw->flags |= RAW3215_THROTTLED;
}
@ -1040,10 +1011,9 @@ static void tty3215_throttle(struct tty_struct * tty)
*/
static void tty3215_unthrottle(struct tty_struct * tty)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
unsigned long flags;
raw = (struct raw3215_info *) tty->driver_data;
if (raw->flags & RAW3215_THROTTLED) {
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
raw->flags &= ~RAW3215_THROTTLED;
@ -1057,9 +1027,8 @@ static void tty3215_unthrottle(struct tty_struct * tty)
*/
static void tty3215_stop(struct tty_struct *tty)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
raw = (struct raw3215_info *) tty->driver_data;
raw->flags |= RAW3215_STOPPED;
}
@ -1068,10 +1037,9 @@ static void tty3215_stop(struct tty_struct *tty)
*/
static void tty3215_start(struct tty_struct *tty)
{
struct raw3215_info *raw;
struct raw3215_info *raw = tty->driver_data;
unsigned long flags;
raw = (struct raw3215_info *) tty->driver_data;
if (raw->flags & RAW3215_STOPPED) {
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
raw->flags &= ~RAW3215_STOPPED;

View File

@ -1218,13 +1218,12 @@ static int get_serial_info(struct tty_struct *tty,
struct fwtty_port *port = tty->driver_data;
mutex_lock(&port->port.mutex);
ss->type = PORT_UNKNOWN;
ss->line = port->port.tty->index;
ss->flags = port->port.flags;
ss->xmit_fifo_size = FWTTY_PORT_TXFIFO_LEN;
ss->line = port->index;
ss->baud_base = 400000000;
ss->close_delay = port->port.close_delay;
ss->close_delay = jiffies_to_msecs(port->port.close_delay) / 10;
ss->closing_wait = 3000;
mutex_unlock(&port->port.mutex);
return 0;
}
@ -1232,20 +1231,20 @@ static int set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct fwtty_port *port = tty->driver_data;
unsigned int cdelay;
if (ss->irq != 0 || ss->port != 0 || ss->custom_divisor != 0 ||
ss->baud_base != 400000000)
return -EPERM;
cdelay = msecs_to_jiffies(ss->close_delay * 10);
mutex_lock(&port->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
if (((ss->flags & ~ASYNC_USR_MASK) !=
if (cdelay != port->port.close_delay ||
((ss->flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&port->port.mutex);
return -EPERM;
}
}
port->port.close_delay = ss->close_delay * HZ / 100;
port->port.close_delay = cdelay;
mutex_unlock(&port->port.mutex);
return 0;

View File

@ -188,7 +188,7 @@ static int gdm_tty_write_room(struct tty_struct *tty)
struct gdm *gdm = tty->driver_data;
if (!GDM_TTY_READY(gdm))
return -ENODEV;
return 0;
return WRITE_SIZE;
}

View File

@ -610,14 +610,13 @@ static int get_serial_info(struct tty_struct *tty,
{
struct gb_tty *gb_tty = tty->driver_data;
ss->type = PORT_16550A;
ss->line = gb_tty->minor;
ss->xmit_fifo_size = 16;
ss->baud_base = 9600;
ss->close_delay = gb_tty->port.close_delay / 10;
ss->close_delay = jiffies_to_msecs(gb_tty->port.close_delay) / 10;
ss->closing_wait =
gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE : gb_tty->port.closing_wait / 10;
ASYNC_CLOSING_WAIT_NONE :
jiffies_to_msecs(gb_tty->port.closing_wait) / 10;
return 0;
}
@ -629,17 +628,16 @@ static int set_serial_info(struct tty_struct *tty,
unsigned int close_delay;
int retval = 0;
close_delay = ss->close_delay * 10;
close_delay = msecs_to_jiffies(ss->close_delay * 10);
closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE : ss->closing_wait * 10;
ASYNC_CLOSING_WAIT_NONE :
msecs_to_jiffies(ss->closing_wait * 10);
mutex_lock(&gb_tty->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
if ((close_delay != gb_tty->port.close_delay) ||
(closing_wait != gb_tty->port.closing_wait))
retval = -EPERM;
else
retval = -EOPNOTSUPP;
} else {
gb_tty->port.close_delay = close_delay;
gb_tty->port.closing_wait = closing_wait;

View File

@ -181,7 +181,7 @@ config SERIAL_NONSTANDARD
help
Say Y here if you have any non-standard serial boards -- boards
which aren't supported using the standard "dumb" serial driver.
This includes intelligent serial boards such as Cyclades,
This includes intelligent serial boards such as
Digiboards, etc. These are usually used for systems that need many
serial ports because they serve many terminals or dial-in
connections.
@ -192,50 +192,6 @@ config SERIAL_NONSTANDARD
Most people can say N here.
config ROCKETPORT
tristate "Comtrol RocketPort support"
depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
help
This driver supports Comtrol RocketPort and RocketModem PCI boards.
These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
modems. For information about the RocketPort/RocketModem boards
and this driver read <file:Documentation/driver-api/serial/rocket.rst>.
To compile this driver as a module, choose M here: the
module will be called rocket.
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.
config CYCLADES
tristate "Cyclades async mux support"
depends on SERIAL_NONSTANDARD && (PCI || ISA)
select FW_LOADER
help
This driver supports Cyclades Z and Y multiserial boards.
You would need something like this to connect more than two modems to
your Linux box, for instance in order to become a dial-in server.
For information about the Cyclades-Z card, read
<file:Documentation/driver-api/serial/cyclades_z.rst>.
To compile this driver as a module, choose M here: the
module will be called cyclades.
If you haven't heard about it, it's safe to say N.
config CYZ_INTR
bool "Cyclades-Z interrupt mode operation"
depends on CYCLADES && PCI
help
The Cyclades-Z family of multiport cards allows 2 (two) driver op
modes: polling and interrupt. In polling mode, the driver will check
the status of the Cyclades-Z ports every certain amount of time
(which is called polling cycle and is configurable). In interrupt
mode, it will use an interrupt line (IRQ) in order to check the
status of the Cyclades-Z ports. The default op mode is polling. If
unsure, say N.
config MOXA_INTELLIO
tristate "Moxa Intellio support"
depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
@ -267,16 +223,6 @@ config SYNCLINK_GT
synchronous and asynchronous serial adapters
manufactured by Microgate Systems, Ltd. (www.microgate.com)
config ISI
tristate "Multi-Tech multiport card support"
depends on SERIAL_NONSTANDARD && PCI
select FW_LOADER
help
This is a driver for the Multi-Tech cards which provide several
serial ports. The driver is experimental and can currently only be
built as a module. The module will be called isicom.
If you want to do that, choose M here.
config N_HDLC
tristate "HDLC line discipline support"
depends on SERIAL_NONSTANDARD
@ -415,36 +361,6 @@ config NULL_TTY
If unsure, say N.
config TRACE_ROUTER
tristate "Trace data router for MIPI P1149.7 cJTAG standard"
depends on TRACE_SINK
help
The trace router uses the Linux tty line discipline framework to
route trace data coming from a tty port (say UART for example) to
the trace sink line discipline driver and to another tty port (say
USB). This is part of a solution for the MIPI P1149.7, compact JTAG,
standard, which is for debugging mobile devices. The PTI driver in
drivers/misc/pti.c defines the majority of this MIPI solution.
You should select this driver if the target kernel is meant for
a mobile device containing a modem. Then you will need to select
"Trace data sink for MIPI P1149.7 cJTAG standard" line discipline
driver.
config TRACE_SINK
tristate "Trace data sink for MIPI P1149.7 cJTAG standard"
help
The trace sink uses the Linux line discipline framework to receive
trace data coming from the trace router line discipline driver
to a user-defined tty port target, like USB.
This is to provide a way to extract modem trace data on
devices that do not have a PTI HW module, or just need modem
trace data to come out of a different HW output port.
This is part of a solution for the P1149.7, compact JTAG, standard.
If you select this option, you need to select
"Trace data router for MIPI P1149.7 cJTAG standard".
config VCC
tristate "Sun Virtual Console Concentrator"
depends on SUN_LDOMS

View File

@ -18,13 +18,10 @@ obj-$(CONFIG_SERIAL_DEV_BUS) += serdev/
# tty drivers
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_CYCLADES) += cyclades.o
obj-$(CONFIG_ISI) += isicom.o
obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
obj-$(CONFIG_NOZOMI) += nozomi.o
obj-$(CONFIG_NULL_TTY) += ttynull.o
obj-$(CONFIG_ROCKETPORT) += rocket.o
obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o
obj-$(CONFIG_GOLDFISH_TTY) += goldfish.o

View File

@ -937,15 +937,21 @@ static void rs_unthrottle(struct tty_struct * tty)
static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
{
struct serial_state *state = tty->driver_data;
unsigned int close_delay, closing_wait;
tty_lock(tty);
close_delay = jiffies_to_msecs(state->tport.close_delay) / 10;
closing_wait = state->tport.closing_wait;
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = jiffies_to_msecs(closing_wait) / 10;
ss->line = tty->index;
ss->port = state->port;
ss->flags = state->tport.flags;
ss->xmit_fifo_size = state->xmit_fifo_size;
ss->baud_base = state->baud_base;
ss->close_delay = state->tport.close_delay;
ss->closing_wait = state->tport.closing_wait;
ss->close_delay = close_delay;
ss->closing_wait = closing_wait;
ss->custom_divisor = state->custom_divisor;
tty_unlock(tty);
return 0;
@ -957,6 +963,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
struct tty_port *port = &state->tport;
bool change_spd;
int retval = 0;
unsigned int close_delay, closing_wait;
tty_lock(tty);
change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) ||
@ -966,10 +973,16 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
tty_unlock(tty);
return -EINVAL;
}
close_delay = msecs_to_jiffies(ss->close_delay * 10);
closing_wait = ss->closing_wait;
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = msecs_to_jiffies(closing_wait * 10);
if (!serial_isroot()) {
if ((ss->baud_base != state->baud_base) ||
(ss->close_delay != port->close_delay) ||
(close_delay != port->close_delay) ||
(closing_wait != port->closing_wait) ||
(ss->xmit_fifo_size != state->xmit_fifo_size) ||
((ss->flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
@ -996,8 +1009,8 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
port->flags = ((port->flags & ~ASYNC_FLAGS) |
(ss->flags & ASYNC_FLAGS));
state->custom_divisor = ss->custom_divisor;
port->close_delay = ss->close_delay * HZ/100;
port->closing_wait = ss->closing_wait * HZ/100;
port->close_delay = close_delay;
port->closing_wait = closing_wait;
check_and_exit:
if (tty_port_initialized(port)) {
@ -1622,21 +1635,17 @@ fail_put_tty_driver:
static int __exit amiga_serial_remove(struct platform_device *pdev)
{
int error;
struct serial_state *state = platform_get_drvdata(pdev);
/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
error = tty_unregister_driver(serial_driver);
if (error)
printk("SERIAL: failed to unregister serial driver (%d)\n",
error);
tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
tty_port_destroy(&state->tport);
free_irq(IRQ_AMIGA_TBE, state);
free_irq(IRQ_AMIGA_RBF, state);
return error;
return 0;
}
static struct platform_driver amiga_serial_driver = {

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
#include "hvc_console.h"
struct hvc_struct *hvc_udbg_dev;
static struct hvc_struct *hvc_udbg_dev;
static int hvc_udbg_put(uint32_t vtermno, const char *buf, int count)
{

View File

@ -290,35 +290,11 @@ static LIST_HEAD(hvcs_structs);
static DEFINE_SPINLOCK(hvcs_structs_lock);
static DEFINE_MUTEX(hvcs_init_mutex);
static void hvcs_unthrottle(struct tty_struct *tty);
static void hvcs_throttle(struct tty_struct *tty);
static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance);
static int hvcs_write(struct tty_struct *tty,
const unsigned char *buf, int count);
static int hvcs_write_room(struct tty_struct *tty);
static int hvcs_chars_in_buffer(struct tty_struct *tty);
static int hvcs_has_pi(struct hvcs_struct *hvcsd);
static void hvcs_set_pi(struct hvcs_partner_info *pi,
struct hvcs_struct *hvcsd);
static int hvcs_get_pi(struct hvcs_struct *hvcsd);
static int hvcs_rescan_devices_list(void);
static int hvcs_partner_connect(struct hvcs_struct *hvcsd);
static void hvcs_partner_free(struct hvcs_struct *hvcsd);
static int hvcs_enable_device(struct hvcs_struct *hvcsd,
uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
static int hvcs_open(struct tty_struct *tty, struct file *filp);
static void hvcs_close(struct tty_struct *tty, struct file *filp);
static void hvcs_hangup(struct tty_struct * tty);
static int hvcs_probe(struct vio_dev *dev,
const struct vio_device_id *id);
static int __init hvcs_module_init(void);
static void __exit hvcs_module_exit(void);
static int hvcs_initialize(void);
#define HVCS_SCHED_READ 0x00000001

View File

@ -235,10 +235,10 @@ static int ipw_write_room(struct tty_struct *linux_tty)
/* FIXME: Exactly how is the tty object locked here .. */
if (!tty)
return -ENODEV;
return 0;
if (!tty->port.count)
return -EINVAL;
return 0;
room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
if (room < 0)
@ -596,13 +596,8 @@ int ipwireless_tty_init(void)
void ipwireless_tty_release(void)
{
int ret;
ret = tty_unregister_driver(ipw_tty_driver);
tty_unregister_driver(ipw_tty_driver);
put_tty_driver(ipw_tty_driver);
if (ret != 0)
printk(KERN_ERR IPWIRELESS_PCCARD_NAME
": tty_unregister_driver failed with code %d\n", ret);
}
int ipwireless_tty_is_modem(struct ipw_tty *tty)

File diff suppressed because it is too large Load Diff

View File

@ -1118,9 +1118,7 @@ static void __exit moxa_exit(void)
del_timer_sync(&moxaTimer);
if (tty_unregister_driver(moxaDriver))
printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
"serial driver\n");
tty_unregister_driver(moxaDriver);
put_tty_driver(moxaDriver);
}
@ -2040,7 +2038,7 @@ static int moxa_get_serial_info(struct tty_struct *tty,
ss->line = info->port.tty->index,
ss->flags = info->port.flags,
ss->baud_base = 921600,
ss->close_delay = info->port.close_delay;
ss->close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
mutex_unlock(&info->port.mutex);
return 0;
}
@ -2050,30 +2048,31 @@ static int moxa_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct moxa_port *info = tty->driver_data;
unsigned int close_delay;
if (tty->index == MAX_PORTS)
return -EINVAL;
if (!info)
return -ENODEV;
if (ss->irq != 0 || ss->port != 0 ||
ss->custom_divisor != 0 ||
ss->baud_base != 921600)
return -EPERM;
close_delay = msecs_to_jiffies(ss->close_delay * 10);
mutex_lock(&info->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
if (((ss->flags & ~ASYNC_USR_MASK) !=
if (close_delay != info->port.close_delay ||
ss->type != info->type ||
((ss->flags & ~ASYNC_USR_MASK) !=
(info->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&info->port.mutex);
return -EPERM;
}
} else {
info->port.close_delay = close_delay;
MoxaSetFifo(info, ss->type == PORT_16550A);
info->type = ss->type;
}
info->port.close_delay = ss->close_delay * HZ / 100;
MoxaSetFifo(info, ss->type == PORT_16550A);
info->type = ss->type;
mutex_unlock(&info->port.mutex);
return 0;
}

View File

@ -1208,19 +1208,26 @@ static int mxser_get_serial_info(struct tty_struct *tty,
{
struct mxser_port *info = tty->driver_data;
struct tty_port *port = &info->port;
unsigned int closing_wait, close_delay;
if (tty->index == MXSER_PORTS)
return -ENOTTY;
mutex_lock(&port->mutex);
close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
closing_wait = info->port.closing_wait;
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = jiffies_to_msecs(closing_wait) / 10;
ss->type = info->type,
ss->line = tty->index,
ss->port = info->ioaddr,
ss->irq = info->board->irq,
ss->flags = info->port.flags,
ss->baud_base = info->baud_base,
ss->close_delay = info->port.close_delay,
ss->closing_wait = info->port.closing_wait,
ss->close_delay = close_delay;
ss->closing_wait = closing_wait;
ss->custom_divisor = info->custom_divisor,
mutex_unlock(&port->mutex);
return 0;
@ -1233,7 +1240,7 @@ static int mxser_set_serial_info(struct tty_struct *tty,
struct tty_port *port = &info->port;
speed_t baud;
unsigned long sl_flags;
unsigned int flags;
unsigned int flags, close_delay, closing_wait;
int retval = 0;
if (tty->index == MXSER_PORTS)
@ -1255,9 +1262,15 @@ static int mxser_set_serial_info(struct tty_struct *tty,
flags = port->flags & ASYNC_SPD_MASK;
close_delay = msecs_to_jiffies(ss->close_delay * 10);
closing_wait = ss->closing_wait;
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = msecs_to_jiffies(closing_wait * 10);
if (!capable(CAP_SYS_ADMIN)) {
if ((ss->baud_base != info->baud_base) ||
(ss->close_delay != info->port.close_delay) ||
(close_delay != info->port.close_delay) ||
(closing_wait != info->port.closing_wait) ||
((ss->flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&port->mutex);
return -EPERM;
@ -1271,8 +1284,8 @@ static int mxser_set_serial_info(struct tty_struct *tty,
*/
port->flags = ((port->flags & ~ASYNC_FLAGS) |
(ss->flags & ASYNC_FLAGS));
port->close_delay = ss->close_delay * HZ / 100;
port->closing_wait = ss->closing_wait * HZ / 100;
port->close_delay = close_delay;
port->closing_wait = closing_wait;
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
(ss->baud_base != info->baud_base ||
ss->custom_divisor !=
@ -1284,12 +1297,12 @@ static int mxser_set_serial_info(struct tty_struct *tty,
baud = ss->baud_base / ss->custom_divisor;
tty_encode_baud_rate(tty, baud, baud);
}
info->type = ss->type;
process_txrx_fifo(info);
}
info->type = ss->type;
process_txrx_fifo(info);
if (tty_port_initialized(port)) {
if (flags != (port->flags & ASYNC_SPD_MASK)) {
spin_lock_irqsave(&info->slock, sl_flags);
@ -2142,14 +2155,7 @@ end_intr:
port->mon_data.rxcnt += cnt;
port->mon_data.up_rxcnt += cnt;
/*
* We are called from an interrupt context with &port->slock
* being held. Drop it temporarily in order to prevent
* recursive locking.
*/
spin_unlock(&port->slock);
tty_flip_buffer_push(&port->port);
spin_lock(&port->slock);
}
static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)

View File

@ -50,6 +50,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/gsmmux.h>
#include "tty.h"
static int debug;
module_param(debug, int, 0600);
@ -266,7 +267,7 @@ struct gsm_mux {
#define MAX_MUX 4 /* 256 minors */
static struct gsm_mux *gsm_mux[MAX_MUX]; /* GSM muxes */
static spinlock_t gsm_mux_lock;
static DEFINE_SPINLOCK(gsm_mux_lock);
static struct tty_driver *gsm_tty_driver;
@ -2384,8 +2385,18 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
/* Don't register device 0 - this is the control channel and not
a usable tty interface */
base = mux_num_to_base(gsm); /* Base for this MUX */
for (i = 1; i < NUM_DLCI; i++)
tty_register_device(gsm_tty_driver, base + i, NULL);
for (i = 1; i < NUM_DLCI; i++) {
struct device *dev;
dev = tty_register_device(gsm_tty_driver,
base + i, NULL);
if (IS_ERR(dev)) {
for (i--; i >= 1; i--)
tty_unregister_device(gsm_tty_driver,
base + i);
return PTR_ERR(dev);
}
}
}
return ret;
}
@ -2416,27 +2427,24 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
struct gsm_mux *gsm = tty->disc_data;
const unsigned char *dp;
char *f;
int i;
char flags = TTY_NORMAL;
if (debug & 4)
print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
cp, count);
for (i = count, dp = cp, f = fp; i; i--, dp++) {
if (f)
flags = *f++;
for (; count; count--, cp++) {
if (fp)
flags = *fp++;
switch (flags) {
case TTY_NORMAL:
gsm->receive(gsm, *dp);
gsm->receive(gsm, *cp);
break;
case TTY_OVERRUN:
case TTY_BREAK:
case TTY_PARITY:
case TTY_FRAME:
gsm_error(gsm, *dp, flags);
gsm_error(gsm, *cp, flags);
break;
default:
WARN_ONCE(1, "%s: unknown flag %d\n",
@ -2849,7 +2857,6 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
/* Line discipline for real tty */
static struct tty_ldisc_ops tty_ldisc_packet = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "n_gsm",
.open = gsmld_open,
.close = gsmld_close,
@ -3052,7 +3059,7 @@ static int gsmtty_write_room(struct tty_struct *tty)
{
struct gsm_dlci *dlci = tty->driver_data;
if (dlci->state == DLCI_CLOSED)
return -EINVAL;
return 0;
return TX_SIZE - kfifo_len(&dlci->fifo);
}
@ -3060,7 +3067,7 @@ static int gsmtty_chars_in_buffer(struct tty_struct *tty)
{
struct gsm_dlci *dlci = tty->driver_data;
if (dlci->state == DLCI_CLOSED)
return -EINVAL;
return 0;
return kfifo_len(&dlci->fifo);
}
@ -3261,8 +3268,6 @@ static int __init gsm_init(void)
gsm_tty_driver->init_termios.c_lflag &= ~ECHO;
tty_set_operations(gsm_tty_driver, &gsmtty_ops);
spin_lock_init(&gsm_mux_lock);
if (tty_register_driver(gsm_tty_driver)) {
put_tty_driver(gsm_tty_driver);
tty_unregister_ldisc(N_GSM0710);

View File

@ -100,6 +100,7 @@
#include <asm/termios.h>
#include <linux/uaccess.h>
#include "tty.h"
/*
* Buffers for individual HDLC frames
@ -787,7 +788,6 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list)
static struct tty_ldisc_ops n_hdlc_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "hdlc",
.open = n_hdlc_tty_open,
.close = n_hdlc_tty_close,

View File

@ -40,7 +40,6 @@ static void n_null_receivebuf(struct tty_struct *tty,
static struct tty_ldisc_ops null_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "n_null",
.open = n_null_open,
.close = n_null_close,

View File

@ -146,7 +146,6 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "R3964",
.open = r3964_open,
.close = r3964_close,

View File

@ -49,6 +49,7 @@
#include <linux/module.h>
#include <linux/ratelimit.h>
#include <linux/vmalloc.h>
#include "tty.h"
/*
* Until this number of characters is queued in the xmit buffer, select will
@ -2488,7 +2489,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
}
static struct tty_ldisc_ops n_tty_ops = {
.magic = TTY_LDISC_MAGIC,
.owner = THIS_MODULE,
.name = "n_tty",
.open = n_tty_open,
.close = n_tty_close,

View File

@ -47,9 +47,6 @@
#include <linux/delay.h>
#define VERSION_STRING DRIVER_DESC " 2.1d"
/* Default debug printout level */
#define NOZOMI_DEBUG_LEVEL 0x00
static int debug = NOZOMI_DEBUG_LEVEL;
@ -89,7 +86,6 @@ do { \
/* Defines */
#define NOZOMI_NAME "nozomi"
#define NOZOMI_NAME_TTY "nozomi_tty"
#define DRIVER_DESC "Nozomi driver"
#define NTTY_TTY_MAXMINORS 256
#define NTTY_FIFO_BUFFER_SIZE 8192
@ -359,12 +355,6 @@ struct nozomi {
u32 open_ttys;
};
/* This is a data packet that is read or written to/from card */
struct buffer {
u32 size; /* size is the length of the data buffer */
u8 *data;
} __attribute__ ((packed));
/* Global variables */
static const struct pci_device_id nozomi_pci_tbl[] = {
{PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */
@ -787,7 +777,6 @@ static int receive_data(enum port_type index, struct nozomi *dc)
int i, ret;
size = __le32_to_cpu(readl(addr));
/* DBG1( "%d bytes port: %d", size, index); */
if (tty && tty_throttled(tty)) {
DBG1("No room in tty, don't read data, don't ack interrupt, "
@ -1318,8 +1307,6 @@ static int nozomi_card_init(struct pci_dev *pdev,
int ndev_idx;
int i;
dev_dbg(&pdev->dev, "Init, new card found\n");
for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
if (!ndevs[ndev_idx])
break;
@ -1453,8 +1440,6 @@ static void tty_exit(struct nozomi *dc)
{
unsigned int i;
DBG1(" ");
for (i = 0; i < MAX_PORT; ++i)
tty_port_tty_hangup(&dc->port[i].port, false);
@ -1619,8 +1604,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
struct port *port = tty->driver_data;
unsigned long flags;
/* DBG1( "WRITEx: %d, index = %d", count, index); */
if (!dc || !port)
return -ENODEV;
@ -1746,8 +1729,6 @@ static int ntty_ioctl(struct tty_struct *tty,
struct port *port = tty->driver_data;
int rval = -ENOIOCTLCMD;
DBG1("******** IOCTL, cmd: %d", cmd);
switch (cmd) {
case TIOCMIWAIT: {
struct async_icount cprev = port->tty_icount;
@ -1773,7 +1754,6 @@ static void ntty_unthrottle(struct tty_struct *tty)
struct nozomi *dc = get_dc_by_tty(tty);
unsigned long flags;
DBG1("UNTHROTTLE");
spin_lock_irqsave(&dc->spin_mutex, flags);
enable_transmit_dl(tty->index % MAX_PORT, dc);
set_rts(tty, 1);
@ -1790,7 +1770,6 @@ static void ntty_throttle(struct tty_struct *tty)
struct nozomi *dc = get_dc_by_tty(tty);
unsigned long flags;
DBG1("THROTTLE");
spin_lock_irqsave(&dc->spin_mutex, flags);
set_rts(tty, 0);
spin_unlock_irqrestore(&dc->spin_mutex, flags);
@ -1847,8 +1826,6 @@ static __init int nozomi_init(void)
{
int ret;
printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
if (!ntty_driver)
return -ENOMEM;
@ -1888,7 +1865,6 @@ free_tty:
static __exit void nozomi_exit(void)
{
printk(KERN_INFO "Unloading %s\n", DRIVER_DESC);
pci_unregister_driver(&nozomi_driver);
tty_unregister_driver(ntty_driver);
put_tty_driver(ntty_driver);
@ -1898,4 +1874,4 @@ module_init(nozomi_init);
module_exit(nozomi_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_DESCRIPTION("Nozomi driver");

View File

@ -29,6 +29,7 @@
#include <linux/file.h>
#include <linux/ioctl.h>
#include <linux/compat.h>
#include "tty.h"
#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
@ -159,6 +160,7 @@ static int pty_chars_in_buffer(struct tty_struct *tty)
static int pty_set_lock(struct tty_struct *tty, int __user *arg)
{
int val;
if (get_user(val, arg))
return -EFAULT;
if (val)
@ -171,6 +173,7 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg)
static int pty_get_lock(struct tty_struct *tty, int __user *arg)
{
int locked = test_bit(TTY_PTY_LOCK, &tty->flags);
return put_user(locked, arg);
}
@ -200,6 +203,7 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
{
int pktmode = tty->packet;
return put_user(pktmode, arg);
}
@ -463,6 +467,7 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
{
struct tty_struct *pair = tty->link;
driver->ttys[tty->index] = NULL;
if (pair)
pair->driver->ttys[pair->index] = NULL;

File diff suppressed because it is too large Load Diff

View File

@ -1,111 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* rocket.h --- the exported interface of the rocket driver to its configuration program.
*
* Written by Theodore Ts'o, Copyright 1997.
* Copyright 1997 Comtrol Corporation.
*
*/
/* Model Information Struct */
typedef struct {
unsigned long model;
char modelString[80];
unsigned long numPorts;
int loadrm2;
int startingPortNumber;
} rocketModel_t;
struct rocket_config {
int line;
int flags;
int closing_wait;
int close_delay;
int port;
int reserved[32];
};
struct rocket_ports {
int tty_major;
int callout_major;
rocketModel_t rocketModel[8];
};
struct rocket_version {
char rocket_version[32];
char rocket_date[32];
char reserved[64];
};
/*
* Rocketport flags
*/
/*#define ROCKET_CALLOUT_NOHUP 0x00000001 */
#define ROCKET_FORCE_CD 0x00000002
#define ROCKET_HUP_NOTIFY 0x00000004
#define ROCKET_SPLIT_TERMIOS 0x00000008
#define ROCKET_SPD_MASK 0x00000070
#define ROCKET_SPD_HI 0x00000010 /* Use 57600 instead of 38400 bps */
#define ROCKET_SPD_VHI 0x00000020 /* Use 115200 instead of 38400 bps */
#define ROCKET_SPD_SHI 0x00000030 /* Use 230400 instead of 38400 bps */
#define ROCKET_SPD_WARP 0x00000040 /* Use 460800 instead of 38400 bps */
#define ROCKET_SAK 0x00000080
#define ROCKET_SESSION_LOCKOUT 0x00000100
#define ROCKET_PGRP_LOCKOUT 0x00000200
#define ROCKET_RTS_TOGGLE 0x00000400
#define ROCKET_MODE_MASK 0x00003000
#define ROCKET_MODE_RS232 0x00000000
#define ROCKET_MODE_RS485 0x00001000
#define ROCKET_MODE_RS422 0x00002000
#define ROCKET_FLAGS 0x00003FFF
#define ROCKET_USR_MASK 0x0071 /* Legal flags that non-privileged
* users can set or reset */
/*
* For closing_wait and closing_wait2
*/
#define ROCKET_CLOSING_WAIT_NONE ASYNC_CLOSING_WAIT_NONE
#define ROCKET_CLOSING_WAIT_INF ASYNC_CLOSING_WAIT_INF
/*
* Rocketport ioctls -- "RP"
*/
#define RCKP_GET_CONFIG 0x00525002
#define RCKP_SET_CONFIG 0x00525003
#define RCKP_GET_PORTS 0x00525004
#define RCKP_RESET_RM2 0x00525005
#define RCKP_GET_VERSION 0x00525006
/* Rocketport Models */
#define MODEL_RP32INTF 0x0001 /* RP 32 port w/external I/F */
#define MODEL_RP8INTF 0x0002 /* RP 8 port w/external I/F */
#define MODEL_RP16INTF 0x0003 /* RP 16 port w/external I/F */
#define MODEL_RP8OCTA 0x0005 /* RP 8 port w/octa cable */
#define MODEL_RP4QUAD 0x0004 /* RP 4 port w/quad cable */
#define MODEL_RP8J 0x0006 /* RP 8 port w/RJ11 connectors */
#define MODEL_RP4J 0x0007 /* RP 4 port w/RJ45 connectors */
#define MODEL_RP8SNI 0x0008 /* RP 8 port w/ DB78 SNI connector */
#define MODEL_RP16SNI 0x0009 /* RP 16 port w/ DB78 SNI connector */
#define MODEL_RPP4 0x000A /* RP Plus 4 port */
#define MODEL_RPP8 0x000B /* RP Plus 8 port */
#define MODEL_RP2_232 0x000E /* RP Plus 2 port RS232 */
#define MODEL_RP2_422 0x000F /* RP Plus 2 port RS232 */
/* Rocketmodem II Models */
#define MODEL_RP6M 0x000C /* RM 6 port */
#define MODEL_RP4M 0x000D /* RM 4 port */
/* Universal PCI boards */
#define MODEL_UPCI_RP32INTF 0x0801 /* RP UPCI 32 port w/external I/F */
#define MODEL_UPCI_RP8INTF 0x0802 /* RP UPCI 8 port w/external I/F */
#define MODEL_UPCI_RP16INTF 0x0803 /* RP UPCI 16 port w/external I/F */
#define MODEL_UPCI_RP8OCTA 0x0805 /* RP UPCI 8 port w/octa cable */
#define MODEL_UPCI_RM3_8PORT 0x080C /* RP UPCI Rocketmodem III 8 port */
#define MODEL_UPCI_RM3_4PORT 0x080C /* RP UPCI Rocketmodem III 4 port */
/* Compact PCI 16 port */
#define MODEL_CPCI_RP16INTF 0x0903 /* RP Compact PCI 16 port w/external I/F */
/* All ISA boards */
#define MODEL_ISA 0x1000

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,10 @@
#define ASPEED_VUART_ADDRL 0x28
#define ASPEED_VUART_ADDRH 0x2c
#define ASPEED_VUART_DEFAULT_LPC_ADDR 0x3f8
#define ASPEED_VUART_DEFAULT_SIRQ 4
#define ASPEED_VUART_DEFAULT_SIRQ_POLARITY IRQ_TYPE_LEVEL_LOW
struct aspeed_vuart {
struct device *dev;
void __iomem *regs;
@ -72,22 +76,31 @@ static ssize_t lpc_address_show(struct device *dev,
return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr);
}
static int aspeed_vuart_set_lpc_address(struct aspeed_vuart *vuart, u32 addr)
{
if (addr > U16_MAX)
return -EINVAL;
writeb(addr >> 8, vuart->regs + ASPEED_VUART_ADDRH);
writeb(addr >> 0, vuart->regs + ASPEED_VUART_ADDRL);
return 0;
}
static ssize_t lpc_address_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;
u32 val;
int err;
err = kstrtoul(buf, 0, &val);
err = kstrtou32(buf, 0, &val);
if (err)
return err;
writeb(val >> 8, vuart->regs + ASPEED_VUART_ADDRH);
writeb(val >> 0, vuart->regs + ASPEED_VUART_ADDRL);
return count;
err = aspeed_vuart_set_lpc_address(vuart, val);
return err ? : count;
}
static DEVICE_ATTR_RW(lpc_address);
@ -105,27 +118,37 @@ static ssize_t sirq_show(struct device *dev,
return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg);
}
static int aspeed_vuart_set_sirq(struct aspeed_vuart *vuart, u32 sirq)
{
u8 reg;
if (sirq > (ASPEED_VUART_GCRB_HOST_SIRQ_MASK >> ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT))
return -EINVAL;
sirq <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
sirq &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
reg = readb(vuart->regs + ASPEED_VUART_GCRB);
reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
reg |= sirq;
writeb(reg, vuart->regs + ASPEED_VUART_GCRB);
return 0;
}
static ssize_t sirq_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;
u8 reg;
err = kstrtoul(buf, 0, &val);
if (err)
return err;
val <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
val &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
reg = readb(vuart->regs + ASPEED_VUART_GCRB);
reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
reg |= val;
writeb(reg, vuart->regs + ASPEED_VUART_GCRB);
return count;
err = aspeed_vuart_set_sirq(vuart, val);
return err ? : count;
}
static DEVICE_ATTR_RW(sirq);
@ -297,7 +320,6 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int iir, lsr;
unsigned long flags;
int space, count;
iir = serial_port_in(port, UART_IIR);
@ -305,7 +327,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
if (iir & UART_IIR_NO_INT)
return 0;
spin_lock_irqsave(&port->lock, flags);
spin_lock(&port->lock);
lsr = serial_port_in(port, UART_LSR);
@ -341,7 +363,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
if (lsr & UART_LSR_THRE)
serial8250_tx_chars(up);
uart_unlock_and_check_sysrq(port, flags);
uart_unlock_and_check_sysrq(port);
return 1;
}
@ -367,6 +389,18 @@ static void aspeed_vuart_auto_configure_sirq_polarity(
aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0);
}
static int aspeed_vuart_map_irq_polarity(u32 dt)
{
switch (dt) {
case IRQ_TYPE_LEVEL_LOW:
return 0;
case IRQ_TYPE_LEVEL_HIGH:
return 1;
default:
return -EINVAL;
}
}
static int aspeed_vuart_probe(struct platform_device *pdev)
{
struct of_phandle_args sirq_polarity_sense_args;
@ -374,8 +408,8 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
struct aspeed_vuart *vuart;
struct device_node *np;
struct resource *res;
u32 clk, prop;
int rc;
u32 clk, prop, sirq[2];
int rc, sirq_polarity;
np = pdev->dev.of_node;
@ -482,6 +516,37 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
of_node_put(sirq_polarity_sense_args.np);
}
rc = of_property_read_u32(np, "aspeed,lpc-io-reg", &prop);
if (rc < 0)
prop = ASPEED_VUART_DEFAULT_LPC_ADDR;
rc = aspeed_vuart_set_lpc_address(vuart, prop);
if (rc < 0) {
dev_err(&pdev->dev, "invalid value in aspeed,lpc-io-reg property\n");
goto err_clk_disable;
}
rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", sirq, 2);
if (rc < 0) {
sirq[0] = ASPEED_VUART_DEFAULT_SIRQ;
sirq[1] = ASPEED_VUART_DEFAULT_SIRQ_POLARITY;
}
rc = aspeed_vuart_set_sirq(vuart, sirq[0]);
if (rc < 0) {
dev_err(&pdev->dev, "invalid sirq number in aspeed,lpc-interrupts property\n");
goto err_clk_disable;
}
sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]);
if (sirq_polarity < 0) {
dev_err(&pdev->dev, "invalid sirq polarity in aspeed,lpc-interrupts property\n");
rc = sirq_polarity;
goto err_clk_disable;
}
aspeed_vuart_set_sirq_polarity(vuart, sirq_polarity);
aspeed_vuart_set_enabled(vuart, true);
aspeed_vuart_set_host_tx_discard(vuart, true);
platform_set_drvdata(pdev, vuart);

File diff suppressed because it is too large Load Diff

View File

@ -354,7 +354,7 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
static void *
__xr17v35x_register_gpio(struct pci_dev *pcidev,
const struct property_entry *properties)
const struct software_node *node)
{
struct platform_device *pdev;
@ -365,7 +365,7 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev,
pdev->dev.parent = &pcidev->dev;
ACPI_COMPANION_SET(&pdev->dev, ACPI_COMPANION(&pcidev->dev));
if (platform_device_add_properties(pdev, properties) < 0 ||
if (device_add_software_node(&pdev->dev, node) < 0 ||
platform_device_add(pdev) < 0) {
platform_device_put(pdev);
return NULL;
@ -380,12 +380,16 @@ static const struct property_entry exar_gpio_properties[] = {
{ }
};
static const struct software_node exar_gpio_node = {
.properties = exar_gpio_properties,
};
static int xr17v35x_register_gpio(struct pci_dev *pcidev,
struct uart_8250_port *port)
{
if (pcidev->vendor == PCI_VENDOR_ID_EXAR)
port->port.private_data =
__xr17v35x_register_gpio(pcidev, exar_gpio_properties);
__xr17v35x_register_gpio(pcidev, &exar_gpio_node);
return 0;
}
@ -457,6 +461,10 @@ static const struct property_entry iot2040_gpio_properties[] = {
{ }
};
static const struct software_node iot2040_gpio_node = {
.properties = iot2040_gpio_properties,
};
static int iot2040_register_gpio(struct pci_dev *pcidev,
struct uart_8250_port *port)
{
@ -468,7 +476,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev,
writeb(IOT2040_UARTS_GPIO_HI_MODE, p + UART_EXAR_MPIOSEL_15_8);
port->port.private_data =
__xr17v35x_register_gpio(pcidev, iot2040_gpio_properties);
__xr17v35x_register_gpio(pcidev, &iot2040_gpio_node);
return 0;
}
@ -547,6 +555,7 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev)
struct uart_8250_port *port = serial8250_get_port(priv->line[0]);
struct platform_device *pdev = port->port.private_data;
device_remove_software_node(&pdev->dev);
platform_device_unregister(pdev);
port->port.private_data = NULL;
}

View File

@ -30,15 +30,14 @@ struct fsl8250_data {
int fsl8250_handle_irq(struct uart_port *port)
{
unsigned char lsr, orig_lsr;
unsigned long flags;
unsigned int iir;
struct uart_8250_port *up = up_to_u8250p(port);
spin_lock_irqsave(&up->port.lock, flags);
spin_lock(&up->port.lock);
iir = port->serial_in(port, UART_IIR);
if (iir & UART_IIR_NO_INT) {
spin_unlock_irqrestore(&up->port.lock, flags);
spin_unlock(&up->port.lock);
return 0;
}
@ -46,7 +45,7 @@ int fsl8250_handle_irq(struct uart_port *port)
if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
up->lsr_saved_flags &= ~UART_LSR_BI;
port->serial_in(port, UART_RX);
spin_unlock_irqrestore(&up->port.lock, flags);
spin_unlock(&up->port.lock);
return 1;
}
@ -82,7 +81,9 @@ int fsl8250_handle_irq(struct uart_port *port)
serial8250_tx_chars(up);
up->lsr_saved_flags = orig_lsr;
uart_unlock_and_check_sysrq(&up->port, flags);
uart_unlock_and_check_sysrq(&up->port);
return 1;
}
EXPORT_SYMBOL_GPL(fsl8250_handle_irq);
@ -104,11 +105,8 @@ static int fsl8250_acpi_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
if (irq != -EPROBE_DEFER)
dev_err(dev, "cannot get irq\n");
if (irq < 0)
return irq;
}
memset(&port8250, 0, sizeof(port8250));

View File

@ -318,6 +318,7 @@ static const struct of_device_id of_platform_serial_table[] = {
{ .compatible = "mrvl,mmp-uart",
.data = (void *)PORT_XSCALE, },
{ .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
{ .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, },
{ .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, },
{ /* end of list */ },
};

View File

@ -1143,7 +1143,6 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = up->port.private_data;
unsigned char status;
unsigned long flags;
u8 iir;
serial8250_rpm_get(up);
@ -1154,7 +1153,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
return IRQ_HANDLED;
}
spin_lock_irqsave(&port->lock, flags);
spin_lock(&port->lock);
status = serial_port_in(port, UART_LSR);
@ -1179,7 +1178,8 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
}
}
uart_unlock_and_check_sysrq(port, flags);
uart_unlock_and_check_sysrq(port);
serial8250_rpm_put(up);
return 1;
}

View File

@ -1466,13 +1466,11 @@ EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
{
struct uart_8250_em485 *em485;
struct uart_8250_port *p;
struct uart_8250_em485 *em485 = container_of(t, struct uart_8250_em485,
stop_tx_timer);
struct uart_8250_port *p = em485->port;
unsigned long flags;
em485 = container_of(t, struct uart_8250_em485, stop_tx_timer);
p = em485->port;
serial8250_rpm_get(p);
spin_lock_irqsave(&p->port.lock, flags);
if (em485->active_timer == &em485->stop_tx_timer) {
@ -1482,16 +1480,13 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
}
spin_unlock_irqrestore(&p->port.lock, flags);
serial8250_rpm_put(p);
return HRTIMER_NORESTART;
}
static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
{
long sec = msec / 1000;
long nsec = (msec % 1000) * 1000000;
ktime_t t = ktime_set(sec, nsec);
hrtimer_start(hrt, t, HRTIMER_MODE_REL);
hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL);
}
static void __stop_tx_rs485(struct uart_8250_port *p)
@ -1633,19 +1628,18 @@ static inline void start_tx_rs485(struct uart_port *port)
static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t)
{
struct uart_8250_em485 *em485;
struct uart_8250_port *p;
struct uart_8250_em485 *em485 = container_of(t, struct uart_8250_em485,
start_tx_timer);
struct uart_8250_port *p = em485->port;
unsigned long flags;
em485 = container_of(t, struct uart_8250_em485, start_tx_timer);
p = em485->port;
spin_lock_irqsave(&p->port.lock, flags);
if (em485->active_timer == &em485->start_tx_timer) {
__start_tx(&p->port);
em485->active_timer = NULL;
}
spin_unlock_irqrestore(&p->port.lock, flags);
return HRTIMER_NORESTART;
}
@ -1885,14 +1879,13 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
{
unsigned char status;
unsigned long flags;
struct uart_8250_port *up = up_to_u8250p(port);
bool skip_rx = false;
if (iir & UART_IIR_NO_INT)
return 0;
spin_lock_irqsave(&port->lock, flags);
spin_lock(&port->lock);
status = serial_port_in(port, UART_LSR);
@ -1918,7 +1911,8 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
(up->ier & UART_IER_THRI))
serial8250_tx_chars(up);
uart_unlock_and_check_sysrq(port, flags);
uart_unlock_and_check_sysrq(port);
return 1;
}
EXPORT_SYMBOL_GPL(serial8250_handle_irq);

View File

@ -15,8 +15,7 @@ config SERIAL_8250
here are those that are setting up dedicated Ethernet WWW/FTP
servers, or users that have one of the various bus mice instead of a
serial mouse and don't intend to use their machine's standard serial
port for anything. (Note that the Cyclades multi serial port driver
does not need this driver built in for it to work.)
port for anything.
To compile this driver as a module, choose M here: the
module will be called 8250.
@ -226,7 +225,7 @@ config SERIAL_8250_MANY_PORTS
serial port hardware which acts similar to standard serial port
hardware. If you only use the standard COM 1/2/3/4 ports, you can
say N here to save some memory. You can also say Y if you have an
"intelligent" multiport card such as Cyclades, Digiboards, etc.
"intelligent" multiport card such as Digiboards, etc.
#
# Multi-port serial cards
@ -404,7 +403,8 @@ config SERIAL_8250_RT288X
config SERIAL_8250_OMAP
tristate "Support for OMAP internal UART (8250 based driver)"
depends on SERIAL_8250 && (ARCH_OMAP2PLUS || ARCH_K3)
depends on SERIAL_8250
depends on ARCH_OMAP2PLUS || ARCH_K3 || COMPILE_TEST
help
If you have a machine based on an Texas Instruments OMAP CPU you
can enable its onboard serial ports by enabling this option.
@ -440,7 +440,8 @@ config SERIAL_8250_LPC18XX
config SERIAL_8250_MT6577
tristate "Mediatek serial port support"
depends on SERIAL_8250 && ARCH_MEDIATEK
depends on SERIAL_8250
depends on ARCH_MEDIATEK || COMPILE_TEST
help
If you have a Mediatek based board and want to use the
serial port, say Y to this option. If unsure, say N.
@ -510,6 +511,16 @@ config SERIAL_8250_TEGRA
Select this option if you have machine with an NVIDIA Tegra SoC and
wish to enable 8250 serial driver for the Tegra serial interfaces.
config SERIAL_8250_BCM7271
tristate "Broadcom 8250 based serial port"
depends on SERIAL_8250 && (ARCH_BRCMSTB || COMPILE_TEST)
default ARCH_BRCMSTB
help
If you have a Broadcom STB based board and want to use the
enhanced features of the Broadcom 8250 based serial port,
including DMA support and high accuracy BAUD rates, say
Y to this option. If unsure, say N.
config SERIAL_OF_PLATFORM
tristate "Devicetree based probing for 8250 ports"
depends on SERIAL_8250 && OF

View File

@ -38,6 +38,7 @@ obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o
obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o
obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt

View File

@ -456,11 +456,11 @@ static int simple_config(struct pcmcia_device *link)
* its base address, then try to grab any standard serial port
* address, and finally try to get any free port.
*/
if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
goto found_port;
dev_warn(&link->dev, "no usable port range found, giving up\n");
return -1;
ret = pcmcia_loop_config(link, simple_config_check_notpicky, NULL);
if (ret) {
dev_warn(&link->dev, "no usable port range found, giving up\n");
return ret;
}
found_port:
if (info->multi && (info->manfid == MANFID_3COM))
@ -474,7 +474,7 @@ found_port:
ret = pcmcia_enable_device(link);
if (ret != 0)
return -1;
return ret;
return setup_serial(link, info, link->resource[0]->start, link->irq);
}

View File

@ -20,7 +20,7 @@ comment "Non-8250 serial port support"
config SERIAL_AMBA_PL010
tristate "ARM AMBA PL010 serial port support"
depends on ARM_AMBA
depends on ARM_AMBA || COMPILE_TEST
select SERIAL_CORE
help
This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
@ -198,7 +198,7 @@ config SERIAL_KGDB_NMI
config SERIAL_MESON
tristate "Meson serial port support"
depends on ARCH_MESON
depends on ARCH_MESON || COMPILE_TEST
select SERIAL_CORE
help
This enables the driver for the on-chip UARTs of the Amlogic
@ -236,7 +236,7 @@ config SERIAL_CLPS711X_CONSOLE
config SERIAL_SAMSUNG
tristate "Samsung SoC serial support"
depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_APPLE || COMPILE_TEST
select SERIAL_CORE
help
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
@ -278,7 +278,7 @@ config SERIAL_SAMSUNG_CONSOLE
config SERIAL_TEGRA
tristate "NVIDIA Tegra20/30 SoC serial controller"
depends on ARCH_TEGRA && TEGRA20_APB_DMA
depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
select SERIAL_CORE
help
Support for the on-chip UARTs on the NVIDIA Tegra series SOCs
@ -289,7 +289,8 @@ config SERIAL_TEGRA
config SERIAL_TEGRA_TCU
tristate "NVIDIA Tegra Combined UART"
depends on ARCH_TEGRA && TEGRA_HSP_MBOX
depends on MAILBOX
depends on (ARCH_TEGRA && TEGRA_HSP_MBOX) || COMPILE_TEST
select SERIAL_CORE
help
Support for the mailbox-based TCU (Tegra Combined UART) serial port.
@ -498,6 +499,7 @@ config SERIAL_IMX_EARLYCON
bool "Earlycon on IMX serial port"
depends on ARCH_MXC || COMPILE_TEST
depends on OF
select SERIAL_CORE
select SERIAL_EARLYCON
select SERIAL_CORE_CONSOLE
default y if SERIAL_IMX_CONSOLE
@ -851,7 +853,8 @@ config SERIAL_MPC52xx_CONSOLE_BAUD
config SERIAL_ICOM
tristate "IBM Multiport Serial Adapter"
depends on PCI && PPC_PSERIES
depends on PCI
depends on PPC_PSERIES || COMPILE_TEST
select SERIAL_CORE
select FW_LOADER
help
@ -920,7 +923,7 @@ config SERIAL_JSM
config SERIAL_MSM
tristate "MSM on-chip serial port support"
depends on ARCH_QCOM
depends on ARCH_QCOM || COMPILE_TEST
select SERIAL_CORE
config SERIAL_MSM_CONSOLE
@ -946,7 +949,7 @@ config SERIAL_QCOM_GENI_CONSOLE
config SERIAL_VT8500
bool "VIA VT8500 on-chip serial port support"
depends on ARCH_VT8500
depends on ARCH_VT8500 || COMPILE_TEST
select SERIAL_CORE
config SERIAL_VT8500_CONSOLE
@ -956,7 +959,7 @@ config SERIAL_VT8500_CONSOLE
config SERIAL_OMAP
tristate "OMAP serial port support"
depends on ARCH_OMAP2PLUS
depends on ARCH_OMAP2PLUS || COMPILE_TEST
select SERIAL_CORE
help
If you have a machine based on an Texas Instruments OMAP CPU you

View File

@ -131,9 +131,7 @@ static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
uart_insert_char(port, 0, 0, ch, flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)

View File

@ -243,9 +243,7 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static void altera_uart_tx_chars(struct altera_uart *pp)

View File

@ -159,9 +159,7 @@ static void pl010_rx_chars(struct uart_amba_port *uap)
ignore_char:
status = readb(uap->port.membase + UART01x_FR);
}
spin_unlock(&uap->port.lock);
tty_flip_buffer_push(&uap->port.state->port);
spin_lock(&uap->port.lock);
}
static void pl010_tx_chars(struct uart_amba_port *uap)

View File

@ -937,12 +937,10 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
fifotaken = pl011_fifo_to_tty(uap);
}
spin_unlock(&uap->port.lock);
dev_vdbg(uap->port.dev,
"Took %d chars from DMA buffer and %d chars from the FIFO\n",
dma_count, fifotaken);
tty_flip_buffer_push(port);
spin_lock(&uap->port.lock);
}
static void pl011_dma_rx_irq(struct uart_amba_port *uap)

View File

@ -117,9 +117,7 @@ static void apbuart_rx_chars(struct uart_port *port)
status = UART_GET_STATUS(port);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static void apbuart_tx_chars(struct uart_port *port)

View File

@ -385,9 +385,7 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)
tty_insert_flip_char(port, ch, TTY_NORMAL);
} while (max_count-- > 0);
spin_unlock(&up->port.lock);
tty_flip_buffer_push(port);
spin_lock(&up->port.lock);
}
static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)

View File

@ -236,9 +236,7 @@ static void arc_serial_rx_chars(struct uart_port *port, unsigned int status)
if (!(uart_handle_sysrq_char(port, ch)))
uart_insert_char(port, status, RXOERR, ch, flg);
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
} while (!((status = UART_GET_STATUS(port)) & RXEMPTY));
}

View File

@ -1178,13 +1178,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
1,
DMA_FROM_DEVICE);
/*
* Drop the lock here since it might end up calling
* uart_start(), which takes the lock.
*/
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
}
@ -1576,13 +1570,7 @@ static void atmel_rx_from_ring(struct uart_port *port)
uart_insert_char(port, status, ATMEL_US_OVRE, c.ch, flg);
}
/*
* Drop the lock here since it might end up calling
* uart_start(), which takes the lock.
*/
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static void atmel_release_rx_pdc(struct uart_port *port)
@ -1667,13 +1655,7 @@ static void atmel_rx_from_pdc(struct uart_port *port)
}
} while (head >= pdc->dma_size);
/*
* Drop the lock here since it might end up calling
* uart_start(), which takes the lock.
*/
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
atmel_uart_writel(port, ATMEL_US_IER,
ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);

View File

@ -294,9 +294,7 @@ static void bcm_uart_do_rx(struct uart_port *port)
} while (--max_count);
spin_unlock(&port->lock);
tty_flip_buffer_push(tty_port);
spin_lock(&port->lock);
}
/*

View File

@ -829,9 +829,7 @@ ignore_char:
}
icom_port->next_rcv = rcv_buff;
spin_unlock(&icom_port->uart_port.lock);
tty_flip_buffer_push(port);
spin_lock(&icom_port->uart_port.lock);
}
static void process_interrupt(u16 port_int_reg,

View File

@ -394,11 +394,7 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
{
long sec = msec / MSEC_PER_SEC;
long nsec = (msec % MSEC_PER_SEC) * 1000000;
ktime_t t = ktime_set(sec, nsec);
hrtimer_start(hrt, t, HRTIMER_MODE_REL);
hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL);
}
/* called with port.lock taken and irqs off */
@ -922,14 +918,8 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
struct imx_port *sport = dev_id;
unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4;
irqreturn_t ret = IRQ_NONE;
unsigned long flags = 0;
/*
* IRQs might not be disabled upon entering this interrupt handler,
* e.g. when interrupt handlers are forced to be threaded. To support
* this scenario as well, disable IRQs when acquiring the spinlock.
*/
spin_lock_irqsave(&sport->port.lock, flags);
spin_lock(&sport->port.lock);
usr1 = imx_uart_readl(sport, USR1);
usr2 = imx_uart_readl(sport, USR2);
@ -999,7 +989,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
ret = IRQ_HANDLED;
}
spin_unlock_irqrestore(&sport->port.lock, flags);
spin_unlock(&sport->port.lock);
return ret;
}

View File

@ -603,18 +603,22 @@ void jsm_input(struct jsm_channel *ch)
if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
for (i = 0; i < s; i++) {
u8 chr = ch->ch_rqueue[tail + i];
u8 error = ch->ch_equeue[tail + i];
char flag = TTY_NORMAL;
/*
* Give the Linux ld the flags in the
* format it likes.
* Give the Linux ld the flags in the format it
* likes.
*/
if (*(ch->ch_equeue + tail + i) & UART_LSR_BI)
tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_BREAK);
else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE)
tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_PARITY);
else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE)
tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_FRAME);
else
tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
if (error & UART_LSR_BI)
flag = TTY_BREAK;
else if (error & UART_LSR_PE)
flag = TTY_PARITY;
else if (error & UART_LSR_FE)
flag = TTY_FRAME;
tty_insert_flip_char(port, chr, flag);
}
} else {
tty_insert_flip_string(port, ch->ch_rqueue + tail, s);

View File

@ -373,9 +373,7 @@ int kgdb_unregister_nmi_console(void)
if (ret)
return ret;
ret = tty_unregister_driver(kgdb_nmi_tty_driver);
if (ret)
return ret;
tty_unregister_driver(kgdb_nmi_tty_driver);
put_tty_driver(kgdb_nmi_tty_driver);
return 0;

View File

@ -270,8 +270,8 @@ static int liteuart_probe(struct platform_device *pdev)
/* get membase */
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (!port->membase)
return -ENXIO;
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);
/* values not from device tree */
port->dev = &pdev->dev;

View File

@ -273,9 +273,7 @@ static void __serial_lpc32xx_rx(struct uart_port *port)
tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
}
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
}
static void __serial_lpc32xx_tx(struct uart_port *port)

View File

@ -273,7 +273,7 @@ struct max310x_port {
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio;
#endif
struct max310x_one p[0];
struct max310x_one p[];
};
static struct uart_driver max310x_uart = {

View File

@ -319,9 +319,7 @@ static void mcf_rx_chars(struct mcf_uart *pp)
uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
/****************************************************************************/

View File

@ -226,9 +226,7 @@ static void meson_receive_chars(struct uart_port *port)
} while (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY));
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
}
static irqreturn_t meson_uart_interrupt(int irq, void *dev_id)

View File

@ -1421,9 +1421,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
}
}
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
return psc_ops->raw_rx_rdy(port);
}

View File

@ -757,9 +757,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
count -= r_count;
}
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
if (misr & (UART_IMR_RXSTALE))
msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
@ -819,9 +817,7 @@ static void msm_handle_rx(struct uart_port *port)
tty_insert_flip_char(tport, c, flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
}
static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count)

View File

@ -159,6 +159,8 @@ struct uart_omap_port {
u32 calc_latency;
struct work_struct qos_work;
bool is_suspending;
unsigned int rs485_tx_filter_count;
};
#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
@ -302,7 +304,8 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_out(up, UART_OMAP_SCR, up->scr);
res = (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ?
1 : 0;
if (gpiod_get_value(up->rts_gpiod) != res) {
if (up->rts_gpiod &&
gpiod_get_value(up->rts_gpiod) != res) {
if (port->rs485.delay_rts_after_send > 0)
mdelay(
port->rs485.delay_rts_after_send);
@ -328,19 +331,6 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
/*
* Empty the RX FIFO, we are not interested in anything
* received during the half-duplex transmission.
*/
serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_RCVR);
/* Re-enable RX interrupts */
up->ier |= UART_IER_RLSI | UART_IER_RDI;
up->port.read_status_mask |= UART_LSR_DR;
serial_out(up, UART_IER, up->ier);
}
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
@ -366,6 +356,10 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
serial_out(up, UART_TX, up->port.x_char);
up->port.icount.tx++;
up->port.x_char = 0;
if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
up->rs485_tx_filter_count++;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
@ -377,6 +371,10 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->port.icount.tx++;
if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
up->rs485_tx_filter_count++;
if (uart_circ_empty(xmit))
break;
} while (--count > 0);
@ -411,7 +409,7 @@ static void serial_omap_start_tx(struct uart_port *port)
/* if rts not already enabled */
res = (port->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
if (gpiod_get_value(up->rts_gpiod) != res) {
if (up->rts_gpiod && gpiod_get_value(up->rts_gpiod) != res) {
gpiod_set_value(up->rts_gpiod, res);
if (port->rs485.delay_rts_before_send > 0)
mdelay(port->rs485.delay_rts_before_send);
@ -420,7 +418,7 @@ static void serial_omap_start_tx(struct uart_port *port)
if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX))
serial_omap_stop_rx(port);
up->rs485_tx_filter_count = 0;
serial_omap_enable_ier_thri(up);
pm_runtime_mark_last_busy(up->dev);
@ -491,8 +489,13 @@ static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr)
* Read one data character out to avoid stalling the receiver according
* to the table 23-246 of the omap4 TRM.
*/
if (likely(lsr & UART_LSR_DR))
if (likely(lsr & UART_LSR_DR)) {
serial_in(up, UART_RX);
if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
!(up->port.rs485.flags & SER_RS485_RX_DURING_TX) &&
up->rs485_tx_filter_count)
up->rs485_tx_filter_count--;
}
up->port.icount.rx++;
flag = TTY_NORMAL;
@ -543,6 +546,13 @@ static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)
return;
ch = serial_in(up, UART_RX);
if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
!(up->port.rs485.flags & SER_RS485_RX_DURING_TX) &&
up->rs485_tx_filter_count) {
up->rs485_tx_filter_count--;
return;
}
flag = TTY_NORMAL;
up->port.icount.rx++;
@ -1407,18 +1417,13 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
/* store new config */
port->rs485 = *rs485;
/*
* Just as a precaution, only allow rs485
* to be enabled if the gpio pin is valid
*/
if (up->rts_gpiod) {
/* enable / disable rts */
val = (port->rs485.flags & SER_RS485_ENABLED) ?
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
val = (port->rs485.flags & val) ? 1 : 0;
gpiod_set_value(up->rts_gpiod, val);
} else
port->rs485.flags &= ~SER_RS485_ENABLED;
}
/* Enable interrupts */
up->ier = mode;

View File

@ -247,9 +247,7 @@ static void owl_uart_receive_chars(struct uart_port *port)
stat = owl_uart_read(port, OWL_UART_STAT);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static irqreturn_t owl_uart_irq(int irq, void *dev_id)

View File

@ -236,7 +236,6 @@ struct eg20t_port {
void *rx_buf_virt;
dma_addr_t rx_buf_dma;
struct dentry *debugfs;
#define IRQ_NAME_SIZE 17
char irq_name[IRQ_NAME_SIZE];
@ -292,8 +291,6 @@ static const int trigger_level_64[4] = { 1, 16, 32, 56 };
static const int trigger_level_16[4] = { 1, 4, 8, 14 };
static const int trigger_level_1[4] = { 1, 1, 1, 1 };
#ifdef CONFIG_DEBUG_FS
#define PCH_REGS_BUFSIZE 1024
@ -353,7 +350,6 @@ static const struct file_operations port_regs_ops = {
.read = port_show_regs,
.llseek = default_llseek,
};
#endif /* CONFIG_DEBUG_FS */
static const struct dmi_system_id pch_uart_dmi_table[] = {
{
@ -1735,9 +1731,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
int fifosize;
int port_type;
struct pch_uart_driver_data *board;
#ifdef CONFIG_DEBUG_FS
char name[32]; /* for debugfs file name */
#endif
char name[32];
board = &drv_dat[id->driver_data];
port_type = board->port_type;
@ -1813,11 +1807,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
if (ret < 0)
goto init_port_hal_free;
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof(name), "uart%d_regs", board->line_no);
priv->debugfs = debugfs_create_file(name, S_IFREG | S_IRUGO,
NULL, priv, &port_regs_ops);
#endif
snprintf(name, sizeof(name), "uart%d_regs", priv->port.line);
debugfs_create_file(name, S_IFREG | S_IRUGO, NULL, priv,
&port_regs_ops);
return priv;
@ -1835,10 +1827,10 @@ init_port_alloc_err:
static void pch_uart_exit_port(struct eg20t_port *priv)
{
char name[32];
#ifdef CONFIG_DEBUG_FS
debugfs_remove(priv->debugfs);
#endif
snprintf(name, sizeof(name), "uart%d_regs", priv->port.line);
debugfs_remove(debugfs_lookup(name, NULL));
uart_remove_one_port(&pch_uart_driver, &priv->port);
free_page((unsigned long)priv->rxbuf.buf);
}

View File

@ -818,7 +818,6 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
u32 s_irq_status;
u32 geni_status;
struct uart_port *uport = dev;
unsigned long flags;
bool drop_rx = false;
struct tty_port *tport = &uport->state->port;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
@ -826,7 +825,8 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
if (uport->suspended)
return IRQ_NONE;
spin_lock_irqsave(&uport->lock, flags);
spin_lock(&uport->lock);
m_irq_status = readl(uport->membase + SE_GENI_M_IRQ_STATUS);
s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
geni_status = readl(uport->membase + SE_GENI_STATUS);
@ -861,7 +861,7 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
qcom_geni_serial_handle_rx(uport, drop_rx);
out_unlock:
uart_unlock_and_check_sysrq(uport, flags);
uart_unlock_and_check_sysrq(uport);
return IRQ_HANDLED;
}

View File

@ -398,9 +398,7 @@ static void rda_uart_receive_chars(struct uart_port *port)
status = rda_uart_read(port, RDA_UART_STATUS);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static irqreturn_t rda_interrupt(int irq, void *dev_id)

View File

@ -424,9 +424,7 @@ static void rp2_rx_chars(struct rp2_uart_port *up)
up->port.icount.rx++;
}
spin_unlock(&up->port.lock);
tty_flip_buffer_push(port);
spin_lock(&up->port.lock);
}
static void rp2_tx_chars(struct rp2_uart_port *up)

View File

@ -223,9 +223,7 @@ sa1100_rx_chars(struct sa1100_port *sport)
UTSR0_TO_SM(UART_GET_UTSR0(sport));
}
spin_unlock(&sport->port.lock);
tty_flip_buffer_push(&sport->port.state->port);
spin_lock(&sport->port.lock);
}
static void sa1100_tx_chars(struct sa1100_port *sport)

View File

@ -56,9 +56,16 @@
/* flag to ignore all characters coming in */
#define RXSTAT_DUMMY_READ (0x10000000)
enum s3c24xx_port_type {
TYPE_S3C24XX,
TYPE_S3C6400,
TYPE_APPLE_S5L,
};
struct s3c24xx_uart_info {
char *name;
unsigned int type;
enum s3c24xx_port_type type;
unsigned int port_type;
unsigned int fifosize;
unsigned long rx_fifomask;
unsigned long rx_fifoshift;
@ -70,6 +77,7 @@ struct s3c24xx_uart_info {
unsigned long num_clks;
unsigned long clksel_mask;
unsigned long clksel_shift;
unsigned long ucon_mask;
/* uart port features */
@ -144,6 +152,8 @@ struct s3c24xx_uart_port {
#endif
};
static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport);
/* conversion functions */
#define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev)
@ -228,16 +238,6 @@ static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
}
/*
* s3c64xx and later SoC's include the interrupt mask and status registers in
* the controller itself, unlike the s3c24xx SoC's which have these registers
* in the interrupt controller. Check if the port type is s3c64xx or higher.
*/
static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port)
{
return to_ourport(port)->info->type == PORT_S3C6400;
}
static void s3c24xx_serial_rx_enable(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
@ -289,10 +289,17 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
if (!ourport->tx_enabled)
return;
if (s3c24xx_serial_has_interrupt_mask(port))
switch (ourport->info->type) {
case TYPE_S3C6400:
s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
else
break;
case TYPE_APPLE_S5L:
s3c24xx_clear_bit(port, APPLE_S5L_UCON_TXTHRESH_ENA, S3C2410_UCON);
break;
default:
disable_irq_nosync(ourport->tx_irq);
break;
}
if (dma && dma->tx_chan && ourport->tx_in_progress == S3C24XX_TX_DMA) {
dmaengine_pause(dma->tx_chan);
@ -353,10 +360,17 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
u32 ucon;
/* Mask Tx interrupt */
if (s3c24xx_serial_has_interrupt_mask(port))
switch (ourport->info->type) {
case TYPE_S3C6400:
s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
else
break;
case TYPE_APPLE_S5L:
WARN_ON(1); // No DMA
break;
default:
disable_irq_nosync(ourport->tx_irq);
break;
}
/* Enable tx dma mode */
ucon = rd_regl(port, S3C2410_UCON);
@ -386,13 +400,28 @@ static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
wr_regl(port, S3C2410_UCON, ucon);
/* Unmask Tx interrupt */
if (s3c24xx_serial_has_interrupt_mask(port))
switch (ourport->info->type) {
case TYPE_S3C6400:
s3c24xx_clear_bit(port, S3C64XX_UINTM_TXD,
S3C64XX_UINTM);
else
break;
case TYPE_APPLE_S5L:
ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK;
wr_regl(port, S3C2410_UCON, ucon);
break;
default:
enable_irq(ourport->tx_irq);
break;
}
ourport->tx_mode = S3C24XX_TX_PIO;
/*
* The Apple version only has edge triggered TX IRQs, so we need
* to kick off the process by sending some characters here.
*/
if (ourport->info->type == TYPE_APPLE_S5L)
s3c24xx_serial_tx_chars(ourport);
}
static void s3c24xx_serial_start_tx_pio(struct s3c24xx_uart_port *ourport)
@ -513,11 +542,19 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
if (ourport->rx_enabled) {
dev_dbg(port->dev, "stopping rx\n");
if (s3c24xx_serial_has_interrupt_mask(port))
switch (ourport->info->type) {
case TYPE_S3C6400:
s3c24xx_set_bit(port, S3C64XX_UINTM_RXD,
S3C64XX_UINTM);
else
break;
case TYPE_APPLE_S5L:
s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
break;
default:
disable_irq_nosync(ourport->rx_irq);
break;
}
ourport->rx_enabled = 0;
}
if (dma && dma->rx_chan) {
@ -651,14 +688,18 @@ static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
/* set Rx mode to DMA mode */
ucon = rd_regl(port, S3C2410_UCON);
ucon &= ~(S3C64XX_UCON_TIMEOUT_MASK |
S3C64XX_UCON_EMPTYINT_EN |
S3C64XX_UCON_DMASUS_EN |
S3C64XX_UCON_TIMEOUT_EN |
S3C64XX_UCON_RXMODE_MASK);
ucon |= 0xf << S3C64XX_UCON_TIMEOUT_SHIFT |
S3C64XX_UCON_TIMEOUT_EN |
S3C64XX_UCON_RXMODE_CPU;
ucon &= ~S3C64XX_UCON_RXMODE_MASK;
ucon |= S3C64XX_UCON_RXMODE_CPU;
/* Apple types use these bits for IRQ masks */
if (ourport->info->type != TYPE_APPLE_S5L) {
ucon &= ~(S3C64XX_UCON_TIMEOUT_MASK |
S3C64XX_UCON_EMPTYINT_EN |
S3C64XX_UCON_DMASUS_EN |
S3C64XX_UCON_TIMEOUT_EN);
ucon |= 0xf << S3C64XX_UCON_TIMEOUT_SHIFT |
S3C64XX_UCON_TIMEOUT_EN;
}
wr_regl(port, S3C2410_UCON, ucon);
ourport->rx_mode = S3C24XX_RX_PIO;
@ -674,13 +715,12 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
struct s3c24xx_uart_dma *dma = ourport->dma;
struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
struct tty_port *t = &port->state->port;
unsigned long flags;
struct dma_tx_state state;
utrstat = rd_regl(port, S3C2410_UTRSTAT);
rd_regl(port, S3C2410_UFSTAT);
spin_lock_irqsave(&port->lock, flags);
spin_lock(&port->lock);
if (!(utrstat & S3C2410_UTRSTAT_TIMEOUT)) {
s3c64xx_start_rx_dma(ourport);
@ -709,7 +749,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
wr_regl(port, S3C2410_UTRSTAT, S3C2410_UTRSTAT_TIMEOUT);
finish:
spin_unlock_irqrestore(&port->lock, flags);
spin_unlock(&port->lock);
return IRQ_HANDLED;
}
@ -805,16 +845,15 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
{
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
spin_lock(&port->lock);
s3c24xx_serial_rx_drain_fifo(ourport);
spin_unlock_irqrestore(&port->lock, flags);
spin_unlock(&port->lock);
return IRQ_HANDLED;
}
static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
static irqreturn_t s3c24xx_serial_rx_irq(int irq, void *dev_id)
{
struct s3c24xx_uart_port *ourport = dev_id;
@ -823,16 +862,12 @@ static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
return s3c24xx_serial_rx_chars_pio(dev_id);
}
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit;
unsigned long flags;
int count, dma_count = 0;
spin_lock_irqsave(&port->lock, flags);
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
if (ourport->dma && ourport->dma->tx_chan &&
@ -849,7 +884,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
wr_reg(port, S3C2410_UTXH, port->x_char);
port->icount.tx++;
port->x_char = 0;
goto out;
return;
}
/* if there isn't anything more to transmit, or the uart is now
@ -858,7 +893,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
s3c24xx_serial_stop_tx(port);
goto out;
return;
}
/* try and drain the buffer... */
@ -880,7 +915,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
if (!count && dma_count) {
s3c24xx_serial_start_tx_dma(ourport, dma_count);
goto out;
return;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
@ -891,9 +926,18 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
if (uart_circ_empty(xmit))
s3c24xx_serial_stop_tx(port);
}
out:
spin_unlock_irqrestore(&port->lock, flags);
static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
spin_lock(&port->lock);
s3c24xx_serial_tx_chars(ourport);
spin_unlock(&port->lock);
return IRQ_HANDLED;
}
@ -906,16 +950,37 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
irqreturn_t ret = IRQ_HANDLED;
if (pend & S3C64XX_UINTM_RXD_MSK) {
ret = s3c24xx_serial_rx_chars(irq, id);
ret = s3c24xx_serial_rx_irq(irq, id);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
}
if (pend & S3C64XX_UINTM_TXD_MSK) {
ret = s3c24xx_serial_tx_chars(irq, id);
ret = s3c24xx_serial_tx_irq(irq, id);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
}
return ret;
}
/* interrupt handler for Apple SoC's.*/
static irqreturn_t apple_serial_handle_irq(int irq, void *id)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
unsigned int pend = rd_regl(port, S3C2410_UTRSTAT);
irqreturn_t ret = IRQ_NONE;
if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) {
wr_regl(port, S3C2410_UTRSTAT,
APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO);
ret = s3c24xx_serial_rx_irq(irq, id);
}
if (pend & APPLE_S5L_UTRSTAT_TXTHRESH) {
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_TXTHRESH);
ret = s3c24xx_serial_tx_irq(irq, id);
}
return ret;
}
static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
@ -1098,27 +1163,62 @@ static void s3c24xx_serial_shutdown(struct uart_port *port)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (ourport->tx_claimed) {
if (!s3c24xx_serial_has_interrupt_mask(port))
free_irq(ourport->tx_irq, ourport);
free_irq(ourport->tx_irq, ourport);
ourport->tx_enabled = 0;
ourport->tx_claimed = 0;
ourport->tx_mode = 0;
}
if (ourport->rx_claimed) {
if (!s3c24xx_serial_has_interrupt_mask(port))
free_irq(ourport->rx_irq, ourport);
free_irq(ourport->rx_irq, ourport);
ourport->rx_claimed = 0;
ourport->rx_enabled = 0;
}
/* Clear pending interrupts and mask all interrupts */
if (s3c24xx_serial_has_interrupt_mask(port)) {
free_irq(port->irq, ourport);
if (ourport->dma)
s3c24xx_serial_release_dma(ourport);
wr_regl(port, S3C64XX_UINTP, 0xf);
wr_regl(port, S3C64XX_UINTM, 0xf);
}
ourport->tx_in_progress = 0;
}
static void s3c64xx_serial_shutdown(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
ourport->tx_enabled = 0;
ourport->tx_mode = 0;
ourport->rx_enabled = 0;
free_irq(port->irq, ourport);
wr_regl(port, S3C64XX_UINTP, 0xf);
wr_regl(port, S3C64XX_UINTM, 0xf);
if (ourport->dma)
s3c24xx_serial_release_dma(ourport);
ourport->tx_in_progress = 0;
}
static void apple_s5l_serial_shutdown(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
unsigned int ucon;
ucon = rd_regl(port, S3C2410_UCON);
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK);
wr_regl(port, S3C2410_UCON, ucon);
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
free_irq(port->irq, ourport);
ourport->tx_enabled = 0;
ourport->tx_mode = 0;
ourport->rx_enabled = 0;
if (ourport->dma)
s3c24xx_serial_release_dma(ourport);
@ -1133,7 +1233,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
ourport->rx_enabled = 1;
ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_irq, 0,
s3c24xx_serial_portname(port), ourport);
if (ret != 0) {
@ -1147,7 +1247,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
ourport->tx_enabled = 1;
ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_irq, 0,
s3c24xx_serial_portname(port), ourport);
if (ret) {
@ -1193,9 +1293,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
/* For compatibility with s3c24xx Soc's */
ourport->rx_enabled = 1;
ourport->rx_claimed = 1;
ourport->tx_enabled = 0;
ourport->tx_claimed = 1;
spin_lock_irqsave(&port->lock, flags);
@ -1215,6 +1313,45 @@ static int s3c64xx_serial_startup(struct uart_port *port)
return ret;
}
static int apple_s5l_serial_startup(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
unsigned long flags;
unsigned int ufcon;
int ret;
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
ret = request_irq(port->irq, apple_serial_handle_irq, 0,
s3c24xx_serial_portname(port), ourport);
if (ret) {
dev_err(port->dev, "cannot get irq %d\n", port->irq);
return ret;
}
/* For compatibility with s3c24xx Soc's */
ourport->rx_enabled = 1;
ourport->tx_enabled = 0;
spin_lock_irqsave(&port->lock, flags);
ufcon = rd_regl(port, S3C2410_UFCON);
ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
if (!uart_console(port))
ufcon |= S3C2410_UFCON_RESETTX;
wr_regl(port, S3C2410_UFCON, ufcon);
enable_rx_pio(ourport);
spin_unlock_irqrestore(&port->lock, flags);
/* Enable Rx Interrupt */
s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
return ret;
}
/* power power management control */
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
@ -1535,41 +1672,26 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
static const char *s3c24xx_serial_type(struct uart_port *port)
{
switch (port->type) {
case PORT_S3C2410:
return "S3C2410";
case PORT_S3C2440:
return "S3C2440";
case PORT_S3C2412:
return "S3C2412";
case PORT_S3C6400:
struct s3c24xx_uart_port *ourport = to_ourport(port);
switch (ourport->info->type) {
case TYPE_S3C24XX:
return "S3C24XX";
case TYPE_S3C6400:
return "S3C6400/10";
case TYPE_APPLE_S5L:
return "APPLE S5L";
default:
return NULL;
}
}
#define MAP_SIZE (0x100)
static void s3c24xx_serial_release_port(struct uart_port *port)
{
release_mem_region(port->mapbase, MAP_SIZE);
}
static int s3c24xx_serial_request_port(struct uart_port *port)
{
const char *name = s3c24xx_serial_portname(port);
return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
}
static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
if (flags & UART_CONFIG_TYPE &&
s3c24xx_serial_request_port(port) == 0)
port->type = info->type;
if (flags & UART_CONFIG_TYPE)
port->type = info->port_type;
}
/*
@ -1580,7 +1702,7 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
if (ser->type != PORT_UNKNOWN && ser->type != info->type)
if (ser->type != PORT_UNKNOWN && ser->type != info->port_type)
return -EINVAL;
return 0;
@ -1608,7 +1730,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
unsigned char c);
#endif
static struct uart_ops s3c24xx_serial_ops = {
static const struct uart_ops s3c24xx_serial_ops = {
.pm = s3c24xx_serial_pm,
.tx_empty = s3c24xx_serial_tx_empty,
.get_mctrl = s3c24xx_serial_get_mctrl,
@ -1621,8 +1743,48 @@ static struct uart_ops s3c24xx_serial_ops = {
.shutdown = s3c24xx_serial_shutdown,
.set_termios = s3c24xx_serial_set_termios,
.type = s3c24xx_serial_type,
.release_port = s3c24xx_serial_release_port,
.request_port = s3c24xx_serial_request_port,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
.poll_get_char = s3c24xx_serial_get_poll_char,
.poll_put_char = s3c24xx_serial_put_poll_char,
#endif
};
static const struct uart_ops s3c64xx_serial_ops = {
.pm = s3c24xx_serial_pm,
.tx_empty = s3c24xx_serial_tx_empty,
.get_mctrl = s3c24xx_serial_get_mctrl,
.set_mctrl = s3c24xx_serial_set_mctrl,
.stop_tx = s3c24xx_serial_stop_tx,
.start_tx = s3c24xx_serial_start_tx,
.stop_rx = s3c24xx_serial_stop_rx,
.break_ctl = s3c24xx_serial_break_ctl,
.startup = s3c64xx_serial_startup,
.shutdown = s3c64xx_serial_shutdown,
.set_termios = s3c24xx_serial_set_termios,
.type = s3c24xx_serial_type,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
.poll_get_char = s3c24xx_serial_get_poll_char,
.poll_put_char = s3c24xx_serial_put_poll_char,
#endif
};
static const struct uart_ops apple_s5l_serial_ops = {
.pm = s3c24xx_serial_pm,
.tx_empty = s3c24xx_serial_tx_empty,
.get_mctrl = s3c24xx_serial_get_mctrl,
.set_mctrl = s3c24xx_serial_set_mctrl,
.stop_tx = s3c24xx_serial_stop_tx,
.start_tx = s3c24xx_serial_start_tx,
.stop_rx = s3c24xx_serial_stop_rx,
.break_ctl = s3c24xx_serial_break_ctl,
.startup = apple_s5l_serial_startup,
.shutdown = apple_s5l_serial_shutdown,
.set_termios = s3c24xx_serial_set_termios,
.type = s3c24xx_serial_type,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
@ -1706,14 +1868,9 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
unsigned long ucon = rd_regl(port, S3C2410_UCON);
unsigned int ucon_mask;
ucon_mask = info->clksel_mask;
if (info->type == PORT_S3C2440)
ucon_mask |= S3C2440_UCON0_DIVMASK;
ucon &= ucon_mask;
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
ucon &= (info->clksel_mask | info->ucon_mask);
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
/* reset both fifos */
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
@ -1868,10 +2025,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
/* setup info for port */
port->dev = &platdev->dev;
/* Startup sequence is different for s3c64xx and higher SoC's */
if (s3c24xx_serial_has_interrupt_mask(port))
s3c24xx_serial_ops.startup = s3c64xx_serial_startup;
port->uartclk = 1;
if (cfg->uart_flags & UPF_CONS_FLOW) {
@ -1889,8 +2042,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
dev_dbg(port->dev, "resource %pR)\n", res);
port->membase = devm_ioremap(port->dev, res->start, resource_size(res));
if (!port->membase) {
port->membase = devm_ioremap_resource(port->dev, res);
if (IS_ERR(port->membase)) {
dev_err(port->dev, "failed to remap controller address\n");
return -EBUSY;
}
@ -1905,11 +2058,16 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->tx_irq = ret + 1;
}
if (!s3c24xx_serial_has_interrupt_mask(port)) {
switch (ourport->info->type) {
case TYPE_S3C24XX:
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
break;
default:
break;
}
/*
* DMA is currently supported only on DT platforms, if DMA properties
* are specified.
@ -1945,10 +2103,26 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
pr_warn("uart: failed to enable baudclk\n");
/* Keep all interrupts masked and cleared */
if (s3c24xx_serial_has_interrupt_mask(port)) {
switch (ourport->info->type) {
case TYPE_S3C6400:
wr_regl(port, S3C64XX_UINTM, 0xf);
wr_regl(port, S3C64XX_UINTP, 0xf);
wr_regl(port, S3C64XX_UINTSP, 0xf);
break;
case TYPE_APPLE_S5L: {
unsigned int ucon;
ucon = rd_regl(port, S3C2410_UCON);
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK);
wr_regl(port, S3C2410_UCON, ucon);
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
break;
}
default:
break;
}
dev_dbg(port->dev, "port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
@ -2019,6 +2193,18 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
dev_get_platdata(&pdev->dev) :
ourport->drv_data->def_cfg;
switch (ourport->info->type) {
case TYPE_S3C24XX:
ourport->port.ops = &s3c24xx_serial_ops;
break;
case TYPE_S3C6400:
ourport->port.ops = &s3c64xx_serial_ops;
break;
case TYPE_APPLE_S5L:
ourport->port.ops = &apple_s5l_serial_ops;
break;
}
if (np) {
of_property_read_u32(np,
"samsung,uart-fifosize", &ourport->port.fifosize);
@ -2142,7 +2328,8 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
if (port) {
/* restore IRQ mask */
if (s3c24xx_serial_has_interrupt_mask(port)) {
switch (ourport->info->type) {
case TYPE_S3C6400: {
unsigned int uintm = 0xf;
if (ourport->tx_enabled)
@ -2156,6 +2343,47 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
if (!IS_ERR(ourport->baudclk))
clk_disable_unprepare(ourport->baudclk);
clk_disable_unprepare(ourport->clk);
break;
}
case TYPE_APPLE_S5L: {
unsigned int ucon;
int ret;
ret = clk_prepare_enable(ourport->clk);
if (ret) {
dev_err(dev, "clk_enable clk failed: %d\n", ret);
return ret;
}
if (!IS_ERR(ourport->baudclk)) {
ret = clk_prepare_enable(ourport->baudclk);
if (ret) {
dev_err(dev, "clk_enable baudclk failed: %d\n", ret);
clk_disable_unprepare(ourport->clk);
return ret;
}
}
ucon = rd_regl(port, S3C2410_UCON);
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK);
if (ourport->tx_enabled)
ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK;
if (ourport->rx_enabled)
ucon |= APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK;
wr_regl(port, S3C2410_UCON, ucon);
if (!IS_ERR(ourport->baudclk))
clk_disable_unprepare(ourport->baudclk);
clk_disable_unprepare(ourport->clk);
break;
}
default:
break;
}
}
@ -2380,7 +2608,8 @@ static struct console s3c24xx_serial_console = {
static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C2410 UART",
.type = PORT_S3C2410,
.type = TYPE_S3C24XX,
.port_type = PORT_S3C2410,
.fifosize = 16,
.rx_fifomask = S3C2410_UFSTAT_RXMASK,
.rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
@ -2407,7 +2636,8 @@ static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C2412 UART",
.type = PORT_S3C2412,
.type = TYPE_S3C24XX,
.port_type = PORT_S3C2412,
.fifosize = 64,
.has_divslot = 1,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
@ -2436,7 +2666,8 @@ static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C2440 UART",
.type = PORT_S3C2440,
.type = TYPE_S3C24XX,
.port_type = PORT_S3C2440,
.fifosize = 64,
.has_divslot = 1,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
@ -2449,6 +2680,7 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
.num_clks = 4,
.clksel_mask = S3C2412_UCON_CLKMASK,
.clksel_shift = S3C2412_UCON_CLKSHIFT,
.ucon_mask = S3C2440_UCON0_DIVMASK,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.ucon = S3C2410_UCON_DEFAULT,
@ -2464,7 +2696,8 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C6400 UART",
.type = PORT_S3C6400,
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
.fifosize = 64,
.has_divslot = 1,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
@ -2492,7 +2725,8 @@ static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S5PV210 UART",
.type = PORT_S3C6400,
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
.has_divslot = 1,
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
@ -2520,7 +2754,8 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
#define EXYNOS_COMMON_SERIAL_DRV_DATA \
.info = &(struct s3c24xx_uart_info) { \
.name = "Samsung Exynos UART", \
.type = PORT_S3C6400, \
.type = TYPE_S3C6400, \
.port_type = PORT_S3C6400, \
.has_divslot = 1, \
.rx_fifomask = S5PV210_UFSTAT_RXMASK, \
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \
@ -2556,6 +2791,34 @@ static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
#define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#endif
#ifdef CONFIG_ARCH_APPLE
static struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Apple S5L UART",
.type = TYPE_APPLE_S5L,
.port_type = PORT_8250,
.fifosize = 16,
.rx_fifomask = S3C2410_UFSTAT_RXMASK,
.rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
.rx_fifofull = S3C2410_UFSTAT_RXFULL,
.tx_fifofull = S3C2410_UFSTAT_TXFULL,
.tx_fifomask = S3C2410_UFSTAT_TXMASK,
.tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
.def_clk_sel = S3C2410_UCON_CLKSEL0,
.num_clks = 1,
.clksel_mask = 0,
.clksel_shift = 0,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.ucon = APPLE_S5L_UCON_DEFAULT,
.ufcon = S3C2410_UFCON_DEFAULT,
},
};
#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)&s5l_serial_drv_data)
#else
#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#endif
static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
{
.name = "s3c2410-uart",
@ -2578,6 +2841,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
}, {
.name = "exynos5433-uart",
.driver_data = EXYNOS5433_SERIAL_DRV_DATA,
}, {
.name = "s5l-uart",
.driver_data = S5L_SERIAL_DRV_DATA,
},
{ },
};
@ -2599,6 +2865,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
.data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
{ .compatible = "samsung,exynos5433-uart",
.data = (void *)EXYNOS5433_SERIAL_DRV_DATA },
{ .compatible = "apple,s5l-uart",
.data = (void *)S5L_SERIAL_DRV_DATA },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
@ -2730,6 +2998,23 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
s5pv210_early_console_setup);
OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
s5pv210_early_console_setup);
/* Apple S5L */
static int __init apple_s5l_early_console_setup(struct earlycon_device *device,
const char *opt)
{
/* Close enough to S3C2410 for earlycon... */
device->port.private_data = &s3c2410_early_console_data;
#ifdef CONFIG_ARM64
/* ... but we need to override the existing fixmap entry as nGnRnE */
__set_fixmap(FIX_EARLYCON_MEM_BASE, device->port.mapbase,
__pgprot(PROT_DEVICE_nGnRnE));
#endif
return samsung_early_console_setup(device, opt);
}
OF_EARLYCON_DECLARE(s5l, "apple,s5l-uart", apple_s5l_early_console_setup);
#endif
MODULE_ALIAS("platform:samsung-uart");

View File

@ -1196,7 +1196,7 @@ static int sc16is7xx_probe(struct device *dev,
ret = regmap_read(regmap,
SC16IS7XX_LSR_REG << SC16IS7XX_REG_SHIFT, &val);
if (ret < 0)
return ret;
return -EPROBE_DEFER;
/* Alloc port structure */
s = devm_kzalloc(dev, struct_size(s, p, devtype->nr_uart), GFP_KERNEL);

View File

@ -759,8 +759,6 @@ static int uart_get_info(struct tty_port *port, struct serial_struct *retinfo)
struct uart_port *uport;
int ret = -ENODEV;
memset(retinfo, 0, sizeof(*retinfo));
/*
* Ensure the state we copy is consistent and no hardware changes
* occur as we go
@ -1305,7 +1303,7 @@ static int uart_set_rs485_config(struct uart_port *port,
unsigned long flags;
if (!port->rs485_config)
return -ENOIOCTLCMD;
return -ENOTTY;
if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user)))
return -EFAULT;
@ -1329,7 +1327,7 @@ static int uart_get_iso7816_config(struct uart_port *port,
struct serial_iso7816 aux;
if (!port->iso7816_config)
return -ENOIOCTLCMD;
return -ENOTTY;
spin_lock_irqsave(&port->lock, flags);
aux = port->iso7816;
@ -1349,7 +1347,7 @@ static int uart_set_iso7816_config(struct uart_port *port,
unsigned long flags;
if (!port->iso7816_config)
return -ENOIOCTLCMD;
return -ENOTTY;
if (copy_from_user(&iso7816, iso7816_user, sizeof(*iso7816_user)))
return -EFAULT;

View File

@ -330,9 +330,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status)
up->port.ignore_status_mask = next_ignore_status_mask;
disr = sio_in(up, TXX9_SIDISR);
} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
spin_unlock(&up->port.lock);
tty_flip_buffer_push(&up->port.state->port);
spin_lock(&up->port.lock);
*status = disr;
}

View File

@ -2124,7 +2124,7 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
unsigned short scscr, scsptr;
unsigned long flags;
/* check wheter the port has SCSPTR */
/* check whether the port has SCSPTR */
if (!sci_getreg(port, SCSPTR)->size) {
/*
* Not supported by hardware. Most parts couple break and rx
@ -2609,21 +2609,10 @@ done:
udelay(DIV_ROUND_UP(10 * 1000000, baud));
}
/*
* Calculate delay for 2 DMA buffers (4 FIFO).
* See serial_core.c::uart_update_timeout().
* With 10 bits (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above
* function calculates 1 jiffie for the data plus 5 jiffies for the
* "slop(e)." Then below we calculate 5 jiffies (20ms) for 2 DMA
* buffers (4 FIFO sizes), but when performing a faster transfer, the
* value obtained by this formula is too small. Therefore, if the value
* is smaller than 20ms, use 20ms as the timeout value for DMA.
*/
/* Calculate delay for 2 DMA buffers (4 FIFO). */
s->rx_frame = (10000 * bits) / (baud / 100);
#ifdef CONFIG_SERIAL_SH_SCI_DMA
s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame;
if (s->rx_timeout < 20)
s->rx_timeout = 20;
#endif
if ((termios->c_cflag & CREAD) != 0)

View File

@ -448,9 +448,7 @@ static void __ssp_receive_chars(struct sifive_serial_port *ssp)
uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL);
}
spin_unlock(&ssp->port.lock);
tty_flip_buffer_push(&ssp->port.state->port);
spin_lock(&ssp->port.lock);
}
/**

View File

@ -218,8 +218,7 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
u32 sr;
char flag;
if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
pm_wakeup_event(tport->tty->dev, 0);
spin_lock(&port->lock);
while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res,
threaded)) {
@ -271,14 +270,14 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
}
}
if (uart_handle_sysrq_char(port, c))
if (uart_prepare_sysrq_char(port, c))
continue;
uart_insert_char(port, sr, USART_SR_ORE, c, flag);
}
spin_unlock(&port->lock);
uart_unlock_and_check_sysrq(port);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
}
static void stm32_usart_tx_dma_complete(void *arg)
@ -286,12 +285,16 @@ static void stm32_usart_tx_dma_complete(void *arg)
struct uart_port *port = arg;
struct stm32_port *stm32port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
unsigned long flags;
dmaengine_terminate_async(stm32port->tx_ch);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
stm32port->tx_dma_busy = false;
/* Let's see if we have pending data to send */
spin_lock_irqsave(&port->lock, flags);
stm32_usart_transmit_chars(port);
spin_unlock_irqrestore(&port->lock, flags);
}
static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
@ -303,7 +306,7 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
* Enables TX FIFO threashold irq when FIFO is enabled,
* or TX empty irq when FIFO is disabled
*/
if (stm32_port->fifoen)
if (stm32_port->fifoen && stm32_port->txftcfg >= 0)
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_TXFTIE);
else
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
@ -314,7 +317,7 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
if (stm32_port->fifoen)
if (stm32_port->fifoen && stm32_port->txftcfg >= 0)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE);
else
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
@ -455,29 +458,34 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
{
struct uart_port *port = ptr;
struct tty_port *tport = &port->state->port;
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
u32 sr;
spin_lock(&port->lock);
sr = readl_relaxed(port->membase + ofs->isr);
if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
writel_relaxed(USART_ICR_RTOCF,
port->membase + ofs->icr);
if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG)
if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) {
/* Clear wake up flag and disable wake up interrupt */
writel_relaxed(USART_ICR_WUCF,
port->membase + ofs->icr);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
pm_wakeup_event(tport->tty->dev, 0);
}
if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch))
stm32_usart_receive_chars(port, false);
if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch))
if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
spin_lock(&port->lock);
stm32_usart_transmit_chars(port);
spin_unlock(&port->lock);
spin_unlock(&port->lock);
}
if (stm32_port->rx_ch)
return IRQ_WAKE_THREAD;
@ -490,13 +498,9 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
struct uart_port *port = ptr;
struct stm32_port *stm32_port = to_stm32_port(port);
spin_lock(&port->lock);
if (stm32_port->rx_ch)
stm32_usart_receive_chars(port, true);
spin_unlock(&port->lock);
return IRQ_HANDLED;
}
@ -505,7 +509,10 @@ static unsigned int stm32_usart_tx_empty(struct uart_port *port)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
return readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE;
if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
return TIOCSER_TEMT;
return 0;
}
static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
@ -584,6 +591,19 @@ static void stm32_usart_start_tx(struct uart_port *port)
stm32_usart_transmit_chars(port);
}
/* Flush the transmit buffer. */
static void stm32_usart_flush_buffer(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
if (stm32_port->tx_ch) {
dmaengine_terminate_async(stm32_port->tx_ch);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
stm32_port->tx_dma_busy = false;
}
}
/* Throttle the remote when input buffer is about to overflow. */
static void stm32_usart_throttle(struct uart_port *port)
{
@ -634,33 +654,30 @@ static int stm32_usart_startup(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
const char *name = to_platform_device(port->dev)->name;
u32 val;
int ret;
ret = request_threaded_irq(port->irq, stm32_usart_interrupt,
stm32_usart_threaded_interrupt,
IRQF_NO_SUSPEND, name, port);
IRQF_ONESHOT | IRQF_NO_SUSPEND,
name, port);
if (ret)
return ret;
/* RX FIFO Flush */
if (ofs->rqr != UNDEF_REG)
stm32_usart_set_bits(port, ofs->rqr, USART_RQR_RXFRQ);
/* Tx and RX FIFO configuration */
if (stm32_port->fifoen) {
val = readl_relaxed(port->membase + ofs->cr3);
val &= ~(USART_CR3_TXFTCFG_MASK | USART_CR3_RXFTCFG_MASK);
val |= USART_CR3_TXFTCFG_HALF << USART_CR3_TXFTCFG_SHIFT;
val |= USART_CR3_RXFTCFG_HALF << USART_CR3_RXFTCFG_SHIFT;
writel_relaxed(val, port->membase + ofs->cr3);
if (stm32_port->swap) {
val = readl_relaxed(port->membase + ofs->cr2);
val |= USART_CR2_SWAP;
writel_relaxed(val, port->membase + ofs->cr2);
}
/* RX FIFO enabling */
val = stm32_port->cr1_irq | USART_CR1_RE;
if (stm32_port->fifoen)
val |= USART_CR1_FIFOEN;
/* RX FIFO Flush */
if (ofs->rqr != UNDEF_REG)
writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr);
/* RX enabling */
val = stm32_port->cr1_irq | USART_CR1_RE | BIT(cfg->uart_enable_bit);
stm32_usart_set_bits(port, ofs->cr1, val);
return 0;
@ -691,6 +708,11 @@ static void stm32_usart_shutdown(struct uart_port *port)
if (ret)
dev_err(port->dev, "Transmission is not complete\n");
/* flush RX & TX FIFO */
if (ofs->rqr != UNDEF_REG)
writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ,
port->membase + ofs->rqr);
stm32_usart_clr_bits(port, ofs->cr1, val);
free_irq(port->irq, port);
@ -737,8 +759,9 @@ static void stm32_usart_set_termios(struct uart_port *port,
unsigned int baud, bits;
u32 usartdiv, mantissa, fraction, oversampling;
tcflag_t cflag = termios->c_cflag;
u32 cr1, cr2, cr3;
u32 cr1, cr2, cr3, isr;
unsigned long flags;
int ret;
if (!stm32_port->hw_flow_control)
cflag &= ~CRTSCTS;
@ -747,21 +770,37 @@ static void stm32_usart_set_termios(struct uart_port *port,
spin_lock_irqsave(&port->lock, flags);
ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr,
isr,
(isr & USART_SR_TC),
10, 100000);
/* Send the TC error message only when ISR_TC is not set. */
if (ret)
dev_err(port->dev, "Transmission is not complete\n");
/* Stop serial port and reset value */
writel_relaxed(0, port->membase + ofs->cr1);
/* flush RX & TX FIFO */
if (ofs->rqr != UNDEF_REG)
stm32_usart_set_bits(port, ofs->rqr,
USART_RQR_TXFRQ | USART_RQR_RXFRQ);
writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ,
port->membase + ofs->rqr);
cr1 = USART_CR1_TE | USART_CR1_RE;
if (stm32_port->fifoen)
cr1 |= USART_CR1_FIFOEN;
cr2 = 0;
cr2 = stm32_port->swap ? USART_CR2_SWAP : 0;
/* Tx and RX FIFO configuration */
cr3 = readl_relaxed(port->membase + ofs->cr3);
cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTCFG_MASK | USART_CR3_RXFTIE
| USART_CR3_TXFTCFG_MASK;
cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTIE;
if (stm32_port->fifoen) {
if (stm32_port->txftcfg >= 0)
cr3 |= stm32_port->txftcfg << USART_CR3_TXFTCFG_SHIFT;
if (stm32_port->rxftcfg >= 0)
cr3 |= stm32_port->rxftcfg << USART_CR3_RXFTCFG_SHIFT;
}
if (cflag & CSTOPB)
cr2 |= USART_CR2_STOP_2B;
@ -790,7 +829,8 @@ static void stm32_usart_set_termios(struct uart_port *port,
, bits);
if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch ||
stm32_port->fifoen)) {
(stm32_port->fifoen &&
stm32_port->rxftcfg >= 0))) {
if (cflag & CSTOPB)
bits = bits + 3; /* 1 start bit + 2 stop bits */
else
@ -817,12 +857,6 @@ static void stm32_usart_set_termios(struct uart_port *port,
cr3 |= USART_CR3_CTSE | USART_CR3_RTSE;
}
/* Handle modem control interrupts */
if (UART_ENABLE_MS(port, termios->c_cflag))
stm32_usart_enable_ms(port);
else
stm32_usart_disable_ms(port);
usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
/*
@ -892,12 +926,24 @@ static void stm32_usart_set_termios(struct uart_port *port,
cr1 &= ~(USART_CR1_DEDT_MASK | USART_CR1_DEAT_MASK);
}
/* Configure wake up from low power on start bit detection */
if (stm32_port->wakeup_src) {
cr3 &= ~USART_CR3_WUS_MASK;
cr3 |= USART_CR3_WUS_START_BIT;
}
writel_relaxed(cr3, port->membase + ofs->cr3);
writel_relaxed(cr2, port->membase + ofs->cr2);
writel_relaxed(cr1, port->membase + ofs->cr1);
stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
spin_unlock_irqrestore(&port->lock, flags);
/* Handle modem control interrupts */
if (UART_ENABLE_MS(port, termios->c_cflag))
stm32_usart_enable_ms(port);
else
stm32_usart_disable_ms(port);
}
static const char *stm32_usart_type(struct uart_port *port)
@ -962,6 +1008,7 @@ static const struct uart_ops stm32_uart_ops = {
.break_ctl = stm32_usart_break_ctl,
.startup = stm32_usart_startup,
.shutdown = stm32_usart_shutdown,
.flush_buffer = stm32_usart_flush_buffer,
.set_termios = stm32_usart_set_termios,
.pm = stm32_usart_pm,
.type = stm32_usart_type,
@ -971,6 +1018,39 @@ static const struct uart_ops stm32_uart_ops = {
.verify_port = stm32_usart_verify_port,
};
/*
* STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG)
* Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case,
* RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE.
* So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1.
*/
static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 };
static void stm32_usart_get_ftcfg(struct platform_device *pdev, const char *p,
int *ftcfg)
{
u32 bytes, i;
/* DT option to get RX & TX FIFO threshold (default to 8 bytes) */
if (of_property_read_u32(pdev->dev.of_node, p, &bytes))
bytes = 8;
for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++)
if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes)
break;
if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg))
i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1;
dev_dbg(&pdev->dev, "%s set to %d bytes\n", p,
stm32h7_usart_fifo_thresh_cfg[i]);
/* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */
if (i)
*ftcfg = i - 1;
else
*ftcfg = -EINVAL;
}
static void stm32_usart_deinit_port(struct stm32_port *stm32port)
{
clk_disable_unprepare(stm32port->clk);
@ -1000,13 +1080,19 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
if (ret)
return ret;
if (stm32port->info->cfg.has_wakeup) {
stm32port->wakeirq = platform_get_irq_optional(pdev, 1);
if (stm32port->wakeirq <= 0 && stm32port->wakeirq != -ENXIO)
return stm32port->wakeirq ? : -ENODEV;
}
stm32port->wakeup_src = stm32port->info->cfg.has_wakeup &&
of_property_read_bool(pdev->dev.of_node, "wakeup-source");
stm32port->swap = stm32port->info->cfg.has_swap &&
of_property_read_bool(pdev->dev.of_node, "rx-tx-swap");
stm32port->fifoen = stm32port->info->cfg.has_fifo;
if (stm32port->fifoen) {
stm32_usart_get_ftcfg(pdev, "rx-threshold",
&stm32port->rxftcfg);
stm32_usart_get_ftcfg(pdev, "tx-threshold",
&stm32port->txftcfg);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, res);
@ -1106,6 +1192,13 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
struct dma_async_tx_descriptor *desc = NULL;
int ret;
/*
* Using DMA and threaded handler for the console could lead to
* deadlocks.
*/
if (uart_console(port))
return -ENODEV;
/* Request DMA RX channel */
stm32port->rx_ch = dma_request_slave_channel(dev, "rx");
if (!stm32port->rx_ch) {
@ -1239,23 +1332,13 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
if (ret)
return ret;
if (stm32port->wakeirq > 0) {
ret = device_init_wakeup(&pdev->dev, true);
if (ret)
goto err_uninit;
ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
stm32port->wakeirq);
if (stm32port->wakeup_src) {
device_set_wakeup_capable(&pdev->dev, true);
ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq);
if (ret)
goto err_nowup;
device_set_wakeup_enable(&pdev->dev, false);
}
ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
if (ret)
goto err_wirq;
ret = stm32_usart_of_dma_rx_probe(stm32port, pdev);
if (ret)
dev_info(&pdev->dev, "interrupt mode used for rx (no dma)\n");
@ -1269,19 +1352,47 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
if (ret)
goto err_port;
pm_runtime_put_sync(&pdev->dev);
return 0;
err_wirq:
if (stm32port->wakeirq > 0)
err_port:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
if (stm32port->rx_ch) {
dmaengine_terminate_async(stm32port->rx_ch);
dma_release_channel(stm32port->rx_ch);
}
if (stm32port->rx_dma_buf)
dma_free_coherent(&pdev->dev,
RX_BUF_L, stm32port->rx_buf,
stm32port->rx_dma_buf);
if (stm32port->tx_ch) {
dmaengine_terminate_async(stm32port->tx_ch);
dma_release_channel(stm32port->tx_ch);
}
if (stm32port->tx_dma_buf)
dma_free_coherent(&pdev->dev,
TX_BUF_L, stm32port->tx_buf,
stm32port->tx_dma_buf);
if (stm32port->wakeup_src)
dev_pm_clear_wake_irq(&pdev->dev);
err_nowup:
if (stm32port->wakeirq > 0)
device_init_wakeup(&pdev->dev, false);
if (stm32port->wakeup_src)
device_set_wakeup_capable(&pdev->dev, false);
err_uninit:
stm32_usart_deinit_port(stm32port);
return ret;
@ -1295,11 +1406,20 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
int err;
pm_runtime_get_sync(&pdev->dev);
err = uart_remove_one_port(&stm32_usart_driver, port);
if (err)
return(err);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
if (stm32_port->rx_ch)
if (stm32_port->rx_ch) {
dmaengine_terminate_async(stm32_port->rx_ch);
dma_release_channel(stm32_port->rx_ch);
}
if (stm32_port->rx_dma_buf)
dma_free_coherent(&pdev->dev,
@ -1308,27 +1428,24 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
if (stm32_port->tx_ch)
if (stm32_port->tx_ch) {
dmaengine_terminate_async(stm32_port->tx_ch);
dma_release_channel(stm32_port->tx_ch);
}
if (stm32_port->tx_dma_buf)
dma_free_coherent(&pdev->dev,
TX_BUF_L, stm32_port->tx_buf,
stm32_port->tx_dma_buf);
if (stm32_port->wakeirq > 0) {
if (stm32_port->wakeup_src) {
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
}
stm32_usart_deinit_port(stm32_port);
err = uart_remove_one_port(&stm32_usart_driver, port);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
return err;
return 0;
}
#ifdef CONFIG_SERIAL_STM32_CONSOLE
@ -1354,13 +1471,10 @@ static void stm32_usart_console_write(struct console *co, const char *s,
u32 old_cr1, new_cr1;
int locked = 1;
local_irq_save(flags);
if (port->sysrq)
locked = 0;
else if (oops_in_progress)
locked = spin_trylock(&port->lock);
if (oops_in_progress)
locked = spin_trylock_irqsave(&port->lock, flags);
else
spin_lock(&port->lock);
spin_lock_irqsave(&port->lock, flags);
/* Save and disable interrupts, enable the transmitter */
old_cr1 = readl_relaxed(port->membase + ofs->cr1);
@ -1374,8 +1488,7 @@ static void stm32_usart_console_write(struct console *co, const char *s,
writel_relaxed(old_cr1, port->membase + ofs->cr1);
if (locked)
spin_unlock(&port->lock);
local_irq_restore(flags);
spin_unlock_irqrestore(&port->lock, flags);
}
static int stm32_usart_console_setup(struct console *co, char *options)
@ -1436,23 +1549,20 @@ static void __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
u32 val;
if (stm32_port->wakeirq <= 0)
if (!stm32_port->wakeup_src)
return;
/*
* Enable low-power wake-up and wake-up irq if argument is set to
* "enable", disable low-power wake-up and wake-up irq otherwise
*/
if (enable) {
stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_UESM);
val = readl_relaxed(port->membase + ofs->cr3);
val &= ~USART_CR3_WUS_MASK;
/* Enable Wake up interrupt from low power on start bit */
val |= USART_CR3_WUS_START_BIT | USART_CR3_WUFIE;
writel_relaxed(val, port->membase + ofs->cr3);
stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_WUFIE);
} else {
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_UESM);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
}
}
@ -1462,10 +1572,8 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev)
uart_suspend_port(&stm32_usart_driver, port);
if (device_may_wakeup(dev))
if (device_may_wakeup(dev) || device_wakeup_path(dev))
stm32_usart_serial_en_wakeup(port, true);
else
stm32_usart_serial_en_wakeup(port, false);
/*
* When "no_console_suspend" is enabled, keep the pinctrl default state
@ -1474,7 +1582,7 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev)
* capabilities.
*/
if (console_suspend_enabled || !uart_console(port)) {
if (device_may_wakeup(dev))
if (device_may_wakeup(dev) || device_wakeup_path(dev))
pinctrl_pm_select_idle_state(dev);
else
pinctrl_pm_select_sleep_state(dev);
@ -1489,7 +1597,7 @@ static int __maybe_unused stm32_usart_serial_resume(struct device *dev)
pinctrl_pm_select_default_state(dev);
if (device_may_wakeup(dev))
if (device_may_wakeup(dev) || device_wakeup_path(dev))
stm32_usart_serial_en_wakeup(port, false);
return uart_resume_port(&stm32_usart_driver, port);

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