1 /* 2 * DMA support use of SYS DMAC with SDHI SD/SDIO controller 3 * 4 * Copyright (C) 2016-17 Renesas Electronics Corporation 5 * Copyright (C) 2016-17 Sang Engineering, Wolfram Sang 6 * Copyright (C) 2017 Horms Solutions, Simon Horman 7 * Copyright (C) 2010-2011 Guennadi Liakhovetski 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/device.h> 15 #include <linux/dma-mapping.h> 16 #include <linux/dmaengine.h> 17 #include <linux/mfd/tmio.h> 18 #include <linux/mmc/host.h> 19 #include <linux/mod_devicetable.h> 20 #include <linux/module.h> 21 #include <linux/of_device.h> 22 #include <linux/pagemap.h> 23 #include <linux/scatterlist.h> 24 #include <linux/sys_soc.h> 25 26 #include "renesas_sdhi.h" 27 #include "tmio_mmc.h" 28 29 #define TMIO_MMC_MIN_DMA_LEN 8 30 31 static const struct renesas_sdhi_of_data of_default_cfg = { 32 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, 33 }; 34 35 static const struct renesas_sdhi_of_data of_rz_compatible = { 36 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_32BIT_DATA_PORT | 37 TMIO_MMC_HAVE_CBSY, 38 .tmio_ocr_mask = MMC_VDD_32_33, 39 .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, 40 }; 41 42 static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = { 43 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | 44 TMIO_MMC_CLK_ACTUAL, 45 .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, 46 }; 47 48 /* Definitions for sampling clocks */ 49 static struct renesas_sdhi_scc rcar_gen2_scc_taps[] = { 50 { 51 .clk_rate = 156000000, 52 .tap = 0x00000703, 53 }, 54 { 55 .clk_rate = 0, 56 .tap = 0x00000300, 57 }, 58 }; 59 60 static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = { 61 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | 62 TMIO_MMC_CLK_ACTUAL | TMIO_MMC_HAVE_CBSY | 63 TMIO_MMC_MIN_RCAR2, 64 .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | 65 MMC_CAP_CMD23, 66 .dma_buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES, 67 .dma_rx_offset = 0x2000, 68 .scc_offset = 0x0300, 69 .taps = rcar_gen2_scc_taps, 70 .taps_num = ARRAY_SIZE(rcar_gen2_scc_taps), 71 }; 72 73 /* Definitions for sampling clocks */ 74 static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { 75 { 76 .clk_rate = 0, 77 .tap = 0x00000300, 78 }, 79 }; 80 81 static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { 82 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | 83 TMIO_MMC_CLK_ACTUAL | TMIO_MMC_HAVE_CBSY | 84 TMIO_MMC_MIN_RCAR2, 85 .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | 86 MMC_CAP_CMD23, 87 .bus_shift = 2, 88 .scc_offset = 0x1000, 89 .taps = rcar_gen3_scc_taps, 90 .taps_num = ARRAY_SIZE(rcar_gen3_scc_taps), 91 }; 92 93 static const struct of_device_id renesas_sdhi_sys_dmac_of_match[] = { 94 { .compatible = "renesas,sdhi-shmobile" }, 95 { .compatible = "renesas,sdhi-sh73a0", .data = &of_default_cfg, }, 96 { .compatible = "renesas,sdhi-r8a73a4", .data = &of_default_cfg, }, 97 { .compatible = "renesas,sdhi-r8a7740", .data = &of_default_cfg, }, 98 { .compatible = "renesas,sdhi-r7s72100", .data = &of_rz_compatible, }, 99 { .compatible = "renesas,sdhi-r8a7778", .data = &of_rcar_gen1_compatible, }, 100 { .compatible = "renesas,sdhi-r8a7779", .data = &of_rcar_gen1_compatible, }, 101 { .compatible = "renesas,sdhi-r8a7743", .data = &of_rcar_gen2_compatible, }, 102 { .compatible = "renesas,sdhi-r8a7745", .data = &of_rcar_gen2_compatible, }, 103 { .compatible = "renesas,sdhi-r8a7790", .data = &of_rcar_gen2_compatible, }, 104 { .compatible = "renesas,sdhi-r8a7791", .data = &of_rcar_gen2_compatible, }, 105 { .compatible = "renesas,sdhi-r8a7792", .data = &of_rcar_gen2_compatible, }, 106 { .compatible = "renesas,sdhi-r8a7793", .data = &of_rcar_gen2_compatible, }, 107 { .compatible = "renesas,sdhi-r8a7794", .data = &of_rcar_gen2_compatible, }, 108 { .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_gen3_compatible, }, 109 { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, }, 110 {}, 111 }; 112 MODULE_DEVICE_TABLE(of, renesas_sdhi_sys_dmac_of_match); 113 114 static void renesas_sdhi_sys_dmac_enable_dma(struct tmio_mmc_host *host, 115 bool enable) 116 { 117 if (!host->chan_tx || !host->chan_rx) 118 return; 119 120 if (host->dma->enable) 121 host->dma->enable(host, enable); 122 } 123 124 static void renesas_sdhi_sys_dmac_abort_dma(struct tmio_mmc_host *host) 125 { 126 renesas_sdhi_sys_dmac_enable_dma(host, false); 127 128 if (host->chan_rx) 129 dmaengine_terminate_all(host->chan_rx); 130 if (host->chan_tx) 131 dmaengine_terminate_all(host->chan_tx); 132 133 renesas_sdhi_sys_dmac_enable_dma(host, true); 134 } 135 136 static void renesas_sdhi_sys_dmac_dataend_dma(struct tmio_mmc_host *host) 137 { 138 complete(&host->dma_dataend); 139 } 140 141 static void renesas_sdhi_sys_dmac_dma_callback(void *arg) 142 { 143 struct tmio_mmc_host *host = arg; 144 145 spin_lock_irq(&host->lock); 146 147 if (!host->data) 148 goto out; 149 150 if (host->data->flags & MMC_DATA_READ) 151 dma_unmap_sg(host->chan_rx->device->dev, 152 host->sg_ptr, host->sg_len, 153 DMA_FROM_DEVICE); 154 else 155 dma_unmap_sg(host->chan_tx->device->dev, 156 host->sg_ptr, host->sg_len, 157 DMA_TO_DEVICE); 158 159 spin_unlock_irq(&host->lock); 160 161 wait_for_completion(&host->dma_dataend); 162 163 spin_lock_irq(&host->lock); 164 tmio_mmc_do_data_irq(host); 165 out: 166 spin_unlock_irq(&host->lock); 167 } 168 169 static void renesas_sdhi_sys_dmac_start_dma_rx(struct tmio_mmc_host *host) 170 { 171 struct scatterlist *sg = host->sg_ptr, *sg_tmp; 172 struct dma_async_tx_descriptor *desc = NULL; 173 struct dma_chan *chan = host->chan_rx; 174 dma_cookie_t cookie; 175 int ret, i; 176 bool aligned = true, multiple = true; 177 unsigned int align = (1 << host->pdata->alignment_shift) - 1; 178 179 for_each_sg(sg, sg_tmp, host->sg_len, i) { 180 if (sg_tmp->offset & align) 181 aligned = false; 182 if (sg_tmp->length & align) { 183 multiple = false; 184 break; 185 } 186 } 187 188 if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_SIZE || 189 (align & PAGE_MASK))) || !multiple) { 190 ret = -EINVAL; 191 goto pio; 192 } 193 194 if (sg->length < TMIO_MMC_MIN_DMA_LEN) { 195 host->force_pio = true; 196 return; 197 } 198 199 tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_RXRDY); 200 201 /* The only sg element can be unaligned, use our bounce buffer then */ 202 if (!aligned) { 203 sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length); 204 host->sg_ptr = &host->bounce_sg; 205 sg = host->sg_ptr; 206 } 207 208 ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE); 209 if (ret > 0) 210 desc = dmaengine_prep_slave_sg(chan, sg, ret, DMA_DEV_TO_MEM, 211 DMA_CTRL_ACK); 212 213 if (desc) { 214 reinit_completion(&host->dma_dataend); 215 desc->callback = renesas_sdhi_sys_dmac_dma_callback; 216 desc->callback_param = host; 217 218 cookie = dmaengine_submit(desc); 219 if (cookie < 0) { 220 desc = NULL; 221 ret = cookie; 222 } 223 } 224 pio: 225 if (!desc) { 226 /* DMA failed, fall back to PIO */ 227 renesas_sdhi_sys_dmac_enable_dma(host, false); 228 if (ret >= 0) 229 ret = -EIO; 230 host->chan_rx = NULL; 231 dma_release_channel(chan); 232 /* Free the Tx channel too */ 233 chan = host->chan_tx; 234 if (chan) { 235 host->chan_tx = NULL; 236 dma_release_channel(chan); 237 } 238 dev_warn(&host->pdev->dev, 239 "DMA failed: %d, falling back to PIO\n", ret); 240 } 241 } 242 243 static void renesas_sdhi_sys_dmac_start_dma_tx(struct tmio_mmc_host *host) 244 { 245 struct scatterlist *sg = host->sg_ptr, *sg_tmp; 246 struct dma_async_tx_descriptor *desc = NULL; 247 struct dma_chan *chan = host->chan_tx; 248 dma_cookie_t cookie; 249 int ret, i; 250 bool aligned = true, multiple = true; 251 unsigned int align = (1 << host->pdata->alignment_shift) - 1; 252 253 for_each_sg(sg, sg_tmp, host->sg_len, i) { 254 if (sg_tmp->offset & align) 255 aligned = false; 256 if (sg_tmp->length & align) { 257 multiple = false; 258 break; 259 } 260 } 261 262 if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_SIZE || 263 (align & PAGE_MASK))) || !multiple) { 264 ret = -EINVAL; 265 goto pio; 266 } 267 268 if (sg->length < TMIO_MMC_MIN_DMA_LEN) { 269 host->force_pio = true; 270 return; 271 } 272 273 tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_TXRQ); 274 275 /* The only sg element can be unaligned, use our bounce buffer then */ 276 if (!aligned) { 277 unsigned long flags; 278 void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags); 279 280 sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length); 281 memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length); 282 tmio_mmc_kunmap_atomic(sg, &flags, sg_vaddr); 283 host->sg_ptr = &host->bounce_sg; 284 sg = host->sg_ptr; 285 } 286 287 ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE); 288 if (ret > 0) 289 desc = dmaengine_prep_slave_sg(chan, sg, ret, DMA_MEM_TO_DEV, 290 DMA_CTRL_ACK); 291 292 if (desc) { 293 reinit_completion(&host->dma_dataend); 294 desc->callback = renesas_sdhi_sys_dmac_dma_callback; 295 desc->callback_param = host; 296 297 cookie = dmaengine_submit(desc); 298 if (cookie < 0) { 299 desc = NULL; 300 ret = cookie; 301 } 302 } 303 pio: 304 if (!desc) { 305 /* DMA failed, fall back to PIO */ 306 renesas_sdhi_sys_dmac_enable_dma(host, false); 307 if (ret >= 0) 308 ret = -EIO; 309 host->chan_tx = NULL; 310 dma_release_channel(chan); 311 /* Free the Rx channel too */ 312 chan = host->chan_rx; 313 if (chan) { 314 host->chan_rx = NULL; 315 dma_release_channel(chan); 316 } 317 dev_warn(&host->pdev->dev, 318 "DMA failed: %d, falling back to PIO\n", ret); 319 } 320 } 321 322 static void renesas_sdhi_sys_dmac_start_dma(struct tmio_mmc_host *host, 323 struct mmc_data *data) 324 { 325 if (data->flags & MMC_DATA_READ) { 326 if (host->chan_rx) 327 renesas_sdhi_sys_dmac_start_dma_rx(host); 328 } else { 329 if (host->chan_tx) 330 renesas_sdhi_sys_dmac_start_dma_tx(host); 331 } 332 } 333 334 static void renesas_sdhi_sys_dmac_issue_tasklet_fn(unsigned long priv) 335 { 336 struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv; 337 struct dma_chan *chan = NULL; 338 339 spin_lock_irq(&host->lock); 340 341 if (host && host->data) { 342 if (host->data->flags & MMC_DATA_READ) 343 chan = host->chan_rx; 344 else 345 chan = host->chan_tx; 346 } 347 348 spin_unlock_irq(&host->lock); 349 350 tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND); 351 352 if (chan) 353 dma_async_issue_pending(chan); 354 } 355 356 static void renesas_sdhi_sys_dmac_request_dma(struct tmio_mmc_host *host, 357 struct tmio_mmc_data *pdata) 358 { 359 /* We can only either use DMA for both Tx and Rx or not use it at all */ 360 if (!host->dma || (!host->pdev->dev.of_node && 361 (!pdata->chan_priv_tx || !pdata->chan_priv_rx))) 362 return; 363 364 if (!host->chan_tx && !host->chan_rx) { 365 struct resource *res = platform_get_resource(host->pdev, 366 IORESOURCE_MEM, 0); 367 struct dma_slave_config cfg = {}; 368 dma_cap_mask_t mask; 369 int ret; 370 371 if (!res) 372 return; 373 374 dma_cap_zero(mask); 375 dma_cap_set(DMA_SLAVE, mask); 376 377 host->chan_tx = dma_request_slave_channel_compat(mask, 378 host->dma->filter, pdata->chan_priv_tx, 379 &host->pdev->dev, "tx"); 380 dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__, 381 host->chan_tx); 382 383 if (!host->chan_tx) 384 return; 385 386 cfg.direction = DMA_MEM_TO_DEV; 387 cfg.dst_addr = res->start + 388 (CTL_SD_DATA_PORT << host->bus_shift); 389 cfg.dst_addr_width = host->dma->dma_buswidth; 390 if (!cfg.dst_addr_width) 391 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 392 cfg.src_addr = 0; 393 ret = dmaengine_slave_config(host->chan_tx, &cfg); 394 if (ret < 0) 395 goto ecfgtx; 396 397 host->chan_rx = dma_request_slave_channel_compat(mask, 398 host->dma->filter, pdata->chan_priv_rx, 399 &host->pdev->dev, "rx"); 400 dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, 401 host->chan_rx); 402 403 if (!host->chan_rx) 404 goto ereqrx; 405 406 cfg.direction = DMA_DEV_TO_MEM; 407 cfg.src_addr = cfg.dst_addr + host->pdata->dma_rx_offset; 408 cfg.src_addr_width = host->dma->dma_buswidth; 409 if (!cfg.src_addr_width) 410 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 411 cfg.dst_addr = 0; 412 ret = dmaengine_slave_config(host->chan_rx, &cfg); 413 if (ret < 0) 414 goto ecfgrx; 415 416 host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA); 417 if (!host->bounce_buf) 418 goto ebouncebuf; 419 420 init_completion(&host->dma_dataend); 421 tasklet_init(&host->dma_issue, 422 renesas_sdhi_sys_dmac_issue_tasklet_fn, 423 (unsigned long)host); 424 } 425 426 renesas_sdhi_sys_dmac_enable_dma(host, true); 427 428 return; 429 430 ebouncebuf: 431 ecfgrx: 432 dma_release_channel(host->chan_rx); 433 host->chan_rx = NULL; 434 ereqrx: 435 ecfgtx: 436 dma_release_channel(host->chan_tx); 437 host->chan_tx = NULL; 438 } 439 440 static void renesas_sdhi_sys_dmac_release_dma(struct tmio_mmc_host *host) 441 { 442 if (host->chan_tx) { 443 struct dma_chan *chan = host->chan_tx; 444 445 host->chan_tx = NULL; 446 dma_release_channel(chan); 447 } 448 if (host->chan_rx) { 449 struct dma_chan *chan = host->chan_rx; 450 451 host->chan_rx = NULL; 452 dma_release_channel(chan); 453 } 454 if (host->bounce_buf) { 455 free_pages((unsigned long)host->bounce_buf, 0); 456 host->bounce_buf = NULL; 457 } 458 } 459 460 static const struct tmio_mmc_dma_ops renesas_sdhi_sys_dmac_dma_ops = { 461 .start = renesas_sdhi_sys_dmac_start_dma, 462 .enable = renesas_sdhi_sys_dmac_enable_dma, 463 .request = renesas_sdhi_sys_dmac_request_dma, 464 .release = renesas_sdhi_sys_dmac_release_dma, 465 .abort = renesas_sdhi_sys_dmac_abort_dma, 466 .dataend = renesas_sdhi_sys_dmac_dataend_dma, 467 }; 468 469 /* 470 * Whitelist of specific R-Car Gen3 SoC ES versions to use this DMAC 471 * implementation. Currently empty as all supported ES versions use 472 * the internal DMAC. 473 */ 474 static const struct soc_device_attribute gen3_soc_whitelist[] = { 475 { /* sentinel */ } 476 }; 477 478 static int renesas_sdhi_sys_dmac_probe(struct platform_device *pdev) 479 { 480 if (of_device_get_match_data(&pdev->dev) == &of_rcar_gen3_compatible && 481 !soc_device_match(gen3_soc_whitelist)) 482 return -ENODEV; 483 484 return renesas_sdhi_probe(pdev, &renesas_sdhi_sys_dmac_dma_ops); 485 } 486 487 static const struct dev_pm_ops renesas_sdhi_sys_dmac_dev_pm_ops = { 488 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 489 pm_runtime_force_resume) 490 SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, 491 tmio_mmc_host_runtime_resume, 492 NULL) 493 }; 494 495 static struct platform_driver renesas_sys_dmac_sdhi_driver = { 496 .driver = { 497 .name = "sh_mobile_sdhi", 498 .pm = &renesas_sdhi_sys_dmac_dev_pm_ops, 499 .of_match_table = renesas_sdhi_sys_dmac_of_match, 500 }, 501 .probe = renesas_sdhi_sys_dmac_probe, 502 .remove = renesas_sdhi_remove, 503 }; 504 505 module_platform_driver(renesas_sys_dmac_sdhi_driver); 506 507 MODULE_DESCRIPTION("Renesas SDHI driver"); 508 MODULE_AUTHOR("Magnus Damm"); 509 MODULE_LICENSE("GPL v2"); 510 MODULE_ALIAS("platform:sh_mobile_sdhi"); 511