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:
@@ -23,7 +23,9 @@ properties:
|
|||||||
- fsl,imx8qxp-lpuart
|
- fsl,imx8qxp-lpuart
|
||||||
- fsl,imxrt1050-lpuart
|
- fsl,imxrt1050-lpuart
|
||||||
- items:
|
- items:
|
||||||
- const: fsl,imx8ulp-lpuart
|
- enum:
|
||||||
|
- fsl,imx93-lpuart
|
||||||
|
- fsl,imx8ulp-lpuart
|
||||||
- const: fsl,imx7ulp-lpuart
|
- const: fsl,imx7ulp-lpuart
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- 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:
|
maintainers:
|
||||||
- Magnus Damm <magnus.damm@gmail.com>
|
- Magnus Damm <magnus.damm@gmail.com>
|
||||||
|
|
||||||
allOf:
|
|
||||||
- $ref: serial.yaml#
|
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
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:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
@@ -23,10 +27,31 @@ properties:
|
|||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
clocks:
|
clocks:
|
||||||
maxItems: 1
|
minItems: 1
|
||||||
|
items:
|
||||||
|
- description: UART functional clock
|
||||||
|
- description: Internal clock to access the registers
|
||||||
|
|
||||||
clock-names:
|
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:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
|
|||||||
@@ -51,10 +51,16 @@ properties:
|
|||||||
- renesas,hscif-r8a77980 # R-Car V3H
|
- renesas,hscif-r8a77980 # R-Car V3H
|
||||||
- renesas,hscif-r8a77990 # R-Car E3
|
- renesas,hscif-r8a77990 # R-Car E3
|
||||||
- renesas,hscif-r8a77995 # R-Car D3
|
- 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,rcar-gen3-hscif # R-Car Gen3 and RZ/G2
|
||||||
- const: renesas,hscif # generic HSCIF compatible UART
|
- 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:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
@@ -113,6 +119,7 @@ if:
|
|||||||
enum:
|
enum:
|
||||||
- renesas,rcar-gen2-hscif
|
- renesas,rcar-gen2-hscif
|
||||||
- renesas,rcar-gen3-hscif
|
- renesas,rcar-gen3-hscif
|
||||||
|
- renesas,rcar-gen4-hscif
|
||||||
then:
|
then:
|
||||||
required:
|
required:
|
||||||
- resets
|
- resets
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ properties:
|
|||||||
- renesas,scif-r8a77980 # R-Car V3H
|
- renesas,scif-r8a77980 # R-Car V3H
|
||||||
- renesas,scif-r8a77990 # R-Car E3
|
- renesas,scif-r8a77990 # R-Car E3
|
||||||
- renesas,scif-r8a77995 # R-Car D3
|
- 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,rcar-gen3-scif # R-Car Gen3 and RZ/G2
|
||||||
- const: renesas,scif # generic SCIF compatible UART
|
- const: renesas,scif # generic SCIF compatible UART
|
||||||
|
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
|
- renesas,scif-r8a779a0 # R-Car V3U
|
||||||
- renesas,scif-r8a779f0 # R-Car S4-8
|
- renesas,scif-r8a779f0 # R-Car S4-8
|
||||||
- const: renesas,rcar-gen4-scif # R-Car Gen4
|
- const: renesas,rcar-gen4-scif # R-Car Gen4
|
||||||
- const: renesas,scif # generic SCIF compatible UART
|
- const: renesas,scif # generic SCIF compatible UART
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ properties:
|
|||||||
description: drive RTS low when sending (default is high).
|
description: drive RTS low when sending (default is high).
|
||||||
$ref: /schemas/types.yaml#/definitions/flag
|
$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:
|
linux,rs485-enabled-at-boot-time:
|
||||||
description: enables the rs485 feature at boot time. It can be disabled
|
description: enables the rs485 feature at boot time. It can be disabled
|
||||||
later with proper ioctl.
|
later with proper ioctl.
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ properties:
|
|||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
clocks:
|
clocks:
|
||||||
minItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
resets:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
auto-flow-control:
|
auto-flow-control:
|
||||||
description: enable automatic flow control support.
|
description: enable automatic flow control support.
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ available subsections can be seen below.
|
|||||||
surface_aggregator/index
|
surface_aggregator/index
|
||||||
switchtec
|
switchtec
|
||||||
sync_file
|
sync_file
|
||||||
|
tty/index
|
||||||
vfio-mediated-device
|
vfio-mediated-device
|
||||||
vfio
|
vfio
|
||||||
vfio-pci-device-specific-driver-acceptance
|
vfio-pci-device-specific-driver-acceptance
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ hardware.
|
|||||||
This call must not sleep
|
This call must not sleep
|
||||||
|
|
||||||
set_ldisc(port,termios)
|
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
|
Locking: caller holds tty_port->mutex
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ Serial drivers
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
moxa-smartio
|
|
||||||
n_gsm
|
|
||||||
serial-iso7816
|
serial-iso7816
|
||||||
serial-rs485
|
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_struct
|
||||||
tty_ldisc
|
tty_ldisc
|
||||||
tty_buffer
|
tty_buffer
|
||||||
n_tty
|
|
||||||
tty_internals
|
tty_internals
|
||||||
|
|
||||||
Writing TTY Driver
|
Writing TTY Driver
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Before one starts writing a TTY driver, they must consider
|
Before one starts writing a TTY driver, they must consider
|
||||||
:doc:`Serial <../driver-api/serial/driver>` and :doc:`USB Serial
|
:doc:`Serial <../serial/driver>` and :doc:`USB Serial <../../usb/usb-serial>`
|
||||||
<../usb/usb-serial>` layers
|
layers first. Drivers for serial devices can often use one of these specific
|
||||||
first. Drivers for serial devices can often use one of these specific layers to
|
layers to implement a serial driver. Only special devices should be handled
|
||||||
implement a serial driver. Only special devices should be handled directly by
|
directly by the TTY Layer. If you are about to write such a driver, read on.
|
||||||
the TTY Layer. If you are about to write such a driver, read on.
|
|
||||||
|
|
||||||
A *typical* sequence a TTY driver performs is as follows:
|
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
|
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_driver`. For the other two (devices handling), look into
|
||||||
:doc:`tty_port`.
|
: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
|
See Documentation/firmware-guide/acpi/gpio-properties.rst for more information
|
||||||
about the _DSD binding related to GPIOs.
|
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
|
MFD devices
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,6 @@ needed).
|
|||||||
misc-devices/index
|
misc-devices/index
|
||||||
scheduler/index
|
scheduler/index
|
||||||
mhi/index
|
mhi/index
|
||||||
tty/index
|
|
||||||
peci/index
|
peci/index
|
||||||
|
|
||||||
Architecture-agnostic documentation
|
Architecture-agnostic documentation
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ fit into other categories.
|
|||||||
isl29003
|
isl29003
|
||||||
lis3lv02d
|
lis3lv02d
|
||||||
max6875
|
max6875
|
||||||
|
oxsemi-tornado
|
||||||
pci-endpoint-test
|
pci-endpoint-test
|
||||||
spear-pcie-gadget
|
spear-pcie-gadget
|
||||||
uacce
|
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
|
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
|
||||||
M: Jiri Slaby <jirislaby@kernel.org>
|
M: Jiri Slaby <jirislaby@kernel.org>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/driver-api/serial/moxa-smartio.rst
|
F: Documentation/driver-api/tty/moxa-smartio.rst
|
||||||
F: drivers/tty/mxser.*
|
F: drivers/tty/mxser.*
|
||||||
|
|
||||||
MR800 AVERMEDIA USB FM RADIO DRIVER
|
MR800 AVERMEDIA USB FM RADIO DRIVER
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
#ifndef _ALPHA_TERMBITS_H
|
#ifndef _ALPHA_TERMBITS_H
|
||||||
#define _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;
|
typedef unsigned int tcflag_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -53,76 +51,58 @@ struct ktermios {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* c_cc characters */
|
/* c_cc characters */
|
||||||
#define VEOF 0
|
#define VEOF 0
|
||||||
#define VEOL 1
|
#define VEOL 1
|
||||||
#define VEOL2 2
|
#define VEOL2 2
|
||||||
#define VERASE 3
|
#define VERASE 3
|
||||||
#define VWERASE 4
|
#define VWERASE 4
|
||||||
#define VKILL 5
|
#define VKILL 5
|
||||||
#define VREPRINT 6
|
#define VREPRINT 6
|
||||||
#define VSWTC 7
|
#define VSWTC 7
|
||||||
#define VINTR 8
|
#define VINTR 8
|
||||||
#define VQUIT 9
|
#define VQUIT 9
|
||||||
#define VSUSP 10
|
#define VSUSP 10
|
||||||
#define VSTART 12
|
#define VSTART 12
|
||||||
#define VSTOP 13
|
#define VSTOP 13
|
||||||
#define VLNEXT 14
|
#define VLNEXT 14
|
||||||
#define VDISCARD 15
|
#define VDISCARD 15
|
||||||
#define VMIN 16
|
#define VMIN 16
|
||||||
#define VTIME 17
|
#define VTIME 17
|
||||||
|
|
||||||
/* c_iflag bits */
|
/* c_iflag bits */
|
||||||
#define IGNBRK 0000001
|
#define IXON 0x0200
|
||||||
#define BRKINT 0000002
|
#define IXOFF 0x0400
|
||||||
#define IGNPAR 0000004
|
#define IUCLC 0x1000
|
||||||
#define PARMRK 0000010
|
#define IMAXBEL 0x2000
|
||||||
#define INPCK 0000020
|
#define IUTF8 0x4000
|
||||||
#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
|
|
||||||
|
|
||||||
/* c_oflag bits */
|
/* c_oflag bits */
|
||||||
#define OPOST 0000001
|
#define ONLCR 0x00002
|
||||||
#define ONLCR 0000002
|
#define OLCUC 0x00004
|
||||||
#define OLCUC 0000004
|
#define NLDLY 0x00300
|
||||||
|
#define NL0 0x00000
|
||||||
#define OCRNL 0000010
|
#define NL1 0x00100
|
||||||
#define ONOCR 0000020
|
#define NL2 0x00200
|
||||||
#define ONLRET 0000040
|
#define NL3 0x00300
|
||||||
|
#define TABDLY 0x00c00
|
||||||
#define OFILL 00000100
|
#define TAB0 0x00000
|
||||||
#define OFDEL 00000200
|
#define TAB1 0x00400
|
||||||
#define NLDLY 00001400
|
#define TAB2 0x00800
|
||||||
#define NL0 00000000
|
#define TAB3 0x00c00
|
||||||
#define NL1 00000400
|
#define CRDLY 0x03000
|
||||||
#define NL2 00001000
|
#define CR0 0x00000
|
||||||
#define NL3 00001400
|
#define CR1 0x01000
|
||||||
#define TABDLY 00006000
|
#define CR2 0x02000
|
||||||
#define TAB0 00000000
|
#define CR3 0x03000
|
||||||
#define TAB1 00002000
|
#define FFDLY 0x04000
|
||||||
#define TAB2 00004000
|
#define FF0 0x00000
|
||||||
#define TAB3 00006000
|
#define FF1 0x04000
|
||||||
#define CRDLY 00030000
|
#define BSDLY 0x08000
|
||||||
#define CR0 00000000
|
#define BS0 0x00000
|
||||||
#define CR1 00010000
|
#define BS1 0x08000
|
||||||
#define CR2 00020000
|
#define VTDLY 0x10000
|
||||||
#define CR3 00030000
|
#define VT0 0x00000
|
||||||
#define FFDLY 00040000
|
#define VT1 0x10000
|
||||||
#define FF0 00000000
|
|
||||||
#define FF1 00040000
|
|
||||||
#define BSDLY 00100000
|
|
||||||
#define BS0 00000000
|
|
||||||
#define BS1 00100000
|
|
||||||
#define VTDLY 00200000
|
|
||||||
#define VT0 00000000
|
|
||||||
#define VT1 00200000
|
|
||||||
/*
|
/*
|
||||||
* Should be equivalent to TAB3, see description of TAB3 in
|
* Should be equivalent to TAB3, see description of TAB3 in
|
||||||
* POSIX.1-2008, Ch. 11.2.3 "Output Modes"
|
* POSIX.1-2008, Ch. 11.2.3 "Output Modes"
|
||||||
@@ -130,61 +110,36 @@ struct ktermios {
|
|||||||
#define XTABS TAB3
|
#define XTABS TAB3
|
||||||
|
|
||||||
/* c_cflag bit meaning */
|
/* c_cflag bit meaning */
|
||||||
#define CBAUD 0000037
|
#define CBAUD 0x0000001f
|
||||||
#define B0 0000000 /* hang up */
|
#define CBAUDEX 0x00000000
|
||||||
#define B50 0000001
|
#define BOTHER 0x0000001f
|
||||||
#define B75 0000002
|
#define B57600 0x00000010
|
||||||
#define B110 0000003
|
#define B115200 0x00000011
|
||||||
#define B134 0000004
|
#define B230400 0x00000012
|
||||||
#define B150 0000005
|
#define B460800 0x00000013
|
||||||
#define B200 0000006
|
#define B500000 0x00000014
|
||||||
#define B300 0000007
|
#define B576000 0x00000015
|
||||||
#define B600 0000010
|
#define B921600 0x00000016
|
||||||
#define B1200 0000011
|
#define B1000000 0x00000017
|
||||||
#define B1800 0000012
|
#define B1152000 0x00000018
|
||||||
#define B2400 0000013
|
#define B1500000 0x00000019
|
||||||
#define B4800 0000014
|
#define B2000000 0x0000001a
|
||||||
#define B9600 0000015
|
#define B2500000 0x0000001b
|
||||||
#define B19200 0000016
|
#define B3000000 0x0000001c
|
||||||
#define B38400 0000017
|
#define B3500000 0x0000001d
|
||||||
#define EXTA B19200
|
#define B4000000 0x0000001e
|
||||||
#define EXTB B38400
|
#define CSIZE 0x00000300
|
||||||
#define CBAUDEX 0000000
|
#define CS5 0x00000000
|
||||||
#define B57600 00020
|
#define CS6 0x00000100
|
||||||
#define B115200 00021
|
#define CS7 0x00000200
|
||||||
#define B230400 00022
|
#define CS8 0x00000300
|
||||||
#define B460800 00023
|
#define CSTOPB 0x00000400
|
||||||
#define B500000 00024
|
#define CREAD 0x00000800
|
||||||
#define B576000 00025
|
#define PARENB 0x00001000
|
||||||
#define B921600 00026
|
#define PARODD 0x00002000
|
||||||
#define B1000000 00027
|
#define HUPCL 0x00004000
|
||||||
#define B1152000 00030
|
#define CLOCAL 0x00008000
|
||||||
#define B1500000 00031
|
#define CIBAUD 0x001f0000
|
||||||
#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
|
|
||||||
|
|
||||||
/* c_lflag bits */
|
/* c_lflag bits */
|
||||||
#define ISIG 0x00000080
|
#define ISIG 0x00000080
|
||||||
@@ -204,17 +159,6 @@ struct ktermios {
|
|||||||
#define IEXTEN 0x00000400
|
#define IEXTEN 0x00000400
|
||||||
#define EXTPROC 0x10000000
|
#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'. */
|
/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */
|
||||||
#define TCSANOW 0
|
#define TCSANOW 0
|
||||||
#define TCSADRAIN 1
|
#define TCSADRAIN 1
|
||||||
|
|||||||
@@ -11,11 +11,9 @@
|
|||||||
#ifndef _ASM_TERMBITS_H
|
#ifndef _ASM_TERMBITS_H
|
||||||
#define _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 tcflag_t;
|
||||||
typedef unsigned int speed_t;
|
|
||||||
typedef unsigned int tcflag_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The ABI says nothing about NCC but seems to use NCCS as
|
* The ABI says nothing about NCC but seems to use NCCS as
|
||||||
@@ -54,175 +52,126 @@ struct ktermios {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* c_cc characters */
|
/* c_cc characters */
|
||||||
#define VINTR 0 /* Interrupt character [ISIG]. */
|
#define VINTR 0 /* Interrupt character [ISIG] */
|
||||||
#define VQUIT 1 /* Quit character [ISIG]. */
|
#define VQUIT 1 /* Quit character [ISIG] */
|
||||||
#define VERASE 2 /* Erase character [ICANON]. */
|
#define VERASE 2 /* Erase character [ICANON] */
|
||||||
#define VKILL 3 /* Kill-line character [ICANON]. */
|
#define VKILL 3 /* Kill-line character [ICANON] */
|
||||||
#define VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */
|
#define VMIN 4 /* Minimum number of bytes read at once [!ICANON] */
|
||||||
#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */
|
#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON] */
|
||||||
#define VEOL2 6 /* Second EOL character [ICANON]. */
|
#define VEOL2 6 /* Second EOL character [ICANON] */
|
||||||
#define VSWTC 7 /* ??? */
|
#define VSWTC 7 /* ??? */
|
||||||
#define VSWTCH VSWTC
|
#define VSWTCH VSWTC
|
||||||
#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF]. */
|
#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF] */
|
||||||
#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF]. */
|
#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF] */
|
||||||
#define VSUSP 10 /* Suspend character [ISIG]. */
|
#define VSUSP 10 /* Suspend character [ISIG] */
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* VDSUSP is not supported
|
* VDSUSP is not supported
|
||||||
*/
|
*/
|
||||||
#define VDSUSP 11 /* Delayed suspend character [ISIG]. */
|
#define VDSUSP 11 /* Delayed suspend character [ISIG] */
|
||||||
#endif
|
#endif
|
||||||
#define VREPRINT 12 /* Reprint-line character [ICANON]. */
|
#define VREPRINT 12 /* Reprint-line character [ICANON] */
|
||||||
#define VDISCARD 13 /* Discard character [IEXTEN]. */
|
#define VDISCARD 13 /* Discard character [IEXTEN] */
|
||||||
#define VWERASE 14 /* Word-erase character [ICANON]. */
|
#define VWERASE 14 /* Word-erase character [ICANON] */
|
||||||
#define VLNEXT 15 /* Literal-next character [IEXTEN]. */
|
#define VLNEXT 15 /* Literal-next character [IEXTEN] */
|
||||||
#define VEOF 16 /* End-of-file character [ICANON]. */
|
#define VEOF 16 /* End-of-file character [ICANON] */
|
||||||
#define VEOL 17 /* End-of-line character [ICANON]. */
|
#define VEOL 17 /* End-of-line character [ICANON] */
|
||||||
|
|
||||||
/* c_iflag bits */
|
/* c_iflag bits */
|
||||||
#define IGNBRK 0000001 /* Ignore break condition. */
|
#define IUCLC 0x0200 /* Map upper case to lower case on input */
|
||||||
#define BRKINT 0000002 /* Signal interrupt on break. */
|
#define IXON 0x0400 /* Enable start/stop output control */
|
||||||
#define IGNPAR 0000004 /* Ignore characters with parity errors. */
|
#define IXOFF 0x1000 /* Enable start/stop input control */
|
||||||
#define PARMRK 0000010 /* Mark parity and framing errors. */
|
#define IMAXBEL 0x2000 /* Ring bell when input queue is full */
|
||||||
#define INPCK 0000020 /* Enable input parity check. */
|
#define IUTF8 0x4000 /* Input is UTF-8 */
|
||||||
#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 */
|
|
||||||
|
|
||||||
/* c_oflag bits */
|
/* c_oflag bits */
|
||||||
#define OPOST 0000001 /* Perform output processing. */
|
#define OLCUC 0x00002 /* Map lower case to upper case on output */
|
||||||
#define OLCUC 0000002 /* Map lower case to upper case on output. */
|
#define ONLCR 0x00004 /* Map NL to CR-NL on output */
|
||||||
#define ONLCR 0000004 /* Map NL to CR-NL on output. */
|
#define NLDLY 0x00100
|
||||||
#define OCRNL 0000010
|
#define NL0 0x00000
|
||||||
#define ONOCR 0000020
|
#define NL1 0x00100
|
||||||
#define ONLRET 0000040
|
#define CRDLY 0x00600
|
||||||
#define OFILL 0000100
|
#define CR0 0x00000
|
||||||
#define OFDEL 0000200
|
#define CR1 0x00200
|
||||||
#define NLDLY 0000400
|
#define CR2 0x00400
|
||||||
#define NL0 0000000
|
#define CR3 0x00600
|
||||||
#define NL1 0000400
|
#define TABDLY 0x01800
|
||||||
#define CRDLY 0003000
|
#define TAB0 0x00000
|
||||||
#define CR0 0000000
|
#define TAB1 0x00800
|
||||||
#define CR1 0001000
|
#define TAB2 0x01000
|
||||||
#define CR2 0002000
|
#define TAB3 0x01800
|
||||||
#define CR3 0003000
|
#define XTABS 0x01800
|
||||||
#define TABDLY 0014000
|
#define BSDLY 0x02000
|
||||||
#define TAB0 0000000
|
#define BS0 0x00000
|
||||||
#define TAB1 0004000
|
#define BS1 0x02000
|
||||||
#define TAB2 0010000
|
#define VTDLY 0x04000
|
||||||
#define TAB3 0014000
|
#define VT0 0x00000
|
||||||
#define XTABS 0014000
|
#define VT1 0x04000
|
||||||
#define BSDLY 0020000
|
#define FFDLY 0x08000
|
||||||
#define BS0 0000000
|
#define FF0 0x00000
|
||||||
#define BS1 0020000
|
#define FF1 0x08000
|
||||||
#define VTDLY 0040000
|
|
||||||
#define VT0 0000000
|
|
||||||
#define VT1 0040000
|
|
||||||
#define FFDLY 0100000
|
|
||||||
#define FF0 0000000
|
|
||||||
#define FF1 0100000
|
|
||||||
/*
|
/*
|
||||||
#define PAGEOUT ???
|
#define PAGEOUT ???
|
||||||
#define WRAP ???
|
#define WRAP ???
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* c_cflag bit meaning */
|
/* c_cflag bit meaning */
|
||||||
#define CBAUD 0010017
|
#define CBAUD 0x0000100f
|
||||||
#define B0 0000000 /* hang up */
|
#define CSIZE 0x00000030 /* Number of bits per byte (mask) */
|
||||||
#define B50 0000001
|
#define CS5 0x00000000 /* 5 bits per byte */
|
||||||
#define B75 0000002
|
#define CS6 0x00000010 /* 6 bits per byte */
|
||||||
#define B110 0000003
|
#define CS7 0x00000020 /* 7 bits per byte */
|
||||||
#define B134 0000004
|
#define CS8 0x00000030 /* 8 bits per byte */
|
||||||
#define B150 0000005
|
#define CSTOPB 0x00000040 /* Two stop bits instead of one */
|
||||||
#define B200 0000006
|
#define CREAD 0x00000080 /* Enable receiver */
|
||||||
#define B300 0000007
|
#define PARENB 0x00000100 /* Parity enable */
|
||||||
#define B600 0000010
|
#define PARODD 0x00000200 /* Odd parity instead of even */
|
||||||
#define B1200 0000011
|
#define HUPCL 0x00000400 /* Hang up on last close */
|
||||||
#define B1800 0000012
|
#define CLOCAL 0x00000800 /* Ignore modem status lines */
|
||||||
#define B2400 0000013
|
#define CBAUDEX 0x00001000
|
||||||
#define B4800 0000014
|
#define BOTHER 0x00001000
|
||||||
#define B9600 0000015
|
#define B57600 0x00001001
|
||||||
#define B19200 0000016
|
#define B115200 0x00001002
|
||||||
#define B38400 0000017
|
#define B230400 0x00001003
|
||||||
#define EXTA B19200
|
#define B460800 0x00001004
|
||||||
#define EXTB B38400
|
#define B500000 0x00001005
|
||||||
#define CSIZE 0000060 /* Number of bits per byte (mask). */
|
#define B576000 0x00001006
|
||||||
#define CS5 0000000 /* 5 bits per byte. */
|
#define B921600 0x00001007
|
||||||
#define CS6 0000020 /* 6 bits per byte. */
|
#define B1000000 0x00001008
|
||||||
#define CS7 0000040 /* 7 bits per byte. */
|
#define B1152000 0x00001009
|
||||||
#define CS8 0000060 /* 8 bits per byte. */
|
#define B1500000 0x0000100a
|
||||||
#define CSTOPB 0000100 /* Two stop bits instead of one. */
|
#define B2000000 0x0000100b
|
||||||
#define CREAD 0000200 /* Enable receiver. */
|
#define B2500000 0x0000100c
|
||||||
#define PARENB 0000400 /* Parity enable. */
|
#define B3000000 0x0000100d
|
||||||
#define PARODD 0001000 /* Odd parity instead of even. */
|
#define B3500000 0x0000100e
|
||||||
#define HUPCL 0002000 /* Hang up on last close. */
|
#define B4000000 0x0000100f
|
||||||
#define CLOCAL 0004000 /* Ignore modem status lines. */
|
#define CIBAUD 0x100f0000 /* input baud rate */
|
||||||
#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 */
|
|
||||||
|
|
||||||
/* c_lflag bits */
|
/* c_lflag bits */
|
||||||
#define ISIG 0000001 /* Enable signals. */
|
#define ISIG 0x00001 /* Enable signals */
|
||||||
#define ICANON 0000002 /* Do erase and kill processing. */
|
#define ICANON 0x00002 /* Do erase and kill processing */
|
||||||
#define XCASE 0000004
|
#define XCASE 0x00004
|
||||||
#define ECHO 0000010 /* Enable echo. */
|
#define ECHO 0x00008 /* Enable echo */
|
||||||
#define ECHOE 0000020 /* Visual erase for ERASE. */
|
#define ECHOE 0x00010 /* Visual erase for ERASE */
|
||||||
#define ECHOK 0000040 /* Echo NL after KILL. */
|
#define ECHOK 0x00020 /* Echo NL after KILL */
|
||||||
#define ECHONL 0000100 /* Echo NL even if ECHO is off. */
|
#define ECHONL 0x00040 /* Echo NL even if ECHO is off */
|
||||||
#define NOFLSH 0000200 /* Disable flush after interrupt. */
|
#define NOFLSH 0x00080 /* Disable flush after interrupt */
|
||||||
#define IEXTEN 0000400 /* Enable DISCARD and LNEXT. */
|
#define IEXTEN 0x00100 /* Enable DISCARD and LNEXT */
|
||||||
#define ECHOCTL 0001000 /* Echo control characters as ^X. */
|
#define ECHOCTL 0x00200 /* Echo control characters as ^X */
|
||||||
#define ECHOPRT 0002000 /* Hardcopy visual erase. */
|
#define ECHOPRT 0x00400 /* Hardcopy visual erase */
|
||||||
#define ECHOKE 0004000 /* Visual erase for KILL. */
|
#define ECHOKE 0x00800 /* Visual erase for KILL */
|
||||||
#define FLUSHO 0020000
|
#define FLUSHO 0x02000
|
||||||
#define PENDIN 0040000 /* Retype pending input (state). */
|
#define PENDIN 0x04000 /* Retype pending input (state) */
|
||||||
#define TOSTOP 0100000 /* Send SIGTTOU for background output. */
|
#define TOSTOP 0x08000 /* Send SIGTTOU for background output */
|
||||||
#define ITOSTOP TOSTOP
|
#define ITOSTOP TOSTOP
|
||||||
#define EXTPROC 0200000 /* External processing on pty */
|
#define EXTPROC 0x10000 /* External processing on pty */
|
||||||
|
|
||||||
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
|
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
#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 */
|
/* tcsetattr uses these */
|
||||||
#define TCSANOW TCSETS /* Change immediately. */
|
#define TCSANOW TCSETS /* Change immediately */
|
||||||
#define TCSADRAIN TCSETSW /* Change when pending output is written. */
|
#define TCSADRAIN TCSETSW /* Change when pending output is written */
|
||||||
#define TCSAFLUSH TCSETSF /* Flush pending input before changing. */
|
#define TCSAFLUSH TCSETSF /* Flush pending input before changing */
|
||||||
|
|
||||||
#endif /* _ASM_TERMBITS_H */
|
#endif /* _ASM_TERMBITS_H */
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
#ifndef __ARCH_PARISC_TERMBITS_H__
|
#ifndef __ARCH_PARISC_TERMBITS_H__
|
||||||
#define __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;
|
typedef unsigned int tcflag_t;
|
||||||
|
|
||||||
#define NCCS 19
|
#define NCCS 19
|
||||||
@@ -41,158 +39,107 @@ struct ktermios {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* c_cc characters */
|
/* c_cc characters */
|
||||||
#define VINTR 0
|
#define VINTR 0
|
||||||
#define VQUIT 1
|
#define VQUIT 1
|
||||||
#define VERASE 2
|
#define VERASE 2
|
||||||
#define VKILL 3
|
#define VKILL 3
|
||||||
#define VEOF 4
|
#define VEOF 4
|
||||||
#define VTIME 5
|
#define VTIME 5
|
||||||
#define VMIN 6
|
#define VMIN 6
|
||||||
#define VSWTC 7
|
#define VSWTC 7
|
||||||
#define VSTART 8
|
#define VSTART 8
|
||||||
#define VSTOP 9
|
#define VSTOP 9
|
||||||
#define VSUSP 10
|
#define VSUSP 10
|
||||||
#define VEOL 11
|
#define VEOL 11
|
||||||
#define VREPRINT 12
|
#define VREPRINT 12
|
||||||
#define VDISCARD 13
|
#define VDISCARD 13
|
||||||
#define VWERASE 14
|
#define VWERASE 14
|
||||||
#define VLNEXT 15
|
#define VLNEXT 15
|
||||||
#define VEOL2 16
|
#define VEOL2 16
|
||||||
|
|
||||||
|
|
||||||
/* c_iflag bits */
|
/* c_iflag bits */
|
||||||
#define IGNBRK 0000001
|
#define IUCLC 0x0200
|
||||||
#define BRKINT 0000002
|
#define IXON 0x0400
|
||||||
#define IGNPAR 0000004
|
#define IXOFF 0x1000
|
||||||
#define PARMRK 0000010
|
#define IMAXBEL 0x4000
|
||||||
#define INPCK 0000020
|
#define IUTF8 0x8000
|
||||||
#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
|
|
||||||
|
|
||||||
/* c_oflag bits */
|
/* c_oflag bits */
|
||||||
#define OPOST 0000001
|
#define OLCUC 0x00002
|
||||||
#define OLCUC 0000002
|
#define ONLCR 0x00004
|
||||||
#define ONLCR 0000004
|
#define NLDLY 0x00100
|
||||||
#define OCRNL 0000010
|
#define NL0 0x00000
|
||||||
#define ONOCR 0000020
|
#define NL1 0x00100
|
||||||
#define ONLRET 0000040
|
#define CRDLY 0x00600
|
||||||
#define OFILL 0000100
|
#define CR0 0x00000
|
||||||
#define OFDEL 0000200
|
#define CR1 0x00200
|
||||||
#define NLDLY 0000400
|
#define CR2 0x00400
|
||||||
#define NL0 0000000
|
#define CR3 0x00600
|
||||||
#define NL1 0000400
|
#define TABDLY 0x01800
|
||||||
#define CRDLY 0003000
|
#define TAB0 0x00000
|
||||||
#define CR0 0000000
|
#define TAB1 0x00800
|
||||||
#define CR1 0001000
|
#define TAB2 0x01000
|
||||||
#define CR2 0002000
|
#define TAB3 0x01800
|
||||||
#define CR3 0003000
|
#define XTABS 0x01800
|
||||||
#define TABDLY 0014000
|
#define BSDLY 0x02000
|
||||||
#define TAB0 0000000
|
#define BS0 0x00000
|
||||||
#define TAB1 0004000
|
#define BS1 0x02000
|
||||||
#define TAB2 0010000
|
#define VTDLY 0x04000
|
||||||
#define TAB3 0014000
|
#define VT0 0x00000
|
||||||
#define XTABS 0014000
|
#define VT1 0x04000
|
||||||
#define BSDLY 0020000
|
#define FFDLY 0x08000
|
||||||
#define BS0 0000000
|
#define FF0 0x00000
|
||||||
#define BS1 0020000
|
#define FF1 0x08000
|
||||||
#define VTDLY 0040000
|
|
||||||
#define VT0 0000000
|
|
||||||
#define VT1 0040000
|
|
||||||
#define FFDLY 0100000
|
|
||||||
#define FF0 0000000
|
|
||||||
#define FF1 0100000
|
|
||||||
|
|
||||||
/* c_cflag bit meaning */
|
/* c_cflag bit meaning */
|
||||||
#define CBAUD 0010017
|
#define CBAUD 0x0000100f
|
||||||
#define B0 0000000 /* hang up */
|
#define CSIZE 0x00000030
|
||||||
#define B50 0000001
|
#define CS5 0x00000000
|
||||||
#define B75 0000002
|
#define CS6 0x00000010
|
||||||
#define B110 0000003
|
#define CS7 0x00000020
|
||||||
#define B134 0000004
|
#define CS8 0x00000030
|
||||||
#define B150 0000005
|
#define CSTOPB 0x00000040
|
||||||
#define B200 0000006
|
#define CREAD 0x00000080
|
||||||
#define B300 0000007
|
#define PARENB 0x00000100
|
||||||
#define B600 0000010
|
#define PARODD 0x00000200
|
||||||
#define B1200 0000011
|
#define HUPCL 0x00000400
|
||||||
#define B1800 0000012
|
#define CLOCAL 0x00000800
|
||||||
#define B2400 0000013
|
#define CBAUDEX 0x00001000
|
||||||
#define B4800 0000014
|
#define BOTHER 0x00001000
|
||||||
#define B9600 0000015
|
#define B57600 0x00001001
|
||||||
#define B19200 0000016
|
#define B115200 0x00001002
|
||||||
#define B38400 0000017
|
#define B230400 0x00001003
|
||||||
#define EXTA B19200
|
#define B460800 0x00001004
|
||||||
#define EXTB B38400
|
#define B500000 0x00001005
|
||||||
#define CSIZE 0000060
|
#define B576000 0x00001006
|
||||||
#define CS5 0000000
|
#define B921600 0x00001007
|
||||||
#define CS6 0000020
|
#define B1000000 0x00001008
|
||||||
#define CS7 0000040
|
#define B1152000 0x00001009
|
||||||
#define CS8 0000060
|
#define B1500000 0x0000100a
|
||||||
#define CSTOPB 0000100
|
#define B2000000 0x0000100b
|
||||||
#define CREAD 0000200
|
#define B2500000 0x0000100c
|
||||||
#define PARENB 0000400
|
#define B3000000 0x0000100d
|
||||||
#define PARODD 0001000
|
#define B3500000 0x0000100e
|
||||||
#define HUPCL 0002000
|
#define B4000000 0x0000100f
|
||||||
#define CLOCAL 0004000
|
#define CIBAUD 0x100f0000 /* input baud rate */
|
||||||
#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 */
|
|
||||||
|
|
||||||
|
|
||||||
/* c_lflag bits */
|
/* c_lflag bits */
|
||||||
#define ISIG 0000001
|
#define ISIG 0x00001
|
||||||
#define ICANON 0000002
|
#define ICANON 0x00002
|
||||||
#define XCASE 0000004
|
#define XCASE 0x00004
|
||||||
#define ECHO 0000010
|
#define ECHO 0x00008
|
||||||
#define ECHOE 0000020
|
#define ECHOE 0x00010
|
||||||
#define ECHOK 0000040
|
#define ECHOK 0x00020
|
||||||
#define ECHONL 0000100
|
#define ECHONL 0x00040
|
||||||
#define NOFLSH 0000200
|
#define NOFLSH 0x00080
|
||||||
#define TOSTOP 0000400
|
#define TOSTOP 0x00100
|
||||||
#define ECHOCTL 0001000
|
#define ECHOCTL 0x00200
|
||||||
#define ECHOPRT 0002000
|
#define ECHOPRT 0x00400
|
||||||
#define ECHOKE 0004000
|
#define ECHOKE 0x00800
|
||||||
#define FLUSHO 0010000
|
#define FLUSHO 0x01000
|
||||||
#define PENDIN 0040000
|
#define PENDIN 0x04000
|
||||||
#define IEXTEN 0100000
|
#define IEXTEN 0x08000
|
||||||
#define EXTPROC 0200000
|
#define EXTPROC 0x10000
|
||||||
|
|
||||||
/* 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 */
|
/* tcsetattr uses these */
|
||||||
#define TCSANOW 0
|
#define TCSANOW 0
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
* 2 of the License, or (at your option) any later version.
|
* 2 of the License, or (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef unsigned char cc_t;
|
#include <asm-generic/termbits-common.h>
|
||||||
typedef unsigned int speed_t;
|
|
||||||
typedef unsigned int tcflag_t;
|
typedef unsigned int tcflag_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -64,115 +64,72 @@ struct ktermios {
|
|||||||
#define VDISCARD 16
|
#define VDISCARD 16
|
||||||
|
|
||||||
/* c_iflag bits */
|
/* c_iflag bits */
|
||||||
#define IGNBRK 0000001
|
#define IXON 0x0200
|
||||||
#define BRKINT 0000002
|
#define IXOFF 0x0400
|
||||||
#define IGNPAR 0000004
|
#define IUCLC 0x1000
|
||||||
#define PARMRK 0000010
|
#define IMAXBEL 0x2000
|
||||||
#define INPCK 0000020
|
#define IUTF8 0x4000
|
||||||
#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
|
|
||||||
|
|
||||||
/* c_oflag bits */
|
/* c_oflag bits */
|
||||||
#define OPOST 0000001
|
#define ONLCR 0x00002
|
||||||
#define ONLCR 0000002
|
#define OLCUC 0x00004
|
||||||
#define OLCUC 0000004
|
#define NLDLY 0x00300
|
||||||
|
#define NL0 0x00000
|
||||||
#define OCRNL 0000010
|
#define NL1 0x00100
|
||||||
#define ONOCR 0000020
|
#define NL2 0x00200
|
||||||
#define ONLRET 0000040
|
#define NL3 0x00300
|
||||||
|
#define TABDLY 0x00c00
|
||||||
#define OFILL 00000100
|
#define TAB0 0x00000
|
||||||
#define OFDEL 00000200
|
#define TAB1 0x00400
|
||||||
#define NLDLY 00001400
|
#define TAB2 0x00800
|
||||||
#define NL0 00000000
|
#define TAB3 0x00c00
|
||||||
#define NL1 00000400
|
#define XTABS 0x00c00 /* required by POSIX to == TAB3 */
|
||||||
#define NL2 00001000
|
#define CRDLY 0x03000
|
||||||
#define NL3 00001400
|
#define CR0 0x00000
|
||||||
#define TABDLY 00006000
|
#define CR1 0x01000
|
||||||
#define TAB0 00000000
|
#define CR2 0x02000
|
||||||
#define TAB1 00002000
|
#define CR3 0x03000
|
||||||
#define TAB2 00004000
|
#define FFDLY 0x04000
|
||||||
#define TAB3 00006000
|
#define FF0 0x00000
|
||||||
#define XTABS 00006000 /* required by POSIX to == TAB3 */
|
#define FF1 0x04000
|
||||||
#define CRDLY 00030000
|
#define BSDLY 0x08000
|
||||||
#define CR0 00000000
|
#define BS0 0x00000
|
||||||
#define CR1 00010000
|
#define BS1 0x08000
|
||||||
#define CR2 00020000
|
#define VTDLY 0x10000
|
||||||
#define CR3 00030000
|
#define VT0 0x00000
|
||||||
#define FFDLY 00040000
|
#define VT1 0x10000
|
||||||
#define FF0 00000000
|
|
||||||
#define FF1 00040000
|
|
||||||
#define BSDLY 00100000
|
|
||||||
#define BS0 00000000
|
|
||||||
#define BS1 00100000
|
|
||||||
#define VTDLY 00200000
|
|
||||||
#define VT0 00000000
|
|
||||||
#define VT1 00200000
|
|
||||||
|
|
||||||
/* c_cflag bit meaning */
|
/* c_cflag bit meaning */
|
||||||
#define CBAUD 0000377
|
#define CBAUD 0x000000ff
|
||||||
#define B0 0000000 /* hang up */
|
#define CBAUDEX 0x00000000
|
||||||
#define B50 0000001
|
#define BOTHER 0x0000001f
|
||||||
#define B75 0000002
|
#define B57600 0x00000010
|
||||||
#define B110 0000003
|
#define B115200 0x00000011
|
||||||
#define B134 0000004
|
#define B230400 0x00000012
|
||||||
#define B150 0000005
|
#define B460800 0x00000013
|
||||||
#define B200 0000006
|
#define B500000 0x00000014
|
||||||
#define B300 0000007
|
#define B576000 0x00000015
|
||||||
#define B600 0000010
|
#define B921600 0x00000016
|
||||||
#define B1200 0000011
|
#define B1000000 0x00000017
|
||||||
#define B1800 0000012
|
#define B1152000 0x00000018
|
||||||
#define B2400 0000013
|
#define B1500000 0x00000019
|
||||||
#define B4800 0000014
|
#define B2000000 0x0000001a
|
||||||
#define B9600 0000015
|
#define B2500000 0x0000001b
|
||||||
#define B19200 0000016
|
#define B3000000 0x0000001c
|
||||||
#define B38400 0000017
|
#define B3500000 0x0000001d
|
||||||
#define EXTA B19200
|
#define B4000000 0x0000001e
|
||||||
#define EXTB B38400
|
#define CSIZE 0x00000300
|
||||||
#define CBAUDEX 0000000
|
#define CS5 0x00000000
|
||||||
#define B57600 00020
|
#define CS6 0x00000100
|
||||||
#define B115200 00021
|
#define CS7 0x00000200
|
||||||
#define B230400 00022
|
#define CS8 0x00000300
|
||||||
#define B460800 00023
|
#define CSTOPB 0x00000400
|
||||||
#define B500000 00024
|
#define CREAD 0x00000800
|
||||||
#define B576000 00025
|
#define PARENB 0x00001000
|
||||||
#define B921600 00026
|
#define PARODD 0x00002000
|
||||||
#define B1000000 00027
|
#define HUPCL 0x00004000
|
||||||
#define B1152000 00030
|
#define CLOCAL 0x00008000
|
||||||
#define B1500000 00031
|
#define CIBAUD 0x00ff0000
|
||||||
#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 */
|
|
||||||
|
|
||||||
/* c_lflag bits */
|
/* c_lflag bits */
|
||||||
#define ISIG 0x00000080
|
#define ISIG 0x00000080
|
||||||
@@ -192,17 +149,6 @@ struct ktermios {
|
|||||||
#define IEXTEN 0x00000400
|
#define IEXTEN 0x00000400
|
||||||
#define EXTPROC 0x10000000
|
#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'. */
|
/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */
|
||||||
#define TCSANOW 0
|
#define TCSANOW 0
|
||||||
#define TCSADRAIN 1
|
#define TCSADRAIN 1
|
||||||
|
|||||||
@@ -2,15 +2,12 @@
|
|||||||
#ifndef _UAPI_SPARC_TERMBITS_H
|
#ifndef _UAPI_SPARC_TERMBITS_H
|
||||||
#define _UAPI_SPARC_TERMBITS_H
|
#define _UAPI_SPARC_TERMBITS_H
|
||||||
|
|
||||||
#include <linux/posix_types.h>
|
#include <asm-generic/termbits-common.h>
|
||||||
|
|
||||||
typedef unsigned char cc_t;
|
|
||||||
typedef unsigned int speed_t;
|
|
||||||
|
|
||||||
#if defined(__sparc__) && defined(__arch64__)
|
#if defined(__sparc__) && defined(__arch64__)
|
||||||
typedef unsigned int tcflag_t;
|
typedef unsigned int tcflag_t;
|
||||||
#else
|
#else
|
||||||
typedef unsigned long tcflag_t;
|
typedef unsigned long tcflag_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NCC 8
|
#define NCC 8
|
||||||
@@ -61,21 +58,19 @@ struct ktermios {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* c_cc characters */
|
/* c_cc characters */
|
||||||
#define VINTR 0
|
#define VINTR 0
|
||||||
#define VQUIT 1
|
#define VQUIT 1
|
||||||
#define VERASE 2
|
#define VERASE 2
|
||||||
#define VKILL 3
|
#define VKILL 3
|
||||||
#define VEOF 4
|
#define VEOF 4
|
||||||
#define VEOL 5
|
#define VEOL 5
|
||||||
#define VEOL2 6
|
#define VEOL2 6
|
||||||
#define VSWTC 7
|
#define VSWTC 7
|
||||||
#define VSTART 8
|
#define VSTART 8
|
||||||
#define VSTOP 9
|
#define VSTOP 9
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VSUSP 10
|
#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 VREPRINT 12
|
||||||
#define VDISCARD 13
|
#define VDISCARD 13
|
||||||
#define VWERASE 14
|
#define VWERASE 14
|
||||||
@@ -90,121 +85,83 @@ struct ktermios {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* c_iflag bits */
|
/* c_iflag bits */
|
||||||
#define IGNBRK 0x00000001
|
#define IUCLC 0x0200
|
||||||
#define BRKINT 0x00000002
|
#define IXON 0x0400
|
||||||
#define IGNPAR 0x00000004
|
#define IXOFF 0x1000
|
||||||
#define PARMRK 0x00000008
|
#define IMAXBEL 0x2000
|
||||||
#define INPCK 0x00000010
|
#define IUTF8 0x4000
|
||||||
#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
|
|
||||||
|
|
||||||
/* c_oflag bits */
|
/* c_oflag bits */
|
||||||
#define OPOST 0x00000001
|
#define OLCUC 0x00002
|
||||||
#define OLCUC 0x00000002
|
#define ONLCR 0x00004
|
||||||
#define ONLCR 0x00000004
|
#define NLDLY 0x00100
|
||||||
#define OCRNL 0x00000008
|
#define NL0 0x00000
|
||||||
#define ONOCR 0x00000010
|
#define NL1 0x00100
|
||||||
#define ONLRET 0x00000020
|
#define CRDLY 0x00600
|
||||||
#define OFILL 0x00000040
|
#define CR0 0x00000
|
||||||
#define OFDEL 0x00000080
|
#define CR1 0x00200
|
||||||
#define NLDLY 0x00000100
|
#define CR2 0x00400
|
||||||
#define NL0 0x00000000
|
#define CR3 0x00600
|
||||||
#define NL1 0x00000100
|
#define TABDLY 0x01800
|
||||||
#define CRDLY 0x00000600
|
#define TAB0 0x00000
|
||||||
#define CR0 0x00000000
|
#define TAB1 0x00800
|
||||||
#define CR1 0x00000200
|
#define TAB2 0x01000
|
||||||
#define CR2 0x00000400
|
#define TAB3 0x01800
|
||||||
#define CR3 0x00000600
|
#define XTABS 0x01800
|
||||||
#define TABDLY 0x00001800
|
#define BSDLY 0x02000
|
||||||
#define TAB0 0x00000000
|
#define BS0 0x00000
|
||||||
#define TAB1 0x00000800
|
#define BS1 0x02000
|
||||||
#define TAB2 0x00001000
|
#define VTDLY 0x04000
|
||||||
#define TAB3 0x00001800
|
#define VT0 0x00000
|
||||||
#define XTABS 0x00001800
|
#define VT1 0x04000
|
||||||
#define BSDLY 0x00002000
|
#define FFDLY 0x08000
|
||||||
#define BS0 0x00000000
|
#define FF0 0x00000
|
||||||
#define BS1 0x00002000
|
#define FF1 0x08000
|
||||||
#define VTDLY 0x00004000
|
#define PAGEOUT 0x10000 /* SUNOS specific */
|
||||||
#define VT0 0x00000000
|
#define WRAP 0x20000 /* SUNOS specific */
|
||||||
#define VT1 0x00004000
|
|
||||||
#define FFDLY 0x00008000
|
|
||||||
#define FF0 0x00000000
|
|
||||||
#define FF1 0x00008000
|
|
||||||
#define PAGEOUT 0x00010000 /* SUNOS specific */
|
|
||||||
#define WRAP 0x00020000 /* SUNOS specific */
|
|
||||||
|
|
||||||
/* c_cflag bit meaning */
|
/* c_cflag bit meaning */
|
||||||
#define CBAUD 0x0000100f
|
#define CBAUD 0x0000100f
|
||||||
#define B0 0x00000000 /* hang up */
|
#define CSIZE 0x00000030
|
||||||
#define B50 0x00000001
|
#define CS5 0x00000000
|
||||||
#define B75 0x00000002
|
#define CS6 0x00000010
|
||||||
#define B110 0x00000003
|
#define CS7 0x00000020
|
||||||
#define B134 0x00000004
|
#define CS8 0x00000030
|
||||||
#define B150 0x00000005
|
#define CSTOPB 0x00000040
|
||||||
#define B200 0x00000006
|
#define CREAD 0x00000080
|
||||||
#define B300 0x00000007
|
#define PARENB 0x00000100
|
||||||
#define B600 0x00000008
|
#define PARODD 0x00000200
|
||||||
#define B1200 0x00000009
|
#define HUPCL 0x00000400
|
||||||
#define B1800 0x0000000a
|
#define CLOCAL 0x00000800
|
||||||
#define B2400 0x0000000b
|
#define CBAUDEX 0x00001000
|
||||||
#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
|
|
||||||
/* We'll never see these speeds with the Zilogs, but for completeness... */
|
/* We'll never see these speeds with the Zilogs, but for completeness... */
|
||||||
#define BOTHER 0x00001000
|
#define BOTHER 0x00001000
|
||||||
#define B57600 0x00001001
|
#define B57600 0x00001001
|
||||||
#define B115200 0x00001002
|
#define B115200 0x00001002
|
||||||
#define B230400 0x00001003
|
#define B230400 0x00001003
|
||||||
#define B460800 0x00001004
|
#define B460800 0x00001004
|
||||||
/* This is what we can do with the Zilogs. */
|
/* This is what we can do with the Zilogs. */
|
||||||
#define B76800 0x00001005
|
#define B76800 0x00001005
|
||||||
/* This is what we can do with the SAB82532. */
|
/* This is what we can do with the SAB82532. */
|
||||||
#define B153600 0x00001006
|
#define B153600 0x00001006
|
||||||
#define B307200 0x00001007
|
#define B307200 0x00001007
|
||||||
#define B614400 0x00001008
|
#define B614400 0x00001008
|
||||||
#define B921600 0x00001009
|
#define B921600 0x00001009
|
||||||
/* And these are the rest... */
|
/* And these are the rest... */
|
||||||
#define B500000 0x0000100a
|
#define B500000 0x0000100a
|
||||||
#define B576000 0x0000100b
|
#define B576000 0x0000100b
|
||||||
#define B1000000 0x0000100c
|
#define B1000000 0x0000100c
|
||||||
#define B1152000 0x0000100d
|
#define B1152000 0x0000100d
|
||||||
#define B1500000 0x0000100e
|
#define B1500000 0x0000100e
|
||||||
#define B2000000 0x0000100f
|
#define B2000000 0x0000100f
|
||||||
/* These have totally bogus values and nobody uses them
|
/* These have totally bogus values and nobody uses them
|
||||||
so far. Later on we'd have to use say 0x10000x and
|
so far. Later on we'd have to use say 0x10000x and
|
||||||
adjust CBAUD constant and drivers accordingly.
|
adjust CBAUD constant and drivers accordingly.
|
||||||
#define B2500000 0x00001010
|
#define B2500000 0x00001010
|
||||||
#define B3000000 0x00001011
|
#define B3000000 0x00001011
|
||||||
#define B3500000 0x00001012
|
#define B3500000 0x00001012
|
||||||
#define B4000000 0x00001013 */
|
#define B4000000 0x00001013 */
|
||||||
#define CIBAUD 0x100f0000 /* input baud rate (not used) */
|
#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 */
|
|
||||||
|
|
||||||
/* c_lflag bits */
|
/* c_lflag bits */
|
||||||
#define ISIG 0x00000001
|
#define ISIG 0x00000001
|
||||||
@@ -219,7 +176,7 @@ struct ktermios {
|
|||||||
#define ECHOCTL 0x00000200
|
#define ECHOCTL 0x00000200
|
||||||
#define ECHOPRT 0x00000400
|
#define ECHOPRT 0x00000400
|
||||||
#define ECHOKE 0x00000800
|
#define ECHOKE 0x00000800
|
||||||
#define DEFECHO 0x00001000 /* SUNOS thing, what is it? */
|
#define DEFECHO 0x00001000 /* SUNOS thing, what is it? */
|
||||||
#define FLUSHO 0x00002000
|
#define FLUSHO 0x00002000
|
||||||
#define PENDIN 0x00004000
|
#define PENDIN 0x00004000
|
||||||
#define IEXTEN 0x00008000
|
#define IEXTEN 0x00008000
|
||||||
@@ -244,21 +201,9 @@ struct ktermios {
|
|||||||
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
|
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
#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 */
|
/* tcsetattr uses these */
|
||||||
#define TCSANOW 0
|
#define TCSANOW 0
|
||||||
#define TCSADRAIN 1
|
#define TCSADRAIN 1
|
||||||
#define TCSAFLUSH 2
|
#define TCSAFLUSH 2
|
||||||
|
|
||||||
#endif /* _UAPI_SPARC_TERMBITS_H */
|
#endif /* _UAPI_SPARC_TERMBITS_H */
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ config TTY_PRINTK
|
|||||||
The feature is useful to inline user messages with kernel
|
The feature is useful to inline user messages with kernel
|
||||||
messages.
|
messages.
|
||||||
In order to use this feature, you should output user 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.
|
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);
|
info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR);
|
||||||
|
|
||||||
/* byte size and parity */
|
/* 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);
|
info->params.data_bits = tty_get_char_size(cflag);
|
||||||
|
|
||||||
if (cflag & CSTOPB)
|
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;
|
info->params.parity = ASYNC_PARITY_ODD;
|
||||||
else
|
else
|
||||||
info->params.parity = ASYNC_PARITY_EVEN;
|
info->params.parity = ASYNC_PARITY_EVEN;
|
||||||
#ifdef CMSPAR
|
|
||||||
if (cflag & CMSPAR)
|
if (cflag & CMSPAR)
|
||||||
info->params.parity = ASYNC_PARITY_SPACE;
|
info->params.parity = ASYNC_PARITY_SPACE;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate number of jiffies to transmit a full
|
/* calculate number of jiffies to transmit a full
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
* of the boot process, for example.
|
* of the boot process, for example.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/console.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/tty.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_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)
|
static int __init ttyprintk_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -195,6 +208,8 @@ static int __init ttyprintk_init(void)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register_console(&ttyprintk_console);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -205,6 +220,7 @@ error:
|
|||||||
|
|
||||||
static void __exit ttyprintk_exit(void)
|
static void __exit ttyprintk_exit(void)
|
||||||
{
|
{
|
||||||
|
unregister_console(&ttyprintk_console);
|
||||||
tty_unregister_driver(ttyprintk_driver);
|
tty_unregister_driver(ttyprintk_driver);
|
||||||
tty_driver_kref_put(ttyprintk_driver);
|
tty_driver_kref_put(ttyprintk_driver);
|
||||||
tty_port_destroy(&tpk_port.port);
|
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))
|
if (!(cflag & PARODD))
|
||||||
cval |= UART_LCR_EPAR;
|
cval |= UART_LCR_EPAR;
|
||||||
#ifdef CMSPAR
|
|
||||||
if (cflag & CMSPAR)
|
if (cflag & CMSPAR)
|
||||||
cval |= UART_LCR_SPAR;
|
cval |= UART_LCR_SPAR;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Determine divisor based on baud rate */
|
/* Determine divisor based on baud rate */
|
||||||
baud = tty_get_baud_rate(tty);
|
baud = tty_get_baud_rate(tty);
|
||||||
|
|||||||
@@ -405,6 +405,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
|
|||||||
err_tty_register_device_failed:
|
err_tty_register_device_failed:
|
||||||
free_irq(irq, qtty);
|
free_irq(irq, qtty);
|
||||||
err_dec_line_count:
|
err_dec_line_count:
|
||||||
|
tty_port_destroy(&qtty->port);
|
||||||
goldfish_tty_current_line_count--;
|
goldfish_tty_current_line_count--;
|
||||||
if (goldfish_tty_current_line_count == 0)
|
if (goldfish_tty_current_line_count == 0)
|
||||||
goldfish_tty_delete_driver();
|
goldfish_tty_delete_driver();
|
||||||
@@ -426,6 +427,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
|
|||||||
iounmap(qtty->base);
|
iounmap(qtty->base);
|
||||||
qtty->base = NULL;
|
qtty->base = NULL;
|
||||||
free_irq(qtty->irq, pdev);
|
free_irq(qtty->irq, pdev);
|
||||||
|
tty_port_destroy(&qtty->port);
|
||||||
goldfish_tty_current_line_count--;
|
goldfish_tty_current_line_count--;
|
||||||
if (goldfish_tty_current_line_count == 0)
|
if (goldfish_tty_current_line_count == 0)
|
||||||
goldfish_tty_delete_driver();
|
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
|
driver. This console is used through a JTAG only on ARM. If you don't have
|
||||||
a JTAG then you probably don't want this option.
|
a JTAG then you probably don't want this option.
|
||||||
|
|
||||||
|
config HVC_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
|
config HVC_RISCV_SBI
|
||||||
bool "RISC-V SBI console support"
|
bool "RISC-V SBI console support"
|
||||||
depends on RISCV_SBI_V01
|
depends on RISCV_SBI_V01
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/* Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. */
|
/* Copyright (c) 2010, 2014, 2022 The Linux Foundation. All rights reserved. */
|
||||||
|
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/cpumask.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/kfifo.h>
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
#include <asm/dcc.h>
|
#include <asm/dcc.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
@@ -15,6 +20,15 @@
|
|||||||
#define DCC_STATUS_RX (1 << 30)
|
#define DCC_STATUS_RX (1 << 30)
|
||||||
#define DCC_STATUS_TX (1 << 29)
|
#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)
|
static void dcc_uart_console_putchar(struct uart_port *port, unsigned char ch)
|
||||||
{
|
{
|
||||||
while (__dcc_getstatus() & DCC_STATUS_TX)
|
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;
|
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)
|
static bool hvc_dcc_check(void)
|
||||||
{
|
{
|
||||||
unsigned long time = jiffies + (HZ / 10);
|
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 */
|
/* Write a test character to check if it is handled */
|
||||||
__dcc_putchar('\n');
|
__dcc_putchar('\n');
|
||||||
|
|
||||||
while (time_is_after_jiffies(time)) {
|
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 true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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 = {
|
static const struct hv_ops hvc_dcc_get_put_ops = {
|
||||||
.get_chars = hvc_dcc_get_chars,
|
.get_chars = hvc_dcc0_get_chars,
|
||||||
.put_chars = hvc_dcc_put_chars,
|
.put_chars = hvc_dcc0_put_chars,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init hvc_dcc_console_init(void)
|
static int __init hvc_dcc_console_init(void)
|
||||||
@@ -108,6 +274,26 @@ static int __init hvc_dcc_init(void)
|
|||||||
if (!hvc_dcc_check())
|
if (!hvc_dcc_check())
|
||||||
return -ENODEV;
|
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);
|
p = hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
|
||||||
|
|
||||||
return PTR_ERR_OR_ZERO(p);
|
return PTR_ERR_OR_ZERO(p);
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
#include <asm/hvconsole.h>
|
#include <asm/hvconsole.h>
|
||||||
#include <asm/prom.h>
|
|
||||||
#include <asm/firmware.h>
|
#include <asm/firmware.h>
|
||||||
#include <asm/hvsi.h>
|
#include <asm/hvsi.h>
|
||||||
#include <asm/udbg.h>
|
#include <asm/udbg.h>
|
||||||
@@ -342,9 +342,9 @@ void __init hvc_opal_init_early(void)
|
|||||||
* path, so we hard wire it
|
* path, so we hard wire it
|
||||||
*/
|
*/
|
||||||
opal = of_find_node_by_path("/ibm,opal/consoles");
|
opal = of_find_node_by_path("/ibm,opal/consoles");
|
||||||
if (opal)
|
if (opal) {
|
||||||
pr_devel("hvc_opal: Found consoles in new location\n");
|
pr_devel("hvc_opal: Found consoles in new location\n");
|
||||||
if (!opal) {
|
} else {
|
||||||
opal = of_find_node_by_path("/ibm,opal");
|
opal = of_find_node_by_path("/ibm,opal");
|
||||||
if (opal)
|
if (opal)
|
||||||
pr_devel("hvc_opal: "
|
pr_devel("hvc_opal: "
|
||||||
|
|||||||
@@ -28,10 +28,10 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
#include <asm/hvconsole.h>
|
#include <asm/hvconsole.h>
|
||||||
#include <asm/vio.h>
|
#include <asm/vio.h>
|
||||||
#include <asm/prom.h>
|
|
||||||
#include <asm/hvsi.h>
|
#include <asm/hvsi.h>
|
||||||
#include <asm/udbg.h>
|
#include <asm/udbg.h>
|
||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
|
|||||||
@@ -581,10 +581,9 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
|
|||||||
|
|
||||||
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
||||||
/* This is synch -- FIXME :js: it is not! */
|
/* This is synch -- FIXME :js: it is not! */
|
||||||
if(got)
|
if (got)
|
||||||
tty_flip_buffer_push(&hvcsd->port);
|
tty_flip_buffer_push(&hvcsd->port);
|
||||||
|
else {
|
||||||
if (!got) {
|
|
||||||
/* Do this _after_ the flip_buffer_push */
|
/* Do this _after_ the flip_buffer_push */
|
||||||
spin_lock_irqsave(&hvcsd->lock, flags);
|
spin_lock_irqsave(&hvcsd->lock, flags);
|
||||||
vio_enable_interrupts(hvcsd->vdev);
|
vio_enable_interrupts(hvcsd->vdev);
|
||||||
|
|||||||
@@ -26,13 +26,13 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/major.h>
|
#include <linux/major.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/sysrq.h>
|
#include <linux/sysrq.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <asm/hvcall.h>
|
#include <asm/hvcall.h>
|
||||||
#include <asm/hvconsole.h>
|
#include <asm/hvconsole.h>
|
||||||
#include <asm/prom.h>
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/vio.h>
|
#include <asm/vio.h>
|
||||||
#include <asm/param.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(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */
|
||||||
outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
|
outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
|
||||||
|
|
||||||
#ifdef BOTHER
|
|
||||||
if (C_BAUD(tty) == BOTHER) {
|
if (C_BAUD(tty) == BOTHER) {
|
||||||
quot = MXSER_BAUD_BASE % newspd;
|
quot = MXSER_BAUD_BASE % newspd;
|
||||||
quot *= 8;
|
quot *= 8;
|
||||||
@@ -539,9 +538,9 @@ static int mxser_set_baud(struct tty_struct *tty, speed_t newspd)
|
|||||||
quot /= newspd;
|
quot /= newspd;
|
||||||
|
|
||||||
mxser_set_must_enum_value(info->ioaddr, quot);
|
mxser_set_must_enum_value(info->ioaddr, quot);
|
||||||
} else
|
} else {
|
||||||
#endif
|
|
||||||
mxser_set_must_enum_value(info->ioaddr, 0);
|
mxser_set_must_enum_value(info->ioaddr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -444,6 +444,25 @@ static u8 gsm_encode_modem(const struct gsm_dlci *dlci)
|
|||||||
return modembits;
|
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
|
* gsm_print_packet - display a frame for debug
|
||||||
* @hdr: header to print before decode
|
* @hdr: header to print before decode
|
||||||
@@ -508,7 +527,7 @@ static void gsm_print_packet(const char *hdr, int addr, int cr,
|
|||||||
else
|
else
|
||||||
pr_cont("(F)");
|
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)
|
if (debug & 4)
|
||||||
print_hex_dump_bytes("gsm_data_kick: ",
|
gsm_hex_dump_bytes(__func__, gsm->txframe, len);
|
||||||
DUMP_PREFIX_OFFSET,
|
|
||||||
gsm->txframe, len);
|
|
||||||
if (gsmld_output(gsm, gsm->txframe, len) <= 0)
|
if (gsmld_output(gsm, gsm->txframe, len) <= 0)
|
||||||
break;
|
break;
|
||||||
/* FIXME: Can eliminate one SOF in many more cases */
|
/* 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;
|
*--dp = msg->ctrl;
|
||||||
if (gsm->initiator)
|
if (gsm->initiator)
|
||||||
*--dp = (msg->addr << 2) | 2 | EA;
|
*--dp = (msg->addr << 2) | CR | EA;
|
||||||
else
|
else
|
||||||
*--dp = (msg->addr << 2) | EA;
|
*--dp = (msg->addr << 2) | EA;
|
||||||
*fcs = gsm_fcs_add_block(INIT_FCS, dp , msg->data - dp);
|
*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 UI|PF:
|
||||||
case UIH:
|
case UIH:
|
||||||
case UIH|PF:
|
case UIH|PF:
|
||||||
#if 0
|
|
||||||
if (cr)
|
|
||||||
goto invalid;
|
|
||||||
#endif
|
|
||||||
if (dlci == NULL || dlci->state != DLCI_OPEN) {
|
if (dlci == NULL || dlci->state != DLCI_OPEN) {
|
||||||
gsm_command(gsm, address, DM|PF);
|
gsm_command(gsm, address, DM|PF);
|
||||||
return;
|
return;
|
||||||
@@ -2448,8 +2461,7 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
|
|||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
if (debug & 4)
|
if (debug & 4)
|
||||||
print_hex_dump_bytes("gsmld_output: ", DUMP_PREFIX_OFFSET,
|
gsm_hex_dump_bytes(__func__, data, len);
|
||||||
data, len);
|
|
||||||
return gsm->tty->ops->write(gsm->tty, 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;
|
char flags = TTY_NORMAL;
|
||||||
|
|
||||||
if (debug & 4)
|
if (debug & 4)
|
||||||
print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
|
gsm_hex_dump_bytes(__func__, cp, count);
|
||||||
cp, count);
|
|
||||||
|
|
||||||
for (; count; count--, cp++) {
|
for (; count; count--, cp++) {
|
||||||
if (fp)
|
if (fp)
|
||||||
|
|||||||
@@ -1220,21 +1220,34 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c)
|
|||||||
process_echoes(tty);
|
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)
|
static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
|
||||||
{
|
{
|
||||||
struct n_tty_data *ldata = tty->disc_data;
|
struct n_tty_data *ldata = tty->disc_data;
|
||||||
|
|
||||||
if (I_IXON(tty)) {
|
if (I_IXON(tty) && n_tty_receive_char_flow_ctrl(tty, c))
|
||||||
if (c == START_CHAR(tty)) {
|
return;
|
||||||
start_tty(tty);
|
|
||||||
process_echoes(tty);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c == STOP_CHAR(tty)) {
|
|
||||||
stop_tty(tty);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (L_ISIG(tty)) {
|
if (L_ISIG(tty)) {
|
||||||
if (c == INTR_CHAR(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;
|
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
|
* job_control - check job control
|
||||||
* @tty: tty
|
* @tty: tty
|
||||||
@@ -2045,7 +2087,14 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
|
|||||||
*/
|
*/
|
||||||
if (*cookie) {
|
if (*cookie) {
|
||||||
if (ldata->icanon && !L_EXTPROC(tty)) {
|
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;
|
return kb - kbuf;
|
||||||
} else {
|
} else {
|
||||||
if (copy_from_read_buf(tty, &kb, &nr))
|
if (copy_from_read_buf(tty, &kb, &nr))
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
struct uart_8250_dma {
|
struct uart_8250_dma {
|
||||||
int (*tx_dma)(struct uart_8250_port *p);
|
int (*tx_dma)(struct uart_8250_port *p);
|
||||||
int (*rx_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 */
|
/* Filter function */
|
||||||
dma_filter_fn fn;
|
dma_filter_fn fn;
|
||||||
@@ -83,6 +85,7 @@ struct serial8250_config {
|
|||||||
#define UART_CAP_MINI BIT(17) /* Mini UART on BCM283X family lacks:
|
#define UART_CAP_MINI BIT(17) /* Mini UART on BCM283X family lacks:
|
||||||
* STOP PARITY EPAR SPAR WLEN5 WLEN6
|
* 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_QUOT BIT(0) /* UART has buggy quot LSB */
|
||||||
#define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */
|
#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);
|
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);
|
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
|
||||||
|
|
||||||
static inline int serial_dl_read(struct uart_8250_port *up)
|
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 void serial8250_rx_dma_flush(struct uart_8250_port *);
|
||||||
extern int serial8250_request_dma(struct uart_8250_port *);
|
extern int serial8250_request_dma(struct uart_8250_port *);
|
||||||
extern void serial8250_release_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
|
#else
|
||||||
static inline int serial8250_tx_dma(struct uart_8250_port *p)
|
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);
|
timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0);
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!res)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
memset(&port, 0, sizeof(port));
|
memset(&port, 0, sizeof(port));
|
||||||
port.port.private_data = vuart;
|
port.port.private_data = vuart;
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/pm_runtime.h>
|
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#ifdef CONFIG_SPARC
|
#ifdef CONFIG_SPARC
|
||||||
#include <linux/sunserialcore.h>
|
#include <linux/sunserialcore.h>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ static void __dma_tx_complete(void *param)
|
|||||||
uart_write_wakeup(&p->port);
|
uart_write_wakeup(&p->port);
|
||||||
|
|
||||||
ret = serial8250_tx_dma(p);
|
ret = serial8250_tx_dma(p);
|
||||||
if (ret)
|
if (ret || !dma->tx_running)
|
||||||
serial8250_set_THRI(p);
|
serial8250_set_THRI(p);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&p->port.lock, flags);
|
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)) {
|
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
|
||||||
/* We have been called from __dma_tx_complete() */
|
/* We have been called from __dma_tx_complete() */
|
||||||
serial8250_rpm_put_tx(p);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
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,
|
desc = dmaengine_prep_slave_single(dma->txchan,
|
||||||
dma->tx_addr + xmit->tail,
|
dma->tx_addr + xmit->tail,
|
||||||
dma->tx_size, DMA_MEM_TO_DEV,
|
dma->tx_size, DMA_MEM_TO_DEV,
|
||||||
@@ -123,6 +124,8 @@ int serial8250_rx_dma(struct uart_8250_port *p)
|
|||||||
if (dma->rx_running)
|
if (dma->rx_running)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
serial8250_do_prepare_rx_dma(p);
|
||||||
|
|
||||||
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
|
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
|
||||||
dma->rx_size, DMA_DEV_TO_MEM,
|
dma->rx_size, DMA_DEV_TO_MEM,
|
||||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/serial_8250.h>
|
#include <linux/serial_8250.h>
|
||||||
#include <linux/serial_reg.h>
|
#include <linux/serial_reg.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_irq.h>
|
|
||||||
#include <linux/of_platform.h>
|
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/property.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@@ -33,30 +33,28 @@
|
|||||||
|
|
||||||
/* Offsets for the DesignWare specific registers */
|
/* Offsets for the DesignWare specific registers */
|
||||||
#define DW_UART_USR 0x1f /* UART Status Register */
|
#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 */
|
/* DesignWare specific register fields */
|
||||||
#define DW_UART_MCR_SIRE BIT(6)
|
#define DW_UART_MCR_SIRE BIT(6)
|
||||||
|
|
||||||
struct dw8250_data {
|
/* Renesas specific register fields */
|
||||||
struct dw8250_port_data data;
|
#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;
|
/* Quirks */
|
||||||
int msr_mask_on;
|
#define DW_UART_QUIRK_OCTEON BIT(0)
|
||||||
int msr_mask_off;
|
#define DW_UART_QUIRK_ARMADA_38X BIT(1)
|
||||||
struct clk *clk;
|
#define DW_UART_QUIRK_SKIP_SET_RATE BIT(2)
|
||||||
struct clk *pclk;
|
#define DW_UART_QUIRK_IS_DMA_FC BIT(3)
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
|
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 uart_8250_port *up = up_to_u8250p(p);
|
||||||
struct dw8250_data *d = to_dw8250_data(p->private_data);
|
struct dw8250_data *d = to_dw8250_data(p->private_data);
|
||||||
unsigned int iir = p->serial_in(p, UART_IIR);
|
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 int status;
|
||||||
unsigned long flags;
|
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
|
* This problem has only been observed so far when not in DMA mode
|
||||||
* so we limit the workaround only to non-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);
|
spin_lock_irqsave(&p->lock, flags);
|
||||||
status = p->serial_in(p, UART_LSR);
|
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);
|
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))
|
if (serial8250_handle_irq(p, iir))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
|
if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
|
||||||
/* Clear the USR */
|
/* Clear the USR */
|
||||||
(void)p->serial_in(p, d->usr_reg);
|
(void)p->serial_in(p, d->pdata->usr_reg);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -384,11 +393,48 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
|
|||||||
return param == chan->device->dev;
|
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)
|
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
|
||||||
{
|
{
|
||||||
struct device_node *np = p->dev->of_node;
|
struct device_node *np = p->dev->of_node;
|
||||||
|
|
||||||
if (np) {
|
if (np) {
|
||||||
|
unsigned int quirks = data->pdata->quirks;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
/* get index of serial line, if found in DT aliases */
|
/* 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)
|
if (id >= 0)
|
||||||
p->line = id;
|
p->line = id;
|
||||||
#ifdef CONFIG_64BIT
|
#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_in = dw8250_serial_inq;
|
||||||
p->serial_out = dw8250_serial_outq;
|
p->serial_out = dw8250_serial_outq;
|
||||||
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
||||||
p->type = PORT_OCTEON;
|
p->type = PORT_OCTEON;
|
||||||
data->usr_reg = 0x27;
|
|
||||||
data->skip_autocfg = true;
|
data->skip_autocfg = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -412,10 +457,16 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
|
|||||||
p->serial_out = dw8250_serial_out32be;
|
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;
|
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;
|
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)) {
|
} else if (acpi_dev_present("APMC0D08", NULL, -1)) {
|
||||||
p->iotype = UPIO_MEM32;
|
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)
|
static int dw8250_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct uart_8250_port uart = {}, *up = &uart;
|
struct uart_8250_port uart = {}, *up = &uart;
|
||||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
struct uart_port *p = &up->port;
|
struct uart_port *p = &up->port;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct dw8250_data *data;
|
struct dw8250_data *data;
|
||||||
|
struct resource *regs;
|
||||||
int irq;
|
int irq;
|
||||||
int err;
|
int err;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
if (!regs) {
|
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
dev_err(dev, "no registers defined\n");
|
if (!regs)
|
||||||
return -EINVAL;
|
return dev_err_probe(dev, -EINVAL, "no registers defined\n");
|
||||||
}
|
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
@@ -476,7 +536,7 @@ static int dw8250_probe(struct platform_device *pdev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
data->data.dma.fn = dw8250_fallback_dma_filter;
|
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;
|
p->private_data = &data->data;
|
||||||
|
|
||||||
data->uart_16550_compatible = device_property_read_bool(dev,
|
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);
|
err = clk_prepare_enable(data->clk);
|
||||||
if (err)
|
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)
|
if (data->clk)
|
||||||
p->uartclk = clk_get_rate(data->clk);
|
p->uartclk = clk_get_rate(data->clk);
|
||||||
|
|
||||||
/* If no clock rate is defined, fail. */
|
/* If no clock rate is defined, fail. */
|
||||||
if (!p->uartclk) {
|
if (!p->uartclk)
|
||||||
dev_err(dev, "clock rate not defined\n");
|
return dev_err_probe(dev, -EINVAL, "clock rate not defined\n");
|
||||||
err = -EINVAL;
|
|
||||||
goto err_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->pclk = devm_clk_get_optional(dev, "apb_pclk");
|
data->pclk = devm_clk_get_optional(dev, "apb_pclk");
|
||||||
if (IS_ERR(data->pclk)) {
|
if (IS_ERR(data->pclk))
|
||||||
err = PTR_ERR(data->pclk);
|
return PTR_ERR(data->pclk);
|
||||||
goto err_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = clk_prepare_enable(data->pclk);
|
err = clk_prepare_enable(data->pclk);
|
||||||
if (err) {
|
if (err)
|
||||||
dev_err(dev, "could not enable apb_pclk\n");
|
return dev_err_probe(dev, err, "could not enable apb_pclk\n");
|
||||||
goto err_clk;
|
|
||||||
}
|
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);
|
data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
|
||||||
if (IS_ERR(data->rst)) {
|
if (IS_ERR(data->rst))
|
||||||
err = PTR_ERR(data->rst);
|
return PTR_ERR(data->rst);
|
||||||
goto err_pclk;
|
|
||||||
}
|
|
||||||
reset_control_deassert(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);
|
dw8250_quirks(p, data);
|
||||||
|
|
||||||
/* If the Busy Functionality is not implemented, don't handle it */
|
/* 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);
|
data->data.line = serial8250_register_8250_port(up);
|
||||||
if (data->data.line < 0) {
|
if (data->data.line < 0)
|
||||||
err = data->data.line;
|
return data->data.line;
|
||||||
goto err_reset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some platforms may provide a reference clock shared between several
|
* 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) {
|
if (data->clk) {
|
||||||
err = clk_notifier_register(data->clk, &data->clk_notifier);
|
err = clk_notifier_register(data->clk, &data->clk_notifier);
|
||||||
if (err)
|
if (err)
|
||||||
dev_warn(p->dev, "Failed to set the clock notifier\n");
|
return dev_err_probe(dev, err, "Failed to set the clock notifier\n");
|
||||||
else
|
queue_work(system_unbound_wq, &data->clk_work);
|
||||||
queue_work(system_unbound_wq, &data->clk_work);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, data);
|
platform_set_drvdata(pdev, data);
|
||||||
@@ -604,17 +665,6 @@ static int dw8250_probe(struct platform_device *pdev)
|
|||||||
pm_runtime_enable(dev);
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
return 0;
|
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)
|
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);
|
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_disable(dev);
|
||||||
pm_runtime_put_noidle(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)
|
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[] = {
|
static const struct of_device_id dw8250_of_match[] = {
|
||||||
{ .compatible = "snps,dw-apb-uart" },
|
{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
|
||||||
{ .compatible = "cavium,octeon-3860-uart" },
|
{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
|
||||||
{ .compatible = "marvell,armada-38x-uart" },
|
{ .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
|
||||||
{ .compatible = "renesas,rzn1-uart" },
|
{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
|
||||||
{ .compatible = "starfive,jh7100-uart" },
|
{ .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data },
|
||||||
{ /* Sentinel */ }
|
{ /* Sentinel */ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
||||||
|
|||||||
@@ -2,19 +2,32 @@
|
|||||||
/* Synopsys DesignWare 8250 library. */
|
/* Synopsys DesignWare 8250 library. */
|
||||||
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/property.h>
|
||||||
#include <linux/serial_8250.h>
|
#include <linux/serial_8250.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
|
||||||
#include "8250_dwlib.h"
|
#include "8250_dwlib.h"
|
||||||
|
|
||||||
/* Offsets for the DesignWare specific registers */
|
/* 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_DLF 0xc0 /* Divisor Latch Fraction Register */
|
||||||
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
|
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
|
||||||
#define DW_UART_UCV 0xf8 /* UART Component Version */
|
#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 */
|
/* Component Parameter Register bits */
|
||||||
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
|
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
|
||||||
#define DW_UART_CPR_AFCE_MODE (1 << 4)
|
#define DW_UART_CPR_AFCE_MODE (1 << 4)
|
||||||
@@ -32,21 +45,6 @@
|
|||||||
/* Helper for FIFO size calculation */
|
/* Helper for FIFO size calculation */
|
||||||
#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16)
|
#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)
|
* divisor = div(I) + div(F)
|
||||||
* "I" means integer, "F" means fractional
|
* "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);
|
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)
|
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);
|
struct uart_8250_port *up = up_to_u8250p(p);
|
||||||
u32 reg;
|
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
|
* If the Component Version Register returns zero, we know that
|
||||||
* ADDITIONAL_FEATURES are not enabled. No need to go any further.
|
* 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);
|
dw8250_writel_ext(p, DW_UART_DLF, 0);
|
||||||
|
|
||||||
if (reg) {
|
if (reg) {
|
||||||
struct dw8250_port_data *d = p->private_data;
|
pd->dlf_size = fls(reg);
|
||||||
|
|
||||||
d->dlf_size = fls(reg);
|
|
||||||
p->get_divisor = dw8250_get_divisor;
|
p->get_divisor = dw8250_get_divisor;
|
||||||
p->set_divisor = dw8250_set_divisor;
|
p->set_divisor = dw8250_set_divisor;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg = dw8250_readl_ext(p, DW_UART_CPR);
|
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)
|
if (!reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -124,7 +200,7 @@ void dw8250_setup_port(struct uart_port *p)
|
|||||||
p->type = PORT_16550A;
|
p->type = PORT_16550A;
|
||||||
p->flags |= UPF_FIXED_TYPE;
|
p->flags |= UPF_FIXED_TYPE;
|
||||||
p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
|
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)
|
if (reg & DW_UART_CPR_AFCE_MODE)
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
/* Synopsys DesignWare 8250 library header file. */
|
/* Synopsys DesignWare 8250 library header file. */
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/notifier.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
#include "8250.h"
|
#include "8250.h"
|
||||||
|
|
||||||
|
struct clk;
|
||||||
|
struct reset_control;
|
||||||
|
|
||||||
struct dw8250_port_data {
|
struct dw8250_port_data {
|
||||||
/* Port properties */
|
/* Port properties */
|
||||||
int line;
|
int line;
|
||||||
@@ -14,7 +20,52 @@ struct dw8250_port_data {
|
|||||||
|
|
||||||
/* Hardware configuration */
|
/* Hardware configuration */
|
||||||
u8 dlf_size;
|
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_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);
|
||||||
void dw8250_setup_port(struct uart_port *p);
|
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)
|
if (!pdata)
|
||||||
return -EINVAL;
|
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) {
|
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));
|
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||||
config |= RS485_URA;
|
config |= RS485_URA;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -54,9 +54,6 @@
|
|||||||
#define MTK_UART_TX_TRIGGER 1
|
#define MTK_UART_TX_TRIGGER 1
|
||||||
#define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
|
#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_XON1 40 /* I/O: Xon character 1 */
|
||||||
#define MTK_UART_XOFF1 42 /* I/O: Xoff 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;
|
uart.dma = data->dma;
|
||||||
#endif
|
#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 */
|
/* Disable Rate Fix function */
|
||||||
writel(0x0, uart.port.membase +
|
writel(0x0, uart.port.membase +
|
||||||
(MTK_UART_RATE_FIX << uart.port.regshift));
|
(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, },
|
.data = (void *)PORT_ALTR_16550_F64, },
|
||||||
{ .compatible = "altr,16550-FIFO128",
|
{ .compatible = "altr,16550-FIFO128",
|
||||||
.data = (void *)PORT_ALTR_16550_F128, },
|
.data = (void *)PORT_ALTR_16550_F128, },
|
||||||
|
{ .compatible = "fsl,16550-FIFO64",
|
||||||
|
.data = (void *)PORT_16550A_FSL64, },
|
||||||
{ .compatible = "mediatek,mtk-btif",
|
{ .compatible = "mediatek,mtk-btif",
|
||||||
.data = (void *)PORT_MTK_BTIF, },
|
.data = (void *)PORT_MTK_BTIF, },
|
||||||
{ .compatible = "mrvl,mmp-uart",
|
{ .compatible = "mrvl,mmp-uart",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/math.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
@@ -994,41 +995,29 @@ static void pci_ite887x_exit(struct pci_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EndRun Technologies.
|
* Oxford Semiconductor Inc.
|
||||||
* Determine the number of ports available on the device.
|
* Check if an OxSemi device is part of the Tornado range of devices.
|
||||||
*/
|
*/
|
||||||
#define PCI_VENDOR_ID_ENDRUN 0x7401
|
#define PCI_VENDOR_ID_ENDRUN 0x7401
|
||||||
#define PCI_DEVICE_ID_ENDRUN_1588 0xe100
|
#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;
|
/* OxSemi Tornado devices are all 0xCxxx */
|
||||||
unsigned long deviceID;
|
if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
|
||||||
unsigned int number_uarts = 0;
|
(dev->device & 0xf000) != 0xc000)
|
||||||
|
return false;
|
||||||
|
|
||||||
/* EndRun device is all 0xexxx */
|
/* EndRun devices are all 0xExxx */
|
||||||
if (dev->vendor == PCI_VENDOR_ID_ENDRUN &&
|
if (dev->vendor == PCI_VENDOR_ID_ENDRUN &&
|
||||||
(dev->device & 0xf000) != 0xe000)
|
(dev->device & 0xf000) != 0xe000)
|
||||||
return 0;
|
return false;
|
||||||
|
|
||||||
p = pci_iomap(dev, 0, 5);
|
return true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Oxford Semiconductor Inc.
|
* Determine the number of ports available on a Tornado device.
|
||||||
* Check that device is part of the Tornado range of devices, then determine
|
|
||||||
* the number of ports available on the device.
|
|
||||||
*/
|
*/
|
||||||
static int pci_oxsemi_tornado_init(struct pci_dev *dev)
|
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 long deviceID;
|
||||||
unsigned int number_uarts = 0;
|
unsigned int number_uarts = 0;
|
||||||
|
|
||||||
/* OxSemi Tornado devices are all 0xCxxx */
|
if (!pci_oxsemi_tornado_p(dev))
|
||||||
if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
|
|
||||||
(dev->device & 0xF000) != 0xC000)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
p = pci_iomap(dev, 0, 5);
|
p = pci_iomap(dev, 0, 5);
|
||||||
@@ -1049,12 +1036,217 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
|
|||||||
/* Tornado device */
|
/* Tornado device */
|
||||||
if (deviceID == 0x07000200) {
|
if (deviceID == 0x07000200) {
|
||||||
number_uarts = ioread8(p + 4);
|
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);
|
pci_iounmap(dev, p);
|
||||||
return number_uarts;
|
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,
|
static int pci_asix_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_8250_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
@@ -2244,7 +2436,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
|
|||||||
.device = PCI_ANY_ID,
|
.device = PCI_ANY_ID,
|
||||||
.subvendor = PCI_ANY_ID,
|
.subvendor = PCI_ANY_ID,
|
||||||
.subdevice = PCI_ANY_ID,
|
.subdevice = PCI_ANY_ID,
|
||||||
.init = pci_endrun_init,
|
.init = pci_oxsemi_tornado_init,
|
||||||
.setup = pci_default_setup,
|
.setup = pci_default_setup,
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
@@ -2256,7 +2448,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
|
|||||||
.subvendor = PCI_ANY_ID,
|
.subvendor = PCI_ANY_ID,
|
||||||
.subdevice = PCI_ANY_ID,
|
.subdevice = PCI_ANY_ID,
|
||||||
.init = pci_oxsemi_tornado_init,
|
.init = pci_oxsemi_tornado_init,
|
||||||
.setup = pci_default_setup,
|
.setup = pci_oxsemi_tornado_setup,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.vendor = PCI_VENDOR_ID_MAINPINE,
|
.vendor = PCI_VENDOR_ID_MAINPINE,
|
||||||
@@ -2264,7 +2456,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
|
|||||||
.subvendor = PCI_ANY_ID,
|
.subvendor = PCI_ANY_ID,
|
||||||
.subdevice = PCI_ANY_ID,
|
.subdevice = PCI_ANY_ID,
|
||||||
.init = pci_oxsemi_tornado_init,
|
.init = pci_oxsemi_tornado_init,
|
||||||
.setup = pci_default_setup,
|
.setup = pci_oxsemi_tornado_setup,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.vendor = PCI_VENDOR_ID_DIGI,
|
.vendor = PCI_VENDOR_ID_DIGI,
|
||||||
@@ -2272,7 +2464,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
|
|||||||
.subvendor = PCI_SUBVENDOR_ID_IBM,
|
.subvendor = PCI_SUBVENDOR_ID_IBM,
|
||||||
.subdevice = PCI_ANY_ID,
|
.subdevice = PCI_ANY_ID,
|
||||||
.init = pci_oxsemi_tornado_init,
|
.init = pci_oxsemi_tornado_init,
|
||||||
.setup = pci_default_setup,
|
.setup = pci_oxsemi_tornado_setup,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.vendor = PCI_VENDOR_ID_INTEL,
|
.vendor = PCI_VENDOR_ID_INTEL,
|
||||||
@@ -2589,7 +2781,7 @@ enum pci_board_num_t {
|
|||||||
pbn_b0_2_1843200,
|
pbn_b0_2_1843200,
|
||||||
pbn_b0_4_1843200,
|
pbn_b0_4_1843200,
|
||||||
|
|
||||||
pbn_b0_1_3906250,
|
pbn_b0_1_15625000,
|
||||||
|
|
||||||
pbn_b0_bt_1_115200,
|
pbn_b0_bt_1_115200,
|
||||||
pbn_b0_bt_2_115200,
|
pbn_b0_bt_2_115200,
|
||||||
@@ -2667,12 +2859,11 @@ enum pci_board_num_t {
|
|||||||
pbn_panacom2,
|
pbn_panacom2,
|
||||||
pbn_panacom4,
|
pbn_panacom4,
|
||||||
pbn_plx_romulus,
|
pbn_plx_romulus,
|
||||||
pbn_endrun_2_3906250,
|
|
||||||
pbn_oxsemi,
|
pbn_oxsemi,
|
||||||
pbn_oxsemi_1_3906250,
|
pbn_oxsemi_1_15625000,
|
||||||
pbn_oxsemi_2_3906250,
|
pbn_oxsemi_2_15625000,
|
||||||
pbn_oxsemi_4_3906250,
|
pbn_oxsemi_4_15625000,
|
||||||
pbn_oxsemi_8_3906250,
|
pbn_oxsemi_8_15625000,
|
||||||
pbn_intel_i960,
|
pbn_intel_i960,
|
||||||
pbn_sgi_ioc3,
|
pbn_sgi_ioc3,
|
||||||
pbn_computone_4,
|
pbn_computone_4,
|
||||||
@@ -2815,10 +3006,10 @@ static struct pciserial_board pci_boards[] = {
|
|||||||
.uart_offset = 8,
|
.uart_offset = 8,
|
||||||
},
|
},
|
||||||
|
|
||||||
[pbn_b0_1_3906250] = {
|
[pbn_b0_1_15625000] = {
|
||||||
.flags = FL_BASE0,
|
.flags = FL_BASE0,
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.base_baud = 3906250,
|
.base_baud = 15625000,
|
||||||
.uart_offset = 8,
|
.uart_offset = 8,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -3189,20 +3380,6 @@ static struct pciserial_board pci_boards[] = {
|
|||||||
.first_offset = 0x03,
|
.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
|
* This board uses the size of PCI Base region 0 to
|
||||||
* signal now many ports are available
|
* signal now many ports are available
|
||||||
@@ -3213,31 +3390,31 @@ static struct pciserial_board pci_boards[] = {
|
|||||||
.base_baud = 115200,
|
.base_baud = 115200,
|
||||||
.uart_offset = 8,
|
.uart_offset = 8,
|
||||||
},
|
},
|
||||||
[pbn_oxsemi_1_3906250] = {
|
[pbn_oxsemi_1_15625000] = {
|
||||||
.flags = FL_BASE0,
|
.flags = FL_BASE0,
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.base_baud = 3906250,
|
.base_baud = 15625000,
|
||||||
.uart_offset = 0x200,
|
.uart_offset = 0x200,
|
||||||
.first_offset = 0x1000,
|
.first_offset = 0x1000,
|
||||||
},
|
},
|
||||||
[pbn_oxsemi_2_3906250] = {
|
[pbn_oxsemi_2_15625000] = {
|
||||||
.flags = FL_BASE0,
|
.flags = FL_BASE0,
|
||||||
.num_ports = 2,
|
.num_ports = 2,
|
||||||
.base_baud = 3906250,
|
.base_baud = 15625000,
|
||||||
.uart_offset = 0x200,
|
.uart_offset = 0x200,
|
||||||
.first_offset = 0x1000,
|
.first_offset = 0x1000,
|
||||||
},
|
},
|
||||||
[pbn_oxsemi_4_3906250] = {
|
[pbn_oxsemi_4_15625000] = {
|
||||||
.flags = FL_BASE0,
|
.flags = FL_BASE0,
|
||||||
.num_ports = 4,
|
.num_ports = 4,
|
||||||
.base_baud = 3906250,
|
.base_baud = 15625000,
|
||||||
.uart_offset = 0x200,
|
.uart_offset = 0x200,
|
||||||
.first_offset = 0x1000,
|
.first_offset = 0x1000,
|
||||||
},
|
},
|
||||||
[pbn_oxsemi_8_3906250] = {
|
[pbn_oxsemi_8_15625000] = {
|
||||||
.flags = FL_BASE0,
|
.flags = FL_BASE0,
|
||||||
.num_ports = 8,
|
.num_ports = 8,
|
||||||
.base_baud = 3906250,
|
.base_baud = 15625000,
|
||||||
.uart_offset = 0x200,
|
.uart_offset = 0x200,
|
||||||
.first_offset = 0x1000,
|
.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[] = {
|
static const struct pci_device_id blacklist[] = {
|
||||||
/* softmodems */
|
/* softmodems */
|
||||||
{ PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
|
{ 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 */
|
{ PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
|
||||||
|
|
||||||
/* multi-io cards handled by parport_serial */
|
/* multi-io cards handled by parport_serial */
|
||||||
{ PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
|
/* WCH CH353 2S1P */
|
||||||
{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
|
{ PCI_DEVICE(0x4348, 0x7053), 0, 0, REPORT_CONFIG(PARPORT_SERIAL), },
|
||||||
{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
|
/* 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 */
|
/* Intel platforms with MID UART */
|
||||||
{ PCI_VDEVICE(INTEL, 0x081b), },
|
{ PCI_VDEVICE(INTEL, 0x081b), REPORT_8250_CONFIG(MID), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x081c), },
|
{ PCI_VDEVICE(INTEL, 0x081c), REPORT_8250_CONFIG(MID), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x081d), },
|
{ PCI_VDEVICE(INTEL, 0x081d), REPORT_8250_CONFIG(MID), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x1191), },
|
{ PCI_VDEVICE(INTEL, 0x1191), REPORT_8250_CONFIG(MID), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x18d8), },
|
{ PCI_VDEVICE(INTEL, 0x18d8), REPORT_8250_CONFIG(MID), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x19d8), },
|
{ PCI_VDEVICE(INTEL, 0x19d8), REPORT_8250_CONFIG(MID), },
|
||||||
|
|
||||||
/* Intel platforms with DesignWare UART */
|
/* Intel platforms with DesignWare UART */
|
||||||
{ PCI_VDEVICE(INTEL, 0x0936), },
|
{ PCI_VDEVICE(INTEL, 0x0936), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x0f0a), },
|
{ PCI_VDEVICE(INTEL, 0x0f0a), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x0f0c), },
|
{ PCI_VDEVICE(INTEL, 0x0f0c), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x228a), },
|
{ PCI_VDEVICE(INTEL, 0x228a), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x228c), },
|
{ PCI_VDEVICE(INTEL, 0x228c), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x4b96), },
|
{ PCI_VDEVICE(INTEL, 0x4b96), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x4b97), },
|
{ PCI_VDEVICE(INTEL, 0x4b97), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x4b98), },
|
{ PCI_VDEVICE(INTEL, 0x4b98), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x4b99), },
|
{ PCI_VDEVICE(INTEL, 0x4b99), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x4b9a), },
|
{ PCI_VDEVICE(INTEL, 0x4b9a), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x4b9b), },
|
{ PCI_VDEVICE(INTEL, 0x4b9b), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x9ce3), },
|
{ PCI_VDEVICE(INTEL, 0x9ce3), REPORT_8250_CONFIG(LPSS), },
|
||||||
{ PCI_VDEVICE(INTEL, 0x9ce4), },
|
{ PCI_VDEVICE(INTEL, 0x9ce4), REPORT_8250_CONFIG(LPSS), },
|
||||||
|
|
||||||
/* Exar devices */
|
/* Exar devices */
|
||||||
{ PCI_VDEVICE(EXAR, PCI_ANY_ID), },
|
{ PCI_VDEVICE(EXAR, PCI_ANY_ID), REPORT_8250_CONFIG(EXAR), },
|
||||||
{ PCI_VDEVICE(COMMTECH, PCI_ANY_ID), },
|
{ PCI_VDEVICE(COMMTECH, PCI_ANY_ID), REPORT_8250_CONFIG(EXAR), },
|
||||||
|
|
||||||
/* Pericom devices */
|
/* Pericom devices */
|
||||||
{ PCI_VDEVICE(PERICOM, PCI_ANY_ID), },
|
{ PCI_VDEVICE(PERICOM, PCI_ANY_ID), REPORT_8250_CONFIG(PERICOM), },
|
||||||
{ PCI_VDEVICE(ACCESSIO, PCI_ANY_ID), },
|
{ PCI_VDEVICE(ACCESSIO, PCI_ANY_ID), REPORT_8250_CONFIG(PERICOM), },
|
||||||
|
|
||||||
/* End of the black list */
|
/* 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];
|
board = &pci_boards[ent->driver_data];
|
||||||
|
|
||||||
exclude = pci_match_id(blacklist, dev);
|
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;
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
rc = pcim_enable_device(dev);
|
rc = pcim_enable_device(dev);
|
||||||
pci_save_state(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,
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
|
||||||
0x10b5, 0x106a, 0, 0,
|
0x10b5, 0x106a, 0, 0,
|
||||||
pbn_plx_romulus },
|
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
|
* Quatech cards. These actually have configurable clocks but for
|
||||||
* now we just use the default.
|
* 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_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
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_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||||
pbn_oxsemi_1_3906250 },
|
pbn_oxsemi_1_15625000 },
|
||||||
/*
|
/*
|
||||||
* Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
|
* 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, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
|
||||||
PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
|
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, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
|
||||||
PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
|
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, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
|
||||||
PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
|
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, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
|
||||||
PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
|
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
|
* Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
|
||||||
*/
|
*/
|
||||||
{ PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
|
{ PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
|
||||||
PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
|
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,
|
* SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ static const struct serial8250_config uart_config[] = {
|
|||||||
.tx_loadsz = 63,
|
.tx_loadsz = 63,
|
||||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
|
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
|
||||||
UART_FCR7_64BYTE,
|
UART_FCR7_64BYTE,
|
||||||
.flags = UART_CAP_FIFO,
|
.flags = UART_CAP_FIFO | UART_CAP_NOTEMT,
|
||||||
},
|
},
|
||||||
[PORT_RT2880] = {
|
[PORT_RT2880] = {
|
||||||
.name = "Palmchip BK-3103",
|
.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.
|
* 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);
|
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;
|
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
|
* rs485_stop_tx() is going to set RTS according to config
|
||||||
* AND flush RX FIFO if required.
|
* 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;
|
em485->active_timer = &em485->stop_tx_timer;
|
||||||
start_hrtimer_ms(&em485->stop_tx_timer,
|
hrtimer_start(&em485->stop_tx_timer, ns_to_ktime(stop_delay), HRTIMER_MODE_REL);
|
||||||
p->port.rs485.delay_rts_after_send);
|
|
||||||
} else {
|
} else {
|
||||||
p->rs485_stop_tx(p);
|
p->rs485_stop_tx(p);
|
||||||
em485->active_timer = NULL;
|
em485->active_timer = NULL;
|
||||||
@@ -1535,16 +1515,32 @@ static inline void __stop_tx(struct uart_8250_port *p)
|
|||||||
|
|
||||||
if (em485) {
|
if (em485) {
|
||||||
unsigned char lsr = serial_in(p, UART_LSR);
|
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,
|
* To provide required timeing and allow FIFO transfer,
|
||||||
* __stop_tx_rs485() must be called only when both FIFO and
|
* __stop_tx_rs485() must be called only when both FIFO and
|
||||||
* shift register are empty. It is for device driver to enable
|
* shift register are empty. The device driver should either
|
||||||
* interrupt on TEMT.
|
* 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)
|
if (!(lsr & UART_LSR_TEMT)) {
|
||||||
return;
|
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);
|
__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);
|
status = serial8250_rx_chars(up, status);
|
||||||
}
|
}
|
||||||
serial8250_modem_status(up);
|
serial8250_modem_status(up);
|
||||||
if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) &&
|
if ((status & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) {
|
||||||
(up->ier & UART_IER_THRI))
|
if (!up->dma || up->dma->tx_err)
|
||||||
serial8250_tx_chars(up);
|
serial8250_tx_chars(up);
|
||||||
|
else
|
||||||
|
__stop_tx(up);
|
||||||
|
}
|
||||||
|
|
||||||
uart_unlock_and_check_sysrq_irqrestore(port, flags);
|
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);
|
serial8250_rpm_put(up);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void wait_for_lsr(struct uart_8250_port *up, int bits)
|
||||||
* Wait for transmitter & holding register to empty
|
|
||||||
*/
|
|
||||||
static void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
|
||||||
{
|
{
|
||||||
unsigned int status, tmout = 10000;
|
unsigned int status, tmout = 10000;
|
||||||
|
|
||||||
@@ -2097,6 +2093,16 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
|||||||
udelay(1);
|
udelay(1);
|
||||||
touch_nmi_watchdog();
|
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 */
|
/* Wait up to 1s for flow control if necessary */
|
||||||
if (up->port.flags & UPF_CONS_FLOW) {
|
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))
|
if (!(c_cflag & PARODD))
|
||||||
cval |= UART_LCR_EPAR;
|
cval |= UART_LCR_EPAR;
|
||||||
#ifdef CMSPAR
|
|
||||||
if (c_cflag & CMSPAR)
|
if (c_cflag & CMSPAR)
|
||||||
cval |= UART_LCR_SPAR;
|
cval |= UART_LCR_SPAR;
|
||||||
#endif
|
|
||||||
|
|
||||||
return cval;
|
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);
|
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
|
* Print a string to the serial port trying not to disturb
|
||||||
* any possible real use of the port...
|
* 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_8250_em485 *em485 = up->em485;
|
||||||
struct uart_port *port = &up->port;
|
struct uart_port *port = &up->port;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int ier;
|
unsigned int ier, use_fifo;
|
||||||
int locked = 1;
|
int locked = 1;
|
||||||
|
|
||||||
touch_nmi_watchdog();
|
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);
|
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
|
* Finally, wait for transmitter to become empty
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/pm_runtime.h>
|
|
||||||
|
|
||||||
#include "8250.h"
|
#include "8250.h"
|
||||||
|
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ config SERIAL_8250_DW
|
|||||||
config SERIAL_8250_EM
|
config SERIAL_8250_EM
|
||||||
tristate "Support for Emma Mobile integrated serial port"
|
tristate "Support for Emma Mobile integrated serial port"
|
||||||
depends on SERIAL_8250 && HAVE_CLK
|
depends on SERIAL_8250 && HAVE_CLK
|
||||||
depends on (ARM && ARCH_RENESAS) || COMPILE_TEST
|
depends on ARCH_RENESAS || COMPILE_TEST
|
||||||
help
|
help
|
||||||
Selecting this option will add support for the integrated serial
|
Selecting this option will add support for the integrated serial
|
||||||
port hardware found on the Emma Mobile line of processors.
|
port hardware found on the Emma Mobile line of processors.
|
||||||
|
|||||||
@@ -782,7 +782,7 @@ config SERIAL_PMACZILOG_CONSOLE
|
|||||||
|
|
||||||
config SERIAL_CPM
|
config SERIAL_CPM
|
||||||
tristate "CPM SCC/SMC serial port support"
|
tristate "CPM SCC/SMC serial port support"
|
||||||
depends on CPM2 || CPM1
|
depends on CPM2 || CPM1 || (PPC32 && COMPILE_TEST)
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
help
|
help
|
||||||
This driver supports the SCC and SMC serial ports on Motorola
|
This driver supports the SCC and SMC serial ports on Motorola
|
||||||
@@ -806,7 +806,7 @@ config SERIAL_CPM_CONSOLE
|
|||||||
|
|
||||||
config SERIAL_PIC32
|
config SERIAL_PIC32
|
||||||
tristate "Microchip PIC32 serial support"
|
tristate "Microchip PIC32 serial support"
|
||||||
depends on MACH_PIC32
|
depends on MACH_PIC32 || (MIPS && COMPILE_TEST)
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
help
|
help
|
||||||
If you have a PIC32, this driver supports the serial ports.
|
If you have a PIC32, this driver supports the serial ports.
|
||||||
@@ -817,7 +817,7 @@ config SERIAL_PIC32
|
|||||||
|
|
||||||
config SERIAL_PIC32_CONSOLE
|
config SERIAL_PIC32_CONSOLE
|
||||||
bool "PIC32 serial console support"
|
bool "PIC32 serial console support"
|
||||||
depends on SERIAL_PIC32
|
depends on SERIAL_PIC32=y
|
||||||
select SERIAL_CORE_CONSOLE
|
select SERIAL_CORE_CONSOLE
|
||||||
help
|
help
|
||||||
If you have a PIC32, this driver supports the putting a console on one
|
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
|
config SERIAL_AR933X
|
||||||
tristate "AR933X serial port support"
|
tristate "AR933X serial port support"
|
||||||
depends on HAVE_CLK && ATH79
|
depends on (HAVE_CLK && ATH79) || (MIPS && COMPILE_TEST)
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||||
help
|
help
|
||||||
@@ -1442,6 +1442,7 @@ config SERIAL_STM32_CONSOLE
|
|||||||
bool "Support for console on STM32"
|
bool "Support for console on STM32"
|
||||||
depends on SERIAL_STM32=y
|
depends on SERIAL_STM32=y
|
||||||
select SERIAL_CORE_CONSOLE
|
select SERIAL_CORE_CONSOLE
|
||||||
|
select SERIAL_EARLYCON
|
||||||
|
|
||||||
config SERIAL_MVEBU_UART
|
config SERIAL_MVEBU_UART
|
||||||
bool "Marvell EBU serial port support"
|
bool "Marvell EBU serial port support"
|
||||||
|
|||||||
@@ -168,10 +168,8 @@ static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending == 0) {
|
if (pending == 0)
|
||||||
pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
|
altera_jtaguart_stop_tx(port);
|
||||||
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
|
static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
|
||||||
|
|||||||
@@ -42,8 +42,6 @@
|
|||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
|
||||||
#include "amba-pl011.h"
|
|
||||||
|
|
||||||
#define UART_NR 14
|
#define UART_NR 14
|
||||||
|
|
||||||
#define SERIAL_AMBA_MAJOR 204
|
#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_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
|
||||||
#define UART_DUMMY_DR_RX (1 << 16)
|
#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] = {
|
static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
|
||||||
[REG_DR] = UART01x_DR,
|
[REG_DR] = UART01x_DR,
|
||||||
[REG_FR] = UART01x_FR,
|
[REG_FR] = UART01x_FR,
|
||||||
@@ -2175,25 +2203,11 @@ static int pl011_rs485_config(struct uart_port *port,
|
|||||||
struct uart_amba_port *uap =
|
struct uart_amba_port *uap =
|
||||||
container_of(port, struct uart_amba_port, port);
|
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)
|
if (port->rs485.flags & SER_RS485_ENABLED)
|
||||||
pl011_rs485_tx_stop(uap);
|
pl011_rs485_tx_stop(uap);
|
||||||
|
|
||||||
/* Set new configuration */
|
|
||||||
port->rs485 = *rs485;
|
|
||||||
|
|
||||||
/* Make sure auto RTS is disabled */
|
/* 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);
|
u32 cr = pl011_read(uap, REG_CR);
|
||||||
|
|
||||||
cr &= ~UART011_CR_RTSEN;
|
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) */
|
/* Resetting serial mode to RS232 (0x0) */
|
||||||
mode &= ~ATMEL_US_USMODE;
|
mode &= ~ATMEL_US_USMODE;
|
||||||
|
|
||||||
port->rs485 = *rs485conf;
|
|
||||||
|
|
||||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||||
dev_dbg(port->dev, "Setting UART to RS485\n");
|
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;
|
atmel_port->tx_done_mask = ATMEL_US_TXRDY;
|
||||||
else
|
else
|
||||||
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
|
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ struct gpio_desc;
|
|||||||
#include "cpm_uart_cpm2.h"
|
#include "cpm_uart_cpm2.h"
|
||||||
#elif defined(CONFIG_CPM1)
|
#elif defined(CONFIG_CPM1)
|
||||||
#include "cpm_uart_cpm1.h"
|
#include "cpm_uart_cpm1.h"
|
||||||
|
#elif defined(CONFIG_COMPILE_TEST)
|
||||||
|
#include "cpm_uart_cpm2.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SERIAL_CPM_MAJOR 204
|
#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_PPC_EARLY_DEBUG_CPM
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_CPM_CONSOLE)
|
||||||
if (!udbg_port)
|
if (!udbg_port)
|
||||||
#endif
|
#endif
|
||||||
udbg_putc = NULL;
|
udbg_putc = NULL;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/fs_pd.h>
|
#include <asm/fs_pd.h>
|
||||||
#include <asm/prom.h>
|
|
||||||
|
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|||||||
@@ -309,6 +309,8 @@ static void digicolor_uart_set_termios(struct uart_port *port,
|
|||||||
case CS8:
|
case CS8:
|
||||||
default:
|
default:
|
||||||
config |= UA_CONFIG_CHAR_LEN;
|
config |= UA_CONFIG_CHAR_LEN;
|
||||||
|
termios->c_cflag &= ~CSIZE;
|
||||||
|
termios->c_cflag |= CS8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -239,8 +239,6 @@
|
|||||||
/* IMX lpuart has four extra unused regs located at the beginning */
|
/* IMX lpuart has four extra unused regs located at the beginning */
|
||||||
#define IMX_REG_OFF 0x10
|
#define IMX_REG_OFF 0x10
|
||||||
|
|
||||||
static DEFINE_IDA(fsl_lpuart_ida);
|
|
||||||
|
|
||||||
enum lpuart_type {
|
enum lpuart_type {
|
||||||
VF610_LPUART,
|
VF610_LPUART,
|
||||||
LS1021A_LPUART,
|
LS1021A_LPUART,
|
||||||
@@ -276,7 +274,6 @@ struct lpuart_port {
|
|||||||
int rx_dma_rng_buf_len;
|
int rx_dma_rng_buf_len;
|
||||||
unsigned int dma_tx_nents;
|
unsigned int dma_tx_nents;
|
||||||
wait_queue_head_t dma_wait;
|
wait_queue_head_t dma_wait;
|
||||||
bool id_allocated;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lpuart_soc_data {
|
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 dma_chan *chan = sport->dma_rx_chan;
|
||||||
struct circ_buf *ring = &sport->rx_ring;
|
struct circ_buf *ring = &sport->rx_ring;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int count = 0, copied;
|
int count, copied;
|
||||||
|
|
||||||
if (lpuart_is_32(sport)) {
|
if (lpuart_is_32(sport)) {
|
||||||
unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
|
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 */
|
/* Enable auto RS-485 RTS mode */
|
||||||
modem |= UARTMODEM_TXRTSE;
|
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.
|
* The hardware defaults to RTS logic HIGH while transfer.
|
||||||
* Switch polarity in case RTS shall be logic HIGH
|
* 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;
|
modem |= UARTMODEM_TXRTSPOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the new configuration */
|
|
||||||
sport->port.rs485 = *rs485;
|
|
||||||
|
|
||||||
writeb(modem, sport->port.membase + UARTMODEM);
|
writeb(modem, sport->port.membase + UARTMODEM);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1428,19 +1409,6 @@ static int lpuart32_config_rs485(struct uart_port *port,
|
|||||||
/* Enable auto RS-485 RTS mode */
|
/* Enable auto RS-485 RTS mode */
|
||||||
modem |= UARTMODEM_TXRTSE;
|
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.
|
* The hardware defaults to RTS logic HIGH while transfer.
|
||||||
* Switch polarity in case RTS shall be logic HIGH
|
* 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;
|
modem |= UARTMODEM_TXRTSPOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the new configuration */
|
|
||||||
sport->port.rs485 = *rs485;
|
|
||||||
|
|
||||||
lpuart32_write(&sport->port, modem, UARTMODIR);
|
lpuart32_write(&sport->port, modem, UARTMODIR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2145,12 +2110,10 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||||||
if (sport->port.rs485.flags & SER_RS485_ENABLED)
|
if (sport->port.rs485.flags & SER_RS485_ENABLED)
|
||||||
termios->c_cflag &= ~CRTSCTS;
|
termios->c_cflag &= ~CRTSCTS;
|
||||||
|
|
||||||
if (termios->c_cflag & CRTSCTS) {
|
if (termios->c_cflag & CRTSCTS)
|
||||||
modem |= (UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
modem |= UARTMODIR_RXRTSE | UARTMODIR_TXCTSE;
|
||||||
} else {
|
else
|
||||||
termios->c_cflag &= ~CRTSCTS;
|
|
||||||
modem &= ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
modem &= ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
|
||||||
}
|
|
||||||
|
|
||||||
if (termios->c_cflag & CSTOPB)
|
if (termios->c_cflag & CSTOPB)
|
||||||
bd |= UARTBAUD_SBNS;
|
bd |= UARTBAUD_SBNS;
|
||||||
@@ -2717,23 +2680,18 @@ static int lpuart_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
ret = of_alias_get_id(np, "serial");
|
ret = of_alias_get_id(np, "serial");
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL);
|
dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
|
||||||
if (ret < 0) {
|
return ret;
|
||||||
dev_err(&pdev->dev, "port line is full, add device failed\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
sport->id_allocated = true;
|
|
||||||
}
|
}
|
||||||
if (ret >= ARRAY_SIZE(lpuart_ports)) {
|
if (ret >= ARRAY_SIZE(lpuart_ports)) {
|
||||||
dev_err(&pdev->dev, "serial%d out of range\n", ret);
|
dev_err(&pdev->dev, "serial%d out of range\n", ret);
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto failed_out_of_range;
|
|
||||||
}
|
}
|
||||||
sport->port.line = ret;
|
sport->port.line = ret;
|
||||||
|
|
||||||
ret = lpuart_enable_clks(sport);
|
ret = lpuart_enable_clks(sport);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto failed_clock_enable;
|
return ret;
|
||||||
sport->port.uartclk = lpuart_get_baud_clk_rate(sport);
|
sport->port.uartclk = lpuart_get_baud_clk_rate(sport);
|
||||||
|
|
||||||
lpuart_ports[sport->port.line] = sport;
|
lpuart_ports[sport->port.line] = sport;
|
||||||
@@ -2781,10 +2739,6 @@ failed_reset:
|
|||||||
uart_remove_one_port(&lpuart_reg, &sport->port);
|
uart_remove_one_port(&lpuart_reg, &sport->port);
|
||||||
failed_attach_port:
|
failed_attach_port:
|
||||||
lpuart_disable_clks(sport);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2794,9 +2748,6 @@ static int lpuart_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
uart_remove_one_port(&lpuart_reg, &sport->port);
|
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);
|
lpuart_disable_clks(sport);
|
||||||
|
|
||||||
if (sport->dma_tx_chan)
|
if (sport->dma_tx_chan)
|
||||||
@@ -2926,7 +2877,6 @@ static int __init lpuart_serial_init(void)
|
|||||||
|
|
||||||
static void __exit lpuart_serial_exit(void)
|
static void __exit lpuart_serial_exit(void)
|
||||||
{
|
{
|
||||||
ida_destroy(&fsl_lpuart_ida);
|
|
||||||
platform_driver_unregister(&lpuart_driver);
|
platform_driver_unregister(&lpuart_driver);
|
||||||
uart_unregister_driver(&lpuart_reg);
|
uart_unregister_driver(&lpuart_reg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
|
#include <linux/serial_core.h>
|
||||||
#include <linux/serial_reg.h>
|
#include <linux/serial_reg.h>
|
||||||
#include <linux/major.h>
|
#include <linux/major.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
@@ -41,15 +42,273 @@
|
|||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
#include "icom.h"
|
|
||||||
|
|
||||||
/*#define ICOM_TRACE enable port trace capabilities */
|
/*#define ICOM_TRACE enable port trace capabilities */
|
||||||
|
|
||||||
#define ICOM_DRIVER_NAME "icom"
|
#define ICOM_DRIVER_NAME "icom"
|
||||||
#define ICOM_VERSION_STR "1.3.1"
|
|
||||||
#define NR_PORTS 128
|
#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[] = {
|
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)) {
|
if (index < (NUM_XBUFFS - 1)) {
|
||||||
memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
|
memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
|
||||||
icom_port->statStg->xmit[index].leLengthASD =
|
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_ADDR", stgAddr);
|
||||||
trace(icom_port, "FOD_XBUFF",
|
trace(icom_port, "FOD_XBUFF",
|
||||||
(unsigned long) icom_port->xmit_buf);
|
(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)) {
|
} else if (index == (NUM_XBUFFS - 1)) {
|
||||||
memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
|
memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
|
||||||
icom_port->statStg->xmit[index].leLengthASD =
|
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",
|
trace(icom_port, "FOD_XBUFF",
|
||||||
(unsigned long) icom_port->xmit_buf);
|
(unsigned long) icom_port->xmit_buf);
|
||||||
icom_port->statStg->xmit[index].leBuffer =
|
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]);
|
stgAddr = stgAddr + sizeof(icom_port->statStg->rcv[0]);
|
||||||
icom_port->statStg->rcv[index].leLength = 0;
|
icom_port->statStg->rcv[index].leLength = 0;
|
||||||
icom_port->statStg->rcv[index].WorkingLength =
|
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) ) {
|
if (index < (NUM_RBUFFS - 1) ) {
|
||||||
offset = stgAddr - (unsigned long) icom_port->statStg;
|
offset = stgAddr - (unsigned long) icom_port->statStg;
|
||||||
icom_port->statStg->rcv[index].leNext =
|
icom_port->statStg->rcv[index].leNext =
|
||||||
@@ -617,16 +876,17 @@ unlock:
|
|||||||
|
|
||||||
static int icom_write(struct uart_port *port)
|
static int icom_write(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
unsigned long data_count;
|
unsigned long data_count;
|
||||||
unsigned char cmdReg;
|
unsigned char cmdReg;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
int temp_tail = port->state->xmit.tail;
|
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) {
|
SA_FLAGS_READY_TO_XMIT) {
|
||||||
trace(ICOM_PORT, "WRITE_FULL", 0);
|
trace(icom_port, "WRITE_FULL", 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,7 +894,7 @@ static int icom_write(struct uart_port *port)
|
|||||||
while ((port->state->xmit.head != temp_tail) &&
|
while ((port->state->xmit.head != temp_tail) &&
|
||||||
(data_count <= XMIT_BUFF_SZ)) {
|
(data_count <= XMIT_BUFF_SZ)) {
|
||||||
|
|
||||||
ICOM_PORT->xmit_buf[data_count++] =
|
icom_port->xmit_buf[data_count++] =
|
||||||
port->state->xmit.buf[temp_tail];
|
port->state->xmit.buf[temp_tail];
|
||||||
|
|
||||||
temp_tail++;
|
temp_tail++;
|
||||||
@@ -642,22 +902,22 @@ static int icom_write(struct uart_port *port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data_count) {
|
if (data_count) {
|
||||||
ICOM_PORT->statStg->xmit[0].flags =
|
icom_port->statStg->xmit[0].flags =
|
||||||
cpu_to_le16(SA_FLAGS_READY_TO_XMIT);
|
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);
|
cpu_to_le16(data_count);
|
||||||
offset =
|
offset =
|
||||||
(unsigned long) &ICOM_PORT->statStg->xmit[0] -
|
(unsigned long) &icom_port->statStg->xmit[0] -
|
||||||
(unsigned long) ICOM_PORT->statStg;
|
(unsigned long) icom_port->statStg;
|
||||||
*ICOM_PORT->xmitRestart =
|
*icom_port->xmitRestart =
|
||||||
cpu_to_le32(ICOM_PORT->statStg_pci + offset);
|
cpu_to_le32(icom_port->statStg_pci + offset);
|
||||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||||
writeb(cmdReg | CMD_XMIT_RCV_ENABLE,
|
writeb(cmdReg | CMD_XMIT_RCV_ENABLE,
|
||||||
&ICOM_PORT->dram->CmdReg);
|
&icom_port->dram->CmdReg);
|
||||||
writeb(START_XMIT, &ICOM_PORT->dram->StartXmitCmd);
|
writeb(START_XMIT, &icom_port->dram->StartXmitCmd);
|
||||||
trace(ICOM_PORT, "WRITE_START", data_count);
|
trace(icom_port, "WRITE_START", data_count);
|
||||||
/* write flush */
|
/* write flush */
|
||||||
readb(&ICOM_PORT->dram->StartXmitCmd);
|
readb(&icom_port->dram->StartXmitCmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data_count;
|
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)
|
static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
|
||||||
{
|
{
|
||||||
unsigned short int count;
|
u16 count, i;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (port_int_reg & (INT_XMIT_COMPLETED)) {
|
if (port_int_reg & (INT_XMIT_COMPLETED)) {
|
||||||
trace(icom_port, "XMIT_COMPLETE", 0);
|
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 &=
|
icom_port->statStg->xmit[0].flags &=
|
||||||
cpu_to_le16(~SA_FLAGS_READY_TO_XMIT);
|
cpu_to_le16(~SA_FLAGS_READY_TO_XMIT);
|
||||||
|
|
||||||
count = (unsigned short int)
|
count = le16_to_cpu(icom_port->statStg->xmit[0].leLength);
|
||||||
cpu_to_le16(icom_port->statStg->xmit[0].leLength);
|
|
||||||
icom_port->uart_port.icount.tx += count;
|
icom_port->uart_port.icount.tx += count;
|
||||||
|
|
||||||
for (i=0; i<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;
|
short int count, rcv_buff;
|
||||||
struct tty_port *port = &icom_port->uart_port.state->port;
|
struct tty_port *port = &icom_port->uart_port.state->port;
|
||||||
unsigned short int status;
|
u16 status;
|
||||||
struct uart_icount *icount;
|
struct uart_icount *icount;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
unsigned char flag;
|
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);
|
trace(icom_port, "RCV_COMPLETE", 0);
|
||||||
rcv_buff = icom_port->next_rcv;
|
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) {
|
while (status & SA_FL_RCV_DONE) {
|
||||||
int first = -1;
|
int first = -1;
|
||||||
|
|
||||||
trace(icom_port, "FID_STATUS", status);
|
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, "RCV_COUNT", count);
|
||||||
|
|
||||||
trace(icom_port, "REAL_COUNT", count);
|
trace(icom_port, "REAL_COUNT", count);
|
||||||
|
|
||||||
offset =
|
offset = le32_to_cpu(icom_port->statStg->rcv[rcv_buff].leBuffer) -
|
||||||
cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
|
|
||||||
icom_port->recv_buf_pci;
|
icom_port->recv_buf_pci;
|
||||||
|
|
||||||
/* Block copy all but the last byte as this may have status */
|
/* 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].flags = 0;
|
||||||
icom_port->statStg->rcv[rcv_buff].leLength = 0;
|
icom_port->statStg->rcv[rcv_buff].leLength = 0;
|
||||||
icom_port->statStg->rcv[rcv_buff].WorkingLength =
|
icom_port->statStg->rcv[rcv_buff].WorkingLength =
|
||||||
(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
|
cpu_to_le16(RCV_BUFF_SZ);
|
||||||
|
|
||||||
rcv_buff++;
|
rcv_buff++;
|
||||||
if (rcv_buff == NUM_RBUFFS)
|
if (rcv_buff == NUM_RBUFFS)
|
||||||
rcv_buff = 0;
|
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;
|
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)
|
static unsigned int icom_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, 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)
|
SA_FLAGS_READY_TO_XMIT)
|
||||||
ret = TIOCSER_TEMT;
|
ret = TIOCSER_TEMT;
|
||||||
else
|
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)
|
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;
|
unsigned char local_osr;
|
||||||
|
|
||||||
trace(ICOM_PORT, "SET_MODEM", 0);
|
trace(icom_port, "SET_MODEM", 0);
|
||||||
local_osr = readb(&ICOM_PORT->dram->osr);
|
local_osr = readb(&icom_port->dram->osr);
|
||||||
|
|
||||||
if (mctrl & TIOCM_RTS) {
|
if (mctrl & TIOCM_RTS) {
|
||||||
trace(ICOM_PORT, "RAISE_RTS", 0);
|
trace(icom_port, "RAISE_RTS", 0);
|
||||||
local_osr |= ICOM_RTS;
|
local_osr |= ICOM_RTS;
|
||||||
} else {
|
} else {
|
||||||
trace(ICOM_PORT, "LOWER_RTS", 0);
|
trace(icom_port, "LOWER_RTS", 0);
|
||||||
local_osr &= ~ICOM_RTS;
|
local_osr &= ~ICOM_RTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mctrl & TIOCM_DTR) {
|
if (mctrl & TIOCM_DTR) {
|
||||||
trace(ICOM_PORT, "RAISE_DTR", 0);
|
trace(icom_port, "RAISE_DTR", 0);
|
||||||
local_osr |= ICOM_DTR;
|
local_osr |= ICOM_DTR;
|
||||||
} else {
|
} else {
|
||||||
trace(ICOM_PORT, "LOWER_DTR", 0);
|
trace(icom_port, "LOWER_DTR", 0);
|
||||||
local_osr &= ~ICOM_DTR;
|
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)
|
static unsigned int icom_get_mctrl(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
unsigned char status;
|
unsigned char status;
|
||||||
unsigned int result;
|
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)
|
result = ((status & ICOM_DCD) ? TIOCM_CAR : 0)
|
||||||
| ((status & ICOM_RI) ? TIOCM_RNG : 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)
|
static void icom_stop_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
unsigned char cmdReg;
|
unsigned char cmdReg;
|
||||||
|
|
||||||
trace(ICOM_PORT, "STOP", 0);
|
trace(icom_port, "STOP", 0);
|
||||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||||
writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
|
writeb(cmdReg | CMD_HOLD_XMIT, &icom_port->dram->CmdReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void icom_start_tx(struct uart_port *port)
|
static void icom_start_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
unsigned char cmdReg;
|
unsigned char cmdReg;
|
||||||
|
|
||||||
trace(ICOM_PORT, "START", 0);
|
trace(icom_port, "START", 0);
|
||||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||||
if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
|
if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
|
||||||
writeb(cmdReg & ~CMD_HOLD_XMIT,
|
writeb(cmdReg & ~CMD_HOLD_XMIT,
|
||||||
&ICOM_PORT->dram->CmdReg);
|
&icom_port->dram->CmdReg);
|
||||||
|
|
||||||
icom_write(port);
|
icom_write(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void icom_send_xchar(struct uart_port *port, char ch)
|
static void icom_send_xchar(struct uart_port *port, char ch)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
unsigned char xdata;
|
unsigned char xdata;
|
||||||
int index;
|
int index;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
trace(ICOM_PORT, "SEND_XCHAR", ch);
|
trace(icom_port, "SEND_XCHAR", ch);
|
||||||
|
|
||||||
/* wait .1 sec to send char */
|
/* wait .1 sec to send char */
|
||||||
for (index = 0; index < 10; index++) {
|
for (index = 0; index < 10; index++) {
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
xdata = readb(&ICOM_PORT->dram->xchar);
|
xdata = readb(&icom_port->dram->xchar);
|
||||||
if (xdata == 0x00) {
|
if (xdata == 0x00) {
|
||||||
trace(ICOM_PORT, "QUICK_WRITE", 0);
|
trace(icom_port, "QUICK_WRITE", 0);
|
||||||
writeb(ch, &ICOM_PORT->dram->xchar);
|
writeb(ch, &icom_port->dram->xchar);
|
||||||
|
|
||||||
/* flush write operation */
|
/* flush write operation */
|
||||||
xdata = readb(&ICOM_PORT->dram->xchar);
|
xdata = readb(&icom_port->dram->xchar);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
break;
|
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)
|
static void icom_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
unsigned char cmdReg;
|
unsigned char cmdReg;
|
||||||
|
|
||||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||||
writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
|
writeb(cmdReg & ~CMD_RCV_ENABLE, &icom_port->dram->CmdReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void icom_break(struct uart_port *port, int break_state)
|
static void icom_break(struct uart_port *port, int break_state)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
unsigned char cmdReg;
|
unsigned char cmdReg;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
trace(ICOM_PORT, "BREAK", 0);
|
trace(icom_port, "BREAK", 0);
|
||||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||||
if (break_state == -1) {
|
if (break_state == -1) {
|
||||||
writeb(cmdReg | CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
|
writeb(cmdReg | CMD_SND_BREAK, &icom_port->dram->CmdReg);
|
||||||
} else {
|
} 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);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int icom_open(struct uart_port *port)
|
static int icom_open(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
kref_get(&ICOM_PORT->adapter->kref);
|
kref_get(&icom_port->adapter->kref);
|
||||||
retval = startup(ICOM_PORT);
|
retval = startup(icom_port);
|
||||||
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
|
kref_put(&icom_port->adapter->kref, icom_kref_release);
|
||||||
trace(ICOM_PORT, "STARTUP_ERROR", 0);
|
trace(icom_port, "STARTUP_ERROR", 0);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1071,23 +1337,25 @@ static int icom_open(struct uart_port *port)
|
|||||||
|
|
||||||
static void icom_close(struct uart_port *port)
|
static void icom_close(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
unsigned char cmdReg;
|
unsigned char cmdReg;
|
||||||
|
|
||||||
trace(ICOM_PORT, "CLOSE", 0);
|
trace(icom_port, "CLOSE", 0);
|
||||||
|
|
||||||
/* stop receiver */
|
/* stop receiver */
|
||||||
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
|
cmdReg = readb(&icom_port->dram->CmdReg);
|
||||||
writeb(cmdReg & ~CMD_RCV_ENABLE, &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,
|
static void icom_set_termios(struct uart_port *port,
|
||||||
struct ktermios *termios,
|
struct ktermios *termios,
|
||||||
struct ktermios *old_termios)
|
struct ktermios *old_termios)
|
||||||
{
|
{
|
||||||
|
struct icom_port *icom_port = to_icom_port(port);
|
||||||
int baud;
|
int baud;
|
||||||
unsigned cflag, iflag;
|
unsigned cflag, iflag;
|
||||||
char new_config2;
|
char new_config2;
|
||||||
@@ -1099,7 +1367,7 @@ static void icom_set_termios(struct uart_port *port,
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
trace(ICOM_PORT, "CHANGE_SPEED", 0);
|
trace(icom_port, "CHANGE_SPEED", 0);
|
||||||
|
|
||||||
cflag = termios->c_cflag;
|
cflag = termios->c_cflag;
|
||||||
iflag = termios->c_iflag;
|
iflag = termios->c_iflag;
|
||||||
@@ -1130,12 +1398,12 @@ static void icom_set_termios(struct uart_port *port,
|
|||||||
if (cflag & PARENB) {
|
if (cflag & PARENB) {
|
||||||
/* parity bit enabled */
|
/* parity bit enabled */
|
||||||
new_config2 |= ICOM_ACFG_PARITY_ENAB;
|
new_config2 |= ICOM_ACFG_PARITY_ENAB;
|
||||||
trace(ICOM_PORT, "PARENB", 0);
|
trace(icom_port, "PARENB", 0);
|
||||||
}
|
}
|
||||||
if (cflag & PARODD) {
|
if (cflag & PARODD) {
|
||||||
/* odd parity */
|
/* odd parity */
|
||||||
new_config2 |= ICOM_ACFG_PARITY_ODD;
|
new_config2 |= ICOM_ACFG_PARITY_ODD;
|
||||||
trace(ICOM_PORT, "PARODD", 0);
|
trace(icom_port, "PARODD", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine divisor based on baud rate */
|
/* 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);
|
uart_update_timeout(port, cflag, baud);
|
||||||
|
|
||||||
/* CTS flow control flag and modem status interrupts */
|
/* 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)
|
if (cflag & CRTSCTS)
|
||||||
tmp_byte |= HDLC_HDW_FLOW;
|
tmp_byte |= HDLC_HDW_FLOW;
|
||||||
else
|
else
|
||||||
tmp_byte &= ~HDLC_HDW_FLOW;
|
tmp_byte &= ~HDLC_HDW_FLOW;
|
||||||
writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
|
writeb(tmp_byte, &(icom_port->dram->HDLCConfigReg));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up parity check flag
|
* 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)
|
if (iflag & INPCK)
|
||||||
ICOM_PORT->read_status_mask |=
|
icom_port->read_status_mask |=
|
||||||
SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
|
SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
|
||||||
|
|
||||||
if ((iflag & BRKINT) || (iflag & PARMRK))
|
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
|
* Characters to ignore
|
||||||
*/
|
*/
|
||||||
ICOM_PORT->ignore_status_mask = 0;
|
icom_port->ignore_status_mask = 0;
|
||||||
if (iflag & IGNPAR)
|
if (iflag & IGNPAR)
|
||||||
ICOM_PORT->ignore_status_mask |=
|
icom_port->ignore_status_mask |=
|
||||||
SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
|
SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
|
||||||
if (iflag & IGNBRK) {
|
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
|
* If we're ignore parity and break indicators, ignore
|
||||||
* overruns too. (For real raw support).
|
* overruns too. (For real raw support).
|
||||||
*/
|
*/
|
||||||
if (iflag & IGNPAR)
|
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
|
* !!! ignore all characters if CREAD is not set
|
||||||
*/
|
*/
|
||||||
if ((cflag & CREAD) == 0)
|
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 */
|
/* 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++) {
|
for (index = 0; index < 10; index++) {
|
||||||
if (readb(&ICOM_PORT->dram->PrevCmdReg) == 0x00) {
|
if (readb(&icom_port->dram->PrevCmdReg) == 0x00) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear all current buffers of data */
|
/* clear all current buffers of data */
|
||||||
for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
|
for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
|
||||||
ICOM_PORT->statStg->rcv[rcv_buff].flags = 0;
|
icom_port->statStg->rcv[rcv_buff].flags = 0;
|
||||||
ICOM_PORT->statStg->rcv[rcv_buff].leLength = 0;
|
icom_port->statStg->rcv[rcv_buff].leLength = 0;
|
||||||
ICOM_PORT->statStg->rcv[rcv_buff].WorkingLength =
|
icom_port->statStg->rcv[rcv_buff].WorkingLength =
|
||||||
(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
|
cpu_to_le16(RCV_BUFF_SZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (xmit_buff = 0; xmit_buff < NUM_XBUFFS; xmit_buff++) {
|
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 */
|
/* activate changes and start xmit and receiver here */
|
||||||
/* Enable the receiver */
|
/* Enable the receiver */
|
||||||
writeb(new_config3, &(ICOM_PORT->dram->async_config3));
|
writeb(new_config3, &(icom_port->dram->async_config3));
|
||||||
writeb(new_config2, &(ICOM_PORT->dram->async_config2));
|
writeb(new_config2, &(icom_port->dram->async_config2));
|
||||||
tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
|
tmp_byte = readb(&(icom_port->dram->HDLCConfigReg));
|
||||||
tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
|
tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
|
||||||
writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
|
writeb(tmp_byte, &(icom_port->dram->HDLCConfigReg));
|
||||||
writeb(0x04, &(ICOM_PORT->dram->FlagFillIdleTimer)); /* 0.5 seconds */
|
writeb(0x04, &(icom_port->dram->FlagFillIdleTimer)); /* 0.5 seconds */
|
||||||
writeb(0xFF, &(ICOM_PORT->dram->ier)); /* enable modem signal interrupts */
|
writeb(0xFF, &(icom_port->dram->ier)); /* enable modem signal interrupts */
|
||||||
|
|
||||||
/* reset processor */
|
/* reset processor */
|
||||||
writeb(CMD_RESTART, &ICOM_PORT->dram->CmdReg);
|
writeb(CMD_RESTART, &icom_port->dram->CmdReg);
|
||||||
|
|
||||||
for (index = 0; index < 10; index++) {
|
for (index = 0; index < 10; index++) {
|
||||||
if (readb(&ICOM_PORT->dram->CmdReg) == 0x00) {
|
if (readb(&icom_port->dram->CmdReg) == 0x00) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable Transmitter and Receiver */
|
/* Enable Transmitter and Receiver */
|
||||||
offset =
|
offset =
|
||||||
(unsigned long) &ICOM_PORT->statStg->rcv[0] -
|
(unsigned long) &icom_port->statStg->rcv[0] -
|
||||||
(unsigned long) ICOM_PORT->statStg;
|
(unsigned long) icom_port->statStg;
|
||||||
writel(ICOM_PORT->statStg_pci + offset,
|
writel(icom_port->statStg_pci + offset,
|
||||||
&ICOM_PORT->dram->RcvStatusAddr);
|
&icom_port->dram->RcvStatusAddr);
|
||||||
ICOM_PORT->next_rcv = 0;
|
icom_port->next_rcv = 0;
|
||||||
ICOM_PORT->put_length = 0;
|
*icom_port->xmitRestart = 0;
|
||||||
*ICOM_PORT->xmitRestart = 0;
|
writel(icom_port->xmitRestart_pci,
|
||||||
writel(ICOM_PORT->xmitRestart_pci,
|
&icom_port->dram->XmitStatusAddr);
|
||||||
&ICOM_PORT->dram->XmitStatusAddr);
|
trace(icom_port, "XR_ENAB", 0);
|
||||||
trace(ICOM_PORT, "XR_ENAB", 0);
|
writeb(CMD_XMIT_RCV_ENABLE, &icom_port->dram->CmdReg);
|
||||||
writeb(CMD_XMIT_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
@@ -1258,15 +1525,6 @@ static const char *icom_type(struct uart_port *port)
|
|||||||
return "icom";
|
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)
|
static void icom_config_port(struct uart_port *port, int flags)
|
||||||
{
|
{
|
||||||
port->type = PORT_ICOM;
|
port->type = PORT_ICOM;
|
||||||
@@ -1285,8 +1543,6 @@ static const struct uart_ops icom_ops = {
|
|||||||
.shutdown = icom_close,
|
.shutdown = icom_close,
|
||||||
.set_termios = icom_set_termios,
|
.set_termios = icom_set_termios,
|
||||||
.type = icom_type,
|
.type = icom_type,
|
||||||
.release_port = icom_release_port,
|
|
||||||
.request_port = icom_request_port,
|
|
||||||
.config_port = icom_config_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 = &icom_adapter->port_info[i];
|
||||||
icom_port->port = i;
|
icom_port->port = i;
|
||||||
icom_port->status = ICOM_PORT_ACTIVE;
|
icom_port->status = ICOM_PORT_ACTIVE;
|
||||||
icom_port->imbed_modem = ICOM_UNKNOWN;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (subsystem_id == PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL) {
|
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->port = i;
|
||||||
icom_port->status = ICOM_PORT_ACTIVE;
|
icom_port->status = ICOM_PORT_ACTIVE;
|
||||||
icom_port->imbed_modem = ICOM_IMBED_MODEM;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icom_adapter->numb_ports = 4;
|
icom_adapter->numb_ports = 4;
|
||||||
|
|
||||||
icom_adapter->port_info[0].port = 0;
|
icom_adapter->port_info[0].port = 0;
|
||||||
icom_adapter->port_info[0].status = ICOM_PORT_ACTIVE;
|
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[1].status = ICOM_PORT_OFF;
|
||||||
|
|
||||||
icom_adapter->port_info[2].port = 2;
|
icom_adapter->port_info[2].port = 2;
|
||||||
icom_adapter->port_info[2].status = ICOM_PORT_ACTIVE;
|
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;
|
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;
|
int adapter_count = 0;
|
||||||
struct icom_adapter *icom_adapter;
|
struct icom_adapter *icom_adapter;
|
||||||
struct icom_adapter *cur_adapter_entry;
|
struct icom_adapter *cur_adapter_entry;
|
||||||
struct list_head *tmp;
|
|
||||||
|
|
||||||
icom_adapter = kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
|
icom_adapter = kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
|
||||||
|
|
||||||
@@ -1409,10 +1652,8 @@ static int icom_alloc_adapter(struct icom_adapter
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each(tmp, &icom_adapter_head) {
|
list_for_each_entry(cur_adapter_entry, &icom_adapter_head,
|
||||||
cur_adapter_entry =
|
icom_adapter_entry) {
|
||||||
list_entry(tmp, struct icom_adapter,
|
|
||||||
icom_adapter_entry);
|
|
||||||
if (cur_adapter_entry->index != adapter_count) {
|
if (cur_adapter_entry->index != adapter_count) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1420,7 +1661,8 @@ static int icom_alloc_adapter(struct icom_adapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
icom_adapter->index = adapter_count;
|
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;
|
*icom_adapter_ref = icom_adapter;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1432,8 +1674,10 @@ static void icom_free_adapter(struct icom_adapter *icom_adapter)
|
|||||||
kfree(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;
|
struct icom_port *icom_port;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@@ -1466,14 +1710,6 @@ static void icom_remove_adapter(struct icom_adapter *icom_adapter)
|
|||||||
icom_free_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,
|
static int icom_probe(struct pci_dev *dev,
|
||||||
const struct pci_device_id *ent)
|
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);
|
retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(&dev->dev, "PCI Config read FAILED\n");
|
dev_err(&dev->dev, "PCI Config read FAILED\n");
|
||||||
return retval;
|
goto probe_exit0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_write_config_dword(dev, PCI_COMMAND,
|
pci_write_config_dword(dev, PCI_COMMAND,
|
||||||
@@ -1589,11 +1825,9 @@ probe_exit0:
|
|||||||
static void icom_remove(struct pci_dev *dev)
|
static void icom_remove(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct icom_adapter *icom_adapter;
|
struct icom_adapter *icom_adapter;
|
||||||
struct list_head *tmp;
|
|
||||||
|
|
||||||
list_for_each(tmp, &icom_adapter_head) {
|
list_for_each_entry(icom_adapter, &icom_adapter_head,
|
||||||
icom_adapter = list_entry(tmp, struct icom_adapter,
|
icom_adapter_entry) {
|
||||||
icom_adapter_entry);
|
|
||||||
if (icom_adapter->pci_dev == dev) {
|
if (icom_adapter->pci_dev == dev) {
|
||||||
kref_put(&icom_adapter->kref, icom_kref_release);
|
kref_put(&icom_adapter->kref, icom_kref_release);
|
||||||
return;
|
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)
|
rs485conf->flags & SER_RS485_RX_DURING_TX)
|
||||||
imx_uart_start_rx(port);
|
imx_uart_start_rx(port);
|
||||||
|
|
||||||
port->rs485 = *rs485conf;
|
|
||||||
|
|
||||||
return 0;
|
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 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_head = 0;
|
||||||
ch->ch_r_tail = 0;
|
ch->ch_r_tail = 0;
|
||||||
ch->ch_e_head = 0;
|
ch->ch_e_head = 0;
|
||||||
@@ -723,14 +723,8 @@ static void cls_param(struct jsm_channel *ch)
|
|||||||
if (!(ch->ch_c_cflag & PARODD))
|
if (!(ch->ch_c_cflag & PARODD))
|
||||||
lcr |= UART_LCR_EPAR;
|
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)
|
if (ch->ch_c_cflag & CMSPAR)
|
||||||
lcr |= UART_LCR_SPAR;
|
lcr |= UART_LCR_SPAR;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ch->ch_c_cflag & CSTOPB)
|
if (ch->ch_c_cflag & CSTOPB)
|
||||||
lcr |= UART_LCR_STOP;
|
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 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_r_head = ch->ch_r_tail = 0;
|
||||||
ch->ch_e_head = ch->ch_e_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))
|
if (!(ch->ch_c_cflag & PARODD))
|
||||||
lcr |= UART_LCR_EPAR;
|
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)
|
if (ch->ch_c_cflag & CMSPAR)
|
||||||
lcr |= UART_LCR_SPAR;
|
lcr |= UART_LCR_SPAR;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ch->ch_c_cflag & CSTOPB)
|
if (ch->ch_c_cflag & CSTOPB)
|
||||||
lcr |= UART_LCR_STOP;
|
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 |
|
rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX |
|
||||||
SER_RS485_ENABLED;
|
SER_RS485_ENABLED;
|
||||||
memset(rs485->padding, 0, sizeof(rs485->padding));
|
|
||||||
port->rs485 = *rs485;
|
port->rs485 = *rs485;
|
||||||
|
|
||||||
schedule_work(&one->rs_work);
|
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.iotype = UPIO_MEM;
|
||||||
uart->port.ops = &men_z135_ops;
|
uart->port.ops = &men_z135_ops;
|
||||||
uart->port.irq = mcb_get_irq(mdev);
|
uart->port.irq = mcb_get_irq(mdev);
|
||||||
uart->port.iotype = UPIO_MEM;
|
|
||||||
uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
|
uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
|
||||||
uart->port.line = line++;
|
uart->port.line = line++;
|
||||||
uart->port.dev = dev;
|
uart->port.dev = dev;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
#define AML_UART_BAUD_MASK 0x7fffff
|
#define AML_UART_BAUD_MASK 0x7fffff
|
||||||
#define AML_UART_BAUD_USE BIT(23)
|
#define AML_UART_BAUD_USE BIT(23)
|
||||||
#define AML_UART_BAUD_XTAL BIT(24)
|
#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_NUM 12
|
||||||
#define AML_UART_PORT_OFFSET 6
|
#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];
|
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)
|
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;
|
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)
|
static void meson_uart_reset(struct uart_port *port)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
@@ -267,9 +280,12 @@ static void meson_uart_reset(struct uart_port *port)
|
|||||||
|
|
||||||
static int meson_uart_startup(struct uart_port *port)
|
static int meson_uart_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
u32 val;
|
u32 val;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
val = readl(port->membase + AML_UART_CONTROL);
|
val = readl(port->membase + AML_UART_CONTROL);
|
||||||
val |= AML_UART_CLEAR_ERR;
|
val |= AML_UART_CLEAR_ERR;
|
||||||
writel(val, port->membase + AML_UART_CONTROL);
|
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));
|
val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2));
|
||||||
writel(val, port->membase + AML_UART_MISC);
|
writel(val, port->membase + AML_UART_MISC);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
ret = request_irq(port->irq, meson_uart_interrupt, 0,
|
ret = request_irq(port->irq, meson_uart_interrupt, 0,
|
||||||
port->name, port);
|
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)
|
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))
|
while (!meson_uart_tx_empty(port))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
if (port->uartclk == 24000000) {
|
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;
|
val |= AML_UART_BAUD_XTAL;
|
||||||
} else {
|
} else {
|
||||||
val = ((port->uartclk * 10 / (baud * 4) + 5) / 10) - 1;
|
val = DIV_ROUND_CLOSEST(port->uartclk / 4, baud) - 1;
|
||||||
}
|
}
|
||||||
val |= AML_UART_BAUD_USE;
|
val |= AML_UART_BAUD_USE;
|
||||||
writel(val, port->membase + AML_UART_REG5);
|
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->x_char = 0;
|
||||||
port->ops = &meson_uart_ops;
|
port->ops = &meson_uart_ops;
|
||||||
port->fifosize = fifosize;
|
port->fifosize = fifosize;
|
||||||
|
port->private_data = (void *)device_get_match_data(&pdev->dev);
|
||||||
|
|
||||||
meson_ports[pdev->id] = port;
|
meson_ports[pdev->id] = port;
|
||||||
platform_set_drvdata(pdev, port);
|
platform_set_drvdata(pdev, port);
|
||||||
@@ -777,11 +803,19 @@ static int meson_uart_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct meson_uart_data s4_uart_data = {
|
||||||
|
.has_xtal_div2 = true,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id meson_uart_dt_match[] = {
|
static const struct of_device_id meson_uart_dt_match[] = {
|
||||||
{ .compatible = "amlogic,meson6-uart" },
|
{ .compatible = "amlogic,meson6-uart" },
|
||||||
{ .compatible = "amlogic,meson8-uart" },
|
{ .compatible = "amlogic,meson8-uart" },
|
||||||
{ .compatible = "amlogic,meson8b-uart" },
|
{ .compatible = "amlogic,meson8b-uart" },
|
||||||
{ .compatible = "amlogic,meson-gx-uart" },
|
{ .compatible = "amlogic,meson-gx-uart" },
|
||||||
|
{
|
||||||
|
.compatible = "amlogic,meson-s4-uart",
|
||||||
|
.data = (void *)&s4_uart_data,
|
||||||
|
},
|
||||||
{ /* sentinel */ },
|
{ /* sentinel */ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
|
MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/clk.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->irqflags = IRQF_SHARED;
|
||||||
port->irq = psc_fifoc_irq;
|
port->irq = psc_fifoc_irq;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_MPC512x
|
|
||||||
|
|
||||||
#define PSC_5125(port) ((struct mpc5125_psc __iomem *)((port)->membase))
|
#define PSC_5125(port) ((struct mpc5125_psc __iomem *)((port)->membase))
|
||||||
#define FIFO_5125(port) ((struct mpc512x_psc_fifo __iomem *)(PSC_5125(port)+1))
|
#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,
|
static void __msm_console_write(struct uart_port *port, const char *s,
|
||||||
unsigned int count, bool is_uartdm)
|
unsigned int count, bool is_uartdm)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
int num_newlines = 0;
|
int num_newlines = 0;
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
@@ -1616,6 +1617,8 @@ static void __msm_console_write(struct uart_port *port, const char *s,
|
|||||||
num_newlines++;
|
num_newlines++;
|
||||||
count += num_newlines;
|
count += num_newlines;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
|
||||||
if (port->sysrq)
|
if (port->sysrq)
|
||||||
locked = 0;
|
locked = 0;
|
||||||
else if (oops_in_progress)
|
else if (oops_in_progress)
|
||||||
@@ -1661,6 +1664,8 @@ static void __msm_console_write(struct uart_port *port, const char *s,
|
|||||||
|
|
||||||
if (locked)
|
if (locked)
|
||||||
spin_unlock(&port->lock);
|
spin_unlock(&port->lock);
|
||||||
|
|
||||||
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msm_console_write(struct console *co, const char *s,
|
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;
|
up->ier = 0;
|
||||||
serial_out(up, UART_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) {
|
if (up->rts_gpiod) {
|
||||||
/* enable / disable rts */
|
/* 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;
|
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);
|
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
|
/* If RS-485 is disabled, make sure the THR interrupt is fired when
|
||||||
* TX FIFO is below the trigger level.
|
* 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)) {
|
||||||
up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
|
up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
|
||||||
serial_out(up, UART_OMAP_SCR, up->scr);
|
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;
|
struct circ_buf *xmit = &port->state->xmit;
|
||||||
unsigned int ch;
|
unsigned int ch;
|
||||||
|
|
||||||
if (uart_tx_stopped(port))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (port->x_char) {
|
if (port->x_char) {
|
||||||
while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU))
|
while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
@@ -195,6 +192,9 @@ static void owl_uart_send_chars(struct uart_port *port)
|
|||||||
port->x_char = 0;
|
port->x_char = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uart_tx_stopped(port))
|
||||||
|
return;
|
||||||
|
|
||||||
while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU)) {
|
while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU)) {
|
||||||
if (uart_circ_empty(xmit))
|
if (uart_circ_empty(xmit))
|
||||||
break;
|
break;
|
||||||
@@ -731,6 +731,7 @@ static int owl_uart_probe(struct platform_device *pdev)
|
|||||||
owl_port->port.uartclk = clk_get_rate(owl_port->clk);
|
owl_port->port.uartclk = clk_get_rate(owl_port->clk);
|
||||||
if (owl_port->port.uartclk == 0) {
|
if (owl_port->port.uartclk == 0) {
|
||||||
dev_err(&pdev->dev, "clock rate is zero\n");
|
dev_err(&pdev->dev, "clock rate is zero\n");
|
||||||
|
clk_disable_unprepare(owl_port->clk);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
owl_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY;
|
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;
|
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,
|
static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
|
||||||
int rx_size)
|
int rx_size)
|
||||||
{
|
{
|
||||||
@@ -624,22 +612,6 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
|
|||||||
return 0;
|
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)
|
static int dma_push_rx(struct eg20t_port *priv, int size)
|
||||||
{
|
{
|
||||||
int room;
|
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);
|
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)
|
static int handle_rx_to(struct eg20t_port *priv)
|
||||||
{
|
{
|
||||||
struct pch_uart_buffer *buf;
|
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 uart_port *port = &priv->port;
|
||||||
struct circ_buf *xmit = &port->state->xmit;
|
struct circ_buf *xmit = &port->state->xmit;
|
||||||
int fifo_size;
|
int fifo_size;
|
||||||
int tx_size;
|
|
||||||
int size;
|
|
||||||
int tx_empty;
|
int tx_empty;
|
||||||
|
|
||||||
if (!priv->start_tx) {
|
if (!priv->start_tx) {
|
||||||
@@ -889,19 +834,19 @@ static unsigned int handle_tx(struct eg20t_port *priv)
|
|||||||
|
|
||||||
fifo_size = max(priv->fifo_size, 1);
|
fifo_size = max(priv->fifo_size, 1);
|
||||||
tx_empty = 1;
|
tx_empty = 1;
|
||||||
if (pop_tx_x(priv, xmit->buf)) {
|
if (port->x_char) {
|
||||||
pch_uart_hal_write(priv, xmit->buf, 1);
|
iowrite8(port->x_char, priv->membase + PCH_UART_THR);
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
|
port->x_char = 0;
|
||||||
tx_empty = 0;
|
tx_empty = 0;
|
||||||
fifo_size--;
|
fifo_size--;
|
||||||
}
|
}
|
||||||
size = min(xmit->head - xmit->tail, fifo_size);
|
|
||||||
if (size < 0)
|
|
||||||
size = fifo_size;
|
|
||||||
|
|
||||||
tx_size = pop_tx(priv, size);
|
while (!uart_tx_stopped(port) && !uart_circ_empty(xmit) && fifo_size) {
|
||||||
if (tx_size > 0) {
|
iowrite8(xmit->buf[xmit->tail], priv->membase + PCH_UART_THR);
|
||||||
port->icount.tx += tx_size;
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
|
port->icount.tx++;
|
||||||
|
fifo_size--;
|
||||||
tx_empty = 0;
|
tx_empty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -946,9 +891,11 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fifo_size = max(priv->fifo_size, 1);
|
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->icount.tx++;
|
||||||
|
port->x_char = 0;
|
||||||
fifo_size--;
|
fifo_size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,13 +25,106 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#include <asm/mach-pic32/pic32.h>
|
#include <asm/mach-pic32/pic32.h>
|
||||||
#include "pic32_uart.h"
|
|
||||||
|
|
||||||
/* UART name and device definitions */
|
/* UART name and device definitions */
|
||||||
#define PIC32_DEV_NAME "pic32-uart"
|
#define PIC32_DEV_NAME "pic32-uart"
|
||||||
#define PIC32_MAX_UARTS 6
|
#define PIC32_MAX_UARTS 6
|
||||||
#define PIC32_SDEV_NAME "ttyPIC"
|
#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 */
|
/* pic32_sport pointer for console use */
|
||||||
static struct pic32_sport *pic32_sports[PIC32_MAX_UARTS];
|
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);
|
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 */
|
/* serial core request to check if uart tx buffer is empty */
|
||||||
static unsigned int pic32_uart_tx_empty(struct uart_port *port)
|
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)
|
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);
|
enable_irq(sport->irq_tx);
|
||||||
tx_irq_enabled(sport) = 1;
|
sport->enable_tx_irq = true;
|
||||||
} else if (!en && tx_irq_enabled(sport)) {
|
} else if (!en && sport->enable_tx_irq) {
|
||||||
/* use disable_irq_nosync() and not disable_irq() to avoid self
|
/* use disable_irq_nosync() and not disable_irq() to avoid self
|
||||||
* imposed deadlock by not waiting for irq handler to end,
|
* imposed deadlock by not waiting for irq handler to end,
|
||||||
* since this callback is called from interrupt context.
|
* since this callback is called from interrupt context.
|
||||||
*/
|
*/
|
||||||
disable_irq_nosync(sport->irq_tx);
|
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);
|
local_irq_save(flags);
|
||||||
|
|
||||||
ret = pic32_enable_clock(sport);
|
ret = clk_prepare_enable(sport->clk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
goto out_done;
|
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.
|
* For each irq request_irq() is called with interrupt disabled.
|
||||||
* And the irq is enabled as soon as we are ready to handle them.
|
* 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",
|
sport->irq_fault_name = kasprintf(GFP_KERNEL, "%s%d-fault",
|
||||||
pic32_uart_type(port),
|
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);
|
irq_set_status_flags(sport->irq_fault, IRQ_NOAUTOEN);
|
||||||
ret = request_irq(sport->irq_fault, pic32_uart_fault_interrupt,
|
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) {
|
if (ret) {
|
||||||
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
||||||
__func__, sport->irq_fault, ret,
|
__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);
|
irq_set_status_flags(sport->irq_rx, IRQ_NOAUTOEN);
|
||||||
ret = request_irq(sport->irq_rx, pic32_uart_rx_interrupt,
|
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) {
|
if (ret) {
|
||||||
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
||||||
__func__, sport->irq_rx, ret,
|
__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);
|
irq_set_status_flags(sport->irq_tx, IRQ_NOAUTOEN);
|
||||||
ret = request_irq(sport->irq_tx, pic32_uart_tx_interrupt,
|
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) {
|
if (ret) {
|
||||||
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
|
||||||
__func__, sport->irq_tx, ret,
|
__func__, sport->irq_tx, ret,
|
||||||
@@ -488,19 +564,21 @@ static int pic32_uart_startup(struct uart_port *port)
|
|||||||
/* enable all interrupts and eanable uart */
|
/* enable all interrupts and eanable uart */
|
||||||
pic32_uart_en_and_unmask(port);
|
pic32_uart_en_and_unmask(port);
|
||||||
|
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
enable_irq(sport->irq_rx);
|
enable_irq(sport->irq_rx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_t:
|
out_t:
|
||||||
kfree(sport->irq_tx_name);
|
|
||||||
free_irq(sport->irq_tx, port);
|
free_irq(sport->irq_tx, port);
|
||||||
|
kfree(sport->irq_tx_name);
|
||||||
out_r:
|
out_r:
|
||||||
kfree(sport->irq_rx_name);
|
|
||||||
free_irq(sport->irq_rx, port);
|
free_irq(sport->irq_rx, port);
|
||||||
|
kfree(sport->irq_rx_name);
|
||||||
out_f:
|
out_f:
|
||||||
kfree(sport->irq_fault_name);
|
|
||||||
free_irq(sport->irq_fault, port);
|
free_irq(sport->irq_fault, port);
|
||||||
|
kfree(sport->irq_fault_name);
|
||||||
out_done:
|
out_done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -515,12 +593,15 @@ static void pic32_uart_shutdown(struct uart_port *port)
|
|||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
pic32_uart_dsbl_and_mask(port);
|
pic32_uart_dsbl_and_mask(port);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
pic32_disable_clock(sport);
|
clk_disable_unprepare(sport->clk);
|
||||||
|
|
||||||
/* free all 3 interrupts for this UART */
|
/* free all 3 interrupts for this UART */
|
||||||
free_irq(sport->irq_fault, port);
|
free_irq(sport->irq_fault, port);
|
||||||
|
kfree(sport->irq_fault_name);
|
||||||
free_irq(sport->irq_tx, port);
|
free_irq(sport->irq_tx, port);
|
||||||
|
kfree(sport->irq_tx_name);
|
||||||
free_irq(sport->irq_rx, port);
|
free_irq(sport->irq_rx, port);
|
||||||
|
kfree(sport->irq_rx_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* serial core request to change current uart setting */
|
/* 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)
|
unsigned int count)
|
||||||
{
|
{
|
||||||
struct pic32_sport *sport = pic32_sports[co->index];
|
struct pic32_sport *sport = pic32_sports[co->index];
|
||||||
struct uart_port *port = pic32_get_port(sport);
|
|
||||||
|
|
||||||
/* call uart helper to deal with \r\n */
|
/* 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
|
/* 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)
|
static int pic32_console_setup(struct console *co, char *options)
|
||||||
{
|
{
|
||||||
struct pic32_sport *sport;
|
struct pic32_sport *sport;
|
||||||
struct uart_port *port = NULL;
|
|
||||||
int baud = 115200;
|
int baud = 115200;
|
||||||
int bits = 8;
|
int bits = 8;
|
||||||
int parity = 'n';
|
int parity = 'n';
|
||||||
@@ -737,16 +816,15 @@ static int pic32_console_setup(struct console *co, char *options)
|
|||||||
sport = pic32_sports[co->index];
|
sport = pic32_sports[co->index];
|
||||||
if (!sport)
|
if (!sport)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
port = pic32_get_port(sport);
|
|
||||||
|
|
||||||
ret = pic32_enable_clock(sport);
|
ret = clk_prepare_enable(sport->clk);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (options)
|
if (options)
|
||||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
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;
|
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->idx = uart_idx;
|
||||||
sport->irq_fault = irq_of_parse_and_map(np, 0);
|
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->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->irq_tx = irq_of_parse_and_map(np, 2);
|
||||||
sport->irqflags_tx = IRQF_NO_THREAD;
|
|
||||||
sport->clk = devm_clk_get(&pdev->dev, NULL);
|
sport->clk = devm_clk_get(&pdev->dev, NULL);
|
||||||
sport->cts_gpio = -EINVAL;
|
|
||||||
sport->dev = &pdev->dev;
|
sport->dev = &pdev->dev;
|
||||||
|
|
||||||
/* Hardware flow control: gpios
|
/* Hardware flow control: gpios
|
||||||
@@ -850,7 +924,6 @@ static int pic32_uart_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
pic32_sports[uart_idx] = sport;
|
pic32_sports[uart_idx] = sport;
|
||||||
port = &sport->port;
|
port = &sport->port;
|
||||||
memset(port, 0, sizeof(*port));
|
|
||||||
port->iotype = UPIO_MEM;
|
port->iotype = UPIO_MEM;
|
||||||
port->mapbase = res_mem->start;
|
port->mapbase = res_mem->start;
|
||||||
port->ops = &pic32_uart_ops;
|
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,
|
/* The peripheral clock has been enabled by console_setup,
|
||||||
* so disable it till the port is used.
|
* so disable it till the port is used.
|
||||||
*/
|
*/
|
||||||
pic32_disable_clock(sport);
|
clk_disable_unprepare(sport->clk);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -893,7 +966,7 @@ static int pic32_uart_remove(struct platform_device *pdev)
|
|||||||
struct pic32_sport *sport = to_pic32_sport(port);
|
struct pic32_sport *sport = to_pic32_sport(port);
|
||||||
|
|
||||||
uart_remove_one_port(&pic32_uart_driver, port);
|
uart_remove_one_port(&pic32_uart_driver, port);
|
||||||
pic32_disable_clock(sport);
|
clk_disable_unprepare(sport->clk);
|
||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
pic32_sports[sport->idx] = 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
|
||||||
#undef DEBUG_HARD
|
|
||||||
#undef USE_CTRL_O_SYSRQ
|
#undef USE_CTRL_O_SYSRQ
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@@ -51,7 +50,6 @@
|
|||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_PMAC
|
#ifdef CONFIG_PPC_PMAC
|
||||||
#include <asm/prom.h>
|
|
||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
#include <asm/pmac_feature.h>
|
#include <asm/pmac_feature.h>
|
||||||
#include <asm/dbdma.h>
|
#include <asm/dbdma.h>
|
||||||
@@ -66,10 +64,6 @@
|
|||||||
|
|
||||||
#include "pmac_zilog.h"
|
#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_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
|
||||||
MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports.");
|
MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports.");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
@@ -446,9 +440,6 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
|
|||||||
spin_lock(&uap_a->port.lock);
|
spin_lock(&uap_a->port.lock);
|
||||||
r3 = read_zsreg(uap_a, R3);
|
r3 = read_zsreg(uap_a, R3);
|
||||||
|
|
||||||
#ifdef DEBUG_HARD
|
|
||||||
pmz_debug("irq, r3: %x\n", r3);
|
|
||||||
#endif
|
|
||||||
/* Channel A */
|
/* Channel A */
|
||||||
push = false;
|
push = false;
|
||||||
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
|
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);
|
struct uart_pmac_port *uap = to_pmz(port);
|
||||||
unsigned char status;
|
unsigned char status;
|
||||||
|
|
||||||
pmz_debug("pmz: start_tx()\n");
|
|
||||||
|
|
||||||
uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
|
uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
|
||||||
uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
|
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;
|
struct circ_buf *xmit = &port->state->xmit;
|
||||||
|
|
||||||
if (uart_circ_empty(xmit))
|
if (uart_circ_empty(xmit))
|
||||||
goto out;
|
return;
|
||||||
write_zsdata(uap, xmit->buf[xmit->tail]);
|
write_zsdata(uap, xmit->buf[xmit->tail]);
|
||||||
zssync(uap);
|
zssync(uap);
|
||||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
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)
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
uart_write_wakeup(&uap->port);
|
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);
|
struct uart_pmac_port *uap = to_pmz(port);
|
||||||
|
|
||||||
pmz_debug("pmz: stop_rx()()\n");
|
|
||||||
|
|
||||||
/* Disable all RX interrupts. */
|
/* Disable all RX interrupts. */
|
||||||
uap->curregs[R1] &= ~RxINT_MASK;
|
uap->curregs[R1] &= ~RxINT_MASK;
|
||||||
pmz_maybe_update_regs(uap);
|
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;
|
unsigned long flags;
|
||||||
int pwr_delay = 0;
|
int pwr_delay = 0;
|
||||||
|
|
||||||
pmz_debug("pmz: startup()\n");
|
|
||||||
|
|
||||||
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
|
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
|
||||||
|
|
||||||
/* A console is never powered down. Else, power up and
|
/* 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);
|
pmz_interrupt_control(uap, 1);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
pmz_debug("pmz: startup() done.\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -957,8 +936,6 @@ static void pmz_shutdown(struct uart_port *port)
|
|||||||
struct uart_pmac_port *uap = to_pmz(port);
|
struct uart_pmac_port *uap = to_pmz(port);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
pmz_debug("pmz: shutdown()\n");
|
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
/* Disable interrupt requests for the channel */
|
/* 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 */
|
pmz_set_scc_power(uap, 0); /* Shut the chip down */
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
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
|
/* 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);
|
struct uart_pmac_port *uap = to_pmz(port);
|
||||||
unsigned long baud;
|
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
|
/* 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
|
* 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
|
* 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);
|
pmz_maybe_update_regs(uap);
|
||||||
}
|
}
|
||||||
uart_update_timeout(port, termios->c_cflag, baud);
|
uart_update_timeout(port, termios->c_cflag, baud);
|
||||||
|
|
||||||
pmz_debug("pmz: set_termios() done.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The port lock is not held. */
|
/* The port lock is not held. */
|
||||||
@@ -1400,7 +1369,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
|
|||||||
char name[1];
|
char name[1];
|
||||||
} *slots;
|
} *slots;
|
||||||
int len;
|
int len;
|
||||||
struct resource r_ports, r_rxdma, r_txdma;
|
struct resource r_ports;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request & map chip registers
|
* 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->control_reg = uap->port.membase;
|
||||||
uap->data_reg = uap->control_reg + 0x10;
|
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
|
* Detect port type
|
||||||
@@ -1506,8 +1446,6 @@ no_dma:
|
|||||||
of_device_is_compatible(np->parent->parent, "gatwick")) {
|
of_device_is_compatible(np->parent->parent, "gatwick")) {
|
||||||
/* IRQs on gatwick are offset by 64 */
|
/* IRQs on gatwick are offset by 64 */
|
||||||
uap->port.irq = irq_create_mapping(NULL, 64 + 15);
|
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
|
/* 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;
|
struct device_node *np;
|
||||||
|
|
||||||
np = uap->node;
|
np = uap->node;
|
||||||
iounmap(uap->rx_dma_regs);
|
|
||||||
iounmap(uap->tx_dma_regs);
|
|
||||||
iounmap(uap->control_reg);
|
iounmap(uap->control_reg);
|
||||||
uap->node = NULL;
|
uap->node = NULL;
|
||||||
of_node_put(np);
|
of_node_put(np);
|
||||||
@@ -1875,7 +1811,6 @@ static struct platform_driver pmz_driver = {
|
|||||||
static int __init init_pmz(void)
|
static int __init init_pmz(void)
|
||||||
{
|
{
|
||||||
int rc, i;
|
int rc, i;
|
||||||
printk(KERN_INFO "%s\n", version);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, we need to do a direct OF-based probe pass. We
|
* 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_TX_ACTIVE 0x00000040
|
||||||
#define PMACZILOG_FLAG_IS_IRDA 0x00000100
|
#define PMACZILOG_FLAG_IS_IRDA 0x00000100
|
||||||
#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
|
#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
|
||||||
#define PMACZILOG_FLAG_HAS_DMA 0x00000400
|
|
||||||
#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
|
#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
|
||||||
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
|
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
|
||||||
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
|
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
|
||||||
@@ -55,16 +54,7 @@ struct uart_pmac_port {
|
|||||||
volatile u8 __iomem *control_reg;
|
volatile u8 __iomem *control_reg;
|
||||||
volatile u8 __iomem *data_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];
|
unsigned char irq_name[8];
|
||||||
|
|
||||||
struct ktermios termios_cache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_pmz(p) ((struct uart_pmac_port *)(p))
|
#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_WANTS_MODEM_STATUS(UP) ((UP)->flags & PMACZILOG_FLAG_MODEM_STATUS)
|
||||||
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
|
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
|
||||||
#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
|
#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_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
|
||||||
#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
|
#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_stop_rx(struct uart_port *uport);
|
||||||
static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
|
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) \
|
#define to_dev_port(ptr, member) \
|
||||||
container_of(ptr, struct qcom_geni_serial_port, 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);
|
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);
|
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
|
||||||
writel(irq_en | M_TX_FIFO_WATERMARK_EN,
|
writel(irq_en | M_TX_FIFO_WATERMARK_EN,
|
||||||
uport->membase + SE_GENI_M_IRQ_EN);
|
uport->membase + SE_GENI_M_IRQ_EN);
|
||||||
@@ -946,25 +940,43 @@ static int qcom_geni_serial_startup(struct uart_port *uport)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long get_clk_cfg(unsigned long clk_freq)
|
static unsigned long get_clk_div_rate(struct clk *clk, unsigned int baud,
|
||||||
{
|
|
||||||
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,
|
|
||||||
unsigned int sampling_rate, unsigned int *clk_div)
|
unsigned int sampling_rate, unsigned int *clk_div)
|
||||||
{
|
{
|
||||||
unsigned long ser_clk;
|
unsigned long ser_clk;
|
||||||
unsigned long desired_clk;
|
unsigned long desired_clk;
|
||||||
|
unsigned long freq, prev;
|
||||||
|
unsigned long div, maxdiv;
|
||||||
|
int64_t mult;
|
||||||
|
|
||||||
desired_clk = baud * sampling_rate;
|
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) {
|
if (!ser_clk) {
|
||||||
pr_err("%s: Can't find matching DFS entry for baud %d\n",
|
pr_err("%s: Can't find matching DFS entry for baud %d\n",
|
||||||
__func__, baud);
|
__func__, baud);
|
||||||
@@ -972,6 +984,9 @@ static unsigned long get_clk_div_rate(unsigned int baud,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*clk_div = ser_clk / desired_clk;
|
*clk_div = ser_clk / desired_clk;
|
||||||
|
if (!(*clk_div))
|
||||||
|
*clk_div = 1;
|
||||||
|
|
||||||
return ser_clk;
|
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)
|
if (ver >= QUP_SE_VERSION_2_5)
|
||||||
sampling_rate /= 2;
|
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)
|
if (!clk_rate)
|
||||||
goto out_restart_rx;
|
goto out_restart_rx;
|
||||||
|
|
||||||
|
|||||||
@@ -262,6 +262,8 @@ static void rda_uart_set_termios(struct uart_port *port,
|
|||||||
fallthrough;
|
fallthrough;
|
||||||
case CS7:
|
case CS7:
|
||||||
ctrl &= ~RDA_UART_DBITS_8;
|
ctrl &= ~RDA_UART_DBITS_8;
|
||||||
|
termios->c_cflag &= ~CSIZE;
|
||||||
|
termios->c_cflag |= CS7;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ctrl |= RDA_UART_DBITS_8;
|
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);
|
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||||
quot = uart_get_divisor(port, baud);
|
quot = uart_get_divisor(port, baud);
|
||||||
|
|
||||||
|
del_timer_sync(&sport->timer);
|
||||||
|
|
||||||
spin_lock_irqsave(&sport->port.lock, flags);
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
|
|
||||||
sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
|
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);
|
UTSR1_TO_SM(UTSR1_ROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
del_timer_sync(&sport->timer);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the per-port timeout.
|
* Update the per-port timeout.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2480,12 +2480,24 @@ s3c24xx_serial_console_write(struct console *co, const char *s,
|
|||||||
unsigned int count)
|
unsigned int count)
|
||||||
{
|
{
|
||||||
unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
|
unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
|
||||||
|
unsigned long flags;
|
||||||
|
bool locked = true;
|
||||||
|
|
||||||
/* not possible to xmit on unconfigured port */
|
/* not possible to xmit on unconfigured port */
|
||||||
if (!s3c24xx_port_configured(ucon))
|
if (!s3c24xx_port_configured(ucon))
|
||||||
return;
|
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);
|
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 */
|
/* 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,
|
.num_clks = 1,
|
||||||
.clksel_mask = 0,
|
.clksel_mask = 0,
|
||||||
.clksel_shift = 0,
|
.clksel_shift = 0,
|
||||||
|
.ucon_mask = APPLE_S5L_UCON_MASK,
|
||||||
},
|
},
|
||||||
.def_cfg = {
|
.def_cfg = {
|
||||||
.ucon = APPLE_S5L_UCON_DEFAULT,
|
.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);
|
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
|
||||||
|
|
||||||
if (rs485->flags & SER_RS485_ENABLED) {
|
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.
|
* RTS signal is handled by HW, it's timing can't be influenced.
|
||||||
* However, it's sometimes useful to delay TX even without RTS
|
* However, it's sometimes useful to delay TX even without RTS
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <linux/sysrq.h>
|
#include <linux/sysrq.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/math64.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
|
|
||||||
#include <linux/irq.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)
|
#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,
|
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
||||||
struct ktermios *old_termios);
|
struct ktermios *old_termios);
|
||||||
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
|
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,
|
uart_update_timeout(struct uart_port *port, unsigned int cflag,
|
||||||
unsigned int baud)
|
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.
|
* Figure the timeout to send the above number of bits.
|
||||||
* Add .02 seconds of slop
|
* Add .02 seconds of slop
|
||||||
*/
|
*/
|
||||||
port->timeout = (HZ * size) / baud + HZ/50;
|
port->timeout = (HZ * size) / baud + HZ/50;
|
||||||
|
port->frame_time = DIV64_U64_ROUND_UP(frame_time, baud);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(uart_update_timeout);
|
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)))
|
if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user)))
|
||||||
return -EFAULT;
|
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);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
ret = port->rs485_config(port, &rs485);
|
ret = port->rs485_config(port, &rs485);
|
||||||
|
if (!ret)
|
||||||
|
port->rs485 = rs485;
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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
|
* Note: we have to use pretty tight timings here to satisfy
|
||||||
* the NIST-PCTS.
|
* the NIST-PCTS.
|
||||||
*/
|
*/
|
||||||
char_time = (port->timeout - HZ/50) / port->fifosize;
|
char_time = max(nsecs_to_jiffies(port->frame_time / 5), 1UL);
|
||||||
char_time = char_time / 5;
|
|
||||||
if (char_time == 0)
|
|
||||||
char_time = 1;
|
|
||||||
if (timeout && timeout < char_time)
|
if (timeout && timeout < char_time)
|
||||||
char_time = timeout;
|
char_time = 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
|
* If the transmitter hasn't cleared in twice the approximate
|
||||||
* ever clear. This assumes the UART isn't doing flow
|
* amount of time to send the entire FIFO, it probably won't
|
||||||
* control, which is currently the case. Hence, if it ever
|
* ever clear. This assumes the UART isn't doing flow
|
||||||
* takes longer than port->timeout, this is probably due to a
|
* control, which is currently the case. Hence, if it ever
|
||||||
* UART bug of some kind. So, we clamp the timeout parameter at
|
* takes longer than port->timeout, this is probably due to a
|
||||||
* 2*port->timeout.
|
* 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 (timeout == 0 || timeout > 2 * port->timeout)
|
||||||
|
timeout = 2 * port->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
expire = jiffies + 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));
|
msleep_interruptible(jiffies_to_msecs(char_time));
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
break;
|
break;
|
||||||
if (time_after(jiffies, expire))
|
if (timeout && time_after(jiffies, expire))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uart_port_deref(port);
|
uart_port_deref(port);
|
||||||
@@ -2174,15 +2211,23 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
|||||||
}
|
}
|
||||||
put_device(tty_dev);
|
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;
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
uport->suspended = 1;
|
uport->suspended = 1;
|
||||||
|
|
||||||
if (tty_port_initialized(port)) {
|
if (tty_port_initialized(port)) {
|
||||||
const struct uart_ops *ops = uport->ops;
|
const struct uart_ops *ops = uport->ops;
|
||||||
int tries;
|
int tries;
|
||||||
|
unsigned int mctrl;
|
||||||
|
|
||||||
tty_port_set_suspended(port, 1);
|
tty_port_set_suspended(port, 1);
|
||||||
tty_port_set_initialized(port, 0);
|
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);
|
spin_lock_irq(&uport->lock);
|
||||||
ops->stop_tx(uport);
|
ops->stop_tx(uport);
|
||||||
ops->set_mctrl(uport, 0);
|
ops->set_mctrl(uport, 0);
|
||||||
|
/* save mctrl so it can be restored on resume */
|
||||||
|
mctrl = uport->mctrl;
|
||||||
|
uport->mctrl = 0;
|
||||||
ops->stop_rx(uport);
|
ops->stop_rx(uport);
|
||||||
spin_unlock_irq(&uport->lock);
|
spin_unlock_irq(&uport->lock);
|
||||||
|
|
||||||
@@ -2203,6 +2251,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
|||||||
uport->name);
|
uport->name);
|
||||||
|
|
||||||
ops->shutdown(uport);
|
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 CS6: /* not supported */
|
||||||
case CS8:
|
case CS8:
|
||||||
cval |= TXX9_SILCR_UMODE_8BIT;
|
cval |= TXX9_SILCR_UMODE_8BIT;
|
||||||
|
termios->c_cflag &= ~CSIZE;
|
||||||
|
termios->c_cflag |= CS8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2379,8 +2379,12 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||||||
int best_clk = -1;
|
int best_clk = -1;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if ((termios->c_cflag & CSIZE) == CS7)
|
if ((termios->c_cflag & CSIZE) == CS7) {
|
||||||
smr_val |= SCSMR_CHR;
|
smr_val |= SCSMR_CHR;
|
||||||
|
} else {
|
||||||
|
termios->c_cflag &= ~CSIZE;
|
||||||
|
termios->c_cflag |= CS8;
|
||||||
|
}
|
||||||
if (termios->c_cflag & PARENB)
|
if (termios->c_cflag & PARENB)
|
||||||
smr_val |= SCSMR_PE;
|
smr_val |= SCSMR_PE;
|
||||||
if (termios->c_cflag & PARODD)
|
if (termios->c_cflag & PARODD)
|
||||||
|
|||||||
@@ -148,7 +148,6 @@
|
|||||||
* @port: struct uart_port embedded in this struct
|
* @port: struct uart_port embedded in this struct
|
||||||
* @dev: struct device *
|
* @dev: struct device *
|
||||||
* @ier: shadowed copy of the interrupt enable register
|
* @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)
|
* @baud_rate: UART serial line rate (e.g., 115200 baud)
|
||||||
* @clk: reference to this device's clock
|
* @clk: reference to this device's clock
|
||||||
* @clk_notifier: clock rate change notifier for upstream clock changes
|
* @clk_notifier: clock rate change notifier for upstream clock changes
|
||||||
@@ -159,7 +158,6 @@ struct sifive_serial_port {
|
|||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
unsigned char ier;
|
unsigned char ier;
|
||||||
unsigned long clkin_rate;
|
|
||||||
unsigned long baud_rate;
|
unsigned long baud_rate;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct notifier_block clk_notifier;
|
struct notifier_block clk_notifier;
|
||||||
@@ -463,7 +461,7 @@ static void __ssp_update_div(struct sifive_serial_port *ssp)
|
|||||||
{
|
{
|
||||||
u16 div;
|
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);
|
__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));
|
udelay(DIV_ROUND_UP(12 * 1000 * 1000, ssp->baud_rate));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event == POST_RATE_CHANGE && ssp->clkin_rate != cnd->new_rate) {
|
if (event == POST_RATE_CHANGE && ssp->port.uartclk != cnd->new_rate) {
|
||||||
ssp->clkin_rate = cnd->new_rate;
|
ssp->port.uartclk = cnd->new_rate;
|
||||||
__ssp_update_div(ssp);
|
__ssp_update_div(ssp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,19 +664,24 @@ static void sifive_serial_set_termios(struct uart_port *port,
|
|||||||
int rate;
|
int rate;
|
||||||
char nstop;
|
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");
|
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))
|
if (termios->c_iflag & (INPCK | PARMRK))
|
||||||
dev_err_once(ssp->port.dev, "parity checking not supported\n");
|
dev_err_once(ssp->port.dev, "parity checking not supported\n");
|
||||||
if (termios->c_iflag & BRKINT)
|
if (termios->c_iflag & BRKINT)
|
||||||
dev_err_once(ssp->port.dev, "BREAK detection not supported\n");
|
dev_err_once(ssp->port.dev, "BREAK detection not supported\n");
|
||||||
|
termios->c_iflag &= ~(INPCK|PARMRK|BRKINT);
|
||||||
|
|
||||||
/* Set number of stop bits */
|
/* Set number of stop bits */
|
||||||
nstop = (termios->c_cflag & CSTOPB) ? 2 : 1;
|
nstop = (termios->c_cflag & CSTOPB) ? 2 : 1;
|
||||||
__ssp_set_stop_bits(ssp, nstop);
|
__ssp_set_stop_bits(ssp, nstop);
|
||||||
|
|
||||||
/* Set line rate */
|
/* 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);
|
__ssp_update_baud_rate(ssp, rate);
|
||||||
|
|
||||||
spin_lock_irqsave(&ssp->port.lock, flags);
|
spin_lock_irqsave(&ssp->port.lock, flags);
|
||||||
@@ -996,9 +999,8 @@ static int sifive_serial_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set up clock divider */
|
/* 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->baud_rate = SIFIVE_DEFAULT_BAUD_RATE;
|
||||||
ssp->port.uartclk = ssp->baud_rate * 16;
|
|
||||||
__ssp_update_div(ssp);
|
__ssp_update_div(ssp);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, 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 */
|
/* set character length */
|
||||||
if ((cflag & CSIZE) == CS7) {
|
if ((cflag & CSIZE) == CS7) {
|
||||||
ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
|
ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
|
||||||
|
cflag |= PARENB;
|
||||||
} else {
|
} else {
|
||||||
ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR :
|
ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR :
|
||||||
ASC_CTL_MODE_8BIT;
|
ASC_CTL_MODE_8BIT;
|
||||||
|
cflag &= ~CSIZE;
|
||||||
|
cflag |= CS8;
|
||||||
}
|
}
|
||||||
|
termios->c_cflag = cflag;
|
||||||
|
|
||||||
/* set stop bit */
|
/* set stop bit */
|
||||||
ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
|
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_stop_tx(struct uart_port *port);
|
||||||
static void stm32_usart_transmit_chars(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)
|
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));
|
stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
|
||||||
|
|
||||||
port->rs485 = *rs485conf;
|
|
||||||
|
|
||||||
rs485conf->flags |= SER_RS485_RX_DURING_TX;
|
rs485conf->flags |= SER_RS485_RX_DURING_TX;
|
||||||
|
|
||||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
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,
|
rs485conf->delay_rts_after_send,
|
||||||
baud);
|
baud);
|
||||||
|
|
||||||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
|
if (rs485conf->flags & SER_RS485_RTS_ON_SEND)
|
||||||
cr3 &= ~USART_CR3_DEP;
|
cr3 &= ~USART_CR3_DEP;
|
||||||
rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
else
|
||||||
} else {
|
|
||||||
cr3 |= USART_CR3_DEP;
|
cr3 |= USART_CR3_DEP;
|
||||||
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
writel_relaxed(cr3, port->membase + ofs->cr3);
|
writel_relaxed(cr3, port->membase + ofs->cr3);
|
||||||
writel_relaxed(cr1, port->membase + ofs->cr1);
|
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);
|
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)
|
static void stm32_usart_rx_dma_complete(void *arg)
|
||||||
{
|
{
|
||||||
struct uart_port *port = 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);
|
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)
|
static void stm32_usart_transmit_chars_pio(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct stm32_port *stm32_port = to_stm32_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;
|
u32 isr;
|
||||||
int ret;
|
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 (port->x_char) {
|
||||||
if (stm32_usart_tx_dma_started(stm32_port) &&
|
if (stm32_usart_tx_dma_started(stm32_port) &&
|
||||||
stm32_usart_tx_dma_enabled(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)
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
uart_write_wakeup(port);
|
uart_write_wakeup(port);
|
||||||
|
|
||||||
if (uart_circ_empty(xmit))
|
if (uart_circ_empty(xmit)) {
|
||||||
stm32_usart_tx_interrupt_disable(port);
|
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)
|
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);
|
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)
|
if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
|
||||||
writel_relaxed(USART_ICR_RTOCF,
|
writel_relaxed(USART_ICR_RTOCF,
|
||||||
port->membase + ofs->icr);
|
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)
|
static void stm32_usart_stop_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct stm32_port *stm32_port = to_stm32_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;
|
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||||
|
|
||||||
stm32_usart_tx_interrupt_disable(port);
|
stm32_usart_tx_interrupt_disable(port);
|
||||||
if (stm32_usart_tx_dma_started(stm32_port) && stm32_usart_tx_dma_enabled(stm32_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);
|
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
|
||||||
|
|
||||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
stm32_usart_rs485_rts_disable(port);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There are probably characters waiting to be transmitted. */
|
/* There are probably characters waiting to be transmitted. */
|
||||||
static void stm32_usart_start_tx(struct uart_port *port)
|
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;
|
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;
|
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);
|
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
|
* CS8 or (CS7 + parity), 8 bits word aka [M1:M0] = 0b00
|
||||||
* M0 and M1 already cleared by cr1 initialization.
|
* M0 and M1 already cleared by cr1 initialization.
|
||||||
*/
|
*/
|
||||||
if (bits == 9)
|
if (bits == 9) {
|
||||||
cr1 |= USART_CR1_M0;
|
cr1 |= USART_CR1_M0;
|
||||||
else if ((bits == 7) && cfg->has_7bits_data)
|
} else if ((bits == 7) && cfg->has_7bits_data) {
|
||||||
cr1 |= USART_CR1_M1;
|
cr1 |= USART_CR1_M1;
|
||||||
else if (bits != 8)
|
} else if (bits != 8) {
|
||||||
dev_dbg(port->dev, "Unsupported data bits config: %u bits\n"
|
dev_dbg(port->dev, "Unsupported data bits config: %u bits\n"
|
||||||
, bits);
|
, 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 ||
|
if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch ||
|
||||||
(stm32_port->fifoen &&
|
(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 = {
|
static const struct uart_ops stm32_uart_ops = {
|
||||||
.tx_empty = stm32_usart_tx_empty,
|
.tx_empty = stm32_usart_tx_empty,
|
||||||
.set_mctrl = stm32_usart_set_mctrl,
|
.set_mctrl = stm32_usart_set_mctrl,
|
||||||
@@ -1243,6 +1330,11 @@ static const struct uart_ops stm32_uart_ops = {
|
|||||||
.request_port = stm32_usart_request_port,
|
.request_port = stm32_usart_request_port,
|
||||||
.config_port = stm32_usart_config_port,
|
.config_port = stm32_usart_config_port,
|
||||||
.verify_port = stm32_usart_verify_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_STM32_CONSOLE
|
static void __maybe_unused stm32_usart_console_putchar(struct uart_port *port, unsigned char ch)
|
||||||
static void stm32_usart_console_putchar(struct uart_port *port, unsigned char ch)
|
|
||||||
{
|
{
|
||||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||||
|
u32 isr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
while (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE))
|
ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, isr,
|
||||||
cpu_relax();
|
(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);
|
writel_relaxed(ch, port->membase + ofs->tdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_STM32_CONSOLE
|
||||||
static void stm32_usart_console_write(struct console *co, const char *s,
|
static void stm32_usart_console_write(struct console *co, const char *s,
|
||||||
unsigned int cnt)
|
unsigned int cnt)
|
||||||
{
|
{
|
||||||
@@ -1727,6 +1825,57 @@ static struct console stm32_console = {
|
|||||||
#define STM32_SERIAL_CONSOLE NULL
|
#define STM32_SERIAL_CONSOLE NULL
|
||||||
#endif /* CONFIG_SERIAL_STM32_CONSOLE */
|
#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 = {
|
static struct uart_driver stm32_usart_driver = {
|
||||||
.driver_name = DRIVER_NAME,
|
.driver_name = DRIVER_NAME,
|
||||||
.dev_name = STM32_SERIAL_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 RX_BUF_P (RX_BUF_L / 2) /* dma rx buffer period */
|
||||||
#define TX_BUF_L RX_BUF_L /* dma tx buffer length */
|
#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 stm32_port {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
@@ -269,6 +271,7 @@ struct stm32_port {
|
|||||||
bool hw_flow_control;
|
bool hw_flow_control;
|
||||||
bool swap; /* swap RX & TX pins */
|
bool swap; /* swap RX & TX pins */
|
||||||
bool fifoen;
|
bool fifoen;
|
||||||
|
bool txdone;
|
||||||
int rxftcfg; /* RX FIFO threshold CFG */
|
int rxftcfg; /* RX FIFO threshold CFG */
|
||||||
int txftcfg; /* TX FIFO threshold CFG */
|
int txftcfg; /* TX FIFO threshold CFG */
|
||||||
bool wakeup_src;
|
bool wakeup_src;
|
||||||
|
|||||||
@@ -498,7 +498,7 @@ static const struct uart_ops sunplus_uart_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE
|
#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,
|
static void sunplus_uart_console_putchar(struct uart_port *port,
|
||||||
unsigned char ch)
|
unsigned char ch)
|
||||||
|
|||||||
@@ -798,10 +798,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
|
|||||||
cval |= UART_LCR_PARITY;
|
cval |= UART_LCR_PARITY;
|
||||||
if (!(cflag & PARODD))
|
if (!(cflag & PARODD))
|
||||||
cval |= UART_LCR_EPAR;
|
cval |= UART_LCR_EPAR;
|
||||||
#ifdef CMSPAR
|
|
||||||
if (cflag & CMSPAR)
|
if (cflag & CMSPAR)
|
||||||
cval |= UART_LCR_SPAR;
|
cval |= UART_LCR_SPAR;
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Work around a bug in the Oxford Semiconductor 952 rev B
|
* 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
Reference in New Issue
Block a user