Module Name: src Committed By: jmcneill Date: Sun Jul 2 15:27:58 UTC 2017
Modified Files: src/sys/dev/fdt: fdt_pinctrl.c fdt_subr.c fdtvar.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/dev/fdt/fdt_pinctrl.c cvs rdiff -u -r1.14 -r1.15 src/sys/dev/fdt/fdt_subr.c cvs rdiff -u -r1.22 -r1.23 src/sys/dev/fdt/fdtvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/fdt/fdt_pinctrl.c diff -u src/sys/dev/fdt/fdt_pinctrl.c:1.3 src/sys/dev/fdt/fdt_pinctrl.c:1.4 --- src/sys/dev/fdt/fdt_pinctrl.c:1.3 Tue Oct 11 13:04:57 2016 +++ src/sys/dev/fdt/fdt_pinctrl.c Sun Jul 2 15:27:58 2017 @@ -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 <jmcne...@invisible.ca> * 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 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_pinctrl. #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 @@ struct fdtbus_pinctrl_controller { 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 @@ fdtbus_pinctrl_lookup(int phandle) 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, sizeof(buf), "pinctrl-%u", index); + + pinctrl_data = fdtbus_get_prop(phandle, buf, &len); + if (pinctrl_data == NULL) + return ENOENT; + + while (len > 0) { + xref = fdtbus_get_phandle_from_native(be32toh(pinctrl_data[0])); + pc = fdtbus_pinctrl_lookup(xref); + if (pc == NULL) + return ENXIO; + + if (of_getprop_uint32(OF_parent(xref), "#pinctrl-cells", &pinctrl_cells) != 0) + pinctrl_cells = 1; + + error = pc->pc_funcs->set_config(pc->pc_dev, pinctrl_data, pinctrl_cells * 4); + if (error != 0) + return error; - snprintf(buf, 80, "pinctrl-%d", index); - - len = OF_getprop(phandle, buf, (char *)&handle, - sizeof(handle)); - if (len != sizeof(int)) { - printf("%s: couldn't get %s.\n", __func__, buf); - return -1; - } - - handle = fdtbus_get_phandle_from_native(be32toh(handle)); - - pc = fdtbus_pinctrl_lookup(handle); - if (!pc) { - printf("%s: Couldn't get handle %d for %s\n", __func__, handle, - buf); - return -1; + 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("/")); +} Index: src/sys/dev/fdt/fdt_subr.c diff -u src/sys/dev/fdt/fdt_subr.c:1.14 src/sys/dev/fdt/fdt_subr.c:1.15 --- src/sys/dev/fdt/fdt_subr.c:1.14 Fri Jun 30 09:11:22 2017 +++ src/sys/dev/fdt/fdt_subr.c Sun Jul 2 15:27:58 2017 @@ -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 <jmcne...@invisible.ca> @@ -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 @@ fdtbus_status_okay(int phandle) 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) { Index: src/sys/dev/fdt/fdtvar.h diff -u src/sys/dev/fdt/fdtvar.h:1.22 src/sys/dev/fdt/fdtvar.h:1.23 --- src/sys/dev/fdt/fdtvar.h:1.22 Fri Jun 30 09:11:22 2017 +++ src/sys/dev/fdt/fdtvar.h Sun Jul 2 15:27:58 2017 @@ -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 <jmcne...@invisible.ca> @@ -85,7 +85,7 @@ struct fdtbus_pinctrl_pin { }; 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 @@ int fdtbus_register_i2c_controller(devi 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 @@ int fdtbus_gpio_read(struct fdtbus_gpio 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 @@ tcflag_t fdtbus_get_stdout_flags(void); 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 *);