serial: sc16is7xx
Subsystems (2)
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
@@ -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
@@ -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
@@ -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
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
@@ -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
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.
Signed-off-by Jon Ringle <[email protected]>--- 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
[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