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 <[email protected]>
* 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 <[email protected]>
@@ -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 <[email protected]>
@@ -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 *);