diff mbox series

[v2,4/4] serial: sh-sci: Improve support for separate TEI and DRI interrupts

Message ID 20180730131716.75484-5-chris.brandt@renesas.com (mailing list archive)
State Superseded
Delegated to: Geert Uytterhoeven
Headers show
Series serial: sh-sci: Clean up previous RZ/A2 support | expand

Commit Message

Chris Brandt July 30, 2018, 1:17 p.m. UTC
Some SCIF versions mux error and break interrupts together and then provide
a separate interrupt ID for just TEI/DRI.

Allow all 6 types of interrupts to be specified via platform data (or DT)
and for any signals that are muxed together (have the same interrupt
number) simply register one handler.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
v2:
* Removed - 1 from loop
* Added Reviewed-by
---
 drivers/tty/serial/sh-sci.c | 90 ++++++++++++++++++++-------------------------
 1 file changed, 40 insertions(+), 50 deletions(-)

Comments

Geert Uytterhoeven July 31, 2018, 10:26 a.m. UTC | #1
Hi Chris,

On Mon, Jul 30, 2018 at 3:17 PM Chris Brandt <chris.brandt@renesas.com> wrote:
> Some SCIF versions mux error and break interrupts together and then provide
> a separate interrupt ID for just TEI/DRI.
>
> Allow all 6 types of interrupts to be specified via platform data (or DT)
> and for any signals that are muxed together (have the same interrupt
> number) simply register one handler.
>
> Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> v2:
> * Removed - 1 from loop
> * Added Reviewed-by

> --- a/drivers/tty/serial/sh-sci.c
> +++ b/drivers/tty/serial/sh-sci.c

> @@ -1845,31 +1858,8 @@ static int sci_request_irq(struct sci_port *port)
>
>                 desc = sci_irq_desc + i;
>                 port->irqstr[j] = NULL;

The above line can be removed again, too.

> -               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);
> +               port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
> +                                           dev_name(up->dev), desc->desc);
>                 if (!port->irqstr[j]) {
>                         ret = -ENOMEM;
>                         goto out_nomem;

Gr{oetje,eeting}s,

                        Geert
Chris Brandt July 31, 2018, 10:35 a.m. UTC | #2
Hi Geert,

As always, thank you for your review.

On Tuesday, July 31, 2018, Geert Uytterhoeven wrote:
> > @@ -1845,31 +1858,8 @@ static int sci_request_irq(struct sci_port *port)
> >
> >                 desc = sci_irq_desc + i;
> >                 port->irqstr[j] = NULL;
> 
> The above line can be removed again, too.


Good point. Thank you.

I will update it now.

Chris
diff mbox series

Patch

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 54ea58bbe3c9..377b2c1b52b9 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -65,7 +65,8 @@  enum {
 	SCIx_RXI_IRQ,
 	SCIx_TXI_IRQ,
 	SCIx_BRI_IRQ,
-	SCIx_TEIDRI_IRQ,
+	SCIx_DRI_IRQ,
+	SCIx_TEI_IRQ,
 	SCIx_NR_IRQS,
 
 	SCIx_MUX_IRQ = SCIx_NR_IRQS,	/* special case */
@@ -77,9 +78,6 @@  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 */
@@ -1685,14 +1683,23 @@  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_br_interrupt(int irq, void *ptr)
+{
+	struct uart_port *port = ptr;
+
+	/* Handle BREAKs */
+	sci_handle_breaks(port);
+	sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
+
+	return IRQ_HANDLED;
+}
 
 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)) {
+	if (s->irqs[SCIx_ERI_IRQ] == s->irqs[SCIx_BRI_IRQ]) {
 		/* Break and Error interrupts are muxed */
 		unsigned short ssr_status = serial_port_in(port, SCxSR);
 
@@ -1727,17 +1734,6 @@  static irqreturn_t sci_er_interrupt(int irq, void *ptr)
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sci_br_interrupt(int irq, void *ptr)
-{
-	struct uart_port *port = ptr;
-
-	/* Handle BREAKs */
-	sci_handle_breaks(port);
-	sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
-
-	return IRQ_HANDLED;
-}
-
 static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 {
 	unsigned short ssr_status, scr_status, err_enabled, orer_status = 0;
@@ -1811,6 +1807,16 @@  static const struct sci_irq_desc {
 		.handler = sci_br_interrupt,
 	},
 
+	[SCIx_DRI_IRQ] = {
+		.desc = "rx ready",
+		.handler = sci_rx_interrupt,
+	},
+
+	[SCIx_TEI_IRQ] = {
+		.desc = "tx end",
+		.handler = sci_tx_interrupt,
+	},
+
 	/*
 	 * Special muxed handler.
 	 */
@@ -1823,12 +1829,19 @@  static const struct sci_irq_desc {
 static int sci_request_irq(struct sci_port *port)
 {
 	struct uart_port *up = &port->port;
-	int i, j, ret = 0;
+	int i, j, w, ret = 0;
 
 	for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
 		const struct sci_irq_desc *desc;
 		int irq;
 
+		/* Check if already registered (muxed) */
+		for (w = 0; w < i; w++)
+			if (port->irqs[w] == port->irqs[i])
+				w = i + 1;
+		if (w > i)
+			continue;
+
 		if (SCIx_IRQ_IS_MUXED(port)) {
 			i = SCIx_MUX_IRQ;
 			irq = up->irq;
@@ -1845,31 +1858,8 @@  static int sci_request_irq(struct sci_port *port)
 
 		desc = sci_irq_desc + i;
 		port->irqstr[j] = NULL;
-		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);
+		port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
+					    dev_name(up->dev), desc->desc);
 		if (!port->irqstr[j]) {
 			ret = -ENOMEM;
 			goto out_nomem;
@@ -2842,17 +2832,17 @@  static int sci_init_single(struct platform_device *dev,
 
 	/* The SCI generates several interrupts. They can be muxed together or
 	 * connected to different interrupt lines. In the muxed case only one
-	 * interrupt resource is specified. In the non-muxed case three or four
-	 * interrupt resources are specified, as the BRI interrupt is optional.
+	 * interrupt resource is specified as there is only one interrupt ID.
+	 * In the non-muxed case, up to 6 interrupt signals might be generated
+	 * from the SCI, however those signals might have their own individual
+	 * interrupt ID numbers, or muxed together with another interrupt.
 	 */
 	if (sci_port->irqs[0] < 0)
 		return -ENXIO;
 
-	if (sci_port->irqs[1] < 0) {
-		sci_port->irqs[1] = sci_port->irqs[0];
-		sci_port->irqs[2] = sci_port->irqs[0];
-		sci_port->irqs[3] = sci_port->irqs[0];
-	}
+	if (sci_port->irqs[1] < 0)
+		for (i = 1; i < ARRAY_SIZE(sci_port->irqs); i++)
+			sci_port->irqs[i] = sci_port->irqs[0];
 
 	sci_port->params = sci_probe_regmap(p);
 	if (unlikely(sci_port->params == NULL))