TTY / Serial driver update for 5.16-rc1

Here is the big set of tty and serial driver updates for 5.16-rc1.
 
 Nothing major in here at all, just lots of tiny serial and tty driver
 updates for various reported things, and some good cleanups.  These
 include:
 	- more good tty api cleanups from Jiri
 	- stm32 serial driver updates
 	- softlockup fix for non-preempt systems under high serial load
 	- rpmsg serial driver update
 	- 8250 drivers updates and fixes
 	- n_gsm line discipline fixes and updates as people are finally
 	  starting to use it.
 
 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-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYYPczQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ykWbwCfaIScbUoCUx+h/uP93nKKD8B3KgYAoMvFuhhD
 D/fTLggs12x5NsvLBgtZ
 =rq0R
 -----END PGP SIGNATURE-----

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

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

  Nothing major in here at all, just lots of tiny serial and tty driver
  updates for various reported things, and some good cleanups. These
  include:

   - more good tty api cleanups from Jiri

   - stm32 serial driver updates

   - softlockup fix for non-preempt systems under high serial load

   - rpmsg serial driver update

   - 8250 drivers updates and fixes

   - n_gsm line discipline fixes and updates as people are finally
     starting to use it.

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

* tag 'tty-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (86 commits)
  tty: Fix extra "not" in TTY_DRIVER_REAL_RAW description
  serial: cpm_uart: Protect udbg definitions by CONFIG_SERIAL_CPM_CONSOLE
  tty: rpmsg: Define tty name via constant string literal
  tty: rpmsg: Add pr_fmt() to prefix messages
  tty: rpmsg: Use dev_err_probe() in ->probe()
  tty: rpmsg: Unify variable used to keep an error code
  tty: rpmsg: Assign returned id to a local variable
  serial: stm32: push DMA RX data before suspending
  serial: stm32: terminate / restart DMA transfer at suspend / resume
  serial: stm32: rework RX dma initialization and release
  serial: 8250_pci: Remove empty stub pci_quatech_exit()
  serial: 8250_pci: Replace custom pci_match_id() implementation
  serial: xilinx_uartps: Fix race condition causing stuck TX
  serial: sunzilog: Mark sunzilog_putchar() __maybe_unused
  Revert "tty: hvc: pass DMA capable memory to put_chars()"
  Revert "virtio-console: remove unnecessary kmemdup()"
  serial: 8250_pci: Replace dev_*() by pci_*() macros
  serial: 8250_pci: Get rid of redundant 'else' keyword
  serial: 8250_pci: Refactor the loop in pci_ite887x_init()
  tty: add rpmsg driver
  ...
This commit is contained in:
Linus Torvalds 2021-11-04 09:09:37 -07:00
commit abfecb3909
66 changed files with 1668 additions and 861 deletions

View File

@ -86,7 +86,7 @@ required:
- reg
- interrupts
additionalProperties: false
unevaluatedProperties: false
if:
properties:

View File

@ -1,36 +0,0 @@
* BCM63xx UART
Required properties:
- compatible: "brcm,bcm6345-uart"
- reg: The base address of the UART register bank.
- interrupts: A single interrupt specifier.
- clocks: Clock driving the hardware; used to figure out the baud rate
divisor.
Optional properties:
- clock-names: Should be "refclk".
Example:
uart0: serial@14e00520 {
compatible = "brcm,bcm6345-uart";
reg = <0x14e00520 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <2>;
clocks = <&periph_clk>;
clock-names = "refclk";
};
clocks {
periph_clk: periph_clk@0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <54000000>;
};
};

View File

@ -0,0 +1,47 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/serial/brcm,bcm6345-uart.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: BCM63xx UART
maintainers:
- Rafał Miłecki <rafal@milecki.pl>
allOf:
- $ref: serial.yaml#
properties:
compatible:
const: brcm,bcm6345-uart
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: refclk
unevaluatedProperties: false
required:
- reg
- interrupts
- clocks
examples:
- |
serial@14e00520 {
compatible = "brcm,bcm6345-uart";
reg = <0x14e00520 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <2>;
clocks = <&periph_clk>;
clock-names = "refclk";
};

View File

@ -26,6 +26,7 @@ properties:
- samsung,s3c6400-uart
- samsung,s5pv210-uart
- samsung,exynos4210-uart
- samsung,exynos850-uart
reg:
maxItems: 1

View File

@ -19,6 +19,7 @@ properties:
- enum:
- sprd,sc9860-uart
- sprd,sc9863a-uart
- sprd,ums512-uart
- const: sprd,sc9836-uart
- const: sprd,sc9836-uart

View File

@ -1,23 +0,0 @@
Xilinx Axi Uartlite controller Device Tree Bindings
---------------------------------------------------------
Required properties:
- compatible : Can be either of
"xlnx,xps-uartlite-1.00.a"
"xlnx,opb-uartlite-1.00.b"
- reg : Physical base address and size of the Axi Uartlite
registers map.
- interrupts : Should contain the UART controller interrupt.
Optional properties:
- port-number : Set Uart port number
- clock-names : Should be "s_axi_aclk"
- clocks : Input clock specifier. Refer to common clock bindings.
Example:
serial@800c0000 {
compatible = "xlnx,xps-uartlite-1.00.a";
reg = <0x0 0x800c0000 0x10000>;
interrupts = <0x0 0x6e 0x1>;
port-number = <0>;
};

View File

@ -0,0 +1,89 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/serial/xlnx,opb-uartlite.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Xilinx Axi Uartlite
maintainers:
- Peter Korsgaard <jacmet@sunsite.dk>
properties:
compatible:
contains:
enum:
- xlnx,xps-uartlite-1.00.a
- xlnx,opb-uartlite-1.00.b
reg:
maxItems: 1
interrupts:
maxItems: 1
port-number:
$ref: /schemas/types.yaml#/definitions/uint32
description: Set Uart port number
clocks:
maxItems: 1
clock-names:
const: s_axi_aclk
current-speed:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The fixed baud rate that the device was configured for.
xlnx,data-bits:
enum: [5, 6, 7, 8]
description:
The fixed number of data bits that the device was configured for.
xlnx,use-parity:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
description:
Whether parity checking was enabled when the device was configured.
xlnx,odd-parity:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
description:
Whether odd parity was configured.
required:
- compatible
- reg
- interrupts
- current-speed
- xlnx,data-bits
- xlnx,use-parity
allOf:
- $ref: /schemas/serial.yaml#
- if:
properties:
xlnx,use-parity:
contains:
const: 1
then:
required:
- xlnx,odd-parity
unevaluatedProperties: false
examples:
- |
serial@800c0000 {
compatible = "xlnx,xps-uartlite-1.00.a";
reg = <0x800c0000 0x10000>;
interrupts = <0x0 0x6e 0x1>;
port-number = <0>;
current-speed = <115200>;
xlnx,data-bits = <8>;
xlnx,use-parity = <0>;
};
...

View File

@ -12,13 +12,16 @@ modems connected to a physical serial port.
How to use it
-------------
1. initialize the modem in 0710 mux mode (usually AT+CMUX= command) through
its serial port. Depending on the modem used, you can pass more or less
parameters to this command,
2. switch the serial line to using the n_gsm line discipline by using
TIOCSETD ioctl,
3. configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl,
4. obtain base gsmtty number for the used serial port,
1. config initiator
^^^^^^^^^^^^^^^^^^^^^
1.1 initialize the modem in 0710 mux mode (usually AT+CMUX= command) through
its serial port. Depending on the modem used, you can pass more or less
parameters to this command.
1.2 switch the serial line to using the n_gsm line discipline by using
TIOCSETD ioctl.
1.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl.
1.4 obtain base gsmtty number for the used serial port.
Major parts of the initialization program :
(a good starting point is util-linux-ng/sys-utils/ldattach.c)::
@ -70,14 +73,14 @@ Major parts of the initialization program :
daemon(0,0);
pause();
5. use these devices as plain serial ports.
1.5 use these devices as plain serial ports.
for example, it's possible:
- and to use gnokii to send / receive SMS on ttygsm1
- to use ppp to establish a datalink on ttygsm2
6. first close all virtual ports before closing the physical port.
1.6 first close all virtual ports before closing the physical port.
Note that after closing the physical port the modem is still in multiplexing
mode. This may prevent a successful re-opening of the port later. To avoid
@ -87,6 +90,56 @@ Major parts of the initialization program :
0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9.
2. config requester
^^^^^^^^^^^^^^^^^^^^^
2.1 receive string "AT+CMUX= command" through its serial port,initialize
mux mode config
2.2 switch the serial line to using the n_gsm line discipline by using
TIOCSETD ioctl.
2.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl.
2.4 obtain base gsmtty number for the used serial port,
#include <stdio.h>
#include <stdint.h>
#include <linux/gsmmux.h>
#include <linux/tty.h>
#define DEFAULT_SPEED B115200
#define SERIAL_PORT /dev/ttyS0
int ldisc = N_GSM0710;
struct gsm_config c;
struct termios configuration;
uint32_t first;
/* open the serial port */
fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
/* configure the serial port : speed, flow control ... */
/* get serial data and check "AT+CMUX=command" parameter ... */
/* use n_gsm line discipline */
ioctl(fd, TIOCSETD, &ldisc);
/* get n_gsm configuration */
ioctl(fd, GSMIOC_GETCONF, &c);
/* we are requester and need encoding 0 (basic) */
c.initiator = 0;
c.encapsulation = 0;
/* our modem defaults to a maximum size of 127 bytes */
c.mru = 127;
c.mtu = 127;
/* set the new configuration */
ioctl(fd, GSMIOC_SETCONF, &c);
/* get first gsmtty device node */
ioctl(fd, GSMIOC_GETFIRST, &first);
printf("first muxed line: /dev/gsmtty%i\n", first);
/* and wait for ever to keep the line discipline enabled */
daemon(0,0);
pause();
Additional Documentation
------------------------
More practical details on the protocol and how it's supported by industrial

View File

@ -58,7 +58,7 @@ close() This is called on a terminal when the line
hangup() Called when the tty line is hung up.
The line discipline should cease I/O to the tty.
No further calls into the ldisc code will occur.
The return value is ignored. Can sleep.
Can sleep.
read() (optional) A process requests reading data from
the line. Multiple read calls may occur in parallel

View File

@ -88,6 +88,8 @@
clock-frequency = <125000000>;
compatible = "xlnx,xps-uartlite-1.00.a";
current-speed = <19200>;
xlnx,use-parity = <0>;
xlnx,data-bits = <8>;
device_type = "serial";
interrupts = <0x12>;
port-number = <0>;

View File

@ -793,7 +793,7 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
break;
default:
err = n_tty_ioctl_helper(tty, file, cmd, arg);
err = n_tty_ioctl_helper(tty, cmd, arg);
break;
}

View File

@ -244,7 +244,7 @@ static int serport_ldisc_compat_ioctl(struct tty_struct *tty,
}
#endif
static int serport_ldisc_hangup(struct tty_struct *tty)
static void serport_ldisc_hangup(struct tty_struct *tty)
{
struct serport *serport = (struct serport *) tty->disc_data;
unsigned long flags;
@ -254,7 +254,6 @@ static int serport_ldisc_hangup(struct tty_struct *tty)
spin_unlock_irqrestore(&serport->lock, flags);
wake_up_interruptible(&serport->wait);
return 0;
}
static void serport_ldisc_write_wakeup(struct tty_struct * tty)

View File

@ -664,10 +664,9 @@ static void slcan_close(struct tty_struct *tty)
/* This will complete via sl_free_netdev */
}
static int slcan_hangup(struct tty_struct *tty)
static void slcan_hangup(struct tty_struct *tty)
{
slcan_close(tty);
return 0;
}
/* Perform I/O control on an active SLCAN channel. */
@ -692,7 +691,7 @@ static int slcan_ioctl(struct tty_struct *tty, struct file *file,
return -EINVAL;
default:
return tty_mode_ioctl(tty, file, cmd, arg);
return tty_mode_ioctl(tty, cmd, arg);
}
}

View File

@ -732,7 +732,7 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
break;
}
default:
err = tty_mode_ioctl(tty, file, cmd, arg);
err = tty_mode_ioctl(tty, cmd, arg);
}
sp_put(sp);

View File

@ -247,10 +247,9 @@ ppp_asynctty_close(struct tty_struct *tty)
* Wait for I/O to driver to complete and unregister PPP channel.
* This is already done by the close routine, so just call that.
*/
static int ppp_asynctty_hangup(struct tty_struct *tty)
static void ppp_asynctty_hangup(struct tty_struct *tty)
{
ppp_asynctty_close(tty);
return 0;
}
/*
@ -311,7 +310,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
/* flush our buffers and the serial port's buffer */
if (arg == TCIOFLUSH || arg == TCOFLUSH)
ppp_async_flush_output(ap);
err = n_tty_ioctl_helper(tty, file, cmd, arg);
err = n_tty_ioctl_helper(tty, cmd, arg);
break;
case FIONREAD:
@ -323,7 +322,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
default:
/* Try the various mode ioctls */
err = tty_mode_ioctl(tty, file, cmd, arg);
err = tty_mode_ioctl(tty, cmd, arg);
}
ap_put(ap);

View File

@ -245,10 +245,9 @@ ppp_sync_close(struct tty_struct *tty)
* Wait for I/O to driver to complete and unregister PPP channel.
* This is already done by the close routine, so just call that.
*/
static int ppp_sync_hangup(struct tty_struct *tty)
static void ppp_sync_hangup(struct tty_struct *tty)
{
ppp_sync_close(tty);
return 0;
}
/*
@ -304,7 +303,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
/* flush our buffers and the serial port's buffer */
if (arg == TCIOFLUSH || arg == TCOFLUSH)
ppp_sync_flush_output(ap);
err = n_tty_ioctl_helper(tty, file, cmd, arg);
err = n_tty_ioctl_helper(tty, cmd, arg);
break;
case FIONREAD:
@ -315,7 +314,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
break;
default:
err = tty_mode_ioctl(tty, file, cmd, arg);
err = tty_mode_ioctl(tty, cmd, arg);
break;
}

View File

@ -907,10 +907,9 @@ static void slip_close(struct tty_struct *tty)
/* This will complete via sl_free_netdev */
}
static int slip_hangup(struct tty_struct *tty)
static void slip_hangup(struct tty_struct *tty)
{
slip_close(tty);
return 0;
}
/************************************************************************
* STANDARD SLIP ENCAPSULATION *
@ -1174,7 +1173,7 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file,
/* VSV changes end */
#endif
default:
return tty_mode_ioctl(tty, file, cmd, arg);
return tty_mode_ioctl(tty, cmd, arg);
}
}

View File

