Skip to content

Commit 628c534

Browse files
seebegregkh
authored andcommitted
serial: sh-sci: Improve support for separate TEI and DRI interrupts
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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 7acece7 commit 628c534

File tree

1 file changed

+40
-51
lines changed

1 file changed

+40
-51
lines changed

drivers/tty/serial/sh-sci.c

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ enum {
6565
SCIx_RXI_IRQ,
6666
SCIx_TXI_IRQ,
6767
SCIx_BRI_IRQ,
68-
SCIx_TEIDRI_IRQ,
68+
SCIx_DRI_IRQ,
69+
SCIx_TEI_IRQ,
6970
SCIx_NR_IRQS,
7071

7172
SCIx_MUX_IRQ = SCIx_NR_IRQS, /* special case */
@@ -77,9 +78,6 @@ enum {
7778
((port)->irqs[SCIx_ERI_IRQ] && \
7879
((port)->irqs[SCIx_RXI_IRQ] < 0))
7980

80-
#define SCIx_TEIDRI_IRQ_EXISTS(port) \
81-
((port)->irqs[SCIx_TEIDRI_IRQ] > 0)
82-
8381
enum SCI_CLKS {
8482
SCI_FCK, /* Functional Clock */
8583
SCI_SCK, /* Optional External Clock */
@@ -1685,14 +1683,23 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
16851683
return IRQ_HANDLED;
16861684
}
16871685

1688-
static irqreturn_t sci_br_interrupt(int irq, void *ptr);
1686+
static irqreturn_t sci_br_interrupt(int irq, void *ptr)
1687+
{
1688+
struct uart_port *port = ptr;
1689+
1690+
/* Handle BREAKs */
1691+
sci_handle_breaks(port);
1692+
sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
1693+
1694+
return IRQ_HANDLED;
1695+
}
16891696

16901697
static irqreturn_t sci_er_interrupt(int irq, void *ptr)
16911698
{
16921699
struct uart_port *port = ptr;
16931700
struct sci_port *s = to_sci_port(port);
16941701

1695-
if (SCIx_TEIDRI_IRQ_EXISTS(s)) {
1702+
if (s->irqs[SCIx_ERI_IRQ] == s->irqs[SCIx_BRI_IRQ]) {
16961703
/* Break and Error interrupts are muxed */
16971704
unsigned short ssr_status = serial_port_in(port, SCxSR);
16981705

@@ -1727,17 +1734,6 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr)
17271734
return IRQ_HANDLED;
17281735
}
17291736

1730-
static irqreturn_t sci_br_interrupt(int irq, void *ptr)
1731-
{
1732-
struct uart_port *port = ptr;
1733-
1734-
/* Handle BREAKs */
1735-
sci_handle_breaks(port);
1736-
sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
1737-
1738-
return IRQ_HANDLED;
1739-
}
1740-
17411737
static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
17421738
{
17431739
unsigned short ssr_status, scr_status, err_enabled, orer_status = 0;
@@ -1811,6 +1807,16 @@ static const struct sci_irq_desc {
18111807
.handler = sci_br_interrupt,
18121808
},
18131809

1810+
[SCIx_DRI_IRQ] = {
1811+
.desc = "rx ready",
1812+
.handler = sci_rx_interrupt,
1813+
},
1814+
1815+
[SCIx_TEI_IRQ] = {
1816+
.desc = "tx end",
1817+
.handler = sci_tx_interrupt,
1818+
},
1819+
18141820
/*
18151821
* Special muxed handler.
18161822
*/
@@ -1823,12 +1829,19 @@ static const struct sci_irq_desc {
18231829
static int sci_request_irq(struct sci_port *port)
18241830
{
18251831
struct uart_port *up = &port->port;
1826-
int i, j, ret = 0;
1832+
int i, j, w, ret = 0;
18271833

18281834
for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
18291835
const struct sci_irq_desc *desc;
18301836
int irq;
18311837

1838+
/* Check if already registered (muxed) */
1839+
for (w = 0; w < i; w++)
1840+
if (port->irqs[w] == port->irqs[i])
1841+
w = i + 1;
1842+
if (w > i)
1843+
continue;
1844+
18321845
if (SCIx_IRQ_IS_MUXED(port)) {
18331846
i = SCIx_MUX_IRQ;
18341847
irq = up->irq;
@@ -1844,32 +1857,8 @@ static int sci_request_irq(struct sci_port *port)
18441857
}
18451858

18461859
desc = sci_irq_desc + i;
1847-
port->irqstr[j] = NULL;
1848-
if (SCIx_TEIDRI_IRQ_EXISTS(port)) {
1849-
/*
1850-
* ERI and BRI are muxed, just register ERI and
1851-
* ignore BRI.
1852-
* TEI and DRI are muxed, but only DRI
1853-
* is enabled, so use RXI handler
1854-
*/
1855-
if (i == SCIx_ERI_IRQ)
1856-
port->irqstr[j] = kasprintf(GFP_KERNEL,
1857-
"%s:err + break",
1858-
dev_name(up->dev));
1859-
if (i == SCIx_BRI_IRQ)
1860-
continue;
1861-
if (i == SCIx_TEIDRI_IRQ) {
1862-
port->irqstr[j] = kasprintf(GFP_KERNEL,
1863-
"%s:tx end + rx ready",
1864-
dev_name(up->dev));
1865-
desc = sci_irq_desc + SCIx_RXI_IRQ;
1866-
}
1867-
}
1868-
1869-
if (!port->irqstr[j])
1870-
port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
1871-
dev_name(up->dev),
1872-
desc->desc);
1860+
port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
1861+
dev_name(up->dev), desc->desc);
18731862
if (!port->irqstr[j]) {
18741863
ret = -ENOMEM;
18751864
goto out_nomem;
@@ -2842,17 +2831,17 @@ static int sci_init_single(struct platform_device *dev,
28422831

28432832
/* The SCI generates several interrupts. They can be muxed together or
28442833
* connected to different interrupt lines. In the muxed case only one
2845-
* interrupt resource is specified. In the non-muxed case three or four
2846-
* interrupt resources are specified, as the BRI interrupt is optional.
2834+
* interrupt resource is specified as there is only one interrupt ID.
2835+
* In the non-muxed case, up to 6 interrupt signals might be generated
2836+
* from the SCI, however those signals might have their own individual
2837+
* interrupt ID numbers, or muxed together with another interrupt.
28472838
*/
28482839
if (sci_port->irqs[0] < 0)
28492840
return -ENXIO;
28502841

2851-
if (sci_port->irqs[1] < 0) {
2852-
sci_port->irqs[1] = sci_port->irqs[0];
2853-
sci_port->irqs[2] = sci_port->irqs[0];
2854-
sci_port->irqs[3] = sci_port->irqs[0];
2855-
}
2842+
if (sci_port->irqs[1] < 0)
2843+
for (i = 1; i < ARRAY_SIZE(sci_port->irqs); i++)
2844+
sci_port->irqs[i] = sci_port->irqs[0];
28562845

28572846
sci_port->params = sci_probe_regmap(p);
28582847
if (unlikely(sci_port->params == NULL))

0 commit comments

Comments
 (0)