Commit e444d51b authored by Linus Torvalds's avatar Linus Torvalds

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

Pull tty/serial driver updates from Greg KH:
 "Even in this age, people are still making new serial port silicon,
  why...

  Anyway, here's the TTY and Serial driver update for 5.4-rc1. Lots of
  changes in here for a number of embedded serial port devices that are
  being worked on because people really like to see those console
  logs...

  Other than that, nothing major here, no core tty changes that anyone
  should care about.

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

* tag 'tty-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (125 commits)
  serial: tegra: Add PIO mode support
  serial: tegra: report clk rate errors
  serial: tegra: add support to adjust baud rate
  serial: tegra: DT for Adjusted baud rates
  serial: tegra: add support to use 8 bytes trigger
  serial: tegra: set maximum num of uart ports to 8
  serial: tegra: check for FIFO mode enabled status
  dt-binding: serial: tegra: add new chips
  serial: tegra: report error to upper tty layer
  serial: tegra: flush the RX fifo on frame error
  serial: tegra: avoid reg access when clk disabled
  serial: tegra: add support to ignore read
  serial: sprd: correct the wrong sequence of arguments
  dt-bindings: serial: Convert riscv,sifive-serial to json-schema
  serial: max310x: turn off transmitter before activating AutoCTS or auto transmitter flow control
  serial: max310x: Properly set flags in AutoCTS mode
  tty: serial: fix platform_no_drv_owner.cocci warnings
  dt-bindings: serial: Document Freescale LINFlexD UART
  serial: fsl_linflexuart: Update compatible string
  tty: n_gsm: avoid recursive locking with async port hangup
  ...
