Skip to contentSkip to conversation

serial: sc16is7xx

PATCH Superseded [email protected] 1 participant 3 messages Apr 3, 2014 – Apr 15, 2014

Subsystems (2)

v5 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

PATCH v5 1/2 serial: sc16is7xx

From: Jon Ringle <[email protected]>

The SC16IS7xx is a slave I2C-bus/SPI interface to a single-channel high performance UART. The SC16IS7xx's internal register set is backward-compatible with the widely used and widely popular 16C450.

The SC16IS7xx also provides additional advanced features such as auto hardware and software flow control, automatic RS-485 support, and software reset.

---
 drivers/tty/serial/Kconfig       |    9 +
 drivers/tty/serial/Makefile      |    1 +
 drivers/tty/serial/sc16is7xx.c   | 1302 ++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/serial_core.h |    3 +
 4 files changed, 1315 insertions(+)
 create mode 100644 drivers/tty/serial/sc16is7xx.c
drivers/tty/serial/Kconfig +9 -0
index febd45c..762bef5 100644
@@ -1179,6 +1179,15 @@ config SERIAL_SCCNXP_CONSOLE
 	help
 	  Support for console on SCCNXP serial ports.
 
+config SERIAL_SC16IS7XX
+	tristate "SC16IS7xx serial support"
+	select SERIAL_CORE
+	select REGMAP_I2C if I2C
+	help
+	  This selects support for SC16IS7xx serial ports.
+	  Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752,
+	  SC16IS760 and SC16IS762.
+
 config SERIAL_BFIN_SPORT
 	tristate "Blackfin SPORT emulate UART"
 	depends on BLACKFIN
drivers/tty/serial/Makefile +1 -0
index 3068c77..c3bac45 100644
@@ -49,6 +49,7 @@ obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o
 obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
+obj-$(CONFIG_SERIAL_SC16IS7XX) += sc16is7xx.o
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
drivers/tty/serial/sc16is7xx.c new file +1302 -0

1,302 lines not on this page · raw message

include/uapi/linux/serial_core.h +3 -0
index b47dba2..a37c79a 100644
@@ -238,4 +238,7 @@
 /* Tilera TILE-Gx UART */
 #define PORT_TILEGX	106
 
+/* SC16IS74xx */
+#define PORT_SC16IS7XX   107
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
Signature · 1 line
1.8.5.4
#1 lore raw

PATCH v5 2/2 serial: sc16is7xx: Add bindings documentation for the SC16IS7XX UARTs

From: Jon Ringle <[email protected]>

This patch adds the devicetree documentation for the NXP SC16IS7XX UARTs.

---
 .../devicetree/bindings/serial/nxp,sc16is7xx.txt   | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt
Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt new file +33 -0
new file mode 100644
index 0000000..246c795
@@ -0,0 +1,33 @@
+* NXP SC16IS7xx advanced Universal Asynchronous Receiver-Transmitter (UART)
+
+Required properties:
+- compatible: Should be one of the following:
+  - "nxp,sc16is740" for NXP SC16IS740,
+  - "nxp,sc16is741" for NXP SC16IS741,
+  - "nxp,sc16is750" for NXP SC16IS750,
+  - "nxp,sc16is752" for NXP SC16IS752,
+  - "nxp,sc16is760" for NXP SC16IS760,
+  - "nxp,sc16is762" for NXP SC16IS762.
+- reg: I2C address of the SC16IS7xx device.
+- interrupt-parent: The phandle for the interrupt controller that
+  services interrupts for this IC.
+- interrupts: Should contain the UART interrupt
+- clocks: Reference to the IC source clock.
+
+Optional properties:
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells: Should be two. The first cell is the GPIO number and
+  the second cell is used to specify the GPIO polarity:
+    0 = active high,
+    1 = active low.
+
+Example:
+        sc16is750: sc16is750@51 {
+                compatible = "nxp,sc16is750";
+                reg = <0x51>;
+                clocks = <&clk20m>;
+                interrupt-parent = <&gpio3>;
+                interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+                gpio-controller;
+                #gpio-cells = <2>;
+        };
Signature · 1 line
1.8.5.4
author
#2 lore raw
In reply to [email protected]
Quoted 19 lines · On Thu, Apr 3, 2014 at 11:23 AM, <[email protected]> wrote:

From: Jon Ringle <[email protected]>

