1 2 /* $NetBSD: scmdspi.c,v 1.1 2021/12/07 17:39:54 brad Exp $ */ 3 4 /* 5 * Copyright (c) 2021 Brad Spencer <brad@anduin.eldar.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: scmdspi.c,v 1.1 2021/12/07 17:39:54 brad Exp $"); 22 23 /* 24 * SPI driver for the Sparkfun Serial motor controller. 25 * Uses the common scmd driver to do the real work. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/kernel.h> 31 #include <sys/device.h> 32 #include <sys/module.h> 33 #include <sys/conf.h> 34 #include <sys/sysctl.h> 35 #include <sys/mutex.h> 36 #include <sys/condvar.h> 37 #include <sys/pool.h> 38 #include <sys/kmem.h> 39 40 #include <dev/i2c/i2cvar.h> 41 #include <dev/spi/spivar.h> 42 #include <dev/ic/scmdreg.h> 43 #include <dev/ic/scmdvar.h> 44 45 extern void scmd_attach(struct scmd_sc *); 46 47 static int scmdspi_match(device_t, cfdata_t, void *); 48 static void scmdspi_attach(device_t, device_t, void *); 49 static int scmdspi_detach(device_t, int); 50 static int scmdspi_activate(device_t, enum devact); 51 52 #define SCMD_DEBUG 53 #ifdef SCMD_DEBUG 54 #define DPRINTF(s, l, x) \ 55 do { \ 56 if (l <= s->sc_scmddebug) \ 57 printf x; \ 58 } while (/*CONSTCOND*/0) 59 #else 60 #define DPRINTF(s, l, x) 61 #endif 62 63 CFATTACH_DECL_NEW(scmdspi, sizeof(struct scmd_sc), 64 scmdspi_match, scmdspi_attach, scmdspi_detach, scmdspi_activate); 65 66 /* For the SPI interface on this device, the reads are done in an odd 67 * manor. The first part is normal enough, you send the register binary 68 * or'ed with 0x80 and then the receive the data. However, you MUST also 69 * then receive a dummy value otherwise, everything gets out of sync and 70 * no further reads appear to work unless you do a SPI receive all by itself. 71 * This is documented in the data sheet for this device. 72 * 73 * Please note that the Ardunio code does this a little differently. What is 74 * below works on a Raspberry PI 3 without any apparent problems. 75 * 76 * The delays are also mentioned in the datasheet as being 20us, however, the 77 * Ardunio code does 50us, so do likewise. 78 */ 79 static int 80 scmdspi_read_reg_direct(struct spi_handle *sh, uint8_t reg, 81 uint8_t *buf) 82 { 83 int err; 84 uint8_t b; 85 uint8_t rreg = reg | 0x80; 86 87 err = spi_send(sh, 1, &rreg); 88 if (err) 89 return err; 90 91 delay(50); 92 93 b = SCMD_HOLE_VALUE; 94 err = spi_recv(sh, 1, &b); 95 if (err) 96 return err; 97 98 *buf = b; 99 100 delay(50); 101 102 b = SCMD_HOLE_VALUE; 103 err = spi_recv(sh, 1, &b); 104 delay(50); 105 106 return err; 107 } 108 109 static int 110 scmdspi_read_reg(struct scmd_sc *sc, uint8_t reg, uint8_t *buf) 111 { 112 return scmdspi_read_reg_direct(sc->sc_sh, reg, buf); 113 } 114 115 /* SPI writes to this device are normal enough. You send the register 116 * you want making sure that the high bit, 0x80, is clear and then the 117 * data. 118 * 119 * The rule about waiting between operations appears to not apply, however. 120 * This does more or less what the Ardunio code does. 121 */ 122 static int 123 scmdspi_write_reg_direct(struct spi_handle *sh, uint8_t reg, 124 uint8_t buf) 125 { 126 uint8_t rreg = reg & 0x7F; 127 int err; 128 129 err = spi_send(sh, 1, &rreg); 130 if (err) 131 return err; 132 133 err = spi_send(sh, 1, &buf); 134 if (err) 135 return err; 136 137 delay(50); 138 139 return err; 140 } 141 142 static int 143 scmdspi_write_reg(struct scmd_sc *sc, uint8_t reg, uint8_t buf) 144 { 145 return scmdspi_write_reg_direct(sc->sc_sh, reg, buf); 146 } 147 148 /* These are to satisfy the common code */ 149 static int 150 scmdspi_acquire_bus(struct scmd_sc *sc) 151 { 152 return 0; 153 } 154 155 static void 156 scmdspi_release_bus(struct scmd_sc *sc) 157 { 158 return; 159 } 160 161 /* Nothing more is done here. It would be nice if the device was 162 * actually checked to make sure it was there, but at least on the 163 * Raspberry PI 3 the SPI pins were not set up in ALT0 mode yet and 164 * everything acts like it succeeds. No errors are ever produced while 165 * in that state. 166 */ 167 static int 168 scmdspi_match(device_t parent, cfdata_t match, void *aux) 169 { 170 struct spi_attach_args *sa = aux; 171 const bool matchdebug = true; 172 173 if (matchdebug) { 174 printf("Trying to match\n"); 175 } 176 177 /* configure for 1MHz and SPI mode 0 according to the data sheet */ 178 if (spi_configure(sa->sa_handle, SPI_MODE_0, 1000000)) 179 return 0; 180 181 return 1; 182 } 183 184 static void 185 scmdspi_attach(device_t parent, device_t self, void *aux) 186 { 187 struct scmd_sc *sc; 188 struct spi_attach_args *sa; 189 190 sa = aux; 191 sc = device_private(self); 192 193 sc->sc_dev = self; 194 sc->sc_sh = sa->sa_handle; 195 sc->sc_scmddebug = 0; 196 sc->sc_topaddr = 0xff; 197 sc->sc_opened = false; 198 sc->sc_dying = false; 199 sc->sc_func_acquire_bus = &scmdspi_acquire_bus; 200 sc->sc_func_release_bus = &scmdspi_release_bus; 201 sc->sc_func_read_register = &scmdspi_read_reg; 202 sc->sc_func_write_register = &scmdspi_write_reg; 203 204 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 205 mutex_init(&sc->sc_condmutex, MUTEX_DEFAULT, IPL_NONE); 206 mutex_init(&sc->sc_dying_mutex, MUTEX_DEFAULT, IPL_NONE); 207 cv_init(&sc->sc_condvar, "scmdspicv"); 208 cv_init(&sc->sc_cond_dying, "scmdspidc"); 209 210 /* Please note that if the pins are not set up for SPI, the attachment 211 * will work, but it will not figure out that there are slave modules. 212 * It is likely required that a re-enumeration be performed after the pins 213 * are set. This can be done from userland later. 214 */ 215 scmd_attach(sc); 216 217 return; 218 } 219 220 /* These really do not do a whole lot, as SPI devices do not seem to work 221 * as modules. 222 */ 223 static int 224 scmdspi_detach(device_t self, int flags) 225 { 226 struct scmd_sc *sc; 227 228 sc = device_private(self); 229 230 mutex_enter(&sc->sc_mutex); 231 sc->sc_dying = true; 232 /* If this is true we are still open, destroy the condvar */ 233 if (sc->sc_opened) { 234 mutex_enter(&sc->sc_dying_mutex); 235 DPRINTF(sc, 2, ("%s: Will wait for anything to exit\n", 236 device_xname(sc->sc_dev))); 237 /* In the worst case this will time out after 5 seconds. 238 * It really should not take that long for the drain / whatever 239 * to happen 240 */ 241 cv_timedwait_sig(&sc->sc_cond_dying, 242 &sc->sc_dying_mutex, mstohz(5000)); 243 mutex_exit(&sc->sc_dying_mutex); 244 cv_destroy(&sc->sc_cond_dying); 245 } 246 cv_destroy(&sc->sc_condvar); 247 mutex_exit(&sc->sc_mutex); 248 249 mutex_destroy(&sc->sc_mutex); 250 mutex_destroy(&sc->sc_condmutex); 251 252 return 0; 253 } 254 255 int 256 scmdspi_activate(device_t self, enum devact act) 257 { 258 struct scmd_sc *sc = device_private(self); 259 260 switch (act) { 261 case DVACT_DEACTIVATE: 262 sc->sc_dying = true; 263 return 0; 264 default: 265 return EOPNOTSUPP; 266 } 267 } 268