When early console are registered via device-tree, currently it is assumed that the console iotype is UPIO_MEM and the regshift is 0. This is not the case for all devices and so add support for reading the device-tree properties "reg-io-width" and "reg-shift" so that the appropriate iotype and regshift can be specified for a given device. Signed-off-by: Jon Hunter <jonathanh@xxxxxxxxxx> --- drivers/of/fdt.c | 26 +++++++++++++++++++++++++- drivers/tty/serial/earlycon.c | 6 ++++-- include/linux/serial_core.h | 3 ++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 655f79db7899..f69406e42631 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -827,7 +827,9 @@ static int __init early_init_dt_scan_chosen_serial(void) return -ENODEV; while (match->compatible[0]) { + const __be32 *prop; u64 addr; + u8 iotype, regshift; if (fdt_node_check_compatible(fdt, offset, match->compatible)) { match++; @@ -838,7 +840,29 @@ static int __init early_init_dt_scan_chosen_serial(void) if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match->data); + prop = fdt_getprop(fdt, offset, "reg-shift", NULL); + regshift = prop ? be32_to_cpup(prop) : 0; + + prop = fdt_getprop(fdt, offset, "reg-io-width", NULL); + if (prop) { + switch (be32_to_cpup(prop)) { + case 1: + iotype = UPIO_MEM; + break; + case 2: + iotype = UPIO_MEM16; + break; + case 4: + iotype = UPIO_MEM32; + break; + default: + return -EINVAL; + } + } else { + iotype = UPIO_MEM; + } + + of_setup_earlycon(addr, iotype, regshift, match->data); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 3f2423690d01..2fd2f19d7091 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -204,17 +204,19 @@ static int __init param_setup_earlycon(char *buf) } early_param("earlycon", param_setup_earlycon); -int __init of_setup_earlycon(unsigned long addr, +int __init of_setup_earlycon(unsigned long addr, unsigned char iotype, + unsigned char regshift, int (*setup)(struct earlycon_device *, const char *)) { int err; struct uart_port *port = &early_console_dev.port; spin_lock_init(&port->lock); - port->iotype = UPIO_MEM; + port->iotype = iotype; port->mapbase = addr; port->uartclk = BASE_BAUD * 16; port->membase = earlycon_map(addr, SZ_4K); + port->regshift = regshift; early_console_dev.con->data = &early_console_dev; err = setup(&early_console_dev, NULL); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index e03d6ba5e5b4..e0e1c7ef2856 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -346,7 +346,8 @@ struct earlycon_id { } __aligned(32); extern int setup_earlycon(char *buf); -extern int of_setup_earlycon(unsigned long addr, +extern int of_setup_earlycon(unsigned long addr, unsigned char iotype, + unsigned char regshift, int (*setup)(struct earlycon_device *, const char *)); #define EARLYCON_DECLARE(_name, func) \ -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html