From 405ada37fbdafaa6691a906f3630ba8d064e5f30 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Sat, 11 Apr 2015 17:16:23 +0000 Subject: [PATCH] Add support for the uart classes to set their default register shift value. This is needed with the pl011 driver. Before this change it would default to a shift of 0, however the hardware places the registers at 4-byte addresses meaning the value should be 2. This patch fixes this for the pl011 when configured using the fdt. The other drivers have a default value of 0 to keep this a no-op. MFC after: 1 week --- sys/arm/amlogic/aml8726/uart_dev_aml8726.c | 3 ++- sys/arm/freescale/vybrid/vf_uart.c | 3 ++- sys/arm/samsung/exynos/exynos_uart.c | 1 + sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c | 1 + sys/dev/uart/uart_bus.h | 1 + sys/dev/uart/uart_bus_fdt.c | 11 +++-------- sys/dev/uart/uart_core.c | 6 ++++++ sys/dev/uart/uart_cpu.h | 1 + sys/dev/uart/uart_cpu_fdt.c | 20 +++++++++++--------- sys/dev/uart/uart_dev_imx.c | 3 ++- sys/dev/uart/uart_dev_lpc.c | 3 ++- sys/dev/uart/uart_dev_msm.c | 1 + sys/dev/uart/uart_dev_ns8250.c | 3 ++- sys/dev/uart/uart_dev_pl011.c | 3 ++- sys/dev/uart/uart_dev_quicc.c | 3 ++- sys/dev/uart/uart_dev_sab82532.c | 3 ++- sys/dev/uart/uart_dev_ti8250.c | 3 ++- sys/dev/uart/uart_dev_z8530.c | 3 ++- sys/mips/adm5120/uart_dev_adm5120.c | 3 ++- sys/mips/atheros/uart_dev_ar933x.c | 3 ++- sys/mips/cavium/uart_dev_oct16550.c | 3 ++- sys/mips/rt305x/uart_dev_rt305x.c | 3 ++- sys/sparc64/pci/sbbc.c | 3 ++- 23 files changed, 55 insertions(+), 32 deletions(-) diff --git a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c index 0932f5da62e9..1dda52f42d18 100644 --- a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c +++ b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c @@ -724,7 +724,8 @@ struct uart_class uart_aml8726_class = { sizeof(struct uart_softc), .uc_ops = &aml8726_uart_ops, .uc_range = 24, - .uc_rclk = 0 + .uc_rclk = 0, + .uc_rshift = 0 }; static struct ofw_compat_data compat_data[] = { diff --git a/sys/arm/freescale/vybrid/vf_uart.c b/sys/arm/freescale/vybrid/vf_uart.c index fcea49fceeae..312f18c17c1d 100644 --- a/sys/arm/freescale/vybrid/vf_uart.c +++ b/sys/arm/freescale/vybrid/vf_uart.c @@ -276,7 +276,8 @@ static struct uart_class uart_vybrid_class = { sizeof(struct vf_uart_softc), .uc_ops = &uart_vybrid_ops, .uc_range = 0x100, - .uc_rclk = 24000000 /* TODO: get value from CCM */ + .uc_rclk = 24000000, /* TODO: get value from CCM */ + .uc_rshift = 0 }; static struct ofw_compat_data compat_data[] = { diff --git a/sys/arm/samsung/exynos/exynos_uart.c b/sys/arm/samsung/exynos/exynos_uart.c index 9e33bcbc2e0d..7b372dedf87f 100644 --- a/sys/arm/samsung/exynos/exynos_uart.c +++ b/sys/arm/samsung/exynos/exynos_uart.c @@ -380,6 +380,7 @@ static struct uart_class uart_exynos4210_class = { .uc_ops = &uart_exynos4210_ops, .uc_range = 8, .uc_rclk = 0, + .uc_rshift = 0 }; static struct ofw_compat_data compat_data[] = { diff --git a/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c b/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c index 2ee121700dec..cc0d59acdd24 100644 --- a/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c +++ b/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c @@ -402,4 +402,5 @@ struct uart_class uart_s3c2410_class = { .uc_ops = &uart_s3c2410_ops, .uc_range = 8, .uc_rclk = 0, + .uc_rshift = 0 }; diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h index 322e9a85e023..7394651e841a 100644 --- a/sys/dev/uart/uart_bus.h +++ b/sys/dev/uart/uart_bus.h @@ -70,6 +70,7 @@ struct uart_class { struct uart_ops *uc_ops; /* Low-level console operations. */ u_int uc_range; /* Bus space address range. */ u_int uc_rclk; /* Default rclk for this device. */ + u_int uc_rshift; /* Default regshift for this device. */ }; struct uart_softc { diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c index 5f0bb24ccfb5..1498eb86b706 100644 --- a/sys/dev/uart/uart_bus_fdt.c +++ b/sys/dev/uart/uart_bus_fdt.c @@ -83,16 +83,10 @@ uart_fdt_get_clock(phandle_t node, pcell_t *cell) int uart_fdt_get_shift(phandle_t node, pcell_t *cell) { -#ifdef __aarch64__ -#define DEFAULT_SHIFT 2 -#else -#define DEFAULT_SHIFT 0 -#endif if ((OF_getencprop(node, "reg-shift", cell, sizeof(*cell))) <= 0) - *cell = DEFAULT_SHIFT; + return (-1); return (0); -#undef DEFAULT_SHIFT } static uintptr_t @@ -130,7 +124,8 @@ uart_fdt_probe(device_t dev) if ((err = uart_fdt_get_clock(node, &clock)) != 0) return (err); - uart_fdt_get_shift(node, &shift); + if (uart_fdt_get_shift(node, &shift) != 0) + shift = uart_getregshift(sc->sc_class); return (uart_bus_probe(dev, (int)shift, (int)clock, 0, 0)); } diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c index eea2d8ce80a1..bbb06ff5c1f5 100644 --- a/sys/dev/uart/uart_core.c +++ b/sys/dev/uart/uart_core.c @@ -88,6 +88,12 @@ uart_getrange(struct uart_class *uc) return ((uc != NULL) ? uc->uc_range : 0); } +u_int +uart_getregshift(struct uart_class *uc) +{ + return ((uc != NULL) ? uc->uc_rshift : 0); +} + /* * Schedule a soft interrupt. We do this on the 0 to !0 transition * of the TTY pending interrupt status. diff --git a/sys/dev/uart/uart_cpu.h b/sys/dev/uart/uart_cpu.h index 2db04123ad0e..d9e5410eacec 100644 --- a/sys/dev/uart/uart_cpu.h +++ b/sys/dev/uart/uart_cpu.h @@ -79,6 +79,7 @@ int uart_getenv(int, struct uart_devinfo *, struct uart_class *); const char *uart_getname(struct uart_class *); struct uart_ops *uart_getops(struct uart_class *); int uart_getrange(struct uart_class *); +u_int uart_getregshift(struct uart_class *); void uart_add_sysdev(struct uart_devinfo *); diff --git a/sys/dev/uart/uart_cpu_fdt.c b/sys/dev/uart/uart_cpu_fdt.c index dc00fe8a70e6..344aad576424 100644 --- a/sys/dev/uart/uart_cpu_fdt.c +++ b/sys/dev/uart/uart_cpu_fdt.c @@ -164,15 +164,6 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) if (node == -1) /* Can't find anything */ return (ENXIO); - /* - * Retrieve serial attributes. - */ - uart_fdt_get_shift(node, &shift); - if (OF_getprop(node, "current-speed", &br, sizeof(br)) <= 0) - br = 0; - else - br = fdt32_to_cpu(br); - /* * Check old style of UART definition first. Unfortunately, the common * FDT processing is not possible if we have clock, power domains and @@ -191,6 +182,17 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) rclk = 0; } + /* + * Retrieve serial attributes. + */ + if (uart_fdt_get_shift(node, &shift) != 0) + shift = uart_getregshift(class); + + if (OF_getprop(node, "current-speed", &br, sizeof(br)) <= 0) + br = 0; + else + br = fdt32_to_cpu(br); + /* * Finalize configuration. */ diff --git a/sys/dev/uart/uart_dev_imx.c b/sys/dev/uart/uart_dev_imx.c index 9e34473cfe35..bc25df37f2d1 100644 --- a/sys/dev/uart/uart_dev_imx.c +++ b/sys/dev/uart/uart_dev_imx.c @@ -298,7 +298,8 @@ static struct uart_class uart_imx_class = { sizeof(struct imx_uart_softc), .uc_ops = &uart_imx_uart_ops, .uc_range = 0x100, - .uc_rclk = 24000000 /* TODO: get value from CCM */ + .uc_rclk = 24000000, /* TODO: get value from CCM */ + .uc_rshift = 0 }; static struct ofw_compat_data compat_data[] = { diff --git a/sys/dev/uart/uart_dev_lpc.c b/sys/dev/uart/uart_dev_lpc.c index 992e89008934..6cd10f1ae48c 100644 --- a/sys/dev/uart/uart_dev_lpc.c +++ b/sys/dev/uart/uart_dev_lpc.c @@ -428,7 +428,8 @@ static struct uart_class uart_lpc_class = { sizeof(struct lpc_ns8250_softc), .uc_ops = &uart_lpc_ns8250_ops, .uc_range = 8, - .uc_rclk = DEFAULT_RCLK + .uc_rclk = DEFAULT_RCLK, + .uc_rshift = 0 }; static struct ofw_compat_data compat_data[] = { diff --git a/sys/dev/uart/uart_dev_msm.c b/sys/dev/uart/uart_dev_msm.c index 114a41588870..7ba46aca2bcf 100644 --- a/sys/dev/uart/uart_dev_msm.c +++ b/sys/dev/uart/uart_dev_msm.c @@ -566,6 +566,7 @@ static struct uart_class uart_msm_class = { .uc_ops = &uart_msm_ops, .uc_range = 8, .uc_rclk = DEF_CLK, + .uc_rshift = 0 }; static struct ofw_compat_data compat_data[] = { diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index 190ee29bd9fc..9ff295a972d0 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -378,7 +378,8 @@ struct uart_class uart_ns8250_class = { sizeof(struct ns8250_softc), .uc_ops = &uart_ns8250_ops, .uc_range = 8, - .uc_rclk = DEFAULT_RCLK + .uc_rclk = DEFAULT_RCLK, + .uc_rshift = 0 }; #ifdef FDT diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c index 8443adbc2f3d..e90e7f8d4e74 100644 --- a/sys/dev/uart/uart_dev_pl011.c +++ b/sys/dev/uart/uart_dev_pl011.c @@ -273,7 +273,8 @@ static struct uart_class uart_pl011_class = { sizeof(struct uart_pl011_softc), .uc_ops = &uart_pl011_ops, .uc_range = 0x48, - .uc_rclk = 0 + .uc_rclk = 0, + .uc_rshift = 2 }; static struct ofw_compat_data compat_data[] = { diff --git a/sys/dev/uart/uart_dev_quicc.c b/sys/dev/uart/uart_dev_quicc.c index bbbc3bd0f5df..0237d6402ee1 100644 --- a/sys/dev/uart/uart_dev_quicc.c +++ b/sys/dev/uart/uart_dev_quicc.c @@ -271,7 +271,8 @@ struct uart_class uart_quicc_class = { sizeof(struct quicc_softc), .uc_ops = &uart_quicc_ops, .uc_range = 2, - .uc_rclk = DEFAULT_RCLK + .uc_rclk = DEFAULT_RCLK, + .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ diff --git a/sys/dev/uart/uart_dev_sab82532.c b/sys/dev/uart/uart_dev_sab82532.c index 8caa7a7f1234..59a963924953 100644 --- a/sys/dev/uart/uart_dev_sab82532.c +++ b/sys/dev/uart/uart_dev_sab82532.c @@ -391,7 +391,8 @@ struct uart_class uart_sab82532_class = { sizeof(struct sab82532_softc), .uc_ops = &uart_sab82532_ops, .uc_range = 64, - .uc_rclk = DEFAULT_RCLK + .uc_rclk = DEFAULT_RCLK, + .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ diff --git a/sys/dev/uart/uart_dev_ti8250.c b/sys/dev/uart/uart_dev_ti8250.c index daddbb7cf4d9..373dc743dc0e 100644 --- a/sys/dev/uart/uart_dev_ti8250.c +++ b/sys/dev/uart/uart_dev_ti8250.c @@ -137,7 +137,8 @@ static struct uart_class uart_ti8250_class = { sizeof(struct ti8250_softc), .uc_ops = &uart_ns8250_ops, .uc_range = 0x88, - .uc_rclk = 48000000 + .uc_rclk = 48000000, + .uc_rshift = 0 }; static struct ofw_compat_data compat_data[] = { {"ti,ns16550", (uintptr_t)&uart_ti8250_class}, diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c index 5cc24a80bd62..5bacd4012e0c 100644 --- a/sys/dev/uart/uart_dev_z8530.c +++ b/sys/dev/uart/uart_dev_z8530.c @@ -307,7 +307,8 @@ struct uart_class uart_z8530_class = { sizeof(struct z8530_softc), .uc_ops = &uart_z8530_ops, .uc_range = 2, - .uc_rclk = DEFAULT_RCLK + .uc_rclk = DEFAULT_RCLK, + .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ diff --git a/sys/mips/adm5120/uart_dev_adm5120.c b/sys/mips/adm5120/uart_dev_adm5120.c index 5ec18c88f0e6..5c3e691b0236 100644 --- a/sys/mips/adm5120/uart_dev_adm5120.c +++ b/sys/mips/adm5120/uart_dev_adm5120.c @@ -175,7 +175,8 @@ struct uart_class uart_adm5120_uart_class = { sizeof(struct adm5120_uart_softc), .uc_ops = &uart_adm5120_uart_ops, .uc_range = 1, /* use hinted range */ - .uc_rclk = 62500000 + .uc_rclk = 62500000, + .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ diff --git a/sys/mips/atheros/uart_dev_ar933x.c b/sys/mips/atheros/uart_dev_ar933x.c index 7be92bca2d21..e769cbed4d2f 100644 --- a/sys/mips/atheros/uart_dev_ar933x.c +++ b/sys/mips/atheros/uart_dev_ar933x.c @@ -351,7 +351,8 @@ struct uart_class uart_ar933x_class = { sizeof(struct ar933x_softc), .uc_ops = &uart_ar933x_ops, .uc_range = 8, - .uc_rclk = DEFAULT_RCLK + .uc_rclk = DEFAULT_RCLK, + .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ diff --git a/sys/mips/cavium/uart_dev_oct16550.c b/sys/mips/cavium/uart_dev_oct16550.c index f3d47ca9ef56..cfb347f06393 100644 --- a/sys/mips/cavium/uart_dev_oct16550.c +++ b/sys/mips/cavium/uart_dev_oct16550.c @@ -424,7 +424,8 @@ struct uart_class uart_oct16550_class = { sizeof(struct oct16550_softc), .uc_ops = &uart_oct16550_ops, .uc_range = 8 << 3, - .uc_rclk = 0 + .uc_rclk = 0, + .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ diff --git a/sys/mips/rt305x/uart_dev_rt305x.c b/sys/mips/rt305x/uart_dev_rt305x.c index d4f23196d053..5d23b1eeaef0 100644 --- a/sys/mips/rt305x/uart_dev_rt305x.c +++ b/sys/mips/rt305x/uart_dev_rt305x.c @@ -217,7 +217,8 @@ struct uart_class uart_rt305x_uart_class = { sizeof(struct rt305x_uart_softc), .uc_ops = &uart_rt305x_uart_ops, .uc_range = 1, /* use hinted range */ - .uc_rclk = SYSTEM_CLOCK + .uc_rclk = SYSTEM_CLOCK, + .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ diff --git a/sys/sparc64/pci/sbbc.c b/sys/sparc64/pci/sbbc.c index c19fb71b0bb3..f1e7fab94ced 100644 --- a/sys/sparc64/pci/sbbc.c +++ b/sys/sparc64/pci/sbbc.c @@ -813,7 +813,8 @@ struct uart_class uart_sbbc_class = { sizeof(struct uart_softc), .uc_ops = &sbbc_uart_ops, .uc_range = 1, - .uc_rclk = 0x5bbc /* arbitrary */ + .uc_rclk = 0x5bbc, /* arbitrary */ + .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \