blob: 4702c6cf5048dd90480d952927d8773739282afe [file] [log] [blame]
San Mehat9d2bd732009-09-22 16:44:22 -07001/*
2 * linux/drivers/mmc/host/msm_sdcc.c - Qualcomm MSM 7X00A SDCC Driver
3 *
4 * Copyright (C) 2007 Google Inc,
5 * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07006 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
San Mehat9d2bd732009-09-22 16:44:22 -07007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Based on mmci.c
13 *
14 * Author: San Mehat (san@android.com)
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/init.h>
21#include <linux/ioport.h>
22#include <linux/device.h>
23#include <linux/interrupt.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070024#include <linux/irq.h>
San Mehat9d2bd732009-09-22 16:44:22 -070025#include <linux/delay.h>
26#include <linux/err.h>
27#include <linux/highmem.h>
28#include <linux/log2.h>
29#include <linux/mmc/host.h>
30#include <linux/mmc/card.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070031#include <linux/mmc/mmc.h>
San Mehatb3fa5792009-11-02 18:46:09 -080032#include <linux/mmc/sdio.h>
San Mehat9d2bd732009-09-22 16:44:22 -070033#include <linux/clk.h>
34#include <linux/scatterlist.h>
35#include <linux/platform_device.h>
36#include <linux/dma-mapping.h>
37#include <linux/debugfs.h>
38#include <linux/io.h>
39#include <linux/memory.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040#include <linux/pm_runtime.h>
41#include <linux/wakelock.h>
Sahitya Tummala7a892482011-01-18 11:22:49 +053042#include <linux/gpio.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043#include <linux/regulator/consumer.h>
44#include <linux/slab.h>
45#include <linux/mmc/mmc.h>
San Mehat9d2bd732009-09-22 16:44:22 -070046
47#include <asm/cacheflush.h>
48#include <asm/div64.h>
49#include <asm/sizes.h>
50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051#include <asm/mach/mmc.h>
San Mehat9d2bd732009-09-22 16:44:22 -070052#include <mach/msm_iomap.h>
Sahitya Tummalab08bb352010-12-08 15:03:05 +053053#include <mach/clk.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070054#include <mach/dma.h>
55#include <mach/htc_pwrsink.h>
56#include <mach/sdio_al.h>
San Mehat9d2bd732009-09-22 16:44:22 -070057
San Mehat9d2bd732009-09-22 16:44:22 -070058#include "msm_sdcc.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059#include "msm_sdcc_dml.h"
San Mehat9d2bd732009-09-22 16:44:22 -070060
61#define DRIVER_NAME "msm-sdcc"
62
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070063#define DBG(host, fmt, args...) \
64 pr_debug("%s: %s: " fmt "\n", mmc_hostname(host->mmc), __func__ , args)
65
66#define IRQ_DEBUG 0
67#define SPS_SDCC_PRODUCER_PIPE_INDEX 1
68#define SPS_SDCC_CONSUMER_PIPE_INDEX 2
69#define SPS_CONS_PERIPHERAL 0
70#define SPS_PROD_PERIPHERAL 1
71/* 16 KB */
72#define SPS_MAX_DESC_SIZE (16 * 1024)
73
74#if defined(CONFIG_DEBUG_FS)
75static void msmsdcc_dbg_createhost(struct msmsdcc_host *);
76static struct dentry *debugfs_dir;
77static struct dentry *debugfs_file;
78static int msmsdcc_dbg_init(void);
79#endif
80
San Mehat9d2bd732009-09-22 16:44:22 -070081static unsigned int msmsdcc_pwrsave = 1;
San Mehat9d2bd732009-09-22 16:44:22 -070082
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083#define DUMMY_52_STATE_NONE 0
84#define DUMMY_52_STATE_SENT 1
San Mehat9d2bd732009-09-22 16:44:22 -070085
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070086static struct mmc_command dummy52cmd;
87static struct mmc_request dummy52mrq = {
88 .cmd = &dummy52cmd,
89 .data = NULL,
90 .stop = NULL,
91};
92static struct mmc_command dummy52cmd = {
93 .opcode = SD_IO_RW_DIRECT,
94 .flags = MMC_RSP_PRESENT,
95 .data = NULL,
96 .mrq = &dummy52mrq,
97};
98/*
99 * An array holding the Tuning pattern to compare with when
100 * executing a tuning cycle.
101 */
102static const u32 cmd19_tuning_block[16] = {
103 0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
104 0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
105 0xF0FFF0FF, 0x3CCCFC0F, 0xCFCC33CC, 0xEEFFEFFF,
106 0xFDFFFDFF, 0xFFBFFFDF, 0xFFF7FFBB, 0xDE7B7FF7
107};
San Mehat865c8062009-11-13 13:42:06 -0800108
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700109#if IRQ_DEBUG == 1
110static char *irq_status_bits[] = { "cmdcrcfail", "datcrcfail", "cmdtimeout",
111 "dattimeout", "txunderrun", "rxoverrun",
112 "cmdrespend", "cmdsent", "dataend", NULL,
113 "datablkend", "cmdactive", "txactive",
114 "rxactive", "txhalfempty", "rxhalffull",
115 "txfifofull", "rxfifofull", "txfifoempty",
116 "rxfifoempty", "txdataavlbl", "rxdataavlbl",
117 "sdiointr", "progdone", "atacmdcompl",
118 "sdiointrope", "ccstimeout", NULL, NULL,
119 NULL, NULL, NULL };
120
121static void
122msmsdcc_print_status(struct msmsdcc_host *host, char *hdr, uint32_t status)
San Mehat865c8062009-11-13 13:42:06 -0800123{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124 int i;
San Mehat8b1c2ba2009-11-16 10:17:30 -0800125
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126 pr_debug("%s-%s ", mmc_hostname(host->mmc), hdr);
127 for (i = 0; i < 32; i++) {
128 if (status & (1 << i))
129 pr_debug("%s ", irq_status_bits[i]);
San Mehat865c8062009-11-13 13:42:06 -0800130 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700131 pr_debug("\n");
San Mehatc7fc9372009-11-22 17:19:07 -0800132}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700133#endif
San Mehat865c8062009-11-13 13:42:06 -0800134
San Mehat9d2bd732009-09-22 16:44:22 -0700135static void
136msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
137 u32 c);
138
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700139#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
140static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
141 struct msmsdcc_sps_ep_conn_data *ep);
142static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
143 struct msmsdcc_sps_ep_conn_data *ep);
144#else
145static inline int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
146 struct msmsdcc_sps_ep_conn_data *ep,
147 bool is_producer) { return 0; }
148static inline void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
149 struct msmsdcc_sps_ep_conn_data *ep) { }
150static inline int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
151 struct msmsdcc_sps_ep_conn_data *ep)
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530152{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153 return 0;
154}
155static inline int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
156 struct msmsdcc_sps_ep_conn_data *ep)
157{
158 return 0;
159}
160static inline int msmsdcc_sps_init(struct msmsdcc_host *host) { return 0; }
161static inline void msmsdcc_sps_exit(struct msmsdcc_host *host) {}
162#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530163
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700164/**
165 * Apply soft reset
166 *
167 * This function applies soft reset to SDCC core and
168 * BAM, DML core.
169 *
170 * This function should be called to recover from error
171 * conditions encountered with CMD/DATA tranfsers with card.
172 *
173 * Soft reset should only be used with SDCC controller v4.
174 *
175 * @host - Pointer to driver's host structure
176 *
177 */
178static void msmsdcc_soft_reset_and_restore(struct msmsdcc_host *host)
179{
180 int rc;
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530181
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700182 if (host->is_sps_mode) {
183 /* Reset DML first */
184 msmsdcc_dml_reset(host);
185 /* Now reset all BAM pipes connections */
186 rc = msmsdcc_sps_reset_ep(host, &host->sps.prod);
187 if (rc)
188 pr_err("%s:msmsdcc_sps_reset_ep() error=%d\n",
189 mmc_hostname(host->mmc), rc);
190 rc = msmsdcc_sps_reset_ep(host, &host->sps.cons);
191 if (rc)
192 pr_err("%s:msmsdcc_sps_reset_ep() error=%d\n",
193 mmc_hostname(host->mmc), rc);
194 }
195 /*
196 * Reset SDCC controller's DPSM (data path state machine
197 * and CPSM (command path state machine).
198 */
199 mb();
200 writel_relaxed(0, host->base + MMCICOMMAND);
201 writel_relaxed(0, host->base + MMCIDATACTRL);
202 mb();
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530203
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 pr_debug("%s: Applied soft reset to Controller\n",
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530205 mmc_hostname(host->mmc));
206
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207 if (host->is_sps_mode) {
208 /* Restore all BAM pipes connections */
209 rc = msmsdcc_sps_restore_ep(host, &host->sps.prod);
210 if (rc)
211 pr_err("%s:msmsdcc_sps_restore_ep() error=%d\n",
212 mmc_hostname(host->mmc), rc);
213 rc = msmsdcc_sps_restore_ep(host, &host->sps.cons);
214 if (rc)
215 pr_err("%s:msmsdcc_sps_restore_ep() error=%d\n",
216 mmc_hostname(host->mmc), rc);
217 msmsdcc_dml_init(host);
218 }
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530219}
220
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
222{
223 if (host->plat->sdcc_v4_sup) {
224 msmsdcc_soft_reset_and_restore(host);
225 } else {
226 /* Give Clock reset (hard reset) to controller */
227 u32 mci_clk = 0;
228 u32 mci_mask0 = 0;
229 int ret;
230
231 /* Save the controller state */
232 mci_clk = readl_relaxed(host->base + MMCICLOCK);
233 mci_mask0 = readl_relaxed(host->base + MMCIMASK0);
234
235 mb();
236 /* Reset the controller */
237 ret = clk_reset(host->clk, CLK_RESET_ASSERT);
238 if (ret)
239 pr_err("%s: Clock assert failed at %u Hz"
240 " with err %d\n", mmc_hostname(host->mmc),
241 host->clk_rate, ret);
242
243 ret = clk_reset(host->clk, CLK_RESET_DEASSERT);
244 if (ret)
245 pr_err("%s: Clock deassert failed at %u Hz"
246 " with err %d\n", mmc_hostname(host->mmc),
247 host->clk_rate, ret);
248
249 pr_debug("%s: Controller has been reinitialized\n",
250 mmc_hostname(host->mmc));
251
252 mb();
253 /* Restore the contoller state */
254 writel_relaxed(host->pwr, host->base + MMCIPOWER);
255 writel_relaxed(mci_clk, host->base + MMCICLOCK);
256 writel_relaxed(mci_mask0, host->base + MMCIMASK0);
257 ret = clk_set_rate(host->clk, host->clk_rate);
258 if (ret)
259 pr_err("%s: Failed to set clk rate %u Hz. err %d\n",
260 mmc_hostname(host->mmc),
261 host->clk_rate, ret);
262 mb();
263 }
264}
265
266static int
San Mehat9d2bd732009-09-22 16:44:22 -0700267msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
268{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700269 int retval = 0;
270
San Mehat9d2bd732009-09-22 16:44:22 -0700271 BUG_ON(host->curr.data);
272
273 host->curr.mrq = NULL;
274 host->curr.cmd = NULL;
275
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700276 del_timer(&host->req_tout_timer);
277
San Mehat9d2bd732009-09-22 16:44:22 -0700278 if (mrq->data)
279 mrq->data->bytes_xfered = host->curr.data_xfered;
280 if (mrq->cmd->error == -ETIMEDOUT)
281 mdelay(5);
282
283 /*
284 * Need to drop the host lock here; mmc_request_done may call
285 * back into the driver...
286 */
287 spin_unlock(&host->lock);
288 mmc_request_done(host->mmc, mrq);
289 spin_lock(&host->lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290
291 return retval;
San Mehat9d2bd732009-09-22 16:44:22 -0700292}
293
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700294static inline void msmsdcc_delay(struct msmsdcc_host *host);
295
San Mehat9d2bd732009-09-22 16:44:22 -0700296static void
297msmsdcc_stop_data(struct msmsdcc_host *host)
298{
San Mehat9d2bd732009-09-22 16:44:22 -0700299 host->curr.data = NULL;
Sahitya Tummala0c521cc2010-12-08 15:03:07 +0530300 host->curr.got_dataend = 0;
Krishna Konda3e5c4d02011-07-11 16:31:45 -0700301 writel_relaxed(0, host->base + MMCIDATACTRL);
302 msmsdcc_delay(host); /* Allow the DPSM to be reset */
San Mehat9d2bd732009-09-22 16:44:22 -0700303}
304
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305static inline uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
San Mehat9d2bd732009-09-22 16:44:22 -0700306{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700307 return host->core_memres->start + MMCIFIFO;
308}
309
310static inline unsigned int msmsdcc_get_min_sup_clk_rate(
311 struct msmsdcc_host *host);
312static inline void msmsdcc_delay(struct msmsdcc_host *host)
313{
314 mb();
315 udelay(1 + ((3 * USEC_PER_SEC) /
316 (host->clk_rate ? host->clk_rate :
317 msmsdcc_get_min_sup_clk_rate(host))));
San Mehat9d2bd732009-09-22 16:44:22 -0700318}
319
San Mehat56a8b5b2009-11-21 12:29:46 -0800320static inline void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c)
322{
323 writel_relaxed(arg, host->base + MMCIARGUMENT);
324 msmsdcc_delay(host);
325 writel_relaxed(c, host->base + MMCICOMMAND);
326 mb();
San Mehat56a8b5b2009-11-21 12:29:46 -0800327}
328
329static void
330msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
331{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700332 struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->user;
San Mehat56a8b5b2009-11-21 12:29:46 -0800333
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 writel_relaxed(host->cmd_timeout, host->base + MMCIDATATIMER);
335 writel_relaxed((unsigned int)host->curr.xfer_size,
336 host->base + MMCIDATALENGTH);
337 msmsdcc_delay(host); /* Allow data parms to be applied */
338 writel_relaxed(host->cmd_datactrl, host->base + MMCIDATACTRL);
339 msmsdcc_delay(host); /* Force delay prior to ADM or command */
San Mehat56a8b5b2009-11-21 12:29:46 -0800340
San Mehat6ac9ea62009-12-02 17:24:58 -0800341 if (host->cmd_cmd) {
342 msmsdcc_start_command_exec(host,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343 (u32)host->cmd_cmd->arg, (u32)host->cmd_c);
San Mehat6ac9ea62009-12-02 17:24:58 -0800344 }
San Mehat56a8b5b2009-11-21 12:29:46 -0800345}
346
San Mehat9d2bd732009-09-22 16:44:22 -0700347static void
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530348msmsdcc_dma_complete_tlet(unsigned long data)
San Mehat9d2bd732009-09-22 16:44:22 -0700349{
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530350 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
San Mehat9d2bd732009-09-22 16:44:22 -0700351 unsigned long flags;
352 struct mmc_request *mrq;
353
354 spin_lock_irqsave(&host->lock, flags);
355 mrq = host->curr.mrq;
356 BUG_ON(!mrq);
357
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530358 if (!(host->dma.result & DMOV_RSLT_VALID)) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700359 pr_err("msmsdcc: Invalid DataMover result\n");
San Mehat9d2bd732009-09-22 16:44:22 -0700360 goto out;
361 }
362
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530363 if (host->dma.result & DMOV_RSLT_DONE) {
San Mehat9d2bd732009-09-22 16:44:22 -0700364 host->curr.data_xfered = host->curr.xfer_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365 host->curr.xfer_remain -= host->curr.xfer_size;
San Mehat9d2bd732009-09-22 16:44:22 -0700366 } else {
367 /* Error or flush */
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530368 if (host->dma.result & DMOV_RSLT_ERROR)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700369 pr_err("%s: DMA error (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530370 mmc_hostname(host->mmc), host->dma.result);
371 if (host->dma.result & DMOV_RSLT_FLUSH)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700372 pr_err("%s: DMA channel flushed (0x%.8x)\n",
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530373 mmc_hostname(host->mmc), host->dma.result);
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530374 pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375 host->dma.err.flush[0], host->dma.err.flush[1],
376 host->dma.err.flush[2], host->dma.err.flush[3],
377 host->dma.err.flush[4],
378 host->dma.err.flush[5]);
Sahitya Tummalab08bb352010-12-08 15:03:05 +0530379 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -0700380 if (!mrq->data->error)
381 mrq->data->error = -EIO;
382 }
San Mehat9d2bd732009-09-22 16:44:22 -0700383 dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
384 host->dma.dir);
385
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700386 if (host->curr.user_pages) {
387 struct scatterlist *sg = host->dma.sg;
388 int i;
389
390 for (i = 0; i < host->dma.num_ents; i++, sg++)
391 flush_dcache_page(sg_page(sg));
392 }
393
San Mehat9d2bd732009-09-22 16:44:22 -0700394 host->dma.sg = NULL;
San Mehat56a8b5b2009-11-21 12:29:46 -0800395 host->dma.busy = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700396
Sahitya Tummala0c521cc2010-12-08 15:03:07 +0530397 if (host->curr.got_dataend || mrq->data->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700398
399 /*
400 * If we've already gotten our DATAEND / DATABLKEND
401 * for this request, then complete it through here.
402 */
403 msmsdcc_stop_data(host);
404
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 if (!mrq->data->error) {
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;
408 }
San Mehat9d2bd732009-09-22 16:44:22 -0700409 if (!mrq->data->stop || mrq->cmd->error) {
San Mehat9d2bd732009-09-22 16:44:22 -0700410 host->curr.mrq = NULL;
411 host->curr.cmd = NULL;
412 mrq->data->bytes_xfered = host->curr.data_xfered;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700413 del_timer(&host->req_tout_timer);
San Mehat9d2bd732009-09-22 16:44:22 -0700414 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700415
San Mehat9d2bd732009-09-22 16:44:22 -0700416 mmc_request_done(host->mmc, mrq);
417 return;
418 } else
419 msmsdcc_start_command(host, mrq->data->stop, 0);
420 }
421
422out:
423 spin_unlock_irqrestore(&host->lock, flags);
424 return;
425}
426
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700427#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
428/**
429 * Callback notification from SPS driver
430 *
431 * This callback function gets triggered called from
432 * SPS driver when requested SPS data transfer is
433 * completed.
434 *
435 * SPS driver invokes this callback in BAM irq context so
436 * SDCC driver schedule a tasklet for further processing
437 * this callback notification at later point of time in
438 * tasklet context and immediately returns control back
439 * to SPS driver.
440 *
441 * @nofity - Pointer to sps event notify sturcture
442 *
443 */
444static void
445msmsdcc_sps_complete_cb(struct sps_event_notify *notify)
446{
447 struct msmsdcc_host *host =
448 (struct msmsdcc_host *)
449 ((struct sps_event_notify *)notify)->user;
450
451 host->sps.notify = *notify;
452 pr_debug("%s: %s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
453 mmc_hostname(host->mmc), __func__, notify->event_id,
454 notify->data.transfer.iovec.addr,
455 notify->data.transfer.iovec.size,
456 notify->data.transfer.iovec.flags);
457 /* Schedule a tasklet for completing data transfer */
458 tasklet_schedule(&host->sps.tlet);
459}
460
461/**
462 * Tasklet handler for processing SPS callback event
463 *
464 * This function processing SPS event notification and
465 * checks if the SPS transfer is completed or not and
466 * then accordingly notifies status to MMC core layer.
467 *
468 * This function is called in tasklet context.
469 *
470 * @data - Pointer to sdcc driver data
471 *
472 */
473static void msmsdcc_sps_complete_tlet(unsigned long data)
474{
475 unsigned long flags;
476 int i, rc;
477 u32 data_xfered = 0;
478 struct mmc_request *mrq;
479 struct sps_iovec iovec;
480 struct sps_pipe *sps_pipe_handle;
481 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
482 struct sps_event_notify *notify = &host->sps.notify;
483
484 spin_lock_irqsave(&host->lock, flags);
485 if (host->sps.dir == DMA_FROM_DEVICE)
486 sps_pipe_handle = host->sps.prod.pipe_handle;
487 else
488 sps_pipe_handle = host->sps.cons.pipe_handle;
489 mrq = host->curr.mrq;
490
491 if (!mrq) {
492 spin_unlock_irqrestore(&host->lock, flags);
493 return;
494 }
495
496 pr_debug("%s: %s: sps event_id=%d\n",
497 mmc_hostname(host->mmc), __func__,
498 notify->event_id);
499
500 if (msmsdcc_is_dml_busy(host)) {
501 /* oops !!! this should never happen. */
502 pr_err("%s: %s: Received SPS EOT event"
503 " but DML HW is still busy !!!\n",
504 mmc_hostname(host->mmc), __func__);
505 }
506 /*
507 * Got End of transfer event!!! Check if all of the data
508 * has been transferred?
509 */
510 for (i = 0; i < host->sps.xfer_req_cnt; i++) {
511 rc = sps_get_iovec(sps_pipe_handle, &iovec);
512 if (rc) {
513 pr_err("%s: %s: sps_get_iovec() failed rc=%d, i=%d",
514 mmc_hostname(host->mmc), __func__, rc, i);
515 break;
516 }
517 data_xfered += iovec.size;
518 }
519
520 if (data_xfered == host->curr.xfer_size) {
521 host->curr.data_xfered = host->curr.xfer_size;
522 host->curr.xfer_remain -= host->curr.xfer_size;
523 pr_debug("%s: Data xfer success. data_xfered=0x%x",
524 mmc_hostname(host->mmc),
525 host->curr.xfer_size);
526 } else {
527 pr_err("%s: Data xfer failed. data_xfered=0x%x,"
528 " xfer_size=%d", mmc_hostname(host->mmc),
529 data_xfered, host->curr.xfer_size);
530 msmsdcc_reset_and_restore(host);
531 if (!mrq->data->error)
532 mrq->data->error = -EIO;
533 }
534
535 /* Unmap sg buffers */
536 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
537 host->sps.dir);
538
539 host->sps.sg = NULL;
540 host->sps.busy = 0;
541
542 if (host->curr.got_dataend || mrq->data->error) {
543 /*
544 * If we've already gotten our DATAEND / DATABLKEND
545 * for this request, then complete it through here.
546 */
547 msmsdcc_stop_data(host);
548
549 if (!mrq->data->error) {
550 host->curr.data_xfered = host->curr.xfer_size;
551 host->curr.xfer_remain -= host->curr.xfer_size;
552 }
553 if (!mrq->data->stop || mrq->cmd->error) {
554 host->curr.mrq = NULL;
555 host->curr.cmd = NULL;
556 mrq->data->bytes_xfered = host->curr.data_xfered;
557 del_timer(&host->req_tout_timer);
558 spin_unlock_irqrestore(&host->lock, flags);
559
560 mmc_request_done(host->mmc, mrq);
561 return;
562 } else {
563 msmsdcc_start_command(host, mrq->data->stop, 0);
564 }
565 }
566 spin_unlock_irqrestore(&host->lock, flags);
567}
568
569/**
570 * Exit from current SPS data transfer
571 *
572 * This function exits from current SPS data transfer.
573 *
574 * This function should be called when error condition
575 * is encountered during data transfer.
576 *
577 * @host - Pointer to sdcc host structure
578 *
579 */
580static void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host)
581{
582 struct mmc_request *mrq;
583
584 mrq = host->curr.mrq;
585 BUG_ON(!mrq);
586
587 msmsdcc_reset_and_restore(host);
588 if (!mrq->data->error)
589 mrq->data->error = -EIO;
590
591 /* Unmap sg buffers */
592 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
593 host->sps.dir);
594
595 host->sps.sg = NULL;
596 host->sps.busy = 0;
597 if (host->curr.data)
598 msmsdcc_stop_data(host);
599
600 if (!mrq->data->stop || mrq->cmd->error)
601 msmsdcc_request_end(host, mrq);
602 else
603 msmsdcc_start_command(host, mrq->data->stop, 0);
604
605}
606#else
607static inline void msmsdcc_sps_complete_cb(struct sps_event_notify *notify) { }
608static inline void msmsdcc_sps_complete_tlet(unsigned long data) { }
609static inline void msmsdcc_sps_exit_curr_xfer(struct msmsdcc_host *host) { }
610#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
611
612static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host);
613
Sahitya Tummala62612cf2010-12-08 15:03:03 +0530614static void
615msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
616 unsigned int result,
617 struct msm_dmov_errdata *err)
618{
619 struct msmsdcc_dma_data *dma_data =
620 container_of(cmd, struct msmsdcc_dma_data, hdr);
621 struct msmsdcc_host *host = dma_data->host;
622
623 dma_data->result = result;
624 if (err)
625 memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
626
627 tasklet_schedule(&host->dma_tlet);
628}
629
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700630static int msmsdcc_check_dma_op_req(struct mmc_data *data)
San Mehat9d2bd732009-09-22 16:44:22 -0700631{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700632 if (((data->blksz * data->blocks) < MCI_FIFOSIZE) ||
633 ((data->blksz * data->blocks) % MCI_FIFOSIZE))
San Mehat9d2bd732009-09-22 16:44:22 -0700634 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700635 else
636 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700637}
638
639static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
640{
641 struct msmsdcc_nc_dmadata *nc;
642 dmov_box *box;
643 uint32_t rows;
644 uint32_t crci;
645 unsigned int n;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700646 int i;
San Mehat9d2bd732009-09-22 16:44:22 -0700647 struct scatterlist *sg = data->sg;
648
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649 if (host->dma.channel == -1)
650 return -ENOENT;
San Mehat9d2bd732009-09-22 16:44:22 -0700651
652 host->dma.sg = data->sg;
653 host->dma.num_ents = data->sg_len;
654
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700655 BUG_ON(host->dma.num_ents > NR_SG); /* Prevent memory corruption */
San Mehat56a8b5b2009-11-21 12:29:46 -0800656
San Mehat9d2bd732009-09-22 16:44:22 -0700657 nc = host->dma.nc;
658
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700659 if (host->pdev_id == 1)
660 crci = DMOV_SDC1_CRCI;
661 else if (host->pdev_id == 2)
662 crci = DMOV_SDC2_CRCI;
663 else if (host->pdev_id == 3)
664 crci = DMOV_SDC3_CRCI;
665 else if (host->pdev_id == 4)
666 crci = DMOV_SDC4_CRCI;
667#ifdef DMOV_SDC5_CRCI
668 else if (host->pdev_id == 5)
669 crci = DMOV_SDC5_CRCI;
670#endif
671 else {
San Mehat9d2bd732009-09-22 16:44:22 -0700672 host->dma.sg = NULL;
673 host->dma.num_ents = 0;
674 return -ENOENT;
675 }
676
677 if (data->flags & MMC_DATA_READ)
678 host->dma.dir = DMA_FROM_DEVICE;
679 else
680 host->dma.dir = DMA_TO_DEVICE;
681
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700682 /* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
San Mehat9d2bd732009-09-22 16:44:22 -0700683 host->curr.user_pages = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700684 box = &nc->cmd[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700685 for (i = 0; i < host->dma.num_ents; i++) {
San Mehat9d2bd732009-09-22 16:44:22 -0700686 box->cmd = CMD_MODE_BOX;
687
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688 /* Initialize sg dma address */
689 sg->dma_address = pfn_to_dma(mmc_dev(host->mmc),
690 page_to_pfn(sg_page(sg)))
691 + sg->offset;
692
693 if (i == (host->dma.num_ents - 1))
San Mehat9d2bd732009-09-22 16:44:22 -0700694 box->cmd |= CMD_LC;
695 rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
696 (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
697 (sg_dma_len(sg) / MCI_FIFOSIZE) ;
698
699 if (data->flags & MMC_DATA_READ) {
700 box->src_row_addr = msmsdcc_fifo_addr(host);
701 box->dst_row_addr = sg_dma_address(sg);
702
703 box->src_dst_len = (MCI_FIFOSIZE << 16) |
704 (MCI_FIFOSIZE);
705 box->row_offset = MCI_FIFOSIZE;
706
707 box->num_rows = rows * ((1 << 16) + 1);
708 box->cmd |= CMD_SRC_CRCI(crci);
709 } else {
710 box->src_row_addr = sg_dma_address(sg);
711 box->dst_row_addr = msmsdcc_fifo_addr(host);
712
713 box->src_dst_len = (MCI_FIFOSIZE << 16) |
714 (MCI_FIFOSIZE);
715 box->row_offset = (MCI_FIFOSIZE << 16);
716
717 box->num_rows = rows * ((1 << 16) + 1);
718 box->cmd |= CMD_DST_CRCI(crci);
719 }
720 box++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700721 sg++;
722 }
723
724 /* location of command block must be 64 bit aligned */
725 BUG_ON(host->dma.cmd_busaddr & 0x07);
726
727 nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
728 host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
729 DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
730 host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
731 host->dma.hdr.crci_mask = msm_dmov_build_crci_mask(1, crci);
732
733 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
734 host->dma.num_ents, host->dma.dir);
735 /* dsb inside dma_map_sg will write nc out to mem as well */
736
737 if (n != host->dma.num_ents) {
738 pr_err("%s: Unable to map in all sg elements\n",
739 mmc_hostname(host->mmc));
740 host->dma.sg = NULL;
741 host->dma.num_ents = 0;
742 return -ENOMEM;
San Mehat56a8b5b2009-11-21 12:29:46 -0800743 }
San Mehat9d2bd732009-09-22 16:44:22 -0700744
745 return 0;
746}
747
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700748#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
749/**
750 * Submits data transfer request to SPS driver
751 *
752 * This function make sg (scatter gather) data buffers
753 * DMA ready and then submits them to SPS driver for
754 * transfer.
755 *
756 * @host - Pointer to sdcc host structure
757 * @data - Pointer to mmc_data structure
758 *
759 * @return 0 if success else negative value
760 */
761static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
762 struct mmc_data *data)
San Mehat56a8b5b2009-11-21 12:29:46 -0800763{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 int rc = 0;
765 u32 flags;
766 int i;
767 u32 addr, len, data_cnt;
768 struct scatterlist *sg = data->sg;
769 struct sps_pipe *sps_pipe_handle;
770
771 BUG_ON(data->sg_len > NR_SG); /* Prevent memory corruption */
772
773 host->sps.sg = data->sg;
774 host->sps.num_ents = data->sg_len;
775 host->sps.xfer_req_cnt = 0;
776 if (data->flags & MMC_DATA_READ) {
777 host->sps.dir = DMA_FROM_DEVICE;
778 sps_pipe_handle = host->sps.prod.pipe_handle;
779 } else {
780 host->sps.dir = DMA_TO_DEVICE;
781 sps_pipe_handle = host->sps.cons.pipe_handle;
782 }
783
784 /* Make sg buffers DMA ready */
785 rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
786 host->sps.dir);
787
788 if (rc != data->sg_len) {
789 pr_err("%s: Unable to map in all sg elements, rc=%d\n",
790 mmc_hostname(host->mmc), rc);
791 host->sps.sg = NULL;
792 host->sps.num_ents = 0;
793 rc = -ENOMEM;
794 goto dma_map_err;
795 }
796
797 pr_debug("%s: %s: %s: pipe=0x%x, total_xfer=0x%x, sg_len=%d\n",
798 mmc_hostname(host->mmc), __func__,
799 host->sps.dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
800 (u32)sps_pipe_handle, host->curr.xfer_size, data->sg_len);
801
802 for (i = 0; i < data->sg_len; i++) {
803 /*
804 * Check if this is the last buffer to transfer?
805 * If yes then set the INT and EOT flags.
806 */
807 len = sg_dma_len(sg);
808 addr = sg_dma_address(sg);
809 flags = 0;
810 while (len > 0) {
811 if (len > SPS_MAX_DESC_SIZE) {
812 data_cnt = SPS_MAX_DESC_SIZE;
813 } else {
814 data_cnt = len;
815 if (i == data->sg_len - 1)
816 flags = SPS_IOVEC_FLAG_INT |
817 SPS_IOVEC_FLAG_EOT;
818 }
819 rc = sps_transfer_one(sps_pipe_handle, addr,
820 data_cnt, host, flags);
821 if (rc) {
822 pr_err("%s: sps_transfer_one() error! rc=%d,"
823 " pipe=0x%x, sg=0x%x, sg_buf_no=%d\n",
824 mmc_hostname(host->mmc), rc,
825 (u32)sps_pipe_handle, (u32)sg, i);
826 goto dma_map_err;
827 }
828 addr += data_cnt;
829 len -= data_cnt;
830 host->sps.xfer_req_cnt++;
831 }
832 sg++;
833 }
834 goto out;
835
836dma_map_err:
837 /* unmap sg buffers */
838 dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
839 host->sps.dir);
840out:
841 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -0700842}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700843#else
844static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
845 struct mmc_data *data) { return 0; }
846#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
San Mehat9d2bd732009-09-22 16:44:22 -0700847
848static void
San Mehat56a8b5b2009-11-21 12:29:46 -0800849msmsdcc_start_command_deferred(struct msmsdcc_host *host,
850 struct mmc_command *cmd, u32 *c)
851{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852 DBG(host, "op %02x arg %08x flags %08x\n",
853 cmd->opcode, cmd->arg, cmd->flags);
854
San Mehat56a8b5b2009-11-21 12:29:46 -0800855 *c |= (cmd->opcode | MCI_CPSM_ENABLE);
856
857 if (cmd->flags & MMC_RSP_PRESENT) {
858 if (cmd->flags & MMC_RSP_136)
859 *c |= MCI_CPSM_LONGRSP;
860 *c |= MCI_CPSM_RESPONSE;
861 }
862
863 if (/*interrupt*/0)
864 *c |= MCI_CPSM_INTERRUPT;
865
866 if ((((cmd->opcode == 17) || (cmd->opcode == 18)) ||
867 ((cmd->opcode == 24) || (cmd->opcode == 25))) ||
868 (cmd->opcode == 53))
869 *c |= MCI_CSPM_DATCMD;
870
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700871 /* Check if AUTO CMD19 is required or not? */
872 if (((cmd->opcode == 17) || (cmd->opcode == 18)) &&
873 host->tuning_needed) {
874 msmsdcc_enable_cdr_cm_sdc4_dll(host);
875 *c |= MCI_CSPM_AUTO_CMD19;
876 }
877
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530878 if (host->prog_scan && (cmd->opcode == 12)) {
879 *c |= MCI_CPSM_PROGENA;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700880 host->prog_enable = 1;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +0530881 }
882
San Mehat56a8b5b2009-11-21 12:29:46 -0800883 if (cmd == cmd->mrq->stop)
884 *c |= MCI_CSPM_MCIABORT;
885
San Mehat56a8b5b2009-11-21 12:29:46 -0800886 if (host->curr.cmd != NULL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700887 pr_err("%s: Overlapping command requests\n",
888 mmc_hostname(host->mmc));
San Mehat56a8b5b2009-11-21 12:29:46 -0800889 }
890 host->curr.cmd = cmd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700891
892 /*
893 * Kick the software command timeout timer here.
894 * Timer expires in 10 secs.
895 */
896 mod_timer(&host->req_tout_timer,
897 (jiffies + msecs_to_jiffies(MSM_MMC_REQ_TIMEOUT)));
San Mehat56a8b5b2009-11-21 12:29:46 -0800898}
899
900static void
901msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data,
902 struct mmc_command *cmd, u32 c)
San Mehat9d2bd732009-09-22 16:44:22 -0700903{
904 unsigned int datactrl, timeout;
905 unsigned long long clks;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700906 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -0700907 unsigned int pio_irqmask = 0;
908
909 host->curr.data = data;
910 host->curr.xfer_size = data->blksz * data->blocks;
911 host->curr.xfer_remain = host->curr.xfer_size;
912 host->curr.data_xfered = 0;
913 host->curr.got_dataend = 0;
San Mehat9d2bd732009-09-22 16:44:22 -0700914
915 memset(&host->pio, 0, sizeof(host->pio));
916
San Mehat9d2bd732009-09-22 16:44:22 -0700917 datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
918
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700919 if (!msmsdcc_check_dma_op_req(data)) {
920 if (host->is_dma_mode && !msmsdcc_config_dma(host, data)) {
921 datactrl |= MCI_DPSM_DMAENABLE;
922 } else if (host->is_sps_mode) {
923 if (!msmsdcc_is_dml_busy(host)) {
924 if (!msmsdcc_sps_start_xfer(host, data)) {
925 /* Now kick start DML transfer */
926 mb();
927 msmsdcc_dml_start_xfer(host, data);
928 datactrl |= MCI_DPSM_DMAENABLE;
929 host->sps.busy = 1;
930 }
931 } else {
932 /*
933 * Can't proceed with new transfer as
934 * previous trasnfer is already in progress.
935 * There is no point of going into PIO mode
936 * as well. Is this a time to do kernel panic?
937 */
938 pr_err("%s: %s: DML HW is busy!!!"
939 " Can't perform new SPS transfers"
940 " now\n", mmc_hostname(host->mmc),
941 __func__);
942 }
943 }
944 }
945
946 /* Is data transfer in PIO mode required? */
947 if (!(datactrl & MCI_DPSM_DMAENABLE)) {
San Mehat9d2bd732009-09-22 16:44:22 -0700948 host->pio.sg = data->sg;
949 host->pio.sg_len = data->sg_len;
950 host->pio.sg_off = 0;
951
952 if (data->flags & MMC_DATA_READ) {
953 pio_irqmask = MCI_RXFIFOHALFFULLMASK;
954 if (host->curr.xfer_remain < MCI_FIFOSIZE)
955 pio_irqmask |= MCI_RXDATAAVLBLMASK;
956 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700957 pio_irqmask = MCI_TXFIFOHALFEMPTYMASK |
958 MCI_TXFIFOEMPTYMASK;
San Mehat9d2bd732009-09-22 16:44:22 -0700959 }
960
961 if (data->flags & MMC_DATA_READ)
962 datactrl |= MCI_DPSM_DIRECTION;
963
San Mehat56a8b5b2009-11-21 12:29:46 -0800964 clks = (unsigned long long)data->timeout_ns * host->clk_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700965 do_div(clks, 1000000000UL);
San Mehat56a8b5b2009-11-21 12:29:46 -0800966 timeout = data->timeout_clks + (unsigned int)clks*2 ;
San Mehat9d2bd732009-09-22 16:44:22 -0700967
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700968 if (host->is_dma_mode && (datactrl & MCI_DPSM_DMAENABLE)) {
969 /* Use ADM (Application Data Mover) HW for Data transfer */
970 /* Save parameters for the dma exec function */
San Mehat56a8b5b2009-11-21 12:29:46 -0800971 host->cmd_timeout = timeout;
972 host->cmd_pio_irqmask = pio_irqmask;
973 host->cmd_datactrl = datactrl;
974 host->cmd_cmd = cmd;
San Mehat9d2bd732009-09-22 16:44:22 -0700975
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700976 host->dma.hdr.exec_func = msmsdcc_dma_exec_func;
977 host->dma.hdr.user = (void *)host;
San Mehat9d2bd732009-09-22 16:44:22 -0700978 host->dma.busy = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700979 if (data->flags & MMC_DATA_WRITE)
980 host->prog_scan = 1;
San Mehat56a8b5b2009-11-21 12:29:46 -0800981
982 if (cmd) {
983 msmsdcc_start_command_deferred(host, cmd, &c);
984 host->cmd_c = c;
985 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700986 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
987 (~(MCI_IRQ_PIO))) | host->cmd_pio_irqmask,
988 host->base + MMCIMASK0);
989 mb();
990 msm_dmov_enqueue_cmd_ext(host->dma.channel, &host->dma.hdr);
San Mehat56a8b5b2009-11-21 12:29:46 -0800991 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700992 /* SPS-BAM mode or PIO mode */
993 if (data->flags & MMC_DATA_WRITE)
994 host->prog_scan = 1;
995 writel_relaxed(timeout, base + MMCIDATATIMER);
San Mehat56a8b5b2009-11-21 12:29:46 -0800996
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997 writel_relaxed(host->curr.xfer_size, base + MMCIDATALENGTH);
San Mehat56a8b5b2009-11-21 12:29:46 -0800998
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700999 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1000 (~(MCI_IRQ_PIO))) | pio_irqmask,
1001 host->base + MMCIMASK0);
1002 msmsdcc_delay(host); /* Allow parms to be applied */
1003 writel_relaxed(datactrl, base + MMCIDATACTRL);
San Mehat56a8b5b2009-11-21 12:29:46 -08001004
1005 if (cmd) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001006 msmsdcc_delay(host); /* Delay between data/command */
San Mehat56a8b5b2009-11-21 12:29:46 -08001007 /* Daisy-chain the command if requested */
1008 msmsdcc_start_command(host, cmd, c);
1009 }
San Mehat9d2bd732009-09-22 16:44:22 -07001010 }
1011}
1012
1013static void
1014msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
1015{
San Mehat56a8b5b2009-11-21 12:29:46 -08001016 msmsdcc_start_command_deferred(host, cmd, &c);
1017 msmsdcc_start_command_exec(host, cmd->arg, c);
San Mehat9d2bd732009-09-22 16:44:22 -07001018}
1019
1020static void
1021msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
1022 unsigned int status)
1023{
1024 if (status & MCI_DATACRCFAIL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001025 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1026 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1027 pr_err("%s: Data CRC error\n",
1028 mmc_hostname(host->mmc));
1029 pr_err("%s: opcode 0x%.8x\n", __func__,
1030 data->mrq->cmd->opcode);
1031 pr_err("%s: blksz %d, blocks %d\n", __func__,
1032 data->blksz, data->blocks);
1033 data->error = -EILSEQ;
1034 }
San Mehat9d2bd732009-09-22 16:44:22 -07001035 } else if (status & MCI_DATATIMEOUT) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001036 /* CRC is optional for the bus test commands, not all
1037 * cards respond back with CRC. However controller
1038 * waits for the CRC and times out. Hence ignore the
1039 * data timeouts during the Bustest.
1040 */
1041 if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
1042 || data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
1043 pr_err("%s: Data timeout\n",
1044 mmc_hostname(host->mmc));
1045 data->error = -ETIMEDOUT;
1046 }
San Mehat9d2bd732009-09-22 16:44:22 -07001047 } else if (status & MCI_RXOVERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001048 pr_err("%s: RX overrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001049 data->error = -EIO;
1050 } else if (status & MCI_TXUNDERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001051 pr_err("%s: TX underrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001052 data->error = -EIO;
1053 } else {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001054 pr_err("%s: Unknown error (0x%.8x)\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001055 mmc_hostname(host->mmc), status);
San Mehat9d2bd732009-09-22 16:44:22 -07001056 data->error = -EIO;
1057 }
San Mehat9d2bd732009-09-22 16:44:22 -07001058
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001059 /* Dummy CMD52 is not needed when CMD53 has errors */
1060 if (host->plat->dummy52_required && host->dummy_52_needed)
1061 host->dummy_52_needed = 0;
1062}
San Mehat9d2bd732009-09-22 16:44:22 -07001063
1064static int
1065msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
1066{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001067 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001068 uint32_t *ptr = (uint32_t *) buffer;
1069 int count = 0;
1070
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301071 if (remain % 4)
1072 remain = ((remain >> 2) + 1) << 2;
1073
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001074 while (readl_relaxed(base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1075
1076 *ptr = readl_relaxed(base + MMCIFIFO + (count % MCI_FIFOSIZE));
San Mehat9d2bd732009-09-22 16:44:22 -07001077 ptr++;
1078 count += sizeof(uint32_t);
1079
1080 remain -= sizeof(uint32_t);
1081 if (remain == 0)
1082 break;
1083 }
1084 return count;
1085}
1086
1087static int
1088msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001089 unsigned int remain)
San Mehat9d2bd732009-09-22 16:44:22 -07001090{
1091 void __iomem *base = host->base;
1092 char *ptr = buffer;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001093 unsigned int maxcnt = MCI_FIFOHALFSIZE;
San Mehat9d2bd732009-09-22 16:44:22 -07001094
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001095 while (readl_relaxed(base + MMCISTATUS) &
1096 (MCI_TXFIFOEMPTY | MCI_TXFIFOHALFEMPTY)) {
1097 unsigned int count, sz;
San Mehat9d2bd732009-09-22 16:44:22 -07001098
San Mehat9d2bd732009-09-22 16:44:22 -07001099 count = min(remain, maxcnt);
1100
Sahitya Tummala71dd9102010-12-08 15:03:06 +05301101 sz = count % 4 ? (count >> 2) + 1 : (count >> 2);
1102 writesl(base + MMCIFIFO, ptr, sz);
San Mehat9d2bd732009-09-22 16:44:22 -07001103 ptr += count;
1104 remain -= count;
1105
1106 if (remain == 0)
1107 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001108 }
1109 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07001110
1111 return ptr - buffer;
1112}
1113
San Mehat1cd22962010-02-03 12:59:29 -08001114static irqreturn_t
San Mehat9d2bd732009-09-22 16:44:22 -07001115msmsdcc_pio_irq(int irq, void *dev_id)
1116{
1117 struct msmsdcc_host *host = dev_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001118 void __iomem *base = host->base;
San Mehat9d2bd732009-09-22 16:44:22 -07001119 uint32_t status;
1120
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001121 status = readl_relaxed(base + MMCISTATUS);
1122 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1123 (MCI_IRQ_PIO)) == 0)
1124 return IRQ_NONE;
1125
1126#if IRQ_DEBUG
1127 msmsdcc_print_status(host, "irq1-r", status);
1128#endif
1129
1130 spin_lock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001131
1132 do {
1133 unsigned long flags;
1134 unsigned int remain, len;
1135 char *buffer;
1136
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001137 if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_TXFIFOEMPTY
1138 | MCI_RXDATAAVLBL)))
1139 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001140
1141 /* Map the current scatter buffer */
1142 local_irq_save(flags);
1143 buffer = kmap_atomic(sg_page(host->pio.sg),
1144 KM_BIO_SRC_IRQ) + host->pio.sg->offset;
1145 buffer += host->pio.sg_off;
1146 remain = host->pio.sg->length - host->pio.sg_off;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001147
San Mehat9d2bd732009-09-22 16:44:22 -07001148 len = 0;
1149 if (status & MCI_RXACTIVE)
1150 len = msmsdcc_pio_read(host, buffer, remain);
1151 if (status & MCI_TXACTIVE)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001152 len = msmsdcc_pio_write(host, buffer, remain);
San Mehat9d2bd732009-09-22 16:44:22 -07001153
1154 /* Unmap the buffer */
1155 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
1156 local_irq_restore(flags);
1157
1158 host->pio.sg_off += len;
1159 host->curr.xfer_remain -= len;
1160 host->curr.data_xfered += len;
1161 remain -= len;
1162
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001163 if (remain) /* Done with this page? */
1164 break; /* Nope */
San Mehat9d2bd732009-09-22 16:44:22 -07001165
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001166 if (status & MCI_RXACTIVE && host->curr.user_pages)
1167 flush_dcache_page(sg_page(host->pio.sg));
San Mehat9d2bd732009-09-22 16:44:22 -07001168
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001169 if (!--host->pio.sg_len) {
1170 memset(&host->pio, 0, sizeof(host->pio));
1171 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001172 }
1173
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001174 /* Advance to next sg */
1175 host->pio.sg++;
1176 host->pio.sg_off = 0;
1177
1178 status = readl_relaxed(base + MMCISTATUS);
San Mehat9d2bd732009-09-22 16:44:22 -07001179 } while (1);
1180
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001181 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
1182 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1183 (~(MCI_IRQ_PIO))) | MCI_RXDATAAVLBLMASK,
1184 host->base + MMCIMASK0);
1185 if (!host->curr.xfer_remain) {
1186 /* Delay needed (same port was just written) */
1187 msmsdcc_delay(host);
1188 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1189 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1190 }
1191 mb();
1192 } else if (!host->curr.xfer_remain) {
1193 writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
1194 (~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
1195 mb();
1196 }
San Mehat9d2bd732009-09-22 16:44:22 -07001197
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001198 spin_unlock(&host->lock);
San Mehat9d2bd732009-09-22 16:44:22 -07001199
1200 return IRQ_HANDLED;
1201}
1202
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001203static void
1204msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq);
1205
1206static void msmsdcc_wait_for_rxdata(struct msmsdcc_host *host,
1207 struct mmc_data *data)
1208{
1209 u32 loop_cnt = 0;
1210
1211 /*
1212 * For read commands with data less than fifo size, it is possible to
1213 * get DATAEND first and RXDATA_AVAIL might be set later because of
1214 * synchronization delay through the asynchronous RX FIFO. Thus, for
1215 * such cases, even after DATAEND interrupt is received software
1216 * should poll for RXDATA_AVAIL until the requested data is read out
1217 * of FIFO. This change is needed to get around this abnormal but
1218 * sometimes expected behavior of SDCC3 controller.
1219 *
1220 * We can expect RXDATAAVAIL bit to be set after 6HCLK clock cycles
1221 * after the data is loaded into RX FIFO. This would amount to less
1222 * than a microsecond and thus looping for 1000 times is good enough
1223 * for that delay.
1224 */
1225 while (((int)host->curr.xfer_remain > 0) && (++loop_cnt < 1000)) {
1226 if (readl_relaxed(host->base + MMCISTATUS) & MCI_RXDATAAVLBL) {
1227 spin_unlock(&host->lock);
1228 msmsdcc_pio_irq(1, host);
1229 spin_lock(&host->lock);
1230 }
1231 }
1232 if (loop_cnt == 1000) {
1233 pr_info("%s: Timed out while polling for Rx Data\n",
1234 mmc_hostname(host->mmc));
1235 data->error = -ETIMEDOUT;
1236 msmsdcc_reset_and_restore(host);
1237 }
1238}
1239
San Mehat9d2bd732009-09-22 16:44:22 -07001240static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
1241{
1242 struct mmc_command *cmd = host->curr.cmd;
San Mehat9d2bd732009-09-22 16:44:22 -07001243
1244 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001245 cmd->resp[0] = readl_relaxed(host->base + MMCIRESPONSE0);
1246 cmd->resp[1] = readl_relaxed(host->base + MMCIRESPONSE1);
1247 cmd->resp[2] = readl_relaxed(host->base + MMCIRESPONSE2);
1248 cmd->resp[3] = readl_relaxed(host->base + MMCIRESPONSE3);
San Mehat9d2bd732009-09-22 16:44:22 -07001249
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001250 if (status & (MCI_CMDTIMEOUT | MCI_AUTOCMD19TIMEOUT)) {
Sahitya Tummala5a0ae912011-07-18 13:34:01 +05301251 pr_debug("%s: Command timeout\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001252 cmd->error = -ETIMEDOUT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001253 } else if ((status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) &&
1254 !host->cmd19_tuning_in_progress) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001255 pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001256 cmd->error = -EILSEQ;
1257 }
1258
1259 if (!cmd->data || cmd->error) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001260 if (host->curr.data && host->dma.sg &&
1261 host->is_dma_mode)
San Mehat9d2bd732009-09-22 16:44:22 -07001262 msm_dmov_stop_cmd(host->dma.channel,
1263 &host->dma.hdr, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001264 else if (host->curr.data && host->sps.sg &&
1265 host->is_sps_mode){
1266 /* Stop current SPS transfer */
1267 msmsdcc_sps_exit_curr_xfer(host);
1268 }
San Mehat9d2bd732009-09-22 16:44:22 -07001269 else if (host->curr.data) { /* Non DMA */
Sahitya Tummalab08bb352010-12-08 15:03:05 +05301270 msmsdcc_reset_and_restore(host);
San Mehat9d2bd732009-09-22 16:44:22 -07001271 msmsdcc_stop_data(host);
1272 msmsdcc_request_end(host, cmd->mrq);
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301273 } else { /* host->data == NULL */
1274 if (!cmd->error && host->prog_enable) {
1275 if (status & MCI_PROGDONE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001276 host->prog_scan = 0;
1277 host->prog_enable = 0;
1278 msmsdcc_request_end(host, cmd->mrq);
1279 } else
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301280 host->curr.cmd = cmd;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301281 } else {
1282 if (host->prog_enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001283 host->prog_scan = 0;
1284 host->prog_enable = 0;
1285 }
1286 if (cmd->data && cmd->error) {
1287 msmsdcc_reset_and_restore(host);
1288 if (host->plat->dummy52_required &&
1289 host->dummy_52_needed)
1290 host->dummy_52_needed = 0;
Sahitya Tummalad5137bd2010-12-08 15:03:04 +05301291 }
1292 msmsdcc_request_end(host, cmd->mrq);
1293 }
1294 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001295 } else if (cmd->data) {
San Mehat56a8b5b2009-11-21 12:29:46 -08001296 if (!(cmd->data->flags & MMC_DATA_READ))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001297 msmsdcc_start_data(host, cmd->data, NULL, 0);
Joe Perchesb5a74d62009-09-22 16:44:25 -07001298 }
1299}
1300
San Mehat9d2bd732009-09-22 16:44:22 -07001301static irqreturn_t
1302msmsdcc_irq(int irq, void *dev_id)
1303{
1304 struct msmsdcc_host *host = dev_id;
San Mehat9d2bd732009-09-22 16:44:22 -07001305 u32 status;
1306 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001307 int timer = 0;
San Mehat9d2bd732009-09-22 16:44:22 -07001308
1309 spin_lock(&host->lock);
1310
1311 do {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001312 struct mmc_command *cmd;
1313 struct mmc_data *data;
San Mehat9d2bd732009-09-22 16:44:22 -07001314
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001315 if (timer) {
1316 timer = 0;
1317 msmsdcc_delay(host);
1318 }
San Mehat865c8062009-11-13 13:42:06 -08001319
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001320 if (!host->clks_on) {
1321 pr_debug("%s: %s: SDIO async irq received\n",
1322 mmc_hostname(host->mmc), __func__);
1323 host->mmc->ios.clock = host->clk_rate;
1324 spin_unlock(&host->lock);
1325 host->mmc->ops->set_ios(host->mmc, &host->mmc->ios);
1326 spin_lock(&host->lock);
1327 if (host->plat->cfg_mpm_sdiowakeup &&
1328 (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1329 wake_lock(&host->sdio_wlock);
1330 /* only ansyc interrupt can come when clocks are off */
1331 writel_relaxed(MCI_SDIOINTMASK, host->base + MMCICLEAR);
1332 }
1333
1334 status = readl_relaxed(host->base + MMCISTATUS);
1335
1336 if (((readl_relaxed(host->base + MMCIMASK0) & status) &
1337 (~(MCI_IRQ_PIO))) == 0)
San Mehat865c8062009-11-13 13:42:06 -08001338 break;
San Mehat9d2bd732009-09-22 16:44:22 -07001339
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001340#if IRQ_DEBUG
1341 msmsdcc_print_status(host, "irq0-r", status);
1342#endif
1343 status &= readl_relaxed(host->base + MMCIMASK0);
1344 writel_relaxed(status, host->base + MMCICLEAR);
1345 mb();
1346#if IRQ_DEBUG
1347 msmsdcc_print_status(host, "irq0-p", status);
1348#endif
1349#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
1350 if (status & MCI_SDIOINTROPE) {
1351 if (host->sdcc_suspending)
1352 wake_lock(&host->sdio_suspend_wlock);
1353 mmc_signal_sdio_irq(host->mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07001354 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001355#endif
1356 if ((host->plat->dummy52_required) &&
1357 (host->dummy_52_state == DUMMY_52_STATE_SENT)) {
1358 if (status & (MCI_PROGDONE | MCI_CMDCRCFAIL |
1359 MCI_CMDTIMEOUT)) {
1360 if (status & MCI_CMDTIMEOUT)
1361 pr_debug("%s: dummy CMD52 timeout\n",
1362 mmc_hostname(host->mmc));
1363 if (status & MCI_CMDCRCFAIL)
1364 pr_debug("%s: dummy CMD52 CRC failed\n",
1365 mmc_hostname(host->mmc));
1366 host->dummy_52_state = DUMMY_52_STATE_NONE;
1367 host->curr.cmd = NULL;
1368 msmsdcc_request_start(host, host->curr.mrq);
1369 spin_unlock(&host->lock);
1370 return IRQ_HANDLED;
1371 }
1372 break;
1373 }
1374
1375 data = host->curr.data;
1376
1377 /*
1378 * Check for proper command response
1379 */
1380 cmd = host->curr.cmd;
1381 if ((status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
1382 MCI_CMDTIMEOUT | MCI_PROGDONE |
1383 MCI_AUTOCMD19TIMEOUT)) && host->curr.cmd) {
1384 msmsdcc_do_cmdirq(host, status);
1385 }
1386
1387 if (data) {
1388 /* Check for data errors */
1389 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|
1390 MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
1391 msmsdcc_data_err(host, data, status);
1392 host->curr.data_xfered = 0;
1393 if (host->dma.sg && host->is_dma_mode)
1394 msm_dmov_stop_cmd(host->dma.channel,
1395 &host->dma.hdr, 0);
1396 else if (host->sps.sg && host->is_sps_mode) {
1397 /* Stop current SPS transfer */
1398 msmsdcc_sps_exit_curr_xfer(host);
1399 }
1400 else {
1401 msmsdcc_reset_and_restore(host);
1402 if (host->curr.data)
1403 msmsdcc_stop_data(host);
1404 if (!data->stop)
1405 timer |=
1406 msmsdcc_request_end(host,
1407 data->mrq);
1408 else {
1409 msmsdcc_start_command(host,
1410 data->stop,
1411 0);
1412 timer = 1;
1413 }
1414 }
1415 }
1416
1417 /* Check for data done */
1418 if (!host->curr.got_dataend && (status & MCI_DATAEND))
1419 host->curr.got_dataend = 1;
1420
1421 if (host->curr.got_dataend) {
1422 /*
1423 * If DMA is still in progress, we complete
1424 * via the completion handler
1425 */
1426 if (!host->dma.busy && !host->sps.busy) {
1427 /*
1428 * There appears to be an issue in the
1429 * controller where if you request a
1430 * small block transfer (< fifo size),
1431 * you may get your DATAEND/DATABLKEND
1432 * irq without the PIO data irq.
1433 *
1434 * Check to see if theres still data
1435 * to be read, and simulate a PIO irq.
1436 */
1437 if (data->flags & MMC_DATA_READ)
1438 msmsdcc_wait_for_rxdata(host,
1439 data);
1440 msmsdcc_stop_data(host);
1441 if (!data->error) {
1442 host->curr.data_xfered =
1443 host->curr.xfer_size;
1444 host->curr.xfer_remain -=
1445 host->curr.xfer_size;
1446 }
1447
1448 if (!data->stop)
1449 timer |= msmsdcc_request_end(
1450 host, data->mrq);
1451 else {
1452 msmsdcc_start_command(host,
1453 data->stop, 0);
1454 timer = 1;
1455 }
1456 }
1457 }
1458 }
1459
San Mehat9d2bd732009-09-22 16:44:22 -07001460 ret = 1;
1461 } while (status);
1462
1463 spin_unlock(&host->lock);
1464
San Mehat9d2bd732009-09-22 16:44:22 -07001465 return IRQ_RETVAL(ret);
1466}
1467
1468static void
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001469msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
1470{
1471 if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
1472 /* Queue/read data, daisy-chain command when data starts */
1473 msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
1474 } else {
1475 msmsdcc_start_command(host, mrq->cmd, 0);
1476 }
1477}
1478
1479static void
San Mehat9d2bd732009-09-22 16:44:22 -07001480msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
1481{
1482 struct msmsdcc_host *host = mmc_priv(mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001483 unsigned long flags;
San Mehat9d2bd732009-09-22 16:44:22 -07001484
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001485 /*
1486 * Get the SDIO AL client out of LPM.
1487 */
1488 if (host->plat->is_sdio_al_client)
1489 msmsdcc_sdio_al_lpm(mmc, false);
San Mehat9d2bd732009-09-22 16:44:22 -07001490
1491 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001492 WARN(host->curr.mrq, "Request in progress\n");
1493 WARN(!host->pwr, "SDCC power is turned off\n");
1494 WARN(!host->clks_on, "SDCC clocks are turned off\n");
1495 WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
San Mehat9d2bd732009-09-22 16:44:22 -07001496
1497 if (host->eject) {
1498 if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) {
1499 mrq->cmd->error = 0;
1500 mrq->data->bytes_xfered = mrq->data->blksz *
1501 mrq->data->blocks;
1502 } else
1503 mrq->cmd->error = -ENOMEDIUM;
1504
1505 spin_unlock_irqrestore(&host->lock, flags);
1506 mmc_request_done(mmc, mrq);
1507 return;
1508 }
1509
1510 host->curr.mrq = mrq;
1511
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001512 if (host->plat->dummy52_required) {
1513 if (host->dummy_52_needed) {
1514 host->dummy_52_state = DUMMY_52_STATE_SENT;
1515 msmsdcc_start_command(host, &dummy52cmd,
1516 MCI_CPSM_PROGENA);
1517 spin_unlock_irqrestore(&host->lock, flags);
1518 if (mrq->data && mrq->data->flags == MMC_DATA_WRITE) {
1519 if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
1520 mrq->cmd->opcode == 54)
1521 host->dummy_52_needed = 1;
1522 } else {
1523 host->dummy_52_needed = 0;
1524 }
1525 return;
1526 }
1527 if (mrq->data && mrq->data->flags == MMC_DATA_WRITE) {
1528 if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
1529 mrq->cmd->opcode == 54)
1530 host->dummy_52_needed = 1;
1531 }
San Mehat9d2bd732009-09-22 16:44:22 -07001532 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001533 msmsdcc_request_start(host, mrq);
San Mehat9d2bd732009-09-22 16:44:22 -07001534 spin_unlock_irqrestore(&host->lock, flags);
1535}
1536
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001537static inline int msmsdcc_vreg_set_voltage(struct msm_mmc_reg_data *vreg,
1538 int min_uV, int max_uV)
1539{
1540 int rc = 0;
1541
1542 if (vreg->set_voltage_sup) {
1543 rc = regulator_set_voltage(vreg->reg, min_uV, max_uV);
1544 if (rc) {
1545 pr_err("%s: regulator_set_voltage(%s) failed."
1546 " min_uV=%d, max_uV=%d, rc=%d\n",
1547 __func__, vreg->name, min_uV, max_uV, rc);
1548 }
1549 }
1550
1551 return rc;
1552}
1553
1554static inline int msmsdcc_vreg_set_optimum_mode(struct msm_mmc_reg_data *vreg,
1555 int uA_load)
1556{
1557 int rc = 0;
1558
1559 rc = regulator_set_optimum_mode(vreg->reg, uA_load);
1560 if (rc < 0)
1561 pr_err("%s: regulator_set_optimum_mode(reg=%s, uA_load=%d)"
1562 " failed. rc=%d\n", __func__, vreg->name,
1563 uA_load, rc);
1564 else
1565 /* regulator_set_optimum_mode() can return non zero value
1566 * even for success case.
1567 */
1568 rc = 0;
1569
1570 return rc;
1571}
1572
1573static inline int msmsdcc_vreg_init_reg(struct msm_mmc_reg_data *vreg,
1574 struct device *dev)
1575{
1576 int rc = 0;
1577
1578 /* check if regulator is already initialized? */
1579 if (vreg->reg)
1580 goto out;
1581
1582 /* Get the regulator handle */
1583 vreg->reg = regulator_get(dev, vreg->name);
1584 if (IS_ERR(vreg->reg)) {
1585 rc = PTR_ERR(vreg->reg);
1586 pr_err("%s: regulator_get(%s) failed. rc=%d\n",
1587 __func__, vreg->name, rc);
1588 }
1589out:
1590 return rc;
1591}
1592
1593static inline void msmsdcc_vreg_deinit_reg(struct msm_mmc_reg_data *vreg)
1594{
1595 if (vreg->reg)
1596 regulator_put(vreg->reg);
1597}
1598
1599/* This init function should be called only once for each SDCC slot */
1600static int msmsdcc_vreg_init(struct msmsdcc_host *host, bool is_init)
1601{
1602 int rc = 0;
1603 struct msm_mmc_slot_reg_data *curr_slot;
1604 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1605 struct device *dev = mmc_dev(host->mmc);
1606
1607 curr_slot = host->plat->vreg_data;
1608 if (!curr_slot)
1609 goto out;
1610
1611 curr_vdd_reg = curr_slot->vdd_data;
1612 curr_vccq_reg = curr_slot->vccq_data;
1613 curr_vddp_reg = curr_slot->vddp_data;
1614
1615 if (is_init) {
1616 /*
1617 * Get the regulator handle from voltage regulator framework
1618 * and then try to set the voltage level for the regulator
1619 */
1620 if (curr_vdd_reg) {
1621 rc = msmsdcc_vreg_init_reg(curr_vdd_reg, dev);
1622 if (rc)
1623 goto out;
1624 }
1625 if (curr_vccq_reg) {
1626 rc = msmsdcc_vreg_init_reg(curr_vccq_reg, dev);
1627 if (rc)
1628 goto vdd_reg_deinit;
1629 }
1630 if (curr_vddp_reg) {
1631 rc = msmsdcc_vreg_init_reg(curr_vddp_reg, dev);
1632 if (rc)
1633 goto vccq_reg_deinit;
1634 }
1635 goto out;
1636 } else {
1637 /* Deregister all regulators from regulator framework */
1638 goto vddp_reg_deinit;
1639 }
1640vddp_reg_deinit:
1641 if (curr_vddp_reg)
1642 msmsdcc_vreg_deinit_reg(curr_vddp_reg);
1643vccq_reg_deinit:
1644 if (curr_vccq_reg)
1645 msmsdcc_vreg_deinit_reg(curr_vccq_reg);
1646vdd_reg_deinit:
1647 if (curr_vdd_reg)
1648 msmsdcc_vreg_deinit_reg(curr_vdd_reg);
1649out:
1650 return rc;
1651}
1652
1653static int msmsdcc_vreg_enable(struct msm_mmc_reg_data *vreg)
1654{
1655 int rc = 0;
1656
1657 if (!vreg->is_enabled) {
1658 /* Set voltage level */
1659 rc = msmsdcc_vreg_set_voltage(vreg, vreg->level,
1660 vreg->level);
1661 if (rc)
1662 goto out;
1663
1664 rc = regulator_enable(vreg->reg);
1665 if (rc) {
1666 pr_err("%s: regulator_enable(%s) failed. rc=%d\n",
1667 __func__, vreg->name, rc);
1668 goto out;
1669 }
1670 vreg->is_enabled = true;
1671 }
1672
1673 /* Put regulator in HPM (high power mode) */
1674 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->hpm_uA);
1675 if (rc < 0)
1676 goto vreg_disable;
1677
1678 goto out;
1679
1680vreg_disable:
1681 regulator_disable(vreg->reg);
1682 vreg->is_enabled = false;
1683out:
1684 return rc;
1685}
1686
1687static int msmsdcc_vreg_disable(struct msm_mmc_reg_data *vreg)
1688{
1689 int rc = 0;
1690
1691 /* Never disable regulator marked as always_on */
1692 if (vreg->is_enabled && !vreg->always_on) {
1693 rc = regulator_disable(vreg->reg);
1694 if (rc) {
1695 pr_err("%s: regulator_disable(%s) failed. rc=%d\n",
1696 __func__, vreg->name, rc);
1697 goto out;
1698 }
1699 vreg->is_enabled = false;
1700
1701 rc = msmsdcc_vreg_set_optimum_mode(vreg, 0);
1702 if (rc < 0)
1703 goto out;
1704
1705 /* Set min. voltage level to 0 */
1706 rc = msmsdcc_vreg_set_voltage(vreg, 0, vreg->level);
1707 if (rc)
1708 goto out;
1709 } else if (vreg->is_enabled && vreg->always_on && vreg->lpm_sup) {
1710 /* Put always_on regulator in LPM (low power mode) */
1711 rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->lpm_uA);
1712 if (rc < 0)
1713 goto out;
1714 }
1715out:
1716 return rc;
1717}
1718
1719static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable)
1720{
1721 int rc = 0, i;
1722 struct msm_mmc_slot_reg_data *curr_slot;
1723 struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
1724 struct msm_mmc_reg_data *vreg_table[3];
1725
1726 curr_slot = host->plat->vreg_data;
1727 if (!curr_slot)
1728 goto out;
1729
1730 curr_vdd_reg = vreg_table[0] = curr_slot->vdd_data;
1731 curr_vccq_reg = vreg_table[1] = curr_slot->vccq_data;
1732 curr_vddp_reg = vreg_table[2] = curr_slot->vddp_data;
1733
1734 for (i = 0; i < ARRAY_SIZE(vreg_table); i++) {
1735 if (vreg_table[i]) {
1736 if (enable)
1737 rc = msmsdcc_vreg_enable(vreg_table[i]);
1738 else
1739 rc = msmsdcc_vreg_disable(vreg_table[i]);
1740 if (rc)
1741 goto out;
1742 }
1743 }
1744out:
1745 return rc;
1746}
1747
1748static int msmsdcc_tune_vdd_pad_level(struct msmsdcc_host *host, int level)
1749{
1750 int rc = 0;
1751
1752 if (host->plat->vreg_data) {
1753 struct msm_mmc_reg_data *vddp_reg =
1754 host->plat->vreg_data->vddp_data;
1755
1756 if (vddp_reg && vddp_reg->is_enabled)
1757 rc = msmsdcc_vreg_set_voltage(vddp_reg, level, level);
1758 }
1759
1760 return rc;
1761}
1762
1763static inline int msmsdcc_is_pwrsave(struct msmsdcc_host *host)
1764{
1765 if (host->clk_rate > 400000 && msmsdcc_pwrsave)
1766 return 1;
1767 return 0;
1768}
1769
1770static inline void msmsdcc_setup_clocks(struct msmsdcc_host *host, bool enable)
1771{
1772 if (enable) {
1773 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1774 clk_enable(host->dfab_pclk);
1775 if (!IS_ERR(host->pclk))
1776 clk_enable(host->pclk);
1777 clk_enable(host->clk);
1778 } else {
1779 clk_disable(host->clk);
1780 if (!IS_ERR(host->pclk))
1781 clk_disable(host->pclk);
1782 if (!IS_ERR_OR_NULL(host->dfab_pclk))
1783 clk_disable(host->dfab_pclk);
1784 }
1785}
1786
1787static inline unsigned int msmsdcc_get_sup_clk_rate(struct msmsdcc_host *host,
1788 unsigned int req_clk)
1789{
1790 unsigned int sel_clk = -1;
1791
1792 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt) {
1793 unsigned char cnt;
1794
1795 for (cnt = 0; cnt < host->plat->sup_clk_cnt; cnt++) {
1796 if (host->plat->sup_clk_table[cnt] > req_clk)
1797 break;
1798 else if (host->plat->sup_clk_table[cnt] == req_clk) {
1799 sel_clk = host->plat->sup_clk_table[cnt];
1800 break;
1801 } else
1802 sel_clk = host->plat->sup_clk_table[cnt];
1803 }
1804 } else {
1805 if ((req_clk < host->plat->msmsdcc_fmax) &&
1806 (req_clk > host->plat->msmsdcc_fmid))
1807 sel_clk = host->plat->msmsdcc_fmid;
1808 else
1809 sel_clk = req_clk;
1810 }
1811
1812 return sel_clk;
1813}
1814
1815static inline unsigned int msmsdcc_get_min_sup_clk_rate(
1816 struct msmsdcc_host *host)
1817{
1818 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1819 return host->plat->sup_clk_table[0];
1820 else
1821 return host->plat->msmsdcc_fmin;
1822}
1823
1824static inline unsigned int msmsdcc_get_max_sup_clk_rate(
1825 struct msmsdcc_host *host)
1826{
1827 if (host->plat->sup_clk_table && host->plat->sup_clk_cnt)
1828 return host->plat->sup_clk_table[host->plat->sup_clk_cnt - 1];
1829 else
1830 return host->plat->msmsdcc_fmax;
1831}
1832
1833static int msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
Sahitya Tummala7a892482011-01-18 11:22:49 +05301834{
1835 struct msm_mmc_gpio_data *curr;
1836 int i, rc = 0;
1837
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001838 curr = host->plat->pin_data->gpio_data;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301839 for (i = 0; i < curr->size; i++) {
1840 if (enable) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001841 if (curr->gpio[i].is_always_on &&
1842 curr->gpio[i].is_enabled)
1843 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301844 rc = gpio_request(curr->gpio[i].no,
1845 curr->gpio[i].name);
1846 if (rc) {
1847 pr_err("%s: gpio_request(%d, %s) failed %d\n",
1848 mmc_hostname(host->mmc),
1849 curr->gpio[i].no,
1850 curr->gpio[i].name, rc);
1851 goto free_gpios;
1852 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001853 curr->gpio[i].is_enabled = true;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301854 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001855 if (curr->gpio[i].is_always_on)
1856 continue;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301857 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001858 curr->gpio[i].is_enabled = false;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301859 }
1860 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001861 goto out;
Sahitya Tummala7a892482011-01-18 11:22:49 +05301862
1863free_gpios:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001864 for (; i >= 0; i--) {
Sahitya Tummala7a892482011-01-18 11:22:49 +05301865 gpio_free(curr->gpio[i].no);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001866 curr->gpio[i].is_enabled = false;
1867 }
1868out:
1869 return rc;
1870}
1871
1872static int msmsdcc_setup_pad(struct msmsdcc_host *host, bool enable)
1873{
1874 struct msm_mmc_pad_data *curr;
1875 int i;
1876
1877 curr = host->plat->pin_data->pad_data;
1878 for (i = 0; i < curr->drv->size; i++) {
1879 if (enable)
1880 msm_tlmm_set_hdrive(curr->drv->on[i].no,
1881 curr->drv->on[i].val);
1882 else
1883 msm_tlmm_set_hdrive(curr->drv->off[i].no,
1884 curr->drv->off[i].val);
1885 }
1886
1887 for (i = 0; i < curr->pull->size; i++) {
1888 if (enable)
1889 msm_tlmm_set_hdrive(curr->pull->on[i].no,
1890 curr->pull->on[i].val);
1891 else
1892 msm_tlmm_set_hdrive(curr->pull->off[i].no,
1893 curr->pull->off[i].val);
1894 }
1895
1896 return 0;
1897}
1898
1899static u32 msmsdcc_setup_pins(struct msmsdcc_host *host, bool enable)
1900{
1901 int rc = 0;
1902
1903 if (!host->plat->pin_data || host->plat->pin_data->cfg_sts == enable)
1904 return 0;
1905
1906 if (host->plat->pin_data->is_gpio)
1907 rc = msmsdcc_setup_gpio(host, enable);
1908 else
1909 rc = msmsdcc_setup_pad(host, enable);
1910
1911 if (!rc)
1912 host->plat->pin_data->cfg_sts = enable;
1913
1914 return rc;
1915}
1916
1917static void msmsdcc_enable_irq_wake(struct msmsdcc_host *host)
1918{
1919 unsigned int wakeup_irq;
1920
1921 wakeup_irq = (host->plat->sdiowakeup_irq) ?
1922 host->plat->sdiowakeup_irq :
1923 host->core_irqres->start;
1924
1925 if (!host->irq_wake_enabled) {
1926 enable_irq_wake(wakeup_irq);
1927 host->irq_wake_enabled = true;
1928 }
1929}
1930
1931static void msmsdcc_disable_irq_wake(struct msmsdcc_host *host)
1932{
1933 unsigned int wakeup_irq;
1934
1935 wakeup_irq = (host->plat->sdiowakeup_irq) ?
1936 host->plat->sdiowakeup_irq :
1937 host->core_irqres->start;
1938
1939 if (host->irq_wake_enabled) {
1940 disable_irq_wake(wakeup_irq);
1941 host->irq_wake_enabled = false;
1942 }
Sahitya Tummala7a892482011-01-18 11:22:49 +05301943}
1944
San Mehat9d2bd732009-09-22 16:44:22 -07001945static void
1946msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1947{
1948 struct msmsdcc_host *host = mmc_priv(mmc);
1949 u32 clk = 0, pwr = 0;
1950 int rc;
San Mehat4adbbcc2009-11-08 13:00:37 -08001951 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001952 unsigned int clock;
San Mehat9d2bd732009-09-22 16:44:22 -07001953
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001954 DBG(host, "ios->clock = %u\n", ios->clock);
Sahitya Tummala7a892482011-01-18 11:22:49 +05301955
San Mehat9d2bd732009-09-22 16:44:22 -07001956 if (ios->clock) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001957 spin_lock_irqsave(&host->lock, flags);
1958 if (!host->clks_on) {
1959 msmsdcc_setup_clocks(host, true);
1960 host->clks_on = 1;
1961 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
1962 if (!host->plat->sdiowakeup_irq) {
1963 writel_relaxed(host->mci_irqenable,
1964 host->base + MMCIMASK0);
1965 mb();
1966 if (host->plat->cfg_mpm_sdiowakeup &&
1967 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
1968 host->plat->cfg_mpm_sdiowakeup(
1969 mmc_dev(mmc), SDC_DAT1_DISWAKE);
1970 msmsdcc_disable_irq_wake(host);
1971 } else if (!(mmc->pm_flags &
1972 MMC_PM_WAKE_SDIO_IRQ)) {
1973 writel_relaxed(host->mci_irqenable,
1974 host->base + MMCIMASK0);
1975 }
1976 }
San Mehat9d2bd732009-09-22 16:44:22 -07001977 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001978 spin_unlock_irqrestore(&host->lock, flags);
1979
1980 clock = msmsdcc_get_sup_clk_rate(host, ios->clock);
1981 /*
1982 * For DDR50 mode, controller needs clock rate to be
1983 * double than what is required on the SD card CLK pin.
1984 */
1985 if (ios->timing == MMC_TIMING_UHS_DDR50) {
1986 /*
1987 * Make sure that we don't double the clock if
1988 * doubled clock rate is already set
1989 */
1990 if (!host->ddr_doubled_clk_rate ||
1991 (host->ddr_doubled_clk_rate &&
1992 (host->ddr_doubled_clk_rate != ios->clock))) {
1993 host->ddr_doubled_clk_rate =
1994 msmsdcc_get_sup_clk_rate(
1995 host, (ios->clock * 2));
1996 clock = host->ddr_doubled_clk_rate;
1997 }
1998 } else {
1999 host->ddr_doubled_clk_rate = 0;
2000 }
2001
2002 if (clock != host->clk_rate) {
2003 rc = clk_set_rate(host->clk, clock);
2004 if (rc < 0)
2005 pr_debug("%s: failed to set clk rate %u\n",
2006 mmc_hostname(mmc), clock);
2007 host->clk_rate = clock;
2008 }
2009 /*
2010 * give atleast 2 MCLK cycles delay for clocks
2011 * and SDCC core to stabilize
2012 */
2013 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002014 clk |= MCI_CLK_ENABLE;
2015 }
2016
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002017 if (ios->bus_width == MMC_BUS_WIDTH_8)
2018 clk |= MCI_CLK_WIDEBUS_8;
2019 else if (ios->bus_width == MMC_BUS_WIDTH_4)
2020 clk |= MCI_CLK_WIDEBUS_4;
2021 else
2022 clk |= MCI_CLK_WIDEBUS_1;
San Mehat9d2bd732009-09-22 16:44:22 -07002023
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002024 if (msmsdcc_is_pwrsave(host))
2025 clk |= MCI_CLK_PWRSAVE;
San Mehat9d2bd732009-09-22 16:44:22 -07002026
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002027 clk |= MCI_CLK_FLOWENA;
San Mehat9d2bd732009-09-22 16:44:22 -07002028
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002029 host->tuning_needed = 0;
2030 /*
2031 * Select the controller timing mode according
2032 * to current bus speed mode
2033 */
2034 if ((ios->timing == MMC_TIMING_UHS_SDR104) ||
2035 (ios->timing == MMC_TIMING_UHS_SDR50)) {
2036 clk |= (4 << 14);
2037 host->tuning_needed = 1;
2038 } else if (ios->timing == MMC_TIMING_UHS_DDR50) {
2039 clk |= (3 << 14);
2040 } else {
2041 clk |= (2 << 14); /* feedback clock */
2042 }
2043
2044 /* Select free running MCLK as input clock of cm_dll_sdc4 */
2045 clk |= (2 << 23);
2046
2047 if (host->io_pad_pwr_switch)
2048 clk |= IO_PAD_PWR_SWITCH;
2049
2050 if (host->plat->translate_vdd && !host->sdio_gpio_lpm)
San Mehat9d2bd732009-09-22 16:44:22 -07002051 pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002052 else if (!host->plat->translate_vdd && !host->sdio_gpio_lpm)
2053 pwr |= msmsdcc_setup_vreg(host, !!ios->vdd);
San Mehat9d2bd732009-09-22 16:44:22 -07002054
2055 switch (ios->power_mode) {
2056 case MMC_POWER_OFF:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002057 htc_pwrsink_set(PWRSINK_SDCARD, 0);
2058 if (!host->sdcc_irq_disabled) {
2059 if (host->plat->cfg_mpm_sdiowakeup)
2060 host->plat->cfg_mpm_sdiowakeup(
2061 mmc_dev(mmc), SDC_DAT1_DISABLE);
2062 disable_irq(host->core_irqres->start);
2063 host->sdcc_irq_disabled = 1;
2064 }
2065 msmsdcc_setup_pins(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07002066 break;
2067 case MMC_POWER_UP:
2068 pwr |= MCI_PWR_UP;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002069 if (host->sdcc_irq_disabled) {
2070 if (host->plat->cfg_mpm_sdiowakeup)
2071 host->plat->cfg_mpm_sdiowakeup(
2072 mmc_dev(mmc), SDC_DAT1_ENABLE);
2073 enable_irq(host->core_irqres->start);
2074 host->sdcc_irq_disabled = 0;
2075 }
2076 msmsdcc_setup_pins(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07002077 break;
2078 case MMC_POWER_ON:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002079 htc_pwrsink_set(PWRSINK_SDCARD, 100);
San Mehat9d2bd732009-09-22 16:44:22 -07002080 pwr |= MCI_PWR_ON;
2081 break;
2082 }
2083
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002084 spin_lock_irqsave(&host->lock, flags);
2085 if (!host->clks_on) {
2086 /* force the clocks to be on */
2087 msmsdcc_setup_clocks(host, true);
2088 /*
2089 * give atleast 2 MCLK cycles delay for clocks
2090 * and SDCC core to stabilize
2091 */
2092 msmsdcc_delay(host);
2093 }
2094 writel_relaxed(clk, host->base + MMCICLOCK);
2095 msmsdcc_delay(host);
San Mehat9d2bd732009-09-22 16:44:22 -07002096
2097 if (host->pwr != pwr) {
2098 host->pwr = pwr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002099 writel_relaxed(pwr, host->base + MMCIPOWER);
2100 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07002101 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002102 if (!host->clks_on) {
2103 /* force the clocks to be off */
2104 msmsdcc_setup_clocks(host, false);
2105 /*
2106 * give atleast 2 MCLK cycles delay for clocks
2107 * and SDCC core to stabilize
2108 */
2109 msmsdcc_delay(host);
2110 }
2111
2112 if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
2113 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
2114 if (!host->plat->sdiowakeup_irq) {
2115 writel_relaxed(MCI_SDIOINTMASK,
2116 host->base + MMCIMASK0);
2117 mb();
2118 if (host->plat->cfg_mpm_sdiowakeup &&
2119 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
2120 host->plat->cfg_mpm_sdiowakeup(
2121 mmc_dev(mmc), SDC_DAT1_ENWAKE);
2122 msmsdcc_enable_irq_wake(host);
2123 } else if (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2124 writel_relaxed(0, host->base + MMCIMASK0);
2125 } else {
2126 writel_relaxed(MCI_SDIOINTMASK,
2127 host->base + MMCIMASK0);
2128 }
2129 msmsdcc_delay(host);
2130 }
2131 msmsdcc_setup_clocks(host, false);
2132 host->clks_on = 0;
2133 }
San Mehat4adbbcc2009-11-08 13:00:37 -08002134 spin_unlock_irqrestore(&host->lock, flags);
San Mehat9d2bd732009-09-22 16:44:22 -07002135}
2136
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002137int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave)
2138{
2139 struct msmsdcc_host *host = mmc_priv(mmc);
2140 u32 clk;
2141
2142 clk = readl_relaxed(host->base + MMCICLOCK);
2143 pr_debug("Changing to pwr_save=%d", pwrsave);
2144 if (pwrsave && msmsdcc_is_pwrsave(host))
2145 clk |= MCI_CLK_PWRSAVE;
2146 else
2147 clk &= ~MCI_CLK_PWRSAVE;
2148 writel_relaxed(clk, host->base + MMCICLOCK);
2149 mb();
2150
2151 return 0;
2152}
2153
2154static int msmsdcc_get_ro(struct mmc_host *mmc)
2155{
2156 int status = -ENOSYS;
2157 struct msmsdcc_host *host = mmc_priv(mmc);
2158
2159 if (host->plat->wpswitch) {
2160 status = host->plat->wpswitch(mmc_dev(mmc));
2161 } else if (host->plat->wpswitch_gpio) {
2162 status = gpio_request(host->plat->wpswitch_gpio,
2163 "SD_WP_Switch");
2164 if (status) {
2165 pr_err("%s: %s: Failed to request GPIO %d\n",
2166 mmc_hostname(mmc), __func__,
2167 host->plat->wpswitch_gpio);
2168 } else {
2169 status = gpio_direction_input(
2170 host->plat->wpswitch_gpio);
2171 if (!status) {
2172 /*
2173 * Wait for atleast 300ms as debounce
2174 * time for GPIO input to stabilize.
2175 */
2176 msleep(300);
2177 status = gpio_get_value_cansleep(
2178 host->plat->wpswitch_gpio);
2179 status ^= !host->plat->wpswitch_polarity;
2180 }
2181 gpio_free(host->plat->wpswitch_gpio);
2182 }
2183 }
2184
2185 if (status < 0)
2186 status = -ENOSYS;
2187 pr_debug("%s: Card read-only status %d\n", __func__, status);
2188
2189 return status;
2190}
2191
2192#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002193static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
2194{
2195 struct msmsdcc_host *host = mmc_priv(mmc);
2196 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002197
2198 if (enable) {
2199 spin_lock_irqsave(&host->lock, flags);
2200 host->mci_irqenable |= MCI_SDIOINTOPERMASK;
2201 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) |
2202 MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2203 spin_unlock_irqrestore(&host->lock, flags);
2204 } else {
2205 host->mci_irqenable &= ~MCI_SDIOINTOPERMASK;
2206 writel_relaxed(readl_relaxed(host->base + MMCIMASK0) &
2207 ~MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
2208 }
2209 mb();
2210}
2211#endif /* CONFIG_MMC_MSM_SDIO_SUPPORT */
2212
2213#ifdef CONFIG_PM_RUNTIME
2214static int msmsdcc_enable(struct mmc_host *mmc)
2215{
2216 int rc;
2217 struct device *dev = mmc->parent;
2218
2219 if (atomic_read(&dev->power.usage_count) > 0) {
2220 pm_runtime_get_noresume(dev);
2221 goto out;
2222 }
2223
2224 rc = pm_runtime_get_sync(dev);
2225
2226 if (rc < 0) {
2227 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2228 __func__, rc);
2229 return rc;
2230 }
2231out:
2232 return 0;
2233}
2234
2235static int msmsdcc_disable(struct mmc_host *mmc, int lazy)
2236{
2237 int rc;
2238
2239 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO)
2240 return -ENOTSUPP;
2241
2242 rc = pm_runtime_put_sync(mmc->parent);
2243
2244 if (rc < 0)
2245 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
2246 __func__, rc);
2247 return rc;
2248}
2249#else
2250#define msmsdcc_enable NULL
2251#define msmsdcc_disable NULL
2252#endif
2253
2254static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
2255 struct mmc_ios *ios)
2256{
2257 struct msmsdcc_host *host = mmc_priv(mmc);
2258 unsigned long flags;
2259 int err = 0;
2260
2261 if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
2262 /* Change voltage level of VDDPX to high voltage */
2263 if (msmsdcc_tune_vdd_pad_level(host, 2950000)) {
2264 pr_err("%s: %s: failed to change vddp level to %d",
2265 mmc_hostname(mmc), __func__, 2950000);
2266 }
2267 goto out;
2268 } else if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
2269 /* invalid selection. don't do anything */
2270 goto out;
2271 }
San Mehat9d2bd732009-09-22 16:44:22 -07002272
2273 spin_lock_irqsave(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002274 /*
2275 * If we are here means voltage switch from high voltage to
2276 * low voltage is required
2277 */
2278
2279 /*
2280 * Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
2281 * register until they become all zeros.
2282 */
2283 if (readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1)) {
2284 err = -EAGAIN;
2285 pr_err("%s: %s: MCIDATIN_3_0 is still not all zeros",
2286 mmc_hostname(mmc), __func__);
2287 goto out_unlock;
San Mehat9d2bd732009-09-22 16:44:22 -07002288 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002289
2290 /* Stop SD CLK output. */
2291 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2292 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2293
San Mehat9d2bd732009-09-22 16:44:22 -07002294 spin_unlock_irqrestore(&host->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002295
2296 /*
2297 * Switch VDDPX from high voltage to low voltage
2298 * to change the VDD of the SD IO pads.
2299 */
2300 if (msmsdcc_tune_vdd_pad_level(host, 1850000)) {
2301 pr_err("%s: %s: failed to change vddp level to %d",
2302 mmc_hostname(mmc), __func__, 1850000);
2303 goto out;
2304 }
2305
2306 spin_lock_irqsave(&host->lock, flags);
2307 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2308 IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
2309 host->io_pad_pwr_switch = 1;
2310 spin_unlock_irqrestore(&host->lock, flags);
2311
2312 /* Wait 5 ms for the voltage regulater in the card to become stable. */
2313 usleep_range(5000, 5500);
2314
2315 spin_lock_irqsave(&host->lock, flags);
2316 /* Start SD CLK output. */
2317 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2318 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2319 spin_unlock_irqrestore(&host->lock, flags);
2320
2321 /*
2322 * If MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT register
2323 * don't become all ones within 1 ms then a Voltage Switch
2324 * sequence has failed and a power cycle to the card is required.
2325 * Otherwise Voltage Switch sequence is completed successfully.
2326 */
2327 usleep_range(1000, 1500);
2328
2329 spin_lock_irqsave(&host->lock, flags);
2330 if ((readl_relaxed(host->base + MCI_TEST_INPUT) & (0xF << 1))
2331 != (0xF << 1)) {
2332 pr_err("%s: %s: MCIDATIN_3_0 are still not all ones",
2333 mmc_hostname(mmc), __func__);
2334 err = -EAGAIN;
2335 goto out_unlock;
2336 }
2337
2338out_unlock:
2339 spin_unlock_irqrestore(&host->lock, flags);
2340out:
2341 return err;
2342}
2343
2344static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2345 u8 phase);
2346/* Initialize the DLL (Programmable Delay Line ) */
2347static int msmsdcc_init_cm_sdc4_dll(struct msmsdcc_host *host)
2348{
2349 int rc = 0;
2350 u32 wait_timeout;
2351
2352 /* Write 0 to DLL_PDN bit of MCI_DLL_CONFIG register */
2353 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2354 & ~MCI_DLL_PDN), host->base + MCI_DLL_CONFIG);
2355
2356 /* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
2357 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2358 | MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2359
2360 msmsdcc_delay(host);
2361
2362 /* Write 0 to DLL_RST bit of MCI_DLL_CONFIG register */
2363 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2364 & ~MCI_DLL_RST), host->base + MCI_DLL_CONFIG);
2365
2366 /* Initialize the phase to 0 */
2367 rc = msmsdcc_config_cm_sdc4_dll_phase(host, 0);
2368 if (rc)
2369 goto out;
2370
2371 wait_timeout = 1000;
2372 /* Wait until DLL_LOCK bit of MCI_DLL_STATUS register becomes '1' */
2373 while (!(readl_relaxed(host->base + MCI_DLL_STATUS) & MCI_DLL_LOCK)) {
2374 /* max. wait for 1 sec for LOCK bit to be set */
2375 if (--wait_timeout == 0) {
2376 pr_err("%s: %s: DLL failed to lock at phase: %d",
2377 mmc_hostname(host->mmc), __func__, 0);
2378 rc = -1;
2379 goto out;
2380 }
2381 /* wait for 1ms */
2382 usleep_range(1000, 1500);
2383 }
2384out:
2385 return rc;
2386}
2387
2388/*
2389 * Enable a CDR circuit in CM_SDC4_DLL block to enable automatic
2390 * calibration sequence. This function should be called before
2391 * enabling AUTO_CMD19 bit in MCI_CMD register for block read
2392 * commands (CMD17/CMD18).
2393 */
2394static void msmsdcc_enable_cdr_cm_sdc4_dll(struct msmsdcc_host *host)
2395{
2396 /* Set CDR_EN bit to 1. */
2397 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG) |
2398 MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2399
2400 /* Set CDR_EXT_EN bit to 0. */
2401 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2402 & ~MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2403
2404 /* Set CK_OUT_EN bit to 0. */
2405 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2406 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2407
2408 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2409 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)
2410 ;
2411
2412 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2413 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2414 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2415
2416 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register is 1. */
2417 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN))
2418 ;
2419}
2420
2421static int msmsdcc_config_cm_sdc4_dll_phase(struct msmsdcc_host *host,
2422 u8 phase)
2423{
2424 int rc = 0;
2425 u32 mclk_freq = 0;
2426 u32 wait_timeout;
2427
2428 /* Set CDR_EN bit to 0. */
2429 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2430 & ~MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
2431
2432 /* Set CDR_EXT_EN bit to 1. */
2433 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2434 | MCI_CDR_EXT_EN), host->base + MCI_DLL_CONFIG);
2435
2436 /* Program the MCLK value to MCLK_FREQ bit field */
2437 if (host->clk_rate <= 112000000)
2438 mclk_freq = 0;
2439 else if (host->clk_rate <= 125000000)
2440 mclk_freq = 1;
2441 else if (host->clk_rate <= 137000000)
2442 mclk_freq = 2;
2443 else if (host->clk_rate <= 150000000)
2444 mclk_freq = 3;
2445 else if (host->clk_rate <= 162000000)
2446 mclk_freq = 4;
2447 else if (host->clk_rate <= 175000000)
2448 mclk_freq = 5;
2449 else if (host->clk_rate <= 187000000)
2450 mclk_freq = 6;
2451 else if (host->clk_rate <= 200000000)
2452 mclk_freq = 7;
2453
2454 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2455 & ~(7 << 24)) | (mclk_freq << 24)),
2456 host->base + MCI_DLL_CONFIG);
2457
2458 /* Set CK_OUT_EN bit to 0. */
2459 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2460 & ~MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2461
2462 /* Set DLL_EN bit to 1. */
2463 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2464 | MCI_DLL_EN), host->base + MCI_DLL_CONFIG);
2465
2466 wait_timeout = 1000;
2467 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '0' */
2468 while (readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN) {
2469 /* max. wait for 1 sec for LOCK bit for be set */
2470 if (--wait_timeout == 0) {
2471 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 0",
2472 mmc_hostname(host->mmc), __func__, phase);
2473 rc = -1;
2474 goto out;
2475 }
2476 /* wait for 1ms */
2477 usleep_range(1000, 1500);
2478 }
2479
2480 /*
2481 * Write the selected DLL clock output phase (0 ... 15)
2482 * to CDR_SELEXT bit field of MCI_DLL_CONFIG register.
2483 */
2484 writel_relaxed(((readl_relaxed(host->base + MCI_DLL_CONFIG)
2485 & ~(0xF << 20)) | (phase << 20)),
2486 host->base + MCI_DLL_CONFIG);
2487
2488 /* Set CK_OUT_EN bit of MCI_DLL_CONFIG register to 1. */
2489 writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
2490 | MCI_CK_OUT_EN), host->base + MCI_DLL_CONFIG);
2491
2492 wait_timeout = 1000;
2493 /* Wait until CK_OUT_EN bit of MCI_DLL_CONFIG register becomes '1' */
2494 while (!(readl_relaxed(host->base + MCI_DLL_CONFIG) & MCI_CK_OUT_EN)) {
2495 /* max. wait for 1 sec for LOCK bit for be set */
2496 if (--wait_timeout == 0) {
2497 pr_err("%s: %s: Failed to set DLL phase: %d, CK_OUT_EN bit is not 1",
2498 mmc_hostname(host->mmc), __func__, phase);
2499 rc = -1;
2500 goto out;
2501 }
2502 /* wait for 1ms */
2503 usleep_range(1000, 1500);
2504 }
2505out:
2506 return rc;
2507}
2508
2509static int msmsdcc_execute_tuning(struct mmc_host *mmc)
2510{
2511 struct msmsdcc_host *host = mmc_priv(mmc);
2512 u8 phase;
2513 u8 *data_buf;
2514 u8 tuned_phases[16], tuned_phase_cnt = 0;
2515 int rc = 0;
2516
2517 /* Tuning is only required for SDR50 & SDR104 modes */
2518 if (!host->tuning_needed) {
2519 rc = 0;
2520 goto out;
2521 }
2522
2523 host->cmd19_tuning_in_progress = 1;
2524 /*
2525 * Make sure that clock is always enabled when DLL
2526 * tuning is in progress. Keeping PWRSAVE ON may
2527 * turn off the clock. So let's disable the PWRSAVE
2528 * here and re-enable it once tuning is completed.
2529 */
2530 writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
2531 & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2532 /* first of all reset the tuning block */
2533 rc = msmsdcc_init_cm_sdc4_dll(host);
2534 if (rc)
2535 goto out;
2536
2537 data_buf = kmalloc(64, GFP_KERNEL);
2538 if (!data_buf) {
2539 rc = -ENOMEM;
2540 goto out;
2541 }
2542
2543 phase = 0;
2544 do {
2545 struct mmc_command cmd = {0};
2546 struct mmc_data data = {0};
2547 struct mmc_request mrq = {
2548 .cmd = &cmd,
2549 .data = &data
2550 };
2551 struct scatterlist sg;
2552
2553 /* set the phase in delay line hw block */
2554 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2555 if (rc)
2556 goto kfree;
2557
2558 cmd.opcode = MMC_SEND_TUNING_BLOCK;
2559 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
2560
2561 data.blksz = 64;
2562 data.blocks = 1;
2563 data.flags = MMC_DATA_READ;
2564 data.timeout_ns = 1000 * 1000 * 1000; /* 1 sec */
2565
2566 data.sg = &sg;
2567 data.sg_len = 1;
2568 sg_init_one(&sg, data_buf, 64);
2569 memset(data_buf, 0, 64);
2570 mmc_wait_for_req(mmc, &mrq);
2571
2572 if (!cmd.error && !data.error &&
2573 !memcmp(data_buf, cmd19_tuning_block, 64)) {
2574 /* tuning is successful with this tuning point */
2575 tuned_phases[tuned_phase_cnt++] = phase;
2576 }
2577 } while (++phase < 16);
2578
2579 kfree(data_buf);
2580
2581 if (tuned_phase_cnt) {
2582 tuned_phase_cnt--;
2583 tuned_phase_cnt = (tuned_phase_cnt * 3) / 4;
2584 phase = tuned_phases[tuned_phase_cnt];
2585 /*
2586 * Finally set the selected phase in delay
2587 * line hw block.
2588 */
2589 rc = msmsdcc_config_cm_sdc4_dll_phase(host, phase);
2590 if (rc)
2591 goto out;
2592 } else {
2593 /* tuning failed */
2594 rc = -EAGAIN;
2595 pr_err("%s: %s: no tuning point found",
2596 mmc_hostname(mmc), __func__);
2597 }
2598 goto out;
2599
2600kfree:
2601 kfree(data_buf);
2602out:
2603 /* re-enable PWESAVE */
2604 writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
2605 MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
2606 host->cmd19_tuning_in_progress = 0;
2607 return rc;
San Mehat9d2bd732009-09-22 16:44:22 -07002608}
2609
2610static const struct mmc_host_ops msmsdcc_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002611 .enable = msmsdcc_enable,
2612 .disable = msmsdcc_disable,
San Mehat9d2bd732009-09-22 16:44:22 -07002613 .request = msmsdcc_request,
2614 .set_ios = msmsdcc_set_ios,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002615 .get_ro = msmsdcc_get_ro,
2616#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
San Mehat9d2bd732009-09-22 16:44:22 -07002617 .enable_sdio_irq = msmsdcc_enable_sdio_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002618#endif
2619 .start_signal_voltage_switch = msmsdcc_start_signal_voltage_switch,
2620 .execute_tuning = msmsdcc_execute_tuning
San Mehat9d2bd732009-09-22 16:44:22 -07002621};
2622
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002623static unsigned int
2624msmsdcc_slot_status(struct msmsdcc_host *host)
2625{
2626 int status;
2627 unsigned int gpio_no = host->plat->status_gpio;
2628
2629 status = gpio_request(gpio_no, "SD_HW_Detect");
2630 if (status) {
2631 pr_err("%s: %s: Failed to request GPIO %d\n",
2632 mmc_hostname(host->mmc), __func__, gpio_no);
2633 } else {
2634 status = gpio_direction_input(gpio_no);
2635 if (!status)
2636 status = !gpio_get_value_cansleep(gpio_no);
2637 gpio_free(gpio_no);
2638 }
2639 return status;
2640}
2641
San Mehat9d2bd732009-09-22 16:44:22 -07002642static void
2643msmsdcc_check_status(unsigned long data)
2644{
2645 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
2646 unsigned int status;
2647
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002648 if (host->plat->status || host->plat->status_gpio) {
2649 if (host->plat->status)
2650 status = host->plat->status(mmc_dev(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07002651 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002652 status = msmsdcc_slot_status(host);
2653
2654 host->eject = !status;
2655 if (status ^ host->oldstat) {
2656 pr_info("%s: Slot status change detected (%d -> %d)\n",
2657 mmc_hostname(host->mmc), host->oldstat, status);
San Mehat9d2bd732009-09-22 16:44:22 -07002658 mmc_detect_change(host->mmc, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002659 }
2660 host->oldstat = status;
2661 } else {
2662 mmc_detect_change(host->mmc, 0);
San Mehat9d2bd732009-09-22 16:44:22 -07002663 }
San Mehat9d2bd732009-09-22 16:44:22 -07002664}
2665
2666static irqreturn_t
2667msmsdcc_platform_status_irq(int irq, void *dev_id)
2668{
2669 struct msmsdcc_host *host = dev_id;
2670
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002671 pr_debug("%s: %d\n", __func__, irq);
San Mehat9d2bd732009-09-22 16:44:22 -07002672 msmsdcc_check_status((unsigned long) host);
2673 return IRQ_HANDLED;
2674}
2675
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002676static irqreturn_t
2677msmsdcc_platform_sdiowakeup_irq(int irq, void *dev_id)
2678{
2679 struct msmsdcc_host *host = dev_id;
2680
2681 pr_debug("%s: SDIO Wake up IRQ : %d\n", mmc_hostname(host->mmc), irq);
2682 spin_lock(&host->lock);
2683 if (!host->sdio_irq_disabled) {
2684 disable_irq_nosync(irq);
2685 if (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
2686 wake_lock(&host->sdio_wlock);
2687 msmsdcc_disable_irq_wake(host);
2688 }
2689 host->sdio_irq_disabled = 1;
2690 }
2691 if (host->plat->is_sdio_al_client) {
2692 if (!host->clks_on) {
2693 msmsdcc_setup_clocks(host, true);
2694 host->clks_on = 1;
2695 }
2696 if (host->sdcc_irq_disabled) {
2697 writel_relaxed(host->mci_irqenable,
2698 host->base + MMCIMASK0);
2699 mb();
2700 enable_irq(host->core_irqres->start);
2701 host->sdcc_irq_disabled = 0;
2702 }
2703 wake_lock(&host->sdio_wlock);
2704 }
2705 spin_unlock(&host->lock);
2706
2707 return IRQ_HANDLED;
2708}
2709
San Mehat9d2bd732009-09-22 16:44:22 -07002710static void
2711msmsdcc_status_notify_cb(int card_present, void *dev_id)
2712{
2713 struct msmsdcc_host *host = dev_id;
2714
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002715 pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
San Mehat9d2bd732009-09-22 16:44:22 -07002716 card_present);
2717 msmsdcc_check_status((unsigned long) host);
2718}
2719
San Mehat9d2bd732009-09-22 16:44:22 -07002720static int
2721msmsdcc_init_dma(struct msmsdcc_host *host)
2722{
2723 memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data));
2724 host->dma.host = host;
2725 host->dma.channel = -1;
2726
2727 if (!host->dmares)
2728 return -ENODEV;
2729
2730 host->dma.nc = dma_alloc_coherent(NULL,
2731 sizeof(struct msmsdcc_nc_dmadata),
2732 &host->dma.nc_busaddr,
2733 GFP_KERNEL);
2734 if (host->dma.nc == NULL) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07002735 pr_err("Unable to allocate DMA buffer\n");
San Mehat9d2bd732009-09-22 16:44:22 -07002736 return -ENOMEM;
2737 }
2738 memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata));
2739 host->dma.cmd_busaddr = host->dma.nc_busaddr;
2740 host->dma.cmdptr_busaddr = host->dma.nc_busaddr +
2741 offsetof(struct msmsdcc_nc_dmadata, cmdptr);
2742 host->dma.channel = host->dmares->start;
2743
2744 return 0;
2745}
2746
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002747#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
2748/**
2749 * Allocate and Connect a SDCC peripheral's SPS endpoint
2750 *
2751 * This function allocates endpoint context and
2752 * connect it with memory endpoint by calling
2753 * appropriate SPS driver APIs.
2754 *
2755 * Also registers a SPS callback function with
2756 * SPS driver
2757 *
2758 * This function should only be called once typically
2759 * during driver probe.
2760 *
2761 * @host - Pointer to sdcc host structure
2762 * @ep - Pointer to sps endpoint data structure
2763 * @is_produce - 1 means Producer endpoint
2764 * 0 means Consumer endpoint
2765 *
2766 * @return - 0 if successful else negative value.
2767 *
2768 */
2769static int msmsdcc_sps_init_ep_conn(struct msmsdcc_host *host,
2770 struct msmsdcc_sps_ep_conn_data *ep,
2771 bool is_producer)
2772{
2773 int rc = 0;
2774 struct sps_pipe *sps_pipe_handle;
2775 struct sps_connect *sps_config = &ep->config;
2776 struct sps_register_event *sps_event = &ep->event;
2777
2778 /* Allocate endpoint context */
2779 sps_pipe_handle = sps_alloc_endpoint();
2780 if (!sps_pipe_handle) {
2781 pr_err("%s: sps_alloc_endpoint() failed!!! is_producer=%d",
2782 mmc_hostname(host->mmc), is_producer);
2783 rc = -ENOMEM;
2784 goto out;
2785 }
2786
2787 /* Get default connection configuration for an endpoint */
2788 rc = sps_get_config(sps_pipe_handle, sps_config);
2789 if (rc) {
2790 pr_err("%s: sps_get_config() failed!!! pipe_handle=0x%x,"
2791 " rc=%d", mmc_hostname(host->mmc),
2792 (u32)sps_pipe_handle, rc);
2793 goto get_config_err;
2794 }
2795
2796 /* Modify the default connection configuration */
2797 if (is_producer) {
2798 /*
2799 * For SDCC producer transfer, source should be
2800 * SDCC peripheral where as destination should
2801 * be system memory.
2802 */
2803 sps_config->source = host->sps.bam_handle;
2804 sps_config->destination = SPS_DEV_HANDLE_MEM;
2805 /* Producer pipe will handle this connection */
2806 sps_config->mode = SPS_MODE_SRC;
2807 sps_config->options =
2808 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2809 } else {
2810 /*
2811 * For SDCC consumer transfer, source should be
2812 * system memory where as destination should
2813 * SDCC peripheral
2814 */
2815 sps_config->source = SPS_DEV_HANDLE_MEM;
2816 sps_config->destination = host->sps.bam_handle;
2817 sps_config->mode = SPS_MODE_DEST;
2818 sps_config->options =
2819 SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
2820 }
2821
2822 /* Producer pipe index */
2823 sps_config->src_pipe_index = host->sps.src_pipe_index;
2824 /* Consumer pipe index */
2825 sps_config->dest_pipe_index = host->sps.dest_pipe_index;
2826 /*
2827 * This event thresold value is only significant for BAM-to-BAM
2828 * transfer. It's ignored for BAM-to-System mode transfer.
2829 */
2830 sps_config->event_thresh = 0x10;
2831 /*
2832 * Max. no of scatter/gather buffers that can
2833 * be passed by block layer = 32 (NR_SG).
2834 * Each BAM descritor needs 64 bits (8 bytes).
2835 * One BAM descriptor is required per buffer transfer.
2836 * So we would require total 256 (32 * 8) bytes of descriptor FIFO.
2837 * But due to HW limitation we need to allocate atleast one extra
2838 * descriptor memory (256 bytes + 8 bytes). But in order to be
2839 * in power of 2, we are allocating 512 bytes of memory.
2840 */
2841 sps_config->desc.size = 512;
2842 sps_config->desc.base = dma_alloc_coherent(mmc_dev(host->mmc),
2843 sps_config->desc.size,
2844 &sps_config->desc.phys_base,
2845 GFP_KERNEL);
2846
2847 memset(sps_config->desc.base, 0x00, sps_config->desc.size);
2848
2849 /* Establish connection between peripheral and memory endpoint */
2850 rc = sps_connect(sps_pipe_handle, sps_config);
2851 if (rc) {
2852 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2853 " rc=%d", mmc_hostname(host->mmc),
2854 (u32)sps_pipe_handle, rc);
2855 goto sps_connect_err;
2856 }
2857
2858 sps_event->mode = SPS_TRIGGER_CALLBACK;
2859 sps_event->options = SPS_O_EOT;
2860 sps_event->callback = msmsdcc_sps_complete_cb;
2861 sps_event->xfer_done = NULL;
2862 sps_event->user = (void *)host;
2863
2864 /* Register callback event for EOT (End of transfer) event. */
2865 rc = sps_register_event(sps_pipe_handle, sps_event);
2866 if (rc) {
2867 pr_err("%s: sps_connect() failed!!! pipe_handle=0x%x,"
2868 " rc=%d", mmc_hostname(host->mmc),
2869 (u32)sps_pipe_handle, rc);
2870 goto reg_event_err;
2871 }
2872 /* Now save the sps pipe handle */
2873 ep->pipe_handle = sps_pipe_handle;
2874 pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"
2875 " desc_fifo.phys_base=0x%x\n", mmc_hostname(host->mmc),
2876 __func__, is_producer ? "READ" : "WRITE",
2877 (u32)sps_pipe_handle, sps_config->desc.phys_base);
2878 goto out;
2879
2880reg_event_err:
2881 sps_disconnect(sps_pipe_handle);
2882sps_connect_err:
2883 dma_free_coherent(mmc_dev(host->mmc),
2884 sps_config->desc.size,
2885 sps_config->desc.base,
2886 sps_config->desc.phys_base);
2887get_config_err:
2888 sps_free_endpoint(sps_pipe_handle);
2889out:
2890 return rc;
2891}
2892
2893/**
2894 * Disconnect and Deallocate a SDCC peripheral's SPS endpoint
2895 *
2896 * This function disconnect endpoint and deallocates
2897 * endpoint context.
2898 *
2899 * This function should only be called once typically
2900 * during driver remove.
2901 *
2902 * @host - Pointer to sdcc host structure
2903 * @ep - Pointer to sps endpoint data structure
2904 *
2905 */
2906static void msmsdcc_sps_exit_ep_conn(struct msmsdcc_host *host,
2907 struct msmsdcc_sps_ep_conn_data *ep)
2908{
2909 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2910 struct sps_connect *sps_config = &ep->config;
2911 struct sps_register_event *sps_event = &ep->event;
2912
2913 sps_event->xfer_done = NULL;
2914 sps_event->callback = NULL;
2915 sps_register_event(sps_pipe_handle, sps_event);
2916 sps_disconnect(sps_pipe_handle);
2917 dma_free_coherent(mmc_dev(host->mmc),
2918 sps_config->desc.size,
2919 sps_config->desc.base,
2920 sps_config->desc.phys_base);
2921 sps_free_endpoint(sps_pipe_handle);
2922}
2923
2924/**
2925 * Reset SDCC peripheral's SPS endpoint
2926 *
2927 * This function disconnects an endpoint.
2928 *
2929 * This function should be called for reseting
2930 * SPS endpoint when data transfer error is
2931 * encountered during data transfer. This
2932 * can be considered as soft reset to endpoint.
2933 *
2934 * This function should only be called if
2935 * msmsdcc_sps_init() is already called.
2936 *
2937 * @host - Pointer to sdcc host structure
2938 * @ep - Pointer to sps endpoint data structure
2939 *
2940 * @return - 0 if successful else negative value.
2941 */
2942static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
2943 struct msmsdcc_sps_ep_conn_data *ep)
2944{
2945 int rc = 0;
2946 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2947
2948 rc = sps_disconnect(sps_pipe_handle);
2949 if (rc) {
2950 pr_err("%s: %s: sps_disconnect() failed!!! pipe_handle=0x%x,"
2951 " rc=%d", mmc_hostname(host->mmc), __func__,
2952 (u32)sps_pipe_handle, rc);
2953 goto out;
2954 }
2955 out:
2956 return rc;
2957}
2958
2959/**
2960 * Restore SDCC peripheral's SPS endpoint
2961 *
2962 * This function connects an endpoint.
2963 *
2964 * This function should be called for restoring
2965 * SPS endpoint after data transfer error is
2966 * encountered during data transfer. This
2967 * can be considered as soft reset to endpoint.
2968 *
2969 * This function should only be called if
2970 * msmsdcc_sps_reset_ep() is called before.
2971 *
2972 * @host - Pointer to sdcc host structure
2973 * @ep - Pointer to sps endpoint data structure
2974 *
2975 * @return - 0 if successful else negative value.
2976 */
2977static int msmsdcc_sps_restore_ep(struct msmsdcc_host *host,
2978 struct msmsdcc_sps_ep_conn_data *ep)
2979{
2980 int rc = 0;
2981 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2982 struct sps_connect *sps_config = &ep->config;
2983 struct sps_register_event *sps_event = &ep->event;
2984
2985 /* Establish connection between peripheral and memory endpoint */
2986 rc = sps_connect(sps_pipe_handle, sps_config);
2987 if (rc) {
2988 pr_err("%s: %s: sps_connect() failed!!! pipe_handle=0x%x,"
2989 " rc=%d", mmc_hostname(host->mmc), __func__,
2990 (u32)sps_pipe_handle, rc);
2991 goto out;
2992 }
2993
2994 /* Register callback event for EOT (End of transfer) event. */
2995 rc = sps_register_event(sps_pipe_handle, sps_event);
2996 if (rc) {
2997 pr_err("%s: %s: sps_register_event() failed!!!"
2998 " pipe_handle=0x%x, rc=%d",
2999 mmc_hostname(host->mmc), __func__,
3000 (u32)sps_pipe_handle, rc);
3001 goto reg_event_err;
3002 }
3003 goto out;
3004
3005reg_event_err:
3006 sps_disconnect(sps_pipe_handle);
3007out:
3008 return rc;
3009}
3010
3011/**
3012 * Initialize SPS HW connected with SDCC core
3013 *
3014 * This function register BAM HW resources with
3015 * SPS driver and then initialize 2 SPS endpoints
3016 *
3017 * This function should only be called once typically
3018 * during driver probe.
3019 *
3020 * @host - Pointer to sdcc host structure
3021 *
3022 * @return - 0 if successful else negative value.
3023 *
3024 */
3025static int msmsdcc_sps_init(struct msmsdcc_host *host)
3026{
3027 int rc = 0;
3028 struct sps_bam_props bam = {0};
3029
3030 host->bam_base = ioremap(host->bam_memres->start,
3031 resource_size(host->bam_memres));
3032 if (!host->bam_base) {
3033 pr_err("%s: BAM ioremap() failed!!! phys_addr=0x%x,"
3034 " size=0x%x", mmc_hostname(host->mmc),
3035 host->bam_memres->start,
3036 (host->bam_memres->end -
3037 host->bam_memres->start));
3038 rc = -ENOMEM;
3039 goto out;
3040 }
3041
3042 bam.phys_addr = host->bam_memres->start;
3043 bam.virt_addr = host->bam_base;
3044 /*
3045 * This event thresold value is only significant for BAM-to-BAM
3046 * transfer. It's ignored for BAM-to-System mode transfer.
3047 */
3048 bam.event_threshold = 0x10; /* Pipe event threshold */
3049 /*
3050 * This threshold controls when the BAM publish
3051 * the descriptor size on the sideband interface.
3052 * SPS HW will only be used when
3053 * data transfer size > MCI_FIFOSIZE (64 bytes).
3054 * PIO mode will be used when
3055 * data transfer size < MCI_FIFOSIZE (64 bytes).
3056 * So set this thresold value to 64 bytes.
3057 */
3058 bam.summing_threshold = 64;
3059 /* SPS driver wll handle the SDCC BAM IRQ */
3060 bam.irq = (u32)host->bam_irqres->start;
3061 bam.manage = SPS_BAM_MGR_LOCAL;
3062
3063 pr_info("%s: bam physical base=0x%x\n", mmc_hostname(host->mmc),
3064 (u32)bam.phys_addr);
3065 pr_info("%s: bam virtual base=0x%x\n", mmc_hostname(host->mmc),
3066 (u32)bam.virt_addr);
3067
3068 /* Register SDCC Peripheral BAM device to SPS driver */
3069 rc = sps_register_bam_device(&bam, &host->sps.bam_handle);
3070 if (rc) {
3071 pr_err("%s: sps_register_bam_device() failed!!! err=%d",
3072 mmc_hostname(host->mmc), rc);
3073 goto reg_bam_err;
3074 }
3075 pr_info("%s: BAM device registered. bam_handle=0x%x",
3076 mmc_hostname(host->mmc), host->sps.bam_handle);
3077
3078 host->sps.src_pipe_index = SPS_SDCC_PRODUCER_PIPE_INDEX;
3079 host->sps.dest_pipe_index = SPS_SDCC_CONSUMER_PIPE_INDEX;
3080
3081 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.prod,
3082 SPS_PROD_PERIPHERAL);
3083 if (rc)
3084 goto sps_reset_err;
3085 rc = msmsdcc_sps_init_ep_conn(host, &host->sps.cons,
3086 SPS_CONS_PERIPHERAL);
3087 if (rc)
3088 goto cons_conn_err;
3089
3090 pr_info("%s: Qualcomm MSM SDCC-BAM at 0x%016llx irq %d\n",
3091 mmc_hostname(host->mmc),
3092 (unsigned long long)host->bam_memres->start,
3093 (unsigned int)host->bam_irqres->start);
3094 goto out;
3095
3096cons_conn_err:
3097 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3098sps_reset_err:
3099 sps_deregister_bam_device(host->sps.bam_handle);
3100reg_bam_err:
3101 iounmap(host->bam_base);
3102out:
3103 return rc;
3104}
3105
3106/**
3107 * De-initialize SPS HW connected with SDCC core
3108 *
3109 * This function deinitialize SPS endpoints and then
3110 * deregisters BAM resources from SPS driver.
3111 *
3112 * This function should only be called once typically
3113 * during driver remove.
3114 *
3115 * @host - Pointer to sdcc host structure
3116 *
3117 */
3118static void msmsdcc_sps_exit(struct msmsdcc_host *host)
3119{
3120 msmsdcc_sps_exit_ep_conn(host, &host->sps.cons);
3121 msmsdcc_sps_exit_ep_conn(host, &host->sps.prod);
3122 sps_deregister_bam_device(host->sps.bam_handle);
3123 iounmap(host->bam_base);
3124}
3125#endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
3126
3127static ssize_t
3128show_polling(struct device *dev, struct device_attribute *attr, char *buf)
3129{
3130 struct mmc_host *mmc = dev_get_drvdata(dev);
3131 struct msmsdcc_host *host = mmc_priv(mmc);
3132 int poll;
3133 unsigned long flags;
3134
3135 spin_lock_irqsave(&host->lock, flags);
3136 poll = !!(mmc->caps & MMC_CAP_NEEDS_POLL);
3137 spin_unlock_irqrestore(&host->lock, flags);
3138
3139 return snprintf(buf, PAGE_SIZE, "%d\n", poll);
3140}
3141
3142static ssize_t
3143set_polling(struct device *dev, struct device_attribute *attr,
3144 const char *buf, size_t count)
3145{
3146 struct mmc_host *mmc = dev_get_drvdata(dev);
3147 struct msmsdcc_host *host = mmc_priv(mmc);
3148 int value;
3149 unsigned long flags;
3150
3151 sscanf(buf, "%d", &value);
3152
3153 spin_lock_irqsave(&host->lock, flags);
3154 if (value) {
3155 mmc->caps |= MMC_CAP_NEEDS_POLL;
3156 mmc_detect_change(host->mmc, 0);
3157 } else {
3158 mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3159 }
3160#ifdef CONFIG_HAS_EARLYSUSPEND
3161 host->polling_enabled = mmc->caps & MMC_CAP_NEEDS_POLL;
3162#endif
3163 spin_unlock_irqrestore(&host->lock, flags);
3164 return count;
3165}
3166
3167static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR,
3168 show_polling, set_polling);
3169static struct attribute *dev_attrs[] = {
3170 &dev_attr_polling.attr,
3171 NULL,
3172};
3173static struct attribute_group dev_attr_grp = {
3174 .attrs = dev_attrs,
3175};
3176
3177#ifdef CONFIG_HAS_EARLYSUSPEND
3178static void msmsdcc_early_suspend(struct early_suspend *h)
3179{
3180 struct msmsdcc_host *host =
3181 container_of(h, struct msmsdcc_host, early_suspend);
3182 unsigned long flags;
3183
3184 spin_lock_irqsave(&host->lock, flags);
3185 host->polling_enabled = host->mmc->caps & MMC_CAP_NEEDS_POLL;
3186 host->mmc->caps &= ~MMC_CAP_NEEDS_POLL;
3187 spin_unlock_irqrestore(&host->lock, flags);
3188};
3189static void msmsdcc_late_resume(struct early_suspend *h)
3190{
3191 struct msmsdcc_host *host =
3192 container_of(h, struct msmsdcc_host, early_suspend);
3193 unsigned long flags;
3194
3195 if (host->polling_enabled) {
3196 spin_lock_irqsave(&host->lock, flags);
3197 host->mmc->caps |= MMC_CAP_NEEDS_POLL;
3198 mmc_detect_change(host->mmc, 0);
3199 spin_unlock_irqrestore(&host->lock, flags);
3200 }
3201};
3202#endif
3203
3204static void msmsdcc_req_tout_timer_hdlr(unsigned long data)
3205{
3206 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
3207 struct mmc_request *mrq;
3208 unsigned long flags;
3209
3210 spin_lock_irqsave(&host->lock, flags);
3211 if ((host->plat->dummy52_required) &&
3212 (host->dummy_52_state == DUMMY_52_STATE_SENT)) {
3213 pr_info("%s: %s: dummy CMD52 timeout\n",
3214 mmc_hostname(host->mmc), __func__);
3215 host->dummy_52_state = DUMMY_52_STATE_NONE;
3216 }
3217
3218 mrq = host->curr.mrq;
3219
3220 if (mrq && mrq->cmd) {
3221 pr_info("%s: %s CMD%d\n", mmc_hostname(host->mmc),
3222 __func__, mrq->cmd->opcode);
3223 if (!mrq->cmd->error)
3224 mrq->cmd->error = -ETIMEDOUT;
3225 if (host->plat->dummy52_required && host->dummy_52_needed)
3226 host->dummy_52_needed = 0;
3227 if (host->curr.data) {
3228 pr_info("%s: %s Request timeout\n",
3229 mmc_hostname(host->mmc), __func__);
3230 if (mrq->data && !mrq->data->error)
3231 mrq->data->error = -ETIMEDOUT;
3232 host->curr.data_xfered = 0;
3233 if (host->dma.sg && host->is_dma_mode) {
3234 msm_dmov_stop_cmd(host->dma.channel,
3235 &host->dma.hdr, 0);
3236 } else if (host->sps.sg && host->is_sps_mode) {
3237 /* Stop current SPS transfer */
3238 msmsdcc_sps_exit_curr_xfer(host);
3239 } else {
3240 msmsdcc_reset_and_restore(host);
3241 msmsdcc_stop_data(host);
3242 if (mrq->data && mrq->data->stop)
3243 msmsdcc_start_command(host,
3244 mrq->data->stop, 0);
3245 else
3246 msmsdcc_request_end(host, mrq);
3247 }
3248 } else {
3249 if (host->prog_enable) {
3250 host->prog_scan = 0;
3251 host->prog_enable = 0;
3252 }
3253 msmsdcc_reset_and_restore(host);
3254 msmsdcc_request_end(host, mrq);
3255 }
3256 }
3257 spin_unlock_irqrestore(&host->lock, flags);
3258}
3259
San Mehat9d2bd732009-09-22 16:44:22 -07003260static int
3261msmsdcc_probe(struct platform_device *pdev)
3262{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003263 struct mmc_platform_data *plat = pdev->dev.platform_data;
San Mehat9d2bd732009-09-22 16:44:22 -07003264 struct msmsdcc_host *host;
3265 struct mmc_host *mmc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003266 unsigned long flags;
3267 struct resource *core_irqres = NULL;
3268 struct resource *bam_irqres = NULL;
3269 struct resource *core_memres = NULL;
3270 struct resource *dml_memres = NULL;
3271 struct resource *bam_memres = NULL;
San Mehat9d2bd732009-09-22 16:44:22 -07003272 struct resource *dmares = NULL;
3273 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003274 int i;
San Mehat9d2bd732009-09-22 16:44:22 -07003275
3276 /* must have platform data */
3277 if (!plat) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003278 pr_err("%s: Platform data not available\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003279 ret = -EINVAL;
3280 goto out;
3281 }
3282
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003283 if (pdev->id < 1 || pdev->id > 5)
San Mehat9d2bd732009-09-22 16:44:22 -07003284 return -EINVAL;
3285
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003286 if (plat->is_sdio_al_client)
3287 if (!plat->sdio_lpm_gpio_setup || !plat->sdiowakeup_irq)
3288 return -EINVAL;
3289
San Mehat9d2bd732009-09-22 16:44:22 -07003290 if (pdev->resource == NULL || pdev->num_resources < 2) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003291 pr_err("%s: Invalid resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003292 return -ENXIO;
3293 }
3294
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003295 for (i = 0; i < pdev->num_resources; i++) {
3296 if (pdev->resource[i].flags & IORESOURCE_MEM) {
3297 if (!strcmp(pdev->resource[i].name,
3298 "sdcc_dml_addr"))
3299 dml_memres = &pdev->resource[i];
3300 else if (!strcmp(pdev->resource[i].name,
3301 "sdcc_bam_addr"))
3302 bam_memres = &pdev->resource[i];
3303 else
3304 core_memres = &pdev->resource[i];
San Mehat9d2bd732009-09-22 16:44:22 -07003305
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003306 }
3307 if (pdev->resource[i].flags & IORESOURCE_IRQ) {
3308 if (!strcmp(pdev->resource[i].name,
3309 "sdcc_bam_irq"))
3310 bam_irqres = &pdev->resource[i];
3311 else
3312 core_irqres = &pdev->resource[i];
3313 }
3314 if (pdev->resource[i].flags & IORESOURCE_DMA)
3315 dmares = &pdev->resource[i];
3316 }
3317
3318 if (!core_irqres || !core_memres) {
3319 pr_err("%s: Invalid sdcc core resource\n", __func__);
3320 return -ENXIO;
3321 }
3322
3323 /*
3324 * Both BAM and DML memory resource should be preset.
3325 * BAM IRQ resource should also be present.
3326 */
3327 if ((bam_memres && !dml_memres) ||
3328 (!bam_memres && dml_memres) ||
3329 ((bam_memres && dml_memres) && !bam_irqres)) {
3330 pr_err("%s: Invalid sdcc BAM/DML resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003331 return -ENXIO;
3332 }
3333
3334 /*
3335 * Setup our host structure
3336 */
San Mehat9d2bd732009-09-22 16:44:22 -07003337 mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev);
3338 if (!mmc) {
3339 ret = -ENOMEM;
3340 goto out;
3341 }
3342
3343 host = mmc_priv(mmc);
3344 host->pdev_id = pdev->id;
3345 host->plat = plat;
3346 host->mmc = mmc;
San Mehat56a8b5b2009-11-21 12:29:46 -08003347 host->curr.cmd = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003348 if (bam_memres && dml_memres && bam_irqres)
3349 host->is_sps_mode = 1;
3350 else if (dmares)
3351 host->is_dma_mode = 1;
San Mehat9d2bd732009-09-22 16:44:22 -07003352
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003353 host->base = ioremap(core_memres->start,
3354 resource_size(core_memres));
San Mehat9d2bd732009-09-22 16:44:22 -07003355 if (!host->base) {
3356 ret = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003357 goto host_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003358 }
3359
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003360 host->core_irqres = core_irqres;
3361 host->bam_irqres = bam_irqres;
3362 host->core_memres = core_memres;
3363 host->dml_memres = dml_memres;
3364 host->bam_memres = bam_memres;
San Mehat9d2bd732009-09-22 16:44:22 -07003365 host->dmares = dmares;
3366 spin_lock_init(&host->lock);
3367
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003368#ifdef CONFIG_MMC_EMBEDDED_SDIO
3369 if (plat->embedded_sdio)
3370 mmc_set_embedded_sdio_data(mmc,
3371 &plat->embedded_sdio->cis,
3372 &plat->embedded_sdio->cccr,
3373 plat->embedded_sdio->funcs,
3374 plat->embedded_sdio->num_funcs);
3375#endif
3376
Sahitya Tummala62612cf2010-12-08 15:03:03 +05303377 tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
3378 (unsigned long)host);
3379
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003380 tasklet_init(&host->sps.tlet, msmsdcc_sps_complete_tlet,
3381 (unsigned long)host);
3382 if (host->is_dma_mode) {
3383 /* Setup DMA */
3384 ret = msmsdcc_init_dma(host);
3385 if (ret)
3386 goto ioremap_free;
3387 } else {
3388 host->dma.channel = -1;
San Mehat9d2bd732009-09-22 16:44:22 -07003389 }
3390
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003391 /*
3392 * Setup SDCC clock if derived from Dayatona
3393 * fabric core clock.
3394 */
3395 if (plat->pclk_src_dfab) {
3396 host->dfab_pclk = clk_get(&pdev->dev, "dfab_sdc_clk");
3397 if (!IS_ERR(host->dfab_pclk)) {
3398 /* Set the clock rate to 64MHz for max. performance */
3399 ret = clk_set_rate(host->dfab_pclk, 64000000);
3400 if (ret)
3401 goto dfab_pclk_put;
3402 ret = clk_enable(host->dfab_pclk);
3403 if (ret)
3404 goto dfab_pclk_put;
3405 } else
3406 goto dma_free;
3407 }
3408
3409 /*
3410 * Setup main peripheral bus clock
3411 */
3412 host->pclk = clk_get(&pdev->dev, "sdc_pclk");
3413 if (!IS_ERR(host->pclk)) {
3414 ret = clk_enable(host->pclk);
3415 if (ret)
3416 goto pclk_put;
3417
3418 host->pclk_rate = clk_get_rate(host->pclk);
3419 }
3420
3421 /*
3422 * Setup SDC MMC clock
3423 */
San Mehat9d2bd732009-09-22 16:44:22 -07003424 host->clk = clk_get(&pdev->dev, "sdc_clk");
3425 if (IS_ERR(host->clk)) {
3426 ret = PTR_ERR(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003427 goto pclk_disable;
San Mehat9d2bd732009-09-22 16:44:22 -07003428 }
3429
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003430 ret = clk_set_rate(host->clk, msmsdcc_get_min_sup_clk_rate(host));
3431 if (ret) {
3432 pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
3433 goto clk_put;
3434 }
3435
3436 ret = clk_enable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003437 if (ret)
3438 goto clk_put;
3439
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003440 host->clk_rate = clk_get_rate(host->clk);
3441
3442 host->clks_on = 1;
3443
3444 ret = msmsdcc_vreg_init(host, true);
San Mehat9d2bd732009-09-22 16:44:22 -07003445 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003446 pr_err("%s: msmsdcc_vreg_init() failed (%d)\n", __func__, ret);
San Mehat9d2bd732009-09-22 16:44:22 -07003447 goto clk_disable;
3448 }
3449
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003450
3451 /* Clocks has to be running before accessing SPS/DML HW blocks */
3452 if (host->is_sps_mode) {
3453 /* Initialize SPS */
3454 ret = msmsdcc_sps_init(host);
3455 if (ret)
3456 goto vreg_deinit;
3457 /* Initialize DML */
3458 ret = msmsdcc_dml_init(host);
3459 if (ret)
3460 goto sps_exit;
3461 }
San Mehat9d2bd732009-09-22 16:44:22 -07003462
San Mehat9d2bd732009-09-22 16:44:22 -07003463 /*
3464 * Setup MMC host structure
3465 */
3466 mmc->ops = &msmsdcc_ops;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003467 mmc->f_min = msmsdcc_get_min_sup_clk_rate(host);
3468 mmc->f_max = msmsdcc_get_max_sup_clk_rate(host);
San Mehat9d2bd732009-09-22 16:44:22 -07003469 mmc->ocr_avail = plat->ocr_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003470 mmc->pm_caps |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
3471 mmc->caps |= plat->mmc_bus_width;
San Mehat9d2bd732009-09-22 16:44:22 -07003472
San Mehat9d2bd732009-09-22 16:44:22 -07003473 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003474 mmc->caps |= plat->uhs_caps;
3475 /*
3476 * XPC controls the maximum current in the default speed mode of SDXC
3477 * card. XPC=0 means 100mA (max.) but speed class is not supported.
3478 * XPC=1 means 150mA (max.) and speed class is supported.
3479 */
3480 if (plat->xpc_cap)
3481 mmc->caps |= (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
3482 MMC_CAP_SET_XPC_180);
3483
3484 if (plat->nonremovable)
3485 mmc->caps |= MMC_CAP_NONREMOVABLE;
3486#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
3487 mmc->caps |= MMC_CAP_SDIO_IRQ;
3488#endif
3489
3490 if (plat->is_sdio_al_client)
3491 mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
San Mehat9d2bd732009-09-22 16:44:22 -07003492
Martin K. Petersena36274e2010-09-10 01:33:59 -04003493 mmc->max_segs = NR_SG;
San Mehat9d2bd732009-09-22 16:44:22 -07003494 mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003495 mmc->max_blk_count = 65535;
San Mehat9d2bd732009-09-22 16:44:22 -07003496
3497 mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */
3498 mmc->max_seg_size = mmc->max_req_size;
3499
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003500 writel_relaxed(0, host->base + MMCIMASK0);
3501 writel_relaxed(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
San Mehat9d2bd732009-09-22 16:44:22 -07003502
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003503 /* Delay needed (MMCIMASK0 was just written above) */
3504 msmsdcc_delay(host);
3505 writel_relaxed(MCI_IRQENABLE, host->base + MMCIMASK0);
3506 mb();
3507 host->mci_irqenable = MCI_IRQENABLE;
San Mehat9d2bd732009-09-22 16:44:22 -07003508
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003509 ret = request_irq(core_irqres->start, msmsdcc_irq, IRQF_SHARED,
3510 DRIVER_NAME " (cmd)", host);
3511 if (ret)
3512 goto dml_exit;
3513
3514 ret = request_irq(core_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
3515 DRIVER_NAME " (pio)", host);
3516 if (ret)
3517 goto irq_free;
3518
3519 /*
3520 * Enable SDCC IRQ only when host is powered on. Otherwise, this
3521 * IRQ is un-necessarily being monitored by MPM (Modem power
3522 * management block) during idle-power collapse. The MPM will be
3523 * configured to monitor the DATA1 GPIO line with level-low trigger
3524 * and thus depending on the GPIO status, it prevents TCXO shutdown
3525 * during idle-power collapse.
3526 */
3527 disable_irq(core_irqres->start);
3528 host->sdcc_irq_disabled = 1;
3529
3530 if (plat->sdiowakeup_irq) {
3531 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3532 mmc_hostname(mmc));
3533 ret = request_irq(plat->sdiowakeup_irq,
3534 msmsdcc_platform_sdiowakeup_irq,
3535 IRQF_SHARED | IRQF_TRIGGER_LOW,
3536 DRIVER_NAME "sdiowakeup", host);
3537 if (ret) {
3538 pr_err("Unable to get sdio wakeup IRQ %d (%d)\n",
3539 plat->sdiowakeup_irq, ret);
3540 goto pio_irq_free;
3541 } else {
3542 spin_lock_irqsave(&host->lock, flags);
3543 if (!host->sdio_irq_disabled) {
3544 disable_irq_nosync(plat->sdiowakeup_irq);
3545 host->sdio_irq_disabled = 1;
3546 }
3547 spin_unlock_irqrestore(&host->lock, flags);
3548 }
3549 }
3550
3551 if (plat->cfg_mpm_sdiowakeup) {
3552 wake_lock_init(&host->sdio_wlock, WAKE_LOCK_SUSPEND,
3553 mmc_hostname(mmc));
3554 }
3555
3556 wake_lock_init(&host->sdio_suspend_wlock, WAKE_LOCK_SUSPEND,
3557 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003558 /*
3559 * Setup card detect change
3560 */
3561
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003562 if (plat->status || plat->status_gpio) {
3563 if (plat->status)
3564 host->oldstat = plat->status(mmc_dev(host->mmc));
3565 else
3566 host->oldstat = msmsdcc_slot_status(host);
3567 host->eject = !host->oldstat;
3568 }
San Mehat9d2bd732009-09-22 16:44:22 -07003569
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003570 if (plat->status_irq) {
3571 ret = request_threaded_irq(plat->status_irq, NULL,
San Mehat9d2bd732009-09-22 16:44:22 -07003572 msmsdcc_platform_status_irq,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003573 plat->irq_flags,
San Mehat9d2bd732009-09-22 16:44:22 -07003574 DRIVER_NAME " (slot)",
3575 host);
3576 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003577 pr_err("Unable to get slot IRQ %d (%d)\n",
3578 plat->status_irq, ret);
3579 goto sdiowakeup_irq_free;
San Mehat9d2bd732009-09-22 16:44:22 -07003580 }
3581 } else if (plat->register_status_notify) {
3582 plat->register_status_notify(msmsdcc_status_notify_cb, host);
3583 } else if (!plat->status)
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003584 pr_err("%s: No card detect facilities available\n",
San Mehat9d2bd732009-09-22 16:44:22 -07003585 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003586
3587 mmc_set_drvdata(pdev, mmc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003588
3589 ret = pm_runtime_set_active(&(pdev)->dev);
3590 if (ret < 0)
3591 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
3592 __func__, ret);
3593 /*
3594 * There is no notion of suspend/resume for SD/MMC/SDIO
3595 * cards. So host can be suspended/resumed with out
3596 * worrying about its children.
3597 */
3598 pm_suspend_ignore_children(&(pdev)->dev, true);
3599
3600 /*
3601 * MMC/SD/SDIO bus suspend/resume operations are defined
3602 * only for the slots that will be used for non-removable
3603 * media or for all slots when CONFIG_MMC_UNSAFE_RESUME is
3604 * defined. Otherwise, they simply become card removal and
3605 * insertion events during suspend and resume respectively.
3606 * Hence, enable run-time PM only for slots for which bus
3607 * suspend/resume operations are defined.
3608 */
3609#ifdef CONFIG_MMC_UNSAFE_RESUME
3610 /*
3611 * If this capability is set, MMC core will enable/disable host
3612 * for every claim/release operation on a host. We use this
3613 * notification to increment/decrement runtime pm usage count.
3614 */
3615 mmc->caps |= MMC_CAP_DISABLE;
3616 pm_runtime_enable(&(pdev)->dev);
3617#else
3618 if (mmc->caps & MMC_CAP_NONREMOVABLE) {
3619 mmc->caps |= MMC_CAP_DISABLE;
3620 pm_runtime_enable(&(pdev)->dev);
3621 }
3622#endif
3623 setup_timer(&host->req_tout_timer, msmsdcc_req_tout_timer_hdlr,
3624 (unsigned long)host);
3625
San Mehat9d2bd732009-09-22 16:44:22 -07003626 mmc_add_host(mmc);
3627
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003628#ifdef CONFIG_HAS_EARLYSUSPEND
3629 host->early_suspend.suspend = msmsdcc_early_suspend;
3630 host->early_suspend.resume = msmsdcc_late_resume;
3631 host->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
3632 register_early_suspend(&host->early_suspend);
3633#endif
San Mehat9d2bd732009-09-22 16:44:22 -07003634
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003635 pr_info("%s: Qualcomm MSM SDCC-core at 0x%016llx irq %d,%d dma %d\n",
3636 mmc_hostname(mmc), (unsigned long long)core_memres->start,
3637 (unsigned int) core_irqres->start,
3638 (unsigned int) plat->status_irq, host->dma.channel);
3639
3640 pr_info("%s: 8 bit data mode %s\n", mmc_hostname(mmc),
3641 (mmc->caps & MMC_CAP_8_BIT_DATA ? "enabled" : "disabled"));
3642 pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc),
3643 (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled"));
3644 pr_info("%s: polling status mode %s\n", mmc_hostname(mmc),
3645 (mmc->caps & MMC_CAP_NEEDS_POLL ? "enabled" : "disabled"));
3646 pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n",
3647 mmc_hostname(mmc), msmsdcc_get_min_sup_clk_rate(host),
3648 msmsdcc_get_max_sup_clk_rate(host), host->pclk_rate);
3649 pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc),
3650 host->eject);
3651 pr_info("%s: Power save feature enable = %d\n",
3652 mmc_hostname(mmc), msmsdcc_pwrsave);
3653
3654 if (host->is_dma_mode && host->dma.channel != -1) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003655 pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003656 mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003657 pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003658 mmc_hostname(mmc), host->dma.cmd_busaddr,
3659 host->dma.cmdptr_busaddr);
3660 } else if (host->is_sps_mode) {
3661 pr_info("%s: SPS-BAM data transfer mode available\n",
3662 mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003663 } else
Joe Perches0a7ff7c2009-09-22 16:44:23 -07003664 pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07003665
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003666#if defined(CONFIG_DEBUG_FS)
3667 msmsdcc_dbg_createhost(host);
3668#endif
3669 if (!plat->status_irq) {
3670 ret = sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);
3671 if (ret)
3672 goto platform_irq_free;
3673 }
San Mehat9d2bd732009-09-22 16:44:22 -07003674 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003675
3676 platform_irq_free:
3677 del_timer_sync(&host->req_tout_timer);
3678 pm_runtime_disable(&(pdev)->dev);
3679 pm_runtime_set_suspended(&(pdev)->dev);
3680
3681 if (plat->status_irq)
3682 free_irq(plat->status_irq, host);
3683 sdiowakeup_irq_free:
3684 wake_lock_destroy(&host->sdio_suspend_wlock);
3685 if (plat->sdiowakeup_irq)
3686 free_irq(plat->sdiowakeup_irq, host);
3687 pio_irq_free:
3688 if (plat->sdiowakeup_irq)
3689 wake_lock_destroy(&host->sdio_wlock);
3690 free_irq(core_irqres->start, host);
3691 irq_free:
3692 free_irq(core_irqres->start, host);
3693 dml_exit:
3694 if (host->is_sps_mode)
3695 msmsdcc_dml_exit(host);
3696 sps_exit:
3697 if (host->is_sps_mode)
3698 msmsdcc_sps_exit(host);
3699 vreg_deinit:
3700 msmsdcc_vreg_init(host, false);
San Mehat9d2bd732009-09-22 16:44:22 -07003701 clk_disable:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003702 clk_disable(host->clk);
San Mehat9d2bd732009-09-22 16:44:22 -07003703 clk_put:
3704 clk_put(host->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003705 pclk_disable:
3706 if (!IS_ERR(host->pclk))
3707 clk_disable(host->pclk);
San Mehat9d2bd732009-09-22 16:44:22 -07003708 pclk_put:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003709 if (!IS_ERR(host->pclk))
3710 clk_put(host->pclk);
3711 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3712 clk_disable(host->dfab_pclk);
3713 dfab_pclk_put:
3714 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3715 clk_put(host->dfab_pclk);
3716 dma_free:
3717 if (host->is_dma_mode) {
3718 if (host->dmares)
3719 dma_free_coherent(NULL,
3720 sizeof(struct msmsdcc_nc_dmadata),
3721 host->dma.nc, host->dma.nc_busaddr);
3722 }
3723 ioremap_free:
3724 iounmap(host->base);
San Mehat9d2bd732009-09-22 16:44:22 -07003725 host_free:
3726 mmc_free_host(mmc);
3727 out:
3728 return ret;
3729}
3730
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003731static int msmsdcc_remove(struct platform_device *pdev)
Daniel Walker08ecfde2010-06-23 12:32:20 -07003732{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003733 struct mmc_host *mmc = mmc_get_drvdata(pdev);
3734 struct mmc_platform_data *plat;
3735 struct msmsdcc_host *host;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003736
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003737 if (!mmc)
3738 return -ENXIO;
3739
3740 if (pm_runtime_suspended(&(pdev)->dev))
3741 pm_runtime_resume(&(pdev)->dev);
3742
3743 host = mmc_priv(mmc);
3744
3745 DBG(host, "Removing SDCC device = %d\n", pdev->id);
3746 plat = host->plat;
3747
3748 if (!plat->status_irq)
3749 sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
3750
3751 del_timer_sync(&host->req_tout_timer);
3752 tasklet_kill(&host->dma_tlet);
3753 tasklet_kill(&host->sps.tlet);
3754 mmc_remove_host(mmc);
3755
3756 if (plat->status_irq)
3757 free_irq(plat->status_irq, host);
3758
3759 wake_lock_destroy(&host->sdio_suspend_wlock);
3760 if (plat->sdiowakeup_irq) {
3761 wake_lock_destroy(&host->sdio_wlock);
3762 irq_set_irq_wake(plat->sdiowakeup_irq, 0);
3763 free_irq(plat->sdiowakeup_irq, host);
Daniel Walker08ecfde2010-06-23 12:32:20 -07003764 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003765
3766 free_irq(host->core_irqres->start, host);
3767 free_irq(host->core_irqres->start, host);
3768
3769 clk_put(host->clk);
3770 if (!IS_ERR(host->pclk))
3771 clk_put(host->pclk);
3772 if (!IS_ERR_OR_NULL(host->dfab_pclk))
3773 clk_put(host->dfab_pclk);
3774
3775 msmsdcc_vreg_init(host, false);
3776
3777 if (host->is_dma_mode) {
3778 if (host->dmares)
3779 dma_free_coherent(NULL,
3780 sizeof(struct msmsdcc_nc_dmadata),
3781 host->dma.nc, host->dma.nc_busaddr);
3782 }
3783
3784 if (host->is_sps_mode) {
3785 msmsdcc_dml_exit(host);
3786 msmsdcc_sps_exit(host);
3787 }
3788
3789 iounmap(host->base);
3790 mmc_free_host(mmc);
3791
3792#ifdef CONFIG_HAS_EARLYSUSPEND
3793 unregister_early_suspend(&host->early_suspend);
3794#endif
3795 pm_runtime_disable(&(pdev)->dev);
3796 pm_runtime_set_suspended(&(pdev)->dev);
3797
3798 return 0;
3799}
3800
3801#ifdef CONFIG_MSM_SDIO_AL
3802int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3803{
3804 struct msmsdcc_host *host = mmc_priv(mmc);
3805 unsigned long flags;
3806
3807 spin_lock_irqsave(&host->lock, flags);
3808 pr_debug("%s: %sabling LPM\n", mmc_hostname(mmc),
3809 enable ? "En" : "Dis");
3810
3811 if (enable) {
3812 if (!host->sdcc_irq_disabled) {
3813 writel_relaxed(0, host->base + MMCIMASK0);
3814 disable_irq(host->core_irqres->start);
3815 host->sdcc_irq_disabled = 1;
3816 }
3817
3818 if (host->clks_on) {
3819 msmsdcc_setup_clocks(host, false);
3820 host->clks_on = 0;
3821 }
3822
3823 if (!host->sdio_gpio_lpm) {
3824 spin_unlock_irqrestore(&host->lock, flags);
3825 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 0);
3826 spin_lock_irqsave(&host->lock, flags);
3827 host->sdio_gpio_lpm = 1;
3828 }
3829
3830 if (host->sdio_irq_disabled) {
3831 msmsdcc_enable_irq_wake(host);
3832 enable_irq(host->plat->sdiowakeup_irq);
3833 host->sdio_irq_disabled = 0;
3834 }
3835 } else {
3836 if (!host->sdio_irq_disabled) {
3837 disable_irq_nosync(host->plat->sdiowakeup_irq);
3838 host->sdio_irq_disabled = 1;
3839 msmsdcc_disable_irq_wake(host);
3840 }
3841
3842 if (host->sdio_gpio_lpm) {
3843 spin_unlock_irqrestore(&host->lock, flags);
3844 host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 1);
3845 spin_lock_irqsave(&host->lock, flags);
3846 host->sdio_gpio_lpm = 0;
3847 }
3848
3849 if (!host->clks_on) {
3850 msmsdcc_setup_clocks(host, true);
3851 host->clks_on = 1;
3852 }
3853
3854 if (host->sdcc_irq_disabled) {
3855 writel_relaxed(host->mci_irqenable,
3856 host->base + MMCIMASK0);
3857 mb();
3858 enable_irq(host->core_irqres->start);
3859 host->sdcc_irq_disabled = 0;
3860 }
3861 wake_lock_timeout(&host->sdio_wlock, 1);
3862 }
3863 spin_unlock_irqrestore(&host->lock, flags);
3864 return 0;
3865}
3866#else
3867int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable)
3868{
3869 return 0;
Daniel Walker08ecfde2010-06-23 12:32:20 -07003870}
3871#endif
3872
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003873#ifdef CONFIG_PM
San Mehat9d2bd732009-09-22 16:44:22 -07003874static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003875msmsdcc_runtime_suspend(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003876{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003877 struct mmc_host *mmc = dev_get_drvdata(dev);
3878 struct msmsdcc_host *host = mmc_priv(mmc);
San Mehat9d2bd732009-09-22 16:44:22 -07003879 int rc = 0;
3880
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003881 if (host->plat->is_sdio_al_client)
3882 return 0;
3883
Sahitya Tummala7661a452011-07-18 13:28:35 +05303884 pr_debug("%s: %s: start\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003885 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003886 host->sdcc_suspending = 1;
3887 mmc->suspend_task = current;
San Mehat9d2bd732009-09-22 16:44:22 -07003888
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003889 /*
3890 * If the clocks are already turned off by SDIO clients (as
3891 * part of LPM), then clocks should be turned on before
3892 * calling mmc_suspend_host() because mmc_suspend_host might
3893 * send some commands to the card. The clocks will be turned
3894 * off again after mmc_suspend_host. Thus for SD/MMC/SDIO
3895 * cards, clocks will be turned on before mmc_suspend_host
3896 * and turned off after mmc_suspend_host.
3897 */
3898 mmc->ios.clock = host->clk_rate;
3899 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07003900
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003901 /*
3902 * MMC core thinks that host is disabled by now since
3903 * runtime suspend is scheduled after msmsdcc_disable()
3904 * is called. Thus, MMC core will try to enable the host
3905 * while suspending it. This results in a synchronous
3906 * runtime resume request while in runtime suspending
3907 * context and hence inorder to complete this resume
3908 * requet, it will wait for suspend to be complete,
3909 * but runtime suspend also can not proceed further
3910 * until the host is resumed. Thus, it leads to a hang.
3911 * Hence, increase the pm usage count before suspending
3912 * the host so that any resume requests after this will
3913 * simple become pm usage counter increment operations.
3914 */
3915 pm_runtime_get_noresume(dev);
3916 rc = mmc_suspend_host(mmc);
3917 pm_runtime_put_noidle(dev);
3918
3919 if (!rc) {
3920 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
3921 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ)) {
3922 disable_irq(host->core_irqres->start);
3923 host->sdcc_irq_disabled = 1;
3924
3925 /*
3926 * If MMC core level suspend is not supported,
3927 * turn off clocks to allow deep sleep (TCXO
3928 * shutdown).
3929 */
3930 mmc->ios.clock = 0;
3931 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
3932 enable_irq(host->core_irqres->start);
3933 host->sdcc_irq_disabled = 0;
3934
3935 if (host->plat->sdiowakeup_irq) {
3936 host->sdio_irq_disabled = 0;
3937 msmsdcc_enable_irq_wake(host);
3938 enable_irq(host->plat->sdiowakeup_irq);
3939 }
3940 }
3941 }
3942 host->sdcc_suspending = 0;
3943 mmc->suspend_task = NULL;
3944 if (rc && wake_lock_active(&host->sdio_suspend_wlock))
3945 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07003946 }
Sahitya Tummala7661a452011-07-18 13:28:35 +05303947 pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003948 return rc;
3949}
3950
3951static int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003952msmsdcc_runtime_resume(struct device *dev)
San Mehat9d2bd732009-09-22 16:44:22 -07003953{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003954 struct mmc_host *mmc = dev_get_drvdata(dev);
3955 struct msmsdcc_host *host = mmc_priv(mmc);
3956 unsigned long flags;
3957
3958 if (host->plat->is_sdio_al_client)
3959 return 0;
San Mehat9d2bd732009-09-22 16:44:22 -07003960
Sahitya Tummala7661a452011-07-18 13:28:35 +05303961 pr_debug("%s: %s: start\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07003962 if (mmc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003963 if (mmc->card && mmc->card->type == MMC_TYPE_SDIO) {
3964 if (host->sdcc_irq_disabled) {
3965 enable_irq(host->core_irqres->start);
3966 host->sdcc_irq_disabled = 0;
3967 }
3968 }
3969 mmc->ios.clock = host->clk_rate;
3970 mmc->ops->set_ios(host->mmc, &host->mmc->ios);
San Mehat9d2bd732009-09-22 16:44:22 -07003971
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003972 spin_lock_irqsave(&host->lock, flags);
3973 writel_relaxed(host->mci_irqenable, host->base + MMCIMASK0);
3974 mb();
San Mehat9d2bd732009-09-22 16:44:22 -07003975
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003976 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO) &&
3977 (mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ) &&
3978 !host->sdio_irq_disabled) {
3979 if (host->plat->sdiowakeup_irq) {
3980 disable_irq_nosync(
3981 host->plat->sdiowakeup_irq);
3982 msmsdcc_disable_irq_wake(host);
3983 host->sdio_irq_disabled = 1;
3984 }
3985 }
San Mehat9d2bd732009-09-22 16:44:22 -07003986
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003987 spin_unlock_irqrestore(&host->lock, flags);
3988
3989 mmc_resume_host(mmc);
3990
3991 /*
3992 * FIXME: Clearing of flags must be handled in clients
3993 * resume handler.
3994 */
3995 spin_lock_irqsave(&host->lock, flags);
3996 mmc->pm_flags = 0;
3997 spin_unlock_irqrestore(&host->lock, flags);
3998
3999 /*
4000 * After resuming the host wait for sometime so that
4001 * the SDIO work will be processed.
4002 */
4003 if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO)) {
4004 if ((host->plat->cfg_mpm_sdiowakeup ||
4005 host->plat->sdiowakeup_irq) &&
4006 wake_lock_active(&host->sdio_wlock))
4007 wake_lock_timeout(&host->sdio_wlock, 1);
4008 }
4009
4010 wake_unlock(&host->sdio_suspend_wlock);
San Mehat9d2bd732009-09-22 16:44:22 -07004011 }
Sahitya Tummala7661a452011-07-18 13:28:35 +05304012 pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07004013 return 0;
4014}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004015
4016static int msmsdcc_runtime_idle(struct device *dev)
4017{
4018 struct mmc_host *mmc = dev_get_drvdata(dev);
4019 struct msmsdcc_host *host = mmc_priv(mmc);
4020
4021 if (host->plat->is_sdio_al_client)
4022 return 0;
4023
4024 /* Idle timeout is not configurable for now */
4025 pm_schedule_suspend(dev, MSM_MMC_IDLE_TIMEOUT);
4026
4027 return -EAGAIN;
4028}
4029
4030static int msmsdcc_pm_suspend(struct device *dev)
4031{
4032 struct mmc_host *mmc = dev_get_drvdata(dev);
4033 struct msmsdcc_host *host = mmc_priv(mmc);
4034 int rc = 0;
4035
4036 if (host->plat->is_sdio_al_client)
4037 return 0;
4038
4039
4040 if (host->plat->status_irq)
4041 disable_irq(host->plat->status_irq);
4042
4043 if (!pm_runtime_suspended(dev))
4044 rc = msmsdcc_runtime_suspend(dev);
4045
4046 return rc;
4047}
4048
4049static int msmsdcc_pm_resume(struct device *dev)
4050{
4051 struct mmc_host *mmc = dev_get_drvdata(dev);
4052 struct msmsdcc_host *host = mmc_priv(mmc);
4053 int rc = 0;
4054
4055 if (host->plat->is_sdio_al_client)
4056 return 0;
4057
4058 rc = msmsdcc_runtime_resume(dev);
4059 if (host->plat->status_irq) {
4060 msmsdcc_check_status((unsigned long)host);
4061 enable_irq(host->plat->status_irq);
4062 }
4063
4064 /* Update the run-time PM status */
4065 pm_runtime_disable(dev);
4066 rc = pm_runtime_set_active(dev);
4067 if (rc < 0)
4068 pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
4069 __func__, rc);
4070 pm_runtime_enable(dev);
4071
4072 return rc;
4073}
4074
Daniel Walker08ecfde2010-06-23 12:32:20 -07004075#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004076#define msmsdcc_runtime_suspend NULL
4077#define msmsdcc_runtime_resume NULL
4078#define msmsdcc_runtime_idle NULL
4079#define msmsdcc_pm_suspend NULL
4080#define msmsdcc_pm_resume NULL
Daniel Walker08ecfde2010-06-23 12:32:20 -07004081#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004082
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004083static const struct dev_pm_ops msmsdcc_dev_pm_ops = {
4084 .runtime_suspend = msmsdcc_runtime_suspend,
4085 .runtime_resume = msmsdcc_runtime_resume,
4086 .runtime_idle = msmsdcc_runtime_idle,
4087 .suspend = msmsdcc_pm_suspend,
4088 .resume = msmsdcc_pm_resume,
4089};
4090
San Mehat9d2bd732009-09-22 16:44:22 -07004091static struct platform_driver msmsdcc_driver = {
4092 .probe = msmsdcc_probe,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004093 .remove = msmsdcc_remove,
San Mehat9d2bd732009-09-22 16:44:22 -07004094 .driver = {
4095 .name = "msm_sdcc",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004096 .pm = &msmsdcc_dev_pm_ops,
San Mehat9d2bd732009-09-22 16:44:22 -07004097 },
4098};
4099
4100static int __init msmsdcc_init(void)
4101{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004102#if defined(CONFIG_DEBUG_FS)
4103 int ret = 0;
4104 ret = msmsdcc_dbg_init();
4105 if (ret) {
4106 pr_err("Failed to create debug fs dir \n");
4107 return ret;
4108 }
4109#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004110 return platform_driver_register(&msmsdcc_driver);
4111}
4112
4113static void __exit msmsdcc_exit(void)
4114{
4115 platform_driver_unregister(&msmsdcc_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004116
4117#if defined(CONFIG_DEBUG_FS)
4118 debugfs_remove(debugfs_file);
4119 debugfs_remove(debugfs_dir);
4120#endif
San Mehat9d2bd732009-09-22 16:44:22 -07004121}
4122
4123module_init(msmsdcc_init);
4124module_exit(msmsdcc_exit);
4125
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004126MODULE_DESCRIPTION("Qualcomm Multimedia Card Interface driver");
San Mehat9d2bd732009-09-22 16:44:22 -07004127MODULE_LICENSE("GPL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004128
4129#if defined(CONFIG_DEBUG_FS)
4130
4131static int
4132msmsdcc_dbg_state_open(struct inode *inode, struct file *file)
4133{
4134 file->private_data = inode->i_private;
4135 return 0;
4136}
4137
4138static ssize_t
4139msmsdcc_dbg_state_read(struct file *file, char __user *ubuf,
4140 size_t count, loff_t *ppos)
4141{
4142 struct msmsdcc_host *host = (struct msmsdcc_host *) file->private_data;
4143 char buf[1024];
4144 int max, i;
4145
4146 i = 0;
4147 max = sizeof(buf) - 1;
4148
4149 i += scnprintf(buf + i, max - i, "STAT: %p %p %p\n", host->curr.mrq,
4150 host->curr.cmd, host->curr.data);
4151 if (host->curr.cmd) {
4152 struct mmc_command *cmd = host->curr.cmd;
4153
4154 i += scnprintf(buf + i, max - i, "CMD : %.8x %.8x %.8x\n",
4155 cmd->opcode, cmd->arg, cmd->flags);
4156 }
4157 if (host->curr.data) {
4158 struct mmc_data *data = host->curr.data;
4159 i += scnprintf(buf + i, max - i,
4160 "DAT0: %.8x %.8x %.8x %.8x %.8x %.8x\n",
4161 data->timeout_ns, data->timeout_clks,
4162 data->blksz, data->blocks, data->error,
4163 data->flags);
4164 i += scnprintf(buf + i, max - i, "DAT1: %.8x %.8x %.8x %p\n",
4165 host->curr.xfer_size, host->curr.xfer_remain,
4166 host->curr.data_xfered, host->dma.sg);
4167 }
4168
4169 return simple_read_from_buffer(ubuf, count, ppos, buf, i);
4170}
4171
4172static const struct file_operations msmsdcc_dbg_state_ops = {
4173 .read = msmsdcc_dbg_state_read,
4174 .open = msmsdcc_dbg_state_open,
4175};
4176
4177static void msmsdcc_dbg_createhost(struct msmsdcc_host *host)
4178{
4179 if (debugfs_dir) {
4180 debugfs_file = debugfs_create_file(mmc_hostname(host->mmc),
4181 0644, debugfs_dir, host,
4182 &msmsdcc_dbg_state_ops);
4183 }
4184}
4185
4186static int __init msmsdcc_dbg_init(void)
4187{
4188 int err;
4189
4190 debugfs_dir = debugfs_create_dir("msmsdcc", 0);
4191 if (IS_ERR(debugfs_dir)) {
4192 err = PTR_ERR(debugfs_dir);
4193 debugfs_dir = NULL;
4194 return err;
4195 }
4196
4197 return 0;
4198}
4199#endif