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