Module Name: src Committed By: thorpej Date: Tue May 18 23:48:16 UTC 2021
Modified Files: src/sys/dev/fdt [thorpej-i2c-spi-conf]: fdt_spi.c src/sys/dev/ofw [thorpej-i2c-spi-conf]: ofw_spi_subr.c src/sys/dev/spi [thorpej-i2c-spi-conf]: spi.c spivar.h Log Message: Define a "spi-enumerate-devices" device call and use it for direct configuration of SPI devices, rather than slinging arrays of dictionaries around. Implement this device call for OpenFirmware / FDT, following the SPI bindings for Device Tree. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.2.2.1 src/sys/dev/fdt/fdt_spi.c cvs rdiff -u -r1.1 -r1.1.6.1 src/sys/dev/ofw/ofw_spi_subr.c cvs rdiff -u -r1.17 -r1.17.2.1 src/sys/dev/spi/spi.c cvs rdiff -u -r1.10 -r1.10.6.1 src/sys/dev/spi/spivar.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_spi.c diff -u src/sys/dev/fdt/fdt_spi.c:1.2 src/sys/dev/fdt/fdt_spi.c:1.2.2.1 --- src/sys/dev/fdt/fdt_spi.c:1.2 Sat Apr 24 23:36:53 2021 +++ src/sys/dev/fdt/fdt_spi.c Tue May 18 23:48:16 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_spi.c,v 1.2 2021/04/24 23:36:53 thorpej Exp $ */ +/* $NetBSD: fdt_spi.c,v 1.2.2.1 2021/05/18 23:48:16 thorpej Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fdt_spi.c,v 1.2 2021/04/24 23:36:53 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdt_spi.c,v 1.2.2.1 2021/05/18 23:48:16 thorpej Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -84,33 +84,17 @@ device_t fdtbus_attach_spibus(device_t dev, int phandle, cfprint_t print) { struct spi_controller *spi; - struct spibus_attach_args sba; - prop_dictionary_t devs; - device_t ret; - u_int address_cells; - - devs = prop_dictionary_create(); - if (of_getprop_uint32(phandle, "#address-cells", &address_cells)) - address_cells = 1; - of_enter_spi_devs(devs, phandle, address_cells * 4); spi = fdtbus_get_spi_controller(phandle); KASSERT(spi != NULL); - memset(&sba, 0, sizeof(sba)); - sba.sba_controller = spi; - sba.sba_child_devices = prop_dictionary_get(devs, "spi-child-devices"); - if (sba.sba_child_devices) - prop_object_retain(sba.sba_child_devices); - prop_object_release(devs); - - ret = config_found(dev, &sba, print, + struct spibus_attach_args sba = { + .sba_controller = spi, + }; + return config_found(dev, &sba, print, CFARG_IATTR, "spibus", + CFARG_DEVHANDLE, device_handle(dev), CFARG_EOL); - if (sba.sba_child_devices) - prop_object_release(sba.sba_child_devices); - - return ret; } Index: src/sys/dev/ofw/ofw_spi_subr.c diff -u src/sys/dev/ofw/ofw_spi_subr.c:1.1 src/sys/dev/ofw/ofw_spi_subr.c:1.1.6.1 --- src/sys/dev/ofw/ofw_spi_subr.c:1.1 Thu Feb 4 20:19:09 2021 +++ src/sys/dev/ofw/ofw_spi_subr.c Tue May 18 23:48:16 2021 @@ -1,100 +1,96 @@ -/* $NetBSD: ofw_spi_subr.c,v 1.1 2021/02/04 20:19:09 thorpej Exp $ */ +/* $NetBSD: ofw_spi_subr.c,v 1.1.6.1 2021/05/18 23:48:16 thorpej Exp $ */ /* - * Copyright 1998 - * Digital Equipment Corporation. All rights reserved. + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * All rights reserved. * - * This software is furnished under license and may be used and - * copied only in accordance with the following terms and conditions. - * Subject to these conditions, you may download, copy, install, - * use, modify and distribute this software in source and/or binary - * form. No title or ownership is transferred hereby. + * 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. * - * 1) Any source code used, modified or distributed must reproduce - * and retain this copyright notice and list of conditions as - * they appear in the source file. - * - * 2) No right is granted to use any trade name, trademark, or logo of - * Digital Equipment Corporation. Neither the "Digital Equipment - * Corporation" name nor any trademark or logo of Digital Equipment - * Corporation may be used to endorse or promote products derived - * from this software without the prior written permission of - * Digital Equipment Corporation. - * - * 3) This software is provided "AS-IS" and any express or implied - * warranties, including but not limited to, any implied warranties - * of merchantability, fitness for a particular purpose, or - * non-infringement are disclaimed. In no event shall DIGITAL be - * liable for any damages whatsoever, and in particular, DIGITAL - * shall not be liable for special, indirect, consequential, or - * incidental damages or damages for lost profits, loss of - * revenue or loss of use, whether such damages arise in contract, - * negligence, tort, under statute, in equity, at law or otherwise, - * even if advised of the possibility of such damage. + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION OR CONTRIBUTORS + * 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: ofw_spi_subr.c,v 1.1 2021/02/04 20:19:09 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ofw_spi_subr.c,v 1.1.6.1 2021/05/18 23:48:16 thorpej Exp $"); #include <sys/param.h> #include <sys/device.h> #include <sys/kmem.h> #include <sys/systm.h> #include <dev/ofw/openfirm.h> +#include <dev/spi/spivar.h> -void -of_enter_spi_devs(prop_dictionary_t props, int ofnode, size_t cell_size) +static int +of_spi_enumerate_devices(device_t dev, devhandle_t call_handle, void *v) { - int node, len; - char name[32]; - uint64_t reg64; - uint32_t reg32; - uint32_t slave; - u_int32_t maxfreq; - prop_array_t array = NULL; - prop_dictionary_t dev; - int mode; + struct spi_enumerate_devices_args *args = v; + int spi_node, node; + char name[32], compat_buf[32]; + uint32_t chip_select; + char *clist; + int clist_size; + bool cbrv; + + spi_node = devhandle_to_of(call_handle); - for (node = OF_child(ofnode); node; node = OF_peer(node)) { - if (OF_getprop(node, "name", name, sizeof(name)) <= 0) + for (node = OF_child(spi_node); node != 0; node = OF_peer(node)) { + if (OF_getprop(node, "name", name, sizeof(name)) <= 0) { continue; - len = OF_getproplen(node, "reg"); - slave = 0; - if (cell_size == 8 && len >= sizeof(reg64)) { - if (OF_getprop(node, "reg", ®64, sizeof(reg64)) - < sizeof(reg64)) - continue; - slave = be64toh(reg64); - } else if (cell_size == 4 && len >= sizeof(reg32)) { - if (OF_getprop(node, "reg", ®32, sizeof(reg32)) - < sizeof(reg32)) - continue; - slave = be32toh(reg32); - } else { + } + + if (of_getprop_uint32(node, "reg", &chip_select) != 0) { continue; } - if (of_getprop_uint32(node, "spi-max-frequency", &maxfreq)) { - maxfreq = 0; + + /* Device Tree bindings specify a max chip select of 256. */ + if (chip_select > 256) { + continue; } - mode = ((int)of_hasprop(node, "cpol") << 1) | (int)of_hasprop(node, "cpha"); - if (array == NULL) - array = prop_array_create(); + clist_size = OF_getproplen(node, "compatible"); + if (clist_size <= 0) { + continue; + } - dev = prop_dictionary_create(); - prop_dictionary_set_string(dev, "name", name); - prop_dictionary_set_uint32(dev, "slave", slave); - prop_dictionary_set_uint32(dev, "mode", mode); - if (maxfreq > 0) - prop_dictionary_set_uint32(dev, "spi-max-frequency", maxfreq); - prop_dictionary_set_uint64(dev, "cookie", node); - of_to_dataprop(dev, node, "compatible", "compatible"); - prop_array_add(array, dev); - prop_object_release(dev); - } + clist = kmem_tmpbuf_alloc(clist_size, + compat_buf, sizeof(compat_buf), KM_SLEEP); + if (OF_getprop(node, "compatible", clist, clist_size) < + clist_size) { + kmem_tmpbuf_free(clist, clist_size, compat_buf); + continue; + } + + args->chip_select = (int)chip_select; + args->sa->sa_name = name; + args->sa->sa_clist = clist; + args->sa->sa_clist_size = clist_size; + args->sa->sa_devhandle = devhandle_from_of(node); - if (array != NULL) { - prop_dictionary_set(props, "spi-child-devices", array); - prop_object_release(array); + cbrv = args->callback(dev, args); + + kmem_tmpbuf_free(clist, clist_size, compat_buf); + + if (!cbrv) { + break; + } } + + return 0; } +OF_DEVICE_CALL_REGISTER("spi-enumerate-devices", of_spi_enumerate_devices); Index: src/sys/dev/spi/spi.c diff -u src/sys/dev/spi/spi.c:1.17 src/sys/dev/spi/spi.c:1.17.2.1 --- src/sys/dev/spi/spi.c:1.17 Sat Apr 24 23:36:59 2021 +++ src/sys/dev/spi/spi.c Tue May 18 23:48:16 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: spi.c,v 1.17 2021/04/24 23:36:59 thorpej Exp $ */ +/* $NetBSD: spi.c,v 1.17.2.1 2021/05/18 23:48:16 thorpej Exp $ */ /*- * Copyright (c) 2006 Urbana-Champaign Independent Media Center. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.17 2021/04/24 23:36:59 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.17.2.1 2021/05/18 23:48:16 thorpej Exp $"); #include "locators.h" @@ -50,7 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.17 #include <sys/systm.h> #include <sys/device.h> #include <sys/conf.h> -#include <sys/malloc.h> +#include <sys/kmem.h> #include <sys/mutex.h> #include <sys/condvar.h> #include <sys/errno.h> @@ -62,12 +62,14 @@ __KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.17 #include "locators.h" struct spi_softc { + device_t sc_dev; struct spi_controller sc_controller; int sc_mode; int sc_speed; int sc_slave; int sc_nslaves; struct spi_handle *sc_slaves; + kmutex_t sc_slave_state_lock; kmutex_t sc_lock; kcondvar_t sc_cv; int sc_flags; @@ -97,13 +99,14 @@ const struct cdevsw spi_cdevsw = { * SPI slave device. We have one of these per slave. */ struct spi_handle { - struct spi_softc *sh_sc; - struct spi_controller *sh_controller; - int sh_slave; - int sh_mode; - int sh_speed; - int sh_flags; -#define SPIH_ATTACHED 1 + struct spi_softc *sh_sc; /* static */ + struct spi_controller *sh_controller; /* static */ + int sh_slave; /* static */ + int sh_mode; /* locked by owning child */ + int sh_speed; /* locked by owning child */ + int sh_flags; /* ^^ slave_state_lock ^^ */ +#define SPIH_ATTACHED __BIT(0) +#define SPIH_DIRECT __BIT(1) }; #define SPI_MAXDATA 4096 @@ -131,152 +134,143 @@ spi_match(device_t parent, cfdata_t cf, } static int -spi_print(void *aux, const char *pnp) +spi_print_direct(void *aux, const char *pnp) { struct spi_attach_args *sa = aux; - if (sa->sa_handle->sh_slave != -1) + if (pnp != NULL) { + aprint_normal("%s%s%s%s at %s slave %d", + sa->sa_name ? sa->sa_name : "(unknown)", + sa->sa_clist ? " (" : "", + sa->sa_clist ? sa->sa_clist : "", + sa->sa_clist ? ")" : "", + pnp, sa->sa_handle->sh_slave); + } else { aprint_normal(" slave %d", sa->sa_handle->sh_slave); + } - return (UNCONF); + return UNCONF; } static int -spi_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) +spi_print(void *aux, const char *pnp) { - struct spi_softc *sc = device_private(parent); - struct spi_attach_args sa; - int addr; - - addr = cf->cf_loc[SPICF_SLAVE]; - if ((addr < 0) || (addr >= sc->sc_controller.sct_nslaves)) { - return -1; - } - - memset(&sa, 0, sizeof sa); - sa.sa_handle = &sc->sc_slaves[addr]; - if (ISSET(sa.sa_handle->sh_flags, SPIH_ATTACHED)) - return -1; + struct spi_attach_args *sa = aux; - if (config_probe(parent, cf, &sa)) { - SET(sa.sa_handle->sh_flags, SPIH_ATTACHED); - config_attach(parent, cf, &sa, spi_print, CFARG_EOL); - } + aprint_normal(" slave %d", sa->sa_handle->sh_slave); - return 0; + return UNCONF; } /* - * XXX this is the same as i2c_fill_compat. It could be refactored into a - * common fill_compat function with pointers to compat & ncompat instead - * of attach_args as the first parameter. + * Direct and indrect for SPI are pretty similar, so we can collapse + * them into a single function. */ static void -spi_fill_compat(struct spi_attach_args *sa, const char *compat, size_t len, - char **buffer) +spi_attach_child(struct spi_softc *sc, struct spi_attach_args *sa, + int chip_select, cfdata_t cf) { - int count, i; - const char *c, *start, **ptr; + struct spi_handle *sh; + device_t newdev = NULL; + bool is_direct = cf == NULL; + const int skip_flags = is_direct ? SPIH_ATTACHED + : (SPIH_ATTACHED | SPIH_DIRECT); + const int claim_flags = skip_flags ^ SPIH_DIRECT; + int locs[SPICF_NLOCS] = { 0 }; - *buffer = NULL; - for (i = count = 0, c = compat; i < len; i++, c++) - if (*c == 0) - count++; - count += 2; - ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK); - if (!ptr) + if (chip_select < 0 || + chip_select >= sc->sc_controller.sct_nslaves) { return; + } - for (i = count = 0, start = c = compat; i < len; i++, c++) { - if (*c == 0) { - ptr[count++] = start; - start = c + 1; - } + sh = &sc->sc_slaves[chip_select]; + + mutex_enter(&sc->sc_slave_state_lock); + if (ISSET(sh->sh_flags, skip_flags)) { + mutex_exit(&sc->sc_slave_state_lock); + return; } - if (start < compat + len) { - /* last string not 0 terminated */ - size_t l = c - start; - *buffer = malloc(l + 1, M_TEMP, M_WAITOK); - memcpy(*buffer, start, l); - (*buffer)[l] = 0; - ptr[count++] = *buffer; + + /* Keep others off of this chip select. */ + SET(sh->sh_flags, claim_flags); + mutex_exit(&sc->sc_slave_state_lock); + + locs[SPICF_SLAVE] = chip_select; + sa->sa_handle = sh; + + if (is_direct) { + newdev = config_found(sc->sc_dev, sa, spi_print_direct, + /* CFARG_SUBMATCH, config_stdsubmatch, XXX */ + CFARG_LOCATORS, locs, + CFARG_DEVHANDLE, sa->sa_devhandle, + CFARG_EOL); + } else { + if (config_probe(sc->sc_dev, cf, &sa)) { + newdev = config_attach(sc->sc_dev, cf, &sa, spi_print, + CFARG_LOCATORS, locs, + CFARG_EOL); + } } - ptr[count] = NULL; - sa->sa_compat = ptr; - sa->sa_ncompat = count; + if (newdev == NULL) { + /* + * Clear our claim on this chip select (yes, just + * the ATTACHED flag; we want to keep indirects off + * of chip selects for which there is a device tree + * node). + */ + mutex_enter(&sc->sc_slave_state_lock); + CLR(sh->sh_flags, SPIH_ATTACHED); + mutex_exit(&sc->sc_slave_state_lock); + } } -static void -spi_direct_attach_child_devices(device_t parent, struct spi_softc *sc, - prop_array_t child_devices) +static int +spi_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) { - unsigned int count; - prop_dictionary_t child; - prop_data_t cdata; - uint32_t slave; - uint64_t cookie; + struct spi_softc *sc = device_private(parent); struct spi_attach_args sa; - int loc[SPICF_NLOCS]; - char *buf; - int i; - - memset(loc, 0, sizeof loc); - count = prop_array_count(child_devices); - for (i = 0; i < count; i++) { - child = prop_array_get(child_devices, i); - if (!child) - continue; - if (!prop_dictionary_get_uint32(child, "slave", &slave)) - continue; - if(slave >= sc->sc_controller.sct_nslaves) - continue; - if (!prop_dictionary_get_uint64(child, "cookie", &cookie)) - continue; - if (!(cdata = prop_dictionary_get(child, "compatible"))) - continue; - loc[SPICF_SLAVE] = slave; - - memset(&sa, 0, sizeof sa); - sa.sa_handle = &sc->sc_slaves[i]; - sa.sa_prop = child; - sa.sa_cookie = cookie; - if (ISSET(sa.sa_handle->sh_flags, SPIH_ATTACHED)) - continue; - SET(sa.sa_handle->sh_flags, SPIH_ATTACHED); - - buf = NULL; - spi_fill_compat(&sa, - prop_data_value(cdata), - prop_data_size(cdata), &buf); - config_found(parent, &sa, spi_print, - CFARG_LOCATORS, loc, - CFARG_EOL); - if (sa.sa_compat) - free(sa.sa_compat, M_TEMP); - if (buf) - free(buf, M_TEMP); + if (cf->cf_loc[SPICF_SLAVE] == SPICF_SLAVE_DEFAULT) { + /* No wildcards for indirect on SPI. */ + return 0; } + + memset(&sa, 0, sizeof(sa)); + spi_attach_child(sc, &sa, cf->cf_loc[SPICF_SLAVE], cf); + + return 0; +} + +static bool +spi_enumerate_devices_callback(device_t self, + struct spi_enumerate_devices_args *args) +{ + struct spi_softc *sc = device_private(self); + + spi_attach_child(sc, args->sa, args->chip_select, NULL); + + return true; /* keep enumerating */ } int spi_compatible_match(const struct spi_attach_args *sa, const cfdata_t cf, const struct device_compatible_entry *compats) { - if (sa->sa_ncompat > 0) - return device_compatible_match(sa->sa_compat, sa->sa_ncompat, - compats); + if (sa->sa_clist != NULL) { + return device_compatible_match_strlist(sa->sa_clist, + sa->sa_clist_size, compats); + } + /* + * In this case, we're using indirect configuration, but SPI + * has no real addressing system, and we've filtered out + * wildcarded chip selects in spi_search(), so we have no + * choice but to trust the user-specified config. + */ return 1; } -/* - * API for device drivers. - * - * We provide wrapper routines to decouple the ABI for the SPI - * device drivers from the ABI for the SPI bus drivers. - */ static void spi_attach(device_t parent, device_t self, void *aux) { @@ -284,17 +278,21 @@ spi_attach(device_t parent, device_t sel struct spibus_attach_args *sba = aux; int i; + sc->sc_dev = self; + aprint_naive(": SPI bus\n"); aprint_normal(": SPI bus\n"); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); + mutex_init(&sc->sc_slave_state_lock, MUTEX_DEFAULT, IPL_NONE); cv_init(&sc->sc_cv, "spictl"); sc->sc_controller = *sba->sba_controller; sc->sc_nslaves = sba->sba_controller->sct_nslaves; + /* allocate slave structures */ - sc->sc_slaves = malloc(sizeof (struct spi_handle) * sc->sc_nslaves, - M_DEVBUF, M_WAITOK | M_ZERO); + sc->sc_slaves = kmem_zalloc(sizeof(*sc->sc_slaves) * sc->sc_nslaves, + KM_SLEEP); sc->sc_speed = 0; sc->sc_mode = -1; @@ -309,16 +307,26 @@ spi_attach(device_t parent, device_t sel sc->sc_slaves[i].sh_controller = &sc->sc_controller; } - /* First attach devices known to be present via fdt */ - if (sba->sba_child_devices) { - spi_direct_attach_child_devices(self, sc, sba->sba_child_devices); - } + /* + * Attempt to enumerate the devices on the bus using the + * platform device tree. + */ + struct spi_attach_args sa = { 0 }; + struct spi_enumerate_devices_args enumargs = { + .sa = &sa, + .callback = spi_enumerate_devices_callback, + }; + device_call(self, "spi-enumerate-devices", &enumargs); + /* Then do any other devices the user may have manually wired */ config_search(self, NULL, CFARG_SEARCH, spi_search, CFARG_EOL); } +CFATTACH_DECL_NEW(spi, sizeof(struct spi_softc), + spi_match, spi_attach, NULL, NULL); + static int spi_open(dev_t dev, int flag, int fmt, lwp_t *l) { @@ -375,11 +383,11 @@ spi_ioctl(dev_t dev, u_long cmd, void *d sbuf = rbuf = NULL; error = 0; if (sit->sit_send && sit->sit_sendlen <= SPI_MAXDATA) { - sbuf = malloc(sit->sit_sendlen, M_DEVBUF, M_WAITOK); + sbuf = kmem_alloc(sit->sit_sendlen, KM_SLEEP); error = copyin(sit->sit_send, sbuf, sit->sit_sendlen); } if (sit->sit_recv && sit->sit_recvlen <= SPI_MAXDATA) { - rbuf = malloc(sit->sit_recvlen, M_DEVBUF, M_WAITOK); + rbuf = kmem_alloc(sit->sit_recvlen, KM_SLEEP); } if (error == 0) { if (sbuf && rbuf) @@ -397,10 +405,10 @@ spi_ioctl(dev_t dev, u_long cmd, void *d if (error == 0) error = copyout(rbuf, sit->sit_recv, sit->sit_recvlen); - free(rbuf, M_DEVBUF); + kmem_free(rbuf, sit->sit_recvlen); } if (sbuf) { - free(sbuf, M_DEVBUF); + kmem_free(sbuf, sit->sit_sendlen); } break; default: @@ -411,8 +419,12 @@ spi_ioctl(dev_t dev, u_long cmd, void *d return error; } -CFATTACH_DECL_NEW(spi, sizeof(struct spi_softc), - spi_match, spi_attach, NULL, NULL); +/* + * API for device drivers. + * + * We provide wrapper routines to decouple the ABI for the SPI + * device drivers from the ABI for the SPI bus drivers. + */ /* * Configure. This should be the first thing that the SPI driver @@ -662,4 +674,3 @@ spi_send_recv(struct spi_handle *sh, int return 0; } - Index: src/sys/dev/spi/spivar.h diff -u src/sys/dev/spi/spivar.h:1.10 src/sys/dev/spi/spivar.h:1.10.6.1 --- src/sys/dev/spi/spivar.h:1.10 Tue Aug 4 13:20:45 2020 +++ src/sys/dev/spi/spivar.h Tue May 18 23:48:16 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: spivar.h,v 1.10 2020/08/04 13:20:45 kardel Exp $ */ +/* $NetBSD: spivar.h,v 1.10.6.1 2021/05/18 23:48:16 thorpej Exp $ */ /*- * Copyright (c) 2006 Urbana-Champaign Independent Media Center. @@ -77,18 +77,30 @@ int spibus_print(void *, const char *); /* one per chip select */ struct spibus_attach_args { struct spi_controller *sba_controller; - prop_array_t sba_child_devices; }; struct spi_attach_args { struct spi_handle *sa_handle; + /* only set if using direct config */ - int sa_ncompat; /* number of pointers in the - ia_compat array */ - const char ** sa_compat; /* chip names */ - prop_dictionary_t sa_prop; /* dictionary for this device */ + const char *sa_name; /* name of the device */ + const char *sa_clist; /* compatible strlist */ + size_t sa_clist_size; /* size of compatible strlist */ + devhandle_t sa_devhandle; /* device handle for the device */ +}; - uintptr_t sa_cookie; /* OF node in openfirmware machines */ +/* + * spi-enumerate-devices device call + * + * Enumerates the devices connected to the SPI bus, filling out + * the spi_attach_args and invoking the callback for each one. + * If the callback returns true, then enumeration continues. If + * the callback returns false, enumeration is stopped. + */ +struct spi_enumerate_devices_args { + struct spi_attach_args *sa; + bool (*callback)(device_t, struct spi_enumerate_devices_args *); + int chip_select; }; /*