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