Skip to content

Commit ea017f5

Browse files
sean-anderson-secogregkh
authored andcommitted
tty: serial: uartlite: Prevent changing fixed parameters
This device does not support changing baud, parity, data bits, stop bits, or detecting breaks. Disable "changing" these settings to prevent their termios from diverging from the actual state of the uart. In order to determine the correct parameters to enforce, we read the various new devicetree parameters to discover how the uart was configured when it was synthesized. The defaults match ulite_console_setup. xlnx,use-parity, xlnx,odd-parity, and xlnx,data-bits are optional since there were in-tree users (and presumably out-of-tree users) who did not set them. Signed-off-by: Sean Anderson <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 8517b62 commit ea017f5

File tree

1 file changed

+80
-11
lines changed

1 file changed

+80
-11
lines changed

drivers/tty/serial/uartlite.c

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <linux/platform_device.h>
1010
#include <linux/module.h>
11+
#include <linux/bitfield.h>
1112
#include <linux/console.h>
1213
#include <linux/serial.h>
1314
#include <linux/serial_core.h>
@@ -63,9 +64,18 @@
6364
static struct uart_port *console_port;
6465
#endif
6566

67+
/**
68+
* struct uartlite_data: Driver private data
69+
* reg_ops: Functions to read/write registers
70+
* clk: Our parent clock, if present
71+
* baud: The baud rate configured when this device was synthesized
72+
* cflags: The cflags for parity and data bits
73+
*/
6674
struct uartlite_data {
6775
const struct uartlite_reg_ops *reg_ops;
6876
struct clk *clk;
77+
unsigned int baud;
78+
tcflag_t cflags;
6979
};
7080

7181
struct uartlite_reg_ops {
@@ -119,6 +129,8 @@ static inline void uart_out32(u32 val, u32 offset, struct uart_port *port)
119129

120130
static struct uart_port ulite_ports[ULITE_NR_UARTS];
121131

132+
static struct uart_driver ulite_uart_driver;
133+
122134
/* ---------------------------------------------------------------------
123135
* Core UART driver operations
124136
*/
@@ -306,7 +318,12 @@ static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
306318
struct ktermios *old)
307319
{
308320
unsigned long flags;
309-
unsigned int baud;
321+
struct uartlite_data *pdata = port->private_data;
322+
323+
/* Set termios to what the hardware supports */
324+
termios->c_cflag &= ~(BRKINT | CSTOPB | PARENB | PARODD | CSIZE);
325+
termios->c_cflag |= pdata->cflags & (PARENB | PARODD | CSIZE);
326+
tty_termios_encode_baud_rate(termios, pdata->baud, pdata->baud);
310327

311328
spin_lock_irqsave(&port->lock, flags);
312329

@@ -329,8 +346,7 @@ static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
329346
| ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
330347

331348
/* update timeout */
332-
baud = uart_get_baud_rate(port, termios, old, 0, 460800);
333-
uart_update_timeout(port, termios->c_cflag, baud);
349+
uart_update_timeout(port, termios->c_cflag, pdata->baud);
334350

335351
spin_unlock_irqrestore(&port->lock, flags);
336352
}
@@ -532,8 +548,6 @@ static int ulite_console_setup(struct console *co, char *options)
532548
return uart_set_options(port, co, baud, parity, bits, flow);
533549
}
534550

535-
static struct uart_driver ulite_uart_driver;
536-
537551
static struct console ulite_console = {
538552
.name = ULITE_NAME,
539553
.write = ulite_console_write,
@@ -765,18 +779,73 @@ static int ulite_probe(struct platform_device *pdev)
765779
struct uartlite_data *pdata;
766780
int irq, ret;
767781
int id = pdev->id;
768-
#ifdef CONFIG_OF
769-
const __be32 *prop;
770782

771-
prop = of_get_property(pdev->dev.of_node, "port-number", NULL);
772-
if (prop)
773-
id = be32_to_cpup(prop);
774-
#endif
775783
pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data),
776784
GFP_KERNEL);
777785
if (!pdata)
778786
return -ENOMEM;
779787

788+
if (IS_ENABLED(CONFIG_OF)) {
789+
const char *prop;
790+
struct device_node *np = pdev->dev.of_node;
791+
u32 val = 0;
792+
793+
prop = "port-number";
794+
ret = of_property_read_u32(np, prop, &id);
795+
if (ret && ret != -EINVAL)
796+
of_err:
797+
return dev_err_probe(&pdev->dev, ret,
798+
"could not read %s\n", prop);
799+
800+
prop = "current-speed";
801+
ret = of_property_read_u32(np, prop, &pdata->baud);
802+
if (ret)
803+
goto of_err;
804+
805+
prop = "xlnx,use-parity";
806+
ret = of_property_read_u32(np, prop, &val);
807+
if (ret && ret != -EINVAL)
808+
goto of_err;
809+
810+
if (val) {
811+
prop = "xlnx,odd-parity";
812+
ret = of_property_read_u32(np, prop, &val);
813+
if (ret)
814+
goto of_err;
815+
816+
if (val)
817+
pdata->cflags |= PARODD;
818+
pdata->cflags |= PARENB;
819+
}
820+
821+
val = 8;
822+
prop = "xlnx,data-bits";
823+
ret = of_property_read_u32(np, prop, &val);
824+
if (ret && ret != -EINVAL)
825+
goto of_err;
826+
827+
switch (val) {
828+
case 5:
829+
pdata->cflags |= CS5;
830+
break;
831+
case 6:
832+
pdata->cflags |= CS6;
833+
break;
834+
case 7:
835+
pdata->cflags |= CS7;
836+
break;
837+
case 8:
838+
pdata->cflags |= CS8;
839+
break;
840+
default:
841+
return dev_err_probe(&pdev->dev, -EINVAL,
842+
"bad data bits %d\n", val);
843+
}
844+
} else {
845+
pdata->baud = 9600;
846+
pdata->cflags = CS8;
847+
}
848+
780849
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
781850
if (!res)
782851
return -ENODEV;

0 commit comments

Comments
 (0)