1 /* $Id: at91spi.c,v 1.2 2008/07/03 01:15:38 matt Exp $ */ 2 /* $NetBSD: at91spi.c,v 1.2 2008/07/03 01:15:38 matt Exp $ */ 3 4 /*- 5 * Copyright (c) 2007 Embedtronics Oy. All rights reserved. 6 * 7 * Based on arch/mips/alchemy/dev/auspi.c, 8 * Copyright (c) 2006 Urbana-Champaign Independent Media Center. 9 * Copyright (c) 2006 Garrett D'Amore. 10 * All rights reserved. 11 * 12 * Portions of this code were written by Garrett D'Amore for the 13 * Champaign-Urbana Community Wireless Network Project. 14 * 15 * Redistribution and use in source and binary forms, with or 16 * without modification, are permitted provided that the following 17 * conditions are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials provided 23 * with the distribution. 24 * 3. All advertising materials mentioning features or use of this 25 * software must display the following acknowledgements: 26 * This product includes software developed by the Urbana-Champaign 27 * Independent Media Center. 28 * This product includes software developed by Garrett D'Amore. 29 * 4. Urbana-Champaign Independent Media Center's name and Garrett 30 * D'Amore's name may not be used to endorse or promote products 31 * derived from this software without specific prior written permission. 32 * 33 * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT 34 * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR 35 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 36 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT 38 * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT, 39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 40 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 41 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 42 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 43 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 45 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 */ 47 48 #include <sys/cdefs.h> 49 __KERNEL_RCSID(0, "$NetBSD: at91spi.c,v 1.2 2008/07/03 01:15:38 matt Exp $"); 50 51 #include "locators.h" 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/kernel.h> 56 #include <sys/device.h> 57 #include <sys/errno.h> 58 #include <sys/proc.h> 59 60 #include <machine/bus.h> 61 #include <machine/cpu.h> 62 #include <machine/vmparam.h> 63 #include <sys/inttypes.h> 64 65 #include <arm/at91/at91var.h> 66 #include <arm/at91/at91reg.h> 67 #include <arm/at91/at91spivar.h> 68 #include <arm/at91/at91spireg.h> 69 70 #define at91spi_select(sc, slave) \ 71 (sc)->sc_md->select_slave((sc), (slave)) 72 73 #define STATIC 74 75 //#define AT91SPI_DEBUG 4 76 77 #ifdef AT91SPI_DEBUG 78 int at91spi_debug = AT91SPI_DEBUG; 79 #define DPRINTFN(n,x) if (at91spi_debug>(n)) printf x; 80 #else 81 #define DPRINTFN(n,x) 82 #endif 83 84 STATIC int at91spi_intr(void *); 85 86 /* SPI service routines */ 87 STATIC int at91spi_configure(void *, int, int, int); 88 STATIC int at91spi_transfer(void *, struct spi_transfer *); 89 STATIC void at91spi_xfer(struct at91spi_softc *sc, int start); 90 91 /* internal stuff */ 92 STATIC void at91spi_done(struct at91spi_softc *, int); 93 STATIC void at91spi_send(struct at91spi_softc *); 94 STATIC void at91spi_recv(struct at91spi_softc *); 95 STATIC void at91spi_sched(struct at91spi_softc *); 96 97 #define GETREG(sc, x) \ 98 bus_space_read_4(sc->sc_iot, sc->sc_ioh, x) 99 #define PUTREG(sc, x, v) \ 100 bus_space_write_4(sc->sc_iot, sc->sc_ioh, x, v) 101 102 void 103 at91spi_attach_common(device_t parent, device_t self, void *aux, 104 at91spi_machdep_tag_t md) 105 { 106 struct at91spi_softc *sc = device_private(self); 107 struct at91bus_attach_args *sa = aux; 108 struct spibus_attach_args sba; 109 bus_dma_segment_t segs; 110 int rsegs, err; 111 112 aprint_normal(": AT91 SPI Controller\n"); 113 114 sc->sc_dev = self; 115 sc->sc_iot = sa->sa_iot; 116 sc->sc_pid = sa->sa_pid; 117 sc->sc_dmat = sa->sa_dmat; 118 sc->sc_md = md; 119 120 if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh)) 121 panic("%s: Cannot map registers", device_xname(self)); 122 123 /* we want to use dma, so allocate dma memory: */ 124 err = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, 0, PAGE_SIZE, 125 &segs, 1, &rsegs, BUS_DMA_WAITOK); 126 if (err == 0) { 127 err = bus_dmamem_map(sc->sc_dmat, &segs, 1, PAGE_SIZE, 128 &sc->sc_dmapage, 129 BUS_DMA_WAITOK); 130 } 131 if (err == 0) { 132 err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, 133 PAGE_SIZE, 0, BUS_DMA_WAITOK, 134 &sc->sc_dmamap); 135 } 136 if (err == 0) { 137 err = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, 138 sc->sc_dmapage, PAGE_SIZE, NULL, 139 BUS_DMA_WAITOK); 140 } 141 if (err != 0) { 142 panic("%s: Cannot get DMA memory", device_xname(sc->sc_dev)); 143 } 144 sc->sc_dmaaddr = sc->sc_dmamap->dm_segs[0].ds_addr; 145 146 /* 147 * Initialize SPI controller 148 */ 149 sc->sc_spi.sct_cookie = sc; 150 sc->sc_spi.sct_configure = at91spi_configure; 151 sc->sc_spi.sct_transfer = at91spi_transfer; 152 153 //sc->sc_spi.sct_nslaves must have been initialized by machdep code 154 if (!sc->sc_spi.sct_nslaves) { 155 aprint_error("%s: no slaves!\n", device_xname(sc->sc_dev)); 156 } 157 158 sba.sba_controller = &sc->sc_spi; 159 160 /* initialize the queue */ 161 SIMPLEQ_INIT(&sc->sc_q); 162 163 /* reset the SPI */ 164 at91_peripheral_clock(sc->sc_pid, 1); 165 PUTREG(sc, SPI_CR, SPI_CR_SWRST); 166 delay(100); 167 168 /* be paranoid and make sure the PDC is dead */ 169 PUTREG(sc, SPI_PDC_BASE + PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); 170 PUTREG(sc, SPI_PDC_BASE + PDC_RNCR, 0); 171 PUTREG(sc, SPI_PDC_BASE + PDC_RCR, 0); 172 PUTREG(sc, SPI_PDC_BASE + PDC_TNCR, 0); 173 PUTREG(sc, SPI_PDC_BASE + PDC_TCR, 0); 174 175 // configure SPI: 176 PUTREG(sc, SPI_IDR, -1); 177 PUTREG(sc, SPI_CSR(0), SPI_CSR_SCBR | SPI_CSR_BITS_8); 178 PUTREG(sc, SPI_CSR(1), SPI_CSR_SCBR | SPI_CSR_BITS_8); 179 PUTREG(sc, SPI_CSR(2), SPI_CSR_SCBR | SPI_CSR_BITS_8); 180 PUTREG(sc, SPI_CSR(3), SPI_CSR_SCBR | SPI_CSR_BITS_8); 181 PUTREG(sc, SPI_MR, SPI_MR_MODFDIS/* <- machdep? */ | SPI_MR_MSTR); 182 183 /* enable device interrupts */ 184 sc->sc_ih = at91_intr_establish(sc->sc_pid, IPL_BIO, INTR_HIGH_LEVEL, 185 at91spi_intr, sc); 186 187 /* enable SPI */ 188 PUTREG(sc, SPI_CR, SPI_CR_SPIEN); 189 if (GETREG(sc, SPI_SR) & SPI_SR_RDRF) 190 (void)GETREG(sc, SPI_RDR); 191 192 PUTREG(sc, SPI_PDC_BASE + PDC_PTCR, PDC_PTCR_TXTEN | PDC_PTCR_RXTEN); 193 194 /* attach slave devices */ 195 (void) config_found_ia(sc->sc_dev, "spibus", &sba, spibus_print); 196 } 197 198 int 199 at91spi_configure(void *arg, int slave, int mode, int speed) 200 { 201 struct at91spi_softc *sc = arg; 202 uint scbr; 203 uint32_t csr; 204 205 /* setup interrupt registers */ 206 PUTREG(sc, SPI_IDR, -1); /* disable interrupts for now */ 207 208 csr = GETREG(sc, SPI_CSR(0)); /* read register */ 209 csr &= SPI_CSR_RESERVED; /* keep reserved bits */ 210 csr |= SPI_CSR_BITS_8; /* assume 8 bit transfers */ 211 212 /* 213 * Calculate clock divider 214 */ 215 scbr = speed ? ((AT91_MSTCLK + speed - 1) / speed + 1) & ~1 : -1; 216 if (scbr > 0xFF) { 217 aprint_error("%s: speed %d not supported\n", 218 device_xname(sc->sc_dev), speed); 219 return EINVAL; 220 } 221 csr |= scbr << SPI_CSR_SCBR_SHIFT; 222 223 /* 224 * I'm not entirely confident that these values are correct. 225 * But at least mode 0 appears to work properly with the 226 * devices I have tested. The documentation seems to suggest 227 * that I have the meaning of the clock delay bit inverted. 228 */ 229 switch (mode) { 230 case SPI_MODE_0: 231 csr |= SPI_CSR_NCPHA; /* CPHA = 0, CPOL = 0 */ 232 break; 233 case SPI_MODE_1: 234 csr |= 0; /* CPHA = 1, CPOL = 0 */ 235 break; 236 case SPI_MODE_2: 237 csr |= SPI_CSR_NCPHA /* CPHA = 0, CPOL = 1 */ 238 | SPI_CSR_CPOL; 239 break; 240 case SPI_MODE_3: 241 csr |= SPI_CSR_CPOL; /* CPHA = 1, CPOL = 1 */ 242 break; 243 default: 244 return EINVAL; 245 } 246 247 PUTREG(sc, SPI_CSR(0), csr); 248 249 DPRINTFN(3, ("%s: slave %d mode %d speed %d, csr=0x%08"PRIX32"\n", 250 __FUNCTION__, slave, mode, speed, csr)); 251 252 #if 0 253 // wait until ready!? 254 for (i = 1000000; i; i -= 10) { 255 if (GETREG(sc, AUPSC_SPISTAT) & SPISTAT_DR) { 256 return 0; 257 } 258 } 259 260 return ETIMEDOUT; 261 #else 262 return 0; 263 #endif 264 } 265 266 #define HALF_BUF_SIZE (PAGE_SIZE / 2) 267 268 void 269 at91spi_xfer(struct at91spi_softc *sc, int start) 270 { 271 struct spi_chunk *chunk; 272 int len; 273 uint32_t sr; 274 275 DPRINTFN(3, ("%s: sc=%p start=%d\n", __FUNCTION__, sc, start)); 276 277 /* so ready to transmit more / anything received? */ 278 if (((sr = GETREG(sc, SPI_SR)) & (SPI_SR_ENDTX | SPI_SR_ENDRX)) != (SPI_SR_ENDTX | SPI_SR_ENDRX)) { 279 /* not ready, get out */ 280 DPRINTFN(3, ("%s: sc=%p start=%d sr=%"PRIX32"\n", __FUNCTION__, sc, start, sr)); 281 return; 282 } 283 284 DPRINTFN(3, ("%s: sr=%"PRIX32"\n", __FUNCTION__, sr)); 285 286 if (!start) { 287 // ok, something has been transfered, synchronize.. 288 int offs = sc->sc_dmaoffs ^ HALF_BUF_SIZE; 289 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, offs, HALF_BUF_SIZE, 290 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 291 292 if ((chunk = sc->sc_rchunk) != NULL) { 293 if ((len = chunk->chunk_rresid) > HALF_BUF_SIZE) 294 len = HALF_BUF_SIZE; 295 if (chunk->chunk_rptr && len > 0) { 296 memcpy(chunk->chunk_rptr, (const uint8_t *)sc->sc_dmapage + offs, len); 297 chunk->chunk_rptr += len; 298 } 299 if ((chunk->chunk_rresid -= len) <= 0) { 300 // done with this chunk, get next 301 sc->sc_rchunk = chunk->chunk_next; 302 } 303 } 304 } 305 306 /* start transmitting next chunk: */ 307 if ((chunk = sc->sc_wchunk) != NULL) { 308 309 /* make sure we transmit just half buffer at a time */ 310 len = MIN(chunk->chunk_wresid, HALF_BUF_SIZE); 311 312 // setup outgoing data 313 if (chunk->chunk_wptr && len > 0) { 314 memcpy((uint8_t *)sc->sc_dmapage + sc->sc_dmaoffs, chunk->chunk_wptr, len); 315 chunk->chunk_wptr += len; 316 } else { 317 memset((uint8_t *)sc->sc_dmapage + sc->sc_dmaoffs, 0, len); 318 } 319 320 /* advance to next transfer if it's time to */ 321 if ((chunk->chunk_wresid -= len) <= 0) { 322 sc->sc_wchunk = sc->sc_wchunk->chunk_next; 323 } 324 325 /* determine which interrupt to get */ 326 if (sc->sc_wchunk) { 327 /* just wait for next buffer to free */ 328 PUTREG(sc, SPI_IER, SPI_SR_ENDRX); 329 } else { 330 /* must wait until transfer has completed */ 331 PUTREG(sc, SPI_IDR, SPI_SR_ENDRX); 332 PUTREG(sc, SPI_IER, SPI_SR_RXBUFF); 333 } 334 335 DPRINTFN(3, ("%s: dmaoffs=%d len=%d wchunk=%p (%p:%d) rchunk=%p (%p:%d) mr=%"PRIX32" sr=%"PRIX32" imr=%"PRIX32" csr0=%"PRIX32"\n", 336 __FUNCTION__, sc->sc_dmaoffs, len, sc->sc_wchunk, 337 sc->sc_wchunk ? sc->sc_wchunk->chunk_wptr : NULL, 338 sc->sc_wchunk ? sc->sc_wchunk->chunk_wresid : -1, 339 sc->sc_rchunk, 340 sc->sc_rchunk ? sc->sc_rchunk->chunk_rptr : NULL, 341 sc->sc_rchunk ? sc->sc_rchunk->chunk_rresid : -1, 342 GETREG(sc, SPI_MR), GETREG(sc, SPI_SR), 343 GETREG(sc, SPI_IMR), GETREG(sc, SPI_CSR(0)))); 344 345 // prepare DMA 346 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_dmaoffs, len, 347 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 348 349 // and start transmitting / receiving 350 PUTREG(sc, SPI_PDC_BASE + PDC_RNPR, sc->sc_dmaaddr + sc->sc_dmaoffs); 351 PUTREG(sc, SPI_PDC_BASE + PDC_RNCR, len); 352 PUTREG(sc, SPI_PDC_BASE + PDC_TNPR, sc->sc_dmaaddr + sc->sc_dmaoffs); 353 PUTREG(sc, SPI_PDC_BASE + PDC_TNCR, len); 354 355 // swap buffer 356 sc->sc_dmaoffs ^= HALF_BUF_SIZE; 357 358 // get out 359 return; 360 } else { 361 DPRINTFN(3, ("%s: nothing to write anymore\n", __FUNCTION__)); 362 return; 363 } 364 } 365 366 void 367 at91spi_sched(struct at91spi_softc *sc) 368 { 369 struct spi_transfer *st; 370 int err; 371 372 while ((st = spi_transq_first(&sc->sc_q)) != NULL) { 373 374 DPRINTFN(2, ("%s: st=%p\n", __FUNCTION__, st)); 375 376 /* remove the item */ 377 spi_transq_dequeue(&sc->sc_q); 378 379 /* note that we are working on it */ 380 sc->sc_transfer = st; 381 382 if ((err = at91spi_select(sc, st->st_slave)) != 0) { 383 spi_done(st, err); 384 continue; 385 } 386 387 /* setup chunks */ 388 sc->sc_rchunk = sc->sc_wchunk = st->st_chunks; 389 390 /* now kick the master start to get the chip running */ 391 at91spi_xfer(sc, TRUE); 392 393 /* enable error interrupts too: */ 394 PUTREG(sc, SPI_IER, SPI_SR_MODF | SPI_SR_OVRES); 395 396 sc->sc_running = TRUE; 397 return; 398 } 399 DPRINTFN(2, ("%s: nothing to do anymore\n", __FUNCTION__)); 400 PUTREG(sc, SPI_IDR, -1); /* disable interrupts */ 401 at91spi_select(sc, -1); 402 sc->sc_running = FALSE; 403 } 404 405 void 406 at91spi_done(struct at91spi_softc *sc, int err) 407 { 408 struct spi_transfer *st; 409 410 /* called from interrupt handler */ 411 if ((st = sc->sc_transfer) != NULL) { 412 sc->sc_transfer = NULL; 413 DPRINTFN(2, ("%s: st %p finished with error code %d\n", __FUNCTION__, st, err)); 414 spi_done(st, err); 415 } 416 /* make sure we clear these bits out */ 417 sc->sc_wchunk = sc->sc_rchunk = NULL; 418 at91spi_sched(sc); 419 } 420 421 int 422 at91spi_intr(void *arg) 423 { 424 struct at91spi_softc *sc = arg; 425 uint32_t imr, sr; 426 int err = 0; 427 428 if ((imr = GETREG(sc, SPI_IMR)) == 0) { 429 /* interrupts are not enabled, get out */ 430 DPRINTFN(4, ("%s: interrupts are not enabled\n", __FUNCTION__)); 431 return 0; 432 } 433 434 sr = GETREG(sc, SPI_SR); 435 if (!(sr & imr)) { 436 /* interrupt did not happen, get out */ 437 DPRINTFN(3, ("%s: interrupts are not enabled, sr=%08"PRIX32" imr=%08"PRIX32"\n", 438 __FUNCTION__, sr, imr)); 439 return 0; 440 } 441 442 DPRINTFN(3, ("%s: sr=%08"PRIX32" imr=%08"PRIX32"\n", 443 __FUNCTION__, sr, imr)); 444 445 if (sr & imr & SPI_SR_MODF) { 446 printf("%s: mode fault!\n", device_xname(sc->sc_dev)); 447 err = EIO; 448 } 449 450 if (sr & imr & SPI_SR_OVRES) { 451 printf("%s: overrun error!\n", device_xname(sc->sc_dev)); 452 err = EIO; 453 } 454 if (err) { 455 /* clear errors */ 456 /* complete transfer */ 457 at91spi_done(sc, err); 458 } else { 459 /* do all data exchanges */ 460 at91spi_xfer(sc, FALSE); 461 462 /* 463 * if the master done bit is set, make sure we do the 464 * right processing. 465 */ 466 if (sr & imr & SPI_SR_RXBUFF) { 467 if ((sc->sc_wchunk != NULL) || 468 (sc->sc_rchunk != NULL)) { 469 printf("%s: partial transfer?\n", 470 device_xname(sc->sc_dev)); 471 err = EIO; 472 } 473 at91spi_done(sc, err); 474 } 475 476 } 477 478 return 1; 479 } 480 481 int 482 at91spi_transfer(void *arg, struct spi_transfer *st) 483 { 484 struct at91spi_softc *sc = arg; 485 int s; 486 487 /* make sure we select the right chip */ 488 s = splbio(); 489 spi_transq_enqueue(&sc->sc_q, st); 490 if (sc->sc_running == 0) { 491 at91spi_sched(sc); 492 } 493 splx(s); 494 return 0; 495 } 496 497