@ -327,6 +327,27 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
}
EXPORT_SYMBOL(rpmsg_trysend_offchannel);
/**
* rpmsg_get_mtu() - get maximum transmission buffer size for sending message.
* @ept: the rpmsg endpoint
*
* This function returns maximum buffer size available for a single outgoing message.
*
* Return: the maximum transmission size on success and an appropriate error
* value on failure.
*/
ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept)
{
if (WARN_ON(!ept))
return -EINVAL;
if (!ept->ops->get_mtu)
return -ENOTSUPP;
return ept->ops->get_mtu(ept);
}
EXPORT_SYMBOL(rpmsg_get_mtu);
/*
* match a rpmsg channel with a channel info struct.
* this is used to make sure we're not creating rpmsg devices for channels

View File

@ -53,6 +53,7 @@ struct rpmsg_device_ops {
* @trysendto: see @rpmsg_trysendto(), optional
* @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional
* @poll: see @rpmsg_poll(), optional
* @get_mtu: see @rpmsg_get_mtu(), optional
*
* Indirection table for the operations that a rpmsg backend should implement.
* In addition to @destroy_ept, the backend must at least implement @send and
@ -72,6 +73,7 @@ struct rpmsg_endpoint_ops {
void *data, int len);
__poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp,
poll_table *wait);
ssize_t (*get_mtu)(struct rpmsg_endpoint *ept);
};
struct device *rpmsg_find_device(struct device *parent,

View File

@ -149,6 +149,7 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
int len, u32 dst);
static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
u32 dst, void *data, int len);
static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept);
static struct rpmsg_device *__rpmsg_create_channel(struct virtproc_info *vrp,
struct rpmsg_channel_info *chinfo);
@ -160,6 +161,7 @@ static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
.trysend = virtio_rpmsg_trysend,
.trysendto = virtio_rpmsg_trysendto,
.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
.get_mtu = virtio_rpmsg_get_mtu,
};
/**
@ -696,6 +698,14 @@ static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
}
static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept)
{
struct rpmsg_device *rpdev = ept->rpdev;
struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
return vch->vrp->buf_size - sizeof(struct rpmsg_hdr);
}
static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
struct rpmsg_hdr *msg, unsigned int len)
{

View File

@ -368,6 +368,18 @@ config VCC
source "drivers/tty/hvc/Kconfig"
config RPMSG_TTY
tristate "RPMSG tty driver"
depends on RPMSG
help
Say y here to export rpmsg endpoints as tty devices, usually found
in /dev/ttyRPMSGx.
This makes it possible for user-space programs to send and receive
rpmsg messages as a standard tty protocol.
To compile this driver as a module, choose M here: the module will be
called rpmsg_tty.
endif # TTY
source "drivers/tty/serdev/Kconfig"

View File

@ -26,5 +26,6 @@ obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o
obj-$(CONFIG_GOLDFISH_TTY) += goldfish.o
obj-$(CONFIG_MIPS_EJTAG_FDC_TTY) += mips_ejtag_fdc.o
obj-$(CONFIG_VCC) += vcc.o
obj-$(CONFIG_RPMSG_TTY) += rpmsg_tty.o
obj-y += ipwireless/

View File

@ -49,7 +49,7 @@
#define N_OUTBUF 16
#define N_INBUF 16
#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
#define __ALIGNED__ __attribute__((__aligned__(L1_CACHE_BYTES)))
static struct tty_driver *hvc_driver;
static struct task_struct *hvc_task;

View File

@ -45,7 +45,307 @@
#include <asm/io.h>
#include <linux/uaccess.h>
#include "moxa.h"
#define MOXA 0x400
#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */
#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */
#define MOXA_GETDATACOUNT (MOXA + 23)
#define MOXA_GET_IOQUEUE (MOXA + 27)
#define MOXA_FLUSH_QUEUE (MOXA + 28)
#define MOXA_GETMSTATUS (MOXA + 65)
/*
* System Configuration
*/
#define Magic_code 0x404
/*
* for C218 BIOS initialization
*/
#define C218_ConfBase 0x800
#define C218_status (C218_ConfBase + 0) /* BIOS running status */
#define C218_diag (C218_ConfBase + 2) /* diagnostic status */
#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */
#define C218DLoad_len (C218_ConfBase + 6) /* WORD */
#define C218check_sum (C218_ConfBase + 8) /* BYTE */
#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */
#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */
#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */
#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */
#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */
#define C218_LoadBuf 0x0F00
#define C218_KeyCode 0x218
#define CP204J_KeyCode 0x204
/*
* for C320 BIOS initialization
*/
#define C320_ConfBase 0x800
#define C320_LoadBuf 0x0f00
#define STS_init 0x05 /* for C320_status */
#define C320_status C320_ConfBase + 0 /* BIOS running status */
#define C320_diag C320_ConfBase + 2 /* diagnostic status */
#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */
#define C320DLoad_len C320_ConfBase + 6 /* WORD */
#define C320check_sum C320_ConfBase + 8 /* WORD */
#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */
#define C320bapi_len C320_ConfBase + 0x0c /* WORD */
#define C320UART_no C320_ConfBase + 0x0e /* WORD */
#define C320_KeyCode 0x320
#define FixPage_addr 0x0000 /* starting addr of static page */
#define DynPage_addr 0x2000 /* starting addr of dynamic page */
#define C218_start 0x3000 /* starting addr of C218 BIOS prg */
#define Control_reg 0x1ff0 /* select page and reset control */
#define HW_reset 0x80
/*
* Function Codes
*/
#define FC_CardReset 0x80
#define FC_ChannelReset 1 /* C320 firmware not supported */
#define FC_EnableCH 2
#define FC_DisableCH 3
#define FC_SetParam 4
#define FC_SetMode 5
#define FC_SetRate 6
#define FC_LineControl 7
#define FC_LineStatus 8
#define FC_XmitControl 9
#define FC_FlushQueue 10
#define FC_SendBreak 11
#define FC_StopBreak 12
#define FC_LoopbackON 13
#define FC_LoopbackOFF 14
#define FC_ClrIrqTable 15
#define FC_SendXon 16
#define FC_SetTermIrq 17 /* C320 firmware not supported */
#define FC_SetCntIrq 18 /* C320 firmware not supported */
#define FC_SetBreakIrq 19
#define FC_SetLineIrq 20
#define FC_SetFlowCtl 21
#define FC_GenIrq 22
#define FC_InCD180 23
#define FC_OutCD180 24
#define FC_InUARTreg 23
#define FC_OutUARTreg 24
#define FC_SetXonXoff 25
#define FC_OutCD180CCR 26
#define FC_ExtIQueue 27
#define FC_ExtOQueue 28
#define FC_ClrLineIrq 29
#define FC_HWFlowCtl 30
#define FC_GetClockRate 35
#define FC_SetBaud 36
#define FC_SetDataMode 41
#define FC_GetCCSR 43
#define FC_GetDataError 45
#define FC_RxControl 50
#define FC_ImmSend 51
#define FC_SetXonState 52
#define FC_SetXoffState 53
#define FC_SetRxFIFOTrig 54
#define FC_SetTxFIFOCnt 55
#define FC_UnixRate 56
#define FC_UnixResetTimer 57
#define RxFIFOTrig1 0
#define RxFIFOTrig4 1
#define RxFIFOTrig8 2
#define RxFIFOTrig14 3
/*
* Dual-Ported RAM
*/
#define DRAM_global 0
#define INT_data (DRAM_global + 0)
#define Config_base (DRAM_global + 0x108)
#define IRQindex (INT_data + 0)
#define IRQpending (INT_data + 4)
#define IRQtable (INT_data + 8)
/*
* Interrupt Status
*/
#define IntrRx 0x01 /* receiver data O.K. */
#define IntrTx 0x02 /* transmit buffer empty */
#define IntrFunc 0x04 /* function complete */
#define IntrBreak 0x08 /* received break */
#define IntrLine 0x10 /* line status change
for transmitter */
#define IntrIntr 0x20 /* received INTR code */
#define IntrQuit 0x40 /* received QUIT code */
#define IntrEOF 0x80 /* received EOF code */
#define IntrRxTrigger 0x100 /* rx data count reach trigger value */
#define IntrTxTrigger 0x200 /* tx data count below trigger value */
#define Magic_no (Config_base + 0)
#define Card_model_no (Config_base + 2)
#define Total_ports (Config_base + 4)
#define Module_cnt (Config_base + 8)
#define Module_no (Config_base + 10)
#define Timer_10ms (Config_base + 14)
#define Disable_IRQ (Config_base + 20)
#define TMS320_PORT1 (Config_base + 22)
#define TMS320_PORT2 (Config_base + 24)
#define TMS320_CLOCK (Config_base + 26)
/*
* DATA BUFFER in DRAM
*/
#define Extern_table 0x400 /* Base address of the external table
(24 words * 64) total 3K bytes
(24 words * 128) total 6K bytes */
#define Extern_size 0x60 /* 96 bytes */
#define RXrptr 0x00 /* read pointer for RX buffer */
#define RXwptr 0x02 /* write pointer for RX buffer */
#define TXrptr 0x04 /* read pointer for TX buffer */
#define TXwptr 0x06 /* write pointer for TX buffer */
#define HostStat 0x08 /* IRQ flag and general flag */
#define FlagStat 0x0A
#define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */
/* x x x x | | | | */
/* | | | + CTS flow */
/* | | +--- RTS flow */
/* | +------ TX Xon/Xoff */
/* +--------- RX Xon/Xoff */
#define Break_cnt 0x0E /* received break count */
#define CD180TXirq 0x10 /* if non-0: enable TX irq */
#define RX_mask 0x12
#define TX_mask 0x14
#define Ofs_rxb 0x16
#define Ofs_txb 0x18
#define Page_rxb 0x1A
#define Page_txb 0x1C
#define EndPage_rxb 0x1E
#define EndPage_txb 0x20
#define Data_error 0x22
#define RxTrigger 0x28
#define TxTrigger 0x2a
#define rRXwptr 0x34
#define Low_water 0x36
#define FuncCode 0x40
#define FuncArg 0x42
#define FuncArg1 0x44
#define C218rx_size 0x2000 /* 8K bytes */
#define C218tx_size 0x8000 /* 32K bytes */
#define C218rx_mask (C218rx_size - 1)
#define C218tx_mask (C218tx_size - 1)
#define C320p8rx_size 0x2000
#define C320p8tx_size 0x8000
#define C320p8rx_mask (C320p8rx_size - 1)
#define C320p8tx_mask (C320p8tx_size - 1)
#define C320p16rx_size 0x2000
#define C320p16tx_size 0x4000
#define C320p16rx_mask (C320p16rx_size - 1)
#define C320p16tx_mask (C320p16tx_size - 1)
#define C320p24rx_size 0x2000
#define C320p24tx_size 0x2000
#define C320p24rx_mask (C320p24rx_size - 1)
#define C320p24tx_mask (C320p24tx_size - 1)
#define C320p32rx_size 0x1000
#define C320p32tx_size 0x1000
#define C320p32rx_mask (C320p32rx_size - 1)
#define C320p32tx_mask (C320p32tx_size - 1)
#define Page_size 0x2000U
#define Page_mask (Page_size - 1)
#define C218rx_spage 3
#define C218tx_spage 4
#define C218rx_pageno 1
#define C218tx_pageno 4
#define C218buf_pageno 5
#define C320p8rx_spage 3
#define C320p8tx_spage 4
#define C320p8rx_pgno 1
#define C320p8tx_pgno 4
#define C320p8buf_pgno 5
#define C320p16rx_spage 3
#define C320p16tx_spage 4
#define C320p16rx_pgno 1
#define C320p16tx_pgno 2
#define C320p16buf_pgno 3
#define C320p24rx_spage 3
#define C320p24tx_spage 4
#define C320p24rx_pgno 1
#define C320p24tx_pgno 1
#define C320p24buf_pgno 2
#define C320p32rx_spage 3
#define C320p32tx_ofs C320p32rx_size
#define C320p32tx_spage 3
#define C320p32buf_pgno 1
/*
* Host Status
*/
#define WakeupRx 0x01
#define WakeupTx 0x02
#define WakeupBreak 0x08
#define WakeupLine 0x10
#define WakeupIntr 0x20
#define WakeupQuit 0x40
#define WakeupEOF 0x80 /* used in VTIME control */
#define WakeupRxTrigger 0x100
#define WakeupTxTrigger 0x200
/*
* Flag status
*/
#define Rx_over 0x01
#define Xoff_state 0x02
#define Tx_flowOff 0x04
#define Tx_enable 0x08
#define CTS_state 0x10
#define DSR_state 0x20
#define DCD_state 0x80
/*
* FlowControl
*/
#define CTS_FlowCtl 1
#define RTS_FlowCtl 2
#define Tx_FlowCtl 4
#define Rx_FlowCtl 8
#define IXM_IXANY 0x10
#define LowWater 128
#define DTR_ON 1
#define RTS_ON 2
#define CTS_ON 1
#define DSR_ON 2
#define DCD_ON 8
/* mode definition */
#define MX_CS8 0x03
#define MX_CS7 0x02
#define MX_CS6 0x01
#define MX_CS5 0x00
#define MX_STOP1 0x00
#define MX_STOP15 0x04
#define MX_STOP2 0x08
#define MX_PARNONE 0x00
#define MX_PAREVEN 0x40
#define MX_PARODD 0xC0
#define MX_PARMARK 0xA0
#define MX_PARSPACE 0x20
#define MOXA_VERSION "6.0k"

View File

