aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2006-03-24 06:18:17 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-24 10:33:27 -0500
commitd129bceb1d44ed3c23b99164849193703372bab4 (patch)
treebcc7fbf2d0cde5fb437d835358ae42f788b14ac1
parent97f2478db161714d0e3e864f38f5789c66f98b81 (diff)
[PATCH] mmc: Secure Digital Host Controller Interface driver
Driver for the Secure Digital Host Controller Interface specification. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx> Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/mmc/Kconfig11
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/sdhci.c1265
-rw-r--r--drivers/mmc/sdhci.h185
5 files changed, 1469 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index bfd7fbfe90ab..5b6a0145505d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2488,6 +2488,13 @@ M: kristen.c.accardi@intel.com
2488L: pcihpd-discuss@lists.sourceforge.net 2488L: pcihpd-discuss@lists.sourceforge.net
2489S: Maintained 2489S: Maintained
2490 2490
2491SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
2492P: Pierre Ossman
2493M: drzeus-sdhci@drzeus.cx
2494L: sdhci-devel@list.drzeus.cx
2495W: http://mmc.drzeus.cx/wiki/Linux/Drivers/sdhci
2496S: Maintained
2497
2491SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS 2498SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
2492P: Stephen Hemminger 2499P: Stephen Hemminger
2493M: shemminger@osdl.org 2500M: shemminger@osdl.org
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 5d397b7a5497..3f5d77f633fa 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -49,6 +49,17 @@ config MMC_PXA
49 49
50 If unsure, say N. 50 If unsure, say N.
51 51
52config MMC_SDHCI
53 tristate "Secure Digital Host Controller Interface support (EXPERIMENTAL)"
54 depends on PCI && MMC && EXPERIMENTAL
55 help
56 This select the generic Secure Digital Host Controller Interface.
57 It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
58 and Toshiba(R). Most controllers found in laptops are of this type.
59 If you have a controller with this interface, say Y or M here.
60
61 If unsure, say N.
62
52config MMC_WBSD 63config MMC_WBSD
53 tristate "Winbond W83L51xD SD/MMC Card Interface support" 64 tristate "Winbond W83L51xD SD/MMC Card Interface support"
54 depends on MMC && ISA_DMA_API 65 depends on MMC && ISA_DMA_API
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index e351e71146e9..769d545284a4 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
17# 17#
18obj-$(CONFIG_MMC_ARMMMCI) += mmci.o 18obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
19obj-$(CONFIG_MMC_PXA) += pxamci.o 19obj-$(CONFIG_MMC_PXA) += pxamci.o
20obj-$(CONFIG_MMC_SDHCI) += sdhci.o
20obj-$(CONFIG_MMC_WBSD) += wbsd.o 21obj-$(CONFIG_MMC_WBSD) += wbsd.o
21obj-$(CONFIG_MMC_AU1X) += au1xmmc.o 22obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
22 23
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
new file mode 100644
index 000000000000..8b811d94371c
--- /dev/null
+++ b/drivers/mmc/sdhci.c
@@ -0,0 +1,1265 @@
1/*
2 * linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
3 *
4 * Copyright (C) 2005-2006 Pierre Ossman, All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11 /*
12 * Note that PIO transfer is rather crappy atm. The buffer full/empty
13 * interrupts aren't reliable so we currently transfer the entire buffer
14 * directly. Patches to solve the problem are welcome.
15 */
16
17#include <linux/delay.h>
18#include <linux/highmem.h>
19#include <linux/pci.h>
20#include <linux/dma-mapping.h>
21
22#include <linux/mmc/host.h>
23#include <linux/mmc/protocol.h>
24
25#include <asm/scatterlist.h>
26
27#include "sdhci.h"
28
29#define DRIVER_NAME "sdhci"
30#define DRIVER_VERSION "0.11"
31
32#define BUGMAIL "<sdhci-devel@list.drzeus.cx>"
33
34#ifdef CONFIG_MMC_DEBUG
35#define DBG(f, x...) \
36 printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__,## x)
37#else
38#define DBG(f, x...) do { } while (0)
39#endif
40
41static const struct pci_device_id pci_ids[] __devinitdata = {
42 /* handle any SD host controller */
43 {PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)},
44 { /* end: all zeroes */ },
45};
46
47MODULE_DEVICE_TABLE(pci, pci_ids);
48
49static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
50static void sdhci_finish_data(struct sdhci_host *);
51
52static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
53static void sdhci_finish_command(struct sdhci_host *);
54
55static void sdhci_dumpregs(struct sdhci_host *host)
56{
57 printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
58
59 printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n",
60 readl(host->ioaddr + SDHCI_DMA_ADDRESS),
61 readw(host->ioaddr + SDHCI_HOST_VERSION));
62 printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n",
63 readw(host->ioaddr + SDHCI_BLOCK_SIZE),
64 readw(host->ioaddr + SDHCI_BLOCK_COUNT));
65 printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
66 readl(host->ioaddr + SDHCI_ARGUMENT),
67 readw(host->ioaddr + SDHCI_TRANSFER_MODE));
68 printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n",
69 readl(host->ioaddr + SDHCI_PRESENT_STATE),
70 readb(host->ioaddr + SDHCI_HOST_CONTROL));
71 printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n",
72 readb(host->ioaddr + SDHCI_POWER_CONTROL),
73 readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL));
74 printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n",
75 readb(host->ioaddr + SDHCI_WALK_UP_CONTROL),
76 readw(host->ioaddr + SDHCI_CLOCK_CONTROL));
77 printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n",
78 readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL),
79 readl(host->ioaddr + SDHCI_INT_STATUS));
80 printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
81 readl(host->ioaddr + SDHCI_INT_ENABLE),
82 readl(host->ioaddr + SDHCI_SIGNAL_ENABLE));
83 printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
84 readw(host->ioaddr + SDHCI_ACMD12_ERR),
85 readw(host->ioaddr + SDHCI_SLOT_INT_STATUS));
86 printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n",
87 readl(host->ioaddr + SDHCI_CAPABILITIES),
88 readl(host->ioaddr + SDHCI_MAX_CURRENT));
89
90 printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
91}
92
93/*****************************************************************************\
94 * *
95 * Low level functions *
96 * *
97\*****************************************************************************/
98
99static void sdhci_reset(struct sdhci_host *host, u8 mask)
100{
101 writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET);
102
103 if (mask & SDHCI_RESET_ALL) {
104 host->clock = 0;
105
106 mdelay(50);
107 }
108}
109
110static void sdhci_init(struct sdhci_host *host)
111{
112 u32 intmask;
113
114 sdhci_reset(host, SDHCI_RESET_ALL);
115
116 intmask = ~(SDHCI_INT_CARD_INT | SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL);
117
118 writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
119 writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
120
121 /* This is unknown magic. */
122 writeb(0xE, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
123}
124
125static void sdhci_activate_led(struct sdhci_host *host)
126{
127 u8 ctrl;
128
129 ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
130 ctrl |= SDHCI_CTRL_LED;
131 writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
132}
133
134static void sdhci_deactivate_led(struct sdhci_host *host)
135{
136 u8 ctrl;
137
138 ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
139 ctrl &= ~SDHCI_CTRL_LED;
140 writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
141}
142
143/*****************************************************************************\
144 * *
145 * Core functions *
146 * *
147\*****************************************************************************/
148
149static inline char* sdhci_kmap_sg(struct sdhci_host* host)
150{
151 host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ);
152 return host->mapped_sg + host->cur_sg->offset;
153}
154
155static inline void sdhci_kunmap_sg(struct sdhci_host* host)
156{
157 kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
158}
159
160static inline int sdhci_next_sg(struct sdhci_host* host)
161{
162 /*
163 * Skip to next SG entry.
164 */
165 host->cur_sg++;
166 host->num_sg--;
167
168 /*
169 * Any entries left?
170 */
171 if (host->num_sg > 0) {
172 host->offset = 0;
173 host->remain = host->cur_sg->length;
174 }
175
176 return host->num_sg;
177}
178
179static void sdhci_transfer_pio(struct sdhci_host *host)
180{
181 char *buffer;
182 u32 mask;
183 int bytes, size;
184 unsigned long max_jiffies;
185
186 BUG_ON(!host->data);
187
188 if (host->num_sg == 0)
189 return;
190
191 bytes = 0;
192 if (host->data->flags & MMC_DATA_READ)
193 mask = SDHCI_DATA_AVAILABLE;
194 else
195 mask = SDHCI_SPACE_AVAILABLE;
196
197 buffer = sdhci_kmap_sg(host) + host->offset;
198
199 /* Transfer shouldn't take more than 5 s */
200 max_jiffies = jiffies + HZ * 5;
201
202 while (host->size > 0) {
203 if (time_after(jiffies, max_jiffies)) {
204 printk(KERN_ERR "%s: PIO transfer stalled. "
205 "Please report this to "
206 BUGMAIL ".\n", mmc_hostname(host->mmc));
207 sdhci_dumpregs(host);
208
209 sdhci_kunmap_sg(host);
210
211 host->data->error = MMC_ERR_FAILED;
212 sdhci_finish_data(host);
213 return;
214 }
215
216 if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask))
217 continue;
218
219 size = min(host->size, host->remain);
220
221 if (size >= 4) {
222 if (host->data->flags & MMC_DATA_READ)
223 *(u32*)buffer = readl(host->ioaddr + SDHCI_BUFFER);
224 else
225 writel(*(u32*)buffer, host->ioaddr + SDHCI_BUFFER);
226 size = 4;
227 } else if (size >= 2) {
228 if (host->data->flags & MMC_DATA_READ)
229 *(u16*)buffer = readw(host->ioaddr + SDHCI_BUFFER);
230 else
231 writew(*(u16*)buffer, host->ioaddr + SDHCI_BUFFER);
232 size = 2;
233 } else {
234 if (host->data->flags & MMC_DATA_READ)
235 *(u8*)buffer = readb(host->ioaddr + SDHCI_BUFFER);
236 else
237 writeb(*(u8*)buffer, host->ioaddr + SDHCI_BUFFER);
238 size = 1;
239 }
240
241 buffer += size;
242 host->offset += size;
243 host->remain -= size;
244
245 bytes += size;
246 host->size -= size;
247
248 if (host->remain == 0) {
249 sdhci_kunmap_sg(host);
250 if (sdhci_next_sg(host) == 0) {
251 DBG("PIO transfer: %d bytes\n", bytes);
252 return;
253 }
254 buffer = sdhci_kmap_sg(host);
255 }
256 }
257
258 sdhci_kunmap_sg(host);
259
260 DBG("PIO transfer: %d bytes\n", bytes);
261}
262
263static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
264{
265 u16 mode;
266
267 WARN_ON(host->data);
268
269 if (data == NULL) {
270 writew(0, host->ioaddr + SDHCI_TRANSFER_MODE);
271 return;
272 }
273
274 DBG("blksz %04x blks %04x flags %08x\n",
275 1 << data->blksz_bits, data->blocks, data->flags);
276 DBG("tsac %d ms nsac %d clk\n",
277 data->timeout_ns / 1000000, data->timeout_clks);
278
279 mode = SDHCI_TRNS_BLK_CNT_EN;
280 if (data->blocks > 1)
281 mode |= SDHCI_TRNS_MULTI;
282 if (data->flags & MMC_DATA_READ)
283 mode |= SDHCI_TRNS_READ;
284 if (host->flags & SDHCI_USE_DMA)
285 mode |= SDHCI_TRNS_DMA;
286
287 writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
288
289 writew(1 << data->blksz_bits, host->ioaddr + SDHCI_BLOCK_SIZE);
290 writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT);
291
292 if (host->flags & SDHCI_USE_DMA) {
293 int count;
294
295 count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len,
296 (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
297 BUG_ON(count != 1);
298
299 writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS);
300 } else {
301 host->size = (1 << data->blksz_bits) * data->blocks;
302
303 host->cur_sg = data->sg;
304 host->num_sg = data->sg_len;
305
306 host->offset = 0;
307 host->remain = host->cur_sg->length;
308 }
309}
310
311static void sdhci_finish_data(struct sdhci_host *host)
312{
313 struct mmc_data *data;
314 u32 intmask;
315 u16 blocks;
316
317 BUG_ON(!host->data);
318
319 data = host->data;
320 host->data = NULL;
321
322 if (host->flags & SDHCI_USE_DMA) {
323 pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len,
324 (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
325 } else {
326 intmask = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);
327 intmask &= ~(SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL);
328 writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
329
330 intmask = readl(host->ioaddr + SDHCI_INT_ENABLE);
331 intmask &= ~(SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL);
332 writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
333 }
334
335 /*
336 * Controller doesn't count down when in single block mode.
337 */
338 if ((data->blocks == 1) && (data->error == MMC_ERR_NONE))
339 blocks = 0;
340 else
341 blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT);
342 data->bytes_xfered = (1 << data->blksz_bits) * (data->blocks - blocks);
343
344 if ((data->error == MMC_ERR_NONE) && blocks) {
345 printk(KERN_ERR "%s: Controller signalled completion even "
346 "though there were blocks left. Please report this "
347 "to " BUGMAIL ".\n", mmc_hostname(host->mmc));
348 data->error = MMC_ERR_FAILED;
349 }
350
351 if (host->size != 0) {
352 printk(KERN_ERR "%s: %d bytes were left untransferred. "
353 "Please report this to " BUGMAIL ".\n",
354 mmc_hostname(host->mmc), host->size);
355 data->error = MMC_ERR_FAILED;
356 }
357
358 DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
359
360 if (data->stop) {
361 /*
362 * The controller needs a reset of internal state machines
363 * upon error conditions.
364 */
365 if (data->error != MMC_ERR_NONE) {
366 sdhci_reset(host, SDHCI_RESET_CMD);
367 sdhci_reset(host, SDHCI_RESET_DATA);
368 }
369
370 sdhci_send_command(host, data->stop);
371 } else
372 tasklet_schedule(&host->finish_tasklet);
373}
374
375static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
376{
377 int flags;
378 u32 present;
379 unsigned long max_jiffies;
380
381 WARN_ON(host->cmd);
382
383 DBG("Sending cmd (%x)\n", cmd->opcode);
384
385 /* Wait max 10 ms */
386 max_jiffies = jiffies + (HZ + 99)/100;
387 do {
388 if (time_after(jiffies, max_jiffies)) {
389 printk(KERN_ERR "%s: Controller never released "
390 "inhibit bits. Please report this to "
391 BUGMAIL ".\n", mmc_hostname(host->mmc));
392 sdhci_dumpregs(host);
393 cmd->error = MMC_ERR_FAILED;
394 tasklet_schedule(&host->finish_tasklet);
395 return;
396 }
397 present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
398 } while (present & (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT));
399
400 mod_timer(&host->timer, jiffies + 10 * HZ);
401
402 host->cmd = cmd;
403
404 sdhci_prepare_data(host, cmd->data);
405
406 writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT);
407
408 if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
409 printk(KERN_ERR "%s: Unsupported response type! "
410 "Please report this to " BUGMAIL ".\n",
411 mmc_hostname(host->mmc));
412 cmd->error = MMC_ERR_INVALID;
413 tasklet_schedule(&host->finish_tasklet);
414 return;
415 }
416
417 if (!(cmd->flags & MMC_RSP_PRESENT))
418 flags = SDHCI_CMD_RESP_NONE;
419 else if (cmd->flags & MMC_RSP_136)
420 flags = SDHCI_CMD_RESP_LONG;
421 else if (cmd->flags & MMC_RSP_BUSY)
422 flags = SDHCI_CMD_RESP_SHORT_BUSY;
423 else
424 flags = SDHCI_CMD_RESP_SHORT;
425
426 if (cmd->flags & MMC_RSP_CRC)
427 flags |= SDHCI_CMD_CRC;
428 if (cmd->flags & MMC_RSP_OPCODE)
429 flags |= SDHCI_CMD_INDEX;
430 if (cmd->data)
431 flags |= SDHCI_CMD_DATA;
432
433 writel(SDHCI_MAKE_CMD(cmd->opcode, flags),
434 host->ioaddr + SDHCI_COMMAND);
435}
436
437static void sdhci_finish_command(struct sdhci_host *host)
438{
439 int i;
440
441 BUG_ON(host->cmd == NULL);
442
443 if (host->cmd->flags & MMC_RSP_PRESENT) {
444 if (host->cmd->flags & MMC_RSP_136) {
445 /* CRC is stripped so we need to do some shifting. */
446 for (i = 0;i < 4;i++) {
447 host->cmd->resp[i] = readl(host->ioaddr +
448 SDHCI_RESPONSE + (3-i)*4) << 8;
449 if (i != 3)
450 host->cmd->resp[i] |=
451 readb(host->ioaddr +
452 SDHCI_RESPONSE + (3-i)*4-1);
453 }
454 } else {
455 host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE);
456 }
457 }
458
459 host->cmd->error = MMC_ERR_NONE;
460
461 DBG("Ending cmd (%x)\n", host->cmd->opcode);
462
463 if (host->cmd->data) {
464 u32 intmask;
465
466 host->data = host->cmd->data;
467
468 if (!(host->flags & SDHCI_USE_DMA)) {
469 /*
470 * Don't enable the interrupts until now to make sure we
471 * get stable handling of the FIFO.
472 */
473 intmask = readl(host->ioaddr + SDHCI_INT_ENABLE);
474 intmask |= SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL;
475 writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
476
477 intmask = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);
478 intmask |= SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL;
479 writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
480
481 /*
482 * The buffer interrupts are to unreliable so we
483 * start the transfer immediatly.
484 */
485 sdhci_transfer_pio(host);
486 }
487 } else
488 tasklet_schedule(&host->finish_tasklet);
489
490 host->cmd = NULL;
491}
492
493static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
494{
495 int div;
496 u16 clk;
497 unsigned long max_jiffies;
498
499 if (clock == host->clock)
500 return;
501
502 writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
503
504 if (clock == 0)
505 goto out;
506
507 for (div = 1;div < 256;div *= 2) {
508 if ((host->max_clk / div) <= clock)
509 break;
510 }
511 div >>= 1;
512
513 clk = div << SDHCI_DIVIDER_SHIFT;
514 clk |= SDHCI_CLOCK_INT_EN;
515 writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
516
517 /* Wait max 10 ms */
518 max_jiffies = jiffies + (HZ + 99)/100;
519 do {
520 if (time_after(jiffies, max_jiffies)) {
521 printk(KERN_ERR "%s: Internal clock never stabilised. "
522 "Please report this to " BUGMAIL ".\n",
523 mmc_hostname(host->mmc));
524 sdhci_dumpregs(host);
525 return;
526 }
527 clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL);
528 } while (!(clk & SDHCI_CLOCK_INT_STABLE));
529
530 clk |= SDHCI_CLOCK_CARD_EN;
531 writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
532
533out:
534 host->clock = clock;
535}
536
537/*****************************************************************************\
538 * *
539 * MMC callbacks *
540 * *
541\*****************************************************************************/
542
543static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
544{
545 struct sdhci_host *host;
546 unsigned long flags;
547
548 host = mmc_priv(mmc);
549
550 spin_lock_irqsave(&host->lock, flags);
551
552 WARN_ON(host->mrq != NULL);
553
554 sdhci_activate_led(host);
555
556 host->mrq = mrq;
557
558 if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
559 host->mrq->cmd->error = MMC_ERR_TIMEOUT;
560 tasklet_schedule(&host->finish_tasklet);
561 } else
562 sdhci_send_command(host, mrq->cmd);
563
564 spin_unlock_irqrestore(&host->lock, flags);
565}
566
567static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
568{
569 struct sdhci_host *host;
570 unsigned long flags;
571 u8 ctrl;
572
573 host = mmc_priv(mmc);
574
575 spin_lock_irqsave(&host->lock, flags);
576
577 DBG("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
578 ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
579 ios->vdd, ios->bus_width);
580
581 /*
582 * Reset the chip on each power off.
583 * Should clear out any weird states.
584 */
585 if (ios->power_mode == MMC_POWER_OFF) {
586 writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
587 spin_unlock_irqrestore(&host->lock, flags);
588 sdhci_init(host);
589 spin_lock_irqsave(&host->lock, flags);
590 }
591
592 sdhci_set_clock(host, ios->clock);
593
594 if (ios->power_mode == MMC_POWER_OFF)
595 writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
596 else
597 writeb(0xFF, host->ioaddr + SDHCI_POWER_CONTROL);
598
599 ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
600 if (ios->bus_width == MMC_BUS_WIDTH_4)
601 ctrl |= SDHCI_CTRL_4BITBUS;
602 else
603 ctrl &= ~SDHCI_CTRL_4BITBUS;
604 writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
605
606 spin_unlock_irqrestore(&host->lock, flags);
607}
608
609static int sdhci_get_ro(struct mmc_host *mmc)
610{
611 struct sdhci_host *host;
612 unsigned long flags;
613 int present;
614
615 host = mmc_priv(mmc);
616
617 spin_lock_irqsave(&host->lock, flags);
618
619 present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
620
621 spin_unlock_irqrestore(&host->lock, flags);
622
623 return !(present & SDHCI_WRITE_PROTECT);
624}
625
626static struct mmc_host_ops sdhci_ops = {
627 .request = sdhci_request,
628 .set_ios = sdhci_set_ios,
629 .get_ro = sdhci_get_ro,
630};
631
632/*****************************************************************************\
633 * *
634 * Tasklets *
635 * *
636\*****************************************************************************/
637
638static void sdhci_tasklet_card(unsigned long param)
639{
640 struct sdhci_host *host;
641 unsigned long flags;
642
643 host = (struct sdhci_host*)param;
644
645 spin_lock_irqsave(&host->lock, flags);
646
647 if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
648 if (host->mrq) {
649 printk(KERN_ERR "%s: Card removed during transfer!\n",
650 mmc_hostname(host->mmc));
651 printk(KERN_ERR "%s: Resetting controller.\n",
652 mmc_hostname(host->mmc));
653
654 sdhci_reset(host, SDHCI_RESET_CMD);
655 sdhci_reset(host, SDHCI_RESET_DATA);
656
657 host->mrq->cmd->error = MMC_ERR_FAILED;
658 tasklet_schedule(&host->finish_tasklet);
659 }
660 }
661
662 spin_unlock_irqrestore(&host->lock, flags);
663
664 mmc_detect_change(host->mmc, msecs_to_jiffies(500));
665}
666
667static void sdhci_tasklet_finish(unsigned long param)
668{
669 struct sdhci_host *host;
670 unsigned long flags;
671 struct mmc_request *mrq;
672
673 host = (struct sdhci_host*)param;
674
675 spin_lock_irqsave(&host->lock, flags);
676
677 del_timer(&host->timer);
678
679 mrq = host->mrq;
680
681 DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode);
682
683 /*
684 * The controller needs a reset of internal state machines
685 * upon error conditions.
686 */
687 if ((mrq->cmd->error != MMC_ERR_NONE) ||
688 (mrq->data && ((mrq->data->error != MMC_ERR_NONE) ||
689 (mrq->data->stop && (mrq->data->stop->error != MMC_ERR_NONE))))) {
690 sdhci_reset(host, SDHCI_RESET_CMD);
691 sdhci_reset(host, SDHCI_RESET_DATA);
692 }
693
694 host->mrq = NULL;
695 host->cmd = NULL;
696 host->data = NULL;
697
698 sdhci_deactivate_led(host);
699
700 spin_unlock_irqrestore(&host->lock, flags);
701
702 mmc_request_done(host->mmc, mrq);
703}
704
705static void sdhci_timeout_timer(unsigned long data)
706{
707 struct sdhci_host *host;
708 unsigned long flags;
709
710 host = (struct sdhci_host*)data;
711
712 spin_lock_irqsave(&host->lock, flags);
713
714 if (host->mrq) {
715 printk(KERN_ERR "%s: Timeout waiting for hardware interrupt. "
716 "Please report this to " BUGMAIL ".\n",
717 mmc_hostname(host->mmc));
718 sdhci_dumpregs(host);
719
720 if (host->data) {
721 host->data->error = MMC_ERR_TIMEOUT;
722 sdhci_finish_data(host);
723 } else {
724 if (host->cmd)
725 host->cmd->error = MMC_ERR_TIMEOUT;
726 else
727 host->mrq->cmd->error = MMC_ERR_TIMEOUT;
728
729 tasklet_schedule(&host->finish_tasklet);
730 }
731 }
732
733 spin_unlock_irqrestore(&host->lock, flags);
734}
735
736/*****************************************************************************\
737 * *
738 * Interrupt handling *
739 * *
740\*****************************************************************************/
741
742static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
743{
744 BUG_ON(intmask == 0);
745
746 if (!host->cmd) {
747 printk(KERN_ERR "%s: Got command interrupt even though no "
748 "command operation was in progress.\n",
749 mmc_hostname(host->mmc));
750 printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n",
751 mmc_hostname(host->mmc));
752 sdhci_dumpregs(host);
753 return;
754 }
755
756 if (intmask & SDHCI_INT_RESPONSE)
757 sdhci_finish_command(host);
758 else {
759 if (intmask & SDHCI_INT_TIMEOUT)
760 host->cmd->error = MMC_ERR_TIMEOUT;
761 else if (intmask & SDHCI_INT_CRC)
762 host->cmd->error = MMC_ERR_BADCRC;
763 else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
764 host->cmd->error = MMC_ERR_FAILED;
765 else
766 host->cmd->error = MMC_ERR_INVALID;
767
768 tasklet_schedule(&host->finish_tasklet);
769 }
770}
771
772static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
773{
774 BUG_ON(intmask == 0);
775
776 if (!host->data) {
777 /*
778 * A data end interrupt is sent together with the response
779 * for the stop command.
780 */
781 if (intmask & SDHCI_INT_DATA_END)
782 return;
783
784 printk(KERN_ERR "%s: Got data interrupt even though no "
785 "data operation was in progress.\n",
786 mmc_hostname(host->mmc));
787 printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n",
788 mmc_hostname(host->mmc));
789 sdhci_dumpregs(host);
790
791 return;
792 }
793
794 if (intmask & SDHCI_INT_DATA_TIMEOUT)
795 host->data->error = MMC_ERR_TIMEOUT;
796 else if (intmask & SDHCI_INT_DATA_CRC)
797 host->data->error = MMC_ERR_BADCRC;
798 else if (intmask & SDHCI_INT_DATA_END_BIT)
799 host->data->error = MMC_ERR_FAILED;
800
801 if (host->data->error != MMC_ERR_NONE)
802 sdhci_finish_data(host);
803 else {
804 if (intmask & (SDHCI_INT_BUF_FULL | SDHCI_INT_BUF_EMPTY))
805 sdhci_transfer_pio(host);
806
807 if (intmask & SDHCI_INT_DATA_END)
808 sdhci_finish_data(host);
809 }
810}
811
812static irqreturn_t sdhci_irq(int irq, void *dev_id, struct pt_regs *regs)
813{
814 irqreturn_t result;
815 struct sdhci_host* host = dev_id;
816 u32 intmask;
817
818 spin_lock(&host->lock);
819
820 intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
821
822 if (!intmask) {
823 result = IRQ_NONE;
824 goto out;
825 }
826
827 DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask);
828
829 if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE))
830 tasklet_schedule(&host->card_tasklet);
831
832 if (intmask & SDHCI_INT_CMD_MASK) {
833 sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
834
835 writel(intmask & SDHCI_INT_CMD_MASK,
836 host->ioaddr + SDHCI_INT_STATUS);
837 }
838
839 if (intmask & SDHCI_INT_DATA_MASK) {
840 sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
841
842 writel(intmask & SDHCI_INT_DATA_MASK,
843 host->ioaddr + SDHCI_INT_STATUS);
844 }
845
846 intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
847
848 if (intmask & SDHCI_INT_CARD_INT) {
849 printk(KERN_ERR "%s: Unexpected card interrupt. Please "
850 "report this to " BUGMAIL ".\n",
851 mmc_hostname(host->mmc));
852 sdhci_dumpregs(host);
853 }
854
855 if (intmask & SDHCI_INT_BUS_POWER) {
856 printk(KERN_ERR "%s: Unexpected bus power interrupt. Please "
857 "report this to " BUGMAIL ".\n",
858 mmc_hostname(host->mmc));
859 sdhci_dumpregs(host);
860 }
861
862 if (intmask & SDHCI_INT_ACMD12ERR) {
863 printk(KERN_ERR "%s: Unexpected auto CMD12 error. Please "
864 "report this to " BUGMAIL ".\n",
865 mmc_hostname(host->mmc));
866 sdhci_dumpregs(host);
867
868 writew(~0, host->ioaddr + SDHCI_ACMD12_ERR);
869 }
870
871 if (intmask)
872 writel(intmask, host->ioaddr + SDHCI_INT_STATUS);
873
874 result = IRQ_HANDLED;
875
876out:
877 spin_unlock(&host->lock);
878
879 return result;
880}
881
882/*****************************************************************************\
883 * *
884 * Suspend/resume *
885 * *
886\*****************************************************************************/
887
888#ifdef CONFIG_PM
889
890static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state)
891{
892 struct sdhci_chip *chip;
893 int i, ret;
894
895 chip = pci_get_drvdata(pdev);
896 if (!chip)
897 return 0;
898
899 DBG("Suspending...\n");
900
901 for (i = 0;i < chip->num_slots;i++) {
902 if (!chip->hosts[i])
903 continue;
904 ret = mmc_suspend_host(chip->hosts[i]->mmc, state);
905 if (ret) {
906 for (i--;i >= 0;i--)
907 mmc_resume_host(chip->hosts[i]->mmc);
908 return ret;
909 }
910 }
911
912 pci_save_state(pdev);
913 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
914 pci_disable_device(pdev);
915 pci_set_power_state(pdev, pci_choose_state(pdev, state));
916
917 return 0;
918}
919
920static int sdhci_resume (struct pci_dev *pdev)
921{
922 struct sdhci_chip *chip;
923 int i, ret;
924
925 chip = pci_get_drvdata(pdev);
926 if (!chip)
927 return 0;
928
929 DBG("Resuming...\n");
930
931 pci_set_power_state(pdev, PCI_D0);
932 pci_restore_state(pdev);
933 pci_enable_device(pdev);
934
935 for (i = 0;i < chip->num_slots;i++) {
936 if (!chip->hosts[i])
937 continue;
938 if (chip->hosts[i]->flags & SDHCI_USE_DMA)
939 pci_set_master(pdev);
940 sdhci_init(chip->hosts[i]);
941 ret = mmc_resume_host(chip->hosts[i]->mmc);
942 if (ret)
943 return ret;
944 }
945
946 return 0;
947}
948
949#else /* CONFIG_PM */
950
951#define sdhci_suspend NULL
952#define sdhci_resume NULL
953
954#endif /* CONFIG_PM */
955
956/*****************************************************************************\
957 * *
958 * Device probing/removal *
959 * *
960\*****************************************************************************/
961
962static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
963{
964 int ret;
965 struct sdhci_chip *chip;
966 struct mmc_host *mmc;
967 struct sdhci_host *host;
968
969 u8 first_bar;
970 unsigned int caps;
971
972 chip = pci_get_drvdata(pdev);
973 BUG_ON(!chip);
974
975 ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
976 if (ret)
977 return ret;
978
979 first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
980
981 if (first_bar > 5) {
982 printk(KERN_ERR DRIVER_NAME ": Invalid first BAR. Aborting.\n");
983 return -ENODEV;
984 }
985
986 if (!(pci_resource_flags(pdev, first_bar + slot) & IORESOURCE_MEM)) {
987 printk(KERN_ERR DRIVER_NAME ": BAR is not iomem. Aborting.\n");
988 return -ENODEV;
989 }
990
991 if (pci_resource_len(pdev, first_bar + slot) != 0x100) {
992 printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n");
993 return -ENODEV;
994 }
995
996 mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev);
997 if (!mmc)
998 return -ENOMEM;
999
1000 host = mmc_priv(mmc);
1001 host->mmc = mmc;
1002
1003 host->bar = first_bar + slot;
1004
1005 host->addr = pci_resource_start(pdev, host->bar);
1006 host->irq = pdev->irq;
1007
1008 DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
1009
1010 snprintf(host->slot_descr, 20, "sdhci:slot%d", slot);
1011
1012 ret = pci_request_region(pdev, host->bar, host->slot_descr);
1013 if (ret)
1014 goto free;
1015
1016 host->ioaddr = ioremap_nocache(host->addr,
1017 pci_resource_len(pdev, host->bar));
1018 if (!host->ioaddr) {
1019 ret = -ENOMEM;
1020 goto release;
1021 }
1022
1023 caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
1024
1025 if ((caps & SDHCI_CAN_DO_DMA) && ((pdev->class & 0x0000FF) == 0x01))
1026 host->flags |= SDHCI_USE_DMA;
1027
1028 if (host->flags & SDHCI_USE_DMA) {
1029 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1030 printk(KERN_WARNING "%s: No suitable DMA available. "
1031 "Falling back to PIO.\n", host->slot_descr);
1032 host->flags &= ~SDHCI_USE_DMA;
1033 }
1034 }
1035
1036 if (host->flags & SDHCI_USE_DMA)
1037 pci_set_master(pdev);
1038 else /* XXX: Hack to get MMC layer to avoid highmem */
1039 pdev->dma_mask = 0;
1040
1041 host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
1042 host->max_clk *= 1000000;
1043
1044 /*
1045 * Set host parameters.
1046 */
1047 mmc->ops = &sdhci_ops;
1048 mmc->f_min = host->max_clk / 256;
1049 mmc->f_max = host->max_clk;
1050 mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
1051 mmc->caps = MMC_CAP_4_BIT_DATA;
1052
1053 spin_lock_init(&host->lock);
1054
1055 /*
1056 * Maximum number of segments. Hardware cannot do scatter lists.
1057 */
1058 if (host->flags & SDHCI_USE_DMA)
1059 mmc->max_hw_segs = 1;
1060 else
1061 mmc->max_hw_segs = 16;
1062 mmc->max_phys_segs = 16;
1063
1064 /*
1065 * Maximum number of sectors in one transfer. Limited by sector
1066 * count register.
1067 */
1068 mmc->max_sectors = 0x3FFF;
1069
1070 /*
1071 * Maximum segment size. Could be one segment with the maximum number
1072 * of sectors.
1073 */
1074 mmc->max_seg_size = mmc->max_sectors * 512;
1075
1076 /*
1077 * Init tasklets.
1078 */
1079 tasklet_init(&host->card_tasklet,
1080 sdhci_tasklet_card, (unsigned long)host);
1081 tasklet_init(&host->finish_tasklet,
1082 sdhci_tasklet_finish, (unsigned long)host);
1083
1084 setup_timer(&host->timer, sdhci_timeout_timer, (int)host);
1085
1086 ret = request_irq(host->irq, sdhci_irq, SA_SHIRQ,
1087 host->slot_descr, host);
1088 if (ret)
1089 goto unmap;
1090
1091 sdhci_init(host);
1092
1093#ifdef CONFIG_MMC_DEBUG
1094 sdhci_dumpregs(host);
1095#endif
1096
1097 host->chip = chip;
1098 chip->hosts[slot] = host;
1099
1100 mmc_add_host(mmc);
1101
1102 printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc),
1103 host->addr, host->irq,
1104 (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
1105
1106 return 0;
1107
1108unmap:
1109 tasklet_kill(&host->card_tasklet);
1110 tasklet_kill(&host->finish_tasklet);
1111
1112 iounmap(host->ioaddr);
1113release:
1114 pci_release_region(pdev, host->bar);
1115free:
1116 mmc_free_host(mmc);
1117
1118 return ret;
1119}
1120
1121static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
1122{
1123 struct sdhci_chip *chip;
1124 struct mmc_host *mmc;
1125 struct sdhci_host *host;
1126
1127 chip = pci_get_drvdata(pdev);
1128 host = chip->hosts[slot];
1129 mmc = host->mmc;
1130
1131 chip->hosts[slot] = NULL;
1132
1133 mmc_remove_host(mmc);
1134
1135 sdhci_reset(host, SDHCI_RESET_ALL);
1136
1137 free_irq(host->irq, host);
1138
1139 del_timer_sync(&host->timer);
1140
1141 tasklet_kill(&host->card_tasklet);
1142 tasklet_kill(&host->finish_tasklet);
1143
1144 iounmap(host->ioaddr);
1145
1146 pci_release_region(pdev, host->bar);
1147
1148 mmc_free_host(mmc);
1149}
1150
1151static int __devinit sdhci_probe(struct pci_dev *pdev,
1152 const struct pci_device_id *ent)
1153{
1154 int ret, i;
1155 u8 slots;
1156 struct sdhci_chip *chip;
1157
1158 BUG_ON(pdev == NULL);
1159 BUG_ON(ent == NULL);
1160
1161 DBG("found at %s\n", pci_name(pdev));
1162
1163 ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
1164 if (ret)
1165 return ret;
1166
1167 slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
1168 DBG("found %d slot(s)\n", slots);
1169 if (slots == 0)
1170 return -ENODEV;
1171
1172 ret = pci_enable_device(pdev);
1173 if (ret)
1174 return ret;
1175
1176 chip = kzalloc(sizeof(struct sdhci_chip) +
1177 sizeof(struct sdhci_host*) * slots, GFP_KERNEL);
1178 if (!chip) {
1179 ret = -ENOMEM;
1180 goto err;
1181 }
1182
1183 chip->pdev = pdev;
1184
1185 chip->num_slots = slots;
1186 pci_set_drvdata(pdev, chip);
1187
1188 for (i = 0;i < slots;i++) {
1189 ret = sdhci_probe_slot(pdev, i);
1190 if (ret) {
1191 for (i--;i >= 0;i--)
1192 sdhci_remove_slot(pdev, i);
1193 goto free;
1194 }
1195 }
1196
1197 return 0;
1198
1199free:
1200 pci_set_drvdata(pdev, NULL);
1201 kfree(chip);
1202
1203err:
1204 pci_disable_device(pdev);
1205 return ret;
1206}
1207
1208static void __devexit sdhci_remove(struct pci_dev *pdev)
1209{
1210 int i;
1211 struct sdhci_chip *chip;
1212
1213 chip = pci_get_drvdata(pdev);
1214
1215 if (chip) {
1216 for (i = 0;i < chip->num_slots;i++)
1217 sdhci_remove_slot(pdev, i);
1218
1219 pci_set_drvdata(pdev, NULL);
1220
1221 kfree(chip);
1222 }
1223
1224 pci_disable_device(pdev);
1225}
1226
1227static struct pci_driver sdhci_driver = {
1228 .name = DRIVER_NAME,
1229 .id_table = pci_ids,
1230 .probe = sdhci_probe,
1231 .remove = __devexit_p(sdhci_remove),
1232 .suspend = sdhci_suspend,
1233 .resume = sdhci_resume,
1234};
1235
1236/*****************************************************************************\
1237 * *
1238 * Driver init/exit *
1239 * *
1240\*****************************************************************************/
1241
1242static int __init sdhci_drv_init(void)
1243{
1244 printk(KERN_INFO DRIVER_NAME
1245 ": Secure Digital Host Controller Interface driver, "
1246 DRIVER_VERSION "\n");
1247 printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
1248
1249 return pci_register_driver(&sdhci_driver);
1250}
1251
1252static void __exit sdhci_drv_exit(void)
1253{
1254 DBG("Exiting\n");
1255
1256 pci_unregister_driver(&sdhci_driver);
1257}
1258
1259module_init(sdhci_drv_init);
1260module_exit(sdhci_drv_exit);
1261
1262MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
1263MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver");
1264MODULE_VERSION(DRIVER_VERSION);
1265MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h
new file mode 100644
index 000000000000..3b270ef486b4
--- /dev/null
+++ b/drivers/mmc/sdhci.h
@@ -0,0 +1,185 @@
1/*
2 * linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver
3 *
4 * Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11/*
12 * PCI registers
13 */
14
15#define PCI_SLOT_INFO 0x40 /* 8 bits */
16#define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7)
17#define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07
18
19/*
20 * Controller registers
21 */
22
23#define SDHCI_DMA_ADDRESS 0x00
24
25#define SDHCI_BLOCK_SIZE 0x04
26
27#define SDHCI_BLOCK_COUNT 0x06
28
29#define SDHCI_ARGUMENT 0x08
30
31#define SDHCI_TRANSFER_MODE 0x0C
32#define SDHCI_TRNS_DMA 0x01
33#define SDHCI_TRNS_BLK_CNT_EN 0x02
34#define SDHCI_TRNS_ACMD12 0x04
35#define SDHCI_TRNS_READ 0x10
36#define SDHCI_TRNS_MULTI 0x20
37
38#define SDHCI_COMMAND 0x0E
39#define SDHCI_CMD_RESP_MASK 0x03
40#define SDHCI_CMD_CRC 0x08
41#define SDHCI_CMD_INDEX 0x10
42#define SDHCI_CMD_DATA 0x20
43
44#define SDHCI_CMD_RESP_NONE 0x00
45#define SDHCI_CMD_RESP_LONG 0x01
46#define SDHCI_CMD_RESP_SHORT 0x02
47#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
48
49#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
50
51#define SDHCI_RESPONSE 0x10
52
53#define SDHCI_BUFFER 0x20
54
55#define SDHCI_PRESENT_STATE 0x24
56#define SDHCI_CMD_INHIBIT 0x00000001
57#define SDHCI_DATA_INHIBIT 0x00000002
58#define SDHCI_DOING_WRITE 0x00000100
59#define SDHCI_DOING_READ 0x00000200
60#define SDHCI_SPACE_AVAILABLE 0x00000400
61#define SDHCI_DATA_AVAILABLE 0x00000800
62#define SDHCI_CARD_PRESENT 0x00010000
63#define SDHCI_WRITE_PROTECT 0x00080000
64
65#define SDHCI_HOST_CONTROL 0x28
66#define SDHCI_CTRL_LED 0x01
67#define SDHCI_CTRL_4BITBUS 0x02
68
69#define SDHCI_POWER_CONTROL 0x29
70
71#define SDHCI_BLOCK_GAP_CONTROL 0x2A
72
73#define SDHCI_WALK_UP_CONTROL 0x2B
74
75#define SDHCI_CLOCK_CONTROL 0x2C
76#define SDHCI_DIVIDER_SHIFT 8
77#define SDHCI_CLOCK_CARD_EN 0x0004
78#define SDHCI_CLOCK_INT_STABLE 0x0002
79#define SDHCI_CLOCK_INT_EN 0x0001
80
81#define SDHCI_TIMEOUT_CONTROL 0x2E
82
83#define SDHCI_SOFTWARE_RESET 0x2F
84#define SDHCI_RESET_ALL 0x01
85#define SDHCI_RESET_CMD 0x02
86#define SDHCI_RESET_DATA 0x04
87
88#define SDHCI_INT_STATUS 0x30
89#define SDHCI_INT_ENABLE 0x34
90#define SDHCI_SIGNAL_ENABLE 0x38
91#define SDHCI_INT_RESPONSE 0x00000001
92#define SDHCI_INT_DATA_END 0x00000002
93#define SDHCI_INT_DMA_END 0x00000008
94#define SDHCI_INT_BUF_EMPTY 0x00000010
95#define SDHCI_INT_BUF_FULL 0x00000020
96#define SDHCI_INT_CARD_INSERT 0x00000040
97#define SDHCI_INT_CARD_REMOVE 0x00000080
98#define SDHCI_INT_CARD_INT 0x00000100
99#define SDHCI_INT_TIMEOUT 0x00010000
100#define SDHCI_INT_CRC 0x00020000
101#define SDHCI_INT_END_BIT 0x00040000
102#define SDHCI_INT_INDEX 0x00080000
103#define SDHCI_INT_DATA_TIMEOUT 0x00100000
104#define SDHCI_INT_DATA_CRC 0x00200000
105#define SDHCI_INT_DATA_END_BIT 0x00400000
106#define SDHCI_INT_BUS_POWER 0x00800000
107#define SDHCI_INT_ACMD12ERR 0x01000000
108
109#define SDHCI_INT_NORMAL_MASK 0x00007FFF
110#define SDHCI_INT_ERROR_MASK 0xFFFF8000
111
112#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
113 SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
114#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
115 SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL | \
116 SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
117 SDHCI_INT_DATA_END_BIT)
118
119#define SDHCI_ACMD12_ERR 0x3C
120
121/* 3E-3F reserved */
122
123#define SDHCI_CAPABILITIES 0x40
124#define SDHCI_CAN_DO_DMA 0x00400000
125#define SDHCI_CLOCK_BASE_MASK 0x00003F00
126#define SDHCI_CLOCK_BASE_SHIFT 8
127
128/* 44-47 reserved for more caps */
129
130#define SDHCI_MAX_CURRENT 0x48
131
132/* 4C-4F reserved for more max current */
133
134/* 50-FB reserved */
135
136#define SDHCI_SLOT_INT_STATUS 0xFC
137
138#define SDHCI_HOST_VERSION 0xFE
139
140struct sdhci_chip;
141
142struct sdhci_host {
143 struct sdhci_chip *chip;
144 struct mmc_host *mmc; /* MMC structure */
145
146 spinlock_t lock; /* Mutex */
147
148 int flags; /* Host attributes */
149#define SDHCI_USE_DMA (1<<0)
150
151 unsigned int max_clk; /* Max possible freq (MHz) */
152
153 unsigned int clock; /* Current clock (MHz) */
154
155 struct mmc_request *mrq; /* Current request */
156 struct mmc_command *cmd; /* Current command */
157 struct mmc_data *data; /* Current data request */
158
159 struct scatterlist *cur_sg; /* We're working on this */
160 char *mapped_sg; /* This is where it's mapped */
161 int num_sg; /* Entries left */
162 int offset; /* Offset into current sg */
163 int remain; /* Bytes left in current */
164
165 int size; /* Remaining bytes in transfer */
166
167 char slot_descr[20]; /* Name for reservations */
168
169 int irq; /* Device IRQ */
170 int bar; /* PCI BAR index */
171 unsigned long addr; /* Bus address */
172 void __iomem * ioaddr; /* Mapped address */
173
174 struct tasklet_struct card_tasklet; /* Tasklet structures */
175 struct tasklet_struct finish_tasklet;
176
177 struct timer_list timer; /* Timer for timeouts */
178};
179
180struct sdhci_chip {
181 struct pci_dev *pdev;
182
183 int num_slots; /* Slots on controller */
184 struct sdhci_host *hosts[0]; /* Pointers to hosts */
185};