serial: sh-sci: Add support for R7S9210
authorChris Brandt <chris.brandt@renesas.com>
Wed, 11 Jul 2018 14:41:30 +0000 (09:41 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Jul 2018 09:56:22 +0000 (11:56 +0200)
Add support for a "RZ_SCIFA" which is different than a traditional
SCIFA. It looks like a normal SCIF with FIFO data, but with a
compressed address space. Also, the break out of interrupts
are different then traditinal SCIF: ERI/BRI, RXI, TXI, TEI, DRI.
The R7S9210 (RZ/A2) contains this type of SCIF.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/sh-sci.c
include/linux/serial_sci.h

index 6eb6516..5808edf 100644 (file)
@@ -65,6 +65,7 @@ enum {
        SCIx_RXI_IRQ,
        SCIx_TXI_IRQ,
        SCIx_BRI_IRQ,
+       SCIx_TEIDRI_IRQ,
        SCIx_NR_IRQS,
 
        SCIx_MUX_IRQ = SCIx_NR_IRQS,    /* special case */
@@ -76,6 +77,9 @@ enum {
        ((port)->irqs[SCIx_ERI_IRQ] &&  \
         ((port)->irqs[SCIx_RXI_IRQ] < 0))
 
+#define SCIx_TEIDRI_IRQ_EXISTS(port)           \
+       ((port)->irqs[SCIx_TEIDRI_IRQ] > 0)
+
 enum SCI_CLKS {
        SCI_FCK,                /* Functional Clock */
        SCI_SCK,                /* Optional External Clock */
@@ -289,6 +293,33 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
                .error_clear = SCIF_ERROR_CLEAR,
        },
 
+       /*
+        * The "SCIFA" that is in RZ/T and RZ/A2.
+        * It looks like a normal SCIF with FIFO data, but with a
+        * compressed address space. Also, the break out of interrupts
+        * are different: ERI/BRI, RXI, TXI, TEI, DRI.
+        */
+       [SCIx_RZ_SCIFA_REGTYPE] = {
+               .regs = {
+                       [SCSMR]         = { 0x00, 16 },
+                       [SCBRR]         = { 0x02,  8 },
+                       [SCSCR]         = { 0x04, 16 },
+                       [SCxTDR]        = { 0x06,  8 },
+                       [SCxSR]         = { 0x08, 16 },
+                       [SCxRDR]        = { 0x0A,  8 },
+                       [SCFCR]         = { 0x0C, 16 },
+                       [SCFDR]         = { 0x0E, 16 },
+                       [SCSPTR]        = { 0x10, 16 },
+                       [SCLSR]         = { 0x12, 16 },
+               },
+               .fifosize = 16,
+               .overrun_reg = SCLSR,
+               .overrun_mask = SCLSR_ORER,
+               .sampling_rate_mask = SCI_SR(32),
+               .error_mask = SCIF_DEFAULT_ERROR_MASK,
+               .error_clear = SCIF_ERROR_CLEAR,
+       },
+
        /*
         * Common SH-3 SCIF definitions.
         */
@@ -1682,11 +1713,26 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t sci_br_interrupt(int irq, void *ptr);
+
 static irqreturn_t sci_er_interrupt(int irq, void *ptr)
 {
        struct uart_port *port = ptr;
        struct sci_port *s = to_sci_port(port);
 
+       if (SCIx_TEIDRI_IRQ_EXISTS(s)) {
+               /* Break and Error interrupts are muxed */
+               unsigned short ssr_status = serial_port_in(port, SCxSR);
+
+               /* Break Interrupt */
+               if (ssr_status & SCxSR_BRK(port))
+                       sci_br_interrupt(irq, ptr);
+
+               /* Break only? */
+               if (!(ssr_status & SCxSR_ERRORS(port)))
+                       return IRQ_HANDLED;
+       }
+
        /* Handle errors */
        if (port->type == PORT_SCI) {
                if (sci_handle_errors(port)) {
@@ -1826,8 +1872,31 @@ static int sci_request_irq(struct sci_port *port)
                }
 
                desc = sci_irq_desc + i;
-               port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
-                                           dev_name(up->dev), desc->desc);
+               if (SCIx_TEIDRI_IRQ_EXISTS(port)) {
+                       /*
+                        * ERI and BRI are muxed, just register ERI and
+                        * ignore BRI.
+                        * TEI and DRI are muxed, but only DRI
+                        * is enabled, so use RXI handler
+                        */
+                       if (i == SCIx_ERI_IRQ)
+                               port->irqstr[j] = kasprintf(GFP_KERNEL,
+                                                           "%s:err + break",
+                                                           dev_name(up->dev));
+                       if (i == SCIx_BRI_IRQ)
+                               continue;
+                       if (i == SCIx_TEIDRI_IRQ) {
+                               port->irqstr[j] = kasprintf(GFP_KERNEL,
+                                                           "%s:tx end + rx ready",
+                                                           dev_name(up->dev));
+                               desc = sci_irq_desc + SCIx_RXI_IRQ;
+                       }
+               }
+
+               if (!port->irqstr[j])
+                       port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
+                                                   dev_name(up->dev),
+                                                   desc->desc);
                if (!port->irqstr[j]) {
                        ret = -ENOMEM;
                        goto out_nomem;
@@ -3074,6 +3143,10 @@ static const struct of_device_id of_sci_match[] = {
                .compatible = "renesas,scif-r7s72100",
                .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH2_SCIF_FIFODATA_REGTYPE),
        },
+       {
+               .compatible = "renesas,scif-r7s9210",
+               .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE),
+       },
        /* Family-specific types */
        {
                .compatible = "renesas,rcar-gen1-scif",
index c0e795d..1c89611 100644 (file)
@@ -36,6 +36,7 @@ enum {
        SCIx_SH4_SCIF_FIFODATA_REGTYPE,
        SCIx_SH7705_SCIF_REGTYPE,
        SCIx_HSCIF_REGTYPE,
+       SCIx_RZ_SCIFA_REGTYPE,
 
        SCIx_NR_REGTYPES,
 };