1 /* $NetBSD: imxspi.c,v 1.6 2019/09/27 02:59:21 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.6 2019/09/27 02:59:21 hkenken Exp $"); 36 37 #include "opt_imxspi.h" 38 #include "opt_fdt.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 #ifdef FDT 56 #include <dev/fdt/fdtvar.h> 57 #endif 58 59 /* SPI service routines */ 60 static int imxspi_configure_enhanced(void *, int, int, int); 61 static int imxspi_configure(void *, int, int, int); 62 static int imxspi_transfer(void *, struct spi_transfer *); 63 64 /* internal stuff */ 65 void imxspi_done(struct imxspi_softc *, int); 66 void imxspi_send(struct imxspi_softc *); 67 void imxspi_recv(struct imxspi_softc *); 68 void imxspi_sched(struct imxspi_softc *); 69 70 #define IMXCSPI_TYPE(type, x) \ 71 ((sc->sc_type == IMX31_CSPI) ? __CONCAT(CSPI_IMX31_, x) : \ 72 (sc->sc_type == IMX35_CSPI) ? __CONCAT(CSPI_IMX35_, x) : 0) 73 #define IMXCSPI(x) __CONCAT(CSPI_, x) 74 #define IMXESPI(x) __CONCAT(ECSPI_, x) 75 #define IMXSPI(x) ((sc->sc_enhanced) ? IMXESPI(x) : IMXCSPI(x)) 76 #define IMXSPI_TYPE(x) ((sc->sc_enhanced) ? IMXESPI(x) : IMXCSPI_TYPE(sc->sc_type, x)) 77 #define READ_REG(sc, x) \ 78 bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXSPI(x)) 79 #define WRITE_REG(sc, x, v) \ 80 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXSPI(x), (v)) 81 82 #ifdef IMXSPI_DEBUG 83 int imxspi_debug = IMXSPI_DEBUG; 84 #define DPRINTFN(n,x) if (imxspi_debug>(n)) printf x; 85 #else 86 #define DPRINTFN(n,x) 87 #endif 88 89 #ifdef FDT 90 static struct spi_controller * 91 imxspi_get_controller(device_t dev) 92 { 93 struct imxspi_softc * const sc = device_private(dev); 94 95 return &sc->sc_spi; 96 } 97 98 static const struct fdtbus_spi_controller_func imxspi_funcs = { 99 .get_controller = imxspi_get_controller 100 }; 101 #endif 102 103 int 104 imxspi_attach_common(device_t self) 105 { 106 struct imxspi_softc * const sc = device_private(self); 107 108 aprint_normal("i.MX %sCSPI Controller (clock %ld Hz)\n", 109 ((sc->sc_enhanced) ? "e" : ""), sc->sc_freq); 110 111 /* Initialize SPI controller */ 112 sc->sc_dev = self; 113 sc->sc_spi.sct_cookie = sc; 114 if (sc->sc_enhanced) 115 sc->sc_spi.sct_configure = imxspi_configure_enhanced; 116 else 117 sc->sc_spi.sct_configure = imxspi_configure; 118 sc->sc_spi.sct_transfer = imxspi_transfer; 119 120 /* sc->sc_spi.sct_nslaves must have been initialized by machdep code */ 121 sc->sc_spi.sct_nslaves = sc->sc_nslaves; 122 if (!sc->sc_spi.sct_nslaves) 123 aprint_error_dev(sc->sc_dev, "no slaves!\n"); 124 125 /* initialize the queue */ 126 SIMPLEQ_INIT(&sc->sc_q); 127 128 /* configure SPI */ 129 /* Setup Control Register */ 130 WRITE_REG(sc, CONREG, 131 __SHIFTIN(0, IMXSPI_TYPE(CON_DRCTL)) | 132 __SHIFTIN(8 - 1, IMXSPI_TYPE(CON_BITCOUNT)) | 133 __SHIFTIN(0xf, IMXSPI(CON_MODE)) | IMXSPI(CON_ENABLE)); 134 /* TC and RR interruption */ 135 WRITE_REG(sc, INTREG, (IMXSPI_TYPE(INTR_TC_EN) | IMXSPI(INTR_RR_EN))); 136 WRITE_REG(sc, STATREG, IMXSPI_TYPE(STAT_CLR)); 137 138 WRITE_REG(sc, PERIODREG, 0x0); 139 140 #ifdef FDT 141 KASSERT(sc->sc_phandle != 0); 142 143 fdtbus_register_spi_controller(self, sc->sc_phandle, &imxspi_funcs); 144 (void) fdtbus_attach_spibus(self, sc->sc_phandle, spibus_print); 145 #else 146 struct spibus_attach_args sba; 147 memset(&sba, 0, sizeof(sba)); 148 sba.sba_controller = &sc->sc_spi; 149 150 /* attach slave devices */ 151 (void)config_found_ia(sc->sc_dev, "spibus", &sba, spibus_print); 152 #endif 153 154 return 0; 155 } 156 157 static int 158 imxspi_configure(void *arg, int slave, int mode, int speed) 159 { 160 struct imxspi_softc *sc = arg; 161 uint32_t div_cnt = 0; 162 uint32_t div; 163 uint32_t contrl = 0; 164 165 div = (sc->sc_freq + (speed - 1)) / speed; 166 div = div - 1; 167 for (div_cnt = 0; div > 0; div_cnt++) 168 div >>= 1; 169 170 div_cnt = div_cnt - 2; 171 if (div_cnt >= 7) 172 div_cnt = 7; 173 174 contrl = READ_REG(sc, CONREG); 175 contrl &= ~CSPI_CON_DIV; 176 contrl |= __SHIFTIN(div_cnt, CSPI_CON_DIV); 177 178 contrl &= ~(CSPI_CON_POL | CSPI_CON_PHA); 179 switch (mode) { 180 case SPI_MODE_0: 181 /* CPHA = 0, CPOL = 0 */ 182 break; 183 case SPI_MODE_1: 184 /* CPHA = 1, CPOL = 0 */ 185 contrl |= CSPI_CON_PHA; 186 break; 187 case SPI_MODE_2: 188 /* CPHA = 0, CPOL = 1 */ 189 contrl |= CSPI_CON_POL; 190 break; 191 case SPI_MODE_3: 192 /* CPHA = 1, CPOL = 1 */ 193 contrl |= CSPI_CON_POL; 194 contrl |= CSPI_CON_PHA; 195 break; 196 default: 197 return EINVAL; 198 } 199 WRITE_REG(sc, CONREG, contrl); 200 201 DPRINTFN(3, ("%s: slave %d mode %d speed %d\n", 202 __func__, slave, mode, speed)); 203 204 return 0; 205 } 206 207 static int 208 imxspi_configure_enhanced(void *arg, int slave, int mode, int speed) 209 { 210 struct imxspi_softc *sc = arg; 211 uint32_t div_cnt = 0; 212 uint32_t div; 213 uint32_t contrl = 0; 214 uint32_t config = 0; 215 216 div = (sc->sc_freq + (speed - 1)) / speed; 217 for (div_cnt = 0; div > 0; div_cnt++) 218 div >>= 1; 219 220 if (div_cnt >= 15) 221 div_cnt = 15; 222 223 contrl = READ_REG(sc, CONREG); 224 contrl |= __SHIFTIN(div_cnt, ECSPI_CON_DIV); 225 contrl |= __SHIFTIN(slave, ECSPI_CON_CS); 226 contrl |= __SHIFTIN(__BIT(slave), ECSPI_CON_MODE); 227 WRITE_REG(sc, CONREG, contrl); 228 229 config = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ECSPI_CONFIGREG); 230 config &= ~(__SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL) | 231 __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA)); 232 switch (mode) { 233 case SPI_MODE_0: 234 /* CPHA = 0, CPOL = 0 */ 235 break; 236 case SPI_MODE_1: 237 /* CPHA = 1, CPOL = 0 */ 238 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA); 239 break; 240 case SPI_MODE_2: 241 /* CPHA = 0, CPOL = 1 */ 242 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL); 243 break; 244 case SPI_MODE_3: 245 /* CPHA = 1, CPOL = 1 */ 246 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA); 247 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL); 248 break; 249 default: 250 return EINVAL; 251 } 252 config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SSB_CTL); 253 bus_space_write_4(sc->sc_iot, sc->sc_ioh, ECSPI_CONFIGREG, config); 254 255 DPRINTFN(3, ("%s: slave %d mode %d speed %d\n", 256 __func__, slave, mode, speed)); 257 258 return 0; 259 } 260 261 void 262 imxspi_send(struct imxspi_softc *sc) 263 { 264 uint32_t data; 265 struct spi_chunk *chunk; 266 267 /* fill the fifo */ 268 while ((chunk = sc->sc_wchunk) != NULL) { 269 while (chunk->chunk_wresid) { 270 /* transmit fifo full? */ 271 if (READ_REG(sc, STATREG) & IMXSPI(STAT_TF)) 272 goto out; 273 274 if (chunk->chunk_wptr) { 275 data = *chunk->chunk_wptr; 276 chunk->chunk_wptr++; 277 } else { 278 data = 0xff; 279 } 280 chunk->chunk_wresid--; 281 282 WRITE_REG(sc, TXDATA, data); 283 } 284 /* advance to next transfer */ 285 sc->sc_wchunk = sc->sc_wchunk->chunk_next; 286 } 287 out: 288 if (!(READ_REG(sc, STATREG) & IMXSPI(INTR_TE_EN))) 289 WRITE_REG(sc, CONREG, READ_REG(sc, CONREG) | IMXSPI(CON_XCH)); 290 } 291 292 void 293 imxspi_recv(struct imxspi_softc *sc) 294 { 295 uint32_t data; 296 struct spi_chunk *chunk; 297 298 while ((chunk = sc->sc_rchunk) != NULL) { 299 while (chunk->chunk_rresid) { 300 /* rx fifo empty? */ 301 if ((!(READ_REG(sc, STATREG) & IMXSPI(STAT_RR)))) 302 return; 303 304 /* collect rx data */ 305 data = READ_REG(sc, RXDATA); 306 if (chunk->chunk_rptr) { 307 *chunk->chunk_rptr = data & 0xff; 308 chunk->chunk_rptr++; 309 } 310 311 chunk->chunk_rresid--; 312 } 313 /* advance next to next transfer */ 314 sc->sc_rchunk = sc->sc_rchunk->chunk_next; 315 } 316 } 317 318 319 void 320 imxspi_sched(struct imxspi_softc *sc) 321 { 322 struct spi_transfer *st; 323 uint32_t chipselect; 324 325 while ((st = spi_transq_first(&sc->sc_q)) != NULL) { 326 /* remove the item */ 327 spi_transq_dequeue(&sc->sc_q); 328 329 /* note that we are working on it */ 330 sc->sc_transfer = st; 331 332 /* chip slect */ 333 if (sc->sc_tag->spi_cs_enable != NULL) 334 sc->sc_tag->spi_cs_enable(sc->sc_tag->cookie, 335 st->st_slave); 336 337 /* chip slect */ 338 chipselect = READ_REG(sc, CONREG); 339 chipselect &= ~IMXSPI_TYPE(CON_CS); 340 chipselect |= __SHIFTIN(st->st_slave, IMXSPI_TYPE(CON_CS)); 341 WRITE_REG(sc, CONREG, chipselect); 342 343 delay(1); 344 345 /* setup chunks */ 346 sc->sc_rchunk = sc->sc_wchunk = st->st_chunks; 347 348 /* now kick the master start to get the chip running */ 349 imxspi_send(sc); 350 351 sc->sc_running = TRUE; 352 return; 353 } 354 355 DPRINTFN(2, ("%s: nothing to do anymore\n", __func__)); 356 sc->sc_running = FALSE; 357 } 358 359 void 360 imxspi_done(struct imxspi_softc *sc, int err) 361 { 362 struct spi_transfer *st; 363 364 /* called from interrupt handler */ 365 if ((st = sc->sc_transfer) != NULL) { 366 if (sc->sc_tag->spi_cs_disable != NULL) 367 sc->sc_tag->spi_cs_disable(sc->sc_tag->cookie, 368 st->st_slave); 369 370 sc->sc_transfer = NULL; 371 spi_done(st, err); 372 } 373 /* make sure we clear these bits out */ 374 sc->sc_wchunk = sc->sc_rchunk = NULL; 375 imxspi_sched(sc); 376 } 377 378 int 379 imxspi_intr(void *arg) 380 { 381 struct imxspi_softc *sc = arg; 382 uint32_t intr, sr; 383 int err = 0; 384 385 if ((intr = READ_REG(sc, INTREG)) == 0) { 386 /* interrupts are not enabled, get out */ 387 DPRINTFN(4, ("%s: interrupts are not enabled\n", __func__)); 388 return 0; 389 } 390 391 sr = READ_REG(sc, STATREG); 392 if (!(sr & intr)) { 393 /* interrupt did not happen, get out */ 394 DPRINTFN(3, ("%s: interrupts did not happen\n", __func__)); 395 return 0; 396 } 397 398 /* RXFIFO ready? */ 399 if (sr & IMXSPI(INTR_RR_EN)) { 400 imxspi_recv(sc); 401 if (sc->sc_wchunk == NULL && sc->sc_rchunk == NULL) 402 imxspi_done(sc, err); 403 } 404 405 /* Transfer Complete? */ 406 if (sr & IMXSPI_TYPE(INTR_TC_EN)) 407 imxspi_send(sc); 408 409 /* status register clear */ 410 WRITE_REG(sc, STATREG, sr); 411 412 return 1; 413 } 414 415 int 416 imxspi_transfer(void *arg, struct spi_transfer *st) 417 { 418 struct imxspi_softc *sc = arg; 419 int s; 420 421 /* make sure we select the right chip */ 422 s = splbio(); 423 spi_transq_enqueue(&sc->sc_q, st); 424 if (sc->sc_running == FALSE) 425 imxspi_sched(sc); 426 splx(s); 427 428 return 0; 429 } 430 431