Index: dev/fdt/i2cmux_fdt.c =================================================================== RCS file: /cvsroot/src/sys/dev/fdt/i2cmux_fdt.c,v retrieving revision 1.10 retrieving revision 1.10.14.1 diff -u -p -r1.10 -r1.10.14.1 --- dev/fdt/i2cmux_fdt.c 27 Jan 2021 03:10:21 -0000 1.10 +++ dev/fdt/i2cmux_fdt.c 9 Aug 2021 00:30:09 -0000 1.10.14.1 @@ -1,4 +1,4 @@ -/* $NetBSD: i2cmux_fdt.c,v 1.10 2021/01/27 03:10:21 thorpej Exp $ */ +/* $NetBSD: i2cmux_fdt.c,v 1.10.14.1 2021/08/09 00:30:09 thorpej Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: i2cmux_fdt.c,v 1.10 2021/01/27 03:10:21 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: i2cmux_fdt.c,v 1.10.14.1 2021/08/09 00:30:09 thorpej Exp $"); #include #include @@ -59,11 +59,12 @@ static void * iicmux_gpio_get_mux_info(struct iicmux_softc * const sc) { struct mux_info_gpio *mux_data; + const int phandle = devhandle_to_of(device_handle(sc->sc_dev)); int i; mux_data = kmem_zalloc(sizeof(*mux_data), KM_SLEEP); - mux_data->npins = fdtbus_gpio_count(sc->sc_handle, "mux-gpios"); + mux_data->npins = fdtbus_gpio_count(phandle, "mux-gpios"); if (mux_data->npins == 0) { aprint_error_dev(sc->sc_dev, "unable to get mux-gpios property\n"); @@ -73,7 +74,7 @@ iicmux_gpio_get_mux_info(struct iicmux_s mux_data->pins = kmem_zalloc(sizeof(*mux_data->pins) * mux_data->npins, KM_SLEEP); for (i = 0; i < mux_data->npins; i++) { - mux_data->pins[i] = fdtbus_gpio_acquire_index(sc->sc_handle, + mux_data->pins[i] = fdtbus_gpio_acquire_index(phandle, "mux-gpios", i, GPIO_PIN_OUTPUT); if (mux_data->pins[i] == NULL) { aprint_error_dev(sc->sc_dev, @@ -83,7 +84,7 @@ iicmux_gpio_get_mux_info(struct iicmux_s } mux_data->has_idle_value = - of_getprop_uint32(sc->sc_handle, "idle-state", + of_getprop_uint32(phandle, "idle-state", &mux_data->idle_value) == 0; return mux_data; @@ -102,12 +103,13 @@ static void * iicmux_gpio_get_bus_info(struct iicmux_bus * const bus) { struct iicmux_softc * const sc = bus->mux; + const int phandle = devhandle_to_of(bus->devhandle); struct bus_info_gpio *bus_info; int error; bus_info = kmem_zalloc(sizeof(*bus_info), KM_SLEEP); - error = fdtbus_get_reg(bus->handle, 0, &bus_info->value, NULL); + error = fdtbus_get_reg(phandle, 0, &bus_info->value, NULL); if (error) { aprint_error_dev(sc->sc_dev, "unable to get reg property for bus %d\n", bus->busidx); @@ -172,12 +174,13 @@ struct bus_info_pinctrl { static void * iicmux_pinctrl_get_mux_info(struct iicmux_softc * const sc) { + const int phandle = devhandle_to_of(device_handle(sc->sc_dev)); struct mux_info_pinctrl *mux_info; mux_info = kmem_alloc(sizeof(*mux_info), KM_SLEEP); mux_info->has_idle_idx = - fdtbus_get_index(sc->sc_handle, "pinctrl-names", "idle", + fdtbus_get_index(phandle, "pinctrl-names", "idle", &mux_info->idle_idx) == 0; return mux_info; @@ -187,12 +190,13 @@ static void * iicmux_pinctrl_get_bus_info(struct iicmux_bus * const bus) { struct iicmux_softc * const sc = bus->mux; + const int phandle = devhandle_to_of(bus->devhandle); struct bus_info_pinctrl *bus_info; int error; bus_info = kmem_alloc(sizeof(*bus_info), KM_SLEEP); - error = fdtbus_get_reg(bus->handle, 0, &bus_info->idx, NULL); + error = fdtbus_get_reg(phandle, 0, &bus_info->idx, NULL); if (error) { aprint_error_dev(sc->sc_dev, "unable to get reg property for bus %d\n", bus->busidx); @@ -208,9 +212,10 @@ iicmux_pinctrl_acquire_bus(struct iicmux int const flags __unused) { struct iicmux_softc * const sc = bus->mux; + const int phandle = devhandle_to_of(device_handle(sc->sc_dev)); struct bus_info_pinctrl * const bus_info = bus->bus_data; - return fdtbus_pinctrl_set_config_index(sc->sc_handle, bus_info->idx); + return fdtbus_pinctrl_set_config_index(phandle, bus_info->idx); } static void @@ -218,10 +223,11 @@ iicmux_pinctrl_release_bus(struct iicmux int const flags __unused) { struct iicmux_softc * const sc = bus->mux; + const int phandle = devhandle_to_of(device_handle(sc->sc_dev)); struct mux_info_pinctrl * const mux_info = sc->sc_mux_data; if (mux_info->has_idle_idx) { - (void) fdtbus_pinctrl_set_config_index(sc->sc_handle, + (void) fdtbus_pinctrl_set_config_index(phandle, mux_info->idle_idx); } } @@ -261,13 +267,13 @@ iicmux_fdt_attach(device_t const parent, struct fdt_attach_args * const faa = aux; sc->sc_dev = self; - sc->sc_handle = faa->faa_phandle; - sc->sc_config = of_compatible_lookup(sc->sc_handle, compat_data)->data; + sc->sc_config = + of_compatible_lookup(faa->faa_phandle, compat_data)->data; aprint_naive("\n"); aprint_normal(": %s I2C mux\n", sc->sc_config->desc); - sc->sc_i2c_parent = fdtbus_i2c_acquire(sc->sc_handle, "i2c-parent"); + sc->sc_i2c_parent = fdtbus_i2c_acquire(faa->faa_phandle, "i2c-parent"); if (sc->sc_i2c_parent == NULL) { aprint_error_dev(sc->sc_dev, "unable to acquire i2c-parent\n"); return; Index: dev/i2c/i2cmux.c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/i2cmux.c,v retrieving revision 1.6 retrieving revision 1.6.2.2 diff -u -p -r1.6 -r1.6.2.2 --- dev/i2c/i2cmux.c 7 Aug 2021 16:19:11 -0000 1.6 +++ dev/i2c/i2cmux.c 9 Aug 2021 00:57:56 -0000 1.6.2.2 @@ -1,4 +1,4 @@ -/* $NetBSD: i2cmux.c,v 1.6 2021/08/07 16:19:11 thorpej Exp $ */ +/* $NetBSD: i2cmux.c,v 1.6.2.2 2021/08/09 00:57:56 thorpej Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -29,26 +29,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) -#include "acpica.h" -#endif - #include -__KERNEL_RCSID(0, "$NetBSD: i2cmux.c,v 1.6 2021/08/07 16:19:11 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: i2cmux.c,v 1.6.2.2 2021/08/09 00:57:56 thorpej Exp $"); #include #include #include #include -#include #include #include -#if NACPICA > 0 -#include -#include -#endif +#include "locators.h" /* * i2c mux @@ -120,57 +112,15 @@ iicmux_exec(void * const v, i2c_op_t con /*****************************************************************************/ -static int -iicmux_count_children(struct iicmux_softc * const sc) -{ - char name[32]; - int child, count; - - restart: - for (child = OF_child(sc->sc_i2c_mux_phandle), count = 0; child; - child = OF_peer(child)) { - if (OF_getprop(child, "name", name, sizeof(name)) <= 0) { - continue; - } - if (strcmp(name, "i2c-mux") == 0) { - /* - * The node we encountered is the acutal parent - * of the i2c bus children. Stash its phandle - * and restart the enumeration. - */ - sc->sc_i2c_mux_phandle = child; - goto restart; - } - count++; - } - - return count; -} - -/* XXX iicbus_print() should be able to do this. */ -static int -iicmux_print(void * const aux, const char * const pnp) -{ - i2c_tag_t const tag = aux; - struct iicmux_bus * const bus = tag->ic_cookie; - int rv; - - rv = iicbus_print(aux, pnp); - aprint_normal(" bus %d", bus->busidx); - - return rv; -} - static void -iicmux_attach_bus(struct iicmux_softc * const sc, - uintptr_t const handle, enum i2c_cookie_type handletype, int const busidx) +iicmux_attach_bus(struct iicmux_softc * const sc, devhandle_t devhandle, + int const busidx) { struct iicmux_bus * const bus = &sc->sc_busses[busidx]; bus->mux = sc; bus->busidx = busidx; - bus->handle = handle; - bus->handletype = handletype; + bus->devhandle = devhandle; bus->bus_data = sc->sc_config->get_bus_info(bus); if (bus->bus_data == NULL) { @@ -181,108 +131,83 @@ iicmux_attach_bus(struct iicmux_softc * iic_tag_init(&bus->controller); bus->controller.ic_cookie = bus; + bus->controller.ic_channel = bus->busidx; bus->controller.ic_acquire_bus = iicmux_acquire_bus; bus->controller.ic_release_bus = iicmux_release_bus; bus->controller.ic_exec = iicmux_exec; - switch (handletype) { - case I2C_COOKIE_OF: +#if defined(I2CMUX_USE_FDT) + if (devhandle_type(devhandle) == DEVHANDLE_TYPE_OF) { fdtbus_register_i2c_controller(&bus->controller, - (int)bus->handle); - - fdtbus_attach_i2cbus(sc->sc_dev, (int)bus->handle, - &bus->controller, iicmux_print); - break; -#if NACPICA > 0 - case I2C_COOKIE_ACPI: { - struct acpi_devnode *ad = acpi_match_node((ACPI_HANDLE)handle); - KASSERT(ad != NULL); - struct i2cbus_attach_args iba = { - .iba_tag = &bus->controller, - .iba_child_devices = acpi_enter_i2c_devs(NULL, ad) - }; - config_found(sc->sc_dev, &iba, iicbus_print, CFARGS_NONE); - } break; -#endif - default: - aprint_error_dev(sc->sc_dev, "unknown handle type\n"); - break; + devhandle_to_of(devhandle)); } +#endif /* I2CMUX_USE_FDT */ + + struct i2cbus_attach_args iba = { + .iba_tag = &bus->controller, + }; + + int locs[I2CBUSCF_NLOCS]; + locs[I2CBUSCF_BUS] = bus->busidx; + + config_found(sc->sc_dev, &iba, iicbus_print_multi, + CFARGS(.submatch = config_stdsubmatch, + .locators = locs, + .devhandle = devhandle)); } -static void -iicmux_attach_fdt(struct iicmux_softc * const sc) +static bool +iicmux_count_busses_callback(device_t self, devhandle_t devhandle, + void *v __unused) { - /* - * We start out assuming that the i2c bus nodes are children of - * our own node. We'll adjust later if we encounter an "i2c-mux" - * node when counting our children. If we encounter such a node, - * then it's that node that is the parent of the i2c bus children. - */ - sc->sc_i2c_mux_phandle = (int)sc->sc_handle; + struct iicmux_softc *sc = device_private(self); - sc->sc_nbusses = iicmux_count_children(sc); - if (sc->sc_nbusses == 0) { - return; +#if defined(I2CMUX_USE_FDT) + if (devhandle_type(devhandle) == DEVHANDLE_TYPE_OF) { + char name[32]; + + if (OF_getprop(devhandle_to_of(devhandle), "name", name, + sizeof(name)) <= 0) { + /* Skip this DT node (shouldn't happen). */ + return true; /* keep enumerating */ + } + if (strcmp(name, "i2c-mux") == 0) { + /* + * This DT node is the actual mux node; reset the + * our devhandle and restart enumeration. + */ + device_set_handle(self, devhandle); + sc->sc_nbusses = -1; + return false; /* stop enumerating */ + } } +#endif /* I2CMUX_USE_FDT */ - sc->sc_busses = kmem_zalloc(sizeof(*sc->sc_busses) * sc->sc_nbusses, - KM_SLEEP); - - int child, idx; - for (child = OF_child(sc->sc_i2c_mux_phandle), idx = 0; child; - child = OF_peer(child), idx++) { - KASSERT(idx < sc->sc_nbusses); - iicmux_attach_bus(sc, child, I2C_COOKIE_OF, idx); - } + sc->sc_nbusses++; + return true; /* keep enumerating */ } -#if NACPICA > 0 -static void -iicmux_attach_acpi(struct iicmux_softc * const sc) +static bool +iicmux_attach_busses_callback(device_t self, devhandle_t devhandle, void *v) { - ACPI_HANDLE hdl = (ACPI_HANDLE)sc->sc_handle; - struct acpi_devnode *devnode, *ad; - int idx; - - devnode = acpi_match_node(hdl); - KASSERT(devnode != NULL); - - /* Count child busses */ - sc->sc_nbusses = 0; - SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { - if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || - !acpi_device_present(ad->ad_handle)) { - continue; - } - sc->sc_nbusses++; - } + struct iicmux_softc *sc = device_private(self); + int * const idxp = v; - sc->sc_busses = kmem_zalloc(sizeof(*sc->sc_busses) * sc->sc_nbusses, - KM_SLEEP); + KASSERT(*idxp < sc->sc_nbusses); + iicmux_attach_bus(sc, devhandle, (*idxp)++); - /* Attach child busses */ - idx = 0; - SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { - if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || - !acpi_device_present(ad->ad_handle)) { - continue; - } - iicmux_attach_bus(sc, (uintptr_t)ad->ad_handle, - I2C_COOKIE_ACPI, idx); - idx++; - } + return true; /* keep enumerating */ } -#endif void iicmux_attach(struct iicmux_softc * const sc) { + int error, idx; + /* - * We expect sc->sc_handle, sc->sc_config, and sc->sc_i2c_parent - * to be initialized by the front-end. + * We expect sc->sc_config and sc->sc_i2c_parent to be initialized + * by the front-end. */ - KASSERT(sc->sc_handle > 0); KASSERT(sc->sc_config != NULL); KASSERT(sc->sc_i2c_parent != NULL); @@ -297,20 +222,39 @@ iicmux_attach(struct iicmux_softc * cons } /* - * Do configuration method (OF, ACPI) specific setup. + * Count the number of busses behind this mux. */ - switch (sc->sc_handletype) { - case I2C_COOKIE_OF: - iicmux_attach_fdt(sc); - break; -#if NACPICA > 0 - case I2C_COOKIE_ACPI: - iicmux_attach_acpi(sc); - break; -#endif - default: - aprint_error_dev(sc->sc_dev, "could not configure mux: " - "handle type %u not supported\n", sc->sc_handletype); - break; + count_again: + error = device_enumerate_children(sc->sc_dev, + iicmux_count_busses_callback, NULL); + if (error) { + aprint_error_dev(sc->sc_dev, + "unable to enumerate busses to count, error = %d\n", error); + return; + } + if (sc->sc_nbusses == -1) { + /* + * We had to reset our devhandle to a different device + * tree node. We need to try counting again. + */ + sc->sc_nbusses = 0; + goto count_again; + } + if (sc->sc_nbusses == 0) { + /* No busses; no more work to do. */ + return; + } + + sc->sc_busses = kmem_zalloc(sizeof(*sc->sc_busses) * sc->sc_nbusses, + KM_SLEEP); + + /* Now attach them. */ + idx = 0; + error = device_enumerate_children(sc->sc_dev, + iicmux_attach_busses_callback, &idx); + if (error) { + aprint_error_dev(sc->sc_dev, + "unable to enumerate busses to attach, error = %d\n", + error); } } Index: dev/i2c/i2cmuxvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/i2cmuxvar.h,v retrieving revision 1.3 retrieving revision 1.3.14.1 diff -u -p -r1.3 -r1.3.14.1 --- dev/i2c/i2cmuxvar.h 25 Jan 2021 12:18:18 -0000 1.3 +++ dev/i2c/i2cmuxvar.h 9 Aug 2021 00:30:09 -0000 1.3.14.1 @@ -1,4 +1,4 @@ -/* $NetBSD: i2cmuxvar.h,v 1.3 2021/01/25 12:18:18 jmcneill Exp $ */ +/* $NetBSD: i2cmuxvar.h,v 1.3.14.1 2021/08/09 00:30:09 thorpej Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -34,6 +34,52 @@ #include +/* XXX This is not ideal, but... XXX */ + +#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) + +#ifdef _KERNEL_OPT +#include "acpica.h" + +#if NACPICA > 0 +#define I2CMUX_USE_ACPI +#endif + +#else /* ! _KERNEL_OPT */ + +#define I2CMUX_USE_ACPI + +#endif /* _KERNEL_OPT */ + +#endif /* __i386__ || __amd64__ || __aarch64__ */ + +#if defined(__arm__) || defined(__aarch64__) + +#ifdef _KERNEL_OPT +#include "opt_fdt.h" + +#if defined(FDT) +#define I2CMUX_USE_FDT +#endif + +#else /* _KERNEL_OPT */ + +#define I2CMUX_USE_FDT + +#endif /* _KERNEL_OPT */ + +#endif /* __arm__ || __aarch64__ */ + +/* XXX ^^^ XXX */ + +#if defined(I2CMUX_USE_ACPI) +#include +#endif + +#if defined(I2CMUX_USE_FDT) +#include +#endif + struct iicmux_softc; struct iicmux_bus; @@ -48,17 +94,13 @@ struct iicmux_config { struct iicmux_bus { struct i2c_controller controller; struct iicmux_softc *mux; - uintptr_t handle; - enum i2c_cookie_type handletype; + devhandle_t devhandle; int busidx; void *bus_data; }; struct iicmux_softc { device_t sc_dev; - enum i2c_cookie_type sc_handletype; - uintptr_t sc_handle; - int sc_i2c_mux_phandle; const struct iicmux_config * sc_config; i2c_tag_t sc_i2c_parent; struct iicmux_bus * sc_busses; Index: dev/i2c/pcai2cmux.c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/pcai2cmux.c,v retrieving revision 1.8 retrieving revision 1.8.14.1 diff -u -p -r1.8 -r1.8.14.1 --- dev/i2c/pcai2cmux.c 27 Jan 2021 02:29:48 -0000 1.8 +++ dev/i2c/pcai2cmux.c 9 Aug 2021 00:30:09 -0000 1.8.14.1 @@ -1,4 +1,4 @@ -/* $NetBSD: pcai2cmux.c,v 1.8 2021/01/27 02:29:48 thorpej Exp $ */ +/* $NetBSD: pcai2cmux.c,v 1.8.14.1 2021/08/09 00:30:09 thorpej Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -29,12 +29,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) -#include "acpica.h" -#endif - #include -__KERNEL_RCSID(0, "$NetBSD: pcai2cmux.c,v 1.8 2021/01/27 02:29:48 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pcai2cmux.c,v 1.8.14.1 2021/08/09 00:30:09 thorpej Exp $"); /* * Driver for NXP PCA954x / PCA984x I2C switches and multiplexers. @@ -60,13 +56,8 @@ __KERNEL_RCSID(0, "$NetBSD: pcai2cmux.c, #include #include -#include #include -#if NACPICA > 0 -#include -#endif - /* There are a maximum of 8 busses supported. */ #define PCAIICMUX_MAX_BUSSES 8 @@ -166,7 +157,9 @@ struct pcaiicmux_softc { int sc_cur_value; const struct pcaiicmux_type *sc_type; +#if defined(I2CMUX_USE_FDT) struct fdtbus_gpio_pin *sc_reset_gpio; +#endif /* I2CMUX_USE_FDT */ bool sc_idle_disconnect; @@ -207,6 +200,7 @@ pcaiicmux_get_bus_info(struct iicmux_bus { struct iicmux_softc * const iicmux = bus->mux; struct pcaiicmux_softc * const sc = iicmux->sc_mux_data; + devhandle_t devhandle = bus->devhandle; bus_addr_t addr; int error; @@ -220,9 +214,11 @@ pcaiicmux_get_bus_info(struct iicmux_bus struct pcaiicmux_bus_info * const bus_info = &sc->sc_bus_info[bus->busidx]; - switch (bus->handletype) { - case I2C_COOKIE_OF: - error = fdtbus_get_reg(bus->handle, 0, &addr, NULL); + switch (devhandle_type(devhandle)) { +#if defined(I2CMUX_USE_FDT) + case DEVHANDLE_TYPE_OF: + error = fdtbus_get_reg(devhandle_to_of(devhandle), + 0, &addr, NULL); if (error) { aprint_error_dev(iicmux->sc_dev, "unable to get reg property for bus %d\n", @@ -230,11 +226,14 @@ pcaiicmux_get_bus_info(struct iicmux_bus return NULL; } break; -#if NACPICA > 0 - case I2C_COOKIE_ACPI: { +#endif /* I2CMUX_USE_FDT */ + +#if defined(I2CMUX_USE_ACPI) + case DEVHANDLE_TYPE_ACPI: { ACPI_INTEGER val; ACPI_STATUS rv; - rv = acpi_eval_integer((ACPI_HANDLE)bus->handle, "_ADR", &val); + rv = acpi_eval_integer(devhandle_to_acpi(devhandle), + "_ADR", &val); if (ACPI_FAILURE(rv)) { aprint_error_dev(iicmux->sc_dev, "unable to evaluate _ADR for bus %d: %s\n", @@ -243,7 +242,8 @@ pcaiicmux_get_bus_info(struct iicmux_bus } addr = (bus_addr_t)val; } break; -#endif +#endif /* I2CMUX_USE_ACPI */ + default: aprint_error_dev(iicmux->sc_dev, "unsupported handle type\n"); return NULL; @@ -337,8 +337,6 @@ pcaiicmux_attach(device_t parent, device int error; sc->sc_iicmux.sc_dev = self; - sc->sc_iicmux.sc_handle = ia->ia_cookie; - sc->sc_iicmux.sc_handletype = ia->ia_cookietype; sc->sc_iicmux.sc_config = &pcaiicmux_config; sc->sc_iicmux.sc_i2c_parent = ia->ia_tag; sc->sc_addr = ia->ia_addr; @@ -350,8 +348,10 @@ pcaiicmux_attach(device_t parent, device aprint_normal(": PCA954x I2C %s\n", sc->sc_type->enable_bit ? "mux" : "switch"); - if (ia->ia_cookietype == I2C_COOKIE_OF) { - const int phandle = (int)ia->ia_cookie; +#if defined(I2CMUX_USE_FDT) + devhandle_t devhandle = device_handle(self); + if (devhandle_type(devhandle) == DEVHANDLE_TYPE_OF) { + const int phandle = devhandle_to_of(devhandle); if (of_hasprop(phandle, "i2c-mux-idle-disconnect")) { sc->sc_idle_disconnect = true; } @@ -366,6 +366,7 @@ pcaiicmux_attach(device_t parent, device delay(10); } } +#endif /* I2CMUX_USE_FDT */ /* Force the mux into a disconnected state. */ sc->sc_cur_value = -1;