Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/fdt Add support for fdt clock and reset controllers.
details: https://anonhg.NetBSD.org/src/rev/0e9968575b28
branches: trunk
changeset: 342452:0e9968575b28
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Tue Dec 22 21:42:11 2015 +0000
description:
Add support for fdt clock and reset controllers.
diffstat:
sys/dev/fdt/fdt_clock.c | 158 ++++++++++++++++++++++++++++++++++++++++
sys/dev/fdt/fdt_reset.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/fdt/fdt_subr.c | 13 ++-
sys/dev/fdt/fdtvar.h | 35 ++++++++-
sys/dev/fdt/files.fdt | 4 +-
5 files changed, 393 insertions(+), 6 deletions(-)
diffs (truncated from 484 to 300 lines):
diff -r 115764e02b87 -r 0e9968575b28 sys/dev/fdt/fdt_clock.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/fdt/fdt_clock.c Tue Dec 22 21:42:11 2015 +0000
@@ -0,0 +1,158 @@
+/* $NetBSD: fdt_clock.c,v 1.1 2015/12/22 21:42:11 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 ``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 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: fdt_clock.c,v 1.1 2015/12/22 21:42:11 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kmem.h>
+
+#include <libfdt.h>
+#include <dev/fdt/fdtvar.h>
+
+struct fdtbus_clock_controller {
+ device_t cc_dev;
+ int cc_phandle;
+ const struct fdtbus_clock_controller_func *cc_funcs;
+
+ struct fdtbus_clock_controller *cc_next;
+};
+
+static struct fdtbus_clock_controller *fdtbus_cc = NULL;
+
+int
+fdtbus_register_clock_controller(device_t dev, int phandle,
+ const struct fdtbus_clock_controller_func *funcs)
+{
+ struct fdtbus_clock_controller *cc;
+
+ cc = kmem_alloc(sizeof(*cc), KM_SLEEP);
+ cc->cc_dev = dev;
+ cc->cc_phandle = phandle;
+ cc->cc_funcs = funcs;
+
+ cc->cc_next = fdtbus_cc;
+ fdtbus_cc = cc;
+
+ return 0;
+}
+
+static struct fdtbus_clock_controller *
+fdtbus_get_clock_controller(int phandle)
+{
+ struct fdtbus_clock_controller *cc;
+
+ for (cc = fdtbus_cc; cc; cc = cc->cc_next) {
+ if (cc->cc_phandle == phandle) {
+ return cc;
+ }
+ }
+
+ return NULL;
+}
+
+struct clk *
+fdtbus_clock_get_index(int phandle, u_int index)
+{
+ struct fdtbus_clock_controller *cc;
+ struct clk *clk = NULL;
+ uint32_t *clocks = NULL;
+ uint32_t *p;
+ u_int n, clock_cells;
+ int len, resid;
+
+ len = OF_getproplen(phandle, "clocks");
+ if (len <= 0)
+ return NULL;
+
+ clocks = kmem_alloc(len, KM_SLEEP);
+ if (OF_getprop(phandle, "clocks", clocks, len) != len) {
+ kmem_free(clocks, len);
+ return NULL;
+ }
+
+ p = clocks;
+ for (n = 0, resid = len; resid > 0; n++) {
+ const int cc_phandle =
+ fdtbus_get_phandle_from_native(be32toh(p[0]));
+ if (of_getprop_uint32(cc_phandle, "#clock-cells", &clock_cells))
+ break;
+ if (n == index) {
+ cc = fdtbus_get_clock_controller(cc_phandle);
+ if (cc == NULL)
+ goto done;
+ clk = cc->cc_funcs->decode(cc->cc_dev,
+ clock_cells > 0 ? &p[1] : NULL, clock_cells * 4);
+ break;
+ }
+ resid -= (clock_cells + 1) * 4;
+ p += clock_cells + 1;
+ }
+
+done:
+ if (clocks)
+ kmem_free(clocks, len);
+
+ return clk;
+}
+
+struct clk *
+fdtbus_clock_get(int phandle, const char *clkname)
+{
+ struct clk *clk = NULL;
+ char *clock_names = NULL;
+ const char *p;
+ u_int index;
+ int len, resid;
+
+ len = OF_getproplen(phandle, "clock-names");
+ if (len <= 0)
+ return NULL;
+
+ clock_names = kmem_alloc(len, KM_SLEEP);
+ if (OF_getprop(phandle, "clock-names", clock_names, len) != len) {
+ kmem_free(clock_names, len);
+ return NULL;
+ }
+
+ p = clock_names;
+ for (index = 0, resid = len; resid > 0; index++) {
+ if (strcmp(p, clkname) == 0) {
+ clk = fdtbus_clock_get_index(phandle, index);
+ break;
+ }
+ resid -= strlen(p);
+ p += strlen(p) + 1;
+ }
+
+ if (clock_names)
+ kmem_free(clock_names, len);
+
+ return clk;
+}
diff -r 115764e02b87 -r 0e9968575b28 sys/dev/fdt/fdt_reset.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/fdt/fdt_reset.c Tue Dec 22 21:42:11 2015 +0000
@@ -0,0 +1,189 @@
+/* $NetBSD: fdt_reset.c,v 1.1 2015/12/22 21:42:11 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 ``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 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: fdt_reset.c,v 1.1 2015/12/22 21:42:11 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kmem.h>
+
+#include <libfdt.h>
+#include <dev/fdt/fdtvar.h>
+
+struct fdtbus_reset_controller {
+ device_t rc_dev;
+ int rc_phandle;
+ const struct fdtbus_reset_controller_func *rc_funcs;
+
+ struct fdtbus_reset_controller *rc_next;
+};
+
+static struct fdtbus_reset_controller *fdtbus_rc = NULL;
+
+int
+fdtbus_register_reset_controller(device_t dev, int phandle,
+ const struct fdtbus_reset_controller_func *funcs)
+{
+ struct fdtbus_reset_controller *rc;
+
+ rc = kmem_alloc(sizeof(*rc), KM_SLEEP);
+ rc->rc_dev = dev;
+ rc->rc_phandle = phandle;
+ rc->rc_funcs = funcs;
+
+ rc->rc_next = fdtbus_rc;
+ fdtbus_rc = rc;
+
+ return 0;
+}
+
+static struct fdtbus_reset_controller *
+fdtbus_get_reset_controller(int phandle)
+{
+ struct fdtbus_reset_controller *rc;
+
+ for (rc = fdtbus_rc; rc; rc = rc->rc_next) {
+ if (rc->rc_phandle == phandle) {
+ return rc;
+ }
+ }
+
+ return NULL;
+}
+
+struct fdtbus_reset *
+fdtbus_reset_get_index(int phandle, u_int index)
+{
+ struct fdtbus_reset_controller *rc;
+ struct fdtbus_reset *rst = NULL;
+ void *rst_priv = NULL;
+ uint32_t *resets = NULL;
+ uint32_t *p;
+ u_int n, reset_cells;
+ int len, resid;
+
+ len = OF_getproplen(phandle, "resets");
+ if (len <= 0)
+ return NULL;
+
+ resets = kmem_alloc(len, KM_SLEEP);
+ if (OF_getprop(phandle, "resets", resets, len) != len) {
+ kmem_free(resets, len);
+ return NULL;
+ }
+
+ p = resets;
+ for (n = 0, resid = len; resid > 0; n++) {
+ const int rc_phandle =
+ fdtbus_get_phandle_from_native(be32toh(p[0]));
+ if (of_getprop_uint32(rc_phandle, "#reset-cells", &reset_cells))
+ break;
+ if (n == index) {
+ rc = fdtbus_get_reset_controller(rc_phandle);
+ if (rc == NULL)
+ goto done;
+ rst_priv = rc->rc_funcs->acquire(rc->rc_dev,
+ reset_cells > 0 ? &p[1] : NULL, reset_cells * 4);
+ if (rst_priv) {
+ rst = kmem_alloc(sizeof(*rst), KM_SLEEP);
+ rst->rst_rc = rc;
+ rst->rst_priv = rst_priv;
+ }
+ break;
+ }
+ resid -= (reset_cells + 1) * 4;
+ p += reset_cells + 1;
+ }
+
+done:
+ if (resets)
+ kmem_free(resets, len);
+
+ return rst;
+}
+
+struct fdtbus_reset *
+fdtbus_reset_get(int phandle, const char *rstname)
+{
+ struct fdtbus_reset *rst = NULL;
Home |
Main Index |
Thread Index |
Old Index