1 /* $NetBSD: imxspi.c,v 1.3 2017/08/07 09:24:43 hkenken Exp $ */ 2 3 /*- 4 * Copyright (c) 2014 Genetec Corporation. All rights reserved. 5 * Written by Hashimoto Kenichi for Genetec Corporation. 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 GENETEC CORPORATION ``AS IS'' AND 17 * 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 GENETEC CORPORATION 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * this module support CSPI and eCSPI. 31 * i.MX51 have 2 eCSPI and 1 CSPI modules. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1.3 2017/08/07 09:24:43 hkenken Exp $"); 36 37 #include "opt_imx.h" 38 #include "opt_imxspi.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/device.h> 44 #include <sys/errno.h> 45 #include <sys/proc.h> 46 #include <sys/intr.h> 47 48 #include <sys/bus.h> 49 #include <machine/cpu.h> 50 #include <machine/intr.h> 51 52 #include <arm/imx/imxspivar.h> 53 #include <arm/imx/imxspireg.h> 54 55 /* SPI service routines */ 56 static int imxspi_configure_enhanced(void *, int, int, int); 57 static int imxspi_configure(void *, int, int, int); 58 static int imxspi_transfer(void *, struct spi_transfer *); 59 static int imxspi_intr(void *); 60 61 /* internal stuff */ 62 void imxspi_done(struct imxspi_softc *, int); 63 void imxspi_send(struct imxspi_softc *); 64 void imxspi_recv(struct imxspi_softc *); 65 void imxspi_sched(struct imxspi_softc *); 66 67 #define IMXSPI(x) \ 68 ((sc->sc_enhanced) ? __CONCAT(ECSPI_, x) : __CONCAT(CSPI_, x)) 69 #define READ_REG(sc, x) \ 70 bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXSPI(x)) 71 #define WRITE_REG(sc, x, v) \ 72 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXSPI(x), (v)) 73 74 #ifdef IMXSPI_DEBUG 75 int imxspi_debug = IMXSPI_DEBUG; 76 #define DPRINTFN(n,x) if (imxspi_debug>(n)) printf x; 77 #else 78 #define DPRINTFN(n,x) 79 #endif 80 81 int 82 imxspi_attach_common(device_t parent, struct imxspi_softc *sc, void *aux) 83 { 84 struct imxspi_attach_args *saa = aux; 85 struct spibus_attach_args sba; 86 bus_addr_t addr = saa->saa_addr; 87 bus_size_t size = saa->saa_size; 88 89 sc->sc_iot = saa->saa_iot; 90 sc->sc_freq = saa->saa_freq; 91 sc->sc_tag = saa->saa_tag; 92 sc->sc_enhanced = saa->saa_enhanced; 93 if (size <= 0) 94 size = SPI_SIZE; 95 96 if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) { 97 aprint_error_dev(sc->sc_dev, "couldn't map registers\n"); 98 return 1; 99 } 100 101 aprint_normal(": i.MX %sCSPI Controller (clock %ld Hz)\n", 102 ((sc->sc_enhanced) ? "e" : ""), sc->sc_freq); 103 104 /* Initialize SPI controller */ 105 sc->sc_spi.sct_cookie = sc; 106 if (sc->sc_enhanced) 107 sc->sc_spi.sct_configure = imxspi_configure_enhanced; 108 else 109 sc->sc_spi.sct_configure = imxspi_configure; 110 sc->sc_spi.sct_transfer = imxspi_transfer; 111 112 /* sc->sc_spi.sct_nslaves must have been initialized by machdep code */ 113 sc->sc_spi.sct_nslaves = saa->saa_nslaves; 114 if (!sc->sc_spi.sct_nslaves) 115 aprint_error_dev(sc->sc_dev, "no slaves!\n"); 116 117 sba.sba_controller = &sc->sc_spi; 118 119 /* initialize the queue */ 120 SIMPLEQ_INIT(&sc->sc_q); 121 122 /* configure SPI */ 123 /* Setup Control Register */ 124 WRITE_REG(sc, CONREG, __SHIFTIN(0, IMXSPI(CON_DRCTL)) | 125 __SHIFTIN(8 - 1, IMXSPI(CON_BITCOUNT)) | 126 __SHIFTIN(0xf, IMXSPI(CON_MODE)) | IMXSPI(CON_ENABLE)); 127 128 /* TC and RR interruption */ 129 WRITE_REG(sc, INTREG, (IMXSPI(INTR_TC_EN) | IMXSPI(INTR_RR_EN))); 130 WRITE_REG(sc, STATREG, IMXSPI(STAT_CLR)); 131 132 WRITE_REG(sc, PERIODREG, 0x0); 133 134 /* enable device interrupts */ 135 sc->sc_ih = intr_establish(saa->saa_irq, IPL_BIO, IST_LEVEL, 136 imxspi_intr, sc); 137 138 /* attach slave devices */ 139 (void)config_found_ia(sc->sc_dev, "spibus", &sba, spibus_print); 140 141 return 0; 142 } 143 144 static int 145 imxspi_configure(void *arg, int slave, int mode, int speed) 146 { 147 struct imxspi_softc *sc = arg; 148 uint32_t div_cnt = 0; 149 uint32_t div; 150 uint32_t contrl = 0; 151 152 div = (sc->sc_freq + (speed - 1)) / speed; 153 div = div - 1; 154 for (div_cnt = 0; div > 0; div_cnt++) 155 div >>= 1; 156 157 div_cnt = div_cnt - 2; 158 if (div_cnt >= 7) 159 div_cnt = 7; 160 161 contrl = READ_REG(sc, CONREG); 162 contrl &= ~CSPI_CON_DIV; 163 contrl |= __SHIFTIN(div_cnt, CSPI_CON_DIV); 164 165 contrl &= ~(CSPI_CON_POL | CSPI_CON_PHA); 166 switch (mode) { 167 case SPI_MODE_0: 168 /* CPHA = 0, CPOL = 0 */ 169 break; 170 case SPI_MODE_1: 171 /* CPHA = 1, CPOL = 0 */ 172 contrl |= CSPI_CON_PHA; 173 break; 174 case SPI_MODE_2: 175 /* CPHA = 0, CPOL = 1 */ 176 contrl |= CSPI_CON_POL; 177 break; 178 case SPI_MODE_3: 179 /* CPHA = 1, CPOL = 1 */ 180 contrl |= CSPI_CON_POL; 181 contrl |= CSPI_CON_PHA; 182 break; 183 default: 184 return EINVAL; 185 } 186 WRITE_REG(sc, CONREG, contrl); 187 188 DPRINTFN(3, ("%s: slave %d mode %d speed %d\n", 189 __func__, slave, mode, speed)); 190 191 return 0; 192 } 193 194 static int 195 imxspi_configure_enhanced(void *arg, int slave, int mode, int speed) 196 { 197 struct imxspi_softc *sc = arg; 198 uint32_t div_cnt = 0; 199 uint32_t div; 200 uint32_t contrl = 0; 201 uint32_t config = 0; 202 203 div = (sc->sc_freq + (speed - 1)) / speed; 204 for (div_cnt = 0; div > 0; div_cnt++) 205 div >>= 1; 206 207 if (div_cnt >= 15) 208 div_cnt = 15; 209 210 contrl = READ_REG(sc, CONREG); 211 contrl |= __SHIFTIN(div_cnt, ECSPI_CON_DIV); 212 contrl |= __SHIFTIN(slave, ECSPI_CON_CS); 213 contrl |= __SHIFTIN(__BIT(slave), ECSPI_CON_MODE); 214 WRITE_REG(sc, CONREG, contrl); 215 216 config = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ECSPI_CONFIGREG); 217 config &= ~(__SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL) | 218 __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA)); 219 switch (mode) { 220 case SPI_MODE_0: 221 /* CPHA = 0, CPOL = 0 */ 222 break; 223 case SPI_MODE_1: 224 /* CPHA = 1, CPOL = 0 */ 225 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA); 226 break; 227 case SPI_MODE_2: 228 /* CPHA = 0, CPOL = 1 */ 229 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL); 230 break; 231 case SPI_MODE_3: 232 /* CPHA = 1, CPOL = 1 */ 233 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA); 234 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL); 235 break; 236 default: 237 return EINVAL; 238 } 239 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SSB_CTL); 240 bus_space_write_4(sc->sc_iot, sc->sc_ioh, ECSPI_CONFIGREG, config); 241 242 DPRINTFN(3, ("%s: slave %d mode %d speed %d\n", 243 __func__, slave, mode, speed)); 244 245 return 0; 246 } 247 248 void 249 imxspi_send(struct imxspi_softc *sc) 250 { 251 uint32_t data; 252 struct spi_chunk *chunk; 253 254 /* fill the fifo */ 255 while ((chunk = sc->sc_wchunk) != NULL) { 256 while (chunk->chunk_wresid) { 257 /* transmit fifo full? */ 258 if (READ_REG(sc, STATREG) & IMXSPI(STAT_TF)) 259 goto out; 260 261 if (chunk->chunk_wptr) { 262 data = *chunk->chunk_wptr; 263 chunk->chunk_wptr++; 264 } else { 265 data = 0xff; 266 } 267 chunk->chunk_wresid--; 268 269 WRITE_REG(sc, TXDATA, data); 270 } 271 /* advance to next transfer */ 272 sc->sc_wchunk = sc->sc_wchunk->chunk_next; 273 } 274 out: 275 if (!(READ_REG(sc, STATREG) & IMXSPI(INTR_TE_EN))) 276 WRITE_REG(sc, CONREG, READ_REG(sc, CONREG) | IMXSPI(CON_XCH)); 277 } 278 279 void 280 imxspi_recv(struct imxspi_softc *sc) 281 { 282 uint32_t data; 283 struct spi_chunk *chunk; 284 285 while ((chunk = sc->sc_rchunk) != NULL) { 286 while (chunk->chunk_rresid) { 287 /* rx fifo empty? */ 288 if ((!(READ_REG(sc, STATREG) & IMXSPI(STAT_RR)))) 289 return; 290 291 /* collect rx data */ 292 data = READ_REG(sc, RXDATA); 293 if (chunk->chunk_rptr) { 294 *chunk->chunk_rptr = data & 0xff; 295 chunk->chunk_rptr++; 296 } 297 298 chunk->chunk_rresid--; 299 } 300 /* advance next to next transfer */ 301 sc->sc_rchunk = sc->sc_rchunk->chunk_next; 302 } 303 } 304 305 306 void 307 imxspi_sched(struct imxspi_softc *sc) 308 { 309 struct spi_transfer *st; 310 uint32_t chipselect; 311 312 while ((st = spi_transq_first(&sc->sc_q)) != NULL) { 313 /* remove the item */ 314 spi_transq_dequeue(&sc->sc_q); 315 316 /* note that we are working on it */ 317 sc->sc_transfer = st; 318 319 /* chip slect */ 320 if (sc->sc_tag->spi_cs_enable != NULL) 321 sc->sc_tag->spi_cs_enable(sc->sc_tag->cookie, 322 st->st_slave); 323 324 /* chip slect */ 325 chipselect = READ_REG(sc, CONREG); 326 chipselect &= ~IMXSPI(CON_CS); 327 chipselect |= __SHIFTIN(st->st_slave, IMXSPI(CON_CS)); 328 WRITE_REG(sc, CONREG, chipselect); 329 330 delay(1); 331 332 /* setup chunks */ 333 sc->sc_rchunk = sc->sc_wchunk = st->st_chunks; 334 335 /* now kick the master start to get the chip running */ 336 imxspi_send(sc); 337 338 sc->sc_running = TRUE; 339 return; 340 } 341 342 DPRINTFN(2, ("%s: nothing to do anymore\n", __func__)); 343 sc->sc_running = FALSE; 344 } 345 346 void 347 imxspi_done(struct imxspi_softc *sc, int err) 348 { 349 struct spi_transfer *st; 350 351 /* called from interrupt handler */ 352 if ((st = sc->sc_transfer) != NULL) { 353 if (sc->sc_tag->spi_cs_disable != NULL) 354 sc->sc_tag->spi_cs_disable(sc->sc_tag->cookie, 355 st->st_slave); 356 357 sc->sc_transfer = NULL; 358 spi_done(st, err); 359 } 360 /* make sure we clear these bits out */ 361 sc->sc_wchunk = sc->sc_rchunk = NULL; 362 imxspi_sched(sc); 363 } 364 365 static int 366 imxspi_intr(void *arg) 367 { 368 struct imxspi_softc *sc = arg; 369 uint32_t intr, sr; 370 int err = 0; 371 372 if ((intr = READ_REG(sc, INTREG)) == 0) { 373 /* interrupts are not enabled, get out */ 374 DPRINTFN(4, ("%s: interrupts are not enabled\n", __func__)); 375 return 0; 376 } 377 378 sr = READ_REG(sc, STATREG); 379 if (!(sr & intr)) { 380 /* interrupt did not happen, get out */ 381 DPRINTFN(3, ("%s: interrupts did not happen\n", __func__)); 382 return 0; 383 } 384 385 /* RXFIFO ready? */ 386 if (sr & IMXSPI(INTR_RR_EN)) { 387 imxspi_recv(sc); 388 if (sc->sc_wchunk == NULL && sc->sc_rchunk == NULL) 389 imxspi_done(sc, err); 390 } 391 392 /* Transfer Conplete? */ 393 if (sr & IMXSPI(INTR_TC_EN)) { 394 /* complete TX */ 395 imxspi_send(sc); 396 } 397 398 /* status register clear */ 399 WRITE_REG(sc, STATREG, sr); 400 401 return 1; 402 } 403 404 int 405 imxspi_transfer(void *arg, struct spi_transfer *st) 406 { 407 struct imxspi_softc *sc = arg; 408 int s; 409 410 /* make sure we select the right chip */ 411 s = splbio(); 412 spi_transq_enqueue(&sc->sc_q, st); 413 if (sc->sc_running == FALSE) 414 imxspi_sched(sc); 415 splx(s); 416 417 return 0; 418 } 419 420