blob: fecc2e0dbc0ac262b598e3a4fa4c6600efdf21c3 [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 -070083#define DUMMY_52_STATE_NONE 0
84#define DUMMY_52_STATE_SENT 1
San Mehat9d2bd732009-09-22 16:44:22 -070085
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070086static struct mmc_command dummy52cmd;
87static struct mmc_request dummy52mrq = {
88 .cmd = &dummy52cmd,
89 .data = NULL,
90 .stop = NULL,
91};
92static struct mmc_command dummy52cmd = {
93 .opcode = SD_IO_RW_DIRECT,
94 .flags = MMC_RSP_PRESENT,
95 .data = NULL,
96 .mrq = &dummy52mrq,
97};
98/*
99 * An array holding the Tuning pattern to compare with when
100 * executing a tuning cycle.
101 */
102static const u32 cmd19_tuning_block[16] = {
103 0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
104 0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
105 0xF0FFF0FF, 0x3CCCFC0F, 0xCFCC33CC, 0xEEFFEFFF,
106 0xFDFFFDFF, 0xFFBFFFDF, 0xFFF7FFBB, 0xDE7B7FF7
107};
San Mehat865c8062009-11-13 13:42:06 -0800108
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700109#define VERBOSE_COMMAND_TIMEOUTS 0
110
111#if IRQ_DEBUG == 1
112static char *irq_status_bits[] = { "cmdcrcfail", "datcrcfail", "cmdtimeout",
113 "dattimeout", "txunderrun", "rxoverrun",
114 "cmdrespend", "cmdsent", "dataend", NULL,
115 "datablkend", "cmdactive", "txactive",
116 "rxactive", "txhalfempty", "rxhalffull",
117 "txfifofull", "rxfifofull", "txfifoempty",
118 "rxfifoempty", "txdataavlbl", "rxdataavlbl",
119 "sdiointr", "progdone", "atacmdcompl",
120 "sdiointrope", "ccstimeout", NULL, NULL,
121 NULL, NULL, NULL };
122
123static void
124msmsdcc_print_status(struct msmsdcc_host *host, char *hdr, uint32_t status)
San Mehat865c8062009-11-13 13:42:06 -0800125{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126 int i;
San Mehat8b1c2ba2009-11-16 10:17:30 -0800127
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700128 pr_debug("%s-%s ", mmc_hostname(host->mmc), hdr);
129 for (i = 0; i < 32; i++) {
130 if (status & (1 << i))
131 pr_debug("%s ", irq_status_bits[i]);
San Mehat865c8062009-11-13 13:42:06 -0800132 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700133 pr_debug("\n");
San Mehatc7fc9372009-11-22 17:19:07 -0800134}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700135#endif
San Mehat865c8062009-11-13 13:42:06 -0800136
San Mehat9d2bd732009-09-22 16:44:22 -0700137static void
138msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
139 u32 c);
140
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
142static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
143 struct msmsdcc_sps_ep_conn_data *ep);
144static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
145 struct msmsdcc_sps_ep_conn_data *ep);
146#else
147static inline int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
148 struct msmsdcc_sps_ep_conn_data *ep,
149 bool is_producer) { return 0; }
150static inline void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
151 struct msmsdcc_sps_ep_conn_data *ep) { }
152static inline int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
153 struct msmsdcc_sps_ep_conn_data *ep)
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530154{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155 return 0;
156}
157static inline int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
158 struct msmsdcc_sps_ep_conn_data *ep)
159{
160 return 0;
161}
162static inline int msmsdcc_sps_init(struct msmsdcc_host *host) { return 0; }
163static inline void msmsdcc_sps_exit(struct msmsdcc_host *host) {}
164#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530165
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166/**
167 * Apply soft reset
168 *
169 * This function applies soft reset to SDCC core and
170 * BAM, DML core.
171 *
172 * This function should be called to recover from error
173 * conditions encountered with CMD/DATA tranfsers with card.
174 *
175 * Soft reset should only be used with SDCC controller v4.
176 *
177 * @host - Pointer to driver's host structure
178 *
179 */
180static void msmsdcc_soft_reset_and_restore(struct msmsdcc_host *host)
181{
182 int rc;
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530183
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700184 if (host->is_sps_mode) {
185 /* Reset DML first */
186 msmsdcc_dml_reset(host);
187 /* Now reset all BAM pipes connections */
188 rc = msmsdcc_sps_reset_ep(host, &host->sps.prod);
189 if (rc)
190 pr_err("%s:msmsdcc_sps_reset_ep() error=%d\n",
191 mmc_hostname(host->mmc), rc);
192 rc = msmsdcc_sps_reset_ep(host, &host->sps.cons);
193 if (rc)
194 pr_err("%s:msmsdcc_sps_reset_ep() error=%d\n",
195 mmc_hostname(host->mmc), rc);
196 }
197 /*
198 * Reset SDCC controller's DPSM (data path state machine
199 * and CPSM (command path state machine).
200 */
201 mb();
202 writel_relaxed(0, host->base + MMCICOMMAND);
203 writel_relaxed(0, host->base + MMCIDATACTRL);
204 mb();
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530205
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700206 pr_debug("%s: Applied soft reset to Controller\n",
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530207 mmc_hostname(host->mmc));
208
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209 if (host->is_sps_mode) {
210 /* Restore all BAM pipes connections */
211 rc = msmsdcc_sps_restore_ep(host, &host->sps.prod);
212 if (rc)
213 pr_err("%s:msmsdcc_sps_restore_ep() error=%d\n",
214 mmc_hostname(host->mmc), rc);
215 rc = msmsdcc_sps_restore_ep(host, &host->sps.cons);
216 if (rc)
217 pr_err("%s:msmsdcc_sps_restore_ep() error=%d\n",
218 mmc_hostname(host->mmc), rc);
219 msmsdcc_dml_init(host);
220 }
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530221}
222
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700223static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
224{
225 if (host->plat->sdcc_v4_sup) {
226 msmsdcc_soft_reset_and_restore(host);
227 } else {
228 /* Give Clock reset (hard reset) to controller */
229 u32 mci_clk = 0;
230 u32 mci_mask0 = 0;
231 int ret;
232
233 /* Save the controller state */
234 mci_clk = readl_relaxed(host->base + MMCICLOCK);
235 mci_mask0 = readl_relaxed(host->base + MMCIMASK0);
236
237 mb();
238 /* Reset the controller */
239 ret = clk_reset(host->clk, CLK_RESET_ASSERT);
240 if (ret)
241 pr_err("%s: Clock assert failed at %u Hz"
242 " with err %d\n", mmc_hostname(host->mmc),
243 host->clk_rate, ret);
244
245 ret = clk_reset(host->clk, CLK_RESET_DEASSERT);
246 if (ret)
247 pr_err("%s: Clock deassert failed at %u Hz"
248 " with err %d\n", mmc_hostname(host->mmc),
249 host->clk_rate, ret);
250
251 pr_debug("%s: Controller has been reinitialized\n",
252 mmc_hostname(host->mmc));
253
254 mb();
255 /* Restore the contoller state */
256 writel_relaxed(host->pwr, host->base + MMCIPOWER);
257 writel_relaxed(mci_clk, host->base + MMCICLOCK);
258 writel_relaxed(mci_mask0, host->base + MMCIMASK0);
259 ret = clk_set_rate(host->clk, host->clk_rate);
260 if (ret)
261 pr_err("%s: Failed to set clk rate %u Hz. err %d\n",
262 mmc_hostname(host->mmc),
263 host->clk_rate, ret);
264 mb();
265 }
266}
267
268static int
San Mehat9d2bd732009-09-22 16:44:22 -0700269msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
270{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700271 int retval = 0;
272
San Mehat9d2bd732009-09-22 16:44:22 -0700273 BUG_ON(host->curr.data);
274
275 host->curr.mrq = NULL;
276 host->curr.cmd = NULL;
277
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700278 del_timer(&host->req_tout_timer);
279
San Mehat9d2bd732009-09-22 16:44:22 -0700280 if (mrq->data)
281 mrq->data->bytes_xfered = host->curr.data_xfered;
282 if (mrq->cmd->error == -ETIMEDOUT)
283 mdelay(5);
284
285 /*
286 * Need to drop the host lock here; mmc_request_done may call
287 * back into the driver...
288 */
289 spin_unlock(&host->lock);
290 mmc_request_done(host->mmc, mrq);
291 spin_lock(&host->lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292
293 return retval;
San Mehat9d2bd732009-09-22 16:44:22 -0700294}
295
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700296static inline void msmsdcc_delay(struct msmsdcc_host *host);
297
San Mehat9d2bd732009-09-22 16:44:22 -0700298static void
299msmsdcc_stop_data(struct msmsdcc_host *host)
300{
San Mehat9d2bd732009-09-22 16:44:22 -0700301 host->curr.data = NULL;
Sahitya Tummala0c521cc2010-12-08 15:03:07 +0530302 host->curr.got_dataend = 0;
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700303 writel_relaxed(0, host->base + MMCIDATACTRL);
304 msmsdcc_delay(host); /* Allow the DPSM to be reset */
San Mehat9d2bd732009-09-22 16:44:22 -0700305}
306
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700307static inline uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
San Mehat9d2bd732009-09-22 16:44:22 -0700308{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700309 return host->core_memres->start + MMCIFIFO;
310}
311
312static inline unsigned int msmsdcc_get_min_sup_clk_rate(
313 struct msmsdcc_host *host);
314static inline void msmsdcc_delay(struct msmsdcc_host *host)
315{
316 mb();
317 udelay(1 + ((3 * USEC_PER_SEC) /
318 (host->clk_rate ? host->clk_rate :
319 msmsdcc_get_min_sup_clk_rate(host))));
San Mehat9d2bd732009-09-22 16:44:22 -0700320}
321
San Mehat56a8b5b2009-11-21 12:29:46 -0800322static inline void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700323msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c)
324{
325 writel_relaxed(arg, host->base + MMCIARGUMENT);
326 msmsdcc_delay(host);
327 writel_relaxed(c, host->base + MMCICOMMAND);
328 mb();
San Mehat56a8b5b2009-11-21 12:29:46 -0800329}
330
331static void
332msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
333{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->user;
San Mehat56a8b5b2009-11-21 12:29:46 -0800335
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 writel_relaxed(host->cmd_timeout, host->base + MMCIDATATIMER);
337 writel_relaxed((unsigned int)host->curr.xfer_size,
338 host->base + MMCIDATALENGTH);
339 msmsdcc_delay(host); /* Allow data parms to be applied */
340 writel_relaxed(host->cmd_datactrl, host->base + MMCIDATACTRL);
341 msmsdcc_delay(host); /* Force delay prior to ADM or command */
San Mehat56a8b5b2009-11-21 12:29:46 -0800342
San Mehat6ac9ea62009-12-02 17:24:58 -0800343 if (host->cmd_cmd) {
344 msmsdcc_start_command_exec(host,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700345 (u32)host->cmd_cmd->arg, (u32)host->cmd_c);
San Mehat6ac9ea62009-12-02 17:24:58 -0800346 }
San Mehat56a8b5b2009-11-21 12:29:46 -0800347}
348
San Mehat9d2bd732009-09-22 16:44:22 -0700349static void
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530350msmsdcc_dma_complete_tlet(unsigned long data)
San Mehat9d2bd732009-09-22 16:44:22 -0700351{
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530352 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
San Mehat9d2bd732009-09-22 16:44:22 -0700353 unsigned long flags;
354 struct mmc_request *mrq;
355
356 spin_lock_irqsave(&host->lock, flags);
357 mrq = host->curr.mrq;
358 BUG_ON(!mrq);
359
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530360 if (!(host->dma.result & DMOV_RSLT_VALID)) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700361 pr_err("msmsdcc: Invalid DataMover result\n");
San Mehat9d2bd732009-09-22 16:44:22 -0700362 goto out;
363 }
364
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530365 if (host->dma.result & DMOV_RSLT_DONE) {
San Mehat9d2bd732009-09-22 16:44:22 -0700366 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700367 host->curr.xfer_remain -= host->curr.xfer_size;
San Mehat9d2bd732009-09-22 16:44:22 -0700368 } else {
369 /* Error or flush */
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530370 if (host->dma.result & DMOV_RSLT_ERROR)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700371 pr_err("%s: DMA error (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530372 mmc_hostname(host->mmc), host->dma.result);
373 if (host->dma.result & DMOV_RSLT_FLUSH)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700374 pr_err("%s: DMA channel flushed (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530375 mmc_hostname(host->mmc), host->dma.result);
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530376 pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377 host->dma.err.flush[0], host->dma.err.flush[1],
378 host->dma.err.flush[2], host->dma.err.flush[3],
379 host->dma.err.flush[4],
380 host->dma.err.flush[5]);
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530381 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -0700382 if (!mrq->data->error)
383 mrq->data->error = -EIO;
384 }
San Mehat9d2bd732009-09-22 16:44:22 -0700385 dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
386 host->dma.dir);
387
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700388 if (host->curr.user_pages) {
389 struct scatterlist *sg = host->dma.sg;
390 int i;
391
392 for (i = 0; i < host->dma.num_ents; i++, sg++)
393 flush_dcache_page(sg_page(sg));
394 }
395
San Mehat9d2bd732009-09-22 16:44:22 -0700396 host->dma.sg = NULL;
San Mehat56a8b5b2009-11-21 12:29:46 -0800397 host->dma.busy = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700398
Sahitya Tummala0c521cc2010-12-08 15:03:07 +0530399 if (host->curr.got_dataend || mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700400
401 /*
402 * If we've already gotten our DATAEND / DATABLKEND
403 * for this request, then complete it through here.
404 */
405 msmsdcc_stop_data(host);
406
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407 if (!mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700408 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700409 host->curr.xfer_remain -= host->curr.xfer_size;
410 }
San Mehat9d2bd732009-09-22 16:44:22 -0700411 if (!mrq->data->stop || mrq->cmd->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700412 host->curr.mrq = NULL;
413 host->curr.cmd = NULL;
414 mrq->data->bytes_xfered = host->curr.data_xfered;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700415 del_timer(&host->req_tout_timer);
San Mehat9d2bd732009-09-22 16:44:22 -0700416 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700417
San Mehat9d2bd732009-09-22 16:44:22 -0700418 mmc_request_done(host->mmc, mrq);
419 return;
420 } else
421 msmsdcc_start_command(host, mrq->data->stop, 0);
422 }
423
424out:
425 spin_unlock_irqrestore(&host->lock, flags);
426 return;
427}
428
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
430/**
431 * Callback notification from SPS driver
432 *
433 * This callback function gets triggered called from
434 * SPS driver when requested SPS data transfer is
435 * completed.
436 *
437 * SPS driver invokes this callback in BAM irq context so
438 * SDCC driver schedule a tasklet for further processing
439 * this callback notification at later point of time in
440 * tasklet context and immediately returns control back
441 * to SPS driver.
442 *
443 * @nofity - Pointer to sps event notify sturcture
444 *
445 */
446static void
447msmsdcc_sps_complete_cb(struct sps_event_notify *notify)
448{
449 struct msmsdcc_host *host =
450 (struct msmsdcc_host *)
451 ((struct sps_event_notify *)notify)->user;
452
453 host->sps.notify = *notify;
454 pr_debug("%s: %s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
455 mmc_hostname(host->mmc), __func__, notify->event_id,
456 notify->data.transfer.iovec.addr,
457 notify->data.transfer.iovec.size,
458 notify->data.transfer.iovec.flags);
459 /* Schedule a tasklet for completing data transfer */
460 tasklet_schedule(&host->sps.tlet);
461}
462
463/**
464 * Tasklet handler for processing SPS callback event
465 *
466 * This function processing SPS event notification and
467 * checks if the SPS transfer is completed or not and
468 * then accordingly notifies status to MMC core layer.
469 *
470 * This function is called in tasklet context.
471 *
472 * @data - Pointer to sdcc driver data
473 *
474 */
475static void msmsdcc_sps_complete_tlet(unsigned long data)
476{
477 unsigned long flags;
478 int i, rc;
479 u32 data_xfered = 0;
480 struct mmc_request *mrq;
481 struct sps_iovec iovec;
482 struct sps_pipe *sps_pipe_handle;
483 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
484 struct sps_event_notify *notify = &host->sps.notify;
485
486 spin_lock_irqsave(&host->lock, flags);
487 if (host->sps.dir == DMA_FROM_DEVICE)
488 sps_pipe_handle = host->sps.prod.pipe_handle;
489 else
490 sps_pipe_handle = host->sps.cons.pipe_handle;
491 mrq = host->curr.mrq;
492
493 if (!mrq) {
494 spin_unlock_irqrestore(&host->lock, flags);
495 return;
496 }
497
498 pr_debug("%s: %s: sps event_id=%d\n",
499 mmc_hostname(host->mmc), __func__,
500 notify->event_id);
501
502 if (msmsdcc_is_dml_busy(host)) {
503 /* oops !!! this should never happen. */
504 pr_err("%s: %s: Received SPS EOT event"
505 " but DML HW is still busy !!!\n",
506 mmc_hostname(host->mmc), __func__);
507 }
508 /*
509 * Got End of transfer event!!! Check if all of the data
510 * has been transferred?
511 */
512 for (i = 0; i < host->sps.xfer_req_cnt; i++) {
513 rc = sps_get_iovec(sps_pipe_handle, &iovec);
514 if (rc) {
515 pr_err("%s: %s: sps_get_iovec() failed rc=%d, i=%d",
516 mmc_hostname(host->mmc), __func__, rc, i);
517 break;
518 }
519 data_xfered += iovec.size;
520 }
521
522 if (data_xfered == host->curr.xfer_size) {
523 host->curr.data_xfered = host->curr.xfer_size;
524 host->curr.xfer_remain -= host->curr.xfer_size;
525 pr_debug("%s: Data xfer success. data_xfered=0x%x",
526 mmc_hostname(host->mmc),
527 host->curr.xfer_size);
528 } else {
529 pr_err("%s: Data xfer failed. data_xfered=0x%x,"
530 " xfer_size=%d", mmc_hostname(host->mmc),
531 data_xfered, host->curr.xfer_size);
532 msmsdcc_reset_and_restore(host);
533 if (!mrq->data->error)
534 mrq->data->error = -EIO;
535 }
536
537 /* Unmap sg buffers */
538 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
539 host->sps.dir);
540
541 host->sps.sg = NULL;
542 host->sps.busy = 0;
543
544 if (host->curr.got_dataend || mrq->data->error) {
545 /*
546 * If we've already gotten our DATAEND / DATABLKEND
547 * for this request, then complete it through here.
548 */
549 msmsdcc_stop_data(host);
550
551 if (!mrq->data->error) {
552 host->curr.data_xfered = host->curr.xfer_size;
553 host->curr.xfer_remain -= host->curr.xfer_size;
554 }
555 if (!mrq->data->stop || mrq->cmd->error) {
556 host->curr.mrq = NULL;
557 host->curr.cmd = NULL;
558 mrq->data->bytes_xfered = host->curr.data_xfered;
559 del_timer(&host->req_tout_timer);
560 spin_unlock_irqrestore(&host->lock, flags);
561
562 mmc_request_done(host->mmc, mrq);
563 return;
564 } else {
565 msmsdcc_start_command(host, mrq->data->stop, 0);
566 }
567 }
568 spin_unlock_irqrestore(&host->lock, flags);
569}
570
571/**
572 * Exit from current SPS data transfer
573 *
574 * This function exits from current SPS data transfer.
575 *
576 * This function should be called when error condition
577 * is encountered during data transfer.
578 *
579 * @host - Pointer to sdcc host structure
580 *
581 */
582static void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host)
583{
584 struct mmc_request *mrq;
585
586 mrq = host->curr.mrq;
587 BUG_ON(!mrq);
588
589 msmsdcc_reset_and_restore(host);
590 if (!mrq->data->error)
591 mrq->data->error = -EIO;
592
593 /* Unmap sg buffers */
594 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
595 host->sps.dir);
596
597 host->sps.sg = NULL;
598 host->sps.busy = 0;
599 if (host->curr.data)
600 msmsdcc_stop_data(host);
601
602 if (!mrq->data->stop || mrq->cmd->error)
603 msmsdcc_request_end(host, mrq);
604 else
605 msmsdcc_start_command(host, mrq->data->stop, 0);
606
607}
608#else
609static inline void msmsdcc_sps_complete_cb(struct sps_event_notify *notify) { }
610static inline void msmsdcc_sps_complete_tlet(unsigned long data) { }
611static inline void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host) { }
612#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
613
614static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host);
615
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530616static void
617msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
618 unsigned int result,
619 struct msm_dmov_errdata *err)
620{
621 struct msmsdcc_dma_data *dma_data =
622 container_of(cmd, struct msmsdcc_dma_data, hdr);
623 struct msmsdcc_host *host = dma_data->host;
624
625 dma_data->result = result;
626 if (err)
627 memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
628
629 tasklet_schedule(&host->dma_tlet);
630}
631
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700632static int msmsdcc_check_dma_op_req(struct mmc_data *data)
San Mehat9d2bd732009-09-22 16:44:22 -0700633{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700634 if (((data->blksz * data->blocks) < MCI_FIFOSIZE) ||
635 ((data->blksz * data->blocks) % MCI_FIFOSIZE))
San Mehat9d2bd732009-09-22 16:44:22 -0700636 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637 else
638 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700639}
640
641static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
642{
643 struct msmsdcc_nc_dmadata *nc;
644 dmov_box *box;
645 uint32_t rows;
646 uint32_t crci;
647 unsigned int n;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700648 int i;
San Mehat9d2bd732009-09-22 16:44:22 -0700649 struct scatterlist *sg = data->sg;
650
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651 if (host->dma.channel == -1)
652 return -ENOENT;
San Mehat9d2bd732009-09-22 16:44:22 -0700653
654 host->dma.sg = data->sg;
655 host->dma.num_ents = data->sg_len;
656
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700657 BUG_ON(host->dma.num_ents > NR_SG); /* Prevent memory corruption */
San Mehat56a8b5b2009-11-21 12:29:46 -0800658
San Mehat9d2bd732009-09-22 16:44:22 -0700659 nc = host->dma.nc;
660
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700661 if (host->pdev_id == 1)
662 crci = DMOV_SDC1_CRCI;
663 else if (host->pdev_id == 2)
664 crci = DMOV_SDC2_CRCI;
665 else if (host->pdev_id == 3)
666 crci = DMOV_SDC3_CRCI;
667 else if (host->pdev_id == 4)
668 crci = DMOV_SDC4_CRCI;
669#ifdef DMOV_SDC5_CRCI
670 else if (host->pdev_id == 5)
671 crci = DMOV_SDC5_CRCI;
672#endif
673 else {
San Mehat9d2bd732009-09-22 16:44:22 -0700674 host->dma.sg = NULL;
675 host->dma.num_ents = 0;
676 return -ENOENT;
677 }
678
679 if (data->flags & MMC_DATA_READ)
680 host->dma.dir = DMA_FROM_DEVICE;
681 else
682 host->dma.dir = DMA_TO_DEVICE;
683
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700684 /* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
San Mehat9d2bd732009-09-22 16:44:22 -0700685 host->curr.user_pages = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700686 box = &nc->cmd[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700687 for (i = 0; i < host->dma.num_ents; i++) {
San Mehat9d2bd732009-09-22 16:44:22 -0700688 box->cmd = CMD_MODE_BOX;
689
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690 /* Initialize sg dma address */
691 sg->dma_address = pfn_to_dma(mmc_dev(host->mmc),
692 page_to_pfn(sg_page(sg)))
693 + sg->offset;
694
695 if (i == (host->dma.num_ents - 1))
San Mehat9d2bd732009-09-22 16:44:22 -0700696 box->cmd |= CMD_LC;
697 rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
698 (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
699 (sg_dma_len(sg) / MCI_FIFOSIZE) ;
700
701 if (data->flags & MMC_DATA_READ) {
702 box->src_row_addr = msmsdcc_fifo_addr(host);
703 box->dst_row_addr = sg_dma_address(sg);
704
705 box->src_dst_len = (MCI_FIFOSIZE << 16) |
706 (MCI_FIFOSIZE);
707 box->row_offset = MCI_FIFOSIZE;
708
709 box->num_rows = rows * ((1 << 16) + 1);
710 box->cmd |= CMD_SRC_CRCI(crci);
711 } else {
712 box->src_row_addr = sg_dma_address(sg);
713 box->dst_row_addr = msmsdcc_fifo_addr(host);
714
715 box->src_dst_len = (MCI_FIFOSIZE << 16) |
716 (MCI_FIFOSIZE);
717 box->row_offset = (MCI_FIFOSIZE << 16);
718
719 box->num_rows = rows * ((1 << 16) + 1);
720 box->cmd |= CMD_DST_CRCI(crci);
721 }
722 box++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700723 sg++;
724 }
725
726 /* location of command block must be 64 bit aligned */
727 BUG_ON(host->dma.cmd_busaddr & 0x07);
728
729 nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
730 host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
731 DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
732 host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
733 host->dma.hdr.crci_mask = msm_dmov_build_crci_mask(1, crci);
734
735 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
736 host->dma.num_ents, host->dma.dir);
737 /* dsb inside dma_map_sg will write nc out to mem as well */
738
739 if (n != host->dma.num_ents) {
740 pr_err("%s: Unable to map in all sg elements\n",
741 mmc_hostname(host->mmc));
742 host->dma.sg = NULL;
743 host->dma.num_ents = 0;
744 return -ENOMEM;
San Mehat56a8b5b2009-11-21 12:29:46 -0800745 }
San Mehat9d2bd732009-09-22 16:44:22 -0700746
747 return 0;
748}
749
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700750#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
751/**
752 * Submits data transfer request to SPS driver
753 *
754 * This function make sg (scatter gather) data buffers
755 * DMA ready and then submits them to SPS driver for
756 * transfer.
757 *
758 * @host - Pointer to sdcc host structure
759 * @data - Pointer to mmc_data structure
760 *
761 * @return 0 if success else negative value
762 */
763static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
764 struct mmc_data *data)
San Mehat56a8b5b2009-11-21 12:29:46 -0800765{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700766 int rc = 0;
767 u32 flags;
768 int i;
769 u32 addr, len, data_cnt;
770 struct scatterlist *sg = data->sg;
771 struct sps_pipe *sps_pipe_handle;
772
773 BUG_ON(data->sg_len > NR_SG); /* Prevent memory corruption */
774
775 host->sps.sg = data->sg;
776 host->sps.num_ents = data->sg_len;
777 host->sps.xfer_req_cnt = 0;
778 if (data->flags & MMC_DATA_READ) {
779 host->sps.dir = DMA_FROM_DEVICE;
780 sps_pipe_handle = host->sps.prod.pipe_handle;
781 } else {
782 host->sps.dir = DMA_TO_DEVICE;
783 sps_pipe_handle = host->sps.cons.pipe_handle;
784 }
785
786 /* Make sg buffers DMA ready */
787 rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
788 host->sps.dir);
789
790 if (rc != data->sg_len) {
791 pr_err("%s: Unable to map in all sg elements, rc=%d\n",
792 mmc_hostname(host->mmc), rc);
793 host->sps.sg = NULL;
794 host->sps.num_ents = 0;
795 rc = -ENOMEM;
796 goto dma_map_err;
797 }
798
799 pr_debug("%s: %s: %s: pipe=0x%x, total_xfer=0x%x, sg_len=%d\n",
800 mmc_hostname(host->mmc), __func__,
801 host->sps.dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
802 (u32)sps_pipe_handle, host->curr.xfer_size, data->sg_len);
803
804 for (i = 0; i < data->sg_len; i++) {
805 /*
806 * Check if this is the last buffer to transfer?
807 * If yes then set the INT and EOT flags.
808 */
809 len = sg_dma_len(sg);
810 addr = sg_dma_address(sg);
811 flags = 0;
812 while (len > 0) {
813 if (len > SPS_MAX_DESC_SIZE) {
814 data_cnt = SPS_MAX_DESC_SIZE;
815 } else {
816 data_cnt = len;
817 if (i == data->sg_len - 1)
818 flags = SPS_IOVEC_FLAG_INT |
819 SPS_IOVEC_FLAG_EOT;
820 }
821 rc = sps_transfer_one(sps_pipe_handle, addr,
822 data_cnt, host, flags);
823 if (rc) {
824 pr_err("%s: sps_transfer_one() error! rc=%d,"
825 " pipe=0x%x, sg=0x%x, sg_buf_no=%d\n",
826 mmc_hostname(host->mmc), rc,
827 (u32)sps_pipe_handle, (u32)sg, i);
828 goto dma_map_err;
829 }
830 addr += data_cnt;
831 len -= data_cnt;
832 host->sps.xfer_req_cnt++;
833 }
834 sg++;
835 }
836 goto out;
837
838dma_map_err:
839 /* unmap sg buffers */
840 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
841 host->sps.dir);
842out:
843 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -0700844}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700845#else
846static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
847 struct mmc_data *data) { return 0; }
848#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
San Mehat9d2bd732009-09-22 16:44:22 -0700849
850static void
San Mehat56a8b5b2009-11-21 12:29:46 -0800851msmsdcc_start_command_deferred(struct msmsdcc_host *host,
852 struct mmc_command *cmd, u32 *c)
853{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854 DBG(host, "op %02x arg %08x flags %08x\n",
855 cmd->opcode, cmd->arg, cmd->flags);
856
San Mehat56a8b5b2009-11-21 12:29:46 -0800857 *c |= (cmd->opcode | MCI_CPSM_ENABLE);
858
859 if (cmd->flags & MMC_RSP_PRESENT) {
860 if (cmd->flags & MMC_RSP_136)
861 *c |= MCI_CPSM_LONGRSP;
862 *c |= MCI_CPSM_RESPONSE;
863 }
864
865 if (/*interrupt*/0)
866 *c |= MCI_CPSM_INTERRUPT;
867
868 if ((((cmd->opcode == 17) || (cmd->opcode == 18)) ||
869 ((cmd->opcode == 24) || (cmd->opcode == 25))) ||
870 (cmd->opcode == 53))
871 *c |= MCI_CSPM_DATCMD;
872
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700873 /* Check if AUTO CMD19 is required or not? */
874 if (((cmd->opcode == 17) || (cmd->opcode == 18)) &&
875 host->tuning_needed) {
876 msmsdcc_enable_cdr_cm_sdc4_dll(host);
877 *c |= MCI_CSPM_AUTO_CMD19;
878 }
879
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530880 if (host->prog_scan && (cmd->opcode == 12)) {
881 *c |= MCI_CPSM_PROGENA;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700882 host->prog_enable = 1;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530883 }
884
San Mehat56a8b5b2009-11-21 12:29:46 -0800885 if (cmd == cmd->mrq->stop)
886 *c |= MCI_CSPM_MCIABORT;
887
San Mehat56a8b5b2009-11-21 12:29:46 -0800888 if (host->curr.cmd != NULL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700889 pr_err("%s: Overlapping command requests\n",
890 mmc_hostname(host->mmc));
San Mehat56a8b5b2009-11-21 12:29:46 -0800891 }
892 host->curr.cmd = cmd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700893
894 /*
895 * Kick the software command timeout timer here.
896 * Timer expires in 10 secs.
897 */
898 mod_timer(&host->req_tout_timer,
899 (jiffies + msecs_to_jiffies(MSM_MMC_REQ_TIMEOUT)));
San Mehat56a8b5b2009-11-21 12:29:46 -0800900}
901
902static void
903msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data,
904 struct mmc_command *cmd, u32 c)
San Mehat9d2bd732009-09-22 16:44:22 -0700905{
906 unsigned int datactrl, timeout;
907 unsigned long long clks;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700908 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -0700909 unsigned int pio_irqmask = 0;
910
911 host->curr.data = data;
912 host->curr.xfer_size = data->blksz * data->blocks;
913 host->curr.xfer_remain = host->curr.xfer_size;
914 host->curr.data_xfered = 0;
915 host->curr.got_dataend = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700916
917 memset(&host->pio, 0, sizeof(host->pio));
918
San Mehat9d2bd732009-09-22 16:44:22 -0700919 datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
920
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700921 if (!msmsdcc_check_dma_op_req(data)) {
922 if (host->is_dma_mode && !msmsdcc_config_dma(host, data)) {
923 datactrl |= MCI_DPSM_DMAENABLE;
924 } else if (host->is_sps_mode) {
925 if (!msmsdcc_is_dml_busy(host)) {
926 if (!msmsdcc_sps_start_xfer(host, data)) {
927 /* Now kick start DML transfer */
928 mb();
929 msmsdcc_dml_start_xfer(host, data);
930 datactrl |= MCI_DPSM_DMAENABLE;
931 host->sps.busy = 1;
932 }
933 } else {
934 /*
935 * Can't proceed with new transfer as
936 * previous trasnfer is already in progress.
937 * There is no point of going into PIO mode
938 * as well. Is this a time to do kernel panic?
939 */
940 pr_err("%s: %s: DML HW is busy!!!"
941 " Can't perform new SPS transfers"
942 " now\n", mmc_hostname(host->mmc),
943 __func__);
944 }
945 }
946 }
947
948 /* Is data transfer in PIO mode required? */
949 if (!(datactrl & MCI_DPSM_DMAENABLE)) {
San Mehat9d2bd732009-09-22 16:44:22 -0700950 host->pio.sg = data->sg;
951 host->pio.sg_len = data->sg_len;
952 host->pio.sg_off = 0;
953
954 if (data->flags & MMC_DATA_READ) {
955 pio_irqmask = MCI_RXFIFOHALFFULLMASK;
956 if (host->curr.xfer_remain < MCI_FIFOSIZE)
957 pio_irqmask |= MCI_RXDATAAVLBLMASK;
958 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700959 pio_irqmask = MCI_TXFIFOHALFEMPTYMASK |
960 MCI_TXFIFOEMPTYMASK;
San Mehat9d2bd732009-09-22 16:44:22 -0700961 }
962
963 if (data->flags & MMC_DATA_READ)
964 datactrl |= MCI_DPSM_DIRECTION;
965
San Mehat56a8b5b2009-11-21 12:29:46 -0800966 clks = (unsigned long long)data->timeout_ns * host->clk_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700967 do_div(clks, 1000000000UL);
San Mehat56a8b5b2009-11-21 12:29:46 -0800968 timeout = data->timeout_clks + (unsigned int)clks*2 ;
San Mehat9d2bd732009-09-22 16:44:22 -0700969
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700970 if (host->is_dma_mode && (datactrl & MCI_DPSM_DMAENABLE)) {
971 /* Use ADM (Application Data Mover) HW for Data transfer */
972 /* Save parameters for the dma exec function */
San Mehat56a8b5b2009-11-21 12:29:46 -0800973 host->cmd_timeout = timeout;
974 host->cmd_pio_irqmask = pio_irqmask;
975 host->cmd_datactrl = datactrl;
976 host->cmd_cmd = cmd;
San Mehat9d2bd732009-09-22 16:44:22 -0700977
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700978 host->dma.hdr.exec_func = msmsdcc_dma_exec_func;
979 host->dma.hdr.user = (void *)host;
San Mehat9d2bd732009-09-22 16:44:22 -0700980 host->dma.busy = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700981 if (data->flags & MMC_DATA_WRITE)
982 host->prog_scan = 1;
San Mehat56a8b5b2009-11-21 12:29:46 -0800983
984 if (cmd) {
985 msmsdcc_start_command_deferred(host, cmd, &c);
986 host->cmd_c = c;
987 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700988 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
989 (~(MCI_IRQ_PIO))) | host->cmd_pio_irqmask,
990 host->base + MMCIMASK0);
991 mb();
992 msm_dmov_enqueue_cmd_ext(host->dma.channel, &host->dma.hdr);
San Mehat56a8b5b2009-11-21 12:29:46 -0800993 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700994 /* SPS-BAM mode or PIO mode */
995 if (data->flags & MMC_DATA_WRITE)
996 host->prog_scan = 1;
997 writel_relaxed(timeout, base + MMCIDATATIMER);
San Mehat56a8b5b2009-11-21 12:29:46 -0800998
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700999 writel_relaxed(host->curr.xfer_size, base + MMCIDATALENGTH);
San Mehat56a8b5b2009-11-21 12:29:46 -08001000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001001 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1002 (~(MCI_IRQ_PIO))) | pio_irqmask,
1003 host->base + MMCIMASK0);
1004 msmsdcc_delay(host); /* Allow parms to be applied */
1005 writel_relaxed(datactrl, base + MMCIDATACTRL);
San Mehat56a8b5b2009-11-21 12:29:46 -08001006
1007 if (cmd) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001008 msmsdcc_delay(host); /* Delay between data/command */
San Mehat56a8b5b2009-11-21 12:29:46 -08001009 /* Daisy-chain the command if requested */
1010 msmsdcc_start_command(host, cmd, c);
1011 }
San Mehat9d2bd732009-09-22 16:44:22 -07001012 }
1013}
1014
1015static void
1016msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
1017{
San Mehat56a8b5b2009-11-21 12:29:46 -08001018 msmsdcc_start_command_deferred(host, cmd, &c);
1019 msmsdcc_start_command_exec(host, cmd->arg, c);
San Mehat9d2bd732009-09-22 16:44:22 -07001020}
1021
1022static void
1023msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
1024 unsigned int status)
1025{
1026 if (status & MCI_DATACRCFAIL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001027 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1028 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1029 pr_err("%s: Data CRC error\n",
1030 mmc_hostname(host->mmc));
1031 pr_err("%s: opcode 0x%.8x\n", __func__,
1032 data->mrq->cmd->opcode);
1033 pr_err("%s: blksz %d, blocks %d\n", __func__,
1034 data->blksz, data->blocks);
1035 data->error = -EILSEQ;
1036 }
San Mehat9d2bd732009-09-22 16:44:22 -07001037 } else if (status & MCI_DATATIMEOUT) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001038 /* CRC is optional for the bus test commands, not all
1039 * cards respond back with CRC. However controller
1040 * waits for the CRC and times out. Hence ignore the
1041 * data timeouts during the Bustest.
1042 */
1043 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1044 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1045 pr_err("%s: Data timeout\n",
1046 mmc_hostname(host->mmc));
1047 data->error = -ETIMEDOUT;
1048 }
San Mehat9d2bd732009-09-22 16:44:22 -07001049 } else if (status & MCI_RXOVERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001050 pr_err("%s: RX overrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001051 data->error = -EIO;
1052 } else if (status & MCI_TXUNDERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001053 pr_err("%s: TX underrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001054 data->error = -EIO;
1055 } else {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001056 pr_err("%s: Unknown error (0x%.8x)\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001057 mmc_hostname(host->mmc), status);
San Mehat9d2bd732009-09-22 16:44:22 -07001058 data->error = -EIO;
1059 }
San Mehat9d2bd732009-09-22 16:44:22 -07001060
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001061 /* Dummy CMD52 is not needed when CMD53 has errors */
1062 if (host->plat->dummy52_required && host->dummy_52_needed)
1063 host->dummy_52_needed = 0;
1064}
San Mehat9d2bd732009-09-22 16:44:22 -07001065
1066static int
1067msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
1068{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001069 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001070 uint32_t *ptr = (uint32_t *) buffer;
1071 int count = 0;
1072
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301073 if (remain % 4)
1074 remain = ((remain >> 2) + 1) << 2;
1075
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001076 while (readl_relaxed(base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1077
1078 *ptr = readl_relaxed(base + MMCIFIFO + (count % MCI_FIFOSIZE));
San Mehat9d2bd732009-09-22 16:44:22 -07001079 ptr++;
1080 count += sizeof(uint32_t);
1081
1082 remain -= sizeof(uint32_t);
1083 if (remain == 0)
1084 break;
1085 }
1086 return count;
1087}
1088
1089static int
1090msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001091 unsigned int remain)
San Mehat9d2bd732009-09-22 16:44:22 -07001092{
1093 void __iomem *base = host->base;
1094 char *ptr = buffer;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001095 unsigned int maxcnt = MCI_FIFOHALFSIZE;
San Mehat9d2bd732009-09-22 16:44:22 -07001096
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001097 while (readl_relaxed(base + MMCISTATUS) &
1098 (MCI_TXFIFOEMPTY | MCI_TXFIFOHALFEMPTY)) {
1099 unsigned int count, sz;
San Mehat9d2bd732009-09-22 16:44:22 -07001100
San Mehat9d2bd732009-09-22 16:44:22 -07001101 count = min(remain, maxcnt);
1102
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301103 sz = count % 4 ? (count >> 2) + 1 : (count >> 2);
1104 writesl(base + MMCIFIFO, ptr, sz);
San Mehat9d2bd732009-09-22 16:44:22 -07001105 ptr += count;
1106 remain -= count;
1107
1108 if (remain == 0)
1109 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001110 }
1111 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07001112
1113 return ptr - buffer;
1114}
1115
San Mehat1cd22962010-02-03 12:59:29 -08001116static irqreturn_t
San Mehat9d2bd732009-09-22 16:44:22 -07001117msmsdcc_pio_irq(int irq, void *dev_id)
1118{
1119 struct msmsdcc_host *host = dev_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001120 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001121 uint32_t status;
1122
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001123 status = readl_relaxed(base + MMCISTATUS);
1124 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1125 (MCI_IRQ_PIO)) == 0)
1126 return IRQ_NONE;
1127
1128#if IRQ_DEBUG
1129 msmsdcc_print_status(host, "irq1-r", status);
1130#endif
1131
1132 spin_lock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001133
1134 do {
1135 unsigned long flags;
1136 unsigned int remain, len;
1137 char *buffer;
1138
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001139 if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_TXFIFOEMPTY
1140 | MCI_RXDATAAVLBL)))
1141 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001142
1143 /* Map the current scatter buffer */
1144 local_irq_save(flags);
1145 buffer = kmap_atomic(sg_page(host->pio.sg),
1146 KM_BIO_SRC_IRQ) + host->pio.sg->offset;
1147 buffer += host->pio.sg_off;
1148 remain = host->pio.sg->length - host->pio.sg_off;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001149
San Mehat9d2bd732009-09-22 16:44:22 -07001150 len = 0;
1151 if (status & MCI_RXACTIVE)
1152 len = msmsdcc_pio_read(host, buffer, remain);
1153 if (status & MCI_TXACTIVE)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001154 len = msmsdcc_pio_write(host, buffer, remain);
San Mehat9d2bd732009-09-22 16:44:22 -07001155
1156 /* Unmap the buffer */
1157 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
1158 local_irq_restore(flags);
1159
1160 host->pio.sg_off += len;
1161 host->curr.xfer_remain -= len;
1162 host->curr.data_xfered += len;
1163 remain -= len;
1164
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001165 if (remain) /* Done with this page? */
1166 break; /* Nope */
San Mehat9d2bd732009-09-22 16:44:22 -07001167
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001168 if (status & MCI_RXACTIVE && host->curr.user_pages)
1169 flush_dcache_page(sg_page(host->pio.sg));
San Mehat9d2bd732009-09-22 16:44:22 -07001170
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001171 if (!--host->pio.sg_len) {
1172 memset(&host->pio, 0, sizeof(host->pio));
1173 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001174 }
1175
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001176 /* Advance to next sg */
1177 host->pio.sg++;
1178 host->pio.sg_off = 0;
1179
1180 status = readl_relaxed(base + MMCISTATUS);
San Mehat9d2bd732009-09-22 16:44:22 -07001181 } while (1);
1182
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001183 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
1184 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1185 (~(MCI_IRQ_PIO))) | MCI_RXDATAAVLBLMASK,
1186 host->base + MMCIMASK0);
1187 if (!host->curr.xfer_remain) {
1188 /* Delay needed (same port was just written) */
1189 msmsdcc_delay(host);
1190 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1191 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1192 }
1193 mb();
1194 } else if (!host->curr.xfer_remain) {
1195 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1196 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1197 mb();
1198 }
San Mehat9d2bd732009-09-22 16:44:22 -07001199
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001200 spin_unlock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001201
1202 return IRQ_HANDLED;
1203}
1204
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001205static void
1206msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq);
1207
1208static void msmsdcc_wait_for_rxdata(struct msmsdcc_host *host,
1209 struct mmc_data *data)
1210{
1211 u32 loop_cnt = 0;
1212
1213 /*
1214 * For read commands with data less than fifo size, it is possible to
1215 * get DATAEND first and RXDATA_AVAIL might be set later because of
1216 * synchronization delay through the asynchronous RX FIFO. Thus, for
1217 * such cases, even after DATAEND interrupt is received software
1218 * should poll for RXDATA_AVAIL until the requested data is read out
1219 * of FIFO. This change is needed to get around this abnormal but
1220 * sometimes expected behavior of SDCC3 controller.
1221 *
1222 * We can expect RXDATAAVAIL bit to be set after 6HCLK clock cycles
1223 * after the data is loaded into RX FIFO. This would amount to less
1224 * than a microsecond and thus looping for 1000 times is good enough
1225 * for that delay.
1226 */
1227 while (((int)host->curr.xfer_remain > 0) && (++loop_cnt < 1000)) {
1228 if (readl_relaxed(host->base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1229 spin_unlock(&host->lock);
1230 msmsdcc_pio_irq(1, host);
1231 spin_lock(&host->lock);
1232 }
1233 }
1234 if (loop_cnt == 1000) {
1235 pr_info("%s: Timed out while polling for Rx Data\n",
1236 mmc_hostname(host->mmc));
1237 data->error = -ETIMEDOUT;
1238 msmsdcc_reset_and_restore(host);
1239 }
1240}
1241
San Mehat9d2bd732009-09-22 16:44:22 -07001242static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
1243{
1244 struct mmc_command *cmd = host->curr.cmd;
San Mehat9d2bd732009-09-22 16:44:22 -07001245
1246 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001247 cmd->resp[0] = readl_relaxed(host->base + MMCIRESPONSE0);
1248 cmd->resp[1] = readl_relaxed(host->base + MMCIRESPONSE1);
1249 cmd->resp[2] = readl_relaxed(host->base + MMCIRESPONSE2);
1250 cmd->resp[3] = readl_relaxed(host->base + MMCIRESPONSE3);
San Mehat9d2bd732009-09-22 16:44:22 -07001251
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001252 if (status & (MCI_CMDTIMEOUT | MCI_AUTOCMD19TIMEOUT)) {
1253#if VERBOSE_COMMAND_TIMEOUTS
1254 pr_err("%s: Command timeout\n", mmc_hostname(host->mmc));
1255#endif
San Mehat9d2bd732009-09-22 16:44:22 -07001256 cmd->error = -ETIMEDOUT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001257 } else if ((status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) &&
1258 !host->cmd19_tuning_in_progress) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001259 pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001260 cmd->error = -EILSEQ;
1261 }
1262
1263 if (!cmd->data || cmd->error) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001264 if (host->curr.data && host->dma.sg &&
1265 host->is_dma_mode)
San Mehat9d2bd732009-09-22 16:44:22 -07001266 msm_dmov_stop_cmd(host->dma.channel,
1267 &host->dma.hdr, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001268 else if (host->curr.data && host->sps.sg &&
1269 host->is_sps_mode){
1270 /* Stop current SPS transfer */
1271 msmsdcc_sps_exit_curr_xfer(host);
1272 }
San Mehat9d2bd732009-09-22 16:44:22 -07001273 else if (host->curr.data) { /* Non DMA */
Sahitya Tummalab08bb352010-12-08 15:03:05 +05301274 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -07001275 msmsdcc_stop_data(host);
1276 msmsdcc_request_end(host, cmd->mrq);
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301277 } else { /* host->data == NULL */
1278 if (!cmd->error && host->prog_enable) {
1279 if (status & MCI_PROGDONE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001280 host->prog_scan = 0;
1281 host->prog_enable = 0;
1282 msmsdcc_request_end(host, cmd->mrq);
1283 } else
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301284 host->curr.cmd = cmd;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301285 } else {
1286 if (host->prog_enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001287 host->prog_scan = 0;
1288 host->prog_enable = 0;
1289 }
1290 if (cmd->data && cmd->error) {
1291 msmsdcc_reset_and_restore(host);
1292 if (host->plat->dummy52_required &&
1293 host->dummy_52_needed)
1294 host->dummy_52_needed = 0;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301295 }
1296 msmsdcc_request_end(host, cmd->mrq);
1297 }
1298 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001299 } else if (cmd->data) {
San Mehat56a8b5b2009-11-21 12:29:46 -08001300 if (!(cmd->data->flags & MMC_DATA_READ))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001301 msmsdcc_start_data(host, cmd->data, NULL, 0);
Joe Perchesb5a74d62009-09-22 16:44:25 -07001302 }
1303}
1304
San Mehat9d2bd732009-09-22 16:44:22 -07001305static irqreturn_t
1306msmsdcc_irq(int irq, void *dev_id)
1307{
1308 struct msmsdcc_host *host = dev_id;
San Mehat9d2bd732009-09-22 16:44:22 -07001309 u32 status;
1310 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001311 int timer = 0;
San Mehat9d2bd732009-09-22 16:44:22 -07001312
1313 spin_lock(&host->lock);
1314
1315 do {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001316 struct mmc_command *cmd;
1317 struct mmc_data *data;
San Mehat9d2bd732009-09-22 16:44:22 -07001318
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001319 if (timer) {
1320 timer = 0;
1321 msmsdcc_delay(host);
1322 }
San Mehat865c8062009-11-13 13:42:06 -08001323
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001324 if (!host->clks_on) {
1325 pr_debug("%s: %s: SDIO async irq received\n",
1326 mmc_hostname(host->mmc), __func__);
1327 host->mmc->ios.clock = host->clk_rate;
1328 spin_unlock(&host->lock);
1329 host->mmc->ops->set_ios(host->mmc, &host->mmc->ios);
1330 spin_lock(&host->lock);
1331 if (host->plat->cfg_mpm_sdiowakeup &&
1332 (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1333 wake_lock(&host->sdio_wlock);
1334 /* only ansyc interrupt can come when clocks are off */
1335 writel_relaxed(MCI_SDIOINTMASK, host->base + MMCICLEAR);
1336 }
1337
1338 status = readl_relaxed(host->base + MMCISTATUS);
1339
1340 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1341 (~(MCI_IRQ_PIO))) == 0)
San Mehat865c8062009-11-13 13:42:06 -08001342 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001343
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001344#if IRQ_DEBUG
1345 msmsdcc_print_status(host, "irq0-r", status);
1346#endif
1347 status &= readl_relaxed(host->base + MMCIMASK0);
1348 writel_relaxed(status, host->base + MMCICLEAR);
1349 mb();
1350#if IRQ_DEBUG
1351 msmsdcc_print_status(host, "irq0-p", status);
1352#endif
1353#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
1354 if (status & MCI_SDIOINTROPE) {
1355 if (host->sdcc_suspending)
1356 wake_lock(&host->sdio_suspend_wlock);
1357 mmc_signal_sdio_irq(host->mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07001358 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001359#endif
1360 if ((host->plat->dummy52_required) &&
1361 (host->dummy_52_state == DUMMY_52_STATE_SENT)) {
1362 if (status & (MCI_PROGDONE | MCI_CMDCRCFAIL |
1363 MCI_CMDTIMEOUT)) {
1364 if (status & MCI_CMDTIMEOUT)
1365 pr_debug("%s: dummy CMD52 timeout\n",
1366 mmc_hostname(host->mmc));
1367 if (status & MCI_CMDCRCFAIL)
1368 pr_debug("%s: dummy CMD52 CRC failed\n",
1369 mmc_hostname(host->mmc));
1370 host->dummy_52_state = DUMMY_52_STATE_NONE;
1371 host->curr.cmd = NULL;
1372 msmsdcc_request_start(host, host->curr.mrq);
1373 spin_unlock(&host->lock);
1374 return IRQ_HANDLED;
1375 }
1376 break;
1377 }
1378
1379 data = host->curr.data;
1380
1381 /*
1382 * Check for proper command response
1383 */
1384 cmd = host->curr.cmd;
1385 if ((status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
1386 MCI_CMDTIMEOUT | MCI_PROGDONE |
1387 MCI_AUTOCMD19TIMEOUT)) && host->curr.cmd) {
1388 msmsdcc_do_cmdirq(host, status);
1389 }
1390
1391 if (data) {
1392 /* Check for data errors */
1393 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|
1394 MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
1395 msmsdcc_data_err(host, data, status);
1396 host->curr.data_xfered = 0;
1397 if (host->dma.sg && host->is_dma_mode)
1398 msm_dmov_stop_cmd(host->dma.channel,
1399 &host->dma.hdr, 0);
1400 else if (host->sps.sg && host->is_sps_mode) {
1401 /* Stop current SPS transfer */
1402 msmsdcc_sps_exit_curr_xfer(host);
1403 }
1404 else {
1405 msmsdcc_reset_and_restore(host);
1406 if (host->curr.data)
1407 msmsdcc_stop_data(host);
1408 if (!data->stop)
1409 timer |=
1410 msmsdcc_request_end(host,
1411 data->mrq);
1412 else {
1413 msmsdcc_start_command(host,
1414 data->stop,
1415 0);
1416 timer = 1;
1417 }
1418 }
1419 }
1420
1421 /* Check for data done */
1422 if (!host->curr.got_dataend && (status & MCI_DATAEND))
1423 host->curr.got_dataend = 1;
1424
1425 if (host->curr.got_dataend) {
1426 /*
1427 * If DMA is still in progress, we complete
1428 * via the completion handler
1429 */
1430 if (!host->dma.busy && !host->sps.busy) {
1431 /*
1432 * There appears to be an issue in the
1433 * controller where if you request a
1434 * small block transfer (< fifo size),
1435 * you may get your DATAEND/DATABLKEND
1436 * irq without the PIO data irq.
1437 *
1438 * Check to see if theres still data
1439 * to be read, and simulate a PIO irq.
1440 */
1441 if (data->flags & MMC_DATA_READ)
1442 msmsdcc_wait_for_rxdata(host,
1443 data);
1444 msmsdcc_stop_data(host);
1445 if (!data->error) {
1446 host->curr.data_xfered =
1447 host->curr.xfer_size;
1448 host->curr.xfer_remain -=
1449 host->curr.xfer_size;
1450 }
1451
1452 if (!data->stop)
1453 timer |= msmsdcc_request_end(
1454 host, data->mrq);
1455 else {
1456 msmsdcc_start_command(host,
1457 data->stop, 0);
1458 timer = 1;
1459 }
1460 }
1461 }
1462 }
1463
San Mehat9d2bd732009-09-22 16:44:22 -07001464 ret = 1;
1465 } while (status);
1466
1467 spin_unlock(&host->lock);
1468
San Mehat9d2bd732009-09-22 16:44:22 -07001469 return IRQ_RETVAL(ret);
1470}
1471
1472static void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001473msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
1474{
1475 if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
1476 /* Queue/read data, daisy-chain command when data starts */
1477 msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
1478 } else {
1479 msmsdcc_start_command(host, mrq->cmd, 0);
1480 }
1481}
1482
1483static void
San Mehat9d2bd732009-09-22 16:44:22 -07001484msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
1485{
1486 struct msmsdcc_host *host = mmc_priv(mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001487 unsigned long flags;
San Mehat9d2bd732009-09-22 16:44:22 -07001488
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001489 /*
1490 * Get the SDIO AL client out of LPM.
1491 */
1492 if (host->plat->is_sdio_al_client)
1493 msmsdcc_sdio_al_lpm(mmc, false);
San Mehat9d2bd732009-09-22 16:44:22 -07001494
1495 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001496 WARN(host->curr.mrq, "Request in progress\n");
1497 WARN(!host->pwr, "SDCC power is turned off\n");
1498 WARN(!host->clks_on, "SDCC clocks are turned off\n");
1499 WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
San Mehat9d2bd732009-09-22 16:44:22 -07001500
1501 if (host->eject) {
1502 if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) {
1503 mrq->cmd->error = 0;
1504 mrq->data->bytes_xfered = mrq->data->blksz *
1505 mrq->data->blocks;
1506 } else
1507 mrq->cmd->error = -ENOMEDIUM;
1508
1509 spin_unlock_irqrestore(&host->lock, flags);
1510 mmc_request_done(mmc, mrq);
1511 return;
1512 }
1513
1514 host->curr.mrq = mrq;
1515
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001516 if (host->plat->dummy52_required) {
1517 if (host->dummy_52_needed) {
1518 host->dummy_52_state = DUMMY_52_STATE_SENT;
1519 msmsdcc_start_command(host, &dummy52cmd,
1520 MCI_CPSM_PROGENA);
1521 spin_unlock_irqrestore(&host->lock, flags);
1522 if (mrq->data && mrq->data->flags == MMC_DATA_WRITE) {
1523 if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
1524 mrq->cmd->opcode == 54)
1525 host->dummy_52_needed = 1;
1526 } else {
1527 host->dummy_52_needed = 0;
1528 }
1529 return;
1530 }
1531 if (mrq->data && mrq->data->flags == MMC_DATA_WRITE) {
1532 if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
1533 mrq->cmd->opcode == 54)
1534 host->dummy_52_needed = 1;
1535 }
San Mehat9d2bd732009-09-22 16:44:22 -07001536 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001537 msmsdcc_request_start(host, mrq);
San Mehat9d2bd732009-09-22 16:44:22 -07001538 spin_unlock_irqrestore(&host->lock, flags);
1539}
1540
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001541static inline int msmsdcc_vreg_set_voltage(struct msm_mmc_reg_data *vreg,
1542 int min_uV, int max_uV)
1543{
1544 int rc = 0;
1545
1546 if (vreg->set_voltage_sup) {
1547 rc = regulator_set_voltage(vreg->reg, min_uV, max_uV);
1548 if (rc) {
1549 pr_err("%s: regulator_set_voltage(%s) failed."
1550 " min_uV=%d, max_uV=%d, rc=%d\n",
1551 __func__, vreg->name, min_uV, max_uV, rc);
1552 }
1553 }
1554
1555 return rc;
1556}
1557
1558static inline int msmsdcc_vreg_set_optimum_mode(struct msm_mmc_reg_data *vreg,
1559 int uA_load)
1560{
1561 int rc = 0;
1562
1563 rc = regulator_set_optimum_mode(vreg->reg, uA_load);
1564 if (rc < 0)
1565 pr_err("%s: regulator_set_optimum_mode(reg=%s, uA_load=%d)"
1566 " failed. rc=%d\n", __func__, vreg->name,
1567 uA_load, rc);
1568 else
1569 /* regulator_set_optimum_mode() can return non zero value
1570 * even for success case.
1571 */
1572 rc = 0;
1573
1574 return rc;
1575}
1576
1577static inline int msmsdcc_vreg_init_reg(struct msm_mmc_reg_data *vreg,
1578 struct device *dev)
1579{
1580 int rc = 0;
1581
1582 /* check if regulator is already initialized? */
1583 if (vreg->reg)
1584 goto out;
1585
1586 /* Get the regulator handle */
1587 vreg->reg = regulator_get(dev, vreg->name);
1588 if (IS_ERR(vreg->reg)) {
1589 rc = PTR_ERR(vreg->reg);
1590 pr_err("%s: regulator_get(%s) failed. rc=%d\n",
1591 __func__, vreg->name, rc);
1592 }
1593out:
1594 return rc;
1595}
1596
1597static inline void msmsdcc_vreg_deinit_reg(struct msm_mmc_reg_data *vreg)
1598{
1599 if (vreg->reg)
1600 regulator_put(vreg->reg);
1601}
1602
1603/* This init function should be called only once for each SDCC slot */
1604static int msmsdcc_vreg_init(struct msmsdcc_host *host, bool is_init)
1605{
1606 int rc = 0;
1607 struct msm_mmc_slot_reg_data *curr_slot;
1608 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1609 struct device *dev = mmc_dev(host->mmc);
1610
1611 curr_slot = host->plat->vreg_data;
1612 if (!curr_slot)
1613 goto out;
1614
1615 curr_vdd_reg = curr_slot->vdd_data;
1616 curr_vccq_reg = curr_slot->vccq_data;
1617 curr_vddp_reg = curr_slot->vddp_data;
1618
1619 if (is_init) {
1620 /*
1621 * Get the regulator handle from voltage regulator framework
1622 * and then try to set the voltage level for the regulator
1623 */
1624 if (curr_vdd_reg) {
1625 rc = msmsdcc_vreg_init_reg(curr_vdd_reg, dev);
1626 if (rc)
1627 goto out;
1628 }
1629 if (curr_vccq_reg) {
1630 rc = msmsdcc_vreg_init_reg(curr_vccq_reg, dev);
1631 if (rc)
1632 goto vdd_reg_deinit;
1633 }
1634 if (curr_vddp_reg) {
1635 rc = msmsdcc_vreg_init_reg(curr_vddp_reg, dev);
1636 if (rc)
1637 goto vccq_reg_deinit;
1638 }
1639 goto out;
1640 } else {
1641 /* Deregister all regulators from regulator framework */
1642 goto vddp_reg_deinit;
1643 }
1644vddp_reg_deinit:
1645 if (curr_vddp_reg)
1646 msmsdcc_vreg_deinit_reg(curr_vddp_reg);
1647vccq_reg_deinit:
1648 if (curr_vccq_reg)
1649 msmsdcc_vreg_deinit_reg(curr_vccq_reg);
1650vdd_reg_deinit:
1651 if (curr_vdd_reg)
1652 msmsdcc_vreg_deinit_reg(curr_vdd_reg);
1653out:
1654 return rc;
1655}
1656
1657static int msmsdcc_vreg_enable(struct msm_mmc_reg_data *vreg)
1658{
1659 int rc = 0;
1660
1661 if (!vreg->is_enabled) {
1662 /* Set voltage level */
1663 rc = msmsdcc_vreg_set_voltage(vreg, vreg->level,
1664 vreg->level);
1665 if (rc)
1666 goto out;
1667
1668 rc = regulator_enable(vreg->reg);
1669 if (rc) {
1670 pr_err("%s: regulator_enable(%s) failed. rc=%d\n",
1671 __func__, vreg->name, rc);
1672 goto out;
1673 }
1674 vreg->is_enabled = true;
1675 }
1676
1677 /* Put regulator in HPM (high power mode) */
1678 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->hpm_uA);
1679 if (rc < 0)
1680 goto vreg_disable;
1681
1682 goto out;
1683
1684vreg_disable:
1685 regulator_disable(vreg->reg);
1686 vreg->is_enabled = false;
1687out:
1688 return rc;
1689}
1690
1691static int msmsdcc_vreg_disable(struct msm_mmc_reg_data *vreg)
1692{
1693 int rc = 0;
1694
1695 /* Never disable regulator marked as always_on */
1696 if (vreg->is_enabled && !vreg->always_on) {
1697 rc = regulator_disable(vreg->reg);
1698 if (rc) {
1699 pr_err("%s: regulator_disable(%s) failed. rc=%d\n",
1700 __func__, vreg->name, rc);
1701 goto out;
1702 }
1703 vreg->is_enabled = false;
1704
1705 rc = msmsdcc_vreg_set_optimum_mode(vreg, 0);
1706 if (rc < 0)
1707 goto out;
1708
1709 /* Set min. voltage level to 0 */
1710 rc = msmsdcc_vreg_set_voltage(vreg, 0, vreg->level);
1711 if (rc)
1712 goto out;
1713 } else if (vreg->is_enabled && vreg->always_on && vreg->lpm_sup) {
1714 /* Put always_on regulator in LPM (low power mode) */
1715 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->lpm_uA);
1716 if (rc < 0)
1717 goto out;
1718 }
1719out:
1720 return rc;
1721}
1722
1723static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable)
1724{
1725 int rc = 0, i;
1726 struct msm_mmc_slot_reg_data *curr_slot;
1727 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1728 struct msm_mmc_reg_data *vreg_table[3];
1729
1730 curr_slot = host->plat->vreg_data;
1731 if (!curr_slot)
1732 goto out;
1733
1734 curr_vdd_reg = vreg_table[0] = curr_slot->vdd_data;
1735 curr_vccq_reg = vreg_table[1] = curr_slot->vccq_data;
1736 curr_vddp_reg = vreg_table[2] = curr_slot->vddp_data;
1737
1738 for (i = 0; i < ARRAY_SIZE(vreg_table); i++) {
1739 if (vreg_table[i]) {
1740 if (enable)
1741 rc = msmsdcc_vreg_enable(vreg_table[i]);
1742 else
1743 rc = msmsdcc_vreg_disable(vreg_table[i]);
1744 if (rc)
1745 goto out;
1746 }
1747 }
1748out:
1749 return rc;
1750}
1751
1752static int msmsdcc_tune_vdd_pad_level(struct msmsdcc_host *host, int level)
1753{
1754 int rc = 0;
1755
1756 if (host->plat->vreg_data) {
1757 struct msm_mmc_reg_data *vddp_reg =
1758 host->plat->vreg_data->vddp_data;
1759
1760 if (vddp_reg && vddp_reg->is_enabled)
1761 rc = msmsdcc_vreg_set_voltage(vddp_reg, level, level);
1762 }
1763
1764 return rc;
1765}
1766
1767static inline int msmsdcc_is_pwrsave(struct msmsdcc_host *host)
1768{
1769 if (host->clk_rate > 400000 && msmsdcc_pwrsave)
1770 return 1;
1771 return 0;
1772}
1773
1774static inline void msmsdcc_setup_clocks(struct msmsdcc_host *host, bool enable)
1775{
1776 if (enable) {
1777 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1778 clk_enable(host->dfab_pclk);
1779 if (!IS_ERR(host->pclk))
1780 clk_enable(host->pclk);
1781 clk_enable(host->clk);
1782 } else {
1783 clk_disable(host->clk);
1784 if (!IS_ERR(host->pclk))
1785 clk_disable(host->pclk);
1786 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1787 clk_disable(host->dfab_pclk);
1788 }
1789}
1790
1791static inline unsigned int msmsdcc_get_sup_clk_rate(struct msmsdcc_host *host,
1792 unsigned int req_clk)
1793{
1794 unsigned int sel_clk = -1;
1795
1796 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt) {
1797 unsigned char cnt;
1798
1799 for (cnt = 0; cnt < host->plat->sup_clk_cnt; cnt++) {
1800 if (host->plat->sup_clk_table[cnt] > req_clk)
1801 break;
1802 else if (host->plat->sup_clk_table[cnt] == req_clk) {
1803 sel_clk = host->plat->sup_clk_table[cnt];
1804 break;
1805 } else
1806 sel_clk = host->plat->sup_clk_table[cnt];
1807 }
1808 } else {
1809 if ((req_clk < host->plat->msmsdcc_fmax) &&
1810 (req_clk > host->plat->msmsdcc_fmid))
1811 sel_clk = host->plat->msmsdcc_fmid;
1812 else
1813 sel_clk = req_clk;
1814 }
1815
1816 return sel_clk;
1817}
1818
1819static inline unsigned int msmsdcc_get_min_sup_clk_rate(
1820 struct msmsdcc_host *host)
1821{
1822 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1823 return host->plat->sup_clk_table[0];
1824 else
1825 return host->plat->msmsdcc_fmin;
1826}
1827
1828static inline unsigned int msmsdcc_get_max_sup_clk_rate(
1829 struct msmsdcc_host *host)
1830{
1831 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1832 return host->plat->sup_clk_table[host->plat->sup_clk_cnt - 1];
1833 else
1834 return host->plat->msmsdcc_fmax;
1835}
1836
1837static int msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
Sahitya Tummala7a892482011-01-18 11:22:49 +05301838{
1839 struct msm_mmc_gpio_data *curr;
1840 int i, rc = 0;
1841
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001842 curr = host->plat->pin_data->gpio_data;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301843 for (i = 0; i < curr->size; i++) {
1844 if (enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001845 if (curr->gpio[i].is_always_on &&
1846 curr->gpio[i].is_enabled)
1847 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301848 rc = gpio_request(curr->gpio[i].no,
1849 curr->gpio[i].name);
1850 if (rc) {
1851 pr_err("%s: gpio_request(%d, %s) failed %d\n",
1852 mmc_hostname(host->mmc),
1853 curr->gpio[i].no,
1854 curr->gpio[i].name, rc);
1855 goto free_gpios;
1856 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001857 curr->gpio[i].is_enabled = true;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301858 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001859 if (curr->gpio[i].is_always_on)
1860 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301861 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001862 curr->gpio[i].is_enabled = false;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301863 }
1864 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001865 goto out;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301866
1867free_gpios:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001868 for (; i >= 0; i--) {
Sahitya Tummala7a892482011-01-18 11:22:49 +05301869 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001870 curr->gpio[i].is_enabled = false;
1871 }
1872out:
1873 return rc;
1874}
1875
1876static int msmsdcc_setup_pad(struct msmsdcc_host *host, bool enable)
1877{
1878 struct msm_mmc_pad_data *curr;
1879 int i;
1880
1881 curr = host->plat->pin_data->pad_data;
1882 for (i = 0; i < curr->drv->size; i++) {
1883 if (enable)
1884 msm_tlmm_set_hdrive(curr->drv->on[i].no,
1885 curr->drv->on[i].val);
1886 else
1887 msm_tlmm_set_hdrive(curr->drv->off[i].no,
1888 curr->drv->off[i].val);
1889 }
1890
1891 for (i = 0; i < curr->pull->size; i++) {
1892 if (enable)
1893 msm_tlmm_set_hdrive(curr->pull->on[i].no,
1894 curr->pull->on[i].val);
1895 else
1896 msm_tlmm_set_hdrive(curr->pull->off[i].no,
1897 curr->pull->off[i].val);
1898 }
1899
1900 return 0;
1901}
1902
1903static u32 msmsdcc_setup_pins(struct msmsdcc_host *host, bool enable)
1904{
1905 int rc = 0;
1906
1907 if (!host->plat->pin_data || host->plat->pin_data->cfg_sts == enable)
1908 return 0;
1909
1910 if (host->plat->pin_data->is_gpio)
1911 rc = msmsdcc_setup_gpio(host, enable);
1912 else
1913 rc = msmsdcc_setup_pad(host, enable);
1914
1915 if (!rc)
1916 host->plat->pin_data->cfg_sts = enable;
1917
1918 return rc;
1919}
1920
1921static void msmsdcc_enable_irq_wake(struct msmsdcc_host *host)
1922{
1923 unsigned int wakeup_irq;
1924
1925 wakeup_irq = (host->plat->sdiowakeup_irq) ?
1926 host->plat->sdiowakeup_irq :
1927 host->core_irqres->start;
1928
1929 if (!host->irq_wake_enabled) {
1930 enable_irq_wake(wakeup_irq);
1931 host->irq_wake_enabled = true;
1932 }
1933}
1934
1935static void msmsdcc_disable_irq_wake(struct msmsdcc_host *host)
1936{
1937 unsigned int wakeup_irq;
1938
1939 wakeup_irq = (host->plat->sdiowakeup_irq) ?
1940 host->plat->sdiowakeup_irq :
1941 host->core_irqres->start;
1942
1943 if (host->irq_wake_enabled) {
1944 disable_irq_wake(wakeup_irq);
1945 host->irq_wake_enabled = false;
1946 }
Sahitya Tummala7a892482011-01-18 11:22:49 +05301947}
1948
San Mehat9d2bd732009-09-22 16:44:22 -07001949static void
1950msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1951{
1952 struct msmsdcc_host *host = mmc_priv(mmc);
1953 u32 clk = 0, pwr = 0;
1954 int rc;
San Mehat4adbbcc2009-11-08 13:00:37 -08001955 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001956 unsigned int clock;
San Mehat9d2bd732009-09-22 16:44:22 -07001957
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001958 DBG(host, "ios->clock = %u\n", ios->clock);
Sahitya Tummala7a892482011-01-18 11:22:49 +05301959
San Mehat9d2bd732009-09-22 16:44:22 -07001960 if (ios->clock) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001961 spin_lock_irqsave(&host->lock, flags);
1962 if (!host->clks_on) {
1963 msmsdcc_setup_clocks(host, true);
1964 host->clks_on = 1;
1965 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
1966 if (!host->plat->sdiowakeup_irq) {
1967 writel_relaxed(host->mci_irqenable,
1968 host->base + MMCIMASK0);
1969 mb();
1970 if (host->plat->cfg_mpm_sdiowakeup &&
1971 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1972 host->plat->cfg_mpm_sdiowakeup(
1973 mmc_dev(mmc), SDC_DAT1_DISWAKE);
1974 msmsdcc_disable_irq_wake(host);
1975 } else if (!(mmc->pm_flags &
1976 MMC_PM_WAKE_SDIO_IRQ)) {
1977 writel_relaxed(host->mci_irqenable,
1978 host->base + MMCIMASK0);
1979 }
1980 }
San Mehat9d2bd732009-09-22 16:44:22 -07001981 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001982 spin_unlock_irqrestore(&host->lock, flags);
1983
1984 clock = msmsdcc_get_sup_clk_rate(host, ios->clock);
1985 /*
1986 * For DDR50 mode, controller needs clock rate to be
1987 * double than what is required on the SD card CLK pin.
1988 */
1989 if (ios->timing == MMC_TIMING_UHS_DDR50) {
1990 /*
1991 * Make sure that we don't double the clock if
1992 * doubled clock rate is already set
1993 */
1994 if (!host->ddr_doubled_clk_rate ||
1995 (host->ddr_doubled_clk_rate &&
1996 (host->ddr_doubled_clk_rate != ios->clock))) {
1997 host->ddr_doubled_clk_rate =
1998 msmsdcc_get_sup_clk_rate(
1999 host, (ios->clock * 2));
2000 clock = host->ddr_doubled_clk_rate;
2001 }
2002 } else {
2003 host->ddr_doubled_clk_rate = 0;
2004 }
2005
2006 if (clock != host->clk_rate) {
2007 rc = clk_set_rate(host->clk, clock);
2008 if (rc < 0)
2009 pr_debug("%s: failed to set clk rate %u\n",
2010 mmc_hostname(mmc), clock);
2011 host->clk_rate = clock;
2012 }
2013 /*
2014 * give atleast 2 MCLK cycles delay for clocks
2015 * and SDCC core to stabilize
2016 */
2017 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002018 clk |= MCI_CLK_ENABLE;
2019 }
2020
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002021 if (ios->bus_width == MMC_BUS_WIDTH_8)
2022 clk |= MCI_CLK_WIDEBUS_8;
2023 else if (ios->bus_width == MMC_BUS_WIDTH_4)
2024 clk |= MCI_CLK_WIDEBUS_4;
2025 else
2026 clk |= MCI_CLK_WIDEBUS_1;
San Mehat9d2bd732009-09-22 16:44:22 -07002027
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002028 if (msmsdcc_is_pwrsave(host))
2029 clk |= MCI_CLK_PWRSAVE;
San Mehat9d2bd732009-09-22 16:44:22 -07002030
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002031 clk |= MCI_CLK_FLOWENA;
San Mehat9d2bd732009-09-22 16:44:22 -07002032
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002033 host->tuning_needed = 0;
2034 /*
2035 * Select the controller timing mode according
2036 * to current bus speed mode
2037 */
2038 if ((ios->timing == MMC_TIMING_UHS_SDR104) ||
2039 (ios->timing == MMC_TIMING_UHS_SDR50)) {
2040 clk |= (4 << 14);
2041 host->tuning_needed = 1;
2042 } else if (ios->timing == MMC_TIMING_UHS_DDR50) {
2043 clk |= (3 << 14);
2044 } else {
2045 clk |= (2 << 14); /* feedback clock */
2046 }
2047
2048 /* Select free running MCLK as input clock of cm_dll_sdc4 */
2049 clk |= (2 << 23);
2050
2051 if (host->io_pad_pwr_switch)
2052 clk |= IO_PAD_PWR_SWITCH;
2053
2054 if (host->plat->translate_vdd && !host->sdio_gpio_lpm)
San Mehat9d2bd732009-09-22 16:44:22 -07002055 pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002056 else if (!host->plat->translate_vdd && !host->sdio_gpio_lpm)
2057 pwr |= msmsdcc_setup_vreg(host, !!ios->vdd);
San Mehat9d2bd732009-09-22 16:44:22 -07002058
2059 switch (ios->power_mode) {
2060 case MMC_POWER_OFF:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002061 htc_pwrsink_set(PWRSINK_SDCARD, 0);
2062 if (!host->sdcc_irq_disabled) {
2063 if (host->plat->cfg_mpm_sdiowakeup)
2064 host->plat->cfg_mpm_sdiowakeup(
2065 mmc_dev(mmc), SDC_DAT1_DISABLE);
2066 disable_irq(host->core_irqres->start);
2067 host->sdcc_irq_disabled = 1;
2068 }
2069 msmsdcc_setup_pins(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07002070 break;
2071 case MMC_POWER_UP:
2072 pwr |= MCI_PWR_UP;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002073 if (host->sdcc_irq_disabled) {
2074 if (host->plat->cfg_mpm_sdiowakeup)
2075 host->plat->cfg_mpm_sdiowakeup(
2076 mmc_dev(mmc), SDC_DAT1_ENABLE);
2077 enable_irq(host->core_irqres->start);
2078 host->sdcc_irq_disabled = 0;
2079 }
2080 msmsdcc_setup_pins(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07002081 break;
2082 case MMC_POWER_ON:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002083 htc_pwrsink_set(PWRSINK_SDCARD, 100);
San Mehat9d2bd732009-09-22 16:44:22 -07002084 pwr |= MCI_PWR_ON;
2085 break;
2086 }
2087
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002088 spin_lock_irqsave(&host->lock, flags);
2089 if (!host->clks_on) {
2090 /* force the clocks to be on */
2091 msmsdcc_setup_clocks(host, true);
2092 /*
2093 * give atleast 2 MCLK cycles delay for clocks
2094 * and SDCC core to stabilize
2095 */
2096 msmsdcc_delay(host);
2097 }
2098 writel_relaxed(clk, host->base + MMCICLOCK);
2099 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002100
2101 if (host->pwr != pwr) {
2102 host->pwr = pwr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002103 writel_relaxed(pwr, host->base + MMCIPOWER);
2104 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07002105 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002106 if (!host->clks_on) {
2107 /* force the clocks to be off */
2108 msmsdcc_setup_clocks(host, false);
2109 /*
2110 * give atleast 2 MCLK cycles delay for clocks
2111 * and SDCC core to stabilize
2112 */
2113 msmsdcc_delay(host);
2114 }
2115
2116 if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
2117 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
2118 if (!host->plat->sdiowakeup_irq) {
2119 writel_relaxed(MCI_SDIOINTMASK,
2120 host->base + MMCIMASK0);
2121 mb();
2122 if (host->plat->cfg_mpm_sdiowakeup &&
2123 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
2124 host->plat->cfg_mpm_sdiowakeup(
2125 mmc_dev(mmc), SDC_DAT1_ENWAKE);
2126 msmsdcc_enable_irq_wake(host);
2127 } else if (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2128 writel_relaxed(0, host->base + MMCIMASK0);
2129 } else {
2130 writel_relaxed(MCI_SDIOINTMASK,
2131 host->base + MMCIMASK0);
2132 }
2133 msmsdcc_delay(host);
2134 }
2135 msmsdcc_setup_clocks(host, false);
2136 host->clks_on = 0;
2137 }
San Mehat4adbbcc2009-11-08 13:00:37 -08002138 spin_unlock_irqrestore(&host->lock, flags);
San Mehat9d2bd732009-09-22 16:44:22 -07002139}
2140
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002141int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave)
2142{
2143 struct msmsdcc_host *host = mmc_priv(mmc);
2144 u32 clk;
2145
2146 clk = readl_relaxed(host->base + MMCICLOCK);
2147 pr_debug("Changing to pwr_save=%d", pwrsave);
2148 if (pwrsave && msmsdcc_is_pwrsave(host))
2149 clk |= MCI_CLK_PWRSAVE;
2150 else
2151 clk &= ~MCI_CLK_PWRSAVE;
2152 writel_relaxed(clk, host->base + MMCICLOCK);
2153 mb();
2154
2155 return 0;
2156}
2157
2158static int msmsdcc_get_ro(struct mmc_host *mmc)
2159{
2160 int status = -ENOSYS;
2161 struct msmsdcc_host *host = mmc_priv(mmc);
2162
2163 if (host->plat->wpswitch) {
2164 status = host->plat->wpswitch(mmc_dev(mmc));
2165 } else if (host->plat->wpswitch_gpio) {
2166 status = gpio_request(host->plat->wpswitch_gpio,
2167 "SD_WP_Switch");
2168 if (status) {
2169 pr_err("%s: %s: Failed to request GPIO %d\n",
2170 mmc_hostname(mmc), __func__,
2171 host->plat->wpswitch_gpio);
2172 } else {
2173 status = gpio_direction_input(
2174 host->plat->wpswitch_gpio);
2175 if (!status) {
2176 /*
2177 * Wait for atleast 300ms as debounce
2178 * time for GPIO input to stabilize.
2179 */
2180 msleep(300);
2181 status = gpio_get_value_cansleep(
2182 host->plat->wpswitch_gpio);
2183 status ^= !host->plat->wpswitch_polarity;
2184 }
2185 gpio_free(host->plat->wpswitch_gpio);
2186 }
2187 }
2188
2189 if (status < 0)
2190 status = -ENOSYS;
2191 pr_debug("%s: Card read-only status %d\n", __func__, status);
2192
2193 return status;
2194}
2195
2196#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002197static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
2198{
2199 struct msmsdcc_host *host = mmc_priv(mmc);
2200 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002201
2202 if (enable) {
2203 spin_lock_irqsave(&host->lock, flags);
2204 host->mci_irqenable |= MCI_SDIOINTOPERMASK;
2205 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) |
2206 MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2207 spin_unlock_irqrestore(&host->lock, flags);
2208 } else {
2209 host->mci_irqenable &= ~MCI_SDIOINTOPERMASK;
2210 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) &
2211 ~MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2212 }
2213 mb();
2214}
2215#endif /* CONFIG_MMC_MSM_SDIO_SUPPORT */
2216
2217#ifdef CONFIG_PM_RUNTIME
2218static int msmsdcc_enable(struct mmc_host *mmc)
2219{
2220 int rc;
2221 struct device *dev = mmc->parent;
2222
2223 if (atomic_read(&dev->power.usage_count) > 0) {
2224 pm_runtime_get_noresume(dev);
2225 goto out;
2226 }
2227
2228 rc = pm_runtime_get_sync(dev);
2229
2230 if (rc < 0) {
2231 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2232 __func__, rc);
2233 return rc;
2234 }
2235out:
2236 return 0;
2237}
2238
2239static int msmsdcc_disable(struct mmc_host *mmc, int lazy)
2240{
2241 int rc;
2242
2243 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO)
2244 return -ENOTSUPP;
2245
2246 rc = pm_runtime_put_sync(mmc->parent);
2247
2248 if (rc < 0)
2249 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2250 __func__, rc);
2251 return rc;
2252}
2253#else
2254#define msmsdcc_enable NULL
2255#define msmsdcc_disable NULL
2256#endif
2257
2258static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
2259 struct mmc_ios *ios)
2260{
2261 struct msmsdcc_host *host = mmc_priv(mmc);
2262 unsigned long flags;
2263 int err = 0;
2264
2265 if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
2266 /* Change voltage level of VDDPX to high voltage */
2267 if (msmsdcc_tune_vdd_pad_level(host, 2950000)) {
2268 pr_err("%s: %s: failed to change vddp level to %d",
2269 mmc_hostname(mmc), __func__, 2950000);
2270 }
2271 goto out;
2272 } else if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
2273 /* invalid selection. don't do anything */
2274 goto out;
2275 }
San Mehat9d2bd732009-09-22 16:44:22 -07002276
2277 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002278 /*
2279 * If we are here means voltage switch from high voltage to
2280 * low voltage is required
2281 */
2282
2283 /*
2284 * Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
2285 * register until they become all zeros.
2286 */
2287 if (readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1)) {
2288 err = -EAGAIN;
2289 pr_err("%s: %s: MCIDATIN_3_0 is still not all zeros",
2290 mmc_hostname(mmc), __func__);
2291 goto out_unlock;
San Mehat9d2bd732009-09-22 16:44:22 -07002292 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002293
2294 /* Stop SD CLK output. */
2295 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2296 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2297
San Mehat9d2bd732009-09-22 16:44:22 -07002298 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002299
2300 /*
2301 * Switch VDDPX from high voltage to low voltage
2302 * to change the VDD of the SD IO pads.
2303 */
2304 if (msmsdcc_tune_vdd_pad_level(host, 1850000)) {
2305 pr_err("%s: %s: failed to change vddp level to %d",
2306 mmc_hostname(mmc), __func__, 1850000);
2307 goto out;
2308 }
2309
2310 spin_lock_irqsave(&host->lock, flags);
2311 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2312 IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
2313 host->io_pad_pwr_switch = 1;
2314 spin_unlock_irqrestore(&host->lock, flags);
2315
2316 /* Wait 5 ms for the voltage regulater in the card to become stable. */
2317 usleep_range(5000, 5500);
2318
2319 spin_lock_irqsave(&host->lock, flags);
2320 /* Start SD CLK output. */
2321 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2322 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2323 spin_unlock_irqrestore(&host->lock, flags);
2324
2325 /*
2326 * If MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT register
2327 * don't become all ones within 1 ms then a Voltage Switch
2328 * sequence has failed and a power cycle to the card is required.
2329 * Otherwise Voltage Switch sequence is completed successfully.
2330 */
2331 usleep_range(1000, 1500);
2332
2333 spin_lock_irqsave(&host->lock, flags);
2334 if ((readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1))
2335 != (0xF << 1)) {
2336 pr_err("%s: %s: MCIDATIN_3_0 are still not all ones",
2337 mmc_hostname(mmc), __func__);
2338 err = -EAGAIN;
2339 goto out_unlock;
2340 }
2341
2342out_unlock:
2343 spin_unlock_irqrestore(&host->lock, flags);
2344out:
2345 return err;
2346}
2347
2348static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2349 u8 phase);
2350/* Initialize the DLL (Programmable Delay Line ) */
2351static int msmsdcc_init_cm_sdc4_dll(struct msmsdcc_host *host)
2352{
2353 int rc = 0;
2354 u32 wait_timeout;
2355
2356 /* Write 0 to DLL_PDN bit of MCI_DLL_CONFIG register */
2357 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2358 & ~MCI_DLL_PDN), host->base + MCI_DLL_CONFIG);
2359
2360 /* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
2361 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2362 | MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2363
2364 msmsdcc_delay(host);
2365
2366 /* Write 0 to DLL_RST bit of MCI_DLL_CONFIG register */
2367 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2368 & ~MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2369
2370 /* Initialize the phase to 0 */
2371 rc = msmsdcc_config_cm_sdc4_dll_phase(host, 0);
2372 if (rc)
2373 goto out;
2374
2375 wait_timeout = 1000;
2376 /* Wait until DLL_LOCK bit of MCI_DLL_STATUS register becomes '1' */
2377 while (!(readl_relaxed(host->base + MCI_DLL_STATUS) & MCI_DLL_LOCK)) {
2378 /* max. wait for 1 sec for LOCK bit to be set */
2379 if (--wait_timeout == 0) {
2380 pr_err("%s: %s: DLL failed to lock at phase: %d",
2381 mmc_hostname(host->mmc), __func__, 0);
2382 rc = -1;
2383 goto out;
2384 }
2385 /* wait for 1ms */
2386 usleep_range(1000, 1500);
2387 }
2388out:
2389 return rc;
2390}
2391
2392/*
2393 * Enable a CDR circuit in CM_SDC4_DLL block to enable automatic
2394 * calibration sequence. This function should be called before
2395 * enabling AUTO_CMD19 bit in MCI_CMD register for block read
2396 * commands (CMD17/CMD18).
2397 */
2398static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host)
2399{
2400 /* Set CDR_EN bit to 1. */
2401 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG) |
2402 MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2403
2404 /* Set CDR_EXT_EN bit to 0. */
2405 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2406 & ~MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2407
2408 /* Set CK_OUT_EN bit to 0. */
2409 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2410 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2411
2412 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2413 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)
2414 ;
2415
2416 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2417 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2418 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2419
2420 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register is 1. */
2421 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN))
2422 ;
2423}
2424
2425static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2426 u8 phase)
2427{
2428 int rc = 0;
2429 u32 mclk_freq = 0;
2430 u32 wait_timeout;
2431
2432 /* Set CDR_EN bit to 0. */
2433 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2434 & ~MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2435
2436 /* Set CDR_EXT_EN bit to 1. */
2437 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2438 | MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2439
2440 /* Program the MCLK value to MCLK_FREQ bit field */
2441 if (host->clk_rate <= 112000000)
2442 mclk_freq = 0;
2443 else if (host->clk_rate <= 125000000)
2444 mclk_freq = 1;
2445 else if (host->clk_rate <= 137000000)
2446 mclk_freq = 2;
2447 else if (host->clk_rate <= 150000000)
2448 mclk_freq = 3;
2449 else if (host->clk_rate <= 162000000)
2450 mclk_freq = 4;
2451 else if (host->clk_rate <= 175000000)
2452 mclk_freq = 5;
2453 else if (host->clk_rate <= 187000000)
2454 mclk_freq = 6;
2455 else if (host->clk_rate <= 200000000)
2456 mclk_freq = 7;
2457
2458 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2459 & ~(7 << 24)) | (mclk_freq << 24)),
2460 host->base + MCI_DLL_CONFIG);
2461
2462 /* Set CK_OUT_EN bit to 0. */
2463 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2464 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2465
2466 /* Set DLL_EN bit to 1. */
2467 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2468 | MCI_DLL_EN), host->base + MCI_DLL_CONFIG);
2469
2470 wait_timeout = 1000;
2471 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2472 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN) {
2473 /* max. wait for 1 sec for LOCK bit for be set */
2474 if (--wait_timeout == 0) {
2475 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 0",
2476 mmc_hostname(host->mmc), __func__, phase);
2477 rc = -1;
2478 goto out;
2479 }
2480 /* wait for 1ms */
2481 usleep_range(1000, 1500);
2482 }
2483
2484 /*
2485 * Write the selected DLL clock output phase (0 ... 15)
2486 * to CDR_SELEXT bit field of MCI_DLL_CONFIG register.
2487 */
2488 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2489 & ~(0xF << 20)) | (phase << 20)),
2490 host->base + MCI_DLL_CONFIG);
2491
2492 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2493 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2494 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2495
2496 wait_timeout = 1000;
2497 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '1' */
2498 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)) {
2499 /* max. wait for 1 sec for LOCK bit for be set */
2500 if (--wait_timeout == 0) {
2501 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 1",
2502 mmc_hostname(host->mmc), __func__, phase);
2503 rc = -1;
2504 goto out;
2505 }
2506 /* wait for 1ms */
2507 usleep_range(1000, 1500);
2508 }
2509out:
2510 return rc;
2511}
2512
2513static int msmsdcc_execute_tuning(struct mmc_host *mmc)
2514{
2515 struct msmsdcc_host *host = mmc_priv(mmc);
2516 u8 phase;
2517 u8 *data_buf;
2518 u8 tuned_phases[16], tuned_phase_cnt = 0;
2519 int rc = 0;
2520
2521 /* Tuning is only required for SDR50 & SDR104 modes */
2522 if (!host->tuning_needed) {
2523 rc = 0;
2524 goto out;
2525 }
2526
2527 host->cmd19_tuning_in_progress = 1;
2528 /*
2529 * Make sure that clock is always enabled when DLL
2530 * tuning is in progress. Keeping PWRSAVE ON may
2531 * turn off the clock. So let's disable the PWRSAVE
2532 * here and re-enable it once tuning is completed.
2533 */
2534 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2535 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2536 /* first of all reset the tuning block */
2537 rc = msmsdcc_init_cm_sdc4_dll(host);
2538 if (rc)
2539 goto out;
2540
2541 data_buf = kmalloc(64, GFP_KERNEL);
2542 if (!data_buf) {
2543 rc = -ENOMEM;
2544 goto out;
2545 }
2546
2547 phase = 0;
2548 do {
2549 struct mmc_command cmd = {0};
2550 struct mmc_data data = {0};
2551 struct mmc_request mrq = {
2552 .cmd = &cmd,
2553 .data = &data
2554 };
2555 struct scatterlist sg;
2556
2557 /* set the phase in delay line hw block */
2558 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2559 if (rc)
2560 goto kfree;
2561
2562 cmd.opcode = MMC_SEND_TUNING_BLOCK;
2563 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
2564
2565 data.blksz = 64;
2566 data.blocks = 1;
2567 data.flags = MMC_DATA_READ;
2568 data.timeout_ns = 1000 * 1000 * 1000; /* 1 sec */
2569
2570 data.sg = &sg;
2571 data.sg_len = 1;
2572 sg_init_one(&sg, data_buf, 64);
2573 memset(data_buf, 0, 64);
2574 mmc_wait_for_req(mmc, &mrq);
2575
2576 if (!cmd.error && !data.error &&
2577 !memcmp(data_buf, cmd19_tuning_block, 64)) {
2578 /* tuning is successful with this tuning point */
2579 tuned_phases[tuned_phase_cnt++] = phase;
2580 }
2581 } while (++phase < 16);
2582
2583 kfree(data_buf);
2584
2585 if (tuned_phase_cnt) {
2586 tuned_phase_cnt--;
2587 tuned_phase_cnt = (tuned_phase_cnt * 3) / 4;
2588 phase = tuned_phases[tuned_phase_cnt];
2589 /*
2590 * Finally set the selected phase in delay
2591 * line hw block.
2592 */
2593 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2594 if (rc)
2595 goto out;
2596 } else {
2597 /* tuning failed */
2598 rc = -EAGAIN;
2599 pr_err("%s: %s: no tuning point found",
2600 mmc_hostname(mmc), __func__);
2601 }
2602 goto out;
2603
2604kfree:
2605 kfree(data_buf);
2606out:
2607 /* re-enable PWESAVE */
2608 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2609 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2610 host->cmd19_tuning_in_progress = 0;
2611 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -07002612}
2613
2614static const struct mmc_host_ops msmsdcc_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002615 .enable = msmsdcc_enable,
2616 .disable = msmsdcc_disable,
San Mehat9d2bd732009-09-22 16:44:22 -07002617 .request = msmsdcc_request,
2618 .set_ios = msmsdcc_set_ios,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002619 .get_ro = msmsdcc_get_ro,
2620#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002621 .enable_sdio_irq = msmsdcc_enable_sdio_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002622#endif
2623 .start_signal_voltage_switch = msmsdcc_start_signal_voltage_switch,
2624 .execute_tuning = msmsdcc_execute_tuning
San Mehat9d2bd732009-09-22 16:44:22 -07002625};
2626
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002627static unsigned int
2628msmsdcc_slot_status(struct msmsdcc_host *host)
2629{
2630 int status;
2631 unsigned int gpio_no = host->plat->status_gpio;
2632
2633 status = gpio_request(gpio_no, "SD_HW_Detect");
2634 if (status) {
2635 pr_err("%s: %s: Failed to request GPIO %d\n",
2636 mmc_hostname(host->mmc), __func__, gpio_no);
2637 } else {
2638 status = gpio_direction_input(gpio_no);
2639 if (!status)
2640 status = !gpio_get_value_cansleep(gpio_no);
2641 gpio_free(gpio_no);
2642 }
2643 return status;
2644}
2645
San Mehat9d2bd732009-09-22 16:44:22 -07002646static void
2647msmsdcc_check_status(unsigned long data)
2648{
2649 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
2650 unsigned int status;
2651
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002652 if (host->plat->status || host->plat->status_gpio) {
2653 if (host->plat->status)
2654 status = host->plat->status(mmc_dev(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07002655 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002656 status = msmsdcc_slot_status(host);
2657
2658 host->eject = !status;
2659 if (status ^ host->oldstat) {
2660 pr_info("%s: Slot status change detected (%d -> %d)\n",
2661 mmc_hostname(host->mmc), host->oldstat, status);
San Mehat9d2bd732009-09-22 16:44:22 -07002662 mmc_detect_change(host->mmc, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002663 }
2664 host->oldstat = status;
2665 } else {
2666 mmc_detect_change(host->mmc, 0);
San Mehat9d2bd732009-09-22 16:44:22 -07002667 }
San Mehat9d2bd732009-09-22 16:44:22 -07002668}
2669
2670static irqreturn_t
2671msmsdcc_platform_status_irq(int irq, void *dev_id)
2672{
2673 struct msmsdcc_host *host = dev_id;
2674
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002675 pr_debug("%s: %d\n", __func__, irq);
San Mehat9d2bd732009-09-22 16:44:22 -07002676 msmsdcc_check_status((unsigned long) host);
2677 return IRQ_HANDLED;
2678}
2679
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002680static irqreturn_t
2681msmsdcc_platform_sdiowakeup_irq(int irq, void *dev_id)
2682{
2683 struct msmsdcc_host *host = dev_id;
2684
2685 pr_debug("%s: SDIO Wake up IRQ : %d\n", mmc_hostname(host->mmc), irq);
2686 spin_lock(&host->lock);
2687 if (!host->sdio_irq_disabled) {
2688 disable_irq_nosync(irq);
2689 if (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2690 wake_lock(&host->sdio_wlock);
2691 msmsdcc_disable_irq_wake(host);
2692 }
2693 host->sdio_irq_disabled = 1;
2694 }
2695 if (host->plat->is_sdio_al_client) {
2696 if (!host->clks_on) {
2697 msmsdcc_setup_clocks(host, true);
2698 host->clks_on = 1;
2699 }
2700 if (host->sdcc_irq_disabled) {
2701 writel_relaxed(host->mci_irqenable,
2702 host->base + MMCIMASK0);
2703 mb();
2704 enable_irq(host->core_irqres->start);
2705 host->sdcc_irq_disabled = 0;
2706 }
2707 wake_lock(&host->sdio_wlock);
2708 }
2709 spin_unlock(&host->lock);
2710
2711 return IRQ_HANDLED;
2712}
2713
San Mehat9d2bd732009-09-22 16:44:22 -07002714static void
2715msmsdcc_status_notify_cb(int card_present, void *dev_id)
2716{
2717 struct msmsdcc_host *host = dev_id;
2718
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002719 pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
San Mehat9d2bd732009-09-22 16:44:22 -07002720 card_present);
2721 msmsdcc_check_status((unsigned long) host);
2722}
2723
San Mehat9d2bd732009-09-22 16:44:22 -07002724static int
2725msmsdcc_init_dma(struct msmsdcc_host *host)
2726{
2727 memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data));
2728 host->dma.host = host;
2729 host->dma.channel = -1;
2730
2731 if (!host->dmares)
2732 return -ENODEV;
2733
2734 host->dma.nc = dma_alloc_coherent(NULL,
2735 sizeof(struct msmsdcc_nc_dmadata),
2736 &host->dma.nc_busaddr,
2737 GFP_KERNEL);
2738 if (host->dma.nc == NULL) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07002739 pr_err("Unable to allocate DMA buffer\n");
San Mehat9d2bd732009-09-22 16:44:22 -07002740 return -ENOMEM;
2741 }
2742 memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata));
2743 host->dma.cmd_busaddr = host->dma.nc_busaddr;
2744 host->dma.cmdptr_busaddr = host->dma.nc_busaddr +
2745 offsetof(struct msmsdcc_nc_dmadata, cmdptr);
2746 host->dma.channel = host->dmares->start;
2747
2748 return 0;
2749}
2750
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002751#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
2752/**
2753 * Allocate and Connect a SDCC peripheral's SPS endpoint
2754 *
2755 * This function allocates endpoint context and
2756 * connect it with memory endpoint by calling
2757 * appropriate SPS driver APIs.
2758 *
2759 * Also registers a SPS callback function with
2760 * SPS driver
2761 *
2762 * This function should only be called once typically
2763 * during driver probe.
2764 *
2765 * @host - Pointer to sdcc host structure
2766 * @ep - Pointer to sps endpoint data structure
2767 * @is_produce - 1 means Producer endpoint
2768 * 0 means Consumer endpoint
2769 *
2770 * @return - 0 if successful else negative value.
2771 *
2772 */
2773static int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
2774 struct msmsdcc_sps_ep_conn_data *ep,
2775 bool is_producer)
2776{
2777 int rc = 0;
2778 struct sps_pipe *sps_pipe_handle;
2779 struct sps_connect *sps_config = &ep->config;
2780 struct sps_register_event *sps_event = &ep->event;
2781
2782 /* Allocate endpoint context */
2783 sps_pipe_handle = sps_alloc_endpoint();
2784 if (!sps_pipe_handle) {
2785 pr_err("%s: sps_alloc_endpoint() failed!!! is_producer=%d",
2786 mmc_hostname(host->mmc), is_producer);
2787 rc = -ENOMEM;
2788 goto out;
2789 }
2790
2791 /* Get default connection configuration for an endpoint */
2792 rc = sps_get_config(sps_pipe_handle, sps_config);
2793 if (rc) {
2794 pr_err("%s: sps_get_config() failed!!! pipe_handle=0x%x,"
2795 " rc=%d", mmc_hostname(host->mmc),
2796 (u32)sps_pipe_handle, rc);
2797 goto get_config_err;
2798 }
2799
2800 /* Modify the default connection configuration */
2801 if (is_producer) {
2802 /*
2803 * For SDCC producer transfer, source should be
2804 * SDCC peripheral where as destination should
2805 * be system memory.
2806 */
2807 sps_config->source = host->sps.bam_handle;
2808 sps_config->destination = SPS_DEV_HANDLE_MEM;
2809 /* Producer pipe will handle this connection */
2810 sps_config->mode = SPS_MODE_SRC;
2811 sps_config->options =
2812 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2813 } else {
2814 /*
2815 * For SDCC consumer transfer, source should be
2816 * system memory where as destination should
2817 * SDCC peripheral
2818 */
2819 sps_config->source = SPS_DEV_HANDLE_MEM;
2820 sps_config->destination = host->sps.bam_handle;
2821 sps_config->mode = SPS_MODE_DEST;
2822 sps_config->options =
2823 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2824 }
2825
2826 /* Producer pipe index */
2827 sps_config->src_pipe_index = host->sps.src_pipe_index;
2828 /* Consumer pipe index */
2829 sps_config->dest_pipe_index = host->sps.dest_pipe_index;
2830 /*
2831 * This event thresold value is only significant for BAM-to-BAM
2832 * transfer. It's ignored for BAM-to-System mode transfer.
2833 */
2834 sps_config->event_thresh = 0x10;
2835 /*
2836 * Max. no of scatter/gather buffers that can
2837 * be passed by block layer = 32 (NR_SG).
2838 * Each BAM descritor needs 64 bits (8 bytes).
2839 * One BAM descriptor is required per buffer transfer.
2840 * So we would require total 256 (32 * 8) bytes of descriptor FIFO.
2841 * But due to HW limitation we need to allocate atleast one extra
2842 * descriptor memory (256 bytes + 8 bytes). But in order to be
2843 * in power of 2, we are allocating 512 bytes of memory.
2844 */
2845 sps_config->desc.size = 512;
2846 sps_config->desc.base = dma_alloc_coherent(mmc_dev(host->mmc),
2847 sps_config->desc.size,
2848 &sps_config->desc.phys_base,
2849 GFP_KERNEL);
2850
2851 memset(sps_config->desc.base, 0x00, sps_config->desc.size);
2852
2853 /* Establish connection between peripheral and memory endpoint */
2854 rc = sps_connect(sps_pipe_handle, sps_config);
2855 if (rc) {
2856 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2857 " rc=%d", mmc_hostname(host->mmc),
2858 (u32)sps_pipe_handle, rc);
2859 goto sps_connect_err;
2860 }
2861
2862 sps_event->mode = SPS_TRIGGER_CALLBACK;
2863 sps_event->options = SPS_O_EOT;
2864 sps_event->callback = msmsdcc_sps_complete_cb;
2865 sps_event->xfer_done = NULL;
2866 sps_event->user = (void *)host;
2867
2868 /* Register callback event for EOT (End of transfer) event. */
2869 rc = sps_register_event(sps_pipe_handle, sps_event);
2870 if (rc) {
2871 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2872 " rc=%d", mmc_hostname(host->mmc),
2873 (u32)sps_pipe_handle, rc);
2874 goto reg_event_err;
2875 }
2876 /* Now save the sps pipe handle */
2877 ep->pipe_handle = sps_pipe_handle;
2878 pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"
2879 " desc_fifo.phys_base=0x%x\n", mmc_hostname(host->mmc),
2880 __func__, is_producer ? "READ" : "WRITE",
2881 (u32)sps_pipe_handle, sps_config->desc.phys_base);
2882 goto out;
2883
2884reg_event_err:
2885 sps_disconnect(sps_pipe_handle);
2886sps_connect_err:
2887 dma_free_coherent(mmc_dev(host->mmc),
2888 sps_config->desc.size,
2889 sps_config->desc.base,
2890 sps_config->desc.phys_base);
2891get_config_err:
2892 sps_free_endpoint(sps_pipe_handle);
2893out:
2894 return rc;
2895}
2896
2897/**
2898 * Disconnect and Deallocate a SDCC peripheral's SPS endpoint
2899 *
2900 * This function disconnect endpoint and deallocates
2901 * endpoint context.
2902 *
2903 * This function should only be called once typically
2904 * during driver remove.
2905 *
2906 * @host - Pointer to sdcc host structure
2907 * @ep - Pointer to sps endpoint data structure
2908 *
2909 */
2910static void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
2911 struct msmsdcc_sps_ep_conn_data *ep)
2912{
2913 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2914 struct sps_connect *sps_config = &ep->config;
2915 struct sps_register_event *sps_event = &ep->event;
2916
2917 sps_event->xfer_done = NULL;
2918 sps_event->callback = NULL;
2919 sps_register_event(sps_pipe_handle, sps_event);
2920 sps_disconnect(sps_pipe_handle);
2921 dma_free_coherent(mmc_dev(host->mmc),
2922 sps_config->desc.size,
2923 sps_config->desc.base,
2924 sps_config->desc.phys_base);
2925 sps_free_endpoint(sps_pipe_handle);
2926}
2927
2928/**
2929 * Reset SDCC peripheral's SPS endpoint
2930 *
2931 * This function disconnects an endpoint.
2932 *
2933 * This function should be called for reseting
2934 * SPS endpoint when data transfer error is
2935 * encountered during data transfer. This
2936 * can be considered as soft reset to endpoint.
2937 *
2938 * This function should only be called if
2939 * msmsdcc_sps_init() is already called.
2940 *
2941 * @host - Pointer to sdcc host structure
2942 * @ep - Pointer to sps endpoint data structure
2943 *
2944 * @return - 0 if successful else negative value.
2945 */
2946static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
2947 struct msmsdcc_sps_ep_conn_data *ep)
2948{
2949 int rc = 0;
2950 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2951
2952 rc = sps_disconnect(sps_pipe_handle);
2953 if (rc) {
2954 pr_err("%s: %s: sps_disconnect() failed!!! pipe_handle=0x%x,"
2955 " rc=%d", mmc_hostname(host->mmc), __func__,
2956 (u32)sps_pipe_handle, rc);
2957 goto out;
2958 }
2959 out:
2960 return rc;
2961}
2962
2963/**
2964 * Restore SDCC peripheral's SPS endpoint
2965 *
2966 * This function connects an endpoint.
2967 *
2968 * This function should be called for restoring
2969 * SPS endpoint after data transfer error is
2970 * encountered during data transfer. This
2971 * can be considered as soft reset to endpoint.
2972 *
2973 * This function should only be called if
2974 * msmsdcc_sps_reset_ep() is called before.
2975 *
2976 * @host - Pointer to sdcc host structure
2977 * @ep - Pointer to sps endpoint data structure
2978 *
2979 * @return - 0 if successful else negative value.
2980 */
2981static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
2982 struct msmsdcc_sps_ep_conn_data *ep)
2983{
2984 int rc = 0;
2985 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2986 struct sps_connect *sps_config = &ep->config;
2987 struct sps_register_event *sps_event = &ep->event;
2988
2989 /* Establish connection between peripheral and memory endpoint */
2990 rc = sps_connect(sps_pipe_handle, sps_config);
2991 if (rc) {
2992 pr_err("%s: %s: sps_connect() failed!!! pipe_handle=0x%x,"
2993 " rc=%d", mmc_hostname(host->mmc), __func__,
2994 (u32)sps_pipe_handle, rc);
2995 goto out;
2996 }
2997
2998 /* Register callback event for EOT (End of transfer) event. */
2999 rc = sps_register_event(sps_pipe_handle, sps_event);
3000 if (rc) {
3001 pr_err("%s: %s: sps_register_event() failed!!!"
3002 " pipe_handle=0x%x, rc=%d",
3003 mmc_hostname(host->mmc), __func__,
3004 (u32)sps_pipe_handle, rc);
3005 goto reg_event_err;
3006 }
3007 goto out;
3008
3009reg_event_err:
3010 sps_disconnect(sps_pipe_handle);
3011out:
3012 return rc;
3013}
3014
3015/**
3016 * Initialize SPS HW connected with SDCC core
3017 *
3018 * This function register BAM HW resources with
3019 * SPS driver and then initialize 2 SPS endpoints
3020 *
3021 * This function should only be called once typically
3022 * during driver probe.
3023 *
3024 * @host - Pointer to sdcc host structure
3025 *
3026 * @return - 0 if successful else negative value.
3027 *
3028 */
3029static int msmsdcc_sps_init(struct msmsdcc_host *host)
3030{
3031 int rc = 0;
3032 struct sps_bam_props bam = {0};
3033
3034 host->bam_base = ioremap(host->bam_memres->start,
3035 resource_size(host->bam_memres));
3036 if (!host->bam_base) {
3037 pr_err("%s: BAM ioremap() failed!!! phys_addr=0x%x,"
3038 " size=0x%x", mmc_hostname(host->mmc),
3039 host->bam_memres->start,
3040 (host->bam_memres->end -
3041 host->bam_memres->start));
3042 rc = -ENOMEM;
3043 goto out;
3044 }
3045
3046 bam.phys_addr = host->bam_memres->start;
3047 bam.virt_addr = host->bam_base;
3048 /*
3049 * This event thresold value is only significant for BAM-to-BAM
3050 * transfer. It's ignored for BAM-to-System mode transfer.
3051 */
3052 bam.event_threshold = 0x10; /* Pipe event threshold */
3053 /*
3054 * This threshold controls when the BAM publish
3055 * the descriptor size on the sideband interface.
3056 * SPS HW will only be used when
3057 * data transfer size > MCI_FIFOSIZE (64 bytes).
3058 * PIO mode will be used when
3059 * data transfer size < MCI_FIFOSIZE (64 bytes).
3060 * So set this thresold value to 64 bytes.
3061 */
3062 bam.summing_threshold = 64;
3063 /* SPS driver wll handle the SDCC BAM IRQ */
3064 bam.irq = (u32)host->bam_irqres->start;
3065 bam.manage = SPS_BAM_MGR_LOCAL;
3066
3067 pr_info("%s: bam physical base=0x%x\n", mmc_hostname(host->mmc),
3068 (u32)bam.phys_addr);
3069 pr_info("%s: bam virtual base=0x%x\n", mmc_hostname(host->mmc),
3070 (u32)bam.virt_addr);
3071
3072 /* Register SDCC Peripheral BAM device to SPS driver */
3073 rc = sps_register_bam_device(&bam, &host->sps.bam_handle);
3074 if (rc) {
3075 pr_err("%s: sps_register_bam_device() failed!!! err=%d",
3076 mmc_hostname(host->mmc), rc);
3077 goto reg_bam_err;
3078 }
3079 pr_info("%s: BAM device registered. bam_handle=0x%x",
3080 mmc_hostname(host->mmc), host->sps.bam_handle);
3081
3082 host->sps.src_pipe_index = SPS_SDCC_PRODUCER_PIPE_INDEX;
3083 host->sps.dest_pipe_index = SPS_SDCC_CONSUMER_PIPE_INDEX;
3084
3085 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.prod,
3086 SPS_PROD_PERIPHERAL);
3087 if (rc)
3088 goto sps_reset_err;
3089 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.cons,
3090 SPS_CONS_PERIPHERAL);
3091 if (rc)
3092 goto cons_conn_err;
3093
3094 pr_info("%s: Qualcomm MSM SDCC-BAM at 0x%016llx irq %d\n",
3095 mmc_hostname(host->mmc),
3096 (unsigned long long)host->bam_memres->start,
3097 (unsigned int)host->bam_irqres->start);
3098 goto out;
3099
3100cons_conn_err:
3101 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3102sps_reset_err:
3103 sps_deregister_bam_device(host->sps.bam_handle);
3104reg_bam_err:
3105 iounmap(host->bam_base);
3106out:
3107 return rc;
3108}
3109
3110/**
3111 * De-initialize SPS HW connected with SDCC core
3112 *
3113 * This function deinitialize SPS endpoints and then
3114 * deregisters BAM resources from SPS driver.
3115 *
3116 * This function should only be called once typically
3117 * during driver remove.
3118 *
3119 * @host - Pointer to sdcc host structure
3120 *
3121 */
3122static void msmsdcc_sps_exit(struct msmsdcc_host *host)
3123{
3124 msmsdcc_sps_exit_ep_conn(host, &host->sps.cons);
3125 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3126 sps_deregister_bam_device(host->sps.bam_handle);
3127 iounmap(host->bam_base);
3128}
3129#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
3130
3131static ssize_t
3132show_polling(struct device *dev, struct device_attribute *attr, char *buf)
3133{
3134 struct mmc_host *mmc = dev_get_drvdata(dev);
3135 struct msmsdcc_host *host = mmc_priv(mmc);
3136 int poll;
3137 unsigned long flags;
3138
3139 spin_lock_irqsave(&host->lock, flags);
3140 poll = !!(mmc->caps & MMC_CAP_NEEDS_POLL);
3141 spin_unlock_irqrestore(&host->lock, flags);
3142
3143 return snprintf(buf, PAGE_SIZE, "%d\n", poll);
3144}
3145
3146static ssize_t
3147set_polling(struct device *dev, struct device_attribute *attr,
3148 const char *buf, size_t count)
3149{
3150 struct mmc_host *mmc = dev_get_drvdata(dev);
3151 struct msmsdcc_host *host = mmc_priv(mmc);
3152 int value;
3153 unsigned long flags;
3154
3155 sscanf(buf, "%d", &value);
3156
3157 spin_lock_irqsave(&host->lock, flags);
3158 if (value) {
3159 mmc->caps |= MMC_CAP_NEEDS_POLL;
3160 mmc_detect_change(host->mmc, 0);
3161 } else {
3162 mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3163 }
3164#ifdef CONFIG_HAS_EARLYSUSPEND
3165 host->polling_enabled = mmc->caps & MMC_CAP_NEEDS_POLL;
3166#endif
3167 spin_unlock_irqrestore(&host->lock, flags);
3168 return count;
3169}
3170
3171static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR,
3172 show_polling, set_polling);
3173static struct attribute *dev_attrs[] = {
3174 &dev_attr_polling.attr,
3175 NULL,
3176};
3177static struct attribute_group dev_attr_grp = {
3178 .attrs = dev_attrs,
3179};
3180
3181#ifdef CONFIG_HAS_EARLYSUSPEND
3182static void msmsdcc_early_suspend(struct early_suspend *h)
3183{
3184 struct msmsdcc_host *host =
3185 container_of(h, struct msmsdcc_host, early_suspend);
3186 unsigned long flags;
3187
3188 spin_lock_irqsave(&host->lock, flags);
3189 host->polling_enabled = host->mmc->caps & MMC_CAP_NEEDS_POLL;
3190 host->mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3191 spin_unlock_irqrestore(&host->lock, flags);
3192};
3193static void msmsdcc_late_resume(struct early_suspend *h)
3194{
3195 struct msmsdcc_host *host =
3196 container_of(h, struct msmsdcc_host, early_suspend);
3197 unsigned long flags;
3198
3199 if (host->polling_enabled) {
3200 spin_lock_irqsave(&host->lock, flags);
3201 host->mmc->caps |= MMC_CAP_NEEDS_POLL;
3202 mmc_detect_change(host->mmc, 0);
3203 spin_unlock_irqrestore(&host->lock, flags);
3204 }
3205};
3206#endif
3207
3208static void msmsdcc_req_tout_timer_hdlr(unsigned long data)
3209{
3210 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
3211 struct mmc_request *mrq;
3212 unsigned long flags;
3213
3214 spin_lock_irqsave(&host->lock, flags);
3215 if ((host->plat->dummy52_required) &&
3216 (host->dummy_52_state == DUMMY_52_STATE_SENT)) {
3217 pr_info("%s: %s: dummy CMD52 timeout\n",
3218 mmc_hostname(host->mmc), __func__);
3219 host->dummy_52_state = DUMMY_52_STATE_NONE;
3220 }
3221
3222 mrq = host->curr.mrq;
3223
3224 if (mrq && mrq->cmd) {
3225 pr_info("%s: %s CMD%d\n", mmc_hostname(host->mmc),
3226 __func__, mrq->cmd->opcode);
3227 if (!mrq->cmd->error)
3228 mrq->cmd->error = -ETIMEDOUT;
3229 if (host->plat->dummy52_required && host->dummy_52_needed)
3230 host->dummy_52_needed = 0;
3231 if (host->curr.data) {
3232 pr_info("%s: %s Request timeout\n",
3233 mmc_hostname(host->mmc), __func__);
3234 if (mrq->data && !mrq->data->error)
3235 mrq->data->error = -ETIMEDOUT;
3236 host->curr.data_xfered = 0;
3237 if (host->dma.sg && host->is_dma_mode) {
3238 msm_dmov_stop_cmd(host->dma.channel,
3239 &host->dma.hdr, 0);
3240 } else if (host->sps.sg && host->is_sps_mode) {
3241 /* Stop current SPS transfer */
3242 msmsdcc_sps_exit_curr_xfer(host);
3243 } else {
3244 msmsdcc_reset_and_restore(host);
3245 msmsdcc_stop_data(host);
3246 if (mrq->data && mrq->data->stop)
3247 msmsdcc_start_command(host,
3248 mrq->data->stop, 0);
3249 else
3250 msmsdcc_request_end(host, mrq);
3251 }
3252 } else {
3253 if (host->prog_enable) {
3254 host->prog_scan = 0;
3255 host->prog_enable = 0;
3256 }
3257 msmsdcc_reset_and_restore(host);
3258 msmsdcc_request_end(host, mrq);
3259 }
3260 }
3261 spin_unlock_irqrestore(&host->lock, flags);
3262}
3263
San Mehat9d2bd732009-09-22 16:44:22 -07003264static int
3265msmsdcc_probe(struct platform_device *pdev)
3266{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003267 struct mmc_platform_data *plat = pdev->dev.platform_data;
San Mehat9d2bd732009-09-22 16:44:22 -07003268 struct msmsdcc_host *host;
3269 struct mmc_host *mmc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003270 unsigned long flags;
3271 struct resource *core_irqres = NULL;
3272 struct resource *bam_irqres = NULL;
3273 struct resource *core_memres = NULL;
3274 struct resource *dml_memres = NULL;
3275 struct resource *bam_memres = NULL;
San Mehat9d2bd732009-09-22 16:44:22 -07003276 struct resource *dmares = NULL;
3277 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003278 int i;
San Mehat9d2bd732009-09-22 16:44:22 -07003279
3280 /* must have platform data */
3281 if (!plat) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003282 pr_err("%s: Platform data not available\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003283 ret = -EINVAL;
3284 goto out;
3285 }
3286
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003287 if (pdev->id < 1 || pdev->id > 5)
San Mehat9d2bd732009-09-22 16:44:22 -07003288 return -EINVAL;
3289
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003290 if (plat->is_sdio_al_client)
3291 if (!plat->sdio_lpm_gpio_setup || !plat->sdiowakeup_irq)
3292 return -EINVAL;
3293
San Mehat9d2bd732009-09-22 16:44:22 -07003294 if (pdev->resource == NULL || pdev->num_resources < 2) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003295 pr_err("%s: Invalid resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003296 return -ENXIO;
3297 }
3298
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003299 for (i = 0; i < pdev->num_resources; i++) {
3300 if (pdev->resource[i].flags & IORESOURCE_MEM) {
3301 if (!strcmp(pdev->resource[i].name,
3302 "sdcc_dml_addr"))
3303 dml_memres = &pdev->resource[i];
3304 else if (!strcmp(pdev->resource[i].name,
3305 "sdcc_bam_addr"))
3306 bam_memres = &pdev->resource[i];
3307 else
3308 core_memres = &pdev->resource[i];
San Mehat9d2bd732009-09-22 16:44:22 -07003309
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003310 }
3311 if (pdev->resource[i].flags & IORESOURCE_IRQ) {
3312 if (!strcmp(pdev->resource[i].name,
3313 "sdcc_bam_irq"))
3314 bam_irqres = &pdev->resource[i];
3315 else
3316 core_irqres = &pdev->resource[i];
3317 }
3318 if (pdev->resource[i].flags & IORESOURCE_DMA)
3319 dmares = &pdev->resource[i];
3320 }
3321
3322 if (!core_irqres || !core_memres) {
3323 pr_err("%s: Invalid sdcc core resource\n", __func__);
3324 return -ENXIO;
3325 }
3326
3327 /*
3328 * Both BAM and DML memory resource should be preset.
3329 * BAM IRQ resource should also be present.
3330 */
3331 if ((bam_memres && !dml_memres) ||
3332 (!bam_memres && dml_memres) ||
3333 ((bam_memres && dml_memres) && !bam_irqres)) {
3334 pr_err("%s: Invalid sdcc BAM/DML resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003335 return -ENXIO;
3336 }
3337
3338 /*
3339 * Setup our host structure
3340 */
San Mehat9d2bd732009-09-22 16:44:22 -07003341 mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev);
3342 if (!mmc) {
3343 ret = -ENOMEM;
3344 goto out;
3345 }
3346
3347 host = mmc_priv(mmc);
3348 host->pdev_id = pdev->id;
3349 host->plat = plat;
3350 host->mmc = mmc;
San Mehat56a8b5b2009-11-21 12:29:46 -08003351 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003352 if (bam_memres && dml_memres && bam_irqres)
3353 host->is_sps_mode = 1;
3354 else if (dmares)
3355 host->is_dma_mode = 1;
San Mehat9d2bd732009-09-22 16:44:22 -07003356
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003357 host->base = ioremap(core_memres->start,
3358 resource_size(core_memres));
San Mehat9d2bd732009-09-22 16:44:22 -07003359 if (!host->base) {
3360 ret = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003361 goto host_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003362 }
3363
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003364 host->core_irqres = core_irqres;
3365 host->bam_irqres = bam_irqres;
3366 host->core_memres = core_memres;
3367 host->dml_memres = dml_memres;
3368 host->bam_memres = bam_memres;
San Mehat9d2bd732009-09-22 16:44:22 -07003369 host->dmares = dmares;
3370 spin_lock_init(&host->lock);
3371
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003372#ifdef CONFIG_MMC_EMBEDDED_SDIO
3373 if (plat->embedded_sdio)
3374 mmc_set_embedded_sdio_data(mmc,
3375 &plat->embedded_sdio->cis,
3376 &plat->embedded_sdio->cccr,
3377 plat->embedded_sdio->funcs,
3378 plat->embedded_sdio->num_funcs);
3379#endif
3380
Sahitya Tummala62612cf2010-12-08 15:03:03 +05303381 tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
3382 (unsigned long)host);
3383
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003384 tasklet_init(&host->sps.tlet, msmsdcc_sps_complete_tlet,
3385 (unsigned long)host);
3386 if (host->is_dma_mode) {
3387 /* Setup DMA */
3388 ret = msmsdcc_init_dma(host);
3389 if (ret)
3390 goto ioremap_free;
3391 } else {
3392 host->dma.channel = -1;
San Mehat9d2bd732009-09-22 16:44:22 -07003393 }
3394
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003395 /*
3396 * Setup SDCC clock if derived from Dayatona
3397 * fabric core clock.
3398 */
3399 if (plat->pclk_src_dfab) {
3400 host->dfab_pclk = clk_get(&pdev->dev, "dfab_sdc_clk");
3401 if (!IS_ERR(host->dfab_pclk)) {
3402 /* Set the clock rate to 64MHz for max. performance */
3403 ret = clk_set_rate(host->dfab_pclk, 64000000);
3404 if (ret)
3405 goto dfab_pclk_put;
3406 ret = clk_enable(host->dfab_pclk);
3407 if (ret)
3408 goto dfab_pclk_put;
3409 } else
3410 goto dma_free;
3411 }
3412
3413 /*
3414 * Setup main peripheral bus clock
3415 */
3416 host->pclk = clk_get(&pdev->dev, "sdc_pclk");
3417 if (!IS_ERR(host->pclk)) {
3418 ret = clk_enable(host->pclk);
3419 if (ret)
3420 goto pclk_put;
3421
3422 host->pclk_rate = clk_get_rate(host->pclk);
3423 }
3424
3425 /*
3426 * Setup SDC MMC clock
3427 */
San Mehat9d2bd732009-09-22 16:44:22 -07003428 host->clk = clk_get(&pdev->dev, "sdc_clk");
3429 if (IS_ERR(host->clk)) {
3430 ret = PTR_ERR(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003431 goto pclk_disable;
San Mehat9d2bd732009-09-22 16:44:22 -07003432 }
3433
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003434 ret = clk_set_rate(host->clk, msmsdcc_get_min_sup_clk_rate(host));
3435 if (ret) {
3436 pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
3437 goto clk_put;
3438 }
3439
3440 ret = clk_enable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003441 if (ret)
3442 goto clk_put;
3443
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003444 host->clk_rate = clk_get_rate(host->clk);
3445
3446 host->clks_on = 1;
3447
3448 ret = msmsdcc_vreg_init(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07003449 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003450 pr_err("%s: msmsdcc_vreg_init() failed (%d)\n", __func__, ret);
San Mehat9d2bd732009-09-22 16:44:22 -07003451 goto clk_disable;
3452 }
3453
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003454
3455 /* Clocks has to be running before accessing SPS/DML HW blocks */
3456 if (host->is_sps_mode) {
3457 /* Initialize SPS */
3458 ret = msmsdcc_sps_init(host);
3459 if (ret)
3460 goto vreg_deinit;
3461 /* Initialize DML */
3462 ret = msmsdcc_dml_init(host);
3463 if (ret)
3464 goto sps_exit;
3465 }
San Mehat9d2bd732009-09-22 16:44:22 -07003466
San Mehat9d2bd732009-09-22 16:44:22 -07003467 /*
3468 * Setup MMC host structure
3469 */
3470 mmc->ops = &msmsdcc_ops;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003471 mmc->f_min = msmsdcc_get_min_sup_clk_rate(host);
3472 mmc->f_max = msmsdcc_get_max_sup_clk_rate(host);
San Mehat9d2bd732009-09-22 16:44:22 -07003473 mmc->ocr_avail = plat->ocr_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003474 mmc->pm_caps |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
3475 mmc->caps |= plat->mmc_bus_width;
San Mehat9d2bd732009-09-22 16:44:22 -07003476
San Mehat9d2bd732009-09-22 16:44:22 -07003477 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003478 mmc->caps |= plat->uhs_caps;
3479 /*
3480 * XPC controls the maximum current in the default speed mode of SDXC
3481 * card. XPC=0 means 100mA (max.) but speed class is not supported.
3482 * XPC=1 means 150mA (max.) and speed class is supported.
3483 */
3484 if (plat->xpc_cap)
3485 mmc->caps |= (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
3486 MMC_CAP_SET_XPC_180);
3487
3488 if (plat->nonremovable)
3489 mmc->caps |= MMC_CAP_NONREMOVABLE;
3490#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
3491 mmc->caps |= MMC_CAP_SDIO_IRQ;
3492#endif
3493
3494 if (plat->is_sdio_al_client)
3495 mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
San Mehat9d2bd732009-09-22 16:44:22 -07003496
Martin K. Petersena36274e2010-09-10 01:33:59 -04003497 mmc->max_segs = NR_SG;
San Mehat9d2bd732009-09-22 16:44:22 -07003498 mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003499 mmc->max_blk_count = 65535;
San Mehat9d2bd732009-09-22 16:44:22 -07003500
3501 mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */
3502 mmc->max_seg_size = mmc->max_req_size;
3503
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003504 writel_relaxed(0, host->base + MMCIMASK0);
3505 writel_relaxed(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
San Mehat9d2bd732009-09-22 16:44:22 -07003506
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003507 /* Delay needed (MMCIMASK0 was just written above) */
3508 msmsdcc_delay(host);
3509 writel_relaxed(MCI_IRQENABLE, host->base + MMCIMASK0);
3510 mb();
3511 host->mci_irqenable = MCI_IRQENABLE;
San Mehat9d2bd732009-09-22 16:44:22 -07003512
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003513 ret = request_irq(core_irqres->start, msmsdcc_irq, IRQF_SHARED,
3514 DRIVER_NAME " (cmd)", host);
3515 if (ret)
3516 goto dml_exit;
3517
3518 ret = request_irq(core_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
3519 DRIVER_NAME " (pio)", host);
3520 if (ret)
3521 goto irq_free;
3522
3523 /*
3524 * Enable SDCC IRQ only when host is powered on. Otherwise, this
3525 * IRQ is un-necessarily being monitored by MPM (Modem power
3526 * management block) during idle-power collapse. The MPM will be
3527 * configured to monitor the DATA1 GPIO line with level-low trigger
3528 * and thus depending on the GPIO status, it prevents TCXO shutdown
3529 * during idle-power collapse.
3530 */
3531 disable_irq(core_irqres->start);
3532 host->sdcc_irq_disabled = 1;
3533
3534 if (plat->sdiowakeup_irq) {
3535 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3536 mmc_hostname(mmc));
3537 ret = request_irq(plat->sdiowakeup_irq,
3538 msmsdcc_platform_sdiowakeup_irq,
3539 IRQF_SHARED | IRQF_TRIGGER_LOW,
3540 DRIVER_NAME "sdiowakeup", host);
3541 if (ret) {
3542 pr_err("Unable to get sdio wakeup IRQ %d (%d)\n",
3543 plat->sdiowakeup_irq, ret);
3544 goto pio_irq_free;
3545 } else {
3546 spin_lock_irqsave(&host->lock, flags);
3547 if (!host->sdio_irq_disabled) {
3548 disable_irq_nosync(plat->sdiowakeup_irq);
3549 host->sdio_irq_disabled = 1;
3550 }
3551 spin_unlock_irqrestore(&host->lock, flags);
3552 }
3553 }
3554
3555 if (plat->cfg_mpm_sdiowakeup) {
3556 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3557 mmc_hostname(mmc));
3558 }
3559
3560 wake_lock_init(&host->sdio_suspend_wlock, WAKE_LOCK_SUSPEND,
3561 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003562 /*
3563 * Setup card detect change
3564 */
3565
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003566 if (plat->status || plat->status_gpio) {
3567 if (plat->status)
3568 host->oldstat = plat->status(mmc_dev(host->mmc));
3569 else
3570 host->oldstat = msmsdcc_slot_status(host);
3571 host->eject = !host->oldstat;
3572 }
San Mehat9d2bd732009-09-22 16:44:22 -07003573
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003574 if (plat->status_irq) {
3575 ret = request_threaded_irq(plat->status_irq, NULL,
San Mehat9d2bd732009-09-22 16:44:22 -07003576 msmsdcc_platform_status_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003577 plat->irq_flags,
San Mehat9d2bd732009-09-22 16:44:22 -07003578 DRIVER_NAME " (slot)",
3579 host);
3580 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003581 pr_err("Unable to get slot IRQ %d (%d)\n",
3582 plat->status_irq, ret);
3583 goto sdiowakeup_irq_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003584 }
3585 } else if (plat->register_status_notify) {
3586 plat->register_status_notify(msmsdcc_status_notify_cb, host);
3587 } else if (!plat->status)
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003588 pr_err("%s: No card detect facilities available\n",
San Mehat9d2bd732009-09-22 16:44:22 -07003589 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003590
3591 mmc_set_drvdata(pdev, mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003592
3593 ret = pm_runtime_set_active(&(pdev)->dev);
3594 if (ret < 0)
3595 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
3596 __func__, ret);
3597 /*
3598 * There is no notion of suspend/resume for SD/MMC/SDIO
3599 * cards. So host can be suspended/resumed with out
3600 * worrying about its children.
3601 */
3602 pm_suspend_ignore_children(&(pdev)->dev, true);
3603
3604 /*
3605 * MMC/SD/SDIO bus suspend/resume operations are defined
3606 * only for the slots that will be used for non-removable
3607 * media or for all slots when CONFIG_MMC_UNSAFE_RESUME is
3608 * defined. Otherwise, they simply become card removal and
3609 * insertion events during suspend and resume respectively.
3610 * Hence, enable run-time PM only for slots for which bus
3611 * suspend/resume operations are defined.
3612 */
3613#ifdef CONFIG_MMC_UNSAFE_RESUME
3614 /*
3615 * If this capability is set, MMC core will enable/disable host
3616 * for every claim/release operation on a host. We use this
3617 * notification to increment/decrement runtime pm usage count.
3618 */
3619 mmc->caps |= MMC_CAP_DISABLE;
3620 pm_runtime_enable(&(pdev)->dev);
3621#else
3622 if (mmc->caps & MMC_CAP_NONREMOVABLE) {
3623 mmc->caps |= MMC_CAP_DISABLE;
3624 pm_runtime_enable(&(pdev)->dev);
3625 }
3626#endif
3627 setup_timer(&host->req_tout_timer, msmsdcc_req_tout_timer_hdlr,
3628 (unsigned long)host);
3629
San Mehat9d2bd732009-09-22 16:44:22 -07003630 mmc_add_host(mmc);
3631
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003632#ifdef CONFIG_HAS_EARLYSUSPEND
3633 host->early_suspend.suspend = msmsdcc_early_suspend;
3634 host->early_suspend.resume = msmsdcc_late_resume;
3635 host->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
3636 register_early_suspend(&host->early_suspend);
3637#endif
San Mehat9d2bd732009-09-22 16:44:22 -07003638
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003639 pr_info("%s: Qualcomm MSM SDCC-core at 0x%016llx irq %d,%d dma %d\n",
3640 mmc_hostname(mmc), (unsigned long long)core_memres->start,
3641 (unsigned int) core_irqres->start,
3642 (unsigned int) plat->status_irq, host->dma.channel);
3643
3644 pr_info("%s: 8 bit data mode %s\n", mmc_hostname(mmc),
3645 (mmc->caps & MMC_CAP_8_BIT_DATA ? "enabled" : "disabled"));
3646 pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc),
3647 (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled"));
3648 pr_info("%s: polling status mode %s\n", mmc_hostname(mmc),
3649 (mmc->caps & MMC_CAP_NEEDS_POLL ? "enabled" : "disabled"));
3650 pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n",
3651 mmc_hostname(mmc), msmsdcc_get_min_sup_clk_rate(host),
3652 msmsdcc_get_max_sup_clk_rate(host), host->pclk_rate);
3653 pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc),
3654 host->eject);
3655 pr_info("%s: Power save feature enable = %d\n",
3656 mmc_hostname(mmc), msmsdcc_pwrsave);
3657
3658 if (host->is_dma_mode && host->dma.channel != -1) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003659 pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003660 mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003661 pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003662 mmc_hostname(mmc), host->dma.cmd_busaddr,
3663 host->dma.cmdptr_busaddr);
3664 } else if (host->is_sps_mode) {
3665 pr_info("%s: SPS-BAM data transfer mode available\n",
3666 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003667 } else
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003668 pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003669
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003670#if defined(CONFIG_DEBUG_FS)
3671 msmsdcc_dbg_createhost(host);
3672#endif
3673 if (!plat->status_irq) {
3674 ret = sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);
3675 if (ret)
3676 goto platform_irq_free;
3677 }
San Mehat9d2bd732009-09-22 16:44:22 -07003678 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003679
3680 platform_irq_free:
3681 del_timer_sync(&host->req_tout_timer);
3682 pm_runtime_disable(&(pdev)->dev);
3683 pm_runtime_set_suspended(&(pdev)->dev);
3684
3685 if (plat->status_irq)
3686 free_irq(plat->status_irq, host);
3687 sdiowakeup_irq_free:
3688 wake_lock_destroy(&host->sdio_suspend_wlock);
3689 if (plat->sdiowakeup_irq)
3690 free_irq(plat->sdiowakeup_irq, host);
3691 pio_irq_free:
3692 if (plat->sdiowakeup_irq)
3693 wake_lock_destroy(&host->sdio_wlock);
3694 free_irq(core_irqres->start, host);
3695 irq_free:
3696 free_irq(core_irqres->start, host);
3697 dml_exit:
3698 if (host->is_sps_mode)
3699 msmsdcc_dml_exit(host);
3700 sps_exit:
3701 if (host->is_sps_mode)
3702 msmsdcc_sps_exit(host);
3703 vreg_deinit:
3704 msmsdcc_vreg_init(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07003705 clk_disable:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003706 clk_disable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003707 clk_put:
3708 clk_put(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003709 pclk_disable:
3710 if (!IS_ERR(host->pclk))
3711 clk_disable(host->pclk);
San Mehat9d2bd732009-09-22 16:44:22 -07003712 pclk_put:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003713 if (!IS_ERR(host->pclk))
3714 clk_put(host->pclk);
3715 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3716 clk_disable(host->dfab_pclk);
3717 dfab_pclk_put:
3718 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3719 clk_put(host->dfab_pclk);
3720 dma_free:
3721 if (host->is_dma_mode) {
3722 if (host->dmares)
3723 dma_free_coherent(NULL,
3724 sizeof(struct msmsdcc_nc_dmadata),
3725 host->dma.nc, host->dma.nc_busaddr);
3726 }
3727 ioremap_free:
3728 iounmap(host->base);
San Mehat9d2bd732009-09-22 16:44:22 -07003729 host_free:
3730 mmc_free_host(mmc);
3731 out:
3732 return ret;
3733}
3734
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003735static int msmsdcc_remove(struct platform_device *pdev)
Daniel Walker08ecfde2010-06-23 12:32:20 -07003736{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003737 struct mmc_host *mmc = mmc_get_drvdata(pdev);
3738 struct mmc_platform_data *plat;
3739 struct msmsdcc_host *host;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003740
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003741 if (!mmc)
3742 return -ENXIO;
3743
3744 if (pm_runtime_suspended(&(pdev)->dev))
3745 pm_runtime_resume(&(pdev)->dev);
3746
3747 host = mmc_priv(mmc);
3748
3749 DBG(host, "Removing SDCC device = %d\n", pdev->id);
3750 plat = host->plat;
3751
3752 if (!plat->status_irq)
3753 sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
3754
3755 del_timer_sync(&host->req_tout_timer);
3756 tasklet_kill(&host->dma_tlet);
3757 tasklet_kill(&host->sps.tlet);
3758 mmc_remove_host(mmc);
3759
3760 if (plat->status_irq)
3761 free_irq(plat->status_irq, host);
3762
3763 wake_lock_destroy(&host->sdio_suspend_wlock);
3764 if (plat->sdiowakeup_irq) {
3765 wake_lock_destroy(&host->sdio_wlock);
3766 irq_set_irq_wake(plat->sdiowakeup_irq, 0);
3767 free_irq(plat->sdiowakeup_irq, host);
Daniel Walker08ecfde2010-06-23 12:32:20 -07003768 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003769
3770 free_irq(host->core_irqres->start, host);
3771 free_irq(host->core_irqres->start, host);
3772
3773 clk_put(host->clk);
3774 if (!IS_ERR(host->pclk))
3775 clk_put(host->pclk);
3776 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3777 clk_put(host->dfab_pclk);
3778
3779 msmsdcc_vreg_init(host, false);
3780
3781 if (host->is_dma_mode) {
3782 if (host->dmares)
3783 dma_free_coherent(NULL,
3784 sizeof(struct msmsdcc_nc_dmadata),
3785 host->dma.nc, host->dma.nc_busaddr);
3786 }
3787
3788 if (host->is_sps_mode) {
3789 msmsdcc_dml_exit(host);
3790 msmsdcc_sps_exit(host);
3791 }
3792
3793 iounmap(host->base);
3794 mmc_free_host(mmc);
3795
3796#ifdef CONFIG_HAS_EARLYSUSPEND
3797 unregister_early_suspend(&host->early_suspend);
3798#endif
3799 pm_runtime_disable(&(pdev)->dev);
3800 pm_runtime_set_suspended(&(pdev)->dev);
3801
3802 return 0;
3803}
3804
3805#ifdef CONFIG_MSM_SDIO_AL
3806int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3807{
3808 struct msmsdcc_host *host = mmc_priv(mmc);
3809 unsigned long flags;
3810
3811 spin_lock_irqsave(&host->lock, flags);
3812 pr_debug("%s: %sabling LPM\n", mmc_hostname(mmc),
3813 enable ? "En" : "Dis");
3814
3815 if (enable) {
3816 if (!host->sdcc_irq_disabled) {
3817 writel_relaxed(0, host->base + MMCIMASK0);
3818 disable_irq(host->core_irqres->start);
3819 host->sdcc_irq_disabled = 1;
3820 }
3821
3822 if (host->clks_on) {
3823 msmsdcc_setup_clocks(host, false);
3824 host->clks_on = 0;
3825 }
3826
3827 if (!host->sdio_gpio_lpm) {
3828 spin_unlock_irqrestore(&host->lock, flags);
3829 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 0);
3830 spin_lock_irqsave(&host->lock, flags);
3831 host->sdio_gpio_lpm = 1;
3832 }
3833
3834 if (host->sdio_irq_disabled) {
3835 msmsdcc_enable_irq_wake(host);
3836 enable_irq(host->plat->sdiowakeup_irq);
3837 host->sdio_irq_disabled = 0;
3838 }
3839 } else {
3840 if (!host->sdio_irq_disabled) {
3841 disable_irq_nosync(host->plat->sdiowakeup_irq);
3842 host->sdio_irq_disabled = 1;
3843 msmsdcc_disable_irq_wake(host);
3844 }
3845
3846 if (host->sdio_gpio_lpm) {
3847 spin_unlock_irqrestore(&host->lock, flags);
3848 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 1);
3849 spin_lock_irqsave(&host->lock, flags);
3850 host->sdio_gpio_lpm = 0;
3851 }
3852
3853 if (!host->clks_on) {
3854 msmsdcc_setup_clocks(host, true);
3855 host->clks_on = 1;
3856 }
3857
3858 if (host->sdcc_irq_disabled) {
3859 writel_relaxed(host->mci_irqenable,
3860 host->base + MMCIMASK0);
3861 mb();
3862 enable_irq(host->core_irqres->start);
3863 host->sdcc_irq_disabled = 0;
3864 }
3865 wake_lock_timeout(&host->sdio_wlock, 1);
3866 }
3867 spin_unlock_irqrestore(&host->lock, flags);
3868 return 0;
3869}
3870#else
3871int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3872{
3873 return 0;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003874}
3875#endif
3876
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003877#ifdef CONFIG_PM
San Mehat9d2bd732009-09-22 16:44:22 -07003878static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003879msmsdcc_runtime_suspend(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003880{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003881 struct mmc_host *mmc = dev_get_drvdata(dev);
3882 struct msmsdcc_host *host = mmc_priv(mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07003883 int rc = 0;
3884
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003885 if (host->plat->is_sdio_al_client)
3886 return 0;
3887
San Mehat9d2bd732009-09-22 16:44:22 -07003888 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003889 host->sdcc_suspending = 1;
3890 mmc->suspend_task = current;
San Mehat9d2bd732009-09-22 16:44:22 -07003891
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003892 /*
3893 * If the clocks are already turned off by SDIO clients (as
3894 * part of LPM), then clocks should be turned on before
3895 * calling mmc_suspend_host() because mmc_suspend_host might
3896 * send some commands to the card. The clocks will be turned
3897 * off again after mmc_suspend_host. Thus for SD/MMC/SDIO
3898 * cards, clocks will be turned on before mmc_suspend_host
3899 * and turned off after mmc_suspend_host.
3900 */
3901 mmc->ios.clock = host->clk_rate;
3902 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07003903
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003904 /*
3905 * MMC core thinks that host is disabled by now since
3906 * runtime suspend is scheduled after msmsdcc_disable()
3907 * is called. Thus, MMC core will try to enable the host
3908 * while suspending it. This results in a synchronous
3909 * runtime resume request while in runtime suspending
3910 * context and hence inorder to complete this resume
3911 * requet, it will wait for suspend to be complete,
3912 * but runtime suspend also can not proceed further
3913 * until the host is resumed. Thus, it leads to a hang.
3914 * Hence, increase the pm usage count before suspending
3915 * the host so that any resume requests after this will
3916 * simple become pm usage counter increment operations.
3917 */
3918 pm_runtime_get_noresume(dev);
3919 rc = mmc_suspend_host(mmc);
3920 pm_runtime_put_noidle(dev);
3921
3922 if (!rc) {
3923 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
3924 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ)) {
3925 disable_irq(host->core_irqres->start);
3926 host->sdcc_irq_disabled = 1;
3927
3928 /*
3929 * If MMC core level suspend is not supported,
3930 * turn off clocks to allow deep sleep (TCXO
3931 * shutdown).
3932 */
3933 mmc->ios.clock = 0;
3934 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
3935 enable_irq(host->core_irqres->start);
3936 host->sdcc_irq_disabled = 0;
3937
3938 if (host->plat->sdiowakeup_irq) {
3939 host->sdio_irq_disabled = 0;
3940 msmsdcc_enable_irq_wake(host);
3941 enable_irq(host->plat->sdiowakeup_irq);
3942 }
3943 }
3944 }
3945 host->sdcc_suspending = 0;
3946 mmc->suspend_task = NULL;
3947 if (rc && wake_lock_active(&host->sdio_suspend_wlock))
3948 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07003949 }
3950 return rc;
3951}
3952
3953static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003954msmsdcc_runtime_resume(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003955{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003956 struct mmc_host *mmc = dev_get_drvdata(dev);
3957 struct msmsdcc_host *host = mmc_priv(mmc);
3958 unsigned long flags;
3959
3960 if (host->plat->is_sdio_al_client)
3961 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -07003962
3963 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003964 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
3965 if (host->sdcc_irq_disabled) {
3966 enable_irq(host->core_irqres->start);
3967 host->sdcc_irq_disabled = 0;
3968 }
3969 }
3970 mmc->ios.clock = host->clk_rate;
3971 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07003972
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003973 spin_lock_irqsave(&host->lock, flags);
3974 writel_relaxed(host->mci_irqenable, host->base + MMCIMASK0);
3975 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07003976
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003977 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
3978 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) &&
3979 !host->sdio_irq_disabled) {
3980 if (host->plat->sdiowakeup_irq) {
3981 disable_irq_nosync(
3982 host->plat->sdiowakeup_irq);
3983 msmsdcc_disable_irq_wake(host);
3984 host->sdio_irq_disabled = 1;
3985 }
3986 }
San Mehat9d2bd732009-09-22 16:44:22 -07003987
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003988 spin_unlock_irqrestore(&host->lock, flags);
3989
3990 mmc_resume_host(mmc);
3991
3992 /*
3993 * FIXME: Clearing of flags must be handled in clients
3994 * resume handler.
3995 */
3996 spin_lock_irqsave(&host->lock, flags);
3997 mmc->pm_flags = 0;
3998 spin_unlock_irqrestore(&host->lock, flags);
3999
4000 /*
4001 * After resuming the host wait for sometime so that
4002 * the SDIO work will be processed.
4003 */
4004 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO)) {
4005 if ((host->plat->cfg_mpm_sdiowakeup ||
4006 host->plat->sdiowakeup_irq) &&
4007 wake_lock_active(&host->sdio_wlock))
4008 wake_lock_timeout(&host->sdio_wlock, 1);
4009 }
4010
4011 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07004012 }
4013 return 0;
4014}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004015
4016static int msmsdcc_runtime_idle(struct device *dev)
4017{
4018 struct mmc_host *mmc = dev_get_drvdata(dev);
4019 struct msmsdcc_host *host = mmc_priv(mmc);
4020
4021 if (host->plat->is_sdio_al_client)
4022 return 0;
4023
4024 /* Idle timeout is not configurable for now */
4025 pm_schedule_suspend(dev, MSM_MMC_IDLE_TIMEOUT);
4026
4027 return -EAGAIN;
4028}
4029
4030static int msmsdcc_pm_suspend(struct device *dev)
4031{
4032 struct mmc_host *mmc = dev_get_drvdata(dev);
4033 struct msmsdcc_host *host = mmc_priv(mmc);
4034 int rc = 0;
4035
4036 if (host->plat->is_sdio_al_client)
4037 return 0;
4038
4039
4040 if (host->plat->status_irq)
4041 disable_irq(host->plat->status_irq);
4042
4043 if (!pm_runtime_suspended(dev))
4044 rc = msmsdcc_runtime_suspend(dev);
4045
4046 return rc;
4047}
4048
4049static int msmsdcc_pm_resume(struct device *dev)
4050{
4051 struct mmc_host *mmc = dev_get_drvdata(dev);
4052 struct msmsdcc_host *host = mmc_priv(mmc);
4053 int rc = 0;
4054
4055 if (host->plat->is_sdio_al_client)
4056 return 0;
4057
4058 rc = msmsdcc_runtime_resume(dev);
4059 if (host->plat->status_irq) {
4060 msmsdcc_check_status((unsigned long)host);
4061 enable_irq(host->plat->status_irq);
4062 }
4063
4064 /* Update the run-time PM status */
4065 pm_runtime_disable(dev);
4066 rc = pm_runtime_set_active(dev);
4067 if (rc < 0)
4068 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
4069 __func__, rc);
4070 pm_runtime_enable(dev);
4071
4072 return rc;
4073}
4074
Daniel Walker08ecfde2010-06-23 12:32:20 -07004075#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004076#define msmsdcc_runtime_suspend NULL
4077#define msmsdcc_runtime_resume NULL
4078#define msmsdcc_runtime_idle NULL
4079#define msmsdcc_pm_suspend NULL
4080#define msmsdcc_pm_resume NULL
Daniel Walker08ecfde2010-06-23 12:32:20 -07004081#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004082
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004083static const struct dev_pm_ops msmsdcc_dev_pm_ops = {
4084 .runtime_suspend = msmsdcc_runtime_suspend,
4085 .runtime_resume = msmsdcc_runtime_resume,
4086 .runtime_idle = msmsdcc_runtime_idle,
4087 .suspend = msmsdcc_pm_suspend,
4088 .resume = msmsdcc_pm_resume,
4089};
4090
San Mehat9d2bd732009-09-22 16:44:22 -07004091static struct platform_driver msmsdcc_driver = {
4092 .probe = msmsdcc_probe,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004093 .remove = msmsdcc_remove,
San Mehat9d2bd732009-09-22 16:44:22 -07004094 .driver = {
4095 .name = "msm_sdcc",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004096 .pm = &msmsdcc_dev_pm_ops,
San Mehat9d2bd732009-09-22 16:44:22 -07004097 },
4098};
4099
4100static int __init msmsdcc_init(void)
4101{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004102#if defined(CONFIG_DEBUG_FS)
4103 int ret = 0;
4104 ret = msmsdcc_dbg_init();
4105 if (ret) {
4106 pr_err("Failed to create debug fs dir \n");
4107 return ret;
4108 }
4109#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004110 return platform_driver_register(&msmsdcc_driver);
4111}
4112
4113static void __exit msmsdcc_exit(void)
4114{
4115 platform_driver_unregister(&msmsdcc_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004116
4117#if defined(CONFIG_DEBUG_FS)
4118 debugfs_remove(debugfs_file);
4119 debugfs_remove(debugfs_dir);
4120#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004121}
4122
4123module_init(msmsdcc_init);
4124module_exit(msmsdcc_exit);
4125
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004126MODULE_DESCRIPTION("Qualcomm Multimedia Card Interface driver");
San Mehat9d2bd732009-09-22 16:44:22 -07004127MODULE_LICENSE("GPL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004128
4129#if defined(CONFIG_DEBUG_FS)
4130
4131static int
4132msmsdcc_dbg_state_open(struct inode *inode, struct file *file)
4133{
4134 file->private_data = inode->i_private;
4135 return 0;
4136}
4137
4138static ssize_t
4139msmsdcc_dbg_state_read(struct file *file, char __user *ubuf,
4140 size_t count, loff_t *ppos)
4141{
4142 struct msmsdcc_host *host = (struct msmsdcc_host *) file->private_data;
4143 char buf[1024];
4144 int max, i;
4145
4146 i = 0;
4147 max = sizeof(buf) - 1;
4148
4149 i += scnprintf(buf + i, max - i, "STAT: %p %p %p\n", host->curr.mrq,
4150 host->curr.cmd, host->curr.data);
4151 if (host->curr.cmd) {
4152 struct mmc_command *cmd = host->curr.cmd;
4153
4154 i += scnprintf(buf + i, max - i, "CMD : %.8x %.8x %.8x\n",
4155 cmd->opcode, cmd->arg, cmd->flags);
4156 }
4157 if (host->curr.data) {
4158 struct mmc_data *data = host->curr.data;
4159 i += scnprintf(buf + i, max - i,
4160 "DAT0: %.8x %.8x %.8x %.8x %.8x %.8x\n",
4161 data->timeout_ns, data->timeout_clks,
4162 data->blksz, data->blocks, data->error,
4163 data->flags);
4164 i += scnprintf(buf + i, max - i, "DAT1: %.8x %.8x %.8x %p\n",
4165 host->curr.xfer_size, host->curr.xfer_remain,
4166 host->curr.data_xfered, host->dma.sg);
4167 }
4168
4169 return simple_read_from_buffer(ubuf, count, ppos, buf, i);
4170}
4171
4172static const struct file_operations msmsdcc_dbg_state_ops = {
4173 .read = msmsdcc_dbg_state_read,
4174 .open = msmsdcc_dbg_state_open,
4175};
4176
4177static void msmsdcc_dbg_createhost(struct msmsdcc_host *host)
4178{
4179 if (debugfs_dir) {
4180 debugfs_file = debugfs_create_file(mmc_hostname(host->mmc),
4181 0644, debugfs_dir, host,
4182 &msmsdcc_dbg_state_ops);
4183 }
4184}
4185
4186static int __init msmsdcc_dbg_init(void)
4187{
4188 int err;
4189
4190 debugfs_dir = debugfs_create_dir("msmsdcc", 0);
4191 if (IS_ERR(debugfs_dir)) {
4192 err = PTR_ERR(debugfs_dir);
4193 debugfs_dir = NULL;
4194 return err;
4195 }
4196
4197 return 0;
4198}
4199#endif