diff options
Diffstat (limited to 'drivers/mmc/host/mmci.c')
| -rw-r--r-- | drivers/mmc/host/mmci.c | 148 |
1 files changed, 88 insertions, 60 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 2ed435bd4b6..840b301b567 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/amba/mmci.h> | 26 | #include <linux/amba/mmci.h> |
| 27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
| 28 | 28 | ||
| 29 | #include <asm/cacheflush.h> | ||
| 30 | #include <asm/div64.h> | 29 | #include <asm/div64.h> |
| 31 | #include <asm/io.h> | 30 | #include <asm/io.h> |
| 32 | #include <asm/sizes.h> | 31 | #include <asm/sizes.h> |
| @@ -37,12 +36,39 @@ | |||
| 37 | 36 | ||
| 38 | static unsigned int fmax = 515633; | 37 | static unsigned int fmax = 515633; |
| 39 | 38 | ||
| 39 | /** | ||
| 40 | * struct variant_data - MMCI variant-specific quirks | ||
| 41 | * @clkreg: default value for MCICLOCK register | ||
| 42 | * @clkreg_enable: enable value for MMCICLOCK register | ||
| 43 | * @datalength_bits: number of bits in the MMCIDATALENGTH register | ||
| 44 | */ | ||
| 45 | struct variant_data { | ||
| 46 | unsigned int clkreg; | ||
| 47 | unsigned int clkreg_enable; | ||
| 48 | unsigned int datalength_bits; | ||
| 49 | }; | ||
| 50 | |||
| 51 | static struct variant_data variant_arm = { | ||
| 52 | .datalength_bits = 16, | ||
| 53 | }; | ||
| 54 | |||
| 55 | static struct variant_data variant_u300 = { | ||
| 56 | .clkreg_enable = 1 << 13, /* HWFCEN */ | ||
| 57 | .datalength_bits = 16, | ||
| 58 | }; | ||
| 59 | |||
| 60 | static struct variant_data variant_ux500 = { | ||
| 61 | .clkreg = MCI_CLK_ENABLE, | ||
| 62 | .clkreg_enable = 1 << 14, /* HWFCEN */ | ||
| 63 | .datalength_bits = 24, | ||
| 64 | }; | ||
| 40 | /* | 65 | /* |
| 41 | * This must be called with host->lock held | 66 | * This must be called with host->lock held |
| 42 | */ | 67 | */ |
| 43 | static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | 68 | static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) |
| 44 | { | 69 | { |
| 45 | u32 clk = 0; | 70 | struct variant_data *variant = host->variant; |
| 71 | u32 clk = variant->clkreg; | ||
| 46 | 72 | ||
| 47 | if (desired) { | 73 | if (desired) { |
| 48 | if (desired >= host->mclk) { | 74 | if (desired >= host->mclk) { |
| @@ -54,8 +80,8 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | |||
| 54 | clk = 255; | 80 | clk = 255; |
| 55 | host->cclk = host->mclk / (2 * (clk + 1)); | 81 | host->cclk = host->mclk / (2 * (clk + 1)); |
| 56 | } | 82 | } |
| 57 | if (host->hw_designer == AMBA_VENDOR_ST) | 83 | |
| 58 | clk |= MCI_ST_FCEN; /* Bug fix in ST IP block */ | 84 | clk |= variant->clkreg_enable; |
| 59 | clk |= MCI_CLK_ENABLE; | 85 | clk |= MCI_CLK_ENABLE; |
| 60 | /* This hasn't proven to be worthwhile */ | 86 | /* This hasn't proven to be worthwhile */ |
| 61 | /* clk |= MCI_CLK_PWRSAVE; */ | 87 | /* clk |= MCI_CLK_PWRSAVE; */ |
| @@ -98,6 +124,18 @@ static void mmci_stop_data(struct mmci_host *host) | |||
| 98 | host->data = NULL; | 124 | host->data = NULL; |
| 99 | } | 125 | } |
| 100 | 126 | ||
| 127 | static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) | ||
| 128 | { | ||
| 129 | unsigned int flags = SG_MITER_ATOMIC; | ||
| 130 | |||
| 131 | if (data->flags & MMC_DATA_READ) | ||
| 132 | flags |= SG_MITER_TO_SG; | ||
| 133 | else | ||
| 134 | flags |= SG_MITER_FROM_SG; | ||
| 135 | |||
| 136 | sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); | ||
| 137 | } | ||
| 138 | |||
| 101 | static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | 139 | static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) |
| 102 | { | 140 | { |
| 103 | unsigned int datactrl, timeout, irqmask; | 141 | unsigned int datactrl, timeout, irqmask; |
| @@ -109,7 +147,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
| 109 | data->blksz, data->blocks, data->flags); | 147 | data->blksz, data->blocks, data->flags); |
| 110 | 148 | ||
| 111 | host->data = data; | 149 | host->data = data; |
| 112 | host->size = data->blksz; | 150 | host->size = data->blksz * data->blocks; |
| 113 | host->data_xfered = 0; | 151 | host->data_xfered = 0; |
| 114 | 152 | ||
| 115 | mmci_init_sg(host, data); | 153 | mmci_init_sg(host, data); |
| @@ -210,8 +248,17 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, | |||
| 210 | * We hit an error condition. Ensure that any data | 248 | * We hit an error condition. Ensure that any data |
| 211 | * partially written to a page is properly coherent. | 249 | * partially written to a page is properly coherent. |
| 212 | */ | 250 | */ |
| 213 | if (host->sg_len && data->flags & MMC_DATA_READ) | 251 | if (data->flags & MMC_DATA_READ) { |
| 214 | flush_dcache_page(sg_page(host->sg_ptr)); | 252 | struct sg_mapping_iter *sg_miter = &host->sg_miter; |
| 253 | unsigned long flags; | ||
| 254 | |||
| 255 | local_irq_save(flags); | ||
| 256 | if (sg_miter_next(sg_miter)) { | ||
| 257 | flush_dcache_page(sg_miter->page); | ||
| 258 | sg_miter_stop(sg_miter); | ||
| 259 | } | ||
| 260 | local_irq_restore(flags); | ||
| 261 | } | ||
| 215 | } | 262 | } |
| 216 | if (status & MCI_DATAEND) { | 263 | if (status & MCI_DATAEND) { |
| 217 | mmci_stop_data(host); | 264 | mmci_stop_data(host); |
| @@ -314,15 +361,18 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem | |||
| 314 | static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | 361 | static irqreturn_t mmci_pio_irq(int irq, void *dev_id) |
| 315 | { | 362 | { |
| 316 | struct mmci_host *host = dev_id; | 363 | struct mmci_host *host = dev_id; |
| 364 | struct sg_mapping_iter *sg_miter = &host->sg_miter; | ||
| 317 | void __iomem *base = host->base; | 365 | void __iomem *base = host->base; |
| 366 | unsigned long flags; | ||
| 318 | u32 status; | 367 | u32 status; |
| 319 | 368 | ||
| 320 | status = readl(base + MMCISTATUS); | 369 | status = readl(base + MMCISTATUS); |
| 321 | 370 | ||
| 322 | dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status); | 371 | dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status); |
| 323 | 372 | ||
| 373 | local_irq_save(flags); | ||
| 374 | |||
| 324 | do { | 375 | do { |
| 325 | unsigned long flags; | ||
| 326 | unsigned int remain, len; | 376 | unsigned int remain, len; |
| 327 | char *buffer; | 377 | char *buffer; |
| 328 | 378 | ||
| @@ -336,11 +386,11 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | |||
| 336 | if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL))) | 386 | if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL))) |
| 337 | break; | 387 | break; |
| 338 | 388 | ||
| 339 | /* | 389 | if (!sg_miter_next(sg_miter)) |
| 340 | * Map the current scatter buffer. | 390 | break; |
| 341 | */ | 391 | |
| 342 | buffer = mmci_kmap_atomic(host, &flags) + host->sg_off; | 392 | buffer = sg_miter->addr; |
| 343 | remain = host->sg_ptr->length - host->sg_off; | 393 | remain = sg_miter->length; |
| 344 | 394 | ||
| 345 | len = 0; | 395 | len = 0; |
| 346 | if (status & MCI_RXACTIVE) | 396 | if (status & MCI_RXACTIVE) |
| @@ -348,31 +398,24 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | |||
| 348 | if (status & MCI_TXACTIVE) | 398 | if (status & MCI_TXACTIVE) |
| 349 | len = mmci_pio_write(host, buffer, remain, status); | 399 | len = mmci_pio_write(host, buffer, remain, status); |
| 350 | 400 | ||
| 351 | /* | 401 | sg_miter->consumed = len; |
| 352 | * Unmap the buffer. | ||
| 353 | */ | ||
| 354 | mmci_kunmap_atomic(host, buffer, &flags); | ||
| 355 | 402 | ||
| 356 | host->sg_off += len; | ||
| 357 | host->size -= len; | 403 | host->size -= len; |
| 358 | remain -= len; | 404 | remain -= len; |
| 359 | 405 | ||
| 360 | if (remain) | 406 | if (remain) |
| 361 | break; | 407 | break; |
| 362 | 408 | ||
| 363 | /* | ||
| 364 | * If we were reading, and we have completed this | ||
| 365 | * page, ensure that the data cache is coherent. | ||
| 366 | */ | ||
| 367 | if (status & MCI_RXACTIVE) | 409 | if (status & MCI_RXACTIVE) |
| 368 | flush_dcache_page(sg_page(host->sg_ptr)); | 410 | flush_dcache_page(sg_miter->page); |
| 369 | |||
| 370 | if (!mmci_next_sg(host)) | ||
| 371 | break; | ||
| 372 | 411 | ||
| 373 | status = readl(base + MMCISTATUS); | 412 | status = readl(base + MMCISTATUS); |
| 374 | } while (1); | 413 | } while (1); |
| 375 | 414 | ||
| 415 | sg_miter_stop(sg_miter); | ||
| 416 | |||
| 417 | local_irq_restore(flags); | ||
| 418 | |||
| 376 | /* | 419 | /* |
| 377 | * If we're nearing the end of the read, switch to | 420 | * If we're nearing the end of the read, switch to |
| 378 | * "any data available" mode. | 421 | * "any data available" mode. |
| @@ -477,16 +520,9 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 477 | /* This implicitly enables the regulator */ | 520 | /* This implicitly enables the regulator */ |
| 478 | mmc_regulator_set_ocr(host->vcc, ios->vdd); | 521 | mmc_regulator_set_ocr(host->vcc, ios->vdd); |
| 479 | #endif | 522 | #endif |
| 480 | /* | 523 | if (host->plat->vdd_handler) |
| 481 | * The translate_vdd function is not used if you have | 524 | pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, |
| 482 | * an external regulator, or your design is really weird. | 525 | ios->power_mode); |
| 483 | * Using it would mean sending in power control BOTH using | ||
| 484 | * a regulator AND the 4 MMCIPWR bits. If we don't have | ||
| 485 | * a regulator, we might have some other platform specific | ||
| 486 | * power control behind this translate function. | ||
| 487 | */ | ||
| 488 | if (!host->vcc && host->plat->translate_vdd) | ||
| 489 | pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); | ||
| 490 | /* The ST version does not have this, fall through to POWER_ON */ | 526 | /* The ST version does not have this, fall through to POWER_ON */ |
| 491 | if (host->hw_designer != AMBA_VENDOR_ST) { | 527 | if (host->hw_designer != AMBA_VENDOR_ST) { |
| 492 | pwr |= MCI_PWR_UP; | 528 | pwr |= MCI_PWR_UP; |
| @@ -555,21 +591,10 @@ static const struct mmc_host_ops mmci_ops = { | |||
| 555 | .get_cd = mmci_get_cd, | 591 | .get_cd = mmci_get_cd, |
| 556 | }; | 592 | }; |
| 557 | 593 | ||
| 558 | static void mmci_check_status(unsigned long data) | ||
| 559 | { | ||
| 560 | struct mmci_host *host = (struct mmci_host *)data; | ||
| 561 | unsigned int status = mmci_get_cd(host->mmc); | ||
| 562 | |||
| 563 | if (status ^ host->oldstat) | ||
| 564 | mmc_detect_change(host->mmc, 0); | ||
| 565 | |||
| 566 | host->oldstat = status; | ||
| 567 | mod_timer(&host->timer, jiffies + HZ); | ||
| 568 | } | ||
| 569 | |||
| 570 | static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | 594 | static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) |
| 571 | { | 595 | { |
| 572 | struct mmci_platform_data *plat = dev->dev.platform_data; | 596 | struct mmci_platform_data *plat = dev->dev.platform_data; |
| 597 | struct variant_data *variant = id->data; | ||
| 573 | struct mmci_host *host; | 598 | struct mmci_host *host; |
| 574 | struct mmc_host *mmc; | 599 | struct mmc_host *mmc; |
| 575 | int ret; | 600 | int ret; |
| @@ -613,6 +638,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 613 | goto clk_free; | 638 | goto clk_free; |
| 614 | 639 | ||
| 615 | host->plat = plat; | 640 | host->plat = plat; |
| 641 | host->variant = variant; | ||
| 616 | host->mclk = clk_get_rate(host->clk); | 642 | host->mclk = clk_get_rate(host->clk); |
| 617 | /* | 643 | /* |
| 618 | * According to the spec, mclk is max 100 MHz, | 644 | * According to the spec, mclk is max 100 MHz, |
| @@ -673,6 +699,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 673 | if (host->vcc == NULL) | 699 | if (host->vcc == NULL) |
| 674 | mmc->ocr_avail = plat->ocr_mask; | 700 | mmc->ocr_avail = plat->ocr_mask; |
| 675 | mmc->caps = plat->capabilities; | 701 | mmc->caps = plat->capabilities; |
| 702 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
| 676 | 703 | ||
| 677 | /* | 704 | /* |
| 678 | * We can do SGIO | 705 | * We can do SGIO |
| @@ -681,10 +708,11 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 681 | mmc->max_phys_segs = NR_SG; | 708 | mmc->max_phys_segs = NR_SG; |
| 682 | 709 | ||
| 683 | /* | 710 | /* |
| 684 | * Since we only have a 16-bit data length register, we must | 711 | * Since only a certain number of bits are valid in the data length |
| 685 | * ensure that we don't exceed 2^16-1 bytes in a single request. | 712 | * register, we must ensure that we don't exceed 2^num-1 bytes in a |
| 713 | * single request. | ||
| 686 | */ | 714 | */ |
| 687 | mmc->max_req_size = 65535; | 715 | mmc->max_req_size = (1 << variant->datalength_bits) - 1; |
| 688 | 716 | ||
| 689 | /* | 717 | /* |
| 690 | * Set the maximum segment size. Since we aren't doing DMA | 718 | * Set the maximum segment size. Since we aren't doing DMA |
| @@ -738,7 +766,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 738 | writel(MCI_IRQENABLE, host->base + MMCIMASK0); | 766 | writel(MCI_IRQENABLE, host->base + MMCIMASK0); |
| 739 | 767 | ||
| 740 | amba_set_drvdata(dev, mmc); | 768 | amba_set_drvdata(dev, mmc); |
| 741 | host->oldstat = mmci_get_cd(host->mmc); | ||
| 742 | 769 | ||
| 743 | mmc_add_host(mmc); | 770 | mmc_add_host(mmc); |
| 744 | 771 | ||
| @@ -746,12 +773,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 746 | mmc_hostname(mmc), amba_rev(dev), amba_config(dev), | 773 | mmc_hostname(mmc), amba_rev(dev), amba_config(dev), |
| 747 | (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]); | 774 | (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]); |
| 748 | 775 | ||
| 749 | init_timer(&host->timer); | ||
| 750 | host->timer.data = (unsigned long)host; | ||
| 751 | host->timer.function = mmci_check_status; | ||
| 752 | host->timer.expires = jiffies + HZ; | ||
| 753 | add_timer(&host->timer); | ||
| 754 | |||
| 755 | return 0; | 776 | return 0; |
| 756 | 777 | ||
| 757 | irq0_free: | 778 | irq0_free: |
| @@ -785,8 +806,6 @@ static int __devexit mmci_remove(struct amba_device *dev) | |||
| 785 | if (mmc) { | 806 | if (mmc) { |
| 786 | struct mmci_host *host = mmc_priv(mmc); | 807 | struct mmci_host *host = mmc_priv(mmc); |
| 787 | 808 | ||
| 788 | del_timer_sync(&host->timer); | ||
| 789 | |||
| 790 | mmc_remove_host(mmc); | 809 | mmc_remove_host(mmc); |
| 791 | 810 | ||
| 792 | writel(0, host->base + MMCIMASK0); | 811 | writel(0, host->base + MMCIMASK0); |
| @@ -860,19 +879,28 @@ static struct amba_id mmci_ids[] = { | |||
| 860 | { | 879 | { |
| 861 | .id = 0x00041180, | 880 | .id = 0x00041180, |
| 862 | .mask = 0x000fffff, | 881 | .mask = 0x000fffff, |
| 882 | .data = &variant_arm, | ||
| 863 | }, | 883 | }, |
| 864 | { | 884 | { |
| 865 | .id = 0x00041181, | 885 | .id = 0x00041181, |
| 866 | .mask = 0x000fffff, | 886 | .mask = 0x000fffff, |
| 887 | .data = &variant_arm, | ||
| 867 | }, | 888 | }, |
| 868 | /* ST Micro variants */ | 889 | /* ST Micro variants */ |
| 869 | { | 890 | { |
| 870 | .id = 0x00180180, | 891 | .id = 0x00180180, |
| 871 | .mask = 0x00ffffff, | 892 | .mask = 0x00ffffff, |
| 893 | .data = &variant_u300, | ||
| 872 | }, | 894 | }, |
| 873 | { | 895 | { |
| 874 | .id = 0x00280180, | 896 | .id = 0x00280180, |
| 875 | .mask = 0x00ffffff, | 897 | .mask = 0x00ffffff, |
| 898 | .data = &variant_u300, | ||
| 899 | }, | ||
| 900 | { | ||
| 901 | .id = 0x00480180, | ||
| 902 | .mask = 0x00ffffff, | ||
| 903 | .data = &variant_ux500, | ||
| 876 | }, | 904 | }, |
| 877 | { 0, 0 }, | 905 | { 0, 0 }, |
| 878 | }; | 906 | }; |
