Module Name:    src
Committed By:   mlelstv
Date:           Sat Feb 23 10:43:25 UTC 2019

Modified Files:
        src/distrib/sets/lists/base: mi
        src/distrib/sets/lists/comp: mi
        src/etc: MAKEDEV.tmpl
        src/share/man/man4: spi.4
        src/sys/dev/spi: spi.c spivar.h
Added Files:
        src/share/man/man9: spi.9
        src/sys/dev/spi: Makefile spi_io.h

Log Message:
Add userland driver to spi framework.

Previously spi would configure the controller to use the lowest speed of
all connected devices since the kernel started and to fail attempted mode
changes. This is now improved to keep individual modes and speeds for each
slave and to reconfigure the controller as necessary for each transfer.

Added man page for spi(9).


To generate a diff of this commit:
cvs rdiff -u -r1.1200 -r1.1201 src/distrib/sets/lists/base/mi
cvs rdiff -u -r1.2259 -r1.2260 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.198 -r1.199 src/etc/MAKEDEV.tmpl
cvs rdiff -u -r1.5 -r1.6 src/share/man/man4/spi.4
cvs rdiff -u -r0 -r1.1 src/share/man/man9/spi.9
cvs rdiff -u -r0 -r1.1 src/sys/dev/spi/Makefile src/sys/dev/spi/spi_io.h
cvs rdiff -u -r1.9 -r1.10 src/sys/dev/spi/spi.c
cvs rdiff -u -r1.6 -r1.7 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/distrib/sets/lists/base/mi
diff -u src/distrib/sets/lists/base/mi:1.1200 src/distrib/sets/lists/base/mi:1.1201
--- src/distrib/sets/lists/base/mi:1.1200	Sat Feb  2 22:39:32 2019
+++ src/distrib/sets/lists/base/mi	Sat Feb 23 10:43:25 2019
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1200 2019/02/02 22:39:32 mrg Exp $
+# $NetBSD: mi,v 1.1201 2019/02/23 10:43:25 mlelstv Exp $
 #
 # Note:	Don't delete entries from here - mark them as "obsolete" instead,
 #	unless otherwise stated below.
@@ -1112,6 +1112,7 @@
 ./usr/include/dev/rcons				base-obsolete		obsolete
 ./usr/include/dev/sbus				base-c-usr
 ./usr/include/dev/scsipi			base-c-usr
+./usr/include/dev/spi				base-c-usr
 ./usr/include/dev/sun				base-c-usr
 ./usr/include/dev/tc				base-c-usr
 ./usr/include/dev/usb				base-c-usr

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.2259 src/distrib/sets/lists/comp/mi:1.2260
--- src/distrib/sets/lists/comp/mi:1.2259	Sat Feb 23 03:10:05 2019
+++ src/distrib/sets/lists/comp/mi	Sat Feb 23 10:43:25 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.2259 2019/02/23 03:10:05 kamil Exp $
+#	$NetBSD: mi,v 1.2260 2019/02/23 10:43:25 mlelstv Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp				comp-sys-root
@@ -709,6 +709,7 @@
 ./usr/include/dev/scsipi/ss_mustek.h		comp-obsolete		obsolete
 ./usr/include/dev/scsipi/ssvar.h		comp-obsolete		obsolete
 ./usr/include/dev/spkrio.h			comp-c-include
+./usr/include/dev/spi/spi_io.h			comp-c-include
 ./usr/include/dev/sun/disklabel.h		comp-c-include
 ./usr/include/dev/sun/eeprom.h			comp-c-include
 ./usr/include/dev/sun/event_var.h		comp-obsolete		obsolete
@@ -19594,6 +19595,7 @@
 ./usr/share/man/html9/specificdata_key_delete.html comp-sys-htmlman	html
 ./usr/share/man/html9/specificdata_setspecific.html comp-sys-htmlman	html
 ./usr/share/man/html9/specificdata_setspecific_nowait.html comp-sys-htmlman html
+./usr/share/man/html9/spi.html			comp-sys-htmlman	html
 ./usr/share/man/html9/spinlockinit.html		comp-sys-htmlman	html
 ./usr/share/man/html9/spinlockmgr.html		comp-sys-htmlman	html
 ./usr/share/man/html9/spl.html			comp-sys-htmlman	html
