1 /* $NetBSD: bcm2835_spi.c,v 1.4 2015/07/29 14:22:49 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 2012 Jonathan A. Kollasch 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: bcm2835_spi.c,v 1.4 2015/07/29 14:22:49 skrll Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/device.h> 34 #include <sys/systm.h> 35 #include <sys/mutex.h> 36 #include <sys/bus.h> 37 #include <sys/intr.h> 38 #include <sys/kernel.h> 39 40 #include <sys/bitops.h> 41 #include <dev/spi/spivar.h> 42 43 #include <arm/broadcom/bcm_amba.h> 44 #include <arm/broadcom/bcm2835reg.h> 45 #include <arm/broadcom/bcm2835_spireg.h> 46 #include <arm/broadcom/bcm2835_gpio_subr.h> 47 48 struct bcmspi_softc { 49 device_t sc_dev; 50 bus_space_tag_t sc_iot; 51 bus_space_handle_t sc_ioh; 52 bus_size_t sc_ios; 53 void *sc_intrh; 54 struct spi_controller sc_spi; 55 SIMPLEQ_HEAD(,spi_transfer) sc_q; 56 struct spi_transfer *sc_transfer; 57 struct spi_chunk *sc_wchunk; 58 struct spi_chunk *sc_rchunk; 59 uint32_t sc_CS; 60 volatile bool sc_running; 61 }; 62 63 static int bcmspi_match(device_t, cfdata_t, void *); 64 static void bcmspi_attach(device_t, device_t, void *); 65 66 static int bcmspi_configure(void *, int, int, int); 67 static int bcmspi_transfer(void *, struct spi_transfer *); 68 69 static void bcmspi_start(struct bcmspi_softc * const); 70 static int bcmspi_intr(void *); 71 72 static void bcmspi_send(struct bcmspi_softc * const); 73 static void bcmspi_recv(struct bcmspi_softc * const); 74 75 CFATTACH_DECL_NEW(bcmspi, sizeof(struct bcmspi_softc), 76 bcmspi_match, bcmspi_attach, NULL, NULL); 77 78 static int 79 bcmspi_match(device_t parent, cfdata_t cf, void *aux) 80 { 81 struct amba_attach_args * const aaa = aux; 82 83 if (strcmp(aaa->aaa_name, "bcmspi") != 0) 84 return 0; 85 86 return 1; 87 } 88 89 static void 90 bcmspi_attach(device_t parent, device_t self, void *aux) 91 { 92 struct amba_attach_args * const aaa = aux; 93 struct bcmspi_softc * const sc = device_private(self); 94 struct spibus_attach_args sba; 95 96 aprint_naive("\n"); 97 aprint_normal(": SPI\n"); 98 99 sc->sc_dev = self; 100 SIMPLEQ_INIT(&sc->sc_q); 101 sc->sc_iot = aaa->aaa_iot; 102 if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, aaa->aaa_size, 0, 103 &sc->sc_ioh) != 0) { 104 aprint_error_dev(sc->sc_dev, "unable to map device\n"); 105 return; 106 } 107 sc->sc_ios = aaa->aaa_size; 108 109 for (u_int pin = 7; pin <= 11; pin++) 110 bcm2835gpio_function_select(pin, BCM2835_GPIO_ALT0); 111 112 sc->sc_intrh = intr_establish(aaa->aaa_intr, IPL_VM, IST_LEVEL, 113 bcmspi_intr, sc); 114 if (sc->sc_intrh == NULL) { 115 aprint_error_dev(sc->sc_dev, "unable to establish interrupt\n"); 116 return; 117 } 118 119 sc->sc_spi.sct_cookie = sc; 120 sc->sc_spi.sct_configure = bcmspi_configure; 121 sc->sc_spi.sct_transfer = bcmspi_transfer; 122 sc->sc_spi.sct_nslaves = 3; 123 124 sba.sba_controller = &sc->sc_spi; 125 126 (void) config_found_ia(self, "spibus", &sba, spibus_print); 127 } 128 129 static int 130 bcmspi_configure(void *cookie, int slave, int mode, int speed) 131 { 132 struct bcmspi_softc * const sc = cookie; 133 uint32_t cs, clk; 134 135 cs = SPI_CS_INTR | SPI_CS_INTD; 136 137 if (slave > 2) 138 return EINVAL; 139 140 if (speed <= 0) 141 return EINVAL; 142 143 switch (mode) { 144 case SPI_MODE_0: 145 cs |= 0; 146 break; 147 case SPI_MODE_1: 148 cs |= SPI_CS_CPHA; 149 break; 150 case SPI_MODE_2: 151 cs |= SPI_CS_CPOL; 152 break; 153 case SPI_MODE_3: 154 cs |= SPI_CS_CPHA|SPI_CS_CPOL; 155 break; 156 default: 157 return EINVAL; 158 } 159 160 sc->sc_CS = cs; 161 162 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_CS, cs); 163 164 clk = 2 * 250000000 / speed; /* XXX 250MHz */ 165 clk = (clk / 2) + (clk & 1); 166 clk = roundup(clk, 2); 167 clk = __SHIFTIN(clk, SPI_CLK_CDIV); 168 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_CLK, clk); 169 170 return 0; 171 } 172 173 static int 174 bcmspi_transfer(void *cookie, struct spi_transfer *st) 175 { 176 struct bcmspi_softc * const sc = cookie; 177 int s; 178 179 s = splbio(); 180 spi_transq_enqueue(&sc->sc_q, st); 181 if (sc->sc_running == false) { 182 bcmspi_start(sc); 183 } 184 splx(s); 185 return 0; 186 } 187 188 static void 189 bcmspi_start(struct bcmspi_softc * const sc) 190 { 191 struct spi_transfer *st; 192 uint32_t cs; 193 194 while ((st = spi_transq_first(&sc->sc_q)) != NULL) { 195 196 spi_transq_dequeue(&sc->sc_q); 197 198 KASSERT(sc->sc_transfer == NULL); 199 sc->sc_transfer = st; 200 sc->sc_rchunk = sc->sc_wchunk = st->st_chunks; 201 202 cs = sc->sc_CS; 203 cs |= SPI_CS_TA; 204 cs |= SPI_CS_CLEAR_TX; 205 cs |= SPI_CS_CLEAR_RX; 206 KASSERT(st->st_slave <= 2); 207 cs |= __SHIFTIN(st->st_slave, SPI_CS_CS); 208 sc->sc_running = true; 209 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_CS, cs); 210 211 if (!cold) 212 return; 213 214 int s = splbio(); 215 for (;;) { 216 bcmspi_intr(sc); 217 if (ISSET(st->st_flags, SPI_F_DONE)) 218 break; 219 } 220 splx(s); 221 } 222 223 sc->sc_running = false; 224 } 225 226 static void 227 bcmspi_send(struct bcmspi_softc * const sc) 228 { 229 uint32_t fd; 230 uint32_t cs; 231 struct spi_chunk *chunk; 232 233 while ((chunk = sc->sc_wchunk) != NULL) { 234 while (chunk->chunk_wresid) { 235 cs = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SPI_CS); 236 if ((cs & SPI_CS_TXD) == 0) 237 return; 238 if (chunk->chunk_wptr) { 239 fd = *chunk->chunk_wptr++; 240 } else { 241 fd = '\0'; 242 } 243 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_FIFO, fd); 244 chunk->chunk_wresid--; 245 } 246 sc->sc_wchunk = sc->sc_wchunk->chunk_next; 247 } 248 } 249 250 static void 251 bcmspi_recv(struct bcmspi_softc * const sc) 252 { 253 uint32_t fd; 254 uint32_t cs; 255 struct spi_chunk *chunk; 256 257 while ((chunk = sc->sc_rchunk) != NULL) { 258 while (chunk->chunk_rresid) { 259 cs = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SPI_CS); 260 if ((cs & SPI_CS_RXD) == 0) 261 return; 262 fd = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SPI_FIFO); 263 if (chunk->chunk_rptr) { 264 *chunk->chunk_rptr++ = fd & 0xff; 265 } 266 chunk->chunk_rresid--; 267 } 268 sc->sc_rchunk = sc->sc_rchunk->chunk_next; 269 } 270 } 271 272 static int 273 bcmspi_intr(void *cookie) 274 { 275 struct bcmspi_softc * const sc = cookie; 276 struct spi_transfer *st; 277 uint32_t cs; 278 279 cs = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SPI_CS); 280 if (ISSET(cs, SPI_CS_DONE)) { 281 if (sc->sc_wchunk != NULL) { 282 bcmspi_send(sc); 283 goto end; 284 } else { 285 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_CS, 286 sc->sc_CS); 287 bcmspi_recv(sc); 288 sc->sc_rchunk = sc->sc_wchunk = NULL; 289 st = sc->sc_transfer; 290 sc->sc_transfer = NULL; 291 KASSERT(st != NULL); 292 spi_done(st, 0); 293 sc->sc_running = false; 294 goto end; 295 } 296 } else if (ISSET(cs, SPI_CS_RXR)) { 297 bcmspi_recv(sc); 298 bcmspi_send(sc); 299 } 300 301 end: 302 return ISSET(cs, SPI_CS_DONE|SPI_CS_RXR); 303 } 304