@ -1,307 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef MOXA_H_FILE
#define MOXA_H_FILE
#define MOXA 0x400
#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */
#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */
#define MOXA_GETDATACOUNT (MOXA + 23)
#define MOXA_GET_IOQUEUE (MOXA + 27)
#define MOXA_FLUSH_QUEUE (MOXA + 28)
#define MOXA_GETMSTATUS (MOXA + 65)
/*
* System Configuration
*/
#define Magic_code 0x404
/*
* for C218 BIOS initialization
*/
#define C218_ConfBase 0x800
#define C218_status (C218_ConfBase + 0) /* BIOS running status */
#define C218_diag (C218_ConfBase + 2) /* diagnostic status */
#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */
#define C218DLoad_len (C218_ConfBase + 6) /* WORD */
#define C218check_sum (C218_ConfBase + 8) /* BYTE */
#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */
#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */
#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */
#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */
#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */
#define C218_LoadBuf 0x0F00
#define C218_KeyCode 0x218
#define CP204J_KeyCode 0x204
/*
* for C320 BIOS initialization
*/
#define C320_ConfBase 0x800
#define C320_LoadBuf 0x0f00
#define STS_init 0x05 /* for C320_status */
#define C320_status C320_ConfBase + 0 /* BIOS running status */
#define C320_diag C320_ConfBase + 2 /* diagnostic status */
#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */
#define C320DLoad_len C320_ConfBase + 6 /* WORD */
#define C320check_sum C320_ConfBase + 8 /* WORD */
#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */
#define C320bapi_len C320_ConfBase + 0x0c /* WORD */
#define C320UART_no C320_ConfBase + 0x0e /* WORD */
#define C320_KeyCode 0x320
#define FixPage_addr 0x0000 /* starting addr of static page */
#define DynPage_addr 0x2000 /* starting addr of dynamic page */
#define C218_start 0x3000 /* starting addr of C218 BIOS prg */
#define Control_reg 0x1ff0 /* select page and reset control */
#define HW_reset 0x80
/*
* Function Codes
*/
#define FC_CardReset 0x80
#define FC_ChannelReset 1 /* C320 firmware not supported */
#define FC_EnableCH 2
#define FC_DisableCH 3
#define FC_SetParam 4
#define FC_SetMode 5
#define FC_SetRate 6
#define FC_LineControl 7
#define FC_LineStatus 8
#define FC_XmitControl 9
#define FC_FlushQueue 10
#define FC_SendBreak 11
#define FC_StopBreak 12
#define FC_LoopbackON 13
#define FC_LoopbackOFF 14
#define FC_ClrIrqTable 15
#define FC_SendXon 16
#define FC_SetTermIrq 17 /* C320 firmware not supported */
#define FC_SetCntIrq 18 /* C320 firmware not supported */
#define FC_SetBreakIrq 19
#define FC_SetLineIrq 20
#define FC_SetFlowCtl 21
#define FC_GenIrq 22
#define FC_InCD180 23
#define FC_OutCD180 24
#define FC_InUARTreg 23
#define FC_OutUARTreg 24
#define FC_SetXonXoff 25
#define FC_OutCD180CCR 26
#define FC_ExtIQueue 27
#define FC_ExtOQueue 28
#define FC_ClrLineIrq 29
#define FC_HWFlowCtl 30
#define FC_GetClockRate 35
#define FC_SetBaud 36
#define FC_SetDataMode 41
#define FC_GetCCSR 43
#define FC_GetDataError 45
#define FC_RxControl 50
#define FC_ImmSend 51
#define FC_SetXonState 52
#define FC_SetXoffState 53
#define FC_SetRxFIFOTrig 54
#define FC_SetTxFIFOCnt 55
#define FC_UnixRate 56
#define FC_UnixResetTimer 57
#define RxFIFOTrig1 0
#define RxFIFOTrig4 1
#define RxFIFOTrig8 2
#define RxFIFOTrig14 3
/*
* Dual-Ported RAM
*/
#define DRAM_global 0
#define INT_data (DRAM_global + 0)
#define Config_base (DRAM_global + 0x108)
#define IRQindex (INT_data + 0)
#define IRQpending (INT_data + 4)
#define IRQtable (INT_data + 8)
/*
* Interrupt Status
*/
#define IntrRx 0x01 /* receiver data O.K. */
#define IntrTx 0x02 /* transmit buffer empty */
#define IntrFunc 0x04 /* function complete */
#define IntrBreak 0x08 /* received break */
#define IntrLine 0x10 /* line status change
for transmitter */
#define IntrIntr 0x20 /* received INTR code */
#define IntrQuit 0x40 /* received QUIT code */
#define IntrEOF 0x80 /* received EOF code */
#define IntrRxTrigger 0x100 /* rx data count reach trigger value */
#define IntrTxTrigger 0x200 /* tx data count below trigger value */
#define Magic_no (Config_base + 0)
#define Card_model_no (Config_base + 2)
#define Total_ports (Config_base + 4)
#define Module_cnt (Config_base + 8)
#define Module_no (Config_base + 10)
#define Timer_10ms (Config_base + 14)
#define Disable_IRQ (Config_base + 20)
#define TMS320_PORT1 (Config_base + 22)
#define TMS320_PORT2 (Config_base + 24)
#define TMS320_CLOCK (Config_base + 26)
/*
* DATA BUFFER in DRAM
*/
#define Extern_table 0x400 /* Base address of the external table
(24 words * 64) total 3K bytes
(24 words * 128) total 6K bytes */
#define Extern_size 0x60 /* 96 bytes */
#define RXrptr 0x00 /* read pointer for RX buffer */
#define RXwptr 0x02 /* write pointer for RX buffer */
#define TXrptr 0x04 /* read pointer for TX buffer */
#define TXwptr 0x06 /* write pointer for TX buffer */
#define HostStat 0x08 /* IRQ flag and general flag */
#define FlagStat 0x0A
#define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */
/* x x x x | | | | */
/* | | | + CTS flow */
/* | | +--- RTS flow */
/* | +------ TX Xon/Xoff */
/* +--------- RX Xon/Xoff */
#define Break_cnt 0x0E /* received break count */
#define CD180TXirq 0x10 /* if non-0: enable TX irq */
#define RX_mask 0x12
#define TX_mask 0x14
#define Ofs_rxb 0x16
#define Ofs_txb 0x18
#define Page_rxb 0x1A
#define Page_txb 0x1C
#define EndPage_rxb 0x1E
#define EndPage_txb 0x20
#define Data_error 0x22
#define RxTrigger 0x28
#define TxTrigger 0x2a
#define rRXwptr 0x34
#define Low_water 0x36
#define FuncCode 0x40
#define FuncArg 0x42
#define FuncArg1 0x44
#define C218rx_size 0x2000 /* 8K bytes */
#define C218tx_size 0x8000 /* 32K bytes */
#define C218rx_mask (C218rx_size - 1)
#define C218tx_mask (C218tx_size - 1)
#define C320p8rx_size 0x2000
#define C320p8tx_size 0x8000
#define C320p8rx_mask (C320p8rx_size - 1)
#define C320p8tx_mask (C320p8tx_size - 1)
#define C320p16rx_size 0x2000
#define C320p16tx_size 0x4000
#define C320p16rx_mask (C320p16rx_size - 1)
#define C320p16tx_mask (C320p16tx_size - 1)
#define C320p24rx_size 0x2000
#define C320p24tx_size 0x2000
#define C320p24rx_mask (C320p24rx_size - 1)
#define C320p24tx_mask (C320p24tx_size - 1)
#define C320p32rx_size 0x1000
#define C320p32tx_size 0x1000
#define C320p32rx_mask (C320p32rx_size - 1)
#define C320p32tx_mask (C320p32tx_size - 1)
#define Page_size 0x2000U
#define Page_mask (Page_size - 1)
#define C218rx_spage 3
#define C218tx_spage 4
#define C218rx_pageno 1
#define C218tx_pageno 4
#define C218buf_pageno 5
#define C320p8rx_spage 3
#define C320p8tx_spage 4
#define C320p8rx_pgno 1
#define C320p8tx_pgno 4
#define C320p8buf_pgno 5
#define C320p16rx_spage 3
#define C320p16tx_spage 4
#define C320p16rx_pgno 1
#define C320p16tx_pgno 2
#define C320p16buf_pgno 3
#define C320p24rx_spage 3
#define C320p24tx_spage 4
#define C320p24rx_pgno 1
#define C320p24tx_pgno 1
#define C320p24buf_pgno 2
#define C320p32rx_spage 3
#define C320p32tx_ofs C320p32rx_size
#define C320p32tx_spage 3
#define C320p32buf_pgno 1
/*
* Host Status
*/
#define WakeupRx 0x01
#define WakeupTx 0x02
#define WakeupBreak 0x08
#define WakeupLine 0x10
#define WakeupIntr 0x20
#define WakeupQuit 0x40
#define WakeupEOF 0x80 /* used in VTIME control */
#define WakeupRxTrigger 0x100
#define WakeupTxTrigger 0x200
/*
* Flag status
*/
#define Rx_over 0x01
#define Xoff_state 0x02
#define Tx_flowOff 0x04
#define Tx_enable 0x08
#define CTS_state 0x10
#define DSR_state 0x20
#define DCD_state 0x80
/*
* FlowControl
*/
#define CTS_FlowCtl 1
#define RTS_FlowCtl 2
#define Tx_FlowCtl 4
#define Rx_FlowCtl 8
#define IXM_IXANY 0x10
#define LowWater 128
#define DTR_ON 1
#define RTS_ON 2
#define CTS_ON 1
#define DSR_ON 2
#define DCD_ON 8
/* mode definition */
#define MX_CS8 0x03
#define MX_CS7 0x02
#define MX_CS6 0x01
#define MX_CS5 0x00
#define MX_STOP1 0x00
#define MX_STOP15 0x04
#define MX_STOP2 0x08
#define MX_PARNONE 0x00
#define MX_PAREVEN 0x40
#define MX_PARODD 0xC0
#define MX_PARMARK 0xA0
#define MX_PARSPACE 0x20
#endif

View File

