mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
TTY / Serial driver changes for 5.19-rc1
Here is the big set of tty and serial driver updates for 5.19-rc1. Lots of tiny cleanups in here, the major stuff is: - termbit cleanups and unification by Ilpo. A much needed change that goes a long way to making things simpler for all of the different arches - tty documentation cleanups and movements to their own place in the documentation tree - old tty driver cleanups and fixes from Jiri to bring some existing drivers into the modern world - RS485 cleanups and unifications to make it easier for individual drivers to support this mode instead of having to duplicate logic in each driver - Lots of 8250 driver updates and additions - new device id additions - n_gsm continued fixes and cleanups - other minor serial driver updates and cleanups All of these have been in linux-next for weeks with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYpndTg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ykFegCgizjLDyOepr72zMDWWdp0bBTekz8AoMWODfJY vB8/kzu329DImJMFB8ET =rmv0 -----END PGP SIGNATURE----- Merge tag 'tty-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty and serial driver updates from Greg KH: "Here is the big set of tty and serial driver updates for 5.19-rc1. Lots of tiny cleanups in here, the major stuff is: - termbit cleanups and unification by Ilpo. A much needed change that goes a long way to making things simpler for all of the different arches - tty documentation cleanups and movements to their own place in the documentation tree - old tty driver cleanups and fixes from Jiri to bring some existing drivers into the modern world - RS485 cleanups and unifications to make it easier for individual drivers to support this mode instead of having to duplicate logic in each driver - Lots of 8250 driver updates and additions - new device id additions - n_gsm continued fixes and cleanups - other minor serial driver updates and cleanups All of these have been in linux-next for weeks with no reported issues" * tag 'tty-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (166 commits) tty: Rework receive flow control char logic pcmcia: synclink_cs: Don't allow CS5-6 serial: stm32-usart: Correct CSIZE, bits, and parity serial: st-asc: Sanitize CSIZE and correct PARENB for CS7 serial: sifive: Sanitize CSIZE and c_iflag serial: sh-sci: Don't allow CS5-6 serial: txx9: Don't allow CS5-6 serial: rda-uart: Don't allow CS5-6 serial: digicolor-usart: Don't allow CS5-6 serial: uartlite: Fix BRKINT clearing serial: cpm_uart: Fix build error without CONFIG_SERIAL_CPM_CONSOLE serial: core: Do stop_rx in suspend path for console if console_suspend is disabled tty: serial: qcom-geni-serial: Remove uart frequency table. Instead, find suitable frequency with call to clk_round_rate. dt-bindings: serial: renesas,em-uart: Add RZ/V2M clock to access the registers serial: 8250_fintek: Check SER_RS485_RTS_* only with RS485 Revert "serial: 8250_mtk: Make sure to select the right FEATURE_SEL" serial: msm_serial: disable interrupts in __msm_console_write() serial: meson: acquire port->lock in startup() serial: 8250_dw: Use dev_err_probe() serial: 8250_dw: Use devm_add_action_or_reset() ...
This commit is contained in:
commit
932c2989b5
@ -23,7 +23,9 @@ properties:
|
||||
- fsl,imx8qxp-lpuart
|
||||
- fsl,imxrt1050-lpuart
|
||||
- items:
|
||||
- const: fsl,imx8ulp-lpuart
|
||||
- enum:
|
||||
- fsl,imx93-lpuart
|
||||
- fsl,imx8ulp-lpuart
|
||||
- const: fsl,imx7ulp-lpuart
|
||||
- items:
|
||||
- enum:
|
||||
|
@ -0,0 +1,86 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/qcom,serial-geni-qcom.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Geni based QUP UART interface
|
||||
|
||||
maintainers:
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/serial/serial.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,geni-uart
|
||||
- qcom,geni-debug-uart
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: se
|
||||
|
||||
interconnects:
|
||||
maxItems: 2
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: qup-core
|
||||
- const: qup-config
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: UART core irq
|
||||
- description: Wakeup irq (RX GPIO)
|
||||
|
||||
operating-points-v2: true
|
||||
|
||||
pinctrl-0: true
|
||||
pinctrl-1: true
|
||||
|
||||
pinctrl-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: default
|
||||
- const: sleep
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sc7180.h>
|
||||
#include <dt-bindings/interconnect/qcom,sc7180.h>
|
||||
|
||||
serial@a88000 {
|
||||
compatible = "qcom,geni-uart";
|
||||
reg = <0xa88000 0x7000>;
|
||||
interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-names = "se";
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
|
||||
pinctrl-0 = <&qup_uart0_default>;
|
||||
pinctrl-names = "default";
|
||||
interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
|
||||
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>;
|
||||
interconnect-names = "qup-core", "qup-config";
|
||||
};
|
||||
...
|
@ -9,12 +9,16 @@ title: Renesas EMMA Mobile UART Interface
|
||||
maintainers:
|
||||
- Magnus Damm <magnus.damm@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: serial.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: renesas,em-uart
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,r9a09g011-uart # RZ/V2M
|
||||
- const: renesas,em-uart # generic EMMA Mobile compatible UART
|
||||
|
||||
- items:
|
||||
- const: renesas,em-uart # generic EMMA Mobile compatible UART
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -23,10 +27,31 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
items:
|
||||
- description: UART functional clock
|
||||
- description: Internal clock to access the registers
|
||||
|
||||
clock-names:
|
||||
const: sclk
|
||||
minItems: 1
|
||||
items:
|
||||
- const: sclk
|
||||
- const: pclk
|
||||
|
||||
allOf:
|
||||
- $ref: serial.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a09g011-uart
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
clock-names:
|
||||
minItems: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -51,10 +51,16 @@ properties:
|
||||
- renesas,hscif-r8a77980 # R-Car V3H
|
||||
- renesas,hscif-r8a77990 # R-Car E3
|
||||
- renesas,hscif-r8a77995 # R-Car D3
|
||||
- renesas,hscif-r8a779a0 # R-Car V3U
|
||||
- const: renesas,rcar-gen3-hscif # R-Car Gen3 and RZ/G2
|
||||
- const: renesas,hscif # generic HSCIF compatible UART
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,hscif-r8a779a0 # R-Car V3U
|
||||
- renesas,hscif-r8a779g0 # R-Car V4H
|
||||
- const: renesas,rcar-gen4-hscif # R-Car Gen4
|
||||
- const: renesas,hscif # generic HSCIF compatible UART
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@ -113,6 +119,7 @@ if:
|
||||
enum:
|
||||
- renesas,rcar-gen2-hscif
|
||||
- renesas,rcar-gen3-hscif
|
||||
- renesas,rcar-gen4-hscif
|
||||
then:
|
||||
required:
|
||||
- resets
|
||||
|
@ -60,12 +60,12 @@ properties:
|
||||
- renesas,scif-r8a77980 # R-Car V3H
|
||||
- renesas,scif-r8a77990 # R-Car E3
|
||||
- renesas,scif-r8a77995 # R-Car D3
|
||||
- renesas,scif-r8a779a0 # R-Car V3U
|
||||
- const: renesas,rcar-gen3-scif # R-Car Gen3 and RZ/G2
|
||||
- const: renesas,scif # generic SCIF compatible UART
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,scif-r8a779a0 # R-Car V3U
|
||||
- renesas,scif-r8a779f0 # R-Car S4-8
|
||||
- const: renesas,rcar-gen4-scif # R-Car Gen4
|
||||
- const: renesas,scif # generic SCIF compatible UART
|
||||
|
@ -33,6 +33,11 @@ properties:
|
||||
description: drive RTS low when sending (default is high).
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
rs485-rx-active-high:
|
||||
description: Polarity of receiver enable signal (when separate from RTS).
|
||||
True indicates active high (default is low).
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
linux,rs485-enabled-at-boot-time:
|
||||
description: enables the rs485 feature at boot time. It can be disabled
|
||||
later with proper ioctl.
|
||||
|
@ -20,7 +20,10 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
auto-flow-control:
|
||||
description: enable automatic flow control support.
|
||||
|
@ -101,6 +101,7 @@ available subsections can be seen below.
|
||||
surface_aggregator/index
|
||||
switchtec
|
||||
sync_file
|
||||
tty/index
|
||||
vfio-mediated-device
|
||||
vfio
|
||||
vfio-pci-device-specific-driver-acceptance
|
||||
|
@ -311,7 +311,7 @@ hardware.
|
||||
This call must not sleep
|
||||
|
||||
set_ldisc(port,termios)
|
||||
Notifier for discipline change. See Documentation/tty/tty_ldisc.rst.
|
||||
Notifier for discipline change. See ../tty/tty_ldisc.rst.
|
||||
|
||||
Locking: caller holds tty_port->mutex
|
||||
|
||||
|
@ -16,8 +16,6 @@ Serial drivers
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
moxa-smartio
|
||||
n_gsm
|
||||
serial-iso7816
|
||||
serial-rs485
|
||||
|
||||
|
@ -1,159 +0,0 @@
|
||||
==============================
|
||||
GSM 0710 tty multiplexor HOWTO
|
||||
==============================
|
||||
|
||||
This line discipline implements the GSM 07.10 multiplexing protocol
|
||||
detailed in the following 3GPP document:
|
||||
|
||||
https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
|
||||
|
||||
This document give some hints on how to use this driver with GPRS and 3G
|
||||
modems connected to a physical serial port.
|
||||
|
||||
How to use it
|
||||
-------------
|
||||
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)::
|
||||
|
||||
#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 connected to the modem */
|
||||
fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
/* configure the serial port : speed, flow control ... */
|
||||
|
||||
/* send the AT commands to switch the modem to CMUX mode
|
||||
and check that it's successful (should return OK) */
|
||||
write(fd, "AT+CMUX=0\r", 10);
|
||||
|
||||
/* experience showed that some modems need some time before
|
||||
being able to answer to the first MUX packet so a delay
|
||||
may be needed here in some case */
|
||||
sleep(3);
|
||||
|
||||
/* use n_gsm line discipline */
|
||||
ioctl(fd, TIOCSETD, &ldisc);
|
||||
|
||||
/* get n_gsm configuration */
|
||||
ioctl(fd, GSMIOC_GETCONF, &c);
|
||||
/* we are initiator and need encoding 0 (basic) */
|
||||
c.initiator = 1;
|
||||
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();
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
this situation either reset the modem if your hardware allows that or send
|
||||
a disconnect command frame manually before initializing the multiplexing mode
|
||||
for the second time. The byte sequence for the disconnect command frame is::
|
||||
|
||||
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
|
||||
modems can be found in the following documents :
|
||||
|
||||
- http://www.telit.com/module/infopool/download.php?id=616
|
||||
- http://www.u-blox.com/images/downloads/Product_Docs/LEON-G100-G200-MuxImplementation_ApplicationNote_%28GSM%20G1-CS-10002%29.pdf
|
||||
- http://www.sierrawireless.com/Support/Downloads/AirPrime/WMP_Series/~/media/Support_Downloads/AirPrime/Application_notes/CMUX_Feature_Application_Note-Rev004.ashx
|
||||
- http://wm.sim.com/sim/News/photo/2010721161442.pdf
|
||||
|
||||
11-03-08 - Eric Bénard - <eric@eukrea.com>
|
@ -36,18 +36,16 @@ In-detail description of the named TTY structures is in separate documents:
|
||||
tty_struct
|
||||
tty_ldisc
|
||||
tty_buffer
|
||||
n_tty
|
||||
tty_internals
|
||||
|
||||
Writing TTY Driver
|
||||
==================
|
||||
|
||||
Before one starts writing a TTY driver, they must consider
|
||||
:doc:`Serial <../driver-api/serial/driver>` and :doc:`USB Serial
|
||||
<../usb/usb-serial>` layers
|
||||
first. Drivers for serial devices can often use one of these specific layers to
|
||||
implement a serial driver. Only special devices should be handled directly by
|
||||
the TTY Layer. If you are about to write such a driver, read on.
|
||||
:doc:`Serial <../serial/driver>` and :doc:`USB Serial <../../usb/usb-serial>`
|
||||
layers first. Drivers for serial devices can often use one of these specific
|
||||
layers to implement a serial driver. Only special devices should be handled
|
||||
directly by the TTY Layer. If you are about to write such a driver, read on.
|
||||
|
||||
A *typical* sequence a TTY driver performs is as follows:
|
||||
|
||||
@ -61,3 +59,15 @@ A *typical* sequence a TTY driver performs is as follows:
|
||||
Steps regarding driver, i.e. 1., 3., and 5. are described in detail in
|
||||
:doc:`tty_driver`. For the other two (devices handling), look into
|
||||
:doc:`tty_port`.
|
||||
|
||||
Other Documentation
|
||||
===================
|
||||
|
||||
Miscellaneous documentation can be further found in these documents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
moxa-smartio
|
||||
n_gsm
|
||||
n_tty
|
153
Documentation/driver-api/tty/n_gsm.rst
Normal file
153
Documentation/driver-api/tty/n_gsm.rst
Normal file
@ -0,0 +1,153 @@
|
||||
==============================
|
||||
GSM 0710 tty multiplexor HOWTO
|
||||
==============================
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
This line discipline implements the GSM 07.10 multiplexing protocol
|
||||
detailed in the following 3GPP document:
|
||||
|
||||
https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
|
||||
|
||||
This document give some hints on how to use this driver with GPRS and 3G
|
||||
modems connected to a physical serial port.
|
||||
|
||||
How to use it
|
||||
=============
|
||||
|
||||
Config Initiator
|
||||
----------------
|
||||
|
||||
#. 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.
|
||||
|
||||
#. Switch the serial line to using the n_gsm line discipline by using
|
||||
``TIOCSETD`` ioctl.
|
||||
|
||||
#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.
|
||||
|
||||
#. 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)::
|
||||
|
||||
#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 connected to the modem */
|
||||
fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
/* configure the serial port : speed, flow control ... */
|
||||
|
||||
/* send the AT commands to switch the modem to CMUX mode
|
||||
and check that it's successful (should return OK) */
|
||||
write(fd, "AT+CMUX=0\r", 10);
|
||||
|
||||
/* experience showed that some modems need some time before
|
||||
being able to answer to the first MUX packet so a delay
|
||||
may be needed here in some case */
|
||||
sleep(3);
|
||||
|
||||
/* use n_gsm line discipline */
|
||||
ioctl(fd, TIOCSETD, &ldisc);
|
||||
|
||||
/* get n_gsm configuration */
|
||||
ioctl(fd, GSMIOC_GETCONF, &c);
|
||||
/* we are initiator and need encoding 0 (basic) */
|
||||
c.initiator = 1;
|
||||
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();
|
||||
|
||||
#. Use these devices as plain serial ports.
|
||||
|
||||
For example, it's possible:
|
||||
|
||||
- to use *gnokii* to send / receive SMS on ``ttygsm1``
|
||||
- to use *ppp* to establish a datalink on ``ttygsm2``
|
||||
|
||||
#. 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
|
||||
this situation either reset the modem if your hardware allows that or send
|
||||
a disconnect command frame manually before initializing the multiplexing mode
|
||||
for the second time. The byte sequence for the disconnect command frame is::
|
||||
|
||||
0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9
|
||||
|
||||
Config Requester
|
||||
----------------
|
||||
|
||||
#. Receive ``AT+CMUX=`` command through its serial port, initialize mux mode
|
||||
config.
|
||||
|
||||
#. Switch the serial line to using the *n_gsm* line discipline by using
|
||||
``TIOCSETD`` ioctl.
|
||||
|
||||
#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.
|
||||
|
||||
#. 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();
|
||||
|
||||
11-03-08 - Eric Bénard - <eric@eukrea.com>
|
@ -389,6 +389,31 @@ descriptors once the device is released.
|
||||
See Documentation/firmware-guide/acpi/gpio-properties.rst for more information
|
||||
about the _DSD binding related to GPIOs.
|
||||
|
||||
RS-485 support
|
||||
==============
|
||||
|
||||
ACPI _DSD (Device Specific Data) can be used to describe RS-485 capability
|
||||
of UART.
|
||||
|
||||
For example::
|
||||
|
||||
Device (DEV)
|
||||
{
|
||||
...
|
||||
|
||||
// ACPI 5.1 _DSD used for RS-485 capabilities
|
||||
Name (_DSD, Package ()
|
||||
{
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package ()
|
||||
{
|
||||
Package () {"rs485-rts-active-low", Zero},
|
||||
Package () {"rs485-rx-active-high", Zero},
|
||||
Package () {"rs485-rx-during-tx", Zero},
|
||||
}
|
||||
})
|
||||
...
|
||||
|
||||
MFD devices
|
||||
===========
|
||||
|
||||
|
@ -136,7 +136,6 @@ needed).
|
||||
misc-devices/index
|
||||
scheduler/index
|
||||
mhi/index
|
||||
tty/index
|
||||
peci/index
|
||||
|
||||
Architecture-agnostic documentation
|
||||
|
@ -25,6 +25,7 @@ fit into other categories.
|
||||
isl29003
|
||||
lis3lv02d
|
||||
max6875
|
||||
oxsemi-tornado
|
||||
pci-endpoint-test
|
||||
spear-pcie-gadget
|
||||
uacce
|
||||
|
131
Documentation/misc-devices/oxsemi-tornado.rst
Normal file
131
Documentation/misc-devices/oxsemi-tornado.rst
Normal file
@ -0,0 +1,131 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================================================================
|
||||
Notes on Oxford Semiconductor PCIe (Tornado) 950 serial port devices
|
||||
====================================================================
|
||||
|
||||
Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven
|
||||
by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock.
|
||||
|
||||
The baud rate produced by the baud generator is obtained from this input
|
||||
frequency by dividing it by the clock prescaler, which can be set to any
|
||||
value from 1 to 63.875 in increments of 0.125, and then the usual 16-bit
|
||||
divisor is used as with the original 8250, to divide the frequency by a
|
||||
value from 1 to 65535. Finally a programmable oversampling rate is used
|
||||
that can take any value from 4 to 16 to divide the frequency further and
|
||||
determine the actual baud rate used. Baud rates from 15625000bps down
|
||||
to 0.933bps can be obtained this way.
|
||||
|
||||
By default the oversampling rate is set to 16 and the clock prescaler is
|
||||
set to 33.875, meaning that the frequency to be used as the reference
|
||||
for the usual 16-bit divisor is 115313.653, which is close enough to the
|
||||
frequency of 115200 used by the original 8250 for the same values to be
|
||||
used for the divisor to obtain the requested baud rates by software that
|
||||
is unaware of the extra clock controls available.
|
||||
|
||||
The oversampling rate is programmed with the TCR register and the clock
|
||||
prescaler is programmed with the CPR/CPR2 register pair [OX200]_ [OX952]_
|
||||
[OX954]_ [OX958]_. To switch away from the default value of 33.875 for
|
||||
the prescaler the enhanced mode has to be explicitly enabled though, by
|
||||
setting bit 4 of the EFR. In that mode setting bit 7 in the MCR enables
|
||||
the prescaler or otherwise it is bypassed as if the value of 1 was used.
|
||||
Additionally writing any value to CPR clears CPR2 for compatibility with
|
||||
old software written for older conventional PCI Oxford Semiconductor
|
||||
devices that do not have the extra prescaler's 9th bit in CPR2, so the
|
||||
CPR/CPR2 register pair has to be programmed in the right order.
|
||||
|
||||
By using these parameters rates from 15625000bps down to 1bps can be
|
||||
obtained, with either exact or highly-accurate actual bit rates for
|
||||
standard and many non-standard rates.
|
||||
|
||||
Here are the figures for the standard and some non-standard baud rates
|
||||
(including those quoted in Oxford Semiconductor documentation), giving
|
||||
the requested rate (r), the actual rate yielded (a) and its deviation
|
||||
from the requested rate (d), and the values of the oversampling rate
|
||||
(tcr), the clock prescaler (cpr) and the divisor (div) produced by the
|
||||
new ``get_divisor`` handler:
|
||||
|
||||
::
|
||||
|
||||
r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1
|
||||
r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1
|
||||
r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1
|
||||
r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1
|
||||
r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1
|
||||
r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1
|
||||
r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1
|
||||
r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1
|
||||
r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1
|
||||
r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1
|
||||
r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1
|
||||
r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1
|
||||
r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1
|
||||
r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1
|
||||
r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2
|
||||
r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2
|
||||
r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5
|
||||
r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5
|
||||
r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31
|
||||
r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35
|
||||
r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30
|
||||
r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105
|
||||
r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643
|
||||
r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647
|
||||
r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286
|
||||
r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294
|
||||
r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215
|
||||
r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625
|
||||
r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245
|
||||
r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153
|
||||
r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348
|
||||
r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461
|
||||
r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500
|
||||
r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500
|
||||
r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828
|
||||
r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828
|
||||
r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154
|
||||
|
||||
With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX
|
||||
limitation imposed by ``serial8250_get_baud_rate`` standard baud rates
|
||||
below 300bps become unavailable in the regular way, e.g. the rate of
|
||||
200bps requires the baud base to be divided by 78125 and that is beyond
|
||||
the unsigned 16-bit range. The historic spd_cust feature can still be
|
||||
used by encoding the values for, the prescaler, the oversampling rate
|
||||
and the clock divisor (DLM/DLL) as follows to obtain such rates if so
|
||||
required:
|
||||
|
||||
::
|
||||
|
||||
31 29 28 20 19 16 15 0
|
||||
+-----+-----------------+-------+-------------------------------+
|
||||
|0 0 0| CPR2:CPR | TCR | DLM:DLL |
|
||||
+-----+-----------------+-------+-------------------------------+
|
||||
|
||||
Use a value such encoded for the ``custom_divisor`` field along with the
|
||||
ASYNC_SPD_CUST flag set in the ``flags`` field in ``struct serial_struct``
|
||||
passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8)
|
||||
utility and its ``divisor`` and ``spd_cust`` parameters, and then select
|
||||
the baud rate of 38400bps. Note that the value of 0 in TCR sets the
|
||||
oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are
|
||||
clamped by the driver to 1.
|
||||
|
||||
For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL
|
||||
respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value,
|
||||
the oversampling rate and the clock divisor of 62.500, 16 and 1250
|
||||
respectively. These parameters will set the baud rate for the serial
|
||||
port to 62500000 / 62.500 / 1250 / 16 = 50bps.
|
||||
|
||||
Maciej W. Rozycki <macro@orcam.me.uk>
|
||||
|
||||
.. [OX200] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor,
|
||||
Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65
|
||||
|
||||
.. [OX952] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port",
|
||||
Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode",
|
||||
p. 20
|
||||
|
||||
.. [OX954] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford
|
||||
Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20
|
||||
|
||||
.. [OX958] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford
|
||||
Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20
|
@ -13411,7 +13411,7 @@ F: drivers/net/phy/motorcomm.c
|
||||
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
|
||||
M: Jiri Slaby <jirislaby@kernel.org>
|
||||
S: Maintained
|
||||
F: Documentation/driver-api/serial/moxa-smartio.rst
|
||||
F: Documentation/driver-api/tty/moxa-smartio.rst
|
||||
F: drivers/tty/mxser.*
|
||||
|
||||
MR800 AVERMEDIA USB FM RADIO DRIVER
|
||||
|
@ -2,10 +2,8 @@
|
||||
#ifndef _ALPHA_TERMBITS_H
|
||||
#define _ALPHA_TERMBITS_H
|
||||
|
||||
#include <linux/posix_types.h>
|
||||
#include <asm-generic/termbits-common.h>
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
/*
|
||||
@ -53,76 +51,58 @@ struct ktermios {
|
||||
};
|
||||
|
||||
/* c_cc characters */
|
||||
#define VEOF 0
|
||||
#define VEOL 1
|
||||
#define VEOL2 2
|
||||
#define VERASE 3
|
||||
#define VWERASE 4
|
||||
#define VKILL 5
|
||||
#define VREPRINT 6
|
||||
#define VSWTC 7
|
||||
#define VINTR 8
|
||||
#define VQUIT 9
|
||||
#define VSUSP 10
|
||||
#define VSTART 12
|
||||
#define VSTOP 13
|
||||
#define VLNEXT 14
|
||||
#define VDISCARD 15
|
||||
#define VMIN 16
|
||||
#define VTIME 17
|
||||
#define VEOF 0
|
||||
#define VEOL 1
|
||||
#define VEOL2 2
|
||||
#define VERASE 3
|
||||
#define VWERASE 4
|
||||
#define VKILL 5
|
||||
#define VREPRINT 6
|
||||
#define VSWTC 7
|
||||
#define VINTR 8
|
||||
#define VQUIT 9
|
||||
#define VSUSP 10
|
||||
#define VSTART 12
|
||||
#define VSTOP 13
|
||||
#define VLNEXT 14
|
||||
#define VDISCARD 15
|
||||
#define VMIN 16
|
||||
#define VTIME 17
|
||||
|
||||
/* c_iflag bits */
|
||||
#define IGNBRK 0000001
|
||||
#define BRKINT 0000002
|
||||
#define IGNPAR 0000004
|
||||
#define PARMRK 0000010
|
||||
#define INPCK 0000020
|
||||
#define ISTRIP 0000040
|
||||
#define INLCR 0000100
|
||||
#define IGNCR 0000200
|
||||
#define ICRNL 0000400
|
||||
#define IXON 0001000
|
||||
#define IXOFF 0002000
|
||||
#define IXANY 0004000
|
||||
#define IUCLC 0010000
|
||||
#define IMAXBEL 0020000
|
||||
#define IUTF8 0040000
|
||||
#define IXON 0x0200
|
||||
#define IXOFF 0x0400
|
||||
#define IUCLC 0x1000
|
||||
#define IMAXBEL 0x2000
|
||||
#define IUTF8 0x4000
|
||||
|
||||
/* c_oflag bits */
|
||||
#define OPOST 0000001
|
||||
#define ONLCR 0000002
|
||||
#define OLCUC 0000004
|
||||
|
||||
#define OCRNL 0000010
|
||||
#define ONOCR 0000020
|
||||
#define ONLRET 0000040
|
||||
|
||||
#define OFILL 00000100
|
||||
#define OFDEL 00000200
|
||||
#define NLDLY 00001400
|
||||
#define NL0 00000000
|
||||
#define NL1 00000400
|
||||
#define NL2 00001000
|
||||
#define NL3 00001400
|
||||
#define TABDLY 00006000
|
||||
#define TAB0 00000000
|
||||
#define TAB1 00002000
|
||||
#define TAB2 00004000
|
||||
#define TAB3 00006000
|
||||
#define CRDLY 00030000
|
||||
#define CR0 00000000
|
||||
#define CR1 00010000
|
||||
#define CR2 00020000
|
||||
#define CR3 00030000
|
||||
#define FFDLY 00040000
|
||||
#define FF0 00000000
|
||||
#define FF1 00040000
|
||||
#define BSDLY 00100000
|
||||
#define BS0 00000000
|
||||
#define BS1 00100000
|
||||
#define VTDLY 00200000
|
||||
#define VT0 00000000
|
||||
#define VT1 00200000
|
||||
#define ONLCR 0x00002
|
||||
#define OLCUC 0x00004
|
||||
#define NLDLY 0x00300
|
||||
#define NL0 0x00000
|
||||
#define NL1 0x00100
|
||||
#define NL2 0x00200
|
||||
#define NL3 0x00300
|
||||
#define TABDLY 0x00c00
|
||||
#define TAB0 0x00000
|
||||
#define TAB1 0x00400
|
||||
#define TAB2 0x00800
|
||||
#define TAB3 0x00c00
|
||||
#define CRDLY 0x03000
|
||||
#define CR0 0x00000
|
||||
#define CR1 0x01000
|
||||
#define CR2 0x02000
|
||||
#define CR3 0x03000
|
||||
#define FFDLY 0x04000
|
||||
#define FF0 0x00000
|
||||
#define FF1 0x04000
|
||||
#define BSDLY 0x08000
|
||||
#define BS0 0x00000
|
||||
#define BS1 0x08000
|
||||
#define VTDLY 0x10000
|
||||
#define VT0 0x00000
|
||||
#define VT1 0x10000
|
||||
/*
|
||||
* Should be equivalent to TAB3, see description of TAB3 in
|
||||
* POSIX.1-2008, Ch. 11.2.3 "Output Modes"
|
||||
@ -130,61 +110,36 @@ struct ktermios {
|
||||
#define XTABS TAB3
|
||||
|
||||
/* c_cflag bit meaning */
|
||||
#define CBAUD 0000037
|
||||
#define B0 0000000 /* hang up */
|
||||
#define B50 0000001
|
||||
#define B75 0000002
|
||||
#define B110 0000003
|
||||
#define B134 0000004
|
||||
#define B150 0000005
|
||||
#define B200 0000006
|
||||
#define B300 0000007
|
||||
#define B600 0000010
|
||||
#define B1200 0000011
|
||||
#define B1800 0000012
|
||||
#define B2400 0000013
|
||||
#define B4800 0000014
|
||||
#define B9600 0000015
|
||||
#define B19200 0000016
|
||||
#define B38400 0000017
|
||||
#define EXTA B19200
|
||||
#define EXTB B38400
|
||||
#define CBAUDEX 0000000
|
||||
#define B57600 00020
|
||||
#define B115200 00021
|
||||
#define B230400 00022
|
||||
#define B460800 00023
|
||||
#define B500000 00024
|
||||
#define B576000 00025
|
||||
#define B921600 00026
|
||||
#define B1000000 00027
|
||||
#define B1152000 00030
|
||||
#define B1500000 00031
|
||||
#define B2000000 00032
|
||||
#define B2500000 00033
|
||||
#define B3000000 00034
|
||||
#define B3500000 00035
|
||||
#define B4000000 00036
|
||||
#define BOTHER 00037
|
||||
|
||||
#define CSIZE 00001400
|
||||
#define CS5 00000000
|
||||
#define CS6 00000400
|
||||
#define CS7 00001000
|
||||
#define CS8 00001400
|
||||
|
||||
#define CSTOPB 00002000
|
||||
#define CREAD 00004000
|
||||
#define PARENB 00010000
|
||||
#define PARODD 00020000
|
||||
#define HUPCL 00040000
|
||||
|
||||
#define CLOCAL 00100000
|
||||
#define CMSPAR 010000000000 /* mark or space (stick) parity */
|
||||
#define CRTSCTS 020000000000 /* flow control */
|
||||
|
||||
#define CIBAUD 07600000
|
||||
#define IBSHIFT 16
|
||||
#define CBAUD 0x0000001f
|
||||
#define CBAUDEX 0x00000000
|
||||
#define BOTHER 0x0000001f
|
||||
#define B57600 0x00000010
|
||||
#define B115200 0x00000011
|
||||
#define B230400 0x00000012
|
||||
#define B460800 0x00000013
|
||||
#define B500000 0x00000014
|
||||
#define B576000 0x00000015
|
||||
#define B921600 0x00000016
|
||||
#define B1000000 0x00000017
|
||||
#define B1152000 0x00000018
|
||||
#define B1500000 0x00000019
|
||||
#define B2000000 0x0000001a
|
||||
#define B2500000 0x0000001b
|
||||
#define B3000000 0x0000001c
|
||||
#define B3500000 0x0000001d
|
||||
#define B4000000 0x0000001e
|
||||
#define CSIZE 0x00000300
|
||||
#define CS5 0x00000000
|
||||
#define CS6 0x00000100
|
||||
#define CS7 0x00000200
|
||||
#define CS8 0x00000300
|
||||
#define CSTOPB 0x00000400
|
||||
#define CREAD 0x00000800
|
||||
#define PARENB 0x00001000
|
||||
#define PARODD 0x00002000
|
||||
#define HUPCL 0x00004000
|
||||
#define CLOCAL 0x00008000
|
||||
#define CIBAUD 0x001f0000
|
||||
|
||||
/* c_lflag bits */
|
||||
#define ISIG 0x00000080
|
||||
@ -204,17 +159,6 @@ struct ktermios {
|
||||
#define IEXTEN 0x00000400
|
||||
#define EXTPROC 0x10000000
|
||||
|
||||
/* Values for the ACTION argument to `tcflow'. */
|
||||
#define TCOOFF 0
|
||||
#define TCOON 1
|
||||
#define TCIOFF 2
|
||||
#define TCION 3
|
||||
|
||||
/* Values for the QUEUE_SELECTOR argument to `tcflush'. */
|
||||
#define TCIFLUSH 0
|
||||
#define TCOFLUSH 1
|
||||
#define TCIOFLUSH 2
|
||||
|
||||
/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */
|
||||
#define TCSANOW 0
|
||||
#define TCSADRAIN 1
|
||||
|
@ -11,11 +11,9 @@
|
||||
#ifndef _ASM_TERMBITS_H
|
||||
#define _ASM_TERMBITS_H
|
||||
|
||||
#include <linux/posix_types.h>
|
||||
#include <asm-generic/termbits-common.h>
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
/*
|
||||
* The ABI says nothing about NCC but seems to use NCCS as
|
||||
@ -54,175 +52,126 @@ struct ktermios {
|
||||
};
|
||||
|
||||
/* c_cc characters */
|
||||
#define VINTR 0 /* Interrupt character [ISIG]. */
|
||||
#define VQUIT 1 /* Quit character [ISIG]. */
|
||||
#define VERASE 2 /* Erase character [ICANON]. */
|
||||
#define VKILL 3 /* Kill-line character [ICANON]. */
|
||||
#define VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */
|
||||
#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */
|
||||
#define VEOL2 6 /* Second EOL character [ICANON]. */
|
||||
#define VINTR 0 /* Interrupt character [ISIG] */
|
||||
#define VQUIT 1 /* Quit character [ISIG] */
|
||||
#define VERASE 2 /* Erase character [ICANON] */
|
||||
#define VKILL 3 /* Kill-line character [ICANON] */
|
||||
#define VMIN 4 /* Minimum number of bytes read at once [!ICANON] */
|
||||
#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON] */
|
||||
#define VEOL2 6 /* Second EOL character [ICANON] */
|
||||
#define VSWTC 7 /* ??? */
|
||||
#define VSWTCH VSWTC
|
||||
#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF]. */
|
||||
#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF]. */
|
||||
#define VSUSP 10 /* Suspend character [ISIG]. */
|
||||
#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF] */
|
||||
#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF] */
|
||||
#define VSUSP 10 /* Suspend character [ISIG] */
|
||||
#if 0
|
||||
/*
|
||||
* VDSUSP is not supported
|
||||
*/
|
||||
#define VDSUSP 11 /* Delayed suspend character [ISIG]. */
|
||||
#define VDSUSP 11 /* Delayed suspend character [ISIG] */
|
||||
#endif
|
||||
#define VREPRINT 12 /* Reprint-line character [ICANON]. */
|
||||
#define VDISCARD 13 /* Discard character [IEXTEN]. */
|
||||
#define VWERASE 14 /* Word-erase character [ICANON]. */
|
||||
#define VLNEXT 15 /* Literal-next character [IEXTEN]. */
|
||||
#define VEOF 16 /* End-of-file character [ICANON]. */
|
||||
#define VEOL 17 /* End-of-line character [ICANON]. */
|
||||
#define VREPRINT 12 /* Reprint-line character [ICANON] */
|
||||
#define VDISCARD 13 /* Discard character [IEXTEN] */
|
||||
#define VWERASE 14 /* Word-erase character [ICANON] */
|
||||
#define VLNEXT 15 /* Literal-next character [IEXTEN] */
|
||||
#define VEOF 16 /* End-of-file character [ICANON] */
|
||||
#define VEOL 17 /* End-of-line character [ICANON] */
|
||||
|
||||
/* c_iflag bits */
|
||||
#define IGNBRK 0000001 /* Ignore break condition. */
|
||||
#define BRKINT 0000002 /* Signal interrupt on break. */
|
||||
#define IGNPAR 0000004 /* Ignore characters with parity errors. */
|
||||
#define PARMRK 0000010 /* Mark parity and framing errors. */
|
||||
#define INPCK 0000020 /* Enable input parity check. */
|
||||
#define ISTRIP 0000040 /* Strip 8th bit off characters. */
|
||||
#define INLCR 0000100 /* Map NL to CR on input. */
|
||||
#define IGNCR 0000200 /* Ignore CR. */
|
||||
#define ICRNL 0000400 /* Map CR to NL on input. */
|
||||
#define IUCLC 0001000 /* Map upper case to lower case on input. */
|
||||
#define IXON 0002000 /* Enable start/stop output control. */
|
||||
#define IXANY 0004000 /* Any character will restart after stop. */
|
||||
#define IXOFF 0010000 /* Enable start/stop input control. */
|
||||
#define IMAXBEL 0020000 /* Ring bell when input queue is full. */
|
||||
#define IUTF8 0040000 /* Input is UTF-8 */
|
||||
#define IUCLC 0x0200 /* Map upper case to lower case on input */
|
||||
#define IXON 0x0400 /* Enable start/stop output control */
|
||||
#define IXOFF 0x1000 /* Enable start/stop input control */
|
||||
#define IMAXBEL 0x2000 /* Ring bell when input queue is full */
|
||||
#define IUTF8 0x4000 /* Input is UTF-8 */
|
||||
|
||||
/* c_oflag bits */
|
||||
#define OPOST 0000001 /* Perform output processing. */
|
||||
#define OLCUC 0000002 /* Map lower case to upper case on output. */
|
||||
#define ONLCR 0000004 /* Map NL to CR-NL on output. */
|
||||
#define OCRNL 0000010
|
||||
#define ONOCR 0000020
|
||||
#define ONLRET 0000040
|
||||
#define OFILL 0000100
|
||||
#define OFDEL 0000200
|
||||
#define NLDLY 0000400
|
||||
#define NL0 0000000
|
||||
#define NL1 0000400
|
||||
#define CRDLY 0003000
|
||||
#define CR0 0000000
|
||||
#define CR1 0001000
|
||||
#define CR2 0002000
|
||||
#define CR3 0003000
|
||||
#define TABDLY 0014000
|
||||
#define TAB0 0000000
|
||||
#define TAB1 0004000
|
||||
#define TAB2 0010000
|
||||
#define TAB3 0014000
|
||||
#define XTABS 0014000
|
||||
#define BSDLY 0020000
|
||||
#define BS0 0000000
|
||||
#define BS1 0020000
|
||||
#define VTDLY 0040000
|
||||
#define VT0 0000000
|
||||
#define VT1 0040000
|
||||
#define FFDLY 0100000
|
||||
#define FF0 0000000
|
||||
#define FF1 0100000
|
||||
#define OLCUC 0x00002 /* Map lower case to upper case on output */
|
||||
#define ONLCR 0x00004 /* Map NL to CR-NL on output */
|
||||
#define NLDLY 0x00100
|
||||
#define NL0 0x00000
|
||||
#define NL1 0x00100
|
||||
#define CRDLY 0x00600
|
||||
#define CR0 0x00000
|
||||
#define CR1 0x00200
|
||||
#define CR2 0x00400
|
||||
#define CR3 0x00600
|
||||
#define TABDLY 0x01800
|
||||
#define TAB0 0x00000
|
||||
#define TAB1 0x00800
|
||||
#define TAB2 0x01000
|
||||
#define TAB3 0x01800
|
||||
#define XTABS 0x01800
|
||||
#define BSDLY 0x02000
|
||||
#define BS0 0x00000
|
||||
#define BS1 0x02000
|
||||
#define VTDLY 0x04000
|
||||
#define VT0 0x00000
|
||||
#define VT1 0x04000
|
||||
#define FFDLY 0x08000
|
||||
#define FF0 0x00000
|
||||
#define FF1 0x08000
|
||||
/*
|
||||
#define PAGEOUT ???
|
||||
#define WRAP ???
|
||||
*/
|
||||
|
||||
/* c_cflag bit meaning */
|
||||
#define CBAUD 0010017
|
||||
#define B0 0000000 /* hang up */
|
||||
#define B50 0000001
|
||||
#define B75 0000002
|
||||
#define B110 0000003
|
||||
#define B134 0000004
|
||||
#define B150 0000005
|
||||
#define B200 0000006
|
||||
#define B300 0000007
|
||||
#define B600 0000010
|
||||
#define B1200 0000011
|
||||
#define B1800 0000012
|
||||
#define B2400 0000013
|
||||
#define B4800 0000014
|
||||
#define B9600 0000015
|
||||
#define B19200 0000016
|
||||
#define B38400 0000017
|
||||
#define EXTA B19200
|
||||
#define EXTB B38400
|
||||
#define CSIZE 0000060 /* Number of bits per byte (mask). */
|
||||
#define CS5 0000000 /* 5 bits per byte. */
|
||||
#define CS6 0000020 /* 6 bits per byte. */
|
||||
#define CS7 0000040 /* 7 bits per byte. */
|
||||
#define CS8 0000060 /* 8 bits per byte. */
|
||||
#define CSTOPB 0000100 /* Two stop bits instead of one. */
|
||||
#define CREAD 0000200 /* Enable receiver. */
|
||||
#define PARENB 0000400 /* Parity enable. */
|
||||
#define PARODD 0001000 /* Odd parity instead of even. */
|
||||
#define HUPCL 0002000 /* Hang up on last close. */
|
||||
#define CLOCAL 0004000 /* Ignore modem status lines. */
|
||||
#define CBAUDEX 0010000
|
||||
#define BOTHER 0010000
|
||||
#define B57600 0010001
|
||||
#define B115200 0010002
|
||||
#define B230400 0010003
|
||||
#define B460800 0010004
|
||||
#define B500000 0010005
|
||||
#define B576000 0010006
|
||||
#define B921600 0010007
|
||||
#define B1000000 0010010
|
||||
#define B1152000 0010011
|
||||
#define B1500000 0010012
|
||||
#define B2000000 0010013
|
||||
#define B2500000 0010014
|
||||
#define B3000000 0010015
|
||||
#define B3500000 0010016
|
||||
#define B4000000 0010017
|
||||
#define CIBAUD 002003600000 /* input baud rate */
|
||||
#define CMSPAR 010000000000 /* mark or space (stick) parity */
|
||||
#define CRTSCTS 020000000000 /* flow control */
|
||||
|
||||
#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
|
||||
#define CBAUD 0x0000100f
|
||||
#define CSIZE 0x00000030 /* Number of bits per byte (mask) */
|
||||
#define CS5 0x00000000 /* 5 bits per byte */
|
||||
#define CS6 0x00000010 /* 6 bits per byte */
|
||||
#define CS7 0x00000020 /* 7 bits per byte */
|
||||
#define CS8 0x00000030 /* 8 bits per byte */
|
||||
#define CSTOPB 0x00000040 /* Two stop bits instead of one */
|
||||
#define CREAD 0x00000080 /* Enable receiver */
|
||||
#define PARENB 0x00000100 /* Parity enable */
|
||||
#define PARODD 0x00000200 /* Odd parity instead of even */
|
||||
#define HUPCL 0x00000400 /* Hang up on last close */
|
||||
#define CLOCAL 0x00000800 /* Ignore modem status lines */
|
||||
#define CBAUDEX 0x00001000
|
||||
#define BOTHER 0x00001000
|
||||
#define B57600 0x00001001
|
||||
#define B115200 0x00001002
|
||||
#define B230400 0x00001003
|
||||
#define B460800 0x00001004
|
||||
#define B500000 0x00001005
|
||||
#define B576000 0x00001006
|
||||
#define B921600 0x00001007
|
||||
#define B1000000 0x00001008
|
||||
#define B1152000 0x00001009
|
||||
#define B1500000 0x0000100a
|
||||
#define B2000000 0x0000100b
|
||||
#define B2500000 0x0000100c
|
||||
#define B3000000 0x0000100d
|
||||
#define B3500000 0x0000100e
|
||||
#define B4000000 0x0000100f
|
||||
#define CIBAUD 0x100f0000 /* input baud rate */
|
||||
|
||||
/* c_lflag bits */
|
||||
#define ISIG 0000001 /* Enable signals. */
|
||||
#define ICANON 0000002 /* Do erase and kill processing. */
|
||||
#define XCASE 0000004
|
||||
#define ECHO 0000010 /* Enable echo. */
|
||||
#define ECHOE 0000020 /* Visual erase for ERASE. */
|
||||
#define ECHOK 0000040 /* Echo NL after KILL. */
|
||||
#define ECHONL 0000100 /* Echo NL even if ECHO is off. */
|
||||
#define NOFLSH 0000200 /* Disable flush after interrupt. */
|
||||
#define IEXTEN 0000400 /* Enable DISCARD and LNEXT. */
|
||||
#define ECHOCTL 0001000 /* Echo control characters as ^X. */
|
||||
#define ECHOPRT 0002000 /* Hardcopy visual erase. */
|
||||
#define ECHOKE 0004000 /* Visual erase for KILL. */
|
||||
#define FLUSHO 0020000
|
||||
#define PENDIN 0040000 /* Retype pending input (state). */
|
||||
#define TOSTOP 0100000 /* Send SIGTTOU for background output. */
|
||||
#define ITOSTOP TOSTOP
|
||||
#define EXTPROC 0200000 /* External processing on pty */
|
||||
#define ISIG 0x00001 /* Enable signals */
|
||||
#define ICANON 0x00002 /* Do erase and kill processing */
|
||||
#define XCASE 0x00004
|
||||
#define ECHO 0x00008 /* Enable echo */
|
||||
#define ECHOE 0x00010 /* Visual erase for ERASE */
|
||||
#define ECHOK 0x00020 /* Echo NL after KILL */
|
||||
#define ECHONL 0x00040 /* Echo NL even if ECHO is off */
|
||||
#define NOFLSH 0x00080 /* Disable flush after interrupt */
|
||||
#define IEXTEN 0x00100 /* Enable DISCARD and LNEXT */
|
||||
#define ECHOCTL 0x00200 /* Echo control characters as ^X */
|
||||
#define ECHOPRT 0x00400 /* Hardcopy visual erase */
|
||||
#define ECHOKE 0x00800 /* Visual erase for KILL */
|
||||
#define FLUSHO 0x02000
|
||||
#define PENDIN 0x04000 /* Retype pending input (state) */
|
||||
#define TOSTOP 0x08000 /* Send SIGTTOU for background output */
|
||||
#define ITOSTOP TOSTOP
|
||||
#define EXTPROC 0x10000 /* External processing on pty */
|
||||
|
||||
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
|
||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
||||
|
||||
/* tcflow() and TCXONC use these */
|
||||
#define TCOOFF 0 /* Suspend output. */
|
||||
#define TCOON 1 /* Restart suspended output. */
|
||||
#define TCIOFF 2 /* Send a STOP character. */
|
||||
#define TCION 3 /* Send a START character. */
|
||||
|
||||
/* tcflush() and TCFLSH use these */
|
||||
#define TCIFLUSH 0 /* Discard data received but not yet read. */
|
||||
#define TCOFLUSH 1 /* Discard data written but not yet sent. */
|
||||
#define TCIOFLUSH 2 /* Discard all pending data. */
|
||||
|
||||
/* tcsetattr uses these */
|
||||
#define TCSANOW TCSETS /* Change immediately. */
|
||||
#define TCSADRAIN TCSETSW /* Change when pending output is written. */
|
||||
#define TCSAFLUSH TCSETSF /* Flush pending input before changing. */
|
||||
#define TCSANOW TCSETS /* Change immediately */
|
||||
#define TCSADRAIN TCSETSW /* Change when pending output is written */
|
||||
#define TCSAFLUSH TCSETSF /* Flush pending input before changing */
|
||||
|
||||
#endif /* _ASM_TERMBITS_H */
|
||||
|
@ -2,10 +2,8 @@
|
||||
#ifndef __ARCH_PARISC_TERMBITS_H__
|
||||
#define __ARCH_PARISC_TERMBITS_H__
|
||||
|
||||
#include <linux/posix_types.h>
|
||||
#include <asm-generic/termbits-common.h>
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
#define NCCS 19
|
||||
@ -41,158 +39,107 @@ struct ktermios {
|
||||
};
|
||||
|
||||
/* c_cc characters */
|
||||
#define VINTR 0
|
||||
#define VQUIT 1
|
||||
#define VERASE 2
|
||||
#define VKILL 3
|
||||
#define VEOF 4
|
||||
#define VTIME 5
|
||||
#define VMIN 6
|
||||
#define VSWTC 7
|
||||
#define VSTART 8
|
||||
#define VSTOP 9
|
||||
#define VSUSP 10
|
||||
#define VEOL 11
|
||||
#define VREPRINT 12
|
||||
#define VDISCARD 13
|
||||
#define VWERASE 14
|
||||
#define VLNEXT 15
|
||||
#define VEOL2 16
|
||||
|
||||
#define VINTR 0
|
||||
#define VQUIT 1
|
||||
#define VERASE 2
|
||||
#define VKILL 3
|
||||
#define VEOF 4
|
||||
#define VTIME 5
|
||||
#define VMIN 6
|
||||
#define VSWTC 7
|
||||
#define VSTART 8
|
||||
#define VSTOP 9
|
||||
#define VSUSP 10
|
||||
#define VEOL 11
|
||||
#define VREPRINT 12
|
||||
#define VDISCARD 13
|
||||
#define VWERASE 14
|
||||
#define VLNEXT 15
|
||||
#define VEOL2 16
|
||||
|
||||
/* c_iflag bits */
|
||||
#define IGNBRK 0000001
|
||||
#define BRKINT 0000002
|
||||
#define IGNPAR 0000004
|
||||
#define PARMRK 0000010
|
||||
#define INPCK 0000020
|
||||
#define ISTRIP 0000040
|
||||
#define INLCR 0000100
|
||||
#define IGNCR 0000200
|
||||
#define ICRNL 0000400
|
||||
#define IUCLC 0001000
|
||||
#define IXON 0002000
|
||||
#define IXANY 0004000
|
||||
#define IXOFF 0010000
|
||||
#define IMAXBEL 0040000
|
||||
#define IUTF8 0100000
|
||||
#define IUCLC 0x0200
|
||||
#define IXON 0x0400
|
||||
#define IXOFF 0x1000
|
||||
#define IMAXBEL 0x4000
|
||||
#define IUTF8 0x8000
|
||||
|
||||
/* c_oflag bits */
|
||||
#define OPOST 0000001
|
||||
#define OLCUC 0000002
|
||||
#define ONLCR 0000004
|
||||
#define OCRNL 0000010
|
||||
#define ONOCR 0000020
|
||||
#define ONLRET 0000040
|
||||
#define OFILL 0000100
|
||||
#define OFDEL 0000200
|
||||
#define NLDLY 0000400
|
||||
#define NL0 0000000
|
||||
#define NL1 0000400
|
||||
#define CRDLY 0003000
|
||||
#define CR0 0000000
|
||||
#define CR1 0001000
|
||||
#define CR2 0002000
|
||||
#define CR3 0003000
|
||||
#define TABDLY 0014000
|
||||
#define TAB0 0000000
|
||||
#define TAB1 0004000
|
||||
#define TAB2 0010000
|
||||
#define TAB3 0014000
|
||||
#define XTABS 0014000
|
||||
#define BSDLY 0020000
|
||||
#define BS0 0000000
|
||||
#define BS1 0020000
|
||||
#define VTDLY 0040000
|
||||
#define VT0 0000000
|
||||
#define VT1 0040000
|
||||
#define FFDLY 0100000
|
||||
#define FF0 0000000
|
||||
#define FF1 0100000
|
||||
#define OLCUC 0x00002
|
||||
#define ONLCR 0x00004
|
||||
#define NLDLY 0x00100
|
||||
#define NL0 0x00000
|
||||
#define NL1 0x00100
|
||||
#define CRDLY 0x00600
|
||||
#define CR0 0x00000
|
||||
#define CR1 0x00200
|
||||
#define CR2 0x00400
|
||||
#define CR3 0x00600
|
||||
#define TABDLY 0x01800
|
||||
#define TAB0 0x00000
|
||||
#define TAB1 0x00800
|
||||
#define TAB2 0x01000
|
||||
#define TAB3 0x01800
|
||||
#define XTABS 0x01800
|
||||
#define BSDLY 0x02000
|
||||
#define BS0 0x00000
|
||||
#define BS1 0x02000
|
||||
#define VTDLY 0x04000
|
||||
#define VT0 0x00000
|
||||
#define VT1 0x04000
|
||||
#define FFDLY 0x08000
|
||||
#define FF0 0x00000
|
||||
#define FF1 0x08000
|
||||
|
||||
/* c_cflag bit meaning */
|
||||
#define CBAUD 0010017
|
||||
#define B0 0000000 /* hang up */
|
||||
#define B50 0000001
|
||||
#define B75 0000002
|
||||
#define B110 0000003
|
||||
#define B134 0000004
|
||||
#define B150 0000005
|
||||
#define B200 0000006
|
||||
#define B300 0000007
|
||||
#define B600 0000010
|
||||
#define B1200 0000011
|
||||
#define B1800 0000012
|
||||
#define B2400 0000013
|
||||
#define B4800 0000014
|
||||
#define B9600 0000015
|
||||
#define B19200 0000016
|
||||
#define B38400 0000017
|
||||
#define EXTA B19200
|
||||
#define EXTB B38400
|
||||
#define CSIZE 0000060
|
||||
#define CS5 0000000
|
||||
#define CS6 0000020
|
||||
#define CS7 0000040
|
||||
#define CS8 0000060
|
||||
#define CSTOPB 0000100
|
||||
#define CREAD 0000200
|
||||
#define PARENB 0000400
|
||||
#define PARODD 0001000
|
||||
#define HUPCL 0002000
|
||||
#define CLOCAL 0004000
|
||||
#define CBAUDEX 0010000
|
||||
#define BOTHER 0010000
|
||||
#define B57600 0010001
|
||||
#define B115200 0010002
|
||||
#define B230400 0010003
|
||||
#define B460800 0010004
|
||||
#define B500000 0010005
|
||||
#define B576000 0010006
|
||||
#define B921600 0010007
|
||||
#define B1000000 0010010
|
||||
#define B1152000 0010011
|
||||
#define B1500000 0010012
|
||||
#define B2000000 0010013
|
||||
#define B2500000 0010014
|
||||
#define B3000000 0010015
|
||||
#define B3500000 0010016
|
||||
#define B4000000 0010017
|
||||
#define CIBAUD 002003600000 /* input baud rate */
|
||||
#define CMSPAR 010000000000 /* mark or space (stick) parity */
|
||||
#define CRTSCTS 020000000000 /* flow control */
|
||||
|
||||
#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
|
||||
|
||||
#define CBAUD 0x0000100f
|
||||
#define CSIZE 0x00000030
|
||||
#define CS5 0x00000000
|
||||
#define CS6 0x00000010
|
||||
#define CS7 0x00000020
|
||||
#define CS8 0x00000030
|
||||
#define CSTOPB 0x00000040
|
||||
#define CREAD 0x00000080
|
||||
#define PARENB 0x00000100
|
||||
#define PARODD 0x00000200
|
||||
#define HUPCL 0x00000400
|
||||
#define CLOCAL 0x00000800
|
||||
#define CBAUDEX 0x00001000
|
||||
#define BOTHER 0x00001000
|
||||
#define B57600 0x00001001
|
||||
#define B115200 0x00001002
|
||||
#define B230400 0x00001003
|
||||
#define B460800 0x00001004
|
||||
#define B500000 0x00001005
|
||||
#define B576000 0x00001006
|
||||
#define B921600 0x00001007
|
||||
#define B1000000 0x00001008
|
||||
#define B1152000 0x00001009
|
||||
#define B1500000 0x0000100a
|
||||
#define B2000000 0x0000100b
|
||||
#define B2500000 0x0000100c
|
||||
#define B3000000 0x0000100d
|
||||
#define B3500000 0x0000100e
|
||||
#define B4000000 0x0000100f
|
||||
#define CIBAUD 0x100f0000 /* input baud rate */
|
||||
|
||||
/* c_lflag bits */
|
||||
#define ISIG 0000001
|
||||
#define ICANON 0000002
|
||||
#define XCASE 0000004
|
||||
#define ECHO 0000010
|
||||
#define ECHOE 0000020
|
||||
#define ECHOK 0000040
|
||||
#define ECHONL 0000100
|
||||
#define NOFLSH 0000200
|
||||
#define TOSTOP 0000400
|
||||
#define ECHOCTL 0001000
|
||||
#define ECHOPRT 0002000
|
||||
#define ECHOKE 0004000
|
||||
#define FLUSHO 0010000
|
||||
#define PENDIN 0040000
|
||||
#define IEXTEN 0100000
|
||||
#define EXTPROC 0200000
|
||||
|
||||
/* tcflow() and TCXONC use these */
|
||||
#define TCOOFF 0
|
||||
#define TCOON 1
|
||||
#define TCIOFF 2
|
||||
#define TCION 3
|
||||
|
||||
/* tcflush() and TCFLSH use these */
|
||||
#define TCIFLUSH 0
|
||||
#define TCOFLUSH 1
|
||||
#define TCIOFLUSH 2
|
||||
#define ISIG 0x00001
|
||||
#define ICANON 0x00002
|
||||
#define XCASE 0x00004
|
||||
#define ECHO 0x00008
|
||||
#define ECHOE 0x00010
|
||||
#define ECHOK 0x00020
|
||||
#define ECHONL 0x00040
|
||||
#define NOFLSH 0x00080
|
||||
#define TOSTOP 0x00100
|
||||
#define ECHOCTL 0x00200
|
||||
#define ECHOPRT 0x00400
|
||||
#define ECHOKE 0x00800
|
||||
#define FLUSHO 0x01000
|
||||
#define PENDIN 0x04000
|
||||
#define IEXTEN 0x08000
|
||||
#define EXTPROC 0x10000
|
||||
|
||||
/* tcsetattr uses these */
|
||||
#define TCSANOW 0
|
||||
|
@ -9,8 +9,8 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
#include <asm-generic/termbits-common.h>
|
||||
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
/*
|
||||
@ -64,115 +64,72 @@ struct ktermios {
|
||||
#define VDISCARD 16
|
||||
|
||||
/* c_iflag bits */
|
||||
#define IGNBRK 0000001
|
||||
#define BRKINT 0000002
|
||||
#define IGNPAR 0000004
|
||||
#define PARMRK 0000010
|
||||
#define INPCK 0000020
|
||||
#define ISTRIP 0000040
|
||||
#define INLCR 0000100
|
||||
#define IGNCR 0000200
|
||||
#define ICRNL 0000400
|
||||
#define IXON 0001000
|
||||
#define IXOFF 0002000
|
||||
#define IXANY 0004000
|
||||
#define IUCLC 0010000
|
||||
#define IMAXBEL 0020000
|
||||
#define IUTF8 0040000
|
||||
#define IXON 0x0200
|
||||
#define IXOFF 0x0400
|
||||
#define IUCLC 0x1000
|
||||
#define IMAXBEL 0x2000
|
||||
#define IUTF8 0x4000
|
||||
|
||||
/* c_oflag bits */
|
||||
#define OPOST 0000001
|
||||
#define ONLCR 0000002
|
||||
#define OLCUC 0000004
|
||||
|
||||
#define OCRNL 0000010
|
||||
#define ONOCR 0000020
|
||||
#define ONLRET 0000040
|
||||
|
||||
#define OFILL 00000100
|
||||
#define OFDEL 00000200
|
||||
#define NLDLY 00001400
|
||||
#define NL0 00000000
|
||||
#define NL1 00000400
|
||||
#define NL2 00001000
|
||||
#define NL3 00001400
|
||||
#define TABDLY 00006000
|
||||
#define TAB0 00000000
|
||||
#define TAB1 00002000
|
||||
#define TAB2 00004000
|
||||
#define TAB3 00006000
|
||||
#define XTABS 00006000 /* required by POSIX to == TAB3 */
|
||||
#define CRDLY 00030000
|
||||
#define CR0 00000000
|
||||
#define CR1 00010000
|
||||
#define CR2 00020000
|
||||
#define CR3 00030000
|
||||
#define FFDLY 00040000
|
||||
#define FF0 00000000
|
||||
#define FF1 00040000
|
||||
#define BSDLY 00100000
|
||||
#define BS0 00000000
|
||||
#define BS1 00100000
|
||||
#define VTDLY 00200000
|
||||
#define VT0 00000000
|
||||
#define VT1 00200000
|
||||
#define ONLCR 0x00002
|
||||
#define OLCUC 0x00004
|
||||
#define NLDLY 0x00300
|
||||
#define NL0 0x00000
|
||||
#define NL1 0x00100
|
||||
#define NL2 0x00200
|
||||
#define NL3 0x00300
|
||||
#define TABDLY 0x00c00
|
||||
#define TAB0 0x00000
|
||||
#define TAB1 0x00400
|
||||
#define TAB2 0x00800
|
||||
#define TAB3 0x00c00
|
||||
#define XTABS 0x00c00 /* required by POSIX to == TAB3 */
|
||||
#define CRDLY 0x03000
|
||||
#define CR0 0x00000
|
||||
#define CR1 0x01000
|
||||
#define CR2 0x02000
|
||||
#define CR3 0x03000
|
||||
#define FFDLY 0x04000
|
||||
#define FF0 0x00000
|
||||
#define FF1 0x04000
|
||||
#define BSDLY 0x08000
|
||||
#define BS0 0x00000
|
||||
#define BS1 0x08000
|
||||
#define VTDLY 0x10000
|
||||
#define VT0 0x00000
|
||||
#define VT1 0x10000
|
||||
|
||||
/* c_cflag bit meaning */
|
||||
#define CBAUD 0000377
|
||||
#define B0 0000000 /* hang up */
|
||||
#define B50 0000001
|
||||
#define B75 0000002
|
||||
#define B110 0000003
|
||||
#define B134 0000004
|
||||
#define B150 0000005
|
||||
#define B200 0000006
|
||||
#define B300 0000007
|
||||
#define B600 0000010
|
||||
#define B1200 0000011
|
||||
#define B1800 0000012
|
||||
#define B2400 0000013
|
||||
#define B4800 0000014
|
||||
#define B9600 0000015
|
||||
#define B19200 0000016
|
||||
#define B38400 0000017
|
||||
#define EXTA B19200
|
||||
#define EXTB B38400
|
||||
#define CBAUDEX 0000000
|
||||
#define B57600 00020
|
||||
#define B115200 00021
|
||||
#define B230400 00022
|
||||
#define B460800 00023
|
||||
#define B500000 00024
|
||||
#define B576000 00025
|
||||
#define B921600 00026
|
||||
#define B1000000 00027
|
||||
#define B1152000 00030
|
||||
#define B1500000 00031
|
||||
#define B2000000 00032
|
||||
#define B2500000 00033
|
||||
#define B3000000 00034
|
||||
#define B3500000 00035
|
||||
#define B4000000 00036
|
||||
#define BOTHER 00037
|
||||
|
||||
#define CIBAUD 077600000
|
||||
#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
|
||||
|
||||
#define CSIZE 00001400
|
||||
#define CS5 00000000
|
||||
#define CS6 00000400
|
||||
#define CS7 00001000
|
||||
#define CS8 00001400
|
||||
|
||||
#define CSTOPB 00002000
|
||||
#define CREAD 00004000
|
||||
#define PARENB 00010000
|
||||
#define PARODD 00020000
|
||||
#define HUPCL 00040000
|
||||
|
||||
#define CLOCAL 00100000
|
||||
#define CMSPAR 010000000000 /* mark or space (stick) parity */
|
||||
#define CRTSCTS 020000000000 /* flow control */
|
||||
#define CBAUD 0x000000ff
|
||||
#define CBAUDEX 0x00000000
|
||||
#define BOTHER 0x0000001f
|
||||
#define B57600 0x00000010
|
||||
#define B115200 0x00000011
|
||||
#define B230400 0x00000012
|
||||
#define B460800 0x00000013
|
||||
#define B500000 0x00000014
|
||||
#define B576000 0x00000015
|
||||
#define B921600 0x00000016
|
||||
#define B1000000 0x00000017
|
||||
#define B1152000 0x00000018
|
||||
#define B1500000 0x00000019
|
||||
#define B2000000 0x0000001a
|
||||
#define B2500000 0x0000001b
|
||||
#define B3000000 0x0000001c
|
||||
#define B3500000 0x0000001d
|
||||
#define B4000000 0x0000001e
|
||||
#define CSIZE 0x00000300
|
||||
#define CS5 0x00000000
|
||||
#define CS6 0x00000100
|
||||
#define CS7 0x00000200
|
||||
#define CS8 0x00000300
|
||||
#define CSTOPB 0x00000400
|
||||
#define CREAD 0x00000800
|
||||
#define PARENB 0x00001000
|
||||
#define PARODD 0x00002000
|
||||
#define HUPCL 0x00004000
|
||||
#define CLOCAL 0x00008000
|
||||
#define CIBAUD 0x00ff0000
|
||||
|
||||
/* c_lflag bits */
|
||||
#define ISIG 0x00000080
|
||||
@ -192,17 +149,6 @@ struct ktermios {
|
||||
#define IEXTEN 0x00000400
|
||||
#define EXTPROC 0x10000000
|
||||
|
||||
/* Values for the ACTION argument to `tcflow'. */
|
||||
#define TCOOFF 0
|
||||
#define TCOON 1
|
||||
#define TCIOFF 2
|
||||
#define TCION 3
|
||||
|
||||
/* Values for the QUEUE_SELECTOR argument to `tcflush'. */
|
||||
#define TCIFLUSH 0
|
||||
#define TCOFLUSH 1
|
||||
#define TCIOFLUSH 2
|
||||
|
||||
/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */
|
||||
#define TCSANOW 0
|
||||
#define TCSADRAIN 1
|
||||
|
@ -2,15 +2,12 @@
|
||||
#ifndef _UAPI_SPARC_TERMBITS_H
|
||||
#define _UAPI_SPARC_TERMBITS_H
|
||||
|
||||
#include <linux/posix_types.h>
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
#include <asm-generic/termbits-common.h>
|
||||
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
typedef unsigned int tcflag_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
#else
|
||||
typedef unsigned long tcflag_t;
|
||||
typedef unsigned long tcflag_t;
|
||||
#endif
|
||||
|
||||
#define NCC 8
|
||||
@ -61,21 +58,19 @@ struct ktermios {
|
||||
};
|
||||
|
||||
/* c_cc characters */
|
||||
#define VINTR 0
|
||||
#define VQUIT 1
|
||||
#define VERASE 2
|
||||
#define VKILL 3
|
||||
#define VEOF 4
|
||||
#define VEOL 5
|
||||
#define VEOL2 6
|
||||
#define VSWTC 7
|
||||
#define VSTART 8
|
||||
#define VSTOP 9
|
||||
|
||||
|
||||
#define VINTR 0
|
||||
#define VQUIT 1
|
||||
#define VERASE 2
|
||||
#define VKILL 3
|
||||
#define VEOF 4
|
||||
#define VEOL 5
|
||||
#define VEOL2 6
|
||||
#define VSWTC 7
|
||||
#define VSTART 8
|
||||
#define VSTOP 9
|
||||
|
||||
#define VSUSP 10
|
||||
#define VDSUSP 11 /* SunOS POSIX nicety I do believe... */
|
||||
#define VDSUSP 11 /* SunOS POSIX nicety I do believe... */
|
||||
#define VREPRINT 12
|
||||
#define VDISCARD 13
|
||||
#define VWERASE 14
|
||||
@ -90,121 +85,83 @@ struct ktermios {
|
||||
#endif
|
||||
|
||||
/* c_iflag bits */
|
||||
#define IGNBRK 0x00000001
|
||||
#define BRKINT 0x00000002
|
||||
#define IGNPAR 0x00000004
|
||||
#define PARMRK 0x00000008
|
||||
#define INPCK 0x00000010
|
||||
#define ISTRIP 0x00000020
|
||||
#define INLCR 0x00000040
|
||||
#define IGNCR 0x00000080
|
||||
#define ICRNL 0x00000100
|
||||
#define IUCLC 0x00000200
|
||||
#define IXON 0x00000400
|
||||
#define IXANY 0x00000800
|
||||
#define IXOFF 0x00001000
|
||||
#define IMAXBEL 0x00002000
|
||||
#define IUTF8 0x00004000
|
||||
#define IUCLC 0x0200
|
||||
#define IXON 0x0400
|
||||
#define IXOFF 0x1000
|
||||
#define IMAXBEL 0x2000
|
||||
#define IUTF8 0x4000
|
||||
|
||||
/* c_oflag bits */
|
||||
#define OPOST 0x00000001
|
||||
#define OLCUC 0x00000002
|
||||
#define ONLCR 0x00000004
|
||||
#define OCRNL 0x00000008
|
||||
#define ONOCR 0x00000010
|
||||
#define ONLRET 0x00000020
|
||||
#define OFILL 0x00000040
|
||||
#define OFDEL 0x00000080
|
||||
#define NLDLY 0x00000100
|
||||
#define NL0 0x00000000
|
||||
#define NL1 0x00000100
|
||||
#define CRDLY 0x00000600
|
||||
#define CR0 0x00000000
|
||||
#define CR1 0x00000200
|
||||
#define CR2 0x00000400
|
||||
#define CR3 0x00000600
|
||||
#define TABDLY 0x00001800
|
||||
#define TAB0 0x00000000
|
||||
#define TAB1 0x00000800
|
||||
#define TAB2 0x00001000
|
||||
#define TAB3 0x00001800
|
||||
#define XTABS 0x00001800
|
||||
#define BSDLY 0x00002000
|
||||
#define BS0 0x00000000
|
||||
#define BS1 0x00002000
|
||||
#define VTDLY 0x00004000
|
||||
#define VT0 0x00000000
|
||||
#define VT1 0x00004000
|
||||
#define FFDLY 0x00008000
|
||||
#define FF0 0x00000000
|
||||
#define FF1 0x00008000
|
||||
#define PAGEOUT 0x00010000 /* SUNOS specific */
|
||||
#define WRAP 0x00020000 /* SUNOS specific */
|
||||
#define OLCUC 0x00002
|
||||
#define ONLCR 0x00004
|
||||
#define NLDLY 0x00100
|
||||
#define NL0 0x00000
|
||||
#define NL1 0x00100
|
||||
#define CRDLY 0x00600
|
||||
#define CR0 0x00000
|
||||
#define CR1 0x00200
|
||||
#define CR2 0x00400
|
||||
#define CR3 0x00600
|
||||
#define TABDLY 0x01800
|
||||
#define TAB0 0x00000
|
||||
#define TAB1 0x00800
|
||||
#define TAB2 0x01000
|
||||
#define TAB3 0x01800
|
||||
#define XTABS 0x01800
|
||||
#define BSDLY 0x02000
|
||||
#define BS0 0x00000
|
||||
#define BS1 0x02000
|
||||
#define VTDLY 0x04000
|
||||
#define VT0 0x00000
|
||||
#define VT1 0x04000
|
||||
#define FFDLY 0x08000
|
||||
#define FF0 0x00000
|
||||
#define FF1 0x08000
|
||||
#define PAGEOUT 0x10000 /* SUNOS specific */
|
||||
#define WRAP 0x20000 /* SUNOS specific */
|
||||
|
||||
/* c_cflag bit meaning */
|
||||
#define CBAUD 0x0000100f
|
||||
#define B0 0x00000000 /* hang up */
|
||||
#define B50 0x00000001
|
||||
#define B75 0x00000002
|
||||
#define B110 0x00000003
|
||||
#define B134 0x00000004
|
||||
#define B150 0x00000005
|
||||
#define B200 0x00000006
|
||||
#define B300 0x00000007
|
||||
#define B600 0x00000008
|
||||
#define B1200 0x00000009
|
||||
#define B1800 0x0000000a
|
||||
#define B2400 0x0000000b
|
||||
#define B4800 0x0000000c
|
||||
#define B9600 0x0000000d
|
||||
#define B19200 0x0000000e
|
||||
#define B38400 0x0000000f
|
||||
#define EXTA B19200
|
||||
#define EXTB B38400
|
||||
#define CSIZE 0x00000030
|
||||
#define CS5 0x00000000
|
||||
#define CS6 0x00000010
|
||||
#define CS7 0x00000020
|
||||
#define CS8 0x00000030
|
||||
#define CSTOPB 0x00000040
|
||||
#define CREAD 0x00000080
|
||||
#define PARENB 0x00000100
|
||||
#define PARODD 0x00000200
|
||||
#define HUPCL 0x00000400
|
||||
#define CLOCAL 0x00000800
|
||||
#define CBAUDEX 0x00001000
|
||||
#define CBAUD 0x0000100f
|
||||
#define CSIZE 0x00000030
|
||||
#define CS5 0x00000000
|
||||
#define CS6 0x00000010
|
||||
#define CS7 0x00000020
|
||||
#define CS8 0x00000030
|
||||
#define CSTOPB 0x00000040
|
||||
#define CREAD 0x00000080
|
||||
#define PARENB 0x00000100
|
||||
#define PARODD 0x00000200
|
||||
#define HUPCL 0x00000400
|
||||
#define CLOCAL 0x00000800
|
||||
#define CBAUDEX 0x00001000
|
||||
/* We'll never see these speeds with the Zilogs, but for completeness... */
|
||||
#define BOTHER 0x00001000
|
||||
#define B57600 0x00001001
|
||||
#define B115200 0x00001002
|
||||
#define B230400 0x00001003
|
||||
#define B460800 0x00001004
|
||||
#define BOTHER 0x00001000
|
||||
#define B57600 0x00001001
|
||||
#define B115200 0x00001002
|
||||
#define B230400 0x00001003
|
||||
#define B460800 0x00001004
|
||||
/* This is what we can do with the Zilogs. */
|
||||
#define B76800 0x00001005
|
||||
#define B76800 0x00001005
|
||||
/* This is what we can do with the SAB82532. */
|
||||
#define B153600 0x00001006
|
||||
#define B307200 0x00001007
|
||||
#define B614400 0x00001008
|
||||
#define B921600 0x00001009
|
||||
#define B153600 0x00001006
|
||||
#define B307200 0x00001007
|
||||
#define B614400 0x00001008
|
||||
#define B921600 0x00001009
|
||||
/* And these are the rest... */
|
||||
#define B500000 0x0000100a
|
||||
#define B576000 0x0000100b
|
||||
#define B1000000 0x0000100c
|
||||
#define B1152000 0x0000100d
|
||||
#define B1500000 0x0000100e
|
||||
#define B2000000 0x0000100f
|
||||
#define B500000 0x0000100a
|
||||
#define B576000 0x0000100b
|
||||
#define B1000000 0x0000100c
|
||||
#define B1152000 0x0000100d
|
||||
#define B1500000 0x0000100e
|
||||
#define B2000000 0x0000100f
|
||||
/* These have totally bogus values and nobody uses them
|
||||
so far. Later on we'd have to use say 0x10000x and
|
||||
adjust CBAUD constant and drivers accordingly.
|
||||
#define B2500000 0x00001010
|
||||
#define B3000000 0x00001011
|
||||
#define B3500000 0x00001012
|
||||
#define B4000000 0x00001013 */
|
||||
#define CIBAUD 0x100f0000 /* input baud rate (not used) */
|
||||
#define CMSPAR 0x40000000 /* mark or space (stick) parity */
|
||||
#define CRTSCTS 0x80000000 /* flow control */
|
||||
|
||||
#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
|
||||
#define B2500000 0x00001010
|
||||
#define B3000000 0x00001011
|
||||
#define B3500000 0x00001012
|
||||
#define B4000000 0x00001013 */
|
||||
#define CIBAUD 0x100f0000 /* input baud rate (not used) */
|
||||
|
||||
/* c_lflag bits */
|
||||
#define ISIG 0x00000001
|
||||
@ -219,7 +176,7 @@ struct ktermios {
|
||||
#define ECHOCTL 0x00000200
|
||||
#define ECHOPRT 0x00000400
|
||||
#define ECHOKE 0x00000800
|
||||
#define DEFECHO 0x00001000 /* SUNOS thing, what is it? */
|
||||
#define DEFECHO 0x00001000 /* SUNOS thing, what is it? */
|
||||
#define FLUSHO 0x00002000
|
||||
#define PENDIN 0x00004000
|
||||
#define IEXTEN 0x00008000
|
||||
@ -244,21 +201,9 @@ struct ktermios {
|
||||
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
|
||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
||||
|
||||
|
||||
/* tcflow() and TCXONC use these */
|
||||
#define TCOOFF 0
|
||||
#define TCOON 1
|
||||
#define TCIOFF 2
|
||||
#define TCION 3
|
||||
|
||||
/* tcflush() and TCFLSH use these */
|
||||
#define TCIFLUSH 0
|
||||
#define TCOFLUSH 1
|
||||
#define TCIOFLUSH 2
|
||||
|
||||
/* tcsetattr uses these */
|
||||
#define TCSANOW 0
|
||||
#define TCSADRAIN 1
|
||||
#define TCSAFLUSH 2
|
||||
#define TCSANOW 0
|
||||
#define TCSADRAIN 1
|
||||
#define TCSAFLUSH 2
|
||||
|
||||
#endif /* _UAPI_SPARC_TERMBITS_H */
|
||||
|
@ -18,7 +18,8 @@ config TTY_PRINTK
|
||||
The feature is useful to inline user messages with kernel
|
||||
messages.
|
||||
In order to use this feature, you should output user messages
|
||||
to /dev/ttyprintk or redirect console to this TTY.
|
||||
to /dev/ttyprintk or redirect console to this TTY, or boot
|
||||
the kernel with console=ttyprintk.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
@ -1418,7 +1418,11 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)
|
||||
info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR);
|
||||
|
||||
/* byte size and parity */
|
||||
|
||||
if ((cflag & CSIZE) != CS8) {
|
||||
cflag &= ~CSIZE;
|
||||
cflag |= CS7;
|
||||
tty->termios.c_cflag = cflag;
|
||||
}
|
||||
info->params.data_bits = tty_get_char_size(cflag);
|
||||
|
||||
if (cflag & CSTOPB)
|
||||
@ -1432,10 +1436,8 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)
|
||||
info->params.parity = ASYNC_PARITY_ODD;
|
||||
else
|
||||
info->params.parity = ASYNC_PARITY_EVEN;
|
||||
#ifdef CMSPAR
|
||||
if (cflag & CMSPAR)
|
||||
info->params.parity = ASYNC_PARITY_SPACE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* calculate number of jiffies to transmit a full
|
||||
|
@ -11,6 +11,7 @@
|
||||
* of the boot process, for example.
|
||||
*/
|
||||
|
||||
#include <linux/console.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/tty.h>
|
||||
@ -163,6 +164,18 @@ static const struct tty_port_operations tpk_port_ops = {
|
||||
|
||||
static struct tty_driver *ttyprintk_driver;
|
||||
|
||||
static struct tty_driver *ttyprintk_console_device(struct console *c,
|
||||
int *index)
|
||||
{
|
||||
*index = 0;
|
||||
return ttyprintk_driver;
|
||||
}
|
||||
|
||||
static struct console ttyprintk_console = {
|
||||
.name = "ttyprintk",
|
||||
.device = ttyprintk_console_device,
|
||||
};
|
||||
|
||||
static int __init ttyprintk_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -195,6 +208,8 @@ static int __init ttyprintk_init(void)
|
||||
goto error;
|
||||
}
|
||||
|
||||
register_console(&ttyprintk_console);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
@ -205,6 +220,7 @@ error:
|
||||
|
||||
static void __exit ttyprintk_exit(void)
|
||||
{
|
||||
unregister_console(&ttyprintk_console);
|
||||
tty_unregister_driver(ttyprintk_driver);
|
||||
tty_driver_kref_put(ttyprintk_driver);
|
||||
tty_port_destroy(&tpk_port.port);
|
||||
|
@ -588,10 +588,8 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
|
||||
}
|
||||
if (!(cflag & PARODD))
|
||||
cval |= UART_LCR_EPAR;
|
||||
#ifdef CMSPAR
|
||||
if (cflag & CMSPAR)
|
||||
cval |= UART_LCR_SPAR;
|
||||
#endif
|
||||
|
||||
/* Determine divisor based on baud rate */
|
||||
baud = tty_get_baud_rate(tty);
|
||||
|
@ -405,6 +405,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
|
||||
err_tty_register_device_failed:
|
||||
free_irq(irq, qtty);
|
||||
err_dec_line_count:
|
||||
tty_port_destroy(&qtty->port);
|
||||
goldfish_tty_current_line_count--;
|
||||
if (goldfish_tty_current_line_count == 0)
|
||||
goldfish_tty_delete_driver();
|
||||
@ -426,6 +427,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
|
||||
iounmap(qtty->base);
|
||||
qtty->base = NULL;
|
||||
free_irq(qtty->irq, pdev);
|
||||
tty_port_destroy(&qtty->port);
|
||||
goldfish_tty_current_line_count--;
|
||||
if (goldfish_tty_current_line_count == 0)
|
||||
goldfish_tty_delete_driver();
|
||||
|
@ -87,6 +87,25 @@ config HVC_DCC
|
||||
driver. This console is used through a JTAG only on ARM. If you don't have
|
||||
a JTAG then you probably don't want this option.
|
||||
|
||||
config HVC_DCC_SERIALIZE_SMP
|
||||
bool "Use DCC only on CPU core 0"
|
||||
depends on SMP && HVC_DCC
|
||||
help
|
||||
This is a DEBUG option to serialize all console input and output to CPU 0.
|
||||
Some external debuggers, do not handle reads/writes from/to DCC on more
|
||||
than one CPU core. Each core has its own DCC device registers, so when a
|
||||
CPU core reads or writes from/to DCC, it only accesses its own DCC device.
|
||||
Since kernel code can run on any CPU core, every time the kernel wants to
|
||||
write to the console, it might write to a different DCC.
|
||||
|
||||
In SMP mode, external debuggers create multiple windows, and each window
|
||||
shows the DCC output only from that core's DCC. The result is that
|
||||
console output is either lost or scattered across windows.
|
||||
|
||||
Enable this option only if you are sure that you do not need features like
|
||||
CPU hotplug to work. For example, during early chipset bringups without
|
||||
debug serial console support. If unsure, say N.
|
||||
|
||||
config HVC_RISCV_SBI
|
||||
bool "RISC-V SBI console support"
|
||||
depends on RISCV_SBI_V01
|
||||
|
@ -1,10 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2010, 2014, 2022 The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/console.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/dcc.h>
|
||||
#include <asm/processor.h>
|
||||
@ -15,6 +20,15 @@
|
||||
#define DCC_STATUS_RX (1 << 30)
|
||||
#define DCC_STATUS_TX (1 << 29)
|
||||
|
||||
#define DCC_INBUF_SIZE 128
|
||||
#define DCC_OUTBUF_SIZE 1024
|
||||
|
||||
/* Lock to serialize access to DCC fifo */
|
||||
static DEFINE_SPINLOCK(dcc_lock);
|
||||
|
||||
static DEFINE_KFIFO(inbuf, unsigned char, DCC_INBUF_SIZE);
|
||||
static DEFINE_KFIFO(outbuf, unsigned char, DCC_OUTBUF_SIZE);
|
||||
|
||||
static void dcc_uart_console_putchar(struct uart_port *port, unsigned char ch)
|
||||
{
|
||||
while (__dcc_getstatus() & DCC_STATUS_TX)
|
||||
@ -67,24 +81,176 @@ static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the DCC is enabled. If CONFIG_HVC_DCC_SERIALIZE_SMP is enabled,
|
||||
* then we assume then this function will be called first on core0. That way,
|
||||
* dcc_core0_available will be true only if it's available on core0.
|
||||
*/
|
||||
static bool hvc_dcc_check(void)
|
||||
{
|
||||
unsigned long time = jiffies + (HZ / 10);
|
||||
static bool dcc_core0_available;
|
||||
|
||||
/*
|
||||
* If we're not on core 0, but we previously confirmed that DCC is
|
||||
* active, then just return true.
|
||||
*/
|
||||
int cpu = get_cpu();
|
||||
|
||||
if (IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP) && cpu && dcc_core0_available) {
|
||||
put_cpu();
|
||||
return true;
|
||||
}
|
||||
|
||||
put_cpu();
|
||||
|
||||
/* Write a test character to check if it is handled */
|
||||
__dcc_putchar('\n');
|
||||
|
||||
while (time_is_after_jiffies(time)) {
|
||||
if (!(__dcc_getstatus() & DCC_STATUS_TX))
|
||||
if (!(__dcc_getstatus() & DCC_STATUS_TX)) {
|
||||
dcc_core0_available = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Workqueue function that writes the output FIFO to the DCC on core 0.
|
||||
*/
|
||||
static void dcc_put_work(struct work_struct *work)
|
||||
{
|
||||
unsigned char ch;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dcc_lock, irqflags);
|
||||
|
||||
/* While there's data in the output FIFO, write it to the DCC */
|
||||
while (kfifo_get(&outbuf, &ch))
|
||||
hvc_dcc_put_chars(0, &ch, 1);
|
||||
|
||||
/* While we're at it, check for any input characters */
|
||||
while (!kfifo_is_full(&inbuf)) {
|
||||
if (!hvc_dcc_get_chars(0, &ch, 1))
|
||||
break;
|
||||
kfifo_put(&inbuf, ch);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dcc_lock, irqflags);
|
||||
}
|
||||
|
||||
static DECLARE_WORK(dcc_pwork, dcc_put_work);
|
||||
|
||||
/*
|
||||
* Workqueue function that reads characters from DCC and puts them into the
|
||||
* input FIFO.
|
||||
*/
|
||||
static void dcc_get_work(struct work_struct *work)
|
||||
{
|
||||
unsigned char ch;
|
||||
unsigned long irqflags;
|
||||
|
||||
/*
|
||||
* Read characters from DCC and put them into the input FIFO, as
|
||||
* long as there is room and we have characters to read.
|
||||
*/
|
||||
spin_lock_irqsave(&dcc_lock, irqflags);
|
||||
|
||||
while (!kfifo_is_full(&inbuf)) {
|
||||
if (!hvc_dcc_get_chars(0, &ch, 1))
|
||||
break;
|
||||
kfifo_put(&inbuf, ch);
|
||||
}
|
||||
spin_unlock_irqrestore(&dcc_lock, irqflags);
|
||||
}
|
||||
|
||||
static DECLARE_WORK(dcc_gwork, dcc_get_work);
|
||||
|
||||
/*
|
||||
* Write characters directly to the DCC if we're on core 0 and the FIFO
|
||||
* is empty, or write them to the FIFO if we're not.
|
||||
*/
|
||||
static int hvc_dcc0_put_chars(u32 vt, const char *buf, int count)
|
||||
{
|
||||
int len;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP))
|
||||
return hvc_dcc_put_chars(vt, buf, count);
|
||||
|
||||
spin_lock_irqsave(&dcc_lock, irqflags);
|
||||
if (smp_processor_id() || (!kfifo_is_empty(&outbuf))) {
|
||||
len = kfifo_in(&outbuf, buf, count);
|
||||
spin_unlock_irqrestore(&dcc_lock, irqflags);
|
||||
|
||||
/*
|
||||
* We just push data to the output FIFO, so schedule the
|
||||
* workqueue that will actually write that data to DCC.
|
||||
* CPU hotplug is disabled in dcc_init so CPU0 cannot be
|
||||
* offlined after the cpu online check.
|
||||
*/
|
||||
if (cpu_online(0))
|
||||
schedule_work_on(0, &dcc_pwork);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're already on core 0, and the FIFO is empty, then just
|
||||
* write the data to DCC.
|
||||
*/
|
||||
len = hvc_dcc_put_chars(vt, buf, count);
|
||||
spin_unlock_irqrestore(&dcc_lock, irqflags);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read characters directly from the DCC if we're on core 0 and the FIFO
|
||||
* is empty, or read them from the FIFO if we're not.
|
||||
*/
|
||||
static int hvc_dcc0_get_chars(u32 vt, char *buf, int count)
|
||||
{
|
||||
int len;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP))
|
||||
return hvc_dcc_get_chars(vt, buf, count);
|
||||
|
||||
spin_lock_irqsave(&dcc_lock, irqflags);
|
||||
|
||||
if (smp_processor_id() || (!kfifo_is_empty(&inbuf))) {
|
||||
len = kfifo_out(&inbuf, buf, count);
|
||||
spin_unlock_irqrestore(&dcc_lock, irqflags);
|
||||
|
||||
/*
|
||||
* If the FIFO was empty, there may be characters in the DCC
|
||||
* that we haven't read yet. Schedule a workqueue to fill
|
||||
* the input FIFO, so that the next time this function is
|
||||
* called, we'll have data. CPU hotplug is disabled in dcc_init
|
||||
* so CPU0 cannot be offlined after the cpu online check.
|
||||
*/
|
||||
if (!len && cpu_online(0))
|
||||
schedule_work_on(0, &dcc_gwork);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're already on core 0, and the FIFO is empty, then just
|
||||
* read the data from DCC.
|
||||
*/
|
||||
len = hvc_dcc_get_chars(vt, buf, count);
|
||||
spin_unlock_irqrestore(&dcc_lock, irqflags);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct hv_ops hvc_dcc_get_put_ops = {
|
||||
.get_chars = hvc_dcc_get_chars,
|
||||
.put_chars = hvc_dcc_put_chars,
|
||||
.get_chars = hvc_dcc0_get_chars,
|
||||
.put_chars = hvc_dcc0_put_chars,
|
||||
};
|
||||
|
||||
static int __init hvc_dcc_console_init(void)
|
||||
@ -108,6 +274,26 @@ static int __init hvc_dcc_init(void)
|
||||
if (!hvc_dcc_check())
|
||||
return -ENODEV;
|
||||
|
||||
if (IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP)) {
|
||||
pr_warn("\n");
|
||||
pr_warn("********************************************************************\n");
|
||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** HVC_DCC_SERIALIZE_SMP SUPPORT HAS BEEN ENABLED IN THIS KERNEL **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** This means that this is a DEBUG kernel and unsafe for **\n");
|
||||
pr_warn("** production use and has important feature like CPU hotplug **\n");
|
||||
pr_warn("** disabled. **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** If you see this message and you are not debugging the **\n");
|
||||
pr_warn("** kernel, report this immediately to your vendor! **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||
pr_warn("********************************************************************\n");
|
||||
|
||||
cpu_hotplug_disable();
|
||||
}
|
||||
|
||||
p = hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
|
||||
|
||||
return PTR_ERR_OR_ZERO(p);
|
||||
|
@ -13,12 +13,12 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/hvconsole.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/hvsi.h>
|
||||
#include <asm/udbg.h>
|
||||
@ -342,9 +342,9 @@ void __init hvc_opal_init_early(void)
|
||||
* path, so we hard wire it
|
||||
*/
|
||||
opal = of_find_node_by_path("/ibm,opal/consoles");
|
||||
if (opal)
|
||||
if (opal) {
|
||||
pr_devel("hvc_opal: Found consoles in new location\n");
|
||||
if (!opal) {
|
||||
} else {
|
||||
opal = of_find_node_by_path("/ibm,opal");
|
||||
if (opal)
|
||||
pr_devel("hvc_opal: "
|
||||
|
@ -28,10 +28,10 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/hvconsole.h>
|
||||
#include <asm/vio.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/hvsi.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/machdep.h>
|
||||
|
@ -581,10 +581,9 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
|
||||
|
||||
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
||||
/* This is synch -- FIXME :js: it is not! */
|
||||
if(got)
|
||||
if (got)
|
||||
tty_flip_buffer_push(&hvcsd->port);
|
||||
|
||||
if (!got) {
|
||||
else {
|
||||
/* Do this _after_ the flip_buffer_push */
|
||||
spin_lock_irqsave(&hvcsd->lock, flags);
|
||||
vio_enable_interrupts(hvcsd->vdev);
|
||||
|
@ -26,13 +26,13 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/hvconsole.h>
|
||||
#include <asm/prom.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/vio.h>
|
||||
#include <asm/param.h>
|
||||
|
@ -528,7 +528,6 @@ static int mxser_set_baud(struct tty_struct *tty, speed_t newspd)
|
||||
outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */
|
||||
outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
|
||||
|
||||
#ifdef BOTHER
|
||||
if (C_BAUD(tty) == BOTHER) {
|
||||
quot = MXSER_BAUD_BASE % newspd;
|
||||
quot *= 8;
|
||||
@ -539,9 +538,9 @@ static int mxser_set_baud(struct tty_struct *tty, speed_t newspd)
|
||||
quot /= newspd;
|
||||
|
||||
mxser_set_must_enum_value(info->ioaddr, quot);
|
||||
} else
|
||||
#endif
|
||||
} else {
|
||||
mxser_set_must_enum_value(info->ioaddr, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -444,6 +444,25 @@ static u8 gsm_encode_modem(const struct gsm_dlci *dlci)
|
||||
return modembits;
|
||||
}
|
||||
|
||||
static void gsm_hex_dump_bytes(const char *fname, const u8 *data,
|
||||
unsigned long len)
|
||||
{
|
||||
char *prefix;
|
||||
|
||||
if (!fname) {
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, data, len,
|
||||
true);
|
||||
return;
|
||||
}
|
||||
|
||||
prefix = kasprintf(GFP_KERNEL, "%s: ", fname);
|
||||
if (!prefix)
|
||||
return;
|
||||
print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 16, 1, data, len,
|
||||
true);
|
||||
kfree(prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsm_print_packet - display a frame for debug
|
||||
* @hdr: header to print before decode
|
||||
@ -508,7 +527,7 @@ static void gsm_print_packet(const char *hdr, int addr, int cr,
|
||||
else
|
||||
pr_cont("(F)");
|
||||
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_NONE, data, dlen);
|
||||
gsm_hex_dump_bytes(NULL, data, dlen);
|
||||
}
|
||||
|
||||
|
||||
@ -698,9 +717,7 @@ static void gsm_data_kick(struct gsm_mux *gsm, struct gsm_dlci *dlci)
|
||||
}
|
||||
|
||||
if (debug & 4)
|
||||
print_hex_dump_bytes("gsm_data_kick: ",
|
||||
DUMP_PREFIX_OFFSET,
|
||||
gsm->txframe, len);
|
||||
gsm_hex_dump_bytes(__func__, gsm->txframe, len);
|
||||
if (gsmld_output(gsm, gsm->txframe, len) <= 0)
|
||||
break;
|
||||
/* FIXME: Can eliminate one SOF in many more cases */
|
||||
@ -749,7 +766,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
|
||||
|
||||
*--dp = msg->ctrl;
|
||||
if (gsm->initiator)
|
||||
*--dp = (msg->addr << 2) | 2 | EA;
|
||||
*--dp = (msg->addr << 2) | CR | EA;
|
||||
else
|
||||
*--dp = (msg->addr << 2) | EA;
|
||||
*fcs = gsm_fcs_add_block(INIT_FCS, dp , msg->data - dp);
|
||||
@ -1907,10 +1924,6 @@ static void gsm_queue(struct gsm_mux *gsm)
|
||||
case UI|PF:
|
||||
case UIH:
|
||||
case UIH|PF:
|
||||
#if 0
|
||||
if (cr)
|
||||
goto invalid;
|
||||
#endif
|
||||
if (dlci == NULL || dlci->state != DLCI_OPEN) {
|
||||
gsm_command(gsm, address, DM|PF);
|
||||
return;
|
||||
@ -2448,8 +2461,7 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
|
||||
return -ENOSPC;
|
||||
}
|
||||
if (debug & 4)
|
||||
print_hex_dump_bytes("gsmld_output: ", DUMP_PREFIX_OFFSET,
|
||||
data, len);
|
||||
gsm_hex_dump_bytes(__func__, data, len);
|
||||
return gsm->tty->ops->write(gsm->tty, data, len);
|
||||
}
|
||||
|
||||
@ -2525,8 +2537,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
char flags = TTY_NORMAL;
|
||||
|
||||
if (debug & 4)
|
||||
print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
|
||||
cp, count);
|
||||
gsm_hex_dump_bytes(__func__, cp, count);
|
||||
|
||||
for (; count; count--, cp++) {
|
||||
if (fp)
|
||||
|
@ -1220,21 +1220,34 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c)
|
||||
process_echoes(tty);
|
||||
}
|
||||
|
||||
static bool n_tty_is_char_flow_ctrl(struct tty_struct *tty, unsigned char c)
|
||||
{
|
||||
return c == START_CHAR(tty) || c == STOP_CHAR(tty);
|
||||
}
|
||||
|
||||
/* Returns true if c is consumed as flow-control character */
|
||||
static bool n_tty_receive_char_flow_ctrl(struct tty_struct *tty, unsigned char c)
|
||||
{
|
||||
if (!n_tty_is_char_flow_ctrl(tty, c))
|
||||
return false;
|
||||
|
||||
if (c == START_CHAR(tty)) {
|
||||
start_tty(tty);
|
||||
process_echoes(tty);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* STOP_CHAR */
|
||||
stop_tty(tty);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
|
||||
if (I_IXON(tty)) {
|
||||
if (c == START_CHAR(tty)) {
|
||||
start_tty(tty);
|
||||
process_echoes(tty);
|
||||
return;
|
||||
}
|
||||
if (c == STOP_CHAR(tty)) {
|
||||
stop_tty(tty);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (I_IXON(tty) && n_tty_receive_char_flow_ctrl(tty, c))
|
||||
return;
|
||||
|
||||
if (L_ISIG(tty)) {
|
||||
if (c == INTR_CHAR(tty)) {
|
||||
@ -1975,6 +1988,35 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty,
|
||||
return ldata->read_tail != canon_head;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we finished a read at the exact location of an
|
||||
* EOF (special EOL character that's a __DISABLED_CHAR)
|
||||
* in the stream, silently eat the EOF.
|
||||
*/
|
||||
static void canon_skip_eof(struct tty_struct *tty)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
size_t tail, canon_head;
|
||||
|
||||
canon_head = smp_load_acquire(&ldata->canon_head);
|
||||
tail = ldata->read_tail;
|
||||
|
||||
// No data?
|
||||
if (tail == canon_head)
|
||||
return;
|
||||
|
||||
// See if the tail position is EOF in the circular buffer
|
||||
tail &= (N_TTY_BUF_SIZE - 1);
|
||||
if (!test_bit(tail, ldata->read_flags))
|
||||
return;
|
||||
if (read_buf(ldata, tail) != __DISABLED_CHAR)
|
||||
return;
|
||||
|
||||
// Clear the EOL bit, skip the EOF char.
|
||||
clear_bit(tail, ldata->read_flags);
|
||||
smp_store_release(&ldata->read_tail, ldata->read_tail + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* job_control - check job control
|
||||
* @tty: tty
|
||||
@ -2045,7 +2087,14 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
|
||||
*/
|
||||
if (*cookie) {
|
||||
if (ldata->icanon && !L_EXTPROC(tty)) {
|
||||
if (canon_copy_from_read_buf(tty, &kb, &nr))
|
||||
/*
|
||||
* If we have filled the user buffer, see
|
||||
* if we should skip an EOF character before
|
||||
* releasing the lock and returning done.
|
||||
*/
|
||||
if (!nr)
|
||||
canon_skip_eof(tty);
|
||||
else if (canon_copy_from_read_buf(tty, &kb, &nr))
|
||||
return kb - kbuf;
|
||||
} else {
|
||||
if (copy_from_read_buf(tty, &kb, &nr))
|
||||
|
@ -17,6 +17,8 @@
|
||||
struct uart_8250_dma {
|
||||
int (*tx_dma)(struct uart_8250_port *p);
|
||||
int (*rx_dma)(struct uart_8250_port *p);
|
||||
void (*prepare_tx_dma)(struct uart_8250_port *p);
|
||||
void (*prepare_rx_dma)(struct uart_8250_port *p);
|
||||
|
||||
/* Filter function */
|
||||
dma_filter_fn fn;
|
||||
@ -83,6 +85,7 @@ struct serial8250_config {
|
||||
#define UART_CAP_MINI BIT(17) /* Mini UART on BCM283X family lacks:
|
||||
* STOP PARITY EPAR SPAR WLEN5 WLEN6
|
||||
*/
|
||||
#define UART_CAP_NOTEMT BIT(18) /* UART without interrupt on TEMT available */
|
||||
|
||||
#define UART_BUG_QUOT BIT(0) /* UART has buggy quot LSB */
|
||||
#define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */
|
||||
@ -120,6 +123,28 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value)
|
||||
up->port.serial_out(&up->port, offset, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* For the 16C950
|
||||
*/
|
||||
static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
|
||||
{
|
||||
serial_out(up, UART_SCR, offset);
|
||||
serial_out(up, UART_ICR, value);
|
||||
}
|
||||
|
||||
static unsigned int __maybe_unused serial_icr_read(struct uart_8250_port *up,
|
||||
int offset)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
|
||||
serial_out(up, UART_SCR, offset);
|
||||
value = serial_in(up, UART_ICR);
|
||||
serial_icr_write(up, UART_ACR, up->acr);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
|
||||
|
||||
static inline int serial_dl_read(struct uart_8250_port *up)
|
||||
@ -302,6 +327,22 @@ extern int serial8250_rx_dma(struct uart_8250_port *);
|
||||
extern void serial8250_rx_dma_flush(struct uart_8250_port *);
|
||||
extern int serial8250_request_dma(struct uart_8250_port *);
|
||||
extern void serial8250_release_dma(struct uart_8250_port *);
|
||||
|
||||
static inline void serial8250_do_prepare_tx_dma(struct uart_8250_port *p)
|
||||
{
|
||||
struct uart_8250_dma *dma = p->dma;
|
||||
|
||||
if (dma->prepare_tx_dma)
|
||||
dma->prepare_tx_dma(p);
|
||||
}
|
||||
|
||||
static inline void serial8250_do_prepare_rx_dma(struct uart_8250_port *p)
|
||||
{
|
||||
struct uart_8250_dma *dma = p->dma;
|
||||
|
||||
if (dma->prepare_rx_dma)
|
||||
dma->prepare_rx_dma(p);
|
||||
}
|
||||
#else
|
||||
static inline int serial8250_tx_dma(struct uart_8250_port *p)
|
||||
{
|
||||
|
@ -429,6 +429,8 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
||||
timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&port, 0, sizeof(port));
|
||||
port.port.private_data = vuart;
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/io.h>
|
||||
#ifdef CONFIG_SPARC
|
||||
#include <linux/sunserialcore.h>
|
||||
|
@ -34,7 +34,7 @@ static void __dma_tx_complete(void *param)
|
||||
uart_write_wakeup(&p->port);
|
||||
|
||||
ret = serial8250_tx_dma(p);
|
||||
if (ret)
|
||||
if (ret || !dma->tx_running)
|
||||
serial8250_set_THRI(p);
|
||||
|
||||
spin_unlock_irqrestore(&p->port.lock, flags);
|
||||
@ -80,12 +80,13 @@ int serial8250_tx_dma(struct uart_8250_port *p)
|
||||
|
||||
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
|
||||
/* We have been called from __dma_tx_complete() */
|
||||
serial8250_rpm_put_tx(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
|
||||
serial8250_do_prepare_tx_dma(p);
|
||||
|
||||
desc = dmaengine_prep_slave_single(dma->txchan,
|
||||
dma->tx_addr + xmit->tail,
|
||||
dma->tx_size, DMA_MEM_TO_DEV,
|
||||
@ -123,6 +124,8 @@ int serial8250_rx_dma(struct uart_8250_port *p)
|
||||
if (dma->rx_running)
|
||||
return 0;
|
||||
|
||||
serial8250_do_prepare_rx_dma(p);
|
||||
|
||||
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
|
||||
dma->rx_size, DMA_DEV_TO_MEM,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
|
@ -12,13 +12,13 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/slab.h>
|
||||
@ -33,30 +33,28 @@
|
||||
|
||||
/* Offsets for the DesignWare specific registers */
|
||||
#define DW_UART_USR 0x1f /* UART Status Register */
|
||||
#define DW_UART_DMASA 0xa8 /* DMA Software Ack */
|
||||
|
||||
#define OCTEON_UART_USR 0x27 /* UART Status Register */
|
||||
|
||||
#define RZN1_UART_TDMACR 0x10c /* DMA Control Register Transmit Mode */
|
||||
#define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */
|
||||
|
||||
/* DesignWare specific register fields */
|
||||
#define DW_UART_MCR_SIRE BIT(6)
|
||||
|
||||
struct dw8250_data {
|
||||
struct dw8250_port_data data;
|
||||
/* Renesas specific register fields */
|
||||
#define RZN1_UART_xDMACR_DMA_EN BIT(0)
|
||||
#define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1)
|
||||
#define RZN1_UART_xDMACR_4_WORD_BURST (1 << 1)
|
||||
#define RZN1_UART_xDMACR_8_WORD_BURST (3 << 1)
|
||||
#define RZN1_UART_xDMACR_BLK_SZ(x) ((x) << 3)
|
||||
|
||||
u8 usr_reg;
|
||||
int msr_mask_on;
|
||||
int msr_mask_off;
|
||||
struct clk *clk;
|
||||
struct clk *pclk;
|
||||
struct notifier_block clk_notifier;
|
||||
struct work_struct clk_work;
|
||||
struct reset_control *rst;
|
||||
|
||||
unsigned int skip_autocfg:1;
|
||||
unsigned int uart_16550_compatible:1;
|
||||
};
|
||||
|
||||
static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
|
||||
{
|
||||
return container_of(data, struct dw8250_data, data);
|
||||
}
|
||||
/* Quirks */
|
||||
#define DW_UART_QUIRK_OCTEON BIT(0)
|
||||
#define DW_UART_QUIRK_ARMADA_38X BIT(1)
|
||||
#define DW_UART_QUIRK_SKIP_SET_RATE BIT(2)
|
||||
#define DW_UART_QUIRK_IS_DMA_FC BIT(3)
|
||||
|
||||
static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
|
||||
{
|
||||
@ -238,6 +236,8 @@ static int dw8250_handle_irq(struct uart_port *p)
|
||||
struct uart_8250_port *up = up_to_u8250p(p);
|
||||
struct dw8250_data *d = to_dw8250_data(p->private_data);
|
||||
unsigned int iir = p->serial_in(p, UART_IIR);
|
||||
bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT;
|
||||
unsigned int quirks = d->pdata->quirks;
|
||||
unsigned int status;
|
||||
unsigned long flags;
|
||||
|
||||
@ -251,7 +251,7 @@ static int dw8250_handle_irq(struct uart_port *p)
|
||||
* This problem has only been observed so far when not in DMA mode
|
||||
* so we limit the workaround only to non-DMA mode.
|
||||
*/
|
||||
if (!up->dma && ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)) {
|
||||
if (!up->dma && rx_timeout) {
|
||||
spin_lock_irqsave(&p->lock, flags);
|
||||
status = p->serial_in(p, UART_LSR);
|
||||
|
||||
@ -261,12 +261,21 @@ static int dw8250_handle_irq(struct uart_port *p)
|
||||
spin_unlock_irqrestore(&p->lock, flags);
|
||||
}
|
||||
|
||||
/* Manually stop the Rx DMA transfer when acting as flow controller */
|
||||
if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) {
|
||||
status = p->serial_in(p, UART_LSR);
|
||||
if (status & (UART_LSR_DR | UART_LSR_BI)) {
|
||||
dw8250_writel_ext(p, RZN1_UART_RDMACR, 0);
|
||||
dw8250_writel_ext(p, DW_UART_DMASA, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (serial8250_handle_irq(p, iir))
|
||||
return 1;
|
||||
|
||||
if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
|
||||
/* Clear the USR */
|
||||
(void)p->serial_in(p, d->usr_reg);
|
||||
(void)p->serial_in(p, d->pdata->usr_reg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -384,11 +393,48 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
|
||||
return param == chan->device->dev;
|
||||
}
|
||||
|
||||
static u32 dw8250_rzn1_get_dmacr_burst(int max_burst)
|
||||
{
|
||||
if (max_burst >= 8)
|
||||
return RZN1_UART_xDMACR_8_WORD_BURST;
|
||||
else if (max_burst >= 4)
|
||||
return RZN1_UART_xDMACR_4_WORD_BURST;
|
||||
else
|
||||
return RZN1_UART_xDMACR_1_WORD_BURST;
|
||||
}
|
||||
|
||||
static void dw8250_prepare_tx_dma(struct uart_8250_port *p)
|
||||
{
|
||||
struct uart_port *up = &p->port;
|
||||
struct uart_8250_dma *dma = p->dma;
|
||||
u32 val;
|
||||
|
||||
dw8250_writel_ext(up, RZN1_UART_TDMACR, 0);
|
||||
val = dw8250_rzn1_get_dmacr_burst(dma->txconf.dst_maxburst) |
|
||||
RZN1_UART_xDMACR_BLK_SZ(dma->tx_size) |
|
||||
RZN1_UART_xDMACR_DMA_EN;
|
||||
dw8250_writel_ext(up, RZN1_UART_TDMACR, val);
|
||||
}
|
||||
|
||||
static void dw8250_prepare_rx_dma(struct uart_8250_port *p)
|
||||
{
|
||||
struct uart_port *up = &p->port;
|
||||
struct uart_8250_dma *dma = p->dma;
|
||||
u32 val;
|
||||
|
||||
dw8250_writel_ext(up, RZN1_UART_RDMACR, 0);
|
||||
val = dw8250_rzn1_get_dmacr_burst(dma->rxconf.src_maxburst) |
|
||||
RZN1_UART_xDMACR_BLK_SZ(dma->rx_size) |
|
||||
RZN1_UART_xDMACR_DMA_EN;
|
||||
dw8250_writel_ext(up, RZN1_UART_RDMACR, val);
|
||||
}
|
||||
|
||||
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
|
||||
{
|
||||
struct device_node *np = p->dev->of_node;
|
||||
|
||||
if (np) {
|
||||
unsigned int quirks = data->pdata->quirks;
|
||||
int id;
|
||||
|
||||
/* get index of serial line, if found in DT aliases */
|
||||
@ -396,12 +442,11 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
|
||||
if (id >= 0)
|
||||
p->line = id;
|
||||
#ifdef CONFIG_64BIT
|
||||
if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
|
||||
if (quirks & DW_UART_QUIRK_OCTEON) {
|
||||
p->serial_in = dw8250_serial_inq;
|
||||
p->serial_out = dw8250_serial_outq;
|
||||
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
||||
p->type = PORT_OCTEON;
|
||||
data->usr_reg = 0x27;
|
||||
data->skip_autocfg = true;
|
||||
}
|
||||
#endif
|
||||
@ -412,10 +457,16 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
|
||||
p->serial_out = dw8250_serial_out32be;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "marvell,armada-38x-uart"))
|
||||
if (quirks & DW_UART_QUIRK_ARMADA_38X)
|
||||
p->serial_out = dw8250_serial_out38x;
|
||||
if (of_device_is_compatible(np, "starfive,jh7100-uart"))
|
||||
if (quirks & DW_UART_QUIRK_SKIP_SET_RATE)
|
||||
p->set_termios = dw8250_do_set_termios;
|
||||
if (quirks & DW_UART_QUIRK_IS_DMA_FC) {
|
||||
data->data.dma.txconf.device_fc = 1;
|
||||
data->data.dma.rxconf.device_fc = 1;
|
||||
data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma;
|
||||
data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma;
|
||||
}
|
||||
|
||||
} else if (acpi_dev_present("APMC0D08", NULL, -1)) {
|
||||
p->iotype = UPIO_MEM32;
|
||||
@ -433,21 +484,30 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
|
||||
}
|
||||
}
|
||||
|
||||
static void dw8250_clk_disable_unprepare(void *data)
|
||||
{
|
||||
clk_disable_unprepare(data);
|
||||
}
|
||||
|
||||
static void dw8250_reset_control_assert(void *data)
|
||||
{
|
||||
reset_control_assert(data);
|
||||
}
|
||||
|
||||
static int dw8250_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_8250_port uart = {}, *up = &uart;
|
||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct uart_port *p = &up->port;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dw8250_data *data;
|
||||
struct resource *regs;
|
||||
int irq;
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
if (!regs) {
|
||||
dev_err(dev, "no registers defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs)
|
||||
return dev_err_probe(dev, -EINVAL, "no registers defined\n");
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
@ -476,7 +536,7 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
data->data.dma.fn = dw8250_fallback_dma_filter;
|
||||
data->usr_reg = DW_UART_USR;
|
||||
data->pdata = device_get_match_data(p->dev);
|
||||
p->private_data = &data->data;
|
||||
|
||||
data->uart_16550_compatible = device_property_read_bool(dev,
|
||||
@ -532,37 +592,41 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
|
||||
err = clk_prepare_enable(data->clk);
|
||||
if (err)
|
||||
dev_warn(dev, "could not enable optional baudclk: %d\n", err);
|
||||
return dev_err_probe(dev, err, "could not enable optional baudclk\n");
|
||||
|
||||
err = devm_add_action_or_reset(dev, dw8250_clk_disable_unprepare, data->clk);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (data->clk)
|
||||
p->uartclk = clk_get_rate(data->clk);
|
||||
|
||||
/* If no clock rate is defined, fail. */
|
||||
if (!p->uartclk) {
|
||||
dev_err(dev, "clock rate not defined\n");
|
||||
err = -EINVAL;
|
||||
goto err_clk;
|
||||
}
|
||||
if (!p->uartclk)
|
||||
return dev_err_probe(dev, -EINVAL, "clock rate not defined\n");
|
||||
|
||||
data->pclk = devm_clk_get_optional(dev, "apb_pclk");
|
||||
if (IS_ERR(data->pclk)) {
|
||||
err = PTR_ERR(data->pclk);
|
||||
goto err_clk;
|
||||
}
|
||||
if (IS_ERR(data->pclk))
|
||||
return PTR_ERR(data->pclk);
|
||||
|
||||
err = clk_prepare_enable(data->pclk);
|
||||
if (err) {
|
||||
dev_err(dev, "could not enable apb_pclk\n");
|
||||
goto err_clk;
|
||||
}
|
||||
if (err)
|
||||
return dev_err_probe(dev, err, "could not enable apb_pclk\n");
|
||||
|
||||
err = devm_add_action_or_reset(dev, dw8250_clk_disable_unprepare, data->pclk);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
|
||||
if (IS_ERR(data->rst)) {
|
||||
err = PTR_ERR(data->rst);
|
||||
goto err_pclk;
|
||||
}
|
||||
if (IS_ERR(data->rst))
|
||||
return PTR_ERR(data->rst);
|
||||
|
||||
reset_control_deassert(data->rst);
|
||||
|
||||
err = devm_add_action_or_reset(dev, dw8250_reset_control_assert, data->rst);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dw8250_quirks(p, data);
|
||||
|
||||
/* If the Busy Functionality is not implemented, don't handle it */
|
||||
@ -580,10 +644,8 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
data->data.line = serial8250_register_8250_port(up);
|
||||
if (data->data.line < 0) {
|
||||
err = data->data.line;
|
||||
goto err_reset;
|
||||
}
|
||||
if (data->data.line < 0)
|
||||
return data->data.line;
|
||||
|
||||
/*
|
||||
* Some platforms may provide a reference clock shared between several
|
||||
@ -593,9 +655,8 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
if (data->clk) {
|
||||
err = clk_notifier_register(data->clk, &data->clk_notifier);
|
||||
if (err)
|
||||
dev_warn(p->dev, "Failed to set the clock notifier\n");
|
||||
else
|
||||
queue_work(system_unbound_wq, &data->clk_work);
|
||||
return dev_err_probe(dev, err, "Failed to set the clock notifier\n");
|
||||
queue_work(system_unbound_wq, &data->clk_work);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
@ -604,17 +665,6 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_reset:
|
||||
reset_control_assert(data->rst);
|
||||
|
||||
err_pclk:
|
||||
clk_disable_unprepare(data->pclk);
|
||||
|
||||
err_clk:
|
||||
clk_disable_unprepare(data->clk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dw8250_remove(struct platform_device *pdev)
|
||||
@ -632,12 +682,6 @@ static int dw8250_remove(struct platform_device *pdev)
|
||||
|
||||
serial8250_unregister_port(data->data.line);
|
||||
|
||||
reset_control_assert(data->rst);
|
||||
|
||||
clk_disable_unprepare(data->pclk);
|
||||
|
||||
clk_disable_unprepare(data->clk);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
|
||||
@ -693,12 +737,37 @@ static const struct dev_pm_ops dw8250_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct dw8250_platform_data dw8250_dw_apb = {
|
||||
.usr_reg = DW_UART_USR,
|
||||
};
|
||||
|
||||
static const struct dw8250_platform_data dw8250_octeon_3860_data = {
|
||||
.usr_reg = OCTEON_UART_USR,
|
||||
.quirks = DW_UART_QUIRK_OCTEON,
|
||||
};
|
||||
|
||||
static const struct dw8250_platform_data dw8250_armada_38x_data = {
|
||||
.usr_reg = DW_UART_USR,
|
||||
.quirks = DW_UART_QUIRK_ARMADA_38X,
|
||||
};
|
||||
|
||||
static const struct dw8250_platform_data dw8250_renesas_rzn1_data = {
|
||||
.usr_reg = DW_UART_USR,
|
||||
.cpr_val = 0x00012f32,
|
||||
.quirks = DW_UART_QUIRK_IS_DMA_FC,
|
||||
};
|
||||
|
||||
static const struct dw8250_platform_data dw8250_starfive_jh7100_data = {
|
||||
.usr_reg = DW_UART_USR,
|
||||
.quirks = DW_UART_QUIRK_SKIP_SET_RATE,
|
||||
};
|
||||
|
||||
static const struct of_device_id dw8250_of_match[] = {
|
||||
{ .compatible = "snps,dw-apb-uart" },
|
||||
{ .compatible = "cavium,octeon-3860-uart" },
|
||||
{ .compatible = "marvell,armada-38x-uart" },
|
||||
{ .compatible = "renesas,rzn1-uart" },
|
||||
{ .compatible = "starfive,jh7100-uart" },
|
||||
{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
|
||||
{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
|
||||
{ .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
|
||||
{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
|
||||
{ .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
||||
|
@ -2,19 +2,32 @@
|
||||
/* Synopsys DesignWare 8250 library. */
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#include "8250_dwlib.h"
|
||||
|
||||
/* Offsets for the DesignWare specific registers */
|
||||
#define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */
|
||||
#define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */
|
||||
#define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */
|
||||
#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
|
||||
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
|
||||
#define DW_UART_UCV 0xf8 /* UART Component Version */
|
||||
|
||||
/* Transceiver Control Register bits */
|
||||
#define DW_UART_TCR_RS485_EN BIT(0)
|
||||
#define DW_UART_TCR_RE_POL BIT(1)
|
||||
#define DW_UART_TCR_DE_POL BIT(2)
|
||||
#define DW_UART_TCR_XFER_MODE GENMASK(4, 3)
|
||||
#define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0)
|
||||
#define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1)
|
||||
#define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2)
|
||||
|
||||
/* Component Parameter Register bits */
|
||||
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
|
||||
#define DW_UART_CPR_AFCE_MODE (1 << 4)
|
||||
@ -32,21 +45,6 @@
|
||||
/* Helper for FIFO size calculation */
|
||||
#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16)
|
||||
|
||||
static inline u32 dw8250_readl_ext(struct uart_port *p, int offset)
|
||||
{
|
||||
if (p->iotype == UPIO_MEM32BE)
|
||||
return ioread32be(p->membase + offset);
|
||||
return readl(p->membase + offset);
|
||||
}
|
||||
|
||||
static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg)
|
||||
{
|
||||
if (p->iotype == UPIO_MEM32BE)
|
||||
iowrite32be(reg, p->membase + offset);
|
||||
else
|
||||
writel(reg, p->membase + offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* divisor = div(I) + div(F)
|
||||
* "I" means integer, "F" means fractional
|
||||
@ -87,11 +85,87 @@ void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw8250_do_set_termios);
|
||||
|
||||
static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485)
|
||||
{
|
||||
u32 tcr;
|
||||
|
||||
tcr = dw8250_readl_ext(p, DW_UART_TCR);
|
||||
tcr &= ~DW_UART_TCR_XFER_MODE;
|
||||
|
||||
if (rs485->flags & SER_RS485_ENABLED) {
|
||||
/* Clear unsupported flags. */
|
||||
rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX |
|
||||
SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND;
|
||||
tcr |= DW_UART_TCR_RS485_EN;
|
||||
|
||||
if (rs485->flags & SER_RS485_RX_DURING_TX) {
|
||||
tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE;
|
||||
} else {
|
||||
/* HW does not support same DE level for tx and rx */
|
||||
if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
|
||||
!(rs485->flags & SER_RS485_RTS_AFTER_SEND))
|
||||
return -EINVAL;
|
||||
|
||||
tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE;
|
||||
}
|
||||
dw8250_writel_ext(p, DW_UART_DE_EN, 1);
|
||||
dw8250_writel_ext(p, DW_UART_RE_EN, 1);
|
||||
} else {
|
||||
rs485->flags = 0;
|
||||
|
||||
tcr &= ~DW_UART_TCR_RS485_EN;
|
||||
}
|
||||
|
||||
/* Reset to default polarity */
|
||||
tcr |= DW_UART_TCR_DE_POL;
|
||||
tcr &= ~DW_UART_TCR_RE_POL;
|
||||
|
||||
if (!(rs485->flags & SER_RS485_RTS_ON_SEND))
|
||||
tcr &= ~DW_UART_TCR_DE_POL;
|
||||
if (device_property_read_bool(p->dev, "rs485-rx-active-high"))
|
||||
tcr |= DW_UART_TCR_RE_POL;
|
||||
|
||||
dw8250_writel_ext(p, DW_UART_TCR, tcr);
|
||||
|
||||
rs485->delay_rts_before_send = 0;
|
||||
rs485->delay_rts_after_send = 0;
|
||||
|
||||
p->rs485 = *rs485;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests if RE_EN register can have non-zero value to see if RS-485 HW support
|
||||
* is present.
|
||||
*/
|
||||
static bool dw8250_detect_rs485_hw(struct uart_port *p)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
dw8250_writel_ext(p, DW_UART_RE_EN, 1);
|
||||
reg = dw8250_readl_ext(p, DW_UART_RE_EN);
|
||||
dw8250_writel_ext(p, DW_UART_RE_EN, 0);
|
||||
return reg;
|
||||
}
|
||||
|
||||
void dw8250_setup_port(struct uart_port *p)
|
||||
{
|
||||
struct dw8250_port_data *pd = p->private_data;
|
||||
struct dw8250_data *data = to_dw8250_data(pd);
|
||||
struct uart_8250_port *up = up_to_u8250p(p);
|
||||
u32 reg;
|
||||
|
||||
pd->hw_rs485_support = dw8250_detect_rs485_hw(p);
|
||||
if (pd->hw_rs485_support) {
|
||||
p->rs485_config = dw8250_rs485_config;
|
||||
} else {
|
||||
p->rs485_config = serial8250_em485_config;
|
||||
up->rs485_start_tx = serial8250_em485_start_tx;
|
||||
up->rs485_stop_tx = serial8250_em485_stop_tx;
|
||||
}
|
||||
up->capabilities |= UART_CAP_NOTEMT;
|
||||
|
||||
/*
|
||||
* If the Component Version Register returns zero, we know that
|
||||
* ADDITIONAL_FEATURES are not enabled. No need to go any further.
|
||||
@ -108,14 +182,16 @@ void dw8250_setup_port(struct uart_port *p)
|
||||
dw8250_writel_ext(p, DW_UART_DLF, 0);
|
||||
|
||||
if (reg) {
|
||||
struct dw8250_port_data *d = p->private_data;
|
||||
|
||||
d->dlf_size = fls(reg);
|
||||
pd->dlf_size = fls(reg);
|
||||
p->get_divisor = dw8250_get_divisor;
|
||||
p->set_divisor = dw8250_set_divisor;
|
||||
}
|
||||
|
||||
reg = dw8250_readl_ext(p, DW_UART_CPR);
|
||||
if (!reg) {
|
||||
reg = data->pdata->cpr_val;
|
||||
dev_dbg(p->dev, "CPR is not available, using 0x%08x instead\n", reg);
|
||||
}
|
||||
if (!reg)
|
||||
return;
|
||||
|
||||
@ -124,7 +200,7 @@ void dw8250_setup_port(struct uart_port *p)
|
||||
p->type = PORT_16550A;
|
||||
p->flags |= UPF_FIXED_TYPE;
|
||||
p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
|
||||
up->capabilities = UART_CAP_FIFO;
|
||||
up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT;
|
||||
}
|
||||
|
||||
if (reg & DW_UART_CPR_AFCE_MODE)
|
||||
|
@ -1,10 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/* Synopsys DesignWare 8250 library header file. */
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
struct clk;
|
||||
struct reset_control;
|
||||
|
||||
struct dw8250_port_data {
|
||||
/* Port properties */
|
||||
int line;
|
||||
@ -14,7 +20,52 @@ struct dw8250_port_data {
|
||||
|
||||
/* Hardware configuration */
|
||||
u8 dlf_size;
|
||||
|
||||
/* RS485 variables */
|
||||
bool hw_rs485_support;
|
||||
};
|
||||
|
||||
struct dw8250_platform_data {
|
||||
u8 usr_reg;
|
||||
u32 cpr_val;
|
||||
unsigned int quirks;
|
||||
};
|
||||
|
||||
struct dw8250_data {
|
||||
struct dw8250_port_data data;
|
||||
const struct dw8250_platform_data *pdata;
|
||||
|
||||
int msr_mask_on;
|
||||
int msr_mask_off;
|
||||
struct clk *clk;
|
||||
struct clk *pclk;
|
||||
struct notifier_block clk_notifier;
|
||||
struct work_struct clk_work;
|
||||
struct reset_control *rst;
|
||||
|
||||
unsigned int skip_autocfg:1;
|
||||
unsigned int uart_16550_compatible:1;
|
||||
};
|
||||
|
||||
void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);
|
||||
void dw8250_setup_port(struct uart_port *p);
|
||||
|
||||
static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
|
||||
{
|
||||
return container_of(data, struct dw8250_data, data);
|
||||
}
|
||||
|
||||
static inline u32 dw8250_readl_ext(struct uart_port *p, int offset)
|
||||
{
|
||||
if (p->iotype == UPIO_MEM32BE)
|
||||
return ioread32be(p->membase + offset);
|
||||
return readl(p->membase + offset);
|
||||
}
|
||||
|
||||
static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg)
|
||||
{
|
||||
if (p->iotype == UPIO_MEM32BE)
|
||||
iowrite32be(reg, p->membase + offset);
|
||||
else
|
||||
writel(reg, p->membase + offset);
|
||||
}
|
||||
|
@ -200,12 +200,12 @@ static int fintek_8250_rs485_config(struct uart_port *port,
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
/* Hardware do not support same RTS level on send and receive */
|
||||
if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
|
||||
!(rs485->flags & SER_RS485_RTS_AFTER_SEND))
|
||||
return -EINVAL;
|
||||
|
||||
if (rs485->flags & SER_RS485_ENABLED) {
|
||||
/* Hardware do not support same RTS level on send and receive */
|
||||
if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
|
||||
!(rs485->flags & SER_RS485_RTS_AFTER_SEND))
|
||||
return -EINVAL;
|
||||
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||
config |= RS485_URA;
|
||||
} else {
|
||||
|
@ -54,9 +54,6 @@
|
||||
#define MTK_UART_TX_TRIGGER 1
|
||||
#define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
|
||||
|
||||
#define MTK_UART_FEATURE_SEL 39 /* Feature Selection register */
|
||||
#define MTK_UART_FEAT_NEWRMAP BIT(0) /* Use new register map */
|
||||
|
||||
#define MTK_UART_XON1 40 /* I/O: Xon character 1 */
|
||||
#define MTK_UART_XOFF1 42 /* I/O: Xoff character 1 */
|
||||
|
||||
@ -575,10 +572,6 @@ static int mtk8250_probe(struct platform_device *pdev)
|
||||
uart.dma = data->dma;
|
||||
#endif
|
||||
|
||||
/* Set AP UART new register map */
|
||||
writel(MTK_UART_FEAT_NEWRMAP, uart.port.membase +
|
||||
(MTK_UART_FEATURE_SEL << uart.port.regshift));
|
||||
|
||||
/* Disable Rate Fix function */
|
||||
writel(0x0, uart.port.membase +
|
||||
(MTK_UART_RATE_FIX << uart.port.regshift));
|
||||
|
@ -326,6 +326,8 @@ static const struct of_device_id of_platform_serial_table[] = {
|
||||
.data = (void *)PORT_ALTR_16550_F64, },
|
||||
{ .compatible = "altr,16550-FIFO128",
|
||||
.data = (void *)PORT_ALTR_16550_F128, },
|
||||
{ .compatible = "fsl,16550-FIFO64",
|
||||
.data = (void *)PORT_16550A_FSL64, },
|
||||
{ .compatible = "mediatek,mtk-btif",
|
||||
.data = (void *)PORT_MTK_BTIF, },
|
||||
{ .compatible = "mrvl,mmp-uart",
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/tty.h>
|
||||
@ -994,41 +995,29 @@ static void pci_ite887x_exit(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* EndRun Technologies.
|
||||
* Determine the number of ports available on the device.
|
||||
* Oxford Semiconductor Inc.
|
||||
* Check if an OxSemi device is part of the Tornado range of devices.
|
||||
*/
|
||||
#define PCI_VENDOR_ID_ENDRUN 0x7401
|
||||
#define PCI_DEVICE_ID_ENDRUN_1588 0xe100
|
||||
|
||||
static int pci_endrun_init(struct pci_dev *dev)
|
||||
static bool pci_oxsemi_tornado_p(struct pci_dev *dev)
|
||||
{
|
||||
u8 __iomem *p;
|
||||
unsigned long deviceID;
|
||||
unsigned int number_uarts = 0;
|
||||
/* OxSemi Tornado devices are all 0xCxxx */
|
||||
if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
|
||||
(dev->device & 0xf000) != 0xc000)
|
||||
return false;
|
||||
|
||||
/* EndRun device is all 0xexxx */
|
||||
/* EndRun devices are all 0xExxx */
|
||||
if (dev->vendor == PCI_VENDOR_ID_ENDRUN &&
|
||||
(dev->device & 0xf000) != 0xe000)
|
||||
return 0;
|
||||
(dev->device & 0xf000) != 0xe000)
|
||||
return false;
|
||||
|
||||
p = pci_iomap(dev, 0, 5);
|
||||
if (p == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
deviceID = ioread32(p);
|
||||
/* EndRun device */
|
||||
if (deviceID == 0x07000200) {
|
||||
number_uarts = ioread8(p + 4);
|
||||
pci_dbg(dev, "%d ports detected on EndRun PCI Express device\n", number_uarts);
|
||||
}
|
||||
pci_iounmap(dev, p);
|
||||
return number_uarts;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Oxford Semiconductor Inc.
|
||||
* Check that device is part of the Tornado range of devices, then determine
|
||||
* the number of ports available on the device.
|
||||
* Determine the number of ports available on a Tornado device.
|
||||
*/
|
||||
static int pci_oxsemi_tornado_init(struct pci_dev *dev)
|
||||
{
|
||||
@ -1036,9 +1025,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
|
||||
unsigned long deviceID;
|
||||
unsigned int number_uarts = 0;
|
||||
|
||||
/* OxSemi Tornado devices are all 0xCxxx */
|
||||
if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
|
||||
(dev->device & 0xF000) != 0xC000)
|
||||
if (!pci_oxsemi_tornado_p(dev))
|
||||
return 0;
|
||||
|
||||
p = pci_iomap(dev, 0, 5);
|
||||
@ -1049,12 +1036,217 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
|
||||
/* Tornado device */
|
||||
if (deviceID == 0x07000200) {
|
||||
number_uarts = ioread8(p + 4);
|
||||
pci_dbg(dev, "%d ports detected on Oxford PCI Express device\n", number_uarts);
|
||||
pci_dbg(dev, "%d ports detected on %s PCI Express device\n",
|
||||
number_uarts,
|
||||
dev->vendor == PCI_VENDOR_ID_ENDRUN ?
|
||||
"EndRun" : "Oxford");
|
||||
}
|
||||
pci_iounmap(dev, p);
|
||||
return number_uarts;
|
||||
}
|
||||
|
||||
/* Tornado-specific constants for the TCR and CPR registers; see below. */
|
||||
#define OXSEMI_TORNADO_TCR_MASK 0xf
|
||||
#define OXSEMI_TORNADO_CPR_MASK 0x1ff
|
||||
#define OXSEMI_TORNADO_CPR_MIN 0x008
|
||||
#define OXSEMI_TORNADO_CPR_DEF 0x10f
|
||||
|
||||
/*
|
||||
* Determine the oversampling rate, the clock prescaler, and the clock
|
||||
* divisor for the requested baud rate. The clock rate is 62.5 MHz,
|
||||
* which is four times the baud base, and the prescaler increments in
|
||||
* steps of 1/8. Therefore to make calculations on integers we need
|
||||
* to use a scaled clock rate, which is the baud base multiplied by 32
|
||||
* (or our assumed UART clock rate multiplied by 2).
|
||||
*
|
||||
* The allowed oversampling rates are from 4 up to 16 inclusive (values
|
||||
* from 0 to 3 inclusive map to 16). Likewise the clock prescaler allows
|
||||
* values between 1.000 and 63.875 inclusive (operation for values from
|
||||
* 0.000 to 0.875 has not been specified). The clock divisor is the usual
|
||||
* unsigned 16-bit integer.
|
||||
*
|
||||
* For the most accurate baud rate we use a table of predetermined
|
||||
* oversampling rates and clock prescalers that records all possible
|
||||
* products of the two parameters in the range from 4 up to 255 inclusive,
|
||||
* and additionally 335 for the 1500000bps rate, with the prescaler scaled
|
||||
* by 8. The table is sorted by the decreasing value of the oversampling
|
||||
* rate and ties are resolved by sorting by the decreasing value of the
|
||||
* product. This way preference is given to higher oversampling rates.
|
||||
*
|
||||
* We iterate over the table and choose the product of an oversampling
|
||||
* rate and a clock prescaler that gives the lowest integer division
|
||||
* result deviation, or if an exact integer divider is found we stop
|
||||
* looking for it right away. We do some fixup if the resulting clock
|
||||
* divisor required would be out of its unsigned 16-bit integer range.
|
||||
*
|
||||
* Finally we abuse the supposed fractional part returned to encode the
|
||||
* 4-bit value of the oversampling rate and the 9-bit value of the clock
|
||||
* prescaler which will end up in the TCR and CPR/CPR2 registers.
|
||||
*/
|
||||
static unsigned int pci_oxsemi_tornado_get_divisor(struct uart_port *port,
|
||||
unsigned int baud,
|
||||
unsigned int *frac)
|
||||
{
|
||||
static u8 p[][2] = {
|
||||
{ 16, 14, }, { 16, 13, }, { 16, 12, }, { 16, 11, },
|
||||
{ 16, 10, }, { 16, 9, }, { 16, 8, }, { 15, 17, },
|
||||
{ 15, 16, }, { 15, 15, }, { 15, 14, }, { 15, 13, },
|
||||
{ 15, 12, }, { 15, 11, }, { 15, 10, }, { 15, 9, },
|
||||
{ 15, 8, }, { 14, 18, }, { 14, 17, }, { 14, 14, },
|
||||
{ 14, 13, }, { 14, 12, }, { 14, 11, }, { 14, 10, },
|
||||
{ 14, 9, }, { 14, 8, }, { 13, 19, }, { 13, 18, },
|
||||
{ 13, 17, }, { 13, 13, }, { 13, 12, }, { 13, 11, },
|
||||
{ 13, 10, }, { 13, 9, }, { 13, 8, }, { 12, 19, },
|
||||
{ 12, 18, }, { 12, 17, }, { 12, 11, }, { 12, 9, },
|
||||
{ 12, 8, }, { 11, 23, }, { 11, 22, }, { 11, 21, },
|
||||
{ 11, 20, }, { 11, 19, }, { 11, 18, }, { 11, 17, },
|
||||
{ 11, 11, }, { 11, 10, }, { 11, 9, }, { 11, 8, },
|
||||
{ 10, 25, }, { 10, 23, }, { 10, 20, }, { 10, 19, },
|
||||
{ 10, 17, }, { 10, 10, }, { 10, 9, }, { 10, 8, },
|
||||
{ 9, 27, }, { 9, 23, }, { 9, 21, }, { 9, 19, },
|
||||
{ 9, 18, }, { 9, 17, }, { 9, 9, }, { 9, 8, },
|
||||
{ 8, 31, }, { 8, 29, }, { 8, 23, }, { 8, 19, },
|
||||
{ 8, 17, }, { 8, 8, }, { 7, 35, }, { 7, 31, },
|
||||
{ 7, 29, }, { 7, 25, }, { 7, 23, }, { 7, 21, },
|
||||
{ 7, 19, }, { 7, 17, }, { 7, 15, }, { 7, 14, },
|
||||
{ 7, 13, }, { 7, 12, }, { 7, 11, }, { 7, 10, },
|
||||
{ 7, 9, }, { 7, 8, }, { 6, 41, }, { 6, 37, },
|
||||
{ 6, 31, }, { 6, 29, }, { 6, 23, }, { 6, 19, },
|
||||
{ 6, 17, }, { 6, 13, }, { 6, 11, }, { 6, 10, },
|
||||
{ 6, 9, }, { 6, 8, }, { 5, 67, }, { 5, 47, },
|
||||
{ 5, 43, }, { 5, 41, }, { 5, 37, }, { 5, 31, },
|
||||
{ 5, 29, }, { 5, 25, }, { 5, 23, }, { 5, 19, },
|
||||
{ 5, 17, }, { 5, 15, }, { 5, 13, }, { 5, 11, },
|
||||
{ 5, 10, }, { 5, 9, }, { 5, 8, }, { 4, 61, },
|
||||
{ 4, 59, }, { 4, 53, }, { 4, 47, }, { 4, 43, },
|
||||
{ 4, 41, }, { 4, 37, }, { 4, 31, }, { 4, 29, },
|
||||
{ 4, 23, }, { 4, 19, }, { 4, 17, }, { 4, 13, },
|
||||
{ 4, 9, }, { 4, 8, },
|
||||
};
|
||||
/* Scale the quotient for comparison to get the fractional part. */
|
||||
const unsigned int quot_scale = 65536;
|
||||
unsigned int sclk = port->uartclk * 2;
|
||||
unsigned int sdiv = DIV_ROUND_CLOSEST(sclk, baud);
|
||||
unsigned int best_squot;
|
||||
unsigned int squot;
|
||||
unsigned int quot;
|
||||
u16 cpr;
|
||||
u8 tcr;
|
||||
int i;
|
||||
|
||||
/* Old custom speed handling. */
|
||||
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
|
||||
unsigned int cust_div = port->custom_divisor;
|
||||
|
||||
quot = cust_div & UART_DIV_MAX;
|
||||
tcr = (cust_div >> 16) & OXSEMI_TORNADO_TCR_MASK;
|
||||
cpr = (cust_div >> 20) & OXSEMI_TORNADO_CPR_MASK;
|
||||
if (cpr < OXSEMI_TORNADO_CPR_MIN)
|
||||
cpr = OXSEMI_TORNADO_CPR_DEF;
|
||||
} else {
|
||||
best_squot = quot_scale;
|
||||
for (i = 0; i < ARRAY_SIZE(p); i++) {
|
||||
unsigned int spre;
|
||||
unsigned int srem;
|
||||
u8 cp;
|
||||
u8 tc;
|
||||
|
||||
tc = p[i][0];
|
||||
cp = p[i][1];
|
||||
spre = tc * cp;
|
||||
|
||||
srem = sdiv % spre;
|
||||
if (srem > spre / 2)
|
||||
srem = spre - srem;
|
||||
squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre);
|
||||
|
||||
if (srem == 0) {
|
||||
tcr = tc;
|
||||
cpr = cp;
|
||||
quot = sdiv / spre;
|
||||
break;
|
||||
} else if (squot < best_squot) {
|
||||
best_squot = squot;
|
||||
tcr = tc;
|
||||
cpr = cp;
|
||||
quot = DIV_ROUND_CLOSEST(sdiv, spre);
|
||||
}
|
||||
}
|
||||
while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 &&
|
||||
quot % 2 == 0) {
|
||||
quot >>= 1;
|
||||
tcr <<= 1;
|
||||
}
|
||||
while (quot > UART_DIV_MAX) {
|
||||
if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) {
|
||||
quot >>= 1;
|
||||
tcr <<= 1;
|
||||
} else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) {
|
||||
quot >>= 1;
|
||||
cpr <<= 1;
|
||||
} else {
|
||||
quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK;
|
||||
cpr = OXSEMI_TORNADO_CPR_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*frac = (cpr << 8) | (tcr & OXSEMI_TORNADO_TCR_MASK);
|
||||
return quot;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the oversampling rate in the transmitter clock cycle register (TCR),
|
||||
* the clock prescaler in the clock prescaler register (CPR and CPR2), and
|
||||
* the clock divisor in the divisor latch (DLL and DLM). Note that for
|
||||
* backwards compatibility any write to CPR clears CPR2 and therefore CPR
|
||||
* has to be written first, followed by CPR2, which occupies the location
|
||||
* of CKS used with earlier UART designs.
|
||||
*/
|
||||
static void pci_oxsemi_tornado_set_divisor(struct uart_port *port,
|
||||
unsigned int baud,
|
||||
unsigned int quot,
|
||||
unsigned int quot_frac)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
u8 cpr2 = quot_frac >> 16;
|
||||
u8 cpr = quot_frac >> 8;
|
||||
u8 tcr = quot_frac;
|
||||
|
||||
serial_icr_write(up, UART_TCR, tcr);
|
||||
serial_icr_write(up, UART_CPR, cpr);
|
||||
serial_icr_write(up, UART_CKS, cpr2);
|
||||
serial8250_do_set_divisor(port, baud, quot, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For Tornado devices we force MCR[7] set for the Divide-by-M N/8 baud rate
|
||||
* generator prescaler (CPR and CPR2). Otherwise no prescaler would be used.
|
||||
*/
|
||||
static void pci_oxsemi_tornado_set_mctrl(struct uart_port *port,
|
||||
unsigned int mctrl)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
|
||||
up->mcr |= UART_MCR_CLKSEL;
|
||||
serial8250_do_set_mctrl(port, mctrl);
|
||||
}
|
||||
|
||||
static int pci_oxsemi_tornado_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *up, int idx)
|
||||
{
|
||||
struct pci_dev *dev = priv->dev;
|
||||
|
||||
if (pci_oxsemi_tornado_p(dev)) {
|
||||
up->port.get_divisor = pci_oxsemi_tornado_get_divisor;
|
||||
up->port.set_divisor = pci_oxsemi_tornado_set_divisor;
|
||||
up->port.set_mctrl = pci_oxsemi_tornado_set_mctrl;
|
||||
}
|
||||
|
||||
return pci_default_setup(priv, board, up, idx);
|
||||
}
|
||||
|
||||
static int pci_asix_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
@ -2244,7 +2436,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_endrun_init,
|
||||
.init = pci_oxsemi_tornado_init,
|
||||
.setup = pci_default_setup,
|
||||
},
|
||||
/*
|
||||
@ -2256,7 +2448,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_oxsemi_tornado_init,
|
||||
.setup = pci_default_setup,
|
||||
.setup = pci_oxsemi_tornado_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_MAINPINE,
|
||||
@ -2264,7 +2456,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_oxsemi_tornado_init,
|
||||
.setup = pci_default_setup,
|
||||
.setup = pci_oxsemi_tornado_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_DIGI,
|
||||
@ -2272,7 +2464,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
|
||||
.subvendor = PCI_SUBVENDOR_ID_IBM,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.init = pci_oxsemi_tornado_init,
|
||||
.setup = pci_default_setup,
|
||||
.setup = pci_oxsemi_tornado_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_INTEL,
|
||||
@ -2589,7 +2781,7 @@ enum pci_board_num_t {
|
||||
pbn_b0_2_1843200,
|
||||
pbn_b0_4_1843200,
|
||||
|
||||
pbn_b0_1_3906250,
|
||||
pbn_b0_1_15625000,
|
||||
|
||||
pbn_b0_bt_1_115200,
|
||||
pbn_b0_bt_2_115200,
|
||||
@ -2667,12 +2859,11 @@ enum pci_board_num_t {
|
||||
pbn_panacom2,
|
||||
pbn_panacom4,
|
||||
pbn_plx_romulus,
|
||||
pbn_endrun_2_3906250,
|
||||
pbn_oxsemi,
|
||||
pbn_oxsemi_1_3906250,
|
||||
pbn_oxsemi_2_3906250,
|
||||
pbn_oxsemi_4_3906250,
|
||||
pbn_oxsemi_8_3906250,
|
||||
pbn_oxsemi_1_15625000,
|
||||
pbn_oxsemi_2_15625000,
|
||||
pbn_oxsemi_4_15625000,
|
||||
pbn_oxsemi_8_15625000,
|
||||
pbn_intel_i960,
|
||||
pbn_sgi_ioc3,
|
||||
pbn_computone_4,
|
||||
@ -2815,10 +3006,10 @@ static struct pciserial_board pci_boards[] = {
|
||||
.uart_offset = 8,
|
||||
},
|
||||
|
||||
[pbn_b0_1_3906250] = {
|
||||
[pbn_b0_1_15625000] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 1,
|
||||
.base_baud = 3906250,
|
||||
.base_baud = 15625000,
|
||||
.uart_offset = 8,
|
||||
},
|
||||
|
||||
@ -3189,20 +3380,6 @@ static struct pciserial_board pci_boards[] = {
|
||||
.first_offset = 0x03,
|
||||
},
|
||||
|
||||
/*
|
||||
* EndRun Technologies
|
||||
* Uses the size of PCI Base region 0 to
|
||||
* signal now many ports are available
|
||||
* 2 port 952 Uart support
|
||||
*/
|
||||
[pbn_endrun_2_3906250] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 2,
|
||||
.base_baud = 3906250,
|
||||
.uart_offset = 0x200,
|
||||
.first_offset = 0x1000,
|
||||
},
|
||||
|
||||
/*
|
||||
* This board uses the size of PCI Base region 0 to
|
||||
* signal now many ports are available
|
||||
@ -3213,31 +3390,31 @@ static struct pciserial_board pci_boards[] = {
|
||||
.base_baud = 115200,
|
||||
.uart_offset = 8,
|
||||
},
|
||||
[pbn_oxsemi_1_3906250] = {
|
||||
[pbn_oxsemi_1_15625000] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 1,
|
||||
.base_baud = 3906250,
|
||||
.base_baud = 15625000,
|
||||
.uart_offset = 0x200,
|
||||
.first_offset = 0x1000,
|
||||
},
|
||||
[pbn_oxsemi_2_3906250] = {
|
||||
[pbn_oxsemi_2_15625000] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 2,
|
||||
.base_baud = 3906250,
|
||||
.base_baud = 15625000,
|
||||
.uart_offset = 0x200,
|
||||
.first_offset = 0x1000,
|
||||
},
|
||||
[pbn_oxsemi_4_3906250] = {
|
||||
[pbn_oxsemi_4_15625000] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 4,
|
||||
.base_baud = 3906250,
|
||||
.base_baud = 15625000,
|
||||
.uart_offset = 0x200,
|
||||
.first_offset = 0x1000,
|
||||
},
|
||||
[pbn_oxsemi_8_3906250] = {
|
||||
[pbn_oxsemi_8_15625000] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 8,
|
||||
.base_baud = 3906250,
|
||||
.base_baud = 15625000,
|
||||
.uart_offset = 0x200,
|
||||
.first_offset = 0x1000,
|
||||
},
|
||||
@ -3518,6 +3695,12 @@ static struct pciserial_board pci_boards[] = {
|
||||
},
|
||||
};
|
||||
|
||||
#define REPORT_CONFIG(option) \
|
||||
(IS_ENABLED(CONFIG_##option) ? 0 : (kernel_ulong_t)&#option)
|
||||
#define REPORT_8250_CONFIG(option) \
|
||||
(IS_ENABLED(CONFIG_SERIAL_8250_##option) ? \
|
||||
0 : (kernel_ulong_t)&"SERIAL_8250_"#option)
|
||||
|
||||
static const struct pci_device_id blacklist[] = {
|
||||
/* softmodems */
|
||||
{ PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
|
||||
@ -3525,40 +3708,43 @@ static const struct pci_device_id blacklist[] = {
|
||||
{ PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
|
||||
|
||||
/* multi-io cards handled by parport_serial */
|
||||
{ PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
|
||||
{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
|
||||
{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
|
||||
/* WCH CH353 2S1P */
|
||||
{ PCI_DEVICE(0x4348, 0x7053), 0, 0, REPORT_CONFIG(PARPORT_SERIAL), },
|
||||
/* WCH CH353 1S1P */
|
||||
{ PCI_DEVICE(0x4348, 0x5053), 0, 0, REPORT_CONFIG(PARPORT_SERIAL), },
|
||||
/* WCH CH382 2S1P */
|
||||
{ PCI_DEVICE(0x1c00, 0x3250), 0, 0, REPORT_CONFIG(PARPORT_SERIAL), },
|
||||
|
||||
/* Intel platforms with MID UART */
|
||||
{ PCI_VDEVICE(INTEL, 0x081b), },
|
||||
{ PCI_VDEVICE(INTEL, 0x081c), },
|
||||
{ PCI_VDEVICE(INTEL, 0x081d), },
|
||||
{ PCI_VDEVICE(INTEL, 0x1191), },
|
||||
{ PCI_VDEVICE(INTEL, 0x18d8), },
|
||||
{ PCI_VDEVICE(INTEL, 0x19d8), },
|
||||
{ PCI_VDEVICE(INTEL, 0x081b), REPORT_8250_CONFIG(MID), },
|
||||
{ PCI_VDEVICE(INTEL, 0x081c), REPORT_8250_CONFIG(MID), },
|
||||
{ PCI_VDEVICE(INTEL, 0x081d), REPORT_8250_CONFIG(MID), },
|
||||
{ PCI_VDEVICE(INTEL, 0x1191), REPORT_8250_CONFIG(MID), },
|
||||
{ PCI_VDEVICE(INTEL, 0x18d8), REPORT_8250_CONFIG(MID), },
|
||||
{ PCI_VDEVICE(INTEL, 0x19d8), REPORT_8250_CONFIG(MID), },
|
||||
|
||||
/* Intel platforms with DesignWare UART */
|
||||
{ PCI_VDEVICE(INTEL, 0x0936), },
|
||||
{ PCI_VDEVICE(INTEL, 0x0f0a), },
|
||||
{ PCI_VDEVICE(INTEL, 0x0f0c), },
|
||||
{ PCI_VDEVICE(INTEL, 0x228a), },
|
||||
{ PCI_VDEVICE(INTEL, 0x228c), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b96), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b97), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b98), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b99), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b9a), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b9b), },
|
||||
{ PCI_VDEVICE(INTEL, 0x9ce3), },
|
||||
{ PCI_VDEVICE(INTEL, 0x9ce4), },
|
||||
{ PCI_VDEVICE(INTEL, 0x0936), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x0f0a), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x0f0c), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x228a), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x228c), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b96), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b97), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b98), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b99), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b9a), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b9b), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x9ce3), REPORT_8250_CONFIG(LPSS), },
|
||||
{ PCI_VDEVICE(INTEL, 0x9ce4), REPORT_8250_CONFIG(LPSS), },
|
||||
|
||||
/* Exar devices */
|
||||
{ PCI_VDEVICE(EXAR, PCI_ANY_ID), },
|
||||
{ PCI_VDEVICE(COMMTECH, PCI_ANY_ID), },
|
||||
{ PCI_VDEVICE(EXAR, PCI_ANY_ID), REPORT_8250_CONFIG(EXAR), },
|
||||
{ PCI_VDEVICE(COMMTECH, PCI_ANY_ID), REPORT_8250_CONFIG(EXAR), },
|
||||
|
||||
/* Pericom devices */
|
||||
{ PCI_VDEVICE(PERICOM, PCI_ANY_ID), },
|
||||
{ PCI_VDEVICE(ACCESSIO, PCI_ANY_ID), },
|
||||
{ PCI_VDEVICE(PERICOM, PCI_ANY_ID), REPORT_8250_CONFIG(PERICOM), },
|
||||
{ PCI_VDEVICE(ACCESSIO, PCI_ANY_ID), REPORT_8250_CONFIG(PERICOM), },
|
||||
|
||||
/* End of the black list */
|
||||
{ }
|
||||
@ -3840,8 +4026,12 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
|
||||
board = &pci_boards[ent->driver_data];
|
||||
|
||||
exclude = pci_match_id(blacklist, dev);
|
||||
if (exclude)
|
||||
if (exclude) {
|
||||
if (exclude->driver_data)
|
||||
pci_warn(dev, "ignoring port, enable %s to handle\n",
|
||||
(const char *)exclude->driver_data);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = pcim_enable_device(dev);
|
||||
pci_save_state(dev);
|
||||
@ -4109,13 +4299,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
|
||||
0x10b5, 0x106a, 0, 0,
|
||||
pbn_plx_romulus },
|
||||
/*
|
||||
* EndRun Technologies. PCI express device range.
|
||||
* EndRun PTP/1588 has 2 Native UARTs.
|
||||
*/
|
||||
{ PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_endrun_2_3906250 },
|
||||
/*
|
||||
* Quatech cards. These actually have configurable clocks but for
|
||||
* now we just use the default.
|
||||
@ -4225,158 +4408,165 @@ static const struct pci_device_id serial_pci_tbl[] = {
|
||||
*/
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_1_3906250 },
|
||||
pbn_b0_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_1_3906250 },
|
||||
pbn_b0_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_1_3906250 },
|
||||
pbn_b0_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_1_3906250 },
|
||||
pbn_b0_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_1_3906250 },
|
||||
pbn_b0_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_1_3906250 },
|
||||
pbn_b0_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_1_3906250 },
|
||||
pbn_b0_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_1_3906250 },
|
||||
pbn_b0_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_2_3906250 },
|
||||
pbn_oxsemi_2_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_2_3906250 },
|
||||
pbn_oxsemi_2_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_4_3906250 },
|
||||
pbn_oxsemi_4_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_4_3906250 },
|
||||
pbn_oxsemi_4_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_8_3906250 },
|
||||
pbn_oxsemi_8_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_8_3906250 },
|
||||
pbn_oxsemi_8_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
/*
|
||||
* Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
|
||||
*/
|
||||
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
|
||||
PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
|
||||
pbn_oxsemi_1_3906250 },
|
||||
pbn_oxsemi_1_15625000 },
|
||||
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
|
||||
PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
|
||||
pbn_oxsemi_2_3906250 },
|
||||
pbn_oxsemi_2_15625000 },
|
||||
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
|
||||
PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
|
||||
pbn_oxsemi_4_3906250 },
|
||||
pbn_oxsemi_4_15625000 },
|
||||
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
|
||||
PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
|
||||
pbn_oxsemi_8_3906250 },
|
||||
pbn_oxsemi_8_15625000 },
|
||||
|
||||
/*
|
||||
* Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
|
||||
*/
|
||||
{ PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
|
||||
PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_2_3906250 },
|
||||
pbn_oxsemi_2_15625000 },
|
||||
/*
|
||||
* EndRun Technologies. PCI express device range.
|
||||
* EndRun PTP/1588 has 2 Native UARTs utilizing OxSemi 952.
|
||||
*/
|
||||
{ PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_oxsemi_2_15625000 },
|
||||
|
||||
/*
|
||||
* SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
|
||||
|
@ -263,7 +263,7 @@ static const struct serial8250_config uart_config[] = {
|
||||
.tx_loadsz = 63,
|
||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
|
||||
UART_FCR7_64BYTE,
|
||||
.flags = UART_CAP_FIFO,
|
||||
.flags = UART_CAP_FIFO | UART_CAP_NOTEMT,
|
||||
},
|
||||
[PORT_RT2880] = {
|
||||
.name = "Palmchip BK-3103",
|
||||
@ -537,27 +537,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For the 16C950
|
||||
*/
|
||||
static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
|
||||
{
|
||||
serial_out(up, UART_SCR, offset);
|
||||
serial_out(up, UART_ICR, value);
|
||||
}
|
||||
|
||||
static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
|
||||
serial_out(up, UART_SCR, offset);
|
||||
value = serial_in(up, UART_ICR);
|
||||
serial_icr_write(up, UART_ACR, up->acr);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIFO support.
|
||||
*/
|
||||
@ -1504,18 +1483,19 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
|
||||
hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
static void __stop_tx_rs485(struct uart_8250_port *p)
|
||||
static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay)
|
||||
{
|
||||
struct uart_8250_em485 *em485 = p->em485;
|
||||
|
||||
stop_delay += (u64)p->port.rs485.delay_rts_after_send * NSEC_PER_MSEC;
|
||||
|
||||
/*
|
||||
* rs485_stop_tx() is going to set RTS according to config
|
||||
* AND flush RX FIFO if required.
|
||||
*/
|
||||
if (p->port.rs485.delay_rts_after_send > 0) {
|
||||
if (stop_delay > 0) {
|
||||
em485->active_timer = &em485->stop_tx_timer;
|
||||
start_hrtimer_ms(&em485->stop_tx_timer,
|
||||
p->port.rs485.delay_rts_after_send);
|
||||
hrtimer_start(&em485->stop_tx_timer, ns_to_ktime(stop_delay), HRTIMER_MODE_REL);
|
||||
} else {
|
||||
p->rs485_stop_tx(p);
|
||||
em485->active_timer = NULL;
|
||||
@ -1535,16 +1515,32 @@ static inline void __stop_tx(struct uart_8250_port *p)
|
||||
|
||||
if (em485) {
|
||||
unsigned char lsr = serial_in(p, UART_LSR);
|
||||
u64 stop_delay = 0;
|
||||
|
||||
if (!(lsr & UART_LSR_THRE))
|
||||
return;
|
||||
/*
|
||||
* To provide required timeing and allow FIFO transfer,
|
||||
* __stop_tx_rs485() must be called only when both FIFO and
|
||||
* shift register are empty. It is for device driver to enable
|
||||
* interrupt on TEMT.
|
||||
* shift register are empty. The device driver should either
|
||||
* enable interrupt on TEMT or set UART_CAP_NOTEMT that will
|
||||
* enlarge stop_tx_timer by the tx time of one frame to cover
|
||||
* for emptying of the shift register.
|
||||
*/
|
||||
if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
|
||||
return;
|
||||
if (!(lsr & UART_LSR_TEMT)) {
|
||||
if (!(p->capabilities & UART_CAP_NOTEMT))
|
||||
return;
|
||||
/*
|
||||
* RTS might get deasserted too early with the normal
|
||||
* frame timing formula. It seems to suggest THRE might
|
||||
* get asserted already during tx of the stop bit
|
||||
* rather than after it is fully sent.
|
||||
* Roughly estimate 1 extra bit here with / 7.
|
||||
*/
|
||||
stop_delay = p->port.frame_time + DIV_ROUND_UP(p->port.frame_time, 7);
|
||||
}
|
||||
|
||||
__stop_tx_rs485(p);
|
||||
__stop_tx_rs485(p, stop_delay);
|
||||
}
|
||||
__do_stop_tx(p);
|
||||
}
|
||||
@ -1948,9 +1944,12 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
|
||||
status = serial8250_rx_chars(up, status);
|
||||
}
|
||||
serial8250_modem_status(up);
|
||||
if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) &&
|
||||
(up->ier & UART_IER_THRI))
|
||||
serial8250_tx_chars(up);
|
||||
if ((status & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) {
|
||||
if (!up->dma || up->dma->tx_err)
|
||||
serial8250_tx_chars(up);
|
||||
else
|
||||
__stop_tx(up);
|
||||
}
|
||||
|
||||
uart_unlock_and_check_sysrq_irqrestore(port, flags);
|
||||
|
||||
@ -2077,10 +2076,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
|
||||
serial8250_rpm_put(up);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for transmitter & holding register to empty
|
||||
*/
|
||||
static void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
||||
static void wait_for_lsr(struct uart_8250_port *up, int bits)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
@ -2097,6 +2093,16 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
||||
udelay(1);
|
||||
touch_nmi_watchdog();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for transmitter & holding register to empty
|
||||
*/
|
||||
static void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
||||
{
|
||||
unsigned int tmout;
|
||||
|
||||
wait_for_lsr(up, bits);
|
||||
|
||||
/* Wait up to 1s for flow control if necessary */
|
||||
if (up->port.flags & UPF_CONS_FLOW) {
|
||||
@ -2614,10 +2620,8 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
|
||||
}
|
||||
if (!(c_cflag & PARODD))
|
||||
cval |= UART_LCR_EPAR;
|
||||
#ifdef CMSPAR
|
||||
if (c_cflag & CMSPAR)
|
||||
cval |= UART_LCR_SPAR;
|
||||
#endif
|
||||
|
||||
return cval;
|
||||
}
|
||||
@ -3332,6 +3336,35 @@ static void serial8250_console_restore(struct uart_8250_port *up)
|
||||
serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a string to the serial port using the device FIFO
|
||||
*
|
||||
* It sends fifosize bytes and then waits for the fifo
|
||||
* to get empty.
|
||||
*/
|
||||
static void serial8250_console_fifo_write(struct uart_8250_port *up,
|
||||
const char *s, unsigned int count)
|
||||
{
|
||||
int i;
|
||||
const char *end = s + count;
|
||||
unsigned int fifosize = up->tx_loadsz;
|
||||
bool cr_sent = false;
|
||||
|
||||
while (s != end) {
|
||||
wait_for_lsr(up, UART_LSR_THRE);
|
||||
|
||||
for (i = 0; i < fifosize && s != end; ++i) {
|
||||
if (*s == '\n' && !cr_sent) {
|
||||
serial_out(up, UART_TX, '\r');
|
||||
cr_sent = true;
|
||||
} else {
|
||||
serial_out(up, UART_TX, *s++);
|
||||
cr_sent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a string to the serial port trying not to disturb
|
||||
* any possible real use of the port...
|
||||
@ -3347,7 +3380,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
|
||||
struct uart_8250_em485 *em485 = up->em485;
|
||||
struct uart_port *port = &up->port;
|
||||
unsigned long flags;
|
||||
unsigned int ier;
|
||||
unsigned int ier, use_fifo;
|
||||
int locked = 1;
|
||||
|
||||
touch_nmi_watchdog();
|
||||
@ -3379,7 +3412,30 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
|
||||
mdelay(port->rs485.delay_rts_before_send);
|
||||
}
|
||||
|
||||
uart_console_write(port, s, count, serial8250_console_putchar);
|
||||
use_fifo = (up->capabilities & UART_CAP_FIFO) &&
|
||||
/*
|
||||
* BCM283x requires to check the fifo
|
||||
* after each byte.
|
||||
*/
|
||||
!(up->capabilities & UART_CAP_MINI) &&
|
||||
/*
|
||||
* tx_loadsz contains the transmit fifo size
|
||||
*/
|
||||
up->tx_loadsz > 1 &&
|
||||
(up->fcr & UART_FCR_ENABLE_FIFO) &&
|
||||
port->state &&
|
||||
test_bit(TTY_PORT_INITIALIZED, &port->state->port.iflags) &&
|
||||
/*
|
||||
* After we put a data in the fifo, the controller will send
|
||||
* it regardless of the CTS state. Therefore, only use fifo
|
||||
* if we don't use control flow.
|
||||
*/
|
||||
!(up->port.flags & UPF_CONS_FLOW);
|
||||
|
||||
if (likely(use_fifo))
|
||||
serial8250_console_fifo_write(up, s, count);
|
||||
else
|
||||
uart_console_write(port, s, count, serial8250_console_putchar);
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
|
@ -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 && ARCH_RENESAS) || COMPILE_TEST
|
||||
depends on 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.
|
||||
|
@ -782,7 +782,7 @@ config SERIAL_PMACZILOG_CONSOLE
|
||||
|
||||
config SERIAL_CPM
|
||||
tristate "CPM SCC/SMC serial port support"
|
||||
depends on CPM2 || CPM1
|
||||
depends on CPM2 || CPM1 || (PPC32 && COMPILE_TEST)
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver supports the SCC and SMC serial ports on Motorola
|
||||
@ -806,7 +806,7 @@ config SERIAL_CPM_CONSOLE
|
||||
|
||||
config SERIAL_PIC32
|
||||
tristate "Microchip PIC32 serial support"
|
||||
depends on MACH_PIC32
|
||||
depends on MACH_PIC32 || (MIPS && COMPILE_TEST)
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a PIC32, this driver supports the serial ports.
|
||||
@ -817,7 +817,7 @@ config SERIAL_PIC32
|
||||
|
||||
config SERIAL_PIC32_CONSOLE
|
||||
bool "PIC32 serial console support"
|
||||
depends on SERIAL_PIC32
|
||||
depends on SERIAL_PIC32=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you have a PIC32, this driver supports the putting a console on one
|
||||
@ -1246,7 +1246,7 @@ config SERIAL_XILINX_PS_UART_CONSOLE
|
||||
|
||||
config SERIAL_AR933X
|
||||
tristate "AR933X serial port support"
|
||||
depends on HAVE_CLK && ATH79
|
||||
depends on (HAVE_CLK && ATH79) || (MIPS && COMPILE_TEST)
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
help
|
||||
@ -1442,6 +1442,7 @@ config SERIAL_STM32_CONSOLE
|
||||
bool "Support for console on STM32"
|
||||
depends on SERIAL_STM32=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_EARLYCON
|
||||
|
||||
config SERIAL_MVEBU_UART
|
||||
bool "Marvell EBU serial port support"
|
||||
|
@ -168,10 +168,8 @@ static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
|
||||
}
|
||||
}
|
||||
|
||||
if (pending == 0) {
|
||||
pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
|
||||
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
||||
}
|
||||
if (pending == 0)
|
||||
altera_jtaguart_stop_tx(port);
|
||||
}
|
||||
|
||||
static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
|
||||
|
@ -42,8 +42,6 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include "amba-pl011.h"
|
||||
|
||||
#define UART_NR 14
|
||||
|
||||
#define SERIAL_AMBA_MAJOR 204
|
||||
@ -55,6 +53,36 @@
|
||||
#define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
|
||||
#define UART_DUMMY_DR_RX (1 << 16)
|
||||
|
||||
enum {
|
||||
REG_DR,
|
||||
REG_ST_DMAWM,
|
||||
REG_ST_TIMEOUT,
|
||||
REG_FR,
|
||||
REG_LCRH_RX,
|
||||
REG_LCRH_TX,
|
||||
REG_IBRD,
|
||||
REG_FBRD,
|
||||
REG_CR,
|
||||
REG_IFLS,
|
||||
REG_IMSC,
|
||||
REG_RIS,
|
||||
REG_MIS,
|
||||
REG_ICR,
|
||||
REG_DMACR,
|
||||
REG_ST_XFCR,
|
||||
REG_ST_XON1,
|
||||
REG_ST_XON2,
|
||||
REG_ST_XOFF1,
|
||||
REG_ST_XOFF2,
|
||||
REG_ST_ITCR,
|
||||
REG_ST_ITIP,
|
||||
REG_ST_ABCR,
|
||||
REG_ST_ABIMSC,
|
||||
|
||||
/* The size of the array - must be last */
|
||||
REG_ARRAY_SIZE,
|
||||
};
|
||||
|
||||
static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
|
||||
[REG_DR] = UART01x_DR,
|
||||
[REG_FR] = UART01x_FR,
|
||||
@ -2175,25 +2203,11 @@ static int pl011_rs485_config(struct uart_port *port,
|
||||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
|
||||
/* pick sane settings if the user hasn't */
|
||||
if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
|
||||
!(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
|
||||
rs485->flags |= SER_RS485_RTS_ON_SEND;
|
||||
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
/* clamp the delays to [0, 100ms] */
|
||||
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
|
||||
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
|
||||
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||
|
||||
if (port->rs485.flags & SER_RS485_ENABLED)
|
||||
pl011_rs485_tx_stop(uap);
|
||||
|
||||
/* Set new configuration */
|
||||
port->rs485 = *rs485;
|
||||
|
||||
/* Make sure auto RTS is disabled */
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
if (rs485->flags & SER_RS485_ENABLED) {
|
||||
u32 cr = pl011_read(uap, REG_CR);
|
||||
|
||||
cr &= ~UART011_CR_RTSEN;
|
||||
|
@ -1,35 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef AMBA_PL011_H
|
||||
#define AMBA_PL011_H
|
||||
|
||||
enum {
|
||||
REG_DR,
|
||||
REG_ST_DMAWM,
|
||||
REG_ST_TIMEOUT,
|
||||
REG_FR,
|
||||
REG_LCRH_RX,
|
||||
REG_LCRH_TX,
|
||||
REG_IBRD,
|
||||
REG_FBRD,
|
||||
REG_CR,
|
||||
REG_IFLS,
|
||||
REG_IMSC,
|
||||
REG_RIS,
|
||||
REG_MIS,
|
||||
REG_ICR,
|
||||
REG_DMACR,
|
||||
REG_ST_XFCR,
|
||||
REG_ST_XON1,
|
||||
REG_ST_XON2,
|
||||
REG_ST_XOFF1,
|
||||
REG_ST_XOFF2,
|
||||
REG_ST_ITCR,
|
||||
REG_ST_ITIP,
|
||||
REG_ST_ABCR,
|
||||
REG_ST_ABIMSC,
|
||||
|
||||
/* The size of the array - must be last */
|
||||
REG_ARRAY_SIZE,
|
||||
};
|
||||
|
||||
#endif
|
@ -299,11 +299,9 @@ static int atmel_config_rs485(struct uart_port *port,
|
||||
/* Resetting serial mode to RS232 (0x0) */
|
||||
mode &= ~ATMEL_US_USMODE;
|
||||
|
||||
port->rs485 = *rs485conf;
|
||||
|
||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||
dev_dbg(port->dev, "Setting UART to RS485\n");
|
||||
if (port->rs485.flags & SER_RS485_RX_DURING_TX)
|
||||
if (rs485conf->flags & SER_RS485_RX_DURING_TX)
|
||||
atmel_port->tx_done_mask = ATMEL_US_TXRDY;
|
||||
else
|
||||
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
|
||||
|
@ -19,6 +19,8 @@ struct gpio_desc;
|
||||
#include "cpm_uart_cpm2.h"
|
||||
#elif defined(CONFIG_CPM1)
|
||||
#include "cpm_uart_cpm1.h"
|
||||
#elif defined(CONFIG_COMPILE_TEST)
|
||||
#include "cpm_uart_cpm2.h"
|
||||
#endif
|
||||
|
||||
#define SERIAL_CPM_MAJOR 204
|
||||
|
@ -1247,7 +1247,7 @@ static int cpm_uart_init_port(struct device_node *np,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_CPM_CONSOLE)
|
||||
if (!udbg_port)
|
||||
#endif
|
||||
udbg_putc = NULL;
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/fs_pd.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -309,6 +309,8 @@ static void digicolor_uart_set_termios(struct uart_port *port,
|
||||
case CS8:
|
||||
default:
|
||||
config |= UA_CONFIG_CHAR_LEN;
|
||||
termios->c_cflag &= ~CSIZE;
|
||||
termios->c_cflag |= CS8;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -239,8 +239,6 @@
|
||||
/* IMX lpuart has four extra unused regs located at the beginning */
|
||||
#define IMX_REG_OFF 0x10
|
||||
|
||||
static DEFINE_IDA(fsl_lpuart_ida);
|
||||
|
||||
enum lpuart_type {
|
||||
VF610_LPUART,
|
||||
LS1021A_LPUART,
|
||||
@ -276,7 +274,6 @@ struct lpuart_port {
|
||||
int rx_dma_rng_buf_len;
|
||||
unsigned int dma_tx_nents;
|
||||
wait_queue_head_t dma_wait;
|
||||
bool id_allocated;
|
||||
};
|
||||
|
||||
struct lpuart_soc_data {
|
||||
@ -1118,7 +1115,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
|
||||
struct dma_chan *chan = sport->dma_rx_chan;
|
||||
struct circ_buf *ring = &sport->rx_ring;
|
||||
unsigned long flags;
|
||||
int count = 0, copied;
|
||||
int count, copied;
|
||||
|
||||
if (lpuart_is_32(sport)) {
|
||||
unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
|
||||
@ -1377,19 +1374,6 @@ static int lpuart_config_rs485(struct uart_port *port,
|
||||
/* Enable auto RS-485 RTS mode */
|
||||
modem |= UARTMODEM_TXRTSE;
|
||||
|
||||
/*
|
||||
* RTS needs to be logic HIGH either during transfer _or_ after
|
||||
* transfer, other variants are not supported by the hardware.
|
||||
*/
|
||||
|
||||
if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
|
||||
SER_RS485_RTS_AFTER_SEND)))
|
||||
rs485->flags |= SER_RS485_RTS_ON_SEND;
|
||||
|
||||
if (rs485->flags & SER_RS485_RTS_ON_SEND &&
|
||||
rs485->flags & SER_RS485_RTS_AFTER_SEND)
|
||||
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
|
||||
/*
|
||||
* The hardware defaults to RTS logic HIGH while transfer.
|
||||
* Switch polarity in case RTS shall be logic HIGH
|
||||
@ -1402,9 +1386,6 @@ static int lpuart_config_rs485(struct uart_port *port,
|
||||
modem |= UARTMODEM_TXRTSPOL;
|
||||
}
|
||||
|
||||
/* Store the new configuration */
|
||||
sport->port.rs485 = *rs485;
|
||||
|
||||
writeb(modem, sport->port.membase + UARTMODEM);
|
||||
return 0;
|
||||
}
|
||||
@ -1428,19 +1409,6 @@ static int lpuart32_config_rs485(struct uart_port *port,
|
||||
/* Enable auto RS-485 RTS mode */
|
||||
modem |= UARTMODEM_TXRTSE;
|
||||
|
||||
/*
|
||||
* RTS needs to be logic HIGH either during transfer _or_ after
|
||||
* transfer, other variants are not supported by the hardware.
|
||||
*/
|
||||
|
||||
if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
|
||||
SER_RS485_RTS_AFTER_SEND)))
|
||||
rs485->flags |= SER_RS485_RTS_ON_SEND;
|
||||
|
||||
if (rs485->flags & SER_RS485_RTS_ON_SEND &&
|
||||
rs485->flags & SER_RS485_RTS_AFTER_SEND)
|
||||
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
|
||||
/*
|
||||
* The hardware defaults to RTS logic HIGH while transfer.
|
||||
* Switch polarity in case RTS shall be logic HIGH
|
||||
@ -1453,9 +1421,6 @@ static int lpuart32_config_rs485(struct uart_port *port,
|
||||
modem |= UARTMODEM_TXRTSPOL;
|
||||
}
|
||||
|
||||
/* Store the new configuration */
|
||||
sport->port.rs485 = *rs485;
|
||||
|
||||
lpuart32_write(&sport->port, modem, UARTMODIR);
|
||||
return 0;
|
||||
}
|
||||
@ -2145,12 +2110,10 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
if (sport->port.rs485.flags & SER_RS485_ENABLED)
|
||||
termios->c_cflag &= ~CRTSCTS;
|
||||
|
||||
if (termios->c_cflag & CRTSCTS) {
|
||||
modem |= (UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
||||
} else {
|
||||
termios->c_cflag &= ~CRTSCTS;
|
||||
if (termios->c_cflag & CRTSCTS)
|
||||
modem |= UARTMODIR_RXRTSE | UARTMODIR_TXCTSE;
|
||||
else
|
||||
modem &= ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
||||
}
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
bd |= UARTBAUD_SBNS;
|
||||
@ -2717,23 +2680,18 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||
|
||||
ret = of_alias_get_id(np, "serial");
|
||||
if (ret < 0) {
|
||||
ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "port line is full, add device failed\n");
|
||||
return ret;
|
||||
}
|
||||
sport->id_allocated = true;
|
||||
dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret >= ARRAY_SIZE(lpuart_ports)) {
|
||||
dev_err(&pdev->dev, "serial%d out of range\n", ret);
|
||||
ret = -EINVAL;
|
||||
goto failed_out_of_range;
|
||||
return -EINVAL;
|
||||
}
|
||||
sport->port.line = ret;
|
||||
|
||||
ret = lpuart_enable_clks(sport);
|
||||
if (ret)
|
||||
goto failed_clock_enable;
|
||||
return ret;
|
||||
sport->port.uartclk = lpuart_get_baud_clk_rate(sport);
|
||||
|
||||
lpuart_ports[sport->port.line] = sport;
|
||||
@ -2781,10 +2739,6 @@ failed_reset:
|
||||
uart_remove_one_port(&lpuart_reg, &sport->port);
|
||||
failed_attach_port:
|
||||
lpuart_disable_clks(sport);
|
||||
failed_clock_enable:
|
||||
failed_out_of_range:
|
||||
if (sport->id_allocated)
|
||||
ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2794,9 +2748,6 @@ static int lpuart_remove(struct platform_device *pdev)
|
||||
|
||||
uart_remove_one_port(&lpuart_reg, &sport->port);
|
||||
|
||||
if (sport->id_allocated)
|
||||
ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
|
||||
|
||||
lpuart_disable_clks(sport);
|
||||
|
||||
if (sport->dma_tx_chan)
|
||||
@ -2926,7 +2877,6 @@ static int __init lpuart_serial_init(void)
|
||||
|
||||
static void __exit lpuart_serial_exit(void)
|
||||
{
|
||||
ida_destroy(&fsl_lpuart_ida);
|
||||
platform_driver_unregister(&lpuart_driver);
|
||||
uart_unregister_driver(&lpuart_reg);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/string.h>
|
||||
@ -41,15 +42,273 @@
|
||||
#include <asm/irq.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "icom.h"
|
||||
|
||||
/*#define ICOM_TRACE enable port trace capabilities */
|
||||
|
||||
#define ICOM_DRIVER_NAME "icom"
|
||||
#define ICOM_VERSION_STR "1.3.1"
|
||||
#define NR_PORTS 128
|
||||
#define ICOM_PORT ((struct icom_port *)port)
|
||||
#define to_icom_adapter(d) container_of(d, struct icom_adapter, kref)
|
||||
|
||||
static const unsigned int icom_acfg_baud[] = {
|
||||
300,
|
||||
600,
|
||||
900,
|
||||
1200,
|
||||
1800,
|
||||
2400,
|
||||
3600,
|
||||
4800,
|
||||
7200,
|
||||
9600,
|
||||
14400,
|
||||
19200,
|
||||
28800,
|
||||
38400,
|
||||
57600,
|
||||
76800,
|
||||
115200,
|
||||
153600,
|
||||
230400,
|
||||
307200,
|
||||
460800,
|
||||
};
|
||||
#define BAUD_TABLE_LIMIT (ARRAY_SIZE(icom_acfg_baud) - 1)
|
||||
|
||||
struct icom_regs {
|
||||
u32 control; /* Adapter Control Register */
|
||||
u32 interrupt; /* Adapter Interrupt Register */
|
||||
u32 int_mask; /* Adapter Interrupt Mask Reg */
|
||||
u32 int_pri; /* Adapter Interrupt Priority r */
|
||||
u32 int_reg_b; /* Adapter non-masked Interrupt */
|
||||
u32 resvd01;
|
||||
u32 resvd02;
|
||||
u32 resvd03;
|
||||
u32 control_2; /* Adapter Control Register 2 */
|
||||
u32 interrupt_2; /* Adapter Interrupt Register 2 */
|
||||
u32 int_mask_2; /* Adapter Interrupt Mask 2 */
|
||||
u32 int_pri_2; /* Adapter Interrupt Prior 2 */
|
||||
u32 int_reg_2b; /* Adapter non-masked 2 */
|
||||
};
|
||||
|
||||
struct func_dram {
|
||||
u32 reserved[108]; /* 0-1B0 reserved by personality code */
|
||||
u32 RcvStatusAddr; /* 1B0-1B3 Status Address for Next rcv */
|
||||
u8 RcvStnAddr; /* 1B4 Receive Station Addr */
|
||||
u8 IdleState; /* 1B5 Idle State */
|
||||
u8 IdleMonitor; /* 1B6 Idle Monitor */
|
||||
u8 FlagFillIdleTimer; /* 1B7 Flag Fill Idle Timer */
|
||||
u32 XmitStatusAddr; /* 1B8-1BB Transmit Status Address */
|
||||
u8 StartXmitCmd; /* 1BC Start Xmit Command */
|
||||
u8 HDLCConfigReg; /* 1BD Reserved */
|
||||
u8 CauseCode; /* 1BE Cause code for fatal error */
|
||||
u8 xchar; /* 1BF High priority send */
|
||||
u32 reserved3; /* 1C0-1C3 Reserved */
|
||||
u8 PrevCmdReg; /* 1C4 Reserved */
|
||||
u8 CmdReg; /* 1C5 Command Register */
|
||||
u8 async_config2; /* 1C6 Async Config Byte 2 */
|
||||
u8 async_config3; /* 1C7 Async Config Byte 3 */
|
||||
u8 dce_resvd[20]; /* 1C8-1DB DCE Rsvd */
|
||||
u8 dce_resvd21; /* 1DC DCE Rsvd (21st byte */
|
||||
u8 misc_flags; /* 1DD misc flags */
|
||||
#define V2_HARDWARE 0x40
|
||||
#define ICOM_HDW_ACTIVE 0x01
|
||||
u8 call_length; /* 1DE Phone #/CFI buff ln */
|
||||
u8 call_length2; /* 1DF Upper byte (unused) */
|
||||
u32 call_addr; /* 1E0-1E3 Phn #/CFI buff addr */
|
||||
u16 timer_value; /* 1E4-1E5 general timer value */
|
||||
u8 timer_command; /* 1E6 general timer cmd */
|
||||
u8 dce_command; /* 1E7 dce command reg */
|
||||
u8 dce_cmd_status; /* 1E8 dce command stat */
|
||||
u8 x21_r1_ioff; /* 1E9 dce ready counter */
|
||||
u8 x21_r0_ioff; /* 1EA dce not ready ctr */
|
||||
u8 x21_ralt_ioff; /* 1EB dce CNR counter */
|
||||
u8 x21_r1_ion; /* 1EC dce ready I on ctr */
|
||||
u8 rsvd_ier; /* 1ED Rsvd for IER (if ne */
|
||||
u8 ier; /* 1EE Interrupt Enable */
|
||||
u8 isr; /* 1EF Input Signal Reg */
|
||||
u8 osr; /* 1F0 Output Signal Reg */
|
||||
u8 reset; /* 1F1 Reset/Reload Reg */
|
||||
u8 disable; /* 1F2 Disable Reg */
|
||||
u8 sync; /* 1F3 Sync Reg */
|
||||
u8 error_stat; /* 1F4 Error Status */
|
||||
u8 cable_id; /* 1F5 Cable ID */
|
||||
u8 cs_length; /* 1F6 CS Load Length */
|
||||
u8 mac_length; /* 1F7 Mac Load Length */
|
||||
u32 cs_load_addr; /* 1F8-1FB Call Load PCI Addr */
|
||||
u32 mac_load_addr; /* 1FC-1FF Mac Load PCI Addr */
|
||||
};
|
||||
|
||||
/*
|
||||
* adapter defines and structures
|
||||
*/
|
||||
#define ICOM_CONTROL_START_A 0x00000008
|
||||
#define ICOM_CONTROL_STOP_A 0x00000004
|
||||
#define ICOM_CONTROL_START_B 0x00000002
|
||||
#define ICOM_CONTROL_STOP_B 0x00000001
|
||||
#define ICOM_CONTROL_START_C 0x00000008
|
||||
#define ICOM_CONTROL_STOP_C 0x00000004
|
||||
#define ICOM_CONTROL_START_D 0x00000002
|
||||
#define ICOM_CONTROL_STOP_D 0x00000001
|
||||
#define ICOM_IRAM_OFFSET 0x1000
|
||||
#define ICOM_IRAM_SIZE 0x0C00
|
||||
#define ICOM_DCE_IRAM_OFFSET 0x0A00
|
||||
#define ICOM_CABLE_ID_VALID 0x01
|
||||
#define ICOM_CABLE_ID_MASK 0xF0
|
||||
#define ICOM_DISABLE 0x80
|
||||
#define CMD_XMIT_RCV_ENABLE 0xC0
|
||||
#define CMD_XMIT_ENABLE 0x40
|
||||
#define CMD_RCV_DISABLE 0x00
|
||||
#define CMD_RCV_ENABLE 0x80
|
||||
#define CMD_RESTART 0x01
|
||||
#define CMD_HOLD_XMIT 0x02
|
||||
#define CMD_SND_BREAK 0x04
|
||||
#define RS232_CABLE 0x06
|
||||
#define V24_CABLE 0x0E
|
||||
#define V35_CABLE 0x0C
|
||||
#define V36_CABLE 0x02
|
||||
#define NO_CABLE 0x00
|
||||
#define START_DOWNLOAD 0x80
|
||||
#define ICOM_INT_MASK_PRC_A 0x00003FFF
|
||||
#define ICOM_INT_MASK_PRC_B 0x3FFF0000
|
||||
#define ICOM_INT_MASK_PRC_C 0x00003FFF
|
||||
#define ICOM_INT_MASK_PRC_D 0x3FFF0000
|
||||
#define INT_RCV_COMPLETED 0x1000
|
||||
#define INT_XMIT_COMPLETED 0x2000
|
||||
#define INT_IDLE_DETECT 0x0800
|
||||
#define INT_RCV_DISABLED 0x0400
|
||||
#define INT_XMIT_DISABLED 0x0200
|
||||
#define INT_RCV_XMIT_SHUTDOWN 0x0100
|
||||
#define INT_FATAL_ERROR 0x0080
|
||||
#define INT_CABLE_PULL 0x0020
|
||||
#define INT_SIGNAL_CHANGE 0x0010
|
||||
#define HDLC_PPP_PURE_ASYNC 0x02
|
||||
#define HDLC_FF_FILL 0x00
|
||||
#define HDLC_HDW_FLOW 0x01
|
||||
#define START_XMIT 0x80
|
||||
#define ICOM_ACFG_DRIVE1 0x20
|
||||
#define ICOM_ACFG_NO_PARITY 0x00
|
||||
#define ICOM_ACFG_PARITY_ENAB 0x02
|
||||
#define ICOM_ACFG_PARITY_ODD 0x01
|
||||
#define ICOM_ACFG_8BPC 0x00
|
||||
#define ICOM_ACFG_7BPC 0x04
|
||||
#define ICOM_ACFG_6BPC 0x08
|
||||
#define ICOM_ACFG_5BPC 0x0C
|
||||
#define ICOM_ACFG_1STOP_BIT 0x00
|
||||
#define ICOM_ACFG_2STOP_BIT 0x10
|
||||
#define ICOM_DTR 0x80
|
||||
#define ICOM_RTS 0x40
|
||||
#define ICOM_RI 0x08
|
||||
#define ICOM_DSR 0x80
|
||||
#define ICOM_DCD 0x20
|
||||
#define ICOM_CTS 0x40
|
||||
|
||||
#define NUM_XBUFFS 1
|
||||
#define NUM_RBUFFS 2
|
||||
#define RCV_BUFF_SZ 0x0200
|
||||
#define XMIT_BUFF_SZ 0x1000
|
||||
struct statusArea {
|
||||
/**********************************************/
|
||||
/* Transmit Status Area */
|
||||
/**********************************************/
|
||||
struct xmit_status_area{
|
||||
__le32 leNext; /* Next entry in Little Endian on Adapter */
|
||||
__le32 leNextASD;
|
||||
__le32 leBuffer; /* Buffer for entry in LE for Adapter */
|
||||
__le16 leLengthASD;
|
||||
__le16 leOffsetASD;
|
||||
__le16 leLength; /* Length of data in segment */
|
||||
__le16 flags;
|
||||
#define SA_FLAGS_DONE 0x0080 /* Done with Segment */
|
||||
#define SA_FLAGS_CONTINUED 0x8000 /* More Segments */
|
||||
#define SA_FLAGS_IDLE 0x4000 /* Mark IDLE after frm */
|
||||
#define SA_FLAGS_READY_TO_XMIT 0x0800
|
||||
#define SA_FLAGS_STAT_MASK 0x007F
|
||||
} xmit[NUM_XBUFFS];
|
||||
|
||||
/**********************************************/
|
||||
/* Receive Status Area */
|
||||
/**********************************************/
|
||||
struct {
|
||||
__le32 leNext; /* Next entry in Little Endian on Adapter */
|
||||
__le32 leNextASD;
|
||||
__le32 leBuffer; /* Buffer for entry in LE for Adapter */
|
||||
__le16 WorkingLength; /* size of segment */
|
||||
__le16 reserv01;
|
||||
__le16 leLength; /* Length of data in segment */
|
||||
__le16 flags;
|
||||
#define SA_FL_RCV_DONE 0x0010 /* Data ready */
|
||||
#define SA_FLAGS_OVERRUN 0x0040
|
||||
#define SA_FLAGS_PARITY_ERROR 0x0080
|
||||
#define SA_FLAGS_FRAME_ERROR 0x0001
|
||||
#define SA_FLAGS_FRAME_TRUNC 0x0002
|
||||
#define SA_FLAGS_BREAK_DET 0x0004 /* set conditionally by device driver, not hardware */
|
||||
#define SA_FLAGS_RCV_MASK 0xFFE6
|
||||
} rcv[NUM_RBUFFS];
|
||||
};
|
||||
|
||||
struct icom_adapter;
|
||||
|
||||
|
||||
#define ICOM_MAJOR 243
|
||||
#define ICOM_MINOR_START 0
|
||||
|
||||
struct icom_port {
|
||||
struct uart_port uart_port;
|
||||
unsigned char cable_id;
|
||||
unsigned char read_status_mask;
|
||||
unsigned char ignore_status_mask;
|
||||
void __iomem * int_reg;
|
||||
struct icom_regs __iomem *global_reg;
|
||||
struct func_dram __iomem *dram;
|
||||
int port;
|
||||
struct statusArea *statStg;
|
||||
dma_addr_t statStg_pci;
|
||||
__le32 *xmitRestart;
|
||||
dma_addr_t xmitRestart_pci;
|
||||
unsigned char *xmit_buf;
|
||||
dma_addr_t xmit_buf_pci;
|
||||
unsigned char *recv_buf;
|
||||
dma_addr_t recv_buf_pci;
|
||||
int next_rcv;
|
||||
int status;
|
||||
#define ICOM_PORT_ACTIVE 1 /* Port exists. */
|
||||
#define ICOM_PORT_OFF 0 /* Port does not exist. */
|
||||
struct icom_adapter *adapter;
|
||||
};
|
||||
|
||||
struct icom_adapter {
|
||||
void __iomem * base_addr;
|
||||
unsigned long base_addr_pci;
|
||||
struct pci_dev *pci_dev;
|
||||
struct icom_port port_info[4];
|
||||
int index;
|
||||
int version;
|
||||
#define ADAPTER_V1 0x0001
|
||||
#define ADAPTER_V2 0x0002
|
||||
u32 subsystem_id;
|
||||
#define FOUR_PORT_MODEL 0x0252
|
||||
#define V2_TWO_PORTS_RVX 0x021A
|
||||
#define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM 0x0251
|
||||
int numb_ports;
|
||||
struct list_head icom_adapter_entry;
|
||||
struct kref kref;
|
||||
};
|
||||
|
||||
/* prototype */
|
||||
extern void iCom_sercons_init(void);
|
||||
|
||||
struct lookup_proc_table {
|
||||
u32 __iomem *global_control_reg;
|
||||
unsigned long processor_id;
|
||||
};
|
||||
|
||||
struct lookup_int_table {
|
||||
u32 __iomem *global_int_mask;
|
||||
unsigned long processor_id;
|
||||
};
|
||||
|
||||
static inline struct icom_port *to_icom_port(struct uart_port *port)
|
||||
{
|
||||
return container_of(port, struct icom_port, uart_port);
|
||||
}
|
||||
|
||||
static const struct pci_device_id icom_pci_table[] = {
|
||||
{
|
||||
@ -222,7 +481,7 @@ static int get_port_memory(struct icom_port *icom_port)
|
||||
if (index < (NUM_XBUFFS - 1)) {
|
||||
memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
|
||||
icom_port->statStg->xmit[index].leLengthASD =
|
||||
(unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
|
||||
cpu_to_le16(XMIT_BUFF_SZ);
|
||||
trace(icom_port, "FOD_ADDR", stgAddr);
|
||||
trace(icom_port, "FOD_XBUFF",
|
||||
(unsigned long) icom_port->xmit_buf);
|
||||
@ -231,7 +490,7 @@ static int get_port_memory(struct icom_port *icom_port)
|
||||
} else if (index == (NUM_XBUFFS - 1)) {
|
||||
memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
|
||||
icom_port->statStg->xmit[index].leLengthASD =
|
||||
(unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
|
||||
cpu_to_le16(XMIT_BUFF_SZ);
|
||||
trace(icom_port, "FOD_XBUFF",
|
||||
(unsigned long) icom_port->xmit_buf);
|
||||
icom_port->statStg->xmit[index].leBuffer =
|
||||
@ -249,7 +508,7 @@ static int get_port_memory(struct icom_port *icom_port)
|
||||
stgAddr = stgAddr + sizeof(icom_port->statStg->rcv[0]);
|
||||
icom_port->statStg->rcv[index].leLength = 0;
|
||||
icom_port->statStg->rcv[index].WorkingLength =
|
||||
(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
|
||||
cpu_to_le16(RCV_BUFF_SZ);
|
||||
if (index < (NUM_RBUFFS - 1) ) {
|
||||
offset = stgAddr - (unsigned long) icom_port->statStg;
|
||||
icom_port->statStg->rcv[index].leNext =
|
||||
@ -617,16 +876,17 @@ unlock:
|
||||
|
||||
static int icom_write(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned long data_count;
|
||||
unsigned char cmdReg;
|
||||
unsigned long offset;
|
||||
int temp_tail = port->state->xmit.tail;
|
||||
|
||||
trace(ICOM_PORT, "WRITE", 0);
|
||||
trace(icom_port, "WRITE", 0);
|
||||
|
||||
if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
|
||||
if (le16_to_cpu(icom_port->statStg->xmit[0].flags) &
|
||||
SA_FLAGS_READY_TO_XMIT) {
|
||||
trace(ICOM_PORT, "WRITE_FULL", 0);
|
||||
trace(icom_port, "WRITE_FULL", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -634,7 +894,7 @@ static int icom_write(struct uart_port *port)
|
||||
while ((port->state->xmit.head != temp_tail) &&
|
||||
(data_count <= XMIT_BUFF_SZ)) {
|
||||
|
||||
ICOM_PORT->xmit_buf[data_count++] =
|
||||
icom_port->xmit_buf[data_count++] =
|
||||
port->state->xmit.buf[temp_tail];
|
||||
|
||||
temp_tail++;
|
||||
@ -642,22 +902,22 @@ static int icom_write(struct uart_port *port)
|
||||
}
|
||||
|
||||
if (data_count) {
|
||||
ICOM_PORT->statStg->xmit[0].flags =
|
||||
icom_port->statStg->xmit[0].flags =
|
||||
cpu_to_le16(SA_FLAGS_READY_TO_XMIT);
|
||||
ICOM_PORT->statStg->xmit[0].leLength =
|
||||
icom_port->statStg->xmit[0].leLength =
|
||||
cpu_to_le16(data_count);
|
||||
offset =
|
||||
(unsigned long) &ICOM_PORT->statStg->xmit[0] -
|
||||
(unsigned long) ICOM_PORT->statStg;
|
||||
*ICOM_PORT->xmitRestart =
|
||||
cpu_to_le32(ICOM_PORT->statStg_pci + offset);
|
||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
||||
(unsigned long) &icom_port->statStg->xmit[0] -
|
||||
(unsigned long) icom_port->statStg;
|
||||
*icom_port->xmitRestart =
|
||||
cpu_to_le32(icom_port->statStg_pci + offset);
|
||||
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||
writeb(cmdReg | CMD_XMIT_RCV_ENABLE,
|
||||
&ICOM_PORT->dram->CmdReg);
|
||||
writeb(START_XMIT, &ICOM_PORT->dram->StartXmitCmd);
|
||||
trace(ICOM_PORT, "WRITE_START", data_count);
|
||||
&icom_port->dram->CmdReg);
|
||||
writeb(START_XMIT, &icom_port->dram->StartXmitCmd);
|
||||
trace(icom_port, "WRITE_START", data_count);
|
||||
/* write flush */
|
||||
readb(&ICOM_PORT->dram->StartXmitCmd);
|
||||
readb(&icom_port->dram->StartXmitCmd);
|
||||
}
|
||||
|
||||
return data_count;
|
||||
@ -696,8 +956,7 @@ static inline void check_modem_status(struct icom_port *icom_port)
|
||||
|
||||
static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
|
||||
{
|
||||
unsigned short int count;
|
||||
int i;
|
||||
u16 count, i;
|
||||
|
||||
if (port_int_reg & (INT_XMIT_COMPLETED)) {
|
||||
trace(icom_port, "XMIT_COMPLETE", 0);
|
||||
@ -706,8 +965,7 @@ static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
|
||||
icom_port->statStg->xmit[0].flags &=
|
||||
cpu_to_le16(~SA_FLAGS_READY_TO_XMIT);
|
||||
|
||||
count = (unsigned short int)
|
||||
cpu_to_le16(icom_port->statStg->xmit[0].leLength);
|
||||
count = le16_to_cpu(icom_port->statStg->xmit[0].leLength);
|
||||
icom_port->uart_port.icount.tx += count;
|
||||
|
||||
for (i=0; i<count &&
|
||||
@ -729,7 +987,7 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
|
||||
{
|
||||
short int count, rcv_buff;
|
||||
struct tty_port *port = &icom_port->uart_port.state->port;
|
||||
unsigned short int status;
|
||||
u16 status;
|
||||
struct uart_icount *icount;
|
||||
unsigned long offset;
|
||||
unsigned char flag;
|
||||
@ -737,19 +995,18 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
|
||||
trace(icom_port, "RCV_COMPLETE", 0);
|
||||
rcv_buff = icom_port->next_rcv;
|
||||
|
||||
status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
|
||||
status = le16_to_cpu(icom_port->statStg->rcv[rcv_buff].flags);
|
||||
while (status & SA_FL_RCV_DONE) {
|
||||
int first = -1;
|
||||
|
||||
trace(icom_port, "FID_STATUS", status);
|
||||
count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
|
||||
count = le16_to_cpu(icom_port->statStg->rcv[rcv_buff].leLength);
|
||||
|
||||
trace(icom_port, "RCV_COUNT", count);
|
||||
|
||||
trace(icom_port, "REAL_COUNT", count);
|
||||
|
||||
offset =
|
||||
cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
|
||||
offset = le32_to_cpu(icom_port->statStg->rcv[rcv_buff].leBuffer) -
|
||||
icom_port->recv_buf_pci;
|
||||
|
||||
/* Block copy all but the last byte as this may have status */
|
||||
@ -819,13 +1076,13 @@ ignore_char:
|
||||
icom_port->statStg->rcv[rcv_buff].flags = 0;
|
||||
icom_port->statStg->rcv[rcv_buff].leLength = 0;
|
||||
icom_port->statStg->rcv[rcv_buff].WorkingLength =
|
||||
(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
|
||||
cpu_to_le16(RCV_BUFF_SZ);
|
||||
|
||||
rcv_buff++;
|
||||
if (rcv_buff == NUM_RBUFFS)
|
||||
rcv_buff = 0;
|
||||
|
||||
status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
|
||||
status = le16_to_cpu(icom_port->statStg->rcv[rcv_buff].flags);
|
||||
}
|
||||
icom_port->next_rcv = rcv_buff;
|
||||
|
||||
@ -925,11 +1182,12 @@ static irqreturn_t icom_interrupt(int irq, void *dev_id)
|
||||
*/
|
||||
static unsigned int icom_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
|
||||
if (le16_to_cpu(icom_port->statStg->xmit[0].flags) &
|
||||
SA_FLAGS_READY_TO_XMIT)
|
||||
ret = TIOCSER_TEMT;
|
||||
else
|
||||
@ -941,38 +1199,40 @@ static unsigned int icom_tx_empty(struct uart_port *port)
|
||||
|
||||
static void icom_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned char local_osr;
|
||||
|
||||
trace(ICOM_PORT, "SET_MODEM", 0);
|
||||
local_osr = readb(&ICOM_PORT->dram->osr);
|
||||
trace(icom_port, "SET_MODEM", 0);
|
||||
local_osr = readb(&icom_port->dram->osr);
|
||||
|
||||
if (mctrl & TIOCM_RTS) {
|
||||
trace(ICOM_PORT, "RAISE_RTS", 0);
|
||||
trace(icom_port, "RAISE_RTS", 0);
|
||||
local_osr |= ICOM_RTS;
|
||||
} else {
|
||||
trace(ICOM_PORT, "LOWER_RTS", 0);
|
||||
trace(icom_port, "LOWER_RTS", 0);
|
||||
local_osr &= ~ICOM_RTS;
|
||||
}
|
||||
|
||||
if (mctrl & TIOCM_DTR) {
|
||||
trace(ICOM_PORT, "RAISE_DTR", 0);
|
||||
trace(icom_port, "RAISE_DTR", 0);
|
||||
local_osr |= ICOM_DTR;
|
||||
} else {
|
||||
trace(ICOM_PORT, "LOWER_DTR", 0);
|
||||
trace(icom_port, "LOWER_DTR", 0);
|
||||
local_osr &= ~ICOM_DTR;
|
||||
}
|
||||
|
||||
writeb(local_osr, &ICOM_PORT->dram->osr);
|
||||
writeb(local_osr, &icom_port->dram->osr);
|
||||
}
|
||||
|
||||
static unsigned int icom_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned char status;
|
||||
unsigned int result;
|
||||
|
||||
trace(ICOM_PORT, "GET_MODEM", 0);
|
||||
trace(icom_port, "GET_MODEM", 0);
|
||||
|
||||
status = readb(&ICOM_PORT->dram->isr);
|
||||
status = readb(&icom_port->dram->isr);
|
||||
|
||||
result = ((status & ICOM_DCD) ? TIOCM_CAR : 0)
|
||||
| ((status & ICOM_RI) ? TIOCM_RNG : 0)
|
||||
@ -983,44 +1243,47 @@ static unsigned int icom_get_mctrl(struct uart_port *port)
|
||||
|
||||
static void icom_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned char cmdReg;
|
||||
|
||||
trace(ICOM_PORT, "STOP", 0);
|
||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
||||
writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
|
||||
trace(icom_port, "STOP", 0);
|
||||
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||
writeb(cmdReg | CMD_HOLD_XMIT, &icom_port->dram->CmdReg);
|
||||
}
|
||||
|
||||
static void icom_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned char cmdReg;
|
||||
|
||||
trace(ICOM_PORT, "START", 0);
|
||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
||||
trace(icom_port, "START", 0);
|
||||
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||
if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
|
||||
writeb(cmdReg & ~CMD_HOLD_XMIT,
|
||||
&ICOM_PORT->dram->CmdReg);
|
||||
&icom_port->dram->CmdReg);
|
||||
|
||||
icom_write(port);
|
||||
}
|
||||
|
||||
static void icom_send_xchar(struct uart_port *port, char ch)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned char xdata;
|
||||
int index;
|
||||
unsigned long flags;
|
||||
|
||||
trace(ICOM_PORT, "SEND_XCHAR", ch);
|
||||
trace(icom_port, "SEND_XCHAR", ch);
|
||||
|
||||
/* wait .1 sec to send char */
|
||||
for (index = 0; index < 10; index++) {
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
xdata = readb(&ICOM_PORT->dram->xchar);
|
||||
xdata = readb(&icom_port->dram->xchar);
|
||||
if (xdata == 0x00) {
|
||||
trace(ICOM_PORT, "QUICK_WRITE", 0);
|
||||
writeb(ch, &ICOM_PORT->dram->xchar);
|
||||
trace(icom_port, "QUICK_WRITE", 0);
|
||||
writeb(ch, &icom_port->dram->xchar);
|
||||
|
||||
/* flush write operation */
|
||||
xdata = readb(&ICOM_PORT->dram->xchar);
|
||||
xdata = readb(&icom_port->dram->xchar);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
break;
|
||||
}
|
||||
@ -1031,38 +1294,41 @@ static void icom_send_xchar(struct uart_port *port, char ch)
|
||||
|
||||
static void icom_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned char cmdReg;
|
||||
|
||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
||||
writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
|
||||
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||
writeb(cmdReg & ~CMD_RCV_ENABLE, &icom_port->dram->CmdReg);
|
||||
}
|
||||
|
||||
static void icom_break(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned char cmdReg;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
trace(ICOM_PORT, "BREAK", 0);
|
||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
||||
trace(icom_port, "BREAK", 0);
|
||||
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||
if (break_state == -1) {
|
||||
writeb(cmdReg | CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
|
||||
writeb(cmdReg | CMD_SND_BREAK, &icom_port->dram->CmdReg);
|
||||
} else {
|
||||
writeb(cmdReg & ~CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
|
||||
writeb(cmdReg & ~CMD_SND_BREAK, &icom_port->dram->CmdReg);
|
||||
}
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int icom_open(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
int retval;
|
||||
|
||||
kref_get(&ICOM_PORT->adapter->kref);
|
||||
retval = startup(ICOM_PORT);
|
||||
kref_get(&icom_port->adapter->kref);
|
||||
retval = startup(icom_port);
|
||||
|
||||
if (retval) {
|
||||
kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
|
||||
trace(ICOM_PORT, "STARTUP_ERROR", 0);
|
||||
kref_put(&icom_port->adapter->kref, icom_kref_release);
|
||||
trace(icom_port, "STARTUP_ERROR", 0);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1071,23 +1337,25 @@ static int icom_open(struct uart_port *port)
|
||||
|
||||
static void icom_close(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
unsigned char cmdReg;
|
||||
|
||||
trace(ICOM_PORT, "CLOSE", 0);
|
||||
trace(icom_port, "CLOSE", 0);
|
||||
|
||||
/* stop receiver */
|
||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
||||
writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
|
||||
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||
writeb(cmdReg & ~CMD_RCV_ENABLE, &icom_port->dram->CmdReg);
|
||||
|
||||
shutdown(ICOM_PORT);
|
||||
shutdown(icom_port);
|
||||
|
||||
kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
|
||||
kref_put(&icom_port->adapter->kref, icom_kref_release);
|
||||
}
|
||||
|
||||
static void icom_set_termios(struct uart_port *port,
|
||||
struct ktermios *termios,
|
||||
struct ktermios *old_termios)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
int baud;
|
||||
unsigned cflag, iflag;
|
||||
char new_config2;
|
||||
@ -1099,7 +1367,7 @@ static void icom_set_termios(struct uart_port *port,
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
trace(ICOM_PORT, "CHANGE_SPEED", 0);
|
||||
trace(icom_port, "CHANGE_SPEED", 0);
|
||||
|
||||
cflag = termios->c_cflag;
|
||||
iflag = termios->c_iflag;
|
||||
@ -1130,12 +1398,12 @@ static void icom_set_termios(struct uart_port *port,
|
||||
if (cflag & PARENB) {
|
||||
/* parity bit enabled */
|
||||
new_config2 |= ICOM_ACFG_PARITY_ENAB;
|
||||
trace(ICOM_PORT, "PARENB", 0);
|
||||
trace(icom_port, "PARENB", 0);
|
||||
}
|
||||
if (cflag & PARODD) {
|
||||
/* odd parity */
|
||||
new_config2 |= ICOM_ACFG_PARITY_ODD;
|
||||
trace(ICOM_PORT, "PARODD", 0);
|
||||
trace(icom_port, "PARODD", 0);
|
||||
}
|
||||
|
||||
/* Determine divisor based on baud rate */
|
||||
@ -1155,100 +1423,99 @@ static void icom_set_termios(struct uart_port *port,
|
||||
uart_update_timeout(port, cflag, baud);
|
||||
|
||||
/* CTS flow control flag and modem status interrupts */
|
||||
tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
|
||||
tmp_byte = readb(&(icom_port->dram->HDLCConfigReg));
|
||||
if (cflag & CRTSCTS)
|
||||
tmp_byte |= HDLC_HDW_FLOW;
|
||||
else
|
||||
tmp_byte &= ~HDLC_HDW_FLOW;
|
||||
writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
|
||||
writeb(tmp_byte, &(icom_port->dram->HDLCConfigReg));
|
||||
|
||||
/*
|
||||
* Set up parity check flag
|
||||
*/
|
||||
ICOM_PORT->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
|
||||
icom_port->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
|
||||
if (iflag & INPCK)
|
||||
ICOM_PORT->read_status_mask |=
|
||||
icom_port->read_status_mask |=
|
||||
SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
|
||||
|
||||
if ((iflag & BRKINT) || (iflag & PARMRK))
|
||||
ICOM_PORT->read_status_mask |= SA_FLAGS_BREAK_DET;
|
||||
icom_port->read_status_mask |= SA_FLAGS_BREAK_DET;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
ICOM_PORT->ignore_status_mask = 0;
|
||||
icom_port->ignore_status_mask = 0;
|
||||
if (iflag & IGNPAR)
|
||||
ICOM_PORT->ignore_status_mask |=
|
||||
icom_port->ignore_status_mask |=
|
||||
SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
|
||||
if (iflag & IGNBRK) {
|
||||
ICOM_PORT->ignore_status_mask |= SA_FLAGS_BREAK_DET;
|
||||
icom_port->ignore_status_mask |= SA_FLAGS_BREAK_DET;
|
||||
/*
|
||||
* If we're ignore parity and break indicators, ignore
|
||||
* overruns too. (For real raw support).
|
||||
*/
|
||||
if (iflag & IGNPAR)
|
||||
ICOM_PORT->ignore_status_mask |= SA_FLAGS_OVERRUN;
|
||||
icom_port->ignore_status_mask |= SA_FLAGS_OVERRUN;
|
||||
}
|
||||
|
||||
/*
|
||||
* !!! ignore all characters if CREAD is not set
|
||||
*/
|
||||
if ((cflag & CREAD) == 0)
|
||||
ICOM_PORT->ignore_status_mask |= SA_FL_RCV_DONE;
|
||||
icom_port->ignore_status_mask |= SA_FL_RCV_DONE;
|
||||
|
||||
/* Turn off Receiver to prepare for reset */
|
||||
writeb(CMD_RCV_DISABLE, &ICOM_PORT->dram->CmdReg);
|
||||
writeb(CMD_RCV_DISABLE, &icom_port->dram->CmdReg);
|
||||
|
||||
for (index = 0; index < 10; index++) {
|
||||
if (readb(&ICOM_PORT->dram->PrevCmdReg) == 0x00) {
|
||||
if (readb(&icom_port->dram->PrevCmdReg) == 0x00) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear all current buffers of data */
|
||||
for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
|
||||
ICOM_PORT->statStg->rcv[rcv_buff].flags = 0;
|
||||
ICOM_PORT->statStg->rcv[rcv_buff].leLength = 0;
|
||||
ICOM_PORT->statStg->rcv[rcv_buff].WorkingLength =
|
||||
(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
|
||||
icom_port->statStg->rcv[rcv_buff].flags = 0;
|
||||
icom_port->statStg->rcv[rcv_buff].leLength = 0;
|
||||
icom_port->statStg->rcv[rcv_buff].WorkingLength =
|
||||
cpu_to_le16(RCV_BUFF_SZ);
|
||||
}
|
||||
|
||||
for (xmit_buff = 0; xmit_buff < NUM_XBUFFS; xmit_buff++) {
|
||||
ICOM_PORT->statStg->xmit[xmit_buff].flags = 0;
|
||||
icom_port->statStg->xmit[xmit_buff].flags = 0;
|
||||
}
|
||||
|
||||
/* activate changes and start xmit and receiver here */
|
||||
/* Enable the receiver */
|
||||
writeb(new_config3, &(ICOM_PORT->dram->async_config3));
|
||||
writeb(new_config2, &(ICOM_PORT->dram->async_config2));
|
||||
tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
|
||||
writeb(new_config3, &(icom_port->dram->async_config3));
|
||||
writeb(new_config2, &(icom_port->dram->async_config2));
|
||||
tmp_byte = readb(&(icom_port->dram->HDLCConfigReg));
|
||||
tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
|
||||
writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
|
||||
writeb(0x04, &(ICOM_PORT->dram->FlagFillIdleTimer)); /* 0.5 seconds */
|
||||
writeb(0xFF, &(ICOM_PORT->dram->ier)); /* enable modem signal interrupts */
|
||||
writeb(tmp_byte, &(icom_port->dram->HDLCConfigReg));
|
||||
writeb(0x04, &(icom_port->dram->FlagFillIdleTimer)); /* 0.5 seconds */
|
||||
writeb(0xFF, &(icom_port->dram->ier)); /* enable modem signal interrupts */
|
||||
|
||||
/* reset processor */
|
||||
writeb(CMD_RESTART, &ICOM_PORT->dram->CmdReg);
|
||||
writeb(CMD_RESTART, &icom_port->dram->CmdReg);
|
||||
|
||||
for (index = 0; index < 10; index++) {
|
||||
if (readb(&ICOM_PORT->dram->CmdReg) == 0x00) {
|
||||
if (readb(&icom_port->dram->CmdReg) == 0x00) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable Transmitter and Receiver */
|
||||
offset =
|
||||
(unsigned long) &ICOM_PORT->statStg->rcv[0] -
|
||||
(unsigned long) ICOM_PORT->statStg;
|
||||
writel(ICOM_PORT->statStg_pci + offset,
|
||||
&ICOM_PORT->dram->RcvStatusAddr);
|
||||
ICOM_PORT->next_rcv = 0;
|
||||
ICOM_PORT->put_length = 0;
|
||||
*ICOM_PORT->xmitRestart = 0;
|
||||
writel(ICOM_PORT->xmitRestart_pci,
|
||||
&ICOM_PORT->dram->XmitStatusAddr);
|
||||
trace(ICOM_PORT, "XR_ENAB", 0);
|
||||
writeb(CMD_XMIT_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
|
||||
(unsigned long) &icom_port->statStg->rcv[0] -
|
||||
(unsigned long) icom_port->statStg;
|
||||
writel(icom_port->statStg_pci + offset,
|
||||
&icom_port->dram->RcvStatusAddr);
|
||||
icom_port->next_rcv = 0;
|
||||
*icom_port->xmitRestart = 0;
|
||||
writel(icom_port->xmitRestart_pci,
|
||||
&icom_port->dram->XmitStatusAddr);
|
||||
trace(icom_port, "XR_ENAB", 0);
|
||||
writeb(CMD_XMIT_RCV_ENABLE, &icom_port->dram->CmdReg);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
@ -1258,15 +1525,6 @@ static const char *icom_type(struct uart_port *port)
|
||||
return "icom";
|
||||
}
|
||||
|
||||
static void icom_release_port(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
static int icom_request_port(struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void icom_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
port->type = PORT_ICOM;
|
||||
@ -1285,8 +1543,6 @@ static const struct uart_ops icom_ops = {
|
||||
.shutdown = icom_close,
|
||||
.set_termios = icom_set_termios,
|
||||
.type = icom_type,
|
||||
.release_port = icom_release_port,
|
||||
.request_port = icom_request_port,
|
||||
.config_port = icom_config_port,
|
||||
};
|
||||
|
||||
@ -1315,7 +1571,6 @@ static int icom_init_ports(struct icom_adapter *icom_adapter)
|
||||
icom_port = &icom_adapter->port_info[i];
|
||||
icom_port->port = i;
|
||||
icom_port->status = ICOM_PORT_ACTIVE;
|
||||
icom_port->imbed_modem = ICOM_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
if (subsystem_id == PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL) {
|
||||
@ -1326,26 +1581,15 @@ static int icom_init_ports(struct icom_adapter *icom_adapter)
|
||||
|
||||
icom_port->port = i;
|
||||
icom_port->status = ICOM_PORT_ACTIVE;
|
||||
icom_port->imbed_modem = ICOM_IMBED_MODEM;
|
||||
}
|
||||
} else {
|
||||
icom_adapter->numb_ports = 4;
|
||||
|
||||
icom_adapter->port_info[0].port = 0;
|
||||
icom_adapter->port_info[0].status = ICOM_PORT_ACTIVE;
|
||||
|
||||
if (subsystem_id ==
|
||||
PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM) {
|
||||
icom_adapter->port_info[0].imbed_modem = ICOM_IMBED_MODEM;
|
||||
} else {
|
||||
icom_adapter->port_info[0].imbed_modem = ICOM_RVX;
|
||||
}
|
||||
|
||||
icom_adapter->port_info[1].status = ICOM_PORT_OFF;
|
||||
|
||||
icom_adapter->port_info[2].port = 2;
|
||||
icom_adapter->port_info[2].status = ICOM_PORT_ACTIVE;
|
||||
icom_adapter->port_info[2].imbed_modem = ICOM_RVX;
|
||||
icom_adapter->port_info[3].status = ICOM_PORT_OFF;
|
||||
}
|
||||
}
|
||||
@ -1401,7 +1645,6 @@ static int icom_alloc_adapter(struct icom_adapter
|
||||
int adapter_count = 0;
|
||||
struct icom_adapter *icom_adapter;
|
||||
struct icom_adapter *cur_adapter_entry;
|
||||
struct list_head *tmp;
|
||||
|
||||
icom_adapter = kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
|
||||
|
||||
@ -1409,10 +1652,8 @@ static int icom_alloc_adapter(struct icom_adapter
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
list_for_each(tmp, &icom_adapter_head) {
|
||||
cur_adapter_entry =
|
||||
list_entry(tmp, struct icom_adapter,
|
||||
icom_adapter_entry);
|
||||
list_for_each_entry(cur_adapter_entry, &icom_adapter_head,
|
||||
icom_adapter_entry) {
|
||||
if (cur_adapter_entry->index != adapter_count) {
|
||||
break;
|
||||
}
|
||||
@ -1420,7 +1661,8 @@ static int icom_alloc_adapter(struct icom_adapter
|
||||
}
|
||||
|
||||
icom_adapter->index = adapter_count;
|
||||
list_add_tail(&icom_adapter->icom_adapter_entry, tmp);
|
||||
list_add_tail(&icom_adapter->icom_adapter_entry,
|
||||
&cur_adapter_entry->icom_adapter_entry);
|
||||
|
||||
*icom_adapter_ref = icom_adapter;
|
||||
return 0;
|
||||
@ -1432,8 +1674,10 @@ static void icom_free_adapter(struct icom_adapter *icom_adapter)
|
||||
kfree(icom_adapter);
|
||||
}
|
||||
|
||||
static void icom_remove_adapter(struct icom_adapter *icom_adapter)
|
||||
static void icom_kref_release(struct kref *kref)
|
||||
{
|
||||
struct icom_adapter *icom_adapter = container_of(kref,
|
||||
struct icom_adapter, kref);
|
||||
struct icom_port *icom_port;
|
||||
int index;
|
||||
|
||||
@ -1466,14 +1710,6 @@ static void icom_remove_adapter(struct icom_adapter *icom_adapter)
|
||||
icom_free_adapter(icom_adapter);
|
||||
}
|
||||
|
||||
static void icom_kref_release(struct kref *kref)
|
||||
{
|
||||
struct icom_adapter *icom_adapter;
|
||||
|
||||
icom_adapter = to_icom_adapter(kref);
|
||||
icom_remove_adapter(icom_adapter);
|
||||
}
|
||||
|
||||
static int icom_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
@ -1501,7 +1737,7 @@ static int icom_probe(struct pci_dev *dev,
|
||||
retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg);
|
||||
if (retval) {
|
||||
dev_err(&dev->dev, "PCI Config read FAILED\n");
|
||||
return retval;
|
||||
goto probe_exit0;
|
||||
}
|
||||
|
||||
pci_write_config_dword(dev, PCI_COMMAND,
|
||||
@ -1589,11 +1825,9 @@ probe_exit0:
|
||||
static void icom_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct icom_adapter *icom_adapter;
|
||||
struct list_head *tmp;
|
||||
|
||||
list_for_each(tmp, &icom_adapter_head) {
|
||||
icom_adapter = list_entry(tmp, struct icom_adapter,
|
||||
icom_adapter_entry);
|
||||
list_for_each_entry(icom_adapter, &icom_adapter_head,
|
||||
icom_adapter_entry) {
|
||||
if (icom_adapter->pci_dev == dev) {
|
||||
kref_put(&icom_adapter->kref, icom_kref_release);
|
||||
return;
|
||||
|
@ -1,274 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* icom.h
|
||||
*
|
||||
* Copyright (C) 2001 Michael Anderson, IBM Corporation
|
||||
*
|
||||
* Serial device driver include file.
|
||||
*/
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#define BAUD_TABLE_LIMIT ((sizeof(icom_acfg_baud)/sizeof(int)) - 1)
|
||||
static int icom_acfg_baud[] = {
|
||||
300,
|
||||
600,
|
||||
900,
|
||||
1200,
|
||||
1800,
|
||||
2400,
|
||||
3600,
|
||||
4800,
|
||||
7200,
|
||||
9600,
|
||||
14400,
|
||||
19200,
|
||||
28800,
|
||||
38400,
|
||||
57600,
|
||||
76800,
|
||||
115200,
|
||||
153600,
|
||||
230400,
|
||||
307200,
|
||||
460800,
|
||||
};
|
||||
|
||||
struct icom_regs {
|
||||
u32 control; /* Adapter Control Register */
|
||||
u32 interrupt; /* Adapter Interrupt Register */
|
||||
u32 int_mask; /* Adapter Interrupt Mask Reg */
|
||||
u32 int_pri; /* Adapter Interrupt Priority r */
|
||||
u32 int_reg_b; /* Adapter non-masked Interrupt */
|
||||
u32 resvd01;
|
||||
u32 resvd02;
|
||||
u32 resvd03;
|
||||
u32 control_2; /* Adapter Control Register 2 */
|
||||
u32 interrupt_2; /* Adapter Interrupt Register 2 */
|
||||
u32 int_mask_2; /* Adapter Interrupt Mask 2 */
|
||||
u32 int_pri_2; /* Adapter Interrupt Prior 2 */
|
||||
u32 int_reg_2b; /* Adapter non-masked 2 */
|
||||
};
|
||||
|
||||
struct func_dram {
|
||||
u32 reserved[108]; /* 0-1B0 reserved by personality code */
|
||||
u32 RcvStatusAddr; /* 1B0-1B3 Status Address for Next rcv */
|
||||
u8 RcvStnAddr; /* 1B4 Receive Station Addr */
|
||||
u8 IdleState; /* 1B5 Idle State */
|
||||
u8 IdleMonitor; /* 1B6 Idle Monitor */
|
||||
u8 FlagFillIdleTimer; /* 1B7 Flag Fill Idle Timer */
|
||||
u32 XmitStatusAddr; /* 1B8-1BB Transmit Status Address */
|
||||
u8 StartXmitCmd; /* 1BC Start Xmit Command */
|
||||
u8 HDLCConfigReg; /* 1BD Reserved */
|
||||
u8 CauseCode; /* 1BE Cause code for fatal error */
|
||||
u8 xchar; /* 1BF High priority send */
|
||||
u32 reserved3; /* 1C0-1C3 Reserved */
|
||||
u8 PrevCmdReg; /* 1C4 Reserved */
|
||||
u8 CmdReg; /* 1C5 Command Register */
|
||||
u8 async_config2; /* 1C6 Async Config Byte 2 */
|
||||
u8 async_config3; /* 1C7 Async Config Byte 3 */
|
||||
u8 dce_resvd[20]; /* 1C8-1DB DCE Rsvd */
|
||||
u8 dce_resvd21; /* 1DC DCE Rsvd (21st byte */
|
||||
u8 misc_flags; /* 1DD misc flags */
|
||||
#define V2_HARDWARE 0x40
|
||||
#define ICOM_HDW_ACTIVE 0x01
|
||||
u8 call_length; /* 1DE Phone #/CFI buff ln */
|
||||
u8 call_length2; /* 1DF Upper byte (unused) */
|
||||
u32 call_addr; /* 1E0-1E3 Phn #/CFI buff addr */
|
||||
u16 timer_value; /* 1E4-1E5 general timer value */
|
||||
u8 timer_command; /* 1E6 general timer cmd */
|
||||
u8 dce_command; /* 1E7 dce command reg */
|
||||
u8 dce_cmd_status; /* 1E8 dce command stat */
|
||||
u8 x21_r1_ioff; /* 1E9 dce ready counter */
|
||||
u8 x21_r0_ioff; /* 1EA dce not ready ctr */
|
||||
u8 x21_ralt_ioff; /* 1EB dce CNR counter */
|
||||
u8 x21_r1_ion; /* 1EC dce ready I on ctr */
|
||||
u8 rsvd_ier; /* 1ED Rsvd for IER (if ne */
|
||||
u8 ier; /* 1EE Interrupt Enable */
|
||||
u8 isr; /* 1EF Input Signal Reg */
|
||||
u8 osr; /* 1F0 Output Signal Reg */
|
||||
u8 reset; /* 1F1 Reset/Reload Reg */
|
||||
u8 disable; /* 1F2 Disable Reg */
|
||||
u8 sync; /* 1F3 Sync Reg */
|
||||
u8 error_stat; /* 1F4 Error Status */
|
||||
u8 cable_id; /* 1F5 Cable ID */
|
||||
u8 cs_length; /* 1F6 CS Load Length */
|
||||
u8 mac_length; /* 1F7 Mac Load Length */
|
||||
u32 cs_load_addr; /* 1F8-1FB Call Load PCI Addr */
|
||||
u32 mac_load_addr; /* 1FC-1FF Mac Load PCI Addr */
|
||||
};
|
||||
|
||||
/*
|
||||
* adapter defines and structures
|
||||
*/
|
||||
#define ICOM_CONTROL_START_A 0x00000008
|
||||
#define ICOM_CONTROL_STOP_A 0x00000004
|
||||
#define ICOM_CONTROL_START_B 0x00000002
|
||||
#define ICOM_CONTROL_STOP_B 0x00000001
|
||||
#define ICOM_CONTROL_START_C 0x00000008
|
||||
#define ICOM_CONTROL_STOP_C 0x00000004
|
||||
#define ICOM_CONTROL_START_D 0x00000002
|
||||
#define ICOM_CONTROL_STOP_D 0x00000001
|
||||
#define ICOM_IRAM_OFFSET 0x1000
|
||||
#define ICOM_IRAM_SIZE 0x0C00
|
||||
#define ICOM_DCE_IRAM_OFFSET 0x0A00
|
||||
#define ICOM_CABLE_ID_VALID 0x01
|
||||
#define ICOM_CABLE_ID_MASK 0xF0
|
||||
#define ICOM_DISABLE 0x80
|
||||
#define CMD_XMIT_RCV_ENABLE 0xC0
|
||||
#define CMD_XMIT_ENABLE 0x40
|
||||
#define CMD_RCV_DISABLE 0x00
|
||||
#define CMD_RCV_ENABLE 0x80
|
||||
#define CMD_RESTART 0x01
|
||||
#define CMD_HOLD_XMIT 0x02
|
||||
#define CMD_SND_BREAK 0x04
|
||||
#define RS232_CABLE 0x06
|
||||
#define V24_CABLE 0x0E
|
||||
#define V35_CABLE 0x0C
|
||||
#define V36_CABLE 0x02
|
||||
#define NO_CABLE 0x00
|
||||
#define START_DOWNLOAD 0x80
|
||||
#define ICOM_INT_MASK_PRC_A 0x00003FFF
|
||||
#define ICOM_INT_MASK_PRC_B 0x3FFF0000
|
||||
#define ICOM_INT_MASK_PRC_C 0x00003FFF
|
||||
#define ICOM_INT_MASK_PRC_D 0x3FFF0000
|
||||
#define INT_RCV_COMPLETED 0x1000
|
||||
#define INT_XMIT_COMPLETED 0x2000
|
||||
#define INT_IDLE_DETECT 0x0800
|
||||
#define INT_RCV_DISABLED 0x0400
|
||||
#define INT_XMIT_DISABLED 0x0200
|
||||
#define INT_RCV_XMIT_SHUTDOWN 0x0100
|
||||
#define INT_FATAL_ERROR 0x0080
|
||||
#define INT_CABLE_PULL 0x0020
|
||||
#define INT_SIGNAL_CHANGE 0x0010
|
||||
#define HDLC_PPP_PURE_ASYNC 0x02
|
||||
#define HDLC_FF_FILL 0x00
|
||||
#define HDLC_HDW_FLOW 0x01
|
||||
#define START_XMIT 0x80
|
||||
#define ICOM_ACFG_DRIVE1 0x20
|
||||
#define ICOM_ACFG_NO_PARITY 0x00
|
||||
#define ICOM_ACFG_PARITY_ENAB 0x02
|
||||
#define ICOM_ACFG_PARITY_ODD 0x01
|
||||
#define ICOM_ACFG_8BPC 0x00
|
||||
#define ICOM_ACFG_7BPC 0x04
|
||||
#define ICOM_ACFG_6BPC 0x08
|
||||
#define ICOM_ACFG_5BPC 0x0C
|
||||
#define ICOM_ACFG_1STOP_BIT 0x00
|
||||
#define ICOM_ACFG_2STOP_BIT 0x10
|
||||
#define ICOM_DTR 0x80
|
||||
#define ICOM_RTS 0x40
|
||||
#define ICOM_RI 0x08
|
||||
#define ICOM_DSR 0x80
|
||||
#define ICOM_DCD 0x20
|
||||
#define ICOM_CTS 0x40
|
||||
|
||||
#define NUM_XBUFFS 1
|
||||
#define NUM_RBUFFS 2
|
||||
#define RCV_BUFF_SZ 0x0200
|
||||
#define XMIT_BUFF_SZ 0x1000
|
||||
struct statusArea {
|
||||
/**********************************************/
|
||||
/* Transmit Status Area */
|
||||
/**********************************************/
|
||||
struct xmit_status_area{
|
||||
u32 leNext; /* Next entry in Little Endian on Adapter */
|
||||
u32 leNextASD;
|
||||
u32 leBuffer; /* Buffer for entry in LE for Adapter */
|
||||
u16 leLengthASD;
|
||||
u16 leOffsetASD;
|
||||
u16 leLength; /* Length of data in segment */
|
||||
u16 flags;
|
||||
#define SA_FLAGS_DONE 0x0080 /* Done with Segment */
|
||||
#define SA_FLAGS_CONTINUED 0x8000 /* More Segments */
|
||||
#define SA_FLAGS_IDLE 0x4000 /* Mark IDLE after frm */
|
||||
#define SA_FLAGS_READY_TO_XMIT 0x0800
|
||||
#define SA_FLAGS_STAT_MASK 0x007F
|
||||
} xmit[NUM_XBUFFS];
|
||||
|
||||
/**********************************************/
|
||||
/* Receive Status Area */
|
||||
/**********************************************/
|
||||
struct {
|
||||
u32 leNext; /* Next entry in Little Endian on Adapter */
|
||||
u32 leNextASD;
|
||||
u32 leBuffer; /* Buffer for entry in LE for Adapter */
|
||||
u16 WorkingLength; /* size of segment */
|
||||
u16 reserv01;
|
||||
u16 leLength; /* Length of data in segment */
|
||||
u16 flags;
|
||||
#define SA_FL_RCV_DONE 0x0010 /* Data ready */
|
||||
#define SA_FLAGS_OVERRUN 0x0040
|
||||
#define SA_FLAGS_PARITY_ERROR 0x0080
|
||||
#define SA_FLAGS_FRAME_ERROR 0x0001
|
||||
#define SA_FLAGS_FRAME_TRUNC 0x0002
|
||||
#define SA_FLAGS_BREAK_DET 0x0004 /* set conditionally by device driver, not hardware */
|
||||
#define SA_FLAGS_RCV_MASK 0xFFE6
|
||||
} rcv[NUM_RBUFFS];
|
||||
};
|
||||
|
||||
struct icom_adapter;
|
||||
|
||||
|
||||
#define ICOM_MAJOR 243
|
||||
#define ICOM_MINOR_START 0
|
||||
|
||||
struct icom_port {
|
||||
struct uart_port uart_port;
|
||||
u8 imbed_modem;
|
||||
#define ICOM_UNKNOWN 1
|
||||
#define ICOM_RVX 2
|
||||
#define ICOM_IMBED_MODEM 3
|
||||
unsigned char cable_id;
|
||||
unsigned char read_status_mask;
|
||||
unsigned char ignore_status_mask;
|
||||
void __iomem * int_reg;
|
||||
struct icom_regs __iomem *global_reg;
|
||||
struct func_dram __iomem *dram;
|
||||
int port;
|
||||
struct statusArea *statStg;
|
||||
dma_addr_t statStg_pci;
|
||||
u32 *xmitRestart;
|
||||
dma_addr_t xmitRestart_pci;
|
||||
unsigned char *xmit_buf;
|
||||
dma_addr_t xmit_buf_pci;
|
||||
unsigned char *recv_buf;
|
||||
dma_addr_t recv_buf_pci;
|
||||
int next_rcv;
|
||||
int put_length;
|
||||
int status;
|
||||
#define ICOM_PORT_ACTIVE 1 /* Port exists. */
|
||||
#define ICOM_PORT_OFF 0 /* Port does not exist. */
|
||||
int load_in_progress;
|
||||
struct icom_adapter *adapter;
|
||||
};
|
||||
|
||||
struct icom_adapter {
|
||||
void __iomem * base_addr;
|
||||
unsigned long base_addr_pci;
|
||||
struct pci_dev *pci_dev;
|
||||
struct icom_port port_info[4];
|
||||
int index;
|
||||
int version;
|
||||
#define ADAPTER_V1 0x0001
|
||||
#define ADAPTER_V2 0x0002
|
||||
u32 subsystem_id;
|
||||
#define FOUR_PORT_MODEL 0x0252
|
||||
#define V2_TWO_PORTS_RVX 0x021A
|
||||
#define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM 0x0251
|
||||
int numb_ports;
|
||||
struct list_head icom_adapter_entry;
|
||||
struct kref kref;
|
||||
};
|
||||
|
||||
/* prototype */
|
||||
extern void iCom_sercons_init(void);
|
||||
|
||||
struct lookup_proc_table {
|
||||
u32 __iomem *global_control_reg;
|
||||
unsigned long processor_id;
|
||||
};
|
||||
|
||||
struct lookup_int_table {
|
||||
u32 __iomem *global_int_mask;
|
||||
unsigned long processor_id;
|
||||
};
|
@ -1937,8 +1937,6 @@ static int imx_uart_rs485_config(struct uart_port *port,
|
||||
rs485conf->flags & SER_RS485_RX_DURING_TX)
|
||||
imx_uart_start_rx(port);
|
||||
|
||||
port->rs485 = *rs485conf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -689,7 +689,7 @@ static void cls_param(struct jsm_channel *ch)
|
||||
/*
|
||||
* If baud rate is zero, flush queues, and set mval to drop DTR.
|
||||
*/
|
||||
if ((ch->ch_c_cflag & (CBAUD)) == 0) {
|
||||
if ((ch->ch_c_cflag & CBAUD) == B0) {
|
||||
ch->ch_r_head = 0;
|
||||
ch->ch_r_tail = 0;
|
||||
ch->ch_e_head = 0;
|
||||
@ -723,14 +723,8 @@ static void cls_param(struct jsm_channel *ch)
|
||||
if (!(ch->ch_c_cflag & PARODD))
|
||||
lcr |= UART_LCR_EPAR;
|
||||
|
||||
/*
|
||||
* Not all platforms support mark/space parity,
|
||||
* so this will hide behind an ifdef.
|
||||
*/
|
||||
#ifdef CMSPAR
|
||||
if (ch->ch_c_cflag & CMSPAR)
|
||||
lcr |= UART_LCR_SPAR;
|
||||
#endif
|
||||
|
||||
if (ch->ch_c_cflag & CSTOPB)
|
||||
lcr |= UART_LCR_STOP;
|
||||
|
@ -938,7 +938,7 @@ static void neo_param(struct jsm_channel *ch)
|
||||
/*
|
||||
* If baud rate is zero, flush queues, and set mval to drop DTR.
|
||||
*/
|
||||
if ((ch->ch_c_cflag & (CBAUD)) == 0) {
|
||||
if ((ch->ch_c_cflag & CBAUD) == B0) {
|
||||
ch->ch_r_head = ch->ch_r_tail = 0;
|
||||
ch->ch_e_head = ch->ch_e_tail = 0;
|
||||
|
||||
@ -997,14 +997,8 @@ static void neo_param(struct jsm_channel *ch)
|
||||
if (!(ch->ch_c_cflag & PARODD))
|
||||
lcr |= UART_LCR_EPAR;
|
||||
|
||||
/*
|
||||
* Not all platforms support mark/space parity,
|
||||
* so this will hide behind an ifdef.
|
||||
*/
|
||||
#ifdef CMSPAR
|
||||
if (ch->ch_c_cflag & CMSPAR)
|
||||
lcr |= UART_LCR_SPAR;
|
||||
#endif
|
||||
|
||||
if (ch->ch_c_cflag & CSTOPB)
|
||||
lcr |= UART_LCR_STOP;
|
||||
|
@ -1037,7 +1037,6 @@ static int max310x_rs485_config(struct uart_port *port,
|
||||
|
||||
rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX |
|
||||
SER_RS485_ENABLED;
|
||||
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||
port->rs485 = *rs485;
|
||||
|
||||
schedule_work(&one->rs_work);
|
||||
|
@ -833,7 +833,6 @@ static int men_z135_probe(struct mcb_device *mdev,
|
||||
uart->port.iotype = UPIO_MEM;
|
||||
uart->port.ops = &men_z135_ops;
|
||||
uart->port.irq = mcb_get_irq(mdev);
|
||||
uart->port.iotype = UPIO_MEM;
|
||||
uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
|
||||
uart->port.line = line++;
|
||||
uart->port.dev = dev;
|
||||
|
@ -68,6 +68,7 @@
|
||||
#define AML_UART_BAUD_MASK 0x7fffff
|
||||
#define AML_UART_BAUD_USE BIT(23)
|
||||
#define AML_UART_BAUD_XTAL BIT(24)
|
||||
#define AML_UART_BAUD_XTAL_DIV2 BIT(27)
|
||||
|
||||
#define AML_UART_PORT_NUM 12
|
||||
#define AML_UART_PORT_OFFSET 6
|
||||
@ -80,6 +81,10 @@ static struct uart_driver meson_uart_driver;
|
||||
|
||||
static struct uart_port *meson_ports[AML_UART_PORT_NUM];
|
||||
|
||||
struct meson_uart_data {
|
||||
bool has_xtal_div2;
|
||||
};
|
||||
|
||||
static void meson_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
}
|
||||
@ -253,6 +258,14 @@ static const char *meson_uart_type(struct uart_port *port)
|
||||
return (port->type == PORT_MESON) ? "meson_uart" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called only from probe() using a temporary io mapping
|
||||
* in order to perform a reset before setting up the device. Since the
|
||||
* temporarily mapped region was successfully requested, there can be no
|
||||
* console on this port at this time. Hence it is not necessary for this
|
||||
* function to acquire the port->lock. (Since there is no console on this
|
||||
* port at this time, the port->lock is not initialized yet.)
|
||||
*/
|
||||
static void meson_uart_reset(struct uart_port *port)
|
||||
{
|
||||
u32 val;
|
||||
@ -267,9 +280,12 @@ static void meson_uart_reset(struct uart_port *port)
|
||||
|
||||
static int meson_uart_startup(struct uart_port *port)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
val = readl(port->membase + AML_UART_CONTROL);
|
||||
val |= AML_UART_CLEAR_ERR;
|
||||
writel(val, port->membase + AML_UART_CONTROL);
|
||||
@ -285,6 +301,8 @@ static int meson_uart_startup(struct uart_port *port)
|
||||
val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2));
|
||||
writel(val, port->membase + AML_UART_MISC);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
ret = request_irq(port->irq, meson_uart_interrupt, 0,
|
||||
port->name, port);
|
||||
|
||||
@ -293,16 +311,23 @@ static int meson_uart_startup(struct uart_port *port)
|
||||
|
||||
static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
|
||||
{
|
||||
u32 val;
|
||||
const struct meson_uart_data *private_data = port->private_data;
|
||||
u32 val = 0;
|
||||
|
||||
while (!meson_uart_tx_empty(port))
|
||||
cpu_relax();
|
||||
|
||||
if (port->uartclk == 24000000) {
|
||||
val = ((port->uartclk / 3) / baud) - 1;
|
||||
unsigned int xtal_div = 3;
|
||||
|
||||
if (private_data && private_data->has_xtal_div2) {
|
||||
xtal_div = 2;
|
||||
val |= AML_UART_BAUD_XTAL_DIV2;
|
||||
}
|
||||
val |= DIV_ROUND_CLOSEST(port->uartclk / xtal_div, baud) - 1;
|
||||
val |= AML_UART_BAUD_XTAL;
|
||||
} else {
|
||||
val = ((port->uartclk * 10 / (baud * 4) + 5) / 10) - 1;
|
||||
val = DIV_ROUND_CLOSEST(port->uartclk / 4, baud) - 1;
|
||||
}
|
||||
val |= AML_UART_BAUD_USE;
|
||||
writel(val, port->membase + AML_UART_REG5);
|
||||
@ -749,6 +774,7 @@ static int meson_uart_probe(struct platform_device *pdev)
|
||||
port->x_char = 0;
|
||||
port->ops = &meson_uart_ops;
|
||||
port->fifosize = fifosize;
|
||||
port->private_data = (void *)device_get_match_data(&pdev->dev);
|
||||
|
||||
meson_ports[pdev->id] = port;
|
||||
platform_set_drvdata(pdev, port);
|
||||
@ -777,11 +803,19 @@ static int meson_uart_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct meson_uart_data s4_uart_data = {
|
||||
.has_xtal_div2 = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id meson_uart_dt_match[] = {
|
||||
{ .compatible = "amlogic,meson6-uart" },
|
||||
{ .compatible = "amlogic,meson8-uart" },
|
||||
{ .compatible = "amlogic,meson8b-uart" },
|
||||
{ .compatible = "amlogic,meson-gx-uart" },
|
||||
{
|
||||
.compatible = "amlogic,meson-s4-uart",
|
||||
.data = (void *)&s4_uart_data,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
@ -754,9 +756,6 @@ static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np)
|
||||
port->irqflags = IRQF_SHARED;
|
||||
port->irq = psc_fifoc_irq;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_MPC512x
|
||||
|
||||
#define PSC_5125(port) ((struct mpc5125_psc __iomem *)((port)->membase))
|
||||
#define FIFO_5125(port) ((struct mpc512x_psc_fifo __iomem *)(PSC_5125(port)+1))
|
||||
|
@ -1599,6 +1599,7 @@ static inline struct uart_port *msm_get_port_from_line(unsigned int line)
|
||||
static void __msm_console_write(struct uart_port *port, const char *s,
|
||||
unsigned int count, bool is_uartdm)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
int num_newlines = 0;
|
||||
bool replaced = false;
|
||||
@ -1616,6 +1617,8 @@ static void __msm_console_write(struct uart_port *port, const char *s,
|
||||
num_newlines++;
|
||||
count += num_newlines;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (port->sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
@ -1661,6 +1664,8 @@ static void __msm_console_write(struct uart_port *port, const char *s,
|
||||
|
||||
if (locked)
|
||||
spin_unlock(&port->lock);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void msm_console_write(struct console *co, const char *s,
|
||||
|
@ -1336,18 +1336,11 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
|
||||
up->ier = 0;
|
||||
serial_out(up, UART_IER, 0);
|
||||
|
||||
/* Clamp the delays to [0, 100ms] */
|
||||
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
|
||||
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
|
||||
|
||||
/* store new config */
|
||||
port->rs485 = *rs485;
|
||||
|
||||
if (up->rts_gpiod) {
|
||||
/* enable / disable rts */
|
||||
val = (port->rs485.flags & SER_RS485_ENABLED) ?
|
||||
val = (rs485->flags & SER_RS485_ENABLED) ?
|
||||
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
|
||||
val = (port->rs485.flags & val) ? 1 : 0;
|
||||
val = (rs485->flags & val) ? 1 : 0;
|
||||
gpiod_set_value(up->rts_gpiod, val);
|
||||
}
|
||||
|
||||
@ -1358,7 +1351,7 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
|
||||
/* If RS-485 is disabled, make sure the THR interrupt is fired when
|
||||
* TX FIFO is below the trigger level.
|
||||
*/
|
||||
if (!(port->rs485.flags & SER_RS485_ENABLED) &&
|
||||
if (!(rs485->flags & SER_RS485_ENABLED) &&
|
||||
(up->scr & OMAP_UART_SCR_TX_EMPTY)) {
|
||||
up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
|
||||
serial_out(up, UART_OMAP_SCR, up->scr);
|
||||
|
@ -184,9 +184,6 @@ static void owl_uart_send_chars(struct uart_port *port)
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
unsigned int ch;
|
||||
|
||||
if (uart_tx_stopped(port))
|
||||
return;
|
||||
|
||||
if (port->x_char) {
|
||||
while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU))
|
||||
cpu_relax();
|
||||
@ -195,6 +192,9 @@ static void owl_uart_send_chars(struct uart_port *port)
|
||||
port->x_char = 0;
|
||||
}
|
||||
|
||||
if (uart_tx_stopped(port))
|
||||
return;
|
||||
|
||||
while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU)) {
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
@ -731,6 +731,7 @@ static int owl_uart_probe(struct platform_device *pdev)
|
||||
owl_port->port.uartclk = clk_get_rate(owl_port->clk);
|
||||
if (owl_port->port.uartclk == 0) {
|
||||
dev_err(&pdev->dev, "clock rate is zero\n");
|
||||
clk_disable_unprepare(owl_port->clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
owl_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY;
|
||||
|
@ -550,18 +550,6 @@ static u8 pch_uart_hal_get_modem(struct eg20t_port *priv)
|
||||
return (u8)msr;
|
||||
}
|
||||
|
||||
static void pch_uart_hal_write(struct eg20t_port *priv,
|
||||
const unsigned char *buf, int tx_size)
|
||||
{
|
||||
int i;
|
||||
unsigned int thr;
|
||||
|
||||
for (i = 0; i < tx_size;) {
|
||||
thr = buf[i++];
|
||||
iowrite8(thr, priv->membase + PCH_UART_THR);
|
||||
}
|
||||
}
|
||||
|
||||
static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
|
||||
int rx_size)
|
||||
{
|
||||
@ -624,22 +612,6 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
struct uart_port *port = &priv->port;
|
||||
|
||||
if (port->x_char) {
|
||||
dev_dbg(priv->port.dev, "%s:X character send %02x (%lu)\n",
|
||||
__func__, port->x_char, jiffies);
|
||||
buf[0] = port->x_char;
|
||||
port->x_char = 0;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dma_push_rx(struct eg20t_port *priv, int size)
|
||||
{
|
||||
int room;
|
||||
@ -785,31 +757,6 @@ static void pch_dma_tx_complete(void *arg)
|
||||
pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
|
||||
}
|
||||
|
||||
static int pop_tx(struct eg20t_port *priv, int size)
|
||||
{
|
||||
int count = 0;
|
||||
struct uart_port *port = &priv->port;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
|
||||
if (uart_tx_stopped(port) || uart_circ_empty(xmit) || count >= size)
|
||||
goto pop_tx_end;
|
||||
|
||||
do {
|
||||
int cnt_to_end =
|
||||
CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
int sz = min(size - count, cnt_to_end);
|
||||
pch_uart_hal_write(priv, &xmit->buf[xmit->tail], sz);
|
||||
xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1);
|
||||
count += sz;
|
||||
} while (!uart_circ_empty(xmit) && count < size);
|
||||
|
||||
pop_tx_end:
|
||||
dev_dbg(priv->port.dev, "%d characters. Remained %d characters.(%lu)\n",
|
||||
count, size - count, jiffies);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int handle_rx_to(struct eg20t_port *priv)
|
||||
{
|
||||
struct pch_uart_buffer *buf;
|
||||
@ -875,8 +822,6 @@ static unsigned int handle_tx(struct eg20t_port *priv)
|
||||
struct uart_port *port = &priv->port;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
int fifo_size;
|
||||
int tx_size;
|
||||
int size;
|
||||
int tx_empty;
|
||||
|
||||
if (!priv->start_tx) {
|
||||
@ -889,19 +834,19 @@ static unsigned int handle_tx(struct eg20t_port *priv)
|
||||
|
||||
fifo_size = max(priv->fifo_size, 1);
|
||||
tx_empty = 1;
|
||||
if (pop_tx_x(priv, xmit->buf)) {
|
||||
pch_uart_hal_write(priv, xmit->buf, 1);
|
||||
if (port->x_char) {
|
||||
iowrite8(port->x_char, priv->membase + PCH_UART_THR);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
tx_empty = 0;
|
||||
fifo_size--;
|
||||
}
|
||||
size = min(xmit->head - xmit->tail, fifo_size);
|
||||
if (size < 0)
|
||||
size = fifo_size;
|
||||
|
||||
tx_size = pop_tx(priv, size);
|
||||
if (tx_size > 0) {
|
||||
port->icount.tx += tx_size;
|
||||
while (!uart_tx_stopped(port) && !uart_circ_empty(xmit) && fifo_size) {
|
||||
iowrite8(xmit->buf[xmit->tail], priv->membase + PCH_UART_THR);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
fifo_size--;
|
||||
tx_empty = 0;
|
||||
}
|
||||
|
||||
@ -946,9 +891,11 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
|
||||
}
|
||||
|
||||
fifo_size = max(priv->fifo_size, 1);
|
||||
if (pop_tx_x(priv, xmit->buf)) {
|
||||
pch_uart_hal_write(priv, xmit->buf, 1);
|
||||
|
||||
if (port->x_char) {
|
||||
iowrite8(port->x_char, priv->membase + PCH_UART_THR);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
fifo_size--;
|
||||
}
|
||||
|
||||
|
@ -25,13 +25,106 @@
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/mach-pic32/pic32.h>
|
||||
#include "pic32_uart.h"
|
||||
|
||||
/* UART name and device definitions */
|
||||
#define PIC32_DEV_NAME "pic32-uart"
|
||||
#define PIC32_MAX_UARTS 6
|
||||
#define PIC32_SDEV_NAME "ttyPIC"
|
||||
|
||||
#define PIC32_UART_DFLT_BRATE 9600
|
||||
#define PIC32_UART_TX_FIFO_DEPTH 8
|
||||
#define PIC32_UART_RX_FIFO_DEPTH 8
|
||||
|
||||
#define PIC32_UART_MODE 0x00
|
||||
#define PIC32_UART_STA 0x10
|
||||
#define PIC32_UART_TX 0x20
|
||||
#define PIC32_UART_RX 0x30
|
||||
#define PIC32_UART_BRG 0x40
|
||||
|
||||
/* struct pic32_sport - pic32 serial port descriptor
|
||||
* @port: uart port descriptor
|
||||
* @idx: port index
|
||||
* @irq_fault: virtual fault interrupt number
|
||||
* @irq_fault_name: irq fault name
|
||||
* @irq_rx: virtual rx interrupt number
|
||||
* @irq_rx_name: irq rx name
|
||||
* @irq_tx: virtual tx interrupt number
|
||||
* @irq_tx_name: irq tx name
|
||||
* @cts_gpio: clear to send gpio
|
||||
* @dev: device descriptor
|
||||
**/
|
||||
struct pic32_sport {
|
||||
struct uart_port port;
|
||||
int idx;
|
||||
|
||||
int irq_fault;
|
||||
const char *irq_fault_name;
|
||||
int irq_rx;
|
||||
const char *irq_rx_name;
|
||||
int irq_tx;
|
||||
const char *irq_tx_name;
|
||||
bool enable_tx_irq;
|
||||
|
||||
bool hw_flow_ctrl;
|
||||
int cts_gpio;
|
||||
|
||||
struct clk *clk;
|
||||
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static inline struct pic32_sport *to_pic32_sport(struct uart_port *port)
|
||||
{
|
||||
return container_of(port, struct pic32_sport, port);
|
||||
}
|
||||
|
||||
static inline void pic32_uart_writel(struct pic32_sport *sport,
|
||||
u32 reg, u32 val)
|
||||
{
|
||||
__raw_writel(val, sport->port.membase + reg);
|
||||
}
|
||||
|
||||
static inline u32 pic32_uart_readl(struct pic32_sport *sport, u32 reg)
|
||||
{
|
||||
return __raw_readl(sport->port.membase + reg);
|
||||
}
|
||||
|
||||
/* pic32 uart mode register bits */
|
||||
#define PIC32_UART_MODE_ON BIT(15)
|
||||
#define PIC32_UART_MODE_FRZ BIT(14)
|
||||
#define PIC32_UART_MODE_SIDL BIT(13)
|
||||
#define PIC32_UART_MODE_IREN BIT(12)
|
||||
#define PIC32_UART_MODE_RTSMD BIT(11)
|
||||
#define PIC32_UART_MODE_RESV1 BIT(10)
|
||||
#define PIC32_UART_MODE_UEN1 BIT(9)
|
||||
#define PIC32_UART_MODE_UEN0 BIT(8)
|
||||
#define PIC32_UART_MODE_WAKE BIT(7)
|
||||
#define PIC32_UART_MODE_LPBK BIT(6)
|
||||
#define PIC32_UART_MODE_ABAUD BIT(5)
|
||||
#define PIC32_UART_MODE_RXINV BIT(4)
|
||||
#define PIC32_UART_MODE_BRGH BIT(3)
|
||||
#define PIC32_UART_MODE_PDSEL1 BIT(2)
|
||||
#define PIC32_UART_MODE_PDSEL0 BIT(1)
|
||||
#define PIC32_UART_MODE_STSEL BIT(0)
|
||||
|
||||
/* pic32 uart status register bits */
|
||||
#define PIC32_UART_STA_UTXISEL1 BIT(15)
|
||||
#define PIC32_UART_STA_UTXISEL0 BIT(14)
|
||||
#define PIC32_UART_STA_UTXINV BIT(13)
|
||||
#define PIC32_UART_STA_URXEN BIT(12)
|
||||
#define PIC32_UART_STA_UTXBRK BIT(11)
|
||||
#define PIC32_UART_STA_UTXEN BIT(10)
|
||||
#define PIC32_UART_STA_UTXBF BIT(9)
|
||||
#define PIC32_UART_STA_TRMT BIT(8)
|
||||
#define PIC32_UART_STA_URXISEL1 BIT(7)
|
||||
#define PIC32_UART_STA_URXISEL0 BIT(6)
|
||||
#define PIC32_UART_STA_ADDEN BIT(5)
|
||||
#define PIC32_UART_STA_RIDLE BIT(4)
|
||||
#define PIC32_UART_STA_PERR BIT(3)
|
||||
#define PIC32_UART_STA_FERR BIT(2)
|
||||
#define PIC32_UART_STA_OERR BIT(1)
|
||||
#define PIC32_UART_STA_URXDA BIT(0)
|
||||
|
||||
/* pic32_sport pointer for console use */
|
||||
static struct pic32_sport *pic32_sports[PIC32_MAX_UARTS];
|
||||
|
||||
@ -42,23 +135,6 @@ static inline void pic32_wait_deplete_txbuf(struct pic32_sport *sport)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline int pic32_enable_clock(struct pic32_sport *sport)
|
||||
{
|
||||
int ret = clk_prepare_enable(sport->clk);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sport->ref_clk++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void pic32_disable_clock(struct pic32_sport *sport)
|
||||
{
|
||||
sport->ref_clk--;
|
||||
clk_disable_unprepare(sport->clk);
|
||||
}
|
||||
|
||||
/* serial core request to check if uart tx buffer is empty */
|
||||
static unsigned int pic32_uart_tx_empty(struct uart_port *port)
|
||||
{
|
||||
@ -117,16 +193,16 @@ static unsigned int pic32_uart_get_mctrl(struct uart_port *port)
|
||||
*/
|
||||
static inline void pic32_uart_irqtxen(struct pic32_sport *sport, u8 en)
|
||||
{
|
||||
if (en && !tx_irq_enabled(sport)) {
|
||||
if (en && !sport->enable_tx_irq) {
|
||||
enable_irq(sport->irq_tx);
|
||||
tx_irq_enabled(sport) = 1;
|
||||
} else if (!en && tx_irq_enabled(sport)) {
|
||||
sport->enable_tx_irq = true;
|
||||
} else if (!en && sport->enable_tx_irq) {
|
||||
/* use disable_irq_nosync() and not disable_irq() to avoid self
|
||||
* imposed deadlock by not waiting for irq handler to end,
|
||||
* since this callback is called from interrupt context.
|
||||
*/
|
||||
disable_irq_nosync(sport->irq_tx);
|
||||
tx_irq_enabled(sport) = 0;
|
||||
sport->enable_tx_irq = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,7 +471,7 @@ static int pic32_uart_startup(struct uart_port *port)
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
ret = pic32_enable_clock(sport);
|
||||
ret = clk_prepare_enable(sport->clk);
|
||||
if (ret) {
|
||||
local_irq_restore(flags);
|
||||
goto out_done;
|
||||
@ -419,7 +495,7 @@ static int pic32_uart_startup(struct uart_port *port)
|
||||
* For each irq request_irq() is called with interrupt disabled.
|
||||
* And the irq is enabled as soon as we are ready to handle them.
|
||||
*/
|
||||
tx_irq_enabled(sport) = 0;
|
||||
sport->enable_tx_irq = false;
|
||||
|
||||
sport->irq_fault_name = kasprintf(GFP_KERNEL, "%s%d-fault",
|
||||
pic32_uart_type(port),
|
||||
@ -431,7 +507,7 @@ static int pic32_uart_startup(struct uart_port *port)
|
||||
}
|
||||
irq_set_status_flags(sport->irq_fault, IRQ_NOAUTOEN);
|
||||
ret = request_irq(sport->irq_fault, pic32_uart_fault_interrupt,
|
||||
sport->irqflags_fault, sport->irq_fault_name, port);
|
||||
IRQF_NO_THREAD, sport->irq_fault_name, port);
|
||||
if (ret) {
|
||||
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
||||
__func__, sport->irq_fault, ret,
|
||||
@ -449,7 +525,7 @@ static int pic32_uart_startup(struct uart_port *port)
|
||||
}
|
||||
irq_set_status_flags(sport->irq_rx, IRQ_NOAUTOEN);
|
||||
ret = request_irq(sport->irq_rx, pic32_uart_rx_interrupt,
|
||||
sport->irqflags_rx, sport->irq_rx_name, port);
|
||||
IRQF_NO_THREAD, sport->irq_rx_name, port);
|
||||
if (ret) {
|
||||
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
||||
__func__, sport->irq_rx, ret,
|
||||
@ -467,7 +543,7 @@ static int pic32_uart_startup(struct uart_port *port)
|
||||
}
|
||||
irq_set_status_flags(sport->irq_tx, IRQ_NOAUTOEN);
|
||||
ret = request_irq(sport->irq_tx, pic32_uart_tx_interrupt,
|
||||
sport->irqflags_tx, sport->irq_tx_name, port);
|
||||
IRQF_NO_THREAD, sport->irq_tx_name, port);
|
||||
if (ret) {
|
||||
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
||||
__func__, sport->irq_tx, ret,
|
||||
@ -488,19 +564,21 @@ static int pic32_uart_startup(struct uart_port *port)
|
||||
/* enable all interrupts and eanable uart */
|
||||
pic32_uart_en_and_unmask(port);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
enable_irq(sport->irq_rx);
|
||||
|
||||
return 0;
|
||||
|
||||
out_t:
|
||||
kfree(sport->irq_tx_name);
|
||||
free_irq(sport->irq_tx, port);
|
||||
kfree(sport->irq_tx_name);
|
||||
out_r:
|
||||
kfree(sport->irq_rx_name);
|
||||
free_irq(sport->irq_rx, port);
|
||||
kfree(sport->irq_rx_name);
|
||||
out_f:
|
||||
kfree(sport->irq_fault_name);
|
||||
free_irq(sport->irq_fault, port);
|
||||
kfree(sport->irq_fault_name);
|
||||
out_done:
|
||||
return ret;
|
||||
}
|
||||
@ -515,12 +593,15 @@ static void pic32_uart_shutdown(struct uart_port *port)
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
pic32_uart_dsbl_and_mask(port);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
pic32_disable_clock(sport);
|
||||
clk_disable_unprepare(sport->clk);
|
||||
|
||||
/* free all 3 interrupts for this UART */
|
||||
free_irq(sport->irq_fault, port);
|
||||
kfree(sport->irq_fault_name);
|
||||
free_irq(sport->irq_tx, port);
|
||||
kfree(sport->irq_tx_name);
|
||||
free_irq(sport->irq_rx, port);
|
||||
kfree(sport->irq_rx_name);
|
||||
}
|
||||
|
||||
/* serial core request to change current uart setting */
|
||||
@ -712,10 +793,9 @@ static void pic32_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
{
|
||||
struct pic32_sport *sport = pic32_sports[co->index];
|
||||
struct uart_port *port = pic32_get_port(sport);
|
||||
|
||||
/* call uart helper to deal with \r\n */
|
||||
uart_console_write(port, s, count, pic32_console_putchar);
|
||||
uart_console_write(&sport->port, s, count, pic32_console_putchar);
|
||||
}
|
||||
|
||||
/* console core request to setup given console, find matching uart
|
||||
@ -724,7 +804,6 @@ static void pic32_console_write(struct console *co, const char *s,
|
||||
static int pic32_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct pic32_sport *sport;
|
||||
struct uart_port *port = NULL;
|
||||
int baud = 115200;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
@ -737,16 +816,15 @@ static int pic32_console_setup(struct console *co, char *options)
|
||||
sport = pic32_sports[co->index];
|
||||
if (!sport)
|
||||
return -ENODEV;
|
||||
port = pic32_get_port(sport);
|
||||
|
||||
ret = pic32_enable_clock(sport);
|
||||
ret = clk_prepare_enable(sport->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static struct uart_driver pic32_uart_driver;
|
||||
@ -816,13 +894,9 @@ static int pic32_uart_probe(struct platform_device *pdev)
|
||||
|
||||
sport->idx = uart_idx;
|
||||
sport->irq_fault = irq_of_parse_and_map(np, 0);
|
||||
sport->irqflags_fault = IRQF_NO_THREAD;
|
||||
sport->irq_rx = irq_of_parse_and_map(np, 1);
|
||||
sport->irqflags_rx = IRQF_NO_THREAD;
|
||||
sport->irq_tx = irq_of_parse_and_map(np, 2);
|
||||
sport->irqflags_tx = IRQF_NO_THREAD;
|
||||
sport->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
sport->cts_gpio = -EINVAL;
|
||||
sport->dev = &pdev->dev;
|
||||
|
||||
/* Hardware flow control: gpios
|
||||
@ -850,7 +924,6 @@ static int pic32_uart_probe(struct platform_device *pdev)
|
||||
|
||||
pic32_sports[uart_idx] = sport;
|
||||
port = &sport->port;
|
||||
memset(port, 0, sizeof(*port));
|
||||
port->iotype = UPIO_MEM;
|
||||
port->mapbase = res_mem->start;
|
||||
port->ops = &pic32_uart_ops;
|
||||
@ -872,7 +945,7 @@ static int pic32_uart_probe(struct platform_device *pdev)
|
||||
/* The peripheral clock has been enabled by console_setup,
|
||||
* so disable it till the port is used.
|
||||
*/
|
||||
pic32_disable_clock(sport);
|
||||
clk_disable_unprepare(sport->clk);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -893,7 +966,7 @@ static int pic32_uart_remove(struct platform_device *pdev)
|
||||
struct pic32_sport *sport = to_pic32_sport(port);
|
||||
|
||||
uart_remove_one_port(&pic32_uart_driver, port);
|
||||
pic32_disable_clock(sport);
|
||||
clk_disable_unprepare(sport->clk);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
pic32_sports[sport->idx] = NULL;
|
||||
|
||||
|
@ -1,125 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* PIC32 Integrated Serial Driver.
|
||||
*
|
||||
* Copyright (C) 2015 Microchip Technology, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Sorin-Andrei Pistirica <andrei.pistirica@microchip.com>
|
||||
*/
|
||||
#ifndef __DT_PIC32_UART_H__
|
||||
#define __DT_PIC32_UART_H__
|
||||
|
||||
#define PIC32_UART_DFLT_BRATE (9600)
|
||||
#define PIC32_UART_TX_FIFO_DEPTH (8)
|
||||
#define PIC32_UART_RX_FIFO_DEPTH (8)
|
||||
|
||||
#define PIC32_UART_MODE 0x00
|
||||
#define PIC32_UART_STA 0x10
|
||||
#define PIC32_UART_TX 0x20
|
||||
#define PIC32_UART_RX 0x30
|
||||
#define PIC32_UART_BRG 0x40
|
||||
|
||||
struct pic32_console_opt {
|
||||
int baud;
|
||||
int parity;
|
||||
int bits;
|
||||
int flow;
|
||||
};
|
||||
|
||||
/* struct pic32_sport - pic32 serial port descriptor
|
||||
* @port: uart port descriptor
|
||||
* @idx: port index
|
||||
* @irq_fault: virtual fault interrupt number
|
||||
* @irqflags_fault: flags related to fault irq
|
||||
* @irq_fault_name: irq fault name
|
||||
* @irq_rx: virtual rx interrupt number
|
||||
* @irqflags_rx: flags related to rx irq
|
||||
* @irq_rx_name: irq rx name
|
||||
* @irq_tx: virtual tx interrupt number
|
||||
* @irqflags_tx: : flags related to tx irq
|
||||
* @irq_tx_name: irq tx name
|
||||
* @cts_gpio: clear to send gpio
|
||||
* @dev: device descriptor
|
||||
**/
|
||||
struct pic32_sport {
|
||||
struct uart_port port;
|
||||
struct pic32_console_opt opt;
|
||||
int idx;
|
||||
|
||||
int irq_fault;
|
||||
int irqflags_fault;
|
||||
const char *irq_fault_name;
|
||||
int irq_rx;
|
||||
int irqflags_rx;
|
||||
const char *irq_rx_name;
|
||||
int irq_tx;
|
||||
int irqflags_tx;
|
||||
const char *irq_tx_name;
|
||||
u8 enable_tx_irq;
|
||||
|
||||
bool hw_flow_ctrl;
|
||||
int cts_gpio;
|
||||
|
||||
int ref_clk;
|
||||
struct clk *clk;
|
||||
|
||||
struct device *dev;
|
||||
};
|
||||
#define to_pic32_sport(c) container_of(c, struct pic32_sport, port)
|
||||
#define pic32_get_port(sport) (&sport->port)
|
||||
#define pic32_get_opt(sport) (&sport->opt)
|
||||
#define tx_irq_enabled(sport) (sport->enable_tx_irq)
|
||||
|
||||
static inline void pic32_uart_writel(struct pic32_sport *sport,
|
||||
u32 reg, u32 val)
|
||||
{
|
||||
struct uart_port *port = pic32_get_port(sport);
|
||||
|
||||
__raw_writel(val, port->membase + reg);
|
||||
}
|
||||
|
||||
static inline u32 pic32_uart_readl(struct pic32_sport *sport, u32 reg)
|
||||
{
|
||||
struct uart_port *port = pic32_get_port(sport);
|
||||
|
||||
return __raw_readl(port->membase + reg);
|
||||
}
|
||||
|
||||
/* pic32 uart mode register bits */
|
||||
#define PIC32_UART_MODE_ON BIT(15)
|
||||
#define PIC32_UART_MODE_FRZ BIT(14)
|
||||
#define PIC32_UART_MODE_SIDL BIT(13)
|
||||
#define PIC32_UART_MODE_IREN BIT(12)
|
||||
#define PIC32_UART_MODE_RTSMD BIT(11)
|
||||
#define PIC32_UART_MODE_RESV1 BIT(10)
|
||||
#define PIC32_UART_MODE_UEN1 BIT(9)
|
||||
#define PIC32_UART_MODE_UEN0 BIT(8)
|
||||
#define PIC32_UART_MODE_WAKE BIT(7)
|
||||
#define PIC32_UART_MODE_LPBK BIT(6)
|
||||
#define PIC32_UART_MODE_ABAUD BIT(5)
|
||||
#define PIC32_UART_MODE_RXINV BIT(4)
|
||||
#define PIC32_UART_MODE_BRGH BIT(3)
|
||||
#define PIC32_UART_MODE_PDSEL1 BIT(2)
|
||||
#define PIC32_UART_MODE_PDSEL0 BIT(1)
|
||||
#define PIC32_UART_MODE_STSEL BIT(0)
|
||||
|
||||
/* pic32 uart status register bits */
|
||||
#define PIC32_UART_STA_UTXISEL1 BIT(15)
|
||||
#define PIC32_UART_STA_UTXISEL0 BIT(14)
|
||||
#define PIC32_UART_STA_UTXINV BIT(13)
|
||||
#define PIC32_UART_STA_URXEN BIT(12)
|
||||
#define PIC32_UART_STA_UTXBRK BIT(11)
|
||||
#define PIC32_UART_STA_UTXEN BIT(10)
|
||||
#define PIC32_UART_STA_UTXBF BIT(9)
|
||||
#define PIC32_UART_STA_TRMT BIT(8)
|
||||
#define PIC32_UART_STA_URXISEL1 BIT(7)
|
||||
#define PIC32_UART_STA_URXISEL0 BIT(6)
|
||||
#define PIC32_UART_STA_ADDEN BIT(5)
|
||||
#define PIC32_UART_STA_RIDLE BIT(4)
|
||||
#define PIC32_UART_STA_PERR BIT(3)
|
||||
#define PIC32_UART_STA_FERR BIT(2)
|
||||
#define PIC32_UART_STA_OERR BIT(1)
|
||||
#define PIC32_UART_STA_URXDA BIT(0)
|
||||
|
||||
#endif /* __DT_PIC32_UART_H__ */
|
@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
#undef DEBUG_HARD
|
||||
#undef USE_CTRL_O_SYSRQ
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -51,7 +50,6 @@
|
||||
#include <asm/irq.h>
|
||||
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/dbdma.h>
|
||||
@ -66,10 +64,6 @@
|
||||
|
||||
#include "pmac_zilog.h"
|
||||
|
||||
/* Not yet implemented */
|
||||
#undef HAS_DBDMA
|
||||
|
||||
static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
|
||||
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
|
||||
MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports.");
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -446,9 +440,6 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
|
||||
spin_lock(&uap_a->port.lock);
|
||||
r3 = read_zsreg(uap_a, R3);
|
||||
|
||||
#ifdef DEBUG_HARD
|
||||
pmz_debug("irq, r3: %x\n", r3);
|
||||
#endif
|
||||
/* Channel A */
|
||||
push = false;
|
||||
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
|
||||
@ -613,8 +604,6 @@ static void pmz_start_tx(struct uart_port *port)
|
||||
struct uart_pmac_port *uap = to_pmz(port);
|
||||
unsigned char status;
|
||||
|
||||
pmz_debug("pmz: start_tx()\n");
|
||||
|
||||
uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
|
||||
uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
|
||||
|
||||
@ -636,7 +625,7 @@ static void pmz_start_tx(struct uart_port *port)
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
goto out;
|
||||
return;
|
||||
write_zsdata(uap, xmit->buf[xmit->tail]);
|
||||
zssync(uap);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
@ -645,8 +634,6 @@ static void pmz_start_tx(struct uart_port *port)
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&uap->port);
|
||||
}
|
||||
out:
|
||||
pmz_debug("pmz: start_tx() done.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -659,13 +646,9 @@ static void pmz_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct uart_pmac_port *uap = to_pmz(port);
|
||||
|
||||
pmz_debug("pmz: stop_rx()()\n");
|
||||
|
||||
/* Disable all RX interrupts. */
|
||||
uap->curregs[R1] &= ~RxINT_MASK;
|
||||
pmz_maybe_update_regs(uap);
|
||||
|
||||
pmz_debug("pmz: stop_rx() done.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -910,8 +893,6 @@ static int pmz_startup(struct uart_port *port)
|
||||
unsigned long flags;
|
||||
int pwr_delay = 0;
|
||||
|
||||
pmz_debug("pmz: startup()\n");
|
||||
|
||||
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
|
||||
|
||||
/* A console is never powered down. Else, power up and
|
||||
@ -947,8 +928,6 @@ static int pmz_startup(struct uart_port *port)
|
||||
pmz_interrupt_control(uap, 1);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
pmz_debug("pmz: startup() done.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -957,8 +936,6 @@ static void pmz_shutdown(struct uart_port *port)
|
||||
struct uart_pmac_port *uap = to_pmz(port);
|
||||
unsigned long flags;
|
||||
|
||||
pmz_debug("pmz: shutdown()\n");
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/* Disable interrupt requests for the channel */
|
||||
@ -987,8 +964,6 @@ static void pmz_shutdown(struct uart_port *port)
|
||||
pmz_set_scc_power(uap, 0); /* Shut the chip down */
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
pmz_debug("pmz: shutdown() done.\n");
|
||||
}
|
||||
|
||||
/* Shared by TTY driver and serial console setup. The port lock is held
|
||||
@ -1233,10 +1208,6 @@ static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct uart_pmac_port *uap = to_pmz(port);
|
||||
unsigned long baud;
|
||||
|
||||
pmz_debug("pmz: set_termios()\n");
|
||||
|
||||
memcpy(&uap->termios_cache, termios, sizeof(struct ktermios));
|
||||
|
||||
/* XXX Check which revs of machines actually allow 1 and 4Mb speeds
|
||||
* on the IR dongle. Note that the IRTTY driver currently doesn't know
|
||||
* about the FIR mode and high speed modes. So these are unused. For
|
||||
@ -1270,8 +1241,6 @@ static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
pmz_maybe_update_regs(uap);
|
||||
}
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
pmz_debug("pmz: set_termios() done.\n");
|
||||
}
|
||||
|
||||
/* The port lock is not held. */
|
||||
@ -1400,7 +1369,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
|
||||
char name[1];
|
||||
} *slots;
|
||||
int len;
|
||||
struct resource r_ports, r_rxdma, r_txdma;
|
||||
struct resource r_ports;
|
||||
|
||||
/*
|
||||
* Request & map chip registers
|
||||
@ -1412,35 +1381,6 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
|
||||
|
||||
uap->control_reg = uap->port.membase;
|
||||
uap->data_reg = uap->control_reg + 0x10;
|
||||
|
||||
/*
|
||||
* Request & map DBDMA registers
|
||||
*/
|
||||
#ifdef HAS_DBDMA
|
||||
if (of_address_to_resource(np, 1, &r_txdma) == 0 &&
|
||||
of_address_to_resource(np, 2, &r_rxdma) == 0)
|
||||
uap->flags |= PMACZILOG_FLAG_HAS_DMA;
|
||||
#else
|
||||
memset(&r_txdma, 0, sizeof(struct resource));
|
||||
memset(&r_rxdma, 0, sizeof(struct resource));
|
||||
#endif
|
||||
if (ZS_HAS_DMA(uap)) {
|
||||
uap->tx_dma_regs = ioremap(r_txdma.start, 0x100);
|
||||
if (uap->tx_dma_regs == NULL) {
|
||||
uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
|
||||
goto no_dma;
|
||||
}
|
||||
uap->rx_dma_regs = ioremap(r_rxdma.start, 0x100);
|
||||
if (uap->rx_dma_regs == NULL) {
|
||||
iounmap(uap->tx_dma_regs);
|
||||
uap->tx_dma_regs = NULL;
|
||||
uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
|
||||
goto no_dma;
|
||||
}
|
||||
uap->tx_dma_irq = irq_of_parse_and_map(np, 1);
|
||||
uap->rx_dma_irq = irq_of_parse_and_map(np, 2);
|
||||
}
|
||||
no_dma:
|
||||
|
||||
/*
|
||||
* Detect port type
|
||||
@ -1506,8 +1446,6 @@ no_dma:
|
||||
of_device_is_compatible(np->parent->parent, "gatwick")) {
|
||||
/* IRQs on gatwick are offset by 64 */
|
||||
uap->port.irq = irq_create_mapping(NULL, 64 + 15);
|
||||
uap->tx_dma_irq = irq_create_mapping(NULL, 64 + 4);
|
||||
uap->rx_dma_irq = irq_create_mapping(NULL, 64 + 5);
|
||||
}
|
||||
|
||||
/* Setup some valid baud rate information in the register
|
||||
@ -1527,8 +1465,6 @@ static void pmz_dispose_port(struct uart_pmac_port *uap)
|
||||
struct device_node *np;
|
||||
|
||||
np = uap->node;
|
||||
iounmap(uap->rx_dma_regs);
|
||||
iounmap(uap->tx_dma_regs);
|
||||
iounmap(uap->control_reg);
|
||||
uap->node = NULL;
|
||||
of_node_put(np);
|
||||
@ -1875,7 +1811,6 @@ static struct platform_driver pmz_driver = {
|
||||
static int __init init_pmz(void)
|
||||
{
|
||||
int rc, i;
|
||||
printk(KERN_INFO "%s\n", version);
|
||||
|
||||
/*
|
||||
* First, we need to do a direct OF-based probe pass. We
|
||||
|
@ -43,7 +43,6 @@ struct uart_pmac_port {
|
||||
#define PMACZILOG_FLAG_TX_ACTIVE 0x00000040
|
||||
#define PMACZILOG_FLAG_IS_IRDA 0x00000100
|
||||
#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
|
||||
#define PMACZILOG_FLAG_HAS_DMA 0x00000400
|
||||
#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
|
||||
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
|
||||
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
|
||||
@ -55,16 +54,7 @@ struct uart_pmac_port {
|
||||
volatile u8 __iomem *control_reg;
|
||||
volatile u8 __iomem *data_reg;
|
||||
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
unsigned int tx_dma_irq;
|
||||
unsigned int rx_dma_irq;
|
||||
volatile struct dbdma_regs __iomem *tx_dma_regs;
|
||||
volatile struct dbdma_regs __iomem *rx_dma_regs;
|
||||
#endif
|
||||
|
||||
unsigned char irq_name[8];
|
||||
|
||||
struct ktermios termios_cache;
|
||||
};
|
||||
|
||||
#define to_pmz(p) ((struct uart_pmac_port *)(p))
|
||||
@ -377,7 +367,6 @@ static inline void zssync(struct uart_pmac_port *port)
|
||||
#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & PMACZILOG_FLAG_MODEM_STATUS)
|
||||
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
|
||||
#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
|
||||
#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
|
||||
#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
|
||||
#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
|
||||
|
||||
|
@ -149,12 +149,6 @@ static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port);
|
||||
static void qcom_geni_serial_stop_rx(struct uart_port *uport);
|
||||
static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
|
||||
|
||||
static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
|
||||
32000000, 48000000, 51200000, 64000000,
|
||||
80000000, 96000000, 100000000,
|
||||
102400000, 112000000, 120000000,
|
||||
128000000};
|
||||
|
||||
#define to_dev_port(ptr, member) \
|
||||
container_of(ptr, struct qcom_geni_serial_port, member)
|
||||
|
||||
@ -507,7 +501,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
|
||||
*/
|
||||
qcom_geni_serial_poll_tx_done(uport);
|
||||
|
||||
if (uart_circ_chars_pending(&uport->state->xmit)) {
|
||||
if (!uart_circ_empty(&uport->state->xmit)) {
|
||||
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
|
||||
writel(irq_en | M_TX_FIFO_WATERMARK_EN,
|
||||
uport->membase + SE_GENI_M_IRQ_EN);
|
||||
@ -946,25 +940,43 @@ static int qcom_geni_serial_startup(struct uart_port *uport)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long get_clk_cfg(unsigned long clk_freq)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(root_freq); i++) {
|
||||
if (!(root_freq[i] % clk_freq))
|
||||
return root_freq[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long get_clk_div_rate(unsigned int baud,
|
||||
static unsigned long get_clk_div_rate(struct clk *clk, unsigned int baud,
|
||||
unsigned int sampling_rate, unsigned int *clk_div)
|
||||
{
|
||||
unsigned long ser_clk;
|
||||
unsigned long desired_clk;
|
||||
unsigned long freq, prev;
|
||||
unsigned long div, maxdiv;
|
||||
int64_t mult;
|
||||
|
||||
desired_clk = baud * sampling_rate;
|
||||
ser_clk = get_clk_cfg(desired_clk);
|
||||
if (!desired_clk) {
|
||||
pr_err("%s: Invalid frequency\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
maxdiv = CLK_DIV_MSK >> CLK_DIV_SHFT;
|
||||
prev = 0;
|
||||
|
||||
for (div = 1; div <= maxdiv; div++) {
|
||||
mult = div * desired_clk;
|
||||
if (mult > ULONG_MAX)
|
||||
break;
|
||||
|
||||
freq = clk_round_rate(clk, (unsigned long)mult);
|
||||
if (!(freq % desired_clk)) {
|
||||
ser_clk = freq;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!prev)
|
||||
ser_clk = freq;
|
||||
else if (prev == freq)
|
||||
break;
|
||||
|
||||
prev = freq;
|
||||
}
|
||||
|
||||
if (!ser_clk) {
|
||||
pr_err("%s: Can't find matching DFS entry for baud %d\n",
|
||||
__func__, baud);
|
||||
@ -972,6 +984,9 @@ static unsigned long get_clk_div_rate(unsigned int baud,
|
||||
}
|
||||
|
||||
*clk_div = ser_clk / desired_clk;
|
||||
if (!(*clk_div))
|
||||
*clk_div = 1;
|
||||
|
||||
return ser_clk;
|
||||
}
|
||||
|
||||
@ -1003,7 +1018,8 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
|
||||
if (ver >= QUP_SE_VERSION_2_5)
|
||||
sampling_rate /= 2;
|
||||
|
||||
clk_rate = get_clk_div_rate(baud, sampling_rate, &clk_div);
|
||||
clk_rate = get_clk_div_rate(port->se.clk, baud,
|
||||
sampling_rate, &clk_div);
|
||||
if (!clk_rate)
|
||||
goto out_restart_rx;
|
||||
|
||||
|
@ -262,6 +262,8 @@ static void rda_uart_set_termios(struct uart_port *port,
|
||||
fallthrough;
|
||||
case CS7:
|
||||
ctrl &= ~RDA_UART_DBITS_8;
|
||||
termios->c_cflag &= ~CSIZE;
|
||||
termios->c_cflag |= CS7;
|
||||
break;
|
||||
default:
|
||||
ctrl |= RDA_UART_DBITS_8;
|
||||
|
@ -446,6 +446,8 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
del_timer_sync(&sport->timer);
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
|
||||
sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
|
||||
@ -476,8 +478,6 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
UTSR1_TO_SM(UTSR1_ROR);
|
||||
}
|
||||
|
||||
del_timer_sync(&sport->timer);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
|
@ -2480,12 +2480,24 @@ s3c24xx_serial_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
|
||||
unsigned long flags;
|
||||
bool locked = true;
|
||||
|
||||
/* not possible to xmit on unconfigured port */
|
||||
if (!s3c24xx_port_configured(ucon))
|
||||
return;
|
||||
|
||||
if (cons_uart->sysrq)
|
||||
locked = false;
|
||||
else if (oops_in_progress)
|
||||
locked = spin_trylock_irqsave(&cons_uart->lock, flags);
|
||||
else
|
||||
spin_lock_irqsave(&cons_uart->lock, flags);
|
||||
|
||||
uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
|
||||
|
||||
if (locked)
|
||||
spin_unlock_irqrestore(&cons_uart->lock, flags);
|
||||
}
|
||||
|
||||
/* Shouldn't be __init, as it can be instantiated from other module */
|
||||
@ -2814,6 +2826,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
|
||||
.num_clks = 1,
|
||||
.clksel_mask = 0,
|
||||
.clksel_shift = 0,
|
||||
.ucon_mask = APPLE_S5L_UCON_MASK,
|
||||
},
|
||||
.def_cfg = {
|
||||
.ucon = APPLE_S5L_UCON_DEFAULT,
|
||||
|
@ -1134,16 +1134,6 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
|
||||
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
|
||||
|
||||
if (rs485->flags & SER_RS485_ENABLED) {
|
||||
bool rts_during_rx, rts_during_tx;
|
||||
|
||||
rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND;
|
||||
rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND;
|
||||
|
||||
if (rts_during_rx == rts_during_tx)
|
||||
dev_err(port->dev,
|
||||
"unsupported RTS signalling on_send:%d after_send:%d - exactly one of RS485 RTS flags should be set\n",
|
||||
rts_during_tx, rts_during_rx);
|
||||
|
||||
/*
|
||||
* RTS signal is handled by HW, it's timing can't be influenced.
|
||||
* However, it's sometimes useful to delay TX even without RTS
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#include <linux/irq.h>
|
||||
@ -42,6 +43,11 @@ static struct lock_class_key port_lock_key;
|
||||
|
||||
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
|
||||
|
||||
/*
|
||||
* Max time with active RTS before/after data is sent.
|
||||
*/
|
||||
#define RS485_MAX_RTS_DELAY 100 /* msecs */
|
||||
|
||||
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
||||
struct ktermios *old_termios);
|
||||
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
|
||||
@ -333,15 +339,18 @@ void
|
||||
uart_update_timeout(struct uart_port *port, unsigned int cflag,
|
||||
unsigned int baud)
|
||||
{
|
||||
unsigned int size;
|
||||
unsigned int size = tty_get_frame_size(cflag);
|
||||
u64 frame_time;
|
||||
|
||||
size = tty_get_frame_size(cflag) * port->fifosize;
|
||||
frame_time = (u64)size * NSEC_PER_SEC;
|
||||
size *= port->fifosize;
|
||||
|
||||
/*
|
||||
* Figure the timeout to send the above number of bits.
|
||||
* Add .02 seconds of slop
|
||||
*/
|
||||
port->timeout = (HZ * size) / baud + HZ/50;
|
||||
port->frame_time = DIV64_U64_ROUND_UP(frame_time, baud);
|
||||
}
|
||||
EXPORT_SYMBOL(uart_update_timeout);
|
||||
|
||||
@ -1296,8 +1305,36 @@ static int uart_set_rs485_config(struct uart_port *port,
|
||||
if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user)))
|
||||
return -EFAULT;
|
||||
|
||||
/* pick sane settings if the user hasn't */
|
||||
if (!(rs485.flags & SER_RS485_RTS_ON_SEND) ==
|
||||
!(rs485.flags & SER_RS485_RTS_AFTER_SEND)) {
|
||||
dev_warn_ratelimited(port->dev,
|
||||
"%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n",
|
||||
port->name, port->line);
|
||||
rs485.flags |= SER_RS485_RTS_ON_SEND;
|
||||
rs485.flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
|
||||
if (rs485.delay_rts_before_send > RS485_MAX_RTS_DELAY) {
|
||||
rs485.delay_rts_before_send = RS485_MAX_RTS_DELAY;
|
||||
dev_warn_ratelimited(port->dev,
|
||||
"%s (%d): RTS delay before sending clamped to %u ms\n",
|
||||
port->name, port->line, rs485.delay_rts_before_send);
|
||||
}
|
||||
|
||||
if (rs485.delay_rts_after_send > RS485_MAX_RTS_DELAY) {
|
||||
rs485.delay_rts_after_send = RS485_MAX_RTS_DELAY;
|
||||
dev_warn_ratelimited(port->dev,
|
||||
"%s (%d): RTS delay after sending clamped to %u ms\n",
|
||||
port->name, port->line, rs485.delay_rts_after_send);
|
||||
}
|
||||
/* Return clean padding area to userspace */
|
||||
memset(rs485.padding, 0, sizeof(rs485.padding));
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
ret = port->rs485_config(port, &rs485);
|
||||
if (!ret)
|
||||
port->rs485 = rs485;
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1610,24 +1647,24 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||
* Note: we have to use pretty tight timings here to satisfy
|
||||
* the NIST-PCTS.
|
||||
*/
|
||||
char_time = (port->timeout - HZ/50) / port->fifosize;
|
||||
char_time = char_time / 5;
|
||||
if (char_time == 0)
|
||||
char_time = 1;
|
||||
char_time = max(nsecs_to_jiffies(port->frame_time / 5), 1UL);
|
||||
|
||||
if (timeout && timeout < char_time)
|
||||
char_time = timeout;
|
||||
|
||||
/*
|
||||
* If the transmitter hasn't cleared in twice the approximate
|
||||
* amount of time to send the entire FIFO, it probably won't
|
||||
* ever clear. This assumes the UART isn't doing flow
|
||||
* control, which is currently the case. Hence, if it ever
|
||||
* takes longer than port->timeout, this is probably due to a
|
||||
* UART bug of some kind. So, we clamp the timeout parameter at
|
||||
* 2*port->timeout.
|
||||
*/
|
||||
if (timeout == 0 || timeout > 2 * port->timeout)
|
||||
timeout = 2 * port->timeout;
|
||||
if (!uart_cts_enabled(port)) {
|
||||
/*
|
||||
* If the transmitter hasn't cleared in twice the approximate
|
||||
* amount of time to send the entire FIFO, it probably won't
|
||||
* ever clear. This assumes the UART isn't doing flow
|
||||
* control, which is currently the case. Hence, if it ever
|
||||
* takes longer than port->timeout, this is probably due to a
|
||||
* UART bug of some kind. So, we clamp the timeout parameter at
|
||||
* 2*port->timeout.
|
||||
*/
|
||||
if (timeout == 0 || timeout > 2 * port->timeout)
|
||||
timeout = 2 * port->timeout;
|
||||
}
|
||||
|
||||
expire = jiffies + timeout;
|
||||
|
||||
@ -1643,7 +1680,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||
msleep_interruptible(jiffies_to_msecs(char_time));
|
||||
if (signal_pending(current))
|
||||
break;
|
||||
if (time_after(jiffies, expire))
|
||||
if (timeout && time_after(jiffies, expire))
|
||||
break;
|
||||
}
|
||||
uart_port_deref(port);
|
||||
@ -2174,15 +2211,23 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
}
|
||||
put_device(tty_dev);
|
||||
|
||||
/* Nothing to do if the console is not suspending */
|
||||
if (!console_suspend_enabled && uart_console(uport))
|
||||
/*
|
||||
* Nothing to do if the console is not suspending
|
||||
* except stop_rx to prevent any asynchronous data
|
||||
* over RX line. Re-start_rx, when required, is
|
||||
* done by set_termios in resume sequence
|
||||
*/
|
||||
if (!console_suspend_enabled && uart_console(uport)) {
|
||||
uport->ops->stop_rx(uport);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
uport->suspended = 1;
|
||||
|
||||
if (tty_port_initialized(port)) {
|
||||
const struct uart_ops *ops = uport->ops;
|
||||
int tries;
|
||||
unsigned int mctrl;
|
||||
|
||||
tty_port_set_suspended(port, 1);
|
||||
tty_port_set_initialized(port, 0);
|
||||
@ -2190,6 +2235,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
spin_lock_irq(&uport->lock);
|
||||
ops->stop_tx(uport);
|
||||
ops->set_mctrl(uport, 0);
|
||||
/* save mctrl so it can be restored on resume */
|
||||
mctrl = uport->mctrl;
|
||||
uport->mctrl = 0;
|
||||
ops->stop_rx(uport);
|
||||
spin_unlock_irq(&uport->lock);
|
||||
|
||||
@ -2203,6 +2251,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
uport->name);
|
||||
|
||||
ops->shutdown(uport);
|
||||
uport->mctrl = mctrl;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -618,6 +618,8 @@ serial_txx9_set_termios(struct uart_port *up, struct ktermios *termios,
|
||||
case CS6: /* not supported */
|
||||
case CS8:
|
||||
cval |= TXX9_SILCR_UMODE_8BIT;
|
||||
termios->c_cflag &= ~CSIZE;
|
||||
termios->c_cflag |= CS8;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2379,8 +2379,12 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
int best_clk = -1;
|
||||
unsigned long flags;
|
||||
|
||||
if ((termios->c_cflag & CSIZE) == CS7)
|
||||
if ((termios->c_cflag & CSIZE) == CS7) {
|
||||
smr_val |= SCSMR_CHR;
|
||||
} else {
|
||||
termios->c_cflag &= ~CSIZE;
|
||||
termios->c_cflag |= CS8;
|
||||
}
|
||||
if (termios->c_cflag & PARENB)
|
||||
smr_val |= SCSMR_PE;
|
||||
if (termios->c_cflag & PARODD)
|
||||
|
@ -148,7 +148,6 @@
|
||||
* @port: struct uart_port embedded in this struct
|
||||
* @dev: struct device *
|
||||
* @ier: shadowed copy of the interrupt enable register
|
||||
* @clkin_rate: input clock to the UART IP block.
|
||||
* @baud_rate: UART serial line rate (e.g., 115200 baud)
|
||||
* @clk: reference to this device's clock
|
||||
* @clk_notifier: clock rate change notifier for upstream clock changes
|
||||
@ -159,7 +158,6 @@ struct sifive_serial_port {
|
||||
struct uart_port port;
|
||||
struct device *dev;
|
||||
unsigned char ier;
|
||||
unsigned long clkin_rate;
|
||||
unsigned long baud_rate;
|
||||
struct clk *clk;
|
||||
struct notifier_block clk_notifier;
|
||||
@ -463,7 +461,7 @@ static void __ssp_update_div(struct sifive_serial_port *ssp)
|
||||
{
|
||||
u16 div;
|
||||
|
||||
div = DIV_ROUND_UP(ssp->clkin_rate, ssp->baud_rate) - 1;
|
||||
div = DIV_ROUND_UP(ssp->port.uartclk, ssp->baud_rate) - 1;
|
||||
|
||||
__ssp_writel(div, SIFIVE_SERIAL_DIV_OFFS, ssp);
|
||||
}
|
||||
@ -648,8 +646,8 @@ static int sifive_serial_clk_notifier(struct notifier_block *nb,
|
||||
udelay(DIV_ROUND_UP(12 * 1000 * 1000, ssp->baud_rate));
|
||||
}
|
||||
|
||||
if (event == POST_RATE_CHANGE && ssp->clkin_rate != cnd->new_rate) {
|
||||
ssp->clkin_rate = cnd->new_rate;
|
||||
if (event == POST_RATE_CHANGE && ssp->port.uartclk != cnd->new_rate) {
|
||||
ssp->port.uartclk = cnd->new_rate;
|
||||
__ssp_update_div(ssp);
|
||||
}
|
||||
|
||||
@ -666,19 +664,24 @@ static void sifive_serial_set_termios(struct uart_port *port,
|
||||
int rate;
|
||||
char nstop;
|
||||
|
||||
if ((termios->c_cflag & CSIZE) != CS8)
|
||||
if ((termios->c_cflag & CSIZE) != CS8) {
|
||||
dev_err_once(ssp->port.dev, "only 8-bit words supported\n");
|
||||
termios->c_cflag &= ~CSIZE;
|
||||
termios->c_cflag |= CS8;
|
||||
}
|
||||
if (termios->c_iflag & (INPCK | PARMRK))
|
||||
dev_err_once(ssp->port.dev, "parity checking not supported\n");
|
||||
if (termios->c_iflag & BRKINT)
|
||||
dev_err_once(ssp->port.dev, "BREAK detection not supported\n");
|
||||
termios->c_iflag &= ~(INPCK|PARMRK|BRKINT);
|
||||
|
||||
/* Set number of stop bits */
|
||||
nstop = (termios->c_cflag & CSTOPB) ? 2 : 1;
|
||||
__ssp_set_stop_bits(ssp, nstop);
|
||||
|
||||
/* Set line rate */
|
||||
rate = uart_get_baud_rate(port, termios, old, 0, ssp->clkin_rate / 16);
|
||||
rate = uart_get_baud_rate(port, termios, old, 0,
|
||||
ssp->port.uartclk / 16);
|
||||
__ssp_update_baud_rate(ssp, rate);
|
||||
|
||||
spin_lock_irqsave(&ssp->port.lock, flags);
|
||||
@ -996,9 +999,8 @@ static int sifive_serial_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Set up clock divider */
|
||||
ssp->clkin_rate = clk_get_rate(ssp->clk);
|
||||
ssp->port.uartclk = clk_get_rate(ssp->clk);
|
||||
ssp->baud_rate = SIFIVE_DEFAULT_BAUD_RATE;
|
||||
ssp->port.uartclk = ssp->baud_rate * 16;
|
||||
__ssp_update_div(ssp);
|
||||
|
||||
platform_set_drvdata(pdev, ssp);
|
||||
|
@ -535,10 +535,14 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
/* set character length */
|
||||
if ((cflag & CSIZE) == CS7) {
|
||||
ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
|
||||
cflag |= PARENB;
|
||||
} else {
|
||||
ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR :
|
||||
ASC_CTL_MODE_8BIT;
|
||||
cflag &= ~CSIZE;
|
||||
cflag |= CS8;
|
||||
}
|
||||
termios->c_cflag = cflag;
|
||||
|
||||
/* set stop bit */
|
||||
ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
static void stm32_usart_stop_tx(struct uart_port *port);
|
||||
static void stm32_usart_transmit_chars(struct uart_port *port);
|
||||
static void __maybe_unused stm32_usart_console_putchar(struct uart_port *port, unsigned char ch);
|
||||
|
||||
static inline struct stm32_port *to_stm32_port(struct uart_port *port)
|
||||
{
|
||||
@ -107,8 +108,6 @@ static int stm32_usart_config_rs485(struct uart_port *port,
|
||||
|
||||
stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
|
||||
|
||||
port->rs485 = *rs485conf;
|
||||
|
||||
rs485conf->flags |= SER_RS485_RX_DURING_TX;
|
||||
|
||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||
@ -128,13 +127,10 @@ static int stm32_usart_config_rs485(struct uart_port *port,
|
||||
rs485conf->delay_rts_after_send,
|
||||
baud);
|
||||
|
||||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
|
||||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND)
|
||||
cr3 &= ~USART_CR3_DEP;
|
||||
rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
} else {
|
||||
else
|
||||
cr3 |= USART_CR3_DEP;
|
||||
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
|
||||
writel_relaxed(cr3, port->membase + ofs->cr3);
|
||||
writel_relaxed(cr1, port->membase + ofs->cr1);
|
||||
@ -421,6 +417,14 @@ 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_tc_interrupt_enable(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
|
||||
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
static void stm32_usart_rx_dma_complete(void *arg)
|
||||
{
|
||||
struct uart_port *port = arg;
|
||||
@ -446,6 +450,50 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
|
||||
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
|
||||
}
|
||||
|
||||
static void stm32_usart_tc_interrupt_disable(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
|
||||
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
static void stm32_usart_rs485_rts_enable(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
struct serial_rs485 *rs485conf = &port->rs485;
|
||||
|
||||
if (stm32_port->hw_flow_control ||
|
||||
!(rs485conf->flags & SER_RS485_ENABLED))
|
||||
return;
|
||||
|
||||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl | TIOCM_RTS);
|
||||
} else {
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl & ~TIOCM_RTS);
|
||||
}
|
||||
}
|
||||
|
||||
static void stm32_usart_rs485_rts_disable(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
struct serial_rs485 *rs485conf = &port->rs485;
|
||||
|
||||
if (stm32_port->hw_flow_control ||
|
||||
!(rs485conf->flags & SER_RS485_ENABLED))
|
||||
return;
|
||||
|
||||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl & ~TIOCM_RTS);
|
||||
} else {
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl | TIOCM_RTS);
|
||||
}
|
||||
}
|
||||
|
||||
static void stm32_usart_transmit_chars_pio(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
@ -553,6 +601,13 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
|
||||
u32 isr;
|
||||
int ret;
|
||||
|
||||
if (!stm32_port->hw_flow_control &&
|
||||
port->rs485.flags & SER_RS485_ENABLED) {
|
||||
stm32_port->txdone = false;
|
||||
stm32_usart_tc_interrupt_disable(port);
|
||||
stm32_usart_rs485_rts_enable(port);
|
||||
}
|
||||
|
||||
if (port->x_char) {
|
||||
if (stm32_usart_tx_dma_started(stm32_port) &&
|
||||
stm32_usart_tx_dma_enabled(stm32_port))
|
||||
@ -593,8 +648,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
if (uart_circ_empty(xmit)) {
|
||||
stm32_usart_tx_interrupt_disable(port);
|
||||
if (!stm32_port->hw_flow_control &&
|
||||
port->rs485.flags & SER_RS485_ENABLED) {
|
||||
stm32_port->txdone = true;
|
||||
stm32_usart_tc_interrupt_enable(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
@ -608,6 +669,13 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
|
||||
sr = readl_relaxed(port->membase + ofs->isr);
|
||||
|
||||
if (!stm32_port->hw_flow_control &&
|
||||
port->rs485.flags & SER_RS485_ENABLED &&
|
||||
(sr & USART_SR_TC)) {
|
||||
stm32_usart_tc_interrupt_disable(port);
|
||||
stm32_usart_rs485_rts_disable(port);
|
||||
}
|
||||
|
||||
if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
|
||||
writel_relaxed(USART_ICR_RTOCF,
|
||||
port->membase + ofs->icr);
|
||||
@ -717,44 +785,27 @@ static void stm32_usart_disable_ms(struct uart_port *port)
|
||||
static void stm32_usart_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
struct serial_rs485 *rs485conf = &port->rs485;
|
||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
|
||||
stm32_usart_tx_interrupt_disable(port);
|
||||
if (stm32_usart_tx_dma_started(stm32_port) && stm32_usart_tx_dma_enabled(stm32_port))
|
||||
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
|
||||
|
||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl & ~TIOCM_RTS);
|
||||
} else {
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl | TIOCM_RTS);
|
||||
}
|
||||
}
|
||||
stm32_usart_rs485_rts_disable(port);
|
||||
}
|
||||
|
||||
/* There are probably characters waiting to be transmitted. */
|
||||
static void stm32_usart_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
struct serial_rs485 *rs485conf = &port->rs485;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
|
||||
if (uart_circ_empty(xmit) && !port->x_char)
|
||||
if (uart_circ_empty(xmit) && !port->x_char) {
|
||||
stm32_usart_rs485_rts_disable(port);
|
||||
return;
|
||||
|
||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl | TIOCM_RTS);
|
||||
} else {
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl & ~TIOCM_RTS);
|
||||
}
|
||||
}
|
||||
|
||||
stm32_usart_rs485_rts_enable(port);
|
||||
|
||||
stm32_usart_transmit_chars(port);
|
||||
}
|
||||
|
||||
@ -1037,13 +1088,22 @@ static void stm32_usart_set_termios(struct uart_port *port,
|
||||
* CS8 or (CS7 + parity), 8 bits word aka [M1:M0] = 0b00
|
||||
* M0 and M1 already cleared by cr1 initialization.
|
||||
*/
|
||||
if (bits == 9)
|
||||
if (bits == 9) {
|
||||
cr1 |= USART_CR1_M0;
|
||||
else if ((bits == 7) && cfg->has_7bits_data)
|
||||
} else if ((bits == 7) && cfg->has_7bits_data) {
|
||||
cr1 |= USART_CR1_M1;
|
||||
else if (bits != 8)
|
||||
} else if (bits != 8) {
|
||||
dev_dbg(port->dev, "Unsupported data bits config: %u bits\n"
|
||||
, bits);
|
||||
cflag &= ~CSIZE;
|
||||
cflag |= CS8;
|
||||
termios->c_cflag = cflag;
|
||||
bits = 8;
|
||||
if (cflag & PARENB) {
|
||||
bits++;
|
||||
cr1 |= USART_CR1_M0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch ||
|
||||
(stm32_port->fifoen &&
|
||||
@ -1222,6 +1282,33 @@ static void stm32_usart_pm(struct uart_port *port, unsigned int state,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CONSOLE_POLL)
|
||||
|
||||
/* Callbacks for characters polling in debug context (i.e. KGDB). */
|
||||
static int stm32_usart_poll_init(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
|
||||
return clk_prepare_enable(stm32_port->clk);
|
||||
}
|
||||
|
||||
static int stm32_usart_poll_get_char(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
|
||||
if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_RXNE))
|
||||
return NO_POLL_CHAR;
|
||||
|
||||
return readl_relaxed(port->membase + ofs->rdr) & stm32_port->rdr_mask;
|
||||
}
|
||||
|
||||
static void stm32_usart_poll_put_char(struct uart_port *port, unsigned char ch)
|
||||
{
|
||||
stm32_usart_console_putchar(port, ch);
|
||||
}
|
||||
#endif /* CONFIG_CONSOLE_POLL */
|
||||
|
||||
static const struct uart_ops stm32_uart_ops = {
|
||||
.tx_empty = stm32_usart_tx_empty,
|
||||
.set_mctrl = stm32_usart_set_mctrl,
|
||||
@ -1243,6 +1330,11 @@ static const struct uart_ops stm32_uart_ops = {
|
||||
.request_port = stm32_usart_request_port,
|
||||
.config_port = stm32_usart_config_port,
|
||||
.verify_port = stm32_usart_verify_port,
|
||||
#if defined(CONFIG_CONSOLE_POLL)
|
||||
.poll_init = stm32_usart_poll_init,
|
||||
.poll_get_char = stm32_usart_poll_get_char,
|
||||
.poll_put_char = stm32_usart_poll_put_char,
|
||||
#endif /* CONFIG_CONSOLE_POLL */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1640,18 +1732,24 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_STM32_CONSOLE
|
||||
static void stm32_usart_console_putchar(struct uart_port *port, unsigned char ch)
|
||||
static void __maybe_unused stm32_usart_console_putchar(struct uart_port *port, unsigned char ch)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
u32 isr;
|
||||
int ret;
|
||||
|
||||
while (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE))
|
||||
cpu_relax();
|
||||
|
||||
ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, isr,
|
||||
(isr & USART_SR_TXE), 100,
|
||||
STM32_USART_TIMEOUT_USEC);
|
||||
if (ret != 0) {
|
||||
dev_err(port->dev, "Error while sending data in UART TX : %d\n", ret);
|
||||
return;
|
||||
}
|
||||
writel_relaxed(ch, port->membase + ofs->tdr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_STM32_CONSOLE
|
||||
static void stm32_usart_console_write(struct console *co, const char *s,
|
||||
unsigned int cnt)
|
||||
{
|
||||
@ -1727,6 +1825,57 @@ static struct console stm32_console = {
|
||||
#define STM32_SERIAL_CONSOLE NULL
|
||||
#endif /* CONFIG_SERIAL_STM32_CONSOLE */
|
||||
|
||||
#ifdef CONFIG_SERIAL_EARLYCON
|
||||
static void early_stm32_usart_console_putchar(struct uart_port *port, unsigned char ch)
|
||||
{
|
||||
struct stm32_usart_info *info = port->private_data;
|
||||
|
||||
while (!(readl_relaxed(port->membase + info->ofs.isr) & USART_SR_TXE))
|
||||
cpu_relax();
|
||||
|
||||
writel_relaxed(ch, port->membase + info->ofs.tdr);
|
||||
}
|
||||
|
||||
static void early_stm32_serial_write(struct console *console, const char *s, unsigned int count)
|
||||
{
|
||||
struct earlycon_device *device = console->data;
|
||||
struct uart_port *port = &device->port;
|
||||
|
||||
uart_console_write(port, s, count, early_stm32_usart_console_putchar);
|
||||
}
|
||||
|
||||
static int __init early_stm32_h7_serial_setup(struct earlycon_device *device, const char *options)
|
||||
{
|
||||
if (!(device->port.membase || device->port.iobase))
|
||||
return -ENODEV;
|
||||
device->port.private_data = &stm32h7_info;
|
||||
device->con->write = early_stm32_serial_write;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init early_stm32_f7_serial_setup(struct earlycon_device *device, const char *options)
|
||||
{
|
||||
if (!(device->port.membase || device->port.iobase))
|
||||
return -ENODEV;
|
||||
device->port.private_data = &stm32f7_info;
|
||||
device->con->write = early_stm32_serial_write;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init early_stm32_f4_serial_setup(struct earlycon_device *device, const char *options)
|
||||
{
|
||||
if (!(device->port.membase || device->port.iobase))
|
||||
return -ENODEV;
|
||||
device->port.private_data = &stm32f4_info;
|
||||
device->con->write = early_stm32_serial_write;
|
||||
return 0;
|
||||
}
|
||||
|
||||
OF_EARLYCON_DECLARE(stm32, "st,stm32h7-uart", early_stm32_h7_serial_setup);
|
||||
OF_EARLYCON_DECLARE(stm32, "st,stm32f7-uart", early_stm32_f7_serial_setup);
|
||||
OF_EARLYCON_DECLARE(stm32, "st,stm32-uart", early_stm32_f4_serial_setup);
|
||||
#endif /* CONFIG_SERIAL_EARLYCON */
|
||||
|
||||
static struct uart_driver stm32_usart_driver = {
|
||||
.driver_name = DRIVER_NAME,
|
||||
.dev_name = STM32_SERIAL_NAME,
|
||||
|
@ -251,6 +251,8 @@ struct stm32_usart_info stm32h7_info = {
|
||||
#define RX_BUF_P (RX_BUF_L / 2) /* dma rx buffer period */
|
||||
#define TX_BUF_L RX_BUF_L /* dma tx buffer length */
|
||||
|
||||
#define STM32_USART_TIMEOUT_USEC USEC_PER_SEC /* 1s timeout in µs */
|
||||
|
||||
struct stm32_port {
|
||||
struct uart_port port;
|
||||
struct clk *clk;
|
||||
@ -269,6 +271,7 @@ struct stm32_port {
|
||||
bool hw_flow_control;
|
||||
bool swap; /* swap RX & TX pins */
|
||||
bool fifoen;
|
||||
bool txdone;
|
||||
int rxftcfg; /* RX FIFO threshold CFG */
|
||||
int txftcfg; /* TX FIFO threshold CFG */
|
||||
bool wakeup_src;
|
||||
|
@ -498,7 +498,7 @@ static const struct uart_ops sunplus_uart_ops = {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE
|
||||
struct sunplus_uart_port *sunplus_console_ports[SUP_UART_NR];
|
||||
static struct sunplus_uart_port *sunplus_console_ports[SUP_UART_NR];
|
||||
|
||||
static void sunplus_uart_console_putchar(struct uart_port *port,
|
||||
unsigned char ch)
|
||||
|
@ -798,10 +798,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
|
||||
cval |= UART_LCR_PARITY;
|
||||
if (!(cflag & PARODD))
|
||||
cval |= UART_LCR_EPAR;
|
||||
#ifdef CMSPAR
|
||||
if (cflag & CMSPAR)
|
||||
cval |= UART_LCR_SPAR;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Work around a bug in the Oxford Semiconductor 952 rev B
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user