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;
};
/*