@ -249,8 +249,9 @@ struct mxser_port {
unsigned char x_char; /* xon/xoff character */
u8 IER; /* Interrupt Enable Register */
u8 MCR; /* Modem control register */
u8 FCR; /* FIFO control register */
unsigned char ldisc_stop_rx;
bool ldisc_stop_rx;
struct async_icount icount; /* kernel counters for 4 input interrupts */
unsigned int timeout;
@ -559,14 +560,20 @@ static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info,
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
static void mxser_change_speed(struct tty_struct *tty)
static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_termios)
{
struct mxser_port *info = tty->driver_data;
unsigned cflag, cval, fcr;
unsigned cflag, cval;
cflag = tty->termios.c_cflag;
mxser_set_baud(tty, tty_get_baud_rate(tty));
if (mxser_set_baud(tty, tty_get_baud_rate(tty))) {
/* Use previous rate on a failure */
if (old_termios) {
speed_t baud = tty_termios_baud_rate(old_termios);
tty_encode_baud_rate(tty, baud, baud);
}
}
/* byte size and parity */
switch (cflag & CSIZE) {
@ -594,33 +601,26 @@ static void mxser_change_speed(struct tty_struct *tty)
if (cflag & CMSPAR)
cval |= UART_LCR_SPAR;
if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
if (info->board->must_hwid) {
fcr = UART_FCR_ENABLE_FIFO;
fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
mxser_set_must_fifo_value(info);
} else
fcr = 0;
} else {
fcr = UART_FCR_ENABLE_FIFO;
if (info->board->must_hwid) {
fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
mxser_set_must_fifo_value(info);
} else {
switch (info->rx_high_water) {
case 1:
fcr |= UART_FCR_TRIGGER_1;
break;
case 4:
fcr |= UART_FCR_TRIGGER_4;
break;
case 8:
fcr |= UART_FCR_TRIGGER_8;
break;
default:
fcr |= UART_FCR_TRIGGER_14;
break;
}
info->FCR = 0;
if (info->board->must_hwid) {
info->FCR |= UART_FCR_ENABLE_FIFO |
MOXA_MUST_FCR_GDA_MODE_ENABLE;
mxser_set_must_fifo_value(info);
} else if (info->type != PORT_8250 && info->type != PORT_16450) {
info->FCR |= UART_FCR_ENABLE_FIFO;
switch (info->rx_high_water) {
case 1:
info->FCR |= UART_FCR_TRIGGER_1;
break;
case 4:
info->FCR |= UART_FCR_TRIGGER_4;
break;
case 8:
info->FCR |= UART_FCR_TRIGGER_8;
break;
default:
info->FCR |= UART_FCR_TRIGGER_14;
break;
}
}
@ -680,7 +680,7 @@ static void mxser_change_speed(struct tty_struct *tty)
}
outb(fcr, info->ioaddr + UART_FCR); /* set fcr */
outb(info->FCR, info->ioaddr + UART_FCR);
outb(cval, info->ioaddr + UART_LCR);
}
@ -707,6 +707,16 @@ static void mxser_check_modem_status(struct tty_struct *tty,
mxser_handle_cts(tty, port, status);
}
static void mxser_disable_and_clear_FIFO(struct mxser_port *info)
{
u8 fcr = UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT;
if (info->board->must_hwid)
fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
outb(fcr, info->ioaddr + UART_FCR);
}
static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
{
struct mxser_port *info = container_of(port, struct mxser_port, port);
@ -731,13 +741,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
* Clear the FIFO buffers and disable them
* (they will be reenabled in mxser_change_speed())
*/
if (info->board->must_hwid)
outb((UART_FCR_CLEAR_RCVR |
UART_FCR_CLEAR_XMIT |
MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR);
else
outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
info->ioaddr + UART_FCR);
mxser_disable_and_clear_FIFO(info);
/*
* At this point there's no way the LSR could still be 0xFF;
@ -791,7 +795,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
/*
* and set the speed of the serial port
*/
mxser_change_speed(tty);
mxser_change_speed(tty, NULL);
spin_unlock_irqrestore(&info->slock, flags);
return 0;
@ -825,13 +829,7 @@ static void mxser_shutdown_port(struct tty_port *port)
outb(0x00, info->ioaddr + UART_IER);
/* clear Rx/Tx FIFO's */
if (info->board->must_hwid)
outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
MOXA_MUST_FCR_GDA_MODE_ENABLE,
info->ioaddr + UART_FCR);
else
outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
info->ioaddr + UART_FCR);
mxser_disable_and_clear_FIFO(info);
/* read data port to reset things */
(void) inb(info->ioaddr + UART_RX);
@ -862,17 +860,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
static void mxser_flush_buffer(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
char fcr;
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
fcr = inb(info->ioaddr + UART_FCR);
outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
outb(info->FCR | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
info->ioaddr + UART_FCR);
outb(fcr, info->ioaddr + UART_FCR);
spin_unlock_irqrestore(&info->slock, flags);
@ -1119,7 +1114,7 @@ static int mxser_set_serial_info(struct tty_struct *tty,
if (tty_port_initialized(port)) {
if (old_speed != (port->flags & ASYNC_SPD_MASK)) {
spin_lock_irqsave(&info->slock, sl_flags);
mxser_change_speed(tty);
mxser_change_speed(tty, NULL);
spin_unlock_irqrestore(&info->slock, sl_flags);
}
} else {
@ -1335,7 +1330,7 @@ static void mxser_stoprx(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
info->ldisc_stop_rx = 1;
info->ldisc_stop_rx = true;
if (I_IXOFF(tty)) {
if (info->board->must_hwid) {
info->IER &= ~MOXA_MUST_RECV_ISR;
@ -1368,7 +1363,7 @@ static void mxser_unthrottle(struct tty_struct *tty)
struct mxser_port *info = tty->driver_data;
/* startrx */
info->ldisc_stop_rx = 0;
info->ldisc_stop_rx = false;
if (I_IXOFF(tty)) {
if (info->x_char)
info->x_char = 0;
@ -1425,7 +1420,7 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
mxser_change_speed(tty);
mxser_change_speed(tty, old_termios);
spin_unlock_irqrestore(&info->slock, flags);
if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) {
@ -1544,11 +1539,7 @@ static bool mxser_receive_chars_new(struct tty_struct *tty,
if (hwid == MOXA_OTHER_UART)
return false;
if (status & UART_LSR_BRK_ERROR_BITS)
return false;
if (hwid == MOXA_MUST_MU860_HWID && (status & MOXA_MUST_LSR_RERR))
return false;
if (status & MOXA_MUST_LSR_RERR)
if (status & (UART_LSR_BRK_ERROR_BITS | MOXA_MUST_LSR_RERR))
return false;
gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER);
@ -1582,8 +1573,7 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty,
ch = inb(port->ioaddr + UART_RX);
if (hwid && (status & UART_LSR_OE))
outb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
MOXA_MUST_FCR_GDA_MODE_ENABLE,
outb(port->FCR | UART_FCR_CLEAR_RCVR,
port->ioaddr + UART_FCR);
status &= port->read_status_mask;
if (status & port->ignore_status_mask) {
@ -1695,8 +1685,7 @@ static bool mxser_port_isr(struct mxser_port *port)
tty = tty_port_tty_get(&port->port);
if (!tty || port->closing || !tty_port_initialized(&port->port)) {
status = inb(port->ioaddr + UART_LSR);
outb(MOXA_MUST_FCR_GDA_MODE_ENABLE | UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
outb(port->FCR | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
port->ioaddr + UART_FCR);
inb(port->ioaddr + UART_MSR);
@ -1847,7 +1836,7 @@ static void mxser_initbrd(struct mxser_board *brd, bool high_baud)
tty_port_init(&info->port);
info->port.ops = &mxser_port_ops;
info->board = brd;
info->ldisc_stop_rx = 0;
info->ldisc_stop_rx = false;
/* Enhance mode enabled here */
if (brd->must_hwid != MOXA_OTHER_UART)

View File

@ -271,6 +271,10 @@ static DEFINE_SPINLOCK(gsm_mux_lock);
static struct tty_driver *gsm_tty_driver;
/* Save dlci open address */
static int addr_open[256] = { 0 };
/* Save dlci open count */
static int addr_cnt;
/*
* This section of the driver logic implements the GSM encodings
* both the basic and the 'advanced'. Reliable transport is not
@ -587,6 +591,10 @@ static void gsm_send(struct gsm_mux *gsm, int addr, int cr, int control)
return;
}
gsmld_output(gsm, cbuf, len);
if (!gsm->initiator) {
cr = cr & gsm->initiator;
control = control & ~PF;
}
gsm_print_packet("-->", addr, cr, control, NULL, 0);
}
@ -601,7 +609,7 @@ static void gsm_send(struct gsm_mux *gsm, int addr, int cr, int control)
static inline void gsm_response(struct gsm_mux *gsm, int addr, int control)
{
gsm_send(gsm, addr, 0, control);
gsm_send(gsm, addr, 1, control);
}
/**
@ -687,7 +695,7 @@ static void gsm_data_kick(struct gsm_mux *gsm, struct gsm_dlci *dlci)
print_hex_dump_bytes("gsm_data_kick: ",
DUMP_PREFIX_OFFSET,
gsm->txframe, len);
if (gsmld_output(gsm, gsm->txframe, len) < 0)
if (gsmld_output(gsm, gsm->txframe, len) <= 0)
break;
/* FIXME: Can eliminate one SOF in many more cases */
gsm->tx_bytes -= msg->len;
@ -1177,6 +1185,7 @@ static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
}
static void gsm_dlci_begin_close(struct gsm_dlci *dlci);
static void gsm_dlci_close(struct gsm_dlci *dlci);
/**
* gsm_control_message - DLCI 0 control processing
@ -1195,15 +1204,28 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
{
u8 buf[1];
unsigned long flags;
struct gsm_dlci *dlci;
int i;
int address;
switch (command) {
case CMD_CLD: {
struct gsm_dlci *dlci = gsm->dlci[0];
if (addr_cnt > 0) {
for (i = 0; i < addr_cnt; i++) {
address = addr_open[i];
dlci = gsm->dlci[address];
gsm_dlci_close(dlci);
addr_open[i] = 0;
}
}
/* Modem wishes to close down */
dlci = gsm->dlci[0];
if (dlci) {
dlci->dead = true;
gsm->dead = true;
gsm_dlci_begin_close(dlci);
gsm_dlci_close(dlci);
addr_cnt = 0;
gsm_response(gsm, 0, UA|PF);
}
}
break;
@ -1429,6 +1451,8 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
kfifo_reset(&dlci->fifo);
} else
dlci->gsm->dead = true;
/* Unregister gsmtty driver,report gsmtty dev remove uevent for user */
tty_unregister_device(gsm_tty_driver, dlci->addr);
wake_up(&dlci->gsm->event);
/* A DLCI 0 close is a MUX termination so we need to kick that
back to userspace somehow */
@ -1450,6 +1474,8 @@ static void gsm_dlci_open(struct gsm_dlci *dlci)
dlci->state = DLCI_OPEN;
if (debug & 8)
pr_debug("DLCI %d goes open.\n", dlci->addr);
/* Register gsmtty driver,report gsmtty dev add uevent for user */
tty_register_device(gsm_tty_driver, dlci->addr, NULL);
wake_up(&dlci->gsm->event);
}
@ -1748,6 +1774,7 @@ static void gsm_queue(struct gsm_mux *gsm)
struct gsm_dlci *dlci;
u8 cr;
int address;
int i, j, k, address_tmp;
/* We have to sneak a look at the packet body to do the FCS.
A somewhat layering violation in the spec */
@ -1779,29 +1806,59 @@ static void gsm_queue(struct gsm_mux *gsm)
switch (gsm->control) {
case SABM|PF:
if (cr == 0)
if (cr == 1)
goto invalid;
if (dlci == NULL)
dlci = gsm_dlci_alloc(gsm, address);
if (dlci == NULL)
return;
if (dlci->dead)
gsm_response(gsm, address, DM);
gsm_response(gsm, address, DM|PF);
else {
gsm_response(gsm, address, UA);
gsm_response(gsm, address, UA|PF);
gsm_dlci_open(dlci);
/* Save dlci open address */
if (address) {
addr_open[addr_cnt] = address;
addr_cnt++;
}
}
break;
case DISC|PF:
if (cr == 0)
if (cr == 1)
goto invalid;
if (dlci == NULL || dlci->state == DLCI_CLOSED) {
gsm_response(gsm, address, DM);
gsm_response(gsm, address, DM|PF);
return;
}
/* Real close complete */
gsm_response(gsm, address, UA);
gsm_dlci_close(dlci);
if (!address) {
if (addr_cnt > 0) {
for (i = 0; i < addr_cnt; i++) {
address = addr_open[i];
dlci = gsm->dlci[address];
gsm_dlci_close(dlci);
addr_open[i] = 0;
}
}
dlci = gsm->dlci[0];
gsm_dlci_close(dlci);
addr_cnt = 0;
gsm_response(gsm, 0, UA|PF);
} else {
gsm_response(gsm, address, UA|PF);
gsm_dlci_close(dlci);
/* clear dlci address */
for (j = 0; j < addr_cnt; j++) {
address_tmp = addr_open[j];
if (address_tmp == address) {
for (k = j; k < addr_cnt; k++)
addr_open[k] = addr_open[k+1];
addr_cnt--;
break;
}
}
}
break;
case UA:
case UA|PF:
@ -2300,7 +2357,7 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
* configuration
*/
if (need_close || need_restart) {
if (gsm->initiator && (need_close || need_restart)) {
int ret;
ret = gsm_disconnect(gsm);
@ -2358,8 +2415,7 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
if (debug & 4)
print_hex_dump_bytes("gsmld_output: ", DUMP_PREFIX_OFFSET,
data, len);
gsm->tty->ops->write(gsm->tty, data, len);
return len;
return gsm->tty->ops->write(gsm->tty, data, len);
}
/**
@ -2384,17 +2440,19 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
else {
/* 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++) {
struct device *dev;
if (gsm->initiator) {
base = mux_num_to_base(gsm); /* Base for this MUX */
for (i = 1; i < NUM_DLCI; i++) {
struct device *dev;
dev = tty_register_device(gsm_tty_driver,
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);
if (IS_ERR(dev)) {
for (i--; i >= 1; i--)
tty_unregister_device(gsm_tty_driver,
base + i);
return PTR_ERR(dev);
}
}
}
}
@ -2416,8 +2474,10 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
int i;
WARN_ON(tty != gsm->tty);
for (i = 1; i < NUM_DLCI; i++)
tty_unregister_device(gsm_tty_driver, base + i);
if (gsm->initiator) {
for (i = 1; i < NUM_DLCI; i++)
tty_unregister_device(gsm_tty_driver, base + i);
}
gsm_cleanup_mux(gsm);
tty_kref_put(gsm->tty);
gsm->tty = NULL;
@ -2651,7 +2711,7 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
base = mux_num_to_base(gsm);
return put_user(base + 1, (__u32 __user *)arg);
default:
return n_tty_ioctl_helper(tty, file, cmd, arg);
return n_tty_ioctl_helper(tty, cmd, arg);
}
}
@ -3000,6 +3060,7 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
{
struct gsm_dlci *dlci = tty->driver_data;
struct tty_port *port = &dlci->port;
struct gsm_mux *gsm = dlci->gsm;
port->count++;
tty_port_tty_set(port, tty);
@ -3009,7 +3070,8 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
a DM straight back. This is ok as that will have caused a hangup */
tty_port_set_initialized(port, 1);
/* Start sending off SABM messages */
gsm_dlci_begin_open(dlci);
if (gsm->initiator)
gsm_dlci_begin_open(dlci);
/* And wait for virtual carrier */
return tty_port_block_til_ready(port, tty, filp);
}

View File

@ -630,7 +630,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
fallthrough; /* to default */
default:
error = n_tty_ioctl_helper(tty, file, cmd, arg);
error = n_tty_ioctl_helper(tty, cmd, arg);
break;
}
return error;

View File

@ -2418,7 +2418,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
up_write(&tty->termios_rwsem);
return put_user(retval, (unsigned int __user *) arg);
default:
return n_tty_ioctl_helper(tty, file, cmd, arg);
return n_tty_ioctl_helper(tty, cmd, arg);
}
}
@ -2450,7 +2450,6 @@ void n_tty_inherit_ops(struct tty_ldisc_ops *ops)
{
*ops = n_tty_ops;
ops->owner = NULL;
ops->flags = 0;
}
EXPORT_SYMBOL_GPL(n_tty_inherit_ops);

275
drivers/tty/rpmsg_tty.c Normal file
View File

@ -0,0 +1,275 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 STMicroelectronics - All Rights Reserved
*
* The rpmsg tty driver implements serial communication on the RPMsg bus to makes
* possible for user-space programs to send and receive rpmsg messages as a standard
* tty protocol.
*
* The remote processor can instantiate a new tty by requesting a "rpmsg-tty" RPMsg service.
* The "rpmsg-tty" service is directly used for data exchange. No flow control is implemented yet.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/rpmsg.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#define RPMSG_TTY_NAME "ttyRPMSG"
#define MAX_TTY_RPMSG 32
static DEFINE_IDR(tty_idr); /* tty instance id */
static DEFINE_MUTEX(idr_lock); /* protects tty_idr */
static struct tty_driver *rpmsg_tty_driver;
struct rpmsg_tty_port {
struct tty_port port; /* TTY port data */
int id; /* TTY rpmsg index */
struct rpmsg_device *rpdev; /* rpmsg device */
};
static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 src)
{
struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev);
int copied;
if (!len)
return -EINVAL;
copied = tty_insert_flip_string(&cport->port, data, len);
if (copied != len)
dev_err_ratelimited(&rpdev->dev, "Trunc buffer: available space is %d\n", copied);
tty_flip_buffer_push(&cport->port);
return 0;
}
static int rpmsg_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct rpmsg_tty_port *cport = idr_find(&tty_idr, tty->index);
tty->driver_data = cport;
return tty_port_install(&cport->port, driver, tty);
}
static int rpmsg_tty_open(struct tty_struct *tty, struct file *filp)
{
return tty_port_open(tty->port, tty, filp);
}
static void rpmsg_tty_close(struct tty_struct *tty, struct file *filp)
{
return tty_port_close(tty->port, tty, filp);
}
static int rpmsg_tty_write(struct tty_struct *tty, const u8 *buf, int len)
{
struct rpmsg_tty_port *cport = tty->driver_data;
struct rpmsg_device *rpdev;
int msg_max_size, msg_size;
int ret;
rpdev = cport->rpdev;
msg_max_size = rpmsg_get_mtu(rpdev->ept);
if (msg_max_size < 0)
return msg_max_size;
msg_size = min(len, msg_max_size);
/*
* Use rpmsg_trysend instead of rpmsg_send to send the message so the caller is not
* hung until a rpmsg buffer is available. In such case rpmsg_trysend returns -ENOMEM.
*/
ret = rpmsg_trysend(rpdev->ept, (void *)buf, msg_size);
if (ret) {
dev_dbg_ratelimited(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
return ret;
}
return msg_size;
}
static unsigned int rpmsg_tty_write_room(struct tty_struct *tty)
{
struct rpmsg_tty_port *cport = tty->driver_data;
int size;
size = rpmsg_get_mtu(cport->rpdev->ept);
if (size < 0)
return 0;
return size;
}
static const struct tty_operations rpmsg_tty_ops = {
.install = rpmsg_tty_install,
.open = rpmsg_tty_open,
.close = rpmsg_tty_close,
.write = rpmsg_tty_write,
.write_room = rpmsg_tty_write_room,
};
static struct rpmsg_tty_port *rpmsg_tty_alloc_cport(void)
{
struct rpmsg_tty_port *cport;
int ret;
cport = kzalloc(sizeof(*cport), GFP_KERNEL);
if (!cport)
return ERR_PTR(-ENOMEM);
mutex_lock(&idr_lock);
ret = idr_alloc(&tty_idr, cport, 0, MAX_TTY_RPMSG, GFP_KERNEL);
mutex_unlock(&idr_lock);
if (ret < 0) {
kfree(cport);
return ERR_PTR(ret);
}
cport->id = ret;
return cport;
}
static void rpmsg_tty_release_cport(struct rpmsg_tty_port *cport)
{
mutex_lock(&idr_lock);
idr_remove(&tty_idr, cport->id);
mutex_unlock(&idr_lock);
kfree(cport);
}
static const struct tty_port_operations rpmsg_tty_port_ops = { };
static int rpmsg_tty_probe(struct rpmsg_device *rpdev)
{
struct rpmsg_tty_port *cport;
struct device *dev = &rpdev->dev;
struct device *tty_dev;
int ret;
cport = rpmsg_tty_alloc_cport();
if (IS_ERR(cport))
return dev_err_probe(dev, PTR_ERR(cport), "Failed to alloc tty port\n");
tty_port_init(&cport->port);
cport->port.ops = &rpmsg_tty_port_ops;
tty_dev = tty_port_register_device(&cport->port, rpmsg_tty_driver,
cport->id, dev);
if (IS_ERR(tty_dev)) {
ret = dev_err_probe(dev, PTR_ERR(tty_dev), "Failed to register tty port\n");
goto err_destroy;
}
cport->rpdev = rpdev;
dev_set_drvdata(dev, cport);
dev_dbg(dev, "New channel: 0x%x -> 0x%x: " RPMSG_TTY_NAME "%d\n",
rpdev->src, rpdev->dst, cport->id);
return 0;
err_destroy:
tty_port_destroy(&cport->port);
rpmsg_tty_release_cport(cport);
return ret;
}
static void rpmsg_tty_remove(struct rpmsg_device *rpdev)
{
struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev);
dev_dbg(&rpdev->dev, "Removing rpmsg tty device %d\n", cport->id);
/* User hang up to release the tty */
if (tty_port_initialized(&cport->port))
tty_port_tty_hangup(&cport->port, false);
tty_unregister_device(rpmsg_tty_driver, cport->id);
tty_port_destroy(&cport->port);
rpmsg_tty_release_cport(cport);
}
static struct rpmsg_device_id rpmsg_driver_tty_id_table[] = {
{ .name = "rpmsg-tty" },
{ },
};
MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_tty_id_table);
static struct rpmsg_driver rpmsg_tty_rpmsg_drv = {
.drv.name = KBUILD_MODNAME,
.id_table = rpmsg_driver_tty_id_table,
.probe = rpmsg_tty_probe,
.callback = rpmsg_tty_cb,
.remove = rpmsg_tty_remove,
};
static int __init rpmsg_tty_init(void)
{
int ret;
rpmsg_tty_driver = tty_alloc_driver(MAX_TTY_RPMSG, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(rpmsg_tty_driver))
return PTR_ERR(rpmsg_tty_driver);
rpmsg_tty_driver->driver_name = "rpmsg_tty";
rpmsg_tty_driver->name = RPMSG_TTY_NAME;
rpmsg_tty_driver->major = 0;
rpmsg_tty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
/* Disable unused mode by default */
rpmsg_tty_driver->init_termios = tty_std_termios;
rpmsg_tty_driver->init_termios.c_lflag &= ~(ECHO | ICANON);
rpmsg_tty_driver->init_termios.c_oflag &= ~(OPOST | ONLCR);
tty_set_operations(rpmsg_tty_driver, &rpmsg_tty_ops);
ret = tty_register_driver(rpmsg_tty_driver);
if (ret < 0) {
pr_err("Couldn't install driver: %d\n", ret);
goto error_put;
}
ret = register_rpmsg_driver(&rpmsg_tty_rpmsg_drv);
if (ret < 0) {
pr_err("Couldn't register driver: %d\n", ret);
goto error_unregister;
}
return 0;
error_unregister:
tty_unregister_driver(rpmsg_tty_driver);
error_put:
tty_driver_kref_put(rpmsg_tty_driver);
return ret;
}
static void __exit rpmsg_tty_exit(void)
{
unregister_rpmsg_driver(&rpmsg_tty_rpmsg_drv);
tty_unregister_driver(rpmsg_tty_driver);
tty_driver_kref_put(rpmsg_tty_driver);
idr_destroy(&tty_idr);
}
module_init(rpmsg_tty_init);
module_exit(rpmsg_tty_exit);
MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>");
MODULE_DESCRIPTION("remote processor messaging tty driver");
MODULE_LICENSE("GPL v2");

View File

