blob: 7994c0b70f1576d85ed0358ffdea69e4d07bb685 [file] [log] [blame]
Pierre Ossmand129bce2006-03-24 03:18:17 -08001/*
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
Pierre Ossmand129bce2006-03-24 03:18:17 -080011#include <linux/delay.h>
12#include <linux/highmem.h>
13#include <linux/pci.h>
14#include <linux/dma-mapping.h>
15
16#include <linux/mmc/host.h>
17#include <linux/mmc/protocol.h>
18
19#include <asm/scatterlist.h>
20
21#include "sdhci.h"
22
23#define DRIVER_NAME "sdhci"
Pierre Ossman2c5f3942006-06-30 02:22:32 -070024#define DRIVER_VERSION "0.12"
Pierre Ossmand129bce2006-03-24 03:18:17 -080025
26#define BUGMAIL "<sdhci-devel@list.drzeus.cx>"
27
Pierre Ossmand129bce2006-03-24 03:18:17 -080028#define DBG(f, x...) \
Russell Kingc6563172006-03-29 09:30:20 +010029 pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
Pierre Ossmand129bce2006-03-24 03:18:17 -080030
Pierre Ossman67435272006-06-30 02:22:31 -070031static unsigned int debug_nodma = 0;
32static unsigned int debug_forcedma = 0;
Pierre Ossmandf673b22006-06-30 02:22:31 -070033static unsigned int debug_quirks = 0;
Pierre Ossman67435272006-06-30 02:22:31 -070034
Pierre Ossman645289d2006-06-30 02:22:33 -070035#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0)
36
Pierre Ossmand129bce2006-03-24 03:18:17 -080037static const struct pci_device_id pci_ids[] __devinitdata = {
Pierre Ossman645289d2006-06-30 02:22:33 -070038 {
39 .vendor = PCI_VENDOR_ID_RICOH,
40 .device = PCI_DEVICE_ID_RICOH_R5C822,
41 .subvendor = PCI_VENDOR_ID_IBM,
42 .subdevice = PCI_ANY_ID,
43 .driver_data = SDHCI_QUIRK_CLOCK_BEFORE_RESET,
44 },
45
46 { /* Generic SD host controller */
47 PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
48 },
49
Pierre Ossmand129bce2006-03-24 03:18:17 -080050 { /* end: all zeroes */ },
51};
52
53MODULE_DEVICE_TABLE(pci, pci_ids);
54
55static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
56static void sdhci_finish_data(struct sdhci_host *);
57
58static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
59static void sdhci_finish_command(struct sdhci_host *);
60
61static void sdhci_dumpregs(struct sdhci_host *host)
62{
63 printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
64
65 printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n",
66 readl(host->ioaddr + SDHCI_DMA_ADDRESS),
67 readw(host->ioaddr + SDHCI_HOST_VERSION));
68 printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n",
69 readw(host->ioaddr + SDHCI_BLOCK_SIZE),
70 readw(host->ioaddr + SDHCI_BLOCK_COUNT));
71 printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
72 readl(host->ioaddr + SDHCI_ARGUMENT),
73 readw(host->ioaddr + SDHCI_TRANSFER_MODE));
74 printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n",
75 readl(host->ioaddr + SDHCI_PRESENT_STATE),
76 readb(host->ioaddr + SDHCI_HOST_CONTROL));
77 printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n",
78 readb(host->ioaddr + SDHCI_POWER_CONTROL),
79 readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL));
80 printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n",
81 readb(host->ioaddr + SDHCI_WALK_UP_CONTROL),
82 readw(host->ioaddr + SDHCI_CLOCK_CONTROL));
83 printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n",
84 readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL),
85 readl(host->ioaddr + SDHCI_INT_STATUS));
86 printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
87 readl(host->ioaddr + SDHCI_INT_ENABLE),
88 readl(host->ioaddr + SDHCI_SIGNAL_ENABLE));
89 printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
90 readw(host->ioaddr + SDHCI_ACMD12_ERR),
91 readw(host->ioaddr + SDHCI_SLOT_INT_STATUS));
92 printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n",
93 readl(host->ioaddr + SDHCI_CAPABILITIES),
94 readl(host->ioaddr + SDHCI_MAX_CURRENT));
95
96 printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
97}
98
99/*****************************************************************************\
100 * *
101 * Low level functions *
102 * *
103\*****************************************************************************/
104
105static void sdhci_reset(struct sdhci_host *host, u8 mask)
106{
Pierre Ossmane16514d2006-06-30 02:22:24 -0700107 unsigned long timeout;
108
Pierre Ossmand129bce2006-03-24 03:18:17 -0800109 writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET);
110
Pierre Ossmane16514d2006-06-30 02:22:24 -0700111 if (mask & SDHCI_RESET_ALL)
Pierre Ossmand129bce2006-03-24 03:18:17 -0800112 host->clock = 0;
113
Pierre Ossmane16514d2006-06-30 02:22:24 -0700114 /* Wait max 100 ms */
115 timeout = 100;
116
117 /* hw clears the bit when it's done */
118 while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) {
119 if (timeout == 0) {
120 printk(KERN_ERR "%s: Reset 0x%x never completed. "
121 "Please report this to " BUGMAIL ".\n",
122 mmc_hostname(host->mmc), (int)mask);
123 sdhci_dumpregs(host);
124 return;
125 }
126 timeout--;
127 mdelay(1);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800128 }
129}
130
131static void sdhci_init(struct sdhci_host *host)
132{
133 u32 intmask;
134
135 sdhci_reset(host, SDHCI_RESET_ALL);
136
Pierre Ossman3192a282006-06-30 02:22:26 -0700137 intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
138 SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
139 SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
140 SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT |
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100141 SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
Pierre Ossman3192a282006-06-30 02:22:26 -0700142 SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800143
144 writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
145 writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800146}
147
148static void sdhci_activate_led(struct sdhci_host *host)
149{
150 u8 ctrl;
151
152 ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
153 ctrl |= SDHCI_CTRL_LED;
154 writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
155}
156
157static void sdhci_deactivate_led(struct sdhci_host *host)
158{
159 u8 ctrl;
160
161 ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
162 ctrl &= ~SDHCI_CTRL_LED;
163 writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
164}
165
166/*****************************************************************************\
167 * *
168 * Core functions *
169 * *
170\*****************************************************************************/
171
172static inline char* sdhci_kmap_sg(struct sdhci_host* host)
173{
174 host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ);
175 return host->mapped_sg + host->cur_sg->offset;
176}
177
178static inline void sdhci_kunmap_sg(struct sdhci_host* host)
179{
180 kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
181}
182
183static inline int sdhci_next_sg(struct sdhci_host* host)
184{
185 /*
186 * Skip to next SG entry.
187 */
188 host->cur_sg++;
189 host->num_sg--;
190
191 /*
192 * Any entries left?
193 */
194 if (host->num_sg > 0) {
195 host->offset = 0;
196 host->remain = host->cur_sg->length;
197 }
198
199 return host->num_sg;
200}
201
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100202static void sdhci_read_block_pio(struct sdhci_host *host)
Pierre Ossmand129bce2006-03-24 03:18:17 -0800203{
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100204 int blksize, chunk_remain;
205 u32 data;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800206 char *buffer;
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100207 int size;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800208
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100209 DBG("PIO reading\n");
Pierre Ossmand129bce2006-03-24 03:18:17 -0800210
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100211 blksize = host->data->blksz;
212 chunk_remain = 0;
213 data = 0;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800214
215 buffer = sdhci_kmap_sg(host) + host->offset;
216
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100217 while (blksize) {
218 if (chunk_remain == 0) {
219 data = readl(host->ioaddr + SDHCI_BUFFER);
220 chunk_remain = min(blksize, 4);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800221 }
222
Pierre Ossmand129bce2006-03-24 03:18:17 -0800223 size = min(host->size, host->remain);
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100224 size = min(size, chunk_remain);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800225
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100226 chunk_remain -= size;
227 blksize -= size;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800228 host->offset += size;
229 host->remain -= size;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800230 host->size -= size;
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100231 while (size) {
232 *buffer = data & 0xFF;
233 buffer++;
234 data >>= 8;
235 size--;
236 }
Pierre Ossmand129bce2006-03-24 03:18:17 -0800237
238 if (host->remain == 0) {
239 sdhci_kunmap_sg(host);
240 if (sdhci_next_sg(host) == 0) {
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100241 BUG_ON(blksize != 0);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800242 return;
243 }
244 buffer = sdhci_kmap_sg(host);
245 }
246 }
247
248 sdhci_kunmap_sg(host);
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100249}
Pierre Ossmand129bce2006-03-24 03:18:17 -0800250
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100251static void sdhci_write_block_pio(struct sdhci_host *host)
252{
253 int blksize, chunk_remain;
254 u32 data;
255 char *buffer;
256 int bytes, size;
257
258 DBG("PIO writing\n");
259
260 blksize = host->data->blksz;
261 chunk_remain = 4;
262 data = 0;
263
264 bytes = 0;
265 buffer = sdhci_kmap_sg(host) + host->offset;
266
267 while (blksize) {
268 size = min(host->size, host->remain);
269 size = min(size, chunk_remain);
270
271 chunk_remain -= size;
272 blksize -= size;
273 host->offset += size;
274 host->remain -= size;
275 host->size -= size;
276 while (size) {
277 data >>= 8;
278 data |= (u32)*buffer << 24;
279 buffer++;
280 size--;
281 }
282
283 if (chunk_remain == 0) {
284 writel(data, host->ioaddr + SDHCI_BUFFER);
285 chunk_remain = min(blksize, 4);
286 }
287
288 if (host->remain == 0) {
289 sdhci_kunmap_sg(host);
290 if (sdhci_next_sg(host) == 0) {
291 BUG_ON(blksize != 0);
292 return;
293 }
294 buffer = sdhci_kmap_sg(host);
295 }
296 }
297
298 sdhci_kunmap_sg(host);
299}
300
301static void sdhci_transfer_pio(struct sdhci_host *host)
302{
303 u32 mask;
304
305 BUG_ON(!host->data);
306
307 if (host->size == 0)
308 return;
309
310 if (host->data->flags & MMC_DATA_READ)
311 mask = SDHCI_DATA_AVAILABLE;
312 else
313 mask = SDHCI_SPACE_AVAILABLE;
314
315 while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
316 if (host->data->flags & MMC_DATA_READ)
317 sdhci_read_block_pio(host);
318 else
319 sdhci_write_block_pio(host);
320
321 if (host->size == 0)
322 break;
323
324 BUG_ON(host->num_sg == 0);
325 }
326
327 DBG("PIO transfer complete.\n");
Pierre Ossmand129bce2006-03-24 03:18:17 -0800328}
329
330static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
331{
Pierre Ossman1c8cde92006-06-30 02:22:25 -0700332 u8 count;
333 unsigned target_timeout, current_timeout;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800334
335 WARN_ON(host->data);
336
Pierre Ossmanc7fa9962006-06-30 02:22:25 -0700337 if (data == NULL)
Pierre Ossmand129bce2006-03-24 03:18:17 -0800338 return;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800339
340 DBG("blksz %04x blks %04x flags %08x\n",
Russell Kinga3fd4a12006-06-04 17:51:15 +0100341 data->blksz, data->blocks, data->flags);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800342 DBG("tsac %d ms nsac %d clk\n",
343 data->timeout_ns / 1000000, data->timeout_clks);
344
Pierre Ossmanbab76962006-07-02 16:51:35 +0100345 /* Sanity checks */
346 BUG_ON(data->blksz * data->blocks > 524288);
Pierre Ossman1d676e02006-07-02 16:52:10 +0100347 BUG_ON(data->blksz > host->max_block);
348 BUG_ON(data->blocks > 65535);
Pierre Ossmanbab76962006-07-02 16:51:35 +0100349
Pierre Ossman1c8cde92006-06-30 02:22:25 -0700350 /* timeout in us */
351 target_timeout = data->timeout_ns / 1000 +
352 data->timeout_clks / host->clock;
353
354 /*
355 * Figure out needed cycles.
356 * We do this in steps in order to fit inside a 32 bit int.
357 * The first step is the minimum timeout, which will have a
358 * minimum resolution of 6 bits:
359 * (1) 2^13*1000 > 2^22,
360 * (2) host->timeout_clk < 2^16
361 * =>
362 * (1) / (2) > 2^6
363 */
364 count = 0;
365 current_timeout = (1 << 13) * 1000 / host->timeout_clk;
366 while (current_timeout < target_timeout) {
367 count++;
368 current_timeout <<= 1;
369 if (count >= 0xF)
370 break;
371 }
372
373 if (count >= 0xF) {
374 printk(KERN_WARNING "%s: Too large timeout requested!\n",
375 mmc_hostname(host->mmc));
376 count = 0xE;
377 }
378
379 writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
380
Pierre Ossmand129bce2006-03-24 03:18:17 -0800381 if (host->flags & SDHCI_USE_DMA) {
382 int count;
383
384 count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len,
385 (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
386 BUG_ON(count != 1);
387
388 writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS);
389 } else {
Russell Kinga3fd4a12006-06-04 17:51:15 +0100390 host->size = data->blksz * data->blocks;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800391
392 host->cur_sg = data->sg;
393 host->num_sg = data->sg_len;
394
395 host->offset = 0;
396 host->remain = host->cur_sg->length;
397 }
Pierre Ossmanc7fa9962006-06-30 02:22:25 -0700398
Pierre Ossmanbab76962006-07-02 16:51:35 +0100399 /* We do not handle DMA boundaries, so set it to max (512 KiB) */
400 writew(SDHCI_MAKE_BLKSZ(7, data->blksz),
401 host->ioaddr + SDHCI_BLOCK_SIZE);
Pierre Ossmanc7fa9962006-06-30 02:22:25 -0700402 writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT);
403}
404
405static void sdhci_set_transfer_mode(struct sdhci_host *host,
406 struct mmc_data *data)
407{
408 u16 mode;
409
410 WARN_ON(host->data);
411
412 if (data == NULL)
413 return;
414
415 mode = SDHCI_TRNS_BLK_CNT_EN;
416 if (data->blocks > 1)
417 mode |= SDHCI_TRNS_MULTI;
418 if (data->flags & MMC_DATA_READ)
419 mode |= SDHCI_TRNS_READ;
420 if (host->flags & SDHCI_USE_DMA)
421 mode |= SDHCI_TRNS_DMA;
422
423 writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800424}
425
426static void sdhci_finish_data(struct sdhci_host *host)
427{
428 struct mmc_data *data;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800429 u16 blocks;
430
431 BUG_ON(!host->data);
432
433 data = host->data;
434 host->data = NULL;
435
436 if (host->flags & SDHCI_USE_DMA) {
437 pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len,
438 (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800439 }
440
441 /*
442 * Controller doesn't count down when in single block mode.
443 */
444 if ((data->blocks == 1) && (data->error == MMC_ERR_NONE))
445 blocks = 0;
446 else
447 blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT);
Russell Kinga3fd4a12006-06-04 17:51:15 +0100448 data->bytes_xfered = data->blksz * (data->blocks - blocks);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800449
450 if ((data->error == MMC_ERR_NONE) && blocks) {
451 printk(KERN_ERR "%s: Controller signalled completion even "
452 "though there were blocks left. Please report this "
453 "to " BUGMAIL ".\n", mmc_hostname(host->mmc));
454 data->error = MMC_ERR_FAILED;
455 }
456
457 if (host->size != 0) {
458 printk(KERN_ERR "%s: %d bytes were left untransferred. "
459 "Please report this to " BUGMAIL ".\n",
460 mmc_hostname(host->mmc), host->size);
461 data->error = MMC_ERR_FAILED;
462 }
463
464 DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
465
466 if (data->stop) {
467 /*
468 * The controller needs a reset of internal state machines
469 * upon error conditions.
470 */
471 if (data->error != MMC_ERR_NONE) {
472 sdhci_reset(host, SDHCI_RESET_CMD);
473 sdhci_reset(host, SDHCI_RESET_DATA);
474 }
475
476 sdhci_send_command(host, data->stop);
477 } else
478 tasklet_schedule(&host->finish_tasklet);
479}
480
481static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
482{
483 int flags;
Pierre Ossmanfd2208d2006-06-30 02:22:28 -0700484 u32 mask;
Pierre Ossman7cb2c762006-06-30 02:22:23 -0700485 unsigned long timeout;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800486
487 WARN_ON(host->cmd);
488
489 DBG("Sending cmd (%x)\n", cmd->opcode);
490
491 /* Wait max 10 ms */
Pierre Ossman7cb2c762006-06-30 02:22:23 -0700492 timeout = 10;
Pierre Ossmanfd2208d2006-06-30 02:22:28 -0700493
494 mask = SDHCI_CMD_INHIBIT;
495 if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
496 mask |= SDHCI_DATA_INHIBIT;
497
498 /* We shouldn't wait for data inihibit for stop commands, even
499 though they might use busy signaling */
500 if (host->mrq->data && (cmd == host->mrq->data->stop))
501 mask &= ~SDHCI_DATA_INHIBIT;
502
503 while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
Pierre Ossman7cb2c762006-06-30 02:22:23 -0700504 if (timeout == 0) {
Pierre Ossmand129bce2006-03-24 03:18:17 -0800505 printk(KERN_ERR "%s: Controller never released "
Pierre Ossmanfd2208d2006-06-30 02:22:28 -0700506 "inhibit bit(s). Please report this to "
Pierre Ossmand129bce2006-03-24 03:18:17 -0800507 BUGMAIL ".\n", mmc_hostname(host->mmc));
508 sdhci_dumpregs(host);
509 cmd->error = MMC_ERR_FAILED;
510 tasklet_schedule(&host->finish_tasklet);
511 return;
512 }
Pierre Ossman7cb2c762006-06-30 02:22:23 -0700513 timeout--;
514 mdelay(1);
515 }
Pierre Ossmand129bce2006-03-24 03:18:17 -0800516
517 mod_timer(&host->timer, jiffies + 10 * HZ);
518
519 host->cmd = cmd;
520
521 sdhci_prepare_data(host, cmd->data);
522
523 writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT);
524
Pierre Ossmanc7fa9962006-06-30 02:22:25 -0700525 sdhci_set_transfer_mode(host, cmd->data);
526
Pierre Ossmand129bce2006-03-24 03:18:17 -0800527 if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
528 printk(KERN_ERR "%s: Unsupported response type! "
529 "Please report this to " BUGMAIL ".\n",
530 mmc_hostname(host->mmc));
531 cmd->error = MMC_ERR_INVALID;
532 tasklet_schedule(&host->finish_tasklet);
533 return;
534 }
535
536 if (!(cmd->flags & MMC_RSP_PRESENT))
537 flags = SDHCI_CMD_RESP_NONE;
538 else if (cmd->flags & MMC_RSP_136)
539 flags = SDHCI_CMD_RESP_LONG;
540 else if (cmd->flags & MMC_RSP_BUSY)
541 flags = SDHCI_CMD_RESP_SHORT_BUSY;
542 else
543 flags = SDHCI_CMD_RESP_SHORT;
544
545 if (cmd->flags & MMC_RSP_CRC)
546 flags |= SDHCI_CMD_CRC;
547 if (cmd->flags & MMC_RSP_OPCODE)
548 flags |= SDHCI_CMD_INDEX;
549 if (cmd->data)
550 flags |= SDHCI_CMD_DATA;
551
552 writel(SDHCI_MAKE_CMD(cmd->opcode, flags),
553 host->ioaddr + SDHCI_COMMAND);
554}
555
556static void sdhci_finish_command(struct sdhci_host *host)
557{
558 int i;
559
560 BUG_ON(host->cmd == NULL);
561
562 if (host->cmd->flags & MMC_RSP_PRESENT) {
563 if (host->cmd->flags & MMC_RSP_136) {
564 /* CRC is stripped so we need to do some shifting. */
565 for (i = 0;i < 4;i++) {
566 host->cmd->resp[i] = readl(host->ioaddr +
567 SDHCI_RESPONSE + (3-i)*4) << 8;
568 if (i != 3)
569 host->cmd->resp[i] |=
570 readb(host->ioaddr +
571 SDHCI_RESPONSE + (3-i)*4-1);
572 }
573 } else {
574 host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE);
575 }
576 }
577
578 host->cmd->error = MMC_ERR_NONE;
579
580 DBG("Ending cmd (%x)\n", host->cmd->opcode);
581
Pierre Ossman3192a282006-06-30 02:22:26 -0700582 if (host->cmd->data)
Pierre Ossmand129bce2006-03-24 03:18:17 -0800583 host->data = host->cmd->data;
Pierre Ossman3192a282006-06-30 02:22:26 -0700584 else
Pierre Ossmand129bce2006-03-24 03:18:17 -0800585 tasklet_schedule(&host->finish_tasklet);
586
587 host->cmd = NULL;
588}
589
590static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
591{
592 int div;
593 u16 clk;
Pierre Ossman7cb2c762006-06-30 02:22:23 -0700594 unsigned long timeout;
Pierre Ossmand129bce2006-03-24 03:18:17 -0800595
596 if (clock == host->clock)
597 return;
598
599 writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
600
601 if (clock == 0)
602 goto out;
603
604 for (div = 1;div < 256;div *= 2) {
605 if ((host->max_clk / div) <= clock)
606 break;
607 }
608 div >>= 1;
609
610 clk = div << SDHCI_DIVIDER_SHIFT;
611 clk |= SDHCI_CLOCK_INT_EN;
612 writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
613
614 /* Wait max 10 ms */
Pierre Ossman7cb2c762006-06-30 02:22:23 -0700615 timeout = 10;
616 while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL))
617 & SDHCI_CLOCK_INT_STABLE)) {
618 if (timeout == 0) {
Pierre Ossmand129bce2006-03-24 03:18:17 -0800619 printk(KERN_ERR "%s: Internal clock never stabilised. "
620 "Please report this to " BUGMAIL ".\n",
621 mmc_hostname(host->mmc));
622 sdhci_dumpregs(host);
623 return;
624 }
Pierre Ossman7cb2c762006-06-30 02:22:23 -0700625 timeout--;
626 mdelay(1);
627 }
Pierre Ossmand129bce2006-03-24 03:18:17 -0800628
629 clk |= SDHCI_CLOCK_CARD_EN;
630 writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
631
632out:
633 host->clock = clock;
634}
635
Pierre Ossman146ad662006-06-30 02:22:23 -0700636static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
637{
638 u8 pwr;
639
640 if (host->power == power)
641 return;
642
643 writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
644
645 if (power == (unsigned short)-1)
646 goto out;
647
648 pwr = SDHCI_POWER_ON;
649
650 switch (power) {
651 case MMC_VDD_170:
652 case MMC_VDD_180:
653 case MMC_VDD_190:
654 pwr |= SDHCI_POWER_180;
655 break;
656 case MMC_VDD_290:
657 case MMC_VDD_300:
658 case MMC_VDD_310:
659 pwr |= SDHCI_POWER_300;
660 break;
661 case MMC_VDD_320:
662 case MMC_VDD_330:
663 case MMC_VDD_340:
664 pwr |= SDHCI_POWER_330;
665 break;
666 default:
667 BUG();
668 }
669
670 writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
671
672out:
673 host->power = power;
674}
675
Pierre Ossmand129bce2006-03-24 03:18:17 -0800676/*****************************************************************************\
677 * *
678 * MMC callbacks *
679 * *
680\*****************************************************************************/
681
682static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
683{
684 struct sdhci_host *host;
685 unsigned long flags;
686
687 host = mmc_priv(mmc);
688
689 spin_lock_irqsave(&host->lock, flags);
690
691 WARN_ON(host->mrq != NULL);
692
693 sdhci_activate_led(host);
694
695 host->mrq = mrq;
696
697 if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
698 host->mrq->cmd->error = MMC_ERR_TIMEOUT;
699 tasklet_schedule(&host->finish_tasklet);
700 } else
701 sdhci_send_command(host, mrq->cmd);
702
703 spin_unlock_irqrestore(&host->lock, flags);
704}
705
706static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
707{
708 struct sdhci_host *host;
709 unsigned long flags;
710 u8 ctrl;
711
712 host = mmc_priv(mmc);
713
714 spin_lock_irqsave(&host->lock, flags);
715
Pierre Ossmand129bce2006-03-24 03:18:17 -0800716 /*
717 * Reset the chip on each power off.
718 * Should clear out any weird states.
719 */
720 if (ios->power_mode == MMC_POWER_OFF) {
721 writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800722 sdhci_init(host);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800723 }
724
725 sdhci_set_clock(host, ios->clock);
726
727 if (ios->power_mode == MMC_POWER_OFF)
Pierre Ossman146ad662006-06-30 02:22:23 -0700728 sdhci_set_power(host, -1);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800729 else
Pierre Ossman146ad662006-06-30 02:22:23 -0700730 sdhci_set_power(host, ios->vdd);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800731
732 ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
733 if (ios->bus_width == MMC_BUS_WIDTH_4)
734 ctrl |= SDHCI_CTRL_4BITBUS;
735 else
736 ctrl &= ~SDHCI_CTRL_4BITBUS;
737 writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
738
739 spin_unlock_irqrestore(&host->lock, flags);
740}
741
742static int sdhci_get_ro(struct mmc_host *mmc)
743{
744 struct sdhci_host *host;
745 unsigned long flags;
746 int present;
747
748 host = mmc_priv(mmc);
749
750 spin_lock_irqsave(&host->lock, flags);
751
752 present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
753
754 spin_unlock_irqrestore(&host->lock, flags);
755
756 return !(present & SDHCI_WRITE_PROTECT);
757}
758
759static struct mmc_host_ops sdhci_ops = {
760 .request = sdhci_request,
761 .set_ios = sdhci_set_ios,
762 .get_ro = sdhci_get_ro,
763};
764
765/*****************************************************************************\
766 * *
767 * Tasklets *
768 * *
769\*****************************************************************************/
770
771static void sdhci_tasklet_card(unsigned long param)
772{
773 struct sdhci_host *host;
774 unsigned long flags;
775
776 host = (struct sdhci_host*)param;
777
778 spin_lock_irqsave(&host->lock, flags);
779
780 if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
781 if (host->mrq) {
782 printk(KERN_ERR "%s: Card removed during transfer!\n",
783 mmc_hostname(host->mmc));
784 printk(KERN_ERR "%s: Resetting controller.\n",
785 mmc_hostname(host->mmc));
786
787 sdhci_reset(host, SDHCI_RESET_CMD);
788 sdhci_reset(host, SDHCI_RESET_DATA);
789
790 host->mrq->cmd->error = MMC_ERR_FAILED;
791 tasklet_schedule(&host->finish_tasklet);
792 }
793 }
794
795 spin_unlock_irqrestore(&host->lock, flags);
796
797 mmc_detect_change(host->mmc, msecs_to_jiffies(500));
798}
799
800static void sdhci_tasklet_finish(unsigned long param)
801{
802 struct sdhci_host *host;
803 unsigned long flags;
804 struct mmc_request *mrq;
805
806 host = (struct sdhci_host*)param;
807
808 spin_lock_irqsave(&host->lock, flags);
809
810 del_timer(&host->timer);
811
812 mrq = host->mrq;
813
814 DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode);
815
816 /*
817 * The controller needs a reset of internal state machines
818 * upon error conditions.
819 */
820 if ((mrq->cmd->error != MMC_ERR_NONE) ||
821 (mrq->data && ((mrq->data->error != MMC_ERR_NONE) ||
822 (mrq->data->stop && (mrq->data->stop->error != MMC_ERR_NONE))))) {
Pierre Ossman645289d2006-06-30 02:22:33 -0700823
824 /* Some controllers need this kick or reset won't work here */
825 if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
826 unsigned int clock;
827
828 /* This is to force an update */
829 clock = host->clock;
830 host->clock = 0;
831 sdhci_set_clock(host, clock);
832 }
833
834 /* Spec says we should do both at the same time, but Ricoh
835 controllers do not like that. */
Pierre Ossmand129bce2006-03-24 03:18:17 -0800836 sdhci_reset(host, SDHCI_RESET_CMD);
837 sdhci_reset(host, SDHCI_RESET_DATA);
838 }
839
840 host->mrq = NULL;
841 host->cmd = NULL;
842 host->data = NULL;
843
844 sdhci_deactivate_led(host);
845
846 spin_unlock_irqrestore(&host->lock, flags);
847
848 mmc_request_done(host->mmc, mrq);
849}
850
851static void sdhci_timeout_timer(unsigned long data)
852{
853 struct sdhci_host *host;
854 unsigned long flags;
855
856 host = (struct sdhci_host*)data;
857
858 spin_lock_irqsave(&host->lock, flags);
859
860 if (host->mrq) {
861 printk(KERN_ERR "%s: Timeout waiting for hardware interrupt. "
862 "Please report this to " BUGMAIL ".\n",
863 mmc_hostname(host->mmc));
864 sdhci_dumpregs(host);
865
866 if (host->data) {
867 host->data->error = MMC_ERR_TIMEOUT;
868 sdhci_finish_data(host);
869 } else {
870 if (host->cmd)
871 host->cmd->error = MMC_ERR_TIMEOUT;
872 else
873 host->mrq->cmd->error = MMC_ERR_TIMEOUT;
874
875 tasklet_schedule(&host->finish_tasklet);
876 }
877 }
878
879 spin_unlock_irqrestore(&host->lock, flags);
880}
881
882/*****************************************************************************\
883 * *
884 * Interrupt handling *
885 * *
886\*****************************************************************************/
887
888static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
889{
890 BUG_ON(intmask == 0);
891
892 if (!host->cmd) {
893 printk(KERN_ERR "%s: Got command interrupt even though no "
894 "command operation was in progress.\n",
895 mmc_hostname(host->mmc));
896 printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n",
897 mmc_hostname(host->mmc));
898 sdhci_dumpregs(host);
899 return;
900 }
901
902 if (intmask & SDHCI_INT_RESPONSE)
903 sdhci_finish_command(host);
904 else {
905 if (intmask & SDHCI_INT_TIMEOUT)
906 host->cmd->error = MMC_ERR_TIMEOUT;
907 else if (intmask & SDHCI_INT_CRC)
908 host->cmd->error = MMC_ERR_BADCRC;
909 else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
910 host->cmd->error = MMC_ERR_FAILED;
911 else
912 host->cmd->error = MMC_ERR_INVALID;
913
914 tasklet_schedule(&host->finish_tasklet);
915 }
916}
917
918static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
919{
920 BUG_ON(intmask == 0);
921
922 if (!host->data) {
923 /*
924 * A data end interrupt is sent together with the response
925 * for the stop command.
926 */
927 if (intmask & SDHCI_INT_DATA_END)
928 return;
929
930 printk(KERN_ERR "%s: Got data interrupt even though no "
931 "data operation was in progress.\n",
932 mmc_hostname(host->mmc));
933 printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n",
934 mmc_hostname(host->mmc));
935 sdhci_dumpregs(host);
936
937 return;
938 }
939
940 if (intmask & SDHCI_INT_DATA_TIMEOUT)
941 host->data->error = MMC_ERR_TIMEOUT;
942 else if (intmask & SDHCI_INT_DATA_CRC)
943 host->data->error = MMC_ERR_BADCRC;
944 else if (intmask & SDHCI_INT_DATA_END_BIT)
945 host->data->error = MMC_ERR_FAILED;
946
947 if (host->data->error != MMC_ERR_NONE)
948 sdhci_finish_data(host);
949 else {
Pierre Ossmana406f5a2006-07-02 16:50:59 +0100950 if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
Pierre Ossmand129bce2006-03-24 03:18:17 -0800951 sdhci_transfer_pio(host);
952
953 if (intmask & SDHCI_INT_DATA_END)
954 sdhci_finish_data(host);
955 }
956}
957
958static irqreturn_t sdhci_irq(int irq, void *dev_id, struct pt_regs *regs)
959{
960 irqreturn_t result;
961 struct sdhci_host* host = dev_id;
962 u32 intmask;
963
964 spin_lock(&host->lock);
965
966 intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
967
968 if (!intmask) {
969 result = IRQ_NONE;
970 goto out;
971 }
972
973 DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask);
974
Pierre Ossman3192a282006-06-30 02:22:26 -0700975 if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
976 writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
977 host->ioaddr + SDHCI_INT_STATUS);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800978 tasklet_schedule(&host->card_tasklet);
Pierre Ossman3192a282006-06-30 02:22:26 -0700979 }
980
981 intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800982
983 if (intmask & SDHCI_INT_CMD_MASK) {
Pierre Ossmand129bce2006-03-24 03:18:17 -0800984 writel(intmask & SDHCI_INT_CMD_MASK,
985 host->ioaddr + SDHCI_INT_STATUS);
Pierre Ossman3192a282006-06-30 02:22:26 -0700986 sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800987 }
988
989 if (intmask & SDHCI_INT_DATA_MASK) {
Pierre Ossmand129bce2006-03-24 03:18:17 -0800990 writel(intmask & SDHCI_INT_DATA_MASK,
991 host->ioaddr + SDHCI_INT_STATUS);
Pierre Ossman3192a282006-06-30 02:22:26 -0700992 sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
Pierre Ossmand129bce2006-03-24 03:18:17 -0800993 }
994
995 intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
996
Pierre Ossmand129bce2006-03-24 03:18:17 -0800997 if (intmask & SDHCI_INT_BUS_POWER) {
Pierre Ossman3192a282006-06-30 02:22:26 -0700998 printk(KERN_ERR "%s: Card is consuming too much power!\n",
Pierre Ossmand129bce2006-03-24 03:18:17 -0800999 mmc_hostname(host->mmc));
Pierre Ossman3192a282006-06-30 02:22:26 -07001000 writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
Pierre Ossmand129bce2006-03-24 03:18:17 -08001001 }
1002
Pierre Ossman3192a282006-06-30 02:22:26 -07001003 intmask &= SDHCI_INT_BUS_POWER;
1004
1005 if (intmask) {
1006 printk(KERN_ERR "%s: Unexpected interrupt 0x%08x. Please "
Pierre Ossmand129bce2006-03-24 03:18:17 -08001007 "report this to " BUGMAIL ".\n",
Pierre Ossman3192a282006-06-30 02:22:26 -07001008 mmc_hostname(host->mmc), intmask);
Pierre Ossmand129bce2006-03-24 03:18:17 -08001009 sdhci_dumpregs(host);
1010
Pierre Ossmand129bce2006-03-24 03:18:17 -08001011 writel(intmask, host->ioaddr + SDHCI_INT_STATUS);
Pierre Ossman3192a282006-06-30 02:22:26 -07001012 }
Pierre Ossmand129bce2006-03-24 03:18:17 -08001013
1014 result = IRQ_HANDLED;
1015
1016out:
1017 spin_unlock(&host->lock);
1018
1019 return result;
1020}
1021
1022/*****************************************************************************\
1023 * *
1024 * Suspend/resume *
1025 * *
1026\*****************************************************************************/
1027
1028#ifdef CONFIG_PM
1029
1030static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state)
1031{
1032 struct sdhci_chip *chip;
1033 int i, ret;
1034
1035 chip = pci_get_drvdata(pdev);
1036 if (!chip)
1037 return 0;
1038
1039 DBG("Suspending...\n");
1040
1041 for (i = 0;i < chip->num_slots;i++) {
1042 if (!chip->hosts[i])
1043 continue;
1044 ret = mmc_suspend_host(chip->hosts[i]->mmc, state);
1045 if (ret) {
1046 for (i--;i >= 0;i--)
1047 mmc_resume_host(chip->hosts[i]->mmc);
1048 return ret;
1049 }
1050 }
1051
1052 pci_save_state(pdev);
1053 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
1054 pci_disable_device(pdev);
1055 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1056
1057 return 0;
1058}
1059
1060static int sdhci_resume (struct pci_dev *pdev)
1061{
1062 struct sdhci_chip *chip;
1063 int i, ret;
1064
1065 chip = pci_get_drvdata(pdev);
1066 if (!chip)
1067 return 0;
1068
1069 DBG("Resuming...\n");
1070
1071 pci_set_power_state(pdev, PCI_D0);
1072 pci_restore_state(pdev);
1073 pci_enable_device(pdev);
1074
1075 for (i = 0;i < chip->num_slots;i++) {
1076 if (!chip->hosts[i])
1077 continue;
1078 if (chip->hosts[i]->flags & SDHCI_USE_DMA)
1079 pci_set_master(pdev);
1080 sdhci_init(chip->hosts[i]);
1081 ret = mmc_resume_host(chip->hosts[i]->mmc);
1082 if (ret)
1083 return ret;
1084 }
1085
1086 return 0;
1087}
1088
1089#else /* CONFIG_PM */
1090
1091#define sdhci_suspend NULL
1092#define sdhci_resume NULL
1093
1094#endif /* CONFIG_PM */
1095
1096/*****************************************************************************\
1097 * *
1098 * Device probing/removal *
1099 * *
1100\*****************************************************************************/
1101
1102static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
1103{
1104 int ret;
Pierre Ossman4a965502006-06-30 02:22:29 -07001105 unsigned int version;
Pierre Ossmand129bce2006-03-24 03:18:17 -08001106 struct sdhci_chip *chip;
1107 struct mmc_host *mmc;
1108 struct sdhci_host *host;
1109
1110 u8 first_bar;
1111 unsigned int caps;
1112
1113 chip = pci_get_drvdata(pdev);
1114 BUG_ON(!chip);
1115
1116 ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
1117 if (ret)
1118 return ret;
1119
1120 first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
1121
1122 if (first_bar > 5) {
1123 printk(KERN_ERR DRIVER_NAME ": Invalid first BAR. Aborting.\n");
1124 return -ENODEV;
1125 }
1126
1127 if (!(pci_resource_flags(pdev, first_bar + slot) & IORESOURCE_MEM)) {
1128 printk(KERN_ERR DRIVER_NAME ": BAR is not iomem. Aborting.\n");
1129 return -ENODEV;
1130 }
1131
1132 if (pci_resource_len(pdev, first_bar + slot) != 0x100) {
1133 printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n");
1134 return -ENODEV;
1135 }
1136
Pierre Ossman67435272006-06-30 02:22:31 -07001137 if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
1138 printk(KERN_ERR DRIVER_NAME ": Vendor specific interface. Aborting.\n");
1139 return -ENODEV;
1140 }
1141
1142 if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) {
1143 printk(KERN_ERR DRIVER_NAME ": Unknown interface. Aborting.\n");
1144 return -ENODEV;
1145 }
1146
Pierre Ossmand129bce2006-03-24 03:18:17 -08001147 mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev);
1148 if (!mmc)
1149 return -ENOMEM;
1150
1151 host = mmc_priv(mmc);
1152 host->mmc = mmc;
1153
1154 host->bar = first_bar + slot;
1155
1156 host->addr = pci_resource_start(pdev, host->bar);
1157 host->irq = pdev->irq;
1158
1159 DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
1160
1161 snprintf(host->slot_descr, 20, "sdhci:slot%d", slot);
1162
1163 ret = pci_request_region(pdev, host->bar, host->slot_descr);
1164 if (ret)
1165 goto free;
1166
1167 host->ioaddr = ioremap_nocache(host->addr,
1168 pci_resource_len(pdev, host->bar));
1169 if (!host->ioaddr) {
1170 ret = -ENOMEM;
1171 goto release;
1172 }
1173
Pierre Ossmand96649e2006-06-30 02:22:30 -07001174 sdhci_reset(host, SDHCI_RESET_ALL);
1175
Pierre Ossman4a965502006-06-30 02:22:29 -07001176 version = readw(host->ioaddr + SDHCI_HOST_VERSION);
1177 version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
1178 if (version != 0) {
1179 printk(KERN_ERR "%s: Unknown controller version (%d). "
1180 "Cowardly refusing to continue.\n", host->slot_descr,
1181 version);
1182 ret = -ENODEV;
1183 goto unmap;
1184 }
1185
Pierre Ossmand129bce2006-03-24 03:18:17 -08001186 caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
1187
Pierre Ossman67435272006-06-30 02:22:31 -07001188 if (debug_nodma)
1189 DBG("DMA forced off\n");
1190 else if (debug_forcedma) {
1191 DBG("DMA forced on\n");
1192 host->flags |= SDHCI_USE_DMA;
1193 } else if ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA)
1194 DBG("Controller doesn't have DMA interface\n");
1195 else if (!(caps & SDHCI_CAN_DO_DMA))
1196 DBG("Controller doesn't have DMA capability\n");
1197 else
Pierre Ossmand129bce2006-03-24 03:18:17 -08001198 host->flags |= SDHCI_USE_DMA;
1199
1200 if (host->flags & SDHCI_USE_DMA) {
1201 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1202 printk(KERN_WARNING "%s: No suitable DMA available. "
1203 "Falling back to PIO.\n", host->slot_descr);
1204 host->flags &= ~SDHCI_USE_DMA;
1205 }
1206 }
1207
1208 if (host->flags & SDHCI_USE_DMA)
1209 pci_set_master(pdev);
1210 else /* XXX: Hack to get MMC layer to avoid highmem */
1211 pdev->dma_mask = 0;
1212
Pierre Ossman8ef1a142006-06-30 02:22:21 -07001213 host->max_clk =
1214 (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
1215 if (host->max_clk == 0) {
1216 printk(KERN_ERR "%s: Hardware doesn't specify base clock "
1217 "frequency.\n", host->slot_descr);
1218 ret = -ENODEV;
1219 goto unmap;
1220 }
Pierre Ossmand129bce2006-03-24 03:18:17 -08001221 host->max_clk *= 1000000;
1222
Pierre Ossman1c8cde92006-06-30 02:22:25 -07001223 host->timeout_clk =
1224 (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
1225 if (host->timeout_clk == 0) {
1226 printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
1227 "frequency.\n", host->slot_descr);
1228 ret = -ENODEV;
1229 goto unmap;
1230 }
1231 if (caps & SDHCI_TIMEOUT_CLK_UNIT)
1232 host->timeout_clk *= 1000;
1233
Pierre Ossman1d676e02006-07-02 16:52:10 +01001234 host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
1235 if (host->max_block >= 3) {
1236 printk(KERN_ERR "%s: Invalid maximum block size.\n",
1237 host->slot_descr);
1238 ret = -ENODEV;
1239 goto unmap;
1240 }
1241 host->max_block = 512 << host->max_block;
1242
Pierre Ossmand129bce2006-03-24 03:18:17 -08001243 /*
1244 * Set host parameters.
1245 */
1246 mmc->ops = &sdhci_ops;
1247 mmc->f_min = host->max_clk / 256;
1248 mmc->f_max = host->max_clk;
Pierre Ossmand129bce2006-03-24 03:18:17 -08001249 mmc->caps = MMC_CAP_4_BIT_DATA;
1250
Pierre Ossman146ad662006-06-30 02:22:23 -07001251 mmc->ocr_avail = 0;
1252 if (caps & SDHCI_CAN_VDD_330)
1253 mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
1254 else if (caps & SDHCI_CAN_VDD_300)
1255 mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
1256 else if (caps & SDHCI_CAN_VDD_180)
1257 mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
1258
1259 if (mmc->ocr_avail == 0) {
1260 printk(KERN_ERR "%s: Hardware doesn't report any "
1261 "support voltages.\n", host->slot_descr);
1262 ret = -ENODEV;
1263 goto unmap;
1264 }
1265
Pierre Ossmand129bce2006-03-24 03:18:17 -08001266 spin_lock_init(&host->lock);
1267
1268 /*
1269 * Maximum number of segments. Hardware cannot do scatter lists.
1270 */
1271 if (host->flags & SDHCI_USE_DMA)
1272 mmc->max_hw_segs = 1;
1273 else
1274 mmc->max_hw_segs = 16;
1275 mmc->max_phys_segs = 16;
1276
1277 /*
Pierre Ossmanbab76962006-07-02 16:51:35 +01001278 * Maximum number of sectors in one transfer. Limited by DMA boundary
1279 * size (512KiB), which means (512 KiB/512=) 1024 entries.
Pierre Ossmand129bce2006-03-24 03:18:17 -08001280 */
Pierre Ossmanbab76962006-07-02 16:51:35 +01001281 mmc->max_sectors = 1024;
Pierre Ossmand129bce2006-03-24 03:18:17 -08001282
1283 /*
1284 * Maximum segment size. Could be one segment with the maximum number
1285 * of sectors.
1286 */
1287 mmc->max_seg_size = mmc->max_sectors * 512;
1288
1289 /*
1290 * Init tasklets.
1291 */
1292 tasklet_init(&host->card_tasklet,
1293 sdhci_tasklet_card, (unsigned long)host);
1294 tasklet_init(&host->finish_tasklet,
1295 sdhci_tasklet_finish, (unsigned long)host);
1296
Andrew Mortone474c662006-06-12 22:10:22 +01001297 setup_timer(&host->timer, sdhci_timeout_timer, (long)host);
Pierre Ossmand129bce2006-03-24 03:18:17 -08001298
1299 ret = request_irq(host->irq, sdhci_irq, SA_SHIRQ,
1300 host->slot_descr, host);
1301 if (ret)
Pierre Ossman8ef1a142006-06-30 02:22:21 -07001302 goto untasklet;
Pierre Ossmand129bce2006-03-24 03:18:17 -08001303
1304 sdhci_init(host);
1305
1306#ifdef CONFIG_MMC_DEBUG
1307 sdhci_dumpregs(host);
1308#endif
1309
1310 host->chip = chip;
1311 chip->hosts[slot] = host;
1312
1313 mmc_add_host(mmc);
1314
1315 printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc),
1316 host->addr, host->irq,
1317 (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
1318
1319 return 0;
1320
Pierre Ossman8ef1a142006-06-30 02:22:21 -07001321untasklet:
Pierre Ossmand129bce2006-03-24 03:18:17 -08001322 tasklet_kill(&host->card_tasklet);
1323 tasklet_kill(&host->finish_tasklet);
Pierre Ossman8ef1a142006-06-30 02:22:21 -07001324unmap:
Pierre Ossmand129bce2006-03-24 03:18:17 -08001325 iounmap(host->ioaddr);
1326release:
1327 pci_release_region(pdev, host->bar);
1328free:
1329 mmc_free_host(mmc);
1330
1331 return ret;
1332}
1333
1334static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
1335{
1336 struct sdhci_chip *chip;
1337 struct mmc_host *mmc;
1338 struct sdhci_host *host;
1339
1340 chip = pci_get_drvdata(pdev);
1341 host = chip->hosts[slot];
1342 mmc = host->mmc;
1343
1344 chip->hosts[slot] = NULL;
1345
1346 mmc_remove_host(mmc);
1347
1348 sdhci_reset(host, SDHCI_RESET_ALL);
1349
1350 free_irq(host->irq, host);
1351
1352 del_timer_sync(&host->timer);
1353
1354 tasklet_kill(&host->card_tasklet);
1355 tasklet_kill(&host->finish_tasklet);
1356
1357 iounmap(host->ioaddr);
1358
1359 pci_release_region(pdev, host->bar);
1360
1361 mmc_free_host(mmc);
1362}
1363
1364static int __devinit sdhci_probe(struct pci_dev *pdev,
1365 const struct pci_device_id *ent)
1366{
1367 int ret, i;
Pierre Ossman51f82bc2006-06-30 02:22:22 -07001368 u8 slots, rev;
Pierre Ossmand129bce2006-03-24 03:18:17 -08001369 struct sdhci_chip *chip;
1370
1371 BUG_ON(pdev == NULL);
1372 BUG_ON(ent == NULL);
1373
Pierre Ossman51f82bc2006-06-30 02:22:22 -07001374 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
1375
1376 printk(KERN_INFO DRIVER_NAME
1377 ": SDHCI controller found at %s [%04x:%04x] (rev %x)\n",
1378 pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
1379 (int)rev);
Pierre Ossmand129bce2006-03-24 03:18:17 -08001380
1381 ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
1382 if (ret)
1383 return ret;
1384
1385 slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
1386 DBG("found %d slot(s)\n", slots);
1387 if (slots == 0)
1388 return -ENODEV;
1389
1390 ret = pci_enable_device(pdev);
1391 if (ret)
1392 return ret;
1393
1394 chip = kzalloc(sizeof(struct sdhci_chip) +
1395 sizeof(struct sdhci_host*) * slots, GFP_KERNEL);
1396 if (!chip) {
1397 ret = -ENOMEM;
1398 goto err;
1399 }
1400
1401 chip->pdev = pdev;
Pierre Ossmandf673b22006-06-30 02:22:31 -07001402 chip->quirks = ent->driver_data;
1403
1404 if (debug_quirks)
1405 chip->quirks = debug_quirks;
Pierre Ossmand129bce2006-03-24 03:18:17 -08001406
1407 chip->num_slots = slots;
1408 pci_set_drvdata(pdev, chip);
1409
1410 for (i = 0;i < slots;i++) {
1411 ret = sdhci_probe_slot(pdev, i);
1412 if (ret) {
1413 for (i--;i >= 0;i--)
1414 sdhci_remove_slot(pdev, i);
1415 goto free;
1416 }
1417 }
1418
1419 return 0;
1420
1421free:
1422 pci_set_drvdata(pdev, NULL);
1423 kfree(chip);
1424
1425err:
1426 pci_disable_device(pdev);
1427 return ret;
1428}
1429
1430static void __devexit sdhci_remove(struct pci_dev *pdev)
1431{
1432 int i;
1433 struct sdhci_chip *chip;
1434
1435 chip = pci_get_drvdata(pdev);
1436
1437 if (chip) {
1438 for (i = 0;i < chip->num_slots;i++)
1439 sdhci_remove_slot(pdev, i);
1440
1441 pci_set_drvdata(pdev, NULL);
1442
1443 kfree(chip);
1444 }
1445
1446 pci_disable_device(pdev);
1447}
1448
1449static struct pci_driver sdhci_driver = {
1450 .name = DRIVER_NAME,
1451 .id_table = pci_ids,
1452 .probe = sdhci_probe,
1453 .remove = __devexit_p(sdhci_remove),
1454 .suspend = sdhci_suspend,
1455 .resume = sdhci_resume,
1456};
1457
1458/*****************************************************************************\
1459 * *
1460 * Driver init/exit *
1461 * *
1462\*****************************************************************************/
1463
1464static int __init sdhci_drv_init(void)
1465{
1466 printk(KERN_INFO DRIVER_NAME
1467 ": Secure Digital Host Controller Interface driver, "
1468 DRIVER_VERSION "\n");
1469 printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
1470
1471 return pci_register_driver(&sdhci_driver);
1472}
1473
1474static void __exit sdhci_drv_exit(void)
1475{
1476 DBG("Exiting\n");
1477
1478 pci_unregister_driver(&sdhci_driver);
1479}
1480
1481module_init(sdhci_drv_init);
1482module_exit(sdhci_drv_exit);
1483
Pierre Ossman67435272006-06-30 02:22:31 -07001484module_param(debug_nodma, uint, 0444);
1485module_param(debug_forcedma, uint, 0444);
Pierre Ossmandf673b22006-06-30 02:22:31 -07001486module_param(debug_quirks, uint, 0444);
Pierre Ossman67435272006-06-30 02:22:31 -07001487
Pierre Ossmand129bce2006-03-24 03:18:17 -08001488MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
1489MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver");
1490MODULE_VERSION(DRIVER_VERSION);
1491MODULE_LICENSE("GPL");
Pierre Ossman67435272006-06-30 02:22:31 -07001492
1493MODULE_PARM_DESC(debug_nodma, "Forcefully disable DMA transfers. (default 0)");
1494MODULE_PARM_DESC(debug_forcedma, "Forcefully enable DMA transfers. (default 0)");
Pierre Ossmandf673b22006-06-30 02:22:31 -07001495MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");