aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/omap_hsmmc.c
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@nokia.com>2010-02-15 13:03:34 -0500
committerTony Lindgren <tony@atomide.com>2010-02-15 13:03:34 -0500
commitdb0fefc5119e2cfaa8f57565331e0abe47f0801e (patch)
tree367d86d4784322e3b8156f187f68667680ce497a /drivers/mmc/host/omap_hsmmc.c
parent88c8460ac32283e2a25e36e4670ff5ab02f3b521 (diff)
omap_hsmmc: Move gpio and regulator control from board file
This patch moves the setup code for GPIO's and Voltage Regulators from the board file mmc-twl4030.c to the driver omap_hsmmc.c. PBIAS and other system control configuration remains in the board file. Moving GPIO code to the driver makes the board initialisation code independent of when GPIO's are defined. That makes the board initialisation now entirely independent of its original twl4030 roots. Moving Voltage Regulator code to the driver allows for further development of regulator support in the core MMC code. It also permits the MMC core to be compiled as a module, because the board code no longer calls MMC core functions. Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r--drivers/mmc/host/omap_hsmmc.c352
1 files changed, 339 insertions, 13 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4b232251890..2c5e15d9f86 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -30,6 +30,8 @@
30#include <linux/mmc/core.h> 30#include <linux/mmc/core.h>
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/semaphore.h> 32#include <linux/semaphore.h>
33#include <linux/gpio.h>
34#include <linux/regulator/consumer.h>
33#include <plat/dma.h> 35#include <plat/dma.h>
34#include <mach/hardware.h> 36#include <mach/hardware.h>
35#include <plat/board.h> 37#include <plat/board.h>
@@ -146,6 +148,15 @@ struct omap_hsmmc_host {
146 struct clk *fclk; 148 struct clk *fclk;
147 struct clk *iclk; 149 struct clk *iclk;
148 struct clk *dbclk; 150 struct clk *dbclk;
151 /*
152 * vcc == configured supply
153 * vcc_aux == optional
154 * - MMC1, supply for DAT4..DAT7
155 * - MMC2/MMC2, external level shifter voltage supply, for
156 * chip (SDIO, eMMC, etc) or transceiver (MMC2 only)
157 */
158 struct regulator *vcc;
159 struct regulator *vcc_aux;
149 struct semaphore sem; 160 struct semaphore sem;
150 struct work_struct mmc_carddetect_work; 161 struct work_struct mmc_carddetect_work;
151 void __iomem *base; 162 void __iomem *base;
@@ -171,10 +182,308 @@ struct omap_hsmmc_host {
171 int vdd; 182 int vdd;
172 int protect_card; 183 int protect_card;
173 int reqs_blocked; 184 int reqs_blocked;
185 int use_reg;
174 186
175 struct omap_mmc_platform_data *pdata; 187 struct omap_mmc_platform_data *pdata;
176}; 188};
177 189
190static int omap_hsmmc_card_detect(struct device *dev, int slot)
191{
192 struct omap_mmc_platform_data *mmc = dev->platform_data;
193
194 /* NOTE: assumes card detect signal is active-low */
195 return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
196}
197
198static int omap_hsmmc_get_wp(struct device *dev, int slot)
199{
200 struct omap_mmc_platform_data *mmc = dev->platform_data;
201
202 /* NOTE: assumes write protect signal is active-high */
203 return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
204}
205
206static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
207{
208 struct omap_mmc_platform_data *mmc = dev->platform_data;
209
210 /* NOTE: assumes card detect signal is active-low */
211 return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
212}
213
214#ifdef CONFIG_PM
215
216static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
217{
218 struct omap_mmc_platform_data *mmc = dev->platform_data;
219
220 disable_irq(mmc->slots[0].card_detect_irq);
221 return 0;
222}
223
224static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
225{
226 struct omap_mmc_platform_data *mmc = dev->platform_data;
227
228 enable_irq(mmc->slots[0].card_detect_irq);
229 return 0;
230}
231
232#else
233
234#define omap_hsmmc_suspend_cdirq NULL
235#define omap_hsmmc_resume_cdirq NULL
236
237#endif
238
239static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on,
240 int vdd)
241{
242 struct omap_hsmmc_host *host =
243 platform_get_drvdata(to_platform_device(dev));
244 int ret;
245
246 if (mmc_slot(host).before_set_reg)
247 mmc_slot(host).before_set_reg(dev, slot, power_on, vdd);
248
249 if (power_on)
250 ret = mmc_regulator_set_ocr(host->vcc, vdd);
251 else
252 ret = mmc_regulator_set_ocr(host->vcc, 0);
253
254 if (mmc_slot(host).after_set_reg)
255 mmc_slot(host).after_set_reg(dev, slot, power_on, vdd);
256
257 return ret;
258}
259
260static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on,
261 int vdd)
262{
263 struct omap_hsmmc_host *host =
264 platform_get_drvdata(to_platform_device(dev));
265 int ret = 0;
266
267 /*
268 * If we don't see a Vcc regulator, assume it's a fixed
269 * voltage always-on regulator.
270 */
271 if (!host->vcc)
272 return 0;
273
274 if (mmc_slot(host).before_set_reg)
275 mmc_slot(host).before_set_reg(dev, slot, power_on, vdd);
276
277 /*
278 * Assume Vcc regulator is used only to power the card ... OMAP
279 * VDDS is used to power the pins, optionally with a transceiver to
280 * support cards using voltages other than VDDS (1.8V nominal). When a
281 * transceiver is used, DAT3..7 are muxed as transceiver control pins.
282 *
283 * In some cases this regulator won't support enable/disable;
284 * e.g. it's a fixed rail for a WLAN chip.
285 *
286 * In other cases vcc_aux switches interface power. Example, for
287 * eMMC cards it represents VccQ. Sometimes transceivers or SDIO
288 * chips/cards need an interface voltage rail too.
289 */
290 if (power_on) {
291 ret = mmc_regulator_set_ocr(host->vcc, vdd);
292 /* Enable interface voltage rail, if needed */
293 if (ret == 0 && host->vcc_aux) {
294 ret = regulator_enable(host->vcc_aux);
295 if (ret < 0)
296 ret = mmc_regulator_set_ocr(host->vcc, 0);
297 }
298 } else {
299 if (host->vcc_aux) {
300 ret = regulator_is_enabled(host->vcc_aux);
301 if (ret > 0)
302 ret = regulator_disable(host->vcc_aux);
303 }
304 if (ret == 0)
305 ret = mmc_regulator_set_ocr(host->vcc, 0);
306 }
307
308 if (mmc_slot(host).after_set_reg)
309 mmc_slot(host).after_set_reg(dev, slot, power_on, vdd);
310
311 return ret;
312}
313
314static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep,
315 int vdd, int cardsleep)
316{
317 struct omap_hsmmc_host *host =
318 platform_get_drvdata(to_platform_device(dev));
319 int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
320
321 return regulator_set_mode(host->vcc, mode);
322}
323
324static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep,
325 int vdd, int cardsleep)
326{
327 struct omap_hsmmc_host *host =
328 platform_get_drvdata(to_platform_device(dev));
329 int err, mode;
330
331 /*
332 * If we don't see a Vcc regulator, assume it's a fixed
333 * voltage always-on regulator.
334 */
335 if (!host->vcc)
336 return 0;
337
338 mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
339
340 if (!host->vcc_aux)
341 return regulator_set_mode(host->vcc, mode);
342
343 if (cardsleep) {
344 /* VCC can be turned off if card is asleep */
345 if (sleep)
346 err = mmc_regulator_set_ocr(host->vcc, 0);
347 else
348 err = mmc_regulator_set_ocr(host->vcc, vdd);
349 } else
350 err = regulator_set_mode(host->vcc, mode);
351 if (err)
352 return err;
353 return regulator_set_mode(host->vcc_aux, mode);
354}
355
356static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
357{
358 int ret;
359
360 if (gpio_is_valid(pdata->slots[0].switch_pin)) {
361 pdata->suspend = omap_hsmmc_suspend_cdirq;
362 pdata->resume = omap_hsmmc_resume_cdirq;
363 if (pdata->slots[0].cover)
364 pdata->slots[0].get_cover_state =
365 omap_hsmmc_get_cover_state;
366 else
367 pdata->slots[0].card_detect = omap_hsmmc_card_detect;
368 pdata->slots[0].card_detect_irq =
369 gpio_to_irq(pdata->slots[0].switch_pin);
370 ret = gpio_request(pdata->slots[0].switch_pin, "mmc_cd");
371 if (ret)
372 return ret;
373 ret = gpio_direction_input(pdata->slots[0].switch_pin);
374 if (ret)
375 goto err_free_sp;
376 } else
377 pdata->slots[0].switch_pin = -EINVAL;
378
379 if (gpio_is_valid(pdata->slots[0].gpio_wp)) {
380 pdata->slots[0].get_ro = omap_hsmmc_get_wp;
381 ret = gpio_request(pdata->slots[0].gpio_wp, "mmc_wp");
382 if (ret)
383 goto err_free_cd;
384 ret = gpio_direction_input(pdata->slots[0].gpio_wp);
385 if (ret)
386 goto err_free_wp;
387 } else
388 pdata->slots[0].gpio_wp = -EINVAL;
389
390 return 0;
391
392err_free_wp:
393 gpio_free(pdata->slots[0].gpio_wp);
394err_free_cd:
395 if (gpio_is_valid(pdata->slots[0].switch_pin))
396err_free_sp:
397 gpio_free(pdata->slots[0].switch_pin);
398 return ret;
399}
400
401static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
402{
403 if (gpio_is_valid(pdata->slots[0].gpio_wp))
404 gpio_free(pdata->slots[0].gpio_wp);
405 if (gpio_is_valid(pdata->slots[0].switch_pin))
406 gpio_free(pdata->slots[0].switch_pin);
407}
408
409static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
410{
411 struct regulator *reg;
412 int ret = 0;
413
414 switch (host->id) {
415 case OMAP_MMC1_DEVID:
416 /* On-chip level shifting via PBIAS0/PBIAS1 */
417 mmc_slot(host).set_power = omap_hsmmc_1_set_power;
418 mmc_slot(host).set_sleep = omap_hsmmc_1_set_sleep;
419 break;
420 case OMAP_MMC2_DEVID:
421 case OMAP_MMC3_DEVID:
422 /* Off-chip level shifting, or none */
423 mmc_slot(host).set_power = omap_hsmmc_23_set_power;
424 mmc_slot(host).set_sleep = omap_hsmmc_23_set_sleep;
425 break;
426 default:
427 pr_err("MMC%d configuration not supported!\n", host->id);
428 return -EINVAL;
429 }
430
431 reg = regulator_get(host->dev, "vmmc");
432 if (IS_ERR(reg)) {
433 dev_dbg(host->dev, "vmmc regulator missing\n");
434 /*
435 * HACK: until fixed.c regulator is usable,
436 * we don't require a main regulator
437 * for MMC2 or MMC3
438 */
439 if (host->id == OMAP_MMC1_DEVID) {
440 ret = PTR_ERR(reg);
441 goto err;
442 }
443 } else {
444 host->vcc = reg;
445 mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg);
446
447 /* Allow an aux regulator */
448 reg = regulator_get(host->dev, "vmmc_aux");
449 host->vcc_aux = IS_ERR(reg) ? NULL : reg;
450
451 /*
452 * UGLY HACK: workaround regulator framework bugs.
453 * When the bootloader leaves a supply active, it's
454 * initialized with zero usecount ... and we can't
455 * disable it without first enabling it. Until the
456 * framework is fixed, we need a workaround like this
457 * (which is safe for MMC, but not in general).
458 */
459 if (regulator_is_enabled(host->vcc) > 0) {
460 regulator_enable(host->vcc);
461 regulator_disable(host->vcc);
462 }
463 if (host->vcc_aux) {
464 if (regulator_is_enabled(reg) > 0) {
465 regulator_enable(reg);
466 regulator_disable(reg);
467 }
468 }
469 }
470
471 return 0;
472
473err:
474 mmc_slot(host).set_power = NULL;
475 mmc_slot(host).set_sleep = NULL;
476 return ret;
477}
478
479static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host)
480{
481 regulator_put(host->vcc);
482 regulator_put(host->vcc_aux);
483 mmc_slot(host).set_power = NULL;
484 mmc_slot(host).set_sleep = NULL;
485}
486
178/* 487/*
179 * Stop clock to the card 488 * Stop clock to the card
180 */ 489 */
@@ -835,7 +1144,7 @@ static void omap_hsmmc_detect(struct work_struct *work)
835 sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); 1144 sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
836 1145
837 if (slot->card_detect) 1146 if (slot->card_detect)
838 carddetect = slot->card_detect(slot->card_detect_irq); 1147 carddetect = slot->card_detect(host->dev, host->slot_id);
839 else { 1148 else {
840 omap_hsmmc_protect_card(host); 1149 omap_hsmmc_protect_card(host);
841 carddetect = -ENOSYS; 1150 carddetect = -ENOSYS;
@@ -1242,7 +1551,7 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc)
1242 1551
1243 if (!mmc_slot(host).card_detect) 1552 if (!mmc_slot(host).card_detect)
1244 return -ENOSYS; 1553 return -ENOSYS;
1245 return mmc_slot(host).card_detect(mmc_slot(host).card_detect_irq); 1554 return mmc_slot(host).card_detect(host->dev, host->slot_id);
1246} 1555}
1247 1556
1248static int omap_hsmmc_get_ro(struct mmc_host *mmc) 1557static int omap_hsmmc_get_ro(struct mmc_host *mmc)
@@ -1616,7 +1925,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
1616 struct mmc_host *mmc; 1925 struct mmc_host *mmc;
1617 struct omap_hsmmc_host *host = NULL; 1926 struct omap_hsmmc_host *host = NULL;
1618 struct resource *res; 1927 struct resource *res;
1619 int ret = 0, irq; 1928 int ret, irq;
1620 1929
1621 if (pdata == NULL) { 1930 if (pdata == NULL) {
1622 dev_err(&pdev->dev, "Platform Data is missing\n"); 1931 dev_err(&pdev->dev, "Platform Data is missing\n");
@@ -1638,10 +1947,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
1638 if (res == NULL) 1947 if (res == NULL)
1639 return -EBUSY; 1948 return -EBUSY;
1640 1949
1950 ret = omap_hsmmc_gpio_init(pdata);
1951 if (ret)
1952 goto err;
1953
1641 mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev); 1954 mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev);
1642 if (!mmc) { 1955 if (!mmc) {
1643 ret = -ENOMEM; 1956 ret = -ENOMEM;
1644 goto err; 1957 goto err_alloc;
1645 } 1958 }
1646 1959
1647 host = mmc_priv(mmc); 1960 host = mmc_priv(mmc);
@@ -1781,7 +2094,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
1781 goto err_irq; 2094 goto err_irq;
1782 } 2095 }
1783 2096
1784 /* initialize power supplies, gpios, etc */
1785 if (pdata->init != NULL) { 2097 if (pdata->init != NULL) {
1786 if (pdata->init(&pdev->dev) != 0) { 2098 if (pdata->init(&pdev->dev) != 0) {
1787 dev_dbg(mmc_dev(host->mmc), 2099 dev_dbg(mmc_dev(host->mmc),
@@ -1789,6 +2101,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
1789 goto err_irq_cd_init; 2101 goto err_irq_cd_init;
1790 } 2102 }
1791 } 2103 }
2104
2105 if (!mmc_slot(host).set_power) {
2106 ret = omap_hsmmc_reg_get(host);
2107 if (ret)
2108 goto err_reg;
2109 host->use_reg = 1;
2110 }
2111
1792 mmc->ocr_avail = mmc_slot(host).ocr_mask; 2112 mmc->ocr_avail = mmc_slot(host).ocr_mask;
1793 2113
1794 /* Request IRQ for card detect */ 2114 /* Request IRQ for card detect */
@@ -1823,19 +2143,22 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
1823 ret = device_create_file(&mmc->class_dev, 2143 ret = device_create_file(&mmc->class_dev,
1824 &dev_attr_cover_switch); 2144 &dev_attr_cover_switch);
1825 if (ret < 0) 2145 if (ret < 0)
1826 goto err_cover_switch; 2146 goto err_slot_name;
1827 } 2147 }
1828 2148
1829 omap_hsmmc_debugfs(mmc); 2149 omap_hsmmc_debugfs(mmc);
1830 2150
1831 return 0; 2151 return 0;
1832 2152
1833err_cover_switch:
1834 device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
1835err_slot_name: 2153err_slot_name:
1836 mmc_remove_host(mmc); 2154 mmc_remove_host(mmc);
1837err_irq_cd:
1838 free_irq(mmc_slot(host).card_detect_irq, host); 2155 free_irq(mmc_slot(host).card_detect_irq, host);
2156err_irq_cd:
2157 if (host->use_reg)
2158 omap_hsmmc_reg_put(host);
2159err_reg:
2160 if (host->pdata->cleanup)
2161 host->pdata->cleanup(&pdev->dev);
1839err_irq_cd_init: 2162err_irq_cd_init:
1840 free_irq(host->irq, host); 2163 free_irq(host->irq, host);
1841err_irq: 2164err_irq:
@@ -1847,14 +2170,14 @@ err_irq:
1847 clk_disable(host->dbclk); 2170 clk_disable(host->dbclk);
1848 clk_put(host->dbclk); 2171 clk_put(host->dbclk);
1849 } 2172 }
1850
1851err1: 2173err1:
1852 iounmap(host->base); 2174 iounmap(host->base);
2175 platform_set_drvdata(pdev, NULL);
2176 mmc_free_host(mmc);
2177err_alloc:
2178 omap_hsmmc_gpio_free(pdata);
1853err: 2179err:
1854 dev_dbg(mmc_dev(host->mmc), "Probe Failed\n");
1855 release_mem_region(res->start, res->end - res->start + 1); 2180 release_mem_region(res->start, res->end - res->start + 1);
1856 if (host)
1857 mmc_free_host(mmc);
1858 return ret; 2181 return ret;
1859} 2182}
1860 2183
@@ -1866,6 +2189,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
1866 if (host) { 2189 if (host) {
1867 mmc_host_enable(host->mmc); 2190 mmc_host_enable(host->mmc);
1868 mmc_remove_host(host->mmc); 2191 mmc_remove_host(host->mmc);
2192 if (host->use_reg)
2193 omap_hsmmc_reg_put(host);
1869 if (host->pdata->cleanup) 2194 if (host->pdata->cleanup)
1870 host->pdata->cleanup(&pdev->dev); 2195 host->pdata->cleanup(&pdev->dev);
1871 free_irq(host->irq, host); 2196 free_irq(host->irq, host);
@@ -1884,6 +2209,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
1884 2209
1885 mmc_free_host(host->mmc); 2210 mmc_free_host(host->mmc);
1886 iounmap(host->base); 2211 iounmap(host->base);
2212 omap_hsmmc_gpio_free(pdev->dev.platform_data);
1887 } 2213 }
1888 2214
1889 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2215 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);