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

2018-07-31 Thread Geert Uytterhoeven
Hi Chris,

On Mon, Jul 30, 2018 at 3:17 PM Chris Brandt  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 
> Reviewed-by: Geert Uytterhoeven 
> ---
> 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

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


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

2018-07-30 Thread Chris Brandt
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 
Reviewed-by: Geert Uytterhoeven 
---
v2:
* Removed - 1 from loop
* Added Reviewed-by
---
 drivers/tty/serial/sh-sci.c | 90 -
 1 file changed, 40 insertions(+), 50 deletions(-)

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;
-   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;
-