Message ID | 20180711144131.73552-2-chris.brandt@renesas.com (mailing list archive) |
---|---|
State | Accepted |
Delegated to: | Geert Uytterhoeven |
Headers | show |
Hi Chris, On Wed, Jul 11, 2018 at 4:42 PM Chris Brandt <chris.brandt@renesas.com> wrote: > 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> Thanks for your patch! > --- a/drivers/tty/serial/sh-sci.c > +++ b/drivers/tty/serial/sh-sci.c > @@ -65,6 +65,7 @@ enum { > SCIx_RXI_IRQ, > SCIx_TXI_IRQ, > SCIx_BRI_IRQ, > + SCIx_TEIDRI_IRQ, Why not separate enum values for TEI and DRI? According to the RZ/A2 docs, there are 6 separate interrupts, but they are multiplexed at the interrupt controller level. > SCIx_NR_IRQS, If you add interrupt value heres, you have to update the comment in sci_init_single(), which talks about "three or four" interrupts. sci_init_single() also fills in all unused sci_port->irqs[], so that code must be updated for the new interrupts. > > 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 */ > @@ -287,6 +291,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, > + }, "Compressed addres space", like SCIx_SH4_SCIF_REGTYPE with regshift -1? ;-) Perhaps we should adjust all offsets in SCIx_SH4_SCIF_REGTYPE and let the current parts use regshift 1, so RZ/A2 can use the same definition with regshift 0? For DT systems, the regshift value could be stored in of_device_id.data by adjusting the SCI_OF_DATA() macro. For legacy SH, probably lots of platform data must be updated. > + > /* > * Common SH-3 SCIF definitions. > */ > @@ -1683,11 +1714,26 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr) > return IRQ_HANDLED; > } > > +static irqreturn_t sci_br_interrupt(int irq, void *ptr); > + For interrupts, please see my response to the DT binding patch. Gr{oetje,eeting}s, Geert
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c181eb37f985..d3435976ba7e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -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 */ @@ -287,6 +291,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. */ @@ -1683,11 +1714,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)) { @@ -1827,8 +1873,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; @@ -3073,6 +3142,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", diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index c0e795d95477..1c89611e0e06 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -36,6 +36,7 @@ enum { SCIx_SH4_SCIF_FIFODATA_REGTYPE, SCIx_SH7705_SCIF_REGTYPE, SCIx_HSCIF_REGTYPE, + SCIx_RZ_SCIFA_REGTYPE, SCIx_NR_REGTYPES, };
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> --- drivers/tty/serial/sh-sci.c | 77 +++++++++++++++++++++++++++++++++++++++++++-- include/linux/serial_sci.h | 1 + 2 files changed, 76 insertions(+), 2 deletions(-)