aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMadhusudhan Chikkature <madhu.cr@ti.com>2009-01-22 19:05:23 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-01-24 06:41:21 -0500
commita45c6cb816474cefe56059fce422a9bdcd77e0dc (patch)
treed8377f26a5159203defb82eff1f4fa43e5d591d4 /drivers
parent409dc360b49480b57869ffd457e4b95901b76b75 (diff)
[ARM] 5369/1: omap mmc: Add new omap hsmmc controller for 2430 and 34xx, v3
Add omap hsmmc controller for 2430 and 34xx. Note that this controller has different registers compared to the earlier omap MMC controller, so sharing code currently is not possible. Various updates and fixes from linux-omap list have been merged into this patch. Signed-off-by: Madhusudhan Chikkature<madhu.cr@ti.com> Acked-by: Pierre Ossman <drzeus@drzeus.cx> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/Kconfig10
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/omap_hsmmc.c1242
3 files changed, 1253 insertions, 0 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index dfa585f7feaf..0efa390978bd 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -76,6 +76,16 @@ config MMC_OMAP
76 76
77 If unsure, say N. 77 If unsure, say N.
78 78
79config MMC_OMAP_HS
80 tristate "TI OMAP High Speed Multimedia Card Interface support"
81 depends on ARCH_OMAP2430 || ARCH_OMAP3
82 help
83 This selects the TI OMAP High Speed Multimedia card Interface.
84 If you have an OMAP2430 or OMAP3 board with a Multimedia Card slot,
85 say Y or M here.
86
87 If unsure, say N.
88
79config MMC_WBSD 89config MMC_WBSD
80 tristate "Winbond W83L51xD SD/MMC Card Interface support" 90 tristate "Winbond W83L51xD SD/MMC Card Interface support"
81 depends on ISA_DMA_API 91 depends on ISA_DMA_API
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index f4853288bbb1..98cab84829b8 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
15obj-$(CONFIG_MMC_WBSD) += wbsd.o 15obj-$(CONFIG_MMC_WBSD) += wbsd.o
16obj-$(CONFIG_MMC_AU1X) += au1xmmc.o 16obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
17obj-$(CONFIG_MMC_OMAP) += omap.o 17obj-$(CONFIG_MMC_OMAP) += omap.o
18obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
18obj-$(CONFIG_MMC_AT91) += at91_mci.o 19obj-$(CONFIG_MMC_AT91) += at91_mci.o
19obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o 20obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
20obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o 21obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
new file mode 100644
index 000000000000..db37490f67ec
--- /dev/null
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -0,0 +1,1242 @@
1/*
2 * drivers/mmc/host/omap_hsmmc.c
3 *
4 * Driver for OMAP2430/3430 MMC controller.
5 *
6 * Copyright (C) 2007 Texas Instruments.
7 *
8 * Authors:
9 * Syed Mohammed Khasim <x0khasim@ti.com>
10 * Madhusudhan <madhu.cr@ti.com>
11 * Mohit Jalori <mjalori@ti.com>
12 *
13 * This file is licensed under the terms of the GNU General Public License
14 * version 2. This program is licensed "as is" without any warranty of any
15 * kind, whether express or implied.
16 */
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/interrupt.h>
21#include <linux/delay.h>
22#include <linux/dma-mapping.h>
23#include <linux/platform_device.h>
24#include <linux/workqueue.h>
25#include <linux/timer.h>
26#include <linux/clk.h>
27#include <linux/mmc/host.h>
28#include <linux/io.h>
29#include <linux/semaphore.h>
30#include <mach/dma.h>
31#include <mach/hardware.h>
32#include <mach/board.h>
33#include <mach/mmc.h>
34#include <mach/cpu.h>
35
36/* OMAP HSMMC Host Controller Registers */
37#define OMAP_HSMMC_SYSCONFIG 0x0010
38#define OMAP_HSMMC_CON 0x002C
39#define OMAP_HSMMC_BLK 0x0104
40#define OMAP_HSMMC_ARG 0x0108
41#define OMAP_HSMMC_CMD 0x010C
42#define OMAP_HSMMC_RSP10 0x0110
43#define OMAP_HSMMC_RSP32 0x0114
44#define OMAP_HSMMC_RSP54 0x0118
45#define OMAP_HSMMC_RSP76 0x011C
46#define OMAP_HSMMC_DATA 0x0120
47#define OMAP_HSMMC_HCTL 0x0128
48#define OMAP_HSMMC_SYSCTL 0x012C
49#define OMAP_HSMMC_STAT 0x0130
50#define OMAP_HSMMC_IE 0x0134
51#define OMAP_HSMMC_ISE 0x0138
52#define OMAP_HSMMC_CAPA 0x0140
53
54#define VS18 (1 << 26)
55#define VS30 (1 << 25)
56#define SDVS18 (0x5 << 9)
57#define SDVS30 (0x6 << 9)
58#define SDVSCLR 0xFFFFF1FF
59#define SDVSDET 0x00000400
60#define AUTOIDLE 0x1
61#define SDBP (1 << 8)
62#define DTO 0xe
63#define ICE 0x1
64#define ICS 0x2
65#define CEN (1 << 2)
66#define CLKD_MASK 0x0000FFC0
67#define CLKD_SHIFT 6
68#define DTO_MASK 0x000F0000
69#define DTO_SHIFT 16
70#define INT_EN_MASK 0x307F0033
71#define INIT_STREAM (1 << 1)
72#define DP_SELECT (1 << 21)
73#define DDIR (1 << 4)
74#define DMA_EN 0x1
75#define MSBS (1 << 5)
76#define BCE (1 << 1)
77#define FOUR_BIT (1 << 1)
78#define CC 0x1
79#define TC 0x02
80#define OD 0x1
81#define ERR (1 << 15)
82#define CMD_TIMEOUT (1 << 16)
83#define DATA_TIMEOUT (1 << 20)
84#define CMD_CRC (1 << 17)
85#define DATA_CRC (1 << 21)
86#define CARD_ERR (1 << 28)
87#define STAT_CLEAR 0xFFFFFFFF
88#define INIT_STREAM_CMD 0x00000000
89#define DUAL_VOLT_OCR_BIT 7
90#define SRC (1 << 25)
91#define SRD (1 << 26)
92
93/*
94 * FIXME: Most likely all the data using these _DEVID defines should come
95 * from the platform_data, or implemented in controller and slot specific
96 * functions.
97 */
98#define OMAP_MMC1_DEVID 0
99#define OMAP_MMC2_DEVID 1
100
101#define OMAP_MMC_DATADIR_NONE 0
102#define OMAP_MMC_DATADIR_READ 1
103#define OMAP_MMC_DATADIR_WRITE 2
104#define MMC_TIMEOUT_MS 20
105#define OMAP_MMC_MASTER_CLOCK 96000000
106#define DRIVER_NAME "mmci-omap-hs"
107
108/*
109 * One controller can have multiple slots, like on some omap boards using
110 * omap.c controller driver. Luckily this is not currently done on any known
111 * omap_hsmmc.c device.
112 */
113#define mmc_slot(host) (host->pdata->slots[host->slot_id])
114
115/*
116 * MMC Host controller read/write API's
117 */
118#define OMAP_HSMMC_READ(base, reg) \
119 __raw_readl((base) + OMAP_HSMMC_##reg)
120
121#define OMAP_HSMMC_WRITE(base, reg, val) \
122 __raw_writel((val), (base) + OMAP_HSMMC_##reg)
123
124struct mmc_omap_host {
125 struct device *dev;
126 struct mmc_host *mmc;
127 struct mmc_request *mrq;
128 struct mmc_command *cmd;
129 struct mmc_data *data;
130 struct clk *fclk;
131 struct clk *iclk;
132 struct clk *dbclk;
133 struct semaphore sem;
134 struct work_struct mmc_carddetect_work;
135 void __iomem *base;
136 resource_size_t mapbase;
137 unsigned int id;
138 unsigned int dma_len;
139 unsigned int dma_dir;
140 unsigned char bus_mode;
141 unsigned char datadir;
142 u32 *buffer;
143 u32 bytesleft;
144 int suspended;
145 int irq;
146 int carddetect;
147 int use_dma, dma_ch;
148 int initstr;
149 int slot_id;
150 int dbclk_enabled;
151 struct omap_mmc_platform_data *pdata;
152};
153
154/*
155 * Stop clock to the card
156 */
157static void omap_mmc_stop_clock(struct mmc_omap_host *host)
158{
159 OMAP_HSMMC_WRITE(host->base, SYSCTL,
160 OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
161 if ((OMAP_HSMMC_READ(host->base, SYSCTL) & CEN) != 0x0)
162 dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n");
163}
164
165/*
166 * Send init stream sequence to card
167 * before sending IDLE command
168 */
169static void send_init_stream(struct mmc_omap_host *host)
170{
171 int reg = 0;
172 unsigned long timeout;
173
174 disable_irq(host->irq);
175 OMAP_HSMMC_WRITE(host->base, CON,
176 OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM);
177 OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
178
179 timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
180 while ((reg != CC) && time_before(jiffies, timeout))
181 reg = OMAP_HSMMC_READ(host->base, STAT) & CC;
182
183 OMAP_HSMMC_WRITE(host->base, CON,
184 OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM);
185 enable_irq(host->irq);
186}
187
188static inline
189int mmc_omap_cover_is_closed(struct mmc_omap_host *host)
190{
191 int r = 1;
192
193 if (host->pdata->slots[host->slot_id].get_cover_state)
194 r = host->pdata->slots[host->slot_id].get_cover_state(host->dev,
195 host->slot_id);
196 return r;
197}
198
199static ssize_t
200mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
201 char *buf)
202{
203 struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
204 struct mmc_omap_host *host = mmc_priv(mmc);
205
206 return sprintf(buf, "%s\n", mmc_omap_cover_is_closed(host) ? "closed" :
207 "open");
208}
209
210static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
211
212static ssize_t
213mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
214 char *buf)
215{
216 struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
217 struct mmc_omap_host *host = mmc_priv(mmc);
218 struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id];
219
220 return sprintf(buf, "slot:%s\n", slot.name);
221}
222
223static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL);
224
225/*
226 * Configure the response type and send the cmd.
227 */
228static void
229mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
230 struct mmc_data *data)
231{
232 int cmdreg = 0, resptype = 0, cmdtype = 0;
233
234 dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
235 mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
236 host->cmd = cmd;
237
238 /*
239 * Clear status bits and enable interrupts
240 */
241 OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
242 OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
243 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
244
245 if (cmd->flags & MMC_RSP_PRESENT) {
246 if (cmd->flags & MMC_RSP_136)
247 resptype = 1;
248 else
249 resptype = 2;
250 }
251
252 /*
253 * Unlike OMAP1 controller, the cmdtype does not seem to be based on
254 * ac, bc, adtc, bcr. Only commands ending an open ended transfer need
255 * a val of 0x3, rest 0x0.
256 */
257 if (cmd == host->mrq->stop)
258 cmdtype = 0x3;
259
260 cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
261
262 if (data) {
263 cmdreg |= DP_SELECT | MSBS | BCE;
264 if (data->flags & MMC_DATA_READ)
265 cmdreg |= DDIR;
266 else
267 cmdreg &= ~(DDIR);
268 }
269
270 if (host->use_dma)
271 cmdreg |= DMA_EN;
272
273 OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg);
274 OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
275}
276
277/*
278 * Notify the transfer complete to MMC core
279 */
280static void
281mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
282{
283 host->data = NULL;
284
285 if (host->use_dma && host->dma_ch != -1)
286 dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
287 host->dma_dir);
288
289 host->datadir = OMAP_MMC_DATADIR_NONE;
290
291 if (!data->error)
292 data->bytes_xfered += data->blocks * (data->blksz);
293 else
294 data->bytes_xfered = 0;
295
296 if (!data->stop) {
297 host->mrq = NULL;
298 mmc_request_done(host->mmc, data->mrq);
299 return;
300 }
301 mmc_omap_start_command(host, data->stop, NULL);
302}
303
304/*
305 * Notify the core about command completion
306 */
307static void
308mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
309{
310 host->cmd = NULL;
311
312 if (cmd->flags & MMC_RSP_PRESENT) {
313 if (cmd->flags & MMC_RSP_136) {
314 /* response type 2 */
315 cmd->resp[3] = OMAP_HSMMC_READ(host->base, RSP10);
316 cmd->resp[2] = OMAP_HSMMC_READ(host->base, RSP32);
317 cmd->resp[1] = OMAP_HSMMC_READ(host->base, RSP54);
318 cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP76);
319 } else {
320 /* response types 1, 1b, 3, 4, 5, 6 */
321 cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
322 }
323 }
324 if (host->data == NULL || cmd->error) {
325 host->mrq = NULL;
326 mmc_request_done(host->mmc, cmd->mrq);
327 }
328}
329
330/*
331 * DMA clean up for command errors
332 */
333static void mmc_dma_cleanup(struct mmc_omap_host *host)
334{
335 host->data->error = -ETIMEDOUT;
336
337 if (host->use_dma && host->dma_ch != -1) {
338 dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
339 host->dma_dir);
340 omap_free_dma(host->dma_ch);
341 host->dma_ch = -1;
342 up(&host->sem);
343 }
344 host->data = NULL;
345 host->datadir = OMAP_MMC_DATADIR_NONE;
346}
347
348/*
349 * Readable error output
350 */
351#ifdef CONFIG_MMC_DEBUG
352static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
353{
354 /* --- means reserved bit without definition at documentation */
355 static const char *mmc_omap_status_bits[] = {
356 "CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ",
357 "OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC",
358 "CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---",
359 "---", "---", "---", "CERR", "CERR", "BADA", "---", "---", "---"
360 };
361 char res[256];
362 char *buf = res;
363 int len, i;
364
365 len = sprintf(buf, "MMC IRQ 0x%x :", status);
366 buf += len;
367
368 for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
369 if (status & (1 << i)) {
370 len = sprintf(buf, " %s", mmc_omap_status_bits[i]);
371 buf += len;
372 }
373
374 dev_dbg(mmc_dev(host->mmc), "%s\n", res);
375}
376#endif /* CONFIG_MMC_DEBUG */
377
378
379/*
380 * MMC controller IRQ handler
381 */
382static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
383{
384 struct mmc_omap_host *host = dev_id;
385 struct mmc_data *data;
386 int end_cmd = 0, end_trans = 0, status;
387
388 if (host->cmd == NULL && host->data == NULL) {
389 OMAP_HSMMC_WRITE(host->base, STAT,
390 OMAP_HSMMC_READ(host->base, STAT));
391 return IRQ_HANDLED;
392 }
393
394 data = host->data;
395 status = OMAP_HSMMC_READ(host->base, STAT);
396 dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
397
398 if (status & ERR) {
399#ifdef CONFIG_MMC_DEBUG
400 mmc_omap_report_irq(host, status);
401#endif
402 if ((status & CMD_TIMEOUT) ||
403 (status & CMD_CRC)) {
404 if (host->cmd) {
405 if (status & CMD_TIMEOUT) {
406 OMAP_HSMMC_WRITE(host->base, SYSCTL,
407 OMAP_HSMMC_READ(host->base,
408 SYSCTL) | SRC);
409 while (OMAP_HSMMC_READ(host->base,
410 SYSCTL) & SRC)
411 ;
412
413 host->cmd->error = -ETIMEDOUT;
414 } else {
415 host->cmd->error = -EILSEQ;
416 }
417 end_cmd = 1;
418 }
419 if (host->data)
420 mmc_dma_cleanup(host);
421 }
422 if ((status & DATA_TIMEOUT) ||
423 (status & DATA_CRC)) {
424 if (host->data) {
425 if (status & DATA_TIMEOUT)
426 mmc_dma_cleanup(host);
427 else
428 host->data->error = -EILSEQ;
429 OMAP_HSMMC_WRITE(host->base, SYSCTL,
430 OMAP_HSMMC_READ(host->base,
431 SYSCTL) | SRD);
432 while (OMAP_HSMMC_READ(host->base,
433 SYSCTL) & SRD)
434 ;
435 end_trans = 1;
436 }
437 }
438 if (status & CARD_ERR) {
439 dev_dbg(mmc_dev(host->mmc),
440 "Ignoring card err CMD%d\n", host->cmd->opcode);
441 if (host->cmd)
442 end_cmd = 1;
443 if (host->data)
444 end_trans = 1;
445 }
446 }
447
448 OMAP_HSMMC_WRITE(host->base, STAT, status);
449
450 if (end_cmd || (status & CC))
451 mmc_omap_cmd_done(host, host->cmd);
452 if (end_trans || (status & TC))
453 mmc_omap_xfer_done(host, data);
454
455 return IRQ_HANDLED;
456}
457
458/*
459 * Switch MMC operating voltage
460 */
461static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
462{
463 u32 reg_val = 0;
464 int ret;
465
466 /* Disable the clocks */
467 clk_disable(host->fclk);
468 clk_disable(host->iclk);
469 clk_disable(host->dbclk);
470
471 /* Turn the power off */
472 ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
473 if (ret != 0)
474 goto err;
475
476 /* Turn the power ON with given VDD 1.8 or 3.0v */
477 ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd);
478 if (ret != 0)
479 goto err;
480
481 clk_enable(host->fclk);
482 clk_enable(host->iclk);
483 clk_enable(host->dbclk);
484
485 OMAP_HSMMC_WRITE(host->base, HCTL,
486 OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
487 reg_val = OMAP_HSMMC_READ(host->base, HCTL);
488 /*
489 * If a MMC dual voltage card is detected, the set_ios fn calls
490 * this fn with VDD bit set for 1.8V. Upon card removal from the
491 * slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF.
492 *
493 * Only MMC1 supports 3.0V. MMC2 will not function if SDVS30 is
494 * set in HCTL.
495 */
496 if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) ||
497 ((1 << vdd) == MMC_VDD_33_34)))
498 reg_val |= SDVS30;
499 if ((1 << vdd) == MMC_VDD_165_195)
500 reg_val |= SDVS18;
501
502 OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
503
504 OMAP_HSMMC_WRITE(host->base, HCTL,
505 OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
506
507 return 0;
508err:
509 dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
510 return ret;
511}
512
513/*
514 * Work Item to notify the core about card insertion/removal
515 */
516static void mmc_omap_detect(struct work_struct *work)
517{
518 struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
519 mmc_carddetect_work);
520
521 sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
522 if (host->carddetect) {
523 mmc_detect_change(host->mmc, (HZ * 200) / 1000);
524 } else {
525 OMAP_HSMMC_WRITE(host->base, SYSCTL,
526 OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
527 while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
528 ;
529
530 mmc_detect_change(host->mmc, (HZ * 50) / 1000);
531 }
532}
533
534/*
535 * ISR for handling card insertion and removal
536 */
537static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
538{
539 struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
540
541 host->carddetect = mmc_slot(host).card_detect(irq);
542 schedule_work(&host->mmc_carddetect_work);
543
544 return IRQ_HANDLED;
545}
546
547/*
548 * DMA call back function
549 */
550static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
551{
552 struct mmc_omap_host *host = data;
553
554 if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ)
555 dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n");
556
557 if (host->dma_ch < 0)
558 return;
559
560 omap_free_dma(host->dma_ch);
561 host->dma_ch = -1;
562 /*
563 * DMA Callback: run in interrupt context.
564 * mutex_unlock will through a kernel warning if used.
565 */
566 up(&host->sem);
567}
568
569/*
570 * Configure dma src and destination parameters
571 */
572static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host,
573 struct mmc_data *data)
574{
575 if (sync_dir == 0) {
576 omap_set_dma_dest_params(host->dma_ch, 0,
577 OMAP_DMA_AMODE_CONSTANT,
578 (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
579 omap_set_dma_src_params(host->dma_ch, 0,
580 OMAP_DMA_AMODE_POST_INC,
581 sg_dma_address(&data->sg[0]), 0, 0);
582 } else {
583 omap_set_dma_src_params(host->dma_ch, 0,
584 OMAP_DMA_AMODE_CONSTANT,
585 (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
586 omap_set_dma_dest_params(host->dma_ch, 0,
587 OMAP_DMA_AMODE_POST_INC,
588 sg_dma_address(&data->sg[0]), 0, 0);
589 }
590 return 0;
591}
592/*
593 * Routine to configure and start DMA for the MMC card
594 */
595static int
596mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
597{
598 int sync_dev, sync_dir = 0;
599 int dma_ch = 0, ret = 0, err = 1;
600 struct mmc_data *data = req->data;
601
602 /*
603 * If for some reason the DMA transfer is still active,
604 * we wait for timeout period and free the dma
605 */
606 if (host->dma_ch != -1) {
607 set_current_state(TASK_UNINTERRUPTIBLE);
608 schedule_timeout(100);
609 if (down_trylock(&host->sem)) {
610 omap_free_dma(host->dma_ch);
611 host->dma_ch = -1;
612 up(&host->sem);
613 return err;
614 }
615 } else {
616 if (down_trylock(&host->sem))
617 return err;
618 }
619
620 if (!(data->flags & MMC_DATA_WRITE)) {
621 host->dma_dir = DMA_FROM_DEVICE;
622 if (host->id == OMAP_MMC1_DEVID)
623 sync_dev = OMAP24XX_DMA_MMC1_RX;
624 else
625 sync_dev = OMAP24XX_DMA_MMC2_RX;
626 } else {
627 host->dma_dir = DMA_TO_DEVICE;
628 if (host->id == OMAP_MMC1_DEVID)
629 sync_dev = OMAP24XX_DMA_MMC1_TX;
630 else
631 sync_dev = OMAP24XX_DMA_MMC2_TX;
632 }
633
634 ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
635 host, &dma_ch);
636 if (ret != 0) {
637 dev_dbg(mmc_dev(host->mmc),
638 "%s: omap_request_dma() failed with %d\n",
639 mmc_hostname(host->mmc), ret);
640 return ret;
641 }
642
643 host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
644 data->sg_len, host->dma_dir);
645 host->dma_ch = dma_ch;
646
647 if (!(data->flags & MMC_DATA_WRITE))
648 mmc_omap_config_dma_param(1, host, data);
649 else
650 mmc_omap_config_dma_param(0, host, data);
651
652 if ((data->blksz % 4) == 0)
653 omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
654 (data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME,
655 sync_dev, sync_dir);
656 else
657 /* REVISIT: The MMC buffer increments only when MSB is written.
658 * Return error for blksz which is non multiple of four.
659 */
660 return -EINVAL;
661
662 omap_start_dma(dma_ch);
663 return 0;
664}
665
666static void set_data_timeout(struct mmc_omap_host *host,
667 struct mmc_request *req)
668{
669 unsigned int timeout, cycle_ns;
670 uint32_t reg, clkd, dto = 0;
671
672 reg = OMAP_HSMMC_READ(host->base, SYSCTL);
673 clkd = (reg & CLKD_MASK) >> CLKD_SHIFT;
674 if (clkd == 0)
675 clkd = 1;
676
677 cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd);
678 timeout = req->data->timeout_ns / cycle_ns;
679 timeout += req->data->timeout_clks;
680 if (timeout) {
681 while ((timeout & 0x80000000) == 0) {
682 dto += 1;
683 timeout <<= 1;
684 }
685 dto = 31 - dto;
686 timeout <<= 1;
687 if (timeout && dto)
688 dto += 1;
689 if (dto >= 13)
690 dto -= 13;
691 else
692 dto = 0;
693 if (dto > 14)
694 dto = 14;
695 }
696
697 reg &= ~DTO_MASK;
698 reg |= dto << DTO_SHIFT;
699 OMAP_HSMMC_WRITE(host->base, SYSCTL, reg);
700}
701
702/*
703 * Configure block length for MMC/SD cards and initiate the transfer.
704 */
705static int
706mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
707{
708 int ret;
709 host->data = req->data;
710
711 if (req->data == NULL) {
712 host->datadir = OMAP_MMC_DATADIR_NONE;
713 OMAP_HSMMC_WRITE(host->base, BLK, 0);
714 return 0;
715 }
716
717 OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
718 | (req->data->blocks << 16));
719 set_data_timeout(host, req);
720
721 host->datadir = (req->data->flags & MMC_DATA_WRITE) ?
722 OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ;
723
724 if (host->use_dma) {
725 ret = mmc_omap_start_dma_transfer(host, req);
726 if (ret != 0) {
727 dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
728 return ret;
729 }
730 }
731 return 0;
732}
733
734/*
735 * Request function. for read/write operation
736 */
737static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
738{
739 struct mmc_omap_host *host = mmc_priv(mmc);
740
741 WARN_ON(host->mrq != NULL);
742 host->mrq = req;
743 mmc_omap_prepare_data(host, req);
744 mmc_omap_start_command(host, req->cmd, req->data);
745}
746
747
748/* Routine to configure clock values. Exposed API to core */
749static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
750{
751 struct mmc_omap_host *host = mmc_priv(mmc);
752 u16 dsor = 0;
753 unsigned long regval;
754 unsigned long timeout;
755
756 switch (ios->power_mode) {
757 case MMC_POWER_OFF:
758 mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
759 /*
760 * Reset bus voltage to 3V if it got set to 1.8V earlier.
761 * REVISIT: If we are able to detect cards after unplugging
762 * a 1.8V card, this code should not be needed.
763 */
764 if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
765 int vdd = fls(host->mmc->ocr_avail) - 1;
766 if (omap_mmc_switch_opcond(host, vdd) != 0)
767 host->mmc->ios.vdd = vdd;
768 }
769 break;
770 case MMC_POWER_UP:
771 mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd);
772 break;
773 }
774
775 switch (mmc->ios.bus_width) {
776 case MMC_BUS_WIDTH_4:
777 OMAP_HSMMC_WRITE(host->base, HCTL,
778 OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
779 break;
780 case MMC_BUS_WIDTH_1:
781 OMAP_HSMMC_WRITE(host->base, HCTL,
782 OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
783 break;
784 }
785
786 if (host->id == OMAP_MMC1_DEVID) {
787 /* Only MMC1 can operate at 3V/1.8V */
788 if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
789 (ios->vdd == DUAL_VOLT_OCR_BIT)) {
790 /*
791 * The mmc_select_voltage fn of the core does
792 * not seem to set the power_mode to
793 * MMC_POWER_UP upon recalculating the voltage.
794 * vdd 1.8v.
795 */
796 if (omap_mmc_switch_opcond(host, ios->vdd) != 0)
797 dev_dbg(mmc_dev(host->mmc),
798 "Switch operation failed\n");
799 }
800 }
801
802 if (ios->clock) {
803 dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
804 if (dsor < 1)
805 dsor = 1;
806
807 if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
808 dsor++;
809
810 if (dsor > 250)
811 dsor = 250;
812 }
813 omap_mmc_stop_clock(host);
814 regval = OMAP_HSMMC_READ(host->base, SYSCTL);
815 regval = regval & ~(CLKD_MASK);
816 regval = regval | (dsor << 6) | (DTO << 16);
817 OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
818 OMAP_HSMMC_WRITE(host->base, SYSCTL,
819 OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
820
821 /* Wait till the ICS bit is set */
822 timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
823 while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != 0x2
824 && time_before(jiffies, timeout))
825 msleep(1);
826
827 OMAP_HSMMC_WRITE(host->base, SYSCTL,
828 OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
829
830 if (ios->power_mode == MMC_POWER_ON)
831 send_init_stream(host);
832
833 if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
834 OMAP_HSMMC_WRITE(host->base, CON,
835 OMAP_HSMMC_READ(host->base, CON) | OD);
836}
837
838static int omap_hsmmc_get_cd(struct mmc_host *mmc)
839{
840 struct mmc_omap_host *host = mmc_priv(mmc);
841 struct omap_mmc_platform_data *pdata = host->pdata;
842
843 if (!pdata->slots[0].card_detect)
844 return -ENOSYS;
845 return pdata->slots[0].card_detect(pdata->slots[0].card_detect_irq);
846}
847
848static int omap_hsmmc_get_ro(struct mmc_host *mmc)
849{
850 struct mmc_omap_host *host = mmc_priv(mmc);
851 struct omap_mmc_platform_data *pdata = host->pdata;
852
853 if (!pdata->slots[0].get_ro)
854 return -ENOSYS;
855 return pdata->slots[0].get_ro(host->dev, 0);
856}
857
858static struct mmc_host_ops mmc_omap_ops = {
859 .request = omap_mmc_request,
860 .set_ios = omap_mmc_set_ios,
861 .get_cd = omap_hsmmc_get_cd,
862 .get_ro = omap_hsmmc_get_ro,
863 /* NYET -- enable_sdio_irq */
864};
865
866static int __init omap_mmc_probe(struct platform_device *pdev)
867{
868 struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
869 struct mmc_host *mmc;
870 struct mmc_omap_host *host = NULL;
871 struct resource *res;
872 int ret = 0, irq;
873 u32 hctl, capa;
874
875 if (pdata == NULL) {
876 dev_err(&pdev->dev, "Platform Data is missing\n");
877 return -ENXIO;
878 }
879
880 if (pdata->nr_slots == 0) {
881 dev_err(&pdev->dev, "No Slots\n");
882 return -ENXIO;
883 }
884
885 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
886 irq = platform_get_irq(pdev, 0);
887 if (res == NULL || irq < 0)
888 return -ENXIO;
889
890 res = request_mem_region(res->start, res->end - res->start + 1,
891 pdev->name);
892 if (res == NULL)
893 return -EBUSY;
894
895 mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
896 if (!mmc) {
897 ret = -ENOMEM;
898 goto err;
899 }
900
901 host = mmc_priv(mmc);
902 host->mmc = mmc;
903 host->pdata = pdata;
904 host->dev = &pdev->dev;
905 host->use_dma = 1;
906 host->dev->dma_mask = &pdata->dma_mask;
907 host->dma_ch = -1;
908 host->irq = irq;
909 host->id = pdev->id;
910 host->slot_id = 0;
911 host->mapbase = res->start;
912 host->base = ioremap(host->mapbase, SZ_4K);
913
914 platform_set_drvdata(pdev, host);
915 INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect);
916
917 mmc->ops = &mmc_omap_ops;
918 mmc->f_min = 400000;
919 mmc->f_max = 52000000;
920
921 sema_init(&host->sem, 1);
922
923 host->iclk = clk_get(&pdev->dev, "mmchs_ick");
924 if (IS_ERR(host->iclk)) {
925 ret = PTR_ERR(host->iclk);
926 host->iclk = NULL;
927 goto err1;
928 }
929 host->fclk = clk_get(&pdev->dev, "mmchs_fck");
930 if (IS_ERR(host->fclk)) {
931 ret = PTR_ERR(host->fclk);
932 host->fclk = NULL;
933 clk_put(host->iclk);
934 goto err1;
935 }
936
937 if (clk_enable(host->fclk) != 0) {
938 clk_put(host->iclk);
939 clk_put(host->fclk);
940 goto err1;
941 }
942
943 if (clk_enable(host->iclk) != 0) {
944 clk_disable(host->fclk);
945 clk_put(host->iclk);
946 clk_put(host->fclk);
947 goto err1;
948 }
949
950 host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
951 /*
952 * MMC can still work without debounce clock.
953 */
954 if (IS_ERR(host->dbclk))
955 dev_warn(mmc_dev(host->mmc), "Failed to get debounce clock\n");
956 else
957 if (clk_enable(host->dbclk) != 0)
958 dev_dbg(mmc_dev(host->mmc), "Enabling debounce"
959 " clk failed\n");
960 else
961 host->dbclk_enabled = 1;
962
963#ifdef CONFIG_MMC_BLOCK_BOUNCE
964 mmc->max_phys_segs = 1;
965 mmc->max_hw_segs = 1;
966#endif
967 mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
968 mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
969 mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
970 mmc->max_seg_size = mmc->max_req_size;
971
972 mmc->ocr_avail = mmc_slot(host).ocr_mask;
973 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
974
975 if (pdata->slots[host->slot_id].wires >= 4)
976 mmc->caps |= MMC_CAP_4_BIT_DATA;
977
978 /* Only MMC1 supports 3.0V */
979 if (host->id == OMAP_MMC1_DEVID) {
980 hctl = SDVS30;
981 capa = VS30 | VS18;
982 } else {
983 hctl = SDVS18;
984 capa = VS18;
985 }
986
987 OMAP_HSMMC_WRITE(host->base, HCTL,
988 OMAP_HSMMC_READ(host->base, HCTL) | hctl);
989
990 OMAP_HSMMC_WRITE(host->base, CAPA,
991 OMAP_HSMMC_READ(host->base, CAPA) | capa);
992
993 /* Set the controller to AUTO IDLE mode */
994 OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
995 OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
996
997 /* Set SD bus power bit */
998 OMAP_HSMMC_WRITE(host->base, HCTL,
999 OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
1000
1001 /* Request IRQ for MMC operations */
1002 ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED,
1003 mmc_hostname(mmc), host);
1004 if (ret) {
1005 dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
1006 goto err_irq;
1007 }
1008
1009 if (pdata->init != NULL) {
1010 if (pdata->init(&pdev->dev) != 0) {
1011 dev_dbg(mmc_dev(host->mmc),
1012 "Unable to configure MMC IRQs\n");
1013 goto err_irq_cd_init;
1014 }
1015 }
1016
1017 /* Request IRQ for card detect */
1018 if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) {
1019 ret = request_irq(mmc_slot(host).card_detect_irq,
1020 omap_mmc_cd_handler,
1021 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1022 | IRQF_DISABLED,
1023 mmc_hostname(mmc), host);
1024 if (ret) {
1025 dev_dbg(mmc_dev(host->mmc),
1026 "Unable to grab MMC CD IRQ\n");
1027 goto err_irq_cd;
1028 }
1029 }
1030
1031 OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
1032 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
1033
1034 mmc_add_host(mmc);
1035
1036 if (host->pdata->slots[host->slot_id].name != NULL) {
1037 ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name);
1038 if (ret < 0)
1039 goto err_slot_name;
1040 }
1041 if (mmc_slot(host).card_detect_irq && mmc_slot(host).card_detect &&
1042 host->pdata->slots[host->slot_id].get_cover_state) {
1043 ret = device_create_file(&mmc->class_dev,
1044 &dev_attr_cover_switch);
1045 if (ret < 0)
1046 goto err_cover_switch;
1047 }
1048
1049 return 0;
1050
1051err_cover_switch:
1052 device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
1053err_slot_name:
1054 mmc_remove_host(mmc);
1055err_irq_cd:
1056 free_irq(mmc_slot(host).card_detect_irq, host);
1057err_irq_cd_init:
1058 free_irq(host->irq, host);
1059err_irq:
1060 clk_disable(host->fclk);
1061 clk_disable(host->iclk);
1062 clk_put(host->fclk);
1063 clk_put(host->iclk);
1064 if (host->dbclk_enabled) {
1065 clk_disable(host->dbclk);
1066 clk_put(host->dbclk);
1067 }
1068
1069err1:
1070 iounmap(host->base);
1071err:
1072 dev_dbg(mmc_dev(host->mmc), "Probe Failed\n");
1073 release_mem_region(res->start, res->end - res->start + 1);
1074 if (host)
1075 mmc_free_host(mmc);
1076 return ret;
1077}
1078
1079static int omap_mmc_remove(struct platform_device *pdev)
1080{
1081 struct mmc_omap_host *host = platform_get_drvdata(pdev);
1082 struct resource *res;
1083
1084 if (host) {
1085 mmc_remove_host(host->mmc);
1086 if (host->pdata->cleanup)
1087 host->pdata->cleanup(&pdev->dev);
1088 free_irq(host->irq, host);
1089 if (mmc_slot(host).card_detect_irq)
1090 free_irq(mmc_slot(host).card_detect_irq, host);
1091 flush_scheduled_work();
1092
1093 clk_disable(host->fclk);
1094 clk_disable(host->iclk);
1095 clk_put(host->fclk);
1096 clk_put(host->iclk);
1097 if (host->dbclk_enabled) {
1098 clk_disable(host->dbclk);
1099 clk_put(host->dbclk);
1100 }
1101
1102 mmc_free_host(host->mmc);
1103 iounmap(host->base);
1104 }
1105
1106 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1107 if (res)
1108 release_mem_region(res->start, res->end - res->start + 1);
1109 platform_set_drvdata(pdev, NULL);
1110
1111 return 0;
1112}
1113
1114#ifdef CONFIG_PM
1115static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
1116{
1117 int ret = 0;
1118 struct mmc_omap_host *host = platform_get_drvdata(pdev);
1119
1120 if (host && host->suspended)
1121 return 0;
1122
1123 if (host) {
1124 ret = mmc_suspend_host(host->mmc, state);
1125 if (ret == 0) {
1126 host->suspended = 1;
1127
1128 OMAP_HSMMC_WRITE(host->base, ISE, 0);
1129 OMAP_HSMMC_WRITE(host->base, IE, 0);
1130
1131 if (host->pdata->suspend) {
1132 ret = host->pdata->suspend(&pdev->dev,
1133 host->slot_id);
1134 if (ret)
1135 dev_dbg(mmc_dev(host->mmc),
1136 "Unable to handle MMC board"
1137 " level suspend\n");
1138 }
1139
1140 if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
1141 OMAP_HSMMC_WRITE(host->base, HCTL,
1142 OMAP_HSMMC_READ(host->base, HCTL)
1143 & SDVSCLR);
1144 OMAP_HSMMC_WRITE(host->base, HCTL,
1145 OMAP_HSMMC_READ(host->base, HCTL)
1146 | SDVS30);
1147 OMAP_HSMMC_WRITE(host->base, HCTL,
1148 OMAP_HSMMC_READ(host->base, HCTL)
1149 | SDBP);
1150 }
1151
1152 clk_disable(host->fclk);
1153 clk_disable(host->iclk);
1154 clk_disable(host->dbclk);
1155 }
1156
1157 }
1158 return ret;
1159}
1160
1161/* Routine to resume the MMC device */
1162static int omap_mmc_resume(struct platform_device *pdev)
1163{
1164 int ret = 0;
1165 struct mmc_omap_host *host = platform_get_drvdata(pdev);
1166
1167 if (host && !host->suspended)
1168 return 0;
1169
1170 if (host) {
1171
1172 ret = clk_enable(host->fclk);
1173 if (ret)
1174 goto clk_en_err;
1175
1176 ret = clk_enable(host->iclk);
1177 if (ret) {
1178 clk_disable(host->fclk);
1179 clk_put(host->fclk);
1180 goto clk_en_err;
1181 }
1182
1183 if (clk_enable(host->dbclk) != 0)
1184 dev_dbg(mmc_dev(host->mmc),
1185 "Enabling debounce clk failed\n");
1186
1187 if (host->pdata->resume) {
1188 ret = host->pdata->resume(&pdev->dev, host->slot_id);
1189 if (ret)
1190 dev_dbg(mmc_dev(host->mmc),
1191 "Unmask interrupt failed\n");
1192 }
1193
1194 /* Notify the core to resume the host */
1195 ret = mmc_resume_host(host->mmc);
1196 if (ret == 0)
1197 host->suspended = 0;
1198 }
1199
1200 return ret;
1201
1202clk_en_err:
1203 dev_dbg(mmc_dev(host->mmc),
1204 "Failed to enable MMC clocks during resume\n");
1205 return ret;
1206}
1207
1208#else
1209#define omap_mmc_suspend NULL
1210#define omap_mmc_resume NULL
1211#endif
1212
1213static struct platform_driver omap_mmc_driver = {
1214 .probe = omap_mmc_probe,
1215 .remove = omap_mmc_remove,
1216 .suspend = omap_mmc_suspend,
1217 .resume = omap_mmc_resume,
1218 .driver = {
1219 .name = DRIVER_NAME,
1220 .owner = THIS_MODULE,
1221 },
1222};
1223
1224static int __init omap_mmc_init(void)
1225{
1226 /* Register the MMC driver */
1227 return platform_driver_register(&omap_mmc_driver);
1228}
1229
1230static void __exit omap_mmc_cleanup(void)
1231{
1232 /* Unregister MMC driver */
1233 platform_driver_unregister(&omap_mmc_driver);
1234}
1235
1236module_init(omap_mmc_init);
1237module_exit(omap_mmc_cleanup);
1238
1239MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver");
1240MODULE_LICENSE("GPL");
1241MODULE_ALIAS("platform:" DRIVER_NAME);
1242MODULE_AUTHOR("Texas Instruments Inc");