#include <linux/platform_device.h>
#include <linux/module.h>
+#include <linux/bitfield.h>
#include <linux/console.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
static struct uart_port *console_port;
#endif
+/**
+ * struct uartlite_data: Driver private data
+ * reg_ops: Functions to read/write registers
+ * clk: Our parent clock, if present
+ * baud: The baud rate configured when this device was synthesized
+ * cflags: The cflags for parity and data bits
+ */
struct uartlite_data {
const struct uartlite_reg_ops *reg_ops;
struct clk *clk;
+ unsigned int baud;
+ tcflag_t cflags;
};
struct uartlite_reg_ops {
static struct uart_port ulite_ports[ULITE_NR_UARTS];
+static struct uart_driver ulite_uart_driver;
+
/* ---------------------------------------------------------------------
* Core UART driver operations
*/
struct ktermios *old)
{
unsigned long flags;
- unsigned int baud;
+ struct uartlite_data *pdata = port->private_data;
+
+ /* Set termios to what the hardware supports */
+ termios->c_cflag &= ~(BRKINT | CSTOPB | PARENB | PARODD | CSIZE);
+ termios->c_cflag |= pdata->cflags & (PARENB | PARODD | CSIZE);
+ tty_termios_encode_baud_rate(termios, pdata->baud, pdata->baud);
spin_lock_irqsave(&port->lock, flags);
| ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
/* update timeout */
- baud = uart_get_baud_rate(port, termios, old, 0, 460800);
- uart_update_timeout(port, termios->c_cflag, baud);
+ uart_update_timeout(port, termios->c_cflag, pdata->baud);
spin_unlock_irqrestore(&port->lock, flags);
}
return uart_set_options(port, co, baud, parity, bits, flow);
}
-static struct uart_driver ulite_uart_driver;
-
static struct console ulite_console = {
.name = ULITE_NAME,
.write = ulite_console_write,
struct uartlite_data *pdata;
int irq, ret;
int id = pdev->id;
-#ifdef CONFIG_OF
- const __be32 *prop;
- prop = of_get_property(pdev->dev.of_node, "port-number", NULL);
- if (prop)
- id = be32_to_cpup(prop);
-#endif
pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data),
GFP_KERNEL);
if (!pdata)
return -ENOMEM;
+ if (IS_ENABLED(CONFIG_OF)) {
+ const char *prop;
+ struct device_node *np = pdev->dev.of_node;
+ u32 val = 0;
+
+ prop = "port-number";
+ ret = of_property_read_u32(np, prop, &id);
+ if (ret && ret != -EINVAL)
+of_err:
+ return dev_err_probe(&pdev->dev, ret,
+ "could not read %s\n", prop);
+
+ prop = "current-speed";
+ ret = of_property_read_u32(np, prop, &pdata->baud);
+ if (ret)
+ goto of_err;
+
+ prop = "xlnx,use-parity";
+ ret = of_property_read_u32(np, prop, &val);
+ if (ret && ret != -EINVAL)
+ goto of_err;
+
+ if (val) {
+ prop = "xlnx,odd-parity";
+ ret = of_property_read_u32(np, prop, &val);
+ if (ret)
+ goto of_err;
+
+ if (val)
+ pdata->cflags |= PARODD;
+ pdata->cflags |= PARENB;
+ }
+
+ val = 8;
+ prop = "xlnx,data-bits";
+ ret = of_property_read_u32(np, prop, &val);
+ if (ret && ret != -EINVAL)
+ goto of_err;
+
+ switch (val) {
+ case 5:
+ pdata->cflags |= CS5;
+ break;
+ case 6:
+ pdata->cflags |= CS6;
+ break;
+ case 7:
+ pdata->cflags |= CS7;
+ break;
+ case 8:
+ pdata->cflags |= CS8;
+ break;
+ default:
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "bad data bits %d\n", val);
+ }
+ } else {
+ pdata->baud = 9600;
+ pdata->cflags = CS8;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;