blob: 03ee5c61e25ba9d33f033ad4a1ed8266f45e69c9 [file] [log] [blame]
Will Newtonf95f3852011-01-02 01:11:59 -05001/*
2 * Synopsys DesignWare Multimedia Card Interface driver
3 * (Based on NXP driver for lpc 31xx)
4 *
5 * Copyright (C) 2009 NXP Semiconductors
6 * Copyright (C) 2009, 2010 Imagination Technologies Ltd.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/blkdev.h>
15#include <linux/clk.h>
16#include <linux/debugfs.h>
17#include <linux/device.h>
18#include <linux/dma-mapping.h>
19#include <linux/err.h>
20#include <linux/init.h>
21#include <linux/interrupt.h>
22#include <linux/ioport.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
Will Newtonf95f3852011-01-02 01:11:59 -050025#include <linux/seq_file.h>
26#include <linux/slab.h>
27#include <linux/stat.h>
28#include <linux/delay.h>
29#include <linux/irq.h>
30#include <linux/mmc/host.h>
31#include <linux/mmc/mmc.h>
Seungwon Jeon90c21432013-08-31 00:14:05 +090032#include <linux/mmc/sdio.h>
Will Newtonf95f3852011-01-02 01:11:59 -050033#include <linux/mmc/dw_mmc.h>
34#include <linux/bitops.h>
Jaehoon Chungc07946a2011-02-25 11:08:14 +090035#include <linux/regulator/consumer.h>
James Hogan1791b13e2011-06-24 13:55:55 +010036#include <linux/workqueue.h>
Thomas Abrahamc91eab42012-09-17 18:16:40 +000037#include <linux/of.h>
Doug Anderson55a6ceb2013-01-11 17:03:53 +000038#include <linux/of_gpio.h>
Will Newtonf95f3852011-01-02 01:11:59 -050039
40#include "dw_mmc.h"
41
42/* Common flag combinations */
Jaehoon Chung3f7eec62013-05-27 13:47:57 +090043#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | \
Will Newtonf95f3852011-01-02 01:11:59 -050044 SDMMC_INT_HTO | SDMMC_INT_SBE | \
45 SDMMC_INT_EBE)
46#define DW_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \
47 SDMMC_INT_RESP_ERR)
48#define DW_MCI_ERROR_FLAGS (DW_MCI_DATA_ERROR_FLAGS | \
49 DW_MCI_CMD_ERROR_FLAGS | SDMMC_INT_HLE)
50#define DW_MCI_SEND_STATUS 1
51#define DW_MCI_RECV_STATUS 2
52#define DW_MCI_DMA_THRESHOLD 16
53
Seungwon Jeon1f44a2a2013-08-31 00:13:31 +090054#define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */
55#define DW_MCI_FREQ_MIN 400000 /* unit: HZ */
56
Will Newtonf95f3852011-01-02 01:11:59 -050057#ifdef CONFIG_MMC_DW_IDMAC
Joonyoung Shimfc79a4d2013-04-26 15:35:22 +090058#define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \
59 SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \
60 SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \
61 SDMMC_IDMAC_INT_TI)
62
Will Newtonf95f3852011-01-02 01:11:59 -050063struct idmac_desc {
64 u32 des0; /* Control Descriptor */
65#define IDMAC_DES0_DIC BIT(1)
66#define IDMAC_DES0_LD BIT(2)
67#define IDMAC_DES0_FD BIT(3)
68#define IDMAC_DES0_CH BIT(4)
69#define IDMAC_DES0_ER BIT(5)
70#define IDMAC_DES0_CES BIT(30)
71#define IDMAC_DES0_OWN BIT(31)
72
73 u32 des1; /* Buffer sizes */
74#define IDMAC_SET_BUFFER1_SIZE(d, s) \
Shashidhar Hiremath9b7bbe12011-07-29 08:49:50 -040075 ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff))
Will Newtonf95f3852011-01-02 01:11:59 -050076
77 u32 des2; /* buffer 1 physical address */
78
79 u32 des3; /* buffer 2 physical address */
80};
81#endif /* CONFIG_MMC_DW_IDMAC */
82
Seungwon Jeon0976f162013-08-31 00:12:42 +090083static const u8 tuning_blk_pattern_4bit[] = {
84 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
85 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
86 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
87 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
88 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
89 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
90 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
91 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
92};
Will Newtonf95f3852011-01-02 01:11:59 -050093
Seungwon Jeon0976f162013-08-31 00:12:42 +090094static const u8 tuning_blk_pattern_8bit[] = {
95 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
96 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
97 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
98 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
99 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
100 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
101 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
102 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
103 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
104 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
105 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
106 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
107 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
108 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
109 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
110 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
Will Newtonf95f3852011-01-02 01:11:59 -0500111};
112
113#if defined(CONFIG_DEBUG_FS)
114static int dw_mci_req_show(struct seq_file *s, void *v)
115{
116 struct dw_mci_slot *slot = s->private;
117 struct mmc_request *mrq;
118 struct mmc_command *cmd;
119 struct mmc_command *stop;
120 struct mmc_data *data;
121
122 /* Make sure we get a consistent snapshot */
123 spin_lock_bh(&slot->host->lock);
124 mrq = slot->mrq;
125
126 if (mrq) {
127 cmd = mrq->cmd;
128 data = mrq->data;
129 stop = mrq->stop;
130
131 if (cmd)
132 seq_printf(s,
133 "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
134 cmd->opcode, cmd->arg, cmd->flags,
135 cmd->resp[0], cmd->resp[1], cmd->resp[2],
136 cmd->resp[2], cmd->error);
137 if (data)
138 seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
139 data->bytes_xfered, data->blocks,
140 data->blksz, data->flags, data->error);
141 if (stop)
142 seq_printf(s,
143 "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
144 stop->opcode, stop->arg, stop->flags,
145 stop->resp[0], stop->resp[1], stop->resp[2],
146 stop->resp[2], stop->error);
147 }
148
149 spin_unlock_bh(&slot->host->lock);
150
151 return 0;
152}
153
154static int dw_mci_req_open(struct inode *inode, struct file *file)
155{
156 return single_open(file, dw_mci_req_show, inode->i_private);
157}
158
159static const struct file_operations dw_mci_req_fops = {
160 .owner = THIS_MODULE,
161 .open = dw_mci_req_open,
162 .read = seq_read,
163 .llseek = seq_lseek,
164 .release = single_release,
165};
166
167static int dw_mci_regs_show(struct seq_file *s, void *v)
168{
169 seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS);
170 seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS);
171 seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD);
172 seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL);
173 seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK);
174 seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA);
175
176 return 0;
177}
178
179static int dw_mci_regs_open(struct inode *inode, struct file *file)
180{
181 return single_open(file, dw_mci_regs_show, inode->i_private);
182}
183
184static const struct file_operations dw_mci_regs_fops = {
185 .owner = THIS_MODULE,
186 .open = dw_mci_regs_open,
187 .read = seq_read,
188 .llseek = seq_lseek,
189 .release = single_release,
190};
191
192static void dw_mci_init_debugfs(struct dw_mci_slot *slot)
193{
194 struct mmc_host *mmc = slot->mmc;
195 struct dw_mci *host = slot->host;
196 struct dentry *root;
197 struct dentry *node;
198
199 root = mmc->debugfs_root;
200 if (!root)
201 return;
202
203 node = debugfs_create_file("regs", S_IRUSR, root, host,
204 &dw_mci_regs_fops);
205 if (!node)
206 goto err;
207
208 node = debugfs_create_file("req", S_IRUSR, root, slot,
209 &dw_mci_req_fops);
210 if (!node)
211 goto err;
212
213 node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state);
214 if (!node)
215 goto err;
216
217 node = debugfs_create_x32("pending_events", S_IRUSR, root,
218 (u32 *)&host->pending_events);
219 if (!node)
220 goto err;
221
222 node = debugfs_create_x32("completed_events", S_IRUSR, root,
223 (u32 *)&host->completed_events);
224 if (!node)
225 goto err;
226
227 return;
228
229err:
230 dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
231}
232#endif /* defined(CONFIG_DEBUG_FS) */
233
234static void dw_mci_set_timeout(struct dw_mci *host)
235{
236 /* timeout (maximum) */
237 mci_writel(host, TMOUT, 0xffffffff);
238}
239
240static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
241{
242 struct mmc_data *data;
Thomas Abraham800d78b2012-09-17 18:16:42 +0000243 struct dw_mci_slot *slot = mmc_priv(mmc);
Arnd Bergmanne95baf12012-11-08 14:26:11 +0000244 const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
Will Newtonf95f3852011-01-02 01:11:59 -0500245 u32 cmdr;
246 cmd->error = -EINPROGRESS;
247
248 cmdr = cmd->opcode;
249
Seungwon Jeon90c21432013-08-31 00:14:05 +0900250 if (cmd->opcode == MMC_STOP_TRANSMISSION ||
251 cmd->opcode == MMC_GO_IDLE_STATE ||
252 cmd->opcode == MMC_GO_INACTIVE_STATE ||
253 (cmd->opcode == SD_IO_RW_DIRECT &&
254 ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT))
Will Newtonf95f3852011-01-02 01:11:59 -0500255 cmdr |= SDMMC_CMD_STOP;
256 else
Seungwon Jeon90c21432013-08-31 00:14:05 +0900257 if (cmd->opcode != MMC_SEND_STATUS && cmd->data)
258 cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
Will Newtonf95f3852011-01-02 01:11:59 -0500259
260 if (cmd->flags & MMC_RSP_PRESENT) {
261 /* We expect a response, so set this bit */
262 cmdr |= SDMMC_CMD_RESP_EXP;
263 if (cmd->flags & MMC_RSP_136)
264 cmdr |= SDMMC_CMD_RESP_LONG;
265 }
266
267 if (cmd->flags & MMC_RSP_CRC)
268 cmdr |= SDMMC_CMD_RESP_CRC;
269
270 data = cmd->data;
271 if (data) {
272 cmdr |= SDMMC_CMD_DAT_EXP;
273 if (data->flags & MMC_DATA_STREAM)
274 cmdr |= SDMMC_CMD_STRM_MODE;
275 if (data->flags & MMC_DATA_WRITE)
276 cmdr |= SDMMC_CMD_DAT_WR;
277 }
278
James Hogancb27a842012-10-16 09:43:08 +0100279 if (drv_data && drv_data->prepare_command)
280 drv_data->prepare_command(slot->host, &cmdr);
Thomas Abraham800d78b2012-09-17 18:16:42 +0000281
Will Newtonf95f3852011-01-02 01:11:59 -0500282 return cmdr;
283}
284
Seungwon Jeon90c21432013-08-31 00:14:05 +0900285static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
286{
287 struct mmc_command *stop;
288 u32 cmdr;
289
290 if (!cmd->data)
291 return 0;
292
293 stop = &host->stop_abort;
294 cmdr = cmd->opcode;
295 memset(stop, 0, sizeof(struct mmc_command));
296
297 if (cmdr == MMC_READ_SINGLE_BLOCK ||
298 cmdr == MMC_READ_MULTIPLE_BLOCK ||
299 cmdr == MMC_WRITE_BLOCK ||
300 cmdr == MMC_WRITE_MULTIPLE_BLOCK) {
301 stop->opcode = MMC_STOP_TRANSMISSION;
302 stop->arg = 0;
303 stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
304 } else if (cmdr == SD_IO_RW_EXTENDED) {
305 stop->opcode = SD_IO_RW_DIRECT;
306 stop->arg |= (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) |
307 ((cmd->arg >> 28) & 0x7);
308 stop->flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
309 } else {
310 return 0;
311 }
312
313 cmdr = stop->opcode | SDMMC_CMD_STOP |
314 SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP;
315
316 return cmdr;
317}
318
Will Newtonf95f3852011-01-02 01:11:59 -0500319static void dw_mci_start_command(struct dw_mci *host,
320 struct mmc_command *cmd, u32 cmd_flags)
321{
322 host->cmd = cmd;
Thomas Abraham4a909202012-09-17 18:16:35 +0000323 dev_vdbg(host->dev,
Will Newtonf95f3852011-01-02 01:11:59 -0500324 "start command: ARGR=0x%08x CMDR=0x%08x\n",
325 cmd->arg, cmd_flags);
326
327 mci_writel(host, CMDARG, cmd->arg);
328 wmb();
329
330 mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
331}
332
Seungwon Jeon90c21432013-08-31 00:14:05 +0900333static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)
Will Newtonf95f3852011-01-02 01:11:59 -0500334{
Seungwon Jeon90c21432013-08-31 00:14:05 +0900335 struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort;
336 dw_mci_start_command(host, stop, host->stop_cmdr);
Will Newtonf95f3852011-01-02 01:11:59 -0500337}
338
339/* DMA interface functions */
340static void dw_mci_stop_dma(struct dw_mci *host)
341{
James Hogan03e8cb52011-06-29 09:28:43 +0100342 if (host->using_dma) {
Will Newtonf95f3852011-01-02 01:11:59 -0500343 host->dma_ops->stop(host);
344 host->dma_ops->cleanup(host);
345 } else {
346 /* Data transfer was stopped by the interrupt handler */
347 set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
348 }
349}
350
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900351static int dw_mci_get_dma_dir(struct mmc_data *data)
352{
353 if (data->flags & MMC_DATA_WRITE)
354 return DMA_TO_DEVICE;
355 else
356 return DMA_FROM_DEVICE;
357}
358
Jaehoon Chung9beee912012-02-16 11:19:38 +0900359#ifdef CONFIG_MMC_DW_IDMAC
Will Newtonf95f3852011-01-02 01:11:59 -0500360static void dw_mci_dma_cleanup(struct dw_mci *host)
361{
362 struct mmc_data *data = host->data;
363
364 if (data)
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900365 if (!data->host_cookie)
Thomas Abraham4a909202012-09-17 18:16:35 +0000366 dma_unmap_sg(host->dev,
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900367 data->sg,
368 data->sg_len,
369 dw_mci_get_dma_dir(data));
Will Newtonf95f3852011-01-02 01:11:59 -0500370}
371
372static void dw_mci_idmac_stop_dma(struct dw_mci *host)
373{
374 u32 temp;
375
376 /* Disable and reset the IDMAC interface */
377 temp = mci_readl(host, CTRL);
378 temp &= ~SDMMC_CTRL_USE_IDMAC;
379 temp |= SDMMC_CTRL_DMA_RESET;
380 mci_writel(host, CTRL, temp);
381
382 /* Stop the IDMAC running */
383 temp = mci_readl(host, BMOD);
Jaehoon Chunga5289a42011-02-25 11:08:13 +0900384 temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB);
Will Newtonf95f3852011-01-02 01:11:59 -0500385 mci_writel(host, BMOD, temp);
386}
387
388static void dw_mci_idmac_complete_dma(struct dw_mci *host)
389{
390 struct mmc_data *data = host->data;
391
Thomas Abraham4a909202012-09-17 18:16:35 +0000392 dev_vdbg(host->dev, "DMA complete\n");
Will Newtonf95f3852011-01-02 01:11:59 -0500393
394 host->dma_ops->cleanup(host);
395
396 /*
397 * If the card was removed, data will be NULL. No point in trying to
398 * send the stop command or waiting for NBUSY in this case.
399 */
400 if (data) {
401 set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
402 tasklet_schedule(&host->tasklet);
403 }
404}
405
406static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
407 unsigned int sg_len)
408{
409 int i;
410 struct idmac_desc *desc = host->sg_cpu;
411
412 for (i = 0; i < sg_len; i++, desc++) {
413 unsigned int length = sg_dma_len(&data->sg[i]);
414 u32 mem_addr = sg_dma_address(&data->sg[i]);
415
416 /* Set the OWN bit and disable interrupts for this descriptor */
417 desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH;
418
419 /* Buffer length */
420 IDMAC_SET_BUFFER1_SIZE(desc, length);
421
422 /* Physical address to DMA to/from */
423 desc->des2 = mem_addr;
424 }
425
426 /* Set first descriptor */
427 desc = host->sg_cpu;
428 desc->des0 |= IDMAC_DES0_FD;
429
430 /* Set last descriptor */
431 desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
432 desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
433 desc->des0 |= IDMAC_DES0_LD;
434
435 wmb();
436}
437
438static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
439{
440 u32 temp;
441
442 dw_mci_translate_sglist(host, host->data, sg_len);
443
444 /* Select IDMAC interface */
445 temp = mci_readl(host, CTRL);
446 temp |= SDMMC_CTRL_USE_IDMAC;
447 mci_writel(host, CTRL, temp);
448
449 wmb();
450
451 /* Enable the IDMAC */
452 temp = mci_readl(host, BMOD);
Jaehoon Chunga5289a42011-02-25 11:08:13 +0900453 temp |= SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB;
Will Newtonf95f3852011-01-02 01:11:59 -0500454 mci_writel(host, BMOD, temp);
455
456 /* Start it running */
457 mci_writel(host, PLDMND, 1);
458}
459
460static int dw_mci_idmac_init(struct dw_mci *host)
461{
462 struct idmac_desc *p;
Seungwon Jeon897b69e2012-09-19 13:58:31 +0800463 int i;
Will Newtonf95f3852011-01-02 01:11:59 -0500464
465 /* Number of descriptors in the ring buffer */
466 host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
467
468 /* Forward link the descriptor list */
469 for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
470 p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1));
471
472 /* Set the last descriptor as the end-of-ring descriptor */
473 p->des3 = host->sg_dma;
474 p->des0 = IDMAC_DES0_ER;
475
Seungwon Jeon141a7122012-05-22 13:01:03 +0900476 mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET);
477
Will Newtonf95f3852011-01-02 01:11:59 -0500478 /* Mask out interrupts - get Tx & Rx complete only */
Joonyoung Shimfc79a4d2013-04-26 15:35:22 +0900479 mci_writel(host, IDSTS, IDMAC_INT_CLR);
Will Newtonf95f3852011-01-02 01:11:59 -0500480 mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI |
481 SDMMC_IDMAC_INT_TI);
482
483 /* Set the descriptor base address */
484 mci_writel(host, DBADDR, host->sg_dma);
485 return 0;
486}
487
Arnd Bergmann8e2b36e2012-11-06 22:55:31 +0100488static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
Seungwon Jeon885c3e82012-02-20 11:01:43 +0900489 .init = dw_mci_idmac_init,
490 .start = dw_mci_idmac_start_dma,
491 .stop = dw_mci_idmac_stop_dma,
492 .complete = dw_mci_idmac_complete_dma,
493 .cleanup = dw_mci_dma_cleanup,
494};
495#endif /* CONFIG_MMC_DW_IDMAC */
496
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900497static int dw_mci_pre_dma_transfer(struct dw_mci *host,
498 struct mmc_data *data,
499 bool next)
Will Newtonf95f3852011-01-02 01:11:59 -0500500{
501 struct scatterlist *sg;
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900502 unsigned int i, sg_len;
Will Newtonf95f3852011-01-02 01:11:59 -0500503
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900504 if (!next && data->host_cookie)
505 return data->host_cookie;
Will Newtonf95f3852011-01-02 01:11:59 -0500506
507 /*
508 * We don't do DMA on "complex" transfers, i.e. with
509 * non-word-aligned buffers or lengths. Also, we don't bother
510 * with all the DMA setup overhead for short transfers.
511 */
512 if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD)
513 return -EINVAL;
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900514
Will Newtonf95f3852011-01-02 01:11:59 -0500515 if (data->blksz & 3)
516 return -EINVAL;
517
518 for_each_sg(data->sg, sg, data->sg_len, i) {
519 if (sg->offset & 3 || sg->length & 3)
520 return -EINVAL;
521 }
522
Thomas Abraham4a909202012-09-17 18:16:35 +0000523 sg_len = dma_map_sg(host->dev,
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900524 data->sg,
525 data->sg_len,
526 dw_mci_get_dma_dir(data));
527 if (sg_len == 0)
528 return -EINVAL;
529
530 if (next)
531 data->host_cookie = sg_len;
532
533 return sg_len;
534}
535
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900536static void dw_mci_pre_req(struct mmc_host *mmc,
537 struct mmc_request *mrq,
538 bool is_first_req)
539{
540 struct dw_mci_slot *slot = mmc_priv(mmc);
541 struct mmc_data *data = mrq->data;
542
543 if (!slot->host->use_dma || !data)
544 return;
545
546 if (data->host_cookie) {
547 data->host_cookie = 0;
548 return;
549 }
550
551 if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0)
552 data->host_cookie = 0;
553}
554
555static void dw_mci_post_req(struct mmc_host *mmc,
556 struct mmc_request *mrq,
557 int err)
558{
559 struct dw_mci_slot *slot = mmc_priv(mmc);
560 struct mmc_data *data = mrq->data;
561
562 if (!slot->host->use_dma || !data)
563 return;
564
565 if (data->host_cookie)
Thomas Abraham4a909202012-09-17 18:16:35 +0000566 dma_unmap_sg(slot->host->dev,
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900567 data->sg,
568 data->sg_len,
569 dw_mci_get_dma_dir(data));
570 data->host_cookie = 0;
571}
572
Seungwon Jeon52426892013-08-31 00:13:42 +0900573static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
574{
575#ifdef CONFIG_MMC_DW_IDMAC
576 unsigned int blksz = data->blksz;
577 const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256};
578 u32 fifo_width = 1 << host->data_shift;
579 u32 blksz_depth = blksz / fifo_width, fifoth_val;
580 u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers;
581 int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1;
582
583 tx_wmark = (host->fifo_depth) / 2;
584 tx_wmark_invers = host->fifo_depth - tx_wmark;
585
586 /*
587 * MSIZE is '1',
588 * if blksz is not a multiple of the FIFO width
589 */
590 if (blksz % fifo_width) {
591 msize = 0;
592 rx_wmark = 1;
593 goto done;
594 }
595
596 do {
597 if (!((blksz_depth % mszs[idx]) ||
598 (tx_wmark_invers % mszs[idx]))) {
599 msize = idx;
600 rx_wmark = mszs[idx] - 1;
601 break;
602 }
603 } while (--idx > 0);
604 /*
605 * If idx is '0', it won't be tried
606 * Thus, initial values are uesed
607 */
608done:
609 fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark);
610 mci_writel(host, FIFOTH, fifoth_val);
611#endif
612}
613
Seungwon Jeonf1d27362013-08-31 00:13:55 +0900614static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data)
615{
616 unsigned int blksz = data->blksz;
617 u32 blksz_depth, fifo_depth;
618 u16 thld_size;
619
620 WARN_ON(!(data->flags & MMC_DATA_READ));
621
622 if (host->timing != MMC_TIMING_MMC_HS200 &&
623 host->timing != MMC_TIMING_UHS_SDR104)
624 goto disable;
625
626 blksz_depth = blksz / (1 << host->data_shift);
627 fifo_depth = host->fifo_depth;
628
629 if (blksz_depth > fifo_depth)
630 goto disable;
631
632 /*
633 * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz'
634 * If (blksz_depth) < (fifo_depth >> 1), should be thld_size = blksz
635 * Currently just choose blksz.
636 */
637 thld_size = blksz;
638 mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1));
639 return;
640
641disable:
642 mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0));
643}
644
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900645static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
646{
647 int sg_len;
648 u32 temp;
649
650 host->using_dma = 0;
651
652 /* If we don't have a channel, we can't do DMA */
653 if (!host->use_dma)
654 return -ENODEV;
655
656 sg_len = dw_mci_pre_dma_transfer(host, data, 0);
Seungwon Jeona99aa9b2012-04-10 09:53:32 +0900657 if (sg_len < 0) {
658 host->dma_ops->stop(host);
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900659 return sg_len;
Seungwon Jeona99aa9b2012-04-10 09:53:32 +0900660 }
Seungwon Jeon9aa51402012-02-06 16:55:07 +0900661
James Hogan03e8cb52011-06-29 09:28:43 +0100662 host->using_dma = 1;
663
Thomas Abraham4a909202012-09-17 18:16:35 +0000664 dev_vdbg(host->dev,
Will Newtonf95f3852011-01-02 01:11:59 -0500665 "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
666 (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
667 sg_len);
668
Seungwon Jeon52426892013-08-31 00:13:42 +0900669 /*
670 * Decide the MSIZE and RX/TX Watermark.
671 * If current block size is same with previous size,
672 * no need to update fifoth.
673 */
674 if (host->prev_blksz != data->blksz)
675 dw_mci_adjust_fifoth(host, data);
676
Will Newtonf95f3852011-01-02 01:11:59 -0500677 /* Enable the DMA interface */
678 temp = mci_readl(host, CTRL);
679 temp |= SDMMC_CTRL_DMA_ENABLE;
680 mci_writel(host, CTRL, temp);
681
682 /* Disable RX/TX IRQs, let DMA handle it */
683 temp = mci_readl(host, INTMASK);
684 temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR);
685 mci_writel(host, INTMASK, temp);
686
687 host->dma_ops->start(host, sg_len);
688
689 return 0;
690}
691
692static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
693{
694 u32 temp;
695
696 data->error = -EINPROGRESS;
697
698 WARN_ON(host->data);
699 host->sg = NULL;
700 host->data = data;
701
Seungwon Jeonf1d27362013-08-31 00:13:55 +0900702 if (data->flags & MMC_DATA_READ) {
James Hogan55c5efbc2011-06-29 09:29:58 +0100703 host->dir_status = DW_MCI_RECV_STATUS;
Seungwon Jeonf1d27362013-08-31 00:13:55 +0900704 dw_mci_ctrl_rd_thld(host, data);
705 } else {
James Hogan55c5efbc2011-06-29 09:29:58 +0100706 host->dir_status = DW_MCI_SEND_STATUS;
Seungwon Jeonf1d27362013-08-31 00:13:55 +0900707 }
James Hogan55c5efbc2011-06-29 09:29:58 +0100708
Will Newtonf95f3852011-01-02 01:11:59 -0500709 if (dw_mci_submit_data_dma(host, data)) {
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +0900710 int flags = SG_MITER_ATOMIC;
711 if (host->data->flags & MMC_DATA_READ)
712 flags |= SG_MITER_TO_SG;
713 else
714 flags |= SG_MITER_FROM_SG;
715
716 sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
Will Newtonf95f3852011-01-02 01:11:59 -0500717 host->sg = data->sg;
James Hogan34b664a2011-06-24 13:57:56 +0100718 host->part_buf_start = 0;
719 host->part_buf_count = 0;
Will Newtonf95f3852011-01-02 01:11:59 -0500720
James Hoganb40af3a2011-06-24 13:54:06 +0100721 mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR);
Will Newtonf95f3852011-01-02 01:11:59 -0500722 temp = mci_readl(host, INTMASK);
723 temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR;
724 mci_writel(host, INTMASK, temp);
725
726 temp = mci_readl(host, CTRL);
727 temp &= ~SDMMC_CTRL_DMA_ENABLE;
728 mci_writel(host, CTRL, temp);
Seungwon Jeon52426892013-08-31 00:13:42 +0900729
730 /*
731 * Use the initial fifoth_val for PIO mode.
732 * If next issued data may be transfered by DMA mode,
733 * prev_blksz should be invalidated.
734 */
735 mci_writel(host, FIFOTH, host->fifoth_val);
736 host->prev_blksz = 0;
737 } else {
738 /*
739 * Keep the current block size.
740 * It will be used to decide whether to update
741 * fifoth register next time.
742 */
743 host->prev_blksz = data->blksz;
Will Newtonf95f3852011-01-02 01:11:59 -0500744 }
745}
746
747static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
748{
749 struct dw_mci *host = slot->host;
750 unsigned long timeout = jiffies + msecs_to_jiffies(500);
751 unsigned int cmd_status = 0;
752
753 mci_writel(host, CMDARG, arg);
754 wmb();
755 mci_writel(host, CMD, SDMMC_CMD_START | cmd);
756
757 while (time_before(jiffies, timeout)) {
758 cmd_status = mci_readl(host, CMD);
759 if (!(cmd_status & SDMMC_CMD_START))
760 return;
761 }
762 dev_err(&slot->mmc->class_dev,
763 "Timeout sending command (cmd %#x arg %#x status %#x)\n",
764 cmd, arg, cmd_status);
765}
766
Abhilash Kesavanab269122012-11-19 10:26:21 +0530767static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
Will Newtonf95f3852011-01-02 01:11:59 -0500768{
769 struct dw_mci *host = slot->host;
Doug Andersonfdf492a2013-08-31 00:11:43 +0900770 unsigned int clock = slot->clock;
Will Newtonf95f3852011-01-02 01:11:59 -0500771 u32 div;
Doug Anderson9623b5b2012-07-25 08:33:17 -0700772 u32 clk_en_a;
Will Newtonf95f3852011-01-02 01:11:59 -0500773
Doug Andersonfdf492a2013-08-31 00:11:43 +0900774 if (!clock) {
775 mci_writel(host, CLKENA, 0);
776 mci_send_cmd(slot,
777 SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
778 } else if (clock != host->current_speed || force_clkinit) {
779 div = host->bus_hz / clock;
780 if (host->bus_hz % clock && host->bus_hz > clock)
Will Newtonf95f3852011-01-02 01:11:59 -0500781 /*
782 * move the + 1 after the divide to prevent
783 * over-clocking the card.
784 */
Seungwon Jeone4199902012-05-22 13:01:21 +0900785 div += 1;
786
Doug Andersonfdf492a2013-08-31 00:11:43 +0900787 div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0;
Will Newtonf95f3852011-01-02 01:11:59 -0500788
Doug Andersonfdf492a2013-08-31 00:11:43 +0900789 if ((clock << div) != slot->__clk_old || force_clkinit)
790 dev_info(&slot->mmc->class_dev,
791 "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n",
792 slot->id, host->bus_hz, clock,
793 div ? ((host->bus_hz / div) >> 1) :
794 host->bus_hz, div);
Will Newtonf95f3852011-01-02 01:11:59 -0500795
796 /* disable clock */
797 mci_writel(host, CLKENA, 0);
798 mci_writel(host, CLKSRC, 0);
799
800 /* inform CIU */
801 mci_send_cmd(slot,
802 SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
803
804 /* set clock to desired speed */
805 mci_writel(host, CLKDIV, div);
806
807 /* inform CIU */
808 mci_send_cmd(slot,
809 SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
810
Doug Anderson9623b5b2012-07-25 08:33:17 -0700811 /* enable clock; only low power if no SDIO */
812 clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
813 if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id)))
814 clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
815 mci_writel(host, CLKENA, clk_en_a);
Will Newtonf95f3852011-01-02 01:11:59 -0500816
817 /* inform CIU */
818 mci_send_cmd(slot,
819 SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
820
Doug Andersonfdf492a2013-08-31 00:11:43 +0900821 /* keep the clock with reflecting clock dividor */
822 slot->__clk_old = clock << div;
Will Newtonf95f3852011-01-02 01:11:59 -0500823 }
824
Doug Andersonfdf492a2013-08-31 00:11:43 +0900825 host->current_speed = clock;
826
Will Newtonf95f3852011-01-02 01:11:59 -0500827 /* Set the current slot bus width */
Seungwon Jeon1d56c452011-06-20 17:23:53 +0900828 mci_writel(host, CTYPE, (slot->ctype << slot->id));
Will Newtonf95f3852011-01-02 01:11:59 -0500829}
830
Seungwon Jeon053b3ce2011-12-22 18:01:29 +0900831static void __dw_mci_start_request(struct dw_mci *host,
832 struct dw_mci_slot *slot,
833 struct mmc_command *cmd)
Will Newtonf95f3852011-01-02 01:11:59 -0500834{
835 struct mmc_request *mrq;
Will Newtonf95f3852011-01-02 01:11:59 -0500836 struct mmc_data *data;
837 u32 cmdflags;
838
839 mrq = slot->mrq;
840 if (host->pdata->select_slot)
841 host->pdata->select_slot(slot->id);
842
Will Newtonf95f3852011-01-02 01:11:59 -0500843 host->cur_slot = slot;
844 host->mrq = mrq;
845
846 host->pending_events = 0;
847 host->completed_events = 0;
Seungwon Jeone352c812013-08-31 00:14:17 +0900848 host->cmd_status = 0;
Will Newtonf95f3852011-01-02 01:11:59 -0500849 host->data_status = 0;
Seungwon Jeone352c812013-08-31 00:14:17 +0900850 host->dir_status = 0;
Will Newtonf95f3852011-01-02 01:11:59 -0500851
Seungwon Jeon053b3ce2011-12-22 18:01:29 +0900852 data = cmd->data;
Will Newtonf95f3852011-01-02 01:11:59 -0500853 if (data) {
854 dw_mci_set_timeout(host);
855 mci_writel(host, BYTCNT, data->blksz*data->blocks);
856 mci_writel(host, BLKSIZ, data->blksz);
857 }
858
Will Newtonf95f3852011-01-02 01:11:59 -0500859 cmdflags = dw_mci_prepare_command(slot->mmc, cmd);
860
861 /* this is the first command, send the initialization clock */
862 if (test_and_clear_bit(DW_MMC_CARD_NEED_INIT, &slot->flags))
863 cmdflags |= SDMMC_CMD_INIT;
864
865 if (data) {
866 dw_mci_submit_data(host, data);
867 wmb();
868 }
869
870 dw_mci_start_command(host, cmd, cmdflags);
871
872 if (mrq->stop)
873 host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
Seungwon Jeon90c21432013-08-31 00:14:05 +0900874 else
875 host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
Will Newtonf95f3852011-01-02 01:11:59 -0500876}
877
Seungwon Jeon053b3ce2011-12-22 18:01:29 +0900878static void dw_mci_start_request(struct dw_mci *host,
879 struct dw_mci_slot *slot)
880{
881 struct mmc_request *mrq = slot->mrq;
882 struct mmc_command *cmd;
883
884 cmd = mrq->sbc ? mrq->sbc : mrq->cmd;
885 __dw_mci_start_request(host, slot, cmd);
886}
887
James Hogan7456caa2011-06-24 13:55:10 +0100888/* must be called with host->lock held */
Will Newtonf95f3852011-01-02 01:11:59 -0500889static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot,
890 struct mmc_request *mrq)
891{
892 dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n",
893 host->state);
894
Will Newtonf95f3852011-01-02 01:11:59 -0500895 slot->mrq = mrq;
896
897 if (host->state == STATE_IDLE) {
898 host->state = STATE_SENDING_CMD;
899 dw_mci_start_request(host, slot);
900 } else {
901 list_add_tail(&slot->queue_node, &host->queue);
902 }
Will Newtonf95f3852011-01-02 01:11:59 -0500903}
904
905static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
906{
907 struct dw_mci_slot *slot = mmc_priv(mmc);
908 struct dw_mci *host = slot->host;
909
910 WARN_ON(slot->mrq);
911
James Hogan7456caa2011-06-24 13:55:10 +0100912 /*
913 * The check for card presence and queueing of the request must be
914 * atomic, otherwise the card could be removed in between and the
915 * request wouldn't fail until another card was inserted.
916 */
917 spin_lock_bh(&host->lock);
918
Will Newtonf95f3852011-01-02 01:11:59 -0500919 if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) {
James Hogan7456caa2011-06-24 13:55:10 +0100920 spin_unlock_bh(&host->lock);
Will Newtonf95f3852011-01-02 01:11:59 -0500921 mrq->cmd->error = -ENOMEDIUM;
922 mmc_request_done(mmc, mrq);
923 return;
924 }
925
Will Newtonf95f3852011-01-02 01:11:59 -0500926 dw_mci_queue_request(host, slot, mrq);
James Hogan7456caa2011-06-24 13:55:10 +0100927
928 spin_unlock_bh(&host->lock);
Will Newtonf95f3852011-01-02 01:11:59 -0500929}
930
931static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
932{
933 struct dw_mci_slot *slot = mmc_priv(mmc);
Arnd Bergmanne95baf12012-11-08 14:26:11 +0000934 const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
Jaehoon Chung41babf72011-02-24 13:46:11 +0900935 u32 regs;
Will Newtonf95f3852011-01-02 01:11:59 -0500936
Will Newtonf95f3852011-01-02 01:11:59 -0500937 switch (ios->bus_width) {
Will Newtonf95f3852011-01-02 01:11:59 -0500938 case MMC_BUS_WIDTH_4:
939 slot->ctype = SDMMC_CTYPE_4BIT;
940 break;
Jaehoon Chungc9b2a062011-02-17 16:12:38 +0900941 case MMC_BUS_WIDTH_8:
942 slot->ctype = SDMMC_CTYPE_8BIT;
943 break;
Jaehoon Chungb2f7cb42012-11-08 17:35:31 +0900944 default:
945 /* set default 1 bit mode */
946 slot->ctype = SDMMC_CTYPE_1BIT;
Will Newtonf95f3852011-01-02 01:11:59 -0500947 }
948
Seungwon Jeon3f514292012-01-02 16:00:02 +0900949 regs = mci_readl(slot->host, UHS_REG);
950
Jaehoon Chung41babf72011-02-24 13:46:11 +0900951 /* DDR mode set */
Seungwon Jeon3f514292012-01-02 16:00:02 +0900952 if (ios->timing == MMC_TIMING_UHS_DDR50)
Hyeonsu Kimc69042a2013-02-22 09:32:46 +0900953 regs |= ((0x1 << slot->id) << 16);
Seungwon Jeon3f514292012-01-02 16:00:02 +0900954 else
Hyeonsu Kimc69042a2013-02-22 09:32:46 +0900955 regs &= ~((0x1 << slot->id) << 16);
Seungwon Jeon3f514292012-01-02 16:00:02 +0900956
957 mci_writel(slot->host, UHS_REG, regs);
Seungwon Jeonf1d27362013-08-31 00:13:55 +0900958 slot->host->timing = ios->timing;
Jaehoon Chung41babf72011-02-24 13:46:11 +0900959
Doug Andersonfdf492a2013-08-31 00:11:43 +0900960 /*
961 * Use mirror of ios->clock to prevent race with mmc
962 * core ios update when finding the minimum.
963 */
964 slot->clock = ios->clock;
Will Newtonf95f3852011-01-02 01:11:59 -0500965
James Hogancb27a842012-10-16 09:43:08 +0100966 if (drv_data && drv_data->set_ios)
967 drv_data->set_ios(slot->host, ios);
Thomas Abraham800d78b2012-09-17 18:16:42 +0000968
Jaehoon Chungbf7cb222012-11-08 17:35:29 +0900969 /* Slot specific timing and width adjustment */
970 dw_mci_setup_bus(slot, false);
971
Will Newtonf95f3852011-01-02 01:11:59 -0500972 switch (ios->power_mode) {
973 case MMC_POWER_UP:
974 set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
James Hogane6f34e22013-03-12 10:43:32 +0000975 /* Power up slot */
976 if (slot->host->pdata->setpower)
977 slot->host->pdata->setpower(slot->id, mmc->ocr_avail);
Jaehoon Chung4366dcc2013-03-26 21:36:14 +0900978 regs = mci_readl(slot->host, PWREN);
979 regs |= (1 << slot->id);
980 mci_writel(slot->host, PWREN, regs);
James Hogane6f34e22013-03-12 10:43:32 +0000981 break;
982 case MMC_POWER_OFF:
983 /* Power down slot */
984 if (slot->host->pdata->setpower)
985 slot->host->pdata->setpower(slot->id, 0);
Jaehoon Chung4366dcc2013-03-26 21:36:14 +0900986 regs = mci_readl(slot->host, PWREN);
987 regs &= ~(1 << slot->id);
988 mci_writel(slot->host, PWREN, regs);
Will Newtonf95f3852011-01-02 01:11:59 -0500989 break;
990 default:
991 break;
992 }
993}
994
995static int dw_mci_get_ro(struct mmc_host *mmc)
996{
997 int read_only;
998 struct dw_mci_slot *slot = mmc_priv(mmc);
999 struct dw_mci_board *brd = slot->host->pdata;
1000
1001 /* Use platform get_ro function, else try on board write protect */
Doug Anderson96406392013-01-11 17:03:54 +00001002 if (slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT)
Thomas Abrahamb4967aa2012-09-17 18:16:39 +00001003 read_only = 0;
1004 else if (brd->get_ro)
Will Newtonf95f3852011-01-02 01:11:59 -05001005 read_only = brd->get_ro(slot->id);
Doug Anderson55a6ceb2013-01-11 17:03:53 +00001006 else if (gpio_is_valid(slot->wp_gpio))
1007 read_only = gpio_get_value(slot->wp_gpio);
Will Newtonf95f3852011-01-02 01:11:59 -05001008 else
1009 read_only =
1010 mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0;
1011
1012 dev_dbg(&mmc->class_dev, "card is %s\n",
1013 read_only ? "read-only" : "read-write");
1014
1015 return read_only;
1016}
1017
1018static int dw_mci_get_cd(struct mmc_host *mmc)
1019{
1020 int present;
1021 struct dw_mci_slot *slot = mmc_priv(mmc);
1022 struct dw_mci_board *brd = slot->host->pdata;
1023
1024 /* Use platform get_cd function, else try onboard card detect */
Jaehoon Chungfc3d7722011-02-25 11:08:15 +09001025 if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
1026 present = 1;
1027 else if (brd->get_cd)
Will Newtonf95f3852011-01-02 01:11:59 -05001028 present = !brd->get_cd(slot->id);
1029 else
1030 present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
1031 == 0 ? 1 : 0;
1032
1033 if (present)
1034 dev_dbg(&mmc->class_dev, "card is present\n");
1035 else
1036 dev_dbg(&mmc->class_dev, "card is not present\n");
1037
1038 return present;
1039}
1040
Doug Anderson9623b5b2012-07-25 08:33:17 -07001041/*
1042 * Disable lower power mode.
1043 *
1044 * Low power mode will stop the card clock when idle. According to the
1045 * description of the CLKENA register we should disable low power mode
1046 * for SDIO cards if we need SDIO interrupts to work.
1047 *
1048 * This function is fast if low power mode is already disabled.
1049 */
1050static void dw_mci_disable_low_power(struct dw_mci_slot *slot)
1051{
1052 struct dw_mci *host = slot->host;
1053 u32 clk_en_a;
1054 const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
1055
1056 clk_en_a = mci_readl(host, CLKENA);
1057
1058 if (clk_en_a & clken_low_pwr) {
1059 mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr);
1060 mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
1061 SDMMC_CMD_PRV_DAT_WAIT, 0);
1062 }
1063}
1064
Shashidhar Hiremath1a5c8e12011-08-29 13:11:46 +05301065static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
1066{
1067 struct dw_mci_slot *slot = mmc_priv(mmc);
1068 struct dw_mci *host = slot->host;
1069 u32 int_mask;
1070
1071 /* Enable/disable Slot Specific SDIO interrupt */
1072 int_mask = mci_readl(host, INTMASK);
1073 if (enb) {
Doug Anderson9623b5b2012-07-25 08:33:17 -07001074 /*
1075 * Turn off low power mode if it was enabled. This is a bit of
1076 * a heavy operation and we disable / enable IRQs a lot, so
1077 * we'll leave low power mode disabled and it will get
1078 * re-enabled again in dw_mci_setup_bus().
1079 */
1080 dw_mci_disable_low_power(slot);
1081
Shashidhar Hiremath1a5c8e12011-08-29 13:11:46 +05301082 mci_writel(host, INTMASK,
Kyoungil Kim705ad042012-05-14 17:38:48 +09001083 (int_mask | SDMMC_INT_SDIO(slot->id)));
Shashidhar Hiremath1a5c8e12011-08-29 13:11:46 +05301084 } else {
1085 mci_writel(host, INTMASK,
Kyoungil Kim705ad042012-05-14 17:38:48 +09001086 (int_mask & ~SDMMC_INT_SDIO(slot->id)));
Shashidhar Hiremath1a5c8e12011-08-29 13:11:46 +05301087 }
1088}
1089
Seungwon Jeon0976f162013-08-31 00:12:42 +09001090static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
1091{
1092 struct dw_mci_slot *slot = mmc_priv(mmc);
1093 struct dw_mci *host = slot->host;
1094 const struct dw_mci_drv_data *drv_data = host->drv_data;
1095 struct dw_mci_tuning_data tuning_data;
1096 int err = -ENOSYS;
1097
1098 if (opcode == MMC_SEND_TUNING_BLOCK_HS200) {
1099 if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
1100 tuning_data.blk_pattern = tuning_blk_pattern_8bit;
1101 tuning_data.blksz = sizeof(tuning_blk_pattern_8bit);
1102 } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
1103 tuning_data.blk_pattern = tuning_blk_pattern_4bit;
1104 tuning_data.blksz = sizeof(tuning_blk_pattern_4bit);
1105 } else {
1106 return -EINVAL;
1107 }
1108 } else if (opcode == MMC_SEND_TUNING_BLOCK) {
1109 tuning_data.blk_pattern = tuning_blk_pattern_4bit;
1110 tuning_data.blksz = sizeof(tuning_blk_pattern_4bit);
1111 } else {
1112 dev_err(host->dev,
1113 "Undefined command(%d) for tuning\n", opcode);
1114 return -EINVAL;
1115 }
1116
1117 if (drv_data && drv_data->execute_tuning)
1118 err = drv_data->execute_tuning(slot, opcode, &tuning_data);
1119 return err;
1120}
1121
Will Newtonf95f3852011-01-02 01:11:59 -05001122static const struct mmc_host_ops dw_mci_ops = {
Shashidhar Hiremath1a5c8e12011-08-29 13:11:46 +05301123 .request = dw_mci_request,
Seungwon Jeon9aa51402012-02-06 16:55:07 +09001124 .pre_req = dw_mci_pre_req,
1125 .post_req = dw_mci_post_req,
Shashidhar Hiremath1a5c8e12011-08-29 13:11:46 +05301126 .set_ios = dw_mci_set_ios,
1127 .get_ro = dw_mci_get_ro,
1128 .get_cd = dw_mci_get_cd,
1129 .enable_sdio_irq = dw_mci_enable_sdio_irq,
Seungwon Jeon0976f162013-08-31 00:12:42 +09001130 .execute_tuning = dw_mci_execute_tuning,
Will Newtonf95f3852011-01-02 01:11:59 -05001131};
1132
1133static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
1134 __releases(&host->lock)
1135 __acquires(&host->lock)
1136{
1137 struct dw_mci_slot *slot;
1138 struct mmc_host *prev_mmc = host->cur_slot->mmc;
1139
1140 WARN_ON(host->cmd || host->data);
1141
1142 host->cur_slot->mrq = NULL;
1143 host->mrq = NULL;
1144 if (!list_empty(&host->queue)) {
1145 slot = list_entry(host->queue.next,
1146 struct dw_mci_slot, queue_node);
1147 list_del(&slot->queue_node);
Thomas Abraham4a909202012-09-17 18:16:35 +00001148 dev_vdbg(host->dev, "list not empty: %s is next\n",
Will Newtonf95f3852011-01-02 01:11:59 -05001149 mmc_hostname(slot->mmc));
1150 host->state = STATE_SENDING_CMD;
1151 dw_mci_start_request(host, slot);
1152 } else {
Thomas Abraham4a909202012-09-17 18:16:35 +00001153 dev_vdbg(host->dev, "list empty\n");
Will Newtonf95f3852011-01-02 01:11:59 -05001154 host->state = STATE_IDLE;
1155 }
1156
1157 spin_unlock(&host->lock);
1158 mmc_request_done(prev_mmc, mrq);
1159 spin_lock(&host->lock);
1160}
1161
Seungwon Jeone352c812013-08-31 00:14:17 +09001162static int dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd)
Will Newtonf95f3852011-01-02 01:11:59 -05001163{
1164 u32 status = host->cmd_status;
1165
1166 host->cmd_status = 0;
1167
1168 /* Read the response from the card (up to 16 bytes) */
1169 if (cmd->flags & MMC_RSP_PRESENT) {
1170 if (cmd->flags & MMC_RSP_136) {
1171 cmd->resp[3] = mci_readl(host, RESP0);
1172 cmd->resp[2] = mci_readl(host, RESP1);
1173 cmd->resp[1] = mci_readl(host, RESP2);
1174 cmd->resp[0] = mci_readl(host, RESP3);
1175 } else {
1176 cmd->resp[0] = mci_readl(host, RESP0);
1177 cmd->resp[1] = 0;
1178 cmd->resp[2] = 0;
1179 cmd->resp[3] = 0;
1180 }
1181 }
1182
1183 if (status & SDMMC_INT_RTO)
1184 cmd->error = -ETIMEDOUT;
1185 else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC))
1186 cmd->error = -EILSEQ;
1187 else if (status & SDMMC_INT_RESP_ERR)
1188 cmd->error = -EIO;
1189 else
1190 cmd->error = 0;
1191
1192 if (cmd->error) {
1193 /* newer ip versions need a delay between retries */
1194 if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY)
1195 mdelay(20);
Will Newtonf95f3852011-01-02 01:11:59 -05001196 }
Seungwon Jeone352c812013-08-31 00:14:17 +09001197
1198 return cmd->error;
1199}
1200
1201static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)
1202{
1203 u32 status = host->data_status, ctrl;
1204
1205 if (status & DW_MCI_DATA_ERROR_FLAGS) {
1206 if (status & SDMMC_INT_DRTO) {
1207 data->error = -ETIMEDOUT;
1208 } else if (status & SDMMC_INT_DCRC) {
1209 data->error = -EILSEQ;
1210 } else if (status & SDMMC_INT_EBE) {
1211 if (host->dir_status ==
1212 DW_MCI_SEND_STATUS) {
1213 /*
1214 * No data CRC status was returned.
1215 * The number of bytes transferred
1216 * will be exaggerated in PIO mode.
1217 */
1218 data->bytes_xfered = 0;
1219 data->error = -ETIMEDOUT;
1220 } else if (host->dir_status ==
1221 DW_MCI_RECV_STATUS) {
1222 data->error = -EIO;
1223 }
1224 } else {
1225 /* SDMMC_INT_SBE is included */
1226 data->error = -EIO;
1227 }
1228
1229 dev_err(host->dev, "data error, status 0x%08x\n", status);
1230
1231 /*
1232 * After an error, there may be data lingering
1233 * in the FIFO, so reset it - doing so
1234 * generates a block interrupt, hence setting
1235 * the scatter-gather pointer to NULL.
1236 */
1237 sg_miter_stop(&host->sg_miter);
1238 host->sg = NULL;
1239 ctrl = mci_readl(host, CTRL);
1240 ctrl |= SDMMC_CTRL_FIFO_RESET;
1241 mci_writel(host, CTRL, ctrl);
1242 } else {
1243 data->bytes_xfered = data->blocks * data->blksz;
1244 data->error = 0;
1245 }
1246
1247 return data->error;
Will Newtonf95f3852011-01-02 01:11:59 -05001248}
1249
1250static void dw_mci_tasklet_func(unsigned long priv)
1251{
1252 struct dw_mci *host = (struct dw_mci *)priv;
1253 struct mmc_data *data;
1254 struct mmc_command *cmd;
Seungwon Jeone352c812013-08-31 00:14:17 +09001255 struct mmc_request *mrq;
Will Newtonf95f3852011-01-02 01:11:59 -05001256 enum dw_mci_state state;
1257 enum dw_mci_state prev_state;
Seungwon Jeone352c812013-08-31 00:14:17 +09001258 u32 ctrl;
1259 unsigned int err;
Will Newtonf95f3852011-01-02 01:11:59 -05001260
1261 spin_lock(&host->lock);
1262
1263 state = host->state;
1264 data = host->data;
Seungwon Jeone352c812013-08-31 00:14:17 +09001265 mrq = host->mrq;
Will Newtonf95f3852011-01-02 01:11:59 -05001266
1267 do {
1268 prev_state = state;
1269
1270 switch (state) {
1271 case STATE_IDLE:
1272 break;
1273
1274 case STATE_SENDING_CMD:
1275 if (!test_and_clear_bit(EVENT_CMD_COMPLETE,
1276 &host->pending_events))
1277 break;
1278
1279 cmd = host->cmd;
1280 host->cmd = NULL;
1281 set_bit(EVENT_CMD_COMPLETE, &host->completed_events);
Seungwon Jeone352c812013-08-31 00:14:17 +09001282 err = dw_mci_command_complete(host, cmd);
1283 if (cmd == mrq->sbc && !err) {
Seungwon Jeon053b3ce2011-12-22 18:01:29 +09001284 prev_state = state = STATE_SENDING_CMD;
1285 __dw_mci_start_request(host, host->cur_slot,
Seungwon Jeone352c812013-08-31 00:14:17 +09001286 mrq->cmd);
Seungwon Jeon053b3ce2011-12-22 18:01:29 +09001287 goto unlock;
1288 }
1289
Seungwon Jeone352c812013-08-31 00:14:17 +09001290 if (cmd->data && err) {
Seungwon Jeon71abb132013-08-31 00:13:59 +09001291 dw_mci_stop_dma(host);
Seungwon Jeon90c21432013-08-31 00:14:05 +09001292 send_stop_abort(host, data);
1293 state = STATE_SENDING_STOP;
1294 break;
Seungwon Jeon71abb132013-08-31 00:13:59 +09001295 }
1296
Seungwon Jeone352c812013-08-31 00:14:17 +09001297 if (!cmd->data || err) {
1298 dw_mci_request_end(host, mrq);
Will Newtonf95f3852011-01-02 01:11:59 -05001299 goto unlock;
1300 }
1301
1302 prev_state = state = STATE_SENDING_DATA;
1303 /* fall through */
1304
1305 case STATE_SENDING_DATA:
1306 if (test_and_clear_bit(EVENT_DATA_ERROR,
1307 &host->pending_events)) {
1308 dw_mci_stop_dma(host);
Seungwon Jeon90c21432013-08-31 00:14:05 +09001309 send_stop_abort(host, data);
Will Newtonf95f3852011-01-02 01:11:59 -05001310 state = STATE_DATA_ERROR;
1311 break;
1312 }
1313
1314 if (!test_and_clear_bit(EVENT_XFER_COMPLETE,
1315 &host->pending_events))
1316 break;
1317
1318 set_bit(EVENT_XFER_COMPLETE, &host->completed_events);
1319 prev_state = state = STATE_DATA_BUSY;
1320 /* fall through */
1321
1322 case STATE_DATA_BUSY:
1323 if (!test_and_clear_bit(EVENT_DATA_COMPLETE,
1324 &host->pending_events))
1325 break;
1326
1327 host->data = NULL;
1328 set_bit(EVENT_DATA_COMPLETE, &host->completed_events);
Seungwon Jeone352c812013-08-31 00:14:17 +09001329 err = dw_mci_data_complete(host, data);
Will Newtonf95f3852011-01-02 01:11:59 -05001330
Seungwon Jeone352c812013-08-31 00:14:17 +09001331 if (!err) {
1332 if (!data->stop || mrq->sbc) {
1333 if (mrq->sbc)
1334 data->stop->error = 0;
1335 dw_mci_request_end(host, mrq);
1336 goto unlock;
Will Newtonf95f3852011-01-02 01:11:59 -05001337 }
Will Newtonf95f3852011-01-02 01:11:59 -05001338
Seungwon Jeon90c21432013-08-31 00:14:05 +09001339 /* stop command for open-ended transfer*/
Seungwon Jeone352c812013-08-31 00:14:17 +09001340 if (data->stop)
1341 send_stop_abort(host, data);
Seungwon Jeon90c21432013-08-31 00:14:05 +09001342 }
Seungwon Jeone352c812013-08-31 00:14:17 +09001343
1344 /*
1345 * If err has non-zero,
1346 * stop-abort command has been already issued.
1347 */
1348 prev_state = state = STATE_SENDING_STOP;
1349
Will Newtonf95f3852011-01-02 01:11:59 -05001350 /* fall through */
1351
1352 case STATE_SENDING_STOP:
1353 if (!test_and_clear_bit(EVENT_CMD_COMPLETE,
1354 &host->pending_events))
1355 break;
1356
Seungwon Jeon71abb132013-08-31 00:13:59 +09001357 /* CMD error in data command */
Seungwon Jeone352c812013-08-31 00:14:17 +09001358 if (mrq->cmd->error && mrq->data) {
Seungwon Jeon71abb132013-08-31 00:13:59 +09001359 sg_miter_stop(&host->sg_miter);
1360 host->sg = NULL;
1361 ctrl = mci_readl(host, CTRL);
1362 ctrl |= SDMMC_CTRL_FIFO_RESET;
1363 mci_writel(host, CTRL, ctrl);
1364 }
1365
Will Newtonf95f3852011-01-02 01:11:59 -05001366 host->cmd = NULL;
Seungwon Jeon71abb132013-08-31 00:13:59 +09001367 host->data = NULL;
Seungwon Jeon90c21432013-08-31 00:14:05 +09001368
Seungwon Jeone352c812013-08-31 00:14:17 +09001369 if (mrq->stop)
1370 dw_mci_command_complete(host, mrq->stop);
Seungwon Jeon90c21432013-08-31 00:14:05 +09001371 else
1372 host->cmd_status = 0;
1373
Seungwon Jeone352c812013-08-31 00:14:17 +09001374 dw_mci_request_end(host, mrq);
Will Newtonf95f3852011-01-02 01:11:59 -05001375 goto unlock;
1376
1377 case STATE_DATA_ERROR:
1378 if (!test_and_clear_bit(EVENT_XFER_COMPLETE,
1379 &host->pending_events))
1380 break;
1381
1382 state = STATE_DATA_BUSY;
1383 break;
1384 }
1385 } while (state != prev_state);
1386
1387 host->state = state;
1388unlock:
1389 spin_unlock(&host->lock);
1390
1391}
1392
James Hogan34b664a2011-06-24 13:57:56 +01001393/* push final bytes to part_buf, only use during push */
1394static void dw_mci_set_part_bytes(struct dw_mci *host, void *buf, int cnt)
1395{
1396 memcpy((void *)&host->part_buf, buf, cnt);
1397 host->part_buf_count = cnt;
1398}
1399
1400/* append bytes to part_buf, only use during push */
1401static int dw_mci_push_part_bytes(struct dw_mci *host, void *buf, int cnt)
1402{
1403 cnt = min(cnt, (1 << host->data_shift) - host->part_buf_count);
1404 memcpy((void *)&host->part_buf + host->part_buf_count, buf, cnt);
1405 host->part_buf_count += cnt;
1406 return cnt;
1407}
1408
1409/* pull first bytes from part_buf, only use during pull */
1410static int dw_mci_pull_part_bytes(struct dw_mci *host, void *buf, int cnt)
1411{
1412 cnt = min(cnt, (int)host->part_buf_count);
1413 if (cnt) {
1414 memcpy(buf, (void *)&host->part_buf + host->part_buf_start,
1415 cnt);
1416 host->part_buf_count -= cnt;
1417 host->part_buf_start += cnt;
1418 }
1419 return cnt;
1420}
1421
1422/* pull final bytes from the part_buf, assuming it's just been filled */
1423static void dw_mci_pull_final_bytes(struct dw_mci *host, void *buf, int cnt)
1424{
1425 memcpy(buf, &host->part_buf, cnt);
1426 host->part_buf_start = cnt;
1427 host->part_buf_count = (1 << host->data_shift) - cnt;
1428}
1429
Will Newtonf95f3852011-01-02 01:11:59 -05001430static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
1431{
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001432 struct mmc_data *data = host->data;
1433 int init_cnt = cnt;
1434
James Hogan34b664a2011-06-24 13:57:56 +01001435 /* try and push anything in the part_buf */
1436 if (unlikely(host->part_buf_count)) {
1437 int len = dw_mci_push_part_bytes(host, buf, cnt);
1438 buf += len;
1439 cnt -= len;
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001440 if (host->part_buf_count == 2) {
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001441 mci_writew(host, DATA(host->data_offset),
1442 host->part_buf16);
James Hogan34b664a2011-06-24 13:57:56 +01001443 host->part_buf_count = 0;
1444 }
1445 }
1446#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
1447 if (unlikely((unsigned long)buf & 0x1)) {
1448 while (cnt >= 2) {
1449 u16 aligned_buf[64];
1450 int len = min(cnt & -2, (int)sizeof(aligned_buf));
1451 int items = len >> 1;
1452 int i;
1453 /* memcpy from input buffer into aligned buffer */
1454 memcpy(aligned_buf, buf, len);
1455 buf += len;
1456 cnt -= len;
1457 /* push data from aligned buffer into fifo */
1458 for (i = 0; i < items; ++i)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001459 mci_writew(host, DATA(host->data_offset),
1460 aligned_buf[i]);
James Hogan34b664a2011-06-24 13:57:56 +01001461 }
1462 } else
1463#endif
1464 {
1465 u16 *pdata = buf;
1466 for (; cnt >= 2; cnt -= 2)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001467 mci_writew(host, DATA(host->data_offset), *pdata++);
James Hogan34b664a2011-06-24 13:57:56 +01001468 buf = pdata;
1469 }
1470 /* put anything remaining in the part_buf */
1471 if (cnt) {
1472 dw_mci_set_part_bytes(host, buf, cnt);
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001473 /* Push data if we have reached the expected data length */
1474 if ((data->bytes_xfered + init_cnt) ==
1475 (data->blksz * data->blocks))
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001476 mci_writew(host, DATA(host->data_offset),
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001477 host->part_buf16);
Will Newtonf95f3852011-01-02 01:11:59 -05001478 }
1479}
1480
1481static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
1482{
James Hogan34b664a2011-06-24 13:57:56 +01001483#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
1484 if (unlikely((unsigned long)buf & 0x1)) {
1485 while (cnt >= 2) {
1486 /* pull data from fifo into aligned buffer */
1487 u16 aligned_buf[64];
1488 int len = min(cnt & -2, (int)sizeof(aligned_buf));
1489 int items = len >> 1;
1490 int i;
1491 for (i = 0; i < items; ++i)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001492 aligned_buf[i] = mci_readw(host,
1493 DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001494 /* memcpy from aligned buffer into output buffer */
1495 memcpy(buf, aligned_buf, len);
1496 buf += len;
1497 cnt -= len;
1498 }
1499 } else
1500#endif
1501 {
1502 u16 *pdata = buf;
1503 for (; cnt >= 2; cnt -= 2)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001504 *pdata++ = mci_readw(host, DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001505 buf = pdata;
1506 }
1507 if (cnt) {
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001508 host->part_buf16 = mci_readw(host, DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001509 dw_mci_pull_final_bytes(host, buf, cnt);
Will Newtonf95f3852011-01-02 01:11:59 -05001510 }
1511}
1512
1513static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
1514{
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001515 struct mmc_data *data = host->data;
1516 int init_cnt = cnt;
1517
James Hogan34b664a2011-06-24 13:57:56 +01001518 /* try and push anything in the part_buf */
1519 if (unlikely(host->part_buf_count)) {
1520 int len = dw_mci_push_part_bytes(host, buf, cnt);
1521 buf += len;
1522 cnt -= len;
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001523 if (host->part_buf_count == 4) {
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001524 mci_writel(host, DATA(host->data_offset),
1525 host->part_buf32);
James Hogan34b664a2011-06-24 13:57:56 +01001526 host->part_buf_count = 0;
1527 }
1528 }
1529#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
1530 if (unlikely((unsigned long)buf & 0x3)) {
1531 while (cnt >= 4) {
1532 u32 aligned_buf[32];
1533 int len = min(cnt & -4, (int)sizeof(aligned_buf));
1534 int items = len >> 2;
1535 int i;
1536 /* memcpy from input buffer into aligned buffer */
1537 memcpy(aligned_buf, buf, len);
1538 buf += len;
1539 cnt -= len;
1540 /* push data from aligned buffer into fifo */
1541 for (i = 0; i < items; ++i)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001542 mci_writel(host, DATA(host->data_offset),
1543 aligned_buf[i]);
James Hogan34b664a2011-06-24 13:57:56 +01001544 }
1545 } else
1546#endif
1547 {
1548 u32 *pdata = buf;
1549 for (; cnt >= 4; cnt -= 4)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001550 mci_writel(host, DATA(host->data_offset), *pdata++);
James Hogan34b664a2011-06-24 13:57:56 +01001551 buf = pdata;
1552 }
1553 /* put anything remaining in the part_buf */
1554 if (cnt) {
1555 dw_mci_set_part_bytes(host, buf, cnt);
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001556 /* Push data if we have reached the expected data length */
1557 if ((data->bytes_xfered + init_cnt) ==
1558 (data->blksz * data->blocks))
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001559 mci_writel(host, DATA(host->data_offset),
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001560 host->part_buf32);
Will Newtonf95f3852011-01-02 01:11:59 -05001561 }
1562}
1563
1564static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
1565{
James Hogan34b664a2011-06-24 13:57:56 +01001566#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
1567 if (unlikely((unsigned long)buf & 0x3)) {
1568 while (cnt >= 4) {
1569 /* pull data from fifo into aligned buffer */
1570 u32 aligned_buf[32];
1571 int len = min(cnt & -4, (int)sizeof(aligned_buf));
1572 int items = len >> 2;
1573 int i;
1574 for (i = 0; i < items; ++i)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001575 aligned_buf[i] = mci_readl(host,
1576 DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001577 /* memcpy from aligned buffer into output buffer */
1578 memcpy(buf, aligned_buf, len);
1579 buf += len;
1580 cnt -= len;
1581 }
1582 } else
1583#endif
1584 {
1585 u32 *pdata = buf;
1586 for (; cnt >= 4; cnt -= 4)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001587 *pdata++ = mci_readl(host, DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001588 buf = pdata;
1589 }
1590 if (cnt) {
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001591 host->part_buf32 = mci_readl(host, DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001592 dw_mci_pull_final_bytes(host, buf, cnt);
Will Newtonf95f3852011-01-02 01:11:59 -05001593 }
1594}
1595
1596static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
1597{
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001598 struct mmc_data *data = host->data;
1599 int init_cnt = cnt;
1600
James Hogan34b664a2011-06-24 13:57:56 +01001601 /* try and push anything in the part_buf */
1602 if (unlikely(host->part_buf_count)) {
1603 int len = dw_mci_push_part_bytes(host, buf, cnt);
1604 buf += len;
1605 cnt -= len;
Seungwon Jeonc09fbd72013-03-25 16:28:22 +09001606
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001607 if (host->part_buf_count == 8) {
Seungwon Jeonc09fbd72013-03-25 16:28:22 +09001608 mci_writeq(host, DATA(host->data_offset),
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001609 host->part_buf);
James Hogan34b664a2011-06-24 13:57:56 +01001610 host->part_buf_count = 0;
1611 }
1612 }
1613#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
1614 if (unlikely((unsigned long)buf & 0x7)) {
1615 while (cnt >= 8) {
1616 u64 aligned_buf[16];
1617 int len = min(cnt & -8, (int)sizeof(aligned_buf));
1618 int items = len >> 3;
1619 int i;
1620 /* memcpy from input buffer into aligned buffer */
1621 memcpy(aligned_buf, buf, len);
1622 buf += len;
1623 cnt -= len;
1624 /* push data from aligned buffer into fifo */
1625 for (i = 0; i < items; ++i)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001626 mci_writeq(host, DATA(host->data_offset),
1627 aligned_buf[i]);
James Hogan34b664a2011-06-24 13:57:56 +01001628 }
1629 } else
1630#endif
1631 {
1632 u64 *pdata = buf;
1633 for (; cnt >= 8; cnt -= 8)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001634 mci_writeq(host, DATA(host->data_offset), *pdata++);
James Hogan34b664a2011-06-24 13:57:56 +01001635 buf = pdata;
1636 }
1637 /* put anything remaining in the part_buf */
1638 if (cnt) {
1639 dw_mci_set_part_bytes(host, buf, cnt);
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001640 /* Push data if we have reached the expected data length */
1641 if ((data->bytes_xfered + init_cnt) ==
1642 (data->blksz * data->blocks))
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001643 mci_writeq(host, DATA(host->data_offset),
Markos Chandrascfbeb59c2013-03-12 10:53:13 +00001644 host->part_buf);
Will Newtonf95f3852011-01-02 01:11:59 -05001645 }
1646}
1647
1648static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
1649{
James Hogan34b664a2011-06-24 13:57:56 +01001650#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
1651 if (unlikely((unsigned long)buf & 0x7)) {
1652 while (cnt >= 8) {
1653 /* pull data from fifo into aligned buffer */
1654 u64 aligned_buf[16];
1655 int len = min(cnt & -8, (int)sizeof(aligned_buf));
1656 int items = len >> 3;
1657 int i;
1658 for (i = 0; i < items; ++i)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001659 aligned_buf[i] = mci_readq(host,
1660 DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001661 /* memcpy from aligned buffer into output buffer */
1662 memcpy(buf, aligned_buf, len);
1663 buf += len;
1664 cnt -= len;
1665 }
1666 } else
1667#endif
1668 {
1669 u64 *pdata = buf;
1670 for (; cnt >= 8; cnt -= 8)
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001671 *pdata++ = mci_readq(host, DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001672 buf = pdata;
Will Newtonf95f3852011-01-02 01:11:59 -05001673 }
James Hogan34b664a2011-06-24 13:57:56 +01001674 if (cnt) {
Jaehoon Chung4e0a5ad2011-10-17 19:36:23 +09001675 host->part_buf = mci_readq(host, DATA(host->data_offset));
James Hogan34b664a2011-06-24 13:57:56 +01001676 dw_mci_pull_final_bytes(host, buf, cnt);
1677 }
1678}
1679
1680static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
1681{
1682 int len;
1683
1684 /* get remaining partial bytes */
1685 len = dw_mci_pull_part_bytes(host, buf, cnt);
1686 if (unlikely(len == cnt))
1687 return;
1688 buf += len;
1689 cnt -= len;
1690
1691 /* get the rest of the data */
1692 host->pull_data(host, buf, cnt);
Will Newtonf95f3852011-01-02 01:11:59 -05001693}
1694
Kyoungil Kim87a74d32013-01-22 16:46:30 +09001695static void dw_mci_read_data_pio(struct dw_mci *host, bool dto)
Will Newtonf95f3852011-01-02 01:11:59 -05001696{
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001697 struct sg_mapping_iter *sg_miter = &host->sg_miter;
1698 void *buf;
1699 unsigned int offset;
Will Newtonf95f3852011-01-02 01:11:59 -05001700 struct mmc_data *data = host->data;
1701 int shift = host->data_shift;
1702 u32 status;
Markos Chandras3e4b0d82013-03-22 12:50:05 -04001703 unsigned int len;
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001704 unsigned int remain, fcnt;
Will Newtonf95f3852011-01-02 01:11:59 -05001705
1706 do {
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001707 if (!sg_miter_next(sg_miter))
1708 goto done;
Will Newtonf95f3852011-01-02 01:11:59 -05001709
Imre Deak4225fc82013-02-27 17:02:57 -08001710 host->sg = sg_miter->piter.sg;
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001711 buf = sg_miter->addr;
1712 remain = sg_miter->length;
1713 offset = 0;
1714
1715 do {
1716 fcnt = (SDMMC_GET_FCNT(mci_readl(host, STATUS))
1717 << shift) + host->part_buf_count;
1718 len = min(remain, fcnt);
1719 if (!len)
1720 break;
1721 dw_mci_pull_data(host, (void *)(buf + offset), len);
Markos Chandras3e4b0d82013-03-22 12:50:05 -04001722 data->bytes_xfered += len;
Will Newtonf95f3852011-01-02 01:11:59 -05001723 offset += len;
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001724 remain -= len;
1725 } while (remain);
Will Newtonf95f3852011-01-02 01:11:59 -05001726
Seungwon Jeone74f3a92012-08-01 09:30:46 +09001727 sg_miter->consumed = offset;
Will Newtonf95f3852011-01-02 01:11:59 -05001728 status = mci_readl(host, MINTSTS);
1729 mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
Kyoungil Kim87a74d32013-01-22 16:46:30 +09001730 /* if the RXDR is ready read again */
1731 } while ((status & SDMMC_INT_RXDR) ||
1732 (dto && SDMMC_GET_FCNT(mci_readl(host, STATUS))));
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001733
1734 if (!remain) {
1735 if (!sg_miter_next(sg_miter))
1736 goto done;
1737 sg_miter->consumed = 0;
1738 }
1739 sg_miter_stop(sg_miter);
Will Newtonf95f3852011-01-02 01:11:59 -05001740 return;
1741
1742done:
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001743 sg_miter_stop(sg_miter);
1744 host->sg = NULL;
Will Newtonf95f3852011-01-02 01:11:59 -05001745 smp_wmb();
1746 set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
1747}
1748
1749static void dw_mci_write_data_pio(struct dw_mci *host)
1750{
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001751 struct sg_mapping_iter *sg_miter = &host->sg_miter;
1752 void *buf;
1753 unsigned int offset;
Will Newtonf95f3852011-01-02 01:11:59 -05001754 struct mmc_data *data = host->data;
1755 int shift = host->data_shift;
1756 u32 status;
Markos Chandras3e4b0d82013-03-22 12:50:05 -04001757 unsigned int len;
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001758 unsigned int fifo_depth = host->fifo_depth;
1759 unsigned int remain, fcnt;
Will Newtonf95f3852011-01-02 01:11:59 -05001760
1761 do {
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001762 if (!sg_miter_next(sg_miter))
1763 goto done;
Will Newtonf95f3852011-01-02 01:11:59 -05001764
Imre Deak4225fc82013-02-27 17:02:57 -08001765 host->sg = sg_miter->piter.sg;
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001766 buf = sg_miter->addr;
1767 remain = sg_miter->length;
1768 offset = 0;
1769
1770 do {
1771 fcnt = ((fifo_depth -
1772 SDMMC_GET_FCNT(mci_readl(host, STATUS)))
1773 << shift) - host->part_buf_count;
1774 len = min(remain, fcnt);
1775 if (!len)
1776 break;
1777 host->push_data(host, (void *)(buf + offset), len);
Markos Chandras3e4b0d82013-03-22 12:50:05 -04001778 data->bytes_xfered += len;
Will Newtonf95f3852011-01-02 01:11:59 -05001779 offset += len;
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001780 remain -= len;
1781 } while (remain);
Will Newtonf95f3852011-01-02 01:11:59 -05001782
Seungwon Jeone74f3a92012-08-01 09:30:46 +09001783 sg_miter->consumed = offset;
Will Newtonf95f3852011-01-02 01:11:59 -05001784 status = mci_readl(host, MINTSTS);
1785 mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
Will Newtonf95f3852011-01-02 01:11:59 -05001786 } while (status & SDMMC_INT_TXDR); /* if TXDR write again */
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001787
1788 if (!remain) {
1789 if (!sg_miter_next(sg_miter))
1790 goto done;
1791 sg_miter->consumed = 0;
1792 }
1793 sg_miter_stop(sg_miter);
Will Newtonf95f3852011-01-02 01:11:59 -05001794 return;
1795
1796done:
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001797 sg_miter_stop(sg_miter);
1798 host->sg = NULL;
Will Newtonf95f3852011-01-02 01:11:59 -05001799 smp_wmb();
1800 set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
1801}
1802
1803static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
1804{
1805 if (!host->cmd_status)
1806 host->cmd_status = status;
1807
1808 smp_wmb();
1809
1810 set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
1811 tasklet_schedule(&host->tasklet);
1812}
1813
1814static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
1815{
1816 struct dw_mci *host = dev_id;
Seungwon Jeon182c9082012-08-01 09:30:30 +09001817 u32 pending;
Shashidhar Hiremath1a5c8e12011-08-29 13:11:46 +05301818 int i;
Will Newtonf95f3852011-01-02 01:11:59 -05001819
Markos Chandras1fb5f682013-03-12 10:53:11 +00001820 pending = mci_readl(host, MINTSTS); /* read-only mask reg */
1821
Doug Anderson476d79f2013-07-09 13:04:40 -07001822 /*
1823 * DTO fix - version 2.10a and below, and only if internal DMA
1824 * is configured.
1825 */
1826 if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
1827 if (!pending &&
1828 ((mci_readl(host, STATUS) >> 17) & 0x1fff))
1829 pending |= SDMMC_INT_DATA_OVER;
1830 }
1831
Markos Chandras1fb5f682013-03-12 10:53:11 +00001832 if (pending) {
Will Newtonf95f3852011-01-02 01:11:59 -05001833 if (pending & DW_MCI_CMD_ERROR_FLAGS) {
1834 mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
Seungwon Jeon182c9082012-08-01 09:30:30 +09001835 host->cmd_status = pending;
Will Newtonf95f3852011-01-02 01:11:59 -05001836 smp_wmb();
1837 set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
Will Newtonf95f3852011-01-02 01:11:59 -05001838 }
1839
1840 if (pending & DW_MCI_DATA_ERROR_FLAGS) {
1841 /* if there is an error report DATA_ERROR */
1842 mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
Seungwon Jeon182c9082012-08-01 09:30:30 +09001843 host->data_status = pending;
Will Newtonf95f3852011-01-02 01:11:59 -05001844 smp_wmb();
1845 set_bit(EVENT_DATA_ERROR, &host->pending_events);
Seungwon Jeon9b2026a2012-08-01 09:30:40 +09001846 tasklet_schedule(&host->tasklet);
Will Newtonf95f3852011-01-02 01:11:59 -05001847 }
1848
1849 if (pending & SDMMC_INT_DATA_OVER) {
1850 mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);
1851 if (!host->data_status)
Seungwon Jeon182c9082012-08-01 09:30:30 +09001852 host->data_status = pending;
Will Newtonf95f3852011-01-02 01:11:59 -05001853 smp_wmb();
1854 if (host->dir_status == DW_MCI_RECV_STATUS) {
1855 if (host->sg != NULL)
Kyoungil Kim87a74d32013-01-22 16:46:30 +09001856 dw_mci_read_data_pio(host, true);
Will Newtonf95f3852011-01-02 01:11:59 -05001857 }
1858 set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
1859 tasklet_schedule(&host->tasklet);
1860 }
1861
1862 if (pending & SDMMC_INT_RXDR) {
1863 mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
James Hoganb40af3a2011-06-24 13:54:06 +01001864 if (host->dir_status == DW_MCI_RECV_STATUS && host->sg)
Kyoungil Kim87a74d32013-01-22 16:46:30 +09001865 dw_mci_read_data_pio(host, false);
Will Newtonf95f3852011-01-02 01:11:59 -05001866 }
1867
1868 if (pending & SDMMC_INT_TXDR) {
1869 mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
James Hoganb40af3a2011-06-24 13:54:06 +01001870 if (host->dir_status == DW_MCI_SEND_STATUS && host->sg)
Will Newtonf95f3852011-01-02 01:11:59 -05001871 dw_mci_write_data_pio(host);
1872 }
1873
1874 if (pending & SDMMC_INT_CMD_DONE) {
1875 mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE);
Seungwon Jeon182c9082012-08-01 09:30:30 +09001876 dw_mci_cmd_interrupt(host, pending);
Will Newtonf95f3852011-01-02 01:11:59 -05001877 }
1878
1879 if (pending & SDMMC_INT_CD) {
1880 mci_writel(host, RINTSTS, SDMMC_INT_CD);
Thomas Abraham95dcc2c2012-05-01 14:57:36 -07001881 queue_work(host->card_workqueue, &host->card_work);
Will Newtonf95f3852011-01-02 01:11:59 -05001882 }
1883
Shashidhar Hiremath1a5c8e12011-08-29 13:11:46 +05301884 /* Handle SDIO Interrupts */
1885 for (i = 0; i < host->num_slots; i++) {
1886 struct dw_mci_slot *slot = host->slot[i];
1887 if (pending & SDMMC_INT_SDIO(i)) {
1888 mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i));
1889 mmc_signal_sdio_irq(slot->mmc);
1890 }
1891 }
1892
Markos Chandras1fb5f682013-03-12 10:53:11 +00001893 }
Will Newtonf95f3852011-01-02 01:11:59 -05001894
1895#ifdef CONFIG_MMC_DW_IDMAC
1896 /* Handle DMA interrupts */
1897 pending = mci_readl(host, IDSTS);
1898 if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
1899 mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
1900 mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
Will Newtonf95f3852011-01-02 01:11:59 -05001901 host->dma_ops->complete(host);
1902 }
1903#endif
1904
1905 return IRQ_HANDLED;
1906}
1907
James Hogan1791b13e2011-06-24 13:55:55 +01001908static void dw_mci_work_routine_card(struct work_struct *work)
Will Newtonf95f3852011-01-02 01:11:59 -05001909{
James Hogan1791b13e2011-06-24 13:55:55 +01001910 struct dw_mci *host = container_of(work, struct dw_mci, card_work);
Will Newtonf95f3852011-01-02 01:11:59 -05001911 int i;
1912
1913 for (i = 0; i < host->num_slots; i++) {
1914 struct dw_mci_slot *slot = host->slot[i];
1915 struct mmc_host *mmc = slot->mmc;
1916 struct mmc_request *mrq;
1917 int present;
1918 u32 ctrl;
1919
1920 present = dw_mci_get_cd(mmc);
1921 while (present != slot->last_detect_state) {
Will Newtonf95f3852011-01-02 01:11:59 -05001922 dev_dbg(&slot->mmc->class_dev, "card %s\n",
1923 present ? "inserted" : "removed");
1924
James Hogan1791b13e2011-06-24 13:55:55 +01001925 spin_lock_bh(&host->lock);
1926
Will Newtonf95f3852011-01-02 01:11:59 -05001927 /* Card change detected */
1928 slot->last_detect_state = present;
1929
James Hogan1791b13e2011-06-24 13:55:55 +01001930 /* Mark card as present if applicable */
1931 if (present != 0)
Will Newtonf95f3852011-01-02 01:11:59 -05001932 set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
Will Newtonf95f3852011-01-02 01:11:59 -05001933
1934 /* Clean up queue if present */
1935 mrq = slot->mrq;
1936 if (mrq) {
1937 if (mrq == host->mrq) {
1938 host->data = NULL;
1939 host->cmd = NULL;
1940
1941 switch (host->state) {
1942 case STATE_IDLE:
1943 break;
1944 case STATE_SENDING_CMD:
1945 mrq->cmd->error = -ENOMEDIUM;
1946 if (!mrq->data)
1947 break;
1948 /* fall through */
1949 case STATE_SENDING_DATA:
1950 mrq->data->error = -ENOMEDIUM;
1951 dw_mci_stop_dma(host);
1952 break;
1953 case STATE_DATA_BUSY:
1954 case STATE_DATA_ERROR:
1955 if (mrq->data->error == -EINPROGRESS)
1956 mrq->data->error = -ENOMEDIUM;
Will Newtonf95f3852011-01-02 01:11:59 -05001957 /* fall through */
1958 case STATE_SENDING_STOP:
Seungwon Jeon90c21432013-08-31 00:14:05 +09001959 if (mrq->stop)
1960 mrq->stop->error = -ENOMEDIUM;
Will Newtonf95f3852011-01-02 01:11:59 -05001961 break;
1962 }
1963
1964 dw_mci_request_end(host, mrq);
1965 } else {
1966 list_del(&slot->queue_node);
1967 mrq->cmd->error = -ENOMEDIUM;
1968 if (mrq->data)
1969 mrq->data->error = -ENOMEDIUM;
1970 if (mrq->stop)
1971 mrq->stop->error = -ENOMEDIUM;
1972
1973 spin_unlock(&host->lock);
1974 mmc_request_done(slot->mmc, mrq);
1975 spin_lock(&host->lock);
1976 }
1977 }
1978
1979 /* Power down slot */
1980 if (present == 0) {
Will Newtonf95f3852011-01-02 01:11:59 -05001981 clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
1982
1983 /*
1984 * Clear down the FIFO - doing so generates a
1985 * block interrupt, hence setting the
1986 * scatter-gather pointer to NULL.
1987 */
Seungwon Jeonf9c2a0d2012-02-09 14:32:43 +09001988 sg_miter_stop(&host->sg_miter);
Will Newtonf95f3852011-01-02 01:11:59 -05001989 host->sg = NULL;
1990
1991 ctrl = mci_readl(host, CTRL);
1992 ctrl |= SDMMC_CTRL_FIFO_RESET;
1993 mci_writel(host, CTRL, ctrl);
1994
1995#ifdef CONFIG_MMC_DW_IDMAC
1996 ctrl = mci_readl(host, BMOD);
Seungwon Jeon141a7122012-05-22 13:01:03 +09001997 /* Software reset of DMA */
1998 ctrl |= SDMMC_IDMAC_SWRESET;
Will Newtonf95f3852011-01-02 01:11:59 -05001999 mci_writel(host, BMOD, ctrl);
2000#endif
2001
2002 }
2003
James Hogan1791b13e2011-06-24 13:55:55 +01002004 spin_unlock_bh(&host->lock);
2005
Will Newtonf95f3852011-01-02 01:11:59 -05002006 present = dw_mci_get_cd(mmc);
2007 }
2008
2009 mmc_detect_change(slot->mmc,
2010 msecs_to_jiffies(host->pdata->detect_delay_ms));
2011 }
2012}
2013
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002014#ifdef CONFIG_OF
2015/* given a slot id, find out the device node representing that slot */
2016static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
2017{
2018 struct device_node *np;
2019 const __be32 *addr;
2020 int len;
2021
2022 if (!dev || !dev->of_node)
2023 return NULL;
2024
2025 for_each_child_of_node(dev->of_node, np) {
2026 addr = of_get_property(np, "reg", &len);
2027 if (!addr || (len < sizeof(int)))
2028 continue;
2029 if (be32_to_cpup(addr) == slot)
2030 return np;
2031 }
2032 return NULL;
2033}
2034
Doug Andersona70aaa62013-01-11 17:03:50 +00002035static struct dw_mci_of_slot_quirks {
2036 char *quirk;
2037 int id;
2038} of_slot_quirks[] = {
2039 {
2040 .quirk = "disable-wp",
2041 .id = DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT,
2042 },
2043};
2044
2045static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
2046{
2047 struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
2048 int quirks = 0;
2049 int idx;
2050
2051 /* get quirks */
2052 for (idx = 0; idx < ARRAY_SIZE(of_slot_quirks); idx++)
2053 if (of_get_property(np, of_slot_quirks[idx].quirk, NULL))
2054 quirks |= of_slot_quirks[idx].id;
2055
2056 return quirks;
2057}
2058
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002059/* find out bus-width for a given slot */
2060static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
2061{
2062 struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
2063 u32 bus_wd = 1;
2064
2065 if (!np)
2066 return 1;
2067
2068 if (of_property_read_u32(np, "bus-width", &bus_wd))
2069 dev_err(dev, "bus-width property not found, assuming width"
2070 " as 1\n");
2071 return bus_wd;
2072}
Doug Anderson55a6ceb2013-01-11 17:03:53 +00002073
2074/* find the write protect gpio for a given slot; or -1 if none specified */
2075static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
2076{
2077 struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
2078 int gpio;
2079
2080 if (!np)
2081 return -EINVAL;
2082
2083 gpio = of_get_named_gpio(np, "wp-gpios", 0);
2084
2085 /* Having a missing entry is valid; return silently */
2086 if (!gpio_is_valid(gpio))
2087 return -EINVAL;
2088
2089 if (devm_gpio_request(dev, gpio, "dw-mci-wp")) {
2090 dev_warn(dev, "gpio [%d] request failed\n", gpio);
2091 return -EINVAL;
2092 }
2093
2094 return gpio;
2095}
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002096#else /* CONFIG_OF */
Doug Andersona70aaa62013-01-11 17:03:50 +00002097static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
2098{
2099 return 0;
2100}
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002101static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
2102{
2103 return 1;
2104}
2105static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
2106{
2107 return NULL;
2108}
Doug Anderson55a6ceb2013-01-11 17:03:53 +00002109static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
2110{
2111 return -EINVAL;
2112}
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002113#endif /* CONFIG_OF */
2114
Jaehoon Chung36c179a2012-08-23 20:31:48 +09002115static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
Will Newtonf95f3852011-01-02 01:11:59 -05002116{
2117 struct mmc_host *mmc;
2118 struct dw_mci_slot *slot;
Arnd Bergmanne95baf12012-11-08 14:26:11 +00002119 const struct dw_mci_drv_data *drv_data = host->drv_data;
Thomas Abraham800d78b2012-09-17 18:16:42 +00002120 int ctrl_id, ret;
Seungwon Jeon1f44a2a2013-08-31 00:13:31 +09002121 u32 freq[2];
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002122 u8 bus_width;
Will Newtonf95f3852011-01-02 01:11:59 -05002123
Thomas Abraham4a909202012-09-17 18:16:35 +00002124 mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
Will Newtonf95f3852011-01-02 01:11:59 -05002125 if (!mmc)
2126 return -ENOMEM;
2127
2128 slot = mmc_priv(mmc);
2129 slot->id = id;
2130 slot->mmc = mmc;
2131 slot->host = host;
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002132 host->slot[id] = slot;
Will Newtonf95f3852011-01-02 01:11:59 -05002133
Doug Andersona70aaa62013-01-11 17:03:50 +00002134 slot->quirks = dw_mci_of_get_slot_quirks(host->dev, slot->id);
2135
Will Newtonf95f3852011-01-02 01:11:59 -05002136 mmc->ops = &dw_mci_ops;
Seungwon Jeon1f44a2a2013-08-31 00:13:31 +09002137 if (of_property_read_u32_array(host->dev->of_node,
2138 "clock-freq-min-max", freq, 2)) {
2139 mmc->f_min = DW_MCI_FREQ_MIN;
2140 mmc->f_max = DW_MCI_FREQ_MAX;
2141 } else {
2142 mmc->f_min = freq[0];
2143 mmc->f_max = freq[1];
2144 }
Will Newtonf95f3852011-01-02 01:11:59 -05002145
2146 if (host->pdata->get_ocr)
2147 mmc->ocr_avail = host->pdata->get_ocr(id);
2148 else
2149 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
2150
2151 /*
2152 * Start with slot power disabled, it will be enabled when a card
2153 * is detected.
2154 */
2155 if (host->pdata->setpower)
2156 host->pdata->setpower(id, 0);
2157
Jaehoon Chungfc3d7722011-02-25 11:08:15 +09002158 if (host->pdata->caps)
2159 mmc->caps = host->pdata->caps;
Jaehoon Chungfc3d7722011-02-25 11:08:15 +09002160
Abhilash Kesavanab269122012-11-19 10:26:21 +05302161 if (host->pdata->pm_caps)
2162 mmc->pm_caps = host->pdata->pm_caps;
2163
Thomas Abraham800d78b2012-09-17 18:16:42 +00002164 if (host->dev->of_node) {
2165 ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
2166 if (ctrl_id < 0)
2167 ctrl_id = 0;
2168 } else {
2169 ctrl_id = to_platform_device(host->dev)->id;
2170 }
James Hogancb27a842012-10-16 09:43:08 +01002171 if (drv_data && drv_data->caps)
2172 mmc->caps |= drv_data->caps[ctrl_id];
Thomas Abraham800d78b2012-09-17 18:16:42 +00002173
Seungwon Jeon4f408cc2011-12-09 14:55:52 +09002174 if (host->pdata->caps2)
2175 mmc->caps2 = host->pdata->caps2;
Seungwon Jeon4f408cc2011-12-09 14:55:52 +09002176
Will Newtonf95f3852011-01-02 01:11:59 -05002177 if (host->pdata->get_bus_wd)
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002178 bus_width = host->pdata->get_bus_wd(slot->id);
2179 else if (host->dev->of_node)
2180 bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id);
2181 else
2182 bus_width = 1;
2183
2184 switch (bus_width) {
2185 case 8:
2186 mmc->caps |= MMC_CAP_8_BIT_DATA;
2187 case 4:
2188 mmc->caps |= MMC_CAP_4_BIT_DATA;
2189 }
Will Newtonf95f3852011-01-02 01:11:59 -05002190
Will Newtonf95f3852011-01-02 01:11:59 -05002191 if (host->pdata->blk_settings) {
2192 mmc->max_segs = host->pdata->blk_settings->max_segs;
2193 mmc->max_blk_size = host->pdata->blk_settings->max_blk_size;
2194 mmc->max_blk_count = host->pdata->blk_settings->max_blk_count;
2195 mmc->max_req_size = host->pdata->blk_settings->max_req_size;
2196 mmc->max_seg_size = host->pdata->blk_settings->max_seg_size;
2197 } else {
2198 /* Useful defaults if platform data is unset. */
Jaehoon Chunga39e5742012-02-04 17:00:27 -05002199#ifdef CONFIG_MMC_DW_IDMAC
2200 mmc->max_segs = host->ring_size;
2201 mmc->max_blk_size = 65536;
2202 mmc->max_blk_count = host->ring_size;
2203 mmc->max_seg_size = 0x1000;
2204 mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count;
2205#else
Will Newtonf95f3852011-01-02 01:11:59 -05002206 mmc->max_segs = 64;
2207 mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
2208 mmc->max_blk_count = 512;
2209 mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
2210 mmc->max_seg_size = mmc->max_req_size;
Will Newtonf95f3852011-01-02 01:11:59 -05002211#endif /* CONFIG_MMC_DW_IDMAC */
Jaehoon Chunga39e5742012-02-04 17:00:27 -05002212 }
Will Newtonf95f3852011-01-02 01:11:59 -05002213
2214 if (dw_mci_get_cd(mmc))
2215 set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
2216 else
2217 clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
2218
Doug Anderson55a6ceb2013-01-11 17:03:53 +00002219 slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id);
2220
Jaehoon Chung0cea5292013-02-15 23:45:45 +09002221 ret = mmc_add_host(mmc);
2222 if (ret)
2223 goto err_setup_bus;
Will Newtonf95f3852011-01-02 01:11:59 -05002224
2225#if defined(CONFIG_DEBUG_FS)
2226 dw_mci_init_debugfs(slot);
2227#endif
2228
2229 /* Card initially undetected */
2230 slot->last_detect_state = 0;
2231
Will Newtonf95f3852011-01-02 01:11:59 -05002232 return 0;
Thomas Abraham800d78b2012-09-17 18:16:42 +00002233
2234err_setup_bus:
2235 mmc_free_host(mmc);
2236 return -EINVAL;
Will Newtonf95f3852011-01-02 01:11:59 -05002237}
2238
2239static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
2240{
2241 /* Shutdown detect IRQ */
2242 if (slot->host->pdata->exit)
2243 slot->host->pdata->exit(id);
2244
2245 /* Debugfs stuff is cleaned up by mmc core */
2246 mmc_remove_host(slot->mmc);
2247 slot->host->slot[id] = NULL;
2248 mmc_free_host(slot->mmc);
2249}
2250
2251static void dw_mci_init_dma(struct dw_mci *host)
2252{
2253 /* Alloc memory for sg translation */
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002254 host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
Will Newtonf95f3852011-01-02 01:11:59 -05002255 &host->sg_dma, GFP_KERNEL);
2256 if (!host->sg_cpu) {
Thomas Abraham4a909202012-09-17 18:16:35 +00002257 dev_err(host->dev, "%s: could not alloc DMA memory\n",
Will Newtonf95f3852011-01-02 01:11:59 -05002258 __func__);
2259 goto no_dma;
2260 }
2261
2262 /* Determine which DMA interface to use */
2263#ifdef CONFIG_MMC_DW_IDMAC
2264 host->dma_ops = &dw_mci_idmac_ops;
Seungwon Jeon00956ea2012-09-28 19:13:11 +09002265 dev_info(host->dev, "Using internal DMA controller.\n");
Will Newtonf95f3852011-01-02 01:11:59 -05002266#endif
2267
2268 if (!host->dma_ops)
2269 goto no_dma;
2270
Jaehoon Chunge1631f92012-04-18 15:42:31 +09002271 if (host->dma_ops->init && host->dma_ops->start &&
2272 host->dma_ops->stop && host->dma_ops->cleanup) {
Will Newtonf95f3852011-01-02 01:11:59 -05002273 if (host->dma_ops->init(host)) {
Thomas Abraham4a909202012-09-17 18:16:35 +00002274 dev_err(host->dev, "%s: Unable to initialize "
Will Newtonf95f3852011-01-02 01:11:59 -05002275 "DMA Controller.\n", __func__);
2276 goto no_dma;
2277 }
2278 } else {
Thomas Abraham4a909202012-09-17 18:16:35 +00002279 dev_err(host->dev, "DMA initialization not found.\n");
Will Newtonf95f3852011-01-02 01:11:59 -05002280 goto no_dma;
2281 }
2282
2283 host->use_dma = 1;
2284 return;
2285
2286no_dma:
Thomas Abraham4a909202012-09-17 18:16:35 +00002287 dev_info(host->dev, "Using PIO mode.\n");
Will Newtonf95f3852011-01-02 01:11:59 -05002288 host->use_dma = 0;
2289 return;
2290}
2291
2292static bool mci_wait_reset(struct device *dev, struct dw_mci *host)
2293{
2294 unsigned long timeout = jiffies + msecs_to_jiffies(500);
2295 unsigned int ctrl;
2296
2297 mci_writel(host, CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET |
2298 SDMMC_CTRL_DMA_RESET));
2299
2300 /* wait till resets clear */
2301 do {
2302 ctrl = mci_readl(host, CTRL);
2303 if (!(ctrl & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET |
2304 SDMMC_CTRL_DMA_RESET)))
2305 return true;
2306 } while (time_before(jiffies, timeout));
2307
2308 dev_err(dev, "Timeout resetting block (ctrl %#x)\n", ctrl);
2309
2310 return false;
2311}
2312
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002313#ifdef CONFIG_OF
2314static struct dw_mci_of_quirks {
2315 char *quirk;
2316 int id;
2317} of_quirks[] = {
2318 {
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002319 .quirk = "broken-cd",
2320 .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
2321 },
2322};
2323
2324static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
2325{
2326 struct dw_mci_board *pdata;
2327 struct device *dev = host->dev;
2328 struct device_node *np = dev->of_node;
Arnd Bergmanne95baf12012-11-08 14:26:11 +00002329 const struct dw_mci_drv_data *drv_data = host->drv_data;
Thomas Abraham800d78b2012-09-17 18:16:42 +00002330 int idx, ret;
Doug Anderson3c6d89e2013-06-07 10:28:30 -07002331 u32 clock_frequency;
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002332
2333 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
2334 if (!pdata) {
2335 dev_err(dev, "could not allocate memory for pdata\n");
2336 return ERR_PTR(-ENOMEM);
2337 }
2338
2339 /* find out number of slots supported */
2340 if (of_property_read_u32(dev->of_node, "num-slots",
2341 &pdata->num_slots)) {
2342 dev_info(dev, "num-slots property not found, "
2343 "assuming 1 slot is available\n");
2344 pdata->num_slots = 1;
2345 }
2346
2347 /* get quirks */
2348 for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++)
2349 if (of_get_property(np, of_quirks[idx].quirk, NULL))
2350 pdata->quirks |= of_quirks[idx].id;
2351
2352 if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth))
2353 dev_info(dev, "fifo-depth property not found, using "
2354 "value of FIFOTH register as default\n");
2355
2356 of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
2357
Doug Anderson3c6d89e2013-06-07 10:28:30 -07002358 if (!of_property_read_u32(np, "clock-frequency", &clock_frequency))
2359 pdata->bus_hz = clock_frequency;
2360
James Hogancb27a842012-10-16 09:43:08 +01002361 if (drv_data && drv_data->parse_dt) {
2362 ret = drv_data->parse_dt(host);
Thomas Abraham800d78b2012-09-17 18:16:42 +00002363 if (ret)
2364 return ERR_PTR(ret);
2365 }
2366
Abhilash Kesavanab269122012-11-19 10:26:21 +05302367 if (of_find_property(np, "keep-power-in-suspend", NULL))
2368 pdata->pm_caps |= MMC_PM_KEEP_POWER;
2369
2370 if (of_find_property(np, "enable-sdio-wakeup", NULL))
2371 pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
2372
Seungwon Jeon10b49842013-08-31 00:13:22 +09002373 if (of_find_property(np, "supports-highspeed", NULL))
2374 pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
2375
Seungwon Jeon5dd63f52013-08-31 00:13:09 +09002376 if (of_find_property(np, "caps2-mmc-hs200-1_8v", NULL))
2377 pdata->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
2378
2379 if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
2380 pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
2381
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002382 return pdata;
2383}
2384
2385#else /* CONFIG_OF */
2386static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
2387{
2388 return ERR_PTR(-EINVAL);
2389}
2390#endif /* CONFIG_OF */
2391
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302392int dw_mci_probe(struct dw_mci *host)
Will Newtonf95f3852011-01-02 01:11:59 -05002393{
Arnd Bergmanne95baf12012-11-08 14:26:11 +00002394 const struct dw_mci_drv_data *drv_data = host->drv_data;
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302395 int width, i, ret = 0;
Will Newtonf95f3852011-01-02 01:11:59 -05002396 u32 fifo_size;
Thomas Abraham1c2215b2012-09-17 18:16:37 +00002397 int init_slots = 0;
Will Newtonf95f3852011-01-02 01:11:59 -05002398
Thomas Abrahamc91eab42012-09-17 18:16:40 +00002399 if (!host->pdata) {
2400 host->pdata = dw_mci_parse_dt(host);
2401 if (IS_ERR(host->pdata)) {
2402 dev_err(host->dev, "platform data not available\n");
2403 return -EINVAL;
2404 }
Will Newtonf95f3852011-01-02 01:11:59 -05002405 }
2406
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302407 if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
Thomas Abraham4a909202012-09-17 18:16:35 +00002408 dev_err(host->dev,
Will Newtonf95f3852011-01-02 01:11:59 -05002409 "Platform data must supply select_slot function\n");
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302410 return -ENODEV;
Will Newtonf95f3852011-01-02 01:11:59 -05002411 }
2412
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002413 host->biu_clk = devm_clk_get(host->dev, "biu");
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002414 if (IS_ERR(host->biu_clk)) {
2415 dev_dbg(host->dev, "biu clock not available\n");
2416 } else {
2417 ret = clk_prepare_enable(host->biu_clk);
2418 if (ret) {
2419 dev_err(host->dev, "failed to enable biu clock\n");
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002420 return ret;
2421 }
Will Newtonf95f3852011-01-02 01:11:59 -05002422 }
2423
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002424 host->ciu_clk = devm_clk_get(host->dev, "ciu");
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002425 if (IS_ERR(host->ciu_clk)) {
2426 dev_dbg(host->dev, "ciu clock not available\n");
Doug Anderson3c6d89e2013-06-07 10:28:30 -07002427 host->bus_hz = host->pdata->bus_hz;
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002428 } else {
2429 ret = clk_prepare_enable(host->ciu_clk);
2430 if (ret) {
2431 dev_err(host->dev, "failed to enable ciu clock\n");
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002432 goto err_clk_biu;
2433 }
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002434
Doug Anderson3c6d89e2013-06-07 10:28:30 -07002435 if (host->pdata->bus_hz) {
2436 ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz);
2437 if (ret)
2438 dev_warn(host->dev,
2439 "Unable to set bus rate to %ul\n",
2440 host->pdata->bus_hz);
2441 }
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002442 host->bus_hz = clk_get_rate(host->ciu_clk);
Doug Anderson3c6d89e2013-06-07 10:28:30 -07002443 }
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002444
Yuvaraj Kumar C D002f0d52013-08-31 00:12:19 +09002445 if (drv_data && drv_data->init) {
2446 ret = drv_data->init(host);
2447 if (ret) {
2448 dev_err(host->dev,
2449 "implementation specific init failed\n");
2450 goto err_clk_ciu;
2451 }
2452 }
2453
James Hogancb27a842012-10-16 09:43:08 +01002454 if (drv_data && drv_data->setup_clock) {
2455 ret = drv_data->setup_clock(host);
Thomas Abraham800d78b2012-09-17 18:16:42 +00002456 if (ret) {
2457 dev_err(host->dev,
2458 "implementation specific clock setup failed\n");
2459 goto err_clk_ciu;
2460 }
2461 }
2462
Mark Browna55d6ff2013-07-29 21:55:27 +01002463 host->vmmc = devm_regulator_get_optional(host->dev, "vmmc");
Doug Anderson870556a2013-06-07 10:28:29 -07002464 if (IS_ERR(host->vmmc)) {
2465 ret = PTR_ERR(host->vmmc);
2466 if (ret == -EPROBE_DEFER)
2467 goto err_clk_ciu;
2468
2469 dev_info(host->dev, "no vmmc regulator found: %d\n", ret);
2470 host->vmmc = NULL;
2471 } else {
2472 ret = regulator_enable(host->vmmc);
2473 if (ret) {
2474 if (ret != -EPROBE_DEFER)
2475 dev_err(host->dev,
2476 "regulator_enable fail: %d\n", ret);
2477 goto err_clk_ciu;
2478 }
2479 }
2480
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002481 if (!host->bus_hz) {
2482 dev_err(host->dev,
2483 "Platform data must supply bus speed\n");
2484 ret = -ENODEV;
Doug Anderson870556a2013-06-07 10:28:29 -07002485 goto err_regulator;
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002486 }
2487
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302488 host->quirks = host->pdata->quirks;
Will Newtonf95f3852011-01-02 01:11:59 -05002489
2490 spin_lock_init(&host->lock);
2491 INIT_LIST_HEAD(&host->queue);
2492
Will Newtonf95f3852011-01-02 01:11:59 -05002493 /*
2494 * Get the host data width - this assumes that HCON has been set with
2495 * the correct values.
2496 */
2497 i = (mci_readl(host, HCON) >> 7) & 0x7;
2498 if (!i) {
2499 host->push_data = dw_mci_push_data16;
2500 host->pull_data = dw_mci_pull_data16;
2501 width = 16;
2502 host->data_shift = 1;
2503 } else if (i == 2) {
2504 host->push_data = dw_mci_push_data64;
2505 host->pull_data = dw_mci_pull_data64;
2506 width = 64;
2507 host->data_shift = 3;
2508 } else {
2509 /* Check for a reserved value, and warn if it is */
2510 WARN((i != 1),
2511 "HCON reports a reserved host data width!\n"
2512 "Defaulting to 32-bit access.\n");
2513 host->push_data = dw_mci_push_data32;
2514 host->pull_data = dw_mci_pull_data32;
2515 width = 32;
2516 host->data_shift = 2;
2517 }
2518
2519 /* Reset all blocks */
Thomas Abraham4a909202012-09-17 18:16:35 +00002520 if (!mci_wait_reset(host->dev, host))
Seungwon Jeon141a7122012-05-22 13:01:03 +09002521 return -ENODEV;
2522
2523 host->dma_ops = host->pdata->dma_ops;
2524 dw_mci_init_dma(host);
Will Newtonf95f3852011-01-02 01:11:59 -05002525
2526 /* Clear the interrupts for the host controller */
2527 mci_writel(host, RINTSTS, 0xFFFFFFFF);
2528 mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
2529
2530 /* Put in max timeout */
2531 mci_writel(host, TMOUT, 0xFFFFFFFF);
2532
2533 /*
2534 * FIFO threshold settings RxMark = fifo_size / 2 - 1,
2535 * Tx Mark = fifo_size / 2 DMA Size = 8
2536 */
James Hoganb86d8252011-06-24 13:57:18 +01002537 if (!host->pdata->fifo_depth) {
2538 /*
2539 * Power-on value of RX_WMark is FIFO_DEPTH-1, but this may
2540 * have been overwritten by the bootloader, just like we're
2541 * about to do, so if you know the value for your hardware, you
2542 * should put it in the platform data.
2543 */
2544 fifo_size = mci_readl(host, FIFOTH);
Jaehoon Chung8234e862012-01-11 09:28:21 +00002545 fifo_size = 1 + ((fifo_size >> 16) & 0xfff);
James Hoganb86d8252011-06-24 13:57:18 +01002546 } else {
2547 fifo_size = host->pdata->fifo_depth;
2548 }
2549 host->fifo_depth = fifo_size;
Seungwon Jeon52426892013-08-31 00:13:42 +09002550 host->fifoth_val =
2551 SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2);
Jaehoon Chunge61cf112011-03-17 20:32:33 +09002552 mci_writel(host, FIFOTH, host->fifoth_val);
Will Newtonf95f3852011-01-02 01:11:59 -05002553
2554 /* disable clock to CIU */
2555 mci_writel(host, CLKENA, 0);
2556 mci_writel(host, CLKSRC, 0);
2557
James Hogan63008762013-03-12 10:43:54 +00002558 /*
2559 * In 2.40a spec, Data offset is changed.
2560 * Need to check the version-id and set data-offset for DATA register.
2561 */
2562 host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
2563 dev_info(host->dev, "Version ID is %04x\n", host->verid);
2564
2565 if (host->verid < DW_MMC_240A)
2566 host->data_offset = DATA_OFFSET;
2567 else
2568 host->data_offset = DATA_240A_OFFSET;
2569
Will Newtonf95f3852011-01-02 01:11:59 -05002570 tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
Thomas Abraham95dcc2c2012-05-01 14:57:36 -07002571 host->card_workqueue = alloc_workqueue("dw-mci-card",
James Hogan1791b13e2011-06-24 13:55:55 +01002572 WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1);
Wei Yongjunef7aef92013-04-19 09:25:45 +08002573 if (!host->card_workqueue) {
2574 ret = -ENOMEM;
James Hogan1791b13e2011-06-24 13:55:55 +01002575 goto err_dmaunmap;
Wei Yongjunef7aef92013-04-19 09:25:45 +08002576 }
James Hogan1791b13e2011-06-24 13:55:55 +01002577 INIT_WORK(&host->card_work, dw_mci_work_routine_card);
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002578 ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
2579 host->irq_flags, "dw-mci", host);
Will Newtonf95f3852011-01-02 01:11:59 -05002580 if (ret)
James Hogan1791b13e2011-06-24 13:55:55 +01002581 goto err_workqueue;
Will Newtonf95f3852011-01-02 01:11:59 -05002582
Will Newtonf95f3852011-01-02 01:11:59 -05002583 if (host->pdata->num_slots)
2584 host->num_slots = host->pdata->num_slots;
2585 else
2586 host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
2587
Yuvaraj CD2da1d7f2012-10-08 14:29:51 +05302588 /*
2589 * Enable interrupts for command done, data over, data empty, card det,
2590 * receive ready and error such as transmit, receive timeout, crc error
2591 */
2592 mci_writel(host, RINTSTS, 0xFFFFFFFF);
2593 mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
2594 SDMMC_INT_TXDR | SDMMC_INT_RXDR |
2595 DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
2596 mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
2597
2598 dev_info(host->dev, "DW MMC controller at irq %d, "
2599 "%d bit host data width, "
2600 "%u deep fifo\n",
2601 host->irq, width, fifo_size);
2602
Will Newtonf95f3852011-01-02 01:11:59 -05002603 /* We need at least one slot to succeed */
2604 for (i = 0; i < host->num_slots; i++) {
2605 ret = dw_mci_init_slot(host, i);
Thomas Abraham1c2215b2012-09-17 18:16:37 +00002606 if (ret)
2607 dev_dbg(host->dev, "slot %d init failed\n", i);
2608 else
2609 init_slots++;
2610 }
2611
2612 if (init_slots) {
2613 dev_info(host->dev, "%d slots initialized\n", init_slots);
2614 } else {
2615 dev_dbg(host->dev, "attempted to initialize %d slots, "
2616 "but failed on all\n", host->num_slots);
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002617 goto err_workqueue;
Will Newtonf95f3852011-01-02 01:11:59 -05002618 }
2619
Will Newtonf95f3852011-01-02 01:11:59 -05002620 if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
Thomas Abraham4a909202012-09-17 18:16:35 +00002621 dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
Will Newtonf95f3852011-01-02 01:11:59 -05002622
2623 return 0;
2624
James Hogan1791b13e2011-06-24 13:55:55 +01002625err_workqueue:
Thomas Abraham95dcc2c2012-05-01 14:57:36 -07002626 destroy_workqueue(host->card_workqueue);
James Hogan1791b13e2011-06-24 13:55:55 +01002627
Will Newtonf95f3852011-01-02 01:11:59 -05002628err_dmaunmap:
2629 if (host->use_dma && host->dma_ops->exit)
2630 host->dma_ops->exit(host);
Will Newtonf95f3852011-01-02 01:11:59 -05002631
Doug Anderson870556a2013-06-07 10:28:29 -07002632err_regulator:
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002633 if (host->vmmc)
Jaehoon Chungc07946a2011-02-25 11:08:14 +09002634 regulator_disable(host->vmmc);
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002635
2636err_clk_ciu:
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002637 if (!IS_ERR(host->ciu_clk))
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002638 clk_disable_unprepare(host->ciu_clk);
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002639
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002640err_clk_biu:
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002641 if (!IS_ERR(host->biu_clk))
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002642 clk_disable_unprepare(host->biu_clk);
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002643
Will Newtonf95f3852011-01-02 01:11:59 -05002644 return ret;
2645}
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302646EXPORT_SYMBOL(dw_mci_probe);
Will Newtonf95f3852011-01-02 01:11:59 -05002647
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302648void dw_mci_remove(struct dw_mci *host)
Will Newtonf95f3852011-01-02 01:11:59 -05002649{
Will Newtonf95f3852011-01-02 01:11:59 -05002650 int i;
2651
2652 mci_writel(host, RINTSTS, 0xFFFFFFFF);
2653 mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
2654
Will Newtonf95f3852011-01-02 01:11:59 -05002655 for (i = 0; i < host->num_slots; i++) {
Thomas Abraham4a909202012-09-17 18:16:35 +00002656 dev_dbg(host->dev, "remove slot %d\n", i);
Will Newtonf95f3852011-01-02 01:11:59 -05002657 if (host->slot[i])
2658 dw_mci_cleanup_slot(host->slot[i], i);
2659 }
2660
2661 /* disable clock to CIU */
2662 mci_writel(host, CLKENA, 0);
2663 mci_writel(host, CLKSRC, 0);
2664
Thomas Abraham95dcc2c2012-05-01 14:57:36 -07002665 destroy_workqueue(host->card_workqueue);
Will Newtonf95f3852011-01-02 01:11:59 -05002666
2667 if (host->use_dma && host->dma_ops->exit)
2668 host->dma_ops->exit(host);
2669
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002670 if (host->vmmc)
Jaehoon Chungc07946a2011-02-25 11:08:14 +09002671 regulator_disable(host->vmmc);
Jaehoon Chungc07946a2011-02-25 11:08:14 +09002672
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002673 if (!IS_ERR(host->ciu_clk))
2674 clk_disable_unprepare(host->ciu_clk);
Seungwon Jeon780f22a2012-11-28 19:26:03 +09002675
Thomas Abrahamf90a0612012-09-17 18:16:38 +00002676 if (!IS_ERR(host->biu_clk))
2677 clk_disable_unprepare(host->biu_clk);
Will Newtonf95f3852011-01-02 01:11:59 -05002678}
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302679EXPORT_SYMBOL(dw_mci_remove);
2680
2681
Will Newtonf95f3852011-01-02 01:11:59 -05002682
Jaehoon Chung6fe88902011-12-08 19:23:03 +09002683#ifdef CONFIG_PM_SLEEP
Will Newtonf95f3852011-01-02 01:11:59 -05002684/*
2685 * TODO: we should probably disable the clock to the card in the suspend path.
2686 */
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302687int dw_mci_suspend(struct dw_mci *host)
Will Newtonf95f3852011-01-02 01:11:59 -05002688{
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302689 int i, ret = 0;
Will Newtonf95f3852011-01-02 01:11:59 -05002690
2691 for (i = 0; i < host->num_slots; i++) {
2692 struct dw_mci_slot *slot = host->slot[i];
2693 if (!slot)
2694 continue;
2695 ret = mmc_suspend_host(slot->mmc);
2696 if (ret < 0) {
2697 while (--i >= 0) {
2698 slot = host->slot[i];
2699 if (slot)
2700 mmc_resume_host(host->slot[i]->mmc);
2701 }
2702 return ret;
2703 }
2704 }
2705
Jaehoon Chungc07946a2011-02-25 11:08:14 +09002706 if (host->vmmc)
2707 regulator_disable(host->vmmc);
2708
Will Newtonf95f3852011-01-02 01:11:59 -05002709 return 0;
2710}
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302711EXPORT_SYMBOL(dw_mci_suspend);
Will Newtonf95f3852011-01-02 01:11:59 -05002712
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302713int dw_mci_resume(struct dw_mci *host)
Will Newtonf95f3852011-01-02 01:11:59 -05002714{
2715 int i, ret;
Will Newtonf95f3852011-01-02 01:11:59 -05002716
Sachin Kamatf2f942c2013-04-04 11:25:10 +05302717 if (host->vmmc) {
2718 ret = regulator_enable(host->vmmc);
2719 if (ret) {
2720 dev_err(host->dev,
2721 "failed to enable regulator: %d\n", ret);
2722 return ret;
2723 }
2724 }
Jaehoon Chung1d6c4e02011-05-11 15:52:39 +09002725
Thomas Abraham4a909202012-09-17 18:16:35 +00002726 if (!mci_wait_reset(host->dev, host)) {
Jaehoon Chunge61cf112011-03-17 20:32:33 +09002727 ret = -ENODEV;
2728 return ret;
2729 }
2730
Jonathan Kliegman3bfe6192012-06-14 13:31:55 -04002731 if (host->use_dma && host->dma_ops->init)
Seungwon Jeon141a7122012-05-22 13:01:03 +09002732 host->dma_ops->init(host);
2733
Seungwon Jeon52426892013-08-31 00:13:42 +09002734 /*
2735 * Restore the initial value at FIFOTH register
2736 * And Invalidate the prev_blksz with zero
2737 */
Jaehoon Chunge61cf112011-03-17 20:32:33 +09002738 mci_writel(host, FIFOTH, host->fifoth_val);
Seungwon Jeon52426892013-08-31 00:13:42 +09002739 host->prev_blksz = 0;
Jaehoon Chunge61cf112011-03-17 20:32:33 +09002740
Doug Anderson2eb29442013-08-31 00:11:49 +09002741 /* Put in max timeout */
2742 mci_writel(host, TMOUT, 0xFFFFFFFF);
2743
Jaehoon Chunge61cf112011-03-17 20:32:33 +09002744 mci_writel(host, RINTSTS, 0xFFFFFFFF);
2745 mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
2746 SDMMC_INT_TXDR | SDMMC_INT_RXDR |
2747 DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
2748 mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
2749
Will Newtonf95f3852011-01-02 01:11:59 -05002750 for (i = 0; i < host->num_slots; i++) {
2751 struct dw_mci_slot *slot = host->slot[i];
2752 if (!slot)
2753 continue;
Abhilash Kesavanab269122012-11-19 10:26:21 +05302754 if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
2755 dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
2756 dw_mci_setup_bus(slot, true);
2757 }
2758
Will Newtonf95f3852011-01-02 01:11:59 -05002759 ret = mmc_resume_host(host->slot[i]->mmc);
2760 if (ret < 0)
2761 return ret;
2762 }
Will Newtonf95f3852011-01-02 01:11:59 -05002763 return 0;
2764}
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302765EXPORT_SYMBOL(dw_mci_resume);
Jaehoon Chung6fe88902011-12-08 19:23:03 +09002766#endif /* CONFIG_PM_SLEEP */
2767
Will Newtonf95f3852011-01-02 01:11:59 -05002768static int __init dw_mci_init(void)
2769{
Sachin Kamat8e1c4e42013-04-04 11:25:11 +05302770 pr_info("Synopsys Designware Multimedia Card Interface Driver\n");
Shashidhar Hiremath62ca8032012-01-13 16:04:57 +05302771 return 0;
Will Newtonf95f3852011-01-02 01:11:59 -05002772}
2773
2774static void __exit dw_mci_exit(void)
2775{
Will Newtonf95f3852011-01-02 01:11:59 -05002776}
2777
2778module_init(dw_mci_init);
2779module_exit(dw_mci_exit);
2780
2781MODULE_DESCRIPTION("DW Multimedia Card Interface driver");
2782MODULE_AUTHOR("NXP Semiconductor VietNam");
2783MODULE_AUTHOR("Imagination Technologies Ltd");
2784MODULE_LICENSE("GPL v2");