diff options
Diffstat (limited to 'drivers/mmc/host/mxcmmc.c')
-rw-r--r-- | drivers/mmc/host/mxcmmc.c | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index bdd2cbb87cba..4428594261c5 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
34 | #include <linux/regulator/consumer.h> | ||
34 | 35 | ||
35 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
36 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
@@ -141,10 +142,49 @@ struct mxcmci_host { | |||
141 | 142 | ||
142 | struct work_struct datawork; | 143 | struct work_struct datawork; |
143 | spinlock_t lock; | 144 | spinlock_t lock; |
145 | |||
146 | struct regulator *vcc; | ||
144 | }; | 147 | }; |
145 | 148 | ||
146 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); | 149 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); |
147 | 150 | ||
151 | static inline void mxcmci_init_ocr(struct mxcmci_host *host) | ||
152 | { | ||
153 | host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc"); | ||
154 | |||
155 | if (IS_ERR(host->vcc)) { | ||
156 | host->vcc = NULL; | ||
157 | } else { | ||
158 | host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc); | ||
159 | if (host->pdata && host->pdata->ocr_avail) | ||
160 | dev_warn(mmc_dev(host->mmc), | ||
161 | "pdata->ocr_avail will not be used\n"); | ||
162 | } | ||
163 | |||
164 | if (host->vcc == NULL) { | ||
165 | /* fall-back to platform data */ | ||
166 | if (host->pdata && host->pdata->ocr_avail) | ||
167 | host->mmc->ocr_avail = host->pdata->ocr_avail; | ||
168 | else | ||
169 | host->mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static inline void mxcmci_set_power(struct mxcmci_host *host, | ||
174 | unsigned char power_mode, | ||
175 | unsigned int vdd) | ||
176 | { | ||
177 | if (host->vcc) { | ||
178 | if (power_mode == MMC_POWER_UP) | ||
179 | mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); | ||
180 | else if (power_mode == MMC_POWER_OFF) | ||
181 | mmc_regulator_set_ocr(host->mmc, host->vcc, 0); | ||
182 | } | ||
183 | |||
184 | if (host->pdata && host->pdata->setpower) | ||
185 | host->pdata->setpower(mmc_dev(host->mmc), vdd); | ||
186 | } | ||
187 | |||
148 | static inline int mxcmci_use_dma(struct mxcmci_host *host) | 188 | static inline int mxcmci_use_dma(struct mxcmci_host *host) |
149 | { | 189 | { |
150 | return host->do_dma; | 190 | return host->do_dma; |
@@ -680,9 +720,9 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
680 | host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; | 720 | host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; |
681 | 721 | ||
682 | if (host->power_mode != ios->power_mode) { | 722 | if (host->power_mode != ios->power_mode) { |
683 | if (host->pdata && host->pdata->setpower) | 723 | mxcmci_set_power(host, ios->power_mode, ios->vdd); |
684 | host->pdata->setpower(mmc_dev(mmc), ios->vdd); | ||
685 | host->power_mode = ios->power_mode; | 724 | host->power_mode = ios->power_mode; |
725 | |||
686 | if (ios->power_mode == MMC_POWER_ON) | 726 | if (ios->power_mode == MMC_POWER_ON) |
687 | host->cmdat |= CMD_DAT_CONT_INIT; | 727 | host->cmdat |= CMD_DAT_CONT_INIT; |
688 | } | 728 | } |
@@ -807,10 +847,7 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
807 | host->pdata = pdev->dev.platform_data; | 847 | host->pdata = pdev->dev.platform_data; |
808 | spin_lock_init(&host->lock); | 848 | spin_lock_init(&host->lock); |
809 | 849 | ||
810 | if (host->pdata && host->pdata->ocr_avail) | 850 | mxcmci_init_ocr(host); |
811 | mmc->ocr_avail = host->pdata->ocr_avail; | ||
812 | else | ||
813 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
814 | 851 | ||
815 | if (host->pdata && host->pdata->dat3_card_detect) | 852 | if (host->pdata && host->pdata->dat3_card_detect) |
816 | host->default_irq_mask = | 853 | host->default_irq_mask = |
@@ -915,6 +952,9 @@ static int mxcmci_remove(struct platform_device *pdev) | |||
915 | 952 | ||
916 | mmc_remove_host(mmc); | 953 | mmc_remove_host(mmc); |
917 | 954 | ||
955 | if (host->vcc) | ||
956 | regulator_put(host->vcc); | ||
957 | |||
918 | if (host->pdata && host->pdata->exit) | 958 | if (host->pdata && host->pdata->exit) |
919 | host->pdata->exit(&pdev->dev, mmc); | 959 | host->pdata->exit(&pdev->dev, mmc); |
920 | 960 | ||
@@ -927,7 +967,6 @@ static int mxcmci_remove(struct platform_device *pdev) | |||
927 | clk_put(host->clk); | 967 | clk_put(host->clk); |
928 | 968 | ||
929 | release_mem_region(host->res->start, resource_size(host->res)); | 969 | release_mem_region(host->res->start, resource_size(host->res)); |
930 | release_resource(host->res); | ||
931 | 970 | ||
932 | mmc_free_host(mmc); | 971 | mmc_free_host(mmc); |
933 | 972 | ||