blob: 22a788e9a3d48a4fad0e373a2ba649741e21c0ed [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 Konda3f5d48f2011-07-27 10:47:31 -0700300 writel_relaxed(readl_relaxed(host->base + MMCIDATACTRL) &
301 (~(MCI_DPSM_ENABLE)), host->base + MMCIDATACTRL);
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700302 msmsdcc_delay(host); /* Allow the DPSM to be reset */
San Mehat9d2bd732009-09-22 16:44:22 -0700303}
304
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305static inline uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
San Mehat9d2bd732009-09-22 16:44:22 -0700306{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700307 return host->core_memres->start + MMCIFIFO;
308}
309
310static inline unsigned int msmsdcc_get_min_sup_clk_rate(
311 struct msmsdcc_host *host);
312static inline void msmsdcc_delay(struct msmsdcc_host *host)
313{
314 mb();
315 udelay(1 + ((3 * USEC_PER_SEC) /
316 (host->clk_rate ? host->clk_rate :
317 msmsdcc_get_min_sup_clk_rate(host))));
San Mehat9d2bd732009-09-22 16:44:22 -0700318}
319
San Mehat56a8b5b2009-11-21 12:29:46 -0800320static inline void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c)
322{
323 writel_relaxed(arg, host->base + MMCIARGUMENT);
324 msmsdcc_delay(host);
325 writel_relaxed(c, host->base + MMCICOMMAND);
326 mb();
San Mehat56a8b5b2009-11-21 12:29:46 -0800327}
328
329static void
330msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
331{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700332 struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->user;
San Mehat56a8b5b2009-11-21 12:29:46 -0800333
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 writel_relaxed(host->cmd_timeout, host->base + MMCIDATATIMER);
335 writel_relaxed((unsigned int)host->curr.xfer_size,
336 host->base + MMCIDATALENGTH);
337 msmsdcc_delay(host); /* Allow data parms to be applied */
338 writel_relaxed(host->cmd_datactrl, host->base + MMCIDATACTRL);
339 msmsdcc_delay(host); /* Force delay prior to ADM or command */
San Mehat56a8b5b2009-11-21 12:29:46 -0800340
San Mehat6ac9ea62009-12-02 17:24:58 -0800341 if (host->cmd_cmd) {
342 msmsdcc_start_command_exec(host,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343 (u32)host->cmd_cmd->arg, (u32)host->cmd_c);
San Mehat6ac9ea62009-12-02 17:24:58 -0800344 }
San Mehat56a8b5b2009-11-21 12:29:46 -0800345}
346
San Mehat9d2bd732009-09-22 16:44:22 -0700347static void
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530348msmsdcc_dma_complete_tlet(unsigned long data)
San Mehat9d2bd732009-09-22 16:44:22 -0700349{
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530350 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
San Mehat9d2bd732009-09-22 16:44:22 -0700351 unsigned long flags;
352 struct mmc_request *mrq;
353
354 spin_lock_irqsave(&host->lock, flags);
355 mrq = host->curr.mrq;
356 BUG_ON(!mrq);
357
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530358 if (!(host->dma.result & DMOV_RSLT_VALID)) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700359 pr_err("msmsdcc: Invalid DataMover result\n");
San Mehat9d2bd732009-09-22 16:44:22 -0700360 goto out;
361 }
362
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530363 if (host->dma.result & DMOV_RSLT_DONE) {
San Mehat9d2bd732009-09-22 16:44:22 -0700364 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365 host->curr.xfer_remain -= host->curr.xfer_size;
San Mehat9d2bd732009-09-22 16:44:22 -0700366 } else {
367 /* Error or flush */
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530368 if (host->dma.result & DMOV_RSLT_ERROR)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700369 pr_err("%s: DMA error (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530370 mmc_hostname(host->mmc), host->dma.result);
371 if (host->dma.result & DMOV_RSLT_FLUSH)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700372 pr_err("%s: DMA channel flushed (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530373 mmc_hostname(host->mmc), host->dma.result);
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530374 pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375 host->dma.err.flush[0], host->dma.err.flush[1],
376 host->dma.err.flush[2], host->dma.err.flush[3],
377 host->dma.err.flush[4],
378 host->dma.err.flush[5]);
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530379 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -0700380 if (!mrq->data->error)
381 mrq->data->error = -EIO;
382 }
San Mehat9d2bd732009-09-22 16:44:22 -0700383 dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
384 host->dma.dir);
385
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700386 if (host->curr.user_pages) {
387 struct scatterlist *sg = host->dma.sg;
388 int i;
389
390 for (i = 0; i < host->dma.num_ents; i++, sg++)
391 flush_dcache_page(sg_page(sg));
392 }
393
San Mehat9d2bd732009-09-22 16:44:22 -0700394 host->dma.sg = NULL;
San Mehat56a8b5b2009-11-21 12:29:46 -0800395 host->dma.busy = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700396
Sahitya Tummala0c521cc2010-12-08 15:03:07 +0530397 if (host->curr.got_dataend || mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700398
399 /*
400 * If we've already gotten our DATAEND / DATABLKEND
401 * for this request, then complete it through here.
402 */
San Mehat9d2bd732009-09-22 16:44:22 -0700403
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404 if (!mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700405 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700406 host->curr.xfer_remain -= host->curr.xfer_size;
407 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -0700408 if (host->dummy_52_needed) {
409 mrq->data->bytes_xfered = host->curr.data_xfered;
410 host->dummy_52_sent = 1;
411 msmsdcc_start_command(host, &dummy52cmd,
412 MCI_CPSM_PROGENA);
413 goto out;
414 }
415 msmsdcc_stop_data(host);
San Mehat9d2bd732009-09-22 16:44:22 -0700416 if (!mrq->data->stop || mrq->cmd->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700417 host->curr.mrq = NULL;
418 host->curr.cmd = NULL;
419 mrq->data->bytes_xfered = host->curr.data_xfered;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700420 del_timer(&host->req_tout_timer);
San Mehat9d2bd732009-09-22 16:44:22 -0700421 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700422
San Mehat9d2bd732009-09-22 16:44:22 -0700423 mmc_request_done(host->mmc, mrq);
424 return;
425 } else
426 msmsdcc_start_command(host, mrq->data->stop, 0);
427 }
428
429out:
430 spin_unlock_irqrestore(&host->lock, flags);
431 return;
432}
433
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
435/**
436 * Callback notification from SPS driver
437 *
438 * This callback function gets triggered called from
439 * SPS driver when requested SPS data transfer is
440 * completed.
441 *
442 * SPS driver invokes this callback in BAM irq context so
443 * SDCC driver schedule a tasklet for further processing
444 * this callback notification at later point of time in
445 * tasklet context and immediately returns control back
446 * to SPS driver.
447 *
448 * @nofity - Pointer to sps event notify sturcture
449 *
450 */
451static void
452msmsdcc_sps_complete_cb(struct sps_event_notify *notify)
453{
454 struct msmsdcc_host *host =
455 (struct msmsdcc_host *)
456 ((struct sps_event_notify *)notify)->user;
457
458 host->sps.notify = *notify;
459 pr_debug("%s: %s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
460 mmc_hostname(host->mmc), __func__, notify->event_id,
461 notify->data.transfer.iovec.addr,
462 notify->data.transfer.iovec.size,
463 notify->data.transfer.iovec.flags);
464 /* Schedule a tasklet for completing data transfer */
465 tasklet_schedule(&host->sps.tlet);
466}
467
468/**
469 * Tasklet handler for processing SPS callback event
470 *
471 * This function processing SPS event notification and
472 * checks if the SPS transfer is completed or not and
473 * then accordingly notifies status to MMC core layer.
474 *
475 * This function is called in tasklet context.
476 *
477 * @data - Pointer to sdcc driver data
478 *
479 */
480static void msmsdcc_sps_complete_tlet(unsigned long data)
481{
482 unsigned long flags;
483 int i, rc;
484 u32 data_xfered = 0;
485 struct mmc_request *mrq;
486 struct sps_iovec iovec;
487 struct sps_pipe *sps_pipe_handle;
488 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
489 struct sps_event_notify *notify = &host->sps.notify;
490
491 spin_lock_irqsave(&host->lock, flags);
492 if (host->sps.dir == DMA_FROM_DEVICE)
493 sps_pipe_handle = host->sps.prod.pipe_handle;
494 else
495 sps_pipe_handle = host->sps.cons.pipe_handle;
496 mrq = host->curr.mrq;
497
498 if (!mrq) {
499 spin_unlock_irqrestore(&host->lock, flags);
500 return;
501 }
502
503 pr_debug("%s: %s: sps event_id=%d\n",
504 mmc_hostname(host->mmc), __func__,
505 notify->event_id);
506
507 if (msmsdcc_is_dml_busy(host)) {
508 /* oops !!! this should never happen. */
509 pr_err("%s: %s: Received SPS EOT event"
510 " but DML HW is still busy !!!\n",
511 mmc_hostname(host->mmc), __func__);
512 }
513 /*
514 * Got End of transfer event!!! Check if all of the data
515 * has been transferred?
516 */
517 for (i = 0; i < host->sps.xfer_req_cnt; i++) {
518 rc = sps_get_iovec(sps_pipe_handle, &iovec);
519 if (rc) {
520 pr_err("%s: %s: sps_get_iovec() failed rc=%d, i=%d",
521 mmc_hostname(host->mmc), __func__, rc, i);
522 break;
523 }
524 data_xfered += iovec.size;
525 }
526
527 if (data_xfered == host->curr.xfer_size) {
528 host->curr.data_xfered = host->curr.xfer_size;
529 host->curr.xfer_remain -= host->curr.xfer_size;
530 pr_debug("%s: Data xfer success. data_xfered=0x%x",
531 mmc_hostname(host->mmc),
532 host->curr.xfer_size);
533 } else {
534 pr_err("%s: Data xfer failed. data_xfered=0x%x,"
535 " xfer_size=%d", mmc_hostname(host->mmc),
536 data_xfered, host->curr.xfer_size);
537 msmsdcc_reset_and_restore(host);
538 if (!mrq->data->error)
539 mrq->data->error = -EIO;
540 }
541
542 /* Unmap sg buffers */
543 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
544 host->sps.dir);
545
546 host->sps.sg = NULL;
547 host->sps.busy = 0;
548
549 if (host->curr.got_dataend || mrq->data->error) {
550 /*
551 * If we've already gotten our DATAEND / DATABLKEND
552 * for this request, then complete it through here.
553 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700554
555 if (!mrq->data->error) {
556 host->curr.data_xfered = host->curr.xfer_size;
557 host->curr.xfer_remain -= host->curr.xfer_size;
558 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -0700559 if (host->dummy_52_needed) {
560 mrq->data->bytes_xfered = host->curr.data_xfered;
561 host->dummy_52_sent = 1;
562 msmsdcc_start_command(host, &dummy52cmd,
563 MCI_CPSM_PROGENA);
564 return;
565 }
566 msmsdcc_stop_data(host);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700567 if (!mrq->data->stop || mrq->cmd->error) {
568 host->curr.mrq = NULL;
569 host->curr.cmd = NULL;
570 mrq->data->bytes_xfered = host->curr.data_xfered;
571 del_timer(&host->req_tout_timer);
572 spin_unlock_irqrestore(&host->lock, flags);
573
574 mmc_request_done(host->mmc, mrq);
575 return;
576 } else {
577 msmsdcc_start_command(host, mrq->data->stop, 0);
578 }
579 }
580 spin_unlock_irqrestore(&host->lock, flags);
581}
582
583/**
584 * Exit from current SPS data transfer
585 *
586 * This function exits from current SPS data transfer.
587 *
588 * This function should be called when error condition
589 * is encountered during data transfer.
590 *
591 * @host - Pointer to sdcc host structure
592 *
593 */
594static void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host)
595{
596 struct mmc_request *mrq;
597
598 mrq = host->curr.mrq;
599 BUG_ON(!mrq);
600
601 msmsdcc_reset_and_restore(host);
602 if (!mrq->data->error)
603 mrq->data->error = -EIO;
604
605 /* Unmap sg buffers */
606 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
607 host->sps.dir);
608
609 host->sps.sg = NULL;
610 host->sps.busy = 0;
611 if (host->curr.data)
612 msmsdcc_stop_data(host);
613
614 if (!mrq->data->stop || mrq->cmd->error)
615 msmsdcc_request_end(host, mrq);
616 else
617 msmsdcc_start_command(host, mrq->data->stop, 0);
618
619}
620#else
621static inline void msmsdcc_sps_complete_cb(struct sps_event_notify *notify) { }
622static inline void msmsdcc_sps_complete_tlet(unsigned long data) { }
623static inline void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host) { }
624#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
625
626static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host);
627
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530628static void
629msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
630 unsigned int result,
631 struct msm_dmov_errdata *err)
632{
633 struct msmsdcc_dma_data *dma_data =
634 container_of(cmd, struct msmsdcc_dma_data, hdr);
635 struct msmsdcc_host *host = dma_data->host;
636
637 dma_data->result = result;
638 if (err)
639 memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
640
641 tasklet_schedule(&host->dma_tlet);
642}
643
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700644static int msmsdcc_check_dma_op_req(struct mmc_data *data)
San Mehat9d2bd732009-09-22 16:44:22 -0700645{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700646 if (((data->blksz * data->blocks) < MCI_FIFOSIZE) ||
647 ((data->blksz * data->blocks) % MCI_FIFOSIZE))
San Mehat9d2bd732009-09-22 16:44:22 -0700648 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649 else
650 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700651}
652
653static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
654{
655 struct msmsdcc_nc_dmadata *nc;
656 dmov_box *box;
657 uint32_t rows;
658 uint32_t crci;
659 unsigned int n;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700660 int i;
San Mehat9d2bd732009-09-22 16:44:22 -0700661 struct scatterlist *sg = data->sg;
662
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663 if (host->dma.channel == -1)
664 return -ENOENT;
San Mehat9d2bd732009-09-22 16:44:22 -0700665
666 host->dma.sg = data->sg;
667 host->dma.num_ents = data->sg_len;
668
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700669 BUG_ON(host->dma.num_ents > NR_SG); /* Prevent memory corruption */
San Mehat56a8b5b2009-11-21 12:29:46 -0800670
San Mehat9d2bd732009-09-22 16:44:22 -0700671 nc = host->dma.nc;
672
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700673 if (host->pdev_id == 1)
674 crci = DMOV_SDC1_CRCI;
675 else if (host->pdev_id == 2)
676 crci = DMOV_SDC2_CRCI;
677 else if (host->pdev_id == 3)
678 crci = DMOV_SDC3_CRCI;
679 else if (host->pdev_id == 4)
680 crci = DMOV_SDC4_CRCI;
681#ifdef DMOV_SDC5_CRCI
682 else if (host->pdev_id == 5)
683 crci = DMOV_SDC5_CRCI;
684#endif
685 else {
San Mehat9d2bd732009-09-22 16:44:22 -0700686 host->dma.sg = NULL;
687 host->dma.num_ents = 0;
688 return -ENOENT;
689 }
690
691 if (data->flags & MMC_DATA_READ)
692 host->dma.dir = DMA_FROM_DEVICE;
693 else
694 host->dma.dir = DMA_TO_DEVICE;
695
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700696 /* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
San Mehat9d2bd732009-09-22 16:44:22 -0700697 host->curr.user_pages = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700698 box = &nc->cmd[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700699 for (i = 0; i < host->dma.num_ents; i++) {
San Mehat9d2bd732009-09-22 16:44:22 -0700700 box->cmd = CMD_MODE_BOX;
701
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700702 /* Initialize sg dma address */
703 sg->dma_address = pfn_to_dma(mmc_dev(host->mmc),
704 page_to_pfn(sg_page(sg)))
705 + sg->offset;
706
707 if (i == (host->dma.num_ents - 1))
San Mehat9d2bd732009-09-22 16:44:22 -0700708 box->cmd |= CMD_LC;
709 rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
710 (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
711 (sg_dma_len(sg) / MCI_FIFOSIZE) ;
712
713 if (data->flags & MMC_DATA_READ) {
714 box->src_row_addr = msmsdcc_fifo_addr(host);
715 box->dst_row_addr = sg_dma_address(sg);
716
717 box->src_dst_len = (MCI_FIFOSIZE << 16) |
718 (MCI_FIFOSIZE);
719 box->row_offset = MCI_FIFOSIZE;
720
721 box->num_rows = rows * ((1 << 16) + 1);
722 box->cmd |= CMD_SRC_CRCI(crci);
723 } else {
724 box->src_row_addr = sg_dma_address(sg);
725 box->dst_row_addr = msmsdcc_fifo_addr(host);
726
727 box->src_dst_len = (MCI_FIFOSIZE << 16) |
728 (MCI_FIFOSIZE);
729 box->row_offset = (MCI_FIFOSIZE << 16);
730
731 box->num_rows = rows * ((1 << 16) + 1);
732 box->cmd |= CMD_DST_CRCI(crci);
733 }
734 box++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700735 sg++;
736 }
737
738 /* location of command block must be 64 bit aligned */
739 BUG_ON(host->dma.cmd_busaddr & 0x07);
740
741 nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
742 host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
743 DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
744 host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
745 host->dma.hdr.crci_mask = msm_dmov_build_crci_mask(1, crci);
746
747 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
748 host->dma.num_ents, host->dma.dir);
749 /* dsb inside dma_map_sg will write nc out to mem as well */
750
751 if (n != host->dma.num_ents) {
752 pr_err("%s: Unable to map in all sg elements\n",
753 mmc_hostname(host->mmc));
754 host->dma.sg = NULL;
755 host->dma.num_ents = 0;
756 return -ENOMEM;
San Mehat56a8b5b2009-11-21 12:29:46 -0800757 }
San Mehat9d2bd732009-09-22 16:44:22 -0700758
759 return 0;
760}
761
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
763/**
764 * Submits data transfer request to SPS driver
765 *
766 * This function make sg (scatter gather) data buffers
767 * DMA ready and then submits them to SPS driver for
768 * transfer.
769 *
770 * @host - Pointer to sdcc host structure
771 * @data - Pointer to mmc_data structure
772 *
773 * @return 0 if success else negative value
774 */
775static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
776 struct mmc_data *data)
San Mehat56a8b5b2009-11-21 12:29:46 -0800777{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778 int rc = 0;
779 u32 flags;
780 int i;
781 u32 addr, len, data_cnt;
782 struct scatterlist *sg = data->sg;
783 struct sps_pipe *sps_pipe_handle;
784
785 BUG_ON(data->sg_len > NR_SG); /* Prevent memory corruption */
786
787 host->sps.sg = data->sg;
788 host->sps.num_ents = data->sg_len;
789 host->sps.xfer_req_cnt = 0;
790 if (data->flags & MMC_DATA_READ) {
791 host->sps.dir = DMA_FROM_DEVICE;
792 sps_pipe_handle = host->sps.prod.pipe_handle;
793 } else {
794 host->sps.dir = DMA_TO_DEVICE;
795 sps_pipe_handle = host->sps.cons.pipe_handle;
796 }
797
798 /* Make sg buffers DMA ready */
799 rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
800 host->sps.dir);
801
802 if (rc != data->sg_len) {
803 pr_err("%s: Unable to map in all sg elements, rc=%d\n",
804 mmc_hostname(host->mmc), rc);
805 host->sps.sg = NULL;
806 host->sps.num_ents = 0;
807 rc = -ENOMEM;
808 goto dma_map_err;
809 }
810
811 pr_debug("%s: %s: %s: pipe=0x%x, total_xfer=0x%x, sg_len=%d\n",
812 mmc_hostname(host->mmc), __func__,
813 host->sps.dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
814 (u32)sps_pipe_handle, host->curr.xfer_size, data->sg_len);
815
816 for (i = 0; i < data->sg_len; i++) {
817 /*
818 * Check if this is the last buffer to transfer?
819 * If yes then set the INT and EOT flags.
820 */
821 len = sg_dma_len(sg);
822 addr = sg_dma_address(sg);
823 flags = 0;
824 while (len > 0) {
825 if (len > SPS_MAX_DESC_SIZE) {
826 data_cnt = SPS_MAX_DESC_SIZE;
827 } else {
828 data_cnt = len;
829 if (i == data->sg_len - 1)
830 flags = SPS_IOVEC_FLAG_INT |
831 SPS_IOVEC_FLAG_EOT;
832 }
833 rc = sps_transfer_one(sps_pipe_handle, addr,
834 data_cnt, host, flags);
835 if (rc) {
836 pr_err("%s: sps_transfer_one() error! rc=%d,"
837 " pipe=0x%x, sg=0x%x, sg_buf_no=%d\n",
838 mmc_hostname(host->mmc), rc,
839 (u32)sps_pipe_handle, (u32)sg, i);
840 goto dma_map_err;
841 }
842 addr += data_cnt;
843 len -= data_cnt;
844 host->sps.xfer_req_cnt++;
845 }
846 sg++;
847 }
848 goto out;
849
850dma_map_err:
851 /* unmap sg buffers */
852 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
853 host->sps.dir);
854out:
855 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -0700856}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700857#else
858static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
859 struct mmc_data *data) { return 0; }
860#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
San Mehat9d2bd732009-09-22 16:44:22 -0700861
862static void
San Mehat56a8b5b2009-11-21 12:29:46 -0800863msmsdcc_start_command_deferred(struct msmsdcc_host *host,
864 struct mmc_command *cmd, u32 *c)
865{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700866 DBG(host, "op %02x arg %08x flags %08x\n",
867 cmd->opcode, cmd->arg, cmd->flags);
868
San Mehat56a8b5b2009-11-21 12:29:46 -0800869 *c |= (cmd->opcode | MCI_CPSM_ENABLE);
870
871 if (cmd->flags & MMC_RSP_PRESENT) {
872 if (cmd->flags & MMC_RSP_136)
873 *c |= MCI_CPSM_LONGRSP;
874 *c |= MCI_CPSM_RESPONSE;
875 }
876
877 if (/*interrupt*/0)
878 *c |= MCI_CPSM_INTERRUPT;
879
880 if ((((cmd->opcode == 17) || (cmd->opcode == 18)) ||
881 ((cmd->opcode == 24) || (cmd->opcode == 25))) ||
882 (cmd->opcode == 53))
883 *c |= MCI_CSPM_DATCMD;
884
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700885 /* Check if AUTO CMD19 is required or not? */
886 if (((cmd->opcode == 17) || (cmd->opcode == 18)) &&
887 host->tuning_needed) {
888 msmsdcc_enable_cdr_cm_sdc4_dll(host);
889 *c |= MCI_CSPM_AUTO_CMD19;
890 }
891
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530892 if (host->prog_scan && (cmd->opcode == 12)) {
893 *c |= MCI_CPSM_PROGENA;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700894 host->prog_enable = 1;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530895 }
896
San Mehat56a8b5b2009-11-21 12:29:46 -0800897 if (cmd == cmd->mrq->stop)
898 *c |= MCI_CSPM_MCIABORT;
899
San Mehat56a8b5b2009-11-21 12:29:46 -0800900 if (host->curr.cmd != NULL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700901 pr_err("%s: Overlapping command requests\n",
902 mmc_hostname(host->mmc));
San Mehat56a8b5b2009-11-21 12:29:46 -0800903 }
904 host->curr.cmd = cmd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905
906 /*
907 * Kick the software command timeout timer here.
908 * Timer expires in 10 secs.
909 */
910 mod_timer(&host->req_tout_timer,
911 (jiffies + msecs_to_jiffies(MSM_MMC_REQ_TIMEOUT)));
San Mehat56a8b5b2009-11-21 12:29:46 -0800912}
913
914static void
915msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data,
916 struct mmc_command *cmd, u32 c)
San Mehat9d2bd732009-09-22 16:44:22 -0700917{
Subhash Jadavani24fb7f82011-07-25 15:54:34 +0530918 unsigned int datactrl = 0, timeout;
San Mehat9d2bd732009-09-22 16:44:22 -0700919 unsigned long long clks;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700920 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -0700921 unsigned int pio_irqmask = 0;
922
923 host->curr.data = data;
924 host->curr.xfer_size = data->blksz * data->blocks;
925 host->curr.xfer_remain = host->curr.xfer_size;
926 host->curr.data_xfered = 0;
927 host->curr.got_dataend = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700928
929 memset(&host->pio, 0, sizeof(host->pio));
930
San Mehat9d2bd732009-09-22 16:44:22 -0700931 datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
932
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700933 if (!msmsdcc_check_dma_op_req(data)) {
934 if (host->is_dma_mode && !msmsdcc_config_dma(host, data)) {
935 datactrl |= MCI_DPSM_DMAENABLE;
936 } else if (host->is_sps_mode) {
937 if (!msmsdcc_is_dml_busy(host)) {
938 if (!msmsdcc_sps_start_xfer(host, data)) {
939 /* Now kick start DML transfer */
940 mb();
941 msmsdcc_dml_start_xfer(host, data);
942 datactrl |= MCI_DPSM_DMAENABLE;
943 host->sps.busy = 1;
944 }
945 } else {
946 /*
947 * Can't proceed with new transfer as
948 * previous trasnfer is already in progress.
949 * There is no point of going into PIO mode
950 * as well. Is this a time to do kernel panic?
951 */
952 pr_err("%s: %s: DML HW is busy!!!"
953 " Can't perform new SPS transfers"
954 " now\n", mmc_hostname(host->mmc),
955 __func__);
956 }
957 }
958 }
959
960 /* Is data transfer in PIO mode required? */
961 if (!(datactrl & MCI_DPSM_DMAENABLE)) {
San Mehat9d2bd732009-09-22 16:44:22 -0700962 host->pio.sg = data->sg;
963 host->pio.sg_len = data->sg_len;
964 host->pio.sg_off = 0;
965
966 if (data->flags & MMC_DATA_READ) {
967 pio_irqmask = MCI_RXFIFOHALFFULLMASK;
968 if (host->curr.xfer_remain < MCI_FIFOSIZE)
969 pio_irqmask |= MCI_RXDATAAVLBLMASK;
970 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700971 pio_irqmask = MCI_TXFIFOHALFEMPTYMASK |
972 MCI_TXFIFOEMPTYMASK;
San Mehat9d2bd732009-09-22 16:44:22 -0700973 }
974
975 if (data->flags & MMC_DATA_READ)
Subhash Jadavani24fb7f82011-07-25 15:54:34 +0530976 datactrl |= (MCI_DPSM_DIRECTION | MCI_RX_DATA_PEND);
San Mehat9d2bd732009-09-22 16:44:22 -0700977
San Mehat56a8b5b2009-11-21 12:29:46 -0800978 clks = (unsigned long long)data->timeout_ns * host->clk_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700979 do_div(clks, 1000000000UL);
San Mehat56a8b5b2009-11-21 12:29:46 -0800980 timeout = data->timeout_clks + (unsigned int)clks*2 ;
San Mehat9d2bd732009-09-22 16:44:22 -0700981
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700982 if (host->is_dma_mode && (datactrl & MCI_DPSM_DMAENABLE)) {
983 /* Use ADM (Application Data Mover) HW for Data transfer */
984 /* Save parameters for the dma exec function */
San Mehat56a8b5b2009-11-21 12:29:46 -0800985 host->cmd_timeout = timeout;
986 host->cmd_pio_irqmask = pio_irqmask;
987 host->cmd_datactrl = datactrl;
988 host->cmd_cmd = cmd;
San Mehat9d2bd732009-09-22 16:44:22 -0700989
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700990 host->dma.hdr.exec_func = msmsdcc_dma_exec_func;
991 host->dma.hdr.user = (void *)host;
San Mehat9d2bd732009-09-22 16:44:22 -0700992 host->dma.busy = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700993 if (data->flags & MMC_DATA_WRITE)
994 host->prog_scan = 1;
San Mehat56a8b5b2009-11-21 12:29:46 -0800995
996 if (cmd) {
997 msmsdcc_start_command_deferred(host, cmd, &c);
998 host->cmd_c = c;
999 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001000 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1001 (~(MCI_IRQ_PIO))) | host->cmd_pio_irqmask,
1002 host->base + MMCIMASK0);
1003 mb();
1004 msm_dmov_enqueue_cmd_ext(host->dma.channel, &host->dma.hdr);
San Mehat56a8b5b2009-11-21 12:29:46 -08001005 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001006 /* SPS-BAM mode or PIO mode */
1007 if (data->flags & MMC_DATA_WRITE)
1008 host->prog_scan = 1;
1009 writel_relaxed(timeout, base + MMCIDATATIMER);
San Mehat56a8b5b2009-11-21 12:29:46 -08001010
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001011 writel_relaxed(host->curr.xfer_size, base + MMCIDATALENGTH);
San Mehat56a8b5b2009-11-21 12:29:46 -08001012
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001013 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1014 (~(MCI_IRQ_PIO))) | pio_irqmask,
1015 host->base + MMCIMASK0);
1016 msmsdcc_delay(host); /* Allow parms to be applied */
1017 writel_relaxed(datactrl, base + MMCIDATACTRL);
San Mehat56a8b5b2009-11-21 12:29:46 -08001018
1019 if (cmd) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001020 msmsdcc_delay(host); /* Delay between data/command */
San Mehat56a8b5b2009-11-21 12:29:46 -08001021 /* Daisy-chain the command if requested */
1022 msmsdcc_start_command(host, cmd, c);
1023 }
San Mehat9d2bd732009-09-22 16:44:22 -07001024 }
1025}
1026
1027static void
1028msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
1029{
San Mehat56a8b5b2009-11-21 12:29:46 -08001030 msmsdcc_start_command_deferred(host, cmd, &c);
1031 msmsdcc_start_command_exec(host, cmd->arg, c);
San Mehat9d2bd732009-09-22 16:44:22 -07001032}
1033
1034static void
1035msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
1036 unsigned int status)
1037{
1038 if (status & MCI_DATACRCFAIL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001039 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1040 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1041 pr_err("%s: Data CRC error\n",
1042 mmc_hostname(host->mmc));
1043 pr_err("%s: opcode 0x%.8x\n", __func__,
1044 data->mrq->cmd->opcode);
1045 pr_err("%s: blksz %d, blocks %d\n", __func__,
1046 data->blksz, data->blocks);
1047 data->error = -EILSEQ;
1048 }
San Mehat9d2bd732009-09-22 16:44:22 -07001049 } else if (status & MCI_DATATIMEOUT) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001050 /* CRC is optional for the bus test commands, not all
1051 * cards respond back with CRC. However controller
1052 * waits for the CRC and times out. Hence ignore the
1053 * data timeouts during the Bustest.
1054 */
1055 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1056 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1057 pr_err("%s: Data timeout\n",
1058 mmc_hostname(host->mmc));
1059 data->error = -ETIMEDOUT;
1060 }
San Mehat9d2bd732009-09-22 16:44:22 -07001061 } else if (status & MCI_RXOVERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001062 pr_err("%s: RX overrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001063 data->error = -EIO;
1064 } else if (status & MCI_TXUNDERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001065 pr_err("%s: TX underrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001066 data->error = -EIO;
1067 } else {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001068 pr_err("%s: Unknown error (0x%.8x)\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001069 mmc_hostname(host->mmc), status);
San Mehat9d2bd732009-09-22 16:44:22 -07001070 data->error = -EIO;
1071 }
San Mehat9d2bd732009-09-22 16:44:22 -07001072
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001073 /* Dummy CMD52 is not needed when CMD53 has errors */
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001074 if (host->dummy_52_needed)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001075 host->dummy_52_needed = 0;
1076}
San Mehat9d2bd732009-09-22 16:44:22 -07001077
1078static int
1079msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
1080{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001081 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001082 uint32_t *ptr = (uint32_t *) buffer;
1083 int count = 0;
1084
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301085 if (remain % 4)
1086 remain = ((remain >> 2) + 1) << 2;
1087
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001088 while (readl_relaxed(base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1089
1090 *ptr = readl_relaxed(base + MMCIFIFO + (count % MCI_FIFOSIZE));
San Mehat9d2bd732009-09-22 16:44:22 -07001091 ptr++;
1092 count += sizeof(uint32_t);
1093
1094 remain -= sizeof(uint32_t);
1095 if (remain == 0)
1096 break;
1097 }
1098 return count;
1099}
1100
1101static int
1102msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001103 unsigned int remain)
San Mehat9d2bd732009-09-22 16:44:22 -07001104{
1105 void __iomem *base = host->base;
1106 char *ptr = buffer;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001107 unsigned int maxcnt = MCI_FIFOHALFSIZE;
San Mehat9d2bd732009-09-22 16:44:22 -07001108
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001109 while (readl_relaxed(base + MMCISTATUS) &
1110 (MCI_TXFIFOEMPTY | MCI_TXFIFOHALFEMPTY)) {
1111 unsigned int count, sz;
San Mehat9d2bd732009-09-22 16:44:22 -07001112
San Mehat9d2bd732009-09-22 16:44:22 -07001113 count = min(remain, maxcnt);
1114
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301115 sz = count % 4 ? (count >> 2) + 1 : (count >> 2);
1116 writesl(base + MMCIFIFO, ptr, sz);
San Mehat9d2bd732009-09-22 16:44:22 -07001117 ptr += count;
1118 remain -= count;
1119
1120 if (remain == 0)
1121 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001122 }
1123 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07001124
1125 return ptr - buffer;
1126}
1127
San Mehat1cd22962010-02-03 12:59:29 -08001128static irqreturn_t
San Mehat9d2bd732009-09-22 16:44:22 -07001129msmsdcc_pio_irq(int irq, void *dev_id)
1130{
1131 struct msmsdcc_host *host = dev_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001132 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001133 uint32_t status;
1134
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001135 status = readl_relaxed(base + MMCISTATUS);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001136
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001137 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1138 (MCI_IRQ_PIO)) == 0)
1139 return IRQ_NONE;
1140
1141#if IRQ_DEBUG
1142 msmsdcc_print_status(host, "irq1-r", status);
1143#endif
1144
1145 spin_lock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001146
1147 do {
1148 unsigned long flags;
1149 unsigned int remain, len;
1150 char *buffer;
1151
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001152 if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_TXFIFOEMPTY
1153 | MCI_RXDATAAVLBL)))
1154 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001155
1156 /* Map the current scatter buffer */
1157 local_irq_save(flags);
1158 buffer = kmap_atomic(sg_page(host->pio.sg),
1159 KM_BIO_SRC_IRQ) + host->pio.sg->offset;
1160 buffer += host->pio.sg_off;
1161 remain = host->pio.sg->length - host->pio.sg_off;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001162
San Mehat9d2bd732009-09-22 16:44:22 -07001163 len = 0;
1164 if (status & MCI_RXACTIVE)
1165 len = msmsdcc_pio_read(host, buffer, remain);
1166 if (status & MCI_TXACTIVE)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001167 len = msmsdcc_pio_write(host, buffer, remain);
San Mehat9d2bd732009-09-22 16:44:22 -07001168
1169 /* Unmap the buffer */
1170 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
1171 local_irq_restore(flags);
1172
1173 host->pio.sg_off += len;
1174 host->curr.xfer_remain -= len;
1175 host->curr.data_xfered += len;
1176 remain -= len;
1177
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001178 if (remain) /* Done with this page? */
1179 break; /* Nope */
San Mehat9d2bd732009-09-22 16:44:22 -07001180
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001181 if (status & MCI_RXACTIVE && host->curr.user_pages)
1182 flush_dcache_page(sg_page(host->pio.sg));
San Mehat9d2bd732009-09-22 16:44:22 -07001183
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001184 if (!--host->pio.sg_len) {
1185 memset(&host->pio, 0, sizeof(host->pio));
1186 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001187 }
1188
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001189 /* Advance to next sg */
1190 host->pio.sg++;
1191 host->pio.sg_off = 0;
1192
1193 status = readl_relaxed(base + MMCISTATUS);
San Mehat9d2bd732009-09-22 16:44:22 -07001194 } while (1);
1195
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001196 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
1197 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1198 (~(MCI_IRQ_PIO))) | MCI_RXDATAAVLBLMASK,
1199 host->base + MMCIMASK0);
1200 if (!host->curr.xfer_remain) {
1201 /* Delay needed (same port was just written) */
1202 msmsdcc_delay(host);
1203 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1204 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1205 }
1206 mb();
1207 } else if (!host->curr.xfer_remain) {
1208 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1209 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1210 mb();
1211 }
San Mehat9d2bd732009-09-22 16:44:22 -07001212
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001213 spin_unlock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001214
1215 return IRQ_HANDLED;
1216}
1217
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001218static void
1219msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq);
1220
1221static void msmsdcc_wait_for_rxdata(struct msmsdcc_host *host,
1222 struct mmc_data *data)
1223{
1224 u32 loop_cnt = 0;
1225
1226 /*
1227 * For read commands with data less than fifo size, it is possible to
1228 * get DATAEND first and RXDATA_AVAIL might be set later because of
1229 * synchronization delay through the asynchronous RX FIFO. Thus, for
1230 * such cases, even after DATAEND interrupt is received software
1231 * should poll for RXDATA_AVAIL until the requested data is read out
1232 * of FIFO. This change is needed to get around this abnormal but
1233 * sometimes expected behavior of SDCC3 controller.
1234 *
1235 * We can expect RXDATAAVAIL bit to be set after 6HCLK clock cycles
1236 * after the data is loaded into RX FIFO. This would amount to less
1237 * than a microsecond and thus looping for 1000 times is good enough
1238 * for that delay.
1239 */
1240 while (((int)host->curr.xfer_remain > 0) && (++loop_cnt < 1000)) {
1241 if (readl_relaxed(host->base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1242 spin_unlock(&host->lock);
1243 msmsdcc_pio_irq(1, host);
1244 spin_lock(&host->lock);
1245 }
1246 }
1247 if (loop_cnt == 1000) {
1248 pr_info("%s: Timed out while polling for Rx Data\n",
1249 mmc_hostname(host->mmc));
1250 data->error = -ETIMEDOUT;
1251 msmsdcc_reset_and_restore(host);
1252 }
1253}
1254
San Mehat9d2bd732009-09-22 16:44:22 -07001255static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
1256{
1257 struct mmc_command *cmd = host->curr.cmd;
San Mehat9d2bd732009-09-22 16:44:22 -07001258
1259 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001260 cmd->resp[0] = readl_relaxed(host->base + MMCIRESPONSE0);
1261 cmd->resp[1] = readl_relaxed(host->base + MMCIRESPONSE1);
1262 cmd->resp[2] = readl_relaxed(host->base + MMCIRESPONSE2);
1263 cmd->resp[3] = readl_relaxed(host->base + MMCIRESPONSE3);
San Mehat9d2bd732009-09-22 16:44:22 -07001264
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001265 if (status & (MCI_CMDTIMEOUT | MCI_AUTOCMD19TIMEOUT)) {
Sahitya Tummala5a0ae912011-07-18 13:34:01 +05301266 pr_debug("%s: Command timeout\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001267 cmd->error = -ETIMEDOUT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001268 } else if ((status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) &&
1269 !host->cmd19_tuning_in_progress) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001270 pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001271 cmd->error = -EILSEQ;
1272 }
1273
1274 if (!cmd->data || cmd->error) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001275 if (host->curr.data && host->dma.sg &&
1276 host->is_dma_mode)
San Mehat9d2bd732009-09-22 16:44:22 -07001277 msm_dmov_stop_cmd(host->dma.channel,
1278 &host->dma.hdr, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001279 else if (host->curr.data && host->sps.sg &&
1280 host->is_sps_mode){
1281 /* Stop current SPS transfer */
1282 msmsdcc_sps_exit_curr_xfer(host);
1283 }
San Mehat9d2bd732009-09-22 16:44:22 -07001284 else if (host->curr.data) { /* Non DMA */
Sahitya Tummalab08bb352010-12-08 15:03:05 +05301285 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -07001286 msmsdcc_stop_data(host);
1287 msmsdcc_request_end(host, cmd->mrq);
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301288 } else { /* host->data == NULL */
1289 if (!cmd->error && host->prog_enable) {
1290 if (status & MCI_PROGDONE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001291 host->prog_scan = 0;
1292 host->prog_enable = 0;
1293 msmsdcc_request_end(host, cmd->mrq);
1294 } else
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301295 host->curr.cmd = cmd;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301296 } else {
1297 if (host->prog_enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001298 host->prog_scan = 0;
1299 host->prog_enable = 0;
1300 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001301 if (host->dummy_52_needed)
1302 host->dummy_52_needed = 0;
1303 if (cmd->data && cmd->error)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001304 msmsdcc_reset_and_restore(host);
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301305 msmsdcc_request_end(host, cmd->mrq);
1306 }
1307 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001308 } else if (cmd->data) {
San Mehat56a8b5b2009-11-21 12:29:46 -08001309 if (!(cmd->data->flags & MMC_DATA_READ))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001310 msmsdcc_start_data(host, cmd->data, NULL, 0);
Joe Perchesb5a74d62009-09-22 16:44:25 -07001311 }
1312}
1313
San Mehat9d2bd732009-09-22 16:44:22 -07001314static irqreturn_t
1315msmsdcc_irq(int irq, void *dev_id)
1316{
1317 struct msmsdcc_host *host = dev_id;
San Mehat9d2bd732009-09-22 16:44:22 -07001318 u32 status;
1319 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001320 int timer = 0;
San Mehat9d2bd732009-09-22 16:44:22 -07001321
1322 spin_lock(&host->lock);
1323
1324 do {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001325 struct mmc_command *cmd;
1326 struct mmc_data *data;
San Mehat9d2bd732009-09-22 16:44:22 -07001327
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001328 if (timer) {
1329 timer = 0;
1330 msmsdcc_delay(host);
1331 }
San Mehat865c8062009-11-13 13:42:06 -08001332
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001333 if (!host->clks_on) {
1334 pr_debug("%s: %s: SDIO async irq received\n",
1335 mmc_hostname(host->mmc), __func__);
1336 host->mmc->ios.clock = host->clk_rate;
1337 spin_unlock(&host->lock);
1338 host->mmc->ops->set_ios(host->mmc, &host->mmc->ios);
1339 spin_lock(&host->lock);
1340 if (host->plat->cfg_mpm_sdiowakeup &&
1341 (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1342 wake_lock(&host->sdio_wlock);
1343 /* only ansyc interrupt can come when clocks are off */
1344 writel_relaxed(MCI_SDIOINTMASK, host->base + MMCICLEAR);
1345 }
1346
1347 status = readl_relaxed(host->base + MMCISTATUS);
1348
1349 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1350 (~(MCI_IRQ_PIO))) == 0)
San Mehat865c8062009-11-13 13:42:06 -08001351 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001352
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001353#if IRQ_DEBUG
1354 msmsdcc_print_status(host, "irq0-r", status);
1355#endif
1356 status &= readl_relaxed(host->base + MMCIMASK0);
1357 writel_relaxed(status, host->base + MMCICLEAR);
1358 mb();
1359#if IRQ_DEBUG
1360 msmsdcc_print_status(host, "irq0-p", status);
1361#endif
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001362
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001363#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
1364 if (status & MCI_SDIOINTROPE) {
1365 if (host->sdcc_suspending)
1366 wake_lock(&host->sdio_suspend_wlock);
1367 mmc_signal_sdio_irq(host->mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07001368 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001369#endif
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001370 data = host->curr.data;
1371
1372 if (host->dummy_52_sent) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001373 if (status & (MCI_PROGDONE | MCI_CMDCRCFAIL |
1374 MCI_CMDTIMEOUT)) {
1375 if (status & MCI_CMDTIMEOUT)
1376 pr_debug("%s: dummy CMD52 timeout\n",
1377 mmc_hostname(host->mmc));
1378 if (status & MCI_CMDCRCFAIL)
1379 pr_debug("%s: dummy CMD52 CRC failed\n",
1380 mmc_hostname(host->mmc));
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001381 host->dummy_52_sent = 0;
1382 host->dummy_52_needed = 0;
1383 if (data) {
1384 msmsdcc_stop_data(host);
1385 msmsdcc_request_end(host, data->mrq);
1386 }
1387 WARN(!data, "No data cmd for dummy CMD52\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001388 spin_unlock(&host->lock);
1389 return IRQ_HANDLED;
1390 }
1391 break;
1392 }
1393
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001394 /*
1395 * Check for proper command response
1396 */
1397 cmd = host->curr.cmd;
1398 if ((status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
1399 MCI_CMDTIMEOUT | MCI_PROGDONE |
1400 MCI_AUTOCMD19TIMEOUT)) && host->curr.cmd) {
1401 msmsdcc_do_cmdirq(host, status);
1402 }
1403
1404 if (data) {
1405 /* Check for data errors */
1406 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|
1407 MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
1408 msmsdcc_data_err(host, data, status);
1409 host->curr.data_xfered = 0;
1410 if (host->dma.sg && host->is_dma_mode)
1411 msm_dmov_stop_cmd(host->dma.channel,
1412 &host->dma.hdr, 0);
1413 else if (host->sps.sg && host->is_sps_mode) {
1414 /* Stop current SPS transfer */
1415 msmsdcc_sps_exit_curr_xfer(host);
1416 }
1417 else {
1418 msmsdcc_reset_and_restore(host);
1419 if (host->curr.data)
1420 msmsdcc_stop_data(host);
1421 if (!data->stop)
1422 timer |=
1423 msmsdcc_request_end(host,
1424 data->mrq);
1425 else {
1426 msmsdcc_start_command(host,
1427 data->stop,
1428 0);
1429 timer = 1;
1430 }
1431 }
1432 }
1433
1434 /* Check for data done */
1435 if (!host->curr.got_dataend && (status & MCI_DATAEND))
1436 host->curr.got_dataend = 1;
1437
1438 if (host->curr.got_dataend) {
1439 /*
1440 * If DMA is still in progress, we complete
1441 * via the completion handler
1442 */
1443 if (!host->dma.busy && !host->sps.busy) {
1444 /*
1445 * There appears to be an issue in the
1446 * controller where if you request a
1447 * small block transfer (< fifo size),
1448 * you may get your DATAEND/DATABLKEND
1449 * irq without the PIO data irq.
1450 *
1451 * Check to see if theres still data
1452 * to be read, and simulate a PIO irq.
1453 */
1454 if (data->flags & MMC_DATA_READ)
1455 msmsdcc_wait_for_rxdata(host,
1456 data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001457 if (!data->error) {
1458 host->curr.data_xfered =
1459 host->curr.xfer_size;
1460 host->curr.xfer_remain -=
1461 host->curr.xfer_size;
1462 }
1463
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001464 if (!host->dummy_52_needed) {
1465 msmsdcc_stop_data(host);
1466 if (!data->stop) {
1467 msmsdcc_request_end(
1468 host,
1469 data->mrq);
1470 } else {
1471 msmsdcc_start_command(
1472 host,
1473 data->stop, 0);
1474 timer = 1;
1475 }
1476 } else {
1477 host->dummy_52_sent = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001478 msmsdcc_start_command(host,
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001479 &dummy52cmd,
1480 MCI_CPSM_PROGENA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001481 }
1482 }
1483 }
1484 }
1485
San Mehat9d2bd732009-09-22 16:44:22 -07001486 ret = 1;
1487 } while (status);
1488
1489 spin_unlock(&host->lock);
1490
San Mehat9d2bd732009-09-22 16:44:22 -07001491 return IRQ_RETVAL(ret);
1492}
1493
1494static void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001495msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
1496{
1497 if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
1498 /* Queue/read data, daisy-chain command when data starts */
1499 msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
1500 } else {
1501 msmsdcc_start_command(host, mrq->cmd, 0);
1502 }
1503}
1504
1505static void
San Mehat9d2bd732009-09-22 16:44:22 -07001506msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
1507{
1508 struct msmsdcc_host *host = mmc_priv(mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001509 unsigned long flags;
San Mehat9d2bd732009-09-22 16:44:22 -07001510
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001511 /*
1512 * Get the SDIO AL client out of LPM.
1513 */
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001514 WARN(host->dummy_52_sent, "Dummy CMD52 in progress\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001515 if (host->plat->is_sdio_al_client)
1516 msmsdcc_sdio_al_lpm(mmc, false);
San Mehat9d2bd732009-09-22 16:44:22 -07001517
1518 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001519 WARN(host->curr.mrq, "Request in progress\n");
1520 WARN(!host->pwr, "SDCC power is turned off\n");
1521 WARN(!host->clks_on, "SDCC clocks are turned off\n");
1522 WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
San Mehat9d2bd732009-09-22 16:44:22 -07001523
1524 if (host->eject) {
1525 if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) {
1526 mrq->cmd->error = 0;
1527 mrq->data->bytes_xfered = mrq->data->blksz *
1528 mrq->data->blocks;
1529 } else
1530 mrq->cmd->error = -ENOMEDIUM;
1531
1532 spin_unlock_irqrestore(&host->lock, flags);
1533 mmc_request_done(mmc, mrq);
1534 return;
1535 }
1536
1537 host->curr.mrq = mrq;
1538
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001539 if (host->plat->dummy52_required) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001540 if (mrq->data && mrq->data->flags == MMC_DATA_WRITE) {
1541 if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001542 mrq->cmd->opcode == 54) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001543 host->dummy_52_needed = 1;
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001544 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001545 }
San Mehat9d2bd732009-09-22 16:44:22 -07001546 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001547 msmsdcc_request_start(host, mrq);
San Mehat9d2bd732009-09-22 16:44:22 -07001548 spin_unlock_irqrestore(&host->lock, flags);
1549}
1550
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001551static inline int msmsdcc_vreg_set_voltage(struct msm_mmc_reg_data *vreg,
1552 int min_uV, int max_uV)
1553{
1554 int rc = 0;
1555
1556 if (vreg->set_voltage_sup) {
1557 rc = regulator_set_voltage(vreg->reg, min_uV, max_uV);
1558 if (rc) {
1559 pr_err("%s: regulator_set_voltage(%s) failed."
1560 " min_uV=%d, max_uV=%d, rc=%d\n",
1561 __func__, vreg->name, min_uV, max_uV, rc);
1562 }
1563 }
1564
1565 return rc;
1566}
1567
1568static inline int msmsdcc_vreg_set_optimum_mode(struct msm_mmc_reg_data *vreg,
1569 int uA_load)
1570{
1571 int rc = 0;
1572
1573 rc = regulator_set_optimum_mode(vreg->reg, uA_load);
1574 if (rc < 0)
1575 pr_err("%s: regulator_set_optimum_mode(reg=%s, uA_load=%d)"
1576 " failed. rc=%d\n", __func__, vreg->name,
1577 uA_load, rc);
1578 else
1579 /* regulator_set_optimum_mode() can return non zero value
1580 * even for success case.
1581 */
1582 rc = 0;
1583
1584 return rc;
1585}
1586
1587static inline int msmsdcc_vreg_init_reg(struct msm_mmc_reg_data *vreg,
1588 struct device *dev)
1589{
1590 int rc = 0;
1591
1592 /* check if regulator is already initialized? */
1593 if (vreg->reg)
1594 goto out;
1595
1596 /* Get the regulator handle */
1597 vreg->reg = regulator_get(dev, vreg->name);
1598 if (IS_ERR(vreg->reg)) {
1599 rc = PTR_ERR(vreg->reg);
1600 pr_err("%s: regulator_get(%s) failed. rc=%d\n",
1601 __func__, vreg->name, rc);
1602 }
1603out:
1604 return rc;
1605}
1606
1607static inline void msmsdcc_vreg_deinit_reg(struct msm_mmc_reg_data *vreg)
1608{
1609 if (vreg->reg)
1610 regulator_put(vreg->reg);
1611}
1612
1613/* This init function should be called only once for each SDCC slot */
1614static int msmsdcc_vreg_init(struct msmsdcc_host *host, bool is_init)
1615{
1616 int rc = 0;
1617 struct msm_mmc_slot_reg_data *curr_slot;
1618 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1619 struct device *dev = mmc_dev(host->mmc);
1620
1621 curr_slot = host->plat->vreg_data;
1622 if (!curr_slot)
1623 goto out;
1624
1625 curr_vdd_reg = curr_slot->vdd_data;
1626 curr_vccq_reg = curr_slot->vccq_data;
1627 curr_vddp_reg = curr_slot->vddp_data;
1628
1629 if (is_init) {
1630 /*
1631 * Get the regulator handle from voltage regulator framework
1632 * and then try to set the voltage level for the regulator
1633 */
1634 if (curr_vdd_reg) {
1635 rc = msmsdcc_vreg_init_reg(curr_vdd_reg, dev);
1636 if (rc)
1637 goto out;
1638 }
1639 if (curr_vccq_reg) {
1640 rc = msmsdcc_vreg_init_reg(curr_vccq_reg, dev);
1641 if (rc)
1642 goto vdd_reg_deinit;
1643 }
1644 if (curr_vddp_reg) {
1645 rc = msmsdcc_vreg_init_reg(curr_vddp_reg, dev);
1646 if (rc)
1647 goto vccq_reg_deinit;
1648 }
1649 goto out;
1650 } else {
1651 /* Deregister all regulators from regulator framework */
1652 goto vddp_reg_deinit;
1653 }
1654vddp_reg_deinit:
1655 if (curr_vddp_reg)
1656 msmsdcc_vreg_deinit_reg(curr_vddp_reg);
1657vccq_reg_deinit:
1658 if (curr_vccq_reg)
1659 msmsdcc_vreg_deinit_reg(curr_vccq_reg);
1660vdd_reg_deinit:
1661 if (curr_vdd_reg)
1662 msmsdcc_vreg_deinit_reg(curr_vdd_reg);
1663out:
1664 return rc;
1665}
1666
1667static int msmsdcc_vreg_enable(struct msm_mmc_reg_data *vreg)
1668{
1669 int rc = 0;
1670
Subhash Jadavanicc922692011-08-01 23:05:01 +05301671 /* Put regulator in HPM (high power mode) */
1672 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->hpm_uA);
1673 if (rc < 0)
1674 goto out;
1675
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001676 if (!vreg->is_enabled) {
1677 /* Set voltage level */
1678 rc = msmsdcc_vreg_set_voltage(vreg, vreg->level,
1679 vreg->level);
1680 if (rc)
1681 goto out;
1682
1683 rc = regulator_enable(vreg->reg);
1684 if (rc) {
1685 pr_err("%s: regulator_enable(%s) failed. rc=%d\n",
1686 __func__, vreg->name, rc);
1687 goto out;
1688 }
1689 vreg->is_enabled = true;
1690 }
1691
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001692out:
1693 return rc;
1694}
1695
1696static int msmsdcc_vreg_disable(struct msm_mmc_reg_data *vreg)
1697{
1698 int rc = 0;
1699
1700 /* Never disable regulator marked as always_on */
1701 if (vreg->is_enabled && !vreg->always_on) {
1702 rc = regulator_disable(vreg->reg);
1703 if (rc) {
1704 pr_err("%s: regulator_disable(%s) failed. rc=%d\n",
1705 __func__, vreg->name, rc);
1706 goto out;
1707 }
1708 vreg->is_enabled = false;
1709
1710 rc = msmsdcc_vreg_set_optimum_mode(vreg, 0);
1711 if (rc < 0)
1712 goto out;
1713
1714 /* Set min. voltage level to 0 */
1715 rc = msmsdcc_vreg_set_voltage(vreg, 0, vreg->level);
1716 if (rc)
1717 goto out;
1718 } else if (vreg->is_enabled && vreg->always_on && vreg->lpm_sup) {
1719 /* Put always_on regulator in LPM (low power mode) */
1720 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->lpm_uA);
1721 if (rc < 0)
1722 goto out;
1723 }
1724out:
1725 return rc;
1726}
1727
1728static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable)
1729{
1730 int rc = 0, i;
1731 struct msm_mmc_slot_reg_data *curr_slot;
1732 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1733 struct msm_mmc_reg_data *vreg_table[3];
1734
1735 curr_slot = host->plat->vreg_data;
1736 if (!curr_slot)
1737 goto out;
1738
1739 curr_vdd_reg = vreg_table[0] = curr_slot->vdd_data;
1740 curr_vccq_reg = vreg_table[1] = curr_slot->vccq_data;
1741 curr_vddp_reg = vreg_table[2] = curr_slot->vddp_data;
1742
1743 for (i = 0; i < ARRAY_SIZE(vreg_table); i++) {
1744 if (vreg_table[i]) {
1745 if (enable)
1746 rc = msmsdcc_vreg_enable(vreg_table[i]);
1747 else
1748 rc = msmsdcc_vreg_disable(vreg_table[i]);
1749 if (rc)
1750 goto out;
1751 }
1752 }
1753out:
1754 return rc;
1755}
1756
1757static int msmsdcc_tune_vdd_pad_level(struct msmsdcc_host *host, int level)
1758{
1759 int rc = 0;
1760
1761 if (host->plat->vreg_data) {
1762 struct msm_mmc_reg_data *vddp_reg =
1763 host->plat->vreg_data->vddp_data;
1764
1765 if (vddp_reg && vddp_reg->is_enabled)
1766 rc = msmsdcc_vreg_set_voltage(vddp_reg, level, level);
1767 }
1768
1769 return rc;
1770}
1771
1772static inline int msmsdcc_is_pwrsave(struct msmsdcc_host *host)
1773{
1774 if (host->clk_rate > 400000 && msmsdcc_pwrsave)
1775 return 1;
1776 return 0;
1777}
1778
1779static inline void msmsdcc_setup_clocks(struct msmsdcc_host *host, bool enable)
1780{
1781 if (enable) {
1782 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1783 clk_enable(host->dfab_pclk);
1784 if (!IS_ERR(host->pclk))
1785 clk_enable(host->pclk);
1786 clk_enable(host->clk);
1787 } else {
1788 clk_disable(host->clk);
1789 if (!IS_ERR(host->pclk))
1790 clk_disable(host->pclk);
1791 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1792 clk_disable(host->dfab_pclk);
1793 }
1794}
1795
1796static inline unsigned int msmsdcc_get_sup_clk_rate(struct msmsdcc_host *host,
1797 unsigned int req_clk)
1798{
1799 unsigned int sel_clk = -1;
1800
1801 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt) {
1802 unsigned char cnt;
1803
1804 for (cnt = 0; cnt < host->plat->sup_clk_cnt; cnt++) {
1805 if (host->plat->sup_clk_table[cnt] > req_clk)
1806 break;
1807 else if (host->plat->sup_clk_table[cnt] == req_clk) {
1808 sel_clk = host->plat->sup_clk_table[cnt];
1809 break;
1810 } else
1811 sel_clk = host->plat->sup_clk_table[cnt];
1812 }
1813 } else {
1814 if ((req_clk < host->plat->msmsdcc_fmax) &&
1815 (req_clk > host->plat->msmsdcc_fmid))
1816 sel_clk = host->plat->msmsdcc_fmid;
1817 else
1818 sel_clk = req_clk;
1819 }
1820
1821 return sel_clk;
1822}
1823
1824static inline unsigned int msmsdcc_get_min_sup_clk_rate(
1825 struct msmsdcc_host *host)
1826{
1827 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1828 return host->plat->sup_clk_table[0];
1829 else
1830 return host->plat->msmsdcc_fmin;
1831}
1832
1833static inline unsigned int msmsdcc_get_max_sup_clk_rate(
1834 struct msmsdcc_host *host)
1835{
1836 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1837 return host->plat->sup_clk_table[host->plat->sup_clk_cnt - 1];
1838 else
1839 return host->plat->msmsdcc_fmax;
1840}
1841
1842static int msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
Sahitya Tummala7a892482011-01-18 11:22:49 +05301843{
1844 struct msm_mmc_gpio_data *curr;
1845 int i, rc = 0;
1846
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001847 curr = host->plat->pin_data->gpio_data;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301848 for (i = 0; i < curr->size; i++) {
1849 if (enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001850 if (curr->gpio[i].is_always_on &&
1851 curr->gpio[i].is_enabled)
1852 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301853 rc = gpio_request(curr->gpio[i].no,
1854 curr->gpio[i].name);
1855 if (rc) {
1856 pr_err("%s: gpio_request(%d, %s) failed %d\n",
1857 mmc_hostname(host->mmc),
1858 curr->gpio[i].no,
1859 curr->gpio[i].name, rc);
1860 goto free_gpios;
1861 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001862 curr->gpio[i].is_enabled = true;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301863 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001864 if (curr->gpio[i].is_always_on)
1865 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301866 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001867 curr->gpio[i].is_enabled = false;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301868 }
1869 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001870 goto out;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301871
1872free_gpios:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001873 for (; i >= 0; i--) {
Sahitya Tummala7a892482011-01-18 11:22:49 +05301874 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001875 curr->gpio[i].is_enabled = false;
1876 }
1877out:
1878 return rc;
1879}
1880
1881static int msmsdcc_setup_pad(struct msmsdcc_host *host, bool enable)
1882{
1883 struct msm_mmc_pad_data *curr;
1884 int i;
1885
1886 curr = host->plat->pin_data->pad_data;
1887 for (i = 0; i < curr->drv->size; i++) {
1888 if (enable)
1889 msm_tlmm_set_hdrive(curr->drv->on[i].no,
1890 curr->drv->on[i].val);
1891 else
1892 msm_tlmm_set_hdrive(curr->drv->off[i].no,
1893 curr->drv->off[i].val);
1894 }
1895
1896 for (i = 0; i < curr->pull->size; i++) {
1897 if (enable)
1898 msm_tlmm_set_hdrive(curr->pull->on[i].no,
1899 curr->pull->on[i].val);
1900 else
1901 msm_tlmm_set_hdrive(curr->pull->off[i].no,
1902 curr->pull->off[i].val);
1903 }
1904
1905 return 0;
1906}
1907
1908static u32 msmsdcc_setup_pins(struct msmsdcc_host *host, bool enable)
1909{
1910 int rc = 0;
1911
1912 if (!host->plat->pin_data || host->plat->pin_data->cfg_sts == enable)
1913 return 0;
1914
1915 if (host->plat->pin_data->is_gpio)
1916 rc = msmsdcc_setup_gpio(host, enable);
1917 else
1918 rc = msmsdcc_setup_pad(host, enable);
1919
1920 if (!rc)
1921 host->plat->pin_data->cfg_sts = enable;
1922
1923 return rc;
1924}
1925
1926static void msmsdcc_enable_irq_wake(struct msmsdcc_host *host)
1927{
1928 unsigned int wakeup_irq;
1929
1930 wakeup_irq = (host->plat->sdiowakeup_irq) ?
1931 host->plat->sdiowakeup_irq :
1932 host->core_irqres->start;
1933
1934 if (!host->irq_wake_enabled) {
1935 enable_irq_wake(wakeup_irq);
1936 host->irq_wake_enabled = true;
1937 }
1938}
1939
1940static void msmsdcc_disable_irq_wake(struct msmsdcc_host *host)
1941{
1942 unsigned int wakeup_irq;
1943
1944 wakeup_irq = (host->plat->sdiowakeup_irq) ?
1945 host->plat->sdiowakeup_irq :
1946 host->core_irqres->start;
1947
1948 if (host->irq_wake_enabled) {
1949 disable_irq_wake(wakeup_irq);
1950 host->irq_wake_enabled = false;
1951 }
Sahitya Tummala7a892482011-01-18 11:22:49 +05301952}
1953
San Mehat9d2bd732009-09-22 16:44:22 -07001954static void
1955msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1956{
1957 struct msmsdcc_host *host = mmc_priv(mmc);
1958 u32 clk = 0, pwr = 0;
1959 int rc;
San Mehat4adbbcc2009-11-08 13:00:37 -08001960 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001961 unsigned int clock;
San Mehat9d2bd732009-09-22 16:44:22 -07001962
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001963 DBG(host, "ios->clock = %u\n", ios->clock);
Sahitya Tummala7a892482011-01-18 11:22:49 +05301964
San Mehat9d2bd732009-09-22 16:44:22 -07001965 if (ios->clock) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001966 spin_lock_irqsave(&host->lock, flags);
1967 if (!host->clks_on) {
1968 msmsdcc_setup_clocks(host, true);
1969 host->clks_on = 1;
1970 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
1971 if (!host->plat->sdiowakeup_irq) {
1972 writel_relaxed(host->mci_irqenable,
1973 host->base + MMCIMASK0);
1974 mb();
1975 if (host->plat->cfg_mpm_sdiowakeup &&
1976 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1977 host->plat->cfg_mpm_sdiowakeup(
1978 mmc_dev(mmc), SDC_DAT1_DISWAKE);
1979 msmsdcc_disable_irq_wake(host);
1980 } else if (!(mmc->pm_flags &
1981 MMC_PM_WAKE_SDIO_IRQ)) {
1982 writel_relaxed(host->mci_irqenable,
1983 host->base + MMCIMASK0);
1984 }
1985 }
San Mehat9d2bd732009-09-22 16:44:22 -07001986 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001987 spin_unlock_irqrestore(&host->lock, flags);
1988
1989 clock = msmsdcc_get_sup_clk_rate(host, ios->clock);
1990 /*
1991 * For DDR50 mode, controller needs clock rate to be
1992 * double than what is required on the SD card CLK pin.
1993 */
Subhash Jadavanib808efac2011-06-27 15:14:07 -07001994 if (ios->ddr || (ios->timing == MMC_TIMING_UHS_DDR50)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001995 /*
1996 * Make sure that we don't double the clock if
1997 * doubled clock rate is already set
1998 */
1999 if (!host->ddr_doubled_clk_rate ||
2000 (host->ddr_doubled_clk_rate &&
2001 (host->ddr_doubled_clk_rate != ios->clock))) {
2002 host->ddr_doubled_clk_rate =
2003 msmsdcc_get_sup_clk_rate(
2004 host, (ios->clock * 2));
2005 clock = host->ddr_doubled_clk_rate;
2006 }
2007 } else {
2008 host->ddr_doubled_clk_rate = 0;
2009 }
2010
2011 if (clock != host->clk_rate) {
2012 rc = clk_set_rate(host->clk, clock);
2013 if (rc < 0)
2014 pr_debug("%s: failed to set clk rate %u\n",
2015 mmc_hostname(mmc), clock);
2016 host->clk_rate = clock;
2017 }
2018 /*
2019 * give atleast 2 MCLK cycles delay for clocks
2020 * and SDCC core to stabilize
2021 */
2022 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002023 clk |= MCI_CLK_ENABLE;
2024 }
2025
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002026 if (ios->bus_width == MMC_BUS_WIDTH_8)
2027 clk |= MCI_CLK_WIDEBUS_8;
2028 else if (ios->bus_width == MMC_BUS_WIDTH_4)
2029 clk |= MCI_CLK_WIDEBUS_4;
2030 else
2031 clk |= MCI_CLK_WIDEBUS_1;
San Mehat9d2bd732009-09-22 16:44:22 -07002032
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002033 if (msmsdcc_is_pwrsave(host))
2034 clk |= MCI_CLK_PWRSAVE;
San Mehat9d2bd732009-09-22 16:44:22 -07002035
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002036 clk |= MCI_CLK_FLOWENA;
San Mehat9d2bd732009-09-22 16:44:22 -07002037
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002038 host->tuning_needed = 0;
2039 /*
2040 * Select the controller timing mode according
2041 * to current bus speed mode
2042 */
2043 if ((ios->timing == MMC_TIMING_UHS_SDR104) ||
2044 (ios->timing == MMC_TIMING_UHS_SDR50)) {
2045 clk |= (4 << 14);
2046 host->tuning_needed = 1;
Subhash Jadavanib808efac2011-06-27 15:14:07 -07002047 } else if (ios->ddr || ios->timing == MMC_TIMING_UHS_DDR50) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002048 clk |= (3 << 14);
2049 } else {
2050 clk |= (2 << 14); /* feedback clock */
2051 }
2052
2053 /* Select free running MCLK as input clock of cm_dll_sdc4 */
2054 clk |= (2 << 23);
2055
2056 if (host->io_pad_pwr_switch)
2057 clk |= IO_PAD_PWR_SWITCH;
2058
2059 if (host->plat->translate_vdd && !host->sdio_gpio_lpm)
San Mehat9d2bd732009-09-22 16:44:22 -07002060 pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002061 else if (!host->plat->translate_vdd && !host->sdio_gpio_lpm)
2062 pwr |= msmsdcc_setup_vreg(host, !!ios->vdd);
San Mehat9d2bd732009-09-22 16:44:22 -07002063
2064 switch (ios->power_mode) {
2065 case MMC_POWER_OFF:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002066 htc_pwrsink_set(PWRSINK_SDCARD, 0);
2067 if (!host->sdcc_irq_disabled) {
2068 if (host->plat->cfg_mpm_sdiowakeup)
2069 host->plat->cfg_mpm_sdiowakeup(
2070 mmc_dev(mmc), SDC_DAT1_DISABLE);
2071 disable_irq(host->core_irqres->start);
2072 host->sdcc_irq_disabled = 1;
2073 }
2074 msmsdcc_setup_pins(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07002075 break;
2076 case MMC_POWER_UP:
2077 pwr |= MCI_PWR_UP;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002078 if (host->sdcc_irq_disabled) {
2079 if (host->plat->cfg_mpm_sdiowakeup)
2080 host->plat->cfg_mpm_sdiowakeup(
2081 mmc_dev(mmc), SDC_DAT1_ENABLE);
2082 enable_irq(host->core_irqres->start);
2083 host->sdcc_irq_disabled = 0;
2084 }
2085 msmsdcc_setup_pins(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07002086 break;
2087 case MMC_POWER_ON:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002088 htc_pwrsink_set(PWRSINK_SDCARD, 100);
San Mehat9d2bd732009-09-22 16:44:22 -07002089 pwr |= MCI_PWR_ON;
2090 break;
2091 }
2092
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002093 spin_lock_irqsave(&host->lock, flags);
2094 if (!host->clks_on) {
2095 /* force the clocks to be on */
2096 msmsdcc_setup_clocks(host, true);
2097 /*
2098 * give atleast 2 MCLK cycles delay for clocks
2099 * and SDCC core to stabilize
2100 */
2101 msmsdcc_delay(host);
2102 }
2103 writel_relaxed(clk, host->base + MMCICLOCK);
2104 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002105
2106 if (host->pwr != pwr) {
2107 host->pwr = pwr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002108 writel_relaxed(pwr, host->base + MMCIPOWER);
2109 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07002110 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002111 if (!host->clks_on) {
2112 /* force the clocks to be off */
2113 msmsdcc_setup_clocks(host, false);
2114 /*
2115 * give atleast 2 MCLK cycles delay for clocks
2116 * and SDCC core to stabilize
2117 */
2118 msmsdcc_delay(host);
2119 }
2120
2121 if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
2122 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
2123 if (!host->plat->sdiowakeup_irq) {
2124 writel_relaxed(MCI_SDIOINTMASK,
2125 host->base + MMCIMASK0);
2126 mb();
2127 if (host->plat->cfg_mpm_sdiowakeup &&
2128 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
2129 host->plat->cfg_mpm_sdiowakeup(
2130 mmc_dev(mmc), SDC_DAT1_ENWAKE);
2131 msmsdcc_enable_irq_wake(host);
2132 } else if (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2133 writel_relaxed(0, host->base + MMCIMASK0);
2134 } else {
2135 writel_relaxed(MCI_SDIOINTMASK,
2136 host->base + MMCIMASK0);
2137 }
2138 msmsdcc_delay(host);
2139 }
2140 msmsdcc_setup_clocks(host, false);
2141 host->clks_on = 0;
2142 }
San Mehat4adbbcc2009-11-08 13:00:37 -08002143 spin_unlock_irqrestore(&host->lock, flags);
San Mehat9d2bd732009-09-22 16:44:22 -07002144}
2145
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002146int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave)
2147{
2148 struct msmsdcc_host *host = mmc_priv(mmc);
2149 u32 clk;
2150
2151 clk = readl_relaxed(host->base + MMCICLOCK);
2152 pr_debug("Changing to pwr_save=%d", pwrsave);
2153 if (pwrsave && msmsdcc_is_pwrsave(host))
2154 clk |= MCI_CLK_PWRSAVE;
2155 else
2156 clk &= ~MCI_CLK_PWRSAVE;
2157 writel_relaxed(clk, host->base + MMCICLOCK);
2158 mb();
2159
2160 return 0;
2161}
2162
2163static int msmsdcc_get_ro(struct mmc_host *mmc)
2164{
2165 int status = -ENOSYS;
2166 struct msmsdcc_host *host = mmc_priv(mmc);
2167
2168 if (host->plat->wpswitch) {
2169 status = host->plat->wpswitch(mmc_dev(mmc));
2170 } else if (host->plat->wpswitch_gpio) {
2171 status = gpio_request(host->plat->wpswitch_gpio,
2172 "SD_WP_Switch");
2173 if (status) {
2174 pr_err("%s: %s: Failed to request GPIO %d\n",
2175 mmc_hostname(mmc), __func__,
2176 host->plat->wpswitch_gpio);
2177 } else {
2178 status = gpio_direction_input(
2179 host->plat->wpswitch_gpio);
2180 if (!status) {
2181 /*
2182 * Wait for atleast 300ms as debounce
2183 * time for GPIO input to stabilize.
2184 */
2185 msleep(300);
2186 status = gpio_get_value_cansleep(
2187 host->plat->wpswitch_gpio);
2188 status ^= !host->plat->wpswitch_polarity;
2189 }
2190 gpio_free(host->plat->wpswitch_gpio);
2191 }
2192 }
2193
2194 if (status < 0)
2195 status = -ENOSYS;
2196 pr_debug("%s: Card read-only status %d\n", __func__, status);
2197
2198 return status;
2199}
2200
2201#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002202static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
2203{
2204 struct msmsdcc_host *host = mmc_priv(mmc);
2205 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002206
2207 if (enable) {
2208 spin_lock_irqsave(&host->lock, flags);
2209 host->mci_irqenable |= MCI_SDIOINTOPERMASK;
2210 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) |
2211 MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2212 spin_unlock_irqrestore(&host->lock, flags);
2213 } else {
2214 host->mci_irqenable &= ~MCI_SDIOINTOPERMASK;
2215 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) &
2216 ~MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2217 }
2218 mb();
2219}
2220#endif /* CONFIG_MMC_MSM_SDIO_SUPPORT */
2221
2222#ifdef CONFIG_PM_RUNTIME
2223static int msmsdcc_enable(struct mmc_host *mmc)
2224{
2225 int rc;
2226 struct device *dev = mmc->parent;
2227
2228 if (atomic_read(&dev->power.usage_count) > 0) {
2229 pm_runtime_get_noresume(dev);
2230 goto out;
2231 }
2232
2233 rc = pm_runtime_get_sync(dev);
2234
2235 if (rc < 0) {
2236 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2237 __func__, rc);
2238 return rc;
2239 }
2240out:
2241 return 0;
2242}
2243
2244static int msmsdcc_disable(struct mmc_host *mmc, int lazy)
2245{
2246 int rc;
2247
2248 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO)
2249 return -ENOTSUPP;
2250
2251 rc = pm_runtime_put_sync(mmc->parent);
2252
2253 if (rc < 0)
2254 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2255 __func__, rc);
2256 return rc;
2257}
2258#else
2259#define msmsdcc_enable NULL
2260#define msmsdcc_disable NULL
2261#endif
2262
2263static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
2264 struct mmc_ios *ios)
2265{
2266 struct msmsdcc_host *host = mmc_priv(mmc);
2267 unsigned long flags;
2268 int err = 0;
2269
2270 if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
2271 /* Change voltage level of VDDPX to high voltage */
2272 if (msmsdcc_tune_vdd_pad_level(host, 2950000)) {
2273 pr_err("%s: %s: failed to change vddp level to %d",
2274 mmc_hostname(mmc), __func__, 2950000);
2275 }
2276 goto out;
2277 } else if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
2278 /* invalid selection. don't do anything */
2279 goto out;
2280 }
San Mehat9d2bd732009-09-22 16:44:22 -07002281
2282 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002283 /*
2284 * If we are here means voltage switch from high voltage to
2285 * low voltage is required
2286 */
2287
2288 /*
2289 * Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
2290 * register until they become all zeros.
2291 */
2292 if (readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1)) {
2293 err = -EAGAIN;
2294 pr_err("%s: %s: MCIDATIN_3_0 is still not all zeros",
2295 mmc_hostname(mmc), __func__);
2296 goto out_unlock;
San Mehat9d2bd732009-09-22 16:44:22 -07002297 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002298
2299 /* Stop SD CLK output. */
2300 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2301 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2302
San Mehat9d2bd732009-09-22 16:44:22 -07002303 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002304
2305 /*
2306 * Switch VDDPX from high voltage to low voltage
2307 * to change the VDD of the SD IO pads.
2308 */
2309 if (msmsdcc_tune_vdd_pad_level(host, 1850000)) {
2310 pr_err("%s: %s: failed to change vddp level to %d",
2311 mmc_hostname(mmc), __func__, 1850000);
2312 goto out;
2313 }
2314
2315 spin_lock_irqsave(&host->lock, flags);
2316 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2317 IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
2318 host->io_pad_pwr_switch = 1;
2319 spin_unlock_irqrestore(&host->lock, flags);
2320
2321 /* Wait 5 ms for the voltage regulater in the card to become stable. */
2322 usleep_range(5000, 5500);
2323
2324 spin_lock_irqsave(&host->lock, flags);
2325 /* Start SD CLK output. */
2326 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2327 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2328 spin_unlock_irqrestore(&host->lock, flags);
2329
2330 /*
2331 * If MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT register
2332 * don't become all ones within 1 ms then a Voltage Switch
2333 * sequence has failed and a power cycle to the card is required.
2334 * Otherwise Voltage Switch sequence is completed successfully.
2335 */
2336 usleep_range(1000, 1500);
2337
2338 spin_lock_irqsave(&host->lock, flags);
2339 if ((readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1))
2340 != (0xF << 1)) {
2341 pr_err("%s: %s: MCIDATIN_3_0 are still not all ones",
2342 mmc_hostname(mmc), __func__);
2343 err = -EAGAIN;
2344 goto out_unlock;
2345 }
2346
2347out_unlock:
2348 spin_unlock_irqrestore(&host->lock, flags);
2349out:
2350 return err;
2351}
2352
2353static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2354 u8 phase);
2355/* Initialize the DLL (Programmable Delay Line ) */
2356static int msmsdcc_init_cm_sdc4_dll(struct msmsdcc_host *host)
2357{
2358 int rc = 0;
2359 u32 wait_timeout;
2360
2361 /* Write 0 to DLL_PDN bit of MCI_DLL_CONFIG register */
2362 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2363 & ~MCI_DLL_PDN), host->base + MCI_DLL_CONFIG);
2364
2365 /* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
2366 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2367 | MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2368
2369 msmsdcc_delay(host);
2370
2371 /* Write 0 to DLL_RST bit of MCI_DLL_CONFIG register */
2372 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2373 & ~MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2374
2375 /* Initialize the phase to 0 */
2376 rc = msmsdcc_config_cm_sdc4_dll_phase(host, 0);
2377 if (rc)
2378 goto out;
2379
2380 wait_timeout = 1000;
2381 /* Wait until DLL_LOCK bit of MCI_DLL_STATUS register becomes '1' */
2382 while (!(readl_relaxed(host->base + MCI_DLL_STATUS) & MCI_DLL_LOCK)) {
2383 /* max. wait for 1 sec for LOCK bit to be set */
2384 if (--wait_timeout == 0) {
2385 pr_err("%s: %s: DLL failed to lock at phase: %d",
2386 mmc_hostname(host->mmc), __func__, 0);
2387 rc = -1;
2388 goto out;
2389 }
2390 /* wait for 1ms */
2391 usleep_range(1000, 1500);
2392 }
2393out:
2394 return rc;
2395}
2396
2397/*
2398 * Enable a CDR circuit in CM_SDC4_DLL block to enable automatic
2399 * calibration sequence. This function should be called before
2400 * enabling AUTO_CMD19 bit in MCI_CMD register for block read
2401 * commands (CMD17/CMD18).
2402 */
2403static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host)
2404{
2405 /* Set CDR_EN bit to 1. */
2406 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG) |
2407 MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2408
2409 /* Set CDR_EXT_EN bit to 0. */
2410 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2411 & ~MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2412
2413 /* Set CK_OUT_EN bit to 0. */
2414 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2415 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2416
2417 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2418 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)
2419 ;
2420
2421 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2422 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2423 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2424
2425 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register is 1. */
2426 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN))
2427 ;
2428}
2429
2430static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2431 u8 phase)
2432{
2433 int rc = 0;
2434 u32 mclk_freq = 0;
2435 u32 wait_timeout;
2436
2437 /* Set CDR_EN bit to 0. */
2438 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2439 & ~MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2440
2441 /* Set CDR_EXT_EN bit to 1. */
2442 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2443 | MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2444
2445 /* Program the MCLK value to MCLK_FREQ bit field */
2446 if (host->clk_rate <= 112000000)
2447 mclk_freq = 0;
2448 else if (host->clk_rate <= 125000000)
2449 mclk_freq = 1;
2450 else if (host->clk_rate <= 137000000)
2451 mclk_freq = 2;
2452 else if (host->clk_rate <= 150000000)
2453 mclk_freq = 3;
2454 else if (host->clk_rate <= 162000000)
2455 mclk_freq = 4;
2456 else if (host->clk_rate <= 175000000)
2457 mclk_freq = 5;
2458 else if (host->clk_rate <= 187000000)
2459 mclk_freq = 6;
2460 else if (host->clk_rate <= 200000000)
2461 mclk_freq = 7;
2462
2463 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2464 & ~(7 << 24)) | (mclk_freq << 24)),
2465 host->base + MCI_DLL_CONFIG);
2466
2467 /* Set CK_OUT_EN bit to 0. */
2468 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2469 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2470
2471 /* Set DLL_EN bit to 1. */
2472 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2473 | MCI_DLL_EN), host->base + MCI_DLL_CONFIG);
2474
2475 wait_timeout = 1000;
2476 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2477 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN) {
2478 /* max. wait for 1 sec for LOCK bit for be set */
2479 if (--wait_timeout == 0) {
2480 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 0",
2481 mmc_hostname(host->mmc), __func__, phase);
2482 rc = -1;
2483 goto out;
2484 }
2485 /* wait for 1ms */
2486 usleep_range(1000, 1500);
2487 }
2488
2489 /*
2490 * Write the selected DLL clock output phase (0 ... 15)
2491 * to CDR_SELEXT bit field of MCI_DLL_CONFIG register.
2492 */
2493 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2494 & ~(0xF << 20)) | (phase << 20)),
2495 host->base + MCI_DLL_CONFIG);
2496
2497 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2498 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2499 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2500
2501 wait_timeout = 1000;
2502 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '1' */
2503 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)) {
2504 /* max. wait for 1 sec for LOCK bit for be set */
2505 if (--wait_timeout == 0) {
2506 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 1",
2507 mmc_hostname(host->mmc), __func__, phase);
2508 rc = -1;
2509 goto out;
2510 }
2511 /* wait for 1ms */
2512 usleep_range(1000, 1500);
2513 }
2514out:
2515 return rc;
2516}
2517
2518static int msmsdcc_execute_tuning(struct mmc_host *mmc)
2519{
2520 struct msmsdcc_host *host = mmc_priv(mmc);
2521 u8 phase;
2522 u8 *data_buf;
2523 u8 tuned_phases[16], tuned_phase_cnt = 0;
2524 int rc = 0;
2525
2526 /* Tuning is only required for SDR50 & SDR104 modes */
2527 if (!host->tuning_needed) {
2528 rc = 0;
2529 goto out;
2530 }
2531
2532 host->cmd19_tuning_in_progress = 1;
2533 /*
2534 * Make sure that clock is always enabled when DLL
2535 * tuning is in progress. Keeping PWRSAVE ON may
2536 * turn off the clock. So let's disable the PWRSAVE
2537 * here and re-enable it once tuning is completed.
2538 */
2539 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2540 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2541 /* first of all reset the tuning block */
2542 rc = msmsdcc_init_cm_sdc4_dll(host);
2543 if (rc)
2544 goto out;
2545
2546 data_buf = kmalloc(64, GFP_KERNEL);
2547 if (!data_buf) {
2548 rc = -ENOMEM;
2549 goto out;
2550 }
2551
2552 phase = 0;
2553 do {
2554 struct mmc_command cmd = {0};
2555 struct mmc_data data = {0};
2556 struct mmc_request mrq = {
2557 .cmd = &cmd,
2558 .data = &data
2559 };
2560 struct scatterlist sg;
2561
2562 /* set the phase in delay line hw block */
2563 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2564 if (rc)
2565 goto kfree;
2566
2567 cmd.opcode = MMC_SEND_TUNING_BLOCK;
2568 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
2569
2570 data.blksz = 64;
2571 data.blocks = 1;
2572 data.flags = MMC_DATA_READ;
2573 data.timeout_ns = 1000 * 1000 * 1000; /* 1 sec */
2574
2575 data.sg = &sg;
2576 data.sg_len = 1;
2577 sg_init_one(&sg, data_buf, 64);
2578 memset(data_buf, 0, 64);
2579 mmc_wait_for_req(mmc, &mrq);
2580
2581 if (!cmd.error && !data.error &&
2582 !memcmp(data_buf, cmd19_tuning_block, 64)) {
2583 /* tuning is successful with this tuning point */
2584 tuned_phases[tuned_phase_cnt++] = phase;
2585 }
2586 } while (++phase < 16);
2587
2588 kfree(data_buf);
2589
2590 if (tuned_phase_cnt) {
2591 tuned_phase_cnt--;
2592 tuned_phase_cnt = (tuned_phase_cnt * 3) / 4;
2593 phase = tuned_phases[tuned_phase_cnt];
2594 /*
2595 * Finally set the selected phase in delay
2596 * line hw block.
2597 */
2598 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2599 if (rc)
2600 goto out;
2601 } else {
2602 /* tuning failed */
2603 rc = -EAGAIN;
2604 pr_err("%s: %s: no tuning point found",
2605 mmc_hostname(mmc), __func__);
2606 }
2607 goto out;
2608
2609kfree:
2610 kfree(data_buf);
2611out:
2612 /* re-enable PWESAVE */
2613 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2614 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2615 host->cmd19_tuning_in_progress = 0;
2616 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -07002617}
2618
2619static const struct mmc_host_ops msmsdcc_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002620 .enable = msmsdcc_enable,
2621 .disable = msmsdcc_disable,
San Mehat9d2bd732009-09-22 16:44:22 -07002622 .request = msmsdcc_request,
2623 .set_ios = msmsdcc_set_ios,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002624 .get_ro = msmsdcc_get_ro,
2625#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002626 .enable_sdio_irq = msmsdcc_enable_sdio_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002627#endif
2628 .start_signal_voltage_switch = msmsdcc_start_signal_voltage_switch,
2629 .execute_tuning = msmsdcc_execute_tuning
San Mehat9d2bd732009-09-22 16:44:22 -07002630};
2631
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002632static unsigned int
2633msmsdcc_slot_status(struct msmsdcc_host *host)
2634{
2635 int status;
2636 unsigned int gpio_no = host->plat->status_gpio;
2637
2638 status = gpio_request(gpio_no, "SD_HW_Detect");
2639 if (status) {
2640 pr_err("%s: %s: Failed to request GPIO %d\n",
2641 mmc_hostname(host->mmc), __func__, gpio_no);
2642 } else {
2643 status = gpio_direction_input(gpio_no);
2644 if (!status)
2645 status = !gpio_get_value_cansleep(gpio_no);
2646 gpio_free(gpio_no);
2647 }
2648 return status;
2649}
2650
San Mehat9d2bd732009-09-22 16:44:22 -07002651static void
2652msmsdcc_check_status(unsigned long data)
2653{
2654 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
2655 unsigned int status;
2656
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002657 if (host->plat->status || host->plat->status_gpio) {
2658 if (host->plat->status)
2659 status = host->plat->status(mmc_dev(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07002660 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002661 status = msmsdcc_slot_status(host);
2662
2663 host->eject = !status;
2664 if (status ^ host->oldstat) {
2665 pr_info("%s: Slot status change detected (%d -> %d)\n",
2666 mmc_hostname(host->mmc), host->oldstat, status);
San Mehat9d2bd732009-09-22 16:44:22 -07002667 mmc_detect_change(host->mmc, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002668 }
2669 host->oldstat = status;
2670 } else {
2671 mmc_detect_change(host->mmc, 0);
San Mehat9d2bd732009-09-22 16:44:22 -07002672 }
San Mehat9d2bd732009-09-22 16:44:22 -07002673}
2674
2675static irqreturn_t
2676msmsdcc_platform_status_irq(int irq, void *dev_id)
2677{
2678 struct msmsdcc_host *host = dev_id;
2679
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002680 pr_debug("%s: %d\n", __func__, irq);
San Mehat9d2bd732009-09-22 16:44:22 -07002681 msmsdcc_check_status((unsigned long) host);
2682 return IRQ_HANDLED;
2683}
2684
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002685static irqreturn_t
2686msmsdcc_platform_sdiowakeup_irq(int irq, void *dev_id)
2687{
2688 struct msmsdcc_host *host = dev_id;
2689
2690 pr_debug("%s: SDIO Wake up IRQ : %d\n", mmc_hostname(host->mmc), irq);
2691 spin_lock(&host->lock);
2692 if (!host->sdio_irq_disabled) {
2693 disable_irq_nosync(irq);
2694 if (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2695 wake_lock(&host->sdio_wlock);
2696 msmsdcc_disable_irq_wake(host);
2697 }
2698 host->sdio_irq_disabled = 1;
2699 }
2700 if (host->plat->is_sdio_al_client) {
2701 if (!host->clks_on) {
2702 msmsdcc_setup_clocks(host, true);
2703 host->clks_on = 1;
2704 }
2705 if (host->sdcc_irq_disabled) {
2706 writel_relaxed(host->mci_irqenable,
2707 host->base + MMCIMASK0);
2708 mb();
2709 enable_irq(host->core_irqres->start);
2710 host->sdcc_irq_disabled = 0;
2711 }
2712 wake_lock(&host->sdio_wlock);
2713 }
2714 spin_unlock(&host->lock);
2715
2716 return IRQ_HANDLED;
2717}
2718
San Mehat9d2bd732009-09-22 16:44:22 -07002719static void
2720msmsdcc_status_notify_cb(int card_present, void *dev_id)
2721{
2722 struct msmsdcc_host *host = dev_id;
2723
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002724 pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
San Mehat9d2bd732009-09-22 16:44:22 -07002725 card_present);
2726 msmsdcc_check_status((unsigned long) host);
2727}
2728
San Mehat9d2bd732009-09-22 16:44:22 -07002729static int
2730msmsdcc_init_dma(struct msmsdcc_host *host)
2731{
2732 memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data));
2733 host->dma.host = host;
2734 host->dma.channel = -1;
2735
2736 if (!host->dmares)
2737 return -ENODEV;
2738
2739 host->dma.nc = dma_alloc_coherent(NULL,
2740 sizeof(struct msmsdcc_nc_dmadata),
2741 &host->dma.nc_busaddr,
2742 GFP_KERNEL);
2743 if (host->dma.nc == NULL) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07002744 pr_err("Unable to allocate DMA buffer\n");
San Mehat9d2bd732009-09-22 16:44:22 -07002745 return -ENOMEM;
2746 }
2747 memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata));
2748 host->dma.cmd_busaddr = host->dma.nc_busaddr;
2749 host->dma.cmdptr_busaddr = host->dma.nc_busaddr +
2750 offsetof(struct msmsdcc_nc_dmadata, cmdptr);
2751 host->dma.channel = host->dmares->start;
2752
2753 return 0;
2754}
2755
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002756#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
2757/**
2758 * Allocate and Connect a SDCC peripheral's SPS endpoint
2759 *
2760 * This function allocates endpoint context and
2761 * connect it with memory endpoint by calling
2762 * appropriate SPS driver APIs.
2763 *
2764 * Also registers a SPS callback function with
2765 * SPS driver
2766 *
2767 * This function should only be called once typically
2768 * during driver probe.
2769 *
2770 * @host - Pointer to sdcc host structure
2771 * @ep - Pointer to sps endpoint data structure
2772 * @is_produce - 1 means Producer endpoint
2773 * 0 means Consumer endpoint
2774 *
2775 * @return - 0 if successful else negative value.
2776 *
2777 */
2778static int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
2779 struct msmsdcc_sps_ep_conn_data *ep,
2780 bool is_producer)
2781{
2782 int rc = 0;
2783 struct sps_pipe *sps_pipe_handle;
2784 struct sps_connect *sps_config = &ep->config;
2785 struct sps_register_event *sps_event = &ep->event;
2786
2787 /* Allocate endpoint context */
2788 sps_pipe_handle = sps_alloc_endpoint();
2789 if (!sps_pipe_handle) {
2790 pr_err("%s: sps_alloc_endpoint() failed!!! is_producer=%d",
2791 mmc_hostname(host->mmc), is_producer);
2792 rc = -ENOMEM;
2793 goto out;
2794 }
2795
2796 /* Get default connection configuration for an endpoint */
2797 rc = sps_get_config(sps_pipe_handle, sps_config);
2798 if (rc) {
2799 pr_err("%s: sps_get_config() failed!!! pipe_handle=0x%x,"
2800 " rc=%d", mmc_hostname(host->mmc),
2801 (u32)sps_pipe_handle, rc);
2802 goto get_config_err;
2803 }
2804
2805 /* Modify the default connection configuration */
2806 if (is_producer) {
2807 /*
2808 * For SDCC producer transfer, source should be
2809 * SDCC peripheral where as destination should
2810 * be system memory.
2811 */
2812 sps_config->source = host->sps.bam_handle;
2813 sps_config->destination = SPS_DEV_HANDLE_MEM;
2814 /* Producer pipe will handle this connection */
2815 sps_config->mode = SPS_MODE_SRC;
2816 sps_config->options =
2817 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2818 } else {
2819 /*
2820 * For SDCC consumer transfer, source should be
2821 * system memory where as destination should
2822 * SDCC peripheral
2823 */
2824 sps_config->source = SPS_DEV_HANDLE_MEM;
2825 sps_config->destination = host->sps.bam_handle;
2826 sps_config->mode = SPS_MODE_DEST;
2827 sps_config->options =
2828 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2829 }
2830
2831 /* Producer pipe index */
2832 sps_config->src_pipe_index = host->sps.src_pipe_index;
2833 /* Consumer pipe index */
2834 sps_config->dest_pipe_index = host->sps.dest_pipe_index;
2835 /*
2836 * This event thresold value is only significant for BAM-to-BAM
2837 * transfer. It's ignored for BAM-to-System mode transfer.
2838 */
2839 sps_config->event_thresh = 0x10;
2840 /*
2841 * Max. no of scatter/gather buffers that can
2842 * be passed by block layer = 32 (NR_SG).
2843 * Each BAM descritor needs 64 bits (8 bytes).
2844 * One BAM descriptor is required per buffer transfer.
2845 * So we would require total 256 (32 * 8) bytes of descriptor FIFO.
2846 * But due to HW limitation we need to allocate atleast one extra
2847 * descriptor memory (256 bytes + 8 bytes). But in order to be
2848 * in power of 2, we are allocating 512 bytes of memory.
2849 */
2850 sps_config->desc.size = 512;
2851 sps_config->desc.base = dma_alloc_coherent(mmc_dev(host->mmc),
2852 sps_config->desc.size,
2853 &sps_config->desc.phys_base,
2854 GFP_KERNEL);
2855
2856 memset(sps_config->desc.base, 0x00, sps_config->desc.size);
2857
2858 /* Establish connection between peripheral and memory endpoint */
2859 rc = sps_connect(sps_pipe_handle, sps_config);
2860 if (rc) {
2861 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2862 " rc=%d", mmc_hostname(host->mmc),
2863 (u32)sps_pipe_handle, rc);
2864 goto sps_connect_err;
2865 }
2866
2867 sps_event->mode = SPS_TRIGGER_CALLBACK;
2868 sps_event->options = SPS_O_EOT;
2869 sps_event->callback = msmsdcc_sps_complete_cb;
2870 sps_event->xfer_done = NULL;
2871 sps_event->user = (void *)host;
2872
2873 /* Register callback event for EOT (End of transfer) event. */
2874 rc = sps_register_event(sps_pipe_handle, sps_event);
2875 if (rc) {
2876 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2877 " rc=%d", mmc_hostname(host->mmc),
2878 (u32)sps_pipe_handle, rc);
2879 goto reg_event_err;
2880 }
2881 /* Now save the sps pipe handle */
2882 ep->pipe_handle = sps_pipe_handle;
2883 pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"
2884 " desc_fifo.phys_base=0x%x\n", mmc_hostname(host->mmc),
2885 __func__, is_producer ? "READ" : "WRITE",
2886 (u32)sps_pipe_handle, sps_config->desc.phys_base);
2887 goto out;
2888
2889reg_event_err:
2890 sps_disconnect(sps_pipe_handle);
2891sps_connect_err:
2892 dma_free_coherent(mmc_dev(host->mmc),
2893 sps_config->desc.size,
2894 sps_config->desc.base,
2895 sps_config->desc.phys_base);
2896get_config_err:
2897 sps_free_endpoint(sps_pipe_handle);
2898out:
2899 return rc;
2900}
2901
2902/**
2903 * Disconnect and Deallocate a SDCC peripheral's SPS endpoint
2904 *
2905 * This function disconnect endpoint and deallocates
2906 * endpoint context.
2907 *
2908 * This function should only be called once typically
2909 * during driver remove.
2910 *
2911 * @host - Pointer to sdcc host structure
2912 * @ep - Pointer to sps endpoint data structure
2913 *
2914 */
2915static void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
2916 struct msmsdcc_sps_ep_conn_data *ep)
2917{
2918 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2919 struct sps_connect *sps_config = &ep->config;
2920 struct sps_register_event *sps_event = &ep->event;
2921
2922 sps_event->xfer_done = NULL;
2923 sps_event->callback = NULL;
2924 sps_register_event(sps_pipe_handle, sps_event);
2925 sps_disconnect(sps_pipe_handle);
2926 dma_free_coherent(mmc_dev(host->mmc),
2927 sps_config->desc.size,
2928 sps_config->desc.base,
2929 sps_config->desc.phys_base);
2930 sps_free_endpoint(sps_pipe_handle);
2931}
2932
2933/**
2934 * Reset SDCC peripheral's SPS endpoint
2935 *
2936 * This function disconnects an endpoint.
2937 *
2938 * This function should be called for reseting
2939 * SPS endpoint when data transfer error is
2940 * encountered during data transfer. This
2941 * can be considered as soft reset to endpoint.
2942 *
2943 * This function should only be called if
2944 * msmsdcc_sps_init() is already called.
2945 *
2946 * @host - Pointer to sdcc host structure
2947 * @ep - Pointer to sps endpoint data structure
2948 *
2949 * @return - 0 if successful else negative value.
2950 */
2951static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
2952 struct msmsdcc_sps_ep_conn_data *ep)
2953{
2954 int rc = 0;
2955 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2956
2957 rc = sps_disconnect(sps_pipe_handle);
2958 if (rc) {
2959 pr_err("%s: %s: sps_disconnect() failed!!! pipe_handle=0x%x,"
2960 " rc=%d", mmc_hostname(host->mmc), __func__,
2961 (u32)sps_pipe_handle, rc);
2962 goto out;
2963 }
2964 out:
2965 return rc;
2966}
2967
2968/**
2969 * Restore SDCC peripheral's SPS endpoint
2970 *
2971 * This function connects an endpoint.
2972 *
2973 * This function should be called for restoring
2974 * SPS endpoint after data transfer error is
2975 * encountered during data transfer. This
2976 * can be considered as soft reset to endpoint.
2977 *
2978 * This function should only be called if
2979 * msmsdcc_sps_reset_ep() is called before.
2980 *
2981 * @host - Pointer to sdcc host structure
2982 * @ep - Pointer to sps endpoint data structure
2983 *
2984 * @return - 0 if successful else negative value.
2985 */
2986static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
2987 struct msmsdcc_sps_ep_conn_data *ep)
2988{
2989 int rc = 0;
2990 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2991 struct sps_connect *sps_config = &ep->config;
2992 struct sps_register_event *sps_event = &ep->event;
2993
2994 /* Establish connection between peripheral and memory endpoint */
2995 rc = sps_connect(sps_pipe_handle, sps_config);
2996 if (rc) {
2997 pr_err("%s: %s: sps_connect() failed!!! pipe_handle=0x%x,"
2998 " rc=%d", mmc_hostname(host->mmc), __func__,
2999 (u32)sps_pipe_handle, rc);
3000 goto out;
3001 }
3002
3003 /* Register callback event for EOT (End of transfer) event. */
3004 rc = sps_register_event(sps_pipe_handle, sps_event);
3005 if (rc) {
3006 pr_err("%s: %s: sps_register_event() failed!!!"
3007 " pipe_handle=0x%x, rc=%d",
3008 mmc_hostname(host->mmc), __func__,
3009 (u32)sps_pipe_handle, rc);
3010 goto reg_event_err;
3011 }
3012 goto out;
3013
3014reg_event_err:
3015 sps_disconnect(sps_pipe_handle);
3016out:
3017 return rc;
3018}
3019
3020/**
3021 * Initialize SPS HW connected with SDCC core
3022 *
3023 * This function register BAM HW resources with
3024 * SPS driver and then initialize 2 SPS endpoints
3025 *
3026 * This function should only be called once typically
3027 * during driver probe.
3028 *
3029 * @host - Pointer to sdcc host structure
3030 *
3031 * @return - 0 if successful else negative value.
3032 *
3033 */
3034static int msmsdcc_sps_init(struct msmsdcc_host *host)
3035{
3036 int rc = 0;
3037 struct sps_bam_props bam = {0};
3038
3039 host->bam_base = ioremap(host->bam_memres->start,
3040 resource_size(host->bam_memres));
3041 if (!host->bam_base) {
3042 pr_err("%s: BAM ioremap() failed!!! phys_addr=0x%x,"
3043 " size=0x%x", mmc_hostname(host->mmc),
3044 host->bam_memres->start,
3045 (host->bam_memres->end -
3046 host->bam_memres->start));
3047 rc = -ENOMEM;
3048 goto out;
3049 }
3050
3051 bam.phys_addr = host->bam_memres->start;
3052 bam.virt_addr = host->bam_base;
3053 /*
3054 * This event thresold value is only significant for BAM-to-BAM
3055 * transfer. It's ignored for BAM-to-System mode transfer.
3056 */
3057 bam.event_threshold = 0x10; /* Pipe event threshold */
3058 /*
3059 * This threshold controls when the BAM publish
3060 * the descriptor size on the sideband interface.
3061 * SPS HW will only be used when
3062 * data transfer size > MCI_FIFOSIZE (64 bytes).
3063 * PIO mode will be used when
3064 * data transfer size < MCI_FIFOSIZE (64 bytes).
3065 * So set this thresold value to 64 bytes.
3066 */
3067 bam.summing_threshold = 64;
3068 /* SPS driver wll handle the SDCC BAM IRQ */
3069 bam.irq = (u32)host->bam_irqres->start;
3070 bam.manage = SPS_BAM_MGR_LOCAL;
3071
3072 pr_info("%s: bam physical base=0x%x\n", mmc_hostname(host->mmc),
3073 (u32)bam.phys_addr);
3074 pr_info("%s: bam virtual base=0x%x\n", mmc_hostname(host->mmc),
3075 (u32)bam.virt_addr);
3076
3077 /* Register SDCC Peripheral BAM device to SPS driver */
3078 rc = sps_register_bam_device(&bam, &host->sps.bam_handle);
3079 if (rc) {
3080 pr_err("%s: sps_register_bam_device() failed!!! err=%d",
3081 mmc_hostname(host->mmc), rc);
3082 goto reg_bam_err;
3083 }
3084 pr_info("%s: BAM device registered. bam_handle=0x%x",
3085 mmc_hostname(host->mmc), host->sps.bam_handle);
3086
3087 host->sps.src_pipe_index = SPS_SDCC_PRODUCER_PIPE_INDEX;
3088 host->sps.dest_pipe_index = SPS_SDCC_CONSUMER_PIPE_INDEX;
3089
3090 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.prod,
3091 SPS_PROD_PERIPHERAL);
3092 if (rc)
3093 goto sps_reset_err;
3094 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.cons,
3095 SPS_CONS_PERIPHERAL);
3096 if (rc)
3097 goto cons_conn_err;
3098
3099 pr_info("%s: Qualcomm MSM SDCC-BAM at 0x%016llx irq %d\n",
3100 mmc_hostname(host->mmc),
3101 (unsigned long long)host->bam_memres->start,
3102 (unsigned int)host->bam_irqres->start);
3103 goto out;
3104
3105cons_conn_err:
3106 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3107sps_reset_err:
3108 sps_deregister_bam_device(host->sps.bam_handle);
3109reg_bam_err:
3110 iounmap(host->bam_base);
3111out:
3112 return rc;
3113}
3114
3115/**
3116 * De-initialize SPS HW connected with SDCC core
3117 *
3118 * This function deinitialize SPS endpoints and then
3119 * deregisters BAM resources from SPS driver.
3120 *
3121 * This function should only be called once typically
3122 * during driver remove.
3123 *
3124 * @host - Pointer to sdcc host structure
3125 *
3126 */
3127static void msmsdcc_sps_exit(struct msmsdcc_host *host)
3128{
3129 msmsdcc_sps_exit_ep_conn(host, &host->sps.cons);
3130 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3131 sps_deregister_bam_device(host->sps.bam_handle);
3132 iounmap(host->bam_base);
3133}
3134#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
3135
3136static ssize_t
3137show_polling(struct device *dev, struct device_attribute *attr, char *buf)
3138{
3139 struct mmc_host *mmc = dev_get_drvdata(dev);
3140 struct msmsdcc_host *host = mmc_priv(mmc);
3141 int poll;
3142 unsigned long flags;
3143
3144 spin_lock_irqsave(&host->lock, flags);
3145 poll = !!(mmc->caps & MMC_CAP_NEEDS_POLL);
3146 spin_unlock_irqrestore(&host->lock, flags);
3147
3148 return snprintf(buf, PAGE_SIZE, "%d\n", poll);
3149}
3150
3151static ssize_t
3152set_polling(struct device *dev, struct device_attribute *attr,
3153 const char *buf, size_t count)
3154{
3155 struct mmc_host *mmc = dev_get_drvdata(dev);
3156 struct msmsdcc_host *host = mmc_priv(mmc);
3157 int value;
3158 unsigned long flags;
3159
3160 sscanf(buf, "%d", &value);
3161
3162 spin_lock_irqsave(&host->lock, flags);
3163 if (value) {
3164 mmc->caps |= MMC_CAP_NEEDS_POLL;
3165 mmc_detect_change(host->mmc, 0);
3166 } else {
3167 mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3168 }
3169#ifdef CONFIG_HAS_EARLYSUSPEND
3170 host->polling_enabled = mmc->caps & MMC_CAP_NEEDS_POLL;
3171#endif
3172 spin_unlock_irqrestore(&host->lock, flags);
3173 return count;
3174}
3175
3176static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR,
3177 show_polling, set_polling);
3178static struct attribute *dev_attrs[] = {
3179 &dev_attr_polling.attr,
3180 NULL,
3181};
3182static struct attribute_group dev_attr_grp = {
3183 .attrs = dev_attrs,
3184};
3185
3186#ifdef CONFIG_HAS_EARLYSUSPEND
3187static void msmsdcc_early_suspend(struct early_suspend *h)
3188{
3189 struct msmsdcc_host *host =
3190 container_of(h, struct msmsdcc_host, early_suspend);
3191 unsigned long flags;
3192
3193 spin_lock_irqsave(&host->lock, flags);
3194 host->polling_enabled = host->mmc->caps & MMC_CAP_NEEDS_POLL;
3195 host->mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3196 spin_unlock_irqrestore(&host->lock, flags);
3197};
3198static void msmsdcc_late_resume(struct early_suspend *h)
3199{
3200 struct msmsdcc_host *host =
3201 container_of(h, struct msmsdcc_host, early_suspend);
3202 unsigned long flags;
3203
3204 if (host->polling_enabled) {
3205 spin_lock_irqsave(&host->lock, flags);
3206 host->mmc->caps |= MMC_CAP_NEEDS_POLL;
3207 mmc_detect_change(host->mmc, 0);
3208 spin_unlock_irqrestore(&host->lock, flags);
3209 }
3210};
3211#endif
3212
3213static void msmsdcc_req_tout_timer_hdlr(unsigned long data)
3214{
3215 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
3216 struct mmc_request *mrq;
3217 unsigned long flags;
3218
3219 spin_lock_irqsave(&host->lock, flags);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003220 if (host->dummy_52_sent) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003221 pr_info("%s: %s: dummy CMD52 timeout\n",
3222 mmc_hostname(host->mmc), __func__);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003223 host->dummy_52_sent = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003224 }
3225
3226 mrq = host->curr.mrq;
3227
3228 if (mrq && mrq->cmd) {
3229 pr_info("%s: %s CMD%d\n", mmc_hostname(host->mmc),
3230 __func__, mrq->cmd->opcode);
3231 if (!mrq->cmd->error)
3232 mrq->cmd->error = -ETIMEDOUT;
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003233 if (host->dummy_52_needed)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003234 host->dummy_52_needed = 0;
3235 if (host->curr.data) {
3236 pr_info("%s: %s Request timeout\n",
3237 mmc_hostname(host->mmc), __func__);
3238 if (mrq->data && !mrq->data->error)
3239 mrq->data->error = -ETIMEDOUT;
3240 host->curr.data_xfered = 0;
3241 if (host->dma.sg && host->is_dma_mode) {
3242 msm_dmov_stop_cmd(host->dma.channel,
3243 &host->dma.hdr, 0);
3244 } else if (host->sps.sg && host->is_sps_mode) {
3245 /* Stop current SPS transfer */
3246 msmsdcc_sps_exit_curr_xfer(host);
3247 } else {
3248 msmsdcc_reset_and_restore(host);
3249 msmsdcc_stop_data(host);
3250 if (mrq->data && mrq->data->stop)
3251 msmsdcc_start_command(host,
3252 mrq->data->stop, 0);
3253 else
3254 msmsdcc_request_end(host, mrq);
3255 }
3256 } else {
3257 if (host->prog_enable) {
3258 host->prog_scan = 0;
3259 host->prog_enable = 0;
3260 }
3261 msmsdcc_reset_and_restore(host);
3262 msmsdcc_request_end(host, mrq);
3263 }
3264 }
3265 spin_unlock_irqrestore(&host->lock, flags);
3266}
3267
San Mehat9d2bd732009-09-22 16:44:22 -07003268static int
3269msmsdcc_probe(struct platform_device *pdev)
3270{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003271 struct mmc_platform_data *plat = pdev->dev.platform_data;
San Mehat9d2bd732009-09-22 16:44:22 -07003272 struct msmsdcc_host *host;
3273 struct mmc_host *mmc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003274 unsigned long flags;
3275 struct resource *core_irqres = NULL;
3276 struct resource *bam_irqres = NULL;
3277 struct resource *core_memres = NULL;
3278 struct resource *dml_memres = NULL;
3279 struct resource *bam_memres = NULL;
San Mehat9d2bd732009-09-22 16:44:22 -07003280 struct resource *dmares = NULL;
3281 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003282 int i;
San Mehat9d2bd732009-09-22 16:44:22 -07003283
3284 /* must have platform data */
3285 if (!plat) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003286 pr_err("%s: Platform data not available\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003287 ret = -EINVAL;
3288 goto out;
3289 }
3290
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003291 if (pdev->id < 1 || pdev->id > 5)
San Mehat9d2bd732009-09-22 16:44:22 -07003292 return -EINVAL;
3293
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003294 if (plat->is_sdio_al_client)
3295 if (!plat->sdio_lpm_gpio_setup || !plat->sdiowakeup_irq)
3296 return -EINVAL;
3297
San Mehat9d2bd732009-09-22 16:44:22 -07003298 if (pdev->resource == NULL || pdev->num_resources < 2) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003299 pr_err("%s: Invalid resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003300 return -ENXIO;
3301 }
3302
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003303 for (i = 0; i < pdev->num_resources; i++) {
3304 if (pdev->resource[i].flags & IORESOURCE_MEM) {
3305 if (!strcmp(pdev->resource[i].name,
3306 "sdcc_dml_addr"))
3307 dml_memres = &pdev->resource[i];
3308 else if (!strcmp(pdev->resource[i].name,
3309 "sdcc_bam_addr"))
3310 bam_memres = &pdev->resource[i];
3311 else
3312 core_memres = &pdev->resource[i];
San Mehat9d2bd732009-09-22 16:44:22 -07003313
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003314 }
3315 if (pdev->resource[i].flags & IORESOURCE_IRQ) {
3316 if (!strcmp(pdev->resource[i].name,
3317 "sdcc_bam_irq"))
3318 bam_irqres = &pdev->resource[i];
3319 else
3320 core_irqres = &pdev->resource[i];
3321 }
3322 if (pdev->resource[i].flags & IORESOURCE_DMA)
3323 dmares = &pdev->resource[i];
3324 }
3325
3326 if (!core_irqres || !core_memres) {
3327 pr_err("%s: Invalid sdcc core resource\n", __func__);
3328 return -ENXIO;
3329 }
3330
3331 /*
3332 * Both BAM and DML memory resource should be preset.
3333 * BAM IRQ resource should also be present.
3334 */
3335 if ((bam_memres && !dml_memres) ||
3336 (!bam_memres && dml_memres) ||
3337 ((bam_memres && dml_memres) && !bam_irqres)) {
3338 pr_err("%s: Invalid sdcc BAM/DML resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003339 return -ENXIO;
3340 }
3341
3342 /*
3343 * Setup our host structure
3344 */
San Mehat9d2bd732009-09-22 16:44:22 -07003345 mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev);
3346 if (!mmc) {
3347 ret = -ENOMEM;
3348 goto out;
3349 }
3350
3351 host = mmc_priv(mmc);
3352 host->pdev_id = pdev->id;
3353 host->plat = plat;
3354 host->mmc = mmc;
San Mehat56a8b5b2009-11-21 12:29:46 -08003355 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003356 if (bam_memres && dml_memres && bam_irqres)
3357 host->is_sps_mode = 1;
3358 else if (dmares)
3359 host->is_dma_mode = 1;
San Mehat9d2bd732009-09-22 16:44:22 -07003360
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003361 host->base = ioremap(core_memres->start,
3362 resource_size(core_memres));
San Mehat9d2bd732009-09-22 16:44:22 -07003363 if (!host->base) {
3364 ret = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003365 goto host_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003366 }
3367
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003368 host->core_irqres = core_irqres;
3369 host->bam_irqres = bam_irqres;
3370 host->core_memres = core_memres;
3371 host->dml_memres = dml_memres;
3372 host->bam_memres = bam_memres;
San Mehat9d2bd732009-09-22 16:44:22 -07003373 host->dmares = dmares;
3374 spin_lock_init(&host->lock);
3375
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003376#ifdef CONFIG_MMC_EMBEDDED_SDIO
3377 if (plat->embedded_sdio)
3378 mmc_set_embedded_sdio_data(mmc,
3379 &plat->embedded_sdio->cis,
3380 &plat->embedded_sdio->cccr,
3381 plat->embedded_sdio->funcs,
3382 plat->embedded_sdio->num_funcs);
3383#endif
3384
Sahitya Tummala62612cf2010-12-08 15:03:03 +05303385 tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
3386 (unsigned long)host);
3387
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003388 tasklet_init(&host->sps.tlet, msmsdcc_sps_complete_tlet,
3389 (unsigned long)host);
3390 if (host->is_dma_mode) {
3391 /* Setup DMA */
3392 ret = msmsdcc_init_dma(host);
3393 if (ret)
3394 goto ioremap_free;
3395 } else {
3396 host->dma.channel = -1;
San Mehat9d2bd732009-09-22 16:44:22 -07003397 }
3398
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003399 /*
3400 * Setup SDCC clock if derived from Dayatona
3401 * fabric core clock.
3402 */
3403 if (plat->pclk_src_dfab) {
3404 host->dfab_pclk = clk_get(&pdev->dev, "dfab_sdc_clk");
3405 if (!IS_ERR(host->dfab_pclk)) {
3406 /* Set the clock rate to 64MHz for max. performance */
3407 ret = clk_set_rate(host->dfab_pclk, 64000000);
3408 if (ret)
3409 goto dfab_pclk_put;
3410 ret = clk_enable(host->dfab_pclk);
3411 if (ret)
3412 goto dfab_pclk_put;
3413 } else
3414 goto dma_free;
3415 }
3416
3417 /*
3418 * Setup main peripheral bus clock
3419 */
3420 host->pclk = clk_get(&pdev->dev, "sdc_pclk");
3421 if (!IS_ERR(host->pclk)) {
3422 ret = clk_enable(host->pclk);
3423 if (ret)
3424 goto pclk_put;
3425
3426 host->pclk_rate = clk_get_rate(host->pclk);
3427 }
3428
3429 /*
3430 * Setup SDC MMC clock
3431 */
San Mehat9d2bd732009-09-22 16:44:22 -07003432 host->clk = clk_get(&pdev->dev, "sdc_clk");
3433 if (IS_ERR(host->clk)) {
3434 ret = PTR_ERR(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003435 goto pclk_disable;
San Mehat9d2bd732009-09-22 16:44:22 -07003436 }
3437
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003438 ret = clk_set_rate(host->clk, msmsdcc_get_min_sup_clk_rate(host));
3439 if (ret) {
3440 pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
3441 goto clk_put;
3442 }
3443
3444 ret = clk_enable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003445 if (ret)
3446 goto clk_put;
3447
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003448 host->clk_rate = clk_get_rate(host->clk);
3449
3450 host->clks_on = 1;
3451
3452 ret = msmsdcc_vreg_init(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07003453 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003454 pr_err("%s: msmsdcc_vreg_init() failed (%d)\n", __func__, ret);
San Mehat9d2bd732009-09-22 16:44:22 -07003455 goto clk_disable;
3456 }
3457
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003458
3459 /* Clocks has to be running before accessing SPS/DML HW blocks */
3460 if (host->is_sps_mode) {
3461 /* Initialize SPS */
3462 ret = msmsdcc_sps_init(host);
3463 if (ret)
3464 goto vreg_deinit;
3465 /* Initialize DML */
3466 ret = msmsdcc_dml_init(host);
3467 if (ret)
3468 goto sps_exit;
3469 }
San Mehat9d2bd732009-09-22 16:44:22 -07003470
San Mehat9d2bd732009-09-22 16:44:22 -07003471 /*
3472 * Setup MMC host structure
3473 */
3474 mmc->ops = &msmsdcc_ops;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003475 mmc->f_min = msmsdcc_get_min_sup_clk_rate(host);
3476 mmc->f_max = msmsdcc_get_max_sup_clk_rate(host);
San Mehat9d2bd732009-09-22 16:44:22 -07003477 mmc->ocr_avail = plat->ocr_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003478 mmc->pm_caps |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
3479 mmc->caps |= plat->mmc_bus_width;
San Mehat9d2bd732009-09-22 16:44:22 -07003480
San Mehat9d2bd732009-09-22 16:44:22 -07003481 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003482 mmc->caps |= plat->uhs_caps;
3483 /*
3484 * XPC controls the maximum current in the default speed mode of SDXC
3485 * card. XPC=0 means 100mA (max.) but speed class is not supported.
3486 * XPC=1 means 150mA (max.) and speed class is supported.
3487 */
3488 if (plat->xpc_cap)
3489 mmc->caps |= (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
3490 MMC_CAP_SET_XPC_180);
3491
3492 if (plat->nonremovable)
3493 mmc->caps |= MMC_CAP_NONREMOVABLE;
3494#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
3495 mmc->caps |= MMC_CAP_SDIO_IRQ;
3496#endif
3497
3498 if (plat->is_sdio_al_client)
3499 mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
San Mehat9d2bd732009-09-22 16:44:22 -07003500
Martin K. Petersena36274e2010-09-10 01:33:59 -04003501 mmc->max_segs = NR_SG;
San Mehat9d2bd732009-09-22 16:44:22 -07003502 mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003503 mmc->max_blk_count = 65535;
San Mehat9d2bd732009-09-22 16:44:22 -07003504
3505 mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */
3506 mmc->max_seg_size = mmc->max_req_size;
3507
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003508 writel_relaxed(0, host->base + MMCIMASK0);
3509 writel_relaxed(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
San Mehat9d2bd732009-09-22 16:44:22 -07003510
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003511 /* Delay needed (MMCIMASK0 was just written above) */
3512 msmsdcc_delay(host);
3513 writel_relaxed(MCI_IRQENABLE, host->base + MMCIMASK0);
3514 mb();
3515 host->mci_irqenable = MCI_IRQENABLE;
San Mehat9d2bd732009-09-22 16:44:22 -07003516
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003517 ret = request_irq(core_irqres->start, msmsdcc_irq, IRQF_SHARED,
3518 DRIVER_NAME " (cmd)", host);
3519 if (ret)
3520 goto dml_exit;
3521
3522 ret = request_irq(core_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
3523 DRIVER_NAME " (pio)", host);
3524 if (ret)
3525 goto irq_free;
3526
3527 /*
3528 * Enable SDCC IRQ only when host is powered on. Otherwise, this
3529 * IRQ is un-necessarily being monitored by MPM (Modem power
3530 * management block) during idle-power collapse. The MPM will be
3531 * configured to monitor the DATA1 GPIO line with level-low trigger
3532 * and thus depending on the GPIO status, it prevents TCXO shutdown
3533 * during idle-power collapse.
3534 */
3535 disable_irq(core_irqres->start);
3536 host->sdcc_irq_disabled = 1;
3537
3538 if (plat->sdiowakeup_irq) {
3539 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3540 mmc_hostname(mmc));
3541 ret = request_irq(plat->sdiowakeup_irq,
3542 msmsdcc_platform_sdiowakeup_irq,
3543 IRQF_SHARED | IRQF_TRIGGER_LOW,
3544 DRIVER_NAME "sdiowakeup", host);
3545 if (ret) {
3546 pr_err("Unable to get sdio wakeup IRQ %d (%d)\n",
3547 plat->sdiowakeup_irq, ret);
3548 goto pio_irq_free;
3549 } else {
3550 spin_lock_irqsave(&host->lock, flags);
3551 if (!host->sdio_irq_disabled) {
3552 disable_irq_nosync(plat->sdiowakeup_irq);
3553 host->sdio_irq_disabled = 1;
3554 }
3555 spin_unlock_irqrestore(&host->lock, flags);
3556 }
3557 }
3558
3559 if (plat->cfg_mpm_sdiowakeup) {
3560 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3561 mmc_hostname(mmc));
3562 }
3563
3564 wake_lock_init(&host->sdio_suspend_wlock, WAKE_LOCK_SUSPEND,
3565 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003566 /*
3567 * Setup card detect change
3568 */
3569
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003570 if (plat->status || plat->status_gpio) {
3571 if (plat->status)
3572 host->oldstat = plat->status(mmc_dev(host->mmc));
3573 else
3574 host->oldstat = msmsdcc_slot_status(host);
3575 host->eject = !host->oldstat;
3576 }
San Mehat9d2bd732009-09-22 16:44:22 -07003577
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003578 if (plat->status_irq) {
3579 ret = request_threaded_irq(plat->status_irq, NULL,
San Mehat9d2bd732009-09-22 16:44:22 -07003580 msmsdcc_platform_status_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003581 plat->irq_flags,
San Mehat9d2bd732009-09-22 16:44:22 -07003582 DRIVER_NAME " (slot)",
3583 host);
3584 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003585 pr_err("Unable to get slot IRQ %d (%d)\n",
3586 plat->status_irq, ret);
3587 goto sdiowakeup_irq_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003588 }
3589 } else if (plat->register_status_notify) {
3590 plat->register_status_notify(msmsdcc_status_notify_cb, host);
3591 } else if (!plat->status)
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003592 pr_err("%s: No card detect facilities available\n",
San Mehat9d2bd732009-09-22 16:44:22 -07003593 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003594
3595 mmc_set_drvdata(pdev, mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003596
3597 ret = pm_runtime_set_active(&(pdev)->dev);
3598 if (ret < 0)
3599 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
3600 __func__, ret);
3601 /*
3602 * There is no notion of suspend/resume for SD/MMC/SDIO
3603 * cards. So host can be suspended/resumed with out
3604 * worrying about its children.
3605 */
3606 pm_suspend_ignore_children(&(pdev)->dev, true);
3607
3608 /*
3609 * MMC/SD/SDIO bus suspend/resume operations are defined
3610 * only for the slots that will be used for non-removable
3611 * media or for all slots when CONFIG_MMC_UNSAFE_RESUME is
3612 * defined. Otherwise, they simply become card removal and
3613 * insertion events during suspend and resume respectively.
3614 * Hence, enable run-time PM only for slots for which bus
3615 * suspend/resume operations are defined.
3616 */
3617#ifdef CONFIG_MMC_UNSAFE_RESUME
3618 /*
3619 * If this capability is set, MMC core will enable/disable host
3620 * for every claim/release operation on a host. We use this
3621 * notification to increment/decrement runtime pm usage count.
3622 */
3623 mmc->caps |= MMC_CAP_DISABLE;
3624 pm_runtime_enable(&(pdev)->dev);
3625#else
3626 if (mmc->caps & MMC_CAP_NONREMOVABLE) {
3627 mmc->caps |= MMC_CAP_DISABLE;
3628 pm_runtime_enable(&(pdev)->dev);
3629 }
3630#endif
3631 setup_timer(&host->req_tout_timer, msmsdcc_req_tout_timer_hdlr,
3632 (unsigned long)host);
3633
San Mehat9d2bd732009-09-22 16:44:22 -07003634 mmc_add_host(mmc);
3635
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003636#ifdef CONFIG_HAS_EARLYSUSPEND
3637 host->early_suspend.suspend = msmsdcc_early_suspend;
3638 host->early_suspend.resume = msmsdcc_late_resume;
3639 host->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
3640 register_early_suspend(&host->early_suspend);
3641#endif
San Mehat9d2bd732009-09-22 16:44:22 -07003642
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003643 pr_info("%s: Qualcomm MSM SDCC-core at 0x%016llx irq %d,%d dma %d\n",
3644 mmc_hostname(mmc), (unsigned long long)core_memres->start,
3645 (unsigned int) core_irqres->start,
3646 (unsigned int) plat->status_irq, host->dma.channel);
3647
3648 pr_info("%s: 8 bit data mode %s\n", mmc_hostname(mmc),
3649 (mmc->caps & MMC_CAP_8_BIT_DATA ? "enabled" : "disabled"));
3650 pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc),
3651 (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled"));
3652 pr_info("%s: polling status mode %s\n", mmc_hostname(mmc),
3653 (mmc->caps & MMC_CAP_NEEDS_POLL ? "enabled" : "disabled"));
3654 pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n",
3655 mmc_hostname(mmc), msmsdcc_get_min_sup_clk_rate(host),
3656 msmsdcc_get_max_sup_clk_rate(host), host->pclk_rate);
3657 pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc),
3658 host->eject);
3659 pr_info("%s: Power save feature enable = %d\n",
3660 mmc_hostname(mmc), msmsdcc_pwrsave);
3661
3662 if (host->is_dma_mode && host->dma.channel != -1) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003663 pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003664 mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003665 pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003666 mmc_hostname(mmc), host->dma.cmd_busaddr,
3667 host->dma.cmdptr_busaddr);
3668 } else if (host->is_sps_mode) {
3669 pr_info("%s: SPS-BAM data transfer mode available\n",
3670 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003671 } else
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003672 pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003673
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003674#if defined(CONFIG_DEBUG_FS)
3675 msmsdcc_dbg_createhost(host);
3676#endif
3677 if (!plat->status_irq) {
3678 ret = sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);
3679 if (ret)
3680 goto platform_irq_free;
3681 }
San Mehat9d2bd732009-09-22 16:44:22 -07003682 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003683
3684 platform_irq_free:
3685 del_timer_sync(&host->req_tout_timer);
3686 pm_runtime_disable(&(pdev)->dev);
3687 pm_runtime_set_suspended(&(pdev)->dev);
3688
3689 if (plat->status_irq)
3690 free_irq(plat->status_irq, host);
3691 sdiowakeup_irq_free:
3692 wake_lock_destroy(&host->sdio_suspend_wlock);
3693 if (plat->sdiowakeup_irq)
3694 free_irq(plat->sdiowakeup_irq, host);
3695 pio_irq_free:
3696 if (plat->sdiowakeup_irq)
3697 wake_lock_destroy(&host->sdio_wlock);
3698 free_irq(core_irqres->start, host);
3699 irq_free:
3700 free_irq(core_irqres->start, host);
3701 dml_exit:
3702 if (host->is_sps_mode)
3703 msmsdcc_dml_exit(host);
3704 sps_exit:
3705 if (host->is_sps_mode)
3706 msmsdcc_sps_exit(host);
3707 vreg_deinit:
3708 msmsdcc_vreg_init(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07003709 clk_disable:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003710 clk_disable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003711 clk_put:
3712 clk_put(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003713 pclk_disable:
3714 if (!IS_ERR(host->pclk))
3715 clk_disable(host->pclk);
San Mehat9d2bd732009-09-22 16:44:22 -07003716 pclk_put:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003717 if (!IS_ERR(host->pclk))
3718 clk_put(host->pclk);
3719 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3720 clk_disable(host->dfab_pclk);
3721 dfab_pclk_put:
3722 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3723 clk_put(host->dfab_pclk);
3724 dma_free:
3725 if (host->is_dma_mode) {
3726 if (host->dmares)
3727 dma_free_coherent(NULL,
3728 sizeof(struct msmsdcc_nc_dmadata),
3729 host->dma.nc, host->dma.nc_busaddr);
3730 }
3731 ioremap_free:
3732 iounmap(host->base);
San Mehat9d2bd732009-09-22 16:44:22 -07003733 host_free:
3734 mmc_free_host(mmc);
3735 out:
3736 return ret;
3737}
3738
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003739static int msmsdcc_remove(struct platform_device *pdev)
Daniel Walker08ecfde2010-06-23 12:32:20 -07003740{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003741 struct mmc_host *mmc = mmc_get_drvdata(pdev);
3742 struct mmc_platform_data *plat;
3743 struct msmsdcc_host *host;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003744
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003745 if (!mmc)
3746 return -ENXIO;
3747
3748 if (pm_runtime_suspended(&(pdev)->dev))
3749 pm_runtime_resume(&(pdev)->dev);
3750
3751 host = mmc_priv(mmc);
3752
3753 DBG(host, "Removing SDCC device = %d\n", pdev->id);
3754 plat = host->plat;
3755
3756 if (!plat->status_irq)
3757 sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
3758
3759 del_timer_sync(&host->req_tout_timer);
3760 tasklet_kill(&host->dma_tlet);
3761 tasklet_kill(&host->sps.tlet);
3762 mmc_remove_host(mmc);
3763
3764 if (plat->status_irq)
3765 free_irq(plat->status_irq, host);
3766
3767 wake_lock_destroy(&host->sdio_suspend_wlock);
3768 if (plat->sdiowakeup_irq) {
3769 wake_lock_destroy(&host->sdio_wlock);
3770 irq_set_irq_wake(plat->sdiowakeup_irq, 0);
3771 free_irq(plat->sdiowakeup_irq, host);
Daniel Walker08ecfde2010-06-23 12:32:20 -07003772 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003773
3774 free_irq(host->core_irqres->start, host);
3775 free_irq(host->core_irqres->start, host);
3776
3777 clk_put(host->clk);
3778 if (!IS_ERR(host->pclk))
3779 clk_put(host->pclk);
3780 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3781 clk_put(host->dfab_pclk);
3782
3783 msmsdcc_vreg_init(host, false);
3784
3785 if (host->is_dma_mode) {
3786 if (host->dmares)
3787 dma_free_coherent(NULL,
3788 sizeof(struct msmsdcc_nc_dmadata),
3789 host->dma.nc, host->dma.nc_busaddr);
3790 }
3791
3792 if (host->is_sps_mode) {
3793 msmsdcc_dml_exit(host);
3794 msmsdcc_sps_exit(host);
3795 }
3796
3797 iounmap(host->base);
3798 mmc_free_host(mmc);
3799
3800#ifdef CONFIG_HAS_EARLYSUSPEND
3801 unregister_early_suspend(&host->early_suspend);
3802#endif
3803 pm_runtime_disable(&(pdev)->dev);
3804 pm_runtime_set_suspended(&(pdev)->dev);
3805
3806 return 0;
3807}
3808
3809#ifdef CONFIG_MSM_SDIO_AL
3810int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3811{
3812 struct msmsdcc_host *host = mmc_priv(mmc);
3813 unsigned long flags;
3814
3815 spin_lock_irqsave(&host->lock, flags);
3816 pr_debug("%s: %sabling LPM\n", mmc_hostname(mmc),
3817 enable ? "En" : "Dis");
3818
3819 if (enable) {
3820 if (!host->sdcc_irq_disabled) {
3821 writel_relaxed(0, host->base + MMCIMASK0);
3822 disable_irq(host->core_irqres->start);
3823 host->sdcc_irq_disabled = 1;
3824 }
3825
3826 if (host->clks_on) {
3827 msmsdcc_setup_clocks(host, false);
3828 host->clks_on = 0;
3829 }
3830
3831 if (!host->sdio_gpio_lpm) {
3832 spin_unlock_irqrestore(&host->lock, flags);
3833 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 0);
3834 spin_lock_irqsave(&host->lock, flags);
3835 host->sdio_gpio_lpm = 1;
3836 }
3837
3838 if (host->sdio_irq_disabled) {
3839 msmsdcc_enable_irq_wake(host);
3840 enable_irq(host->plat->sdiowakeup_irq);
3841 host->sdio_irq_disabled = 0;
3842 }
3843 } else {
3844 if (!host->sdio_irq_disabled) {
3845 disable_irq_nosync(host->plat->sdiowakeup_irq);
3846 host->sdio_irq_disabled = 1;
3847 msmsdcc_disable_irq_wake(host);
3848 }
3849
3850 if (host->sdio_gpio_lpm) {
3851 spin_unlock_irqrestore(&host->lock, flags);
3852 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 1);
3853 spin_lock_irqsave(&host->lock, flags);
3854 host->sdio_gpio_lpm = 0;
3855 }
3856
3857 if (!host->clks_on) {
3858 msmsdcc_setup_clocks(host, true);
3859 host->clks_on = 1;
3860 }
3861
3862 if (host->sdcc_irq_disabled) {
3863 writel_relaxed(host->mci_irqenable,
3864 host->base + MMCIMASK0);
3865 mb();
3866 enable_irq(host->core_irqres->start);
3867 host->sdcc_irq_disabled = 0;
3868 }
3869 wake_lock_timeout(&host->sdio_wlock, 1);
3870 }
3871 spin_unlock_irqrestore(&host->lock, flags);
3872 return 0;
3873}
3874#else
3875int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3876{
3877 return 0;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003878}
3879#endif
3880
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003881#ifdef CONFIG_PM
San Mehat9d2bd732009-09-22 16:44:22 -07003882static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003883msmsdcc_runtime_suspend(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003884{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003885 struct mmc_host *mmc = dev_get_drvdata(dev);
3886 struct msmsdcc_host *host = mmc_priv(mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07003887 int rc = 0;
3888
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003889 if (host->plat->is_sdio_al_client)
3890 return 0;
3891
Sahitya Tummala7661a452011-07-18 13:28:35 +05303892 pr_debug("%s: %s: start\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003893 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003894 host->sdcc_suspending = 1;
3895 mmc->suspend_task = current;
San Mehat9d2bd732009-09-22 16:44:22 -07003896
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003897 /*
3898 * If the clocks are already turned off by SDIO clients (as
3899 * part of LPM), then clocks should be turned on before
3900 * calling mmc_suspend_host() because mmc_suspend_host might
3901 * send some commands to the card. The clocks will be turned
3902 * off again after mmc_suspend_host. Thus for SD/MMC/SDIO
3903 * cards, clocks will be turned on before mmc_suspend_host
3904 * and turned off after mmc_suspend_host.
3905 */
3906 mmc->ios.clock = host->clk_rate;
3907 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07003908
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003909 /*
3910 * MMC core thinks that host is disabled by now since
3911 * runtime suspend is scheduled after msmsdcc_disable()
3912 * is called. Thus, MMC core will try to enable the host
3913 * while suspending it. This results in a synchronous
3914 * runtime resume request while in runtime suspending
3915 * context and hence inorder to complete this resume
3916 * requet, it will wait for suspend to be complete,
3917 * but runtime suspend also can not proceed further
3918 * until the host is resumed. Thus, it leads to a hang.
3919 * Hence, increase the pm usage count before suspending
3920 * the host so that any resume requests after this will
3921 * simple become pm usage counter increment operations.
3922 */
3923 pm_runtime_get_noresume(dev);
3924 rc = mmc_suspend_host(mmc);
3925 pm_runtime_put_noidle(dev);
3926
3927 if (!rc) {
3928 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
3929 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ)) {
3930 disable_irq(host->core_irqres->start);
3931 host->sdcc_irq_disabled = 1;
3932
3933 /*
3934 * If MMC core level suspend is not supported,
3935 * turn off clocks to allow deep sleep (TCXO
3936 * shutdown).
3937 */
3938 mmc->ios.clock = 0;
3939 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
3940 enable_irq(host->core_irqres->start);
3941 host->sdcc_irq_disabled = 0;
3942
3943 if (host->plat->sdiowakeup_irq) {
3944 host->sdio_irq_disabled = 0;
3945 msmsdcc_enable_irq_wake(host);
3946 enable_irq(host->plat->sdiowakeup_irq);
3947 }
3948 }
3949 }
3950 host->sdcc_suspending = 0;
3951 mmc->suspend_task = NULL;
3952 if (rc && wake_lock_active(&host->sdio_suspend_wlock))
3953 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07003954 }
Sahitya Tummala7661a452011-07-18 13:28:35 +05303955 pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003956 return rc;
3957}
3958
3959static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003960msmsdcc_runtime_resume(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003961{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003962 struct mmc_host *mmc = dev_get_drvdata(dev);
3963 struct msmsdcc_host *host = mmc_priv(mmc);
3964 unsigned long flags;
3965
3966 if (host->plat->is_sdio_al_client)
3967 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -07003968
Sahitya Tummala7661a452011-07-18 13:28:35 +05303969 pr_debug("%s: %s: start\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003970 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003971 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
3972 if (host->sdcc_irq_disabled) {
3973 enable_irq(host->core_irqres->start);
3974 host->sdcc_irq_disabled = 0;
3975 }
3976 }
3977 mmc->ios.clock = host->clk_rate;
3978 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07003979
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003980 spin_lock_irqsave(&host->lock, flags);
3981 writel_relaxed(host->mci_irqenable, host->base + MMCIMASK0);
3982 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07003983
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003984 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
3985 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) &&
3986 !host->sdio_irq_disabled) {
3987 if (host->plat->sdiowakeup_irq) {
3988 disable_irq_nosync(
3989 host->plat->sdiowakeup_irq);
3990 msmsdcc_disable_irq_wake(host);
3991 host->sdio_irq_disabled = 1;
3992 }
3993 }
San Mehat9d2bd732009-09-22 16:44:22 -07003994
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003995 spin_unlock_irqrestore(&host->lock, flags);
3996
3997 mmc_resume_host(mmc);
3998
3999 /*
4000 * FIXME: Clearing of flags must be handled in clients
4001 * resume handler.
4002 */
4003 spin_lock_irqsave(&host->lock, flags);
4004 mmc->pm_flags = 0;
4005 spin_unlock_irqrestore(&host->lock, flags);
4006
4007 /*
4008 * After resuming the host wait for sometime so that
4009 * the SDIO work will be processed.
4010 */
4011 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO)) {
4012 if ((host->plat->cfg_mpm_sdiowakeup ||
4013 host->plat->sdiowakeup_irq) &&
4014 wake_lock_active(&host->sdio_wlock))
4015 wake_lock_timeout(&host->sdio_wlock, 1);
4016 }
4017
4018 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07004019 }
Sahitya Tummala7661a452011-07-18 13:28:35 +05304020 pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07004021 return 0;
4022}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004023
4024static int msmsdcc_runtime_idle(struct device *dev)
4025{
4026 struct mmc_host *mmc = dev_get_drvdata(dev);
4027 struct msmsdcc_host *host = mmc_priv(mmc);
4028
4029 if (host->plat->is_sdio_al_client)
4030 return 0;
4031
4032 /* Idle timeout is not configurable for now */
4033 pm_schedule_suspend(dev, MSM_MMC_IDLE_TIMEOUT);
4034
4035 return -EAGAIN;
4036}
4037
4038static int msmsdcc_pm_suspend(struct device *dev)
4039{
4040 struct mmc_host *mmc = dev_get_drvdata(dev);
4041 struct msmsdcc_host *host = mmc_priv(mmc);
4042 int rc = 0;
4043
4044 if (host->plat->is_sdio_al_client)
4045 return 0;
4046
4047
4048 if (host->plat->status_irq)
4049 disable_irq(host->plat->status_irq);
4050
4051 if (!pm_runtime_suspended(dev))
4052 rc = msmsdcc_runtime_suspend(dev);
4053
4054 return rc;
4055}
4056
4057static int msmsdcc_pm_resume(struct device *dev)
4058{
4059 struct mmc_host *mmc = dev_get_drvdata(dev);
4060 struct msmsdcc_host *host = mmc_priv(mmc);
4061 int rc = 0;
4062
4063 if (host->plat->is_sdio_al_client)
4064 return 0;
4065
4066 rc = msmsdcc_runtime_resume(dev);
4067 if (host->plat->status_irq) {
4068 msmsdcc_check_status((unsigned long)host);
4069 enable_irq(host->plat->status_irq);
4070 }
4071
4072 /* Update the run-time PM status */
4073 pm_runtime_disable(dev);
4074 rc = pm_runtime_set_active(dev);
4075 if (rc < 0)
4076 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
4077 __func__, rc);
4078 pm_runtime_enable(dev);
4079
4080 return rc;
4081}
4082
Daniel Walker08ecfde2010-06-23 12:32:20 -07004083#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004084#define msmsdcc_runtime_suspend NULL
4085#define msmsdcc_runtime_resume NULL
4086#define msmsdcc_runtime_idle NULL
4087#define msmsdcc_pm_suspend NULL
4088#define msmsdcc_pm_resume NULL
Daniel Walker08ecfde2010-06-23 12:32:20 -07004089#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004090
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004091static const struct dev_pm_ops msmsdcc_dev_pm_ops = {
4092 .runtime_suspend = msmsdcc_runtime_suspend,
4093 .runtime_resume = msmsdcc_runtime_resume,
4094 .runtime_idle = msmsdcc_runtime_idle,
4095 .suspend = msmsdcc_pm_suspend,
4096 .resume = msmsdcc_pm_resume,
4097};
4098
San Mehat9d2bd732009-09-22 16:44:22 -07004099static struct platform_driver msmsdcc_driver = {
4100 .probe = msmsdcc_probe,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004101 .remove = msmsdcc_remove,
San Mehat9d2bd732009-09-22 16:44:22 -07004102 .driver = {
4103 .name = "msm_sdcc",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004104 .pm = &msmsdcc_dev_pm_ops,
San Mehat9d2bd732009-09-22 16:44:22 -07004105 },
4106};
4107
4108static int __init msmsdcc_init(void)
4109{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004110#if defined(CONFIG_DEBUG_FS)
4111 int ret = 0;
4112 ret = msmsdcc_dbg_init();
4113 if (ret) {
4114 pr_err("Failed to create debug fs dir \n");
4115 return ret;
4116 }
4117#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004118 return platform_driver_register(&msmsdcc_driver);
4119}
4120
4121static void __exit msmsdcc_exit(void)
4122{
4123 platform_driver_unregister(&msmsdcc_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004124
4125#if defined(CONFIG_DEBUG_FS)
4126 debugfs_remove(debugfs_file);
4127 debugfs_remove(debugfs_dir);
4128#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004129}
4130
4131module_init(msmsdcc_init);
4132module_exit(msmsdcc_exit);
4133
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004134MODULE_DESCRIPTION("Qualcomm Multimedia Card Interface driver");
San Mehat9d2bd732009-09-22 16:44:22 -07004135MODULE_LICENSE("GPL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004136
4137#if defined(CONFIG_DEBUG_FS)
4138
4139static int
4140msmsdcc_dbg_state_open(struct inode *inode, struct file *file)
4141{
4142 file->private_data = inode->i_private;
4143 return 0;
4144}
4145
4146static ssize_t
4147msmsdcc_dbg_state_read(struct file *file, char __user *ubuf,
4148 size_t count, loff_t *ppos)
4149{
4150 struct msmsdcc_host *host = (struct msmsdcc_host *) file->private_data;
4151 char buf[1024];
4152 int max, i;
4153
4154 i = 0;
4155 max = sizeof(buf) - 1;
4156
4157 i += scnprintf(buf + i, max - i, "STAT: %p %p %p\n", host->curr.mrq,
4158 host->curr.cmd, host->curr.data);
4159 if (host->curr.cmd) {
4160 struct mmc_command *cmd = host->curr.cmd;
4161
4162 i += scnprintf(buf + i, max - i, "CMD : %.8x %.8x %.8x\n",
4163 cmd->opcode, cmd->arg, cmd->flags);
4164 }
4165 if (host->curr.data) {
4166 struct mmc_data *data = host->curr.data;
4167 i += scnprintf(buf + i, max - i,
4168 "DAT0: %.8x %.8x %.8x %.8x %.8x %.8x\n",
4169 data->timeout_ns, data->timeout_clks,
4170 data->blksz, data->blocks, data->error,
4171 data->flags);
4172 i += scnprintf(buf + i, max - i, "DAT1: %.8x %.8x %.8x %p\n",
4173 host->curr.xfer_size, host->curr.xfer_remain,
4174 host->curr.data_xfered, host->dma.sg);
4175 }
4176
4177 return simple_read_from_buffer(ubuf, count, ppos, buf, i);
4178}
4179
4180static const struct file_operations msmsdcc_dbg_state_ops = {
4181 .read = msmsdcc_dbg_state_read,
4182 .open = msmsdcc_dbg_state_open,
4183};
4184
4185static void msmsdcc_dbg_createhost(struct msmsdcc_host *host)
4186{
4187 if (debugfs_dir) {
4188 debugfs_file = debugfs_create_file(mmc_hostname(host->mmc),
4189 0644, debugfs_dir, host,
4190 &msmsdcc_dbg_state_ops);
4191 }
4192}
4193
4194static int __init msmsdcc_dbg_init(void)
4195{
4196 int err;
4197
4198 debugfs_dir = debugfs_create_dir("msmsdcc", 0);
4199 if (IS_ERR(debugfs_dir)) {
4200 err = PTR_ERR(debugfs_dir);
4201 debugfs_dir = NULL;
4202 return err;
4203 }
4204
4205 return 0;
4206}
4207#endif