Index: sys/conf/majors
===================================================================
RCS file: /cvsroot/src/sys/conf/majors,v
retrieving revision 1.80
diff -p -u -r1.80 majors
--- sys/conf/majors	7 Nov 2018 07:43:07 -0000	1.80
+++ sys/conf/majors	14 Feb 2019 20:38:29 -0000
@@ -79,3 +79,4 @@ device-major qemufwcfg char 342		   qemu
 device-major autofs    char 343		   autofs
 device-major gpiopps   char 344            gpiopps
 device-major nvmm      char 345            nvmm
+device-major spi       char 346		   spi
Index: sys/dev/spi/Makefile
===================================================================
RCS file: sys/dev/spi/Makefile
diff -N sys/dev/spi/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/dev/spi/Makefile	14 Feb 2019 20:38:29 -0000
@@ -0,0 +1,6 @@
+# $NetBSD: $
+
+INCSDIR= /usr/include/dev/spi
+INCS=   spi_io.h
+
+.include <bsd.kinc.mk>
Index: sys/dev/spi/spi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/spi/spi.c,v
retrieving revision 1.9
diff -p -u -r1.9 spi.c
--- sys/dev/spi/spi.c	3 Sep 2018 16:29:33 -0000	1.9
+++ sys/dev/spi/spi.c	14 Feb 2019 20:38:29 -0000
@@ -49,12 +49,17 @@ __KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.9 
 #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;
@@ -64,6 +69,25 @@ struct spi_softc {
 	struct spi_handle	*sc_slaves;
 };
 
+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
+};
+
 /*
  * SPI slave device.  We have one of these per slave.
  */
@@ -73,6 +97,8 @@ struct spi_handle {
 	int			sh_slave;
 };
 
+#define SPI_MAXDATA 4096
+
 /*
  * API for bus drivers.
  */
@@ -166,6 +192,97 @@ 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;
+
+	/* XXX */
+	sc->sc_speed = 0;
+	sc->sc_mode = -1;
+
+	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 (sc->sc_nslaves == 0) {
+			error = EINVAL;
+			break;
+		}
+		sh = &sc->sc_slaves[0];
+		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);
 
Index: sys/dev/spi/spi_io.h
===================================================================
RCS file: sys/dev/spi/spi_io.h
diff -N sys/dev/spi/spi_io.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/dev/spi/spi_io.h	14 Feb 2019 20:38:29 -0000
@@ -0,0 +1,52 @@
+/*	$NetBSD: i2c_io.h,v 1.4 2017/10/28 06:27:32 riastradh 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_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_ */
Index: etc/MAKEDEV.tmpl
===================================================================
RCS file: /cvsroot/src/etc/MAKEDEV.tmpl,v
retrieving revision 1.197
diff -p -u -r1.197 MAKEDEV.tmpl
--- etc/MAKEDEV.tmpl	27 Jan 2019 08:53:28 -0000	1.197
+++ etc/MAKEDEV.tmpl	14 Feb 2019 20:38:29 -0000
@@ -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: distrib/sets/lists/comp/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/comp/mi,v
retrieving revision 1.2258
diff -p -u -r1.2258 mi
--- distrib/sets/lists/comp/mi	10 Feb 2019 04:03:03 -0000	1.2258
+++ distrib/sets/lists/comp/mi	14 Feb 2019 20:38:30 -0000
@@ -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
Index: distrib/sets/lists/base/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/base/mi,v
retrieving revision 1.1200
diff -p -u -r1.1200 mi
--- distrib/sets/lists/base/mi	2 Feb 2019 22:39:32 -0000	1.1200
+++ distrib/sets/lists/base/mi	14 Feb 2019 20:38:32 -0000
@@ -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
