Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/fdt Fix the pinctrl api to match the spec. A pinctrl...



details:   https://anonhg.NetBSD.org/src/rev/6a65d12e24ac
branches:  trunk
changeset: 354872:6a65d12e24ac
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Jul 02 15:27:58 2017 +0000

description:
Fix the pinctrl api to match the spec. A pinctrl config can have more
than one xref, and an xref may have specifier data associated with it.

diffstat:

 sys/dev/fdt/fdt_pinctrl.c |  110 +++++++++++++++++++++++++++++----------------
 sys/dev/fdt/fdt_subr.c    |   12 ++++-
 sys/dev/fdt/fdtvar.h      |    8 ++-
 3 files changed, 86 insertions(+), 44 deletions(-)

diffs (246 lines):

diff -r 3307b9345efa -r 6a65d12e24ac sys/dev/fdt/fdt_pinctrl.c
--- a/sys/dev/fdt/fdt_pinctrl.c Sun Jul 02 15:09:53 2017 +0000
+++ b/sys/dev/fdt/fdt_pinctrl.c Sun Jul 02 15:27:58 2017 +0000
@@ -1,6 +1,7 @@
-/* $NetBSD: fdt_pinctrl.c,v 1.3 2016/10/11 13:04:57 maxv Exp $ */
+/* $NetBSD: fdt_pinctrl.c,v 1.4 2017/07/02 15:27:58 jmcneill Exp $ */
 
 /*-
+ * Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
  * Copyright (c) 2015 Martin Fouts
  * All rights reserved.
  *
@@ -27,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_pinctrl.c,v 1.3 2016/10/11 13:04:57 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_pinctrl.c,v 1.4 2017/07/02 15:27:58 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -37,8 +38,8 @@
 #include <dev/fdt/fdtvar.h>
 
 struct fdtbus_pinctrl_controller {
+       device_t pc_dev;
        int pc_phandle;
-       void *pc_cookie;
        const struct fdtbus_pinctrl_controller_func *pc_funcs;
 
        struct fdtbus_pinctrl_controller *pc_next;
@@ -47,13 +48,13 @@
 static struct fdtbus_pinctrl_controller *fdtbus_pc = NULL;
 
 int
-fdtbus_register_pinctrl_config(void *cookie, int phandle,
+fdtbus_register_pinctrl_config(device_t dev, int phandle,
     const struct fdtbus_pinctrl_controller_func *funcs)
 {
        struct fdtbus_pinctrl_controller *pc;
 
        pc = kmem_alloc(sizeof(*pc), KM_SLEEP);
-       pc->pc_cookie = cookie;
+       pc->pc_dev = dev;
        pc->pc_phandle = phandle;
        pc->pc_funcs = funcs;
 
@@ -78,57 +79,88 @@
 int
 fdtbus_pinctrl_set_config_index(int phandle, u_int index)
 {
-       char buf[80];
-       int len, handle;
        struct fdtbus_pinctrl_controller *pc;
+       const u_int *pinctrl_data;
+       char buf[16];
+       u_int xref, pinctrl_cells;
+       int len, error;
 
-       snprintf(buf, 80, "pinctrl-%d", index);
+       snprintf(buf, sizeof(buf), "pinctrl-%u", index);
+
+       pinctrl_data = fdtbus_get_prop(phandle, buf, &len);
+       if (pinctrl_data == NULL)
+               return ENOENT;
 
-       len = OF_getprop(phandle, buf, (char *)&handle,
-                        sizeof(handle));
-       if (len != sizeof(int)) {
-               printf("%s: couldn't get %s.\n", __func__, buf);
-               return -1;
-       }
+       while (len > 0) {
+               xref = fdtbus_get_phandle_from_native(be32toh(pinctrl_data[0]));
+               pc = fdtbus_pinctrl_lookup(xref);
+               if (pc == NULL)
+                       return ENXIO;
 
-       handle = fdtbus_get_phandle_from_native(be32toh(handle));
+               if (of_getprop_uint32(OF_parent(xref), "#pinctrl-cells", &pinctrl_cells) != 0)
+                       pinctrl_cells = 1;
 
-       pc = fdtbus_pinctrl_lookup(handle);
-       if (!pc) {
-               printf("%s: Couldn't get handle %d for %s\n", __func__, handle,
-                      buf);
-               return -1;
+               error = pc->pc_funcs->set_config(pc->pc_dev, pinctrl_data, pinctrl_cells * 4);
+               if (error != 0)
+                       return error;
+
+               pinctrl_data += pinctrl_cells;
+               len -= (pinctrl_cells * 4);
        }
 
-       return pc->pc_funcs->set_config(pc->pc_cookie);
+       return 0;
 }
 
 int
 fdtbus_pinctrl_set_config(int phandle, const char *cfgname)
 {
-       int index = 0;
-       int len;
-       char *result;
-       char *next;
+       const char *pinctrl_names, *name;
+       int len, index;
 
-       len = OF_getproplen(phandle, "pinctrl-names");
-       if (len <= 0)
+       if ((len = OF_getproplen(phandle, "pinctrl-names")) < 0)
                return -1;
-       result = kmem_zalloc(len, KM_SLEEP);
-       OF_getprop(phandle, "pinctrl-names", result, len);
 
-       next = result;
-       while (next - result < len) {
-               if (!strcmp(next, cfgname)) {
-                       kmem_free(result, len);
+       pinctrl_names = fdtbus_get_string(phandle, "pinctrl-names");
+
+       for (name = pinctrl_names, index = 0; len > 0;
+            name += strlen(name) + 1, index++) {
+               if (strcmp(name, cfgname) == 0)
                        return fdtbus_pinctrl_set_config_index(phandle, index);
-               }
-               index++;
-               while (*next)
-                       next++;
-               next++;
        }
 
-       kmem_free(result, len);
+       /* Not found */
        return -1;
 }
