diff options
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 150 |
1 files changed, 21 insertions, 129 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 7c71dcdcba8b..f84cfb01716d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/mmc/host.h> | 36 | #include <linux/mmc/host.h> |
37 | #include <linux/mmc/core.h> | 37 | #include <linux/mmc/core.h> |
38 | #include <linux/mmc/mmc.h> | 38 | #include <linux/mmc/mmc.h> |
39 | #include <linux/mmc/slot-gpio.h> | ||
39 | #include <linux/io.h> | 40 | #include <linux/io.h> |
40 | #include <linux/irq.h> | 41 | #include <linux/irq.h> |
41 | #include <linux/gpio.h> | 42 | #include <linux/gpio.h> |
@@ -251,55 +252,24 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); | |||
251 | static int omap_hsmmc_card_detect(struct device *dev) | 252 | static int omap_hsmmc_card_detect(struct device *dev) |
252 | { | 253 | { |
253 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 254 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
254 | struct omap_hsmmc_platform_data *mmc = host->pdata; | ||
255 | 255 | ||
256 | /* NOTE: assumes card detect signal is active-low */ | 256 | return mmc_gpio_get_cd(host->mmc); |
257 | return !gpio_get_value_cansleep(mmc->switch_pin); | ||
258 | } | 257 | } |
259 | 258 | ||
260 | static int omap_hsmmc_get_wp(struct device *dev) | 259 | static int omap_hsmmc_get_wp(struct device *dev) |
261 | { | 260 | { |
262 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 261 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
263 | struct omap_hsmmc_platform_data *mmc = host->pdata; | ||
264 | 262 | ||
265 | /* NOTE: assumes write protect signal is active-high */ | 263 | return mmc_gpio_get_ro(host->mmc); |
266 | return gpio_get_value_cansleep(mmc->gpio_wp); | ||
267 | } | 264 | } |
268 | 265 | ||
269 | static int omap_hsmmc_get_cover_state(struct device *dev) | 266 | static int omap_hsmmc_get_cover_state(struct device *dev) |
270 | { | 267 | { |
271 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 268 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
272 | struct omap_hsmmc_platform_data *mmc = host->pdata; | ||
273 | 269 | ||
274 | /* NOTE: assumes card detect signal is active-low */ | 270 | return mmc_gpio_get_cd(host->mmc); |
275 | return !gpio_get_value_cansleep(mmc->switch_pin); | ||
276 | } | 271 | } |
277 | 272 | ||
278 | #ifdef CONFIG_PM | ||
279 | |||
280 | static int omap_hsmmc_suspend_cdirq(struct device *dev) | ||
281 | { | ||
282 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
283 | |||
284 | disable_irq(host->card_detect_irq); | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int omap_hsmmc_resume_cdirq(struct device *dev) | ||
289 | { | ||
290 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
291 | |||
292 | enable_irq(host->card_detect_irq); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | #else | ||
297 | |||
298 | #define omap_hsmmc_suspend_cdirq NULL | ||
299 | #define omap_hsmmc_resume_cdirq NULL | ||
300 | |||
301 | #endif | ||
302 | |||
303 | #ifdef CONFIG_REGULATOR | 273 | #ifdef CONFIG_REGULATOR |
304 | 274 | ||
305 | static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd) | 275 | static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd) |
@@ -464,7 +434,10 @@ static inline int omap_hsmmc_have_reg(void) | |||
464 | 434 | ||
465 | #endif | 435 | #endif |
466 | 436 | ||
467 | static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, | 437 | static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id); |
438 | |||
439 | static int omap_hsmmc_gpio_init(struct mmc_host *mmc, | ||
440 | struct omap_hsmmc_host *host, | ||
468 | struct omap_hsmmc_platform_data *pdata) | 441 | struct omap_hsmmc_platform_data *pdata) |
469 | { | 442 | { |
470 | int ret; | 443 | int ret; |
@@ -477,46 +450,24 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, | |||
477 | host->card_detect = omap_hsmmc_card_detect; | 450 | host->card_detect = omap_hsmmc_card_detect; |
478 | host->card_detect_irq = | 451 | host->card_detect_irq = |
479 | gpio_to_irq(pdata->switch_pin); | 452 | gpio_to_irq(pdata->switch_pin); |
480 | ret = gpio_request(pdata->switch_pin, "mmc_cd"); | 453 | mmc_gpio_set_cd_isr(mmc, omap_hsmmc_detect); |
454 | ret = mmc_gpio_request_cd(mmc, pdata->switch_pin, 0); | ||
481 | if (ret) | 455 | if (ret) |
482 | return ret; | 456 | return ret; |
483 | ret = gpio_direction_input(pdata->switch_pin); | ||
484 | if (ret) | ||
485 | goto err_free_sp; | ||
486 | } else { | 457 | } else { |
487 | pdata->switch_pin = -EINVAL; | 458 | pdata->switch_pin = -EINVAL; |
488 | } | 459 | } |
489 | 460 | ||
490 | if (gpio_is_valid(pdata->gpio_wp)) { | 461 | if (gpio_is_valid(pdata->gpio_wp)) { |
491 | host->get_ro = omap_hsmmc_get_wp; | 462 | host->get_ro = omap_hsmmc_get_wp; |
492 | ret = gpio_request(pdata->gpio_wp, "mmc_wp"); | 463 | ret = mmc_gpio_request_ro(mmc, pdata->gpio_wp); |
493 | if (ret) | ||
494 | goto err_free_cd; | ||
495 | ret = gpio_direction_input(pdata->gpio_wp); | ||
496 | if (ret) | 464 | if (ret) |
497 | goto err_free_wp; | 465 | return ret; |
498 | } else { | 466 | } else { |
499 | pdata->gpio_wp = -EINVAL; | 467 | pdata->gpio_wp = -EINVAL; |
500 | } | 468 | } |
501 | 469 | ||
502 | return 0; | 470 | return 0; |
503 | |||
504 | err_free_wp: | ||
505 | gpio_free(pdata->gpio_wp); | ||
506 | err_free_cd: | ||
507 | if (gpio_is_valid(pdata->switch_pin)) | ||
508 | err_free_sp: | ||
509 | gpio_free(pdata->switch_pin); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | static void omap_hsmmc_gpio_free(struct omap_hsmmc_host *host, | ||
514 | struct omap_hsmmc_platform_data *pdata) | ||
515 | { | ||
516 | if (gpio_is_valid(pdata->gpio_wp)) | ||
517 | gpio_free(pdata->gpio_wp); | ||
518 | if (gpio_is_valid(pdata->switch_pin)) | ||
519 | gpio_free(pdata->switch_pin); | ||
520 | } | 471 | } |
521 | 472 | ||
522 | /* | 473 | /* |
@@ -1978,13 +1929,6 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
1978 | { | 1929 | { |
1979 | struct omap_hsmmc_platform_data *pdata; | 1930 | struct omap_hsmmc_platform_data *pdata; |
1980 | struct device_node *np = dev->of_node; | 1931 | struct device_node *np = dev->of_node; |
1981 | u32 bus_width, max_freq; | ||
1982 | int cd_gpio, wp_gpio; | ||
1983 | |||
1984 | cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
1985 | wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); | ||
1986 | if (cd_gpio == -EPROBE_DEFER || wp_gpio == -EPROBE_DEFER) | ||
1987 | return ERR_PTR(-EPROBE_DEFER); | ||
1988 | 1932 | ||
1989 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 1933 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
1990 | if (!pdata) | 1934 | if (!pdata) |
@@ -1993,34 +1937,20 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
1993 | if (of_find_property(np, "ti,dual-volt", NULL)) | 1937 | if (of_find_property(np, "ti,dual-volt", NULL)) |
1994 | pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; | 1938 | pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; |
1995 | 1939 | ||
1996 | pdata->switch_pin = cd_gpio; | 1940 | pdata->switch_pin = -EINVAL; |
1997 | pdata->gpio_wp = wp_gpio; | 1941 | pdata->gpio_wp = -EINVAL; |
1998 | 1942 | ||
1999 | if (of_find_property(np, "ti,non-removable", NULL)) { | 1943 | if (of_find_property(np, "ti,non-removable", NULL)) { |
2000 | pdata->nonremovable = true; | 1944 | pdata->nonremovable = true; |
2001 | pdata->no_regulator_off_init = true; | 1945 | pdata->no_regulator_off_init = true; |
2002 | } | 1946 | } |
2003 | of_property_read_u32(np, "bus-width", &bus_width); | ||
2004 | if (bus_width == 4) | ||
2005 | pdata->caps |= MMC_CAP_4_BIT_DATA; | ||
2006 | else if (bus_width == 8) | ||
2007 | pdata->caps |= MMC_CAP_8_BIT_DATA; | ||
2008 | 1947 | ||
2009 | if (of_find_property(np, "ti,needs-special-reset", NULL)) | 1948 | if (of_find_property(np, "ti,needs-special-reset", NULL)) |
2010 | pdata->features |= HSMMC_HAS_UPDATED_RESET; | 1949 | pdata->features |= HSMMC_HAS_UPDATED_RESET; |
2011 | 1950 | ||
2012 | if (!of_property_read_u32(np, "max-frequency", &max_freq)) | ||
2013 | pdata->max_freq = max_freq; | ||
2014 | |||
2015 | if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) | 1951 | if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) |
2016 | pdata->features |= HSMMC_HAS_HSPE_SUPPORT; | 1952 | pdata->features |= HSMMC_HAS_HSPE_SUPPORT; |
2017 | 1953 | ||
2018 | if (of_find_property(np, "keep-power-in-suspend", NULL)) | ||
2019 | pdata->pm_caps |= MMC_PM_KEEP_POWER; | ||
2020 | |||
2021 | if (of_find_property(np, "enable-sdio-wakeup", NULL)) | ||
2022 | pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | ||
2023 | |||
2024 | return pdata; | 1954 | return pdata; |
2025 | } | 1955 | } |
2026 | #else | 1956 | #else |
@@ -2078,6 +2008,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2078 | goto err; | 2008 | goto err; |
2079 | } | 2009 | } |
2080 | 2010 | ||
2011 | ret = mmc_of_parse(mmc); | ||
2012 | if (ret) | ||
2013 | goto err1; | ||
2014 | |||
2081 | host = mmc_priv(mmc); | 2015 | host = mmc_priv(mmc); |
2082 | host->mmc = mmc; | 2016 | host->mmc = mmc; |
2083 | host->pdata = pdata; | 2017 | host->pdata = pdata; |
@@ -2091,7 +2025,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2091 | host->next_data.cookie = 1; | 2025 | host->next_data.cookie = 1; |
2092 | host->pbias_enabled = 0; | 2026 | host->pbias_enabled = 0; |
2093 | 2027 | ||
2094 | ret = omap_hsmmc_gpio_init(host, pdata); | 2028 | ret = omap_hsmmc_gpio_init(mmc, host, pdata); |
2095 | if (ret) | 2029 | if (ret) |
2096 | goto err_gpio; | 2030 | goto err_gpio; |
2097 | 2031 | ||
@@ -2106,7 +2040,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2106 | 2040 | ||
2107 | if (pdata->max_freq > 0) | 2041 | if (pdata->max_freq > 0) |
2108 | mmc->f_max = pdata->max_freq; | 2042 | mmc->f_max = pdata->max_freq; |
2109 | else | 2043 | else if (mmc->f_max == 0) |
2110 | mmc->f_max = OMAP_MMC_MAX_CLOCK; | 2044 | mmc->f_max = OMAP_MMC_MAX_CLOCK; |
2111 | 2045 | ||
2112 | spin_lock_init(&host->irq_lock); | 2046 | spin_lock_init(&host->irq_lock); |
@@ -2160,7 +2094,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2160 | if (mmc_pdata(host)->nonremovable) | 2094 | if (mmc_pdata(host)->nonremovable) |
2161 | mmc->caps |= MMC_CAP_NONREMOVABLE; | 2095 | mmc->caps |= MMC_CAP_NONREMOVABLE; |
2162 | 2096 | ||
2163 | mmc->pm_caps = mmc_pdata(host)->pm_caps; | 2097 | mmc->pm_caps |= mmc_pdata(host)->pm_caps; |
2164 | 2098 | ||
2165 | omap_hsmmc_conf_bus_power(host); | 2099 | omap_hsmmc_conf_bus_power(host); |
2166 | 2100 | ||
@@ -2222,22 +2156,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2222 | 2156 | ||
2223 | mmc->ocr_avail = mmc_pdata(host)->ocr_mask; | 2157 | mmc->ocr_avail = mmc_pdata(host)->ocr_mask; |
2224 | 2158 | ||
2225 | /* Request IRQ for card detect */ | ||
2226 | if (host->card_detect_irq) { | ||
2227 | ret = devm_request_threaded_irq(&pdev->dev, | ||
2228 | host->card_detect_irq, | ||
2229 | NULL, omap_hsmmc_detect, | ||
2230 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
2231 | mmc_hostname(mmc), host); | ||
2232 | if (ret) { | ||
2233 | dev_err(mmc_dev(host->mmc), | ||
2234 | "Unable to grab MMC CD IRQ\n"); | ||
2235 | goto err_irq_cd; | ||
2236 | } | ||
2237 | host->suspend = omap_hsmmc_suspend_cdirq; | ||
2238 | host->resume = omap_hsmmc_resume_cdirq; | ||
2239 | } | ||
2240 | |||
2241 | omap_hsmmc_disable_irq(host); | 2159 | omap_hsmmc_disable_irq(host); |
2242 | 2160 | ||
2243 | /* | 2161 | /* |
@@ -2276,7 +2194,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2276 | 2194 | ||
2277 | err_slot_name: | 2195 | err_slot_name: |
2278 | mmc_remove_host(mmc); | 2196 | mmc_remove_host(mmc); |
2279 | err_irq_cd: | ||
2280 | if (host->use_reg) | 2197 | if (host->use_reg) |
2281 | omap_hsmmc_reg_put(host); | 2198 | omap_hsmmc_reg_put(host); |
2282 | err_irq: | 2199 | err_irq: |
@@ -2289,7 +2206,6 @@ err_irq: | |||
2289 | if (host->dbclk) | 2206 | if (host->dbclk) |
2290 | clk_disable_unprepare(host->dbclk); | 2207 | clk_disable_unprepare(host->dbclk); |
2291 | err1: | 2208 | err1: |
2292 | omap_hsmmc_gpio_free(host, pdata); | ||
2293 | err_gpio: | 2209 | err_gpio: |
2294 | mmc_free_host(mmc); | 2210 | mmc_free_host(mmc); |
2295 | err: | 2211 | err: |
@@ -2315,32 +2231,12 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
2315 | if (host->dbclk) | 2231 | if (host->dbclk) |
2316 | clk_disable_unprepare(host->dbclk); | 2232 | clk_disable_unprepare(host->dbclk); |
2317 | 2233 | ||
2318 | omap_hsmmc_gpio_free(host, host->pdata); | ||
2319 | mmc_free_host(host->mmc); | 2234 | mmc_free_host(host->mmc); |
2320 | 2235 | ||
2321 | return 0; | 2236 | return 0; |
2322 | } | 2237 | } |
2323 | 2238 | ||
2324 | #ifdef CONFIG_PM | 2239 | #ifdef CONFIG_PM |
2325 | static int omap_hsmmc_prepare(struct device *dev) | ||
2326 | { | ||
2327 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
2328 | |||
2329 | if (host->suspend) | ||
2330 | return host->suspend(dev); | ||
2331 | |||
2332 | return 0; | ||
2333 | } | ||
2334 | |||
2335 | static void omap_hsmmc_complete(struct device *dev) | ||
2336 | { | ||
2337 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
2338 | |||
2339 | if (host->resume) | ||
2340 | host->resume(dev); | ||
2341 | |||
2342 | } | ||
2343 | |||
2344 | static int omap_hsmmc_suspend(struct device *dev) | 2240 | static int omap_hsmmc_suspend(struct device *dev) |
2345 | { | 2241 | { |
2346 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 2242 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
@@ -2398,8 +2294,6 @@ static int omap_hsmmc_resume(struct device *dev) | |||
2398 | } | 2294 | } |
2399 | 2295 | ||
2400 | #else | 2296 | #else |
2401 | #define omap_hsmmc_prepare NULL | ||
2402 | #define omap_hsmmc_complete NULL | ||
2403 | #define omap_hsmmc_suspend NULL | 2297 | #define omap_hsmmc_suspend NULL |
2404 | #define omap_hsmmc_resume NULL | 2298 | #define omap_hsmmc_resume NULL |
2405 | #endif | 2299 | #endif |
@@ -2484,8 +2378,6 @@ static int omap_hsmmc_runtime_resume(struct device *dev) | |||
2484 | static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { | 2378 | static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { |
2485 | .suspend = omap_hsmmc_suspend, | 2379 | .suspend = omap_hsmmc_suspend, |
2486 | .resume = omap_hsmmc_resume, | 2380 | .resume = omap_hsmmc_resume, |
2487 | .prepare = omap_hsmmc_prepare, | ||
2488 | .complete = omap_hsmmc_complete, | ||
2489 | .runtime_suspend = omap_hsmmc_runtime_suspend, | 2381 | .runtime_suspend = omap_hsmmc_runtime_suspend, |
2490 | .runtime_resume = omap_hsmmc_runtime_resume, | 2382 | .runtime_resume = omap_hsmmc_runtime_resume, |
2491 | }; | 2383 | }; |