diff options
Diffstat (limited to 'drivers/mmc/host/mmci.c')
| -rw-r--r-- | drivers/mmc/host/mmci.c | 62 |
1 files changed, 53 insertions, 9 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 840b301b5671..f2e02d7d9f3d 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -41,23 +41,35 @@ static unsigned int fmax = 515633; | |||
| 41 | * @clkreg: default value for MCICLOCK register | 41 | * @clkreg: default value for MCICLOCK register |
| 42 | * @clkreg_enable: enable value for MMCICLOCK register | 42 | * @clkreg_enable: enable value for MMCICLOCK register |
| 43 | * @datalength_bits: number of bits in the MMCIDATALENGTH register | 43 | * @datalength_bits: number of bits in the MMCIDATALENGTH register |
| 44 | * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY | ||
| 45 | * is asserted (likewise for RX) | ||
| 46 | * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY | ||
| 47 | * is asserted (likewise for RX) | ||
| 44 | */ | 48 | */ |
| 45 | struct variant_data { | 49 | struct variant_data { |
| 46 | unsigned int clkreg; | 50 | unsigned int clkreg; |
| 47 | unsigned int clkreg_enable; | 51 | unsigned int clkreg_enable; |
| 48 | unsigned int datalength_bits; | 52 | unsigned int datalength_bits; |
| 53 | unsigned int fifosize; | ||
| 54 | unsigned int fifohalfsize; | ||
| 49 | }; | 55 | }; |
| 50 | 56 | ||
| 51 | static struct variant_data variant_arm = { | 57 | static struct variant_data variant_arm = { |
| 58 | .fifosize = 16 * 4, | ||
| 59 | .fifohalfsize = 8 * 4, | ||
| 52 | .datalength_bits = 16, | 60 | .datalength_bits = 16, |
| 53 | }; | 61 | }; |
| 54 | 62 | ||
| 55 | static struct variant_data variant_u300 = { | 63 | static struct variant_data variant_u300 = { |
| 64 | .fifosize = 16 * 4, | ||
| 65 | .fifohalfsize = 8 * 4, | ||
| 56 | .clkreg_enable = 1 << 13, /* HWFCEN */ | 66 | .clkreg_enable = 1 << 13, /* HWFCEN */ |
| 57 | .datalength_bits = 16, | 67 | .datalength_bits = 16, |
| 58 | }; | 68 | }; |
| 59 | 69 | ||
| 60 | static struct variant_data variant_ux500 = { | 70 | static struct variant_data variant_ux500 = { |
| 71 | .fifosize = 30 * 4, | ||
| 72 | .fifohalfsize = 8 * 4, | ||
| 61 | .clkreg = MCI_CLK_ENABLE, | 73 | .clkreg = MCI_CLK_ENABLE, |
| 62 | .clkreg_enable = 1 << 14, /* HWFCEN */ | 74 | .clkreg_enable = 1 << 14, /* HWFCEN */ |
| 63 | .datalength_bits = 24, | 75 | .datalength_bits = 24, |
| @@ -138,6 +150,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) | |||
| 138 | 150 | ||
| 139 | static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | 151 | static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) |
| 140 | { | 152 | { |
| 153 | struct variant_data *variant = host->variant; | ||
| 141 | unsigned int datactrl, timeout, irqmask; | 154 | unsigned int datactrl, timeout, irqmask; |
| 142 | unsigned long long clks; | 155 | unsigned long long clks; |
| 143 | void __iomem *base; | 156 | void __iomem *base; |
| @@ -173,7 +186,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
| 173 | * If we have less than a FIFOSIZE of bytes to transfer, | 186 | * If we have less than a FIFOSIZE of bytes to transfer, |
| 174 | * trigger a PIO interrupt as soon as any data is available. | 187 | * trigger a PIO interrupt as soon as any data is available. |
| 175 | */ | 188 | */ |
| 176 | if (host->size < MCI_FIFOSIZE) | 189 | if (host->size < variant->fifosize) |
| 177 | irqmask |= MCI_RXDATAAVLBLMASK; | 190 | irqmask |= MCI_RXDATAAVLBLMASK; |
| 178 | } else { | 191 | } else { |
| 179 | /* | 192 | /* |
| @@ -332,13 +345,15 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema | |||
| 332 | 345 | ||
| 333 | static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status) | 346 | static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status) |
| 334 | { | 347 | { |
| 348 | struct variant_data *variant = host->variant; | ||
| 335 | void __iomem *base = host->base; | 349 | void __iomem *base = host->base; |
| 336 | char *ptr = buffer; | 350 | char *ptr = buffer; |
| 337 | 351 | ||
| 338 | do { | 352 | do { |
| 339 | unsigned int count, maxcnt; | 353 | unsigned int count, maxcnt; |
| 340 | 354 | ||
| 341 | maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE; | 355 | maxcnt = status & MCI_TXFIFOEMPTY ? |
| 356 | variant->fifosize : variant->fifohalfsize; | ||
| 342 | count = min(remain, maxcnt); | 357 | count = min(remain, maxcnt); |
| 343 | 358 | ||
| 344 | writesl(base + MMCIFIFO, ptr, count >> 2); | 359 | writesl(base + MMCIFIFO, ptr, count >> 2); |
| @@ -362,6 +377,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | |||
| 362 | { | 377 | { |
| 363 | struct mmci_host *host = dev_id; | 378 | struct mmci_host *host = dev_id; |
| 364 | struct sg_mapping_iter *sg_miter = &host->sg_miter; | 379 | struct sg_mapping_iter *sg_miter = &host->sg_miter; |
| 380 | struct variant_data *variant = host->variant; | ||
| 365 | void __iomem *base = host->base; | 381 | void __iomem *base = host->base; |
| 366 | unsigned long flags; | 382 | unsigned long flags; |
| 367 | u32 status; | 383 | u32 status; |
| @@ -420,7 +436,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | |||
| 420 | * If we're nearing the end of the read, switch to | 436 | * If we're nearing the end of the read, switch to |
| 421 | * "any data available" mode. | 437 | * "any data available" mode. |
| 422 | */ | 438 | */ |
| 423 | if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE) | 439 | if (status & MCI_RXACTIVE && host->size < variant->fifosize) |
| 424 | writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); | 440 | writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); |
| 425 | 441 | ||
| 426 | /* | 442 | /* |
| @@ -564,18 +580,23 @@ static int mmci_get_ro(struct mmc_host *mmc) | |||
| 564 | if (host->gpio_wp == -ENOSYS) | 580 | if (host->gpio_wp == -ENOSYS) |
| 565 | return -ENOSYS; | 581 | return -ENOSYS; |
| 566 | 582 | ||
| 567 | return gpio_get_value(host->gpio_wp); | 583 | return gpio_get_value_cansleep(host->gpio_wp); |
| 568 | } | 584 | } |
| 569 | 585 | ||
| 570 | static int mmci_get_cd(struct mmc_host *mmc) | 586 | static int mmci_get_cd(struct mmc_host *mmc) |
| 571 | { | 587 | { |
| 572 | struct mmci_host *host = mmc_priv(mmc); | 588 | struct mmci_host *host = mmc_priv(mmc); |
| 589 | struct mmci_platform_data *plat = host->plat; | ||
| 573 | unsigned int status; | 590 | unsigned int status; |
| 574 | 591 | ||
| 575 | if (host->gpio_cd == -ENOSYS) | 592 | if (host->gpio_cd == -ENOSYS) { |
| 576 | status = host->plat->status(mmc_dev(host->mmc)); | 593 | if (!plat->status) |
| 577 | else | 594 | return 1; /* Assume always present */ |
| 578 | status = !gpio_get_value(host->gpio_cd); | 595 | |
| 596 | status = plat->status(mmc_dev(host->mmc)); | ||
| 597 | } else | ||
| 598 | status = !!gpio_get_value_cansleep(host->gpio_cd) | ||
| 599 | ^ plat->cd_invert; | ||
| 579 | 600 | ||
| 580 | /* | 601 | /* |
| 581 | * Use positive logic throughout - status is zero for no card, | 602 | * Use positive logic throughout - status is zero for no card, |
| @@ -584,6 +605,15 @@ static int mmci_get_cd(struct mmc_host *mmc) | |||
| 584 | return status; | 605 | return status; |
| 585 | } | 606 | } |
| 586 | 607 | ||
| 608 | static irqreturn_t mmci_cd_irq(int irq, void *dev_id) | ||
| 609 | { | ||
| 610 | struct mmci_host *host = dev_id; | ||
| 611 | |||
| 612 | mmc_detect_change(host->mmc, msecs_to_jiffies(500)); | ||
| 613 | |||
| 614 | return IRQ_HANDLED; | ||
| 615 | } | ||
| 616 | |||
| 587 | static const struct mmc_host_ops mmci_ops = { | 617 | static const struct mmc_host_ops mmci_ops = { |
| 588 | .request = mmci_request, | 618 | .request = mmci_request, |
| 589 | .set_ios = mmci_set_ios, | 619 | .set_ios = mmci_set_ios, |
| @@ -620,6 +650,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 620 | 650 | ||
| 621 | host->gpio_wp = -ENOSYS; | 651 | host->gpio_wp = -ENOSYS; |
| 622 | host->gpio_cd = -ENOSYS; | 652 | host->gpio_cd = -ENOSYS; |
| 653 | host->gpio_cd_irq = -1; | ||
| 623 | 654 | ||
| 624 | host->hw_designer = amba_manf(dev); | 655 | host->hw_designer = amba_manf(dev); |
| 625 | host->hw_revision = amba_rev(dev); | 656 | host->hw_revision = amba_rev(dev); |
| @@ -699,7 +730,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 699 | if (host->vcc == NULL) | 730 | if (host->vcc == NULL) |
| 700 | mmc->ocr_avail = plat->ocr_mask; | 731 | mmc->ocr_avail = plat->ocr_mask; |
| 701 | mmc->caps = plat->capabilities; | 732 | mmc->caps = plat->capabilities; |
| 702 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
| 703 | 733 | ||
| 704 | /* | 734 | /* |
| 705 | * We can do SGIO | 735 | * We can do SGIO |
| @@ -744,6 +774,12 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 744 | host->gpio_cd = plat->gpio_cd; | 774 | host->gpio_cd = plat->gpio_cd; |
| 745 | else if (ret != -ENOSYS) | 775 | else if (ret != -ENOSYS) |
| 746 | goto err_gpio_cd; | 776 | goto err_gpio_cd; |
| 777 | |||
| 778 | ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), | ||
| 779 | mmci_cd_irq, 0, | ||
| 780 | DRIVER_NAME " (cd)", host); | ||
| 781 | if (ret >= 0) | ||
| 782 | host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); | ||
| 747 | } | 783 | } |
| 748 | if (gpio_is_valid(plat->gpio_wp)) { | 784 | if (gpio_is_valid(plat->gpio_wp)) { |
| 749 | ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); | 785 | ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); |
| @@ -755,6 +791,10 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 755 | goto err_gpio_wp; | 791 | goto err_gpio_wp; |
| 756 | } | 792 | } |
| 757 | 793 | ||
| 794 | if ((host->plat->status || host->gpio_cd != -ENOSYS) | ||
| 795 | && host->gpio_cd_irq < 0) | ||
| 796 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
| 797 | |||
| 758 | ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); | 798 | ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); |
| 759 | if (ret) | 799 | if (ret) |
| 760 | goto unmap; | 800 | goto unmap; |
| @@ -781,6 +821,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 781 | if (host->gpio_wp != -ENOSYS) | 821 | if (host->gpio_wp != -ENOSYS) |
| 782 | gpio_free(host->gpio_wp); | 822 | gpio_free(host->gpio_wp); |
| 783 | err_gpio_wp: | 823 | err_gpio_wp: |
| 824 | if (host->gpio_cd_irq >= 0) | ||
| 825 | free_irq(host->gpio_cd_irq, host); | ||
| 784 | if (host->gpio_cd != -ENOSYS) | 826 | if (host->gpio_cd != -ENOSYS) |
| 785 | gpio_free(host->gpio_cd); | 827 | gpio_free(host->gpio_cd); |
| 786 | err_gpio_cd: | 828 | err_gpio_cd: |
| @@ -819,6 +861,8 @@ static int __devexit mmci_remove(struct amba_device *dev) | |||
| 819 | 861 | ||
| 820 | if (host->gpio_wp != -ENOSYS) | 862 | if (host->gpio_wp != -ENOSYS) |
| 821 | gpio_free(host->gpio_wp); | 863 | gpio_free(host->gpio_wp); |
| 864 | if (host->gpio_cd_irq >= 0) | ||
| 865 | free_irq(host->gpio_cd_irq, host); | ||
| 822 | if (host->gpio_cd != -ENOSYS) | 866 | if (host->gpio_cd != -ENOSYS) |
| 823 | gpio_free(host->gpio_cd); | 867 | gpio_free(host->gpio_cd); |
| 824 | 868 | ||