parents c6b48dad 1dce2df3
......@@ -1094,6 +1094,12 @@
the framebuffer, pass the 'ram' option so that it is
mapped with the correct attributes.
linflex,<addr>
Use early console provided by Freescale LinFlex UART
serial driver for NXP S32V234 SoCs. A valid base
address must be provided, and the serial port must
already be setup and configured.
earlyprintk= [X86,SH,ARM,M68k,S390]
earlyprintk=vga
earlyprintk=sclp
......
* Freescale LINFlexD UART
The LINFlexD controller implements several LIN protocol versions, as well as
support for full-duplex UART communication through 8-bit and 9-bit frames.
See chapter 47 ("LINFlexD") in the reference manual[1].
Required properties:
- compatible :
- "fsl,s32v234-linflexuart" for LINFlexD configured in UART mode, which
is compatible with the one integrated on S32V234 SoC
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
Example:
uart0: serial@40053000 {
compatible = "fsl,s32v234-linflexuart";
reg = <0x0 0x40053000 0x0 0x1000>;
interrupts = <0 59 4>;
};
[1] https://www.nxp.com/webapp/Download?colCode=S32V234RM
NVIDIA Tegra20/Tegra30 high speed (DMA based) UART controller driver.
Required properties:
- compatible : should be "nvidia,tegra30-hsuart", "nvidia,tegra20-hsuart".
- compatible : should be,
"nvidia,tegra20-hsuart" for Tegra20,
"nvidia,tegra30-hsuart" for Tegra30,
"nvidia,tegra186-hsuart" for Tegra186,
"nvidia,tegra194-hsuart" for Tegra194.
- reg: Should contain UART controller registers location and length.
- interrupts: Should contain UART controller interrupts.
- clocks: Must contain one entry, for the module clock.
......@@ -19,6 +24,37 @@ Required properties:
Optional properties:
- nvidia,enable-modem-interrupt: Enable modem interrupts. Should be enable
only if all 8 lines of UART controller are pinmuxed.
- nvidia,adjust-baud-rates: List of entries providing percentage of baud rate
adjustment within a range.
Each entry contains sets of 3 values. Range low/high and adjusted rate.
<range_low range_high adjusted_rate>
When baud rate set on controller falls within the range mentioned in this
field, baud rate will be adjusted by percentage mentioned here.
Ex: <9600 115200 200>
Increase baud rate by 2% when set baud rate falls within range 9600 to 115200
Baud Rate tolerance:
Standard UART devices are expected to have tolerance for baud rate error by
-4 to +4 %. All Tegra devices till Tegra210 had this support. However,
Tegra186 chip has a known hardware issue. UART Rx baud rate tolerance level
is 0% to +4% in 1-stop config. Otherwise, the received data will have
corruption/invalid framing errors. Parker errata suggests adjusting baud
rate to be higher than the deviations observed in Tx.
Tx deviation of connected device can be captured over scope (or noted from
its spec) for valid range and Tegra baud rate has to be set above actual
Tx baud rate observed. To do this we use nvidia,adjust-baud-rates
As an example, consider there is deviation observed in Tx for baud rates as
listed below.
0 to 9600 has 1% deviation
9600 to 115200 2% deviation
This slight deviation is expcted and Tegra UART is expected to handle it. Due
to the issue stated above, baud rate on Tegra UART should be set equal to or
above deviation observed for avoiding frame errors.
Property should be set like this
nvidia,adjust-baud-rates = <0 9600 100>,
<9600 115200 200>;
Example:
......@@ -33,4 +69,5 @@ serial@70006000 {
reset-names = "serial";
dmas = <&apbdma 8>, <&apbdma 8>;
dma-names = "rx", "tx";
nvidia,adjust-baud-rates = <1000000 4000000 136>; /* 1.36% shift */
};
SiFive asynchronous serial interface (UART)
Required properties:
- compatible: should be something similar to
"sifive,<chip>-uart" for the UART as integrated
on a particular chip, and "sifive,uart<version>" for the
general UART IP block programming model. Supported
compatible strings as of the date of this writing are:
"sifive,fu540-c000-uart" for the SiFive UART v0 as
integrated onto the SiFive FU540 chip, or "sifive,uart0"
for the SiFive UART v0 IP block with no chip integration
tweaks (if any)
- reg: address and length of the register space
- interrupts: Should contain the UART interrupt identifier
- clocks: Should contain a clock identifier for the UART's parent clock
UART HDL that corresponds to the IP block version numbers can be found
here:
https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/uart
Example:
uart0: serial@10010000 {
compatible = "sifive,fu540-c000-uart", "sifive,uart0";
interrupt-parent = <&plic0>;
interrupts = <80>;
reg = <0x0 0x10010000 0x0 0x1000>;
clocks = <&prci PRCI_CLK_TLCLK>;
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/serial/sifive-serial.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SiFive asynchronous serial interface (UART)
maintainers:
- Pragnesh Patel <pragnesh.patel@sifive.com>
- Paul Walmsley <paul.walmsley@sifive.com>
- Palmer Dabbelt <palmer@sifive.com>
allOf:
- $ref: /schemas/serial.yaml#
properties:
compatible:
items:
- const: sifive,fu540-c000-uart
- const: sifive,uart0
description:
Should be something similar to "sifive,<chip>-uart"
for the UART as integrated on a particular chip,
and "sifive,uart<version>" for the general UART IP
block programming model.
UART HDL that corresponds to the IP block version
numbers can be found here -
https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/uart
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/sifive-fu540-prci.h>
serial@10010000 {
compatible = "sifive,fu540-c000-uart", "sifive,uart0";
interrupt-parent = <&plic0>;
interrupts = <80>;
reg = <0x0 0x10010000 0x0 0x1000>;
clocks = <&prci PRCI_CLK_TLCLK>;
};
...
......@@ -20,6 +20,11 @@ Optional properties:
linux,rs485-enabled-at-boot-time: see rs485.txt.
- dmas: phandle(s) to DMA controller node(s). Refer to stm32-dma.txt
- dma-names: "rx" and/or "tx"
- wakeup-source: bool flag to indicate this device has wakeup capabilities
- interrupt-names, if optional wake-up interrupt is used, should be:
- "event": the name for the interrupt line of the USART instance
- "wakeup" the name for the optional wake-up interrupt
Examples:
usart4: serial@40004c00 {
......
......@@ -18,18 +18,22 @@ How to use it
2. switch the serial line to using the n_gsm line discipline by using
TIOCSETD ioctl,
3. configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl,
4. obtain base gsmtty number for the used serial port,
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>
#define N_GSM0710 21 /* GSM 0710 Mux */
#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);
......@@ -58,21 +62,14 @@ Major parts of the initialization program :
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();
4. create the devices corresponding to the "virtual" serial ports (take care,
each modem has its configuration and some DLC have dedicated functions,
for example GPS), starting with minor 1 (DLC0 is reserved for the management
of the mux)::
MAJOR=`cat /proc/devices |grep gsmtty | awk '{print $1}`
for i in `seq 1 4`; do
mknod /dev/ttygsm$i c $MAJOR $i
done
5. use these devices as plain serial ports.
for example, it's possible:
......
......@@ -61,7 +61,10 @@ enum parport_pc_pci_cards {
wch_ch382_0s1p,
wch_ch382_2s1p,
brainboxes_5s1p,
sunix_2s1p,
sunix_4008a,
sunix_5069a,
sunix_5079a,
sunix_5099a,
};
/* each element directly indexed from enum list, above */
......@@ -151,7 +154,10 @@ static struct parport_pc_pci cards[] = {
/* wch_ch382_0s1p*/ { 1, { { 2, -1}, } },
/* wch_ch382_2s1p*/ { 1, { { 2, -1}, } },
/* brainboxes_5s1p */ { 1, { { 3, -1 }, } },
/* sunix_2s1p */ { 1, { { 3, -1 }, } },
/* sunix_4008a */ { 1, { { 1, 2 }, } },
/* sunix_5069a */ { 1, { { 1, 2 }, } },
/* sunix_5079a */ { 1, { { 1, 2 }, } },
/* sunix_5099a */ { 1, { { 1, 2 }, } },
};
static struct pci_device_id parport_serial_pci_tbl[] = {
......@@ -261,13 +267,15 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
{ PCI_VENDOR_ID_INTASHIELD, 0x4100,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_5s1p },
/*
* More SUNIX variations. At least one of these has part number
* '5079A but subdevice 0x102. That board reports 0x0708 as
* its PCI Class.
*/
/* Sunix boards */
{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
0x0102, 0, 0, sunix_2s1p },
0x0100, 0, 0, sunix_4008a },
{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
0x0101, 0, 0, sunix_5069a },
{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
0x0102, 0, 0, sunix_5079a },
{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
0x0104, 0, 0, sunix_5099a },
{ 0, } /* terminate list */
};
......@@ -516,11 +524,23 @@ static struct pciserial_board pci_parport_serial_boards[] = {
.base_baud = 921600,
.uart_offset = 8,
},
[sunix_2s1p] = {
.flags = FL_BASE0|FL_BASE_BARS,
[sunix_4008a] = {
.num_ports = 0,
},
[sunix_5069a] = {
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 0x8,
},
[sunix_5079a] = {
.num_ports = 2,
.base_baud = 921600,
.uart_offset = 8,
.base_baud = 921600,
.uart_offset = 0x8,
},
[sunix_5099a] = {
.num_ports = 4,
.base_baud = 921600,
.uart_offset = 0x8,
},
};
......
......@@ -871,8 +871,8 @@ static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
hvcsd->p_partition_ID = pi->partition_ID;
/* copy the null-term char too */
strlcpy(&hvcsd->p_location_code[0],
&pi->location_code[0], sizeof(hvcsd->p_location_code));
strlcpy(hvcsd->p_location_code, pi->location_code,
sizeof(hvcsd->p_location_code));
}
/*
......
......@@ -553,7 +553,6 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
tty = tty_port_tty_get(&port->port);
if (tty == NULL) {
word_count = byte_count >> 1;
while (byte_count > 1) {
inw(base);
byte_count -= 2;
......
......@@ -1716,7 +1716,7 @@ static void gsm_dlci_release(struct gsm_dlci *dlci)
gsm_destroy_network(dlci);
mutex_unlock(&dlci->mutex);
tty_vhangup(tty);
tty_hangup(tty);
tty_port_tty_set(&dlci->port, NULL);
tty_kref_put(tty);
......@@ -2171,6 +2171,16 @@ static inline void mux_put(struct gsm_mux *gsm)
kref_put(&gsm->ref, gsm_free_muxr);
}
static inline unsigned int mux_num_to_base(struct gsm_mux *gsm)
{
return gsm->num * NUM_DLCI;
}
static inline unsigned int mux_line_to_num(unsigned int line)
{
return line / NUM_DLCI;
}
/**
* gsm_alloc_mux - allocate a mux
*
......@@ -2351,7 +2361,8 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
{
int ret, i, base;
unsigned int base;
int ret, i;
gsm->tty = tty_kref_get(tty);
gsm->output = gsmld_output;
......@@ -2361,7 +2372,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
else {
/* Don't register device 0 - this is the control channel and not
a usable tty interface */
base = gsm->num << 6; /* Base for this MUX */
base = mux_num_to_base(gsm); /* Base for this MUX */
for (i = 1; i < NUM_DLCI; i++)
tty_register_device(gsm_tty_driver, base + i, NULL);
}
......@@ -2379,8 +2390,8 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
{
unsigned int base = mux_num_to_base(gsm); /* Base for this MUX */
int i;
int base = gsm->num << 6; /* Base for this MUX */
WARN_ON(tty != gsm->tty);
for (i = 1; i < NUM_DLCI; i++)
......@@ -2602,6 +2613,7 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
{
struct gsm_config c;
struct gsm_mux *gsm = tty->disc_data;
unsigned int base;
switch (cmd) {
case GSMIOC_GETCONF:
......@@ -2613,6 +2625,9 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
if (copy_from_user(&c, (void *)arg, sizeof(c)))
return -EFAULT;
return gsm_config(gsm, &c);
case GSMIOC_GETFIRST:
base = mux_num_to_base(gsm);
return put_user(base + 1, (__u32 __user *)arg);
default:
return n_tty_ioctl_helper(tty, file, cmd, arg);
}
......@@ -2908,7 +2923,7 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
struct gsm_mux *gsm;
struct gsm_dlci *dlci;
unsigned int line = tty->index;
unsigned int mux = line >> 6;
unsigned int mux = mux_line_to_num(line);
bool alloc = false;
int ret;
......
......@@ -1282,7 +1282,7 @@ static void nozomi_setup_private_data(struct nozomi *dc)
static ssize_t card_type_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
const struct nozomi *dc = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", dc->card_type);
}
......@@ -1291,7 +1291,7 @@ static DEVICE_ATTR_RO(card_type);
static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
const struct nozomi *dc = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", dc->open_ttys);
}
......
......@@ -56,10 +56,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
/* get the interrupt */
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(&pdev->dev, "irq not found - %i", ret);
if (ret < 0)
return ret;
}
data->uart.port.irq = ret;
/* map the main registers */
......
......@@ -1026,10 +1026,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
if (!has_acpi_companion(uart->port.dev)) {
gpios = mctrl_gpio_init(&uart->port, 0);
if (IS_ERR(gpios)) {
if (PTR_ERR(gpios) != -ENOSYS) {
ret = PTR_ERR(gpios);
goto out_unlock;
}
ret = PTR_ERR(gpios);
goto out_unlock;
} else {
uart->gpios = gpios;
}
......
......@@ -27,66 +27,36 @@
#include <asm/byteorder.h>
#include "8250.h"
#include "8250_dwlib.h"
/* Offsets for the DesignWare specific registers */
#define DW_UART_USR 0x1f /* UART Status Register */
#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
#define DW_UART_UCV 0xf8 /* UART Component Version */
/* Component Parameter Register bits */
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
#define DW_UART_CPR_AFCE_MODE (1 << 4)
#define DW_UART_CPR_THRE_MODE (1 << 5)
#define DW_UART_CPR_SIR_MODE (1 << 6)
#define DW_UART_CPR_SIR_LP_MODE (1 << 7)
#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8)
#define DW_UART_CPR_FIFO_ACCESS (1 << 9)
#define DW_UART_CPR_FIFO_STAT (1 << 10)
#define DW_UART_CPR_SHADOW (1 << 11)
#define DW_UART_CPR_ENCODED_PARMS (1 << 12)
#define DW_UART_CPR_DMA_EXTRA (1 << 13)
#define DW_UART_CPR_FIFO_MODE (0xff << 16)
/* Helper for fifo size calculation */
#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16)
/* DesignWare specific register fields */
#define DW_UART_MCR_SIRE BIT(6)
struct dw8250_data {
struct dw8250_port_data data;
u8 usr_reg;
u8 dlf_size;
int line;
int msr_mask_on;
int msr_mask_off;
struct clk *clk;
struct clk *pclk;
struct reset_control *rst;
struct uart_8250_dma dma;
unsigned int skip_autocfg:1;
unsigned int uart_16550_compatible:1;
};
static inline u32 dw8250_readl_ext(struct uart_port *p, int offset)
static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
{
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);
return container_of(data, struct dw8250_data, data);
}
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
struct dw8250_data *d = to_dw8250_data(p->private_data);
/* Override any modem control signals if needed */
if (offset == UART_MSR) {
......@@ -160,7 +130,7 @@ static void dw8250_tx_wait_empty(struct uart_port *p)
static void dw8250_serial_out38x(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
struct dw8250_data *d = to_dw8250_data(p->private_data);
/* Allow the TX to drain before we reconfigure */
if (offset == UART_LCR)
......@@ -175,7 +145,7 @@ static void dw8250_serial_out38x(struct uart_port *p, int offset, int value)
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
struct dw8250_data *d = to_dw8250_data(p->private_data);
writeb(value, p->membase + (offset << p->regshift));
......@@ -202,7 +172,7 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset)
static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
struct dw8250_data *d = to_dw8250_data(p->private_data);
value &= 0xff;
__raw_writeq(value, p->membase + (offset << p->regshift));
......@@ -216,7 +186,7 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
struct dw8250_data *d = to_dw8250_data(p->private_data);
writel(value, p->membase + (offset << p->regshift));
......@@ -233,7 +203,7 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
static void dw8250_serial_out32be(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
struct dw8250_data *d = to_dw8250_data(p->private_data);
iowrite32be(value, p->membase + (offset << p->regshift));
......@@ -252,7 +222,7 @@ static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset)
static int dw8250_handle_irq(struct uart_port *p)
{
struct uart_8250_port *up = up_to_u8250p(p);
struct dw8250_data *d = p->private_data;
struct dw8250_data *d = to_dw8250_data(p->private_data);
unsigned int iir = p->serial_in(p, UART_IIR);
unsigned int status;
unsigned long flags;
......@@ -306,7 +276,7 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
struct dw8250_data *d = p->private_data;
struct dw8250_data *d = to_dw8250_data(p->private_data);
long rate;
int ret;
......@@ -368,37 +338,6 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
return param == chan->device->dev;
}
/*
* divisor = div(I) + div(F)
* "I" means integer, "F" means fractional
* quot = div(I) = clk / (16 * baud)
* frac = div(F) * 2^dlf_size
*
* let rem = clk % (16 * baud)
* we have: div(F) * (16 * baud) = rem
* so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud)
*/
static unsigned int dw8250_get_divisor(struct uart_port *p,
unsigned int baud,
unsigned int *frac)
{
unsigned int quot, rem, base_baud = baud * 16;
struct dw8250_data *d = p->private_data;
quot = p->uartclk / base_baud;
rem = p->uartclk % base_baud;
*frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud);
return quot;
}
static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
unsigned int quot, unsigned int quot_frac)
{
dw8250_writel_ext(p, DW_UART_DLF, quot_frac);
serial8250_do_set_divisor(p, baud, quot, quot_frac);
}
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
{
if (p->dev->of_node) {
......@@ -437,65 +376,18 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
/* Platforms with iDMA 64-bit */
if (platform_get_resource_byname(to_platform_device(p->dev),
IORESOURCE_MEM, "lpss_priv")) {
data->dma.rx_param = p->dev->parent;
data->dma.tx_param = p->dev->parent;
data->dma.fn = dw8250_idma_filter;
}
}
static void dw8250_setup_port(struct uart_port *p)
{
struct uart_8250_port *up = up_to_u8250p(p);
u32 reg;
/*
* If the Component Version Register returns zero, we know that
* ADDITIONAL_FEATURES are not enabled. No need to go any further.
*/
reg = dw8250_readl_ext(p, DW_UART_UCV);
if (!reg)
return;
dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
(reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
dw8250_writel_ext(p, DW_UART_DLF, ~0U);
reg = dw8250_readl_ext(p, DW_UART_DLF);
dw8250_writel_ext(p, DW_UART_DLF, 0);
if (reg) {
struct dw8250_data *d = p->private_data;
d->dlf_size = fls(reg);
p->get_divisor = dw8250_get_divisor;
p->set_divisor = dw8250_set_divisor;
}
reg = dw8250_readl_ext(p, DW_UART_CPR);
if (!reg)
return;
/* Select the type based on fifo */
if (reg & DW_UART_CPR_FIFO_MODE) {
p->type = PORT_16550A;
p->flags |= UPF_FIXED_TYPE;
p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
up->capabilities = UART_CAP_FIFO;
data->data.dma.rx_param = p->dev->parent;
data->data.dma.tx_param = p->dev->parent;
data->data.dma.fn = dw8250_idma_filter;
}
if (reg & DW_UART_CPR_AFCE_MODE)
up->capabilities |= UART_CAP_AFE;
if (reg & DW_UART_CPR_SIR_MODE)
up->capabilities |= UART_CAP_IRDA;
}
static int dw8250_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {};
struct uart_8250_port uart = {}, *up = &uart;
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0);
struct uart_port *p = &uart.port;
struct uart_port *p = &up->port;
struct device *dev = &pdev->dev;
struct dw8250_data *data;
int err;
......@@ -534,9 +426,9 @@ static int dw8250_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
data->dma.fn = dw8250_fallback_dma_filter;
data->data.dma.fn = dw8250_fallback_dma_filter;
data->usr_reg = DW_UART_USR;
p->private_data = data;
p->private_data = &data->data;
data->uart_16550_compatible = device_property_read_bool(dev,
"snps,uart-16550-compatible");
......@@ -632,14 +524,14 @@ static int dw8250_probe(struct platform_device *pdev)
/* If we have a valid fifosize, try hooking up DMA */
if (p->fifosize) {
data->dma.rxconf.src_maxburst = p->fifosize / 4;
data->dma.txconf.dst_maxburst = p->fifosize / 4;
uart.dma = &data->dma;
data->data.dma.rxconf.src_maxburst = p->fifosize / 4;
data->data.dma.txconf.dst_maxburst = p->fifosize / 4;
up->dma = &data->data.dma;
}
data->line = serial8250_register_8250_port(&uart);
if (data->line < 0) {
err = data->line;
data->data.line = serial8250_register_8250_port(up);
if (data->data.line < 0) {
err = data->data.line;
goto err_reset;
}
......@@ -667,10 +559,11 @@ static int dw8250_probe(struct platform_device *pdev)
static int dw8250_remove(struct platform_device *pdev)
{
struct dw8250_data *data = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
pm_runtime_get_sync(&pdev->dev);
pm_runtime_get_sync(dev);
serial8250_unregister_port(data->line);
serial8250_unregister_port(data->data.line);
reset_control_assert(data->rst);
......@@ -680,8 +573,8 @@ static int dw8250_remove(struct platform_device *pdev)
if (!IS_ERR(data->clk))
clk_disable_unprepare(data->clk);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
return 0;
}
......@@ -691,7 +584,7 @@ static int dw8250_suspend(struct device *dev)
{
struct dw8250_data *data = dev_get_drvdata(dev);
serial8250_suspend_port(data->line);
serial8250_suspend_port(data->data.line);
return 0;
}
......@@ -700,7 +593,7 @@ static int dw8250_resume(struct device *dev)
{
struct dw8250_data *data = dev_get_drvdata(dev);
serial8250_resume_port(data->line);
serial8250_resume_port(data->data.line);
return 0;
}
......
// SPDX-License-Identifier: GPL-2.0+
/* Synopsys DesignWare 8250 library. */
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/serial_8250.h>
#include <linux/serial_core.h>
#include "8250_dwlib.h"
/* Offsets for the DesignWare specific registers */
#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
#define DW_UART_UCV 0xf8 /* UART Component Version */
/* Component Parameter Register bits */
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
#define DW_UART_CPR_AFCE_MODE (1 << 4)
#define DW_UART_CPR_THRE_MODE (1 << 5)
#define DW_UART_CPR_SIR_MODE (1 << 6)
#define DW_UART_CPR_SIR_LP_MODE (1 << 7)
#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8)
#define DW_UART_CPR_FIFO_ACCESS (1 << 9)
#define DW_UART_CPR_FIFO_STAT (1 << 10)
#define DW_UART_CPR_SHADOW (1 << 11)
#define DW_UART_CPR_ENCODED_PARMS (1 << 12)
#define DW_UART_CPR_DMA_EXTRA (1 << 13)
#define DW_UART_CPR_FIFO_MODE (0xff << 16)
/* Helper for FIFO size calculation */
#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16)
static inline u32 dw8250_readl_ext(struct uart_port *p, int offset)
{
if (p->iotype == UPIO_MEM32BE)
return ioread32be(p->membase + offset);
return readl(p->membase + offset);
}
static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg)
{
if (p->iotype == UPIO_MEM32BE)
iowrite32be(reg, p->membase + offset);
else
writel(reg, p->membase + offset);
}
/*
* divisor = div(I) + div(F)
* "I" means integer, "F" means fractional
* quot = div(I) = clk / (16 * baud)
* frac = div(F) * 2^dlf_size
*
* let rem = clk % (16 * baud)
* we have: div(F) * (16 * baud) = rem
* so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud)
*/
static unsigned int dw8250_get_divisor(struct uart_port *p, unsigned int baud,
unsigned int *frac)
{
unsigned int quot, rem, base_baud = baud * 16;
struct dw8250_port_data *d = p->private_data;
quot = p->uartclk / base_baud;
rem = p->uartclk % base_baud;
*frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud);
return quot;
}
static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
unsigned int quot, unsigned int quot_frac)
{
dw8250_writel_ext(p, DW_UART_DLF, quot_frac);
serial8250_do_set_divisor(p, baud, quot, quot_frac);
}
void dw8250_setup_port(struct uart_port *p)
{
struct uart_8250_port *up = up_to_u8250p(p);
u32 reg;
/*
* If the Component Version Register returns zero, we know that
* ADDITIONAL_FEATURES are not enabled. No need to go any further.
*/
reg = dw8250_readl_ext(p, DW_UART_UCV);
if (!reg)
return;
dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
(reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
dw8250_writel_ext(p, DW_UART_DLF, ~0U);
reg = dw8250_readl_ext(p, DW_UART_DLF);
dw8250_writel_ext(p, DW_UART_DLF, 0);
if (reg) {
struct dw8250_port_data *d = p->private_data;
d->dlf_size = fls(reg);
p->get_divisor = dw8250_get_divisor;
p->set_divisor = dw8250_set_divisor;
}
reg = dw8250_readl_ext(p, DW_UART_CPR);
if (!reg)
return;
/* Select the type based on FIFO */
if (reg & DW_UART_CPR_FIFO_MODE) {
p->type = PORT_16550A;
p->flags |= UPF_FIXED_TYPE;
p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
up->capabilities = UART_CAP_FIFO;
}
if (reg & DW_UART_CPR_AFCE_MODE)
up->capabilities |= UART_CAP_AFE;
if (reg & DW_UART_CPR_SIR_MODE)
up->capabilities |= UART_CAP_IRDA;
}
EXPORT_SYMBOL_GPL(dw8250_setup_port);
// SPDX-License-Identifier: GPL-2.0+
/* Synopsys DesignWare 8250 library header file. */
#include <linux/types.h>
#include "8250.h"
struct dw8250_port_data {
/* Port properties */
int line;
/* DMA operations */
struct uart_8250_dma dma;
/* Hardware configuration */
u8 dlf_size;
};
void dw8250_setup_port(struct uart_port *p);
......@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/tty.h>
#include <linux/8250_pci.h>
#include <linux/delay.h>
#include <asm/byteorder.h>
......@@ -36,6 +37,8 @@
#define UART_EXAR_INT0 0x80
#define UART_EXAR_8XMODE 0x88 /* 8X sampling rate select */
#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
#define UART_EXAR_DVID 0x8d /* Device identification */
#define UART_EXAR_FCTR 0x08 /* Feature Control Register */
#define UART_FCTR_EXAR_IRDA 0x10 /* IrDa data encode select */
......@@ -127,18 +130,95 @@ struct exar8250 {
int line[0];
};
static void exar_pm(struct uart_port *port, unsigned int state, unsigned int old)
{
/*
* Exar UARTs have a SLEEP register that enables or disables each UART
* to enter sleep mode separately. On the XR17V35x the register
* is accessible to each UART at the UART_EXAR_SLEEP offset, but
* the UART channel may only write to the corresponding bit.
*/
serial_port_out(port, UART_EXAR_SLEEP, state ? 0xff : 0);
}
/*
* XR17V35x UARTs have an extra fractional divisor register (DLD)
* Calculate divisor with extra 4-bit fractional portion
*/
static unsigned int xr17v35x_get_divisor(struct uart_port *p, unsigned int baud,
unsigned int *frac)
{
unsigned int quot_16;
quot_16 = DIV_ROUND_CLOSEST(p->uartclk, baud);
*frac = quot_16 & 0x0f;
return quot_16 >> 4;
}
static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud,
unsigned int quot, unsigned int quot_frac)
{
serial8250_do_set_divisor(p, baud, quot, quot_frac);
/* Preserve bits not related to baudrate; DLD[7:4]. */
quot_frac |= serial_port_in(p, 0x2) & 0xf0;
serial_port_out(p, 0x2, quot_frac);
}
static void exar_shutdown(struct uart_port *port)
{
unsigned char lsr;
bool tx_complete = 0;
struct uart_8250_port *up = up_to_u8250p(port);
struct circ_buf *xmit = &port->state->xmit;
int i = 0;
do {
lsr = serial_in(up, UART_LSR);
if (lsr & (UART_LSR_TEMT | UART_LSR_THRE))
tx_complete = 1;
else
tx_complete = 0;
usleep_range(1000, 1100);
} while (!uart_circ_empty(xmit) && !tx_complete && i++ < 1000);
serial8250_do_shutdown(port);
}
static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,
int idx, unsigned int offset,
struct uart_8250_port *port)
{
const struct exar8250_board *board = priv->board;
unsigned int bar = 0;
unsigned char status;
port->port.iotype = UPIO_MEM;
port->port.mapbase = pci_resource_start(pcidev, bar) + offset;
port->port.membase = priv->virt + offset;
port->port.regshift = board->reg_shift;
/*
* XR17V35x UARTs have an extra divisor register, DLD that gets enabled
* with when DLAB is set which will cause the device to incorrectly match
* and assign port type to PORT_16650. The EFR for this UART is found
* at offset 0x09. Instead check the Deice ID (DVID) register
* for a 2, 4 or 8 port UART.
*/
status = readb(port->port.membase + UART_EXAR_DVID);
if (status == 0x82 || status == 0x84 || status == 0x88) {
port->port.type = PORT_XR17V35X;
port->port.get_divisor = xr17v35x_get_divisor;
port->port.set_divisor = xr17v35x_set_divisor;
} else {
port->port.type = PORT_XR17D15X;
}
port->port.pm = exar_pm;
port->port.shutdown = exar_shutdown;
return 0;
}
......@@ -434,6 +514,16 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev)
port->port.private_data = NULL;
}
static inline void exar_misc_clear(struct exar8250 *priv)
{
/* Clear all PCI interrupts by reading INT0. No effect on IIR */
readb(priv->virt + UART_EXAR_INT0);
/* Clear INT0 for Expansion Interface slave ports, too */
if (priv->board->num_ports > 8)
readb(priv->virt + 0x2000 + UART_EXAR_INT0);
}
/*
* These Exar UARTs have an extra interrupt indicator that could fire for a
* few interrupts that are not presented/cleared through IIR. One of which is
......@@ -445,14 +535,7 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev)
*/
static irqreturn_t exar_misc_handler(int irq, void *data)
{
struct exar8250 *priv = data;
/* Clear all PCI interrupts by reading INT0. No effect on IIR */
readb(priv->virt + UART_EXAR_INT0);
/* Clear INT0 for Expansion Interface slave ports, too */
if (priv->board->num_ports > 8)
readb(priv->virt + 0x2000 + UART_EXAR_INT0);
exar_misc_clear(data);
return IRQ_HANDLED;
}
......@@ -478,9 +561,7 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
nr_ports = board->num_ports ? board->num_ports : pcidev->device & 0x0f;
priv = devm_kzalloc(&pcidev->dev, sizeof(*priv) +
sizeof(unsigned int) * nr_ports,
GFP_KERNEL);
priv = devm_kzalloc(&pcidev->dev, struct_size(priv, line, nr_ports), GFP_KERNEL);
if (!priv)
return -ENOMEM;
......@@ -496,8 +577,7 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
return rc;
memset(&uart, 0, sizeof(uart));
uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ
| UPF_EXAR_EFR;
uart.port.flags = UPF_SHARE_IRQ | UPF_EXAR_EFR | UPF_FIXED_TYPE | UPF_FIXED_PORT;
uart.port.irq = pci_irq_vector(pcidev, 0);
uart.port.dev = &pcidev->dev;
......@@ -506,6 +586,9 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
if (rc)
return rc;
/* Clear interrupts */
exar_misc_clear(priv);
for (i = 0; i < nr_ports && i < maxnr; i++) {
rc = board->setup(priv, pcidev, &uart, i);
if (rc) {
......@@ -561,10 +644,11 @@ static int __maybe_unused exar_suspend(struct device *dev)
static int __maybe_unused exar_resume(struct device *dev)
{
struct pci_dev *pcidev = to_pci_dev(dev);
struct exar8250 *priv = pci_get_drvdata(pcidev);
struct exar8250 *priv = dev_get_drvdata(dev);
unsigned int i;
exar_misc_clear(priv);
for (i = 0; i < priv->nr; i++)
if (priv->line[i] >= 0)
serial8250_resume_port(priv->line[i]);
......
......@@ -106,10 +106,8 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
int irq, ret;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "irq not found");
if (irq < 0)
return irq;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
......
......@@ -14,7 +14,7 @@
#include <linux/dmaengine.h>
#include <linux/dma/dw.h>
#include "8250.h"
#include "8250_dwlib.h"
#define PCI_DEVICE_ID_INTEL_QRK_UARTx 0x0936
......@@ -24,6 +24,13 @@
#define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a
#define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c
#define PCI_DEVICE_ID_INTEL_EHL_UART0 0x4b96
#define PCI_DEVICE_ID_INTEL_EHL_UART1 0x4b97
#define PCI_DEVICE_ID_INTEL_EHL_UART2 0x4b98
#define PCI_DEVICE_ID_INTEL_EHL_UART3 0x4b99
#define PCI_DEVICE_ID_INTEL_EHL_UART4 0x4b9a
#define PCI_DEVICE_ID_INTEL_EHL_UART5 0x4b9b
#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3
#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4
......@@ -48,21 +55,25 @@ struct lpss8250_board {
};
struct lpss8250 {
int line;
struct dw8250_port_data data;
struct lpss8250_board *board;
/* DMA parameters */
struct uart_8250_dma dma;
struct dw_dma_chip dma_chip;
struct dw_dma_slave dma_param;
u8 dma_maxburst;
};
static inline struct lpss8250 *to_lpss8250(struct dw8250_port_data *data)
{
return container_of(data, struct lpss8250, data);
}
static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
struct lpss8250 *lpss = p->private_data;
struct lpss8250 *lpss = to_lpss8250(p->private_data);
unsigned long fref = lpss->board->freq, fuart = baud * 16;
unsigned long w = BIT(15) - 1;
unsigned long m, n;
......@@ -109,7 +120,6 @@ static unsigned int byt_get_mctrl(struct uart_port *port)
static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct dw_dma_slave *param = &lpss->dma_param;
struct uart_8250_port *up = up_to_u8250p(port);
struct pci_dev *pdev = to_pci_dev(port->dev);
unsigned int dma_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
struct pci_dev *dma_dev = pci_get_slot(pdev->bus, dma_devfn);
......@@ -135,10 +145,6 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
param->m_master = 0;
param->p_master = 1;
/* TODO: Detect FIFO size automaticaly for DesignWare 8250 */
port->fifosize = 64;
up->tx_loadsz = 64;
lpss->dma_maxburst = 16;
port->set_termios = byt_set_termios;
......@@ -163,16 +169,19 @@ static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port)
{
struct uart_8250_dma *dma = &lpss->dma;
struct uart_8250_dma *dma = &lpss->data.dma;
struct dw_dma_chip *chip = &lpss->dma_chip;
struct dw_dma_slave *param = &lpss->dma_param;
struct pci_dev *pdev = to_pci_dev(port->dev);
int ret;
chip->pdata = &qrk_serial_dma_pdata;
chip->dev = &pdev->dev;
chip->id = pdev->devfn;
chip->irq = pci_irq_vector(pdev, 0);
chip->regs = pci_ioremap_bar(pdev, 1);
chip->pdata = &qrk_serial_dma_pdata;
if (!chip->regs)
return;
/* Falling back to PIO mode if DMA probing fails */
ret = dw_dma_probe(chip);
......@@ -195,11 +204,15 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port)
static void qrk_serial_exit_dma(struct lpss8250 *lpss)
{
struct dw_dma_chip *chip = &lpss->dma_chip;
struct dw_dma_slave *param = &lpss->dma_param;
if (!param->dma_dev)
return;
dw_dma_remove(&lpss->dma_chip);
dw_dma_remove(chip);
pci_iounmap(to_pci_dev(chip->dev), chip->regs);
}
#else /* CONFIG_SERIAL_8250_DMA */
static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) {}
......@@ -241,7 +254,7 @@ static bool lpss8250_dma_filter(struct dma_chan *chan, void *param)
static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port)
{
struct uart_8250_dma *dma = &lpss->dma;
struct uart_8250_dma *dma = &lpss->data.dma;
struct dw_dma_slave *rx_param, *tx_param;
struct device *dev = port->port.dev;
......@@ -290,7 +303,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
uart.port.dev = &pdev->dev;
uart.port.irq = pdev->irq;
uart.port.private_data = lpss;
uart.port.private_data = &lpss->data;
uart.port.type = PORT_16550A;
uart.port.iotype = UPIO_MEM;
uart.port.regshift = 2;
......@@ -306,6 +319,8 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
return ret;
dw8250_setup_port(&uart.port);
ret = lpss8250_dma_setup(lpss, &uart);
if (ret)
goto err_exit;
......@@ -314,7 +329,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret < 0)
goto err_exit;
lpss->line = ret;
lpss->data.line = ret;
pci_set_drvdata(pdev, lpss);
return 0;
......@@ -329,7 +344,7 @@ static void lpss8250_remove(struct pci_dev *pdev)
{
struct lpss8250 *lpss = pci_get_drvdata(pdev);
serial8250_unregister_port(lpss->line);
serial8250_unregister_port(lpss->data.line);
if (lpss->board->exit)
lpss->board->exit(lpss);
......@@ -341,6 +356,11 @@ static const struct lpss8250_board byt_board = {
.setup = byt_serial_setup,
};
static const struct lpss8250_board ehl_board = {
.freq = 200000000,
.base_baud = 12500000,
};
static const struct lpss8250_board qrk_board = {
.freq = 44236800,
.base_baud = 2764800,
......@@ -348,17 +368,21 @@ static const struct lpss8250_board qrk_board = {
.exit = qrk_serial_exit,
};
#define LPSS_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
static const struct pci_device_id pci_ids[] = {
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_QRK_UARTx, qrk_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART1, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART2, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART1, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART2, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART1, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART2, byt_board),
{ },
{ PCI_DEVICE_DATA(INTEL, QRK_UARTx, &qrk_board) },
{ PCI_DEVICE_DATA(INTEL, EHL_UART0, &ehl_board) },
{ PCI_DEVICE_DATA(INTEL, EHL_UART1, &ehl_board) },
{ PCI_DEVICE_DATA(INTEL, EHL_UART2, &ehl_board) },
{ PCI_DEVICE_DATA(INTEL, EHL_UART3, &ehl_board) },
{ PCI_DEVICE_DATA(INTEL, EHL_UART4, &ehl_board) },
{ PCI_DEVICE_DATA(INTEL, EHL_UART5, &ehl_board) },
{ PCI_DEVICE_DATA(INTEL, BYT_UART1, &byt_board) },
{ PCI_DEVICE_DATA(INTEL, BYT_UART2, &byt_board) },
{ PCI_DEVICE_DATA(INTEL, BSW_UART1, &byt_board) },
{ PCI_DEVICE_DATA(INTEL, BSW_UART2, &byt_board) },
{ PCI_DEVICE_DATA(INTEL, BDW_UART1, &byt_board) },
{ PCI_DEVICE_DATA(INTEL, BDW_UART2, &byt_board) },
{ }
};
MODULE_DEVICE_TABLE(pci, pci_ids);
......
// SPDX-License-Identifier: GPL-2.0
/*
* 8250_moxa.c - MOXA Smartio/Industio MUE multiport serial driver.
*
* Author: Mathieu OTHACEHE <m.othacehe@gmail.com>
*/
#include <linux/module.h>
#include <linux/pci.h>
#include "8250.h"
#define PCI_DEVICE_ID_MOXA_CP102E 0x1024
#define PCI_DEVICE_ID_MOXA_CP102EL 0x1025
#define PCI_DEVICE_ID_MOXA_CP104EL_A 0x1045
#define PCI_DEVICE_ID_MOXA_CP114EL 0x1144
#define PCI_DEVICE_ID_MOXA_CP116E_A_A 0x1160
#define PCI_DEVICE_ID_MOXA_CP116E_A_B 0x1161
#define PCI_DEVICE_ID_MOXA_CP118EL_A 0x1182
#define PCI_DEVICE_ID_MOXA_CP118E_A_I 0x1183
#define PCI_DEVICE_ID_MOXA_CP132EL 0x1322
#define PCI_DEVICE_ID_MOXA_CP134EL_A 0x1342
#define PCI_DEVICE_ID_MOXA_CP138E_A 0x1381
#define PCI_DEVICE_ID_MOXA_CP168EL_A 0x1683
#define MOXA_BASE_BAUD 921600
#define MOXA_UART_OFFSET 0x200
#define MOXA_BASE_BAR 1
struct moxa8250_board {
unsigned int num_ports;
int line[0];
};
enum {
moxa8250_2p = 0,
moxa8250_4p,
moxa8250_8p
};
static struct moxa8250_board moxa8250_boards[] = {
[moxa8250_2p] = { .num_ports = 2},
[moxa8250_4p] = { .num_ports = 4},
[moxa8250_8p] = { .num_ports = 8},
};
static int moxa8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct uart_8250_port uart;
struct moxa8250_board *brd;
void __iomem *ioaddr;
resource_size_t baseaddr;
unsigned int i, nr_ports;
unsigned int offset;
int ret;
brd = &moxa8250_boards[id->driver_data];
nr_ports = brd->num_ports;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
brd = devm_kzalloc(&pdev->dev, sizeof(struct moxa8250_board) +
sizeof(unsigned int) * nr_ports, GFP_KERNEL);
if (!brd)
return -ENOMEM;
brd->num_ports = nr_ports;
memset(&uart, 0, sizeof(struct uart_8250_port));
uart.port.dev = &pdev->dev;
uart.port.irq = pdev->irq;
uart.port.uartclk = MOXA_BASE_BAUD * 16;
uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
baseaddr = pci_resource_start(pdev, MOXA_BASE_BAR);
ioaddr = pcim_iomap(pdev, MOXA_BASE_BAR, 0);
if (!ioaddr)
return -ENOMEM;
for (i = 0; i < nr_ports; i++) {
/*
* MOXA Smartio MUE boards with 4 ports have
* a different offset for port #3
*/
if (nr_ports == 4 && i == 3)
offset = 7 * MOXA_UART_OFFSET;
else
offset = i * MOXA_UART_OFFSET;
uart.port.iotype = UPIO_MEM;
uart.port.iobase = 0;
uart.port.mapbase = baseaddr + offset;
uart.port.membase = ioaddr + offset;
uart.port.regshift = 0;
dev_dbg(&pdev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
uart.port.iobase, uart.port.irq, uart.port.iotype);
brd->line[i] = serial8250_register_8250_port(&uart);
if (brd->line[i] < 0) {
dev_err(&pdev->dev,
"Couldn't register serial port %lx, irq %d, type %d, error %d\n",
uart.port.iobase, uart.port.irq,
uart.port.iotype, brd->line[i]);
break;
}
}
pci_set_drvdata(pdev, brd);
return 0;
}
static void moxa8250_remove(struct pci_dev *pdev)
{
struct moxa8250_board *brd = pci_get_drvdata(pdev);
unsigned int i;
for (i = 0; i < brd->num_ports; i++)
serial8250_unregister_port(brd->line[i]);
}
#define MOXA_DEVICE(id, data) { PCI_VDEVICE(MOXA, id), (kernel_ulong_t)data }
static const struct pci_device_id pci_ids[] = {
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP102E, moxa8250_2p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP102EL, moxa8250_2p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP104EL_A, moxa8250_4p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP114EL, moxa8250_4p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP116E_A_A, moxa8250_8p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP116E_A_B, moxa8250_8p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP118EL_A, moxa8250_8p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP118E_A_I, moxa8250_8p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP132EL, moxa8250_2p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP134EL_A, moxa8250_4p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP138E_A, moxa8250_8p),
MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP168EL_A, moxa8250_8p),
{0}
};
MODULE_DEVICE_TABLE(pci, pci_ids);
static struct pci_driver moxa8250_pci_driver = {
.name = "8250_moxa",
.id_table = pci_ids,
.probe = moxa8250_probe,
.remove = moxa8250_remove,
};
module_pci_driver(moxa8250_pci_driver);
MODULE_AUTHOR("Mathieu OTHACEHE");
MODULE_DESCRIPTION("MOXA SmartIO MUE driver");
MODULE_LICENSE("GPL v2");
......@@ -1234,7 +1234,16 @@ static int omap8250_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, true);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
/*
* Disable runtime PM until autosuspend delay unless specifically
* enabled by the user via sysfs. This is the historic way to
* prevent an unsafe default policy with lossy characters on wake-up.
* For serdev devices this is not needed, the policy can be managed by
* the serdev driver.
*/
if (!of_get_available_child_count(pdev->dev.of_node))
pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
pm_runtime_irq_safe(&pdev->dev);
pm_runtime_enable(&pdev->dev);
......
This diff is collapsed.
......@@ -498,10 +498,9 @@ static void serial_pnp_remove(struct pnp_dev *dev)
serial8250_unregister_port(line - 1);
}
#ifdef CONFIG_PM
static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
static int __maybe_unused serial_pnp_suspend(struct device *dev)
{
long line = (long)pnp_get_drvdata(dev);
long line = (long)dev_get_drvdata(dev);
if (!line)
return -ENODEV;
......@@ -509,26 +508,25 @@ static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
return 0;
}
static int serial_pnp_resume(struct pnp_dev *dev)
static int __maybe_unused serial_pnp_resume(struct device *dev)
{
long line = (long)pnp_get_drvdata(dev);
long line = (long)dev_get_drvdata(dev);
if (!line)
return -ENODEV;
serial8250_resume_port(line - 1);
return 0;
}
#else
#define serial_pnp_suspend NULL
#define serial_pnp_resume NULL
#endif /* CONFIG_PM */
static SIMPLE_DEV_PM_OPS(serial_pnp_pm_ops, serial_pnp_suspend, serial_pnp_resume);
static struct pnp_driver serial_pnp_driver = {
.name = "serial",
.probe = serial_pnp_probe,
.remove = serial_pnp_remove,
.suspend = serial_pnp_suspend,
.resume = serial_pnp_resume,
.driver = {
.pm = &serial_pnp_pm_ops,
},
.id_table = pnp_dev_table,
};
......
......@@ -40,13 +40,6 @@
#include "8250.h"
/*
* These are definitions for the Exar XR17V35X and XR17(C|D)15X
*/
#define UART_EXAR_INT0 0x80
#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
#define UART_EXAR_DVID 0x8d /* Device identification */
/* Nuvoton NPCM timeout register */
#define UART_NPCM_TOR 7
#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */
......@@ -308,6 +301,14 @@ static const struct serial8250_config uart_config[] = {
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO,
},
[PORT_SUNIX] = {
.name = "Sunix",
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.rxtrig_bytes = {1, 32, 64, 112},
.flags = UART_CAP_FIFO | UART_CAP_SLEEP,
},
};
/* Uart divisor latch read */
......@@ -709,19 +710,8 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put_tx);
static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
unsigned char lcr = 0, efr = 0;
/*
* Exar UARTs have a SLEEP register that enables or disables
* each UART to enter sleep mode separately. On the XR17V35x the
* register is accessible to each UART at the UART_EXAR_SLEEP
* offset but the UART channel may only write to the corresponding
* bit.
*/
serial8250_rpm_get(p);
if ((p->port.type == PORT_XR17V35X) ||
(p->port.type == PORT_XR17D15X)) {
serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
goto out;
}
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
......@@ -738,7 +728,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
serial_out(p, UART_LCR, lcr);
}
}
out:
serial8250_rpm_put(p);
}
......@@ -1011,27 +1001,6 @@ static void autoconfig_16550a(struct uart_8250_port *up)
up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO;
/*
* XR17V35x UARTs have an extra divisor register, DLD
* that gets enabled with when DLAB is set which will
* cause the device to incorrectly match and assign
* port type to PORT_16650. The EFR for this UART is
* found at offset 0x09. Instead check the Deice ID (DVID)
* register for a 2, 4 or 8 port UART.
*/
if (up->port.flags & UPF_EXAR_EFR) {
status1 = serial_in(up, UART_EXAR_DVID);
if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
DEBUG_AUTOCONF("Exar XR17V35x ");
up->port.type = PORT_XR17V35X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
}
}
/*
* Check for presence of the EFR when DLAB is set.
* Only ST16C650V1 UARTs pass this test.
......@@ -1170,18 +1139,6 @@ static void autoconfig_16550a(struct uart_8250_port *up)
}
serial_out(up, UART_IER, iersave);
/*
* Exar uarts have EFR in a weird location
*/
if (up->port.flags & UPF_EXAR_EFR) {
DEBUG_AUTOCONF("Exar XR17D15x ");
up->port.type = PORT_XR17D15X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
}
/*
* We distinguish between 16550A and U6 16550A by counting
* how many bytes are in the FIFO.
......@@ -2184,8 +2141,6 @@ int serial8250_do_startup(struct uart_port *port)
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
serial_port_in(port, UART_EXAR_INT0);
/*
* At this point, there's no way the LSR could still be 0xff;
......@@ -2343,8 +2298,6 @@ int serial8250_do_startup(struct uart_port *port)
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
serial_port_in(port, UART_EXAR_INT0);
up->lsr_saved_flags = 0;
up->msr_saved_flags = 0;
......@@ -2453,23 +2406,6 @@ static void serial8250_shutdown(struct uart_port *port)
serial8250_do_shutdown(port);
}
/*
* XR17V35x UARTs have an extra fractional divisor register (DLD)
* Calculate divisor with extra 4-bit fractional portion
*/
static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up,
unsigned int baud,
unsigned int *frac)
{
struct uart_port *port = &up->port;
unsigned int quot_16;
quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud);
*frac = quot_16 & 0x0f;
return quot_16 >> 4;
}
/* Nuvoton NPCM UARTs have a custom divisor calculation */
static unsigned int npcm_get_divisor(struct uart_8250_port *up,
unsigned int baud)
......@@ -2497,8 +2433,6 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port,
else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
baud == (port->uartclk/8))
quot = 0x8002;
else if (up->port.type == PORT_XR17V35X)
quot = xr17v35x_get_divisor(up, baud, frac);
else if (up->port.type == PORT_NPCM)
quot = npcm_get_divisor(up, baud);
else
......@@ -2585,13 +2519,6 @@ void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
serial_dl_write(up, quot);
/* XR17V35x UARTs have an extra fractional divisor register (DLD) */
if (up->port.type == PORT_XR17V35X) {
/* Preserve bits not related to baudrate; DLD[7:4]. */
quot_frac |= serial_port_in(port, 0x2) & 0xf0;
serial_port_out(port, 0x2, quot_frac);
}
}
EXPORT_SYMBOL_GPL(serial8250_do_set_divisor);
......
......@@ -176,10 +176,8 @@ static int uniphier_uart_probe(struct platform_device *pdev)
return -ENOMEM;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "failed to get IRQ number\n");
if (irq < 0)
return irq;
}
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
......
......@@ -314,6 +314,9 @@ config SERIAL_8250_RSA
If you don't have such card, or if unsure, say N.
config SERIAL_8250_DWLIB
bool
config SERIAL_8250_ACORN
tristate "Acorn expansion card serial port support"
depends on ARCH_ACORN && SERIAL_8250
......@@ -354,6 +357,7 @@ config SERIAL_8250_FSL
config SERIAL_8250_DW
tristate "Support for Synopsys DesignWare 8250 quirks"
depends on SERIAL_8250
select SERIAL_8250_DWLIB
help
Selecting this option will enable handling of the extra features
present in the Synopsys DesignWare APB UART.
......@@ -440,6 +444,7 @@ config SERIAL_8250_LPSS
default SERIAL_8250
depends on SERIAL_8250 && PCI
depends on X86 || COMPILE_TEST
select SERIAL_8250_DWLIB
select DW_DMAC_CORE if SERIAL_8250_DMA
select DW_DMAC_PCI if (SERIAL_8250_DMA && X86_INTEL_LPSS)
select RATIONAL
......@@ -463,16 +468,6 @@ config SERIAL_8250_MID
present on the UART found on Intel Medfield SOC and various other
Intel platforms.
config SERIAL_8250_MOXA
tristate "MOXA SmartIO MUE support"
depends on SERIAL_8250 && PCI
help
Say Y here if you have a Moxa SmartIO MUE multiport serial card.
If unsure, say N.
This driver can also be built as a module. The module will be called
8250_moxa. If you want to do that, say M here.
config SERIAL_8250_PXA
tristate "PXA serial port support"
depends on SERIAL_8250
......
......@@ -8,6 +8,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
8250_base-y := 8250_port.o
8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
8250_base-$(CONFIG_SERIAL_8250_DWLIB) += 8250_dwlib.o
8250_base-$(CONFIG_SERIAL_8250_FINTEK) += 8250_fintek.o
obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
......@@ -34,7 +35,6 @@ obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o
obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
......
......@@ -197,23 +197,6 @@ config SERIAL_KGDB_NMI
If unsure, say N.
config SERIAL_KS8695
bool "Micrel KS8695 (Centaur) serial port support"
depends on ARCH_KS8695
select SERIAL_CORE
help
This selects the Micrel Centaur KS8695 UART. Say Y here.
config SERIAL_KS8695_CONSOLE
bool "Support for console on KS8695 (Centaur) serial port"
depends on SERIAL_KS8695=y
select SERIAL_CORE_CONSOLE
help
Say Y here if you wish to use a KS8695 (Centaur) UART as the
system console (the system console is the device which
receives all kernel messages and warnings and which allows
logins in single user mode).
config SERIAL_MESON
tristate "Meson serial port support"
depends on ARCH_MESON
......@@ -1407,6 +1390,22 @@ config SERIAL_FSL_LPUART_CONSOLE
If you have enabled the lpuart serial port on the Freescale SoCs,
you can make it the console by answering Y to this option.
config SERIAL_FSL_LINFLEXUART
tristate "Freescale linflexuart serial port support"
depends on PRINTK
select SERIAL_CORE
help
Support for the on-chip linflexuart on some Freescale SOCs.
config SERIAL_FSL_LINFLEXUART_CONSOLE
bool "Console on Freescale linflexuart serial port"
depends on SERIAL_FSL_LINFLEXUART=y
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
help
If you have enabled the linflexuart serial port on the Freescale
SoCs, you can make it the console by answering Y to this option.
config SERIAL_CONEXANT_DIGICOLOR
tristate "Conexant Digicolor CX92xxx USART serial port support"
depends on OF
......
......@@ -56,7 +56,6 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
obj-$(CONFIG_SERIAL_QCOM_GENI) += qcom_geni_serial.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o
......@@ -78,6 +77,7 @@ obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
obj-$(CONFIG_SERIAL_ARC) += arc_uart.o
obj-$(CONFIG_SERIAL_RP2) += rp2.o
obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o
obj-$(CONFIG_SERIAL_FSL_LINFLEXUART) += fsl_linflexuart.o
obj-$(CONFIG_SERIAL_CONEXANT_DIGICOLOR) += digicolor-usart.o
obj-$(CONFIG_SERIAL_MEN_Z135) += men_z135_uart.o
obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
......
......@@ -2718,11 +2718,8 @@ static int sbsa_uart_probe(struct platform_device *pdev)
return -ENOMEM;
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "cannot obtain irq\n");
if (ret < 0)
return ret;
}
uap->port.irq = ret;
#ifdef CONFIG_ACPI_SPCR_TABLE
......
......@@ -294,50 +294,6 @@ static void atmel_tasklet_schedule(struct atmel_uart_port *atmel_port,
tasklet_schedule(t);
}
static unsigned int atmel_get_lines_status(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status, ret = 0;
status = atmel_uart_readl(port, ATMEL_US_CSR);
mctrl_gpio_get(atmel_port->gpios, &ret);
if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios,
UART_GPIO_CTS))) {
if (ret & TIOCM_CTS)
status &= ~ATMEL_US_CTS;
else
status |= ATMEL_US_CTS;
}
if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios,
UART_GPIO_DSR))) {
if (ret & TIOCM_DSR)
status &= ~ATMEL_US_DSR;
else
status |= ATMEL_US_DSR;
}
if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios,
UART_GPIO_RI))) {
if (ret & TIOCM_RI)
status &= ~ATMEL_US_RI;
else
status |= ATMEL_US_RI;
}
if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios,
UART_GPIO_DCD))) {
if (ret & TIOCM_CD)
status &= ~ATMEL_US_DCD;
else
status |= ATMEL_US_DCD;
}
return status;
}
/* Enable or disable the rs485 support */
static int atmel_config_rs485(struct uart_port *port,
struct serial_rs485 *rs485conf)
......@@ -1400,7 +1356,6 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
atmel_port->hd_start_rx = false;
atmel_start_rx(port);
return;
}
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
......@@ -1454,7 +1409,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
spin_lock(&atmel_port->lock_suspended);
do {
status = atmel_get_lines_status(port);
status = atmel_uart_readl(port, ATMEL_US_CSR);
mask = atmel_uart_readl(port, ATMEL_US_IMR);
pending = status & mask;
if (!pending)
......@@ -2003,7 +1958,7 @@ static int atmel_startup(struct uart_port *port)
}
/* Save current CSR for comparison in atmel_tasklet_func() */
atmel_port->irq_status_prev = atmel_get_lines_status(port);
atmel_port->irq_status_prev = atmel_uart_readl(port, ATMEL_US_CSR);
/*
* Finally, enable the serial port
......@@ -2888,7 +2843,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
struct atmel_uart_port *atmel_port;
struct device_node *np = pdev->dev.parent->of_node;
void *data;
int ret = -ENODEV;
int ret;
bool rs485_enabled;
BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
......
This diff is collapsed.
This diff is collapsed.
......@@ -207,8 +207,6 @@ static int get_port_memory(struct icom_port *icom_port)
return -ENOMEM;
}
memset(icom_port->statStg, 0, 4096);
/* FODs: Frame Out Descriptor Queue, this is a FIFO queue that
indicates that frames are to be transmitted
*/
......
......@@ -402,12 +402,6 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
mctrl_gpio_set(sport->gpios, sport->port.mctrl);
}
/* called with port.lock taken and irqs caller dependent */
static void imx_uart_rts_auto(struct imx_port *sport, u32 *ucr2)
{
*ucr2 |= UCR2_CTSC;
}
/* called with port.lock taken and irqs off */
static void imx_uart_start_rx(struct uart_port *port)
{
......@@ -445,7 +439,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
return;
ucr1 = imx_uart_readl(sport, UCR1);
imx_uart_writel(sport, ucr1 & ~UCR1_TXMPTYEN, UCR1);
imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1);
/* in rs485 mode disable transmitter if shifter is empty */
if (port->rs485.flags & SER_RS485_ENABLED &&
......@@ -523,7 +517,7 @@ static inline void imx_uart_transmit_buffer(struct imx_port *sport)
* and the TX IRQ is disabled.
**/
ucr1 = imx_uart_readl(sport, UCR1);
ucr1 &= ~UCR1_TXMPTYEN;
ucr1 &= ~UCR1_TRDYEN;
if (sport->dma_is_txing) {
ucr1 |= UCR1_TXDMAEN;
imx_uart_writel(sport, ucr1, UCR1);
......@@ -685,7 +679,7 @@ static void imx_uart_start_tx(struct uart_port *port)
if (!sport->dma_is_enabled) {
ucr1 = imx_uart_readl(sport, UCR1);
imx_uart_writel(sport, ucr1 | UCR1_TXMPTYEN, UCR1);
imx_uart_writel(sport, ucr1 | UCR1_TRDYEN, UCR1);
}
if (sport->dma_is_enabled) {
......@@ -694,7 +688,7 @@ static void imx_uart_start_tx(struct uart_port *port)
* disable TX DMA to let TX interrupt to send X-char */
ucr1 = imx_uart_readl(sport, UCR1);
ucr1 &= ~UCR1_TXDMAEN;
ucr1 |= UCR1_TXMPTYEN;
ucr1 |= UCR1_TRDYEN;
imx_uart_writel(sport, ucr1, UCR1);
return;
}
......@@ -880,7 +874,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
usr1 &= ~USR1_RRDY;
if ((ucr2 & UCR2_ATEN) == 0)
usr1 &= ~USR1_AGTIM;
if ((ucr1 & UCR1_TXMPTYEN) == 0)
if ((ucr1 & UCR1_TRDYEN) == 0)
usr1 &= ~USR1_TRDY;
if ((ucr4 & UCR4_TCEN) == 0)
usr2 &= ~USR2_TXDC;
......@@ -969,10 +963,22 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (!(port->rs485.flags & SER_RS485_ENABLED)) {
u32 ucr2;
/*
* Turn off autoRTS if RTS is lowered and restore autoRTS
* setting if RTS is raised.
*/
ucr2 = imx_uart_readl(sport, UCR2);
ucr2 &= ~(UCR2_CTS | UCR2_CTSC);
if (mctrl & TIOCM_RTS)
ucr2 |= UCR2_CTS | UCR2_CTSC;
if (mctrl & TIOCM_RTS) {
ucr2 |= UCR2_CTS;
/*
* UCR2_IRTS is unset if and only if the port is
* configured for CRTSCTS, so we use inverted UCR2_IRTS
* to get the state to restore to.
*/
if (!(ucr2 & UCR2_IRTS))
ucr2 |= UCR2_CTSC;
}
imx_uart_writel(sport, ucr2, UCR2);
}
......@@ -1468,7 +1474,7 @@ static void imx_uart_shutdown(struct uart_port *port)
spin_lock_irqsave(&sport->port.lock, flags);
ucr1 = imx_uart_readl(sport, UCR1);
ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN | UCR1_RXDMAEN | UCR1_ATDMAEN);
ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN | UCR1_RXDMAEN | UCR1_ATDMAEN);
imx_uart_writel(sport, ucr1, UCR1);
spin_unlock_irqrestore(&sport->port.lock, flags);
......@@ -1535,11 +1541,11 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct imx_port *sport = (struct imx_port *)port;
unsigned long flags;
u32 ucr2, old_ucr1, old_ucr2, ufcr;
u32 ucr2, old_ucr2, ufcr;
unsigned int baud, quot;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
unsigned long div;
unsigned long num, denom;
unsigned long num, denom, old_ubir, old_ubmr;
uint64_t tdiv64;
/*
......@@ -1587,8 +1593,14 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
else
imx_uart_rts_inactive(sport, &ucr2);
} else if (termios->c_cflag & CRTSCTS)
imx_uart_rts_auto(sport, &ucr2);
} else if (termios->c_cflag & CRTSCTS) {
/*
* Only let receiver control RTS output if we were not requested
* to have RTS inactive (which then should take precedence).
*/
if (ucr2 & UCR2_CTS)
ucr2 |= UCR2_CTSC;
}
if (termios->c_cflag & CRTSCTS)
ucr2 &= ~UCR2_IRTS;
......@@ -1631,21 +1643,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
*/
uart_update_timeout(port, termios->c_cflag, baud);
/*
* disable interrupts and drain transmitter
*/
old_ucr1 = imx_uart_readl(sport, UCR1);
imx_uart_writel(sport,
old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
UCR1);
imx_uart_writel(sport, old_ucr2 & ~UCR2_ATEN, UCR2);
while (!(imx_uart_readl(sport, USR2) & USR2_TXDC))
barrier();
/* then, disable everything */
imx_uart_writel(sport, old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN | UCR2_ATEN), UCR2);
/* custom-baudrate handling */
div = sport->port.uartclk / (baud * 16);
if (baud == 38400 && quot != div)
......@@ -1673,15 +1670,26 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div);
imx_uart_writel(sport, ufcr, UFCR);
imx_uart_writel(sport, num, UBIR);
imx_uart_writel(sport, denom, UBMR);
/*
* Two registers below should always be written both and in this
* particular order. One consequence is that we need to check if any of
* them changes and then update both. We do need the check for change
* as even writing the same values seem to "restart"
* transmission/receiving logic in the hardware, that leads to data
* breakage even when rate doesn't in fact change. E.g., user switches
* RTS/CTS handshake and suddenly gets broken bytes.
*/
old_ubir = imx_uart_readl(sport, UBIR);
old_ubmr = imx_uart_readl(sport, UBMR);
if (old_ubir != num || old_ubmr != denom) {
imx_uart_writel(sport, num, UBIR);
imx_uart_writel(sport, denom, UBMR);
}
if (!imx_uart_is_imx1(sport))
imx_uart_writel(sport, sport->port.uartclk / div / 1000,
IMX21_ONEMS);
imx_uart_writel(sport, old_ucr1, UCR1);
imx_uart_writel(sport, ucr2, UCR2);
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
......@@ -1770,7 +1778,7 @@ static int imx_uart_poll_init(struct uart_port *port)
ucr1 |= IMX1_UCR1_UARTCLKEN;
ucr1 |= UCR1_UARTEN;
ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RTSDEN | UCR1_RRDYEN);
ucr1 &= ~(UCR1_TRDYEN | UCR1_RTSDEN | UCR1_RRDYEN);
ucr2 |= UCR2_RXEN;
ucr2 &= ~UCR2_ATEN;
......@@ -1930,7 +1938,7 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
if (imx_uart_is_imx1(sport))
ucr1 |= IMX1_UCR1_UARTCLKEN;
ucr1 |= UCR1_UARTEN;
ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN);
imx_uart_writel(sport, ucr1, UCR1);
......@@ -2286,7 +2294,7 @@ static int imx_uart_probe(struct platform_device *pdev)
/* Disable interrupts before requesting them */
ucr1 = imx_uart_readl(sport, UCR1);
ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
UCR1_TXMPTYEN | UCR1_RTSDEN);
UCR1_TRDYEN | UCR1_RTSDEN);
imx_uart_writel(sport, ucr1, UCR1);
if (!imx_uart_is_imx1(sport) && sport->dte_mode) {
......
This diff is collapsed.
......@@ -658,11 +658,8 @@ static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
p->port.membase = NULL;
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n",
uarts_registered);
if (ret < 0)
return ret;
}
p->port.irq = ret;
p->port.iotype = UPIO_MEM32;
......
......@@ -689,7 +689,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
* tail.
*/
uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT,
one->rx_buf[rxlen], flag);
one->rx_buf[rxlen-1], flag);
} else {
if (unlikely(rxlen >= port->fifosize)) {
......@@ -955,17 +955,43 @@ static void max310x_set_termios(struct uart_port *port,
/* Configure flow control */
max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]);
max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]);
if (termios->c_cflag & CRTSCTS)
/* Disable transmitter before enabling AutoCTS or auto transmitter
* flow control
*/
if (termios->c_cflag & CRTSCTS || termios->c_iflag & IXOFF) {
max310x_port_update(port, MAX310X_MODE1_REG,
MAX310X_MODE1_TXDIS_BIT,
MAX310X_MODE1_TXDIS_BIT);
}
port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
if (termios->c_cflag & CRTSCTS) {
/* Enable AUTORTS and AUTOCTS */
port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
flow |= MAX310X_FLOWCTRL_AUTOCTS_BIT |
MAX310X_FLOWCTRL_AUTORTS_BIT;
}
if (termios->c_iflag & IXON)
flow |= MAX310X_FLOWCTRL_SWFLOW3_BIT |
MAX310X_FLOWCTRL_SWFLOWEN_BIT;
if (termios->c_iflag & IXOFF)
if (termios->c_iflag & IXOFF) {
port->status |= UPSTAT_AUTOXOFF;
flow |= MAX310X_FLOWCTRL_SWFLOW1_BIT |
MAX310X_FLOWCTRL_SWFLOWEN_BIT;
}
max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow);
/* Enable transmitter after disabling AutoCTS and auto transmitter
* flow control
*/
if (!(termios->c_cflag & CRTSCTS) && !(termios->c_iflag & IXOFF)) {
max310x_port_update(port, MAX310X_MODE1_REG,
MAX310X_MODE1_TXDIS_BIT,
0);
}
/* Get baud rate generator configuration */
baud = uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / 0xffff,
......
......@@ -884,10 +884,8 @@ static int mvebu_uart_probe(struct platform_device *pdev)
if (platform_irq_count(pdev) == 1) {
/* Old bindings: no name on the single unamed UART0 IRQ */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "unable to get UART IRQ\n");
if (irq < 0)
return irq;
}
mvuart->irq[UART_IRQ_SUM] = irq;
} else {
......@@ -897,18 +895,14 @@ static int mvebu_uart_probe(struct platform_device *pdev)
* uart-sum of UART0 port.
*/
irq = platform_get_irq_byname(pdev, "uart-rx");
if (irq < 0) {
dev_err(&pdev->dev, "unable to get 'uart-rx' IRQ\n");
if (irq < 0)
return irq;
}
mvuart->irq[UART_RX_IRQ] = irq;
irq = platform_get_irq_byname(pdev, "uart-tx");
if (irq < 0) {
dev_err(&pdev->dev, "unable to get 'uart-tx' IRQ\n");
if (irq < 0)
return irq;
}
mvuart->irq[UART_TX_IRQ] = irq;
}
......
......@@ -969,10 +969,8 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s)
}
#define RTS_AT_AUART() IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(s->gpios, \
UART_GPIO_RTS))
#define CTS_AT_AUART() IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(s->gpios, \
UART_GPIO_CTS))
#define RTS_AT_AUART() !mctrl_gpio_to_gpiod(s->gpios, UART_GPIO_RTS)
#define CTS_AT_AUART() !mctrl_gpio_to_gpiod(s->gpios, UART_GPIO_CTS)
static void mxs_auart_settermios(struct uart_port *u,
struct ktermios *termios,
struct ktermios *old)
......
......@@ -662,10 +662,8 @@ static int owl_uart_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "could not get irq\n");
if (irq < 0)
return irq;
}
if (owl_uart_ports[pdev->id]) {
dev_err(&pdev->dev, "port %d already allocated\n", pdev->id);
......
......@@ -198,10 +198,8 @@ static int qcom_geni_serial_request_port(struct uart_port *uport)
{
struct platform_device *pdev = to_platform_device(uport->dev);
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
uport->membase = devm_ioremap_resource(&pdev->dev, res);
uport->membase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(uport->membase))
return PTR_ERR(uport->membase);
port->se.base = uport->membase;
......@@ -920,12 +918,13 @@ static unsigned long get_clk_cfg(unsigned long clk_freq)
return 0;
}
static unsigned long get_clk_div_rate(unsigned int baud, unsigned int *clk_div)
static unsigned long get_clk_div_rate(unsigned int baud,
unsigned int sampling_rate, unsigned int *clk_div)
{
unsigned long ser_clk;
unsigned long desired_clk;
desired_clk = baud * UART_OVERSAMPLING;
desired_clk = baud * sampling_rate;
ser_clk = get_clk_cfg(desired_clk);
if (!ser_clk) {
pr_err("%s: Can't find matching DFS entry for baud %d\n",
......@@ -951,12 +950,20 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
u32 ser_clk_cfg;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
unsigned long clk_rate;
u32 ver, sampling_rate;
qcom_geni_serial_stop_rx(uport);
/* baud rate */
baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
port->baud = baud;
clk_rate = get_clk_div_rate(baud, &clk_div);
sampling_rate = UART_OVERSAMPLING;
/* Sampling rate is halved for IP versions >= 2.5 */
ver = geni_se_get_qup_hw_version(&port->se);
if (GENI_SE_VERSION_MAJOR(ver) >= 2 && GENI_SE_VERSION_MINOR(ver) >= 5)
sampling_rate /= 2;
clk_rate = get_clk_div_rate(baud, sampling_rate, &clk_div);
if (!clk_rate)
goto out_restart_rx;
......@@ -1291,10 +1298,8 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get IRQ %d\n", irq);
if (irq < 0)
return irq;
}
uport->irq = irq;
uport->private_data = drv;
......
......@@ -735,10 +735,8 @@ static int rda_uart_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "could not get irq\n");
if (irq < 0)
return irq;
}
if (rda_uart_ports[pdev->id]) {
dev_err(&pdev->dev, "port %d already allocated\n", pdev->id);
......
......@@ -961,7 +961,6 @@ static int sccnxp_probe(struct platform_device *pdev)
if (!s->poll) {
s->irq = platform_get_irq(pdev, 0);
if (s->irq < 0) {
dev_err(&pdev->dev, "Missing irq resource data\n");
ret = -ENXIO;
goto err_out;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -27,16 +27,21 @@ struct mctrl_gpios {
static const struct {
const char *name;
unsigned int mctrl;
bool dir_out;
enum gpiod_flags flags;
} mctrl_gpios_desc[UART_GPIO_MAX] = {
{ "cts", TIOCM_CTS, false, },
{ "dsr", TIOCM_DSR, false, },
{ "dcd", TIOCM_CD, false, },
{ "rng", TIOCM_RNG, false, },
{ "rts", TIOCM_RTS, true, },
{ "dtr", TIOCM_DTR, true, },
{ "cts", TIOCM_CTS, GPIOD_IN, },
{ "dsr", TIOCM_DSR, GPIOD_IN, },
{ "dcd", TIOCM_CD, GPIOD_IN, },
{ "rng", TIOCM_RNG, GPIOD_IN, },
{ "rts", TIOCM_RTS, GPIOD_OUT_LOW, },
{ "dtr", TIOCM_DTR, GPIOD_OUT_LOW, },
};
static bool mctrl_gpio_flags_is_dir_out(unsigned int idx)
{
return mctrl_gpios_desc[idx].flags & GPIOD_FLAGS_BIT_DIR_OUT;
}
void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
{
enum mctrl_gpio_idx i;
......@@ -48,7 +53,7 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
return;
for (i = 0; i < UART_GPIO_MAX; i++)
if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) {
if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) {
desc_array[count] = gpios->gpio[i];
__assign_bit(count, values,
mctrl & mctrl_gpios_desc[i].mctrl);
......@@ -73,7 +78,7 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
return *mctrl;
for (i = 0; i < UART_GPIO_MAX; i++) {
if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) {
if (gpios->gpio[i] && !mctrl_gpio_flags_is_dir_out(i)) {
if (gpiod_get_value(gpios->gpio[i]))
*mctrl |= mctrl_gpios_desc[i].mctrl;
else
......@@ -94,7 +99,7 @@ mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl)
return *mctrl;
for (i = 0; i < UART_GPIO_MAX; i++) {
if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) {
if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) {
if (gpiod_get_value(gpios->gpio[i]))
*mctrl |= mctrl_gpios_desc[i].mctrl;
else
......@@ -116,7 +121,6 @@ struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
return ERR_PTR(-ENOMEM);
for (i = 0; i < UART_GPIO_MAX; i++) {
enum gpiod_flags flags;
char *gpio_str;
bool present;
......@@ -131,15 +135,11 @@ struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
if (!present)
continue;
if (mctrl_gpios_desc[i].dir_out)
flags = GPIOD_OUT_LOW;
else
flags = GPIOD_IN;
gpios->gpio[i] =
devm_gpiod_get_index_optional(dev,
mctrl_gpios_desc[i].name,
idx, flags);
idx,
mctrl_gpios_desc[i].flags);
if (IS_ERR(gpios->gpio[i]))
return ERR_CAST(gpios->gpio[i]);
......@@ -200,7 +200,7 @@ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
for (i = 0; i < UART_GPIO_MAX; ++i) {
int ret;
if (!gpios->gpio[i] || mctrl_gpios_desc[i].dir_out)
if (!gpios->gpio[i] || mctrl_gpio_flags_is_dir_out(i))
continue;
ret = gpiod_to_irq(gpios->gpio[i]);
......
......@@ -114,19 +114,19 @@ static inline
struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
enum mctrl_gpio_idx gidx)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline
struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline
struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline
......
This diff is collapsed.
......@@ -896,10 +896,8 @@ static int sifive_serial_probe(struct platform_device *pdev)
int irq, id, r;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "could not acquire interrupt\n");
if (irq < 0)
return -EPROBE_DEFER;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, mem);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment