blob: 74630974420ba235981cce780895be254809b845 [file] [log] [blame]
San Mehat9d2bd732009-09-22 16:44:22 -07001/*
2 * linux/drivers/mmc/host/msm_sdcc.c - Qualcomm MSM 7X00A SDCC Driver
3 *
4 * Copyright (C) 2007 Google Inc,
5 * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07006 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
San Mehat9d2bd732009-09-22 16:44:22 -07007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Based on mmci.c
13 *
14 * Author: San Mehat (san@android.com)
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/init.h>
21#include <linux/ioport.h>
22#include <linux/device.h>
23#include <linux/interrupt.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070024#include <linux/irq.h>
San Mehat9d2bd732009-09-22 16:44:22 -070025#include <linux/delay.h>
26#include <linux/err.h>
27#include <linux/highmem.h>
28#include <linux/log2.h>
29#include <linux/mmc/host.h>
30#include <linux/mmc/card.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070031#include <linux/mmc/mmc.h>
San Mehatb3fa5792009-11-02 18:46:09 -080032#include <linux/mmc/sdio.h>
San Mehat9d2bd732009-09-22 16:44:22 -070033#include <linux/clk.h>
34#include <linux/scatterlist.h>
35#include <linux/platform_device.h>
36#include <linux/dma-mapping.h>
37#include <linux/debugfs.h>
38#include <linux/io.h>
39#include <linux/memory.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040#include <linux/pm_runtime.h>
41#include <linux/wakelock.h>
Sahitya Tummala7a892482011-01-18 11:22:49 +053042#include <linux/gpio.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043#include <linux/regulator/consumer.h>
44#include <linux/slab.h>
45#include <linux/mmc/mmc.h>
San Mehat9d2bd732009-09-22 16:44:22 -070046
47#include <asm/cacheflush.h>
48#include <asm/div64.h>
49#include <asm/sizes.h>
50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051#include <asm/mach/mmc.h>
San Mehat9d2bd732009-09-22 16:44:22 -070052#include <mach/msm_iomap.h>
Sahitya Tummalab08bb352010-12-08 15:03:05 +053053#include <mach/clk.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070054#include <mach/dma.h>
55#include <mach/htc_pwrsink.h>
56#include <mach/sdio_al.h>
San Mehat9d2bd732009-09-22 16:44:22 -070057
San Mehat9d2bd732009-09-22 16:44:22 -070058#include "msm_sdcc.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059#include "msm_sdcc_dml.h"
San Mehat9d2bd732009-09-22 16:44:22 -070060
61#define DRIVER_NAME "msm-sdcc"
62
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070063#define DBG(host, fmt, args...) \
64 pr_debug("%s: %s: " fmt "\n", mmc_hostname(host->mmc), __func__ , args)
65
66#define IRQ_DEBUG 0
67#define SPS_SDCC_PRODUCER_PIPE_INDEX 1
68#define SPS_SDCC_CONSUMER_PIPE_INDEX 2
69#define SPS_CONS_PERIPHERAL 0
70#define SPS_PROD_PERIPHERAL 1
71/* 16 KB */
72#define SPS_MAX_DESC_SIZE (16 * 1024)
73
74#if defined(CONFIG_DEBUG_FS)
75static void msmsdcc_dbg_createhost(struct msmsdcc_host *);
76static struct dentry *debugfs_dir;
77static struct dentry *debugfs_file;
78static int msmsdcc_dbg_init(void);
79#endif
80
San Mehat9d2bd732009-09-22 16:44:22 -070081static unsigned int msmsdcc_pwrsave = 1;
San Mehat9d2bd732009-09-22 16:44:22 -070082
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083static struct mmc_command dummy52cmd;
84static struct mmc_request dummy52mrq = {
85 .cmd = &dummy52cmd,
86 .data = NULL,
87 .stop = NULL,
88};
89static struct mmc_command dummy52cmd = {
90 .opcode = SD_IO_RW_DIRECT,
91 .flags = MMC_RSP_PRESENT,
92 .data = NULL,
93 .mrq = &dummy52mrq,
94};
95/*
96 * An array holding the Tuning pattern to compare with when
97 * executing a tuning cycle.
98 */
99static const u32 cmd19_tuning_block[16] = {
100 0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
101 0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
102 0xF0FFF0FF, 0x3CCCFC0F, 0xCFCC33CC, 0xEEFFEFFF,
103 0xFDFFFDFF, 0xFFBFFFDF, 0xFFF7FFBB, 0xDE7B7FF7
104};
San Mehat865c8062009-11-13 13:42:06 -0800105
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700106#if IRQ_DEBUG == 1
107static char *irq_status_bits[] = { "cmdcrcfail", "datcrcfail", "cmdtimeout",
108 "dattimeout", "txunderrun", "rxoverrun",
109 "cmdrespend", "cmdsent", "dataend", NULL,
110 "datablkend", "cmdactive", "txactive",
111 "rxactive", "txhalfempty", "rxhalffull",
112 "txfifofull", "rxfifofull", "txfifoempty",
113 "rxfifoempty", "txdataavlbl", "rxdataavlbl",
114 "sdiointr", "progdone", "atacmdcompl",
115 "sdiointrope", "ccstimeout", NULL, NULL,
116 NULL, NULL, NULL };
117
118static void
119msmsdcc_print_status(struct msmsdcc_host *host, char *hdr, uint32_t status)
San Mehat865c8062009-11-13 13:42:06 -0800120{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700121 int i;
San Mehat8b1c2ba2009-11-16 10:17:30 -0800122
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700123 pr_debug("%s-%s ", mmc_hostname(host->mmc), hdr);
124 for (i = 0; i < 32; i++) {
125 if (status & (1 << i))
126 pr_debug("%s ", irq_status_bits[i]);
San Mehat865c8062009-11-13 13:42:06 -0800127 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700128 pr_debug("\n");
San Mehatc7fc9372009-11-22 17:19:07 -0800129}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700130#endif
San Mehat865c8062009-11-13 13:42:06 -0800131
San Mehat9d2bd732009-09-22 16:44:22 -0700132static void
133msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
134 u32 c);
135
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700136#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
137static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
138 struct msmsdcc_sps_ep_conn_data *ep);
139static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
140 struct msmsdcc_sps_ep_conn_data *ep);
141#else
142static inline int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
143 struct msmsdcc_sps_ep_conn_data *ep,
144 bool is_producer) { return 0; }
145static inline void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
146 struct msmsdcc_sps_ep_conn_data *ep) { }
147static inline int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
148 struct msmsdcc_sps_ep_conn_data *ep)
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530149{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700150 return 0;
151}
152static inline int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
153 struct msmsdcc_sps_ep_conn_data *ep)
154{
155 return 0;
156}
157static inline int msmsdcc_sps_init(struct msmsdcc_host *host) { return 0; }
158static inline void msmsdcc_sps_exit(struct msmsdcc_host *host) {}
159#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530160
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700161/**
162 * Apply soft reset
163 *
164 * This function applies soft reset to SDCC core and
165 * BAM, DML core.
166 *
167 * This function should be called to recover from error
168 * conditions encountered with CMD/DATA tranfsers with card.
169 *
170 * Soft reset should only be used with SDCC controller v4.
171 *
172 * @host - Pointer to driver's host structure
173 *
174 */
175static void msmsdcc_soft_reset_and_restore(struct msmsdcc_host *host)
176{
177 int rc;
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530178
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700179 if (host->is_sps_mode) {
180 /* Reset DML first */
181 msmsdcc_dml_reset(host);
182 /* Now reset all BAM pipes connections */
183 rc = msmsdcc_sps_reset_ep(host, &host->sps.prod);
184 if (rc)
185 pr_err("%s:msmsdcc_sps_reset_ep() error=%d\n",
186 mmc_hostname(host->mmc), rc);
187 rc = msmsdcc_sps_reset_ep(host, &host->sps.cons);
188 if (rc)
189 pr_err("%s:msmsdcc_sps_reset_ep() error=%d\n",
190 mmc_hostname(host->mmc), rc);
191 }
192 /*
193 * Reset SDCC controller's DPSM (data path state machine
194 * and CPSM (command path state machine).
195 */
196 mb();
197 writel_relaxed(0, host->base + MMCICOMMAND);
198 writel_relaxed(0, host->base + MMCIDATACTRL);
199 mb();
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700201 pr_debug("%s: Applied soft reset to Controller\n",
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530202 mmc_hostname(host->mmc));
203
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 if (host->is_sps_mode) {
205 /* Restore all BAM pipes connections */
206 rc = msmsdcc_sps_restore_ep(host, &host->sps.prod);
207 if (rc)
208 pr_err("%s:msmsdcc_sps_restore_ep() error=%d\n",
209 mmc_hostname(host->mmc), rc);
210 rc = msmsdcc_sps_restore_ep(host, &host->sps.cons);
211 if (rc)
212 pr_err("%s:msmsdcc_sps_restore_ep() error=%d\n",
213 mmc_hostname(host->mmc), rc);
214 msmsdcc_dml_init(host);
215 }
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530216}
217
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
219{
220 if (host->plat->sdcc_v4_sup) {
221 msmsdcc_soft_reset_and_restore(host);
222 } else {
223 /* Give Clock reset (hard reset) to controller */
224 u32 mci_clk = 0;
225 u32 mci_mask0 = 0;
226 int ret;
227
228 /* Save the controller state */
229 mci_clk = readl_relaxed(host->base + MMCICLOCK);
230 mci_mask0 = readl_relaxed(host->base + MMCIMASK0);
231
232 mb();
233 /* Reset the controller */
234 ret = clk_reset(host->clk, CLK_RESET_ASSERT);
235 if (ret)
236 pr_err("%s: Clock assert failed at %u Hz"
237 " with err %d\n", mmc_hostname(host->mmc),
238 host->clk_rate, ret);
239
240 ret = clk_reset(host->clk, CLK_RESET_DEASSERT);
241 if (ret)
242 pr_err("%s: Clock deassert failed at %u Hz"
243 " with err %d\n", mmc_hostname(host->mmc),
244 host->clk_rate, ret);
245
246 pr_debug("%s: Controller has been reinitialized\n",
247 mmc_hostname(host->mmc));
248
249 mb();
250 /* Restore the contoller state */
251 writel_relaxed(host->pwr, host->base + MMCIPOWER);
252 writel_relaxed(mci_clk, host->base + MMCICLOCK);
253 writel_relaxed(mci_mask0, host->base + MMCIMASK0);
254 ret = clk_set_rate(host->clk, host->clk_rate);
255 if (ret)
256 pr_err("%s: Failed to set clk rate %u Hz. err %d\n",
257 mmc_hostname(host->mmc),
258 host->clk_rate, ret);
259 mb();
260 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -0700261 if (host->dummy_52_needed)
262 host->dummy_52_needed = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263}
264
265static int
San Mehat9d2bd732009-09-22 16:44:22 -0700266msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
267{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268 int retval = 0;
269
San Mehat9d2bd732009-09-22 16:44:22 -0700270 BUG_ON(host->curr.data);
271
272 host->curr.mrq = NULL;
273 host->curr.cmd = NULL;
274
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700275 del_timer(&host->req_tout_timer);
276
San Mehat9d2bd732009-09-22 16:44:22 -0700277 if (mrq->data)
278 mrq->data->bytes_xfered = host->curr.data_xfered;
279 if (mrq->cmd->error == -ETIMEDOUT)
280 mdelay(5);
281
282 /*
283 * Need to drop the host lock here; mmc_request_done may call
284 * back into the driver...
285 */
286 spin_unlock(&host->lock);
287 mmc_request_done(host->mmc, mrq);
288 spin_lock(&host->lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700289
290 return retval;
San Mehat9d2bd732009-09-22 16:44:22 -0700291}
292
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700293static inline void msmsdcc_delay(struct msmsdcc_host *host);
294
San Mehat9d2bd732009-09-22 16:44:22 -0700295static void
296msmsdcc_stop_data(struct msmsdcc_host *host)
297{
San Mehat9d2bd732009-09-22 16:44:22 -0700298 host->curr.data = NULL;
Sahitya Tummala0c521cc2010-12-08 15:03:07 +0530299 host->curr.got_dataend = 0;
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700300 writel_relaxed(0, host->base + MMCIDATACTRL);
301 msmsdcc_delay(host); /* Allow the DPSM to be reset */
San Mehat9d2bd732009-09-22 16:44:22 -0700302}
303
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700304static inline uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
San Mehat9d2bd732009-09-22 16:44:22 -0700305{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700306 return host->core_memres->start + MMCIFIFO;
307}
308
309static inline unsigned int msmsdcc_get_min_sup_clk_rate(
310 struct msmsdcc_host *host);
311static inline void msmsdcc_delay(struct msmsdcc_host *host)
312{
313 mb();
314 udelay(1 + ((3 * USEC_PER_SEC) /
315 (host->clk_rate ? host->clk_rate :
316 msmsdcc_get_min_sup_clk_rate(host))));
San Mehat9d2bd732009-09-22 16:44:22 -0700317}
318
San Mehat56a8b5b2009-11-21 12:29:46 -0800319static inline void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700320msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c)
321{
322 writel_relaxed(arg, host->base + MMCIARGUMENT);
323 msmsdcc_delay(host);
324 writel_relaxed(c, host->base + MMCICOMMAND);
325 mb();
San Mehat56a8b5b2009-11-21 12:29:46 -0800326}
327
328static void
329msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
330{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700331 struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->user;
San Mehat56a8b5b2009-11-21 12:29:46 -0800332
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700333 writel_relaxed(host->cmd_timeout, host->base + MMCIDATATIMER);
334 writel_relaxed((unsigned int)host->curr.xfer_size,
335 host->base + MMCIDATALENGTH);
336 msmsdcc_delay(host); /* Allow data parms to be applied */
337 writel_relaxed(host->cmd_datactrl, host->base + MMCIDATACTRL);
338 msmsdcc_delay(host); /* Force delay prior to ADM or command */
San Mehat56a8b5b2009-11-21 12:29:46 -0800339
San Mehat6ac9ea62009-12-02 17:24:58 -0800340 if (host->cmd_cmd) {
341 msmsdcc_start_command_exec(host,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342 (u32)host->cmd_cmd->arg, (u32)host->cmd_c);
San Mehat6ac9ea62009-12-02 17:24:58 -0800343 }
San Mehat56a8b5b2009-11-21 12:29:46 -0800344}
345
San Mehat9d2bd732009-09-22 16:44:22 -0700346static void
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530347msmsdcc_dma_complete_tlet(unsigned long data)
San Mehat9d2bd732009-09-22 16:44:22 -0700348{
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530349 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
San Mehat9d2bd732009-09-22 16:44:22 -0700350 unsigned long flags;
351 struct mmc_request *mrq;
352
353 spin_lock_irqsave(&host->lock, flags);
354 mrq = host->curr.mrq;
355 BUG_ON(!mrq);
356
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530357 if (!(host->dma.result & DMOV_RSLT_VALID)) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700358 pr_err("msmsdcc: Invalid DataMover result\n");
San Mehat9d2bd732009-09-22 16:44:22 -0700359 goto out;
360 }
361
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530362 if (host->dma.result & DMOV_RSLT_DONE) {
San Mehat9d2bd732009-09-22 16:44:22 -0700363 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 host->curr.xfer_remain -= host->curr.xfer_size;
San Mehat9d2bd732009-09-22 16:44:22 -0700365 } else {
366 /* Error or flush */
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530367 if (host->dma.result & DMOV_RSLT_ERROR)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700368 pr_err("%s: DMA error (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530369 mmc_hostname(host->mmc), host->dma.result);
370 if (host->dma.result & DMOV_RSLT_FLUSH)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700371 pr_err("%s: DMA channel flushed (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530372 mmc_hostname(host->mmc), host->dma.result);
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530373 pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 host->dma.err.flush[0], host->dma.err.flush[1],
375 host->dma.err.flush[2], host->dma.err.flush[3],
376 host->dma.err.flush[4],
377 host->dma.err.flush[5]);
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530378 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -0700379 if (!mrq->data->error)
380 mrq->data->error = -EIO;
381 }
San Mehat9d2bd732009-09-22 16:44:22 -0700382 dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
383 host->dma.dir);
384
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700385 if (host->curr.user_pages) {
386 struct scatterlist *sg = host->dma.sg;
387 int i;
388
389 for (i = 0; i < host->dma.num_ents; i++, sg++)
390 flush_dcache_page(sg_page(sg));
391 }
392
San Mehat9d2bd732009-09-22 16:44:22 -0700393 host->dma.sg = NULL;
San Mehat56a8b5b2009-11-21 12:29:46 -0800394 host->dma.busy = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700395
Sahitya Tummala0c521cc2010-12-08 15:03:07 +0530396 if (host->curr.got_dataend || mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700397
398 /*
399 * If we've already gotten our DATAEND / DATABLKEND
400 * for this request, then complete it through here.
401 */
San Mehat9d2bd732009-09-22 16:44:22 -0700402
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700403 if (!mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700404 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 host->curr.xfer_remain -= host->curr.xfer_size;
406 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -0700407 if (host->dummy_52_needed) {
408 mrq->data->bytes_xfered = host->curr.data_xfered;
409 host->dummy_52_sent = 1;
410 msmsdcc_start_command(host, &dummy52cmd,
411 MCI_CPSM_PROGENA);
412 goto out;
413 }
414 msmsdcc_stop_data(host);
San Mehat9d2bd732009-09-22 16:44:22 -0700415 if (!mrq->data->stop || mrq->cmd->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700416 host->curr.mrq = NULL;
417 host->curr.cmd = NULL;
418 mrq->data->bytes_xfered = host->curr.data_xfered;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700419 del_timer(&host->req_tout_timer);
San Mehat9d2bd732009-09-22 16:44:22 -0700420 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700421
San Mehat9d2bd732009-09-22 16:44:22 -0700422 mmc_request_done(host->mmc, mrq);
423 return;
424 } else
425 msmsdcc_start_command(host, mrq->data->stop, 0);
426 }
427
428out:
429 spin_unlock_irqrestore(&host->lock, flags);
430 return;
431}
432
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
434/**
435 * Callback notification from SPS driver
436 *
437 * This callback function gets triggered called from
438 * SPS driver when requested SPS data transfer is
439 * completed.
440 *
441 * SPS driver invokes this callback in BAM irq context so
442 * SDCC driver schedule a tasklet for further processing
443 * this callback notification at later point of time in
444 * tasklet context and immediately returns control back
445 * to SPS driver.
446 *
447 * @nofity - Pointer to sps event notify sturcture
448 *
449 */
450static void
451msmsdcc_sps_complete_cb(struct sps_event_notify *notify)
452{
453 struct msmsdcc_host *host =
454 (struct msmsdcc_host *)
455 ((struct sps_event_notify *)notify)->user;
456
457 host->sps.notify = *notify;
458 pr_debug("%s: %s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
459 mmc_hostname(host->mmc), __func__, notify->event_id,
460 notify->data.transfer.iovec.addr,
461 notify->data.transfer.iovec.size,
462 notify->data.transfer.iovec.flags);
463 /* Schedule a tasklet for completing data transfer */
464 tasklet_schedule(&host->sps.tlet);
465}
466
467/**
468 * Tasklet handler for processing SPS callback event
469 *
470 * This function processing SPS event notification and
471 * checks if the SPS transfer is completed or not and
472 * then accordingly notifies status to MMC core layer.
473 *
474 * This function is called in tasklet context.
475 *
476 * @data - Pointer to sdcc driver data
477 *
478 */
479static void msmsdcc_sps_complete_tlet(unsigned long data)
480{
481 unsigned long flags;
482 int i, rc;
483 u32 data_xfered = 0;
484 struct mmc_request *mrq;
485 struct sps_iovec iovec;
486 struct sps_pipe *sps_pipe_handle;
487 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
488 struct sps_event_notify *notify = &host->sps.notify;
489
490 spin_lock_irqsave(&host->lock, flags);
491 if (host->sps.dir == DMA_FROM_DEVICE)
492 sps_pipe_handle = host->sps.prod.pipe_handle;
493 else
494 sps_pipe_handle = host->sps.cons.pipe_handle;
495 mrq = host->curr.mrq;
496
497 if (!mrq) {
498 spin_unlock_irqrestore(&host->lock, flags);
499 return;
500 }
501
502 pr_debug("%s: %s: sps event_id=%d\n",
503 mmc_hostname(host->mmc), __func__,
504 notify->event_id);
505
506 if (msmsdcc_is_dml_busy(host)) {
507 /* oops !!! this should never happen. */
508 pr_err("%s: %s: Received SPS EOT event"
509 " but DML HW is still busy !!!\n",
510 mmc_hostname(host->mmc), __func__);
511 }
512 /*
513 * Got End of transfer event!!! Check if all of the data
514 * has been transferred?
515 */
516 for (i = 0; i < host->sps.xfer_req_cnt; i++) {
517 rc = sps_get_iovec(sps_pipe_handle, &iovec);
518 if (rc) {
519 pr_err("%s: %s: sps_get_iovec() failed rc=%d, i=%d",
520 mmc_hostname(host->mmc), __func__, rc, i);
521 break;
522 }
523 data_xfered += iovec.size;
524 }
525
526 if (data_xfered == host->curr.xfer_size) {
527 host->curr.data_xfered = host->curr.xfer_size;
528 host->curr.xfer_remain -= host->curr.xfer_size;
529 pr_debug("%s: Data xfer success. data_xfered=0x%x",
530 mmc_hostname(host->mmc),
531 host->curr.xfer_size);
532 } else {
533 pr_err("%s: Data xfer failed. data_xfered=0x%x,"
534 " xfer_size=%d", mmc_hostname(host->mmc),
535 data_xfered, host->curr.xfer_size);
536 msmsdcc_reset_and_restore(host);
537 if (!mrq->data->error)
538 mrq->data->error = -EIO;
539 }
540
541 /* Unmap sg buffers */
542 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
543 host->sps.dir);
544
545 host->sps.sg = NULL;
546 host->sps.busy = 0;
547
548 if (host->curr.got_dataend || mrq->data->error) {
549 /*
550 * If we've already gotten our DATAEND / DATABLKEND
551 * for this request, then complete it through here.
552 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700553
554 if (!mrq->data->error) {
555 host->curr.data_xfered = host->curr.xfer_size;
556 host->curr.xfer_remain -= host->curr.xfer_size;
557 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -0700558 if (host->dummy_52_needed) {
559 mrq->data->bytes_xfered = host->curr.data_xfered;
560 host->dummy_52_sent = 1;
561 msmsdcc_start_command(host, &dummy52cmd,
562 MCI_CPSM_PROGENA);
563 return;
564 }
565 msmsdcc_stop_data(host);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700566 if (!mrq->data->stop || mrq->cmd->error) {
567 host->curr.mrq = NULL;
568 host->curr.cmd = NULL;
569 mrq->data->bytes_xfered = host->curr.data_xfered;
570 del_timer(&host->req_tout_timer);
571 spin_unlock_irqrestore(&host->lock, flags);
572
573 mmc_request_done(host->mmc, mrq);
574 return;
575 } else {
576 msmsdcc_start_command(host, mrq->data->stop, 0);
577 }
578 }
579 spin_unlock_irqrestore(&host->lock, flags);
580}
581
582/**
583 * Exit from current SPS data transfer
584 *
585 * This function exits from current SPS data transfer.
586 *
587 * This function should be called when error condition
588 * is encountered during data transfer.
589 *
590 * @host - Pointer to sdcc host structure
591 *
592 */
593static void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host)
594{
595 struct mmc_request *mrq;
596
597 mrq = host->curr.mrq;
598 BUG_ON(!mrq);
599
600 msmsdcc_reset_and_restore(host);
601 if (!mrq->data->error)
602 mrq->data->error = -EIO;
603
604 /* Unmap sg buffers */
605 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
606 host->sps.dir);
607
608 host->sps.sg = NULL;
609 host->sps.busy = 0;
610 if (host->curr.data)
611 msmsdcc_stop_data(host);
612
613 if (!mrq->data->stop || mrq->cmd->error)
614 msmsdcc_request_end(host, mrq);
615 else
616 msmsdcc_start_command(host, mrq->data->stop, 0);
617
618}
619#else
620static inline void msmsdcc_sps_complete_cb(struct sps_event_notify *notify) { }
621static inline void msmsdcc_sps_complete_tlet(unsigned long data) { }
622static inline void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host) { }
623#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
624
625static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host);
626
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530627static void
628msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
629 unsigned int result,
630 struct msm_dmov_errdata *err)
631{
632 struct msmsdcc_dma_data *dma_data =
633 container_of(cmd, struct msmsdcc_dma_data, hdr);
634 struct msmsdcc_host *host = dma_data->host;
635
636 dma_data->result = result;
637 if (err)
638 memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
639
640 tasklet_schedule(&host->dma_tlet);
641}
642
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700643static int msmsdcc_check_dma_op_req(struct mmc_data *data)
San Mehat9d2bd732009-09-22 16:44:22 -0700644{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700645 if (((data->blksz * data->blocks) < MCI_FIFOSIZE) ||
646 ((data->blksz * data->blocks) % MCI_FIFOSIZE))
San Mehat9d2bd732009-09-22 16:44:22 -0700647 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700648 else
649 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700650}
651
652static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
653{
654 struct msmsdcc_nc_dmadata *nc;
655 dmov_box *box;
656 uint32_t rows;
657 uint32_t crci;
658 unsigned int n;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700659 int i;
San Mehat9d2bd732009-09-22 16:44:22 -0700660 struct scatterlist *sg = data->sg;
661
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700662 if (host->dma.channel == -1)
663 return -ENOENT;
San Mehat9d2bd732009-09-22 16:44:22 -0700664
665 host->dma.sg = data->sg;
666 host->dma.num_ents = data->sg_len;
667
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700668 BUG_ON(host->dma.num_ents > NR_SG); /* Prevent memory corruption */
San Mehat56a8b5b2009-11-21 12:29:46 -0800669
San Mehat9d2bd732009-09-22 16:44:22 -0700670 nc = host->dma.nc;
671
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700672 if (host->pdev_id == 1)
673 crci = DMOV_SDC1_CRCI;
674 else if (host->pdev_id == 2)
675 crci = DMOV_SDC2_CRCI;
676 else if (host->pdev_id == 3)
677 crci = DMOV_SDC3_CRCI;
678 else if (host->pdev_id == 4)
679 crci = DMOV_SDC4_CRCI;
680#ifdef DMOV_SDC5_CRCI
681 else if (host->pdev_id == 5)
682 crci = DMOV_SDC5_CRCI;
683#endif
684 else {
San Mehat9d2bd732009-09-22 16:44:22 -0700685 host->dma.sg = NULL;
686 host->dma.num_ents = 0;
687 return -ENOENT;
688 }
689
690 if (data->flags & MMC_DATA_READ)
691 host->dma.dir = DMA_FROM_DEVICE;
692 else
693 host->dma.dir = DMA_TO_DEVICE;
694
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700695 /* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
San Mehat9d2bd732009-09-22 16:44:22 -0700696 host->curr.user_pages = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700697 box = &nc->cmd[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700698 for (i = 0; i < host->dma.num_ents; i++) {
San Mehat9d2bd732009-09-22 16:44:22 -0700699 box->cmd = CMD_MODE_BOX;
700
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700701 /* Initialize sg dma address */
702 sg->dma_address = pfn_to_dma(mmc_dev(host->mmc),
703 page_to_pfn(sg_page(sg)))
704 + sg->offset;
705
706 if (i == (host->dma.num_ents - 1))
San Mehat9d2bd732009-09-22 16:44:22 -0700707 box->cmd |= CMD_LC;
708 rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
709 (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
710 (sg_dma_len(sg) / MCI_FIFOSIZE) ;
711
712 if (data->flags & MMC_DATA_READ) {
713 box->src_row_addr = msmsdcc_fifo_addr(host);
714 box->dst_row_addr = sg_dma_address(sg);
715
716 box->src_dst_len = (MCI_FIFOSIZE << 16) |
717 (MCI_FIFOSIZE);
718 box->row_offset = MCI_FIFOSIZE;
719
720 box->num_rows = rows * ((1 << 16) + 1);
721 box->cmd |= CMD_SRC_CRCI(crci);
722 } else {
723 box->src_row_addr = sg_dma_address(sg);
724 box->dst_row_addr = msmsdcc_fifo_addr(host);
725
726 box->src_dst_len = (MCI_FIFOSIZE << 16) |
727 (MCI_FIFOSIZE);
728 box->row_offset = (MCI_FIFOSIZE << 16);
729
730 box->num_rows = rows * ((1 << 16) + 1);
731 box->cmd |= CMD_DST_CRCI(crci);
732 }
733 box++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700734 sg++;
735 }
736
737 /* location of command block must be 64 bit aligned */
738 BUG_ON(host->dma.cmd_busaddr & 0x07);
739
740 nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
741 host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
742 DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
743 host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
744 host->dma.hdr.crci_mask = msm_dmov_build_crci_mask(1, crci);
745
746 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
747 host->dma.num_ents, host->dma.dir);
748 /* dsb inside dma_map_sg will write nc out to mem as well */
749
750 if (n != host->dma.num_ents) {
751 pr_err("%s: Unable to map in all sg elements\n",
752 mmc_hostname(host->mmc));
753 host->dma.sg = NULL;
754 host->dma.num_ents = 0;
755 return -ENOMEM;
San Mehat56a8b5b2009-11-21 12:29:46 -0800756 }
San Mehat9d2bd732009-09-22 16:44:22 -0700757
758 return 0;
759}
760
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700761#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
762/**
763 * Submits data transfer request to SPS driver
764 *
765 * This function make sg (scatter gather) data buffers
766 * DMA ready and then submits them to SPS driver for
767 * transfer.
768 *
769 * @host - Pointer to sdcc host structure
770 * @data - Pointer to mmc_data structure
771 *
772 * @return 0 if success else negative value
773 */
774static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
775 struct mmc_data *data)
San Mehat56a8b5b2009-11-21 12:29:46 -0800776{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777 int rc = 0;
778 u32 flags;
779 int i;
780 u32 addr, len, data_cnt;
781 struct scatterlist *sg = data->sg;
782 struct sps_pipe *sps_pipe_handle;
783
784 BUG_ON(data->sg_len > NR_SG); /* Prevent memory corruption */
785
786 host->sps.sg = data->sg;
787 host->sps.num_ents = data->sg_len;
788 host->sps.xfer_req_cnt = 0;
789 if (data->flags & MMC_DATA_READ) {
790 host->sps.dir = DMA_FROM_DEVICE;
791 sps_pipe_handle = host->sps.prod.pipe_handle;
792 } else {
793 host->sps.dir = DMA_TO_DEVICE;
794 sps_pipe_handle = host->sps.cons.pipe_handle;
795 }
796
797 /* Make sg buffers DMA ready */
798 rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
799 host->sps.dir);
800
801 if (rc != data->sg_len) {
802 pr_err("%s: Unable to map in all sg elements, rc=%d\n",
803 mmc_hostname(host->mmc), rc);
804 host->sps.sg = NULL;
805 host->sps.num_ents = 0;
806 rc = -ENOMEM;
807 goto dma_map_err;
808 }
809
810 pr_debug("%s: %s: %s: pipe=0x%x, total_xfer=0x%x, sg_len=%d\n",
811 mmc_hostname(host->mmc), __func__,
812 host->sps.dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
813 (u32)sps_pipe_handle, host->curr.xfer_size, data->sg_len);
814
815 for (i = 0; i < data->sg_len; i++) {
816 /*
817 * Check if this is the last buffer to transfer?
818 * If yes then set the INT and EOT flags.
819 */
820 len = sg_dma_len(sg);
821 addr = sg_dma_address(sg);
822 flags = 0;
823 while (len > 0) {
824 if (len > SPS_MAX_DESC_SIZE) {
825 data_cnt = SPS_MAX_DESC_SIZE;
826 } else {
827 data_cnt = len;
828 if (i == data->sg_len - 1)
829 flags = SPS_IOVEC_FLAG_INT |
830 SPS_IOVEC_FLAG_EOT;
831 }
832 rc = sps_transfer_one(sps_pipe_handle, addr,
833 data_cnt, host, flags);
834 if (rc) {
835 pr_err("%s: sps_transfer_one() error! rc=%d,"
836 " pipe=0x%x, sg=0x%x, sg_buf_no=%d\n",
837 mmc_hostname(host->mmc), rc,
838 (u32)sps_pipe_handle, (u32)sg, i);
839 goto dma_map_err;
840 }
841 addr += data_cnt;
842 len -= data_cnt;
843 host->sps.xfer_req_cnt++;
844 }
845 sg++;
846 }
847 goto out;
848
849dma_map_err:
850 /* unmap sg buffers */
851 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
852 host->sps.dir);
853out:
854 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -0700855}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856#else
857static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
858 struct mmc_data *data) { return 0; }
859#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
San Mehat9d2bd732009-09-22 16:44:22 -0700860
861static void
San Mehat56a8b5b2009-11-21 12:29:46 -0800862msmsdcc_start_command_deferred(struct msmsdcc_host *host,
863 struct mmc_command *cmd, u32 *c)
864{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700865 DBG(host, "op %02x arg %08x flags %08x\n",
866 cmd->opcode, cmd->arg, cmd->flags);
867
San Mehat56a8b5b2009-11-21 12:29:46 -0800868 *c |= (cmd->opcode | MCI_CPSM_ENABLE);
869
870 if (cmd->flags & MMC_RSP_PRESENT) {
871 if (cmd->flags & MMC_RSP_136)
872 *c |= MCI_CPSM_LONGRSP;
873 *c |= MCI_CPSM_RESPONSE;
874 }
875
876 if (/*interrupt*/0)
877 *c |= MCI_CPSM_INTERRUPT;
878
879 if ((((cmd->opcode == 17) || (cmd->opcode == 18)) ||
880 ((cmd->opcode == 24) || (cmd->opcode == 25))) ||
881 (cmd->opcode == 53))
882 *c |= MCI_CSPM_DATCMD;
883
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700884 /* Check if AUTO CMD19 is required or not? */
885 if (((cmd->opcode == 17) || (cmd->opcode == 18)) &&
886 host->tuning_needed) {
887 msmsdcc_enable_cdr_cm_sdc4_dll(host);
888 *c |= MCI_CSPM_AUTO_CMD19;
889 }
890
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530891 if (host->prog_scan && (cmd->opcode == 12)) {
892 *c |= MCI_CPSM_PROGENA;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700893 host->prog_enable = 1;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530894 }
895
San Mehat56a8b5b2009-11-21 12:29:46 -0800896 if (cmd == cmd->mrq->stop)
897 *c |= MCI_CSPM_MCIABORT;
898
San Mehat56a8b5b2009-11-21 12:29:46 -0800899 if (host->curr.cmd != NULL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900 pr_err("%s: Overlapping command requests\n",
901 mmc_hostname(host->mmc));
San Mehat56a8b5b2009-11-21 12:29:46 -0800902 }
903 host->curr.cmd = cmd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904
905 /*
906 * Kick the software command timeout timer here.
907 * Timer expires in 10 secs.
908 */
909 mod_timer(&host->req_tout_timer,
910 (jiffies + msecs_to_jiffies(MSM_MMC_REQ_TIMEOUT)));
San Mehat56a8b5b2009-11-21 12:29:46 -0800911}
912
913static void
914msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data,
915 struct mmc_command *cmd, u32 c)
San Mehat9d2bd732009-09-22 16:44:22 -0700916{
Subhash Jadavani24fb7f82011-07-25 15:54:34 +0530917 unsigned int datactrl = 0, timeout;
San Mehat9d2bd732009-09-22 16:44:22 -0700918 unsigned long long clks;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700919 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -0700920 unsigned int pio_irqmask = 0;
921
922 host->curr.data = data;
923 host->curr.xfer_size = data->blksz * data->blocks;
924 host->curr.xfer_remain = host->curr.xfer_size;
925 host->curr.data_xfered = 0;
926 host->curr.got_dataend = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700927
928 memset(&host->pio, 0, sizeof(host->pio));
929
San Mehat9d2bd732009-09-22 16:44:22 -0700930 datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
931
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700932 if (!msmsdcc_check_dma_op_req(data)) {
933 if (host->is_dma_mode && !msmsdcc_config_dma(host, data)) {
934 datactrl |= MCI_DPSM_DMAENABLE;
935 } else if (host->is_sps_mode) {
936 if (!msmsdcc_is_dml_busy(host)) {
937 if (!msmsdcc_sps_start_xfer(host, data)) {
938 /* Now kick start DML transfer */
939 mb();
940 msmsdcc_dml_start_xfer(host, data);
941 datactrl |= MCI_DPSM_DMAENABLE;
942 host->sps.busy = 1;
943 }
944 } else {
945 /*
946 * Can't proceed with new transfer as
947 * previous trasnfer is already in progress.
948 * There is no point of going into PIO mode
949 * as well. Is this a time to do kernel panic?
950 */
951 pr_err("%s: %s: DML HW is busy!!!"
952 " Can't perform new SPS transfers"
953 " now\n", mmc_hostname(host->mmc),
954 __func__);
955 }
956 }
957 }
958
959 /* Is data transfer in PIO mode required? */
960 if (!(datactrl & MCI_DPSM_DMAENABLE)) {
San Mehat9d2bd732009-09-22 16:44:22 -0700961 host->pio.sg = data->sg;
962 host->pio.sg_len = data->sg_len;
963 host->pio.sg_off = 0;
964
965 if (data->flags & MMC_DATA_READ) {
966 pio_irqmask = MCI_RXFIFOHALFFULLMASK;
967 if (host->curr.xfer_remain < MCI_FIFOSIZE)
968 pio_irqmask |= MCI_RXDATAAVLBLMASK;
969 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700970 pio_irqmask = MCI_TXFIFOHALFEMPTYMASK |
971 MCI_TXFIFOEMPTYMASK;
San Mehat9d2bd732009-09-22 16:44:22 -0700972 }
973
974 if (data->flags & MMC_DATA_READ)
Subhash Jadavani24fb7f82011-07-25 15:54:34 +0530975 datactrl |= (MCI_DPSM_DIRECTION | MCI_RX_DATA_PEND);
San Mehat9d2bd732009-09-22 16:44:22 -0700976
San Mehat56a8b5b2009-11-21 12:29:46 -0800977 clks = (unsigned long long)data->timeout_ns * host->clk_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700978 do_div(clks, 1000000000UL);
San Mehat56a8b5b2009-11-21 12:29:46 -0800979 timeout = data->timeout_clks + (unsigned int)clks*2 ;
San Mehat9d2bd732009-09-22 16:44:22 -0700980
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700981 if (host->is_dma_mode && (datactrl & MCI_DPSM_DMAENABLE)) {
982 /* Use ADM (Application Data Mover) HW for Data transfer */
983 /* Save parameters for the dma exec function */
San Mehat56a8b5b2009-11-21 12:29:46 -0800984 host->cmd_timeout = timeout;
985 host->cmd_pio_irqmask = pio_irqmask;
986 host->cmd_datactrl = datactrl;
987 host->cmd_cmd = cmd;
San Mehat9d2bd732009-09-22 16:44:22 -0700988
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989 host->dma.hdr.exec_func = msmsdcc_dma_exec_func;
990 host->dma.hdr.user = (void *)host;
San Mehat9d2bd732009-09-22 16:44:22 -0700991 host->dma.busy = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700992 if (data->flags & MMC_DATA_WRITE)
993 host->prog_scan = 1;
San Mehat56a8b5b2009-11-21 12:29:46 -0800994
995 if (cmd) {
996 msmsdcc_start_command_deferred(host, cmd, &c);
997 host->cmd_c = c;
998 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700999 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1000 (~(MCI_IRQ_PIO))) | host->cmd_pio_irqmask,
1001 host->base + MMCIMASK0);
1002 mb();
1003 msm_dmov_enqueue_cmd_ext(host->dma.channel, &host->dma.hdr);
San Mehat56a8b5b2009-11-21 12:29:46 -08001004 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001005 /* SPS-BAM mode or PIO mode */
1006 if (data->flags & MMC_DATA_WRITE)
1007 host->prog_scan = 1;
1008 writel_relaxed(timeout, base + MMCIDATATIMER);
San Mehat56a8b5b2009-11-21 12:29:46 -08001009
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001010 writel_relaxed(host->curr.xfer_size, base + MMCIDATALENGTH);
San Mehat56a8b5b2009-11-21 12:29:46 -08001011
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001012 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1013 (~(MCI_IRQ_PIO))) | pio_irqmask,
1014 host->base + MMCIMASK0);
1015 msmsdcc_delay(host); /* Allow parms to be applied */
1016 writel_relaxed(datactrl, base + MMCIDATACTRL);
San Mehat56a8b5b2009-11-21 12:29:46 -08001017
1018 if (cmd) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001019 msmsdcc_delay(host); /* Delay between data/command */
San Mehat56a8b5b2009-11-21 12:29:46 -08001020 /* Daisy-chain the command if requested */
1021 msmsdcc_start_command(host, cmd, c);
1022 }
San Mehat9d2bd732009-09-22 16:44:22 -07001023 }
1024}
1025
1026static void
1027msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
1028{
San Mehat56a8b5b2009-11-21 12:29:46 -08001029 msmsdcc_start_command_deferred(host, cmd, &c);
1030 msmsdcc_start_command_exec(host, cmd->arg, c);
San Mehat9d2bd732009-09-22 16:44:22 -07001031}
1032
1033static void
1034msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
1035 unsigned int status)
1036{
1037 if (status & MCI_DATACRCFAIL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001038 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1039 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1040 pr_err("%s: Data CRC error\n",
1041 mmc_hostname(host->mmc));
1042 pr_err("%s: opcode 0x%.8x\n", __func__,
1043 data->mrq->cmd->opcode);
1044 pr_err("%s: blksz %d, blocks %d\n", __func__,
1045 data->blksz, data->blocks);
1046 data->error = -EILSEQ;
1047 }
San Mehat9d2bd732009-09-22 16:44:22 -07001048 } else if (status & MCI_DATATIMEOUT) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001049 /* CRC is optional for the bus test commands, not all
1050 * cards respond back with CRC. However controller
1051 * waits for the CRC and times out. Hence ignore the
1052 * data timeouts during the Bustest.
1053 */
1054 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1055 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1056 pr_err("%s: Data timeout\n",
1057 mmc_hostname(host->mmc));
1058 data->error = -ETIMEDOUT;
1059 }
San Mehat9d2bd732009-09-22 16:44:22 -07001060 } else if (status & MCI_RXOVERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001061 pr_err("%s: RX overrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001062 data->error = -EIO;
1063 } else if (status & MCI_TXUNDERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001064 pr_err("%s: TX underrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001065 data->error = -EIO;
1066 } else {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001067 pr_err("%s: Unknown error (0x%.8x)\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001068 mmc_hostname(host->mmc), status);
San Mehat9d2bd732009-09-22 16:44:22 -07001069 data->error = -EIO;
1070 }
San Mehat9d2bd732009-09-22 16:44:22 -07001071
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001072 /* Dummy CMD52 is not needed when CMD53 has errors */
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001073 if (host->dummy_52_needed)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001074 host->dummy_52_needed = 0;
1075}
San Mehat9d2bd732009-09-22 16:44:22 -07001076
1077static int
1078msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
1079{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001080 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001081 uint32_t *ptr = (uint32_t *) buffer;
1082 int count = 0;
1083
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301084 if (remain % 4)
1085 remain = ((remain >> 2) + 1) << 2;
1086
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001087 while (readl_relaxed(base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1088
1089 *ptr = readl_relaxed(base + MMCIFIFO + (count % MCI_FIFOSIZE));
San Mehat9d2bd732009-09-22 16:44:22 -07001090 ptr++;
1091 count += sizeof(uint32_t);
1092
1093 remain -= sizeof(uint32_t);
1094 if (remain == 0)
1095 break;
1096 }
1097 return count;
1098}
1099
1100static int
1101msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001102 unsigned int remain)
San Mehat9d2bd732009-09-22 16:44:22 -07001103{
1104 void __iomem *base = host->base;
1105 char *ptr = buffer;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001106 unsigned int maxcnt = MCI_FIFOHALFSIZE;
San Mehat9d2bd732009-09-22 16:44:22 -07001107
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001108 while (readl_relaxed(base + MMCISTATUS) &
1109 (MCI_TXFIFOEMPTY | MCI_TXFIFOHALFEMPTY)) {
1110 unsigned int count, sz;
San Mehat9d2bd732009-09-22 16:44:22 -07001111
San Mehat9d2bd732009-09-22 16:44:22 -07001112 count = min(remain, maxcnt);
1113
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301114 sz = count % 4 ? (count >> 2) + 1 : (count >> 2);
1115 writesl(base + MMCIFIFO, ptr, sz);
San Mehat9d2bd732009-09-22 16:44:22 -07001116 ptr += count;
1117 remain -= count;
1118
1119 if (remain == 0)
1120 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001121 }
1122 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07001123
1124 return ptr - buffer;
1125}
1126
San Mehat1cd22962010-02-03 12:59:29 -08001127static irqreturn_t
San Mehat9d2bd732009-09-22 16:44:22 -07001128msmsdcc_pio_irq(int irq, void *dev_id)
1129{
1130 struct msmsdcc_host *host = dev_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001131 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001132 uint32_t status;
1133
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001134 status = readl_relaxed(base + MMCISTATUS);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001135
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001136 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1137 (MCI_IRQ_PIO)) == 0)
1138 return IRQ_NONE;
1139
1140#if IRQ_DEBUG
1141 msmsdcc_print_status(host, "irq1-r", status);
1142#endif
1143
1144 spin_lock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001145
1146 do {
1147 unsigned long flags;
1148 unsigned int remain, len;
1149 char *buffer;
1150
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001151 if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_TXFIFOEMPTY
1152 | MCI_RXDATAAVLBL)))
1153 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001154
1155 /* Map the current scatter buffer */
1156 local_irq_save(flags);
1157 buffer = kmap_atomic(sg_page(host->pio.sg),
1158 KM_BIO_SRC_IRQ) + host->pio.sg->offset;
1159 buffer += host->pio.sg_off;
1160 remain = host->pio.sg->length - host->pio.sg_off;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001161
San Mehat9d2bd732009-09-22 16:44:22 -07001162 len = 0;
1163 if (status & MCI_RXACTIVE)
1164 len = msmsdcc_pio_read(host, buffer, remain);
1165 if (status & MCI_TXACTIVE)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001166 len = msmsdcc_pio_write(host, buffer, remain);
San Mehat9d2bd732009-09-22 16:44:22 -07001167
1168 /* Unmap the buffer */
1169 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
1170 local_irq_restore(flags);
1171
1172 host->pio.sg_off += len;
1173 host->curr.xfer_remain -= len;
1174 host->curr.data_xfered += len;
1175 remain -= len;
1176
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001177 if (remain) /* Done with this page? */
1178 break; /* Nope */
San Mehat9d2bd732009-09-22 16:44:22 -07001179
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001180 if (status & MCI_RXACTIVE && host->curr.user_pages)
1181 flush_dcache_page(sg_page(host->pio.sg));
San Mehat9d2bd732009-09-22 16:44:22 -07001182
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001183 if (!--host->pio.sg_len) {
1184 memset(&host->pio, 0, sizeof(host->pio));
1185 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001186 }
1187
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001188 /* Advance to next sg */
1189 host->pio.sg++;
1190 host->pio.sg_off = 0;
1191
1192 status = readl_relaxed(base + MMCISTATUS);
San Mehat9d2bd732009-09-22 16:44:22 -07001193 } while (1);
1194
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001195 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
1196 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1197 (~(MCI_IRQ_PIO))) | MCI_RXDATAAVLBLMASK,
1198 host->base + MMCIMASK0);
1199 if (!host->curr.xfer_remain) {
1200 /* Delay needed (same port was just written) */
1201 msmsdcc_delay(host);
1202 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1203 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1204 }
1205 mb();
1206 } else if (!host->curr.xfer_remain) {
1207 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1208 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1209 mb();
1210 }
San Mehat9d2bd732009-09-22 16:44:22 -07001211
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001212 spin_unlock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001213
1214 return IRQ_HANDLED;
1215}
1216
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001217static void
1218msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq);
1219
1220static void msmsdcc_wait_for_rxdata(struct msmsdcc_host *host,
1221 struct mmc_data *data)
1222{
1223 u32 loop_cnt = 0;
1224
1225 /*
1226 * For read commands with data less than fifo size, it is possible to
1227 * get DATAEND first and RXDATA_AVAIL might be set later because of
1228 * synchronization delay through the asynchronous RX FIFO. Thus, for
1229 * such cases, even after DATAEND interrupt is received software
1230 * should poll for RXDATA_AVAIL until the requested data is read out
1231 * of FIFO. This change is needed to get around this abnormal but
1232 * sometimes expected behavior of SDCC3 controller.
1233 *
1234 * We can expect RXDATAAVAIL bit to be set after 6HCLK clock cycles
1235 * after the data is loaded into RX FIFO. This would amount to less
1236 * than a microsecond and thus looping for 1000 times is good enough
1237 * for that delay.
1238 */
1239 while (((int)host->curr.xfer_remain > 0) && (++loop_cnt < 1000)) {
1240 if (readl_relaxed(host->base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1241 spin_unlock(&host->lock);
1242 msmsdcc_pio_irq(1, host);
1243 spin_lock(&host->lock);
1244 }
1245 }
1246 if (loop_cnt == 1000) {
1247 pr_info("%s: Timed out while polling for Rx Data\n",
1248 mmc_hostname(host->mmc));
1249 data->error = -ETIMEDOUT;
1250 msmsdcc_reset_and_restore(host);
1251 }
1252}
1253
San Mehat9d2bd732009-09-22 16:44:22 -07001254static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
1255{
1256 struct mmc_command *cmd = host->curr.cmd;
San Mehat9d2bd732009-09-22 16:44:22 -07001257
1258 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001259 cmd->resp[0] = readl_relaxed(host->base + MMCIRESPONSE0);
1260 cmd->resp[1] = readl_relaxed(host->base + MMCIRESPONSE1);
1261 cmd->resp[2] = readl_relaxed(host->base + MMCIRESPONSE2);
1262 cmd->resp[3] = readl_relaxed(host->base + MMCIRESPONSE3);
San Mehat9d2bd732009-09-22 16:44:22 -07001263
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001264 if (status & (MCI_CMDTIMEOUT | MCI_AUTOCMD19TIMEOUT)) {
Sahitya Tummala5a0ae912011-07-18 13:34:01 +05301265 pr_debug("%s: Command timeout\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001266 cmd->error = -ETIMEDOUT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001267 } else if ((status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) &&
1268 !host->cmd19_tuning_in_progress) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001269 pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001270 cmd->error = -EILSEQ;
1271 }
1272
1273 if (!cmd->data || cmd->error) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001274 if (host->curr.data && host->dma.sg &&
1275 host->is_dma_mode)
San Mehat9d2bd732009-09-22 16:44:22 -07001276 msm_dmov_stop_cmd(host->dma.channel,
1277 &host->dma.hdr, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001278 else if (host->curr.data && host->sps.sg &&
1279 host->is_sps_mode){
1280 /* Stop current SPS transfer */
1281 msmsdcc_sps_exit_curr_xfer(host);
1282 }
San Mehat9d2bd732009-09-22 16:44:22 -07001283 else if (host->curr.data) { /* Non DMA */
Sahitya Tummalab08bb352010-12-08 15:03:05 +05301284 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -07001285 msmsdcc_stop_data(host);
1286 msmsdcc_request_end(host, cmd->mrq);
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301287 } else { /* host->data == NULL */
1288 if (!cmd->error && host->prog_enable) {
1289 if (status & MCI_PROGDONE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001290 host->prog_scan = 0;
1291 host->prog_enable = 0;
1292 msmsdcc_request_end(host, cmd->mrq);
1293 } else
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301294 host->curr.cmd = cmd;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301295 } else {
1296 if (host->prog_enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001297 host->prog_scan = 0;
1298 host->prog_enable = 0;
1299 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001300 if (host->dummy_52_needed)
1301 host->dummy_52_needed = 0;
1302 if (cmd->data && cmd->error)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001303 msmsdcc_reset_and_restore(host);
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301304 msmsdcc_request_end(host, cmd->mrq);
1305 }
1306 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001307 } else if (cmd->data) {
San Mehat56a8b5b2009-11-21 12:29:46 -08001308 if (!(cmd->data->flags & MMC_DATA_READ))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001309 msmsdcc_start_data(host, cmd->data, NULL, 0);
Joe Perchesb5a74d62009-09-22 16:44:25 -07001310 }
1311}
1312
San Mehat9d2bd732009-09-22 16:44:22 -07001313static irqreturn_t
1314msmsdcc_irq(int irq, void *dev_id)
1315{
1316 struct msmsdcc_host *host = dev_id;
San Mehat9d2bd732009-09-22 16:44:22 -07001317 u32 status;
1318 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001319 int timer = 0;
San Mehat9d2bd732009-09-22 16:44:22 -07001320
1321 spin_lock(&host->lock);
1322
1323 do {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001324 struct mmc_command *cmd;
1325 struct mmc_data *data;
San Mehat9d2bd732009-09-22 16:44:22 -07001326
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001327 if (timer) {
1328 timer = 0;
1329 msmsdcc_delay(host);
1330 }
San Mehat865c8062009-11-13 13:42:06 -08001331
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001332 if (!host->clks_on) {
1333 pr_debug("%s: %s: SDIO async irq received\n",
1334 mmc_hostname(host->mmc), __func__);
1335 host->mmc->ios.clock = host->clk_rate;
1336 spin_unlock(&host->lock);
1337 host->mmc->ops->set_ios(host->mmc, &host->mmc->ios);
1338 spin_lock(&host->lock);
1339 if (host->plat->cfg_mpm_sdiowakeup &&
1340 (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1341 wake_lock(&host->sdio_wlock);
1342 /* only ansyc interrupt can come when clocks are off */
1343 writel_relaxed(MCI_SDIOINTMASK, host->base + MMCICLEAR);
1344 }
1345
1346 status = readl_relaxed(host->base + MMCISTATUS);
1347
1348 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1349 (~(MCI_IRQ_PIO))) == 0)
San Mehat865c8062009-11-13 13:42:06 -08001350 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001351
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001352#if IRQ_DEBUG
1353 msmsdcc_print_status(host, "irq0-r", status);
1354#endif
1355 status &= readl_relaxed(host->base + MMCIMASK0);
1356 writel_relaxed(status, host->base + MMCICLEAR);
1357 mb();
1358#if IRQ_DEBUG
1359 msmsdcc_print_status(host, "irq0-p", status);
1360#endif
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001361
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001362#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
1363 if (status & MCI_SDIOINTROPE) {
1364 if (host->sdcc_suspending)
1365 wake_lock(&host->sdio_suspend_wlock);
1366 mmc_signal_sdio_irq(host->mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07001367 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001368#endif
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001369 data = host->curr.data;
1370
1371 if (host->dummy_52_sent) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001372 if (status & (MCI_PROGDONE | MCI_CMDCRCFAIL |
1373 MCI_CMDTIMEOUT)) {
1374 if (status & MCI_CMDTIMEOUT)
1375 pr_debug("%s: dummy CMD52 timeout\n",
1376 mmc_hostname(host->mmc));
1377 if (status & MCI_CMDCRCFAIL)
1378 pr_debug("%s: dummy CMD52 CRC failed\n",
1379 mmc_hostname(host->mmc));
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001380 host->dummy_52_sent = 0;
1381 host->dummy_52_needed = 0;
1382 if (data) {
1383 msmsdcc_stop_data(host);
1384 msmsdcc_request_end(host, data->mrq);
1385 }
1386 WARN(!data, "No data cmd for dummy CMD52\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001387 spin_unlock(&host->lock);
1388 return IRQ_HANDLED;
1389 }
1390 break;
1391 }
1392
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001393 /*
1394 * Check for proper command response
1395 */
1396 cmd = host->curr.cmd;
1397 if ((status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
1398 MCI_CMDTIMEOUT | MCI_PROGDONE |
1399 MCI_AUTOCMD19TIMEOUT)) && host->curr.cmd) {
1400 msmsdcc_do_cmdirq(host, status);
1401 }
1402
1403 if (data) {
1404 /* Check for data errors */
1405 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|
1406 MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
1407 msmsdcc_data_err(host, data, status);
1408 host->curr.data_xfered = 0;
1409 if (host->dma.sg && host->is_dma_mode)
1410 msm_dmov_stop_cmd(host->dma.channel,
1411 &host->dma.hdr, 0);
1412 else if (host->sps.sg && host->is_sps_mode) {
1413 /* Stop current SPS transfer */
1414 msmsdcc_sps_exit_curr_xfer(host);
1415 }
1416 else {
1417 msmsdcc_reset_and_restore(host);
1418 if (host->curr.data)
1419 msmsdcc_stop_data(host);
1420 if (!data->stop)
1421 timer |=
1422 msmsdcc_request_end(host,
1423 data->mrq);
1424 else {
1425 msmsdcc_start_command(host,
1426 data->stop,
1427 0);
1428 timer = 1;
1429 }
1430 }
1431 }
1432
1433 /* Check for data done */
1434 if (!host->curr.got_dataend && (status & MCI_DATAEND))
1435 host->curr.got_dataend = 1;
1436
1437 if (host->curr.got_dataend) {
1438 /*
1439 * If DMA is still in progress, we complete
1440 * via the completion handler
1441 */
1442 if (!host->dma.busy && !host->sps.busy) {
1443 /*
1444 * There appears to be an issue in the
1445 * controller where if you request a
1446 * small block transfer (< fifo size),
1447 * you may get your DATAEND/DATABLKEND
1448 * irq without the PIO data irq.
1449 *
1450 * Check to see if theres still data
1451 * to be read, and simulate a PIO irq.
1452 */
1453 if (data->flags & MMC_DATA_READ)
1454 msmsdcc_wait_for_rxdata(host,
1455 data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001456 if (!data->error) {
1457 host->curr.data_xfered =
1458 host->curr.xfer_size;
1459 host->curr.xfer_remain -=
1460 host->curr.xfer_size;
1461 }
1462
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001463 if (!host->dummy_52_needed) {
1464 msmsdcc_stop_data(host);
1465 if (!data->stop) {
1466 msmsdcc_request_end(
1467 host,
1468 data->mrq);
1469 } else {
1470 msmsdcc_start_command(
1471 host,
1472 data->stop, 0);
1473 timer = 1;
1474 }
1475 } else {
1476 host->dummy_52_sent = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001477 msmsdcc_start_command(host,
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001478 &dummy52cmd,
1479 MCI_CPSM_PROGENA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001480 }
1481 }
1482 }
1483 }
1484
San Mehat9d2bd732009-09-22 16:44:22 -07001485 ret = 1;
1486 } while (status);
1487
1488 spin_unlock(&host->lock);
1489
San Mehat9d2bd732009-09-22 16:44:22 -07001490 return IRQ_RETVAL(ret);
1491}
1492
1493static void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001494msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
1495{
1496 if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
1497 /* Queue/read data, daisy-chain command when data starts */
1498 msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
1499 } else {
1500 msmsdcc_start_command(host, mrq->cmd, 0);
1501 }
1502}
1503
1504static void
San Mehat9d2bd732009-09-22 16:44:22 -07001505msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
1506{
1507 struct msmsdcc_host *host = mmc_priv(mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001508 unsigned long flags;
San Mehat9d2bd732009-09-22 16:44:22 -07001509
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001510 /*
1511 * Get the SDIO AL client out of LPM.
1512 */
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001513 WARN(host->dummy_52_sent, "Dummy CMD52 in progress\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001514 if (host->plat->is_sdio_al_client)
1515 msmsdcc_sdio_al_lpm(mmc, false);
San Mehat9d2bd732009-09-22 16:44:22 -07001516
1517 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001518 WARN(host->curr.mrq, "Request in progress\n");
1519 WARN(!host->pwr, "SDCC power is turned off\n");
1520 WARN(!host->clks_on, "SDCC clocks are turned off\n");
1521 WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
San Mehat9d2bd732009-09-22 16:44:22 -07001522
1523 if (host->eject) {
1524 if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) {
1525 mrq->cmd->error = 0;
1526 mrq->data->bytes_xfered = mrq->data->blksz *
1527 mrq->data->blocks;
1528 } else
1529 mrq->cmd->error = -ENOMEDIUM;
1530
1531 spin_unlock_irqrestore(&host->lock, flags);
1532 mmc_request_done(mmc, mrq);
1533 return;
1534 }
1535
1536 host->curr.mrq = mrq;
1537
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001538 if (host->plat->dummy52_required) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001539 if (mrq->data && mrq->data->flags == MMC_DATA_WRITE) {
1540 if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001541 mrq->cmd->opcode == 54) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001542 host->dummy_52_needed = 1;
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001543 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001544 }
San Mehat9d2bd732009-09-22 16:44:22 -07001545 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001546 msmsdcc_request_start(host, mrq);
San Mehat9d2bd732009-09-22 16:44:22 -07001547 spin_unlock_irqrestore(&host->lock, flags);
1548}
1549
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001550static inline int msmsdcc_vreg_set_voltage(struct msm_mmc_reg_data *vreg,
1551 int min_uV, int max_uV)
1552{
1553 int rc = 0;
1554
1555 if (vreg->set_voltage_sup) {
1556 rc = regulator_set_voltage(vreg->reg, min_uV, max_uV);
1557 if (rc) {
1558 pr_err("%s: regulator_set_voltage(%s) failed."
1559 " min_uV=%d, max_uV=%d, rc=%d\n",
1560 __func__, vreg->name, min_uV, max_uV, rc);
1561 }
1562 }
1563
1564 return rc;
1565}
1566
1567static inline int msmsdcc_vreg_set_optimum_mode(struct msm_mmc_reg_data *vreg,
1568 int uA_load)
1569{
1570 int rc = 0;
1571
1572 rc = regulator_set_optimum_mode(vreg->reg, uA_load);
1573 if (rc < 0)
1574 pr_err("%s: regulator_set_optimum_mode(reg=%s, uA_load=%d)"
1575 " failed. rc=%d\n", __func__, vreg->name,
1576 uA_load, rc);
1577 else
1578 /* regulator_set_optimum_mode() can return non zero value
1579 * even for success case.
1580 */
1581 rc = 0;
1582
1583 return rc;
1584}
1585
1586static inline int msmsdcc_vreg_init_reg(struct msm_mmc_reg_data *vreg,
1587 struct device *dev)
1588{
1589 int rc = 0;
1590
1591 /* check if regulator is already initialized? */
1592 if (vreg->reg)
1593 goto out;
1594
1595 /* Get the regulator handle */
1596 vreg->reg = regulator_get(dev, vreg->name);
1597 if (IS_ERR(vreg->reg)) {
1598 rc = PTR_ERR(vreg->reg);
1599 pr_err("%s: regulator_get(%s) failed. rc=%d\n",
1600 __func__, vreg->name, rc);
1601 }
1602out:
1603 return rc;
1604}
1605
1606static inline void msmsdcc_vreg_deinit_reg(struct msm_mmc_reg_data *vreg)
1607{
1608 if (vreg->reg)
1609 regulator_put(vreg->reg);
1610}
1611
1612/* This init function should be called only once for each SDCC slot */
1613static int msmsdcc_vreg_init(struct msmsdcc_host *host, bool is_init)
1614{
1615 int rc = 0;
1616 struct msm_mmc_slot_reg_data *curr_slot;
1617 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1618 struct device *dev = mmc_dev(host->mmc);
1619
1620 curr_slot = host->plat->vreg_data;
1621 if (!curr_slot)
1622 goto out;
1623
1624 curr_vdd_reg = curr_slot->vdd_data;
1625 curr_vccq_reg = curr_slot->vccq_data;
1626 curr_vddp_reg = curr_slot->vddp_data;
1627
1628 if (is_init) {
1629 /*
1630 * Get the regulator handle from voltage regulator framework
1631 * and then try to set the voltage level for the regulator
1632 */
1633 if (curr_vdd_reg) {
1634 rc = msmsdcc_vreg_init_reg(curr_vdd_reg, dev);
1635 if (rc)
1636 goto out;
1637 }
1638 if (curr_vccq_reg) {
1639 rc = msmsdcc_vreg_init_reg(curr_vccq_reg, dev);
1640 if (rc)
1641 goto vdd_reg_deinit;
1642 }
1643 if (curr_vddp_reg) {
1644 rc = msmsdcc_vreg_init_reg(curr_vddp_reg, dev);
1645 if (rc)
1646 goto vccq_reg_deinit;
1647 }
1648 goto out;
1649 } else {
1650 /* Deregister all regulators from regulator framework */
1651 goto vddp_reg_deinit;
1652 }
1653vddp_reg_deinit:
1654 if (curr_vddp_reg)
1655 msmsdcc_vreg_deinit_reg(curr_vddp_reg);
1656vccq_reg_deinit:
1657 if (curr_vccq_reg)
1658 msmsdcc_vreg_deinit_reg(curr_vccq_reg);
1659vdd_reg_deinit:
1660 if (curr_vdd_reg)
1661 msmsdcc_vreg_deinit_reg(curr_vdd_reg);
1662out:
1663 return rc;
1664}
1665
1666static int msmsdcc_vreg_enable(struct msm_mmc_reg_data *vreg)
1667{
1668 int rc = 0;
1669
1670 if (!vreg->is_enabled) {
1671 /* Set voltage level */
1672 rc = msmsdcc_vreg_set_voltage(vreg, vreg->level,
1673 vreg->level);
1674 if (rc)
1675 goto out;
1676
1677 rc = regulator_enable(vreg->reg);
1678 if (rc) {
1679 pr_err("%s: regulator_enable(%s) failed. rc=%d\n",
1680 __func__, vreg->name, rc);
1681 goto out;
1682 }
1683 vreg->is_enabled = true;
1684 }
1685
1686 /* Put regulator in HPM (high power mode) */
1687 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->hpm_uA);
1688 if (rc < 0)
1689 goto vreg_disable;
1690
1691 goto out;
1692
1693vreg_disable:
1694 regulator_disable(vreg->reg);
1695 vreg->is_enabled = false;
1696out:
1697 return rc;
1698}
1699
1700static int msmsdcc_vreg_disable(struct msm_mmc_reg_data *vreg)
1701{
1702 int rc = 0;
1703
1704 /* Never disable regulator marked as always_on */
1705 if (vreg->is_enabled && !vreg->always_on) {
1706 rc = regulator_disable(vreg->reg);
1707 if (rc) {
1708 pr_err("%s: regulator_disable(%s) failed. rc=%d\n",
1709 __func__, vreg->name, rc);
1710 goto out;
1711 }
1712 vreg->is_enabled = false;
1713
1714 rc = msmsdcc_vreg_set_optimum_mode(vreg, 0);
1715 if (rc < 0)
1716 goto out;
1717
1718 /* Set min. voltage level to 0 */
1719 rc = msmsdcc_vreg_set_voltage(vreg, 0, vreg->level);
1720 if (rc)
1721 goto out;
1722 } else if (vreg->is_enabled && vreg->always_on && vreg->lpm_sup) {
1723 /* Put always_on regulator in LPM (low power mode) */
1724 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->lpm_uA);
1725 if (rc < 0)
1726 goto out;
1727 }
1728out:
1729 return rc;
1730}
1731
1732static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable)
1733{
1734 int rc = 0, i;
1735 struct msm_mmc_slot_reg_data *curr_slot;
1736 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1737 struct msm_mmc_reg_data *vreg_table[3];
1738
1739 curr_slot = host->plat->vreg_data;
1740 if (!curr_slot)
1741 goto out;
1742
1743 curr_vdd_reg = vreg_table[0] = curr_slot->vdd_data;
1744 curr_vccq_reg = vreg_table[1] = curr_slot->vccq_data;
1745 curr_vddp_reg = vreg_table[2] = curr_slot->vddp_data;
1746
1747 for (i = 0; i < ARRAY_SIZE(vreg_table); i++) {
1748 if (vreg_table[i]) {
1749 if (enable)
1750 rc = msmsdcc_vreg_enable(vreg_table[i]);
1751 else
1752 rc = msmsdcc_vreg_disable(vreg_table[i]);
1753 if (rc)
1754 goto out;
1755 }
1756 }
1757out:
1758 return rc;
1759}
1760
1761static int msmsdcc_tune_vdd_pad_level(struct msmsdcc_host *host, int level)
1762{
1763 int rc = 0;
1764
1765 if (host->plat->vreg_data) {
1766 struct msm_mmc_reg_data *vddp_reg =
1767 host->plat->vreg_data->vddp_data;
1768
1769 if (vddp_reg && vddp_reg->is_enabled)
1770 rc = msmsdcc_vreg_set_voltage(vddp_reg, level, level);
1771 }
1772
1773 return rc;
1774}
1775
1776static inline int msmsdcc_is_pwrsave(struct msmsdcc_host *host)
1777{
1778 if (host->clk_rate > 400000 && msmsdcc_pwrsave)
1779 return 1;
1780 return 0;
1781}
1782
1783static inline void msmsdcc_setup_clocks(struct msmsdcc_host *host, bool enable)
1784{
1785 if (enable) {
1786 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1787 clk_enable(host->dfab_pclk);
1788 if (!IS_ERR(host->pclk))
1789 clk_enable(host->pclk);
1790 clk_enable(host->clk);
1791 } else {
1792 clk_disable(host->clk);
1793 if (!IS_ERR(host->pclk))
1794 clk_disable(host->pclk);
1795 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1796 clk_disable(host->dfab_pclk);
1797 }
1798}
1799
1800static inline unsigned int msmsdcc_get_sup_clk_rate(struct msmsdcc_host *host,
1801 unsigned int req_clk)
1802{
1803 unsigned int sel_clk = -1;
1804
1805 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt) {
1806 unsigned char cnt;
1807
1808 for (cnt = 0; cnt < host->plat->sup_clk_cnt; cnt++) {
1809 if (host->plat->sup_clk_table[cnt] > req_clk)
1810 break;
1811 else if (host->plat->sup_clk_table[cnt] == req_clk) {
1812 sel_clk = host->plat->sup_clk_table[cnt];
1813 break;
1814 } else
1815 sel_clk = host->plat->sup_clk_table[cnt];
1816 }
1817 } else {
1818 if ((req_clk < host->plat->msmsdcc_fmax) &&
1819 (req_clk > host->plat->msmsdcc_fmid))
1820 sel_clk = host->plat->msmsdcc_fmid;
1821 else
1822 sel_clk = req_clk;
1823 }
1824
1825 return sel_clk;
1826}
1827
1828static inline unsigned int msmsdcc_get_min_sup_clk_rate(
1829 struct msmsdcc_host *host)
1830{
1831 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1832 return host->plat->sup_clk_table[0];
1833 else
1834 return host->plat->msmsdcc_fmin;
1835}
1836
1837static inline unsigned int msmsdcc_get_max_sup_clk_rate(
1838 struct msmsdcc_host *host)
1839{
1840 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1841 return host->plat->sup_clk_table[host->plat->sup_clk_cnt - 1];
1842 else
1843 return host->plat->msmsdcc_fmax;
1844}
1845
1846static int msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
Sahitya Tummala7a892482011-01-18 11:22:49 +05301847{
1848 struct msm_mmc_gpio_data *curr;
1849 int i, rc = 0;
1850
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001851 curr = host->plat->pin_data->gpio_data;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301852 for (i = 0; i < curr->size; i++) {
1853 if (enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001854 if (curr->gpio[i].is_always_on &&
1855 curr->gpio[i].is_enabled)
1856 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301857 rc = gpio_request(curr->gpio[i].no,
1858 curr->gpio[i].name);
1859 if (rc) {
1860 pr_err("%s: gpio_request(%d, %s) failed %d\n",
1861 mmc_hostname(host->mmc),
1862 curr->gpio[i].no,
1863 curr->gpio[i].name, rc);
1864 goto free_gpios;
1865 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001866 curr->gpio[i].is_enabled = true;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301867 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001868 if (curr->gpio[i].is_always_on)
1869 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301870 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001871 curr->gpio[i].is_enabled = false;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301872 }
1873 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001874 goto out;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301875
1876free_gpios:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001877 for (; i >= 0; i--) {
Sahitya Tummala7a892482011-01-18 11:22:49 +05301878 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001879 curr->gpio[i].is_enabled = false;
1880 }
1881out:
1882 return rc;
1883}
1884
1885static int msmsdcc_setup_pad(struct msmsdcc_host *host, bool enable)
1886{
1887 struct msm_mmc_pad_data *curr;
1888 int i;
1889
1890 curr = host->plat->pin_data->pad_data;
1891 for (i = 0; i < curr->drv->size; i++) {
1892 if (enable)
1893 msm_tlmm_set_hdrive(curr->drv->on[i].no,
1894 curr->drv->on[i].val);
1895 else
1896 msm_tlmm_set_hdrive(curr->drv->off[i].no,
1897 curr->drv->off[i].val);
1898 }
1899
1900 for (i = 0; i < curr->pull->size; i++) {
1901 if (enable)
1902 msm_tlmm_set_hdrive(curr->pull->on[i].no,
1903 curr->pull->on[i].val);
1904 else
1905 msm_tlmm_set_hdrive(curr->pull->off[i].no,
1906 curr->pull->off[i].val);
1907 }
1908
1909 return 0;
1910}
1911
1912static u32 msmsdcc_setup_pins(struct msmsdcc_host *host, bool enable)
1913{
1914 int rc = 0;
1915
1916 if (!host->plat->pin_data || host->plat->pin_data->cfg_sts == enable)
1917 return 0;
1918
1919 if (host->plat->pin_data->is_gpio)
1920 rc = msmsdcc_setup_gpio(host, enable);
1921 else
1922 rc = msmsdcc_setup_pad(host, enable);
1923
1924 if (!rc)
1925 host->plat->pin_data->cfg_sts = enable;
1926
1927 return rc;
1928}
1929
1930static void msmsdcc_enable_irq_wake(struct msmsdcc_host *host)
1931{
1932 unsigned int wakeup_irq;
1933
1934 wakeup_irq = (host->plat->sdiowakeup_irq) ?
1935 host->plat->sdiowakeup_irq :
1936 host->core_irqres->start;
1937
1938 if (!host->irq_wake_enabled) {
1939 enable_irq_wake(wakeup_irq);
1940 host->irq_wake_enabled = true;
1941 }
1942}
1943
1944static void msmsdcc_disable_irq_wake(struct msmsdcc_host *host)
1945{
1946 unsigned int wakeup_irq;
1947
1948 wakeup_irq = (host->plat->sdiowakeup_irq) ?
1949 host->plat->sdiowakeup_irq :
1950 host->core_irqres->start;
1951
1952 if (host->irq_wake_enabled) {
1953 disable_irq_wake(wakeup_irq);
1954 host->irq_wake_enabled = false;
1955 }
Sahitya Tummala7a892482011-01-18 11:22:49 +05301956}
1957
San Mehat9d2bd732009-09-22 16:44:22 -07001958static void
1959msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1960{
1961 struct msmsdcc_host *host = mmc_priv(mmc);
1962 u32 clk = 0, pwr = 0;
1963 int rc;
San Mehat4adbbcc2009-11-08 13:00:37 -08001964 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001965 unsigned int clock;
San Mehat9d2bd732009-09-22 16:44:22 -07001966
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001967 DBG(host, "ios->clock = %u\n", ios->clock);
Sahitya Tummala7a892482011-01-18 11:22:49 +05301968
San Mehat9d2bd732009-09-22 16:44:22 -07001969 if (ios->clock) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001970 spin_lock_irqsave(&host->lock, flags);
1971 if (!host->clks_on) {
1972 msmsdcc_setup_clocks(host, true);
1973 host->clks_on = 1;
1974 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
1975 if (!host->plat->sdiowakeup_irq) {
1976 writel_relaxed(host->mci_irqenable,
1977 host->base + MMCIMASK0);
1978 mb();
1979 if (host->plat->cfg_mpm_sdiowakeup &&
1980 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1981 host->plat->cfg_mpm_sdiowakeup(
1982 mmc_dev(mmc), SDC_DAT1_DISWAKE);
1983 msmsdcc_disable_irq_wake(host);
1984 } else if (!(mmc->pm_flags &
1985 MMC_PM_WAKE_SDIO_IRQ)) {
1986 writel_relaxed(host->mci_irqenable,
1987 host->base + MMCIMASK0);
1988 }
1989 }
San Mehat9d2bd732009-09-22 16:44:22 -07001990 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001991 spin_unlock_irqrestore(&host->lock, flags);
1992
1993 clock = msmsdcc_get_sup_clk_rate(host, ios->clock);
1994 /*
1995 * For DDR50 mode, controller needs clock rate to be
1996 * double than what is required on the SD card CLK pin.
1997 */
1998 if (ios->timing == MMC_TIMING_UHS_DDR50) {
1999 /*
2000 * Make sure that we don't double the clock if
2001 * doubled clock rate is already set
2002 */
2003 if (!host->ddr_doubled_clk_rate ||
2004 (host->ddr_doubled_clk_rate &&
2005 (host->ddr_doubled_clk_rate != ios->clock))) {
2006 host->ddr_doubled_clk_rate =
2007 msmsdcc_get_sup_clk_rate(
2008 host, (ios->clock * 2));
2009 clock = host->ddr_doubled_clk_rate;
2010 }
2011 } else {
2012 host->ddr_doubled_clk_rate = 0;
2013 }
2014
2015 if (clock != host->clk_rate) {
2016 rc = clk_set_rate(host->clk, clock);
2017 if (rc < 0)
2018 pr_debug("%s: failed to set clk rate %u\n",
2019 mmc_hostname(mmc), clock);
2020 host->clk_rate = clock;
2021 }
2022 /*
2023 * give atleast 2 MCLK cycles delay for clocks
2024 * and SDCC core to stabilize
2025 */
2026 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002027 clk |= MCI_CLK_ENABLE;
2028 }
2029
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002030 if (ios->bus_width == MMC_BUS_WIDTH_8)
2031 clk |= MCI_CLK_WIDEBUS_8;
2032 else if (ios->bus_width == MMC_BUS_WIDTH_4)
2033 clk |= MCI_CLK_WIDEBUS_4;
2034 else
2035 clk |= MCI_CLK_WIDEBUS_1;
San Mehat9d2bd732009-09-22 16:44:22 -07002036
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002037 if (msmsdcc_is_pwrsave(host))
2038 clk |= MCI_CLK_PWRSAVE;
San Mehat9d2bd732009-09-22 16:44:22 -07002039
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002040 clk |= MCI_CLK_FLOWENA;
San Mehat9d2bd732009-09-22 16:44:22 -07002041
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002042 host->tuning_needed = 0;
2043 /*
2044 * Select the controller timing mode according
2045 * to current bus speed mode
2046 */
2047 if ((ios->timing == MMC_TIMING_UHS_SDR104) ||
2048 (ios->timing == MMC_TIMING_UHS_SDR50)) {
2049 clk |= (4 << 14);
2050 host->tuning_needed = 1;
2051 } else if (ios->timing == MMC_TIMING_UHS_DDR50) {
2052 clk |= (3 << 14);
2053 } else {
2054 clk |= (2 << 14); /* feedback clock */
2055 }
2056
2057 /* Select free running MCLK as input clock of cm_dll_sdc4 */
2058 clk |= (2 << 23);
2059
2060 if (host->io_pad_pwr_switch)
2061 clk |= IO_PAD_PWR_SWITCH;
2062
2063 if (host->plat->translate_vdd && !host->sdio_gpio_lpm)
San Mehat9d2bd732009-09-22 16:44:22 -07002064 pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002065 else if (!host->plat->translate_vdd && !host->sdio_gpio_lpm)
2066 pwr |= msmsdcc_setup_vreg(host, !!ios->vdd);
San Mehat9d2bd732009-09-22 16:44:22 -07002067
2068 switch (ios->power_mode) {
2069 case MMC_POWER_OFF:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002070 htc_pwrsink_set(PWRSINK_SDCARD, 0);
2071 if (!host->sdcc_irq_disabled) {
2072 if (host->plat->cfg_mpm_sdiowakeup)
2073 host->plat->cfg_mpm_sdiowakeup(
2074 mmc_dev(mmc), SDC_DAT1_DISABLE);
2075 disable_irq(host->core_irqres->start);
2076 host->sdcc_irq_disabled = 1;
2077 }
2078 msmsdcc_setup_pins(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07002079 break;
2080 case MMC_POWER_UP:
2081 pwr |= MCI_PWR_UP;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002082 if (host->sdcc_irq_disabled) {
2083 if (host->plat->cfg_mpm_sdiowakeup)
2084 host->plat->cfg_mpm_sdiowakeup(
2085 mmc_dev(mmc), SDC_DAT1_ENABLE);
2086 enable_irq(host->core_irqres->start);
2087 host->sdcc_irq_disabled = 0;
2088 }
2089 msmsdcc_setup_pins(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07002090 break;
2091 case MMC_POWER_ON:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002092 htc_pwrsink_set(PWRSINK_SDCARD, 100);
San Mehat9d2bd732009-09-22 16:44:22 -07002093 pwr |= MCI_PWR_ON;
2094 break;
2095 }
2096
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002097 spin_lock_irqsave(&host->lock, flags);
2098 if (!host->clks_on) {
2099 /* force the clocks to be on */
2100 msmsdcc_setup_clocks(host, true);
2101 /*
2102 * give atleast 2 MCLK cycles delay for clocks
2103 * and SDCC core to stabilize
2104 */
2105 msmsdcc_delay(host);
2106 }
2107 writel_relaxed(clk, host->base + MMCICLOCK);
2108 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002109
2110 if (host->pwr != pwr) {
2111 host->pwr = pwr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002112 writel_relaxed(pwr, host->base + MMCIPOWER);
2113 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07002114 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002115 if (!host->clks_on) {
2116 /* force the clocks to be off */
2117 msmsdcc_setup_clocks(host, false);
2118 /*
2119 * give atleast 2 MCLK cycles delay for clocks
2120 * and SDCC core to stabilize
2121 */
2122 msmsdcc_delay(host);
2123 }
2124
2125 if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
2126 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
2127 if (!host->plat->sdiowakeup_irq) {
2128 writel_relaxed(MCI_SDIOINTMASK,
2129 host->base + MMCIMASK0);
2130 mb();
2131 if (host->plat->cfg_mpm_sdiowakeup &&
2132 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
2133 host->plat->cfg_mpm_sdiowakeup(
2134 mmc_dev(mmc), SDC_DAT1_ENWAKE);
2135 msmsdcc_enable_irq_wake(host);
2136 } else if (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2137 writel_relaxed(0, host->base + MMCIMASK0);
2138 } else {
2139 writel_relaxed(MCI_SDIOINTMASK,
2140 host->base + MMCIMASK0);
2141 }
2142 msmsdcc_delay(host);
2143 }
2144 msmsdcc_setup_clocks(host, false);
2145 host->clks_on = 0;
2146 }
San Mehat4adbbcc2009-11-08 13:00:37 -08002147 spin_unlock_irqrestore(&host->lock, flags);
San Mehat9d2bd732009-09-22 16:44:22 -07002148}
2149
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002150int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave)
2151{
2152 struct msmsdcc_host *host = mmc_priv(mmc);
2153 u32 clk;
2154
2155 clk = readl_relaxed(host->base + MMCICLOCK);
2156 pr_debug("Changing to pwr_save=%d", pwrsave);
2157 if (pwrsave && msmsdcc_is_pwrsave(host))
2158 clk |= MCI_CLK_PWRSAVE;
2159 else
2160 clk &= ~MCI_CLK_PWRSAVE;
2161 writel_relaxed(clk, host->base + MMCICLOCK);
2162 mb();
2163
2164 return 0;
2165}
2166
2167static int msmsdcc_get_ro(struct mmc_host *mmc)
2168{
2169 int status = -ENOSYS;
2170 struct msmsdcc_host *host = mmc_priv(mmc);
2171
2172 if (host->plat->wpswitch) {
2173 status = host->plat->wpswitch(mmc_dev(mmc));
2174 } else if (host->plat->wpswitch_gpio) {
2175 status = gpio_request(host->plat->wpswitch_gpio,
2176 "SD_WP_Switch");
2177 if (status) {
2178 pr_err("%s: %s: Failed to request GPIO %d\n",
2179 mmc_hostname(mmc), __func__,
2180 host->plat->wpswitch_gpio);
2181 } else {
2182 status = gpio_direction_input(
2183 host->plat->wpswitch_gpio);
2184 if (!status) {
2185 /*
2186 * Wait for atleast 300ms as debounce
2187 * time for GPIO input to stabilize.
2188 */
2189 msleep(300);
2190 status = gpio_get_value_cansleep(
2191 host->plat->wpswitch_gpio);
2192 status ^= !host->plat->wpswitch_polarity;
2193 }
2194 gpio_free(host->plat->wpswitch_gpio);
2195 }
2196 }
2197
2198 if (status < 0)
2199 status = -ENOSYS;
2200 pr_debug("%s: Card read-only status %d\n", __func__, status);
2201
2202 return status;
2203}
2204
2205#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002206static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
2207{
2208 struct msmsdcc_host *host = mmc_priv(mmc);
2209 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002210
2211 if (enable) {
2212 spin_lock_irqsave(&host->lock, flags);
2213 host->mci_irqenable |= MCI_SDIOINTOPERMASK;
2214 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) |
2215 MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2216 spin_unlock_irqrestore(&host->lock, flags);
2217 } else {
2218 host->mci_irqenable &= ~MCI_SDIOINTOPERMASK;
2219 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) &
2220 ~MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2221 }
2222 mb();
2223}
2224#endif /* CONFIG_MMC_MSM_SDIO_SUPPORT */
2225
2226#ifdef CONFIG_PM_RUNTIME
2227static int msmsdcc_enable(struct mmc_host *mmc)
2228{
2229 int rc;
2230 struct device *dev = mmc->parent;
2231
2232 if (atomic_read(&dev->power.usage_count) > 0) {
2233 pm_runtime_get_noresume(dev);
2234 goto out;
2235 }
2236
2237 rc = pm_runtime_get_sync(dev);
2238
2239 if (rc < 0) {
2240 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2241 __func__, rc);
2242 return rc;
2243 }
2244out:
2245 return 0;
2246}
2247
2248static int msmsdcc_disable(struct mmc_host *mmc, int lazy)
2249{
2250 int rc;
2251
2252 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO)
2253 return -ENOTSUPP;
2254
2255 rc = pm_runtime_put_sync(mmc->parent);
2256
2257 if (rc < 0)
2258 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2259 __func__, rc);
2260 return rc;
2261}
2262#else
2263#define msmsdcc_enable NULL
2264#define msmsdcc_disable NULL
2265#endif
2266
2267static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
2268 struct mmc_ios *ios)
2269{
2270 struct msmsdcc_host *host = mmc_priv(mmc);
2271 unsigned long flags;
2272 int err = 0;
2273
2274 if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
2275 /* Change voltage level of VDDPX to high voltage */
2276 if (msmsdcc_tune_vdd_pad_level(host, 2950000)) {
2277 pr_err("%s: %s: failed to change vddp level to %d",
2278 mmc_hostname(mmc), __func__, 2950000);
2279 }
2280 goto out;
2281 } else if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
2282 /* invalid selection. don't do anything */
2283 goto out;
2284 }
San Mehat9d2bd732009-09-22 16:44:22 -07002285
2286 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002287 /*
2288 * If we are here means voltage switch from high voltage to
2289 * low voltage is required
2290 */
2291
2292 /*
2293 * Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
2294 * register until they become all zeros.
2295 */
2296 if (readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1)) {
2297 err = -EAGAIN;
2298 pr_err("%s: %s: MCIDATIN_3_0 is still not all zeros",
2299 mmc_hostname(mmc), __func__);
2300 goto out_unlock;
San Mehat9d2bd732009-09-22 16:44:22 -07002301 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002302
2303 /* Stop SD CLK output. */
2304 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2305 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2306
San Mehat9d2bd732009-09-22 16:44:22 -07002307 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002308
2309 /*
2310 * Switch VDDPX from high voltage to low voltage
2311 * to change the VDD of the SD IO pads.
2312 */
2313 if (msmsdcc_tune_vdd_pad_level(host, 1850000)) {
2314 pr_err("%s: %s: failed to change vddp level to %d",
2315 mmc_hostname(mmc), __func__, 1850000);
2316 goto out;
2317 }
2318
2319 spin_lock_irqsave(&host->lock, flags);
2320 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2321 IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
2322 host->io_pad_pwr_switch = 1;
2323 spin_unlock_irqrestore(&host->lock, flags);
2324
2325 /* Wait 5 ms for the voltage regulater in the card to become stable. */
2326 usleep_range(5000, 5500);
2327
2328 spin_lock_irqsave(&host->lock, flags);
2329 /* Start SD CLK output. */
2330 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2331 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2332 spin_unlock_irqrestore(&host->lock, flags);
2333
2334 /*
2335 * If MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT register
2336 * don't become all ones within 1 ms then a Voltage Switch
2337 * sequence has failed and a power cycle to the card is required.
2338 * Otherwise Voltage Switch sequence is completed successfully.
2339 */
2340 usleep_range(1000, 1500);
2341
2342 spin_lock_irqsave(&host->lock, flags);
2343 if ((readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1))
2344 != (0xF << 1)) {
2345 pr_err("%s: %s: MCIDATIN_3_0 are still not all ones",
2346 mmc_hostname(mmc), __func__);
2347 err = -EAGAIN;
2348 goto out_unlock;
2349 }
2350
2351out_unlock:
2352 spin_unlock_irqrestore(&host->lock, flags);
2353out:
2354 return err;
2355}
2356
2357static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2358 u8 phase);
2359/* Initialize the DLL (Programmable Delay Line ) */
2360static int msmsdcc_init_cm_sdc4_dll(struct msmsdcc_host *host)
2361{
2362 int rc = 0;
2363 u32 wait_timeout;
2364
2365 /* Write 0 to DLL_PDN bit of MCI_DLL_CONFIG register */
2366 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2367 & ~MCI_DLL_PDN), host->base + MCI_DLL_CONFIG);
2368
2369 /* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
2370 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2371 | MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2372
2373 msmsdcc_delay(host);
2374
2375 /* Write 0 to DLL_RST bit of MCI_DLL_CONFIG register */
2376 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2377 & ~MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2378
2379 /* Initialize the phase to 0 */
2380 rc = msmsdcc_config_cm_sdc4_dll_phase(host, 0);
2381 if (rc)
2382 goto out;
2383
2384 wait_timeout = 1000;
2385 /* Wait until DLL_LOCK bit of MCI_DLL_STATUS register becomes '1' */
2386 while (!(readl_relaxed(host->base + MCI_DLL_STATUS) & MCI_DLL_LOCK)) {
2387 /* max. wait for 1 sec for LOCK bit to be set */
2388 if (--wait_timeout == 0) {
2389 pr_err("%s: %s: DLL failed to lock at phase: %d",
2390 mmc_hostname(host->mmc), __func__, 0);
2391 rc = -1;
2392 goto out;
2393 }
2394 /* wait for 1ms */
2395 usleep_range(1000, 1500);
2396 }
2397out:
2398 return rc;
2399}
2400
2401/*
2402 * Enable a CDR circuit in CM_SDC4_DLL block to enable automatic
2403 * calibration sequence. This function should be called before
2404 * enabling AUTO_CMD19 bit in MCI_CMD register for block read
2405 * commands (CMD17/CMD18).
2406 */
2407static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host)
2408{
2409 /* Set CDR_EN bit to 1. */
2410 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG) |
2411 MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2412
2413 /* Set CDR_EXT_EN bit to 0. */
2414 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2415 & ~MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2416
2417 /* Set CK_OUT_EN bit to 0. */
2418 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2419 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2420
2421 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2422 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)
2423 ;
2424
2425 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2426 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2427 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2428
2429 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register is 1. */
2430 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN))
2431 ;
2432}
2433
2434static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2435 u8 phase)
2436{
2437 int rc = 0;
2438 u32 mclk_freq = 0;
2439 u32 wait_timeout;
2440
2441 /* Set CDR_EN bit to 0. */
2442 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2443 & ~MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2444
2445 /* Set CDR_EXT_EN bit to 1. */
2446 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2447 | MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2448
2449 /* Program the MCLK value to MCLK_FREQ bit field */
2450 if (host->clk_rate <= 112000000)
2451 mclk_freq = 0;
2452 else if (host->clk_rate <= 125000000)
2453 mclk_freq = 1;
2454 else if (host->clk_rate <= 137000000)
2455 mclk_freq = 2;
2456 else if (host->clk_rate <= 150000000)
2457 mclk_freq = 3;
2458 else if (host->clk_rate <= 162000000)
2459 mclk_freq = 4;
2460 else if (host->clk_rate <= 175000000)
2461 mclk_freq = 5;
2462 else if (host->clk_rate <= 187000000)
2463 mclk_freq = 6;
2464 else if (host->clk_rate <= 200000000)
2465 mclk_freq = 7;
2466
2467 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2468 & ~(7 << 24)) | (mclk_freq << 24)),
2469 host->base + MCI_DLL_CONFIG);
2470
2471 /* Set CK_OUT_EN bit to 0. */
2472 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2473 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2474
2475 /* Set DLL_EN bit to 1. */
2476 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2477 | MCI_DLL_EN), host->base + MCI_DLL_CONFIG);
2478
2479 wait_timeout = 1000;
2480 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2481 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN) {
2482 /* max. wait for 1 sec for LOCK bit for be set */
2483 if (--wait_timeout == 0) {
2484 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 0",
2485 mmc_hostname(host->mmc), __func__, phase);
2486 rc = -1;
2487 goto out;
2488 }
2489 /* wait for 1ms */
2490 usleep_range(1000, 1500);
2491 }
2492
2493 /*
2494 * Write the selected DLL clock output phase (0 ... 15)
2495 * to CDR_SELEXT bit field of MCI_DLL_CONFIG register.
2496 */
2497 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2498 & ~(0xF << 20)) | (phase << 20)),
2499 host->base + MCI_DLL_CONFIG);
2500
2501 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2502 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2503 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2504
2505 wait_timeout = 1000;
2506 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '1' */
2507 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)) {
2508 /* max. wait for 1 sec for LOCK bit for be set */
2509 if (--wait_timeout == 0) {
2510 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 1",
2511 mmc_hostname(host->mmc), __func__, phase);
2512 rc = -1;
2513 goto out;
2514 }
2515 /* wait for 1ms */
2516 usleep_range(1000, 1500);
2517 }
2518out:
2519 return rc;
2520}
2521
2522static int msmsdcc_execute_tuning(struct mmc_host *mmc)
2523{
2524 struct msmsdcc_host *host = mmc_priv(mmc);
2525 u8 phase;
2526 u8 *data_buf;
2527 u8 tuned_phases[16], tuned_phase_cnt = 0;
2528 int rc = 0;
2529
2530 /* Tuning is only required for SDR50 & SDR104 modes */
2531 if (!host->tuning_needed) {
2532 rc = 0;
2533 goto out;
2534 }
2535
2536 host->cmd19_tuning_in_progress = 1;
2537 /*
2538 * Make sure that clock is always enabled when DLL
2539 * tuning is in progress. Keeping PWRSAVE ON may
2540 * turn off the clock. So let's disable the PWRSAVE
2541 * here and re-enable it once tuning is completed.
2542 */
2543 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2544 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2545 /* first of all reset the tuning block */
2546 rc = msmsdcc_init_cm_sdc4_dll(host);
2547 if (rc)
2548 goto out;
2549
2550 data_buf = kmalloc(64, GFP_KERNEL);
2551 if (!data_buf) {
2552 rc = -ENOMEM;
2553 goto out;
2554 }
2555
2556 phase = 0;
2557 do {
2558 struct mmc_command cmd = {0};
2559 struct mmc_data data = {0};
2560 struct mmc_request mrq = {
2561 .cmd = &cmd,
2562 .data = &data
2563 };
2564 struct scatterlist sg;
2565
2566 /* set the phase in delay line hw block */
2567 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2568 if (rc)
2569 goto kfree;
2570
2571 cmd.opcode = MMC_SEND_TUNING_BLOCK;
2572 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
2573
2574 data.blksz = 64;
2575 data.blocks = 1;
2576 data.flags = MMC_DATA_READ;
2577 data.timeout_ns = 1000 * 1000 * 1000; /* 1 sec */
2578
2579 data.sg = &sg;
2580 data.sg_len = 1;
2581 sg_init_one(&sg, data_buf, 64);
2582 memset(data_buf, 0, 64);
2583 mmc_wait_for_req(mmc, &mrq);
2584
2585 if (!cmd.error && !data.error &&
2586 !memcmp(data_buf, cmd19_tuning_block, 64)) {
2587 /* tuning is successful with this tuning point */
2588 tuned_phases[tuned_phase_cnt++] = phase;
2589 }
2590 } while (++phase < 16);
2591
2592 kfree(data_buf);
2593
2594 if (tuned_phase_cnt) {
2595 tuned_phase_cnt--;
2596 tuned_phase_cnt = (tuned_phase_cnt * 3) / 4;
2597 phase = tuned_phases[tuned_phase_cnt];
2598 /*
2599 * Finally set the selected phase in delay
2600 * line hw block.
2601 */
2602 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2603 if (rc)
2604 goto out;
2605 } else {
2606 /* tuning failed */
2607 rc = -EAGAIN;
2608 pr_err("%s: %s: no tuning point found",
2609 mmc_hostname(mmc), __func__);
2610 }
2611 goto out;
2612
2613kfree:
2614 kfree(data_buf);
2615out:
2616 /* re-enable PWESAVE */
2617 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2618 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2619 host->cmd19_tuning_in_progress = 0;
2620 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -07002621}
2622
2623static const struct mmc_host_ops msmsdcc_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002624 .enable = msmsdcc_enable,
2625 .disable = msmsdcc_disable,
San Mehat9d2bd732009-09-22 16:44:22 -07002626 .request = msmsdcc_request,
2627 .set_ios = msmsdcc_set_ios,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002628 .get_ro = msmsdcc_get_ro,
2629#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002630 .enable_sdio_irq = msmsdcc_enable_sdio_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002631#endif
2632 .start_signal_voltage_switch = msmsdcc_start_signal_voltage_switch,
2633 .execute_tuning = msmsdcc_execute_tuning
San Mehat9d2bd732009-09-22 16:44:22 -07002634};
2635
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002636static unsigned int
2637msmsdcc_slot_status(struct msmsdcc_host *host)
2638{
2639 int status;
2640 unsigned int gpio_no = host->plat->status_gpio;
2641
2642 status = gpio_request(gpio_no, "SD_HW_Detect");
2643 if (status) {
2644 pr_err("%s: %s: Failed to request GPIO %d\n",
2645 mmc_hostname(host->mmc), __func__, gpio_no);
2646 } else {
2647 status = gpio_direction_input(gpio_no);
2648 if (!status)
2649 status = !gpio_get_value_cansleep(gpio_no);
2650 gpio_free(gpio_no);
2651 }
2652 return status;
2653}
2654
San Mehat9d2bd732009-09-22 16:44:22 -07002655static void
2656msmsdcc_check_status(unsigned long data)
2657{
2658 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
2659 unsigned int status;
2660
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002661 if (host->plat->status || host->plat->status_gpio) {
2662 if (host->plat->status)
2663 status = host->plat->status(mmc_dev(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07002664 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002665 status = msmsdcc_slot_status(host);
2666
2667 host->eject = !status;
2668 if (status ^ host->oldstat) {
2669 pr_info("%s: Slot status change detected (%d -> %d)\n",
2670 mmc_hostname(host->mmc), host->oldstat, status);
San Mehat9d2bd732009-09-22 16:44:22 -07002671 mmc_detect_change(host->mmc, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002672 }
2673 host->oldstat = status;
2674 } else {
2675 mmc_detect_change(host->mmc, 0);
San Mehat9d2bd732009-09-22 16:44:22 -07002676 }
San Mehat9d2bd732009-09-22 16:44:22 -07002677}
2678
2679static irqreturn_t
2680msmsdcc_platform_status_irq(int irq, void *dev_id)
2681{
2682 struct msmsdcc_host *host = dev_id;
2683
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002684 pr_debug("%s: %d\n", __func__, irq);
San Mehat9d2bd732009-09-22 16:44:22 -07002685 msmsdcc_check_status((unsigned long) host);
2686 return IRQ_HANDLED;
2687}
2688
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002689static irqreturn_t
2690msmsdcc_platform_sdiowakeup_irq(int irq, void *dev_id)
2691{
2692 struct msmsdcc_host *host = dev_id;
2693
2694 pr_debug("%s: SDIO Wake up IRQ : %d\n", mmc_hostname(host->mmc), irq);
2695 spin_lock(&host->lock);
2696 if (!host->sdio_irq_disabled) {
2697 disable_irq_nosync(irq);
2698 if (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2699 wake_lock(&host->sdio_wlock);
2700 msmsdcc_disable_irq_wake(host);
2701 }
2702 host->sdio_irq_disabled = 1;
2703 }
2704 if (host->plat->is_sdio_al_client) {
2705 if (!host->clks_on) {
2706 msmsdcc_setup_clocks(host, true);
2707 host->clks_on = 1;
2708 }
2709 if (host->sdcc_irq_disabled) {
2710 writel_relaxed(host->mci_irqenable,
2711 host->base + MMCIMASK0);
2712 mb();
2713 enable_irq(host->core_irqres->start);
2714 host->sdcc_irq_disabled = 0;
2715 }
2716 wake_lock(&host->sdio_wlock);
2717 }
2718 spin_unlock(&host->lock);
2719
2720 return IRQ_HANDLED;
2721}
2722
San Mehat9d2bd732009-09-22 16:44:22 -07002723static void
2724msmsdcc_status_notify_cb(int card_present, void *dev_id)
2725{
2726 struct msmsdcc_host *host = dev_id;
2727
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002728 pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
San Mehat9d2bd732009-09-22 16:44:22 -07002729 card_present);
2730 msmsdcc_check_status((unsigned long) host);
2731}
2732
San Mehat9d2bd732009-09-22 16:44:22 -07002733static int
2734msmsdcc_init_dma(struct msmsdcc_host *host)
2735{
2736 memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data));
2737 host->dma.host = host;
2738 host->dma.channel = -1;
2739
2740 if (!host->dmares)
2741 return -ENODEV;
2742
2743 host->dma.nc = dma_alloc_coherent(NULL,
2744 sizeof(struct msmsdcc_nc_dmadata),
2745 &host->dma.nc_busaddr,
2746 GFP_KERNEL);
2747 if (host->dma.nc == NULL) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07002748 pr_err("Unable to allocate DMA buffer\n");
San Mehat9d2bd732009-09-22 16:44:22 -07002749 return -ENOMEM;
2750 }
2751 memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata));
2752 host->dma.cmd_busaddr = host->dma.nc_busaddr;
2753 host->dma.cmdptr_busaddr = host->dma.nc_busaddr +
2754 offsetof(struct msmsdcc_nc_dmadata, cmdptr);
2755 host->dma.channel = host->dmares->start;
2756
2757 return 0;
2758}
2759
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002760#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
2761/**
2762 * Allocate and Connect a SDCC peripheral's SPS endpoint
2763 *
2764 * This function allocates endpoint context and
2765 * connect it with memory endpoint by calling
2766 * appropriate SPS driver APIs.
2767 *
2768 * Also registers a SPS callback function with
2769 * SPS driver
2770 *
2771 * This function should only be called once typically
2772 * during driver probe.
2773 *
2774 * @host - Pointer to sdcc host structure
2775 * @ep - Pointer to sps endpoint data structure
2776 * @is_produce - 1 means Producer endpoint
2777 * 0 means Consumer endpoint
2778 *
2779 * @return - 0 if successful else negative value.
2780 *
2781 */
2782static int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
2783 struct msmsdcc_sps_ep_conn_data *ep,
2784 bool is_producer)
2785{
2786 int rc = 0;
2787 struct sps_pipe *sps_pipe_handle;
2788 struct sps_connect *sps_config = &ep->config;
2789 struct sps_register_event *sps_event = &ep->event;
2790
2791 /* Allocate endpoint context */
2792 sps_pipe_handle = sps_alloc_endpoint();
2793 if (!sps_pipe_handle) {
2794 pr_err("%s: sps_alloc_endpoint() failed!!! is_producer=%d",
2795 mmc_hostname(host->mmc), is_producer);
2796 rc = -ENOMEM;
2797 goto out;
2798 }
2799
2800 /* Get default connection configuration for an endpoint */
2801 rc = sps_get_config(sps_pipe_handle, sps_config);
2802 if (rc) {
2803 pr_err("%s: sps_get_config() failed!!! pipe_handle=0x%x,"
2804 " rc=%d", mmc_hostname(host->mmc),
2805 (u32)sps_pipe_handle, rc);
2806 goto get_config_err;
2807 }
2808
2809 /* Modify the default connection configuration */
2810 if (is_producer) {
2811 /*
2812 * For SDCC producer transfer, source should be
2813 * SDCC peripheral where as destination should
2814 * be system memory.
2815 */
2816 sps_config->source = host->sps.bam_handle;
2817 sps_config->destination = SPS_DEV_HANDLE_MEM;
2818 /* Producer pipe will handle this connection */
2819 sps_config->mode = SPS_MODE_SRC;
2820 sps_config->options =
2821 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2822 } else {
2823 /*
2824 * For SDCC consumer transfer, source should be
2825 * system memory where as destination should
2826 * SDCC peripheral
2827 */
2828 sps_config->source = SPS_DEV_HANDLE_MEM;
2829 sps_config->destination = host->sps.bam_handle;
2830 sps_config->mode = SPS_MODE_DEST;
2831 sps_config->options =
2832 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2833 }
2834
2835 /* Producer pipe index */
2836 sps_config->src_pipe_index = host->sps.src_pipe_index;
2837 /* Consumer pipe index */
2838 sps_config->dest_pipe_index = host->sps.dest_pipe_index;
2839 /*
2840 * This event thresold value is only significant for BAM-to-BAM
2841 * transfer. It's ignored for BAM-to-System mode transfer.
2842 */
2843 sps_config->event_thresh = 0x10;
2844 /*
2845 * Max. no of scatter/gather buffers that can
2846 * be passed by block layer = 32 (NR_SG).
2847 * Each BAM descritor needs 64 bits (8 bytes).
2848 * One BAM descriptor is required per buffer transfer.
2849 * So we would require total 256 (32 * 8) bytes of descriptor FIFO.
2850 * But due to HW limitation we need to allocate atleast one extra
2851 * descriptor memory (256 bytes + 8 bytes). But in order to be
2852 * in power of 2, we are allocating 512 bytes of memory.
2853 */
2854 sps_config->desc.size = 512;
2855 sps_config->desc.base = dma_alloc_coherent(mmc_dev(host->mmc),
2856 sps_config->desc.size,
2857 &sps_config->desc.phys_base,
2858 GFP_KERNEL);
2859
2860 memset(sps_config->desc.base, 0x00, sps_config->desc.size);
2861
2862 /* Establish connection between peripheral and memory endpoint */
2863 rc = sps_connect(sps_pipe_handle, sps_config);
2864 if (rc) {
2865 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2866 " rc=%d", mmc_hostname(host->mmc),
2867 (u32)sps_pipe_handle, rc);
2868 goto sps_connect_err;
2869 }
2870
2871 sps_event->mode = SPS_TRIGGER_CALLBACK;
2872 sps_event->options = SPS_O_EOT;
2873 sps_event->callback = msmsdcc_sps_complete_cb;
2874 sps_event->xfer_done = NULL;
2875 sps_event->user = (void *)host;
2876
2877 /* Register callback event for EOT (End of transfer) event. */
2878 rc = sps_register_event(sps_pipe_handle, sps_event);
2879 if (rc) {
2880 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2881 " rc=%d", mmc_hostname(host->mmc),
2882 (u32)sps_pipe_handle, rc);
2883 goto reg_event_err;
2884 }
2885 /* Now save the sps pipe handle */
2886 ep->pipe_handle = sps_pipe_handle;
2887 pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"
2888 " desc_fifo.phys_base=0x%x\n", mmc_hostname(host->mmc),
2889 __func__, is_producer ? "READ" : "WRITE",
2890 (u32)sps_pipe_handle, sps_config->desc.phys_base);
2891 goto out;
2892
2893reg_event_err:
2894 sps_disconnect(sps_pipe_handle);
2895sps_connect_err:
2896 dma_free_coherent(mmc_dev(host->mmc),
2897 sps_config->desc.size,
2898 sps_config->desc.base,
2899 sps_config->desc.phys_base);
2900get_config_err:
2901 sps_free_endpoint(sps_pipe_handle);
2902out:
2903 return rc;
2904}
2905
2906/**
2907 * Disconnect and Deallocate a SDCC peripheral's SPS endpoint
2908 *
2909 * This function disconnect endpoint and deallocates
2910 * endpoint context.
2911 *
2912 * This function should only be called once typically
2913 * during driver remove.
2914 *
2915 * @host - Pointer to sdcc host structure
2916 * @ep - Pointer to sps endpoint data structure
2917 *
2918 */
2919static void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
2920 struct msmsdcc_sps_ep_conn_data *ep)
2921{
2922 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2923 struct sps_connect *sps_config = &ep->config;
2924 struct sps_register_event *sps_event = &ep->event;
2925
2926 sps_event->xfer_done = NULL;
2927 sps_event->callback = NULL;
2928 sps_register_event(sps_pipe_handle, sps_event);
2929 sps_disconnect(sps_pipe_handle);
2930 dma_free_coherent(mmc_dev(host->mmc),
2931 sps_config->desc.size,
2932 sps_config->desc.base,
2933 sps_config->desc.phys_base);
2934 sps_free_endpoint(sps_pipe_handle);
2935}
2936
2937/**
2938 * Reset SDCC peripheral's SPS endpoint
2939 *
2940 * This function disconnects an endpoint.
2941 *
2942 * This function should be called for reseting
2943 * SPS endpoint when data transfer error is
2944 * encountered during data transfer. This
2945 * can be considered as soft reset to endpoint.
2946 *
2947 * This function should only be called if
2948 * msmsdcc_sps_init() is already called.
2949 *
2950 * @host - Pointer to sdcc host structure
2951 * @ep - Pointer to sps endpoint data structure
2952 *
2953 * @return - 0 if successful else negative value.
2954 */
2955static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
2956 struct msmsdcc_sps_ep_conn_data *ep)
2957{
2958 int rc = 0;
2959 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2960
2961 rc = sps_disconnect(sps_pipe_handle);
2962 if (rc) {
2963 pr_err("%s: %s: sps_disconnect() failed!!! pipe_handle=0x%x,"
2964 " rc=%d", mmc_hostname(host->mmc), __func__,
2965 (u32)sps_pipe_handle, rc);
2966 goto out;
2967 }
2968 out:
2969 return rc;
2970}
2971
2972/**
2973 * Restore SDCC peripheral's SPS endpoint
2974 *
2975 * This function connects an endpoint.
2976 *
2977 * This function should be called for restoring
2978 * SPS endpoint after data transfer error is
2979 * encountered during data transfer. This
2980 * can be considered as soft reset to endpoint.
2981 *
2982 * This function should only be called if
2983 * msmsdcc_sps_reset_ep() is called before.
2984 *
2985 * @host - Pointer to sdcc host structure
2986 * @ep - Pointer to sps endpoint data structure
2987 *
2988 * @return - 0 if successful else negative value.
2989 */
2990static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
2991 struct msmsdcc_sps_ep_conn_data *ep)
2992{
2993 int rc = 0;
2994 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2995 struct sps_connect *sps_config = &ep->config;
2996 struct sps_register_event *sps_event = &ep->event;
2997
2998 /* Establish connection between peripheral and memory endpoint */
2999 rc = sps_connect(sps_pipe_handle, sps_config);
3000 if (rc) {
3001 pr_err("%s: %s: sps_connect() failed!!! pipe_handle=0x%x,"
3002 " rc=%d", mmc_hostname(host->mmc), __func__,
3003 (u32)sps_pipe_handle, rc);
3004 goto out;
3005 }
3006
3007 /* Register callback event for EOT (End of transfer) event. */
3008 rc = sps_register_event(sps_pipe_handle, sps_event);
3009 if (rc) {
3010 pr_err("%s: %s: sps_register_event() failed!!!"
3011 " pipe_handle=0x%x, rc=%d",
3012 mmc_hostname(host->mmc), __func__,
3013 (u32)sps_pipe_handle, rc);
3014 goto reg_event_err;
3015 }
3016 goto out;
3017
3018reg_event_err:
3019 sps_disconnect(sps_pipe_handle);
3020out:
3021 return rc;
3022}
3023
3024/**
3025 * Initialize SPS HW connected with SDCC core
3026 *
3027 * This function register BAM HW resources with
3028 * SPS driver and then initialize 2 SPS endpoints
3029 *
3030 * This function should only be called once typically
3031 * during driver probe.
3032 *
3033 * @host - Pointer to sdcc host structure
3034 *
3035 * @return - 0 if successful else negative value.
3036 *
3037 */
3038static int msmsdcc_sps_init(struct msmsdcc_host *host)
3039{
3040 int rc = 0;
3041 struct sps_bam_props bam = {0};
3042
3043 host->bam_base = ioremap(host->bam_memres->start,
3044 resource_size(host->bam_memres));
3045 if (!host->bam_base) {
3046 pr_err("%s: BAM ioremap() failed!!! phys_addr=0x%x,"
3047 " size=0x%x", mmc_hostname(host->mmc),
3048 host->bam_memres->start,
3049 (host->bam_memres->end -
3050 host->bam_memres->start));
3051 rc = -ENOMEM;
3052 goto out;
3053 }
3054
3055 bam.phys_addr = host->bam_memres->start;
3056 bam.virt_addr = host->bam_base;
3057 /*
3058 * This event thresold value is only significant for BAM-to-BAM
3059 * transfer. It's ignored for BAM-to-System mode transfer.
3060 */
3061 bam.event_threshold = 0x10; /* Pipe event threshold */
3062 /*
3063 * This threshold controls when the BAM publish
3064 * the descriptor size on the sideband interface.
3065 * SPS HW will only be used when
3066 * data transfer size > MCI_FIFOSIZE (64 bytes).
3067 * PIO mode will be used when
3068 * data transfer size < MCI_FIFOSIZE (64 bytes).
3069 * So set this thresold value to 64 bytes.
3070 */
3071 bam.summing_threshold = 64;
3072 /* SPS driver wll handle the SDCC BAM IRQ */
3073 bam.irq = (u32)host->bam_irqres->start;
3074 bam.manage = SPS_BAM_MGR_LOCAL;
3075
3076 pr_info("%s: bam physical base=0x%x\n", mmc_hostname(host->mmc),
3077 (u32)bam.phys_addr);
3078 pr_info("%s: bam virtual base=0x%x\n", mmc_hostname(host->mmc),
3079 (u32)bam.virt_addr);
3080
3081 /* Register SDCC Peripheral BAM device to SPS driver */
3082 rc = sps_register_bam_device(&bam, &host->sps.bam_handle);
3083 if (rc) {
3084 pr_err("%s: sps_register_bam_device() failed!!! err=%d",
3085 mmc_hostname(host->mmc), rc);
3086 goto reg_bam_err;
3087 }
3088 pr_info("%s: BAM device registered. bam_handle=0x%x",
3089 mmc_hostname(host->mmc), host->sps.bam_handle);
3090
3091 host->sps.src_pipe_index = SPS_SDCC_PRODUCER_PIPE_INDEX;
3092 host->sps.dest_pipe_index = SPS_SDCC_CONSUMER_PIPE_INDEX;
3093
3094 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.prod,
3095 SPS_PROD_PERIPHERAL);
3096 if (rc)
3097 goto sps_reset_err;
3098 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.cons,
3099 SPS_CONS_PERIPHERAL);
3100 if (rc)
3101 goto cons_conn_err;
3102
3103 pr_info("%s: Qualcomm MSM SDCC-BAM at 0x%016llx irq %d\n",
3104 mmc_hostname(host->mmc),
3105 (unsigned long long)host->bam_memres->start,
3106 (unsigned int)host->bam_irqres->start);
3107 goto out;
3108
3109cons_conn_err:
3110 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3111sps_reset_err:
3112 sps_deregister_bam_device(host->sps.bam_handle);
3113reg_bam_err:
3114 iounmap(host->bam_base);
3115out:
3116 return rc;
3117}
3118
3119/**
3120 * De-initialize SPS HW connected with SDCC core
3121 *
3122 * This function deinitialize SPS endpoints and then
3123 * deregisters BAM resources from SPS driver.
3124 *
3125 * This function should only be called once typically
3126 * during driver remove.
3127 *
3128 * @host - Pointer to sdcc host structure
3129 *
3130 */
3131static void msmsdcc_sps_exit(struct msmsdcc_host *host)
3132{
3133 msmsdcc_sps_exit_ep_conn(host, &host->sps.cons);
3134 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3135 sps_deregister_bam_device(host->sps.bam_handle);
3136 iounmap(host->bam_base);
3137}
3138#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
3139
3140static ssize_t
3141show_polling(struct device *dev, struct device_attribute *attr, char *buf)
3142{
3143 struct mmc_host *mmc = dev_get_drvdata(dev);
3144 struct msmsdcc_host *host = mmc_priv(mmc);
3145 int poll;
3146 unsigned long flags;
3147
3148 spin_lock_irqsave(&host->lock, flags);
3149 poll = !!(mmc->caps & MMC_CAP_NEEDS_POLL);
3150 spin_unlock_irqrestore(&host->lock, flags);
3151
3152 return snprintf(buf, PAGE_SIZE, "%d\n", poll);
3153}
3154
3155static ssize_t
3156set_polling(struct device *dev, struct device_attribute *attr,
3157 const char *buf, size_t count)
3158{
3159 struct mmc_host *mmc = dev_get_drvdata(dev);
3160 struct msmsdcc_host *host = mmc_priv(mmc);
3161 int value;
3162 unsigned long flags;
3163
3164 sscanf(buf, "%d", &value);
3165
3166 spin_lock_irqsave(&host->lock, flags);
3167 if (value) {
3168 mmc->caps |= MMC_CAP_NEEDS_POLL;
3169 mmc_detect_change(host->mmc, 0);
3170 } else {
3171 mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3172 }
3173#ifdef CONFIG_HAS_EARLYSUSPEND
3174 host->polling_enabled = mmc->caps & MMC_CAP_NEEDS_POLL;
3175#endif
3176 spin_unlock_irqrestore(&host->lock, flags);
3177 return count;
3178}
3179
3180static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR,
3181 show_polling, set_polling);
3182static struct attribute *dev_attrs[] = {
3183 &dev_attr_polling.attr,
3184 NULL,
3185};
3186static struct attribute_group dev_attr_grp = {
3187 .attrs = dev_attrs,
3188};
3189
3190#ifdef CONFIG_HAS_EARLYSUSPEND
3191static void msmsdcc_early_suspend(struct early_suspend *h)
3192{
3193 struct msmsdcc_host *host =
3194 container_of(h, struct msmsdcc_host, early_suspend);
3195 unsigned long flags;
3196
3197 spin_lock_irqsave(&host->lock, flags);
3198 host->polling_enabled = host->mmc->caps & MMC_CAP_NEEDS_POLL;
3199 host->mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3200 spin_unlock_irqrestore(&host->lock, flags);
3201};
3202static void msmsdcc_late_resume(struct early_suspend *h)
3203{
3204 struct msmsdcc_host *host =
3205 container_of(h, struct msmsdcc_host, early_suspend);
3206 unsigned long flags;
3207
3208 if (host->polling_enabled) {
3209 spin_lock_irqsave(&host->lock, flags);
3210 host->mmc->caps |= MMC_CAP_NEEDS_POLL;
3211 mmc_detect_change(host->mmc, 0);
3212 spin_unlock_irqrestore(&host->lock, flags);
3213 }
3214};
3215#endif
3216
3217static void msmsdcc_req_tout_timer_hdlr(unsigned long data)
3218{
3219 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
3220 struct mmc_request *mrq;
3221 unsigned long flags;
3222
3223 spin_lock_irqsave(&host->lock, flags);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003224 if (host->dummy_52_sent) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003225 pr_info("%s: %s: dummy CMD52 timeout\n",
3226 mmc_hostname(host->mmc), __func__);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003227 host->dummy_52_sent = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003228 }
3229
3230 mrq = host->curr.mrq;
3231
3232 if (mrq && mrq->cmd) {
3233 pr_info("%s: %s CMD%d\n", mmc_hostname(host->mmc),
3234 __func__, mrq->cmd->opcode);
3235 if (!mrq->cmd->error)
3236 mrq->cmd->error = -ETIMEDOUT;
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003237 if (host->dummy_52_needed)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003238 host->dummy_52_needed = 0;
3239 if (host->curr.data) {
3240 pr_info("%s: %s Request timeout\n",
3241 mmc_hostname(host->mmc), __func__);
3242 if (mrq->data && !mrq->data->error)
3243 mrq->data->error = -ETIMEDOUT;
3244 host->curr.data_xfered = 0;
3245 if (host->dma.sg && host->is_dma_mode) {
3246 msm_dmov_stop_cmd(host->dma.channel,
3247 &host->dma.hdr, 0);
3248 } else if (host->sps.sg && host->is_sps_mode) {
3249 /* Stop current SPS transfer */
3250 msmsdcc_sps_exit_curr_xfer(host);
3251 } else {
3252 msmsdcc_reset_and_restore(host);
3253 msmsdcc_stop_data(host);
3254 if (mrq->data && mrq->data->stop)
3255 msmsdcc_start_command(host,
3256 mrq->data->stop, 0);
3257 else
3258 msmsdcc_request_end(host, mrq);
3259 }
3260 } else {
3261 if (host->prog_enable) {
3262 host->prog_scan = 0;
3263 host->prog_enable = 0;
3264 }
3265 msmsdcc_reset_and_restore(host);
3266 msmsdcc_request_end(host, mrq);
3267 }
3268 }
3269 spin_unlock_irqrestore(&host->lock, flags);
3270}
3271
San Mehat9d2bd732009-09-22 16:44:22 -07003272static int
3273msmsdcc_probe(struct platform_device *pdev)
3274{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003275 struct mmc_platform_data *plat = pdev->dev.platform_data;
San Mehat9d2bd732009-09-22 16:44:22 -07003276 struct msmsdcc_host *host;
3277 struct mmc_host *mmc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003278 unsigned long flags;
3279 struct resource *core_irqres = NULL;
3280 struct resource *bam_irqres = NULL;
3281 struct resource *core_memres = NULL;
3282 struct resource *dml_memres = NULL;
3283 struct resource *bam_memres = NULL;
San Mehat9d2bd732009-09-22 16:44:22 -07003284 struct resource *dmares = NULL;
3285 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003286 int i;
San Mehat9d2bd732009-09-22 16:44:22 -07003287
3288 /* must have platform data */
3289 if (!plat) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003290 pr_err("%s: Platform data not available\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003291 ret = -EINVAL;
3292 goto out;
3293 }
3294
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003295 if (pdev->id < 1 || pdev->id > 5)
San Mehat9d2bd732009-09-22 16:44:22 -07003296 return -EINVAL;
3297
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003298 if (plat->is_sdio_al_client)
3299 if (!plat->sdio_lpm_gpio_setup || !plat->sdiowakeup_irq)
3300 return -EINVAL;
3301
San Mehat9d2bd732009-09-22 16:44:22 -07003302 if (pdev->resource == NULL || pdev->num_resources < 2) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003303 pr_err("%s: Invalid resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003304 return -ENXIO;
3305 }
3306
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003307 for (i = 0; i < pdev->num_resources; i++) {
3308 if (pdev->resource[i].flags & IORESOURCE_MEM) {
3309 if (!strcmp(pdev->resource[i].name,
3310 "sdcc_dml_addr"))
3311 dml_memres = &pdev->resource[i];
3312 else if (!strcmp(pdev->resource[i].name,
3313 "sdcc_bam_addr"))
3314 bam_memres = &pdev->resource[i];
3315 else
3316 core_memres = &pdev->resource[i];
San Mehat9d2bd732009-09-22 16:44:22 -07003317
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003318 }
3319 if (pdev->resource[i].flags & IORESOURCE_IRQ) {
3320 if (!strcmp(pdev->resource[i].name,
3321 "sdcc_bam_irq"))
3322 bam_irqres = &pdev->resource[i];
3323 else
3324 core_irqres = &pdev->resource[i];
3325 }
3326 if (pdev->resource[i].flags & IORESOURCE_DMA)
3327 dmares = &pdev->resource[i];
3328 }
3329
3330 if (!core_irqres || !core_memres) {
3331 pr_err("%s: Invalid sdcc core resource\n", __func__);
3332 return -ENXIO;
3333 }
3334
3335 /*
3336 * Both BAM and DML memory resource should be preset.
3337 * BAM IRQ resource should also be present.
3338 */
3339 if ((bam_memres && !dml_memres) ||
3340 (!bam_memres && dml_memres) ||
3341 ((bam_memres && dml_memres) && !bam_irqres)) {
3342 pr_err("%s: Invalid sdcc BAM/DML resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003343 return -ENXIO;
3344 }
3345
3346 /*
3347 * Setup our host structure
3348 */
San Mehat9d2bd732009-09-22 16:44:22 -07003349 mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev);
3350 if (!mmc) {
3351 ret = -ENOMEM;
3352 goto out;
3353 }
3354
3355 host = mmc_priv(mmc);
3356 host->pdev_id = pdev->id;
3357 host->plat = plat;
3358 host->mmc = mmc;
San Mehat56a8b5b2009-11-21 12:29:46 -08003359 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003360 if (bam_memres && dml_memres && bam_irqres)
3361 host->is_sps_mode = 1;
3362 else if (dmares)
3363 host->is_dma_mode = 1;
San Mehat9d2bd732009-09-22 16:44:22 -07003364
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003365 host->base = ioremap(core_memres->start,
3366 resource_size(core_memres));
San Mehat9d2bd732009-09-22 16:44:22 -07003367 if (!host->base) {
3368 ret = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003369 goto host_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003370 }
3371
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003372 host->core_irqres = core_irqres;
3373 host->bam_irqres = bam_irqres;
3374 host->core_memres = core_memres;
3375 host->dml_memres = dml_memres;
3376 host->bam_memres = bam_memres;
San Mehat9d2bd732009-09-22 16:44:22 -07003377 host->dmares = dmares;
3378 spin_lock_init(&host->lock);
3379
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003380#ifdef CONFIG_MMC_EMBEDDED_SDIO
3381 if (plat->embedded_sdio)
3382 mmc_set_embedded_sdio_data(mmc,
3383 &plat->embedded_sdio->cis,
3384 &plat->embedded_sdio->cccr,
3385 plat->embedded_sdio->funcs,
3386 plat->embedded_sdio->num_funcs);
3387#endif
3388
Sahitya Tummala62612cf2010-12-08 15:03:03 +05303389 tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
3390 (unsigned long)host);
3391
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003392 tasklet_init(&host->sps.tlet, msmsdcc_sps_complete_tlet,
3393 (unsigned long)host);
3394 if (host->is_dma_mode) {
3395 /* Setup DMA */
3396 ret = msmsdcc_init_dma(host);
3397 if (ret)
3398 goto ioremap_free;
3399 } else {
3400 host->dma.channel = -1;
San Mehat9d2bd732009-09-22 16:44:22 -07003401 }
3402
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003403 /*
3404 * Setup SDCC clock if derived from Dayatona
3405 * fabric core clock.
3406 */
3407 if (plat->pclk_src_dfab) {
3408 host->dfab_pclk = clk_get(&pdev->dev, "dfab_sdc_clk");
3409 if (!IS_ERR(host->dfab_pclk)) {
3410 /* Set the clock rate to 64MHz for max. performance */
3411 ret = clk_set_rate(host->dfab_pclk, 64000000);
3412 if (ret)
3413 goto dfab_pclk_put;
3414 ret = clk_enable(host->dfab_pclk);
3415 if (ret)
3416 goto dfab_pclk_put;
3417 } else
3418 goto dma_free;
3419 }
3420
3421 /*
3422 * Setup main peripheral bus clock
3423 */
3424 host->pclk = clk_get(&pdev->dev, "sdc_pclk");
3425 if (!IS_ERR(host->pclk)) {
3426 ret = clk_enable(host->pclk);
3427 if (ret)
3428 goto pclk_put;
3429
3430 host->pclk_rate = clk_get_rate(host->pclk);
3431 }
3432
3433 /*
3434 * Setup SDC MMC clock
3435 */
San Mehat9d2bd732009-09-22 16:44:22 -07003436 host->clk = clk_get(&pdev->dev, "sdc_clk");
3437 if (IS_ERR(host->clk)) {
3438 ret = PTR_ERR(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003439 goto pclk_disable;
San Mehat9d2bd732009-09-22 16:44:22 -07003440 }
3441
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003442 ret = clk_set_rate(host->clk, msmsdcc_get_min_sup_clk_rate(host));
3443 if (ret) {
3444 pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
3445 goto clk_put;
3446 }
3447
3448 ret = clk_enable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003449 if (ret)
3450 goto clk_put;
3451
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003452 host->clk_rate = clk_get_rate(host->clk);
3453
3454 host->clks_on = 1;
3455
3456 ret = msmsdcc_vreg_init(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07003457 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003458 pr_err("%s: msmsdcc_vreg_init() failed (%d)\n", __func__, ret);
San Mehat9d2bd732009-09-22 16:44:22 -07003459 goto clk_disable;
3460 }
3461
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003462
3463 /* Clocks has to be running before accessing SPS/DML HW blocks */
3464 if (host->is_sps_mode) {
3465 /* Initialize SPS */
3466 ret = msmsdcc_sps_init(host);
3467 if (ret)
3468 goto vreg_deinit;
3469 /* Initialize DML */
3470 ret = msmsdcc_dml_init(host);
3471 if (ret)
3472 goto sps_exit;
3473 }
San Mehat9d2bd732009-09-22 16:44:22 -07003474
San Mehat9d2bd732009-09-22 16:44:22 -07003475 /*
3476 * Setup MMC host structure
3477 */
3478 mmc->ops = &msmsdcc_ops;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003479 mmc->f_min = msmsdcc_get_min_sup_clk_rate(host);
3480 mmc->f_max = msmsdcc_get_max_sup_clk_rate(host);
San Mehat9d2bd732009-09-22 16:44:22 -07003481 mmc->ocr_avail = plat->ocr_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003482 mmc->pm_caps |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
3483 mmc->caps |= plat->mmc_bus_width;
San Mehat9d2bd732009-09-22 16:44:22 -07003484
San Mehat9d2bd732009-09-22 16:44:22 -07003485 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003486 mmc->caps |= plat->uhs_caps;
3487 /*
3488 * XPC controls the maximum current in the default speed mode of SDXC
3489 * card. XPC=0 means 100mA (max.) but speed class is not supported.
3490 * XPC=1 means 150mA (max.) and speed class is supported.
3491 */
3492 if (plat->xpc_cap)
3493 mmc->caps |= (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
3494 MMC_CAP_SET_XPC_180);
3495
3496 if (plat->nonremovable)
3497 mmc->caps |= MMC_CAP_NONREMOVABLE;
3498#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
3499 mmc->caps |= MMC_CAP_SDIO_IRQ;
3500#endif
3501
3502 if (plat->is_sdio_al_client)
3503 mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
San Mehat9d2bd732009-09-22 16:44:22 -07003504
Martin K. Petersena36274e2010-09-10 01:33:59 -04003505 mmc->max_segs = NR_SG;
San Mehat9d2bd732009-09-22 16:44:22 -07003506 mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003507 mmc->max_blk_count = 65535;
San Mehat9d2bd732009-09-22 16:44:22 -07003508
3509 mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */
3510 mmc->max_seg_size = mmc->max_req_size;
3511
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003512 writel_relaxed(0, host->base + MMCIMASK0);
3513 writel_relaxed(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
San Mehat9d2bd732009-09-22 16:44:22 -07003514
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003515 /* Delay needed (MMCIMASK0 was just written above) */
3516 msmsdcc_delay(host);
3517 writel_relaxed(MCI_IRQENABLE, host->base + MMCIMASK0);
3518 mb();
3519 host->mci_irqenable = MCI_IRQENABLE;
San Mehat9d2bd732009-09-22 16:44:22 -07003520
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003521 ret = request_irq(core_irqres->start, msmsdcc_irq, IRQF_SHARED,
3522 DRIVER_NAME " (cmd)", host);
3523 if (ret)
3524 goto dml_exit;
3525
3526 ret = request_irq(core_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
3527 DRIVER_NAME " (pio)", host);
3528 if (ret)
3529 goto irq_free;
3530
3531 /*
3532 * Enable SDCC IRQ only when host is powered on. Otherwise, this
3533 * IRQ is un-necessarily being monitored by MPM (Modem power
3534 * management block) during idle-power collapse. The MPM will be
3535 * configured to monitor the DATA1 GPIO line with level-low trigger
3536 * and thus depending on the GPIO status, it prevents TCXO shutdown
3537 * during idle-power collapse.
3538 */
3539 disable_irq(core_irqres->start);
3540 host->sdcc_irq_disabled = 1;
3541
3542 if (plat->sdiowakeup_irq) {
3543 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3544 mmc_hostname(mmc));
3545 ret = request_irq(plat->sdiowakeup_irq,
3546 msmsdcc_platform_sdiowakeup_irq,
3547 IRQF_SHARED | IRQF_TRIGGER_LOW,
3548 DRIVER_NAME "sdiowakeup", host);
3549 if (ret) {
3550 pr_err("Unable to get sdio wakeup IRQ %d (%d)\n",
3551 plat->sdiowakeup_irq, ret);
3552 goto pio_irq_free;
3553 } else {
3554 spin_lock_irqsave(&host->lock, flags);
3555 if (!host->sdio_irq_disabled) {
3556 disable_irq_nosync(plat->sdiowakeup_irq);
3557 host->sdio_irq_disabled = 1;
3558 }
3559 spin_unlock_irqrestore(&host->lock, flags);
3560 }
3561 }
3562
3563 if (plat->cfg_mpm_sdiowakeup) {
3564 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3565 mmc_hostname(mmc));
3566 }
3567
3568 wake_lock_init(&host->sdio_suspend_wlock, WAKE_LOCK_SUSPEND,
3569 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003570 /*
3571 * Setup card detect change
3572 */
3573
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003574 if (plat->status || plat->status_gpio) {
3575 if (plat->status)
3576 host->oldstat = plat->status(mmc_dev(host->mmc));
3577 else
3578 host->oldstat = msmsdcc_slot_status(host);
3579 host->eject = !host->oldstat;
3580 }
San Mehat9d2bd732009-09-22 16:44:22 -07003581
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003582 if (plat->status_irq) {
3583 ret = request_threaded_irq(plat->status_irq, NULL,
San Mehat9d2bd732009-09-22 16:44:22 -07003584 msmsdcc_platform_status_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003585 plat->irq_flags,
San Mehat9d2bd732009-09-22 16:44:22 -07003586 DRIVER_NAME " (slot)",
3587 host);
3588 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003589 pr_err("Unable to get slot IRQ %d (%d)\n",
3590 plat->status_irq, ret);
3591 goto sdiowakeup_irq_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003592 }
3593 } else if (plat->register_status_notify) {
3594 plat->register_status_notify(msmsdcc_status_notify_cb, host);
3595 } else if (!plat->status)
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003596 pr_err("%s: No card detect facilities available\n",
San Mehat9d2bd732009-09-22 16:44:22 -07003597 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003598
3599 mmc_set_drvdata(pdev, mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003600
3601 ret = pm_runtime_set_active(&(pdev)->dev);
3602 if (ret < 0)
3603 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
3604 __func__, ret);
3605 /*
3606 * There is no notion of suspend/resume for SD/MMC/SDIO
3607 * cards. So host can be suspended/resumed with out
3608 * worrying about its children.
3609 */
3610 pm_suspend_ignore_children(&(pdev)->dev, true);
3611
3612 /*
3613 * MMC/SD/SDIO bus suspend/resume operations are defined
3614 * only for the slots that will be used for non-removable
3615 * media or for all slots when CONFIG_MMC_UNSAFE_RESUME is
3616 * defined. Otherwise, they simply become card removal and
3617 * insertion events during suspend and resume respectively.
3618 * Hence, enable run-time PM only for slots for which bus
3619 * suspend/resume operations are defined.
3620 */
3621#ifdef CONFIG_MMC_UNSAFE_RESUME
3622 /*
3623 * If this capability is set, MMC core will enable/disable host
3624 * for every claim/release operation on a host. We use this
3625 * notification to increment/decrement runtime pm usage count.
3626 */
3627 mmc->caps |= MMC_CAP_DISABLE;
3628 pm_runtime_enable(&(pdev)->dev);
3629#else
3630 if (mmc->caps & MMC_CAP_NONREMOVABLE) {
3631 mmc->caps |= MMC_CAP_DISABLE;
3632 pm_runtime_enable(&(pdev)->dev);
3633 }
3634#endif
3635 setup_timer(&host->req_tout_timer, msmsdcc_req_tout_timer_hdlr,
3636 (unsigned long)host);
3637
San Mehat9d2bd732009-09-22 16:44:22 -07003638 mmc_add_host(mmc);
3639
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003640#ifdef CONFIG_HAS_EARLYSUSPEND
3641 host->early_suspend.suspend = msmsdcc_early_suspend;
3642 host->early_suspend.resume = msmsdcc_late_resume;
3643 host->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
3644 register_early_suspend(&host->early_suspend);
3645#endif
San Mehat9d2bd732009-09-22 16:44:22 -07003646
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003647 pr_info("%s: Qualcomm MSM SDCC-core at 0x%016llx irq %d,%d dma %d\n",
3648 mmc_hostname(mmc), (unsigned long long)core_memres->start,
3649 (unsigned int) core_irqres->start,
3650 (unsigned int) plat->status_irq, host->dma.channel);
3651
3652 pr_info("%s: 8 bit data mode %s\n", mmc_hostname(mmc),
3653 (mmc->caps & MMC_CAP_8_BIT_DATA ? "enabled" : "disabled"));
3654 pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc),
3655 (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled"));
3656 pr_info("%s: polling status mode %s\n", mmc_hostname(mmc),
3657 (mmc->caps & MMC_CAP_NEEDS_POLL ? "enabled" : "disabled"));
3658 pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n",
3659 mmc_hostname(mmc), msmsdcc_get_min_sup_clk_rate(host),
3660 msmsdcc_get_max_sup_clk_rate(host), host->pclk_rate);
3661 pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc),
3662 host->eject);
3663 pr_info("%s: Power save feature enable = %d\n",
3664 mmc_hostname(mmc), msmsdcc_pwrsave);
3665
3666 if (host->is_dma_mode && host->dma.channel != -1) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003667 pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003668 mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003669 pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003670 mmc_hostname(mmc), host->dma.cmd_busaddr,
3671 host->dma.cmdptr_busaddr);
3672 } else if (host->is_sps_mode) {
3673 pr_info("%s: SPS-BAM data transfer mode available\n",
3674 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003675 } else
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003676 pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003677
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003678#if defined(CONFIG_DEBUG_FS)
3679 msmsdcc_dbg_createhost(host);
3680#endif
3681 if (!plat->status_irq) {
3682 ret = sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);
3683 if (ret)
3684 goto platform_irq_free;
3685 }
San Mehat9d2bd732009-09-22 16:44:22 -07003686 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003687
3688 platform_irq_free:
3689 del_timer_sync(&host->req_tout_timer);
3690 pm_runtime_disable(&(pdev)->dev);
3691 pm_runtime_set_suspended(&(pdev)->dev);
3692
3693 if (plat->status_irq)
3694 free_irq(plat->status_irq, host);
3695 sdiowakeup_irq_free:
3696 wake_lock_destroy(&host->sdio_suspend_wlock);
3697 if (plat->sdiowakeup_irq)
3698 free_irq(plat->sdiowakeup_irq, host);
3699 pio_irq_free:
3700 if (plat->sdiowakeup_irq)
3701 wake_lock_destroy(&host->sdio_wlock);
3702 free_irq(core_irqres->start, host);
3703 irq_free:
3704 free_irq(core_irqres->start, host);
3705 dml_exit:
3706 if (host->is_sps_mode)
3707 msmsdcc_dml_exit(host);
3708 sps_exit:
3709 if (host->is_sps_mode)
3710 msmsdcc_sps_exit(host);
3711 vreg_deinit:
3712 msmsdcc_vreg_init(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07003713 clk_disable:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003714 clk_disable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003715 clk_put:
3716 clk_put(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003717 pclk_disable:
3718 if (!IS_ERR(host->pclk))
3719 clk_disable(host->pclk);
San Mehat9d2bd732009-09-22 16:44:22 -07003720 pclk_put:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003721 if (!IS_ERR(host->pclk))
3722 clk_put(host->pclk);
3723 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3724 clk_disable(host->dfab_pclk);
3725 dfab_pclk_put:
3726 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3727 clk_put(host->dfab_pclk);
3728 dma_free:
3729 if (host->is_dma_mode) {
3730 if (host->dmares)
3731 dma_free_coherent(NULL,
3732 sizeof(struct msmsdcc_nc_dmadata),
3733 host->dma.nc, host->dma.nc_busaddr);
3734 }
3735 ioremap_free:
3736 iounmap(host->base);
San Mehat9d2bd732009-09-22 16:44:22 -07003737 host_free:
3738 mmc_free_host(mmc);
3739 out:
3740 return ret;
3741}
3742
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003743static int msmsdcc_remove(struct platform_device *pdev)
Daniel Walker08ecfde2010-06-23 12:32:20 -07003744{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003745 struct mmc_host *mmc = mmc_get_drvdata(pdev);
3746 struct mmc_platform_data *plat;
3747 struct msmsdcc_host *host;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003748
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003749 if (!mmc)
3750 return -ENXIO;
3751
3752 if (pm_runtime_suspended(&(pdev)->dev))
3753 pm_runtime_resume(&(pdev)->dev);
3754
3755 host = mmc_priv(mmc);
3756
3757 DBG(host, "Removing SDCC device = %d\n", pdev->id);
3758 plat = host->plat;
3759
3760 if (!plat->status_irq)
3761 sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
3762
3763 del_timer_sync(&host->req_tout_timer);
3764 tasklet_kill(&host->dma_tlet);
3765 tasklet_kill(&host->sps.tlet);
3766 mmc_remove_host(mmc);
3767
3768 if (plat->status_irq)
3769 free_irq(plat->status_irq, host);
3770
3771 wake_lock_destroy(&host->sdio_suspend_wlock);
3772 if (plat->sdiowakeup_irq) {
3773 wake_lock_destroy(&host->sdio_wlock);
3774 irq_set_irq_wake(plat->sdiowakeup_irq, 0);
3775 free_irq(plat->sdiowakeup_irq, host);
Daniel Walker08ecfde2010-06-23 12:32:20 -07003776 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003777
3778 free_irq(host->core_irqres->start, host);
3779 free_irq(host->core_irqres->start, host);
3780
3781 clk_put(host->clk);
3782 if (!IS_ERR(host->pclk))
3783 clk_put(host->pclk);
3784 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3785 clk_put(host->dfab_pclk);
3786
3787 msmsdcc_vreg_init(host, false);
3788
3789 if (host->is_dma_mode) {
3790 if (host->dmares)
3791 dma_free_coherent(NULL,
3792 sizeof(struct msmsdcc_nc_dmadata),
3793 host->dma.nc, host->dma.nc_busaddr);
3794 }
3795
3796 if (host->is_sps_mode) {
3797 msmsdcc_dml_exit(host);
3798 msmsdcc_sps_exit(host);
3799 }
3800
3801 iounmap(host->base);
3802 mmc_free_host(mmc);
3803
3804#ifdef CONFIG_HAS_EARLYSUSPEND
3805 unregister_early_suspend(&host->early_suspend);
3806#endif
3807 pm_runtime_disable(&(pdev)->dev);
3808 pm_runtime_set_suspended(&(pdev)->dev);
3809
3810 return 0;
3811}
3812
3813#ifdef CONFIG_MSM_SDIO_AL
3814int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3815{
3816 struct msmsdcc_host *host = mmc_priv(mmc);
3817 unsigned long flags;
3818
3819 spin_lock_irqsave(&host->lock, flags);
3820 pr_debug("%s: %sabling LPM\n", mmc_hostname(mmc),
3821 enable ? "En" : "Dis");
3822
3823 if (enable) {
3824 if (!host->sdcc_irq_disabled) {
3825 writel_relaxed(0, host->base + MMCIMASK0);
3826 disable_irq(host->core_irqres->start);
3827 host->sdcc_irq_disabled = 1;
3828 }
3829
3830 if (host->clks_on) {
3831 msmsdcc_setup_clocks(host, false);
3832 host->clks_on = 0;
3833 }
3834
3835 if (!host->sdio_gpio_lpm) {
3836 spin_unlock_irqrestore(&host->lock, flags);
3837 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 0);
3838 spin_lock_irqsave(&host->lock, flags);
3839 host->sdio_gpio_lpm = 1;
3840 }
3841
3842 if (host->sdio_irq_disabled) {
3843 msmsdcc_enable_irq_wake(host);
3844 enable_irq(host->plat->sdiowakeup_irq);
3845 host->sdio_irq_disabled = 0;
3846 }
3847 } else {
3848 if (!host->sdio_irq_disabled) {
3849 disable_irq_nosync(host->plat->sdiowakeup_irq);
3850 host->sdio_irq_disabled = 1;
3851 msmsdcc_disable_irq_wake(host);
3852 }
3853
3854 if (host->sdio_gpio_lpm) {
3855 spin_unlock_irqrestore(&host->lock, flags);
3856 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 1);
3857 spin_lock_irqsave(&host->lock, flags);
3858 host->sdio_gpio_lpm = 0;
3859 }
3860
3861 if (!host->clks_on) {
3862 msmsdcc_setup_clocks(host, true);
3863 host->clks_on = 1;
3864 }
3865
3866 if (host->sdcc_irq_disabled) {
3867 writel_relaxed(host->mci_irqenable,
3868 host->base + MMCIMASK0);
3869 mb();
3870 enable_irq(host->core_irqres->start);
3871 host->sdcc_irq_disabled = 0;
3872 }
3873 wake_lock_timeout(&host->sdio_wlock, 1);
3874 }
3875 spin_unlock_irqrestore(&host->lock, flags);
3876 return 0;
3877}
3878#else
3879int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3880{
3881 return 0;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003882}
3883#endif
3884
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003885#ifdef CONFIG_PM
San Mehat9d2bd732009-09-22 16:44:22 -07003886static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003887msmsdcc_runtime_suspend(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003888{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003889 struct mmc_host *mmc = dev_get_drvdata(dev);
3890 struct msmsdcc_host *host = mmc_priv(mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07003891 int rc = 0;
3892
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003893 if (host->plat->is_sdio_al_client)
3894 return 0;
3895
Sahitya Tummala7661a452011-07-18 13:28:35 +05303896 pr_debug("%s: %s: start\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003897 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003898 host->sdcc_suspending = 1;
3899 mmc->suspend_task = current;
San Mehat9d2bd732009-09-22 16:44:22 -07003900
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003901 /*
3902 * If the clocks are already turned off by SDIO clients (as
3903 * part of LPM), then clocks should be turned on before
3904 * calling mmc_suspend_host() because mmc_suspend_host might
3905 * send some commands to the card. The clocks will be turned
3906 * off again after mmc_suspend_host. Thus for SD/MMC/SDIO
3907 * cards, clocks will be turned on before mmc_suspend_host
3908 * and turned off after mmc_suspend_host.
3909 */
3910 mmc->ios.clock = host->clk_rate;
3911 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07003912
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003913 /*
3914 * MMC core thinks that host is disabled by now since
3915 * runtime suspend is scheduled after msmsdcc_disable()
3916 * is called. Thus, MMC core will try to enable the host
3917 * while suspending it. This results in a synchronous
3918 * runtime resume request while in runtime suspending
3919 * context and hence inorder to complete this resume
3920 * requet, it will wait for suspend to be complete,
3921 * but runtime suspend also can not proceed further
3922 * until the host is resumed. Thus, it leads to a hang.
3923 * Hence, increase the pm usage count before suspending
3924 * the host so that any resume requests after this will
3925 * simple become pm usage counter increment operations.
3926 */
3927 pm_runtime_get_noresume(dev);
3928 rc = mmc_suspend_host(mmc);
3929 pm_runtime_put_noidle(dev);
3930
3931 if (!rc) {
3932 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
3933 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ)) {
3934 disable_irq(host->core_irqres->start);
3935 host->sdcc_irq_disabled = 1;
3936
3937 /*
3938 * If MMC core level suspend is not supported,
3939 * turn off clocks to allow deep sleep (TCXO
3940 * shutdown).
3941 */
3942 mmc->ios.clock = 0;
3943 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
3944 enable_irq(host->core_irqres->start);
3945 host->sdcc_irq_disabled = 0;
3946
3947 if (host->plat->sdiowakeup_irq) {
3948 host->sdio_irq_disabled = 0;
3949 msmsdcc_enable_irq_wake(host);
3950 enable_irq(host->plat->sdiowakeup_irq);
3951 }
3952 }
3953 }
3954 host->sdcc_suspending = 0;
3955 mmc->suspend_task = NULL;
3956 if (rc && wake_lock_active(&host->sdio_suspend_wlock))
3957 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07003958 }
Sahitya Tummala7661a452011-07-18 13:28:35 +05303959 pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003960 return rc;
3961}
3962
3963static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003964msmsdcc_runtime_resume(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003965{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003966 struct mmc_host *mmc = dev_get_drvdata(dev);
3967 struct msmsdcc_host *host = mmc_priv(mmc);
3968 unsigned long flags;
3969
3970 if (host->plat->is_sdio_al_client)
3971 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -07003972
Sahitya Tummala7661a452011-07-18 13:28:35 +05303973 pr_debug("%s: %s: start\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003974 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003975 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
3976 if (host->sdcc_irq_disabled) {
3977 enable_irq(host->core_irqres->start);
3978 host->sdcc_irq_disabled = 0;
3979 }
3980 }
3981 mmc->ios.clock = host->clk_rate;
3982 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07003983
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003984 spin_lock_irqsave(&host->lock, flags);
3985 writel_relaxed(host->mci_irqenable, host->base + MMCIMASK0);
3986 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07003987
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003988 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
3989 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) &&
3990 !host->sdio_irq_disabled) {
3991 if (host->plat->sdiowakeup_irq) {
3992 disable_irq_nosync(
3993 host->plat->sdiowakeup_irq);
3994 msmsdcc_disable_irq_wake(host);
3995 host->sdio_irq_disabled = 1;
3996 }
3997 }
San Mehat9d2bd732009-09-22 16:44:22 -07003998
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003999 spin_unlock_irqrestore(&host->lock, flags);
4000
4001 mmc_resume_host(mmc);
4002
4003 /*
4004 * FIXME: Clearing of flags must be handled in clients
4005 * resume handler.
4006 */
4007 spin_lock_irqsave(&host->lock, flags);
4008 mmc->pm_flags = 0;
4009 spin_unlock_irqrestore(&host->lock, flags);
4010
4011 /*
4012 * After resuming the host wait for sometime so that
4013 * the SDIO work will be processed.
4014 */
4015 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO)) {
4016 if ((host->plat->cfg_mpm_sdiowakeup ||
4017 host->plat->sdiowakeup_irq) &&
4018 wake_lock_active(&host->sdio_wlock))
4019 wake_lock_timeout(&host->sdio_wlock, 1);
4020 }
4021
4022 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07004023 }
Sahitya Tummala7661a452011-07-18 13:28:35 +05304024 pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07004025 return 0;
4026}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004027
4028static int msmsdcc_runtime_idle(struct device *dev)
4029{
4030 struct mmc_host *mmc = dev_get_drvdata(dev);
4031 struct msmsdcc_host *host = mmc_priv(mmc);
4032
4033 if (host->plat->is_sdio_al_client)
4034 return 0;
4035
4036 /* Idle timeout is not configurable for now */
4037 pm_schedule_suspend(dev, MSM_MMC_IDLE_TIMEOUT);
4038
4039 return -EAGAIN;
4040}
4041
4042static int msmsdcc_pm_suspend(struct device *dev)
4043{
4044 struct mmc_host *mmc = dev_get_drvdata(dev);
4045 struct msmsdcc_host *host = mmc_priv(mmc);
4046 int rc = 0;
4047
4048 if (host->plat->is_sdio_al_client)
4049 return 0;
4050
4051
4052 if (host->plat->status_irq)
4053 disable_irq(host->plat->status_irq);
4054
4055 if (!pm_runtime_suspended(dev))
4056 rc = msmsdcc_runtime_suspend(dev);
4057
4058 return rc;
4059}
4060
4061static int msmsdcc_pm_resume(struct device *dev)
4062{
4063 struct mmc_host *mmc = dev_get_drvdata(dev);
4064 struct msmsdcc_host *host = mmc_priv(mmc);
4065 int rc = 0;
4066
4067 if (host->plat->is_sdio_al_client)
4068 return 0;
4069
4070 rc = msmsdcc_runtime_resume(dev);
4071 if (host->plat->status_irq) {
4072 msmsdcc_check_status((unsigned long)host);
4073 enable_irq(host->plat->status_irq);
4074 }
4075
4076 /* Update the run-time PM status */
4077 pm_runtime_disable(dev);
4078 rc = pm_runtime_set_active(dev);
4079 if (rc < 0)
4080 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
4081 __func__, rc);
4082 pm_runtime_enable(dev);
4083
4084 return rc;
4085}
4086
Daniel Walker08ecfde2010-06-23 12:32:20 -07004087#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004088#define msmsdcc_runtime_suspend NULL
4089#define msmsdcc_runtime_resume NULL
4090#define msmsdcc_runtime_idle NULL
4091#define msmsdcc_pm_suspend NULL
4092#define msmsdcc_pm_resume NULL
Daniel Walker08ecfde2010-06-23 12:32:20 -07004093#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004094
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004095static const struct dev_pm_ops msmsdcc_dev_pm_ops = {
4096 .runtime_suspend = msmsdcc_runtime_suspend,
4097 .runtime_resume = msmsdcc_runtime_resume,
4098 .runtime_idle = msmsdcc_runtime_idle,
4099 .suspend = msmsdcc_pm_suspend,
4100 .resume = msmsdcc_pm_resume,
4101};
4102
San Mehat9d2bd732009-09-22 16:44:22 -07004103static struct platform_driver msmsdcc_driver = {
4104 .probe = msmsdcc_probe,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004105 .remove = msmsdcc_remove,
San Mehat9d2bd732009-09-22 16:44:22 -07004106 .driver = {
4107 .name = "msm_sdcc",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004108 .pm = &msmsdcc_dev_pm_ops,
San Mehat9d2bd732009-09-22 16:44:22 -07004109 },
4110};
4111
4112static int __init msmsdcc_init(void)
4113{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004114#if defined(CONFIG_DEBUG_FS)
4115 int ret = 0;
4116 ret = msmsdcc_dbg_init();
4117 if (ret) {
4118 pr_err("Failed to create debug fs dir \n");
4119 return ret;
4120 }
4121#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004122 return platform_driver_register(&msmsdcc_driver);
4123}
4124
4125static void __exit msmsdcc_exit(void)
4126{
4127 platform_driver_unregister(&msmsdcc_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004128
4129#if defined(CONFIG_DEBUG_FS)
4130 debugfs_remove(debugfs_file);
4131 debugfs_remove(debugfs_dir);
4132#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004133}
4134
4135module_init(msmsdcc_init);
4136module_exit(msmsdcc_exit);
4137
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004138MODULE_DESCRIPTION("Qualcomm Multimedia Card Interface driver");
San Mehat9d2bd732009-09-22 16:44:22 -07004139MODULE_LICENSE("GPL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004140
4141#if defined(CONFIG_DEBUG_FS)
4142
4143static int
4144msmsdcc_dbg_state_open(struct inode *inode, struct file *file)
4145{
4146 file->private_data = inode->i_private;
4147 return 0;
4148}
4149
4150static ssize_t
4151msmsdcc_dbg_state_read(struct file *file, char __user *ubuf,
4152 size_t count, loff_t *ppos)
4153{
4154 struct msmsdcc_host *host = (struct msmsdcc_host *) file->private_data;
4155 char buf[1024];
4156 int max, i;
4157
4158 i = 0;
4159 max = sizeof(buf) - 1;
4160
4161 i += scnprintf(buf + i, max - i, "STAT: %p %p %p\n", host->curr.mrq,
4162 host->curr.cmd, host->curr.data);
4163 if (host->curr.cmd) {
4164 struct mmc_command *cmd = host->curr.cmd;
4165
4166 i += scnprintf(buf + i, max - i, "CMD : %.8x %.8x %.8x\n",
4167 cmd->opcode, cmd->arg, cmd->flags);
4168 }
4169 if (host->curr.data) {
4170 struct mmc_data *data = host->curr.data;
4171 i += scnprintf(buf + i, max - i,
4172 "DAT0: %.8x %.8x %.8x %.8x %.8x %.8x\n",
4173 data->timeout_ns, data->timeout_clks,
4174 data->blksz, data->blocks, data->error,
4175 data->flags);
4176 i += scnprintf(buf + i, max - i, "DAT1: %.8x %.8x %.8x %p\n",
4177 host->curr.xfer_size, host->curr.xfer_remain,
4178 host->curr.data_xfered, host->dma.sg);
4179 }
4180
4181 return simple_read_from_buffer(ubuf, count, ppos, buf, i);
4182}
4183
4184static const struct file_operations msmsdcc_dbg_state_ops = {
4185 .read = msmsdcc_dbg_state_read,
4186 .open = msmsdcc_dbg_state_open,
4187};
4188
4189static void msmsdcc_dbg_createhost(struct msmsdcc_host *host)
4190{
4191 if (debugfs_dir) {
4192 debugfs_file = debugfs_create_file(mmc_hostname(host->mmc),
4193 0644, debugfs_dir, host,
4194 &msmsdcc_dbg_state_ops);
4195 }
4196}
4197
4198static int __init msmsdcc_dbg_init(void)
4199{
4200 int err;
4201
4202 debugfs_dir = debugfs_create_dir("msmsdcc", 0);
4203 if (IS_ERR(debugfs_dir)) {
4204 err = PTR_ERR(debugfs_dir);
4205 debugfs_dir = NULL;
4206 return err;
4207 }
4208
4209 return 0;
4210}
4211#endif