blob: 2dea65ccb0376dcafa289bf4fb5838e8b62baf8c [file] [log] [blame]
San Mehat9d2bd732009-09-22 16:44:22 -07001/*
2 * linux/drivers/mmc/host/msm_sdcc.c - Qualcomm MSM 7X00A SDCC Driver
3 *
4 * Copyright (C) 2007 Google Inc,
5 * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07006 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
San Mehat9d2bd732009-09-22 16:44:22 -07007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Based on mmci.c
13 *
14 * Author: San Mehat (san@android.com)
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/init.h>
21#include <linux/ioport.h>
22#include <linux/device.h>
23#include <linux/interrupt.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070024#include <linux/irq.h>
San Mehat9d2bd732009-09-22 16:44:22 -070025#include <linux/delay.h>
26#include <linux/err.h>
27#include <linux/highmem.h>
28#include <linux/log2.h>
29#include <linux/mmc/host.h>
30#include <linux/mmc/card.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070031#include <linux/mmc/mmc.h>
San Mehatb3fa5792009-11-02 18:46:09 -080032#include <linux/mmc/sdio.h>
San Mehat9d2bd732009-09-22 16:44:22 -070033#include <linux/clk.h>
34#include <linux/scatterlist.h>
35#include <linux/platform_device.h>
36#include <linux/dma-mapping.h>
37#include <linux/debugfs.h>
38#include <linux/io.h>
39#include <linux/memory.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040#include <linux/pm_runtime.h>
41#include <linux/wakelock.h>
Sahitya Tummala7a892482011-01-18 11:22:49 +053042#include <linux/gpio.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043#include <linux/regulator/consumer.h>
44#include <linux/slab.h>
45#include <linux/mmc/mmc.h>
San Mehat9d2bd732009-09-22 16:44:22 -070046
47#include <asm/cacheflush.h>
48#include <asm/div64.h>
49#include <asm/sizes.h>
50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051#include <asm/mach/mmc.h>
San Mehat9d2bd732009-09-22 16:44:22 -070052#include <mach/msm_iomap.h>
Sahitya Tummalab08bb352010-12-08 15:03:05 +053053#include <mach/clk.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070054#include <mach/dma.h>
55#include <mach/htc_pwrsink.h>
56#include <mach/sdio_al.h>
San Mehat9d2bd732009-09-22 16:44:22 -070057
San Mehat9d2bd732009-09-22 16:44:22 -070058#include "msm_sdcc.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059#include "msm_sdcc_dml.h"
San Mehat9d2bd732009-09-22 16:44:22 -070060
61#define DRIVER_NAME "msm-sdcc"
62
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070063#define DBG(host, fmt, args...) \
64 pr_debug("%s: %s: " fmt "\n", mmc_hostname(host->mmc), __func__ , args)
65
66#define IRQ_DEBUG 0
67#define SPS_SDCC_PRODUCER_PIPE_INDEX 1
68#define SPS_SDCC_CONSUMER_PIPE_INDEX 2
69#define SPS_CONS_PERIPHERAL 0
70#define SPS_PROD_PERIPHERAL 1
71/* 16 KB */
72#define SPS_MAX_DESC_SIZE (16 * 1024)
73
74#if defined(CONFIG_DEBUG_FS)
75static void msmsdcc_dbg_createhost(struct msmsdcc_host *);
76static struct dentry *debugfs_dir;
77static struct dentry *debugfs_file;
78static int msmsdcc_dbg_init(void);
79#endif
80
San Mehat9d2bd732009-09-22 16:44:22 -070081static unsigned int msmsdcc_pwrsave = 1;
San Mehat9d2bd732009-09-22 16:44:22 -070082
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083static struct mmc_command dummy52cmd;
84static struct mmc_request dummy52mrq = {
85 .cmd = &dummy52cmd,
86 .data = NULL,
87 .stop = NULL,
88};
89static struct mmc_command dummy52cmd = {
90 .opcode = SD_IO_RW_DIRECT,
91 .flags = MMC_RSP_PRESENT,
92 .data = NULL,
93 .mrq = &dummy52mrq,
94};
95/*
96 * An array holding the Tuning pattern to compare with when
97 * executing a tuning cycle.
98 */
99static const u32 cmd19_tuning_block[16] = {
100 0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
101 0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
102 0xF0FFF0FF, 0x3CCCFC0F, 0xCFCC33CC, 0xEEFFEFFF,
103 0xFDFFFDFF, 0xFFBFFFDF, 0xFFF7FFBB, 0xDE7B7FF7
104};
San Mehat865c8062009-11-13 13:42:06 -0800105
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700106#if IRQ_DEBUG == 1
107static char *irq_status_bits[] = { "cmdcrcfail", "datcrcfail", "cmdtimeout",
108 "dattimeout", "txunderrun", "rxoverrun",
109 "cmdrespend", "cmdsent", "dataend", NULL,
110 "datablkend", "cmdactive", "txactive",
111 "rxactive", "txhalfempty", "rxhalffull",
112 "txfifofull", "rxfifofull", "txfifoempty",
113 "rxfifoempty", "txdataavlbl", "rxdataavlbl",
114 "sdiointr", "progdone", "atacmdcompl",
115 "sdiointrope", "ccstimeout", NULL, NULL,
116 NULL, NULL, NULL };
117
118static void
119msmsdcc_print_status(struct msmsdcc_host *host, char *hdr, uint32_t status)
San Mehat865c8062009-11-13 13:42:06 -0800120{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700121 int i;
San Mehat8b1c2ba2009-11-16 10:17:30 -0800122
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700123 pr_debug("%s-%s ", mmc_hostname(host->mmc), hdr);
124 for (i = 0; i < 32; i++) {
125 if (status & (1 << i))
126 pr_debug("%s ", irq_status_bits[i]);
San Mehat865c8062009-11-13 13:42:06 -0800127 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700128 pr_debug("\n");
San Mehatc7fc9372009-11-22 17:19:07 -0800129}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700130#endif
San Mehat865c8062009-11-13 13:42:06 -0800131
San Mehat9d2bd732009-09-22 16:44:22 -0700132static void
133msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
134 u32 c);
135
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700136#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
137static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
138 struct msmsdcc_sps_ep_conn_data *ep);
139static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
140 struct msmsdcc_sps_ep_conn_data *ep);
141#else
142static inline int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
143 struct msmsdcc_sps_ep_conn_data *ep,
144 bool is_producer) { return 0; }
145static inline void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
146 struct msmsdcc_sps_ep_conn_data *ep) { }
147static inline int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
148 struct msmsdcc_sps_ep_conn_data *ep)
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530149{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700150 return 0;
151}
152static inline int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
153 struct msmsdcc_sps_ep_conn_data *ep)
154{
155 return 0;
156}
157static inline int msmsdcc_sps_init(struct msmsdcc_host *host) { return 0; }
158static inline void msmsdcc_sps_exit(struct msmsdcc_host *host) {}
159#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530160
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700161/**
Subhash Jadavanib5b07742011-08-29 17:48:07 +0530162 * Apply soft reset to all SDCC BAM pipes
163 *
164 * This function applies soft reset to SDCC BAM pipe.
165 *
166 * This function should be called to recover from error
167 * conditions encountered during CMD/DATA tranfsers with card.
168 *
169 * @host - Pointer to driver's host structure
170 *
171 */
172static void msmsdcc_sps_pipes_reset_and_restore(struct msmsdcc_host *host)
173{
174 int rc;
175
176 /* Reset all SDCC BAM pipes */
177 rc = msmsdcc_sps_reset_ep(host, &host->sps.prod);
178 if (rc)
179 pr_err("%s:msmsdcc_sps_reset_ep(prod) error=%d\n",
180 mmc_hostname(host->mmc), rc);
181 rc = msmsdcc_sps_reset_ep(host, &host->sps.cons);
182 if (rc)
183 pr_err("%s:msmsdcc_sps_reset_ep(cons) error=%d\n",
184 mmc_hostname(host->mmc), rc);
185
186 /* Restore all BAM pipes connections */
187 rc = msmsdcc_sps_restore_ep(host, &host->sps.prod);
188 if (rc)
189 pr_err("%s:msmsdcc_sps_restore_ep(prod) error=%d\n",
190 mmc_hostname(host->mmc), rc);
191 rc = msmsdcc_sps_restore_ep(host, &host->sps.cons);
192 if (rc)
193 pr_err("%s:msmsdcc_sps_restore_ep(cons) error=%d\n",
194 mmc_hostname(host->mmc), rc);
195}
196
197/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700198 * Apply soft reset
199 *
Subhash Jadavanib5b07742011-08-29 17:48:07 +0530200 * This function applies soft reset to SDCC core and DML core.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700201 *
202 * This function should be called to recover from error
203 * conditions encountered with CMD/DATA tranfsers with card.
204 *
205 * Soft reset should only be used with SDCC controller v4.
206 *
207 * @host - Pointer to driver's host structure
208 *
209 */
210static void msmsdcc_soft_reset_and_restore(struct msmsdcc_host *host)
211{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700212 if (host->is_sps_mode) {
213 /* Reset DML first */
214 msmsdcc_dml_reset(host);
Subhash Jadavanib5b07742011-08-29 17:48:07 +0530215 /*
216 * delay the SPS pipe reset in thread context as
217 * sps_connect/sps_disconnect APIs can be called
218 * only from non-atomic context.
219 */
220 host->sps.pipe_reset_pending = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221 }
222 /*
223 * Reset SDCC controller's DPSM (data path state machine
224 * and CPSM (command path state machine).
225 */
226 mb();
227 writel_relaxed(0, host->base + MMCICOMMAND);
228 writel_relaxed(0, host->base + MMCIDATACTRL);
229 mb();
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530230
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700231 pr_debug("%s: Applied soft reset to Controller\n",
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530232 mmc_hostname(host->mmc));
233
Subhash Jadavanib5b07742011-08-29 17:48:07 +0530234 if (host->is_sps_mode)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700235 msmsdcc_dml_init(host);
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530236}
237
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700238static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
239{
240 if (host->plat->sdcc_v4_sup) {
241 msmsdcc_soft_reset_and_restore(host);
242 } else {
243 /* Give Clock reset (hard reset) to controller */
244 u32 mci_clk = 0;
245 u32 mci_mask0 = 0;
246 int ret;
247
248 /* Save the controller state */
249 mci_clk = readl_relaxed(host->base + MMCICLOCK);
250 mci_mask0 = readl_relaxed(host->base + MMCIMASK0);
251
252 mb();
253 /* Reset the controller */
254 ret = clk_reset(host->clk, CLK_RESET_ASSERT);
255 if (ret)
256 pr_err("%s: Clock assert failed at %u Hz"
257 " with err %d\n", mmc_hostname(host->mmc),
258 host->clk_rate, ret);
259
260 ret = clk_reset(host->clk, CLK_RESET_DEASSERT);
261 if (ret)
262 pr_err("%s: Clock deassert failed at %u Hz"
263 " with err %d\n", mmc_hostname(host->mmc),
264 host->clk_rate, ret);
265
266 pr_debug("%s: Controller has been reinitialized\n",
267 mmc_hostname(host->mmc));
268
269 mb();
270 /* Restore the contoller state */
271 writel_relaxed(host->pwr, host->base + MMCIPOWER);
272 writel_relaxed(mci_clk, host->base + MMCICLOCK);
273 writel_relaxed(mci_mask0, host->base + MMCIMASK0);
274 ret = clk_set_rate(host->clk, host->clk_rate);
275 if (ret)
276 pr_err("%s: Failed to set clk rate %u Hz. err %d\n",
277 mmc_hostname(host->mmc),
278 host->clk_rate, ret);
279 mb();
280 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -0700281 if (host->dummy_52_needed)
282 host->dummy_52_needed = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283}
284
285static int
San Mehat9d2bd732009-09-22 16:44:22 -0700286msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
287{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700288 int retval = 0;
289
San Mehat9d2bd732009-09-22 16:44:22 -0700290 BUG_ON(host->curr.data);
291
292 host->curr.mrq = NULL;
293 host->curr.cmd = NULL;
294
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295 del_timer(&host->req_tout_timer);
296
San Mehat9d2bd732009-09-22 16:44:22 -0700297 if (mrq->data)
298 mrq->data->bytes_xfered = host->curr.data_xfered;
299 if (mrq->cmd->error == -ETIMEDOUT)
300 mdelay(5);
301
302 /*
303 * Need to drop the host lock here; mmc_request_done may call
304 * back into the driver...
305 */
306 spin_unlock(&host->lock);
307 mmc_request_done(host->mmc, mrq);
308 spin_lock(&host->lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700309
310 return retval;
San Mehat9d2bd732009-09-22 16:44:22 -0700311}
312
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700313static inline void msmsdcc_delay(struct msmsdcc_host *host);
314
San Mehat9d2bd732009-09-22 16:44:22 -0700315static void
316msmsdcc_stop_data(struct msmsdcc_host *host)
317{
San Mehat9d2bd732009-09-22 16:44:22 -0700318 host->curr.data = NULL;
Sahitya Tummala0c521cc2010-12-08 15:03:07 +0530319 host->curr.got_dataend = 0;
Subhash Jadavani7a651aa2011-08-03 20:44:58 +0530320 host->curr.wait_for_auto_prog_done = 0;
321 host->curr.got_auto_prog_done = 0;
Krishna Konda3f5d48f2011-07-27 10:47:31 -0700322 writel_relaxed(readl_relaxed(host->base + MMCIDATACTRL) &
323 (~(MCI_DPSM_ENABLE)), host->base + MMCIDATACTRL);
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700324 msmsdcc_delay(host); /* Allow the DPSM to be reset */
San Mehat9d2bd732009-09-22 16:44:22 -0700325}
326
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700327static inline uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
San Mehat9d2bd732009-09-22 16:44:22 -0700328{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700329 return host->core_memres->start + MMCIFIFO;
330}
331
332static inline unsigned int msmsdcc_get_min_sup_clk_rate(
333 struct msmsdcc_host *host);
Subhash Jadavani8f13e5b2011-08-04 21:15:11 +0530334
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700335static inline void msmsdcc_delay(struct msmsdcc_host *host)
336{
Subhash Jadavani8f13e5b2011-08-04 21:15:11 +0530337 ktime_t start, diff;
338
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700339 mb();
340 udelay(1 + ((3 * USEC_PER_SEC) /
341 (host->clk_rate ? host->clk_rate :
342 msmsdcc_get_min_sup_clk_rate(host))));
Subhash Jadavani8f13e5b2011-08-04 21:15:11 +0530343
344 if (host->plat->sdcc_v4_sup &&
345 (readl_relaxed(host->base + MCI_STATUS2) &
346 MCI_MCLK_REG_WR_ACTIVE)) {
347 start = ktime_get();
348 while (readl_relaxed(host->base + MCI_STATUS2) &
349 MCI_MCLK_REG_WR_ACTIVE) {
350 diff = ktime_sub(ktime_get(), start);
351 /* poll for max. 1 ms */
352 if (ktime_to_us(diff) > 1000) {
353 pr_warning("%s: previous reg. write is"
354 " still active\n",
355 mmc_hostname(host->mmc));
356 break;
357 }
358 }
359 }
San Mehat9d2bd732009-09-22 16:44:22 -0700360}
361
San Mehat56a8b5b2009-11-21 12:29:46 -0800362static inline void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700363msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c)
364{
365 writel_relaxed(arg, host->base + MMCIARGUMENT);
366 msmsdcc_delay(host);
367 writel_relaxed(c, host->base + MMCICOMMAND);
368 mb();
San Mehat56a8b5b2009-11-21 12:29:46 -0800369}
370
371static void
372msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
373{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->user;
San Mehat56a8b5b2009-11-21 12:29:46 -0800375
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700376 writel_relaxed(host->cmd_timeout, host->base + MMCIDATATIMER);
377 writel_relaxed((unsigned int)host->curr.xfer_size,
378 host->base + MMCIDATALENGTH);
379 msmsdcc_delay(host); /* Allow data parms to be applied */
380 writel_relaxed(host->cmd_datactrl, host->base + MMCIDATACTRL);
381 msmsdcc_delay(host); /* Force delay prior to ADM or command */
San Mehat56a8b5b2009-11-21 12:29:46 -0800382
San Mehat6ac9ea62009-12-02 17:24:58 -0800383 if (host->cmd_cmd) {
384 msmsdcc_start_command_exec(host,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700385 (u32)host->cmd_cmd->arg, (u32)host->cmd_c);
San Mehat6ac9ea62009-12-02 17:24:58 -0800386 }
San Mehat56a8b5b2009-11-21 12:29:46 -0800387}
388
San Mehat9d2bd732009-09-22 16:44:22 -0700389static void
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530390msmsdcc_dma_complete_tlet(unsigned long data)
San Mehat9d2bd732009-09-22 16:44:22 -0700391{
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530392 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
San Mehat9d2bd732009-09-22 16:44:22 -0700393 unsigned long flags;
394 struct mmc_request *mrq;
395
396 spin_lock_irqsave(&host->lock, flags);
397 mrq = host->curr.mrq;
398 BUG_ON(!mrq);
399
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530400 if (!(host->dma.result & DMOV_RSLT_VALID)) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700401 pr_err("msmsdcc: Invalid DataMover result\n");
San Mehat9d2bd732009-09-22 16:44:22 -0700402 goto out;
403 }
404
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530405 if (host->dma.result & DMOV_RSLT_DONE) {
San Mehat9d2bd732009-09-22 16:44:22 -0700406 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407 host->curr.xfer_remain -= host->curr.xfer_size;
San Mehat9d2bd732009-09-22 16:44:22 -0700408 } else {
409 /* Error or flush */
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530410 if (host->dma.result & DMOV_RSLT_ERROR)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700411 pr_err("%s: DMA error (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530412 mmc_hostname(host->mmc), host->dma.result);
413 if (host->dma.result & DMOV_RSLT_FLUSH)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700414 pr_err("%s: DMA channel flushed (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530415 mmc_hostname(host->mmc), host->dma.result);
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530416 pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700417 host->dma.err.flush[0], host->dma.err.flush[1],
418 host->dma.err.flush[2], host->dma.err.flush[3],
419 host->dma.err.flush[4],
420 host->dma.err.flush[5]);
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530421 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -0700422 if (!mrq->data->error)
423 mrq->data->error = -EIO;
424 }
San Mehat9d2bd732009-09-22 16:44:22 -0700425 dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
426 host->dma.dir);
427
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428 if (host->curr.user_pages) {
429 struct scatterlist *sg = host->dma.sg;
430 int i;
431
432 for (i = 0; i < host->dma.num_ents; i++, sg++)
433 flush_dcache_page(sg_page(sg));
434 }
435
San Mehat9d2bd732009-09-22 16:44:22 -0700436 host->dma.sg = NULL;
San Mehat56a8b5b2009-11-21 12:29:46 -0800437 host->dma.busy = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700438
Subhash Jadavani7a651aa2011-08-03 20:44:58 +0530439 if ((host->curr.got_dataend && (!host->curr.wait_for_auto_prog_done ||
440 (host->curr.wait_for_auto_prog_done &&
441 host->curr.got_auto_prog_done))) || mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700442 /*
443 * If we've already gotten our DATAEND / DATABLKEND
444 * for this request, then complete it through here.
445 */
San Mehat9d2bd732009-09-22 16:44:22 -0700446
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700447 if (!mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700448 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700449 host->curr.xfer_remain -= host->curr.xfer_size;
450 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -0700451 if (host->dummy_52_needed) {
452 mrq->data->bytes_xfered = host->curr.data_xfered;
453 host->dummy_52_sent = 1;
454 msmsdcc_start_command(host, &dummy52cmd,
455 MCI_CPSM_PROGENA);
456 goto out;
457 }
458 msmsdcc_stop_data(host);
San Mehat9d2bd732009-09-22 16:44:22 -0700459 if (!mrq->data->stop || mrq->cmd->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700460 host->curr.mrq = NULL;
461 host->curr.cmd = NULL;
462 mrq->data->bytes_xfered = host->curr.data_xfered;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700463 del_timer(&host->req_tout_timer);
San Mehat9d2bd732009-09-22 16:44:22 -0700464 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700465
San Mehat9d2bd732009-09-22 16:44:22 -0700466 mmc_request_done(host->mmc, mrq);
467 return;
468 } else
469 msmsdcc_start_command(host, mrq->data->stop, 0);
470 }
471
472out:
473 spin_unlock_irqrestore(&host->lock, flags);
474 return;
475}
476
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700477#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
478/**
479 * Callback notification from SPS driver
480 *
481 * This callback function gets triggered called from
482 * SPS driver when requested SPS data transfer is
483 * completed.
484 *
485 * SPS driver invokes this callback in BAM irq context so
486 * SDCC driver schedule a tasklet for further processing
487 * this callback notification at later point of time in
488 * tasklet context and immediately returns control back
489 * to SPS driver.
490 *
491 * @nofity - Pointer to sps event notify sturcture
492 *
493 */
494static void
495msmsdcc_sps_complete_cb(struct sps_event_notify *notify)
496{
497 struct msmsdcc_host *host =
498 (struct msmsdcc_host *)
499 ((struct sps_event_notify *)notify)->user;
500
501 host->sps.notify = *notify;
502 pr_debug("%s: %s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
503 mmc_hostname(host->mmc), __func__, notify->event_id,
504 notify->data.transfer.iovec.addr,
505 notify->data.transfer.iovec.size,
506 notify->data.transfer.iovec.flags);
507 /* Schedule a tasklet for completing data transfer */
508 tasklet_schedule(&host->sps.tlet);
509}
510
511/**
512 * Tasklet handler for processing SPS callback event
513 *
514 * This function processing SPS event notification and
515 * checks if the SPS transfer is completed or not and
516 * then accordingly notifies status to MMC core layer.
517 *
518 * This function is called in tasklet context.
519 *
520 * @data - Pointer to sdcc driver data
521 *
522 */
523static void msmsdcc_sps_complete_tlet(unsigned long data)
524{
525 unsigned long flags;
526 int i, rc;
527 u32 data_xfered = 0;
528 struct mmc_request *mrq;
529 struct sps_iovec iovec;
530 struct sps_pipe *sps_pipe_handle;
531 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
532 struct sps_event_notify *notify = &host->sps.notify;
533
534 spin_lock_irqsave(&host->lock, flags);
535 if (host->sps.dir == DMA_FROM_DEVICE)
536 sps_pipe_handle = host->sps.prod.pipe_handle;
537 else
538 sps_pipe_handle = host->sps.cons.pipe_handle;
539 mrq = host->curr.mrq;
540
541 if (!mrq) {
542 spin_unlock_irqrestore(&host->lock, flags);
543 return;
544 }
545
546 pr_debug("%s: %s: sps event_id=%d\n",
547 mmc_hostname(host->mmc), __func__,
548 notify->event_id);
549
550 if (msmsdcc_is_dml_busy(host)) {
551 /* oops !!! this should never happen. */
552 pr_err("%s: %s: Received SPS EOT event"
553 " but DML HW is still busy !!!\n",
554 mmc_hostname(host->mmc), __func__);
555 }
556 /*
557 * Got End of transfer event!!! Check if all of the data
558 * has been transferred?
559 */
560 for (i = 0; i < host->sps.xfer_req_cnt; i++) {
561 rc = sps_get_iovec(sps_pipe_handle, &iovec);
562 if (rc) {
563 pr_err("%s: %s: sps_get_iovec() failed rc=%d, i=%d",
564 mmc_hostname(host->mmc), __func__, rc, i);
565 break;
566 }
567 data_xfered += iovec.size;
568 }
569
570 if (data_xfered == host->curr.xfer_size) {
571 host->curr.data_xfered = host->curr.xfer_size;
572 host->curr.xfer_remain -= host->curr.xfer_size;
573 pr_debug("%s: Data xfer success. data_xfered=0x%x",
574 mmc_hostname(host->mmc),
575 host->curr.xfer_size);
576 } else {
577 pr_err("%s: Data xfer failed. data_xfered=0x%x,"
578 " xfer_size=%d", mmc_hostname(host->mmc),
579 data_xfered, host->curr.xfer_size);
580 msmsdcc_reset_and_restore(host);
581 if (!mrq->data->error)
582 mrq->data->error = -EIO;
583 }
584
585 /* Unmap sg buffers */
586 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
587 host->sps.dir);
588
589 host->sps.sg = NULL;
590 host->sps.busy = 0;
591
Subhash Jadavani7a651aa2011-08-03 20:44:58 +0530592 if ((host->curr.got_dataend && (!host->curr.wait_for_auto_prog_done ||
593 (host->curr.wait_for_auto_prog_done &&
594 host->curr.got_auto_prog_done))) || mrq->data->error) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700595 /*
596 * If we've already gotten our DATAEND / DATABLKEND
597 * for this request, then complete it through here.
598 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599
600 if (!mrq->data->error) {
601 host->curr.data_xfered = host->curr.xfer_size;
602 host->curr.xfer_remain -= host->curr.xfer_size;
603 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -0700604 if (host->dummy_52_needed) {
605 mrq->data->bytes_xfered = host->curr.data_xfered;
606 host->dummy_52_sent = 1;
607 msmsdcc_start_command(host, &dummy52cmd,
608 MCI_CPSM_PROGENA);
609 return;
610 }
611 msmsdcc_stop_data(host);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700612 if (!mrq->data->stop || mrq->cmd->error) {
613 host->curr.mrq = NULL;
614 host->curr.cmd = NULL;
615 mrq->data->bytes_xfered = host->curr.data_xfered;
616 del_timer(&host->req_tout_timer);
617 spin_unlock_irqrestore(&host->lock, flags);
618
619 mmc_request_done(host->mmc, mrq);
620 return;
621 } else {
622 msmsdcc_start_command(host, mrq->data->stop, 0);
623 }
624 }
625 spin_unlock_irqrestore(&host->lock, flags);
626}
627
628/**
629 * Exit from current SPS data transfer
630 *
631 * This function exits from current SPS data transfer.
632 *
633 * This function should be called when error condition
634 * is encountered during data transfer.
635 *
636 * @host - Pointer to sdcc host structure
637 *
638 */
639static void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host)
640{
641 struct mmc_request *mrq;
642
643 mrq = host->curr.mrq;
644 BUG_ON(!mrq);
645
646 msmsdcc_reset_and_restore(host);
647 if (!mrq->data->error)
648 mrq->data->error = -EIO;
649
650 /* Unmap sg buffers */
651 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
652 host->sps.dir);
653
654 host->sps.sg = NULL;
655 host->sps.busy = 0;
656 if (host->curr.data)
657 msmsdcc_stop_data(host);
658
659 if (!mrq->data->stop || mrq->cmd->error)
660 msmsdcc_request_end(host, mrq);
661 else
662 msmsdcc_start_command(host, mrq->data->stop, 0);
663
664}
665#else
666static inline void msmsdcc_sps_complete_cb(struct sps_event_notify *notify) { }
667static inline void msmsdcc_sps_complete_tlet(unsigned long data) { }
668static inline void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host) { }
669#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
670
671static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host);
672
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530673static void
674msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
675 unsigned int result,
676 struct msm_dmov_errdata *err)
677{
678 struct msmsdcc_dma_data *dma_data =
679 container_of(cmd, struct msmsdcc_dma_data, hdr);
680 struct msmsdcc_host *host = dma_data->host;
681
682 dma_data->result = result;
683 if (err)
684 memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
685
686 tasklet_schedule(&host->dma_tlet);
687}
688
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700689static int msmsdcc_check_dma_op_req(struct mmc_data *data)
San Mehat9d2bd732009-09-22 16:44:22 -0700690{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700691 if (((data->blksz * data->blocks) < MCI_FIFOSIZE) ||
692 ((data->blksz * data->blocks) % MCI_FIFOSIZE))
San Mehat9d2bd732009-09-22 16:44:22 -0700693 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700694 else
695 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700696}
697
698static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
699{
700 struct msmsdcc_nc_dmadata *nc;
701 dmov_box *box;
702 uint32_t rows;
San Mehat9d2bd732009-09-22 16:44:22 -0700703 unsigned int n;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700704 int i;
San Mehat9d2bd732009-09-22 16:44:22 -0700705 struct scatterlist *sg = data->sg;
706
Krishna Konda25786ec2011-07-25 16:21:36 -0700707 if ((host->dma.channel == -1) || (host->dma.crci == -1))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700708 return -ENOENT;
San Mehat9d2bd732009-09-22 16:44:22 -0700709
Krishna Konda25786ec2011-07-25 16:21:36 -0700710 BUG_ON((host->pdev_id < 1) || (host->pdev_id > 5));
711
San Mehat9d2bd732009-09-22 16:44:22 -0700712 host->dma.sg = data->sg;
713 host->dma.num_ents = data->sg_len;
714
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700715 BUG_ON(host->dma.num_ents > NR_SG); /* Prevent memory corruption */
San Mehat56a8b5b2009-11-21 12:29:46 -0800716
San Mehat9d2bd732009-09-22 16:44:22 -0700717 nc = host->dma.nc;
718
San Mehat9d2bd732009-09-22 16:44:22 -0700719 if (data->flags & MMC_DATA_READ)
720 host->dma.dir = DMA_FROM_DEVICE;
721 else
722 host->dma.dir = DMA_TO_DEVICE;
723
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700724 /* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
San Mehat9d2bd732009-09-22 16:44:22 -0700725 host->curr.user_pages = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700726 box = &nc->cmd[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700727 for (i = 0; i < host->dma.num_ents; i++) {
San Mehat9d2bd732009-09-22 16:44:22 -0700728 box->cmd = CMD_MODE_BOX;
729
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730 /* Initialize sg dma address */
731 sg->dma_address = pfn_to_dma(mmc_dev(host->mmc),
732 page_to_pfn(sg_page(sg)))
733 + sg->offset;
734
735 if (i == (host->dma.num_ents - 1))
San Mehat9d2bd732009-09-22 16:44:22 -0700736 box->cmd |= CMD_LC;
737 rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
738 (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
739 (sg_dma_len(sg) / MCI_FIFOSIZE) ;
740
741 if (data->flags & MMC_DATA_READ) {
742 box->src_row_addr = msmsdcc_fifo_addr(host);
743 box->dst_row_addr = sg_dma_address(sg);
744
745 box->src_dst_len = (MCI_FIFOSIZE << 16) |
746 (MCI_FIFOSIZE);
747 box->row_offset = MCI_FIFOSIZE;
748
749 box->num_rows = rows * ((1 << 16) + 1);
Krishna Konda25786ec2011-07-25 16:21:36 -0700750 box->cmd |= CMD_SRC_CRCI(host->dma.crci);
San Mehat9d2bd732009-09-22 16:44:22 -0700751 } else {
752 box->src_row_addr = sg_dma_address(sg);
753 box->dst_row_addr = msmsdcc_fifo_addr(host);
754
755 box->src_dst_len = (MCI_FIFOSIZE << 16) |
756 (MCI_FIFOSIZE);
757 box->row_offset = (MCI_FIFOSIZE << 16);
758
759 box->num_rows = rows * ((1 << 16) + 1);
Krishna Konda25786ec2011-07-25 16:21:36 -0700760 box->cmd |= CMD_DST_CRCI(host->dma.crci);
San Mehat9d2bd732009-09-22 16:44:22 -0700761 }
762 box++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700763 sg++;
764 }
765
766 /* location of command block must be 64 bit aligned */
767 BUG_ON(host->dma.cmd_busaddr & 0x07);
768
769 nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
770 host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
771 DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
772 host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
Krishna Konda25786ec2011-07-25 16:21:36 -0700773 host->dma.hdr.crci_mask = msm_dmov_build_crci_mask(1, host->dma.crci);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700774
775 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
776 host->dma.num_ents, host->dma.dir);
777 /* dsb inside dma_map_sg will write nc out to mem as well */
778
779 if (n != host->dma.num_ents) {
780 pr_err("%s: Unable to map in all sg elements\n",
781 mmc_hostname(host->mmc));
782 host->dma.sg = NULL;
783 host->dma.num_ents = 0;
784 return -ENOMEM;
San Mehat56a8b5b2009-11-21 12:29:46 -0800785 }
San Mehat9d2bd732009-09-22 16:44:22 -0700786
787 return 0;
788}
789
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
791/**
792 * Submits data transfer request to SPS driver
793 *
794 * This function make sg (scatter gather) data buffers
795 * DMA ready and then submits them to SPS driver for
796 * transfer.
797 *
798 * @host - Pointer to sdcc host structure
799 * @data - Pointer to mmc_data structure
800 *
801 * @return 0 if success else negative value
802 */
803static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
804 struct mmc_data *data)
San Mehat56a8b5b2009-11-21 12:29:46 -0800805{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700806 int rc = 0;
807 u32 flags;
808 int i;
809 u32 addr, len, data_cnt;
810 struct scatterlist *sg = data->sg;
811 struct sps_pipe *sps_pipe_handle;
812
813 BUG_ON(data->sg_len > NR_SG); /* Prevent memory corruption */
814
815 host->sps.sg = data->sg;
816 host->sps.num_ents = data->sg_len;
817 host->sps.xfer_req_cnt = 0;
818 if (data->flags & MMC_DATA_READ) {
819 host->sps.dir = DMA_FROM_DEVICE;
820 sps_pipe_handle = host->sps.prod.pipe_handle;
821 } else {
822 host->sps.dir = DMA_TO_DEVICE;
823 sps_pipe_handle = host->sps.cons.pipe_handle;
824 }
825
826 /* Make sg buffers DMA ready */
827 rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
828 host->sps.dir);
829
830 if (rc != data->sg_len) {
831 pr_err("%s: Unable to map in all sg elements, rc=%d\n",
832 mmc_hostname(host->mmc), rc);
833 host->sps.sg = NULL;
834 host->sps.num_ents = 0;
835 rc = -ENOMEM;
836 goto dma_map_err;
837 }
838
839 pr_debug("%s: %s: %s: pipe=0x%x, total_xfer=0x%x, sg_len=%d\n",
840 mmc_hostname(host->mmc), __func__,
841 host->sps.dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
842 (u32)sps_pipe_handle, host->curr.xfer_size, data->sg_len);
843
844 for (i = 0; i < data->sg_len; i++) {
845 /*
846 * Check if this is the last buffer to transfer?
847 * If yes then set the INT and EOT flags.
848 */
849 len = sg_dma_len(sg);
850 addr = sg_dma_address(sg);
851 flags = 0;
852 while (len > 0) {
853 if (len > SPS_MAX_DESC_SIZE) {
854 data_cnt = SPS_MAX_DESC_SIZE;
855 } else {
856 data_cnt = len;
857 if (i == data->sg_len - 1)
858 flags = SPS_IOVEC_FLAG_INT |
859 SPS_IOVEC_FLAG_EOT;
860 }
861 rc = sps_transfer_one(sps_pipe_handle, addr,
862 data_cnt, host, flags);
863 if (rc) {
864 pr_err("%s: sps_transfer_one() error! rc=%d,"
865 " pipe=0x%x, sg=0x%x, sg_buf_no=%d\n",
866 mmc_hostname(host->mmc), rc,
867 (u32)sps_pipe_handle, (u32)sg, i);
868 goto dma_map_err;
869 }
870 addr += data_cnt;
871 len -= data_cnt;
872 host->sps.xfer_req_cnt++;
873 }
874 sg++;
875 }
876 goto out;
877
878dma_map_err:
879 /* unmap sg buffers */
880 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
881 host->sps.dir);
882out:
883 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -0700884}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700885#else
886static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
887 struct mmc_data *data) { return 0; }
888#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
San Mehat9d2bd732009-09-22 16:44:22 -0700889
890static void
San Mehat56a8b5b2009-11-21 12:29:46 -0800891msmsdcc_start_command_deferred(struct msmsdcc_host *host,
892 struct mmc_command *cmd, u32 *c)
893{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700894 DBG(host, "op %02x arg %08x flags %08x\n",
895 cmd->opcode, cmd->arg, cmd->flags);
896
San Mehat56a8b5b2009-11-21 12:29:46 -0800897 *c |= (cmd->opcode | MCI_CPSM_ENABLE);
898
899 if (cmd->flags & MMC_RSP_PRESENT) {
900 if (cmd->flags & MMC_RSP_136)
901 *c |= MCI_CPSM_LONGRSP;
902 *c |= MCI_CPSM_RESPONSE;
903 }
904
905 if (/*interrupt*/0)
906 *c |= MCI_CPSM_INTERRUPT;
907
908 if ((((cmd->opcode == 17) || (cmd->opcode == 18)) ||
909 ((cmd->opcode == 24) || (cmd->opcode == 25))) ||
910 (cmd->opcode == 53))
911 *c |= MCI_CSPM_DATCMD;
912
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700913 /* Check if AUTO CMD19 is required or not? */
914 if (((cmd->opcode == 17) || (cmd->opcode == 18)) &&
915 host->tuning_needed) {
916 msmsdcc_enable_cdr_cm_sdc4_dll(host);
917 *c |= MCI_CSPM_AUTO_CMD19;
918 }
919
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530920 if (host->prog_scan && (cmd->opcode == 12)) {
921 *c |= MCI_CPSM_PROGENA;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700922 host->prog_enable = 1;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530923 }
924
San Mehat56a8b5b2009-11-21 12:29:46 -0800925 if (cmd == cmd->mrq->stop)
926 *c |= MCI_CSPM_MCIABORT;
927
San Mehat56a8b5b2009-11-21 12:29:46 -0800928 if (host->curr.cmd != NULL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700929 pr_err("%s: Overlapping command requests\n",
930 mmc_hostname(host->mmc));
San Mehat56a8b5b2009-11-21 12:29:46 -0800931 }
932 host->curr.cmd = cmd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700933
934 /*
935 * Kick the software command timeout timer here.
936 * Timer expires in 10 secs.
937 */
938 mod_timer(&host->req_tout_timer,
939 (jiffies + msecs_to_jiffies(MSM_MMC_REQ_TIMEOUT)));
San Mehat56a8b5b2009-11-21 12:29:46 -0800940}
941
942static void
943msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data,
944 struct mmc_command *cmd, u32 c)
San Mehat9d2bd732009-09-22 16:44:22 -0700945{
Subhash Jadavani24fb7f82011-07-25 15:54:34 +0530946 unsigned int datactrl = 0, timeout;
San Mehat9d2bd732009-09-22 16:44:22 -0700947 unsigned long long clks;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700948 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -0700949 unsigned int pio_irqmask = 0;
950
951 host->curr.data = data;
952 host->curr.xfer_size = data->blksz * data->blocks;
953 host->curr.xfer_remain = host->curr.xfer_size;
954 host->curr.data_xfered = 0;
955 host->curr.got_dataend = 0;
Subhash Jadavani7a651aa2011-08-03 20:44:58 +0530956 host->curr.got_auto_prog_done = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700957
958 memset(&host->pio, 0, sizeof(host->pio));
959
San Mehat9d2bd732009-09-22 16:44:22 -0700960 datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
961
Subhash Jadavani7a651aa2011-08-03 20:44:58 +0530962 if (host->curr.wait_for_auto_prog_done)
963 datactrl |= MCI_AUTO_PROG_DONE;
964
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700965 if (!msmsdcc_check_dma_op_req(data)) {
966 if (host->is_dma_mode && !msmsdcc_config_dma(host, data)) {
967 datactrl |= MCI_DPSM_DMAENABLE;
968 } else if (host->is_sps_mode) {
969 if (!msmsdcc_is_dml_busy(host)) {
970 if (!msmsdcc_sps_start_xfer(host, data)) {
971 /* Now kick start DML transfer */
972 mb();
973 msmsdcc_dml_start_xfer(host, data);
974 datactrl |= MCI_DPSM_DMAENABLE;
975 host->sps.busy = 1;
976 }
977 } else {
978 /*
979 * Can't proceed with new transfer as
980 * previous trasnfer is already in progress.
981 * There is no point of going into PIO mode
982 * as well. Is this a time to do kernel panic?
983 */
984 pr_err("%s: %s: DML HW is busy!!!"
985 " Can't perform new SPS transfers"
986 " now\n", mmc_hostname(host->mmc),
987 __func__);
988 }
989 }
990 }
991
992 /* Is data transfer in PIO mode required? */
993 if (!(datactrl & MCI_DPSM_DMAENABLE)) {
San Mehat9d2bd732009-09-22 16:44:22 -0700994 host->pio.sg = data->sg;
995 host->pio.sg_len = data->sg_len;
996 host->pio.sg_off = 0;
997
998 if (data->flags & MMC_DATA_READ) {
999 pio_irqmask = MCI_RXFIFOHALFFULLMASK;
1000 if (host->curr.xfer_remain < MCI_FIFOSIZE)
1001 pio_irqmask |= MCI_RXDATAAVLBLMASK;
1002 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001003 pio_irqmask = MCI_TXFIFOHALFEMPTYMASK |
1004 MCI_TXFIFOEMPTYMASK;
San Mehat9d2bd732009-09-22 16:44:22 -07001005 }
1006
1007 if (data->flags & MMC_DATA_READ)
Subhash Jadavani24fb7f82011-07-25 15:54:34 +05301008 datactrl |= (MCI_DPSM_DIRECTION | MCI_RX_DATA_PEND);
San Mehat9d2bd732009-09-22 16:44:22 -07001009
San Mehat56a8b5b2009-11-21 12:29:46 -08001010 clks = (unsigned long long)data->timeout_ns * host->clk_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001011 do_div(clks, 1000000000UL);
San Mehat56a8b5b2009-11-21 12:29:46 -08001012 timeout = data->timeout_clks + (unsigned int)clks*2 ;
San Mehat9d2bd732009-09-22 16:44:22 -07001013
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001014 if (host->is_dma_mode && (datactrl & MCI_DPSM_DMAENABLE)) {
1015 /* Use ADM (Application Data Mover) HW for Data transfer */
1016 /* Save parameters for the dma exec function */
San Mehat56a8b5b2009-11-21 12:29:46 -08001017 host->cmd_timeout = timeout;
1018 host->cmd_pio_irqmask = pio_irqmask;
1019 host->cmd_datactrl = datactrl;
1020 host->cmd_cmd = cmd;
San Mehat9d2bd732009-09-22 16:44:22 -07001021
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001022 host->dma.hdr.exec_func = msmsdcc_dma_exec_func;
1023 host->dma.hdr.user = (void *)host;
San Mehat9d2bd732009-09-22 16:44:22 -07001024 host->dma.busy = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001025 if (data->flags & MMC_DATA_WRITE)
1026 host->prog_scan = 1;
San Mehat56a8b5b2009-11-21 12:29:46 -08001027
1028 if (cmd) {
1029 msmsdcc_start_command_deferred(host, cmd, &c);
1030 host->cmd_c = c;
1031 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001032 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1033 (~(MCI_IRQ_PIO))) | host->cmd_pio_irqmask,
1034 host->base + MMCIMASK0);
1035 mb();
1036 msm_dmov_enqueue_cmd_ext(host->dma.channel, &host->dma.hdr);
San Mehat56a8b5b2009-11-21 12:29:46 -08001037 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001038 /* SPS-BAM mode or PIO mode */
1039 if (data->flags & MMC_DATA_WRITE)
1040 host->prog_scan = 1;
1041 writel_relaxed(timeout, base + MMCIDATATIMER);
San Mehat56a8b5b2009-11-21 12:29:46 -08001042
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001043 writel_relaxed(host->curr.xfer_size, base + MMCIDATALENGTH);
San Mehat56a8b5b2009-11-21 12:29:46 -08001044
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001045 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1046 (~(MCI_IRQ_PIO))) | pio_irqmask,
1047 host->base + MMCIMASK0);
1048 msmsdcc_delay(host); /* Allow parms to be applied */
1049 writel_relaxed(datactrl, base + MMCIDATACTRL);
San Mehat56a8b5b2009-11-21 12:29:46 -08001050
1051 if (cmd) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001052 msmsdcc_delay(host); /* Delay between data/command */
San Mehat56a8b5b2009-11-21 12:29:46 -08001053 /* Daisy-chain the command if requested */
1054 msmsdcc_start_command(host, cmd, c);
1055 }
San Mehat9d2bd732009-09-22 16:44:22 -07001056 }
1057}
1058
1059static void
1060msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
1061{
San Mehat56a8b5b2009-11-21 12:29:46 -08001062 msmsdcc_start_command_deferred(host, cmd, &c);
1063 msmsdcc_start_command_exec(host, cmd->arg, c);
San Mehat9d2bd732009-09-22 16:44:22 -07001064}
1065
1066static void
1067msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
1068 unsigned int status)
1069{
1070 if (status & MCI_DATACRCFAIL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001071 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1072 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1073 pr_err("%s: Data CRC error\n",
1074 mmc_hostname(host->mmc));
1075 pr_err("%s: opcode 0x%.8x\n", __func__,
1076 data->mrq->cmd->opcode);
1077 pr_err("%s: blksz %d, blocks %d\n", __func__,
1078 data->blksz, data->blocks);
1079 data->error = -EILSEQ;
1080 }
San Mehat9d2bd732009-09-22 16:44:22 -07001081 } else if (status & MCI_DATATIMEOUT) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001082 /* CRC is optional for the bus test commands, not all
1083 * cards respond back with CRC. However controller
1084 * waits for the CRC and times out. Hence ignore the
1085 * data timeouts during the Bustest.
1086 */
1087 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1088 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1089 pr_err("%s: Data timeout\n",
1090 mmc_hostname(host->mmc));
1091 data->error = -ETIMEDOUT;
1092 }
San Mehat9d2bd732009-09-22 16:44:22 -07001093 } else if (status & MCI_RXOVERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001094 pr_err("%s: RX overrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001095 data->error = -EIO;
1096 } else if (status & MCI_TXUNDERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001097 pr_err("%s: TX underrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001098 data->error = -EIO;
1099 } else {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001100 pr_err("%s: Unknown error (0x%.8x)\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001101 mmc_hostname(host->mmc), status);
San Mehat9d2bd732009-09-22 16:44:22 -07001102 data->error = -EIO;
1103 }
San Mehat9d2bd732009-09-22 16:44:22 -07001104
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001105 /* Dummy CMD52 is not needed when CMD53 has errors */
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001106 if (host->dummy_52_needed)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001107 host->dummy_52_needed = 0;
1108}
San Mehat9d2bd732009-09-22 16:44:22 -07001109
1110static int
1111msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
1112{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001113 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001114 uint32_t *ptr = (uint32_t *) buffer;
1115 int count = 0;
1116
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301117 if (remain % 4)
1118 remain = ((remain >> 2) + 1) << 2;
1119
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001120 while (readl_relaxed(base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1121
1122 *ptr = readl_relaxed(base + MMCIFIFO + (count % MCI_FIFOSIZE));
San Mehat9d2bd732009-09-22 16:44:22 -07001123 ptr++;
1124 count += sizeof(uint32_t);
1125
1126 remain -= sizeof(uint32_t);
1127 if (remain == 0)
1128 break;
1129 }
1130 return count;
1131}
1132
1133static int
1134msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001135 unsigned int remain)
San Mehat9d2bd732009-09-22 16:44:22 -07001136{
1137 void __iomem *base = host->base;
1138 char *ptr = buffer;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001139 unsigned int maxcnt = MCI_FIFOHALFSIZE;
San Mehat9d2bd732009-09-22 16:44:22 -07001140
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001141 while (readl_relaxed(base + MMCISTATUS) &
1142 (MCI_TXFIFOEMPTY | MCI_TXFIFOHALFEMPTY)) {
1143 unsigned int count, sz;
San Mehat9d2bd732009-09-22 16:44:22 -07001144
San Mehat9d2bd732009-09-22 16:44:22 -07001145 count = min(remain, maxcnt);
1146
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301147 sz = count % 4 ? (count >> 2) + 1 : (count >> 2);
1148 writesl(base + MMCIFIFO, ptr, sz);
San Mehat9d2bd732009-09-22 16:44:22 -07001149 ptr += count;
1150 remain -= count;
1151
1152 if (remain == 0)
1153 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001154 }
1155 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07001156
1157 return ptr - buffer;
1158}
1159
San Mehat1cd22962010-02-03 12:59:29 -08001160static irqreturn_t
San Mehat9d2bd732009-09-22 16:44:22 -07001161msmsdcc_pio_irq(int irq, void *dev_id)
1162{
1163 struct msmsdcc_host *host = dev_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001164 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001165 uint32_t status;
1166
Murali Palnati36448a42011-09-02 15:06:18 +05301167 spin_lock(&host->lock);
1168
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001169 status = readl_relaxed(base + MMCISTATUS);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001170
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001171 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
Murali Palnati36448a42011-09-02 15:06:18 +05301172 (MCI_IRQ_PIO)) == 0) {
1173 spin_unlock(&host->lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001174 return IRQ_NONE;
Murali Palnati36448a42011-09-02 15:06:18 +05301175 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001176
1177#if IRQ_DEBUG
1178 msmsdcc_print_status(host, "irq1-r", status);
1179#endif
1180
San Mehat9d2bd732009-09-22 16:44:22 -07001181 do {
1182 unsigned long flags;
1183 unsigned int remain, len;
1184 char *buffer;
1185
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001186 if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_TXFIFOEMPTY
1187 | MCI_RXDATAAVLBL)))
1188 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001189
1190 /* Map the current scatter buffer */
1191 local_irq_save(flags);
1192 buffer = kmap_atomic(sg_page(host->pio.sg),
1193 KM_BIO_SRC_IRQ) + host->pio.sg->offset;
1194 buffer += host->pio.sg_off;
1195 remain = host->pio.sg->length - host->pio.sg_off;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001196
San Mehat9d2bd732009-09-22 16:44:22 -07001197 len = 0;
1198 if (status & MCI_RXACTIVE)
1199 len = msmsdcc_pio_read(host, buffer, remain);
1200 if (status & MCI_TXACTIVE)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001201 len = msmsdcc_pio_write(host, buffer, remain);
San Mehat9d2bd732009-09-22 16:44:22 -07001202
1203 /* Unmap the buffer */
1204 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
1205 local_irq_restore(flags);
1206
1207 host->pio.sg_off += len;
1208 host->curr.xfer_remain -= len;
1209 host->curr.data_xfered += len;
1210 remain -= len;
1211
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001212 if (remain) /* Done with this page? */
1213 break; /* Nope */
San Mehat9d2bd732009-09-22 16:44:22 -07001214
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001215 if (status & MCI_RXACTIVE && host->curr.user_pages)
1216 flush_dcache_page(sg_page(host->pio.sg));
San Mehat9d2bd732009-09-22 16:44:22 -07001217
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001218 if (!--host->pio.sg_len) {
1219 memset(&host->pio, 0, sizeof(host->pio));
1220 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001221 }
1222
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001223 /* Advance to next sg */
1224 host->pio.sg++;
1225 host->pio.sg_off = 0;
1226
1227 status = readl_relaxed(base + MMCISTATUS);
San Mehat9d2bd732009-09-22 16:44:22 -07001228 } while (1);
1229
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001230 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
1231 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1232 (~(MCI_IRQ_PIO))) | MCI_RXDATAAVLBLMASK,
1233 host->base + MMCIMASK0);
1234 if (!host->curr.xfer_remain) {
1235 /* Delay needed (same port was just written) */
1236 msmsdcc_delay(host);
1237 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1238 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1239 }
1240 mb();
1241 } else if (!host->curr.xfer_remain) {
1242 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1243 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1244 mb();
1245 }
San Mehat9d2bd732009-09-22 16:44:22 -07001246
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001247 spin_unlock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001248
1249 return IRQ_HANDLED;
1250}
1251
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001252static void
1253msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq);
1254
1255static void msmsdcc_wait_for_rxdata(struct msmsdcc_host *host,
1256 struct mmc_data *data)
1257{
1258 u32 loop_cnt = 0;
1259
1260 /*
1261 * For read commands with data less than fifo size, it is possible to
1262 * get DATAEND first and RXDATA_AVAIL might be set later because of
1263 * synchronization delay through the asynchronous RX FIFO. Thus, for
1264 * such cases, even after DATAEND interrupt is received software
1265 * should poll for RXDATA_AVAIL until the requested data is read out
1266 * of FIFO. This change is needed to get around this abnormal but
1267 * sometimes expected behavior of SDCC3 controller.
1268 *
1269 * We can expect RXDATAAVAIL bit to be set after 6HCLK clock cycles
1270 * after the data is loaded into RX FIFO. This would amount to less
1271 * than a microsecond and thus looping for 1000 times is good enough
1272 * for that delay.
1273 */
1274 while (((int)host->curr.xfer_remain > 0) && (++loop_cnt < 1000)) {
1275 if (readl_relaxed(host->base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1276 spin_unlock(&host->lock);
1277 msmsdcc_pio_irq(1, host);
1278 spin_lock(&host->lock);
1279 }
1280 }
1281 if (loop_cnt == 1000) {
1282 pr_info("%s: Timed out while polling for Rx Data\n",
1283 mmc_hostname(host->mmc));
1284 data->error = -ETIMEDOUT;
1285 msmsdcc_reset_and_restore(host);
1286 }
1287}
1288
San Mehat9d2bd732009-09-22 16:44:22 -07001289static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
1290{
1291 struct mmc_command *cmd = host->curr.cmd;
San Mehat9d2bd732009-09-22 16:44:22 -07001292
1293 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001294 cmd->resp[0] = readl_relaxed(host->base + MMCIRESPONSE0);
1295 cmd->resp[1] = readl_relaxed(host->base + MMCIRESPONSE1);
1296 cmd->resp[2] = readl_relaxed(host->base + MMCIRESPONSE2);
1297 cmd->resp[3] = readl_relaxed(host->base + MMCIRESPONSE3);
San Mehat9d2bd732009-09-22 16:44:22 -07001298
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001299 if (status & (MCI_CMDTIMEOUT | MCI_AUTOCMD19TIMEOUT)) {
Sahitya Tummala5a0ae912011-07-18 13:34:01 +05301300 pr_debug("%s: Command timeout\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001301 cmd->error = -ETIMEDOUT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001302 } else if ((status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) &&
1303 !host->cmd19_tuning_in_progress) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001304 pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001305 cmd->error = -EILSEQ;
1306 }
1307
1308 if (!cmd->data || cmd->error) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001309 if (host->curr.data && host->dma.sg &&
1310 host->is_dma_mode)
San Mehat9d2bd732009-09-22 16:44:22 -07001311 msm_dmov_stop_cmd(host->dma.channel,
1312 &host->dma.hdr, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001313 else if (host->curr.data && host->sps.sg &&
1314 host->is_sps_mode){
1315 /* Stop current SPS transfer */
1316 msmsdcc_sps_exit_curr_xfer(host);
1317 }
San Mehat9d2bd732009-09-22 16:44:22 -07001318 else if (host->curr.data) { /* Non DMA */
Sahitya Tummalab08bb352010-12-08 15:03:05 +05301319 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -07001320 msmsdcc_stop_data(host);
1321 msmsdcc_request_end(host, cmd->mrq);
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301322 } else { /* host->data == NULL */
1323 if (!cmd->error && host->prog_enable) {
1324 if (status & MCI_PROGDONE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001325 host->prog_scan = 0;
1326 host->prog_enable = 0;
1327 msmsdcc_request_end(host, cmd->mrq);
1328 } else
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301329 host->curr.cmd = cmd;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301330 } else {
1331 if (host->prog_enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001332 host->prog_scan = 0;
1333 host->prog_enable = 0;
1334 }
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001335 if (host->dummy_52_needed)
1336 host->dummy_52_needed = 0;
1337 if (cmd->data && cmd->error)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001338 msmsdcc_reset_and_restore(host);
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301339 msmsdcc_request_end(host, cmd->mrq);
1340 }
1341 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001342 } else if (cmd->data) {
San Mehat56a8b5b2009-11-21 12:29:46 -08001343 if (!(cmd->data->flags & MMC_DATA_READ))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001344 msmsdcc_start_data(host, cmd->data, NULL, 0);
Joe Perchesb5a74d62009-09-22 16:44:25 -07001345 }
1346}
1347
San Mehat9d2bd732009-09-22 16:44:22 -07001348static irqreturn_t
1349msmsdcc_irq(int irq, void *dev_id)
1350{
1351 struct msmsdcc_host *host = dev_id;
San Mehat9d2bd732009-09-22 16:44:22 -07001352 u32 status;
1353 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001354 int timer = 0;
San Mehat9d2bd732009-09-22 16:44:22 -07001355
1356 spin_lock(&host->lock);
1357
1358 do {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001359 struct mmc_command *cmd;
1360 struct mmc_data *data;
San Mehat9d2bd732009-09-22 16:44:22 -07001361
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001362 if (timer) {
1363 timer = 0;
1364 msmsdcc_delay(host);
1365 }
San Mehat865c8062009-11-13 13:42:06 -08001366
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001367 if (!host->clks_on) {
1368 pr_debug("%s: %s: SDIO async irq received\n",
1369 mmc_hostname(host->mmc), __func__);
1370 host->mmc->ios.clock = host->clk_rate;
1371 spin_unlock(&host->lock);
1372 host->mmc->ops->set_ios(host->mmc, &host->mmc->ios);
1373 spin_lock(&host->lock);
1374 if (host->plat->cfg_mpm_sdiowakeup &&
1375 (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1376 wake_lock(&host->sdio_wlock);
1377 /* only ansyc interrupt can come when clocks are off */
1378 writel_relaxed(MCI_SDIOINTMASK, host->base + MMCICLEAR);
1379 }
1380
1381 status = readl_relaxed(host->base + MMCISTATUS);
1382
1383 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1384 (~(MCI_IRQ_PIO))) == 0)
San Mehat865c8062009-11-13 13:42:06 -08001385 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001386
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001387#if IRQ_DEBUG
1388 msmsdcc_print_status(host, "irq0-r", status);
1389#endif
1390 status &= readl_relaxed(host->base + MMCIMASK0);
1391 writel_relaxed(status, host->base + MMCICLEAR);
1392 mb();
1393#if IRQ_DEBUG
1394 msmsdcc_print_status(host, "irq0-p", status);
1395#endif
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001396
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001397#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
1398 if (status & MCI_SDIOINTROPE) {
1399 if (host->sdcc_suspending)
1400 wake_lock(&host->sdio_suspend_wlock);
1401 mmc_signal_sdio_irq(host->mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07001402 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001403#endif
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001404 data = host->curr.data;
1405
1406 if (host->dummy_52_sent) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001407 if (status & (MCI_PROGDONE | MCI_CMDCRCFAIL |
1408 MCI_CMDTIMEOUT)) {
1409 if (status & MCI_CMDTIMEOUT)
1410 pr_debug("%s: dummy CMD52 timeout\n",
1411 mmc_hostname(host->mmc));
1412 if (status & MCI_CMDCRCFAIL)
1413 pr_debug("%s: dummy CMD52 CRC failed\n",
1414 mmc_hostname(host->mmc));
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001415 host->dummy_52_sent = 0;
1416 host->dummy_52_needed = 0;
1417 if (data) {
1418 msmsdcc_stop_data(host);
1419 msmsdcc_request_end(host, data->mrq);
1420 }
1421 WARN(!data, "No data cmd for dummy CMD52\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001422 spin_unlock(&host->lock);
1423 return IRQ_HANDLED;
1424 }
1425 break;
1426 }
1427
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001428 /*
1429 * Check for proper command response
1430 */
1431 cmd = host->curr.cmd;
1432 if ((status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
1433 MCI_CMDTIMEOUT | MCI_PROGDONE |
1434 MCI_AUTOCMD19TIMEOUT)) && host->curr.cmd) {
1435 msmsdcc_do_cmdirq(host, status);
1436 }
1437
1438 if (data) {
1439 /* Check for data errors */
1440 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|
1441 MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
1442 msmsdcc_data_err(host, data, status);
1443 host->curr.data_xfered = 0;
1444 if (host->dma.sg && host->is_dma_mode)
1445 msm_dmov_stop_cmd(host->dma.channel,
1446 &host->dma.hdr, 0);
1447 else if (host->sps.sg && host->is_sps_mode) {
1448 /* Stop current SPS transfer */
1449 msmsdcc_sps_exit_curr_xfer(host);
1450 }
1451 else {
1452 msmsdcc_reset_and_restore(host);
1453 if (host->curr.data)
1454 msmsdcc_stop_data(host);
1455 if (!data->stop)
1456 timer |=
1457 msmsdcc_request_end(host,
1458 data->mrq);
1459 else {
1460 msmsdcc_start_command(host,
1461 data->stop,
1462 0);
1463 timer = 1;
1464 }
1465 }
1466 }
1467
Subhash Jadavani7a651aa2011-08-03 20:44:58 +05301468 /* Check for prog done */
1469 if (host->curr.wait_for_auto_prog_done &&
1470 (status & MCI_PROGDONE))
1471 host->curr.got_auto_prog_done = 1;
1472
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001473 /* Check for data done */
1474 if (!host->curr.got_dataend && (status & MCI_DATAEND))
1475 host->curr.got_dataend = 1;
1476
Subhash Jadavani7a651aa2011-08-03 20:44:58 +05301477 if (host->curr.got_dataend &&
1478 (!host->curr.wait_for_auto_prog_done ||
1479 (host->curr.wait_for_auto_prog_done &&
1480 host->curr.got_auto_prog_done))) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001481 /*
1482 * If DMA is still in progress, we complete
1483 * via the completion handler
1484 */
1485 if (!host->dma.busy && !host->sps.busy) {
1486 /*
1487 * There appears to be an issue in the
1488 * controller where if you request a
1489 * small block transfer (< fifo size),
1490 * you may get your DATAEND/DATABLKEND
1491 * irq without the PIO data irq.
1492 *
1493 * Check to see if theres still data
1494 * to be read, and simulate a PIO irq.
1495 */
1496 if (data->flags & MMC_DATA_READ)
1497 msmsdcc_wait_for_rxdata(host,
1498 data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001499 if (!data->error) {
1500 host->curr.data_xfered =
1501 host->curr.xfer_size;
1502 host->curr.xfer_remain -=
1503 host->curr.xfer_size;
1504 }
1505
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001506 if (!host->dummy_52_needed) {
1507 msmsdcc_stop_data(host);
1508 if (!data->stop) {
1509 msmsdcc_request_end(
1510 host,
1511 data->mrq);
1512 } else {
1513 msmsdcc_start_command(
1514 host,
1515 data->stop, 0);
1516 timer = 1;
1517 }
1518 } else {
1519 host->dummy_52_sent = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001520 msmsdcc_start_command(host,
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001521 &dummy52cmd,
1522 MCI_CPSM_PROGENA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001523 }
1524 }
1525 }
1526 }
1527
San Mehat9d2bd732009-09-22 16:44:22 -07001528 ret = 1;
1529 } while (status);
1530
1531 spin_unlock(&host->lock);
1532
San Mehat9d2bd732009-09-22 16:44:22 -07001533 return IRQ_RETVAL(ret);
1534}
1535
1536static void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001537msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
1538{
1539 if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
1540 /* Queue/read data, daisy-chain command when data starts */
1541 msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
1542 } else {
1543 msmsdcc_start_command(host, mrq->cmd, 0);
1544 }
1545}
1546
1547static void
San Mehat9d2bd732009-09-22 16:44:22 -07001548msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
1549{
1550 struct msmsdcc_host *host = mmc_priv(mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001551 unsigned long flags;
San Mehat9d2bd732009-09-22 16:44:22 -07001552
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001553 /*
1554 * Get the SDIO AL client out of LPM.
1555 */
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07001556 WARN(host->dummy_52_sent, "Dummy CMD52 in progress\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001557 if (host->plat->is_sdio_al_client)
1558 msmsdcc_sdio_al_lpm(mmc, false);
San Mehat9d2bd732009-09-22 16:44:22 -07001559
Subhash Jadavanib5b07742011-08-29 17:48:07 +05301560 /* check if sps pipe reset is pending? */
1561 if (host->is_sps_mode && host->sps.pipe_reset_pending) {
1562 msmsdcc_sps_pipes_reset_and_restore(host);
1563 host->sps.pipe_reset_pending = false;
1564 }
1565
San Mehat9d2bd732009-09-22 16:44:22 -07001566 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001567 WARN(host->curr.mrq, "Request in progress\n");
1568 WARN(!host->pwr, "SDCC power is turned off\n");
1569 WARN(!host->clks_on, "SDCC clocks are turned off\n");
1570 WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
San Mehat9d2bd732009-09-22 16:44:22 -07001571
1572 if (host->eject) {
1573 if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) {
1574 mrq->cmd->error = 0;
1575 mrq->data->bytes_xfered = mrq->data->blksz *
1576 mrq->data->blocks;
1577 } else
1578 mrq->cmd->error = -ENOMEDIUM;
1579
1580 spin_unlock_irqrestore(&host->lock, flags);
1581 mmc_request_done(mmc, mrq);
1582 return;
1583 }
1584
1585 host->curr.mrq = mrq;
1586
Subhash Jadavani7a651aa2011-08-03 20:44:58 +05301587 if (mrq->data && mrq->data->flags == MMC_DATA_WRITE) {
1588 if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
1589 mrq->cmd->opcode == 54) {
1590 if (!host->plat->sdcc_v4_sup)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001591 host->dummy_52_needed = 1;
Subhash Jadavani7a651aa2011-08-03 20:44:58 +05301592 else
1593 /*
1594 * SDCCv4 supports AUTO_PROG_DONE bit for SDIO
1595 * write operations using CMD53 and CMD54.
1596 * Setting this bit with CMD53 would
1597 * automatically triggers PROG_DONE interrupt
1598 * without the need of sending dummy CMD52.
1599 */
1600 host->curr.wait_for_auto_prog_done = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001601 }
San Mehat9d2bd732009-09-22 16:44:22 -07001602 }
Subhash Jadavani7a651aa2011-08-03 20:44:58 +05301603
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001604 msmsdcc_request_start(host, mrq);
San Mehat9d2bd732009-09-22 16:44:22 -07001605 spin_unlock_irqrestore(&host->lock, flags);
1606}
1607
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001608static inline int msmsdcc_vreg_set_voltage(struct msm_mmc_reg_data *vreg,
1609 int min_uV, int max_uV)
1610{
1611 int rc = 0;
1612
1613 if (vreg->set_voltage_sup) {
1614 rc = regulator_set_voltage(vreg->reg, min_uV, max_uV);
1615 if (rc) {
1616 pr_err("%s: regulator_set_voltage(%s) failed."
1617 " min_uV=%d, max_uV=%d, rc=%d\n",
1618 __func__, vreg->name, min_uV, max_uV, rc);
1619 }
1620 }
1621
1622 return rc;
1623}
1624
1625static inline int msmsdcc_vreg_set_optimum_mode(struct msm_mmc_reg_data *vreg,
1626 int uA_load)
1627{
1628 int rc = 0;
1629
1630 rc = regulator_set_optimum_mode(vreg->reg, uA_load);
1631 if (rc < 0)
1632 pr_err("%s: regulator_set_optimum_mode(reg=%s, uA_load=%d)"
1633 " failed. rc=%d\n", __func__, vreg->name,
1634 uA_load, rc);
1635 else
1636 /* regulator_set_optimum_mode() can return non zero value
1637 * even for success case.
1638 */
1639 rc = 0;
1640
1641 return rc;
1642}
1643
1644static inline int msmsdcc_vreg_init_reg(struct msm_mmc_reg_data *vreg,
1645 struct device *dev)
1646{
1647 int rc = 0;
1648
1649 /* check if regulator is already initialized? */
1650 if (vreg->reg)
1651 goto out;
1652
1653 /* Get the regulator handle */
1654 vreg->reg = regulator_get(dev, vreg->name);
1655 if (IS_ERR(vreg->reg)) {
1656 rc = PTR_ERR(vreg->reg);
1657 pr_err("%s: regulator_get(%s) failed. rc=%d\n",
1658 __func__, vreg->name, rc);
1659 }
1660out:
1661 return rc;
1662}
1663
1664static inline void msmsdcc_vreg_deinit_reg(struct msm_mmc_reg_data *vreg)
1665{
1666 if (vreg->reg)
1667 regulator_put(vreg->reg);
1668}
1669
1670/* This init function should be called only once for each SDCC slot */
1671static int msmsdcc_vreg_init(struct msmsdcc_host *host, bool is_init)
1672{
1673 int rc = 0;
1674 struct msm_mmc_slot_reg_data *curr_slot;
1675 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1676 struct device *dev = mmc_dev(host->mmc);
1677
1678 curr_slot = host->plat->vreg_data;
1679 if (!curr_slot)
1680 goto out;
1681
1682 curr_vdd_reg = curr_slot->vdd_data;
1683 curr_vccq_reg = curr_slot->vccq_data;
1684 curr_vddp_reg = curr_slot->vddp_data;
1685
1686 if (is_init) {
1687 /*
1688 * Get the regulator handle from voltage regulator framework
1689 * and then try to set the voltage level for the regulator
1690 */
1691 if (curr_vdd_reg) {
1692 rc = msmsdcc_vreg_init_reg(curr_vdd_reg, dev);
1693 if (rc)
1694 goto out;
1695 }
1696 if (curr_vccq_reg) {
1697 rc = msmsdcc_vreg_init_reg(curr_vccq_reg, dev);
1698 if (rc)
1699 goto vdd_reg_deinit;
1700 }
1701 if (curr_vddp_reg) {
1702 rc = msmsdcc_vreg_init_reg(curr_vddp_reg, dev);
1703 if (rc)
1704 goto vccq_reg_deinit;
1705 }
1706 goto out;
1707 } else {
1708 /* Deregister all regulators from regulator framework */
1709 goto vddp_reg_deinit;
1710 }
1711vddp_reg_deinit:
1712 if (curr_vddp_reg)
1713 msmsdcc_vreg_deinit_reg(curr_vddp_reg);
1714vccq_reg_deinit:
1715 if (curr_vccq_reg)
1716 msmsdcc_vreg_deinit_reg(curr_vccq_reg);
1717vdd_reg_deinit:
1718 if (curr_vdd_reg)
1719 msmsdcc_vreg_deinit_reg(curr_vdd_reg);
1720out:
1721 return rc;
1722}
1723
1724static int msmsdcc_vreg_enable(struct msm_mmc_reg_data *vreg)
1725{
1726 int rc = 0;
1727
Subhash Jadavanicc922692011-08-01 23:05:01 +05301728 /* Put regulator in HPM (high power mode) */
1729 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->hpm_uA);
1730 if (rc < 0)
1731 goto out;
1732
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001733 if (!vreg->is_enabled) {
1734 /* Set voltage level */
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05301735 rc = msmsdcc_vreg_set_voltage(vreg, vreg->high_vol_level,
1736 vreg->high_vol_level);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001737 if (rc)
1738 goto out;
1739
1740 rc = regulator_enable(vreg->reg);
1741 if (rc) {
1742 pr_err("%s: regulator_enable(%s) failed. rc=%d\n",
1743 __func__, vreg->name, rc);
1744 goto out;
1745 }
1746 vreg->is_enabled = true;
1747 }
1748
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001749out:
1750 return rc;
1751}
1752
1753static int msmsdcc_vreg_disable(struct msm_mmc_reg_data *vreg)
1754{
1755 int rc = 0;
1756
1757 /* Never disable regulator marked as always_on */
1758 if (vreg->is_enabled && !vreg->always_on) {
1759 rc = regulator_disable(vreg->reg);
1760 if (rc) {
1761 pr_err("%s: regulator_disable(%s) failed. rc=%d\n",
1762 __func__, vreg->name, rc);
1763 goto out;
1764 }
1765 vreg->is_enabled = false;
1766
1767 rc = msmsdcc_vreg_set_optimum_mode(vreg, 0);
1768 if (rc < 0)
1769 goto out;
1770
1771 /* Set min. voltage level to 0 */
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05301772 rc = msmsdcc_vreg_set_voltage(vreg, 0, vreg->high_vol_level);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001773 if (rc)
1774 goto out;
1775 } else if (vreg->is_enabled && vreg->always_on && vreg->lpm_sup) {
1776 /* Put always_on regulator in LPM (low power mode) */
1777 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->lpm_uA);
1778 if (rc < 0)
1779 goto out;
1780 }
1781out:
1782 return rc;
1783}
1784
1785static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable)
1786{
1787 int rc = 0, i;
1788 struct msm_mmc_slot_reg_data *curr_slot;
1789 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1790 struct msm_mmc_reg_data *vreg_table[3];
1791
1792 curr_slot = host->plat->vreg_data;
1793 if (!curr_slot)
1794 goto out;
1795
1796 curr_vdd_reg = vreg_table[0] = curr_slot->vdd_data;
1797 curr_vccq_reg = vreg_table[1] = curr_slot->vccq_data;
1798 curr_vddp_reg = vreg_table[2] = curr_slot->vddp_data;
1799
1800 for (i = 0; i < ARRAY_SIZE(vreg_table); i++) {
1801 if (vreg_table[i]) {
1802 if (enable)
1803 rc = msmsdcc_vreg_enable(vreg_table[i]);
1804 else
1805 rc = msmsdcc_vreg_disable(vreg_table[i]);
1806 if (rc)
1807 goto out;
1808 }
1809 }
1810out:
1811 return rc;
1812}
1813
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05301814static int msmsdcc_set_vddp_level(struct msmsdcc_host *host, int level)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001815{
1816 int rc = 0;
1817
1818 if (host->plat->vreg_data) {
1819 struct msm_mmc_reg_data *vddp_reg =
1820 host->plat->vreg_data->vddp_data;
1821
1822 if (vddp_reg && vddp_reg->is_enabled)
1823 rc = msmsdcc_vreg_set_voltage(vddp_reg, level, level);
1824 }
1825
1826 return rc;
1827}
1828
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05301829static inline int msmsdcc_set_vddp_low_vol(struct msmsdcc_host *host)
1830{
1831 struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
1832 int rc = 0;
1833
1834 if (curr_slot && curr_slot->vddp_data) {
1835 rc = msmsdcc_set_vddp_level(host,
1836 curr_slot->vddp_data->low_vol_level);
1837
1838 if (rc)
1839 pr_err("%s: %s: failed to change vddp level to %d",
1840 mmc_hostname(host->mmc), __func__,
1841 curr_slot->vddp_data->low_vol_level);
1842 }
1843
1844 return rc;
1845}
1846
1847static inline int msmsdcc_set_vddp_high_vol(struct msmsdcc_host *host)
1848{
1849 struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
1850 int rc = 0;
1851
1852 if (curr_slot && curr_slot->vddp_data) {
1853 rc = msmsdcc_set_vddp_level(host,
1854 curr_slot->vddp_data->high_vol_level);
1855
1856 if (rc)
1857 pr_err("%s: %s: failed to change vddp level to %d",
1858 mmc_hostname(host->mmc), __func__,
1859 curr_slot->vddp_data->high_vol_level);
1860 }
1861
1862 return rc;
1863}
1864
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001865static inline int msmsdcc_is_pwrsave(struct msmsdcc_host *host)
1866{
1867 if (host->clk_rate > 400000 && msmsdcc_pwrsave)
1868 return 1;
1869 return 0;
1870}
1871
1872static inline void msmsdcc_setup_clocks(struct msmsdcc_host *host, bool enable)
1873{
1874 if (enable) {
1875 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1876 clk_enable(host->dfab_pclk);
1877 if (!IS_ERR(host->pclk))
1878 clk_enable(host->pclk);
1879 clk_enable(host->clk);
1880 } else {
1881 clk_disable(host->clk);
1882 if (!IS_ERR(host->pclk))
1883 clk_disable(host->pclk);
1884 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1885 clk_disable(host->dfab_pclk);
1886 }
1887}
1888
1889static inline unsigned int msmsdcc_get_sup_clk_rate(struct msmsdcc_host *host,
1890 unsigned int req_clk)
1891{
1892 unsigned int sel_clk = -1;
1893
1894 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt) {
1895 unsigned char cnt;
1896
1897 for (cnt = 0; cnt < host->plat->sup_clk_cnt; cnt++) {
1898 if (host->plat->sup_clk_table[cnt] > req_clk)
1899 break;
1900 else if (host->plat->sup_clk_table[cnt] == req_clk) {
1901 sel_clk = host->plat->sup_clk_table[cnt];
1902 break;
1903 } else
1904 sel_clk = host->plat->sup_clk_table[cnt];
1905 }
1906 } else {
1907 if ((req_clk < host->plat->msmsdcc_fmax) &&
1908 (req_clk > host->plat->msmsdcc_fmid))
1909 sel_clk = host->plat->msmsdcc_fmid;
1910 else
1911 sel_clk = req_clk;
1912 }
1913
1914 return sel_clk;
1915}
1916
1917static inline unsigned int msmsdcc_get_min_sup_clk_rate(
1918 struct msmsdcc_host *host)
1919{
1920 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1921 return host->plat->sup_clk_table[0];
1922 else
1923 return host->plat->msmsdcc_fmin;
1924}
1925
1926static inline unsigned int msmsdcc_get_max_sup_clk_rate(
1927 struct msmsdcc_host *host)
1928{
1929 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1930 return host->plat->sup_clk_table[host->plat->sup_clk_cnt - 1];
1931 else
1932 return host->plat->msmsdcc_fmax;
1933}
1934
1935static int msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
Sahitya Tummala7a892482011-01-18 11:22:49 +05301936{
1937 struct msm_mmc_gpio_data *curr;
1938 int i, rc = 0;
1939
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001940 curr = host->plat->pin_data->gpio_data;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301941 for (i = 0; i < curr->size; i++) {
1942 if (enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001943 if (curr->gpio[i].is_always_on &&
1944 curr->gpio[i].is_enabled)
1945 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301946 rc = gpio_request(curr->gpio[i].no,
1947 curr->gpio[i].name);
1948 if (rc) {
1949 pr_err("%s: gpio_request(%d, %s) failed %d\n",
1950 mmc_hostname(host->mmc),
1951 curr->gpio[i].no,
1952 curr->gpio[i].name, rc);
1953 goto free_gpios;
1954 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001955 curr->gpio[i].is_enabled = true;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301956 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001957 if (curr->gpio[i].is_always_on)
1958 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301959 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001960 curr->gpio[i].is_enabled = false;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301961 }
1962 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001963 goto out;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301964
1965free_gpios:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001966 for (; i >= 0; i--) {
Sahitya Tummala7a892482011-01-18 11:22:49 +05301967 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001968 curr->gpio[i].is_enabled = false;
1969 }
1970out:
1971 return rc;
1972}
1973
1974static int msmsdcc_setup_pad(struct msmsdcc_host *host, bool enable)
1975{
1976 struct msm_mmc_pad_data *curr;
1977 int i;
1978
1979 curr = host->plat->pin_data->pad_data;
1980 for (i = 0; i < curr->drv->size; i++) {
1981 if (enable)
1982 msm_tlmm_set_hdrive(curr->drv->on[i].no,
1983 curr->drv->on[i].val);
1984 else
1985 msm_tlmm_set_hdrive(curr->drv->off[i].no,
1986 curr->drv->off[i].val);
1987 }
1988
1989 for (i = 0; i < curr->pull->size; i++) {
1990 if (enable)
1991 msm_tlmm_set_hdrive(curr->pull->on[i].no,
1992 curr->pull->on[i].val);
1993 else
1994 msm_tlmm_set_hdrive(curr->pull->off[i].no,
1995 curr->pull->off[i].val);
1996 }
1997
1998 return 0;
1999}
2000
2001static u32 msmsdcc_setup_pins(struct msmsdcc_host *host, bool enable)
2002{
2003 int rc = 0;
2004
2005 if (!host->plat->pin_data || host->plat->pin_data->cfg_sts == enable)
2006 return 0;
2007
2008 if (host->plat->pin_data->is_gpio)
2009 rc = msmsdcc_setup_gpio(host, enable);
2010 else
2011 rc = msmsdcc_setup_pad(host, enable);
2012
2013 if (!rc)
2014 host->plat->pin_data->cfg_sts = enable;
2015
2016 return rc;
2017}
2018
2019static void msmsdcc_enable_irq_wake(struct msmsdcc_host *host)
2020{
2021 unsigned int wakeup_irq;
2022
2023 wakeup_irq = (host->plat->sdiowakeup_irq) ?
2024 host->plat->sdiowakeup_irq :
2025 host->core_irqres->start;
2026
2027 if (!host->irq_wake_enabled) {
2028 enable_irq_wake(wakeup_irq);
2029 host->irq_wake_enabled = true;
2030 }
2031}
2032
2033static void msmsdcc_disable_irq_wake(struct msmsdcc_host *host)
2034{
2035 unsigned int wakeup_irq;
2036
2037 wakeup_irq = (host->plat->sdiowakeup_irq) ?
2038 host->plat->sdiowakeup_irq :
2039 host->core_irqres->start;
2040
2041 if (host->irq_wake_enabled) {
2042 disable_irq_wake(wakeup_irq);
2043 host->irq_wake_enabled = false;
2044 }
Sahitya Tummala7a892482011-01-18 11:22:49 +05302045}
2046
San Mehat9d2bd732009-09-22 16:44:22 -07002047static void
2048msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
2049{
2050 struct msmsdcc_host *host = mmc_priv(mmc);
2051 u32 clk = 0, pwr = 0;
2052 int rc;
San Mehat4adbbcc2009-11-08 13:00:37 -08002053 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002054 unsigned int clock;
San Mehat9d2bd732009-09-22 16:44:22 -07002055
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002056 DBG(host, "ios->clock = %u\n", ios->clock);
Sahitya Tummala7a892482011-01-18 11:22:49 +05302057
San Mehat9d2bd732009-09-22 16:44:22 -07002058 if (ios->clock) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002059 spin_lock_irqsave(&host->lock, flags);
2060 if (!host->clks_on) {
2061 msmsdcc_setup_clocks(host, true);
2062 host->clks_on = 1;
2063 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
2064 if (!host->plat->sdiowakeup_irq) {
2065 writel_relaxed(host->mci_irqenable,
2066 host->base + MMCIMASK0);
2067 mb();
2068 if (host->plat->cfg_mpm_sdiowakeup &&
2069 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
2070 host->plat->cfg_mpm_sdiowakeup(
2071 mmc_dev(mmc), SDC_DAT1_DISWAKE);
2072 msmsdcc_disable_irq_wake(host);
2073 } else if (!(mmc->pm_flags &
2074 MMC_PM_WAKE_SDIO_IRQ)) {
2075 writel_relaxed(host->mci_irqenable,
2076 host->base + MMCIMASK0);
2077 }
2078 }
San Mehat9d2bd732009-09-22 16:44:22 -07002079 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002080 spin_unlock_irqrestore(&host->lock, flags);
2081
2082 clock = msmsdcc_get_sup_clk_rate(host, ios->clock);
2083 /*
2084 * For DDR50 mode, controller needs clock rate to be
2085 * double than what is required on the SD card CLK pin.
2086 */
Subhash Jadavani0e027b72011-08-30 17:40:55 +05302087 if (ios->timing == MMC_TIMING_UHS_DDR50) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002088 /*
2089 * Make sure that we don't double the clock if
2090 * doubled clock rate is already set
2091 */
2092 if (!host->ddr_doubled_clk_rate ||
2093 (host->ddr_doubled_clk_rate &&
2094 (host->ddr_doubled_clk_rate != ios->clock))) {
2095 host->ddr_doubled_clk_rate =
2096 msmsdcc_get_sup_clk_rate(
2097 host, (ios->clock * 2));
2098 clock = host->ddr_doubled_clk_rate;
2099 }
2100 } else {
2101 host->ddr_doubled_clk_rate = 0;
2102 }
2103
2104 if (clock != host->clk_rate) {
2105 rc = clk_set_rate(host->clk, clock);
2106 if (rc < 0)
2107 pr_debug("%s: failed to set clk rate %u\n",
2108 mmc_hostname(mmc), clock);
2109 host->clk_rate = clock;
2110 }
2111 /*
2112 * give atleast 2 MCLK cycles delay for clocks
2113 * and SDCC core to stabilize
2114 */
2115 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002116 clk |= MCI_CLK_ENABLE;
2117 }
2118
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002119 if (ios->bus_width == MMC_BUS_WIDTH_8)
2120 clk |= MCI_CLK_WIDEBUS_8;
2121 else if (ios->bus_width == MMC_BUS_WIDTH_4)
2122 clk |= MCI_CLK_WIDEBUS_4;
2123 else
2124 clk |= MCI_CLK_WIDEBUS_1;
San Mehat9d2bd732009-09-22 16:44:22 -07002125
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002126 if (msmsdcc_is_pwrsave(host))
2127 clk |= MCI_CLK_PWRSAVE;
San Mehat9d2bd732009-09-22 16:44:22 -07002128
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002129 clk |= MCI_CLK_FLOWENA;
San Mehat9d2bd732009-09-22 16:44:22 -07002130
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002131 host->tuning_needed = 0;
2132 /*
2133 * Select the controller timing mode according
2134 * to current bus speed mode
2135 */
2136 if ((ios->timing == MMC_TIMING_UHS_SDR104) ||
2137 (ios->timing == MMC_TIMING_UHS_SDR50)) {
2138 clk |= (4 << 14);
2139 host->tuning_needed = 1;
Subhash Jadavani0e027b72011-08-30 17:40:55 +05302140 } else if (ios->timing == MMC_TIMING_UHS_DDR50) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002141 clk |= (3 << 14);
2142 } else {
2143 clk |= (2 << 14); /* feedback clock */
2144 }
2145
2146 /* Select free running MCLK as input clock of cm_dll_sdc4 */
2147 clk |= (2 << 23);
2148
2149 if (host->io_pad_pwr_switch)
2150 clk |= IO_PAD_PWR_SWITCH;
2151
2152 if (host->plat->translate_vdd && !host->sdio_gpio_lpm)
San Mehat9d2bd732009-09-22 16:44:22 -07002153 pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002154 else if (!host->plat->translate_vdd && !host->sdio_gpio_lpm)
2155 pwr |= msmsdcc_setup_vreg(host, !!ios->vdd);
San Mehat9d2bd732009-09-22 16:44:22 -07002156
2157 switch (ios->power_mode) {
2158 case MMC_POWER_OFF:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002159 htc_pwrsink_set(PWRSINK_SDCARD, 0);
2160 if (!host->sdcc_irq_disabled) {
2161 if (host->plat->cfg_mpm_sdiowakeup)
2162 host->plat->cfg_mpm_sdiowakeup(
2163 mmc_dev(mmc), SDC_DAT1_DISABLE);
2164 disable_irq(host->core_irqres->start);
2165 host->sdcc_irq_disabled = 1;
2166 }
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302167 /*
2168 * As VDD pad rail is always on, set low voltage for VDD
2169 * pad rail when slot is unused (when card is not present
2170 * or during system suspend).
2171 */
2172 msmsdcc_set_vddp_low_vol(host);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002173 msmsdcc_setup_pins(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07002174 break;
2175 case MMC_POWER_UP:
2176 pwr |= MCI_PWR_UP;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002177 if (host->sdcc_irq_disabled) {
2178 if (host->plat->cfg_mpm_sdiowakeup)
2179 host->plat->cfg_mpm_sdiowakeup(
2180 mmc_dev(mmc), SDC_DAT1_ENABLE);
2181 enable_irq(host->core_irqres->start);
2182 host->sdcc_irq_disabled = 0;
2183 }
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302184 msmsdcc_set_vddp_high_vol(host);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002185 msmsdcc_setup_pins(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07002186 break;
2187 case MMC_POWER_ON:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002188 htc_pwrsink_set(PWRSINK_SDCARD, 100);
San Mehat9d2bd732009-09-22 16:44:22 -07002189 pwr |= MCI_PWR_ON;
2190 break;
2191 }
2192
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002193 spin_lock_irqsave(&host->lock, flags);
2194 if (!host->clks_on) {
2195 /* force the clocks to be on */
2196 msmsdcc_setup_clocks(host, true);
2197 /*
2198 * give atleast 2 MCLK cycles delay for clocks
2199 * and SDCC core to stabilize
2200 */
2201 msmsdcc_delay(host);
2202 }
2203 writel_relaxed(clk, host->base + MMCICLOCK);
2204 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002205
2206 if (host->pwr != pwr) {
2207 host->pwr = pwr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002208 writel_relaxed(pwr, host->base + MMCIPOWER);
2209 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07002210 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002211 if (!host->clks_on) {
2212 /* force the clocks to be off */
2213 msmsdcc_setup_clocks(host, false);
2214 /*
2215 * give atleast 2 MCLK cycles delay for clocks
2216 * and SDCC core to stabilize
2217 */
2218 msmsdcc_delay(host);
2219 }
2220
2221 if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
2222 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
2223 if (!host->plat->sdiowakeup_irq) {
2224 writel_relaxed(MCI_SDIOINTMASK,
2225 host->base + MMCIMASK0);
2226 mb();
2227 if (host->plat->cfg_mpm_sdiowakeup &&
2228 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
2229 host->plat->cfg_mpm_sdiowakeup(
2230 mmc_dev(mmc), SDC_DAT1_ENWAKE);
2231 msmsdcc_enable_irq_wake(host);
2232 } else if (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2233 writel_relaxed(0, host->base + MMCIMASK0);
2234 } else {
2235 writel_relaxed(MCI_SDIOINTMASK,
2236 host->base + MMCIMASK0);
2237 }
2238 msmsdcc_delay(host);
2239 }
2240 msmsdcc_setup_clocks(host, false);
2241 host->clks_on = 0;
2242 }
San Mehat4adbbcc2009-11-08 13:00:37 -08002243 spin_unlock_irqrestore(&host->lock, flags);
San Mehat9d2bd732009-09-22 16:44:22 -07002244}
2245
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002246int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave)
2247{
2248 struct msmsdcc_host *host = mmc_priv(mmc);
2249 u32 clk;
2250
2251 clk = readl_relaxed(host->base + MMCICLOCK);
2252 pr_debug("Changing to pwr_save=%d", pwrsave);
2253 if (pwrsave && msmsdcc_is_pwrsave(host))
2254 clk |= MCI_CLK_PWRSAVE;
2255 else
2256 clk &= ~MCI_CLK_PWRSAVE;
2257 writel_relaxed(clk, host->base + MMCICLOCK);
2258 mb();
2259
2260 return 0;
2261}
2262
2263static int msmsdcc_get_ro(struct mmc_host *mmc)
2264{
2265 int status = -ENOSYS;
2266 struct msmsdcc_host *host = mmc_priv(mmc);
2267
2268 if (host->plat->wpswitch) {
2269 status = host->plat->wpswitch(mmc_dev(mmc));
2270 } else if (host->plat->wpswitch_gpio) {
2271 status = gpio_request(host->plat->wpswitch_gpio,
2272 "SD_WP_Switch");
2273 if (status) {
2274 pr_err("%s: %s: Failed to request GPIO %d\n",
2275 mmc_hostname(mmc), __func__,
2276 host->plat->wpswitch_gpio);
2277 } else {
2278 status = gpio_direction_input(
2279 host->plat->wpswitch_gpio);
2280 if (!status) {
2281 /*
2282 * Wait for atleast 300ms as debounce
2283 * time for GPIO input to stabilize.
2284 */
2285 msleep(300);
2286 status = gpio_get_value_cansleep(
2287 host->plat->wpswitch_gpio);
2288 status ^= !host->plat->wpswitch_polarity;
2289 }
2290 gpio_free(host->plat->wpswitch_gpio);
2291 }
2292 }
2293
2294 if (status < 0)
2295 status = -ENOSYS;
2296 pr_debug("%s: Card read-only status %d\n", __func__, status);
2297
2298 return status;
2299}
2300
2301#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002302static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
2303{
2304 struct msmsdcc_host *host = mmc_priv(mmc);
2305 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002306
2307 if (enable) {
2308 spin_lock_irqsave(&host->lock, flags);
2309 host->mci_irqenable |= MCI_SDIOINTOPERMASK;
2310 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) |
2311 MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2312 spin_unlock_irqrestore(&host->lock, flags);
2313 } else {
2314 host->mci_irqenable &= ~MCI_SDIOINTOPERMASK;
2315 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) &
2316 ~MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2317 }
2318 mb();
2319}
2320#endif /* CONFIG_MMC_MSM_SDIO_SUPPORT */
2321
2322#ifdef CONFIG_PM_RUNTIME
2323static int msmsdcc_enable(struct mmc_host *mmc)
2324{
Sahitya Tummala8605fca2011-08-22 15:39:19 +05302325 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002326 struct device *dev = mmc->parent;
2327
Sahitya Tummala8605fca2011-08-22 15:39:19 +05302328 if (pm_runtime_suspended(dev))
2329 rc = pm_runtime_get_sync(dev);
2330 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002331 pm_runtime_get_noresume(dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002332
Sahitya Tummala8605fca2011-08-22 15:39:19 +05302333 if (rc < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002334 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2335 __func__, rc);
Sahitya Tummala8605fca2011-08-22 15:39:19 +05302336 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002337}
2338
2339static int msmsdcc_disable(struct mmc_host *mmc, int lazy)
2340{
2341 int rc;
Sahitya Tummalab07e1ae2011-09-02 11:58:42 +05302342 struct msmsdcc_host *host = mmc_priv(mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002343
Sahitya Tummalab07e1ae2011-09-02 11:58:42 +05302344 if (host->plat->disable_runtime_pm)
2345 return -ENOTSUPP;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002346 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO)
2347 return -ENOTSUPP;
2348
2349 rc = pm_runtime_put_sync(mmc->parent);
2350
2351 if (rc < 0)
2352 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2353 __func__, rc);
2354 return rc;
2355}
2356#else
2357#define msmsdcc_enable NULL
2358#define msmsdcc_disable NULL
2359#endif
2360
2361static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
2362 struct mmc_ios *ios)
2363{
2364 struct msmsdcc_host *host = mmc_priv(mmc);
2365 unsigned long flags;
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302366 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002367
2368 if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
2369 /* Change voltage level of VDDPX to high voltage */
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302370 rc = msmsdcc_set_vddp_high_vol(host);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002371 goto out;
2372 } else if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
2373 /* invalid selection. don't do anything */
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302374 rc = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002375 goto out;
2376 }
San Mehat9d2bd732009-09-22 16:44:22 -07002377
2378 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002379 /*
2380 * If we are here means voltage switch from high voltage to
2381 * low voltage is required
2382 */
2383
2384 /*
2385 * Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
2386 * register until they become all zeros.
2387 */
2388 if (readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1)) {
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302389 rc = -EAGAIN;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002390 pr_err("%s: %s: MCIDATIN_3_0 is still not all zeros",
2391 mmc_hostname(mmc), __func__);
2392 goto out_unlock;
San Mehat9d2bd732009-09-22 16:44:22 -07002393 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002394
2395 /* Stop SD CLK output. */
2396 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2397 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2398
San Mehat9d2bd732009-09-22 16:44:22 -07002399 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002400
2401 /*
2402 * Switch VDDPX from high voltage to low voltage
2403 * to change the VDD of the SD IO pads.
2404 */
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302405 rc = msmsdcc_set_vddp_low_vol(host);
2406 if (rc)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002407 goto out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002408
2409 spin_lock_irqsave(&host->lock, flags);
2410 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2411 IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
2412 host->io_pad_pwr_switch = 1;
2413 spin_unlock_irqrestore(&host->lock, flags);
2414
2415 /* Wait 5 ms for the voltage regulater in the card to become stable. */
2416 usleep_range(5000, 5500);
2417
2418 spin_lock_irqsave(&host->lock, flags);
2419 /* Start SD CLK output. */
2420 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2421 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2422 spin_unlock_irqrestore(&host->lock, flags);
2423
2424 /*
2425 * If MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT register
2426 * don't become all ones within 1 ms then a Voltage Switch
2427 * sequence has failed and a power cycle to the card is required.
2428 * Otherwise Voltage Switch sequence is completed successfully.
2429 */
2430 usleep_range(1000, 1500);
2431
2432 spin_lock_irqsave(&host->lock, flags);
2433 if ((readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1))
2434 != (0xF << 1)) {
2435 pr_err("%s: %s: MCIDATIN_3_0 are still not all ones",
2436 mmc_hostname(mmc), __func__);
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302437 rc = -EAGAIN;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002438 goto out_unlock;
2439 }
2440
2441out_unlock:
2442 spin_unlock_irqrestore(&host->lock, flags);
2443out:
Subhash Jadavani99ba53a2011-08-01 16:04:18 +05302444 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002445}
2446
2447static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2448 u8 phase);
2449/* Initialize the DLL (Programmable Delay Line ) */
2450static int msmsdcc_init_cm_sdc4_dll(struct msmsdcc_host *host)
2451{
2452 int rc = 0;
2453 u32 wait_timeout;
2454
2455 /* Write 0 to DLL_PDN bit of MCI_DLL_CONFIG register */
2456 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2457 & ~MCI_DLL_PDN), host->base + MCI_DLL_CONFIG);
2458
2459 /* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
2460 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2461 | MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2462
2463 msmsdcc_delay(host);
2464
2465 /* Write 0 to DLL_RST bit of MCI_DLL_CONFIG register */
2466 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2467 & ~MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2468
2469 /* Initialize the phase to 0 */
2470 rc = msmsdcc_config_cm_sdc4_dll_phase(host, 0);
2471 if (rc)
2472 goto out;
2473
2474 wait_timeout = 1000;
2475 /* Wait until DLL_LOCK bit of MCI_DLL_STATUS register becomes '1' */
2476 while (!(readl_relaxed(host->base + MCI_DLL_STATUS) & MCI_DLL_LOCK)) {
2477 /* max. wait for 1 sec for LOCK bit to be set */
2478 if (--wait_timeout == 0) {
2479 pr_err("%s: %s: DLL failed to lock at phase: %d",
2480 mmc_hostname(host->mmc), __func__, 0);
2481 rc = -1;
2482 goto out;
2483 }
2484 /* wait for 1ms */
2485 usleep_range(1000, 1500);
2486 }
2487out:
2488 return rc;
2489}
2490
2491/*
2492 * Enable a CDR circuit in CM_SDC4_DLL block to enable automatic
2493 * calibration sequence. This function should be called before
2494 * enabling AUTO_CMD19 bit in MCI_CMD register for block read
2495 * commands (CMD17/CMD18).
2496 */
2497static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host)
2498{
2499 /* Set CDR_EN bit to 1. */
2500 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG) |
2501 MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2502
2503 /* Set CDR_EXT_EN bit to 0. */
2504 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2505 & ~MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2506
2507 /* Set CK_OUT_EN bit to 0. */
2508 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2509 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2510
2511 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2512 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)
2513 ;
2514
2515 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2516 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2517 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2518
2519 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register is 1. */
2520 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN))
2521 ;
2522}
2523
2524static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2525 u8 phase)
2526{
2527 int rc = 0;
2528 u32 mclk_freq = 0;
2529 u32 wait_timeout;
2530
2531 /* Set CDR_EN bit to 0. */
2532 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2533 & ~MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2534
2535 /* Set CDR_EXT_EN bit to 1. */
2536 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2537 | MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2538
2539 /* Program the MCLK value to MCLK_FREQ bit field */
2540 if (host->clk_rate <= 112000000)
2541 mclk_freq = 0;
2542 else if (host->clk_rate <= 125000000)
2543 mclk_freq = 1;
2544 else if (host->clk_rate <= 137000000)
2545 mclk_freq = 2;
2546 else if (host->clk_rate <= 150000000)
2547 mclk_freq = 3;
2548 else if (host->clk_rate <= 162000000)
2549 mclk_freq = 4;
2550 else if (host->clk_rate <= 175000000)
2551 mclk_freq = 5;
2552 else if (host->clk_rate <= 187000000)
2553 mclk_freq = 6;
2554 else if (host->clk_rate <= 200000000)
2555 mclk_freq = 7;
2556
2557 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2558 & ~(7 << 24)) | (mclk_freq << 24)),
2559 host->base + MCI_DLL_CONFIG);
2560
2561 /* Set CK_OUT_EN bit to 0. */
2562 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2563 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2564
2565 /* Set DLL_EN bit to 1. */
2566 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2567 | MCI_DLL_EN), host->base + MCI_DLL_CONFIG);
2568
2569 wait_timeout = 1000;
2570 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2571 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN) {
2572 /* max. wait for 1 sec for LOCK bit for be set */
2573 if (--wait_timeout == 0) {
2574 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 0",
2575 mmc_hostname(host->mmc), __func__, phase);
2576 rc = -1;
2577 goto out;
2578 }
2579 /* wait for 1ms */
2580 usleep_range(1000, 1500);
2581 }
2582
2583 /*
2584 * Write the selected DLL clock output phase (0 ... 15)
2585 * to CDR_SELEXT bit field of MCI_DLL_CONFIG register.
2586 */
2587 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2588 & ~(0xF << 20)) | (phase << 20)),
2589 host->base + MCI_DLL_CONFIG);
2590
2591 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2592 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2593 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2594
2595 wait_timeout = 1000;
2596 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '1' */
2597 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)) {
2598 /* max. wait for 1 sec for LOCK bit for be set */
2599 if (--wait_timeout == 0) {
2600 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 1",
2601 mmc_hostname(host->mmc), __func__, phase);
2602 rc = -1;
2603 goto out;
2604 }
2605 /* wait for 1ms */
2606 usleep_range(1000, 1500);
2607 }
2608out:
2609 return rc;
2610}
2611
2612static int msmsdcc_execute_tuning(struct mmc_host *mmc)
2613{
2614 struct msmsdcc_host *host = mmc_priv(mmc);
2615 u8 phase;
2616 u8 *data_buf;
2617 u8 tuned_phases[16], tuned_phase_cnt = 0;
2618 int rc = 0;
2619
2620 /* Tuning is only required for SDR50 & SDR104 modes */
2621 if (!host->tuning_needed) {
2622 rc = 0;
2623 goto out;
2624 }
2625
2626 host->cmd19_tuning_in_progress = 1;
2627 /*
2628 * Make sure that clock is always enabled when DLL
2629 * tuning is in progress. Keeping PWRSAVE ON may
2630 * turn off the clock. So let's disable the PWRSAVE
2631 * here and re-enable it once tuning is completed.
2632 */
2633 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2634 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2635 /* first of all reset the tuning block */
2636 rc = msmsdcc_init_cm_sdc4_dll(host);
2637 if (rc)
2638 goto out;
2639
2640 data_buf = kmalloc(64, GFP_KERNEL);
2641 if (!data_buf) {
2642 rc = -ENOMEM;
2643 goto out;
2644 }
2645
2646 phase = 0;
2647 do {
2648 struct mmc_command cmd = {0};
2649 struct mmc_data data = {0};
2650 struct mmc_request mrq = {
2651 .cmd = &cmd,
2652 .data = &data
2653 };
2654 struct scatterlist sg;
2655
2656 /* set the phase in delay line hw block */
2657 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2658 if (rc)
2659 goto kfree;
2660
2661 cmd.opcode = MMC_SEND_TUNING_BLOCK;
2662 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
2663
2664 data.blksz = 64;
2665 data.blocks = 1;
2666 data.flags = MMC_DATA_READ;
2667 data.timeout_ns = 1000 * 1000 * 1000; /* 1 sec */
2668
2669 data.sg = &sg;
2670 data.sg_len = 1;
2671 sg_init_one(&sg, data_buf, 64);
2672 memset(data_buf, 0, 64);
2673 mmc_wait_for_req(mmc, &mrq);
2674
2675 if (!cmd.error && !data.error &&
2676 !memcmp(data_buf, cmd19_tuning_block, 64)) {
2677 /* tuning is successful with this tuning point */
2678 tuned_phases[tuned_phase_cnt++] = phase;
2679 }
2680 } while (++phase < 16);
2681
2682 kfree(data_buf);
2683
2684 if (tuned_phase_cnt) {
2685 tuned_phase_cnt--;
2686 tuned_phase_cnt = (tuned_phase_cnt * 3) / 4;
2687 phase = tuned_phases[tuned_phase_cnt];
2688 /*
2689 * Finally set the selected phase in delay
2690 * line hw block.
2691 */
2692 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2693 if (rc)
2694 goto out;
2695 } else {
2696 /* tuning failed */
2697 rc = -EAGAIN;
2698 pr_err("%s: %s: no tuning point found",
2699 mmc_hostname(mmc), __func__);
2700 }
2701 goto out;
2702
2703kfree:
2704 kfree(data_buf);
2705out:
2706 /* re-enable PWESAVE */
2707 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2708 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2709 host->cmd19_tuning_in_progress = 0;
2710 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -07002711}
2712
2713static const struct mmc_host_ops msmsdcc_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002714 .enable = msmsdcc_enable,
2715 .disable = msmsdcc_disable,
San Mehat9d2bd732009-09-22 16:44:22 -07002716 .request = msmsdcc_request,
2717 .set_ios = msmsdcc_set_ios,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002718 .get_ro = msmsdcc_get_ro,
2719#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002720 .enable_sdio_irq = msmsdcc_enable_sdio_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002721#endif
2722 .start_signal_voltage_switch = msmsdcc_start_signal_voltage_switch,
2723 .execute_tuning = msmsdcc_execute_tuning
San Mehat9d2bd732009-09-22 16:44:22 -07002724};
2725
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002726static unsigned int
2727msmsdcc_slot_status(struct msmsdcc_host *host)
2728{
2729 int status;
2730 unsigned int gpio_no = host->plat->status_gpio;
2731
2732 status = gpio_request(gpio_no, "SD_HW_Detect");
2733 if (status) {
2734 pr_err("%s: %s: Failed to request GPIO %d\n",
2735 mmc_hostname(host->mmc), __func__, gpio_no);
2736 } else {
2737 status = gpio_direction_input(gpio_no);
2738 if (!status)
2739 status = !gpio_get_value_cansleep(gpio_no);
2740 gpio_free(gpio_no);
2741 }
2742 return status;
2743}
2744
San Mehat9d2bd732009-09-22 16:44:22 -07002745static void
2746msmsdcc_check_status(unsigned long data)
2747{
2748 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
2749 unsigned int status;
2750
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002751 if (host->plat->status || host->plat->status_gpio) {
2752 if (host->plat->status)
2753 status = host->plat->status(mmc_dev(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07002754 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002755 status = msmsdcc_slot_status(host);
2756
2757 host->eject = !status;
2758 if (status ^ host->oldstat) {
2759 pr_info("%s: Slot status change detected (%d -> %d)\n",
2760 mmc_hostname(host->mmc), host->oldstat, status);
San Mehat9d2bd732009-09-22 16:44:22 -07002761 mmc_detect_change(host->mmc, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002762 }
2763 host->oldstat = status;
2764 } else {
2765 mmc_detect_change(host->mmc, 0);
San Mehat9d2bd732009-09-22 16:44:22 -07002766 }
San Mehat9d2bd732009-09-22 16:44:22 -07002767}
2768
2769static irqreturn_t
2770msmsdcc_platform_status_irq(int irq, void *dev_id)
2771{
2772 struct msmsdcc_host *host = dev_id;
2773
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002774 pr_debug("%s: %d\n", __func__, irq);
San Mehat9d2bd732009-09-22 16:44:22 -07002775 msmsdcc_check_status((unsigned long) host);
2776 return IRQ_HANDLED;
2777}
2778
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002779static irqreturn_t
2780msmsdcc_platform_sdiowakeup_irq(int irq, void *dev_id)
2781{
2782 struct msmsdcc_host *host = dev_id;
2783
2784 pr_debug("%s: SDIO Wake up IRQ : %d\n", mmc_hostname(host->mmc), irq);
2785 spin_lock(&host->lock);
2786 if (!host->sdio_irq_disabled) {
2787 disable_irq_nosync(irq);
2788 if (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2789 wake_lock(&host->sdio_wlock);
2790 msmsdcc_disable_irq_wake(host);
2791 }
2792 host->sdio_irq_disabled = 1;
2793 }
2794 if (host->plat->is_sdio_al_client) {
2795 if (!host->clks_on) {
2796 msmsdcc_setup_clocks(host, true);
2797 host->clks_on = 1;
2798 }
2799 if (host->sdcc_irq_disabled) {
2800 writel_relaxed(host->mci_irqenable,
2801 host->base + MMCIMASK0);
2802 mb();
2803 enable_irq(host->core_irqres->start);
2804 host->sdcc_irq_disabled = 0;
2805 }
2806 wake_lock(&host->sdio_wlock);
2807 }
2808 spin_unlock(&host->lock);
2809
2810 return IRQ_HANDLED;
2811}
2812
San Mehat9d2bd732009-09-22 16:44:22 -07002813static void
2814msmsdcc_status_notify_cb(int card_present, void *dev_id)
2815{
2816 struct msmsdcc_host *host = dev_id;
2817
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002818 pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
San Mehat9d2bd732009-09-22 16:44:22 -07002819 card_present);
2820 msmsdcc_check_status((unsigned long) host);
2821}
2822
San Mehat9d2bd732009-09-22 16:44:22 -07002823static int
2824msmsdcc_init_dma(struct msmsdcc_host *host)
2825{
2826 memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data));
2827 host->dma.host = host;
2828 host->dma.channel = -1;
Krishna Konda25786ec2011-07-25 16:21:36 -07002829 host->dma.crci = -1;
San Mehat9d2bd732009-09-22 16:44:22 -07002830
2831 if (!host->dmares)
2832 return -ENODEV;
2833
2834 host->dma.nc = dma_alloc_coherent(NULL,
2835 sizeof(struct msmsdcc_nc_dmadata),
2836 &host->dma.nc_busaddr,
2837 GFP_KERNEL);
2838 if (host->dma.nc == NULL) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07002839 pr_err("Unable to allocate DMA buffer\n");
San Mehat9d2bd732009-09-22 16:44:22 -07002840 return -ENOMEM;
2841 }
2842 memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata));
2843 host->dma.cmd_busaddr = host->dma.nc_busaddr;
2844 host->dma.cmdptr_busaddr = host->dma.nc_busaddr +
2845 offsetof(struct msmsdcc_nc_dmadata, cmdptr);
2846 host->dma.channel = host->dmares->start;
Krishna Konda25786ec2011-07-25 16:21:36 -07002847 host->dma.crci = host->dma_crci_res->start;
San Mehat9d2bd732009-09-22 16:44:22 -07002848
2849 return 0;
2850}
2851
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002852#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
2853/**
2854 * Allocate and Connect a SDCC peripheral's SPS endpoint
2855 *
2856 * This function allocates endpoint context and
2857 * connect it with memory endpoint by calling
2858 * appropriate SPS driver APIs.
2859 *
2860 * Also registers a SPS callback function with
2861 * SPS driver
2862 *
2863 * This function should only be called once typically
2864 * during driver probe.
2865 *
2866 * @host - Pointer to sdcc host structure
2867 * @ep - Pointer to sps endpoint data structure
2868 * @is_produce - 1 means Producer endpoint
2869 * 0 means Consumer endpoint
2870 *
2871 * @return - 0 if successful else negative value.
2872 *
2873 */
2874static int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
2875 struct msmsdcc_sps_ep_conn_data *ep,
2876 bool is_producer)
2877{
2878 int rc = 0;
2879 struct sps_pipe *sps_pipe_handle;
2880 struct sps_connect *sps_config = &ep->config;
2881 struct sps_register_event *sps_event = &ep->event;
2882
2883 /* Allocate endpoint context */
2884 sps_pipe_handle = sps_alloc_endpoint();
2885 if (!sps_pipe_handle) {
2886 pr_err("%s: sps_alloc_endpoint() failed!!! is_producer=%d",
2887 mmc_hostname(host->mmc), is_producer);
2888 rc = -ENOMEM;
2889 goto out;
2890 }
2891
2892 /* Get default connection configuration for an endpoint */
2893 rc = sps_get_config(sps_pipe_handle, sps_config);
2894 if (rc) {
2895 pr_err("%s: sps_get_config() failed!!! pipe_handle=0x%x,"
2896 " rc=%d", mmc_hostname(host->mmc),
2897 (u32)sps_pipe_handle, rc);
2898 goto get_config_err;
2899 }
2900
2901 /* Modify the default connection configuration */
2902 if (is_producer) {
2903 /*
2904 * For SDCC producer transfer, source should be
2905 * SDCC peripheral where as destination should
2906 * be system memory.
2907 */
2908 sps_config->source = host->sps.bam_handle;
2909 sps_config->destination = SPS_DEV_HANDLE_MEM;
2910 /* Producer pipe will handle this connection */
2911 sps_config->mode = SPS_MODE_SRC;
2912 sps_config->options =
2913 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2914 } else {
2915 /*
2916 * For SDCC consumer transfer, source should be
2917 * system memory where as destination should
2918 * SDCC peripheral
2919 */
2920 sps_config->source = SPS_DEV_HANDLE_MEM;
2921 sps_config->destination = host->sps.bam_handle;
2922 sps_config->mode = SPS_MODE_DEST;
2923 sps_config->options =
2924 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2925 }
2926
2927 /* Producer pipe index */
2928 sps_config->src_pipe_index = host->sps.src_pipe_index;
2929 /* Consumer pipe index */
2930 sps_config->dest_pipe_index = host->sps.dest_pipe_index;
2931 /*
2932 * This event thresold value is only significant for BAM-to-BAM
2933 * transfer. It's ignored for BAM-to-System mode transfer.
2934 */
2935 sps_config->event_thresh = 0x10;
2936 /*
2937 * Max. no of scatter/gather buffers that can
2938 * be passed by block layer = 32 (NR_SG).
2939 * Each BAM descritor needs 64 bits (8 bytes).
2940 * One BAM descriptor is required per buffer transfer.
2941 * So we would require total 256 (32 * 8) bytes of descriptor FIFO.
2942 * But due to HW limitation we need to allocate atleast one extra
2943 * descriptor memory (256 bytes + 8 bytes). But in order to be
2944 * in power of 2, we are allocating 512 bytes of memory.
2945 */
2946 sps_config->desc.size = 512;
2947 sps_config->desc.base = dma_alloc_coherent(mmc_dev(host->mmc),
2948 sps_config->desc.size,
2949 &sps_config->desc.phys_base,
2950 GFP_KERNEL);
2951
2952 memset(sps_config->desc.base, 0x00, sps_config->desc.size);
2953
2954 /* Establish connection between peripheral and memory endpoint */
2955 rc = sps_connect(sps_pipe_handle, sps_config);
2956 if (rc) {
2957 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2958 " rc=%d", mmc_hostname(host->mmc),
2959 (u32)sps_pipe_handle, rc);
2960 goto sps_connect_err;
2961 }
2962
2963 sps_event->mode = SPS_TRIGGER_CALLBACK;
2964 sps_event->options = SPS_O_EOT;
2965 sps_event->callback = msmsdcc_sps_complete_cb;
2966 sps_event->xfer_done = NULL;
2967 sps_event->user = (void *)host;
2968
2969 /* Register callback event for EOT (End of transfer) event. */
2970 rc = sps_register_event(sps_pipe_handle, sps_event);
2971 if (rc) {
2972 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2973 " rc=%d", mmc_hostname(host->mmc),
2974 (u32)sps_pipe_handle, rc);
2975 goto reg_event_err;
2976 }
2977 /* Now save the sps pipe handle */
2978 ep->pipe_handle = sps_pipe_handle;
2979 pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"
2980 " desc_fifo.phys_base=0x%x\n", mmc_hostname(host->mmc),
2981 __func__, is_producer ? "READ" : "WRITE",
2982 (u32)sps_pipe_handle, sps_config->desc.phys_base);
2983 goto out;
2984
2985reg_event_err:
2986 sps_disconnect(sps_pipe_handle);
2987sps_connect_err:
2988 dma_free_coherent(mmc_dev(host->mmc),
2989 sps_config->desc.size,
2990 sps_config->desc.base,
2991 sps_config->desc.phys_base);
2992get_config_err:
2993 sps_free_endpoint(sps_pipe_handle);
2994out:
2995 return rc;
2996}
2997
2998/**
2999 * Disconnect and Deallocate a SDCC peripheral's SPS endpoint
3000 *
3001 * This function disconnect endpoint and deallocates
3002 * endpoint context.
3003 *
3004 * This function should only be called once typically
3005 * during driver remove.
3006 *
3007 * @host - Pointer to sdcc host structure
3008 * @ep - Pointer to sps endpoint data structure
3009 *
3010 */
3011static void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
3012 struct msmsdcc_sps_ep_conn_data *ep)
3013{
3014 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
3015 struct sps_connect *sps_config = &ep->config;
3016 struct sps_register_event *sps_event = &ep->event;
3017
3018 sps_event->xfer_done = NULL;
3019 sps_event->callback = NULL;
3020 sps_register_event(sps_pipe_handle, sps_event);
3021 sps_disconnect(sps_pipe_handle);
3022 dma_free_coherent(mmc_dev(host->mmc),
3023 sps_config->desc.size,
3024 sps_config->desc.base,
3025 sps_config->desc.phys_base);
3026 sps_free_endpoint(sps_pipe_handle);
3027}
3028
3029/**
3030 * Reset SDCC peripheral's SPS endpoint
3031 *
3032 * This function disconnects an endpoint.
3033 *
3034 * This function should be called for reseting
3035 * SPS endpoint when data transfer error is
3036 * encountered during data transfer. This
3037 * can be considered as soft reset to endpoint.
3038 *
3039 * This function should only be called if
3040 * msmsdcc_sps_init() is already called.
3041 *
3042 * @host - Pointer to sdcc host structure
3043 * @ep - Pointer to sps endpoint data structure
3044 *
3045 * @return - 0 if successful else negative value.
3046 */
3047static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
3048 struct msmsdcc_sps_ep_conn_data *ep)
3049{
3050 int rc = 0;
3051 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
3052
3053 rc = sps_disconnect(sps_pipe_handle);
3054 if (rc) {
3055 pr_err("%s: %s: sps_disconnect() failed!!! pipe_handle=0x%x,"
3056 " rc=%d", mmc_hostname(host->mmc), __func__,
3057 (u32)sps_pipe_handle, rc);
3058 goto out;
3059 }
3060 out:
3061 return rc;
3062}
3063
3064/**
3065 * Restore SDCC peripheral's SPS endpoint
3066 *
3067 * This function connects an endpoint.
3068 *
3069 * This function should be called for restoring
3070 * SPS endpoint after data transfer error is
3071 * encountered during data transfer. This
3072 * can be considered as soft reset to endpoint.
3073 *
3074 * This function should only be called if
3075 * msmsdcc_sps_reset_ep() is called before.
3076 *
3077 * @host - Pointer to sdcc host structure
3078 * @ep - Pointer to sps endpoint data structure
3079 *
3080 * @return - 0 if successful else negative value.
3081 */
3082static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
3083 struct msmsdcc_sps_ep_conn_data *ep)
3084{
3085 int rc = 0;
3086 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
3087 struct sps_connect *sps_config = &ep->config;
3088 struct sps_register_event *sps_event = &ep->event;
3089
3090 /* Establish connection between peripheral and memory endpoint */
3091 rc = sps_connect(sps_pipe_handle, sps_config);
3092 if (rc) {
3093 pr_err("%s: %s: sps_connect() failed!!! pipe_handle=0x%x,"
3094 " rc=%d", mmc_hostname(host->mmc), __func__,
3095 (u32)sps_pipe_handle, rc);
3096 goto out;
3097 }
3098
3099 /* Register callback event for EOT (End of transfer) event. */
3100 rc = sps_register_event(sps_pipe_handle, sps_event);
3101 if (rc) {
3102 pr_err("%s: %s: sps_register_event() failed!!!"
3103 " pipe_handle=0x%x, rc=%d",
3104 mmc_hostname(host->mmc), __func__,
3105 (u32)sps_pipe_handle, rc);
3106 goto reg_event_err;
3107 }
3108 goto out;
3109
3110reg_event_err:
3111 sps_disconnect(sps_pipe_handle);
3112out:
3113 return rc;
3114}
3115
3116/**
3117 * Initialize SPS HW connected with SDCC core
3118 *
3119 * This function register BAM HW resources with
3120 * SPS driver and then initialize 2 SPS endpoints
3121 *
3122 * This function should only be called once typically
3123 * during driver probe.
3124 *
3125 * @host - Pointer to sdcc host structure
3126 *
3127 * @return - 0 if successful else negative value.
3128 *
3129 */
3130static int msmsdcc_sps_init(struct msmsdcc_host *host)
3131{
3132 int rc = 0;
3133 struct sps_bam_props bam = {0};
3134
3135 host->bam_base = ioremap(host->bam_memres->start,
3136 resource_size(host->bam_memres));
3137 if (!host->bam_base) {
3138 pr_err("%s: BAM ioremap() failed!!! phys_addr=0x%x,"
3139 " size=0x%x", mmc_hostname(host->mmc),
3140 host->bam_memres->start,
3141 (host->bam_memres->end -
3142 host->bam_memres->start));
3143 rc = -ENOMEM;
3144 goto out;
3145 }
3146
3147 bam.phys_addr = host->bam_memres->start;
3148 bam.virt_addr = host->bam_base;
3149 /*
3150 * This event thresold value is only significant for BAM-to-BAM
3151 * transfer. It's ignored for BAM-to-System mode transfer.
3152 */
3153 bam.event_threshold = 0x10; /* Pipe event threshold */
3154 /*
3155 * This threshold controls when the BAM publish
3156 * the descriptor size on the sideband interface.
3157 * SPS HW will only be used when
3158 * data transfer size > MCI_FIFOSIZE (64 bytes).
3159 * PIO mode will be used when
3160 * data transfer size < MCI_FIFOSIZE (64 bytes).
3161 * So set this thresold value to 64 bytes.
3162 */
3163 bam.summing_threshold = 64;
3164 /* SPS driver wll handle the SDCC BAM IRQ */
3165 bam.irq = (u32)host->bam_irqres->start;
3166 bam.manage = SPS_BAM_MGR_LOCAL;
3167
3168 pr_info("%s: bam physical base=0x%x\n", mmc_hostname(host->mmc),
3169 (u32)bam.phys_addr);
3170 pr_info("%s: bam virtual base=0x%x\n", mmc_hostname(host->mmc),
3171 (u32)bam.virt_addr);
3172
3173 /* Register SDCC Peripheral BAM device to SPS driver */
3174 rc = sps_register_bam_device(&bam, &host->sps.bam_handle);
3175 if (rc) {
3176 pr_err("%s: sps_register_bam_device() failed!!! err=%d",
3177 mmc_hostname(host->mmc), rc);
3178 goto reg_bam_err;
3179 }
3180 pr_info("%s: BAM device registered. bam_handle=0x%x",
3181 mmc_hostname(host->mmc), host->sps.bam_handle);
3182
3183 host->sps.src_pipe_index = SPS_SDCC_PRODUCER_PIPE_INDEX;
3184 host->sps.dest_pipe_index = SPS_SDCC_CONSUMER_PIPE_INDEX;
3185
3186 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.prod,
3187 SPS_PROD_PERIPHERAL);
3188 if (rc)
3189 goto sps_reset_err;
3190 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.cons,
3191 SPS_CONS_PERIPHERAL);
3192 if (rc)
3193 goto cons_conn_err;
3194
3195 pr_info("%s: Qualcomm MSM SDCC-BAM at 0x%016llx irq %d\n",
3196 mmc_hostname(host->mmc),
3197 (unsigned long long)host->bam_memres->start,
3198 (unsigned int)host->bam_irqres->start);
3199 goto out;
3200
3201cons_conn_err:
3202 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3203sps_reset_err:
3204 sps_deregister_bam_device(host->sps.bam_handle);
3205reg_bam_err:
3206 iounmap(host->bam_base);
3207out:
3208 return rc;
3209}
3210
3211/**
3212 * De-initialize SPS HW connected with SDCC core
3213 *
3214 * This function deinitialize SPS endpoints and then
3215 * deregisters BAM resources from SPS driver.
3216 *
3217 * This function should only be called once typically
3218 * during driver remove.
3219 *
3220 * @host - Pointer to sdcc host structure
3221 *
3222 */
3223static void msmsdcc_sps_exit(struct msmsdcc_host *host)
3224{
3225 msmsdcc_sps_exit_ep_conn(host, &host->sps.cons);
3226 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3227 sps_deregister_bam_device(host->sps.bam_handle);
3228 iounmap(host->bam_base);
3229}
3230#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
3231
3232static ssize_t
3233show_polling(struct device *dev, struct device_attribute *attr, char *buf)
3234{
3235 struct mmc_host *mmc = dev_get_drvdata(dev);
3236 struct msmsdcc_host *host = mmc_priv(mmc);
3237 int poll;
3238 unsigned long flags;
3239
3240 spin_lock_irqsave(&host->lock, flags);
3241 poll = !!(mmc->caps & MMC_CAP_NEEDS_POLL);
3242 spin_unlock_irqrestore(&host->lock, flags);
3243
3244 return snprintf(buf, PAGE_SIZE, "%d\n", poll);
3245}
3246
3247static ssize_t
3248set_polling(struct device *dev, struct device_attribute *attr,
3249 const char *buf, size_t count)
3250{
3251 struct mmc_host *mmc = dev_get_drvdata(dev);
3252 struct msmsdcc_host *host = mmc_priv(mmc);
3253 int value;
3254 unsigned long flags;
3255
3256 sscanf(buf, "%d", &value);
3257
3258 spin_lock_irqsave(&host->lock, flags);
3259 if (value) {
3260 mmc->caps |= MMC_CAP_NEEDS_POLL;
3261 mmc_detect_change(host->mmc, 0);
3262 } else {
3263 mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3264 }
3265#ifdef CONFIG_HAS_EARLYSUSPEND
3266 host->polling_enabled = mmc->caps & MMC_CAP_NEEDS_POLL;
3267#endif
3268 spin_unlock_irqrestore(&host->lock, flags);
3269 return count;
3270}
3271
3272static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR,
3273 show_polling, set_polling);
3274static struct attribute *dev_attrs[] = {
3275 &dev_attr_polling.attr,
3276 NULL,
3277};
3278static struct attribute_group dev_attr_grp = {
3279 .attrs = dev_attrs,
3280};
3281
3282#ifdef CONFIG_HAS_EARLYSUSPEND
3283static void msmsdcc_early_suspend(struct early_suspend *h)
3284{
3285 struct msmsdcc_host *host =
3286 container_of(h, struct msmsdcc_host, early_suspend);
3287 unsigned long flags;
3288
3289 spin_lock_irqsave(&host->lock, flags);
3290 host->polling_enabled = host->mmc->caps & MMC_CAP_NEEDS_POLL;
3291 host->mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3292 spin_unlock_irqrestore(&host->lock, flags);
3293};
3294static void msmsdcc_late_resume(struct early_suspend *h)
3295{
3296 struct msmsdcc_host *host =
3297 container_of(h, struct msmsdcc_host, early_suspend);
3298 unsigned long flags;
3299
3300 if (host->polling_enabled) {
3301 spin_lock_irqsave(&host->lock, flags);
3302 host->mmc->caps |= MMC_CAP_NEEDS_POLL;
3303 mmc_detect_change(host->mmc, 0);
3304 spin_unlock_irqrestore(&host->lock, flags);
3305 }
3306};
3307#endif
3308
3309static void msmsdcc_req_tout_timer_hdlr(unsigned long data)
3310{
3311 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
3312 struct mmc_request *mrq;
3313 unsigned long flags;
3314
3315 spin_lock_irqsave(&host->lock, flags);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003316 if (host->dummy_52_sent) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003317 pr_info("%s: %s: dummy CMD52 timeout\n",
3318 mmc_hostname(host->mmc), __func__);
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003319 host->dummy_52_sent = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003320 }
3321
3322 mrq = host->curr.mrq;
3323
3324 if (mrq && mrq->cmd) {
3325 pr_info("%s: %s CMD%d\n", mmc_hostname(host->mmc),
3326 __func__, mrq->cmd->opcode);
3327 if (!mrq->cmd->error)
3328 mrq->cmd->error = -ETIMEDOUT;
Oluwafemi Adeyemicb791442011-07-11 22:51:25 -07003329 if (host->dummy_52_needed)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003330 host->dummy_52_needed = 0;
3331 if (host->curr.data) {
3332 pr_info("%s: %s Request timeout\n",
3333 mmc_hostname(host->mmc), __func__);
3334 if (mrq->data && !mrq->data->error)
3335 mrq->data->error = -ETIMEDOUT;
3336 host->curr.data_xfered = 0;
3337 if (host->dma.sg && host->is_dma_mode) {
3338 msm_dmov_stop_cmd(host->dma.channel,
3339 &host->dma.hdr, 0);
3340 } else if (host->sps.sg && host->is_sps_mode) {
3341 /* Stop current SPS transfer */
3342 msmsdcc_sps_exit_curr_xfer(host);
3343 } else {
3344 msmsdcc_reset_and_restore(host);
3345 msmsdcc_stop_data(host);
3346 if (mrq->data && mrq->data->stop)
3347 msmsdcc_start_command(host,
3348 mrq->data->stop, 0);
3349 else
3350 msmsdcc_request_end(host, mrq);
3351 }
3352 } else {
3353 if (host->prog_enable) {
3354 host->prog_scan = 0;
3355 host->prog_enable = 0;
3356 }
3357 msmsdcc_reset_and_restore(host);
3358 msmsdcc_request_end(host, mrq);
3359 }
3360 }
3361 spin_unlock_irqrestore(&host->lock, flags);
3362}
3363
San Mehat9d2bd732009-09-22 16:44:22 -07003364static int
3365msmsdcc_probe(struct platform_device *pdev)
3366{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003367 struct mmc_platform_data *plat = pdev->dev.platform_data;
San Mehat9d2bd732009-09-22 16:44:22 -07003368 struct msmsdcc_host *host;
3369 struct mmc_host *mmc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003370 unsigned long flags;
3371 struct resource *core_irqres = NULL;
3372 struct resource *bam_irqres = NULL;
3373 struct resource *core_memres = NULL;
3374 struct resource *dml_memres = NULL;
3375 struct resource *bam_memres = NULL;
San Mehat9d2bd732009-09-22 16:44:22 -07003376 struct resource *dmares = NULL;
Krishna Konda25786ec2011-07-25 16:21:36 -07003377 struct resource *dma_crci_res = NULL;
San Mehat9d2bd732009-09-22 16:44:22 -07003378 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003379 int i;
San Mehat9d2bd732009-09-22 16:44:22 -07003380
3381 /* must have platform data */
3382 if (!plat) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003383 pr_err("%s: Platform data not available\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003384 ret = -EINVAL;
3385 goto out;
3386 }
3387
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003388 if (pdev->id < 1 || pdev->id > 5)
San Mehat9d2bd732009-09-22 16:44:22 -07003389 return -EINVAL;
3390
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003391 if (plat->is_sdio_al_client)
3392 if (!plat->sdio_lpm_gpio_setup || !plat->sdiowakeup_irq)
3393 return -EINVAL;
3394
San Mehat9d2bd732009-09-22 16:44:22 -07003395 if (pdev->resource == NULL || pdev->num_resources < 2) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003396 pr_err("%s: Invalid resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003397 return -ENXIO;
3398 }
3399
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003400 for (i = 0; i < pdev->num_resources; i++) {
3401 if (pdev->resource[i].flags & IORESOURCE_MEM) {
3402 if (!strcmp(pdev->resource[i].name,
3403 "sdcc_dml_addr"))
3404 dml_memres = &pdev->resource[i];
3405 else if (!strcmp(pdev->resource[i].name,
3406 "sdcc_bam_addr"))
3407 bam_memres = &pdev->resource[i];
3408 else
3409 core_memres = &pdev->resource[i];
San Mehat9d2bd732009-09-22 16:44:22 -07003410
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003411 }
3412 if (pdev->resource[i].flags & IORESOURCE_IRQ) {
3413 if (!strcmp(pdev->resource[i].name,
3414 "sdcc_bam_irq"))
3415 bam_irqres = &pdev->resource[i];
3416 else
3417 core_irqres = &pdev->resource[i];
3418 }
Krishna Konda25786ec2011-07-25 16:21:36 -07003419 if (pdev->resource[i].flags & IORESOURCE_DMA) {
3420 if (!strncmp(pdev->resource[i].name,
3421 "sdcc_dma_chnl",
3422 sizeof("sdcc_dma_chnl")))
3423 dmares = &pdev->resource[i];
3424 else if (!strncmp(pdev->resource[i].name,
3425 "sdcc_dma_crci",
3426 sizeof("sdcc_dma_crci")))
3427 dma_crci_res = &pdev->resource[i];
3428 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003429 }
3430
3431 if (!core_irqres || !core_memres) {
3432 pr_err("%s: Invalid sdcc core resource\n", __func__);
3433 return -ENXIO;
3434 }
3435
3436 /*
3437 * Both BAM and DML memory resource should be preset.
3438 * BAM IRQ resource should also be present.
3439 */
3440 if ((bam_memres && !dml_memres) ||
3441 (!bam_memres && dml_memres) ||
3442 ((bam_memres && dml_memres) && !bam_irqres)) {
3443 pr_err("%s: Invalid sdcc BAM/DML resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003444 return -ENXIO;
3445 }
3446
3447 /*
3448 * Setup our host structure
3449 */
San Mehat9d2bd732009-09-22 16:44:22 -07003450 mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev);
3451 if (!mmc) {
3452 ret = -ENOMEM;
3453 goto out;
3454 }
3455
3456 host = mmc_priv(mmc);
3457 host->pdev_id = pdev->id;
3458 host->plat = plat;
3459 host->mmc = mmc;
San Mehat56a8b5b2009-11-21 12:29:46 -08003460 host->curr.cmd = NULL;
Sahitya Tummalad9df3272011-08-19 16:50:46 +05303461
3462 if (!plat->disable_bam && bam_memres && dml_memres && bam_irqres)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003463 host->is_sps_mode = 1;
3464 else if (dmares)
3465 host->is_dma_mode = 1;
San Mehat9d2bd732009-09-22 16:44:22 -07003466
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003467 host->base = ioremap(core_memres->start,
3468 resource_size(core_memres));
San Mehat9d2bd732009-09-22 16:44:22 -07003469 if (!host->base) {
3470 ret = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003471 goto host_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003472 }
3473
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003474 host->core_irqres = core_irqres;
3475 host->bam_irqres = bam_irqres;
3476 host->core_memres = core_memres;
3477 host->dml_memres = dml_memres;
3478 host->bam_memres = bam_memres;
San Mehat9d2bd732009-09-22 16:44:22 -07003479 host->dmares = dmares;
Krishna Konda25786ec2011-07-25 16:21:36 -07003480 host->dma_crci_res = dma_crci_res;
San Mehat9d2bd732009-09-22 16:44:22 -07003481 spin_lock_init(&host->lock);
3482
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003483#ifdef CONFIG_MMC_EMBEDDED_SDIO
3484 if (plat->embedded_sdio)
3485 mmc_set_embedded_sdio_data(mmc,
3486 &plat->embedded_sdio->cis,
3487 &plat->embedded_sdio->cccr,
3488 plat->embedded_sdio->funcs,
3489 plat->embedded_sdio->num_funcs);
3490#endif
3491
Sahitya Tummala62612cf2010-12-08 15:03:03 +05303492 tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
3493 (unsigned long)host);
3494
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003495 tasklet_init(&host->sps.tlet, msmsdcc_sps_complete_tlet,
3496 (unsigned long)host);
3497 if (host->is_dma_mode) {
3498 /* Setup DMA */
3499 ret = msmsdcc_init_dma(host);
3500 if (ret)
3501 goto ioremap_free;
3502 } else {
3503 host->dma.channel = -1;
Krishna Konda25786ec2011-07-25 16:21:36 -07003504 host->dma.crci = -1;
San Mehat9d2bd732009-09-22 16:44:22 -07003505 }
3506
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003507 /*
3508 * Setup SDCC clock if derived from Dayatona
3509 * fabric core clock.
3510 */
3511 if (plat->pclk_src_dfab) {
Matt Wagantall37ce3842011-08-17 16:00:36 -07003512 host->dfab_pclk = clk_get(&pdev->dev, "bus_clk");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003513 if (!IS_ERR(host->dfab_pclk)) {
3514 /* Set the clock rate to 64MHz for max. performance */
3515 ret = clk_set_rate(host->dfab_pclk, 64000000);
3516 if (ret)
3517 goto dfab_pclk_put;
3518 ret = clk_enable(host->dfab_pclk);
3519 if (ret)
3520 goto dfab_pclk_put;
3521 } else
3522 goto dma_free;
3523 }
3524
3525 /*
3526 * Setup main peripheral bus clock
3527 */
Matt Wagantall37ce3842011-08-17 16:00:36 -07003528 host->pclk = clk_get(&pdev->dev, "iface_clk");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003529 if (!IS_ERR(host->pclk)) {
3530 ret = clk_enable(host->pclk);
3531 if (ret)
3532 goto pclk_put;
3533
3534 host->pclk_rate = clk_get_rate(host->pclk);
3535 }
3536
3537 /*
3538 * Setup SDC MMC clock
3539 */
Matt Wagantall37ce3842011-08-17 16:00:36 -07003540 host->clk = clk_get(&pdev->dev, "core_clk");
San Mehat9d2bd732009-09-22 16:44:22 -07003541 if (IS_ERR(host->clk)) {
3542 ret = PTR_ERR(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003543 goto pclk_disable;
San Mehat9d2bd732009-09-22 16:44:22 -07003544 }
3545
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003546 ret = clk_set_rate(host->clk, msmsdcc_get_min_sup_clk_rate(host));
3547 if (ret) {
3548 pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
3549 goto clk_put;
3550 }
3551
3552 ret = clk_enable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003553 if (ret)
3554 goto clk_put;
3555
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003556 host->clk_rate = clk_get_rate(host->clk);
3557
3558 host->clks_on = 1;
3559
3560 ret = msmsdcc_vreg_init(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07003561 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003562 pr_err("%s: msmsdcc_vreg_init() failed (%d)\n", __func__, ret);
San Mehat9d2bd732009-09-22 16:44:22 -07003563 goto clk_disable;
3564 }
3565
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003566
3567 /* Clocks has to be running before accessing SPS/DML HW blocks */
3568 if (host->is_sps_mode) {
3569 /* Initialize SPS */
3570 ret = msmsdcc_sps_init(host);
3571 if (ret)
3572 goto vreg_deinit;
3573 /* Initialize DML */
3574 ret = msmsdcc_dml_init(host);
3575 if (ret)
3576 goto sps_exit;
3577 }
San Mehat9d2bd732009-09-22 16:44:22 -07003578
San Mehat9d2bd732009-09-22 16:44:22 -07003579 /*
3580 * Setup MMC host structure
3581 */
3582 mmc->ops = &msmsdcc_ops;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003583 mmc->f_min = msmsdcc_get_min_sup_clk_rate(host);
3584 mmc->f_max = msmsdcc_get_max_sup_clk_rate(host);
San Mehat9d2bd732009-09-22 16:44:22 -07003585 mmc->ocr_avail = plat->ocr_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003586 mmc->pm_caps |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
3587 mmc->caps |= plat->mmc_bus_width;
San Mehat9d2bd732009-09-22 16:44:22 -07003588
San Mehat9d2bd732009-09-22 16:44:22 -07003589 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003590 mmc->caps |= plat->uhs_caps;
3591 /*
3592 * XPC controls the maximum current in the default speed mode of SDXC
3593 * card. XPC=0 means 100mA (max.) but speed class is not supported.
3594 * XPC=1 means 150mA (max.) and speed class is supported.
3595 */
3596 if (plat->xpc_cap)
3597 mmc->caps |= (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
3598 MMC_CAP_SET_XPC_180);
3599
3600 if (plat->nonremovable)
3601 mmc->caps |= MMC_CAP_NONREMOVABLE;
3602#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
3603 mmc->caps |= MMC_CAP_SDIO_IRQ;
3604#endif
3605
3606 if (plat->is_sdio_al_client)
3607 mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
San Mehat9d2bd732009-09-22 16:44:22 -07003608
Martin K. Petersena36274e2010-09-10 01:33:59 -04003609 mmc->max_segs = NR_SG;
San Mehat9d2bd732009-09-22 16:44:22 -07003610 mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003611 mmc->max_blk_count = 65535;
San Mehat9d2bd732009-09-22 16:44:22 -07003612
3613 mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */
3614 mmc->max_seg_size = mmc->max_req_size;
3615
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003616 writel_relaxed(0, host->base + MMCIMASK0);
3617 writel_relaxed(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
San Mehat9d2bd732009-09-22 16:44:22 -07003618
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003619 /* Delay needed (MMCIMASK0 was just written above) */
3620 msmsdcc_delay(host);
3621 writel_relaxed(MCI_IRQENABLE, host->base + MMCIMASK0);
3622 mb();
3623 host->mci_irqenable = MCI_IRQENABLE;
San Mehat9d2bd732009-09-22 16:44:22 -07003624
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003625 ret = request_irq(core_irqres->start, msmsdcc_irq, IRQF_SHARED,
3626 DRIVER_NAME " (cmd)", host);
3627 if (ret)
3628 goto dml_exit;
3629
3630 ret = request_irq(core_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
3631 DRIVER_NAME " (pio)", host);
3632 if (ret)
3633 goto irq_free;
3634
3635 /*
3636 * Enable SDCC IRQ only when host is powered on. Otherwise, this
3637 * IRQ is un-necessarily being monitored by MPM (Modem power
3638 * management block) during idle-power collapse. The MPM will be
3639 * configured to monitor the DATA1 GPIO line with level-low trigger
3640 * and thus depending on the GPIO status, it prevents TCXO shutdown
3641 * during idle-power collapse.
3642 */
3643 disable_irq(core_irqres->start);
3644 host->sdcc_irq_disabled = 1;
3645
3646 if (plat->sdiowakeup_irq) {
3647 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3648 mmc_hostname(mmc));
3649 ret = request_irq(plat->sdiowakeup_irq,
3650 msmsdcc_platform_sdiowakeup_irq,
3651 IRQF_SHARED | IRQF_TRIGGER_LOW,
3652 DRIVER_NAME "sdiowakeup", host);
3653 if (ret) {
3654 pr_err("Unable to get sdio wakeup IRQ %d (%d)\n",
3655 plat->sdiowakeup_irq, ret);
3656 goto pio_irq_free;
3657 } else {
3658 spin_lock_irqsave(&host->lock, flags);
3659 if (!host->sdio_irq_disabled) {
3660 disable_irq_nosync(plat->sdiowakeup_irq);
3661 host->sdio_irq_disabled = 1;
3662 }
3663 spin_unlock_irqrestore(&host->lock, flags);
3664 }
3665 }
3666
3667 if (plat->cfg_mpm_sdiowakeup) {
3668 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3669 mmc_hostname(mmc));
3670 }
3671
3672 wake_lock_init(&host->sdio_suspend_wlock, WAKE_LOCK_SUSPEND,
3673 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003674 /*
3675 * Setup card detect change
3676 */
3677
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003678 if (plat->status || plat->status_gpio) {
3679 if (plat->status)
3680 host->oldstat = plat->status(mmc_dev(host->mmc));
3681 else
3682 host->oldstat = msmsdcc_slot_status(host);
3683 host->eject = !host->oldstat;
3684 }
San Mehat9d2bd732009-09-22 16:44:22 -07003685
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003686 if (plat->status_irq) {
3687 ret = request_threaded_irq(plat->status_irq, NULL,
San Mehat9d2bd732009-09-22 16:44:22 -07003688 msmsdcc_platform_status_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003689 plat->irq_flags,
San Mehat9d2bd732009-09-22 16:44:22 -07003690 DRIVER_NAME " (slot)",
3691 host);
3692 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003693 pr_err("Unable to get slot IRQ %d (%d)\n",
3694 plat->status_irq, ret);
3695 goto sdiowakeup_irq_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003696 }
3697 } else if (plat->register_status_notify) {
3698 plat->register_status_notify(msmsdcc_status_notify_cb, host);
3699 } else if (!plat->status)
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003700 pr_err("%s: No card detect facilities available\n",
San Mehat9d2bd732009-09-22 16:44:22 -07003701 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003702
3703 mmc_set_drvdata(pdev, mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003704
3705 ret = pm_runtime_set_active(&(pdev)->dev);
3706 if (ret < 0)
3707 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
3708 __func__, ret);
3709 /*
3710 * There is no notion of suspend/resume for SD/MMC/SDIO
3711 * cards. So host can be suspended/resumed with out
3712 * worrying about its children.
3713 */
3714 pm_suspend_ignore_children(&(pdev)->dev, true);
3715
3716 /*
3717 * MMC/SD/SDIO bus suspend/resume operations are defined
3718 * only for the slots that will be used for non-removable
3719 * media or for all slots when CONFIG_MMC_UNSAFE_RESUME is
3720 * defined. Otherwise, they simply become card removal and
3721 * insertion events during suspend and resume respectively.
3722 * Hence, enable run-time PM only for slots for which bus
3723 * suspend/resume operations are defined.
3724 */
3725#ifdef CONFIG_MMC_UNSAFE_RESUME
3726 /*
3727 * If this capability is set, MMC core will enable/disable host
3728 * for every claim/release operation on a host. We use this
3729 * notification to increment/decrement runtime pm usage count.
3730 */
3731 mmc->caps |= MMC_CAP_DISABLE;
3732 pm_runtime_enable(&(pdev)->dev);
3733#else
3734 if (mmc->caps & MMC_CAP_NONREMOVABLE) {
3735 mmc->caps |= MMC_CAP_DISABLE;
3736 pm_runtime_enable(&(pdev)->dev);
3737 }
3738#endif
3739 setup_timer(&host->req_tout_timer, msmsdcc_req_tout_timer_hdlr,
3740 (unsigned long)host);
3741
San Mehat9d2bd732009-09-22 16:44:22 -07003742 mmc_add_host(mmc);
3743
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003744#ifdef CONFIG_HAS_EARLYSUSPEND
3745 host->early_suspend.suspend = msmsdcc_early_suspend;
3746 host->early_suspend.resume = msmsdcc_late_resume;
3747 host->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
3748 register_early_suspend(&host->early_suspend);
3749#endif
San Mehat9d2bd732009-09-22 16:44:22 -07003750
Krishna Konda25786ec2011-07-25 16:21:36 -07003751 pr_info("%s: Qualcomm MSM SDCC-core at 0x%016llx irq %d,%d dma %d"
3752 " dmacrcri %d\n", mmc_hostname(mmc),
3753 (unsigned long long)core_memres->start,
3754 (unsigned int) core_irqres->start,
3755 (unsigned int) plat->status_irq, host->dma.channel,
3756 host->dma.crci);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003757
3758 pr_info("%s: 8 bit data mode %s\n", mmc_hostname(mmc),
3759 (mmc->caps & MMC_CAP_8_BIT_DATA ? "enabled" : "disabled"));
3760 pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc),
3761 (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled"));
3762 pr_info("%s: polling status mode %s\n", mmc_hostname(mmc),
3763 (mmc->caps & MMC_CAP_NEEDS_POLL ? "enabled" : "disabled"));
3764 pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n",
3765 mmc_hostname(mmc), msmsdcc_get_min_sup_clk_rate(host),
3766 msmsdcc_get_max_sup_clk_rate(host), host->pclk_rate);
3767 pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc),
3768 host->eject);
3769 pr_info("%s: Power save feature enable = %d\n",
3770 mmc_hostname(mmc), msmsdcc_pwrsave);
3771
Krishna Konda25786ec2011-07-25 16:21:36 -07003772 if (host->is_dma_mode && host->dma.channel != -1
3773 && host->dma.crci != -1) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003774 pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003775 mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003776 pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003777 mmc_hostname(mmc), host->dma.cmd_busaddr,
3778 host->dma.cmdptr_busaddr);
3779 } else if (host->is_sps_mode) {
3780 pr_info("%s: SPS-BAM data transfer mode available\n",
3781 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003782 } else
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003783 pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003784
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003785#if defined(CONFIG_DEBUG_FS)
3786 msmsdcc_dbg_createhost(host);
3787#endif
3788 if (!plat->status_irq) {
3789 ret = sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);
3790 if (ret)
3791 goto platform_irq_free;
3792 }
San Mehat9d2bd732009-09-22 16:44:22 -07003793 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003794
3795 platform_irq_free:
3796 del_timer_sync(&host->req_tout_timer);
3797 pm_runtime_disable(&(pdev)->dev);
3798 pm_runtime_set_suspended(&(pdev)->dev);
3799
3800 if (plat->status_irq)
3801 free_irq(plat->status_irq, host);
3802 sdiowakeup_irq_free:
3803 wake_lock_destroy(&host->sdio_suspend_wlock);
3804 if (plat->sdiowakeup_irq)
3805 free_irq(plat->sdiowakeup_irq, host);
3806 pio_irq_free:
3807 if (plat->sdiowakeup_irq)
3808 wake_lock_destroy(&host->sdio_wlock);
3809 free_irq(core_irqres->start, host);
3810 irq_free:
3811 free_irq(core_irqres->start, host);
3812 dml_exit:
3813 if (host->is_sps_mode)
3814 msmsdcc_dml_exit(host);
3815 sps_exit:
3816 if (host->is_sps_mode)
3817 msmsdcc_sps_exit(host);
3818 vreg_deinit:
3819 msmsdcc_vreg_init(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07003820 clk_disable:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003821 clk_disable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003822 clk_put:
3823 clk_put(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003824 pclk_disable:
3825 if (!IS_ERR(host->pclk))
3826 clk_disable(host->pclk);
San Mehat9d2bd732009-09-22 16:44:22 -07003827 pclk_put:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003828 if (!IS_ERR(host->pclk))
3829 clk_put(host->pclk);
3830 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3831 clk_disable(host->dfab_pclk);
3832 dfab_pclk_put:
3833 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3834 clk_put(host->dfab_pclk);
3835 dma_free:
3836 if (host->is_dma_mode) {
3837 if (host->dmares)
3838 dma_free_coherent(NULL,
3839 sizeof(struct msmsdcc_nc_dmadata),
3840 host->dma.nc, host->dma.nc_busaddr);
3841 }
3842 ioremap_free:
3843 iounmap(host->base);
San Mehat9d2bd732009-09-22 16:44:22 -07003844 host_free:
3845 mmc_free_host(mmc);
3846 out:
3847 return ret;
3848}
3849
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003850static int msmsdcc_remove(struct platform_device *pdev)
Daniel Walker08ecfde2010-06-23 12:32:20 -07003851{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003852 struct mmc_host *mmc = mmc_get_drvdata(pdev);
3853 struct mmc_platform_data *plat;
3854 struct msmsdcc_host *host;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003855
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003856 if (!mmc)
3857 return -ENXIO;
3858
3859 if (pm_runtime_suspended(&(pdev)->dev))
3860 pm_runtime_resume(&(pdev)->dev);
3861
3862 host = mmc_priv(mmc);
3863
3864 DBG(host, "Removing SDCC device = %d\n", pdev->id);
3865 plat = host->plat;
3866
3867 if (!plat->status_irq)
3868 sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
3869
3870 del_timer_sync(&host->req_tout_timer);
3871 tasklet_kill(&host->dma_tlet);
3872 tasklet_kill(&host->sps.tlet);
3873 mmc_remove_host(mmc);
3874
3875 if (plat->status_irq)
3876 free_irq(plat->status_irq, host);
3877
3878 wake_lock_destroy(&host->sdio_suspend_wlock);
3879 if (plat->sdiowakeup_irq) {
3880 wake_lock_destroy(&host->sdio_wlock);
3881 irq_set_irq_wake(plat->sdiowakeup_irq, 0);
3882 free_irq(plat->sdiowakeup_irq, host);
Daniel Walker08ecfde2010-06-23 12:32:20 -07003883 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003884
3885 free_irq(host->core_irqres->start, host);
3886 free_irq(host->core_irqres->start, host);
3887
3888 clk_put(host->clk);
3889 if (!IS_ERR(host->pclk))
3890 clk_put(host->pclk);
3891 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3892 clk_put(host->dfab_pclk);
3893
3894 msmsdcc_vreg_init(host, false);
3895
3896 if (host->is_dma_mode) {
3897 if (host->dmares)
3898 dma_free_coherent(NULL,
3899 sizeof(struct msmsdcc_nc_dmadata),
3900 host->dma.nc, host->dma.nc_busaddr);
3901 }
3902
3903 if (host->is_sps_mode) {
3904 msmsdcc_dml_exit(host);
3905 msmsdcc_sps_exit(host);
3906 }
3907
3908 iounmap(host->base);
3909 mmc_free_host(mmc);
3910
3911#ifdef CONFIG_HAS_EARLYSUSPEND
3912 unregister_early_suspend(&host->early_suspend);
3913#endif
3914 pm_runtime_disable(&(pdev)->dev);
3915 pm_runtime_set_suspended(&(pdev)->dev);
3916
3917 return 0;
3918}
3919
3920#ifdef CONFIG_MSM_SDIO_AL
3921int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3922{
3923 struct msmsdcc_host *host = mmc_priv(mmc);
3924 unsigned long flags;
3925
3926 spin_lock_irqsave(&host->lock, flags);
3927 pr_debug("%s: %sabling LPM\n", mmc_hostname(mmc),
3928 enable ? "En" : "Dis");
3929
3930 if (enable) {
3931 if (!host->sdcc_irq_disabled) {
3932 writel_relaxed(0, host->base + MMCIMASK0);
Sujith Reddy Thummade773b82011-08-03 19:58:15 +05303933 disable_irq_nosync(host->core_irqres->start);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003934 host->sdcc_irq_disabled = 1;
3935 }
3936
3937 if (host->clks_on) {
3938 msmsdcc_setup_clocks(host, false);
3939 host->clks_on = 0;
3940 }
3941
3942 if (!host->sdio_gpio_lpm) {
3943 spin_unlock_irqrestore(&host->lock, flags);
3944 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 0);
3945 spin_lock_irqsave(&host->lock, flags);
3946 host->sdio_gpio_lpm = 1;
3947 }
3948
3949 if (host->sdio_irq_disabled) {
3950 msmsdcc_enable_irq_wake(host);
3951 enable_irq(host->plat->sdiowakeup_irq);
3952 host->sdio_irq_disabled = 0;
3953 }
3954 } else {
3955 if (!host->sdio_irq_disabled) {
3956 disable_irq_nosync(host->plat->sdiowakeup_irq);
3957 host->sdio_irq_disabled = 1;
3958 msmsdcc_disable_irq_wake(host);
3959 }
3960
3961 if (host->sdio_gpio_lpm) {
3962 spin_unlock_irqrestore(&host->lock, flags);
3963 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 1);
3964 spin_lock_irqsave(&host->lock, flags);
3965 host->sdio_gpio_lpm = 0;
3966 }
3967
3968 if (!host->clks_on) {
3969 msmsdcc_setup_clocks(host, true);
3970 host->clks_on = 1;
3971 }
3972
3973 if (host->sdcc_irq_disabled) {
3974 writel_relaxed(host->mci_irqenable,
3975 host->base + MMCIMASK0);
3976 mb();
3977 enable_irq(host->core_irqres->start);
3978 host->sdcc_irq_disabled = 0;
3979 }
3980 wake_lock_timeout(&host->sdio_wlock, 1);
3981 }
3982 spin_unlock_irqrestore(&host->lock, flags);
3983 return 0;
3984}
3985#else
3986int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3987{
3988 return 0;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003989}
3990#endif
3991
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003992#ifdef CONFIG_PM
San Mehat9d2bd732009-09-22 16:44:22 -07003993static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003994msmsdcc_runtime_suspend(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003995{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003996 struct mmc_host *mmc = dev_get_drvdata(dev);
3997 struct msmsdcc_host *host = mmc_priv(mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07003998 int rc = 0;
3999
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004000 if (host->plat->is_sdio_al_client)
4001 return 0;
4002
Sahitya Tummala7661a452011-07-18 13:28:35 +05304003 pr_debug("%s: %s: start\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07004004 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004005 host->sdcc_suspending = 1;
4006 mmc->suspend_task = current;
San Mehat9d2bd732009-09-22 16:44:22 -07004007
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004008 /*
4009 * If the clocks are already turned off by SDIO clients (as
4010 * part of LPM), then clocks should be turned on before
4011 * calling mmc_suspend_host() because mmc_suspend_host might
4012 * send some commands to the card. The clocks will be turned
4013 * off again after mmc_suspend_host. Thus for SD/MMC/SDIO
4014 * cards, clocks will be turned on before mmc_suspend_host
4015 * and turned off after mmc_suspend_host.
4016 */
4017 mmc->ios.clock = host->clk_rate;
4018 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07004019
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004020 /*
4021 * MMC core thinks that host is disabled by now since
4022 * runtime suspend is scheduled after msmsdcc_disable()
4023 * is called. Thus, MMC core will try to enable the host
4024 * while suspending it. This results in a synchronous
4025 * runtime resume request while in runtime suspending
4026 * context and hence inorder to complete this resume
4027 * requet, it will wait for suspend to be complete,
4028 * but runtime suspend also can not proceed further
4029 * until the host is resumed. Thus, it leads to a hang.
4030 * Hence, increase the pm usage count before suspending
4031 * the host so that any resume requests after this will
4032 * simple become pm usage counter increment operations.
4033 */
4034 pm_runtime_get_noresume(dev);
4035 rc = mmc_suspend_host(mmc);
4036 pm_runtime_put_noidle(dev);
4037
4038 if (!rc) {
4039 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
4040 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ)) {
4041 disable_irq(host->core_irqres->start);
4042 host->sdcc_irq_disabled = 1;
4043
4044 /*
4045 * If MMC core level suspend is not supported,
4046 * turn off clocks to allow deep sleep (TCXO
4047 * shutdown).
4048 */
4049 mmc->ios.clock = 0;
4050 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
4051 enable_irq(host->core_irqres->start);
4052 host->sdcc_irq_disabled = 0;
4053
4054 if (host->plat->sdiowakeup_irq) {
4055 host->sdio_irq_disabled = 0;
4056 msmsdcc_enable_irq_wake(host);
4057 enable_irq(host->plat->sdiowakeup_irq);
4058 }
4059 }
4060 }
4061 host->sdcc_suspending = 0;
4062 mmc->suspend_task = NULL;
4063 if (rc && wake_lock_active(&host->sdio_suspend_wlock))
4064 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07004065 }
Sahitya Tummala7661a452011-07-18 13:28:35 +05304066 pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07004067 return rc;
4068}
4069
4070static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004071msmsdcc_runtime_resume(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07004072{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004073 struct mmc_host *mmc = dev_get_drvdata(dev);
4074 struct msmsdcc_host *host = mmc_priv(mmc);
4075 unsigned long flags;
4076
4077 if (host->plat->is_sdio_al_client)
4078 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -07004079
Sahitya Tummala7661a452011-07-18 13:28:35 +05304080 pr_debug("%s: %s: start\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07004081 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004082 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
4083 if (host->sdcc_irq_disabled) {
4084 enable_irq(host->core_irqres->start);
4085 host->sdcc_irq_disabled = 0;
4086 }
4087 }
4088 mmc->ios.clock = host->clk_rate;
4089 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07004090
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004091 spin_lock_irqsave(&host->lock, flags);
4092 writel_relaxed(host->mci_irqenable, host->base + MMCIMASK0);
4093 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07004094
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004095 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
4096 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) &&
4097 !host->sdio_irq_disabled) {
4098 if (host->plat->sdiowakeup_irq) {
4099 disable_irq_nosync(
4100 host->plat->sdiowakeup_irq);
4101 msmsdcc_disable_irq_wake(host);
4102 host->sdio_irq_disabled = 1;
4103 }
4104 }
San Mehat9d2bd732009-09-22 16:44:22 -07004105
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004106 spin_unlock_irqrestore(&host->lock, flags);
4107
4108 mmc_resume_host(mmc);
4109
4110 /*
4111 * FIXME: Clearing of flags must be handled in clients
4112 * resume handler.
4113 */
4114 spin_lock_irqsave(&host->lock, flags);
4115 mmc->pm_flags = 0;
4116 spin_unlock_irqrestore(&host->lock, flags);
4117
4118 /*
4119 * After resuming the host wait for sometime so that
4120 * the SDIO work will be processed.
4121 */
4122 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO)) {
4123 if ((host->plat->cfg_mpm_sdiowakeup ||
4124 host->plat->sdiowakeup_irq) &&
4125 wake_lock_active(&host->sdio_wlock))
4126 wake_lock_timeout(&host->sdio_wlock, 1);
4127 }
4128
4129 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07004130 }
Sahitya Tummala7661a452011-07-18 13:28:35 +05304131 pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07004132 return 0;
4133}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004134
4135static int msmsdcc_runtime_idle(struct device *dev)
4136{
4137 struct mmc_host *mmc = dev_get_drvdata(dev);
4138 struct msmsdcc_host *host = mmc_priv(mmc);
4139
4140 if (host->plat->is_sdio_al_client)
4141 return 0;
4142
4143 /* Idle timeout is not configurable for now */
4144 pm_schedule_suspend(dev, MSM_MMC_IDLE_TIMEOUT);
4145
4146 return -EAGAIN;
4147}
4148
4149static int msmsdcc_pm_suspend(struct device *dev)
4150{
4151 struct mmc_host *mmc = dev_get_drvdata(dev);
4152 struct msmsdcc_host *host = mmc_priv(mmc);
4153 int rc = 0;
4154
4155 if (host->plat->is_sdio_al_client)
4156 return 0;
4157
4158
4159 if (host->plat->status_irq)
4160 disable_irq(host->plat->status_irq);
4161
4162 if (!pm_runtime_suspended(dev))
4163 rc = msmsdcc_runtime_suspend(dev);
4164
4165 return rc;
4166}
4167
4168static int msmsdcc_pm_resume(struct device *dev)
4169{
4170 struct mmc_host *mmc = dev_get_drvdata(dev);
4171 struct msmsdcc_host *host = mmc_priv(mmc);
4172 int rc = 0;
4173
4174 if (host->plat->is_sdio_al_client)
4175 return 0;
4176
Sahitya Tummalafb486372011-09-02 19:01:49 +05304177 if (!pm_runtime_suspended(dev))
4178 rc = msmsdcc_runtime_resume(dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004179 if (host->plat->status_irq) {
4180 msmsdcc_check_status((unsigned long)host);
4181 enable_irq(host->plat->status_irq);
4182 }
4183
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004184 return rc;
4185}
4186
Daniel Walker08ecfde2010-06-23 12:32:20 -07004187#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004188#define msmsdcc_runtime_suspend NULL
4189#define msmsdcc_runtime_resume NULL
4190#define msmsdcc_runtime_idle NULL
4191#define msmsdcc_pm_suspend NULL
4192#define msmsdcc_pm_resume NULL
Daniel Walker08ecfde2010-06-23 12:32:20 -07004193#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004194
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004195static const struct dev_pm_ops msmsdcc_dev_pm_ops = {
4196 .runtime_suspend = msmsdcc_runtime_suspend,
4197 .runtime_resume = msmsdcc_runtime_resume,
4198 .runtime_idle = msmsdcc_runtime_idle,
4199 .suspend = msmsdcc_pm_suspend,
4200 .resume = msmsdcc_pm_resume,
4201};
4202
San Mehat9d2bd732009-09-22 16:44:22 -07004203static struct platform_driver msmsdcc_driver = {
4204 .probe = msmsdcc_probe,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004205 .remove = msmsdcc_remove,
San Mehat9d2bd732009-09-22 16:44:22 -07004206 .driver = {
4207 .name = "msm_sdcc",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004208 .pm = &msmsdcc_dev_pm_ops,
San Mehat9d2bd732009-09-22 16:44:22 -07004209 },
4210};
4211
4212static int __init msmsdcc_init(void)
4213{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004214#if defined(CONFIG_DEBUG_FS)
4215 int ret = 0;
4216 ret = msmsdcc_dbg_init();
4217 if (ret) {
4218 pr_err("Failed to create debug fs dir \n");
4219 return ret;
4220 }
4221#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004222 return platform_driver_register(&msmsdcc_driver);
4223}
4224
4225static void __exit msmsdcc_exit(void)
4226{
4227 platform_driver_unregister(&msmsdcc_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004228
4229#if defined(CONFIG_DEBUG_FS)
4230 debugfs_remove(debugfs_file);
4231 debugfs_remove(debugfs_dir);
4232#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004233}
4234
4235module_init(msmsdcc_init);
4236module_exit(msmsdcc_exit);
4237
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004238MODULE_DESCRIPTION("Qualcomm Multimedia Card Interface driver");
San Mehat9d2bd732009-09-22 16:44:22 -07004239MODULE_LICENSE("GPL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004240
4241#if defined(CONFIG_DEBUG_FS)
4242
4243static int
4244msmsdcc_dbg_state_open(struct inode *inode, struct file *file)
4245{
4246 file->private_data = inode->i_private;
4247 return 0;
4248}
4249
4250static ssize_t
4251msmsdcc_dbg_state_read(struct file *file, char __user *ubuf,
4252 size_t count, loff_t *ppos)
4253{
4254 struct msmsdcc_host *host = (struct msmsdcc_host *) file->private_data;
4255 char buf[1024];
4256 int max, i;
4257
4258 i = 0;
4259 max = sizeof(buf) - 1;
4260
4261 i += scnprintf(buf + i, max - i, "STAT: %p %p %p\n", host->curr.mrq,
4262 host->curr.cmd, host->curr.data);
4263 if (host->curr.cmd) {
4264 struct mmc_command *cmd = host->curr.cmd;
4265
4266 i += scnprintf(buf + i, max - i, "CMD : %.8x %.8x %.8x\n",
4267 cmd->opcode, cmd->arg, cmd->flags);
4268 }
4269 if (host->curr.data) {
4270 struct mmc_data *data = host->curr.data;
4271 i += scnprintf(buf + i, max - i,
4272 "DAT0: %.8x %.8x %.8x %.8x %.8x %.8x\n",
4273 data->timeout_ns, data->timeout_clks,
4274 data->blksz, data->blocks, data->error,
4275 data->flags);
4276 i += scnprintf(buf + i, max - i, "DAT1: %.8x %.8x %.8x %p\n",
4277 host->curr.xfer_size, host->curr.xfer_remain,
4278 host->curr.data_xfered, host->dma.sg);
4279 }
4280
4281 return simple_read_from_buffer(ubuf, count, ppos, buf, i);
4282}
4283
4284static const struct file_operations msmsdcc_dbg_state_ops = {
4285 .read = msmsdcc_dbg_state_read,
4286 .open = msmsdcc_dbg_state_open,
4287};
4288
4289static void msmsdcc_dbg_createhost(struct msmsdcc_host *host)
4290{
4291 if (debugfs_dir) {
4292 debugfs_file = debugfs_create_file(mmc_hostname(host->mmc),
4293 0644, debugfs_dir, host,
4294 &msmsdcc_dbg_state_ops);
4295 }
4296}
4297
4298static int __init msmsdcc_dbg_init(void)
4299{
4300 int err;
4301
4302 debugfs_dir = debugfs_create_dir("msmsdcc", 0);
4303 if (IS_ERR(debugfs_dir)) {
4304 err = PTR_ERR(debugfs_dir);
4305 debugfs_dir = NULL;
4306 return err;
4307 }
4308
4309 return 0;
4310}
4311#endif