@@ -27626,6 +27628,7 @@
 ./usr/share/man/man9/specificdata_key_delete.9	comp-sys-man		.man
 ./usr/share/man/man9/specificdata_setspecific.9	comp-sys-man		.man
 ./usr/share/man/man9/specificdata_setspecific_nowait.9 comp-sys-man	.man
+./usr/share/man/man9/spi.9			comp-sys-man		.man
 ./usr/share/man/man9/spinlockinit.9		comp-sys-man		.man
 ./usr/share/man/man9/spinlockmgr.9		comp-sys-man		.man
 ./usr/share/man/man9/spl.9			comp-sys-man		.man

Index: src/etc/MAKEDEV.tmpl
diff -u src/etc/MAKEDEV.tmpl:1.198 src/etc/MAKEDEV.tmpl:1.199
--- src/etc/MAKEDEV.tmpl:1.198	Sat Feb 23 03:10:06 2019
+++ src/etc/MAKEDEV.tmpl	Sat Feb 23 10:43:25 2019
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$NetBSD: MAKEDEV.tmpl,v 1.198 2019/02/23 03:10:06 kamil Exp $
+#	$NetBSD: MAKEDEV.tmpl,v 1.199 2019/02/23 10:43:25 mlelstv Exp $
 #
 # Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -272,6 +272,7 @@
 #	se*	SCSI Ethernet
 #	ses*	SES/SAF-TE SCSI Devices
 #	speaker	PC speaker		(XXX - installed)
+#	spi*	SPI bus device
 #	sram	battery backuped memory (x68k)
 #	ss*	SCSI scanner
 #	stic*	PixelStamp interface chip
@@ -1584,6 +1585,12 @@ iic[0-9]*)
 	mkdev iic$unit c %iic_chr% $unit 600
 	;;
 
