From 623ac1d4a52f279d9379bae61ae1eb37c5767f96 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Sat, 3 Dec 2016 18:40:25 +0800 Subject: tty: serial: sh-sci: set error code when kasprintf fails When the call to kasprintf() returns a NULL pointer, function sci_request_irq() frees the preallocated memory and returns 0 is returned. Because 0 means no error, the caller of sci_request_irq() will keep going, and the freed memory may be used or freed again. To avoid the above issue, this patch assigns "-ENOMEM" to the return variable ret. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188691 Signed-off-by: Pan Bian Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 91e7dddbf72c..b33199af8877 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1743,8 +1743,10 @@ static int sci_request_irq(struct sci_port *port) desc = sci_irq_desc + i; port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s", dev_name(up->dev), desc->desc); - if (!port->irqstr[j]) + if (!port->irqstr[j]) { + ret = -ENOMEM; goto out_nomem; + } ret = request_irq(irq, desc->handler, up->irqflags, port->irqstr[j], port); -- cgit v1.2.3 From 9f8325b3c19cf2e5df6b9624480748421104d00c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:23 +0200 Subject: serial: sh-sci: Set the SCSCR TE and RE bits in the driver The Transmit Enable and Receive Enable bits are set in the scscr field of all instances of the sh-sci platform data. Set them in the driver directly to prepare for their removal from platform data. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index b33199af8877..28e96213bad8 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2343,7 +2343,8 @@ done: serial_port_out(port, SCFCR, ctrl); } - scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0); + scr_val |= SCSCR_RE | SCSCR_TE | + (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)); dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val); serial_port_out(port, SCSCR, scr_val); if ((srr + 1 == 5) && @@ -2793,7 +2794,8 @@ static void serial_console_write(struct console *co, const char *s, /* first save SCSCR then disable interrupts, keep clock source */ ctrl = serial_port_in(port, SCSCR); - ctrl_temp = (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | + ctrl_temp = SCSCR_RE | SCSCR_TE | + (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | (ctrl & (SCSCR_CKE1 | SCSCR_CKE0)); serial_port_out(port, SCSCR, ctrl_temp); @@ -2996,7 +2998,6 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; p->type = SCI_OF_TYPE(match->data); p->regtype = SCI_OF_REGTYPE(match->data); - p->scscr = SCSCR_RE | SCSCR_TE; if (of_find_property(np, "uart-has-rtscts", NULL)) p->capabilities |= SCIx_HAVE_RTSCTS; @@ -3164,9 +3165,9 @@ static int __init early_console_setup(struct earlycon_device *device, sci_ports[0].cfg = &port_cfg; sci_ports[0].cfg->type = type; sci_probe_regmap(sci_ports[0].cfg); - port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR) | - SCSCR_RE | SCSCR_TE; - sci_serial_out(&sci_ports[0].port, SCSCR, port_cfg.scscr); + port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR); + sci_serial_out(&sci_ports[0].port, SCSCR, + SCSCR_RE | SCSCR_TE | port_cfg.scscr); device->con->write = serial_console_write; return 0; -- cgit v1.2.3 From 3d73f32bfa312155a0990efd95803a3e7061140c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:24 +0200 Subject: serial: sh-sci: Don't rely on platform data flags when not needed The UPF_BOOT_AUTOCONF platform data flag is set by all platforms, hardcode it. The UPF_IOREMAP flag is set by a single SH platform and thus needs to be kept. However, for ARM platforms, we can base the decision on whether an OF node is present and bypass the platform data flags completely. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 28e96213bad8..d0102bcca4ef 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2455,7 +2455,7 @@ static int sci_remap_port(struct uart_port *port) if (port->membase) return 0; - if (port->flags & UPF_IOREMAP) { + if (port->dev->of_node || (port->flags & UPF_IOREMAP)) { port->membase = ioremap_nocache(port->mapbase, sport->reg_size); if (unlikely(!port->membase)) { dev_err(port->dev, "can't remap port#%d\n", port->line); @@ -2477,7 +2477,7 @@ static void sci_release_port(struct uart_port *port) { struct sci_port *sport = to_sci_port(port); - if (port->flags & UPF_IOREMAP) { + if (port->dev->of_node || (port->flags & UPF_IOREMAP)) { iounmap(port->membase); port->membase = NULL; } @@ -2733,7 +2733,7 @@ static int sci_init_single(struct platform_device *dev, } port->type = p->type; - port->flags = UPF_FIXED_PORT | p->flags; + port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags; port->regshift = p->regshift; /* @@ -2995,7 +2995,6 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) *dev_id = id; - p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; p->type = SCI_OF_TYPE(match->data); p->regtype = SCI_OF_REGTYPE(match->data); -- cgit v1.2.3 From a752ba18af8285e3eeda572f40dddaebff0c3621 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:32 +0200 Subject: serial: sh-sci: Fix register offsets for the IRDA serial port Even though most of its registers are 8-bit wide, the IRDA has two 16-bit registers that make it a 16-bit peripheral and not a 8-bit peripheral with addresses shifted by one. Fix the registers offset in the driver and the platform data regshift value. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d0102bcca4ef..baa041c1f28f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -193,18 +193,17 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { }, /* - * Common definitions for legacy IrDA ports, dependent on - * regshift value. + * Common definitions for legacy IrDA ports. */ [SCIx_IRDA_REGTYPE] = { [SCSMR] = { 0x00, 8 }, - [SCBRR] = { 0x01, 8 }, - [SCSCR] = { 0x02, 8 }, - [SCxTDR] = { 0x03, 8 }, - [SCxSR] = { 0x04, 8 }, - [SCxRDR] = { 0x05, 8 }, - [SCFCR] = { 0x06, 8 }, - [SCFDR] = { 0x07, 16 }, + [SCBRR] = { 0x02, 8 }, + [SCSCR] = { 0x04, 8 }, + [SCxTDR] = { 0x06, 8 }, + [SCxSR] = { 0x08, 16 }, + [SCxRDR] = { 0x0a, 8 }, + [SCFCR] = { 0x0c, 8 }, + [SCFDR] = { 0x0e, 16 }, [SCTFDR] = sci_reg_invalid, [SCRFDR] = sci_reg_invalid, [SCSPTR] = sci_reg_invalid, -- cgit v1.2.3 From 40b34ddb0385a2a698dec150b50e6b400fc373a0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:33 +0200 Subject: serial: sh-sci: Remove initialization of zero fields in sci_port_params The compiler zeros uninitialized fields, don't zero them manually. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 94 --------------------------------------------- 1 file changed, 94 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index baa041c1f28f..4a12c55eae61 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -160,14 +160,7 @@ struct plat_sci_reg { u8 offset, size; }; -/* Helper for invalidating specific entries of an inherited map. */ -#define sci_reg_invalid { .offset = 0, .size = 0 } - static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { - [SCIx_PROBE_REGTYPE] = { - [0 ... SCIx_NR_REGS - 1] = sci_reg_invalid, - }, - /* * Common SCI definitions, dependent on the port's regshift * value. @@ -179,17 +172,6 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxTDR] = { 0x03, 8 }, [SCxSR] = { 0x04, 8 }, [SCxRDR] = { 0x05, 8 }, - [SCFCR] = sci_reg_invalid, - [SCFDR] = sci_reg_invalid, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, - [SCSPTR] = sci_reg_invalid, - [SCLSR] = sci_reg_invalid, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -204,15 +186,6 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x0a, 8 }, [SCFCR] = { 0x0c, 8 }, [SCFDR] = { 0x0e, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, - [SCSPTR] = sci_reg_invalid, - [SCLSR] = sci_reg_invalid, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -227,15 +200,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x24, 8 }, [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, - [SCSPTR] = sci_reg_invalid, - [SCLSR] = sci_reg_invalid, - [HSSRR] = sci_reg_invalid, [SCPCR] = { 0x30, 16 }, [SCPDR] = { 0x34, 16 }, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -249,16 +215,10 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxSR] = { 0x14, 16 }, [SCxRDR] = { 0x60, 8 }, [SCFCR] = { 0x18, 16 }, - [SCFDR] = sci_reg_invalid, [SCTFDR] = { 0x38, 16 }, [SCRFDR] = { 0x3c, 16 }, - [SCSPTR] = sci_reg_invalid, - [SCLSR] = sci_reg_invalid, - [HSSRR] = sci_reg_invalid, [SCPCR] = { 0x30, 16 }, [SCPDR] = { 0x34, 16 }, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -274,15 +234,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x14, 8 }, [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, [SCSPTR] = { 0x20, 16 }, [SCLSR] = { 0x24, 16 }, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -297,15 +250,6 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x0a, 8 }, [SCFCR] = { 0x0c, 8 }, [SCFDR] = { 0x0e, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, - [SCSPTR] = sci_reg_invalid, - [SCLSR] = sci_reg_invalid, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -320,15 +264,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x14, 8 }, [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, [SCSPTR] = { 0x20, 16 }, [SCLSR] = { 0x24, 16 }, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -344,13 +281,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x14, 8 }, [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, [SCSPTR] = { 0x20, 16 }, [SCLSR] = { 0x24, 16 }, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, [SCDL] = { 0x30, 16 }, [SCCKS] = { 0x34, 16 }, }, @@ -367,13 +299,9 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x14, 8 }, [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, [SCSPTR] = { 0x20, 16 }, [SCLSR] = { 0x24, 16 }, [HSSRR] = { 0x40, 16 }, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, [SCDL] = { 0x30, 16 }, [SCCKS] = { 0x34, 16 }, }, @@ -391,15 +319,7 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x14, 8 }, [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, - [SCSPTR] = sci_reg_invalid, [SCLSR] = { 0x24, 16 }, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -419,11 +339,6 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCRFDR] = { 0x20, 16 }, [SCSPTR] = { 0x24, 16 }, [SCLSR] = { 0x28, 16 }, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, /* @@ -439,15 +354,6 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCxRDR] = { 0x24, 8 }, [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, - [SCSPTR] = sci_reg_invalid, - [SCLSR] = sci_reg_invalid, - [HSSRR] = sci_reg_invalid, - [SCPCR] = sci_reg_invalid, - [SCPDR] = sci_reg_invalid, - [SCDL] = sci_reg_invalid, - [SCCKS] = sci_reg_invalid, }, }; -- cgit v1.2.3 From e095ee6b447a35ea90c523ce399d5a61753ade25 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:34 +0200 Subject: serial: sh-sci: Replace regmap array with port parameters Turn the regmap two-dimensional array to an array of port parameters and store a pointer to the port parameters in the sci_port structure. This will allow handling additional port type dependent parameters. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 278 ++++++++++++++++++++++++-------------------- 1 file changed, 155 insertions(+), 123 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 4a12c55eae61..7e72823f6388 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -101,10 +101,19 @@ enum SCI_CLKS { for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--) \ if ((_port)->sampling_rate_mask & SCI_SR((_sr))) +struct plat_sci_reg { + u8 offset, size; +}; + +struct sci_port_params { + const struct plat_sci_reg regs[SCIx_NR_REGS]; +}; + struct sci_port { struct uart_port port; /* Platform configuration */ + const struct sci_port_params *params; struct plat_sci_port *cfg; unsigned int overrun_reg; unsigned int overrun_mask; @@ -156,69 +165,73 @@ to_sci_port(struct uart_port *uart) return container_of(uart, struct sci_port, port); } -struct plat_sci_reg { - u8 offset, size; -}; - -static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { +static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { /* * Common SCI definitions, dependent on the port's regshift * value. */ [SCIx_SCI_REGTYPE] = { - [SCSMR] = { 0x00, 8 }, - [SCBRR] = { 0x01, 8 }, - [SCSCR] = { 0x02, 8 }, - [SCxTDR] = { 0x03, 8 }, - [SCxSR] = { 0x04, 8 }, - [SCxRDR] = { 0x05, 8 }, + .regs = { + [SCSMR] = { 0x00, 8 }, + [SCBRR] = { 0x01, 8 }, + [SCSCR] = { 0x02, 8 }, + [SCxTDR] = { 0x03, 8 }, + [SCxSR] = { 0x04, 8 }, + [SCxRDR] = { 0x05, 8 }, + }, }, /* * Common definitions for legacy IrDA ports. */ [SCIx_IRDA_REGTYPE] = { - [SCSMR] = { 0x00, 8 }, - [SCBRR] = { 0x02, 8 }, - [SCSCR] = { 0x04, 8 }, - [SCxTDR] = { 0x06, 8 }, - [SCxSR] = { 0x08, 16 }, - [SCxRDR] = { 0x0a, 8 }, - [SCFCR] = { 0x0c, 8 }, - [SCFDR] = { 0x0e, 16 }, + .regs = { + [SCSMR] = { 0x00, 8 }, + [SCBRR] = { 0x02, 8 }, + [SCSCR] = { 0x04, 8 }, + [SCxTDR] = { 0x06, 8 }, + [SCxSR] = { 0x08, 16 }, + [SCxRDR] = { 0x0a, 8 }, + [SCFCR] = { 0x0c, 8 }, + [SCFDR] = { 0x0e, 16 }, + }, }, /* * Common SCIFA definitions. */ [SCIx_SCIFA_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x20, 8 }, - [SCxSR] = { 0x14, 16 }, - [SCxRDR] = { 0x24, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCFDR] = { 0x1c, 16 }, - [SCPCR] = { 0x30, 16 }, - [SCPDR] = { 0x34, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x20, 8 }, + [SCxSR] = { 0x14, 16 }, + [SCxRDR] = { 0x24, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCPCR] = { 0x30, 16 }, + [SCPDR] = { 0x34, 16 }, + }, }, /* * Common SCIFB definitions. */ [SCIx_SCIFB_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x40, 8 }, - [SCxSR] = { 0x14, 16 }, - [SCxRDR] = { 0x60, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCTFDR] = { 0x38, 16 }, - [SCRFDR] = { 0x3c, 16 }, - [SCPCR] = { 0x30, 16 }, - [SCPDR] = { 0x34, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x40, 8 }, + [SCxSR] = { 0x14, 16 }, + [SCxRDR] = { 0x60, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCTFDR] = { 0x38, 16 }, + [SCRFDR] = { 0x3c, 16 }, + [SCPCR] = { 0x30, 16 }, + [SCPDR] = { 0x34, 16 }, + }, }, /* @@ -226,46 +239,52 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { * count registers. */ [SCIx_SH2_SCIF_FIFODATA_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x0c, 8 }, - [SCxSR] = { 0x10, 16 }, - [SCxRDR] = { 0x14, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCFDR] = { 0x1c, 16 }, - [SCSPTR] = { 0x20, 16 }, - [SCLSR] = { 0x24, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCSPTR] = { 0x20, 16 }, + [SCLSR] = { 0x24, 16 }, + }, }, /* * Common SH-3 SCIF definitions. */ [SCIx_SH3_SCIF_REGTYPE] = { - [SCSMR] = { 0x00, 8 }, - [SCBRR] = { 0x02, 8 }, - [SCSCR] = { 0x04, 8 }, - [SCxTDR] = { 0x06, 8 }, - [SCxSR] = { 0x08, 16 }, - [SCxRDR] = { 0x0a, 8 }, - [SCFCR] = { 0x0c, 8 }, - [SCFDR] = { 0x0e, 16 }, + .regs = { + [SCSMR] = { 0x00, 8 }, + [SCBRR] = { 0x02, 8 }, + [SCSCR] = { 0x04, 8 }, + [SCxTDR] = { 0x06, 8 }, + [SCxSR] = { 0x08, 16 }, + [SCxRDR] = { 0x0a, 8 }, + [SCFCR] = { 0x0c, 8 }, + [SCFDR] = { 0x0e, 16 }, + }, }, /* * Common SH-4(A) SCIF(B) definitions. */ [SCIx_SH4_SCIF_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x0c, 8 }, - [SCxSR] = { 0x10, 16 }, - [SCxRDR] = { 0x14, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCFDR] = { 0x1c, 16 }, - [SCSPTR] = { 0x20, 16 }, - [SCLSR] = { 0x24, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCSPTR] = { 0x20, 16 }, + [SCLSR] = { 0x24, 16 }, + }, }, /* @@ -273,37 +292,41 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { * External Clock (BRG). */ [SCIx_SH4_SCIF_BRG_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x0c, 8 }, - [SCxSR] = { 0x10, 16 }, - [SCxRDR] = { 0x14, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCFDR] = { 0x1c, 16 }, - [SCSPTR] = { 0x20, 16 }, - [SCLSR] = { 0x24, 16 }, - [SCDL] = { 0x30, 16 }, - [SCCKS] = { 0x34, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCSPTR] = { 0x20, 16 }, + [SCLSR] = { 0x24, 16 }, + [SCDL] = { 0x30, 16 }, + [SCCKS] = { 0x34, 16 }, + }, }, /* * Common HSCIF definitions. */ [SCIx_HSCIF_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x0c, 8 }, - [SCxSR] = { 0x10, 16 }, - [SCxRDR] = { 0x14, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCFDR] = { 0x1c, 16 }, - [SCSPTR] = { 0x20, 16 }, - [SCLSR] = { 0x24, 16 }, - [HSSRR] = { 0x40, 16 }, - [SCDL] = { 0x30, 16 }, - [SCCKS] = { 0x34, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCSPTR] = { 0x20, 16 }, + [SCLSR] = { 0x24, 16 }, + [HSSRR] = { 0x40, 16 }, + [SCDL] = { 0x30, 16 }, + [SCCKS] = { 0x34, 16 }, + }, }, /* @@ -311,15 +334,17 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { * register. */ [SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x0c, 8 }, - [SCxSR] = { 0x10, 16 }, - [SCxRDR] = { 0x14, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCFDR] = { 0x1c, 16 }, - [SCLSR] = { 0x24, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCLSR] = { 0x24, 16 }, + }, }, /* @@ -327,18 +352,20 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { * count registers. */ [SCIx_SH4_SCIF_FIFODATA_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x0c, 8 }, - [SCxSR] = { 0x10, 16 }, - [SCxRDR] = { 0x14, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCFDR] = { 0x1c, 16 }, - [SCTFDR] = { 0x1c, 16 }, /* aliased to SCFDR */ - [SCRFDR] = { 0x20, 16 }, - [SCSPTR] = { 0x24, 16 }, - [SCLSR] = { 0x28, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = { 0x1c, 16 }, /* aliased to SCFDR */ + [SCRFDR] = { 0x20, 16 }, + [SCSPTR] = { 0x24, 16 }, + [SCLSR] = { 0x28, 16 }, + }, }, /* @@ -346,18 +373,20 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { * registers. */ [SCIx_SH7705_SCIF_REGTYPE] = { - [SCSMR] = { 0x00, 16 }, - [SCBRR] = { 0x04, 8 }, - [SCSCR] = { 0x08, 16 }, - [SCxTDR] = { 0x20, 8 }, - [SCxSR] = { 0x14, 16 }, - [SCxRDR] = { 0x24, 8 }, - [SCFCR] = { 0x18, 16 }, - [SCFDR] = { 0x1c, 16 }, + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x20, 8 }, + [SCxSR] = { 0x14, 16 }, + [SCxRDR] = { 0x24, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + }, }, }; -#define sci_getreg(up, offset) (sci_regmap[to_sci_port(up)->cfg->regtype] + offset) +#define sci_getreg(up, offset) (&to_sci_port(up)->params->regs[offset]) /* * The "offset" here is rather misleading, in that it refers to an enum @@ -2557,6 +2586,8 @@ static int sci_init_single(struct platform_device *dev, return ret; } + sci_port->params = &sci_port_params[p->regtype]; + switch (p->type) { case PORT_SCIFB: port->fifosize = 256; @@ -3069,6 +3100,7 @@ static int __init early_console_setup(struct earlycon_device *device, sci_ports[0].cfg = &port_cfg; sci_ports[0].cfg->type = type; sci_probe_regmap(sci_ports[0].cfg); + sci_ports[0].params = &sci_port_params[sci_ports[0].cfg->regtype]; port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR); sci_serial_out(&sci_ports[0].port, SCSCR, SCSCR_RE | SCSCR_TE | port_cfg.scscr); -- cgit v1.2.3 From daf5a8959a835bd91534e0ab049d0bfe8448536d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:35 +0200 Subject: serial: sh-sci: Constify platform data The driver modifies platform data for internal purpose only. Fix that and make the platform data structure const. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 97 +++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 48 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 7e72823f6388..d50368e58314 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -114,7 +114,7 @@ struct sci_port { /* Platform configuration */ const struct sci_port_params *params; - struct plat_sci_port *cfg; + const struct plat_sci_port *cfg; unsigned int overrun_reg; unsigned int overrun_mask; unsigned int error_mask; @@ -420,41 +420,6 @@ static void sci_serial_out(struct uart_port *p, int offset, int value) WARN(1, "Invalid register access\n"); } -static int sci_probe_regmap(struct plat_sci_port *cfg) -{ - switch (cfg->type) { - case PORT_SCI: - cfg->regtype = SCIx_SCI_REGTYPE; - break; - case PORT_IRDA: - cfg->regtype = SCIx_IRDA_REGTYPE; - break; - case PORT_SCIFA: - cfg->regtype = SCIx_SCIFA_REGTYPE; - break; - case PORT_SCIFB: - cfg->regtype = SCIx_SCIFB_REGTYPE; - break; - case PORT_SCIF: - /* - * The SH-4 is a bit of a misnomer here, although that's - * where this particular port layout originated. This - * configuration (or some slight variation thereof) - * remains the dominant model for all SCIFs. - */ - cfg->regtype = SCIx_SH4_SCIF_REGTYPE; - break; - case PORT_HSCIF: - cfg->regtype = SCIx_HSCIF_REGTYPE; - break; - default: - pr_err("Can't probe register map for given port\n"); - return -EINVAL; - } - - return 0; -} - static void sci_port_enable(struct sci_port *sci_port) { unsigned int i; @@ -2541,9 +2506,50 @@ found: return 0; } +static const struct sci_port_params * +sci_probe_regmap(const struct plat_sci_port *cfg) +{ + unsigned int regtype; + + if (cfg->regtype != SCIx_PROBE_REGTYPE) + return &sci_port_params[cfg->regtype]; + + switch (cfg->type) { + case PORT_SCI: + regtype = SCIx_SCI_REGTYPE; + break; + case PORT_IRDA: + regtype = SCIx_IRDA_REGTYPE; + break; + case PORT_SCIFA: + regtype = SCIx_SCIFA_REGTYPE; + break; + case PORT_SCIFB: + regtype = SCIx_SCIFB_REGTYPE; + break; + case PORT_SCIF: + /* + * The SH-4 is a bit of a misnomer here, although that's + * where this particular port layout originated. This + * configuration (or some slight variation thereof) + * remains the dominant model for all SCIFs. + */ + regtype = SCIx_SH4_SCIF_REGTYPE; + break; + case PORT_HSCIF: + regtype = SCIx_HSCIF_REGTYPE; + break; + default: + pr_err("Can't probe register map for given port\n"); + return NULL; + } + + return &sci_port_params[regtype]; +} + static int sci_init_single(struct platform_device *dev, struct sci_port *sci_port, unsigned int index, - struct plat_sci_port *p, bool early) + const struct plat_sci_port *p, bool early) { struct uart_port *port = &sci_port->port; const struct resource *res; @@ -2580,13 +2586,9 @@ static int sci_init_single(struct platform_device *dev, sci_port->irqs[3] = sci_port->irqs[0]; } - if (p->regtype == SCIx_PROBE_REGTYPE) { - ret = sci_probe_regmap(p); - if (unlikely(ret)) - return ret; - } - - sci_port->params = &sci_port_params[p->regtype]; + sci_port->params = sci_probe_regmap(p); + if (unlikely(sci_port->params == NULL)) + return -EINVAL; switch (p->type) { case PORT_SCIFB: @@ -2806,7 +2808,7 @@ static char early_serial_buf[32]; static int sci_probe_earlyprintk(struct platform_device *pdev) { - struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev); + const struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev); if (early_serial_console.data) return -EEXIST; @@ -3097,10 +3099,9 @@ static int __init early_console_setup(struct earlycon_device *device, device->port.serial_out = sci_serial_out; device->port.type = type; memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port)); + port_cfg.type = type; sci_ports[0].cfg = &port_cfg; - sci_ports[0].cfg->type = type; - sci_probe_regmap(sci_ports[0].cfg); - sci_ports[0].params = &sci_port_params[sci_ports[0].cfg->regtype]; + sci_ports[0].params = sci_probe_regmap(&port_cfg); port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR); sci_serial_out(&sci_ports[0].port, SCSCR, SCSCR_RE | SCSCR_TE | port_cfg.scscr); -- cgit v1.2.3 From b2f20ed9c483859e2e83cfb1a3193e40760c18ad Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:36 +0200 Subject: serial: sh-sci: Extend sci_port_params with more port parameters The fifo size, overrun register and mask, sampling rate mask and error mask all depend on the port type only and don't need to be computed at runtime. Add them to the sci_port_parameters structure. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 181 ++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 81 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d50368e58314..a8607cacee6c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -107,6 +107,12 @@ struct plat_sci_reg { struct sci_port_params { const struct plat_sci_reg regs[SCIx_NR_REGS]; + unsigned int fifosize; + unsigned int overrun_reg; + unsigned int overrun_mask; + unsigned int sampling_rate_mask; + unsigned int error_mask; + unsigned int error_clear; }; struct sci_port { @@ -115,10 +121,6 @@ struct sci_port { /* Platform configuration */ const struct sci_port_params *params; const struct plat_sci_port *cfg; - unsigned int overrun_reg; - unsigned int overrun_mask; - unsigned int error_mask; - unsigned int error_clear; unsigned int sampling_rate_mask; resource_size_t reg_size; struct mctrl_gpios *gpios; @@ -179,6 +181,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCxSR] = { 0x04, 8 }, [SCxRDR] = { 0x05, 8 }, }, + .fifosize = 1, + .overrun_reg = SCxSR, + .overrun_mask = SCI_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER, + .error_clear = SCI_ERROR_CLEAR & ~SCI_ORER, }, /* @@ -195,6 +203,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCFCR] = { 0x0c, 8 }, [SCFDR] = { 0x0e, 16 }, }, + .fifosize = 1, + .overrun_reg = SCxSR, + .overrun_mask = SCI_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER, + .error_clear = SCI_ERROR_CLEAR & ~SCI_ORER, }, /* @@ -213,6 +227,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCPCR] = { 0x30, 16 }, [SCPDR] = { 0x34, 16 }, }, + .fifosize = 64, + .overrun_reg = SCxSR, + .overrun_mask = SCIFA_ORER, + .sampling_rate_mask = SCI_SR_SCIFAB, + .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER, + .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER, }, /* @@ -232,6 +252,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCPCR] = { 0x30, 16 }, [SCPDR] = { 0x34, 16 }, }, + .fifosize = 256, + .overrun_reg = SCxSR, + .overrun_mask = SCIFA_ORER, + .sampling_rate_mask = SCI_SR_SCIFAB, + .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER, + .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER, }, /* @@ -251,6 +277,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCSPTR] = { 0x20, 16 }, [SCLSR] = { 0x24, 16 }, }, + .fifosize = 16, + .overrun_reg = SCLSR, + .overrun_mask = SCLSR_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCIF_DEFAULT_ERROR_MASK, + .error_clear = SCIF_ERROR_CLEAR, }, /* @@ -267,6 +299,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCFCR] = { 0x0c, 8 }, [SCFDR] = { 0x0e, 16 }, }, + .fifosize = 16, + .overrun_reg = SCLSR, + .overrun_mask = SCLSR_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCIF_DEFAULT_ERROR_MASK, + .error_clear = SCIF_ERROR_CLEAR, }, /* @@ -285,6 +323,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCSPTR] = { 0x20, 16 }, [SCLSR] = { 0x24, 16 }, }, + .fifosize = 16, + .overrun_reg = SCLSR, + .overrun_mask = SCLSR_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCIF_DEFAULT_ERROR_MASK, + .error_clear = SCIF_ERROR_CLEAR, }, /* @@ -306,6 +350,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCDL] = { 0x30, 16 }, [SCCKS] = { 0x34, 16 }, }, + .fifosize = 16, + .overrun_reg = SCLSR, + .overrun_mask = SCLSR_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCIF_DEFAULT_ERROR_MASK, + .error_clear = SCIF_ERROR_CLEAR, }, /* @@ -327,6 +377,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCDL] = { 0x30, 16 }, [SCCKS] = { 0x34, 16 }, }, + .fifosize = 128, + .overrun_reg = SCLSR, + .overrun_mask = SCLSR_ORER, + .sampling_rate_mask = SCI_SR_RANGE(8, 32), + .error_mask = SCIF_DEFAULT_ERROR_MASK, + .error_clear = SCIF_ERROR_CLEAR, }, /* @@ -345,6 +401,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCFDR] = { 0x1c, 16 }, [SCLSR] = { 0x24, 16 }, }, + .fifosize = 16, + .overrun_reg = SCLSR, + .overrun_mask = SCLSR_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCIF_DEFAULT_ERROR_MASK, + .error_clear = SCIF_ERROR_CLEAR, }, /* @@ -366,6 +428,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCSPTR] = { 0x24, 16 }, [SCLSR] = { 0x28, 16 }, }, + .fifosize = 16, + .overrun_reg = SCLSR, + .overrun_mask = SCLSR_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCIF_DEFAULT_ERROR_MASK, + .error_clear = SCIF_ERROR_CLEAR, }, /* @@ -383,6 +451,12 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, }, + .fifosize = 16, + .overrun_reg = SCxSR, + .overrun_mask = SCIFA_ORER, + .sampling_rate_mask = SCI_SR(16), + .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER, + .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER, }, }; @@ -545,7 +619,7 @@ static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask) if (port->type == PORT_SCI) { /* Just store the mask */ serial_port_out(port, SCxSR, mask); - } else if (to_sci_port(port)->overrun_mask == SCIFA_ORER) { + } else if (to_sci_port(port)->params->overrun_mask == SCIFA_ORER) { /* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */ /* Only clear the status bits we want to clear */ serial_port_out(port, SCxSR, @@ -640,11 +714,13 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) static int sci_txfill(struct uart_port *port) { + struct sci_port *s = to_sci_port(port); + unsigned int fifo_mask = (s->params->fifosize << 1) - 1; const struct plat_sci_reg *reg; reg = sci_getreg(port, SCTFDR); if (reg->size) - return serial_port_in(port, SCTFDR) & ((port->fifosize << 1) - 1); + return serial_port_in(port, SCTFDR) & fifo_mask; reg = sci_getreg(port, SCFDR); if (reg->size) @@ -660,15 +736,17 @@ static int sci_txroom(struct uart_port *port) static int sci_rxfill(struct uart_port *port) { + struct sci_port *s = to_sci_port(port); + unsigned int fifo_mask = (s->params->fifosize << 1) - 1; const struct plat_sci_reg *reg; reg = sci_getreg(port, SCRFDR); if (reg->size) - return serial_port_in(port, SCRFDR) & ((port->fifosize << 1) - 1); + return serial_port_in(port, SCRFDR) & fifo_mask; reg = sci_getreg(port, SCFDR); if (reg->size) - return serial_port_in(port, SCFDR) & ((port->fifosize << 1) - 1); + return serial_port_in(port, SCFDR) & fifo_mask; return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; } @@ -879,7 +957,7 @@ static int sci_handle_errors(struct uart_port *port) struct sci_port *s = to_sci_port(port); /* Handle overruns */ - if (status & s->overrun_mask) { + if (status & s->params->overrun_mask) { port->icount.overrun++; /* overrun error */ @@ -945,14 +1023,14 @@ static int sci_handle_fifo_overrun(struct uart_port *port) int copied = 0; u16 status; - reg = sci_getreg(port, s->overrun_reg); + reg = sci_getreg(port, s->params->overrun_reg); if (!reg->size) return 0; - status = serial_port_in(port, s->overrun_reg); - if (status & s->overrun_mask) { - status &= ~s->overrun_mask; - serial_port_out(port, s->overrun_reg, status); + status = serial_port_in(port, s->params->overrun_reg); + if (status & s->params->overrun_mask) { + status &= ~s->params->overrun_mask; + serial_port_out(port, s->params->overrun_reg, status); port->icount.overrun++; @@ -1541,12 +1619,10 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) ssr_status = serial_port_in(port, SCxSR); scr_status = serial_port_in(port, SCSCR); - if (s->overrun_reg == SCxSR) + if (s->params->overrun_reg == SCxSR) orer_status = ssr_status; - else { - if (sci_getreg(port, s->overrun_reg)->size) - orer_status = serial_port_in(port, s->overrun_reg); - } + else if (sci_getreg(port, s->params->overrun_reg)->size) + orer_status = serial_port_in(port, s->params->overrun_reg); err_enabled = scr_status & port_rx_irq_mask(port); @@ -1572,7 +1648,7 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) ret = sci_br_interrupt(irq, ptr); /* Overrun Interrupt */ - if (orer_status & s->overrun_mask) { + if (orer_status & s->params->overrun_mask) { sci_handle_fifo_overrun(port); ret = IRQ_HANDLED; } @@ -2590,51 +2666,13 @@ static int sci_init_single(struct platform_device *dev, if (unlikely(sci_port->params == NULL)) return -EINVAL; - switch (p->type) { - case PORT_SCIFB: - port->fifosize = 256; - sci_port->overrun_reg = SCxSR; - sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate_mask = SCI_SR_SCIFAB; - break; - case PORT_HSCIF: - port->fifosize = 128; - sci_port->overrun_reg = SCLSR; - sci_port->overrun_mask = SCLSR_ORER; - sci_port->sampling_rate_mask = SCI_SR_RANGE(8, 32); - break; - case PORT_SCIFA: - port->fifosize = 64; - sci_port->overrun_reg = SCxSR; - sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate_mask = SCI_SR_SCIFAB; - break; - case PORT_SCIF: - port->fifosize = 16; - if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) { - sci_port->overrun_reg = SCxSR; - sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate_mask = SCI_SR(16); - } else { - sci_port->overrun_reg = SCLSR; - sci_port->overrun_mask = SCLSR_ORER; - sci_port->sampling_rate_mask = SCI_SR(32); - } - break; - default: - port->fifosize = 1; - sci_port->overrun_reg = SCxSR; - sci_port->overrun_mask = SCI_ORER; - sci_port->sampling_rate_mask = SCI_SR(32); - break; - } - /* SCIFA on sh7723 and sh7724 need a custom sampling rate that doesn't * match the SoC datasheet, this should be investigated. Let platform * data override the sampling rate for now. */ - if (p->sampling_rate) - sci_port->sampling_rate_mask = SCI_SR(p->sampling_rate); + sci_port->sampling_rate_mask = p->sampling_rate + ? SCI_SR(p->sampling_rate) + : sci_port->params->sampling_rate_mask; if (!early) { ret = sci_init_clocks(sci_port, &dev->dev); @@ -2650,29 +2688,10 @@ static int sci_init_single(struct platform_device *dev, sci_port->break_timer.function = sci_break_timer; init_timer(&sci_port->break_timer); - /* - * Establish some sensible defaults for the error detection. - */ - if (p->type == PORT_SCI) { - sci_port->error_mask = SCI_DEFAULT_ERROR_MASK; - sci_port->error_clear = SCI_ERROR_CLEAR; - } else { - sci_port->error_mask = SCIF_DEFAULT_ERROR_MASK; - sci_port->error_clear = SCIF_ERROR_CLEAR; - } - - /* - * Make the error mask inclusive of overrun detection, if - * supported. - */ - if (sci_port->overrun_reg == SCxSR) { - sci_port->error_mask |= sci_port->overrun_mask; - sci_port->error_clear &= ~sci_port->overrun_mask; - } - port->type = p->type; port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags; port->regshift = p->regshift; + port->fifosize = sci_port->params->fifosize; /* * The UART port needs an IRQ value, so we peg this to the RX IRQ -- cgit v1.2.3 From 219fb0c1436e4893a290ba270bc0e644d02465a3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:37 +0200 Subject: serial: sh-sci: Remove the platform data dma slave rx/tx channel IDs Only SH platforms still use platform data for the sh-sci, and none of them declare DMA channels connected to the SCI. Remove the corresponding platform data fields and simplify the driver accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index a8607cacee6c..c6aa5b9c2bfd 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1387,20 +1387,14 @@ static void rx_timer_fn(unsigned long arg) } static struct dma_chan *sci_request_dma_chan(struct uart_port *port, - enum dma_transfer_direction dir, - unsigned int id) + enum dma_transfer_direction dir) { - dma_cap_mask_t mask; struct dma_chan *chan; struct dma_slave_config cfg; int ret; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, - (void *)(unsigned long)id, port->dev, - dir == DMA_MEM_TO_DEV ? "tx" : "rx"); + chan = dma_request_slave_channel(port->dev, + dir == DMA_MEM_TO_DEV ? "tx" : "rx"); if (!chan) { dev_warn(port->dev, "dma_request_slave_channel_compat failed\n"); @@ -1436,12 +1430,11 @@ static void sci_request_dma(struct uart_port *port) dev_dbg(port->dev, "%s: port %d\n", __func__, port->line); - if (!port->dev->of_node && - (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0)) + if (!port->dev->of_node) return; s->cookie_tx = -EINVAL; - chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV, s->cfg->dma_slave_tx); + chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV); dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan); if (chan) { s->chan_tx = chan; @@ -1463,7 +1456,7 @@ static void sci_request_dma(struct uart_port *port) INIT_WORK(&s->work_tx, work_fn_tx); } - chan = sci_request_dma_chan(port, DMA_DEV_TO_MEM, s->cfg->dma_slave_rx); + chan = sci_request_dma_chan(port, DMA_DEV_TO_MEM); dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan); if (chan) { unsigned int i; @@ -2706,10 +2699,6 @@ static int sci_init_single(struct platform_device *dev, port->serial_in = sci_serial_in; port->serial_out = sci_serial_out; - if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) - dev_dbg(port->dev, "DMA tx %d, rx %d\n", - p->dma_slave_tx, p->dma_slave_rx); - return 0; } -- cgit v1.2.3 From d5cb1319a91d4f1328b1c70b82c5899acd96af85 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:38 +0200 Subject: serial: sh-sci: Remove manual break debouncing The sh-sci driver implements manual break debouncing for a few SH platforms by reading the value of the RX pin port register. This feature is optional and the driver considers all negative or zero values of the platform data port_reg field as invalid. As the four platforms that set the field to a register address all use an address higher than 0x7fffffff, the driver will always consider the value as invalid and never perform debouncing. The feature is unused, remove it. Debouncing could be implemented properly in the future using the pinctrl and GPIO APIs if desired. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 124 +++----------------------------------------- 1 file changed, 7 insertions(+), 117 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c6aa5b9c2bfd..ae1404e701ea 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -125,10 +125,6 @@ struct sci_port { resource_size_t reg_size; struct mctrl_gpios *gpios; - /* Break timer */ - struct timer_list break_timer; - int break_flag; - /* Clocks */ struct clk *clks[SCI_NUM_CLKS]; unsigned long clk_rates[SCI_NUM_CLKS]; @@ -517,14 +513,6 @@ static void sci_port_disable(struct sci_port *sci_port) if (!sci_port->port.dev) return; - /* Cancel the break timer to ensure that the timer handler will not try - * to access the hardware with clocks and power disabled. Reset the - * break flag to make the break debouncing state machine ready for the - * next break. - */ - del_timer_sync(&sci_port->break_timer); - sci_port->break_flag = 0; - for (i = SCI_NUM_CLKS; i-- > 0; ) clk_disable_unprepare(sci_port->clks[i]); @@ -751,20 +739,6 @@ static int sci_rxfill(struct uart_port *port) return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; } -/* - * SCI helper for checking the state of the muxed port/RXD pins. - */ -static inline int sci_rxd_in(struct uart_port *port) -{ - struct sci_port *s = to_sci_port(port); - - if (s->cfg->port_reg <= 0) - return 1; - - /* Cast for ARM damage */ - return !!__raw_readb((void __iomem *)(uintptr_t)s->cfg->port_reg); -} - /* ********************************************************************** * * the interrupt related routines * * ********************************************************************** */ @@ -832,7 +806,6 @@ static void sci_transmit_chars(struct uart_port *port) static void sci_receive_chars(struct uart_port *port) { - struct sci_port *sci_port = to_sci_port(port); struct tty_port *tport = &port->state->port; int i, count, copied = 0; unsigned short status; @@ -852,8 +825,7 @@ static void sci_receive_chars(struct uart_port *port) if (port->type == PORT_SCI) { char c = serial_port_in(port, SCxRDR); - if (uart_handle_sysrq_char(port, c) || - sci_port->break_flag) + if (uart_handle_sysrq_char(port, c)) count = 0; else tty_insert_flip_char(tport, c, TTY_NORMAL); @@ -862,25 +834,6 @@ static void sci_receive_chars(struct uart_port *port) char c = serial_port_in(port, SCxRDR); status = serial_port_in(port, SCxSR); -#if defined(CONFIG_CPU_SH3) - /* Skip "chars" during break */ - if (sci_port->break_flag) { - if ((c == 0) && - (status & SCxSR_FER(port))) { - count--; i--; - continue; - } - - /* Nonzero => end-of-break */ - dev_dbg(port->dev, "debounce<%02x>\n", c); - sci_port->break_flag = 0; - - if (STEPFN(c)) { - count--; i--; - continue; - } - } -#endif /* CONFIG_CPU_SH3 */ if (uart_handle_sysrq_char(port, c)) { count--; i--; continue; @@ -918,37 +871,6 @@ static void sci_receive_chars(struct uart_port *port) } } -#define SCI_BREAK_JIFFIES (HZ/20) - -/* - * The sci generates interrupts during the break, - * 1 per millisecond or so during the break period, for 9600 baud. - * So dont bother disabling interrupts. - * But dont want more than 1 break event. - * Use a kernel timer to periodically poll the rx line until - * the break is finished. - */ -static inline void sci_schedule_break_timer(struct sci_port *port) -{ - mod_timer(&port->break_timer, jiffies + SCI_BREAK_JIFFIES); -} - -/* Ensure that two consecutive samples find the break over. */ -static void sci_break_timer(unsigned long data) -{ - struct sci_port *port = (struct sci_port *)data; - - if (sci_rxd_in(&port->port) == 0) { - port->break_flag = 1; - sci_schedule_break_timer(port); - } else if (port->break_flag == 1) { - /* break is over. */ - port->break_flag = 2; - sci_schedule_break_timer(port); - } else - port->break_flag = 0; -} - static int sci_handle_errors(struct uart_port *port) { int copied = 0; @@ -968,35 +890,13 @@ static int sci_handle_errors(struct uart_port *port) } if (status & SCxSR_FER(port)) { - if (sci_rxd_in(port) == 0) { - /* Notify of BREAK */ - struct sci_port *sci_port = to_sci_port(port); - - if (!sci_port->break_flag) { - port->icount.brk++; - - sci_port->break_flag = 1; - sci_schedule_break_timer(sci_port); - - /* Do sysrq handling. */ - if (uart_handle_break(port)) - return 0; - - dev_dbg(port->dev, "BREAK detected\n"); - - if (tty_insert_flip_char(tport, 0, TTY_BREAK)) - copied++; - } - - } else { - /* frame error */ - port->icount.frame++; + /* frame error */ + port->icount.frame++; - if (tty_insert_flip_char(tport, 0, TTY_FRAME)) - copied++; + if (tty_insert_flip_char(tport, 0, TTY_FRAME)) + copied++; - dev_notice(port->dev, "frame error\n"); - } + dev_notice(port->dev, "frame error\n"); } if (status & SCxSR_PER(port)) { @@ -1049,17 +949,11 @@ static int sci_handle_breaks(struct uart_port *port) int copied = 0; unsigned short status = serial_port_in(port, SCxSR); struct tty_port *tport = &port->state->port; - struct sci_port *s = to_sci_port(port); if (uart_handle_break(port)) return 0; - if (!s->break_flag && status & SCxSR_BRK(port)) { -#if defined(CONFIG_CPU_SH3) - /* Debounce break */ - s->break_flag = 1; -#endif - + if (status & SCxSR_BRK(port)) { port->icount.brk++; /* Notify of BREAK */ @@ -2677,10 +2571,6 @@ static int sci_init_single(struct platform_device *dev, pm_runtime_enable(&dev->dev); } - sci_port->break_timer.data = (unsigned long)sci_port; - sci_port->break_timer.function = sci_break_timer; - init_timer(&sci_port->break_timer); - port->type = p->type; port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags; port->regshift = p->regshift; -- cgit v1.2.3 From 97ed9790c514066bfae67f22e084b505ed5af436 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:39 +0200 Subject: serial: sh-sci: Remove unused platform data capabilities field The field isn't set by any platform but is only used internally in the driver to hold data parsed from DT. Move it to the sci_port structure. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index ae1404e701ea..a04ed40279d1 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -149,6 +149,7 @@ struct sci_port { unsigned int rx_timeout; #endif + bool has_rtscts; bool autorts; }; @@ -680,7 +681,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) /* Enable RXD and TXD pin functions */ ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC); - if (to_sci_port(port)->cfg->capabilities & SCIx_HAVE_RTSCTS) { + if (to_sci_port(port)->has_rtscts) { /* RTS# is output, driven 1 */ ctrl |= SCPCR_RTSC; serial_port_out(port, SCPDR, @@ -1738,7 +1739,7 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) mctrl_gpio_set(s->gpios, mctrl); - if (!(s->cfg->capabilities & SCIx_HAVE_RTSCTS)) + if (!s->has_rtscts) return; if (!(mctrl & TIOCM_RTS)) { @@ -2809,6 +2810,7 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; struct plat_sci_port *p; + struct sci_port *sp; int id; if (!IS_ENABLED(CONFIG_OF) || !np) @@ -2829,13 +2831,14 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) return NULL; } + sp = &sci_ports[id]; *dev_id = id; p->type = SCI_OF_TYPE(match->data); p->regtype = SCI_OF_REGTYPE(match->data); if (of_find_property(np, "uart-has-rtscts", NULL)) - p->capabilities |= SCIx_HAVE_RTSCTS; + sp->has_rtscts = true; return p; } @@ -2863,7 +2866,7 @@ static int sci_probe_single(struct platform_device *dev, if (IS_ERR(sciport->gpios) && PTR_ERR(sciport->gpios) != -ENOSYS) return PTR_ERR(sciport->gpios); - if (p->capabilities & SCIx_HAVE_RTSCTS) { + if (sciport->has_rtscts) { if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios, UART_GPIO_CTS)) || !IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios, -- cgit v1.2.3 From dfc80387aefb78161f83732804c6d01c89c24595 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:40 +0200 Subject: serial: sh-sci: Compute the regshift value for SCI ports SCI instances found in SH SoCs have different spacing between registers depending on the SoC. The platform data contains a regshift field that tells the driver by how many bits to shift the register offset to compute its address. We can compute the regshift value automatically based on the memory resource size, there's no need to pass the value through platform data. Fix the sh7750 SCI and sh7760 SIM port memory resources length to ensure proper computation of the regshift value. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index a04ed40279d1..a18f4cb8e1fb 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2574,9 +2574,15 @@ static int sci_init_single(struct platform_device *dev, port->type = p->type; port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags; - port->regshift = p->regshift; port->fifosize = sci_port->params->fifosize; + if (port->type == PORT_SCI) { + if (sci_port->reg_size >= 0x20) + port->regshift = 2; + else + port->regshift = 1; + } + /* * The UART port needs an IRQ value, so we peg this to the RX IRQ * for the multi-IRQ ports, which is where we are primarily -- cgit v1.2.3 From 54b12c48f0c603f25bac3c7c58a02cee65610171 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 25 Jan 2017 15:55:49 +0100 Subject: serial: sh-sci: Reformat sci_parse_dt() for git diff As the function header of sci_parse_dt() is split in an unusual way, "git diff" gets confused when changes to the body of the function are made, and attributes them to the wrong function. Reformat the function header to fix this. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index a18f4cb8e1fb..d7535b47bf10 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2810,8 +2810,8 @@ static const struct of_device_id of_sci_match[] = { }; MODULE_DEVICE_TABLE(of, of_sci_match); -static struct plat_sci_port * -sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) +static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, + unsigned int *dev_id) { struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; -- cgit v1.2.3 From 54e14ae2f3e82b327853e40afa9382a984a56742 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Thu, 2 Feb 2017 18:10:14 +0100 Subject: serial: sh-sci: add FIFO trigger bits Defines the bits controlling FIFO thresholds, adds the additional HSCIF registers to the register map. Signed-off-by: Ulrich Hecht Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d7535b47bf10..5044a5e5d340 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -373,6 +373,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [HSSRR] = { 0x40, 16 }, [SCDL] = { 0x30, 16 }, [SCCKS] = { 0x34, 16 }, + [HSRTRGR] = { 0x54, 16 }, + [HSTTRGR] = { 0x58, 16 }, }, .fifosize = 128, .overrun_reg = SCLSR, -- cgit v1.2.3 From a380ed461f66d1b843cf13380a43a5fe790b8430 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Thu, 2 Feb 2017 18:10:16 +0100 Subject: serial: sh-sci: implement FIFO threshold register setting Sets the closest match for a desired RX trigger level. Signed-off-by: Ulrich Hecht Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5044a5e5d340..050d028cf2a1 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -974,6 +974,65 @@ static int sci_handle_breaks(struct uart_port *port) return copied; } +static int scif_set_rtrg(struct uart_port *port, int rx_trig) +{ + unsigned int bits; + + if (rx_trig < 1) + rx_trig = 1; + if (rx_trig >= port->fifosize) + rx_trig = port->fifosize; + + /* HSCIF can be set to an arbitrary level. */ + if (sci_getreg(port, HSRTRGR)->size) { + serial_port_out(port, HSRTRGR, rx_trig); + return rx_trig; + } + + switch (port->type) { + case PORT_SCIF: + if (rx_trig < 4) { + bits = 0; + rx_trig = 1; + } else if (rx_trig < 8) { + bits = SCFCR_RTRG0; + rx_trig = 4; + } else if (rx_trig < 14) { + bits = SCFCR_RTRG1; + rx_trig = 8; + } else { + bits = SCFCR_RTRG0 | SCFCR_RTRG1; + rx_trig = 14; + } + break; + case PORT_SCIFA: + case PORT_SCIFB: + if (rx_trig < 16) { + bits = 0; + rx_trig = 1; + } else if (rx_trig < 32) { + bits = SCFCR_RTRG0; + rx_trig = 16; + } else if (rx_trig < 48) { + bits = SCFCR_RTRG1; + rx_trig = 32; + } else { + bits = SCFCR_RTRG0 | SCFCR_RTRG1; + rx_trig = 48; + } + break; + default: + WARN(1, "unknown FIFO configuration"); + return 1; + } + + serial_port_out(port, SCFCR, + (serial_port_in(port, SCFCR) & + ~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits); + + return rx_trig; +} + #ifdef CONFIG_SERIAL_SH_SCI_DMA static void sci_dma_tx_complete(void *arg) { -- cgit v1.2.3 From 18e8cf159177100e69d528293f8cf6875c0b1bca Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 3 Feb 2017 11:38:17 +0100 Subject: serial: sh-sci: increase RX FIFO trigger defaults for (H)SCIF Sets reasonable trigger defaults for the various SCIF variants. Also corrects the FIFO size for SH7705-style ports. Signed-off-by: Ulrich Hecht Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial/sh-sci.c') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 050d028cf2a1..520e344a811d 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -148,6 +148,7 @@ struct sci_port { struct timer_list rx_timer; unsigned int rx_timeout; #endif + int rx_trigger; bool has_rtscts; bool autorts; @@ -450,7 +451,7 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCFCR] = { 0x18, 16 }, [SCFDR] = { 0x1c, 16 }, }, - .fifosize = 16, + .fifosize = 64, .overrun_reg = SCxSR, .overrun_mask = SCIFA_ORER, .sampling_rate_mask = SCI_SR(16), @@ -2062,6 +2063,7 @@ static void sci_reset(struct uart_port *port) { const struct plat_sci_reg *reg; unsigned int status; + struct sci_port *s = to_sci_port(port); do { status = serial_port_in(port, SCxSR); @@ -2081,6 +2083,9 @@ static void sci_reset(struct uart_port *port) status &= ~(SCLSR_TO | SCLSR_ORER); serial_port_out(port, SCLSR, status); } + + if (s->rx_trigger > 1) + scif_set_rtrg(port, s->rx_trigger); } static void sci_set_termios(struct uart_port *port, struct ktermios *termios, @@ -2615,6 +2620,28 @@ static int sci_init_single(struct platform_device *dev, if (unlikely(sci_port->params == NULL)) return -EINVAL; + switch (p->type) { + case PORT_SCIFB: + sci_port->rx_trigger = 48; + break; + case PORT_HSCIF: + sci_port->rx_trigger = 64; + break; + case PORT_SCIFA: + sci_port->rx_trigger = 32; + break; + case PORT_SCIF: + if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) + /* RX triggering not implemented for this IP */ + sci_port->rx_trigger = 1; + else + sci_port->rx_trigger = 8; + break; + default: + sci_port->rx_trigger = 1; + break; + } + /* SCIFA on sh7723 and sh7724 need a custom sampling rate that doesn't * match the SoC datasheet, this should be investigated. Let platform * data override the sampling rate for now. -- cgit v1.2.3 From 039403765e5da3c6a4c2cc048c201bfad932033a Mon Sep 17 00:00:00 2001 From: Ulrich Hecht <