|
@@ -74,6 +74,7 @@ struct sci_port {
|
|
/* Function clock */
|
|
/* Function clock */
|
|
struct clk *fclk;
|
|
struct clk *fclk;
|
|
|
|
|
|
|
|
+ int irqs[SCIx_NR_IRQS];
|
|
char *irqstr[SCIx_NR_IRQS];
|
|
char *irqstr[SCIx_NR_IRQS];
|
|
char *gpiostr[SCIx_NR_FNS];
|
|
char *gpiostr[SCIx_NR_FNS];
|
|
|
|
|
|
@@ -1079,19 +1080,19 @@ static int sci_request_irq(struct sci_port *port)
|
|
|
|
|
|
for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
|
|
for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
|
|
struct sci_irq_desc *desc;
|
|
struct sci_irq_desc *desc;
|
|
- unsigned int irq;
|
|
|
|
|
|
+ int irq;
|
|
|
|
|
|
if (SCIx_IRQ_IS_MUXED(port)) {
|
|
if (SCIx_IRQ_IS_MUXED(port)) {
|
|
i = SCIx_MUX_IRQ;
|
|
i = SCIx_MUX_IRQ;
|
|
irq = up->irq;
|
|
irq = up->irq;
|
|
} else {
|
|
} else {
|
|
- irq = port->cfg->irqs[i];
|
|
|
|
|
|
+ irq = port->irqs[i];
|
|
|
|
|
|
/*
|
|
/*
|
|
* Certain port types won't support all of the
|
|
* Certain port types won't support all of the
|
|
* available interrupt sources.
|
|
* available interrupt sources.
|
|
*/
|
|
*/
|
|
- if (unlikely(!irq))
|
|
|
|
|
|
+ if (unlikely(irq < 0))
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1116,7 +1117,7 @@ static int sci_request_irq(struct sci_port *port)
|
|
|
|
|
|
out_noirq:
|
|
out_noirq:
|
|
while (--i >= 0)
|
|
while (--i >= 0)
|
|
- free_irq(port->cfg->irqs[i], port);
|
|
|
|
|
|
+ free_irq(port->irqs[i], port);
|
|
|
|
|
|
out_nomem:
|
|
out_nomem:
|
|
while (--j >= 0)
|
|
while (--j >= 0)
|
|
@@ -1134,16 +1135,16 @@ static void sci_free_irq(struct sci_port *port)
|
|
* IRQ first.
|
|
* IRQ first.
|
|
*/
|
|
*/
|
|
for (i = 0; i < SCIx_NR_IRQS; i++) {
|
|
for (i = 0; i < SCIx_NR_IRQS; i++) {
|
|
- unsigned int irq = port->cfg->irqs[i];
|
|
|
|
|
|
+ int irq = port->irqs[i];
|
|
|
|
|
|
/*
|
|
/*
|
|
* Certain port types won't support all of the available
|
|
* Certain port types won't support all of the available
|
|
* interrupt sources.
|
|
* interrupt sources.
|
|
*/
|
|
*/
|
|
- if (unlikely(!irq))
|
|
|
|
|
|
+ if (unlikely(irq < 0))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- free_irq(port->cfg->irqs[i], port);
|
|
|
|
|
|
+ free_irq(port->irqs[i], port);
|
|
kfree(port->irqstr[i]);
|
|
kfree(port->irqstr[i]);
|
|
|
|
|
|
if (SCIx_IRQ_IS_MUXED(port)) {
|
|
if (SCIx_IRQ_IS_MUXED(port)) {
|
|
@@ -1659,7 +1660,7 @@ static void rx_timer_fn(unsigned long arg)
|
|
|
|
|
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
|
scr &= ~0x4000;
|
|
scr &= ~0x4000;
|
|
- enable_irq(s->cfg->irqs[1]);
|
|
|
|
|
|
+ enable_irq(s->irqs[SCIx_RXI_IRQ]);
|
|
}
|
|
}
|
|
serial_port_out(port, SCSCR, scr | SCSCR_RIE);
|
|
serial_port_out(port, SCSCR, scr | SCSCR_RIE);
|
|
dev_dbg(port->dev, "DMA Rx timed out\n");
|
|
dev_dbg(port->dev, "DMA Rx timed out\n");
|
|
@@ -2150,11 +2151,12 @@ static struct uart_ops sci_uart_ops = {
|
|
};
|
|
};
|
|
|
|
|
|
static int sci_init_single(struct platform_device *dev,
|
|
static int sci_init_single(struct platform_device *dev,
|
|
- struct sci_port *sci_port,
|
|
|
|
- unsigned int index,
|
|
|
|
- struct plat_sci_port *p)
|
|
|
|
|
|
+ struct sci_port *sci_port, unsigned int index,
|
|
|
|
+ struct plat_sci_port *p, bool early)
|
|
{
|
|
{
|
|
struct uart_port *port = &sci_port->port;
|
|
struct uart_port *port = &sci_port->port;
|
|
|
|
+ const struct resource *res;
|
|
|
|
+ unsigned int i;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
sci_port->cfg = p;
|
|
sci_port->cfg = p;
|
|
@@ -2163,6 +2165,38 @@ static int sci_init_single(struct platform_device *dev,
|
|
port->iotype = UPIO_MEM;
|
|
port->iotype = UPIO_MEM;
|
|
port->line = index;
|
|
port->line = index;
|
|
|
|
|
|
|
|
+ if (dev->num_resources) {
|
|
|
|
+ /* Device has resources, use them. */
|
|
|
|
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
|
|
|
+ if (res == NULL)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ port->mapbase = res->start;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(sci_port->irqs); ++i)
|
|
|
|
+ sci_port->irqs[i] = platform_get_irq(dev, i);
|
|
|
|
+
|
|
|
|
+ /* 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.
|
|
|
|
+ */
|
|
|
|
+ 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];
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ /* No resources, use old-style platform data. */
|
|
|
|
+ port->mapbase = p->mapbase;
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(sci_port->irqs); ++i)
|
|
|
|
+ sci_port->irqs[i] = p->irqs[i] ? p->irqs[i] : -ENXIO;
|
|
|
|
+ }
|
|
|
|
+
|
|
switch (p->type) {
|
|
switch (p->type) {
|
|
case PORT_SCIFB:
|
|
case PORT_SCIFB:
|
|
port->fifosize = 256;
|
|
port->fifosize = 256;
|
|
@@ -2187,7 +2221,7 @@ static int sci_init_single(struct platform_device *dev,
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
- if (dev) {
|
|
|
|
|
|
+ if (!early) {
|
|
sci_port->iclk = clk_get(&dev->dev, "sci_ick");
|
|
sci_port->iclk = clk_get(&dev->dev, "sci_ick");
|
|
if (IS_ERR(sci_port->iclk)) {
|
|
if (IS_ERR(sci_port->iclk)) {
|
|
sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
|
|
sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
|
|
@@ -2242,7 +2276,6 @@ static int sci_init_single(struct platform_device *dev,
|
|
p->error_mask |= (1 << p->overrun_bit);
|
|
p->error_mask |= (1 << p->overrun_bit);
|
|
}
|
|
}
|
|
|
|
|
|
- port->mapbase = p->mapbase;
|
|
|
|
port->type = p->type;
|
|
port->type = p->type;
|
|
port->flags = UPF_FIXED_PORT | p->flags;
|
|
port->flags = UPF_FIXED_PORT | p->flags;
|
|
port->regshift = p->regshift;
|
|
port->regshift = p->regshift;
|
|
@@ -2254,7 +2287,7 @@ static int sci_init_single(struct platform_device *dev,
|
|
*
|
|
*
|
|
* For the muxed case there's nothing more to do.
|
|
* For the muxed case there's nothing more to do.
|
|
*/
|
|
*/
|
|
- port->irq = p->irqs[SCIx_RXI_IRQ];
|
|
|
|
|
|
+ port->irq = sci_port->irqs[SCIx_RXI_IRQ];
|
|
port->irqflags = 0;
|
|
port->irqflags = 0;
|
|
|
|
|
|
port->serial_in = sci_serial_in;
|
|
port->serial_in = sci_serial_in;
|
|
@@ -2386,7 +2419,7 @@ static int sci_probe_earlyprintk(struct platform_device *pdev)
|
|
|
|
|
|
early_serial_console.index = pdev->id;
|
|
early_serial_console.index = pdev->id;
|
|
|
|
|
|
- sci_init_single(NULL, &sci_ports[pdev->id], pdev->id, cfg);
|
|
|
|
|
|
+ sci_init_single(pdev, &sci_ports[pdev->id], pdev->id, cfg, true);
|
|
|
|
|
|
serial_console_setup(&early_serial_console, early_serial_buf);
|
|
serial_console_setup(&early_serial_console, early_serial_buf);
|
|
|
|
|
|
@@ -2453,7 +2486,7 @@ static int sci_probe_single(struct platform_device *dev,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- ret = sci_init_single(dev, sciport, index, p);
|
|
|
|
|
|
+ ret = sci_init_single(dev, sciport, index, p, false);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|