diff options
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
| -rw-r--r-- | drivers/tty/serial/sh-sci.c | 80 |
1 files changed, 45 insertions, 35 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index fbfe5575bd3c..bd7486315338 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1182,6 +1182,11 @@ static int sci_handle_errors(struct uart_port *port) return copied; } +static bool sci_is_rsci_type(u8 type) +{ + return (type == RSCI_PORT_SCIF16 || type == RSCI_PORT_SCIF32); +} + static int sci_handle_fifo_overrun(struct uart_port *port) { struct tty_port *tport = &port->state->port; @@ -1190,7 +1195,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port) int copied = 0; u32 status; - if (s->type != SCI_PORT_RSCI) { + if (!sci_is_rsci_type(s->type)) { reg = sci_getreg(port, s->params->overrun_reg); if (!reg->size) return 0; @@ -1198,7 +1203,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port) status = s->ops->read_reg(port, s->params->overrun_reg); if (status & s->params->overrun_mask) { - if (s->type == SCI_PORT_RSCI) { + if (sci_is_rsci_type(s->type)) { /* * All of the CFCLR_*C clearing bits match the corresponding * CSR_*status bits. So, reuse the overrun mask for clearing. @@ -2015,7 +2020,7 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr) unsigned long flags; u32 ctrl; - if (s->type != PORT_SCI && s->type != SCI_PORT_RSCI) + if (s->type != PORT_SCI && !sci_is_rsci_type(s->type)) return sci_tx_interrupt(irq, ptr); uart_port_lock_irqsave(port, &flags); @@ -2568,9 +2573,8 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps, } /* calculate sample rate, BRR, and clock select */ -static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, - unsigned int *brr, unsigned int *srr, - unsigned int *cks) +int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, + unsigned int *srr, unsigned int *cks) { unsigned long freq = s->clk_rates[SCI_FCK]; unsigned int sr, br, prediv, scrate, c; @@ -2634,6 +2638,7 @@ found: min_err, *brr, *srr + 1, *cks); return min_err; } +EXPORT_SYMBOL_NS_GPL(sci_scbrr_calc, "SH_SCI"); static void sci_reset(struct uart_port *port) { @@ -3167,15 +3172,21 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) [SCI_SCK] = "sck", [SCI_BRG_INT] = "brg_int", [SCI_SCIF_CLK] = "scif_clk", + [SCI_FCK_DIV4] = "tclk_div4", + [SCI_FCK_DIV16] = "tclk_div16", + [SCI_FCK_DIV64] = "tclk_div64", }; struct clk *clk; unsigned int i; if (sci_port->type == PORT_HSCIF) { clk_names[SCI_SCK] = "hsck"; - } else if (sci_port->type == SCI_PORT_RSCI) { + } else if (sci_port->type == RSCI_PORT_SCIF16) { clk_names[SCI_FCK] = "operation"; clk_names[SCI_BRG_INT] = "bus"; + } else if (sci_port->type == RSCI_PORT_SCIF32) { + clk_names[SCI_FCK] = "tclk"; + clk_names[SCI_BRG_INT] = "pclk"; } for (i = 0; i < SCI_NUM_CLKS; i++) { @@ -3185,12 +3196,13 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) if (IS_ERR(clk)) return PTR_ERR(clk); - if (!clk && sci_port->type == SCI_PORT_RSCI && - (i == SCI_FCK || i == SCI_BRG_INT)) { - return dev_err_probe(dev, -ENODEV, - "failed to get %s\n", - name); - } + if (!clk && sci_port->type == RSCI_PORT_SCIF16 && + (i == SCI_FCK || i == SCI_BRG_INT)) + return dev_err_probe(dev, -ENODEV, "failed to get %s\n", name); + + if (!clk && sci_port->type == RSCI_PORT_SCIF32 && + (i != SCI_SCK && i != SCI_SCIF_CLK)) + return dev_err_probe(dev, -ENODEV, "failed to get %s\n", name); if (!clk && i == SCI_FCK) { /* @@ -3200,16 +3212,13 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) */ clk = devm_clk_get(dev, "peripheral_clk"); if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "failed to get %s\n", - name); + return dev_err_probe(dev, PTR_ERR(clk), "failed to get %s\n", name); } if (!clk) dev_dbg(dev, "failed to get %s\n", name); else - dev_dbg(dev, "clk %s is %pC rate %lu\n", name, - clk, clk_get_rate(clk)); + dev_dbg(dev, "clk %s is %pC rate %lu\n", name, clk, clk_get_rate(clk)); sci_port->clks[i] = clk; } return 0; @@ -3295,7 +3304,7 @@ static int sci_init_single(struct platform_device *dev, * The fourth interrupt on SCI and RSCI port is transmit end interrupt, so * shuffle the interrupts. */ - if (p->type == PORT_SCI || p->type == SCI_PORT_RSCI) + if (p->type == PORT_SCI || sci_is_rsci_type(p->type)) swap(sci_port->irqs[SCIx_BRI_IRQ], sci_port->irqs[SCIx_TEI_IRQ]); /* The SCI generates several interrupts. They can be muxed together or @@ -3320,6 +3329,7 @@ static int sci_init_single(struct platform_device *dev, sci_port->rx_trigger = 64; break; case PORT_SCIFA: + case RSCI_PORT_SCIF32: sci_port->rx_trigger = 32; break; case PORT_SCIF: @@ -3329,8 +3339,8 @@ static int sci_init_single(struct platform_device *dev, else sci_port->rx_trigger = 8; break; - case SCI_PORT_RSCI: - sci_port->rx_trigger = 15; + case RSCI_PORT_SCIF16: + sci_port->rx_trigger = 16; break; default: sci_port->rx_trigger = 1; @@ -3422,7 +3432,10 @@ static void serial_console_write(struct console *co, const char *s, cpu_relax(); /* restore the SCSCR */ - sci_port->ops->write_reg(port, regs->control, ctrl); + if (sci_port->ops->finish_console_write) + sci_port->ops->finish_console_write(port, ctrl); + else + sci_port->ops->write_reg(port, regs->control, ctrl); if (locked) uart_port_unlock_irqrestore(port, flags); @@ -3549,16 +3562,14 @@ static struct uart_driver sci_uart_driver = { static void sci_remove(struct platform_device *dev) { struct sci_port *s = platform_get_drvdata(dev); - unsigned int type = s->type; /* uart_remove_... clears it */ sci_ports_in_use &= ~BIT(s->port.line); uart_remove_one_port(&sci_uart_driver, &s->port); - if (s->port.fifosize > 1) + if (s->port.fifosize > 1) { device_remove_file(&dev->dev, &dev_attr_rx_fifo_trigger); - if (type == PORT_SCIFA || type == PORT_SCIFB || type == PORT_HSCIF || - type == SCI_PORT_RSCI) device_remove_file(&dev->dev, &dev_attr_rx_fifo_timeout); + } } static const struct sci_of_data of_sci_scif_sh2 = { @@ -3653,8 +3664,12 @@ static const struct of_device_id of_sci_match[] __maybe_unused = { }, #ifdef CONFIG_SERIAL_RSCI { + .compatible = "renesas,r9a09g047-rsci", + .data = &of_rsci_rzg3e_data, + }, + { .compatible = "renesas,r9a09g077-rsci", - .data = &of_sci_rsci_data, + .data = &of_rsci_rzt2h_data, }, #endif /* CONFIG_SERIAL_RSCI */ /* Family-specific types */ @@ -3716,7 +3731,7 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, data = of_device_get_match_data(&pdev->dev); - rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + rstc = devm_reset_control_array_get_optional_exclusive(&pdev->dev); if (IS_ERR(rstc)) return ERR_PTR(dev_err_probe(&pdev->dev, PTR_ERR(rstc), "failed to get reset ctrl\n")); @@ -3917,15 +3932,10 @@ static int sci_probe(struct platform_device *dev) ret = device_create_file(&dev->dev, &dev_attr_rx_fifo_trigger); if (ret) return ret; - } - if (sp->type == PORT_SCIFA || sp->type == PORT_SCIFB || - sp->type == PORT_HSCIF || sp->type == SCI_PORT_RSCI) { + ret = device_create_file(&dev->dev, &dev_attr_rx_fifo_timeout); if (ret) { - if (sp->port.fifosize > 1) { - device_remove_file(&dev->dev, - &dev_attr_rx_fifo_trigger); - } + device_remove_file(&dev->dev, &dev_attr_rx_fifo_trigger); return ret; } } |