@ -338,23 +338,16 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
rate = clk_round_rate(d->clk, newrate);
if (rate > 0) {
/*
* Premilinary set the uartclk to the new clock rate so the
* clock update event handler caused by the clk_set_rate()
* calling wouldn't actually update the UART divisor since
* we about to do this anyway.
* Note that any clock-notifer worker will block in
* serial8250_update_uartclk() until we are done.
*/
swap(p->uartclk, rate);
ret = clk_set_rate(d->clk, newrate);
if (ret)
swap(p->uartclk, rate);
if (!ret)
p->uartclk = rate;
}
clk_prepare_enable(d->clk);
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
serial8250_do_set_termios(p, termios, old);
dw8250_do_set_termios(p, termios, old);
}
static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios)
@ -393,8 +386,9 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
{
if (p->dev->of_node) {
struct device_node *np = p->dev->of_node;
struct device_node *np = p->dev->of_node;
if (np) {
int id;
/* get index of serial line, if found in DT aliases */
@ -411,11 +405,13 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
data->skip_autocfg = true;
}
#endif
if (of_device_is_big_endian(p->dev->of_node)) {
if (of_device_is_big_endian(np)) {
p->iotype = UPIO_MEM32BE;
p->serial_in = dw8250_serial_in32be;
p->serial_out = dw8250_serial_out32be;
}
if (of_device_is_compatible(np, "marvell,armada-38x-uart"))
p->serial_out = dw8250_serial_out38x;
@ -726,7 +722,7 @@ static struct platform_driver dw8250_platform_driver = {
.name = "dw-apb-uart",
.pm = &dw8250_pm_ops,
.of_match_table = dw8250_of_match,
.acpi_match_table = ACPI_PTR(dw8250_acpi_match),
.acpi_match_table = dw8250_acpi_match,
},
.probe = dw8250_probe,
.remove = dw8250_remove,

View File

@ -77,6 +77,16 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
serial8250_do_set_divisor(p, baud, quot, quot_frac);
}
void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old)
{
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
serial8250_do_set_termios(p, termios, old);
}
EXPORT_SYMBOL_GPL(dw8250_do_set_termios);
void dw8250_setup_port(struct uart_port *p)
{
struct uart_8250_port *up = up_to_u8250p(p);

View File

@ -16,4 +16,5 @@ struct dw8250_port_data {
u8 dlf_size;
};
void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);
void dw8250_setup_port(struct uart_port *p);

View File

@ -23,10 +23,6 @@
#include "8250.h"
struct fsl8250_data {
int line;
};
int fsl8250_handle_irq(struct uart_port *port)
{
unsigned char lsr, orig_lsr;
@ -90,6 +86,10 @@ int fsl8250_handle_irq(struct uart_port *port)
EXPORT_SYMBOL_GPL(fsl8250_handle_irq);
#ifdef CONFIG_ACPI
struct fsl8250_data {
int line;
};
static int fsl8250_acpi_probe(struct platform_device *pdev)
{
struct fsl8250_data *data;

View File

@ -100,11 +100,7 @@ static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
writel(reg, p->membase + BYT_PRV_CLK);
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
serial8250_do_set_termios(p, termios, old);
dw8250_do_set_termios(p, termios, old);
}
static unsigned int byt_get_mctrl(struct uart_port *port)
@ -168,6 +164,9 @@ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
* matching with the registered General Purpose DMA controllers.
*/
up->dma = dma;
port->set_termios = dw8250_do_set_termios;
return 0;
}

View File

@ -75,13 +75,12 @@ static int pci_default_setup(struct serial_private*,
static void moan_device(const char *str, struct pci_dev *dev)
{
dev_err(&dev->dev,
"%s: %s\n"
pci_err(dev, "%s\n"
"Please send the output of lspci -vv, this\n"
"message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
"manufacturer and name of serial board or\n"
"modem board to <linux-serial@vger.kernel.org>.\n",
pci_name(dev), str, dev->vendor, dev->device,
str, dev->vendor, dev->device,
dev->subsystem_vendor, dev->subsystem_device);
}
@ -238,7 +237,7 @@ static int pci_inteli960ni_init(struct pci_dev *dev)
/* is firmware started? */
pci_read_config_dword(dev, 0x44, &oldval);
if (oldval == 0x00001000L) { /* RESET value */
dev_dbg(&dev->dev, "Local i960 firmware missing\n");
pci_dbg(dev, "Local i960 firmware missing\n");
return -ENODEV;
}
return 0;
@ -515,7 +514,7 @@ static int pci_siig_init(struct pci_dev *dev)
if (type == 0x1000)
return pci_siig10x_init(dev);
else if (type == 0x2000)
if (type == 0x2000)
return pci_siig20x_init(dev);
moan_device("Unknown SIIG card", dev);
@ -588,9 +587,8 @@ static int pci_timedia_probe(struct pci_dev *dev)
* (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
*/
if ((dev->subsystem_device & 0x00f0) >= 0x70) {
dev_info(&dev->dev,
"ignoring Timedia subdevice %04x for parport_serial\n",
dev->subsystem_device);
pci_info(dev, "ignoring Timedia subdevice %04x for parport_serial\n",
dev->subsystem_device);
return -ENODEV;
}
@ -792,9 +790,9 @@ static int pci_netmos_9900_setup(struct serial_private *priv,
bar = 3 * idx;
return setup_port(priv, port, bar, 0, board->reg_shift);
} else {
return pci_default_setup(priv, board, port, idx);
}
return pci_default_setup(priv, board, port, idx);
}
/* the 99xx series comes with a range of device IDs and a variety
@ -827,8 +825,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev)
if (sub_serports > 0)
return sub_serports;
dev_err(&dev->dev,
"NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
pci_err(dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
return 0;
}
@ -897,18 +894,16 @@ static int pci_netmos_init(struct pci_dev *dev)
/* enable IO_Space bit */
#define ITE_887x_POSIO_ENABLE (1 << 31)
/* inta_addr are the configuration addresses of the ITE */
static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, 0x200, 0x280 };
static int pci_ite887x_init(struct pci_dev *dev)
{
/* inta_addr are the configuration addresses of the ITE */
static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
0x200, 0x280, 0 };
int ret, i, type;
struct resource *iobase = NULL;
u32 miscr, uartbar, ioport;
/* search for the base-ioport */
i = 0;
while (inta_addr[i] && iobase == NULL) {
for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
"ite887x");
if (iobase != NULL) {
@ -925,13 +920,11 @@ static int pci_ite887x_init(struct pci_dev *dev)
break;
}
release_region(iobase->start, ITE_887x_IOSIZE);
iobase = NULL;
}
i++;
}
if (!inta_addr[i]) {
dev_err(&dev->dev, "ite887x: could not find iobase\n");
if (i == ARRAY_SIZE(inta_addr)) {
pci_err(dev, "could not find iobase\n");
return -ENODEV;
}
@ -1026,9 +1019,7 @@ static int pci_endrun_init(struct pci_dev *dev)
/* EndRun device */
if (deviceID == 0x07000200) {
number_uarts = ioread8(p + 4);
dev_dbg(&dev->dev,
"%d ports detected on EndRun PCI Express device\n",
number_uarts);
pci_dbg(dev, "%d ports detected on EndRun PCI Express device\n", number_uarts);
}
pci_iounmap(dev, p);
return number_uarts;
@ -1058,9 +1049,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
/* Tornado device */
if (deviceID == 0x07000200) {
number_uarts = ioread8(p + 4);
dev_dbg(&dev->dev,
"%d ports detected on Oxford PCI Express device\n",
number_uarts);
pci_dbg(dev, "%d ports detected on Oxford PCI Express device\n", number_uarts);
}
pci_iounmap(dev, p);
return number_uarts;
@ -1074,13 +1063,6 @@ static int pci_asix_setup(struct serial_private *priv,
return pci_default_setup(priv, board, port, idx);
}
/* Quatech devices have their own extra interface features */
struct quatech_feature {
u16 devid;
bool amcc;
};
#define QPCR_TEST_FOR1 0x3F
#define QPCR_TEST_GET1 0x00
#define QPCR_TEST_FOR2 0x40
@ -1096,42 +1078,30 @@ struct quatech_feature {
#define QOPR_CLOCK_X8 0x0003
#define QOPR_CLOCK_RATE_MASK 0x0003
static struct quatech_feature quatech_cards[] = {
{ PCI_DEVICE_ID_QUATECH_QSC100, 1 },
{ PCI_DEVICE_ID_QUATECH_DSC100, 1 },
{ PCI_DEVICE_ID_QUATECH_DSC100E, 0 },
{ PCI_DEVICE_ID_QUATECH_DSC200, 1 },
{ PCI_DEVICE_ID_QUATECH_DSC200E, 0 },
{ PCI_DEVICE_ID_QUATECH_ESC100D, 1 },
{ PCI_DEVICE_ID_QUATECH_ESC100M, 1 },
{ PCI_DEVICE_ID_QUATECH_QSCP100, 1 },
{ PCI_DEVICE_ID_QUATECH_DSCP100, 1 },
{ PCI_DEVICE_ID_QUATECH_QSCP200, 1 },
{ PCI_DEVICE_ID_QUATECH_DSCP200, 1 },
{ PCI_DEVICE_ID_QUATECH_ESCLP100, 0 },
{ PCI_DEVICE_ID_QUATECH_QSCLP100, 0 },
{ PCI_DEVICE_ID_QUATECH_DSCLP100, 0 },
{ PCI_DEVICE_ID_QUATECH_SSCLP100, 0 },
{ PCI_DEVICE_ID_QUATECH_QSCLP200, 0 },
{ PCI_DEVICE_ID_QUATECH_DSCLP200, 0 },
{ PCI_DEVICE_ID_QUATECH_SSCLP200, 0 },
{ PCI_DEVICE_ID_QUATECH_SPPXP_100, 0 },
/* Quatech devices have their own extra interface features */
static struct pci_device_id quatech_cards[] = {
{ PCI_DEVICE_DATA(QUATECH, QSC100, 1) },
{ PCI_DEVICE_DATA(QUATECH, DSC100, 1) },
{ PCI_DEVICE_DATA(QUATECH, DSC100E, 0) },
{ PCI_DEVICE_DATA(QUATECH, DSC200, 1) },
{ PCI_DEVICE_DATA(QUATECH, DSC200E, 0) },
{ PCI_DEVICE_DATA(QUATECH, ESC100D, 1) },
{ PCI_DEVICE_DATA(QUATECH, ESC100M, 1) },
{ PCI_DEVICE_DATA(QUATECH, QSCP100, 1) },
{ PCI_DEVICE_DATA(QUATECH, DSCP100, 1) },
{ PCI_DEVICE_DATA(QUATECH, QSCP200, 1) },
{ PCI_DEVICE_DATA(QUATECH, DSCP200, 1) },
{ PCI_DEVICE_DATA(QUATECH, ESCLP100, 0) },
{ PCI_DEVICE_DATA(QUATECH, QSCLP100, 0) },
{ PCI_DEVICE_DATA(QUATECH, DSCLP100, 0) },
{ PCI_DEVICE_DATA(QUATECH, SSCLP100, 0) },
{ PCI_DEVICE_DATA(QUATECH, QSCLP200, 0) },
{ PCI_DEVICE_DATA(QUATECH, DSCLP200, 0) },
{ PCI_DEVICE_DATA(QUATECH, SSCLP200, 0) },
{ PCI_DEVICE_DATA(QUATECH, SPPXP_100, 0) },
{ 0, }
};
static int pci_quatech_amcc(u16 devid)
{
struct quatech_feature *qf = &quatech_cards[0];
while (qf->devid) {
if (qf->devid == devid)
return qf->amcc;
qf++;
}
pr_err("quatech: unknown port type '0x%04X'.\n", devid);
return 0;
};
static int pci_quatech_rqopr(struct uart_8250_port *port)
{
unsigned long base = port->port.iobase;
@ -1291,7 +1261,16 @@ static int pci_quatech_rs422(struct uart_8250_port *port)
static int pci_quatech_init(struct pci_dev *dev)
{
if (pci_quatech_amcc(dev->device)) {
const struct pci_device_id *match;
bool amcc = false;
match = pci_match_id(quatech_cards, dev);
if (match)
amcc = match->driver_data;
else
pci_err(dev, "unknown port type '0x%04X'.\n", dev->device);
if (amcc) {
unsigned long base = pci_resource_start(dev, 0);
if (base) {
u32 tmp;
@ -1315,14 +1294,10 @@ static int pci_quatech_setup(struct serial_private *priv,
port->port.uartclk = pci_quatech_clock(port);
/* For now just warn about RS422 */
if (pci_quatech_rs422(port))
pr_warn("quatech: software control of RS422 features not currently supported.\n");
pci_warn(priv->dev, "software control of RS422 features not currently supported.\n");
return pci_default_setup(priv, board, port, idx);
}
static void pci_quatech_exit(struct pci_dev *dev)
{
}
static int pci_default_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
@ -1525,7 +1500,7 @@ static int pci_fintek_setup(struct serial_private *priv,
/* Get the io address from configuration space */
pci_read_config_word(pdev, config_base + 4, &iobase);
dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%x", __func__, idx, iobase);
pci_dbg(pdev, "idx=%d iobase=0x%x", idx, iobase);
port->port.iotype = UPIO_PORT;
port->port.iobase = iobase;
@ -1689,7 +1664,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
struct uart_8250_port *port, int idx)
{
port->port.quirks |= UPQ_NO_TXEN_TEST;
dev_dbg(&priv->dev->dev,
pci_dbg(priv->dev,
"serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n",
priv->dev->vendor, priv->dev->device,
priv->dev->subsystem_vendor, priv->dev->subsystem_device);
@ -2197,7 +2172,6 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.subdevice = PCI_ANY_ID,
.init = pci_quatech_init,
.setup = pci_quatech_setup,
.exit = pci_quatech_exit,
},
/*
* Panacom
@ -3981,9 +3955,7 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
nr_ports = rc;
}
priv = kzalloc(sizeof(struct serial_private) +
sizeof(unsigned int) * nr_ports,
GFP_KERNEL);
priv = kzalloc(struct_size(priv, line, nr_ports), GFP_KERNEL);
if (!priv) {
priv = ERR_PTR(-ENOMEM);
goto err_deinit;
@ -4000,12 +3972,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
uart.port.irq = 0;
} else {
if (pci_match_id(pci_use_msi, dev)) {
dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n");
pci_dbg(dev, "Using MSI(-X) interrupts\n");
pci_set_master(dev);
uart.port.flags &= ~UPF_SHARE_IRQ;
rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES);
} else {
dev_dbg(&dev->dev, "Using legacy interrupts\n");
pci_dbg(dev, "Using legacy interrupts\n");
rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY);
}
if (rc < 0) {
@ -4023,12 +3995,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
if (quirk->setup(priv, board, &uart, i))
break;
dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
pci_dbg(dev, "Setup PCI port: port %lx, irq %d, type %d\n",
uart.port.iobase, uart.port.irq, uart.port.iotype);
priv->line[i] = serial8250_register_8250_port(&uart);
if (priv->line[i] < 0) {
dev_err(&dev->dev,
pci_err(dev,
"Couldn't register serial port %lx, irq %d, type %d, error %d\n",
uart.port.iobase, uart.port.irq,
uart.port.iotype, priv->line[i]);
@ -4124,8 +4096,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
}
if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
dev_err(&dev->dev, "invalid driver_data: %ld\n",
ent->driver_data);
pci_err(dev, "invalid driver_data: %ld\n", ent->driver_data);
return -EINVAL;
}
@ -4208,7 +4179,7 @@ static int pciserial_resume_one(struct device *dev)
err = pci_enable_device(pdev);
/* FIXME: We cannot simply error out here */
if (err)
dev_err(dev, "Unable to re-enable ports, trying to continue.\n");
pci_err(pdev, "Unable to re-enable ports, trying to continue.\n");
pciserial_resume_ports(priv);
}
return 0;

View File

@ -56,10 +56,6 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "BRI1400", 0 },
/* Boca 33.6 Kbps Internal FD34FSVD */
{ "BRI3400", 0 },
/* Boca 33.6 Kbps Internal FD34FSVD */
{ "BRI0A49", 0 },
/* Best Data Products Inc. Smart One 336F PnP Modem */
{ "BDP3336", 0 },
/* Computer Peripherals Inc */
/* EuroViVa CommCenter-33.6 SP PnP */
{ "CPI4050", 0 },

View File

@ -1338,7 +1338,7 @@ static void autoconfig(struct uart_8250_port *up)
up->tx_loadsz = uart_config[port->type].tx_loadsz;
if (port->type == PORT_UNKNOWN)
goto out_lock;
goto out_unlock;
/*
* Reset the UART.
@ -1355,7 +1355,7 @@ static void autoconfig(struct uart_8250_port *up)
else
serial_out(up, UART_IER, 0);
out_lock:
out_unlock:
spin_unlock_irqrestore(&port->lock, flags);
/*
@ -2696,21 +2696,32 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
{
struct uart_8250_port *up = up_to_u8250p(port);
struct tty_port *tport = &port->state->port;
unsigned int baud, quot, frac = 0;
struct ktermios *termios;
struct tty_struct *tty;
unsigned long flags;
mutex_lock(&port->state->port.mutex);
tty = tty_port_tty_get(tport);
if (!tty) {
mutex_lock(&tport->mutex);
port->uartclk = uartclk;
mutex_unlock(&tport->mutex);
return;
}
down_write(&tty->termios_rwsem);
mutex_lock(&tport->mutex);
if (port->uartclk == uartclk)
goto out_lock;
goto out_unlock;
port->uartclk = uartclk;
if (!tty_port_initialized(&port->state->port))
goto out_lock;
if (!tty_port_initialized(tport))
goto out_unlock;
termios = &port->state->port.tty->termios;
termios = &tty->termios;
baud = serial8250_get_baud_rate(port, termios, NULL);
quot = serial8250_get_divisor(port, baud, &frac);
@ -2726,8 +2737,10 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
out_lock:
mutex_unlock(&port->state->port.mutex);
out_unlock:
mutex_unlock(&tport->mutex);
up_write(&tty->termios_rwsem);
tty_kref_put(tty);
}
EXPORT_SYMBOL_GPL(serial8250_update_uartclk);

View File

@ -380,7 +380,7 @@ config SERIAL_8250_DW
config SERIAL_8250_EM
tristate "Support for Emma Mobile integrated serial port"
depends on SERIAL_8250 && HAVE_CLK
depends on ARM || COMPILE_TEST
depends on (ARM && ARCH_RENESAS) || COMPILE_TEST
help
Selecting this option will add support for the integrated serial
port hardware found on the Emma Mobile line of processors.

View File

@ -239,10 +239,11 @@ config SERIAL_SAMSUNG
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,
providing /dev/ttySAC0, 1 and 2 (note, some machines may not
provide all of these ports, depending on how the serial port
pins are configured.
Support for the on-chip UARTs on the Samsung
S3C24xx/S3C64xx/S5Pv210/Exynos and Apple M1 SoCs, providing
/dev/ttySAC0, 1 and 2 (note, some machines may not provide all of
these ports, depending on how the serial port pins are configured.
Choose Y/M here only if you build for such SoC.
config SERIAL_SAMSUNG_UARTS_4
bool

View File

@ -2084,7 +2084,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
switch (state) {
case 0:
case UART_PM_STATE_ON:
/*
* Enable the peripheral clock for this serial port.
* This is called on uart_open() or a resume event.
@ -2094,7 +2094,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
/* re-enable interrupts if we disabled some on suspend */
atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
break;
case 3:
case UART_PM_STATE_OFF:
/* Back up the interrupt mask and disable all interrupts */
atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
atmel_uart_writel(port, ATMEL_US_IDR, -1);

View File

@ -1090,6 +1090,7 @@ static void cpm_put_poll_char(struct uart_port *port,
cpm_uart_early_write(pinfo, ch, 1, false);
}
#ifdef CONFIG_SERIAL_CPM_CONSOLE
static struct uart_port *udbg_port;
static void udbg_cpm_putc(char c)
@ -1114,6 +1115,7 @@ static int udbg_cpm_getc(void)
cpu_relax();
return c;
}
#endif /* CONFIG_SERIAL_CPM_CONSOLE */
#endif /* CONFIG_CONSOLE_POLL */

View File

@ -2017,7 +2017,7 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
* If the port was already initialised (eg, by a boot loader),
* try to determine the current setup.
*/
static void __init
static void
imx_uart_console_get_options(struct imx_port *sport, int *baud,
int *parity, int *bits)
{
@ -2076,7 +2076,7 @@ imx_uart_console_get_options(struct imx_port *sport, int *baud,
}
}
static int __init
static int
imx_uart_console_setup(struct console *co, char *options)
{
struct imx_port *sport;
@ -2124,12 +2124,24 @@ error_console:
return retval;
}
static int
imx_uart_console_exit(struct console *co)
{
struct imx_port *sport = imx_uart_ports[co->index];
clk_disable_unprepare(sport->clk_per);
clk_disable_unprepare(sport->clk_ipg);
return 0;
}
static struct uart_driver imx_uart_uart_driver;
static struct console imx_uart_console = {
.name = DEV_NAME,
.write = imx_uart_console_write,
.device = uart_console_device,
.setup = imx_uart_console_setup,
.exit = imx_uart_console_exit,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &imx_uart_uart_driver,

View File

@ -1426,7 +1426,7 @@ out_clk:
return ret;
}
static int max310x_remove(struct device *dev)
static void max310x_remove(struct device *dev)
{
struct max310x_port *s = dev_get_drvdata(dev);
int i;
@ -1441,8 +1441,6 @@ static int max310x_remove(struct device *dev)
}
clk_disable_unprepare(s->clk);
return 0;
}
static const struct of_device_id __maybe_unused max310x_dt_ids[] = {
@ -1491,7 +1489,8 @@ static int max310x_spi_probe(struct spi_device *spi)
static int max310x_spi_remove(struct spi_device *spi)
{
return max310x_remove(&spi->dev);
max310x_remove(&spi->dev);
return 0;
}
static const struct spi_device_id max310x_id_table[] = {

View File

@ -65,7 +65,7 @@ enum s3c24xx_port_type {
struct s3c24xx_uart_info {
char *name;
enum s3c24xx_port_type type;
unsigned int has_usi;
bool has_usi;
unsigned int port_type;
unsigned int fifosize;
unsigned long rx_fifomask;
@ -2780,7 +2780,7 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
#endif
#if defined(CONFIG_ARCH_EXYNOS)
#define EXYNOS_COMMON_SERIAL_DRV_DATA_USI(_has_usi) \
#define EXYNOS_COMMON_SERIAL_DRV_DATA(_has_usi) \
.info = &(struct s3c24xx_uart_info) { \
.name = "Samsung Exynos UART", \
.type = TYPE_S3C6400, \
@ -2804,21 +2804,18 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.has_fracval = 1, \
} \
#define EXYNOS_COMMON_SERIAL_DRV_DATA \
EXYNOS_COMMON_SERIAL_DRV_DATA_USI(0)
static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA,
EXYNOS_COMMON_SERIAL_DRV_DATA(false),
.fifosize = { 256, 64, 16, 16 },
};
static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA,
EXYNOS_COMMON_SERIAL_DRV_DATA(false),
.fifosize = { 64, 256, 16, 256 },
};
static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA_USI(1),
EXYNOS_COMMON_SERIAL_DRV_DATA(true),
.fifosize = { 256, 64, 64, 64 },
};

View File

@ -1365,7 +1365,7 @@ out_clk:
return ret;
}
static int sc16is7xx_remove(struct device *dev)
static void sc16is7xx_remove(struct device *dev)
{
struct sc16is7xx_port *s = dev_get_drvdata(dev);
int i;
@ -1385,8 +1385,6 @@ static int sc16is7xx_remove(struct device *dev)
kthread_stop(s->kworker_task);
clk_disable_unprepare(s->clk);
return 0;
}
static const struct of_device_id __maybe_unused sc16is7xx_dt_ids[] = {
@ -1444,7 +1442,9 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)
static int sc16is7xx_spi_remove(struct spi_device *spi)
{
return sc16is7xx_remove(&spi->dev);
sc16is7xx_remove(&spi->dev);
return 0;
}
static const struct spi_device_id sc16is7xx_spi_id_table[] = {
@ -1497,7 +1497,9 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
static int sc16is7xx_i2c_remove(struct i2c_client *client)
{
return sc16is7xx_remove(&client->dev);
sc16is7xx_remove(&client->dev);
return 0;
}
static const struct i2c_device_id sc16is7xx_i2c_id_table[] = {

View File

@ -222,7 +222,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
if (retval == 0) {
if (uart_console(uport) && uport->cons->cflag) {
tty->termios.c_cflag = uport->cons->cflag;
tty->termios.c_ispeed = uport->cons->ispeed;
tty->termios.c_ospeed = uport->cons->ospeed;
uport->cons->cflag = 0;
uport->cons->ispeed = 0;
uport->cons->ospeed = 0;
}
/*
* Initialise the hardware port settings.
@ -290,8 +294,11 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
/*
* Turn off DTR and RTS early.
*/
if (uport && uart_console(uport) && tty)
if (uport && uart_console(uport) && tty) {
uport->cons->cflag = tty->termios.c_cflag;
uport->cons->ispeed = tty->termios.c_ispeed;
uport->cons->ospeed = tty->termios.c_ospeed;
}
if (!tty || C_HUPCL(tty))
uart_port_dtr_rts(uport, 0);
@ -2094,8 +2101,11 @@ uart_set_options(struct uart_port *port, struct console *co,
* Allow the setting of the UART parameters with a NULL console
* too:
*/
if (co)
if (co) {
co->cflag = termios.c_cflag;
co->ispeed = termios.c_ispeed;
co->ospeed = termios.c_ospeed;
}
return 0;
}
@ -2229,6 +2239,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
*/
memset(&termios, 0, sizeof(struct ktermios));
termios.c_cflag = uport->cons->cflag;
termios.c_ispeed = uport->cons->ispeed;
termios.c_ospeed = uport->cons->ospeed;
/*
* If that's unset, use the tty termios setting.

View File

@ -887,7 +887,7 @@ static void __ssp_add_console_port(struct sifive_serial_port *ssp)
static void __ssp_remove_console_port(struct sifive_serial_port *ssp)
{
sifive_serial_console_ports[ssp->port.line] = 0;
sifive_serial_console_ports[ssp->port.line] = NULL;
}
#define SIFIVE_SERIAL_CONSOLE (&sifive_serial_console)

View File

@ -165,63 +165,61 @@ static int stm32_usart_init_rs485(struct uart_port *port,
return uart_get_rs485_mode(port);
}
static int stm32_usart_pending_rx(struct uart_port *port, u32 *sr,
int *last_res, bool threaded)
static bool stm32_usart_rx_dma_enabled(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
enum dma_status status;
struct dma_tx_state state;
*sr = readl_relaxed(port->membase + ofs->isr);
if (!stm32_port->rx_ch)
return false;
if (threaded && stm32_port->rx_ch) {
status = dmaengine_tx_status(stm32_port->rx_ch,
stm32_port->rx_ch->cookie,
&state);
if (status == DMA_IN_PROGRESS && (*last_res != state.residue))
return 1;
else
return 0;
} else if (*sr & USART_SR_RXNE) {
return 1;
}
return 0;
return !!(readl_relaxed(port->membase + ofs->cr3) & USART_CR3_DMAR);
}
static unsigned long stm32_usart_get_char(struct uart_port *port, u32 *sr,
int *last_res)
/* Return true when data is pending (in pio mode), and false when no data is pending. */
static bool stm32_usart_pending_rx_pio(struct uart_port *port, u32 *sr)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
*sr = readl_relaxed(port->membase + ofs->isr);
/* Get pending characters in RDR or FIFO */
if (*sr & USART_SR_RXNE) {
/* Get all pending characters from the RDR or the FIFO when using interrupts */
if (!stm32_usart_rx_dma_enabled(port))
return true;
/* Handle only RX data errors when using DMA */
if (*sr & USART_SR_ERR_MASK)
return true;
}
return false;
}
static unsigned long stm32_usart_get_char_pio(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
unsigned long c;
if (stm32_port->rx_ch) {
c = stm32_port->rx_buf[RX_BUF_L - (*last_res)--];
if ((*last_res) == 0)
*last_res = RX_BUF_L;
} else {
c = readl_relaxed(port->membase + ofs->rdr);
/* apply RDR data mask */
c &= stm32_port->rdr_mask;
}
c = readl_relaxed(port->membase + ofs->rdr);
/* Apply RDR data mask */
c &= stm32_port->rdr_mask;
return c;
}
static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
static unsigned int stm32_usart_receive_chars_pio(struct uart_port *port)
{
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;
unsigned long c;
unsigned int size = 0;
u32 sr;
char flag;
spin_lock(&port->lock);
while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res,
threaded)) {
while (stm32_usart_pending_rx_pio(port, &sr)) {
sr |= USART_SR_DUMMY_RX;
flag = TTY_NORMAL;
@ -240,8 +238,9 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
writel_relaxed(sr & USART_SR_ERR_MASK,
port->membase + ofs->icr);
c = stm32_usart_get_char(port, &sr, &stm32_port->last_res);
c = stm32_usart_get_char_pio(port);
port->icount.rx++;
size++;
if (sr & USART_SR_ERR_MASK) {
if (sr & USART_SR_ORE) {
port->icount.overrun++;
@ -275,9 +274,95 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
uart_insert_char(port, sr, USART_SR_ORE, c, flag);
}
uart_unlock_and_check_sysrq(port);
return size;
}
tty_flip_buffer_push(tport);
static void stm32_usart_push_buffer_dma(struct uart_port *port, unsigned int dma_size)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct tty_port *ttyport = &stm32_port->port.state->port;
unsigned char *dma_start;
int dma_count, i;
dma_start = stm32_port->rx_buf + (RX_BUF_L - stm32_port->last_res);
/*
* Apply rdr_mask on buffer in order to mask parity bit.
* This loop is useless in cs8 mode because DMA copies only
* 8 bits and already ignores parity bit.
*/
if (!(stm32_port->rdr_mask == (BIT(8) - 1)))
for (i = 0; i < dma_size; i++)
*(dma_start + i) &= stm32_port->rdr_mask;
dma_count = tty_insert_flip_string(ttyport, dma_start, dma_size);
port->icount.rx += dma_count;
if (dma_count != dma_size)
port->icount.buf_overrun++;
stm32_port->last_res -= dma_count;
if (stm32_port->last_res == 0)
stm32_port->last_res = RX_BUF_L;
}
static unsigned int stm32_usart_receive_chars_dma(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
unsigned int dma_size, size = 0;
/* DMA buffer is configured in cyclic mode and handles the rollback of the buffer. */
if (stm32_port->rx_dma_state.residue > stm32_port->last_res) {
/* Conditional first part: from last_res to end of DMA buffer */
dma_size = stm32_port->last_res;
stm32_usart_push_buffer_dma(port, dma_size);
size = dma_size;
}
dma_size = stm32_port->last_res - stm32_port->rx_dma_state.residue;
stm32_usart_push_buffer_dma(port, dma_size);
size += dma_size;
return size;
}
static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force_dma_flush)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
enum dma_status rx_dma_status;
u32 sr;
unsigned int size = 0;
if (stm32_usart_rx_dma_enabled(port) || force_dma_flush) {
rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch,
stm32_port->rx_ch->cookie,
&stm32_port->rx_dma_state);
if (rx_dma_status == DMA_IN_PROGRESS) {
/* Empty DMA buffer */
size = stm32_usart_receive_chars_dma(port);
sr = readl_relaxed(port->membase + ofs->isr);
if (sr & USART_SR_ERR_MASK) {
/* Disable DMA request line */
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
/* Switch to PIO mode to handle the errors */
size += stm32_usart_receive_chars_pio(port);
/* Switch back to DMA mode */
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR);
}
} else {
/* Disable RX DMA */
dmaengine_terminate_async(stm32_port->rx_ch);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
/* Fall back to interrupt mode */
dev_dbg(port->dev, "DMA error, fallback to irq mode\n");
size = stm32_usart_receive_chars_pio(port);
}
} else {
size = stm32_usart_receive_chars_pio(port);
}
return size;
}
static void stm32_usart_tx_dma_complete(void *arg)
@ -312,6 +397,20 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
}
static void stm32_usart_rx_dma_complete(void *arg)
{
struct uart_port *port = arg;
struct tty_port *tport = &port->state->port;
unsigned int size;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
size = stm32_usart_receive_chars(port, false);
uart_unlock_and_check_sysrq_irqrestore(port, flags);
if (size)
tty_flip_buffer_push(tport);
}
static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
@ -462,6 +561,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
u32 sr;
unsigned int size;
sr = readl_relaxed(port->membase + ofs->isr);
@ -478,8 +578,20 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
pm_wakeup_event(tport->tty->dev, 0);
}
if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch))
stm32_usart_receive_chars(port, false);
/*
* rx errors in dma mode has to be handled ASAP to avoid overrun as the DMA request
* line has been masked by HW and rx data are stacking in FIFO.
*/
if (!stm32_port->throttled) {
if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_enabled(port)) ||
((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_enabled(port))) {
spin_lock(&port->lock);
size = stm32_usart_receive_chars(port, false);
uart_unlock_and_check_sysrq(port);
if (size)
tty_flip_buffer_push(tport);
}
}
if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
spin_lock(&port->lock);
@ -487,7 +599,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
spin_unlock(&port->lock);
}
if (stm32_port->rx_ch)
if (stm32_usart_rx_dma_enabled(port))
return IRQ_WAKE_THREAD;
else
return IRQ_HANDLED;
@ -496,10 +608,19 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
static irqreturn_t stm32_usart_threaded_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);
unsigned int size;
unsigned long flags;
if (stm32_port->rx_ch)
stm32_usart_receive_chars(port, true);
/* Receiver timeout irq for DMA RX */
if (!stm32_port->throttled) {
spin_lock_irqsave(&port->lock, flags);
size = stm32_usart_receive_chars(port, false);
uart_unlock_and_check_sysrq_irqrestore(port, flags);
if (size)
tty_flip_buffer_push(tport);
}
return IRQ_HANDLED;
}
@ -612,10 +733,19 @@ static void stm32_usart_throttle(struct uart_port *port)
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
/*
* Disable DMA request line if enabled, so the RX data gets queued into the FIFO.
* Hardware flow control is triggered when RX FIFO is full.
*/
if (stm32_usart_rx_dma_enabled(port))
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
if (stm32_port->cr3_irq)
stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
stm32_port->throttled = true;
spin_unlock_irqrestore(&port->lock, flags);
}
@ -631,6 +761,14 @@ static void stm32_usart_unthrottle(struct uart_port *port)
if (stm32_port->cr3_irq)
stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq);
/*
* Switch back to DMA mode (re-enable DMA request line).
* Hardware flow control is stopped when FIFO is not full any more.
*/
if (stm32_port->rx_ch)
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR);
stm32_port->throttled = false;
spin_unlock_irqrestore(&port->lock, flags);
}
@ -640,6 +778,10 @@ static void stm32_usart_stop_rx(struct uart_port *port)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
/* Disable DMA request line. */
if (stm32_port->rx_ch)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
if (stm32_port->cr3_irq)
stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
@ -650,6 +792,48 @@ static void stm32_usart_break_ctl(struct uart_port *port, int break_state)
{
}
static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct dma_async_tx_descriptor *desc;
int ret;
stm32_port->last_res = RX_BUF_L;
/* Prepare a DMA cyclic transaction */
desc = dmaengine_prep_dma_cyclic(stm32_port->rx_ch,
stm32_port->rx_dma_buf,
RX_BUF_L, RX_BUF_P,
DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT);
if (!desc) {
dev_err(port->dev, "rx dma prep cyclic failed\n");
return -ENODEV;
}
desc->callback = stm32_usart_rx_dma_complete;
desc->callback_param = port;
/* Push current DMA transaction in the pending queue */
ret = dma_submit_error(dmaengine_submit(desc));
if (ret) {
dmaengine_terminate_sync(stm32_port->rx_ch);
return ret;
}
/* Issue pending DMA requests */
dma_async_issue_pending(stm32_port->rx_ch);
/*
* DMA request line not re-enabled at resume when port is throttled.
* It will be re-enabled by unthrottle ops.
*/
if (!stm32_port->throttled)
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR);
return 0;
}
static int stm32_usart_startup(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
@ -676,6 +860,14 @@ static int stm32_usart_startup(struct uart_port *port)
if (ofs->rqr != UNDEF_REG)
writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr);
if (stm32_port->rx_ch) {
ret = stm32_usart_start_rx_dma_cyclic(port);
if (ret) {
free_irq(port->irq, port);
return ret;
}
}
/* RX enabling */
val = stm32_port->cr1_irq | USART_CR1_RE | BIT(cfg->uart_enable_bit);
stm32_usart_set_bits(port, ofs->cr1, val);
@ -708,6 +900,10 @@ static void stm32_usart_shutdown(struct uart_port *port)
if (ret)
dev_err(port->dev, "Transmission is not complete\n");
/* Disable RX DMA. */
if (stm32_port->rx_ch)
dmaengine_terminate_async(stm32_port->rx_ch);
/* flush RX & TX FIFO */
if (ofs->rqr != UNDEF_REG)
writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ,
@ -810,9 +1006,11 @@ static void stm32_usart_set_termios(struct uart_port *port,
stm32_port->cr1_irq = USART_CR1_RTOIE;
writel_relaxed(bits, port->membase + ofs->rtor);
cr2 |= USART_CR2_RTOEN;
/* Not using dma, enable fifo threshold irq */
if (!stm32_port->rx_ch)
stm32_port->cr3_irq = USART_CR3_RXFTIE;
/*
* Enable fifo threshold irq in two cases, either when there is no DMA, or when
* wake up over usart, from low power until the DMA gets re-enabled by resume.
*/
stm32_port->cr3_irq = USART_CR3_RXFTIE;
}
cr1 |= stm32_port->cr1_irq;
@ -875,8 +1073,16 @@ static void stm32_usart_set_termios(struct uart_port *port,
if ((termios->c_cflag & CREAD) == 0)
port->ignore_status_mask |= USART_SR_DUMMY_RX;
if (stm32_port->rx_ch)
if (stm32_port->rx_ch) {
/*
* Setup DMA to collect only valid data and enable error irqs.
* This also enables break reception when using DMA.
*/
cr1 |= USART_CR1_PEIE;
cr3 |= USART_CR3_EIE;
cr3 |= USART_CR3_DMAR;
cr3 |= USART_CR3_DDRE;
}
if (rs485conf->flags & SER_RS485_ENABLED) {
stm32_usart_config_reg_rs485(&cr1, &cr3,
@ -1166,7 +1372,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
struct uart_port *port = &stm32port->port;
struct device *dev = &pdev->dev;
struct dma_slave_config config;
struct dma_async_tx_descriptor *desc = NULL;
int ret;
/*
@ -1194,32 +1399,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
return ret;
}
/* Prepare a DMA cyclic transaction */
desc = dmaengine_prep_dma_cyclic(stm32port->rx_ch,
stm32port->rx_dma_buf,
RX_BUF_L, RX_BUF_P, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT);
if (!desc) {
dev_err(dev, "rx dma prep cyclic failed\n");
stm32_usart_of_dma_rx_remove(stm32port, pdev);
return -ENODEV;
}
/* No callback as dma buffer is drained on usart interrupt */
desc->callback = NULL;
desc->callback_param = NULL;
/* Push current DMA transaction in the pending queue */
ret = dma_submit_error(dmaengine_submit(desc));
if (ret) {
dmaengine_terminate_sync(stm32port->rx_ch);
stm32_usart_of_dma_rx_remove(stm32port, pdev);
return ret;
}
/* Issue pending DMA requests */
dma_async_issue_pending(stm32port->rx_ch);
return 0;
}
@ -1372,6 +1551,7 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
int err;
u32 cr3;
pm_runtime_get_sync(&pdev->dev);
err = uart_remove_one_port(&stm32_usart_driver, port);
@ -1382,7 +1562,12 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_PEIE);
cr3 = readl_relaxed(port->membase + ofs->cr3);
cr3 &= ~USART_CR3_EIE;
cr3 &= ~USART_CR3_DMAR;
cr3 &= ~USART_CR3_DDRE;
writel_relaxed(cr3, port->membase + ofs->cr3);
if (stm32_port->tx_ch) {
dmaengine_terminate_async(stm32_port->tx_ch);
@ -1391,7 +1576,6 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
}
if (stm32_port->rx_ch) {
dmaengine_terminate_async(stm32_port->rx_ch);
stm32_usart_of_dma_rx_remove(stm32_port, pdev);
dma_release_channel(stm32_port->rx_ch);
}
@ -1504,14 +1688,18 @@ static struct uart_driver stm32_usart_driver = {
.cons = STM32_SERIAL_CONSOLE,
};
static void __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
bool enable)
static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
bool enable)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct tty_port *tport = &port->state->port;
int ret;
unsigned int size;
unsigned long flags;
if (!stm32_port->wakeup_src)
return;
if (!stm32_port->wakeup_src || !tty_port_initialized(tport))
return 0;
/*
* Enable low-power wake-up and wake-up irq if argument is set to
@ -1520,20 +1708,52 @@ static void __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
if (enable) {
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_UESM);
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_WUFIE);
/*
* When DMA is used for reception, it must be disabled before
* entering low-power mode and re-enabled when exiting from
* low-power mode.
*/
if (stm32_port->rx_ch) {
spin_lock_irqsave(&port->lock, flags);
/* Avoid race with RX IRQ when DMAR is cleared */
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
/* Poll data from DMA RX buffer if any */
size = stm32_usart_receive_chars(port, true);
dmaengine_terminate_async(stm32_port->rx_ch);
uart_unlock_and_check_sysrq_irqrestore(port, flags);
if (size)
tty_flip_buffer_push(tport);
}
/* Poll data from RX FIFO if any */
stm32_usart_receive_chars(port, false);
} else {
if (stm32_port->rx_ch) {
ret = stm32_usart_start_rx_dma_cyclic(port);
if (ret)
return ret;
}
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_UESM);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
}
return 0;
}
static int __maybe_unused stm32_usart_serial_suspend(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
int ret;
uart_suspend_port(&stm32_usart_driver, port);
if (device_may_wakeup(dev) || device_wakeup_path(dev))
stm32_usart_serial_en_wakeup(port, true);
if (device_may_wakeup(dev) || device_wakeup_path(dev)) {
ret = stm32_usart_serial_en_wakeup(port, true);
if (ret)
return ret;
}
/*
* When "no_console_suspend" is enabled, keep the pinctrl default state
@ -1554,11 +1774,15 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev)
static int __maybe_unused stm32_usart_serial_resume(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
int ret;
pinctrl_pm_select_default_state(dev);
if (device_may_wakeup(dev) || device_wakeup_path(dev))
stm32_usart_serial_en_wakeup(port, false);
if (device_may_wakeup(dev) || device_wakeup_path(dev)) {
ret = stm32_usart_serial_en_wakeup(port, false);
if (ret)
return ret;
}
return uart_resume_port(&stm32_usart_driver, port);
}

View File

@ -109,7 +109,7 @@ struct stm32_usart_info stm32h7_info = {
/* USART_SR (F4) / USART_ISR (F7) */
#define USART_SR_PE BIT(0)
#define USART_SR_FE BIT(1)
#define USART_SR_NF BIT(2)
#define USART_SR_NE BIT(2) /* F7 (NF for F4) */
#define USART_SR_ORE BIT(3)
#define USART_SR_IDLE BIT(4)
#define USART_SR_RXNE BIT(5)
@ -126,7 +126,8 @@ struct stm32_usart_info stm32h7_info = {
#define USART_SR_SBKF BIT(18) /* F7 */
#define USART_SR_WUF BIT(20) /* H7 */
#define USART_SR_TEACK BIT(21) /* F7 */
#define USART_SR_ERR_MASK (USART_SR_ORE | USART_SR_FE | USART_SR_PE)
#define USART_SR_ERR_MASK (USART_SR_ORE | USART_SR_NE | USART_SR_FE |\
USART_SR_PE)
/* Dummy bits */
#define USART_SR_DUMMY_RX BIT(16)
@ -246,9 +247,9 @@ struct stm32_usart_info stm32h7_info = {
#define STM32_SERIAL_NAME "ttySTM"
#define STM32_MAX_PORTS 8
#define RX_BUF_L 200 /* dma rx buffer length */
#define RX_BUF_P RX_BUF_L /* dma rx buffer period */
#define TX_BUF_L 200 /* dma tx buffer length */
#define RX_BUF_L 4096 /* dma rx buffer length */
#define RX_BUF_P (RX_BUF_L / 2) /* dma rx buffer period */
#define TX_BUF_L RX_BUF_L /* dma tx buffer length */
struct stm32_port {
struct uart_port port;
@ -264,6 +265,7 @@ struct stm32_port {
u32 cr3_irq; /* USART_CR3_RXFTIE */
int last_res;
bool tx_dma_busy; /* dma tx busy */
bool throttled; /* port throttled */
bool hw_flow_control;
bool swap; /* swap RX & TX pins */
bool fifoen;
@ -272,6 +274,7 @@ struct stm32_port {
bool wakeup_src;
int rdr_mask; /* receive data register mask */
struct mctrl_gpios *gpios; /* modem control gpios */
struct dma_tx_state rx_dma_state;
};
static struct stm32_port stm32_ports[STM32_MAX_PORTS];

View File

@ -1125,7 +1125,7 @@ static void sunzilog_free_tables(void)
#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
static void sunzilog_putchar(struct uart_port *port, int ch)
static void __maybe_unused sunzilog_putchar(struct uart_port *port, int ch)
{
struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
int loops = ZS_PUT_CHAR_MAX_DELAY;

View File

@ -8,6 +8,7 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/bitfield.h>
#include <linux/console.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
@ -63,9 +64,18 @@
static struct uart_port *console_port;
#endif
/**
* struct uartlite_data: Driver private data
* reg_ops: Functions to read/write registers
* clk: Our parent clock, if present
* baud: The baud rate configured when this device was synthesized
* cflags: The cflags for parity and data bits
*/
struct uartlite_data {
const struct uartlite_reg_ops *reg_ops;
struct clk *clk;
unsigned int baud;
tcflag_t cflags;
};
struct uartlite_reg_ops {
@ -119,6 +129,8 @@ static inline void uart_out32(u32 val, u32 offset, struct uart_port *port)
static struct uart_port ulite_ports[ULITE_NR_UARTS];
static struct uart_driver ulite_uart_driver;
/* ---------------------------------------------------------------------
* Core UART driver operations
*/
@ -306,7 +318,12 @@ static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
unsigned long flags;
unsigned int baud;
struct uartlite_data *pdata = port->private_data;
/* Set termios to what the hardware supports */
termios->c_cflag &= ~(BRKINT | CSTOPB | PARENB | PARODD | CSIZE);
termios->c_cflag |= pdata->cflags & (PARENB | PARODD | CSIZE);
tty_termios_encode_baud_rate(termios, pdata->baud, pdata->baud);
spin_lock_irqsave(&port->lock, flags);
@ -329,8 +346,7 @@ static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
| ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
/* update timeout */
baud = uart_get_baud_rate(port, termios, old, 0, 460800);
uart_update_timeout(port, termios->c_cflag, baud);
uart_update_timeout(port, termios->c_cflag, pdata->baud);
spin_unlock_irqrestore(&port->lock, flags);
}
@ -532,8 +548,6 @@ static int ulite_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
static struct uart_driver ulite_uart_driver;
static struct console ulite_console = {
.name = ULITE_NAME,
.write = ulite_console_write,
@ -765,18 +779,73 @@ static int ulite_probe(struct platform_device *pdev)
struct uartlite_data *pdata;
int irq, ret;
int id = pdev->id;
#ifdef CONFIG_OF
const __be32 *prop;
prop = of_get_property(pdev->dev.of_node, "port-number", NULL);
if (prop)
id = be32_to_cpup(prop);
#endif
pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data),
GFP_KERNEL);
if (!pdata)
return -ENOMEM;
if (IS_ENABLED(CONFIG_OF)) {
const char *prop;
struct device_node *np = pdev->dev.of_node;
u32 val = 0;
prop = "port-number";
ret = of_property_read_u32(np, prop, &id);
if (ret && ret != -EINVAL)
of_err:
return dev_err_probe(&pdev->dev, ret,
"could not read %s\n", prop);
prop = "current-speed";
ret = of_property_read_u32(np, prop, &pdata->baud);
if (ret)
goto of_err;
prop = "xlnx,use-parity";
ret = of_property_read_u32(np, prop, &val);
if (ret && ret != -EINVAL)
goto of_err;
if (val) {
prop = "xlnx,odd-parity";
ret = of_property_read_u32(np, prop, &val);
if (ret)
goto of_err;
if (val)
pdata->cflags |= PARODD;
pdata->cflags |= PARENB;
}
val = 8;
prop = "xlnx,data-bits";
ret = of_property_read_u32(np, prop, &val);
if (ret && ret != -EINVAL)
goto of_err;
switch (val) {
case 5:
pdata->cflags |= CS5;
break;
case 6:
pdata->cflags |= CS6;
break;
case 7:
pdata->cflags |= CS7;
break;
case 8:
pdata->cflags |= CS8;
break;
default:
return dev_err_probe(&pdev->dev, -EINVAL,
"bad data bits %d\n", val);
}
} else {
pdata->baud = 9600;
pdata->cflags = CS8;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;

View File

@ -601,9 +601,10 @@ static void cdns_uart_start_tx(struct uart_port *port)
if (uart_circ_empty(&port->state->xmit))
return;
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR);
cdns_uart_handle_tx(port);
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR);
/* Enable the TX Empty interrupt */
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER);
}

View File

@ -843,6 +843,8 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq,
sysrq->shift = KEY_RESERVED;
else if (value != 2)
sysrq->shift = code;
if (sysrq->active)
sysrq->shift_use = sysrq->shift;
break;
case KEY_SYSRQ:

View File

@ -154,7 +154,7 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
termios->c_ospeed = obaud;
#ifdef IBSHIFT
if ((termios->c_cflag >> IBSHIFT) & CBAUD)
if (((termios->c_cflag >> IBSHIFT) & CBAUD) != B0)
ibinput = 1; /* An input speed was specified */
#endif
#ifdef BOTHER

View File

@ -544,6 +544,9 @@ static void flush_to_ldisc(struct work_struct *work)
if (!count)
break;
head->read += count;
if (need_resched())
cond_resched();
}
mutex_unlock(&buf->lock);

