diff options
Diffstat (limited to 'drivers')
| -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 | }; |
