summaryrefslogtreecommitdiffstats
path: root/sys/dev/uart
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2015-05-23 20:54:25 +0000
committerian <ian@FreeBSD.org>2015-05-23 20:54:25 +0000
commitf3f411e10b20906a8640a6316ddcc3c1f24725e3 (patch)
treeb8226cf0be8fe4cd6baeb7595bf89042db51e870 /sys/dev/uart
parentce1bf49e72ea9be2396679cd9569beeec685e9c6 (diff)
downloadFreeBSD-src-f3f411e10b20906a8640a6316ddcc3c1f24725e3.zip
FreeBSD-src-f3f411e10b20906a8640a6316ddcc3c1f24725e3.tar.gz
MFC r279723, r279724:
Define new linker set, UART_FDT_CLASS_AND_DEVICE, for registering full (class and device) FDT UART. Define second one, UART_FDT_CLASS, for UART class only. Move the uart_class definitions and fdt compat data into the individual uart implementations, and export them using the new linker-set mechanism.
Diffstat (limited to 'sys/dev/uart')
-rw-r--r--sys/dev/uart/uart.h14
-rw-r--r--sys/dev/uart/uart_bus_fdt.c53
-rw-r--r--sys/dev/uart/uart_cpu_fdt.c66
-rw-r--r--sys/dev/uart/uart_cpu_fdt.h54
-rw-r--r--sys/dev/uart/uart_dev_imx.c15
-rw-r--r--sys/dev/uart/uart_dev_lpc.c9
-rw-r--r--sys/dev/uart/uart_dev_msm.c9
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c11
-rw-r--r--sys/dev/uart/uart_dev_pl011.c9
-rw-r--r--sys/dev/uart/uart_dev_ti8250.c9
-rw-r--r--sys/dev/uart/uart_subr.c1
11 files changed, 181 insertions, 69 deletions
diff --git a/sys/dev/uart/uart.h b/sys/dev/uart/uart.h
index b62dec6..c40846b 100644
--- a/sys/dev/uart/uart.h
+++ b/sys/dev/uart/uart.h
@@ -64,26 +64,12 @@ struct uart_bas {
*/
struct uart_class;
-extern struct uart_class uart_imx_class __attribute__((weak));
-extern struct uart_class uart_msm_class __attribute__((weak));
extern struct uart_class uart_ns8250_class __attribute__((weak));
extern struct uart_class uart_quicc_class __attribute__((weak));
extern struct uart_class uart_s3c2410_class __attribute__((weak));
extern struct uart_class uart_sab82532_class __attribute__((weak));
extern struct uart_class uart_sbbc_class __attribute__((weak));
extern struct uart_class uart_z8530_class __attribute__((weak));
-extern struct uart_class uart_lpc_class __attribute__((weak));
-extern struct uart_class uart_pl011_class __attribute__((weak));
-extern struct uart_class uart_cdnc_class __attribute__((weak));
-extern struct uart_class uart_ti8250_class __attribute__((weak));
-extern struct uart_class uart_vybrid_class __attribute__((weak));
-extern struct uart_class at91_usart_class __attribute__((weak));
-extern struct uart_class uart_exynos4210_class __attribute__((weak));
-
-#ifdef FDT
-struct ofw_compat_data;
-extern const struct ofw_compat_data *uart_fdt_compat_data;
-#endif
#ifdef PC98
struct uart_class *uart_pc98_getdev(u_long port);
diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c
index 457e041..3c68d95 100644
--- a/sys/dev/uart/uart_bus_fdt.c
+++ b/sys/dev/uart/uart_bus_fdt.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
static int uart_fdt_probe(device_t);
@@ -62,37 +63,6 @@ static driver_t uart_fdt_driver = {
sizeof(struct uart_softc),
};
-/*
- * Compatible devices. Keep this sorted in most- to least-specific order first,
- * alphabetical second. That is, "zwie,ns16550" should appear before "ns16550"
- * on the theory that the zwie driver knows how to make better use of the
- * hardware than the generic driver. Likewise with chips within a family, the
- * highest-numbers / most recent models should probably appear earlier.
- */
-static struct ofw_compat_data compat_data[] = {
- {"arm,pl011", (uintptr_t)&uart_pl011_class},
- {"atmel,at91rm9200-usart",(uintptr_t)&at91_usart_class},
- {"atmel,at91sam9260-usart",(uintptr_t)&at91_usart_class},
- {"cadence,uart", (uintptr_t)&uart_cdnc_class},
- {"exynos", (uintptr_t)&uart_exynos4210_class},
- {"fsl,imx6q-uart", (uintptr_t)&uart_imx_class},
- {"fsl,imx53-uart", (uintptr_t)&uart_imx_class},
- {"fsl,imx51-uart", (uintptr_t)&uart_imx_class},
- {"fsl,imx31-uart", (uintptr_t)&uart_imx_class},
- {"fsl,imx27-uart", (uintptr_t)&uart_imx_class},
- {"fsl,imx25-uart", (uintptr_t)&uart_imx_class},
- {"fsl,imx21-uart", (uintptr_t)&uart_imx_class},
- {"fsl,mvf600-uart", (uintptr_t)&uart_vybrid_class},
- {"lpc,uart", (uintptr_t)&uart_lpc_class},
- {"qcom,msm-uartdm", (uintptr_t)&uart_msm_class},
- {"ti,ns16550", (uintptr_t)&uart_ti8250_class},
- {"ns16550", (uintptr_t)&uart_ns8250_class},
- {NULL, (uintptr_t)NULL},
-};
-
-/* Export the compat_data table for use by the uart_cpu_fdt.c probe routine. */
-const struct ofw_compat_data *uart_fdt_compat_data = compat_data;
-
static int
uart_fdt_get_clock(phandle_t node, pcell_t *cell)
{
@@ -127,6 +97,20 @@ uart_fdt_get_shift(phandle_t node, pcell_t *cell)
return (0);
}
+static uintptr_t
+uart_fdt_find_device(device_t dev)
+{
+ struct ofw_compat_data **cd;
+ const struct ofw_compat_data *ocd;
+
+ SET_FOREACH(cd, uart_fdt_class_and_device_set) {
+ ocd = ofw_bus_search_compatible(dev, *cd);
+ if (ocd->ocd_data != 0)
+ return (ocd->ocd_data);
+ }
+ return (0);
+}
+
static int
uart_fdt_probe(device_t dev)
{
@@ -134,19 +118,16 @@ uart_fdt_probe(device_t dev)
phandle_t node;
pcell_t clock, shift;
int err;
- const struct ofw_compat_data * cd;
sc = device_get_softc(dev);
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- cd = ofw_bus_search_compatible(dev, compat_data);
- if (cd->ocd_data == (uintptr_t)NULL)
+ sc->sc_class = (struct uart_class *)uart_fdt_find_device(dev);
+ if (sc->sc_class == NULL)
return (ENXIO);
- sc->sc_class = (struct uart_class *)cd->ocd_data;
-
node = ofw_bus_get_node(dev);
if ((err = uart_fdt_get_clock(node, &clock)) != 0)
diff --git a/sys/dev/uart/uart_cpu_fdt.c b/sys/dev/uart/uart_cpu_fdt.c
index 356049b..8dfdb3c 100644
--- a/sys/dev/uart/uart_cpu_fdt.c
+++ b/sys/dev/uart/uart_cpu_fdt.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
/*
* UART console routines.
@@ -115,13 +116,46 @@ phandle_chosen_propdev(phandle_t chosen, const char *name, phandle_t *node)
return (0);
}
+static const struct ofw_compat_data *
+uart_fdt_find_compatible(phandle_t node, const struct ofw_compat_data *cd)
+{
+ const struct ofw_compat_data *ocd;
+
+ for (ocd = cd; ocd->ocd_str != NULL; ocd++) {
+ if (fdt_is_compatible(node, ocd->ocd_str))
+ return (ocd);
+ }
+ return (NULL);
+}
+
+static uintptr_t
+uart_fdt_find_by_node(phandle_t node, int class_list)
+{
+ struct ofw_compat_data **cd;
+ const struct ofw_compat_data *ocd;
+
+ if (class_list) {
+ SET_FOREACH(cd, uart_fdt_class_set) {
+ ocd = uart_fdt_find_compatible(node, *cd);
+ if ((ocd != NULL) && (ocd->ocd_data != 0))
+ return (ocd->ocd_data);
+ }
+ } else {
+ SET_FOREACH(cd, uart_fdt_class_and_device_set) {
+ ocd = uart_fdt_find_compatible(node, *cd);
+ if ((ocd != NULL) && (ocd->ocd_data != 0))
+ return (ocd->ocd_data);
+ }
+ }
+ return (0);
+}
+
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
const char *propnames[] = {"stdout-path", "linux,stdout-path", "stdout",
"stdin-path", "stdin", NULL};
const char **name;
- const struct ofw_compat_data *cd;
struct uart_class *class;
phandle_t node, chosen;
pcell_t shift, br, rclk;
@@ -160,24 +194,32 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
* Retrieve serial attributes.
*/
uart_fdt_get_shift(node, &shift);
-
if (OF_getprop(node, "current-speed", &br, sizeof(br)) <= 0)
br = 0;
- br = fdt32_to_cpu(br);
+ else
+ br = fdt32_to_cpu(br);
- if ((err = uart_fdt_get_clock(node, &rclk)) != 0)
- return (err);
/*
- * Finalize configuration.
+ * Check old style of UART definition first. Unfortunately, the common
+ * FDT processing is not possible if we have clock, power domains and
+ * pinmux stuff.
*/
- for (cd = uart_fdt_compat_data; cd->ocd_str != NULL; ++cd) {
- if (fdt_is_compatible(node, cd->ocd_str))
- break;
+ class = (struct uart_class *)uart_fdt_find_by_node(node, 0);
+ if (class != NULL) {
+ if ((err = uart_fdt_get_clock(node, &rclk)) != 0)
+ return (err);
+ } else {
+ /* Check class only linker set */
+ class =
+ (struct uart_class *)uart_fdt_find_by_node(node, 1);
+ if (class == NULL)
+ return (ENXIO);
+ rclk = 0;
}
- if (cd->ocd_str == NULL)
- return (ENXIO);
- class = (struct uart_class *)cd->ocd_data;
+ /*
+ * Finalize configuration.
+ */
di->bas.chan = 0;
di->bas.regshft = (u_int)shift;
di->baudrate = br;
diff --git a/sys/dev/uart/uart_cpu_fdt.h b/sys/dev/uart/uart_cpu_fdt.h
new file mode 100644
index 0000000..e7aaecd
--- /dev/null
+++ b/sys/dev/uart/uart_cpu_fdt.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright 2015 Michal Meloun
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_UART_CPU_FDT_H_
+#define _DEV_UART_CPU_FDT_H_
+
+#include <sys/linker_set.h>
+
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * If your UART driver implements only uart_class and uses uart_cpu_fdt.c
+ * for device instantiation, then use UART_FDT_CLASS_AND_DEVICE for its
+ * declaration
+ */
+SET_DECLARE(uart_fdt_class_and_device_set, struct ofw_compat_data );
+#define UART_FDT_CLASS_AND_DEVICE(data) \
+ DATA_SET(uart_fdt_class_and_device_set, data)
+
+/*
+ * If your UART driver implements uart_class and custom device layer,
+ * then use UART_FDT_CLASS for its declaration
+ */
+SET_DECLARE(uart_fdt_class_set, struct ofw_compat_data );
+#define UART_FDT_CLASS(data) \
+ DATA_SET(uart_fdt_class_set, data)
+
+
+#endif /* _DEV_UART_CPU_FDT_H_ */
diff --git a/sys/dev/uart/uart_dev_imx.c b/sys/dev/uart/uart_dev_imx.c
index 2f5fc06..9e34473 100644
--- a/sys/dev/uart/uart_dev_imx.c
+++ b/sys/dev/uart/uart_dev_imx.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_dev_imx.h>
#include "uart_if.h"
@@ -291,7 +292,7 @@ static kobj_method_t imx_uart_methods[] = {
{ 0, 0 }
};
-struct uart_class uart_imx_class = {
+static struct uart_class uart_imx_class = {
"imx",
imx_uart_methods,
sizeof(struct imx_uart_softc),
@@ -300,6 +301,18 @@ struct uart_class uart_imx_class = {
.uc_rclk = 24000000 /* TODO: get value from CCM */
};
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6q-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx53-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx51-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx31-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx27-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx25-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx21-uart", (uintptr_t)&uart_imx_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+
#define SIGCHG(c, i, s, d) \
if (c) { \
i |= (i & s) ? s : s | d; \
diff --git a/sys/dev/uart/uart_dev_lpc.c b/sys/dev/uart/uart_dev_lpc.c
index 08cebc9..992e890 100644
--- a/sys/dev/uart/uart_dev_lpc.c
+++ b/sys/dev/uart/uart_dev_lpc.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
#include <dev/uart/uart_bus.h>
#include <dev/ic/ns16550.h>
@@ -421,7 +422,7 @@ static kobj_method_t lpc_ns8250_methods[] = {
{ 0, 0 }
};
-struct uart_class uart_lpc_class = {
+static struct uart_class uart_lpc_class = {
"lpc_ns8250",
lpc_ns8250_methods,
sizeof(struct lpc_ns8250_softc),
@@ -430,6 +431,12 @@ struct uart_class uart_lpc_class = {
.uc_rclk = DEFAULT_RCLK
};
+static struct ofw_compat_data compat_data[] = {
+ {"lpc,uart", (uintptr_t)&uart_lpc_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+
#define SIGCHG(c, i, s, d) \
if (c) { \
i |= (i & s) ? s : s | d; \
diff --git a/sys/dev/uart/uart_dev_msm.c b/sys/dev/uart/uart_dev_msm.c
index 12dc8a7..114a415 100644
--- a/sys/dev/uart/uart_dev_msm.c
+++ b/sys/dev/uart/uart_dev_msm.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_dev_msm.h>
@@ -558,7 +559,7 @@ msm_bus_ungrab(struct uart_softc *sc)
uart_unlock(sc->sc_hwmtx);
}
-struct uart_class uart_msm_class = {
+static struct uart_class uart_msm_class = {
"msm",
msm_methods,
sizeof(struct msm_uart_softc),
@@ -566,3 +567,9 @@ struct uart_class uart_msm_class = {
.uc_range = 8,
.uc_rclk = DEF_CLK,
};
+
+static struct ofw_compat_data compat_data[] = {
+ {"qcom,msm-uartdm", (uintptr_t)&uart_msm_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 47a61bf..99692e6 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -45,6 +45,9 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
+#ifdef FDT
+#include <dev/uart/uart_cpu_fdt.h>
+#endif
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_dev_ns8250.h>
@@ -379,6 +382,14 @@ struct uart_class uart_ns8250_class = {
.uc_rclk = DEFAULT_RCLK
};
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+ {"ns16550", (uintptr_t)&uart_ns8250_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+#endif
+
#define SIGCHG(c, i, s, d) \
if (c) { \
i |= (i & s) ? s : s | d; \
diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c
index 1d17286..9084c35 100644
--- a/sys/dev/uart/uart_dev_pl011.c
+++ b/sys/dev/uart/uart_dev_pl011.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
#include <dev/uart/uart_bus.h>
#include "uart_if.h"
@@ -266,7 +267,7 @@ static kobj_method_t uart_pl011_methods[] = {
{ 0, 0 }
};
-struct uart_class uart_pl011_class = {
+static struct uart_class uart_pl011_class = {
"uart_pl011",
uart_pl011_methods,
sizeof(struct uart_pl011_softc),
@@ -275,6 +276,12 @@ struct uart_class uart_pl011_class = {
.uc_rclk = 0
};
+static struct ofw_compat_data compat_data[] = {
+ {"arm,pl011", (uintptr_t)&uart_pl011_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+
static int
uart_pl011_bus_attach(struct uart_softc *sc)
{
diff --git a/sys/dev/uart/uart_dev_ti8250.c b/sys/dev/uart/uart_dev_ti8250.c
index 12d059a..daddbb7 100644
--- a/sys/dev/uart/uart_dev_ti8250.c
+++ b/sys/dev/uart/uart_dev_ti8250.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_dev_ns8250.h>
@@ -130,7 +131,7 @@ static kobj_method_t ti8250_methods[] = {
KOBJMETHOD_END
};
-struct uart_class uart_ti8250_class = {
+static struct uart_class uart_ti8250_class = {
"ti8250",
ti8250_methods,
sizeof(struct ti8250_softc),
@@ -138,4 +139,8 @@ struct uart_class uart_ti8250_class = {
.uc_range = 0x88,
.uc_rclk = 48000000
};
-
+static struct ofw_compat_data compat_data[] = {
+ {"ti,ns16550", (uintptr_t)&uart_ti8250_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
diff --git a/sys/dev/uart/uart_subr.c b/sys/dev/uart/uart_subr.c
index 0277b21..b24f7eb 100644
--- a/sys/dev/uart/uart_subr.c
+++ b/sys/dev/uart/uart_subr.c
@@ -53,7 +53,6 @@ static struct uart_class *uart_classes[] = {
&uart_sab82532_class,
&uart_z8530_class,
#if defined(__arm__)
- &uart_lpc_class,
&uart_s3c2410_class,
#endif
};
OpenPOWER on IntegriCloud