View File

@ -675,7 +675,6 @@ static int tty_change_softcar(struct tty_struct *tty, int arg)
/**
* tty_mode_ioctl - mode related ioctls
* @tty: tty for the ioctl
* @file: file pointer for the tty
* @cmd: command
* @arg: ioctl argument
*
@ -684,16 +683,13 @@ static int tty_change_softcar(struct tty_struct *tty, int arg)
* consistent mode setting.
*/
int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
int tty_mode_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
struct tty_struct *real_tty;
void __user *p = (void __user *)arg;
int ret = 0;
struct ktermios kterm;
BUG_ON(file == NULL);
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
real_tty = tty->link;
@ -858,8 +854,8 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
}
EXPORT_SYMBOL_GPL(tty_perform_flush);
int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
int n_tty_ioctl_helper(struct tty_struct *tty, unsigned int cmd,
unsigned long arg)
{
int retval;
@ -904,7 +900,7 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
return __tty_perform_flush(tty, arg);
default:
/* Try the mode commands */
return tty_mode_ioctl(tty, file, cmd, arg);
return tty_mode_ioctl(tty, cmd, arg);
}
}
EXPORT_SYMBOL(n_tty_ioctl_helper);

View File

@ -149,6 +149,8 @@ struct console {
short flags;
short index;
int cflag;
uint ispeed;
uint ospeed;
void *data;
struct console *next;
};

View File

@ -186,6 +186,8 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
__poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp,
poll_table *wait);
ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept);
#else
static inline int rpmsg_register_device(struct rpmsg_device *rpdev)
@ -296,6 +298,14 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept,
return 0;
}
static inline ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
#endif /* IS_ENABLED(CONFIG_RPMSG) */
/* use a macro to avoid include chaining to get THIS_MODULE */

View File

@ -252,20 +252,20 @@ static inline bool tty_throttled(struct tty_struct *tty)
}
#ifdef CONFIG_TTY
extern void tty_kref_put(struct tty_struct *tty);
extern struct pid *tty_get_pgrp(struct tty_struct *tty);
extern void tty_vhangup_self(void);
extern void disassociate_ctty(int priv);
extern dev_t tty_devnum(struct tty_struct *tty);
extern void proc_clear_tty(struct task_struct *p);
extern struct tty_struct *get_current_tty(void);
void tty_kref_put(struct tty_struct *tty);
struct pid *tty_get_pgrp(struct tty_struct *tty);
void tty_vhangup_self(void);
void disassociate_ctty(int priv);
dev_t tty_devnum(struct tty_struct *tty);
void proc_clear_tty(struct task_struct *p);
struct tty_struct *get_current_tty(void);
/* tty_io.c */
extern int __init tty_init(void);
extern const char *tty_name(const struct tty_struct *tty);
extern struct tty_struct *tty_kopen_exclusive(dev_t device);
extern struct tty_struct *tty_kopen_shared(dev_t device);
extern void tty_kclose(struct tty_struct *tty);
extern int tty_dev_name_to_number(const char *name, dev_t *number);
int __init tty_init(void);
const char *tty_name(const struct tty_struct *tty);
struct tty_struct *tty_kopen_exclusive(dev_t device);
struct tty_struct *tty_kopen_shared(dev_t device);
void tty_kclose(struct tty_struct *tty);
int tty_dev_name_to_number(const char *name, dev_t *number);
#else
static inline void tty_kref_put(struct tty_struct *tty)
{ }
@ -296,7 +296,7 @@ static inline int tty_dev_name_to_number(const char *name, dev_t *number)
extern struct ktermios tty_std_termios;
extern int vcs_init(void);
int vcs_init(void);
extern struct class *tty_class;
@ -316,34 +316,34 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty)
return tty;
}
extern const char *tty_driver_name(const struct tty_struct *tty);
extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
extern void stop_tty(struct tty_struct *tty);
extern void start_tty(struct tty_struct *tty);
extern void tty_write_message(struct tty_struct *tty, char *msg);
extern int tty_send_xchar(struct tty_struct *tty, char ch);
extern int tty_put_char(struct tty_struct *tty, unsigned char c);
extern unsigned int tty_chars_in_buffer(struct tty_struct *tty);
extern unsigned int tty_write_room(struct tty_struct *tty);
extern void tty_driver_flush_buffer(struct tty_struct *tty);
extern void tty_unthrottle(struct tty_struct *tty);
extern int tty_throttle_safe(struct tty_struct *tty);
extern int tty_unthrottle_safe(struct tty_struct *tty);
extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
extern int tty_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount);
extern int is_current_pgrp_orphaned(void);
extern void tty_hangup(struct tty_struct *tty);
extern void tty_vhangup(struct tty_struct *tty);
extern int tty_hung_up_p(struct file *filp);
extern void do_SAK(struct tty_struct *tty);
extern void __do_SAK(struct tty_struct *tty);
extern void no_tty(void);
extern speed_t tty_termios_baud_rate(struct ktermios *termios);
extern void tty_termios_encode_baud_rate(struct ktermios *termios,
speed_t ibaud, speed_t obaud);
extern void tty_encode_baud_rate(struct tty_struct *tty,
speed_t ibaud, speed_t obaud);
const char *tty_driver_name(const struct tty_struct *tty);
void tty_wait_until_sent(struct tty_struct *tty, long timeout);
void stop_tty(struct tty_struct *tty);
void start_tty(struct tty_struct *tty);
void tty_write_message(struct tty_struct *tty, char *msg);
int tty_send_xchar(struct tty_struct *tty, char ch);
int tty_put_char(struct tty_struct *tty, unsigned char c);
unsigned int tty_chars_in_buffer(struct tty_struct *tty);
unsigned int tty_write_room(struct tty_struct *tty);
void tty_driver_flush_buffer(struct tty_struct *tty);
void tty_unthrottle(struct tty_struct *tty);
int tty_throttle_safe(struct tty_struct *tty);
int tty_unthrottle_safe(struct tty_struct *tty);
int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
int tty_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount);
int is_current_pgrp_orphaned(void);
void tty_hangup(struct tty_struct *tty);
void tty_vhangup(struct tty_struct *tty);
int tty_hung_up_p(struct file *filp);
void do_SAK(struct tty_struct *tty);
void __do_SAK(struct tty_struct *tty);
void no_tty(void);
speed_t tty_termios_baud_rate(struct ktermios *termios);
void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud,
speed_t obaud);
void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud,
speed_t obaud);
/**
* tty_get_baud_rate - get tty bit rates
@ -363,37 +363,36 @@ static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
unsigned char tty_get_char_size(unsigned int cflag);
unsigned char tty_get_frame_size(unsigned int cflag);
extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
extern int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b);
extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b);
int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
extern void tty_wakeup(struct tty_struct *tty);
void tty_wakeup(struct tty_struct *tty);
extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
extern void tty_release_struct(struct tty_struct *tty, int idx);
extern void tty_init_termios(struct tty_struct *tty);
extern void tty_save_termios(struct tty_struct *tty);
extern int tty_standard_install(struct tty_driver *driver,
int tty_mode_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
void tty_release_struct(struct tty_struct *tty, int idx);
void tty_init_termios(struct tty_struct *tty);
void tty_save_termios(struct tty_struct *tty);
int tty_standard_install(struct tty_driver *driver,
struct tty_struct *tty);
extern struct mutex tty_mutex;
/* n_tty.c */
extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
#ifdef CONFIG_TTY
extern void __init n_tty_init(void);
void __init n_tty_init(void);
#else
static inline void n_tty_init(void) { }
#endif
/* tty_audit.c */
#ifdef CONFIG_AUDIT
extern void tty_audit_exit(void);
extern void tty_audit_fork(struct signal_struct *sig);
extern int tty_audit_push(void);
void tty_audit_exit(void);
void tty_audit_fork(struct signal_struct *sig);
int tty_audit_push(void);
#else
static inline void tty_audit_exit(void)
{
@ -408,24 +407,23 @@ static inline int tty_audit_push(void)
#endif
/* tty_ioctl.c */
extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
int n_tty_ioctl_helper(struct tty_struct *tty, unsigned int cmd,
unsigned long arg);
/* vt.c */
extern int vt_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
int vt_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
extern long vt_compat_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
long vt_compat_ioctl(struct tty_struct *tty, unsigned int cmd,
unsigned long arg);
/* tty_mutex.c */
/* functions for preparation of BKL removal */
extern void tty_lock(struct tty_struct *tty);
extern int tty_lock_interruptible(struct tty_struct *tty);
extern void tty_unlock(struct tty_struct *tty);
extern void tty_lock_slave(struct tty_struct *tty);
extern void tty_unlock_slave(struct tty_struct *tty);
extern void tty_set_lock_subclass(struct tty_struct *tty);
void tty_lock(struct tty_struct *tty);
int tty_lock_interruptible(struct tty_struct *tty);
void tty_unlock(struct tty_struct *tty);
void tty_lock_slave(struct tty_struct *tty);
void tty_unlock_slave(struct tty_struct *tty);
void tty_set_lock_subclass(struct tty_struct *tty);
#endif

View File

@ -327,11 +327,11 @@ struct tty_driver {
extern struct list_head tty_drivers;
extern struct tty_driver *__tty_alloc_driver(unsigned int lines,
struct module *owner, unsigned long flags);
extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
unsigned long flags);
struct tty_driver *tty_find_polling_driver(char *name, int *line);
extern void tty_driver_kref_put(struct tty_driver *driver);
void tty_driver_kref_put(struct tty_driver *driver);
/* Use TTY_DRIVER_* flags below */
#define tty_alloc_driver(lines, flags) \
@ -360,7 +360,7 @@ static inline void tty_set_operations(struct tty_driver *driver,
* Used for PTY's, in particular.
*
* TTY_DRIVER_REAL_RAW --- if set, indicates that the driver will
* guarantee never not to set any special character handling
* guarantee never to set any special character handling
* flags if ((IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR ||
* !INPCK)). That is, if there is no reason for the driver to
* send notifications of parity and break characters up to the

View File

@ -7,16 +7,16 @@
struct tty_ldisc;
extern int tty_buffer_set_limit(struct tty_port *port, int limit);
extern unsigned int tty_buffer_space_avail(struct tty_port *port);
extern int tty_buffer_request_room(struct tty_port *port, size_t size);
extern int tty_insert_flip_string_flags(struct tty_port *port,
int tty_buffer_set_limit(struct tty_port *port, int limit);
unsigned int tty_buffer_space_avail(struct tty_port *port);
int tty_buffer_request_room(struct tty_port *port, size_t size);
int tty_insert_flip_string_flags(struct tty_port *port,
const unsigned char *chars, const char *flags, size_t size);
extern int tty_insert_flip_string_fixed_flag(struct tty_port *port,
int tty_insert_flip_string_fixed_flag(struct tty_port *port,
const unsigned char *chars, char flag, size_t size);
extern int tty_prepare_flip_string(struct tty_port *port,
unsigned char **chars, size_t size);
extern void tty_flip_buffer_push(struct tty_port *port);
int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
size_t size);
void tty_flip_buffer_push(struct tty_port *port);
void tty_schedule_flip(struct tty_port *port);
int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag);
@ -45,7 +45,7 @@ static inline int tty_insert_flip_string(struct tty_port *port,
int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
const char *f, int count);
extern void tty_buffer_lock_exclusive(struct tty_port *port);
extern void tty_buffer_unlock_exclusive(struct tty_port *port);
void tty_buffer_lock_exclusive(struct tty_port *port);
void tty_buffer_unlock_exclusive(struct tty_port *port);
#endif /* _LINUX_TTY_FLIP_H */

View File

@ -146,7 +146,7 @@ struct ld_semaphore {
#endif
};
extern void __init_ldsem(struct ld_semaphore *sem, const char *name,
void __init_ldsem(struct ld_semaphore *sem, const char *name,
struct lock_class_key *key);
#define init_ldsem(sem) \
@ -157,18 +157,18 @@ do { \
} while (0)
extern int ldsem_down_read(struct ld_semaphore *sem, long timeout);
extern int ldsem_down_read_trylock(struct ld_semaphore *sem);
extern int ldsem_down_write(struct ld_semaphore *sem, long timeout);
extern int ldsem_down_write_trylock(struct ld_semaphore *sem);
extern void ldsem_up_read(struct ld_semaphore *sem);
extern void ldsem_up_write(struct ld_semaphore *sem);
int ldsem_down_read(struct ld_semaphore *sem, long timeout);
int ldsem_down_read_trylock(struct ld_semaphore *sem);
int ldsem_down_write(struct ld_semaphore *sem, long timeout);
int ldsem_down_write_trylock(struct ld_semaphore *sem);
void ldsem_up_read(struct ld_semaphore *sem);
void ldsem_up_write(struct ld_semaphore *sem);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
extern int ldsem_down_read_nested(struct ld_semaphore *sem, int subclass,
long timeout);
extern int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass,
long timeout);
int ldsem_down_read_nested(struct ld_semaphore *sem, int subclass,
long timeout);
int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass,
long timeout);
#else
# define ldsem_down_read_nested(sem, subclass, timeout) \
ldsem_down_read(sem, timeout)
@ -180,7 +180,6 @@ extern int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass,
struct tty_ldisc_ops {
char *name;
int num;
int flags;
/*
* The following routines are called from above.
@ -200,7 +199,7 @@ struct tty_ldisc_ops {
void (*set_termios)(struct tty_struct *tty, struct ktermios *old);
__poll_t (*poll)(struct tty_struct *, struct file *,
struct poll_table_struct *);
int (*hangup)(struct tty_struct *tty);
void (*hangup)(struct tty_struct *tty);
/*
* The following routines are called from below.
@ -220,8 +219,6 @@ struct tty_ldisc {
struct tty_struct *tty;
};
#define LDISC_FLAG_DEFINED 0x00000001
#define MODULE_ALIAS_LDISC(ldisc) \
MODULE_ALIAS("tty-ldisc-" __stringify(ldisc))

View File

@ -337,7 +337,7 @@ static int nci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
return -EBUSY;
break;
default:
err = n_tty_ioctl_helper(tty, file, cmd, arg);
err = n_tty_ioctl_helper(tty, cmd, arg);
break;
}

View File

@ -252,10 +252,9 @@ static void v253_close(struct tty_struct *tty)
}
/* Line discipline .hangup() */
static int v253_hangup(struct tty_struct *tty)
static void v253_hangup(struct tty_struct *tty)
{
v253_close(tty);
return 0;
}
/* Line discipline .receive_buf() */

View File

@ -330,10 +330,9 @@ static void cx81801_close(struct tty_struct *tty)
}
/* Line discipline .hangup() */
static int cx81801_hangup(struct tty_struct *tty)
static void cx81801_hangup(struct tty_struct *tty)
{
cx81801_close(tty);
return 0;
}
/* Line discipline .receive_buf() */