The SC16IS7xx is a slave I2C-bus/SPI interface to a single-channel high performance UART. The SC16IS7xx's internal register set is backward-compatible with the widely used and widely popular 16C450.

The SC16IS7xx also provides additional advanced features such as auto hardware and software flow control, automatic RS-485 support, and software reset.

---
 drivers/tty/serial/Kconfig       |    9 +
 drivers/tty/serial/Makefile      |    1 +
 drivers/tty/serial/sc16is7xx.c   | 1302 ++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/serial_core.h |    3 +
 4 files changed, 1315 insertions(+)
 create mode 100644 drivers/tty/serial/sc16is7xx.c

[snip]

Quoted 5 lines
drivers/tty/serial/sc16is7xx.c new file +0 -0
new file mode 100644
index 0000000..20d96cc

[snip]

Quoted 11 lines
drivers/tty/serial/sc16is7xx.c new file +11 -0
+static bool sc16is7xx_regmap_writeable(struct device *dev, unsigned int reg)
+{
+       switch (reg >> SC16IS7XX_REG_SHIFT) {
+       case SC16IS7XX_THR_REG:
+       case SC16IS7XX_IER_REG:
+       case SC16IS7XX_FCR_REG:
+       case SC16IS7XX_LCR_REG:
+       case SC16IS7XX_MCR_REG:
+       case SC16IS7XX_SPR_REG:
+       case SC16IS7XX_IODIR_REG:
+       case SC16IS7XX_IOSTATE_REG:

drivers/tty/serial/sc16is7xx.c line 411

Quoted 10 lines
drivers/tty/serial/sc16is7xx.c new file +10 -0
+       case SC16IS7XX_IOINTENA_REG:
+       case SC16IS7XX_IOCONTROL_REG:
+       case SC16IS7XX_EFCR_REG:
+               return true;
+       default:
+               break;
+       }
+
+       return false;
+}

Having the above regmap_writeable callback causes problem with the bulk I2C write (via regmap_raw_write()) that is done in sc16is7xx_handle_tx(). Removing this callback fixes the issue.

[snip]

Quoted 24 lines
drivers/tty/serial/sc16is7xx.c new file +24 -0
+static void sc16is7xx_handle_tx(struct uart_port *port)
+{
+       struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+       struct circ_buf *xmit = &port->state->xmit;
+       unsigned int txlen, to_send, i;
+       u8 buf[port->fifosize];
+
+       if (unlikely(port->x_char)) {
+               sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char);
+               port->icount.tx++;
+               port->x_char = 0;
+               return;
+       }
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+               return;
+
+       /* Get length of data pending in circular buffer */
+       to_send = uart_circ_chars_pending(xmit);
+       if (likely(to_send)) {
+               /* Limit to size of TX FIFO */
+               txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG);
+               to_send = (to_send > txlen) ? txlen : to_send;
+

drivers/tty/serial/sc16is7xx.c line 605

Quoted 10 lines
drivers/tty/serial/sc16is7xx.c new file +10 -0
+               /* Add data to send */
+               port->icount.tx += to_send;
+
+               /* Convert to linear buffer */
+               for (i = 0; i < to_send; ++i) {
+                       buf[i] = xmit->buf[xmit->tail];
+                       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               }
+               regcache_cache_bypass(s->regmap, true);
+               regmap_raw_write(s->regmap, SC16IS7XX_THR_REG, buf, to_send);

This call fails with -EINVAL if to_send is > 20 because it assumes that we are writing to consecutive registers rather than writing to a single register over and over.

Quoted 6 lines
drivers/tty/serial/sc16is7xx.c new file +6 -0
+               regcache_cache_bypass(s->regmap, false);
+       }
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+}

[snip]

drivers/tty/serial/sc16is7xx.c line 1241

Quoted 6 lines
drivers/tty/serial/sc16is7xx.c new file +6 -0
+static struct regmap_config regcfg = {
+       .reg_bits = 7,
+       .pad_bits = 1,
+       .val_bits = 8,
+       .cache_type = REGCACHE_RBTREE,
+       .writeable_reg = sc16is7xx_regmap_writeable,

Removing writeable_reg

New patch forthcoming that removes the regmap writeable_reg callback. But, I also wonder if there is a way to keep it, but teach regcache that regmap_raw_write/read() done necessariy increment the register being written to or read from. Then I probably wouldn't have to do the regcach_cache_bypass business I am doing either.

Jon