1 /* $NetBSD: tegra_apbdma.c,v 1.4 2017/09/23 23:58:18 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2017 Jared D. McNeill <jmcneill@invisible.ca> 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: tegra_apbdma.c,v 1.4 2017/09/23 23:58:18 jmcneill Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/device.h> 35 #include <sys/intr.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 39 #include <arm/nvidia/tegra_reg.h> 40 #include <arm/nvidia/tegra_apbdmareg.h> 41 #include <arm/nvidia/tegra_var.h> 42 43 #include <dev/fdt/fdtvar.h> 44 45 #define TEGRA_APBDMA_NCHAN 32 46 47 static void * tegra_apbdma_acquire(device_t, const void *, size_t, 48 void (*)(void *), void *); 49 static void tegra_apbdma_release(device_t, void *); 50 static int tegra_apbdma_transfer(device_t, void *, 51 struct fdtbus_dma_req *); 52 static void tegra_apbdma_halt(device_t, void *); 53 54 static const struct fdtbus_dma_controller_func tegra_apbdma_funcs = { 55 .acquire = tegra_apbdma_acquire, 56 .release = tegra_apbdma_release, 57 .transfer = tegra_apbdma_transfer, 58 .halt = tegra_apbdma_halt 59 }; 60 61 static int tegra_apbdma_match(device_t, cfdata_t, void *); 62 static void tegra_apbdma_attach(device_t, device_t, void *); 63 64 static int tegra_apbdma_intr(void *); 65 66 struct tegra_apbdma_softc; 67 68 struct tegra_apbdma_chan { 69 struct tegra_apbdma_softc *ch_sc; 70 u_int ch_n; 71 void *ch_ih; 72 void (*ch_cb)(void *); 73 void *ch_cbarg; 74 u_int ch_req; 75 }; 76 77 struct tegra_apbdma_softc { 78 device_t sc_dev; 79 bus_space_tag_t sc_bst; 80 bus_space_handle_t sc_bsh; 81 int sc_phandle; 82 83 struct tegra_apbdma_chan sc_chan[TEGRA_APBDMA_NCHAN]; 84 }; 85 86 CFATTACH_DECL_NEW(tegra_apbdma, sizeof(struct tegra_apbdma_softc), 87 tegra_apbdma_match, tegra_apbdma_attach, NULL, NULL); 88 89 #define APBDMA_READ(sc, reg) \ 90 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 91 #define APBDMA_WRITE(sc, reg, val) \ 92 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 93 94 static int 95 tegra_apbdma_match(device_t parent, cfdata_t cf, void *aux) 96 { 97 const char * const compatible[] = { 98 "nvidia,tegra210-apbdma", 99 "nvidia,tegra124-apbdma", 100 NULL 101 }; 102 struct fdt_attach_args * const faa = aux; 103 104 return of_match_compatible(faa->faa_phandle, compatible); 105 } 106 107 static void 108 tegra_apbdma_attach(device_t parent, device_t self, void *aux) 109 { 110 struct tegra_apbdma_softc *sc = device_private(self); 111 struct fdt_attach_args * const faa = aux; 112 const int phandle = faa->faa_phandle; 113 struct fdtbus_reset *rst; 114 struct clk *clk; 115 bus_addr_t addr; 116 bus_size_t size; 117 int error; 118 u_int n; 119 120 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 121 aprint_error(": couldn't get registers\n"); 122 return; 123 } 124 125 clk = fdtbus_clock_get_index(phandle, 0); 126 if (clk == NULL) { 127 aprint_error(": couldn't get clock\n"); 128 return; 129 } 130 rst = fdtbus_reset_get(phandle, "dma"); 131 if (rst == NULL) { 132 aprint_error(": couldn't get reset dma\n"); 133 return; 134 } 135 136 fdtbus_reset_assert(rst); 137 error = clk_enable(clk); 138 if (error) { 139 aprint_error(": couldn't enable clock dma: %d\n", error); 140 return; 141 } 142 fdtbus_reset_deassert(rst); 143 144 sc->sc_dev = self; 145 sc->sc_bst = faa->faa_bst; 146 sc->sc_phandle = phandle; 147 error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); 148 if (error) { 149 aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error); 150 return; 151 } 152 for (n = 0; n < TEGRA_APBDMA_NCHAN; n++) { 153 sc->sc_chan[n].ch_sc = sc; 154 sc->sc_chan[n].ch_n = n; 155 } 156 157 aprint_naive("\n"); 158 aprint_normal(": APBDMA\n"); 159 160 /* Stop all channels */ 161 for (n = 0; n < TEGRA_APBDMA_NCHAN; n++) 162 APBDMA_WRITE(sc, APBDMACHAN_CSR_REG(n), 0); 163 164 /* Mask interrupts */ 165 APBDMA_WRITE(sc, APBDMA_IRQ_MASK_REG, 0); 166 167 /* Global enable */ 168 APBDMA_WRITE(sc, APBDMA_COMMAND_REG, APBDMA_COMMAND_GEN); 169 170 fdtbus_register_dma_controller(self, phandle, &tegra_apbdma_funcs); 171 } 172 173 static int 174 tegra_apbdma_intr(void *priv) 175 { 176 struct tegra_apbdma_chan *ch = priv; 177 struct tegra_apbdma_softc *sc = ch->ch_sc; 178 const u_int n = ch->ch_n; 179 uint32_t sta; 180 181 sta = APBDMA_READ(sc, APBDMACHAN_STA_REG(n)); 182 APBDMA_WRITE(sc, APBDMACHAN_STA_REG(n), sta); /* clear EOC */ 183 184 ch->ch_cb(ch->ch_cbarg); 185 186 return 1; 187 } 188 189 static void * 190 tegra_apbdma_acquire(device_t dev, const void *data, size_t len, 191 void (*cb)(void *), void *cbarg) 192 { 193 struct tegra_apbdma_softc *sc = device_private(dev); 194 struct tegra_apbdma_chan *ch; 195 u_int n; 196 char intrstr[128]; 197 198 if (len != 4) 199 return NULL; 200 201 const u_int req = be32dec(data); 202 if (req > __SHIFTOUT_MASK(APBDMACHAN_CSR_REQ_SEL)) 203 return NULL; 204 205 for (n = 0; n < TEGRA_APBDMA_NCHAN; n++) { 206 ch = &sc->sc_chan[n]; 207 if (ch->ch_ih == NULL) 208 break; 209 } 210 if (n >= TEGRA_APBDMA_NCHAN) { 211 aprint_error_dev(dev, "no free DMA channel\n"); 212 return NULL; 213 } 214 215 if (!fdtbus_intr_str(sc->sc_phandle, n, intrstr, sizeof(intrstr))) { 216 aprint_error_dev(dev, "failed to decode interrupt %u\n", n); 217 return NULL; 218 } 219 220 ch->ch_ih = fdtbus_intr_establish(sc->sc_phandle, n, IPL_VM, 221 FDT_INTR_MPSAFE, tegra_apbdma_intr, ch); 222 if (ch->ch_ih == NULL) { 223 aprint_error_dev(dev, "failed to establish interrupt on %s\n", 224 intrstr); 225 return NULL; 226 } 227 aprint_normal_dev(dev, "interrupting on %s (channel %u)\n", intrstr, n); 228 229 ch->ch_cb = cb; 230 ch->ch_cbarg = cbarg; 231 ch->ch_req = req; 232 233 /* Unmask interrupts for this channel */ 234 APBDMA_WRITE(sc, APBDMA_IRQ_MASK_SET_REG, __BIT(n)); 235 236 return ch; 237 } 238 static void 239 tegra_apbdma_release(device_t dev, void *priv) 240 { 241 struct tegra_apbdma_softc *sc = device_private(dev); 242 struct tegra_apbdma_chan *ch = priv; 243 const u_int n = ch->ch_n; 244 245 KASSERT(ch->ch_ih != NULL); 246 247 /* Halt the channel */ 248 APBDMA_WRITE(sc, APBDMACHAN_CSR_REG(n), 0); 249 250 /* Mask interrupts for this channel */ 251 APBDMA_WRITE(sc, APBDMA_IRQ_MASK_CLR_REG, __BIT(n)); 252 253 fdtbus_intr_disestablish(sc->sc_phandle, ch->ch_ih); 254 255 ch->ch_cb = NULL; 256 ch->ch_cbarg = NULL; 257 } 258 259 static int 260 tegra_apbdma_transfer(device_t dev, void *priv, struct fdtbus_dma_req *req) 261 262 { 263 struct tegra_apbdma_softc *sc = device_private(dev); 264 struct tegra_apbdma_chan *ch = priv; 265 const u_int n = ch->ch_n; 266 uint32_t csr = 0; 267 uint32_t csre = 0; 268 uint32_t ahb_seq = 0; 269 uint32_t apb_seq = 0; 270 271 /* Scatter-gather not supported */ 272 if (req->dreq_nsegs != 1) 273 return EINVAL; 274 275 /* Addresses must be aligned to 32-bits */ 276 if ((req->dreq_segs[0].ds_addr & 3) != 0 || 277 (req->dreq_dev_phys & 3) != 0) 278 return EINVAL; 279 280 /* Length must be a multiple of 32-bits */ 281 if ((req->dreq_segs[0].ds_len & 3) != 0) 282 return EINVAL; 283 284 csr |= __SHIFTIN(ch->ch_req, APBDMACHAN_CSR_REQ_SEL); 285 286 /* 287 * Set DMA transfer direction. 288 * APBDMACHAN_CSR_DIR=0 means "APB read to AHB write", and 289 * APBDMACHAN_CSR_DIR=1 means "AHB read to APB write". 290 */ 291 if (req->dreq_dir == FDT_DMA_WRITE) 292 csr |= APBDMACHAN_CSR_DIR; 293 294 /* 295 * Generate interrupt when DMA block transfer completes. 296 */ 297 if (req->dreq_block_irq) 298 csr |= APBDMACHAN_CSR_IE_EOC; 299 300 /* 301 * Single or multiple block transfer 302 */ 303 if (!req->dreq_block_multi) 304 csr |= APBDMACHAN_CSR_ONCE; 305 306 /* 307 * Flow control enable 308 */ 309 if (req->dreq_flow) 310 csr |= APBDMACHAN_CSR_FLOW; 311 312 /* 313 * Route interrupt to CPU. 1 = CPU, 0 = COP 314 */ 315 ahb_seq |= APBDMACHAN_AHB_SEQ_INTR_ENB; 316 317 /* 318 * AHB is a 32-bit bus. 319 */ 320 if (req->dreq_mem_opt.opt_bus_width != 32) 321 return EINVAL; 322 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_BUS_WIDTH_32, 323 APBDMACHAN_AHB_SEQ_BUS_WIDTH); 324 325 /* 326 * AHB data swap. 327 */ 328 if (req->dreq_mem_opt.opt_swap) 329 ahb_seq |= APBDMACHAN_AHB_SEQ_DATA_SWAP; 330 331 /* 332 * AHB burst size. 333 */ 334 switch (req->dreq_mem_opt.opt_burst_len) { 335 case 32: 336 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_BURST_1, 337 APBDMACHAN_AHB_SEQ_BURST); 338 break; 339 case 128: 340 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_BURST_4, 341 APBDMACHAN_AHB_SEQ_BURST); 342 break; 343 case 256: 344 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_BURST_8, 345 APBDMACHAN_AHB_SEQ_BURST); 346 break; 347 default: 348 return EINVAL; 349 } 350 351 /* 352 * 2X double buffering mode. Only supported in run-multiple mode 353 * with no-wrap operations. 354 */ 355 if (req->dreq_mem_opt.opt_dblbuf) { 356 if (req->dreq_mem_opt.opt_wrap_len != 0) 357 return EINVAL; 358 if (!req->dreq_block_multi) 359 return EINVAL; 360 ahb_seq |= APBDMACHAN_AHB_SEQ_DBL_BUF; 361 } 362 363 /* 364 * AHB address wrap. 365 */ 366 switch (req->dreq_mem_opt.opt_wrap_len) { 367 case 0: 368 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_WRAP_NO_WRAP, 369 APBDMACHAN_AHB_SEQ_WRAP); 370 break; 371 case 128: 372 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_WRAP_32, 373 APBDMACHAN_AHB_SEQ_WRAP); 374 break; 375 case 256: 376 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_WRAP_64, 377 APBDMACHAN_AHB_SEQ_WRAP); 378 break; 379 case 512: 380 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_WRAP_128, 381 APBDMACHAN_AHB_SEQ_WRAP); 382 break; 383 case 1024: 384 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_WRAP_256, 385 APBDMACHAN_AHB_SEQ_WRAP); 386 break; 387 case 2048: 388 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_WRAP_512, 389 APBDMACHAN_AHB_SEQ_WRAP); 390 break; 391 case 4096: 392 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_WRAP_1024, 393 APBDMACHAN_AHB_SEQ_WRAP); 394 break; 395 case 8192: 396 ahb_seq |= __SHIFTIN(APBDMACHAN_AHB_SEQ_WRAP_2048, 397 APBDMACHAN_AHB_SEQ_WRAP); 398 break; 399 default: 400 return EINVAL; 401 } 402 403 /* 404 * APB bus width. 405 */ 406 switch (req->dreq_dev_opt.opt_bus_width) { 407 case 8: 408 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_BUS_WIDTH_8, 409 APBDMACHAN_APB_SEQ_BUS_WIDTH); 410 break; 411 case 16: 412 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_BUS_WIDTH_16, 413 APBDMACHAN_APB_SEQ_BUS_WIDTH); 414 break; 415 case 32: 416 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_BUS_WIDTH_32, 417 APBDMACHAN_APB_SEQ_BUS_WIDTH); 418 break; 419 default: 420 return EINVAL; 421 } 422 423 /* 424 * APB data swap. 425 */ 426 if (req->dreq_dev_opt.opt_swap) 427 apb_seq |= APBDMACHAN_APB_SEQ_DATA_SWAP; 428 429 /* 430 * APB address wrap-around window. 431 */ 432 switch (req->dreq_dev_opt.opt_wrap_len) { 433 case 0: 434 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_WRAP_NO_WRAP, 435 APBDMACHAN_APB_SEQ_WRAP); 436 break; 437 case 4: 438 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_WRAP_1, 439 APBDMACHAN_APB_SEQ_WRAP); 440 break; 441 case 8: 442 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_WRAP_2, 443 APBDMACHAN_APB_SEQ_WRAP); 444 break; 445 case 16: 446 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_WRAP_4, 447 APBDMACHAN_APB_SEQ_WRAP); 448 break; 449 case 32: 450 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_WRAP_8, 451 APBDMACHAN_APB_SEQ_WRAP); 452 break; 453 case 64: 454 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_WRAP_16, 455 APBDMACHAN_APB_SEQ_WRAP); 456 break; 457 case 128: 458 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_WRAP_32, 459 APBDMACHAN_APB_SEQ_WRAP); 460 break; 461 case 256: 462 apb_seq |= __SHIFTIN(APBDMACHAN_APB_SEQ_WRAP_64, 463 APBDMACHAN_APB_SEQ_WRAP); 464 break; 465 default: 466 return EINVAL; 467 } 468 469 /* 470 * Program all channel registers before setting the channel enable bit. 471 */ 472 APBDMA_WRITE(sc, APBDMACHAN_AHB_PTR_REG(n), req->dreq_segs[0].ds_addr); 473 APBDMA_WRITE(sc, APBDMACHAN_APB_PTR_REG(n), req->dreq_dev_phys); 474 APBDMA_WRITE(sc, APBDMACHAN_AHB_SEQ_REG(n), ahb_seq); 475 APBDMA_WRITE(sc, APBDMACHAN_APB_SEQ_REG(n), apb_seq); 476 APBDMA_WRITE(sc, APBDMACHAN_WCOUNT_REG(n), req->dreq_segs[0].ds_len); 477 APBDMA_WRITE(sc, APBDMACHAN_CSRE_REG(n), csre); 478 APBDMA_WRITE(sc, APBDMACHAN_CSR_REG(n), csr | APBDMACHAN_CSR_ENB); 479 480 return 0; 481 } 482 483 static void 484 tegra_apbdma_halt(device_t dev, void *priv) 485 { 486 struct tegra_apbdma_softc *sc = device_private(dev); 487 struct tegra_apbdma_chan *ch = priv; 488 const u_int n = ch->ch_n; 489 uint32_t v; 490 491 v = APBDMA_READ(sc, APBDMACHAN_CSR_REG(n)); 492 v &= ~APBDMACHAN_CSR_ENB; 493 APBDMA_WRITE(sc, APBDMACHAN_CSR_REG(n), v); 494 } 495