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).
This commit is contained in:
parent
65e39aee46
commit
975ce0ba8d
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 digital to analog converter.
|
||||
Texas Instruments TMP121 temperature sensor.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr spi 9 ,
|
||||
.Xr m25p 4 ,
|
||||
.Xr mcp23s17gpio 4 ,
|
||||
.Xr mcp3kadc 4 ,
|
||||
|
163
share/man/man9/spi.9
Normal file
163
share/man/man9/spi.9
Normal file
@ -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 .
|
6
sys/dev/spi/Makefile
Normal file
6
sys/dev/spi/Makefile
Normal file
@ -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>
|
@ -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 self, void *aux)
|
||||
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 self, void *aux)
|
||||
|
||||
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 self, void *aux)
|
||||
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_softc),
|
||||
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;
|
||||
sh->sh_mode = mode;
|
||||
sh->sh_speed = speed;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = splbio();
|
||||
/* pick lowest configured speed */
|
||||
if (speed == 0)
|
||||
speed = sc->sc_speed;
|
||||
if (sc->sc_speed)
|
||||
speed = uimin(sc->sc_speed, speed);
|
||||
/*
|
||||
* Acquire controller
|
||||
*/
|
||||
static void
|
||||
spi_acquire(struct spi_handle *sh)
|
||||
{
|
||||
struct spi_softc *sc = sh->sh_sc;
|
||||
|
||||
rv = (*tag->sct_configure)(tag->sct_cookie, sh->sh_slave,
|
||||
mode, speed);
|
||||
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);
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
sc->sc_mode = mode;
|
||||
sc->sc_speed = speed;
|
||||
}
|
||||
splx(s);
|
||||
return rv;
|
||||
/*
|
||||
* 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 *st)
|
||||
{
|
||||
|
||||
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, struct spi_chunk *chunk)
|
||||
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, struct spi_transfer *st)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 scnt, const uint8_t *snd,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
53
sys/dev/spi/spi_io.h
Normal file
53
sys/dev/spi/spi_io.h
Normal file
@ -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_ */
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user