+spi[0-9]*)
+	unit=${i#spi}
+	: ${unit:-0}
+	mkdev spi$unit c %spi_chr% $unit 600
+	;;
+
 amr[0-9]*)
 	unit=${i#amr}
 	mkdev amr$unit c %amr_chr% $unit

Index: src/share/man/man4/spi.4
diff -u src/share/man/man4/spi.4:1.5 src/share/man/man4/spi.4:1.6
--- src/share/man/man4/spi.4:1.5	Tue Aug 18 19:40:21 2015
+++ src/share/man/man4/spi.4	Sat Feb 23 10:43:25 2019
@@ -1,4 +1,4 @@
-.\"	$NetBSD: spi.4,v 1.5 2015/08/18 19:40:21 phx Exp $
+.\"	$NetBSD: spi.4,v 1.6 2019/02/23 10:43:25 mlelstv Exp $
 .\"
 .\" Copyright (c) 2006 Urbana-Champaign Independent Media Center.
 .\" Copyright (c) 2006 Garrett D'Amore.
@@ -107,6 +107,7 @@ Microchip MCP4801/MCP4811/MCP4821 digita
 Texas Instruments TMP121 temperature sensor.
 .El
 .Sh SEE ALSO
+.Xr spi 9 ,
 .Xr m25p 4 ,
 .Xr mcp23s17gpio 4 ,
 .Xr mcp3kadc 4 ,

Index: src/sys/dev/spi/spi.c
diff -u src/sys/dev/spi/spi.c:1.9 src/sys/dev/spi/spi.c:1.10
--- src/sys/dev/spi/spi.c:1.9	Mon Sep  3 16:29:33 2018
+++ src/sys/dev/spi/spi.c	Sat Feb 23 10:43:25 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: spi.c,v 1.9 2018/09/03 16:29:33 riastradh Exp $ */
+/* $NetBSD: spi.c,v 1.10 2019/02/23 10:43:25 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2006 Urbana-Champaign Independent Media Center.
@@ -42,26 +42,55 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.9 2018/09/03 16:29:33 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.10 2019/02/23 10:43:25 mlelstv Exp $");
 
 #include "locators.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <sys/conf.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/condvar.h>
 #include <sys/errno.h>
 
 #include <dev/spi/spivar.h>
+#include <dev/spi/spi_io.h>
+
+#include "ioconf.h"
+#include "locators.h"
 
 struct spi_softc {
 	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_lock;
+	kcondvar_t		sc_cv;
+	int			sc_flags;
+#define SPIC_BUSY		1
+};
+
+static dev_type_open(spi_open);
+static dev_type_close(spi_close);
+static dev_type_ioctl(spi_ioctl);
+
+const struct cdevsw spi_cdevsw = {
+	.d_open = spi_open,
+	.d_close = spi_close,
+	.d_read = noread,
+	.d_write = nowrite,
+	.d_ioctl = spi_ioctl,
+	.d_stop = nostop,
+	.d_tty = notty,
+	.d_poll = nopoll,
+	.d_mmap = nommap,
+	.d_kqfilter = nokqfilter,
+	.d_discard = nodiscard,
+	.d_flag = D_OTHER
 };
 
 /*
@@ -71,8 +100,12 @@ struct spi_handle {
 	struct spi_softc	*sh_sc;
 	struct spi_controller	*sh_controller;
 	int			sh_slave;
+	int			sh_mode;
+	int			sh_speed;
 };
 
+#define SPI_MAXDATA 4096
+
 /*
  * API for bus drivers.
  */
@@ -142,6 +175,9 @@ spi_attach(device_t parent, device_t sel
 	aprint_naive(": SPI bus\n");
 	aprint_normal(": SPI bus\n");
 
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
+	cv_init(&sc->sc_cv, "spictl");
+
 	sc->sc_controller = *sba->sba_controller;
 	sc->sc_nslaves = sba->sba_controller->sct_nslaves;
 	/* allocate slave structures */
@@ -150,6 +186,7 @@ spi_attach(device_t parent, device_t sel
 
 	sc->sc_speed = 0;
 	sc->sc_mode = -1;
+	sc->sc_slave = -1;
 
 	/*
 	 * Initialize slave handles
@@ -166,6 +203,93 @@ spi_attach(device_t parent, device_t sel
 	config_search_ia(spi_search, self, "spi", NULL);
 }
 
+static int
+spi_open(dev_t dev, int flag, int fmt, lwp_t *l)
+{
+	struct spi_softc *sc = device_lookup_private(&spi_cd, minor(dev));
+
+	if (sc == NULL)
+		return ENXIO;
+
+	return 0;
+}
+
+static int
+spi_close(dev_t dev, int flag, int fmt, lwp_t *l)
+{
+
+	return 0;
+}
+
+static int
+spi_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
+{
+	struct spi_softc *sc = device_lookup_private(&spi_cd, minor(dev));
+	struct spi_handle *sh;
+	spi_ioctl_configure_t *sic;
+	spi_ioctl_transfer_t *sit;
+	uint8_t *sbuf, *rbuf;
+	int error;
+
+	if (sc == NULL)
+		return ENXIO;
+
+	switch (cmd) {
+	case SPI_IOCTL_CONFIGURE:
+		sic = (spi_ioctl_configure_t *)data;
+		if (sic->sic_addr < 0 || sic->sic_addr >= sc->sc_nslaves) {
+			error = EINVAL;
+			break;
+		}
+		sh = &sc->sc_slaves[sic->sic_addr];
+		error = spi_configure(sh, sic->sic_mode, sic->sic_speed);
+		break;
+	case SPI_IOCTL_TRANSFER:
+		sit = (spi_ioctl_transfer_t *)data;
+		if (sit->sit_addr < 0 || sit->sit_addr >= sc->sc_nslaves) {
+			error = EINVAL;
+			break;
+		}
+		sh = &sc->sc_slaves[sit->sit_addr];
+		sbuf = rbuf = NULL;
+		error = 0;
+		if (sit->sit_send && sit->sit_sendlen < SPI_MAXDATA) {
+			sbuf = malloc(sit->sit_sendlen, M_DEVBUF, M_WAITOK);
+			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);
+		}
+		if (error == 0) {
+			if (sbuf && rbuf)
+				error = spi_send_recv(sh,
+					sit->sit_sendlen, sbuf,
+					sit->sit_recvlen, rbuf);
+			else if (sbuf)
+				error = spi_send(sh,
+					sit->sit_sendlen, sbuf);
+			else if (rbuf)
+				error = spi_recv(sh,
+					sit->sit_recvlen, rbuf);
+		}
+		if (rbuf) {
+			if (error == 0)
+				error = copyout(rbuf, sit->sit_recv,
+						sit->sit_recvlen);
+			free(rbuf, M_DEVBUF);
+		}
+		if (sbuf) {
+			free(sbuf, M_DEVBUF);
+		}
+		break;
+	default:
+		error = ENODEV;
+		break;
+	}
+
+	return error;
+}
+
 CFATTACH_DECL_NEW(spi, sizeof(struct spi_softc),
     spi_match, spi_attach, NULL, NULL);
 
@@ -181,30 +305,39 @@ CFATTACH_DECL_NEW(spi, sizeof(struct spi
 int
 spi_configure(struct spi_handle *sh, int mode, int speed)
 {
-	int			s, rv;
-	struct spi_softc	*sc = sh->sh_sc;
-	struct spi_controller	*tag = sh->sh_controller;
 
-	/* ensure that request is compatible with other devices on the bus */
-	if ((sc->sc_mode >= 0) && (sc->sc_mode != mode))
-		return EINVAL;
-
-	s = splbio();
-	/* pick lowest configured speed */
-	if (speed == 0)
-		speed = sc->sc_speed;
-	if (sc->sc_speed)
-		speed = uimin(sc->sc_speed, speed);
-
-	rv = (*tag->sct_configure)(tag->sct_cookie, sh->sh_slave,
-	    mode, speed);
-
-	if (rv == 0) {
-		sc->sc_mode = mode;
-		sc->sc_speed = speed;
-	}
-	splx(s);
-	return rv;
+	sh->sh_mode = mode;
+	sh->sh_speed = speed;
+	return 0;
+}
+
+/*
+ * Acquire controller
+ */
+static void
+spi_acquire(struct spi_handle *sh)
+{
+	struct spi_softc *sc = sh->sh_sc;
+
+	mutex_enter(&sc->sc_lock);
+	while ((sc->sc_flags & SPIC_BUSY) != 0)
+		cv_wait(&sc->sc_cv, &sc->sc_lock);
+	sc->sc_flags |= SPIC_BUSY;
+	mutex_exit(&sc->sc_lock);
+}
+
+/*
+ * Release controller
+ */
+static void
+spi_release(struct spi_handle *sh)
+{
+	struct spi_softc *sc = sh->sh_sc;
+
+	mutex_enter(&sc->sc_lock);
+	sc->sc_flags &= ~SPIC_BUSY;
+	cv_broadcast(&sc->sc_cv);
+	mutex_exit(&sc->sc_lock);
 }
 
 void
@@ -212,7 +345,7 @@ spi_transfer_init(struct spi_transfer *s
 {
 
 	mutex_init(&st->st_lock, MUTEX_DEFAULT, IPL_BIO);
-	cv_init(&st->st_cv, "spicv");
+	cv_init(&st->st_cv, "spixfr");
 
 	st->st_flags = 0;
 	st->st_errno = 0;
@@ -246,8 +379,10 @@ spi_transfer_add(struct spi_transfer *st
 int
 spi_transfer(struct spi_handle *sh, struct spi_transfer *st)
 {
+	struct spi_softc	*sc = sh->sh_sc;
 	struct spi_controller	*tag = sh->sh_controller;
 	struct spi_chunk	*chunk;
+	int error;
 
 	/*
 	 * Initialize "resid" counters and pointers, so that callers
@@ -260,16 +395,45 @@ spi_transfer(struct spi_handle *sh, stru
 	}
 
 	/*
-	 * Match slave to handle's slave.
+	 * Match slave and parameters to handle
 	 */
 	st->st_slave = sh->sh_slave;
 
-	return (*tag->sct_transfer)(tag->sct_cookie, st);
+	/*
+	 * Reserve controller during transaction
+ 	 */
+	spi_acquire(sh);
+
+	st->st_spiprivate = (void *)sh;
+	
+	/*
+	 * Reconfigure controller
+	 *
+	 * XXX backends don't configure per-slave parameters
+	 * Whenever we switch slaves or change mode or speed, we
+	 * need to tell the backend.
+	 */
+	if (sc->sc_slave != sh->sh_slave
+	    || sc->sc_mode != sh->sh_mode
+	    || sc->sc_speed != sh->sh_speed) {
+		error = (*tag->sct_configure)(tag->sct_cookie,
+				sh->sh_slave, sh->sh_mode, sh->sh_speed);
+		if (error)
+			return error;
+	}
+	sc->sc_mode = sh->sh_mode;
+	sc->sc_speed = sh->sh_speed;
+	sc->sc_slave = sh->sh_slave;
+
+	error = (*tag->sct_transfer)(tag->sct_cookie, st);
+
+	return error;
 }
 
 void
 spi_wait(struct spi_transfer *st)
 {
+	struct spi_handle *sh = st->st_spiprivate;
 
 	mutex_enter(&st->st_lock);
 	while (!(st->st_flags & SPI_F_DONE)) {
@@ -278,6 +442,11 @@ spi_wait(struct spi_transfer *st)
 	mutex_exit(&st->st_lock);
 	cv_destroy(&st->st_cv);
 	mutex_destroy(&st->st_lock);
+
+	/*
+	 * End transaction
+	 */
+	spi_release(sh);
 }
 
 void
@@ -372,3 +541,4 @@ 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.6 src/sys/dev/spi/spivar.h:1.7
--- src/sys/dev/spi/spivar.h:1.6	Sun Jul 13 17:12:23 2014
+++ src/sys/dev/spi/spivar.h	Sat Feb 23 10:43:25 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: spivar.h,v 1.6 2014/07/13 17:12:23 dholland Exp $ */
+/* $NetBSD: spivar.h,v 1.7 2019/02/23 10:43:25 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2006 Urbana-Champaign Independent Media Center.
@@ -111,6 +111,7 @@ struct spi_transfer {
 	kmutex_t	st_lock;
 	kcondvar_t	st_cv;
 	void		*st_busprivate;
+	void		*st_spiprivate;
 };
 
 /* declare a list of transfers */

Added files:

Index: src/share/man/man9/spi.9
diff -u /dev/null src/share/man/man9/spi.9:1.1
--- /dev/null	Sat Feb 23 10:43:26 2019
+++ src/share/man/man9/spi.9	Sat Feb 23 10:43:25 2019
@@ -0,0 +1,163 @@
+.\"	$NetBSD: spi.9,v 1.1 2019/02/23 10:43:25 mlelstv Exp $
+.\"
+.\" Copyright (c) 2019 The NetBSD Foundation
+.\" All rights reserved.
+.\"
+.\" Written by Michael van Elst
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+.\" 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.
+.\"
+.Dd February 23, 2019
+.Dt SPI 9
+.Os
+.Sh NAME
+.Nm spi_configure ,
+.Nm spi_transfer ,
+.Nm spi_transfer_init ,
+.Nm spi_chunk_init ,
+.Nm spi_transfer_add ,
+.Nm spi_wait ,
+.Nm spi_done ,
+.Nm spi_send ,
+.Nm spi_recv ,
+.Nm spi_send_recv
+.Sh SYNOPSIS
+.In dev/spi/spivar.h
+.Ft int
+.Fo spi_configure
+.Fa "struct spi_handle *sh"
+.Fa "int mode"
+.Fa "int speed"
+.Fc
+.Ft int
+.Fo spi_transfer
+.Fa "struct spi_handle *sh"
+.Fa "struct spi_transfer *st"
+.Fc
+.Ft void
+.Fo spi_transfer_init
+.Fa "struct spi_transfer *st"
+.Fc
+.Ft void
+.Fo spi_chunk_init
+.Fa "struct spi_chunk *chunk"
+.Fa "int cnt"
+.Fa "const uint8_t *wptr"
+.Fa "uint8_t *rptr"
+.Fc
+.Ft void
+.Fo spi_transfer_add
+.Fa "struct spi_transfer *st"
+.Fa "struct spi_chunk *chunk"
+.Fc
+.Ft void
+.Fo spi_wait
+.Fa "struct spi_transfer *st"
+.Fc
+.Ft void
+.Fo spi_done
+.Fa "struct spi_transfer *st"
+.Fa "int err"
+.Fc
+.Ft int
+.Fo spi_recv
+.Fa "struct spi_handle *sh"
+.Fa "int cnt"
+.Fa "uint8_t *data"
+.Fc
+.Ft int
+.Fo spi_send
+.Fa "struct spi_handle *sh"
+.Fa "int cnt"
+.Fa "const uint8_t *data"
+.Fc
+.Ft int
+.Fo spi_send_recv
+.Fa "struct spi_handle *sh"
+.Fa "int scnt"
+.Fa "const uint8_t *snd"
+.Fa "int rcnt"
+.Fa "const uint8_t *rcv"
+.Fc
+.Sh DESCRIPTION
+SPI is a 4-wire synchronous full-duplex serial bus.
+It is commonly used for connecting devices such as EEPROMs,
+displays, and other types of integrated circuits.
+The
+.Nm spi
+interface provides a means of communicating with SPI-connected devices.
+.Sh FUNCTIONS
+The following functions comprise the API provided to drivers of
+SPI-connected devices.
+.Pp
+The
+.Fa struct spi_handle
+corresponding to the device is passed in the driver attachment.
+.Bl -tag -width spi_transfer_init
+.It Fn spi_configure "sh" "mode" "speed"
+Sets mode and speed for subsequent communication with a SPI slave.
+.It Fn spi_transfer "sh" "st"
+Queue transfer to SPI controller.
+.Fn spi_transfer
+returns an errno value when the transfer couldn't be queued.
+.It Fn spi_transfer_init "st"
+Initialize a transfer structure.
+.It Fn spi_chunk_init "chunk" "cnt" "wptr" rptr"
+Initialize a chunk structure, each chunk corresponds to
+a possibly bi-directional transfer where the same amount
+of bytes is shifted in and out.
+.It Fn spi_transfer_add "st" "chunk"
+Append a chunk to transfer structure.
+.It Fn spi_wait "st"
+Wait for a transfer to complete. When the transfer has failed
+for some reason, the field
+.Va st->st_errno
+is set to a non-zero value.
+.It Fn spi_done "st" "err"
+Called back machine-dependent backend to signal completion
+of a transfer.
+.El
+.Pp
+For simplicity there are convenience functions that combine
+common operations.
+These functions return an errno value when the transfer failed.
+.Bl -tag -width spi_transfer_init
+.It Fn spi_recv "sh" "cnt" "data"
+Prepares a chunk for receiving data, queues a transfer and
+waits for it to complete.
+.It Fn spi_send "sh" "cnt" "data"
+Prepares a chunk for sending data, queues a transfer and
+waits for it to complete.
+.It Fn spi_send_recv "sh" "scnt" "snd" "rcnt" "rcv"
+Prepares two chunks for sending data first and then receiving
+an answer,
+queues a transfer and waits for it to complete.
+This is not a full-duplex operation.
+.El
+.Sh SEE ALSO
+.Xr spi 4
+.Rs
+.Sh HISTORY
+The
+.Nm spi
+API first appeared in
+.Nx 4.0 .

Index: src/sys/dev/spi/Makefile
diff -u /dev/null src/sys/dev/spi/Makefile:1.1
--- /dev/null	Sat Feb 23 10:43:26 2019
+++ src/sys/dev/spi/Makefile	Sat Feb 23 10:43:25 2019
@@ -0,0 +1,6 @@
+# $NetBSD: Makefile,v 1.1 2019/02/23 10:43:25 mlelstv Exp $
+
+INCSDIR= /usr/include/dev/spi
+INCS=   spi_io.h
+
+.include <bsd.kinc.mk>
Index: src/sys/dev/spi/spi_io.h
diff -u /dev/null src/sys/dev/spi/spi_io.h:1.1
--- /dev/null	Sat Feb 23 10:43:26 2019
+++ src/sys/dev/spi/spi_io.h	Sat Feb 23 10:43:25 2019
@@ -0,0 +1,53 @@
+/*	$NetBSD: spi_io.h,v 1.1 2019/02/23 10:43:25 mlelstv Exp $	*/
+
+/*
+ * Copyright (c) 2019 Michael van Elst
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+#ifndef _DEV_SPI_SPI_IO_H_
+#define	_DEV_SPI_SPI_IO_H_
+
+#include <sys/types.h>
+#include <sys/ioccom.h>
+#include <sys/uio.h>
+
+typedef struct spi_ioctl_configure {
+	int sic_addr;
+	int sic_mode;
+	int sic_speed;
+} spi_ioctl_configure_t;
+
+typedef struct spi_ioctl_transfer {
+	int sit_addr;
+	const void *sit_send;
+	size_t sit_sendlen;
+	void *sit_recv;
+	size_t sit_recvlen;
+} spi_ioctl_transfer_t;
+
+#define	SPI_IOCTL_CONFIGURE		_IOW('S', 0, spi_ioctl_configure_t)
+#define	SPI_IOCTL_TRANSFER		_IOW('S', 1, spi_ioctl_transfer_t)
+
+#endif /* _DEV_SPI_SPI_IO_H_ */

Reply via email to