summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/sh-sci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-rw-r--r--drivers/tty/serial/sh-sci.c80
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;
}
}