+
+static void
+fdtbus_pinctrl_configure_node(int phandle)
+{
+       char buf[256];
+       int child, error;
+
+       for (child = OF_child(phandle); child; child = OF_peer(child)) {
+               if (!fdtbus_status_okay(child))
+                       continue;
+
+               /* Configure child nodes */
+               fdtbus_pinctrl_configure_node(child);
+
+               /*
+                * Set configuration 0 for this node. This may fail if the
+                * pinctrl provider is missing; that's OK, we will re-configure
+                * when that provider attaches.
+                */
+               fdtbus_get_path(child, buf, sizeof(buf));
+               error = fdtbus_pinctrl_set_config_index(child, 0);
+               if (error == 0)
+                       aprint_debug("pinctrl: set config pinctrl-0 for %s\n", buf);
+               else if (error != ENOENT)
+                       aprint_debug("pinctrl: failed to set config pinctrl-0 for %s: %d\n", buf, error);
+       }
+}
+
+void
+fdtbus_pinctrl_configure(void)
+{
+       fdtbus_pinctrl_configure_node(OF_finddevice("/"));
+}
diff -r 3307b9345efa -r 6a65d12e24ac sys/dev/fdt/fdt_subr.c
--- a/sys/dev/fdt/fdt_subr.c    Sun Jul 02 15:09:53 2017 +0000
+++ b/sys/dev/fdt/fdt_subr.c    Sun Jul 02 15:27:58 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_subr.c,v 1.14 2017/06/30 09:11:22 jmcneill Exp $ */
+/* $NetBSD: fdt_subr.c,v 1.15 2017/07/02 15:27:58 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.14 2017/06/30 09:11:22 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.15 2017/07/02 15:27:58 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -407,6 +407,14 @@
        return strncmp(prop, "ok", 2) == 0;
 }
 
+const void *
+fdtbus_get_prop(int phandle, const char *prop, int *plen)
+{
+       const int off = fdtbus_phandle2offset(phandle);
+
+       return fdt_getprop(fdtbus_get_data(), off, prop, plen);
+}
+
 const char *
 fdtbus_get_string(int phandle, const char *prop)
 {
diff -r 3307b9345efa -r 6a65d12e24ac sys/dev/fdt/fdtvar.h
--- a/sys/dev/fdt/fdtvar.h      Sun Jul 02 15:09:53 2017 +0000
+++ b/sys/dev/fdt/fdtvar.h      Sun Jul 02 15:27:58 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fdtvar.h,v 1.22 2017/06/30 09:11:22 jmcneill Exp $ */
+/* $NetBSD: fdtvar.h,v 1.23 2017/07/02 15:27:58 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -85,7 +85,7 @@
 };
 
 struct fdtbus_pinctrl_controller_func {
-       int (*set_config)(void *);
+       int (*set_config)(device_t, const void *, size_t);
 };
 
 struct fdtbus_regulator_controller;
@@ -211,7 +211,7 @@
                    const struct fdtbus_i2c_controller_func *);
 int            fdtbus_register_gpio_controller(device_t, int,
                    const struct fdtbus_gpio_controller_func *);
-int            fdtbus_register_pinctrl_config(void *, int,
+int            fdtbus_register_pinctrl_config(device_t, int,
                    const struct fdtbus_pinctrl_controller_func *);
 int            fdtbus_register_regulator_controller(device_t, int,
                    const struct fdtbus_regulator_controller_func *);
@@ -241,6 +241,7 @@
 void           fdtbus_gpio_write(struct fdtbus_gpio_pin *, int);
 int            fdtbus_gpio_read_raw(struct fdtbus_gpio_pin *);
 void           fdtbus_gpio_write_raw(struct fdtbus_gpio_pin *, int);
+void           fdtbus_pinctrl_configure(void);
 int            fdtbus_pinctrl_set_config_index(int, u_int);
 int            fdtbus_pinctrl_set_config(int, const char *);
 struct fdtbus_regulator *fdtbus_regulator_acquire(int, const char *);
@@ -294,6 +295,7 @@
 
 bool           fdtbus_status_okay(int);
 
+const void *   fdtbus_get_prop(int, const char *, int *);
 const char *   fdtbus_get_string(int, const char *);
 
 int            fdtbus_print(void *, const char *);



Home | Main Index | Thread Index | Old Index