diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-02 17:58:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-02 17:58:03 -0400 |
commit | 168d04b3b4de7723eb73b3cffc9cb75224e0f393 (patch) | |
tree | 55fda7a4784902100da9c716109d44bded281e80 /drivers/mmc | |
parent | 6ce6c7faf2d0fede5e1530b0f731a90f138fd69e (diff) | |
parent | 2c5f394025df6e54a9c09afda03855f3877b9afa (diff) |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-mmc
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-mmc:
[MMC] sdhci: version bump sdhci
[MMC] sdhci: support controller specific quirks
[MMC] sdhci: more DMA capabilities tests
[MMC] sdhci: reset sdhci controller early
[MMC] sdhci: check controller version
[MMC] sdhci: check only relevant inhibit bits
[MMC] sdhci: Test for invalid block size
[MMC] sdhci: Avoid sdhci DMA boundaries
[MMC] Fix sdhci PIO routines
[MMC] sdhci: fix interrupt handling
[MMC] sdhci: correct register order
[MMC] sdhci: proper timeout handling
[MMC] sdhci: fix sdhci reset timeout
[MMC] sdhci: fix timeout loops in sdhci
[MMC] sdhci: support for multiple voltages
[MMC] sdhci: print device id
[MMC] sdhci: check SDHCI base clock
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/sdhci.c | 541 | ||||
-rw-r--r-- | drivers/mmc/sdhci.h | 34 |
2 files changed, 407 insertions, 168 deletions
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index a871c09a6e11..74134699ccee 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c | |||
@@ -8,12 +8,6 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 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> | 11 | #include <linux/delay.h> |
18 | #include <linux/highmem.h> | 12 | #include <linux/highmem.h> |
19 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
@@ -27,13 +21,17 @@ | |||
27 | #include "sdhci.h" | 21 | #include "sdhci.h" |
28 | 22 | ||
29 | #define DRIVER_NAME "sdhci" | 23 | #define DRIVER_NAME "sdhci" |
30 | #define DRIVER_VERSION "0.11" | 24 | #define DRIVER_VERSION "0.12" |
31 | 25 | ||
32 | #define BUGMAIL "<sdhci-devel@list.drzeus.cx>" | 26 | #define BUGMAIL "<sdhci-devel@list.drzeus.cx>" |
33 | 27 | ||
34 | #define DBG(f, x...) \ | 28 | #define DBG(f, x...) \ |
35 | pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) | 29 | pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) |
36 | 30 | ||
31 | static unsigned int debug_nodma = 0; | ||
32 | static unsigned int debug_forcedma = 0; | ||
33 | static unsigned int debug_quirks = 0; | ||
34 | |||
37 | static const struct pci_device_id pci_ids[] __devinitdata = { | 35 | static const struct pci_device_id pci_ids[] __devinitdata = { |
38 | /* handle any SD host controller */ | 36 | /* handle any SD host controller */ |
39 | {PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)}, | 37 | {PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)}, |
@@ -94,12 +92,27 @@ static void sdhci_dumpregs(struct sdhci_host *host) | |||
94 | 92 | ||
95 | static void sdhci_reset(struct sdhci_host *host, u8 mask) | 93 | static void sdhci_reset(struct sdhci_host *host, u8 mask) |
96 | { | 94 | { |
95 | unsigned long timeout; | ||
96 | |||
97 | writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET); | 97 | writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET); |
98 | 98 | ||
99 | if (mask & SDHCI_RESET_ALL) { | 99 | if (mask & SDHCI_RESET_ALL) |
100 | host->clock = 0; | 100 | host->clock = 0; |
101 | 101 | ||
102 | mdelay(50); | 102 | /* Wait max 100 ms */ |
103 | timeout = 100; | ||
104 | |||
105 | /* hw clears the bit when it's done */ | ||
106 | while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) { | ||
107 | if (timeout == 0) { | ||
108 | printk(KERN_ERR "%s: Reset 0x%x never completed. " | ||
109 | "Please report this to " BUGMAIL ".\n", | ||
110 | mmc_hostname(host->mmc), (int)mask); | ||
111 | sdhci_dumpregs(host); | ||
112 | return; | ||
113 | } | ||
114 | timeout--; | ||
115 | mdelay(1); | ||
103 | } | 116 | } |
104 | } | 117 | } |
105 | 118 | ||
@@ -109,13 +122,15 @@ static void sdhci_init(struct sdhci_host *host) | |||
109 | 122 | ||
110 | sdhci_reset(host, SDHCI_RESET_ALL); | 123 | sdhci_reset(host, SDHCI_RESET_ALL); |
111 | 124 | ||
112 | intmask = ~(SDHCI_INT_CARD_INT | SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL); | 125 | intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | |
126 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | | ||
127 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | | ||
128 | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT | | ||
129 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | | ||
130 | SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE; | ||
113 | 131 | ||
114 | writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); | 132 | writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); |
115 | writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); | 133 | writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); |
116 | |||
117 | /* This is unknown magic. */ | ||
118 | writeb(0xE, host->ioaddr + SDHCI_TIMEOUT_CONTROL); | ||
119 | } | 134 | } |
120 | 135 | ||
121 | static void sdhci_activate_led(struct sdhci_host *host) | 136 | static void sdhci_activate_led(struct sdhci_host *host) |
@@ -172,79 +187,96 @@ static inline int sdhci_next_sg(struct sdhci_host* host) | |||
172 | return host->num_sg; | 187 | return host->num_sg; |
173 | } | 188 | } |
174 | 189 | ||
175 | static void sdhci_transfer_pio(struct sdhci_host *host) | 190 | static void sdhci_read_block_pio(struct sdhci_host *host) |
176 | { | 191 | { |
192 | int blksize, chunk_remain; | ||
193 | u32 data; | ||
177 | char *buffer; | 194 | char *buffer; |
178 | u32 mask; | 195 | int size; |
179 | int bytes, size; | ||
180 | unsigned long max_jiffies; | ||
181 | |||
182 | BUG_ON(!host->data); | ||
183 | 196 | ||
184 | if (host->num_sg == 0) | 197 | DBG("PIO reading\n"); |
185 | return; | ||
186 | 198 | ||
187 | bytes = 0; | 199 | blksize = host->data->blksz; |
188 | if (host->data->flags & MMC_DATA_READ) | 200 | chunk_remain = 0; |
189 | mask = SDHCI_DATA_AVAILABLE; | 201 | data = 0; |
190 | else | ||
191 | mask = SDHCI_SPACE_AVAILABLE; | ||
192 | 202 | ||
193 | buffer = sdhci_kmap_sg(host) + host->offset; | 203 | buffer = sdhci_kmap_sg(host) + host->offset; |
194 | 204 | ||
195 | /* Transfer shouldn't take more than 5 s */ | 205 | while (blksize) { |
196 | max_jiffies = jiffies + HZ * 5; | 206 | if (chunk_remain == 0) { |
207 | data = readl(host->ioaddr + SDHCI_BUFFER); | ||
208 | chunk_remain = min(blksize, 4); | ||
209 | } | ||
197 | 210 | ||
198 | while (host->size > 0) { | 211 | size = min(host->size, host->remain); |
199 | if (time_after(jiffies, max_jiffies)) { | 212 | size = min(size, chunk_remain); |
200 | printk(KERN_ERR "%s: PIO transfer stalled. " | ||
201 | "Please report this to " | ||
202 | BUGMAIL ".\n", mmc_hostname(host->mmc)); | ||
203 | sdhci_dumpregs(host); | ||
204 | 213 | ||
205 | sdhci_kunmap_sg(host); | 214 | chunk_remain -= size; |
215 | blksize -= size; | ||
216 | host->offset += size; | ||
217 | host->remain -= size; | ||
218 | host->size -= size; | ||
219 | while (size) { | ||
220 | *buffer = data & 0xFF; | ||
221 | buffer++; | ||
222 | data >>= 8; | ||
223 | size--; | ||
224 | } | ||
206 | 225 | ||
207 | host->data->error = MMC_ERR_FAILED; | 226 | if (host->remain == 0) { |
208 | sdhci_finish_data(host); | 227 | sdhci_kunmap_sg(host); |
209 | return; | 228 | if (sdhci_next_sg(host) == 0) { |
229 | BUG_ON(blksize != 0); | ||
230 | return; | ||
231 | } | ||
232 | buffer = sdhci_kmap_sg(host); | ||
210 | } | 233 | } |
234 | } | ||
211 | 235 | ||
212 | if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask)) | 236 | sdhci_kunmap_sg(host); |
213 | continue; | 237 | } |
214 | 238 | ||
215 | size = min(host->size, host->remain); | 239 | static void sdhci_write_block_pio(struct sdhci_host *host) |
240 | { | ||
241 | int blksize, chunk_remain; | ||
242 | u32 data; | ||
243 | char *buffer; | ||
244 | int bytes, size; | ||
216 | 245 | ||
217 | if (size >= 4) { | 246 | DBG("PIO writing\n"); |
218 | if (host->data->flags & MMC_DATA_READ) | 247 | |
219 | *(u32*)buffer = readl(host->ioaddr + SDHCI_BUFFER); | 248 | blksize = host->data->blksz; |
220 | else | 249 | chunk_remain = 4; |
221 | writel(*(u32*)buffer, host->ioaddr + SDHCI_BUFFER); | 250 | data = 0; |
222 | size = 4; | ||
223 | } else if (size >= 2) { | ||
224 | if (host->data->flags & MMC_DATA_READ) | ||
225 | *(u16*)buffer = readw(host->ioaddr + SDHCI_BUFFER); | ||
226 | else | ||
227 | writew(*(u16*)buffer, host->ioaddr + SDHCI_BUFFER); | ||
228 | size = 2; | ||
229 | } else { | ||
230 | if (host->data->flags & MMC_DATA_READ) | ||
231 | *(u8*)buffer = readb(host->ioaddr + SDHCI_BUFFER); | ||
232 | else | ||
233 | writeb(*(u8*)buffer, host->ioaddr + SDHCI_BUFFER); | ||
234 | size = 1; | ||
235 | } | ||
236 | 251 | ||
237 | buffer += size; | 252 | bytes = 0; |
253 | buffer = sdhci_kmap_sg(host) + host->offset; | ||
254 | |||
255 | while (blksize) { | ||
256 | size = min(host->size, host->remain); | ||
257 | size = min(size, chunk_remain); | ||
258 | |||
259 | chunk_remain -= size; | ||
260 | blksize -= size; | ||
238 | host->offset += size; | 261 | host->offset += size; |
239 | host->remain -= size; | 262 | host->remain -= size; |
240 | |||
241 | bytes += size; | ||
242 | host->size -= size; | 263 | host->size -= size; |
264 | while (size) { | ||
265 | data >>= 8; | ||
266 | data |= (u32)*buffer << 24; | ||
267 | buffer++; | ||
268 | size--; | ||
269 | } | ||
270 | |||
271 | if (chunk_remain == 0) { | ||
272 | writel(data, host->ioaddr + SDHCI_BUFFER); | ||
273 | chunk_remain = min(blksize, 4); | ||
274 | } | ||
243 | 275 | ||
244 | if (host->remain == 0) { | 276 | if (host->remain == 0) { |
245 | sdhci_kunmap_sg(host); | 277 | sdhci_kunmap_sg(host); |
246 | if (sdhci_next_sg(host) == 0) { | 278 | if (sdhci_next_sg(host) == 0) { |
247 | DBG("PIO transfer: %d bytes\n", bytes); | 279 | BUG_ON(blksize != 0); |
248 | return; | 280 | return; |
249 | } | 281 | } |
250 | buffer = sdhci_kmap_sg(host); | 282 | buffer = sdhci_kmap_sg(host); |
@@ -252,38 +284,87 @@ static void sdhci_transfer_pio(struct sdhci_host *host) | |||
252 | } | 284 | } |
253 | 285 | ||
254 | sdhci_kunmap_sg(host); | 286 | sdhci_kunmap_sg(host); |
287 | } | ||
288 | |||
289 | static void sdhci_transfer_pio(struct sdhci_host *host) | ||
290 | { | ||
291 | u32 mask; | ||
292 | |||
293 | BUG_ON(!host->data); | ||
294 | |||
295 | if (host->size == 0) | ||
296 | return; | ||
297 | |||
298 | if (host->data->flags & MMC_DATA_READ) | ||
299 | mask = SDHCI_DATA_AVAILABLE; | ||
300 | else | ||
301 | mask = SDHCI_SPACE_AVAILABLE; | ||
302 | |||
303 | while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { | ||
304 | if (host->data->flags & MMC_DATA_READ) | ||
305 | sdhci_read_block_pio(host); | ||
306 | else | ||
307 | sdhci_write_block_pio(host); | ||
255 | 308 | ||
256 | DBG("PIO transfer: %d bytes\n", bytes); | 309 | if (host->size == 0) |
310 | break; | ||
311 | |||
312 | BUG_ON(host->num_sg == 0); | ||
313 | } | ||
314 | |||
315 | DBG("PIO transfer complete.\n"); | ||
257 | } | 316 | } |
258 | 317 | ||
259 | static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | 318 | static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) |
260 | { | 319 | { |
261 | u16 mode; | 320 | u8 count; |
321 | unsigned target_timeout, current_timeout; | ||
262 | 322 | ||
263 | WARN_ON(host->data); | 323 | WARN_ON(host->data); |
264 | 324 | ||
265 | if (data == NULL) { | 325 | if (data == NULL) |
266 | writew(0, host->ioaddr + SDHCI_TRANSFER_MODE); | ||
267 | return; | 326 | return; |
268 | } | ||
269 | 327 | ||
270 | DBG("blksz %04x blks %04x flags %08x\n", | 328 | DBG("blksz %04x blks %04x flags %08x\n", |
271 | data->blksz, data->blocks, data->flags); | 329 | data->blksz, data->blocks, data->flags); |
272 | DBG("tsac %d ms nsac %d clk\n", | 330 | DBG("tsac %d ms nsac %d clk\n", |
273 | data->timeout_ns / 1000000, data->timeout_clks); | 331 | data->timeout_ns / 1000000, data->timeout_clks); |
274 | 332 | ||
275 | mode = SDHCI_TRNS_BLK_CNT_EN; | 333 | /* Sanity checks */ |
276 | if (data->blocks > 1) | 334 | BUG_ON(data->blksz * data->blocks > 524288); |
277 | mode |= SDHCI_TRNS_MULTI; | 335 | BUG_ON(data->blksz > host->max_block); |
278 | if (data->flags & MMC_DATA_READ) | 336 | BUG_ON(data->blocks > 65535); |
279 | mode |= SDHCI_TRNS_READ; | ||
280 | if (host->flags & SDHCI_USE_DMA) | ||
281 | mode |= SDHCI_TRNS_DMA; | ||
282 | 337 | ||
283 | writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE); | 338 | /* timeout in us */ |
339 | target_timeout = data->timeout_ns / 1000 + | ||
340 | data->timeout_clks / host->clock; | ||
284 | 341 | ||
285 | writew(data->blksz, host->ioaddr + SDHCI_BLOCK_SIZE); | 342 | /* |
286 | writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT); | 343 | * Figure out needed cycles. |
344 | * We do this in steps in order to fit inside a 32 bit int. | ||
345 | * The first step is the minimum timeout, which will have a | ||
346 | * minimum resolution of 6 bits: | ||
347 | * (1) 2^13*1000 > 2^22, | ||
348 | * (2) host->timeout_clk < 2^16 | ||
349 | * => | ||
350 | * (1) / (2) > 2^6 | ||
351 | */ | ||
352 | count = 0; | ||
353 | current_timeout = (1 << 13) * 1000 / host->timeout_clk; | ||
354 | while (current_timeout < target_timeout) { | ||
355 | count++; | ||
356 | current_timeout <<= 1; | ||
357 | if (count >= 0xF) | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | if (count >= 0xF) { | ||
362 | printk(KERN_WARNING "%s: Too large timeout requested!\n", | ||
363 | mmc_hostname(host->mmc)); | ||
364 | count = 0xE; | ||
365 | } | ||
366 | |||
367 | writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL); | ||
287 | 368 | ||
288 | if (host->flags & SDHCI_USE_DMA) { | 369 | if (host->flags & SDHCI_USE_DMA) { |
289 | int count; | 370 | int count; |
@@ -302,12 +383,37 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
302 | host->offset = 0; | 383 | host->offset = 0; |
303 | host->remain = host->cur_sg->length; | 384 | host->remain = host->cur_sg->length; |
304 | } | 385 | } |
386 | |||
387 | /* We do not handle DMA boundaries, so set it to max (512 KiB) */ | ||
388 | writew(SDHCI_MAKE_BLKSZ(7, data->blksz), | ||
389 | host->ioaddr + SDHCI_BLOCK_SIZE); | ||
390 | writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT); | ||
391 | } | ||
392 | |||
393 | static void sdhci_set_transfer_mode(struct sdhci_host *host, | ||
394 | struct mmc_data *data) | ||
395 | { | ||
396 | u16 mode; | ||
397 | |||
398 | WARN_ON(host->data); | ||
399 | |||
400 | if (data == NULL) | ||
401 | return; | ||
402 | |||
403 | mode = SDHCI_TRNS_BLK_CNT_EN; | ||
404 | if (data->blocks > 1) | ||
405 | mode |= SDHCI_TRNS_MULTI; | ||
406 | if (data->flags & MMC_DATA_READ) | ||
407 | mode |= SDHCI_TRNS_READ; | ||
408 | if (host->flags & SDHCI_USE_DMA) | ||
409 | mode |= SDHCI_TRNS_DMA; | ||
410 | |||
411 | writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE); | ||
305 | } | 412 | } |
306 | 413 | ||
307 | static void sdhci_finish_data(struct sdhci_host *host) | 414 | static void sdhci_finish_data(struct sdhci_host *host) |
308 | { | 415 | { |
309 | struct mmc_data *data; | 416 | struct mmc_data *data; |
310 | u32 intmask; | ||
311 | u16 blocks; | 417 | u16 blocks; |
312 | 418 | ||
313 | BUG_ON(!host->data); | 419 | BUG_ON(!host->data); |
@@ -318,14 +424,6 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
318 | if (host->flags & SDHCI_USE_DMA) { | 424 | if (host->flags & SDHCI_USE_DMA) { |
319 | pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len, | 425 | pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len, |
320 | (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE); | 426 | (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE); |
321 | } else { | ||
322 | intmask = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); | ||
323 | intmask &= ~(SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL); | ||
324 | writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); | ||
325 | |||
326 | intmask = readl(host->ioaddr + SDHCI_INT_ENABLE); | ||
327 | intmask &= ~(SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL); | ||
328 | writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); | ||
329 | } | 427 | } |
330 | 428 | ||
331 | /* | 429 | /* |
@@ -371,27 +469,38 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
371 | static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | 469 | static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) |
372 | { | 470 | { |
373 | int flags; | 471 | int flags; |
374 | u32 present; | 472 | u32 mask; |
375 | unsigned long max_jiffies; | 473 | unsigned long timeout; |
376 | 474 | ||
377 | WARN_ON(host->cmd); | 475 | WARN_ON(host->cmd); |
378 | 476 | ||
379 | DBG("Sending cmd (%x)\n", cmd->opcode); | 477 | DBG("Sending cmd (%x)\n", cmd->opcode); |
380 | 478 | ||
381 | /* Wait max 10 ms */ | 479 | /* Wait max 10 ms */ |
382 | max_jiffies = jiffies + (HZ + 99)/100; | 480 | timeout = 10; |
383 | do { | 481 | |
384 | if (time_after(jiffies, max_jiffies)) { | 482 | mask = SDHCI_CMD_INHIBIT; |
483 | if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) | ||
484 | mask |= SDHCI_DATA_INHIBIT; | ||
485 | |||
486 | /* We shouldn't wait for data inihibit for stop commands, even | ||
487 | though they might use busy signaling */ | ||
488 | if (host->mrq->data && (cmd == host->mrq->data->stop)) | ||
489 | mask &= ~SDHCI_DATA_INHIBIT; | ||
490 | |||
491 | while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { | ||
492 | if (timeout == 0) { | ||
385 | printk(KERN_ERR "%s: Controller never released " | 493 | printk(KERN_ERR "%s: Controller never released " |
386 | "inhibit bits. Please report this to " | 494 | "inhibit bit(s). Please report this to " |
387 | BUGMAIL ".\n", mmc_hostname(host->mmc)); | 495 | BUGMAIL ".\n", mmc_hostname(host->mmc)); |
388 | sdhci_dumpregs(host); | 496 | sdhci_dumpregs(host); |
389 | cmd->error = MMC_ERR_FAILED; | 497 | cmd->error = MMC_ERR_FAILED; |
390 | tasklet_schedule(&host->finish_tasklet); | 498 | tasklet_schedule(&host->finish_tasklet); |
391 | return; | 499 | return; |
392 | } | 500 | } |
393 | present = readl(host->ioaddr + SDHCI_PRESENT_STATE); | 501 | timeout--; |
394 | } while (present & (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)); | 502 | mdelay(1); |
503 | } | ||
395 | 504 | ||
396 | mod_timer(&host->timer, jiffies + 10 * HZ); | 505 | mod_timer(&host->timer, jiffies + 10 * HZ); |
397 | 506 | ||
@@ -401,6 +510,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
401 | 510 | ||
402 | writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT); | 511 | writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT); |
403 | 512 | ||
513 | sdhci_set_transfer_mode(host, cmd->data); | ||
514 | |||
404 | if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { | 515 | if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { |
405 | printk(KERN_ERR "%s: Unsupported response type! " | 516 | printk(KERN_ERR "%s: Unsupported response type! " |
406 | "Please report this to " BUGMAIL ".\n", | 517 | "Please report this to " BUGMAIL ".\n", |
@@ -456,31 +567,9 @@ static void sdhci_finish_command(struct sdhci_host *host) | |||
456 | 567 | ||
457 | DBG("Ending cmd (%x)\n", host->cmd->opcode); | 568 | DBG("Ending cmd (%x)\n", host->cmd->opcode); |
458 | 569 | ||
459 | if (host->cmd->data) { | 570 | if (host->cmd->data) |
460 | u32 intmask; | ||
461 | |||
462 | host->data = host->cmd->data; | 571 | host->data = host->cmd->data; |
463 | 572 | else | |
464 | if (!(host->flags & SDHCI_USE_DMA)) { | ||
465 | /* | ||
466 | * Don't enable the interrupts until now to make sure we | ||
467 | * get stable handling of the FIFO. | ||
468 | */ | ||
469 | intmask = readl(host->ioaddr + SDHCI_INT_ENABLE); | ||
470 | intmask |= SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL; | ||
471 | writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); | ||
472 | |||
473 | intmask = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); | ||
474 | intmask |= SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL; | ||
475 | writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); | ||
476 | |||
477 | /* | ||
478 | * The buffer interrupts are to unreliable so we | ||
479 | * start the transfer immediatly. | ||
480 | */ | ||
481 | sdhci_transfer_pio(host); | ||
482 | } | ||
483 | } else | ||
484 | tasklet_schedule(&host->finish_tasklet); | 573 | tasklet_schedule(&host->finish_tasklet); |
485 | 574 | ||
486 | host->cmd = NULL; | 575 | host->cmd = NULL; |
@@ -490,7 +579,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
490 | { | 579 | { |
491 | int div; | 580 | int div; |
492 | u16 clk; | 581 | u16 clk; |
493 | unsigned long max_jiffies; | 582 | unsigned long timeout; |
494 | 583 | ||
495 | if (clock == host->clock) | 584 | if (clock == host->clock) |
496 | return; | 585 | return; |
@@ -511,17 +600,19 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
511 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); | 600 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); |
512 | 601 | ||
513 | /* Wait max 10 ms */ | 602 | /* Wait max 10 ms */ |
514 | max_jiffies = jiffies + (HZ + 99)/100; | 603 | timeout = 10; |
515 | do { | 604 | while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL)) |
516 | if (time_after(jiffies, max_jiffies)) { | 605 | & SDHCI_CLOCK_INT_STABLE)) { |
606 | if (timeout == 0) { | ||
517 | printk(KERN_ERR "%s: Internal clock never stabilised. " | 607 | printk(KERN_ERR "%s: Internal clock never stabilised. " |
518 | "Please report this to " BUGMAIL ".\n", | 608 | "Please report this to " BUGMAIL ".\n", |
519 | mmc_hostname(host->mmc)); | 609 | mmc_hostname(host->mmc)); |
520 | sdhci_dumpregs(host); | 610 | sdhci_dumpregs(host); |
521 | return; | 611 | return; |
522 | } | 612 | } |
523 | clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL); | 613 | timeout--; |
524 | } while (!(clk & SDHCI_CLOCK_INT_STABLE)); | 614 | mdelay(1); |
615 | } | ||
525 | 616 | ||
526 | clk |= SDHCI_CLOCK_CARD_EN; | 617 | clk |= SDHCI_CLOCK_CARD_EN; |
527 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); | 618 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); |
@@ -530,6 +621,46 @@ out: | |||
530 | host->clock = clock; | 621 | host->clock = clock; |
531 | } | 622 | } |
532 | 623 | ||
624 | static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | ||
625 | { | ||
626 | u8 pwr; | ||
627 | |||
628 | if (host->power == power) | ||
629 | return; | ||
630 | |||
631 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); | ||
632 | |||
633 | if (power == (unsigned short)-1) | ||
634 | goto out; | ||
635 | |||
636 | pwr = SDHCI_POWER_ON; | ||
637 | |||
638 | switch (power) { | ||
639 | case MMC_VDD_170: | ||
640 | case MMC_VDD_180: | ||
641 | case MMC_VDD_190: | ||
642 | pwr |= SDHCI_POWER_180; | ||
643 | break; | ||
644 | case MMC_VDD_290: | ||
645 | case MMC_VDD_300: | ||
646 | case MMC_VDD_310: | ||
647 | pwr |= SDHCI_POWER_300; | ||
648 | break; | ||
649 | case MMC_VDD_320: | ||
650 | case MMC_VDD_330: | ||
651 | case MMC_VDD_340: | ||
652 | pwr |= SDHCI_POWER_330; | ||
653 | break; | ||
654 | default: | ||
655 | BUG(); | ||
656 | } | ||
657 | |||
658 | writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL); | ||
659 | |||
660 | out: | ||
661 | host->power = power; | ||
662 | } | ||
663 | |||
533 | /*****************************************************************************\ | 664 | /*****************************************************************************\ |
534 | * * | 665 | * * |
535 | * MMC callbacks * | 666 | * MMC callbacks * |
@@ -576,17 +707,15 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
576 | */ | 707 | */ |
577 | if (ios->power_mode == MMC_POWER_OFF) { | 708 | if (ios->power_mode == MMC_POWER_OFF) { |
578 | writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE); | 709 | writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE); |
579 | spin_unlock_irqrestore(&host->lock, flags); | ||
580 | sdhci_init(host); | 710 | sdhci_init(host); |
581 | spin_lock_irqsave(&host->lock, flags); | ||
582 | } | 711 | } |
583 | 712 | ||
584 | sdhci_set_clock(host, ios->clock); | 713 | sdhci_set_clock(host, ios->clock); |
585 | 714 | ||
586 | if (ios->power_mode == MMC_POWER_OFF) | 715 | if (ios->power_mode == MMC_POWER_OFF) |
587 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); | 716 | sdhci_set_power(host, -1); |
588 | else | 717 | else |
589 | writeb(0xFF, host->ioaddr + SDHCI_POWER_CONTROL); | 718 | sdhci_set_power(host, ios->vdd); |
590 | 719 | ||
591 | ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); | 720 | ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); |
592 | if (ios->bus_width == MMC_BUS_WIDTH_4) | 721 | if (ios->bus_width == MMC_BUS_WIDTH_4) |
@@ -793,7 +922,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
793 | if (host->data->error != MMC_ERR_NONE) | 922 | if (host->data->error != MMC_ERR_NONE) |
794 | sdhci_finish_data(host); | 923 | sdhci_finish_data(host); |
795 | else { | 924 | else { |
796 | if (intmask & (SDHCI_INT_BUF_FULL | SDHCI_INT_BUF_EMPTY)) | 925 | if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) |
797 | sdhci_transfer_pio(host); | 926 | sdhci_transfer_pio(host); |
798 | 927 | ||
799 | if (intmask & SDHCI_INT_DATA_END) | 928 | if (intmask & SDHCI_INT_DATA_END) |
@@ -818,50 +947,44 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
818 | 947 | ||
819 | DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask); | 948 | DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask); |
820 | 949 | ||
821 | if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) | 950 | if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { |
951 | writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE), | ||
952 | host->ioaddr + SDHCI_INT_STATUS); | ||
822 | tasklet_schedule(&host->card_tasklet); | 953 | tasklet_schedule(&host->card_tasklet); |
954 | } | ||
823 | 955 | ||
824 | if (intmask & SDHCI_INT_CMD_MASK) { | 956 | intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); |
825 | sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); | ||
826 | 957 | ||
958 | if (intmask & SDHCI_INT_CMD_MASK) { | ||
827 | writel(intmask & SDHCI_INT_CMD_MASK, | 959 | writel(intmask & SDHCI_INT_CMD_MASK, |
828 | host->ioaddr + SDHCI_INT_STATUS); | 960 | host->ioaddr + SDHCI_INT_STATUS); |
961 | sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); | ||
829 | } | 962 | } |
830 | 963 | ||
831 | if (intmask & SDHCI_INT_DATA_MASK) { | 964 | if (intmask & SDHCI_INT_DATA_MASK) { |
832 | sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); | ||
833 | |||
834 | writel(intmask & SDHCI_INT_DATA_MASK, | 965 | writel(intmask & SDHCI_INT_DATA_MASK, |
835 | host->ioaddr + SDHCI_INT_STATUS); | 966 | host->ioaddr + SDHCI_INT_STATUS); |
967 | sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); | ||
836 | } | 968 | } |
837 | 969 | ||
838 | intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); | 970 | intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); |
839 | 971 | ||
840 | if (intmask & SDHCI_INT_CARD_INT) { | ||
841 | printk(KERN_ERR "%s: Unexpected card interrupt. Please " | ||
842 | "report this to " BUGMAIL ".\n", | ||
843 | mmc_hostname(host->mmc)); | ||
844 | sdhci_dumpregs(host); | ||
845 | } | ||
846 | |||
847 | if (intmask & SDHCI_INT_BUS_POWER) { | 972 | if (intmask & SDHCI_INT_BUS_POWER) { |
848 | printk(KERN_ERR "%s: Unexpected bus power interrupt. Please " | 973 | printk(KERN_ERR "%s: Card is consuming too much power!\n", |
849 | "report this to " BUGMAIL ".\n", | ||
850 | mmc_hostname(host->mmc)); | 974 | mmc_hostname(host->mmc)); |
851 | sdhci_dumpregs(host); | 975 | writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS); |
852 | } | 976 | } |
853 | 977 | ||
854 | if (intmask & SDHCI_INT_ACMD12ERR) { | 978 | intmask &= SDHCI_INT_BUS_POWER; |
855 | printk(KERN_ERR "%s: Unexpected auto CMD12 error. Please " | 979 | |
980 | if (intmask) { | ||
981 | printk(KERN_ERR "%s: Unexpected interrupt 0x%08x. Please " | ||
856 | "report this to " BUGMAIL ".\n", | 982 | "report this to " BUGMAIL ".\n", |
857 | mmc_hostname(host->mmc)); | 983 | mmc_hostname(host->mmc), intmask); |
858 | sdhci_dumpregs(host); | 984 | sdhci_dumpregs(host); |
859 | 985 | ||
860 | writew(~0, host->ioaddr + SDHCI_ACMD12_ERR); | ||
861 | } | ||
862 | |||
863 | if (intmask) | ||
864 | writel(intmask, host->ioaddr + SDHCI_INT_STATUS); | 986 | writel(intmask, host->ioaddr + SDHCI_INT_STATUS); |
987 | } | ||
865 | 988 | ||
866 | result = IRQ_HANDLED; | 989 | result = IRQ_HANDLED; |
867 | 990 | ||
@@ -954,6 +1077,7 @@ static int sdhci_resume (struct pci_dev *pdev) | |||
954 | static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | 1077 | static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) |
955 | { | 1078 | { |
956 | int ret; | 1079 | int ret; |
1080 | unsigned int version; | ||
957 | struct sdhci_chip *chip; | 1081 | struct sdhci_chip *chip; |
958 | struct mmc_host *mmc; | 1082 | struct mmc_host *mmc; |
959 | struct sdhci_host *host; | 1083 | struct sdhci_host *host; |
@@ -985,6 +1109,16 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
985 | return -ENODEV; | 1109 | return -ENODEV; |
986 | } | 1110 | } |
987 | 1111 | ||
1112 | if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { | ||
1113 | printk(KERN_ERR DRIVER_NAME ": Vendor specific interface. Aborting.\n"); | ||
1114 | return -ENODEV; | ||
1115 | } | ||
1116 | |||
1117 | if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) { | ||
1118 | printk(KERN_ERR DRIVER_NAME ": Unknown interface. Aborting.\n"); | ||
1119 | return -ENODEV; | ||
1120 | } | ||
1121 | |||
988 | mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev); | 1122 | mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev); |
989 | if (!mmc) | 1123 | if (!mmc) |
990 | return -ENOMEM; | 1124 | return -ENOMEM; |
@@ -1012,9 +1146,30 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1012 | goto release; | 1146 | goto release; |
1013 | } | 1147 | } |
1014 | 1148 | ||
1149 | sdhci_reset(host, SDHCI_RESET_ALL); | ||
1150 | |||
1151 | version = readw(host->ioaddr + SDHCI_HOST_VERSION); | ||
1152 | version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; | ||
1153 | if (version != 0) { | ||
1154 | printk(KERN_ERR "%s: Unknown controller version (%d). " | ||
1155 | "Cowardly refusing to continue.\n", host->slot_descr, | ||
1156 | version); | ||
1157 | ret = -ENODEV; | ||
1158 | goto unmap; | ||
1159 | } | ||
1160 | |||
1015 | caps = readl(host->ioaddr + SDHCI_CAPABILITIES); | 1161 | caps = readl(host->ioaddr + SDHCI_CAPABILITIES); |
1016 | 1162 | ||
1017 | if ((caps & SDHCI_CAN_DO_DMA) && ((pdev->class & 0x0000FF) == 0x01)) | 1163 | if (debug_nodma) |
1164 | DBG("DMA forced off\n"); | ||
1165 | else if (debug_forcedma) { | ||
1166 | DBG("DMA forced on\n"); | ||
1167 | host->flags |= SDHCI_USE_DMA; | ||
1168 | } else if ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) | ||
1169 | DBG("Controller doesn't have DMA interface\n"); | ||
1170 | else if (!(caps & SDHCI_CAN_DO_DMA)) | ||
1171 | DBG("Controller doesn't have DMA capability\n"); | ||
1172 | else | ||
1018 | host->flags |= SDHCI_USE_DMA; | 1173 | host->flags |= SDHCI_USE_DMA; |
1019 | 1174 | ||
1020 | if (host->flags & SDHCI_USE_DMA) { | 1175 | if (host->flags & SDHCI_USE_DMA) { |
@@ -1030,18 +1185,59 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1030 | else /* XXX: Hack to get MMC layer to avoid highmem */ | 1185 | else /* XXX: Hack to get MMC layer to avoid highmem */ |
1031 | pdev->dma_mask = 0; | 1186 | pdev->dma_mask = 0; |
1032 | 1187 | ||
1033 | host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; | 1188 | host->max_clk = |
1189 | (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; | ||
1190 | if (host->max_clk == 0) { | ||
1191 | printk(KERN_ERR "%s: Hardware doesn't specify base clock " | ||
1192 | "frequency.\n", host->slot_descr); | ||
1193 | ret = -ENODEV; | ||
1194 | goto unmap; | ||
1195 | } | ||
1034 | host->max_clk *= 1000000; | 1196 | host->max_clk *= 1000000; |
1035 | 1197 | ||
1198 | host->timeout_clk = | ||
1199 | (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; | ||
1200 | if (host->timeout_clk == 0) { | ||
1201 | printk(KERN_ERR "%s: Hardware doesn't specify timeout clock " | ||
1202 | "frequency.\n", host->slot_descr); | ||
1203 | ret = -ENODEV; | ||
1204 | goto unmap; | ||
1205 | } | ||
1206 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) | ||
1207 | host->timeout_clk *= 1000; | ||
1208 | |||
1209 | host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; | ||
1210 | if (host->max_block >= 3) { | ||
1211 | printk(KERN_ERR "%s: Invalid maximum block size.\n", | ||
1212 | host->slot_descr); | ||
1213 | ret = -ENODEV; | ||
1214 | goto unmap; | ||
1215 | } | ||
1216 | host->max_block = 512 << host->max_block; | ||
1217 | |||
1036 | /* | 1218 | /* |
1037 | * Set host parameters. | 1219 | * Set host parameters. |
1038 | */ | 1220 | */ |
1039 | mmc->ops = &sdhci_ops; | 1221 | mmc->ops = &sdhci_ops; |
1040 | mmc->f_min = host->max_clk / 256; | 1222 | mmc->f_min = host->max_clk / 256; |
1041 | mmc->f_max = host->max_clk; | 1223 | mmc->f_max = host->max_clk; |
1042 | mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; | ||
1043 | mmc->caps = MMC_CAP_4_BIT_DATA; | 1224 | mmc->caps = MMC_CAP_4_BIT_DATA; |
1044 | 1225 | ||
1226 | mmc->ocr_avail = 0; | ||
1227 | if (caps & SDHCI_CAN_VDD_330) | ||
1228 | mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; | ||
1229 | else if (caps & SDHCI_CAN_VDD_300) | ||
1230 | mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; | ||
1231 | else if (caps & SDHCI_CAN_VDD_180) | ||
1232 | mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; | ||
1233 | |||
1234 | if (mmc->ocr_avail == 0) { | ||
1235 | printk(KERN_ERR "%s: Hardware doesn't report any " | ||
1236 | "support voltages.\n", host->slot_descr); | ||
1237 | ret = -ENODEV; | ||
1238 | goto unmap; | ||
1239 | } | ||
1240 | |||
1045 | spin_lock_init(&host->lock); | 1241 | spin_lock_init(&host->lock); |
1046 | 1242 | ||
1047 | /* | 1243 | /* |
@@ -1054,10 +1250,10 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1054 | mmc->max_phys_segs = 16; | 1250 | mmc->max_phys_segs = 16; |
1055 | 1251 | ||
1056 | /* | 1252 | /* |
1057 | * Maximum number of sectors in one transfer. Limited by sector | 1253 | * Maximum number of sectors in one transfer. Limited by DMA boundary |
1058 | * count register. | 1254 | * size (512KiB), which means (512 KiB/512=) 1024 entries. |
1059 | */ | 1255 | */ |
1060 | mmc->max_sectors = 0x3FFF; | 1256 | mmc->max_sectors = 1024; |
1061 | 1257 | ||
1062 | /* | 1258 | /* |
1063 | * Maximum segment size. Could be one segment with the maximum number | 1259 | * Maximum segment size. Could be one segment with the maximum number |
@@ -1078,7 +1274,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1078 | ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, | 1274 | ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, |
1079 | host->slot_descr, host); | 1275 | host->slot_descr, host); |
1080 | if (ret) | 1276 | if (ret) |
1081 | goto unmap; | 1277 | goto untasklet; |
1082 | 1278 | ||
1083 | sdhci_init(host); | 1279 | sdhci_init(host); |
1084 | 1280 | ||
@@ -1097,10 +1293,10 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1097 | 1293 | ||
1098 | return 0; | 1294 | return 0; |
1099 | 1295 | ||
1100 | unmap: | 1296 | untasklet: |
1101 | tasklet_kill(&host->card_tasklet); | 1297 | tasklet_kill(&host->card_tasklet); |
1102 | tasklet_kill(&host->finish_tasklet); | 1298 | tasklet_kill(&host->finish_tasklet); |
1103 | 1299 | unmap: | |
1104 | iounmap(host->ioaddr); | 1300 | iounmap(host->ioaddr); |
1105 | release: | 1301 | release: |
1106 | pci_release_region(pdev, host->bar); | 1302 | pci_release_region(pdev, host->bar); |
@@ -1144,13 +1340,18 @@ static int __devinit sdhci_probe(struct pci_dev *pdev, | |||
1144 | const struct pci_device_id *ent) | 1340 | const struct pci_device_id *ent) |
1145 | { | 1341 | { |
1146 | int ret, i; | 1342 | int ret, i; |
1147 | u8 slots; | 1343 | u8 slots, rev; |
1148 | struct sdhci_chip *chip; | 1344 | struct sdhci_chip *chip; |
1149 | 1345 | ||
1150 | BUG_ON(pdev == NULL); | 1346 | BUG_ON(pdev == NULL); |
1151 | BUG_ON(ent == NULL); | 1347 | BUG_ON(ent == NULL); |
1152 | 1348 | ||
1153 | DBG("found at %s\n", pci_name(pdev)); | 1349 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev); |
1350 | |||
1351 | printk(KERN_INFO DRIVER_NAME | ||
1352 | ": SDHCI controller found at %s [%04x:%04x] (rev %x)\n", | ||
1353 | pci_name(pdev), (int)pdev->vendor, (int)pdev->device, | ||
1354 | (int)rev); | ||
1154 | 1355 | ||
1155 | ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots); | 1356 | ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots); |
1156 | if (ret) | 1357 | if (ret) |
@@ -1173,6 +1374,10 @@ static int __devinit sdhci_probe(struct pci_dev *pdev, | |||
1173 | } | 1374 | } |
1174 | 1375 | ||
1175 | chip->pdev = pdev; | 1376 | chip->pdev = pdev; |
1377 | chip->quirks = ent->driver_data; | ||
1378 | |||
1379 | if (debug_quirks) | ||
1380 | chip->quirks = debug_quirks; | ||
1176 | 1381 | ||
1177 | chip->num_slots = slots; | 1382 | chip->num_slots = slots; |
1178 | pci_set_drvdata(pdev, chip); | 1383 | pci_set_drvdata(pdev, chip); |
@@ -1251,7 +1456,15 @@ static void __exit sdhci_drv_exit(void) | |||
1251 | module_init(sdhci_drv_init); | 1456 | module_init(sdhci_drv_init); |
1252 | module_exit(sdhci_drv_exit); | 1457 | module_exit(sdhci_drv_exit); |
1253 | 1458 | ||
1459 | module_param(debug_nodma, uint, 0444); | ||
1460 | module_param(debug_forcedma, uint, 0444); | ||
1461 | module_param(debug_quirks, uint, 0444); | ||
1462 | |||
1254 | MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>"); | 1463 | MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>"); |
1255 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver"); | 1464 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver"); |
1256 | MODULE_VERSION(DRIVER_VERSION); | 1465 | MODULE_VERSION(DRIVER_VERSION); |
1257 | MODULE_LICENSE("GPL"); | 1466 | MODULE_LICENSE("GPL"); |
1467 | |||
1468 | MODULE_PARM_DESC(debug_nodma, "Forcefully disable DMA transfers. (default 0)"); | ||
1469 | MODULE_PARM_DESC(debug_forcedma, "Forcefully enable DMA transfers. (default 0)"); | ||
1470 | MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); | ||
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h index 3b270ef486b4..f2453343f783 100644 --- a/drivers/mmc/sdhci.h +++ b/drivers/mmc/sdhci.h | |||
@@ -12,6 +12,10 @@ | |||
12 | * PCI registers | 12 | * PCI registers |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #define PCI_SDHCI_IFPIO 0x00 | ||
16 | #define PCI_SDHCI_IFDMA 0x01 | ||
17 | #define PCI_SDHCI_IFVENDOR 0x02 | ||
18 | |||
15 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ | 19 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ |
16 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) | 20 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) |
17 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 | 21 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 |
@@ -23,6 +27,7 @@ | |||
23 | #define SDHCI_DMA_ADDRESS 0x00 | 27 | #define SDHCI_DMA_ADDRESS 0x00 |
24 | 28 | ||
25 | #define SDHCI_BLOCK_SIZE 0x04 | 29 | #define SDHCI_BLOCK_SIZE 0x04 |
30 | #define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF)) | ||
26 | 31 | ||
27 | #define SDHCI_BLOCK_COUNT 0x06 | 32 | #define SDHCI_BLOCK_COUNT 0x06 |
28 | 33 | ||
@@ -67,6 +72,10 @@ | |||
67 | #define SDHCI_CTRL_4BITBUS 0x02 | 72 | #define SDHCI_CTRL_4BITBUS 0x02 |
68 | 73 | ||
69 | #define SDHCI_POWER_CONTROL 0x29 | 74 | #define SDHCI_POWER_CONTROL 0x29 |
75 | #define SDHCI_POWER_ON 0x01 | ||
76 | #define SDHCI_POWER_180 0x0A | ||
77 | #define SDHCI_POWER_300 0x0C | ||
78 | #define SDHCI_POWER_330 0x0E | ||
70 | 79 | ||
71 | #define SDHCI_BLOCK_GAP_CONTROL 0x2A | 80 | #define SDHCI_BLOCK_GAP_CONTROL 0x2A |
72 | 81 | ||
@@ -91,8 +100,8 @@ | |||
91 | #define SDHCI_INT_RESPONSE 0x00000001 | 100 | #define SDHCI_INT_RESPONSE 0x00000001 |
92 | #define SDHCI_INT_DATA_END 0x00000002 | 101 | #define SDHCI_INT_DATA_END 0x00000002 |
93 | #define SDHCI_INT_DMA_END 0x00000008 | 102 | #define SDHCI_INT_DMA_END 0x00000008 |
94 | #define SDHCI_INT_BUF_EMPTY 0x00000010 | 103 | #define SDHCI_INT_SPACE_AVAIL 0x00000010 |
95 | #define SDHCI_INT_BUF_FULL 0x00000020 | 104 | #define SDHCI_INT_DATA_AVAIL 0x00000020 |
96 | #define SDHCI_INT_CARD_INSERT 0x00000040 | 105 | #define SDHCI_INT_CARD_INSERT 0x00000040 |
97 | #define SDHCI_INT_CARD_REMOVE 0x00000080 | 106 | #define SDHCI_INT_CARD_REMOVE 0x00000080 |
98 | #define SDHCI_INT_CARD_INT 0x00000100 | 107 | #define SDHCI_INT_CARD_INT 0x00000100 |
@@ -112,7 +121,7 @@ | |||
112 | #define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ | 121 | #define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ |
113 | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) | 122 | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) |
114 | #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ | 123 | #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ |
115 | SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL | \ | 124 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ |
116 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ | 125 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ |
117 | SDHCI_INT_DATA_END_BIT) | 126 | SDHCI_INT_DATA_END_BIT) |
118 | 127 | ||
@@ -121,9 +130,17 @@ | |||
121 | /* 3E-3F reserved */ | 130 | /* 3E-3F reserved */ |
122 | 131 | ||
123 | #define SDHCI_CAPABILITIES 0x40 | 132 | #define SDHCI_CAPABILITIES 0x40 |
124 | #define SDHCI_CAN_DO_DMA 0x00400000 | 133 | #define SDHCI_TIMEOUT_CLK_MASK 0x0000003F |
134 | #define SDHCI_TIMEOUT_CLK_SHIFT 0 | ||
135 | #define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 | ||
125 | #define SDHCI_CLOCK_BASE_MASK 0x00003F00 | 136 | #define SDHCI_CLOCK_BASE_MASK 0x00003F00 |
126 | #define SDHCI_CLOCK_BASE_SHIFT 8 | 137 | #define SDHCI_CLOCK_BASE_SHIFT 8 |
138 | #define SDHCI_MAX_BLOCK_MASK 0x00030000 | ||
139 | #define SDHCI_MAX_BLOCK_SHIFT 16 | ||
140 | #define SDHCI_CAN_DO_DMA 0x00400000 | ||
141 | #define SDHCI_CAN_VDD_330 0x01000000 | ||
142 | #define SDHCI_CAN_VDD_300 0x02000000 | ||
143 | #define SDHCI_CAN_VDD_180 0x04000000 | ||
127 | 144 | ||
128 | /* 44-47 reserved for more caps */ | 145 | /* 44-47 reserved for more caps */ |
129 | 146 | ||
@@ -136,6 +153,10 @@ | |||
136 | #define SDHCI_SLOT_INT_STATUS 0xFC | 153 | #define SDHCI_SLOT_INT_STATUS 0xFC |
137 | 154 | ||
138 | #define SDHCI_HOST_VERSION 0xFE | 155 | #define SDHCI_HOST_VERSION 0xFE |
156 | #define SDHCI_VENDOR_VER_MASK 0xFF00 | ||
157 | #define SDHCI_VENDOR_VER_SHIFT 8 | ||
158 | #define SDHCI_SPEC_VER_MASK 0x00FF | ||
159 | #define SDHCI_SPEC_VER_SHIFT 0 | ||
139 | 160 | ||
140 | struct sdhci_chip; | 161 | struct sdhci_chip; |
141 | 162 | ||
@@ -149,8 +170,11 @@ struct sdhci_host { | |||
149 | #define SDHCI_USE_DMA (1<<0) | 170 | #define SDHCI_USE_DMA (1<<0) |
150 | 171 | ||
151 | unsigned int max_clk; /* Max possible freq (MHz) */ | 172 | unsigned int max_clk; /* Max possible freq (MHz) */ |
173 | unsigned int timeout_clk; /* Timeout freq (KHz) */ | ||
174 | unsigned int max_block; /* Max block size (bytes) */ | ||
152 | 175 | ||
153 | unsigned int clock; /* Current clock (MHz) */ | 176 | unsigned int clock; /* Current clock (MHz) */ |
177 | unsigned short power; /* Current voltage */ | ||
154 | 178 | ||
155 | struct mmc_request *mrq; /* Current request */ | 179 | struct mmc_request *mrq; /* Current request */ |
156 | struct mmc_command *cmd; /* Current command */ | 180 | struct mmc_command *cmd; /* Current command */ |
@@ -180,6 +204,8 @@ struct sdhci_host { | |||
180 | struct sdhci_chip { | 204 | struct sdhci_chip { |
181 | struct pci_dev *pdev; | 205 | struct pci_dev *pdev; |
182 | 206 | ||
207 | unsigned long quirks; | ||
208 | |||
183 | int num_slots; /* Slots on controller */ | 209 | int num_slots; /* Slots on controller */ |
184 | struct sdhci_host *hosts[0]; /* Pointers to hosts */ | 210 | struct sdhci_host *hosts[0]; /* Pointers to hosts */ |
185 | }; | 211 | }; |