diff options
Diffstat (limited to 'drivers/mmc')
48 files changed, 1562 insertions, 2378 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c69afb5e264e..2c25271f8c41 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -2230,7 +2230,7 @@ static int mmc_blk_alloc_part(struct mmc_card *card, | |||
2230 | part_md->part_type = part_type; | 2230 | part_md->part_type = part_type; |
2231 | list_add(&part_md->part, &md->part); | 2231 | list_add(&part_md->part, &md->part); |
2232 | 2232 | ||
2233 | string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2, | 2233 | string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2, |
2234 | cap_str, sizeof(cap_str)); | 2234 | cap_str, sizeof(cap_str)); |
2235 | pr_info("%s: %s %s partition %u %s\n", | 2235 | pr_info("%s: %s %s partition %u %s\n", |
2236 | part_md->disk->disk_name, mmc_card_id(card), | 2236 | part_md->disk->disk_name, mmc_card_id(card), |
@@ -2418,9 +2418,8 @@ static const struct mmc_fixup blk_fixups[] = | |||
2418 | END_FIXUP | 2418 | END_FIXUP |
2419 | }; | 2419 | }; |
2420 | 2420 | ||
2421 | static int mmc_blk_probe(struct device *dev) | 2421 | static int mmc_blk_probe(struct mmc_card *card) |
2422 | { | 2422 | { |
2423 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
2424 | struct mmc_blk_data *md, *part_md; | 2423 | struct mmc_blk_data *md, *part_md; |
2425 | char cap_str[10]; | 2424 | char cap_str[10]; |
2426 | 2425 | ||
@@ -2436,7 +2435,7 @@ static int mmc_blk_probe(struct device *dev) | |||
2436 | if (IS_ERR(md)) | 2435 | if (IS_ERR(md)) |
2437 | return PTR_ERR(md); | 2436 | return PTR_ERR(md); |
2438 | 2437 | ||
2439 | string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, | 2438 | string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2, |
2440 | cap_str, sizeof(cap_str)); | 2439 | cap_str, sizeof(cap_str)); |
2441 | pr_info("%s: %s %s %s %s\n", | 2440 | pr_info("%s: %s %s %s %s\n", |
2442 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), | 2441 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), |
@@ -2445,7 +2444,7 @@ static int mmc_blk_probe(struct device *dev) | |||
2445 | if (mmc_blk_alloc_parts(card, md)) | 2444 | if (mmc_blk_alloc_parts(card, md)) |
2446 | goto out; | 2445 | goto out; |
2447 | 2446 | ||
2448 | dev_set_drvdata(dev, md); | 2447 | dev_set_drvdata(&card->dev, md); |
2449 | 2448 | ||
2450 | if (mmc_add_disk(md)) | 2449 | if (mmc_add_disk(md)) |
2451 | goto out; | 2450 | goto out; |
@@ -2475,10 +2474,9 @@ static int mmc_blk_probe(struct device *dev) | |||
2475 | return 0; | 2474 | return 0; |
2476 | } | 2475 | } |
2477 | 2476 | ||
2478 | static int mmc_blk_remove(struct device *dev) | 2477 | static void mmc_blk_remove(struct mmc_card *card) |
2479 | { | 2478 | { |
2480 | struct mmc_card *card = mmc_dev_to_card(dev); | 2479 | struct mmc_blk_data *md = dev_get_drvdata(&card->dev); |
2481 | struct mmc_blk_data *md = dev_get_drvdata(dev); | ||
2482 | 2480 | ||
2483 | mmc_blk_remove_parts(card, md); | 2481 | mmc_blk_remove_parts(card, md); |
2484 | pm_runtime_get_sync(&card->dev); | 2482 | pm_runtime_get_sync(&card->dev); |
@@ -2489,15 +2487,13 @@ static int mmc_blk_remove(struct device *dev) | |||
2489 | pm_runtime_disable(&card->dev); | 2487 | pm_runtime_disable(&card->dev); |
2490 | pm_runtime_put_noidle(&card->dev); | 2488 | pm_runtime_put_noidle(&card->dev); |
2491 | mmc_blk_remove_req(md); | 2489 | mmc_blk_remove_req(md); |
2492 | dev_set_drvdata(dev, NULL); | 2490 | dev_set_drvdata(&card->dev, NULL); |
2493 | |||
2494 | return 0; | ||
2495 | } | 2491 | } |
2496 | 2492 | ||
2497 | static int _mmc_blk_suspend(struct device *dev) | 2493 | static int _mmc_blk_suspend(struct mmc_card *card) |
2498 | { | 2494 | { |
2499 | struct mmc_blk_data *part_md; | 2495 | struct mmc_blk_data *part_md; |
2500 | struct mmc_blk_data *md = dev_get_drvdata(dev); | 2496 | struct mmc_blk_data *md = dev_get_drvdata(&card->dev); |
2501 | 2497 | ||
2502 | if (md) { | 2498 | if (md) { |
2503 | mmc_queue_suspend(&md->queue); | 2499 | mmc_queue_suspend(&md->queue); |
@@ -2508,15 +2504,17 @@ static int _mmc_blk_suspend(struct device *dev) | |||
2508 | return 0; | 2504 | return 0; |
2509 | } | 2505 | } |
2510 | 2506 | ||
2511 | static void mmc_blk_shutdown(struct device *dev) | 2507 | static void mmc_blk_shutdown(struct mmc_card *card) |
2512 | { | 2508 | { |
2513 | _mmc_blk_suspend(dev); | 2509 | _mmc_blk_suspend(card); |
2514 | } | 2510 | } |
2515 | 2511 | ||
2516 | #ifdef CONFIG_PM_SLEEP | 2512 | #ifdef CONFIG_PM_SLEEP |
2517 | static int mmc_blk_suspend(struct device *dev) | 2513 | static int mmc_blk_suspend(struct device *dev) |
2518 | { | 2514 | { |
2519 | return _mmc_blk_suspend(dev); | 2515 | struct mmc_card *card = mmc_dev_to_card(dev); |
2516 | |||
2517 | return _mmc_blk_suspend(card); | ||
2520 | } | 2518 | } |
2521 | 2519 | ||
2522 | static int mmc_blk_resume(struct device *dev) | 2520 | static int mmc_blk_resume(struct device *dev) |
@@ -2541,9 +2539,11 @@ static int mmc_blk_resume(struct device *dev) | |||
2541 | 2539 | ||
2542 | static SIMPLE_DEV_PM_OPS(mmc_blk_pm_ops, mmc_blk_suspend, mmc_blk_resume); | 2540 | static SIMPLE_DEV_PM_OPS(mmc_blk_pm_ops, mmc_blk_suspend, mmc_blk_resume); |
2543 | 2541 | ||
2544 | static struct device_driver mmc_driver = { | 2542 | static struct mmc_driver mmc_driver = { |
2545 | .name = "mmcblk", | 2543 | .drv = { |
2546 | .pm = &mmc_blk_pm_ops, | 2544 | .name = "mmcblk", |
2545 | .pm = &mmc_blk_pm_ops, | ||
2546 | }, | ||
2547 | .probe = mmc_blk_probe, | 2547 | .probe = mmc_blk_probe, |
2548 | .remove = mmc_blk_remove, | 2548 | .remove = mmc_blk_remove, |
2549 | .shutdown = mmc_blk_shutdown, | 2549 | .shutdown = mmc_blk_shutdown, |
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 7dac4695163b..53b741398b93 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/mmc/host.h> | 14 | #include <linux/mmc/host.h> |
15 | #include <linux/mmc/mmc.h> | 15 | #include <linux/mmc/mmc.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/device.h> | ||
18 | 17 | ||
19 | #include <linux/scatterlist.h> | 18 | #include <linux/scatterlist.h> |
20 | #include <linux/swap.h> /* For nr_free_buffer_pages() */ | 19 | #include <linux/swap.h> /* For nr_free_buffer_pages() */ |
@@ -2996,9 +2995,8 @@ err: | |||
2996 | return ret; | 2995 | return ret; |
2997 | } | 2996 | } |
2998 | 2997 | ||
2999 | static int mmc_test_probe(struct device *dev) | 2998 | static int mmc_test_probe(struct mmc_card *card) |
3000 | { | 2999 | { |
3001 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
3002 | int ret; | 3000 | int ret; |
3003 | 3001 | ||
3004 | if (!mmc_card_mmc(card) && !mmc_card_sd(card)) | 3002 | if (!mmc_card_mmc(card) && !mmc_card_sd(card)) |
@@ -3013,22 +3011,20 @@ static int mmc_test_probe(struct device *dev) | |||
3013 | return 0; | 3011 | return 0; |
3014 | } | 3012 | } |
3015 | 3013 | ||
3016 | static int mmc_test_remove(struct device *dev) | 3014 | static void mmc_test_remove(struct mmc_card *card) |
3017 | { | 3015 | { |
3018 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
3019 | |||
3020 | mmc_test_free_result(card); | 3016 | mmc_test_free_result(card); |
3021 | mmc_test_free_dbgfs_file(card); | 3017 | mmc_test_free_dbgfs_file(card); |
3022 | |||
3023 | return 0; | ||
3024 | } | 3018 | } |
3025 | 3019 | ||
3026 | static void mmc_test_shutdown(struct device *dev) | 3020 | static void mmc_test_shutdown(struct mmc_card *card) |
3027 | { | 3021 | { |
3028 | } | 3022 | } |
3029 | 3023 | ||
3030 | static struct device_driver mmc_driver = { | 3024 | static struct mmc_driver mmc_driver = { |
3031 | .name = "mmc_test", | 3025 | .drv = { |
3026 | .name = "mmc_test", | ||
3027 | }, | ||
3032 | .probe = mmc_test_probe, | 3028 | .probe = mmc_test_probe, |
3033 | .remove = mmc_test_remove, | 3029 | .remove = mmc_test_remove, |
3034 | .shutdown = mmc_test_shutdown, | 3030 | .shutdown = mmc_test_shutdown, |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index c5ef10065a4a..972ff844cf5a 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include "sdio_cis.h" | 26 | #include "sdio_cis.h" |
27 | #include "bus.h" | 27 | #include "bus.h" |
28 | 28 | ||
29 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) | ||
30 | |||
29 | static ssize_t type_show(struct device *dev, | 31 | static ssize_t type_show(struct device *dev, |
30 | struct device_attribute *attr, char *buf) | 32 | struct device_attribute *attr, char *buf) |
31 | { | 33 | { |
@@ -105,14 +107,33 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
105 | return retval; | 107 | return retval; |
106 | } | 108 | } |
107 | 109 | ||
110 | static int mmc_bus_probe(struct device *dev) | ||
111 | { | ||
112 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
113 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
114 | |||
115 | return drv->probe(card); | ||
116 | } | ||
117 | |||
118 | static int mmc_bus_remove(struct device *dev) | ||
119 | { | ||
120 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
121 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
122 | |||
123 | drv->remove(card); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
108 | static void mmc_bus_shutdown(struct device *dev) | 128 | static void mmc_bus_shutdown(struct device *dev) |
109 | { | 129 | { |
130 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
110 | struct mmc_card *card = mmc_dev_to_card(dev); | 131 | struct mmc_card *card = mmc_dev_to_card(dev); |
111 | struct mmc_host *host = card->host; | 132 | struct mmc_host *host = card->host; |
112 | int ret; | 133 | int ret; |
113 | 134 | ||
114 | if (dev->driver && dev->driver->shutdown) | 135 | if (dev->driver && drv->shutdown) |
115 | dev->driver->shutdown(dev); | 136 | drv->shutdown(card); |
116 | 137 | ||
117 | if (host->bus_ops->shutdown) { | 138 | if (host->bus_ops->shutdown) { |
118 | ret = host->bus_ops->shutdown(host); | 139 | ret = host->bus_ops->shutdown(host); |
@@ -181,6 +202,8 @@ static struct bus_type mmc_bus_type = { | |||
181 | .dev_groups = mmc_dev_groups, | 202 | .dev_groups = mmc_dev_groups, |
182 | .match = mmc_bus_match, | 203 | .match = mmc_bus_match, |
183 | .uevent = mmc_bus_uevent, | 204 | .uevent = mmc_bus_uevent, |
205 | .probe = mmc_bus_probe, | ||
206 | .remove = mmc_bus_remove, | ||
184 | .shutdown = mmc_bus_shutdown, | 207 | .shutdown = mmc_bus_shutdown, |
185 | .pm = &mmc_bus_pm_ops, | 208 | .pm = &mmc_bus_pm_ops, |
186 | }; | 209 | }; |
@@ -199,22 +222,24 @@ void mmc_unregister_bus(void) | |||
199 | * mmc_register_driver - register a media driver | 222 | * mmc_register_driver - register a media driver |
200 | * @drv: MMC media driver | 223 | * @drv: MMC media driver |
201 | */ | 224 | */ |
202 | int mmc_register_driver(struct device_driver *drv) | 225 | int mmc_register_driver(struct mmc_driver *drv) |
203 | { | 226 | { |
204 | drv->bus = &mmc_bus_type; | 227 | drv->drv.bus = &mmc_bus_type; |
205 | return driver_register(drv); | 228 | return driver_register(&drv->drv); |
206 | } | 229 | } |
230 | |||
207 | EXPORT_SYMBOL(mmc_register_driver); | 231 | EXPORT_SYMBOL(mmc_register_driver); |
208 | 232 | ||
209 | /** | 233 | /** |
210 | * mmc_unregister_driver - unregister a media driver | 234 | * mmc_unregister_driver - unregister a media driver |
211 | * @drv: MMC media driver | 235 | * @drv: MMC media driver |
212 | */ | 236 | */ |
213 | void mmc_unregister_driver(struct device_driver *drv) | 237 | void mmc_unregister_driver(struct mmc_driver *drv) |
214 | { | 238 | { |
215 | drv->bus = &mmc_bus_type; | 239 | drv->drv.bus = &mmc_bus_type; |
216 | driver_unregister(drv); | 240 | driver_unregister(&drv->drv); |
217 | } | 241 | } |
242 | |||
218 | EXPORT_SYMBOL(mmc_unregister_driver); | 243 | EXPORT_SYMBOL(mmc_unregister_driver); |
219 | 244 | ||
220 | static void mmc_release_card(struct device *dev) | 245 | static void mmc_release_card(struct device *dev) |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 23f10f72e5f3..c296bc098fe2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -897,6 +897,7 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) | |||
897 | DECLARE_WAITQUEUE(wait, current); | 897 | DECLARE_WAITQUEUE(wait, current); |
898 | unsigned long flags; | 898 | unsigned long flags; |
899 | int stop; | 899 | int stop; |
900 | bool pm = false; | ||
900 | 901 | ||
901 | might_sleep(); | 902 | might_sleep(); |
902 | 903 | ||
@@ -916,15 +917,18 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) | |||
916 | host->claimed = 1; | 917 | host->claimed = 1; |
917 | host->claimer = current; | 918 | host->claimer = current; |
918 | host->claim_cnt += 1; | 919 | host->claim_cnt += 1; |
920 | if (host->claim_cnt == 1) | ||
921 | pm = true; | ||
919 | } else | 922 | } else |
920 | wake_up(&host->wq); | 923 | wake_up(&host->wq); |
921 | spin_unlock_irqrestore(&host->lock, flags); | 924 | spin_unlock_irqrestore(&host->lock, flags); |
922 | remove_wait_queue(&host->wq, &wait); | 925 | remove_wait_queue(&host->wq, &wait); |
923 | if (host->ops->enable && !stop && host->claim_cnt == 1) | 926 | |
924 | host->ops->enable(host); | 927 | if (pm) |
928 | pm_runtime_get_sync(mmc_dev(host)); | ||
929 | |||
925 | return stop; | 930 | return stop; |
926 | } | 931 | } |
927 | |||
928 | EXPORT_SYMBOL(__mmc_claim_host); | 932 | EXPORT_SYMBOL(__mmc_claim_host); |
929 | 933 | ||
930 | /** | 934 | /** |
@@ -940,9 +944,6 @@ void mmc_release_host(struct mmc_host *host) | |||
940 | 944 | ||
941 | WARN_ON(!host->claimed); | 945 | WARN_ON(!host->claimed); |
942 | 946 | ||
943 | if (host->ops->disable && host->claim_cnt == 1) | ||
944 | host->ops->disable(host); | ||
945 | |||
946 | spin_lock_irqsave(&host->lock, flags); | 947 | spin_lock_irqsave(&host->lock, flags); |
947 | if (--host->claim_cnt) { | 948 | if (--host->claim_cnt) { |
948 | /* Release for nested claim */ | 949 | /* Release for nested claim */ |
@@ -952,6 +953,8 @@ void mmc_release_host(struct mmc_host *host) | |||
952 | host->claimer = NULL; | 953 | host->claimer = NULL; |
953 | spin_unlock_irqrestore(&host->lock, flags); | 954 | spin_unlock_irqrestore(&host->lock, flags); |
954 | wake_up(&host->wq); | 955 | wake_up(&host->wq); |
956 | pm_runtime_mark_last_busy(mmc_dev(host)); | ||
957 | pm_runtime_put_autosuspend(mmc_dev(host)); | ||
955 | } | 958 | } |
956 | } | 959 | } |
957 | EXPORT_SYMBOL(mmc_release_host); | 960 | EXPORT_SYMBOL(mmc_release_host); |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 1d41e8541f38..f36c76f8b232 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/of.h> | ||
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
15 | #include <linux/stat.h> | 16 | #include <linux/stat.h> |
16 | #include <linux/pm_runtime.h> | 17 | #include <linux/pm_runtime.h> |
@@ -336,6 +337,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
336 | { | 337 | { |
337 | int err = 0, idx; | 338 | int err = 0, idx; |
338 | unsigned int part_size; | 339 | unsigned int part_size; |
340 | struct device_node *np; | ||
341 | bool broken_hpi = false; | ||
339 | 342 | ||
340 | /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ | 343 | /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ |
341 | card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; | 344 | card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; |
@@ -349,6 +352,11 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
349 | } | 352 | } |
350 | } | 353 | } |
351 | 354 | ||
355 | np = mmc_of_find_child_device(card->host, 0); | ||
356 | if (np && of_device_is_compatible(np, "mmc-card")) | ||
357 | broken_hpi = of_property_read_bool(np, "broken-hpi"); | ||
358 | of_node_put(np); | ||
359 | |||
352 | /* | 360 | /* |
353 | * The EXT_CSD format is meant to be forward compatible. As long | 361 | * The EXT_CSD format is meant to be forward compatible. As long |
354 | * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV | 362 | * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV |
@@ -494,7 +502,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
494 | } | 502 | } |
495 | 503 | ||
496 | /* check whether the eMMC card supports HPI */ | 504 | /* check whether the eMMC card supports HPI */ |
497 | if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) { | 505 | if (!broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) { |
498 | card->ext_csd.hpi = 1; | 506 | card->ext_csd.hpi = 1; |
499 | if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) | 507 | if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) |
500 | card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; | 508 | card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; |
@@ -1750,7 +1758,7 @@ static int mmc_runtime_suspend(struct mmc_host *host) | |||
1750 | 1758 | ||
1751 | err = _mmc_suspend(host, true); | 1759 | err = _mmc_suspend(host, true); |
1752 | if (err) | 1760 | if (err) |
1753 | pr_err("%s: error %d doing aggessive suspend\n", | 1761 | pr_err("%s: error %d doing aggressive suspend\n", |
1754 | mmc_hostname(host), err); | 1762 | mmc_hostname(host), err); |
1755 | 1763 | ||
1756 | return err; | 1764 | return err; |
@@ -1768,7 +1776,7 @@ static int mmc_runtime_resume(struct mmc_host *host) | |||
1768 | 1776 | ||
1769 | err = _mmc_resume(host); | 1777 | err = _mmc_resume(host); |
1770 | if (err) | 1778 | if (err) |
1771 | pr_err("%s: error %d doing aggessive resume\n", | 1779 | pr_err("%s: error %d doing aggressive resume\n", |
1772 | mmc_hostname(host), err); | 1780 | mmc_hostname(host), err); |
1773 | 1781 | ||
1774 | return 0; | 1782 | return 0; |
diff --git a/drivers/mmc/core/pwrseq.c b/drivers/mmc/core/pwrseq.c index 862356123d78..4c1d1757dbf9 100644 --- a/drivers/mmc/core/pwrseq.c +++ b/drivers/mmc/core/pwrseq.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | struct mmc_pwrseq_match { | 20 | struct mmc_pwrseq_match { |
21 | const char *compatible; | 21 | const char *compatible; |
22 | int (*alloc)(struct mmc_host *host, struct device *dev); | 22 | struct mmc_pwrseq *(*alloc)(struct mmc_host *host, struct device *dev); |
23 | }; | 23 | }; |
24 | 24 | ||
25 | static struct mmc_pwrseq_match pwrseq_match[] = { | 25 | static struct mmc_pwrseq_match pwrseq_match[] = { |
@@ -52,6 +52,7 @@ int mmc_pwrseq_alloc(struct mmc_host *host) | |||
52 | struct platform_device *pdev; | 52 | struct platform_device *pdev; |
53 | struct device_node *np; | 53 | struct device_node *np; |
54 | struct mmc_pwrseq_match *match; | 54 | struct mmc_pwrseq_match *match; |
55 | struct mmc_pwrseq *pwrseq; | ||
55 | int ret = 0; | 56 | int ret = 0; |
56 | 57 | ||
57 | np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0); | 58 | np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0); |
@@ -70,9 +71,14 @@ int mmc_pwrseq_alloc(struct mmc_host *host) | |||
70 | goto err; | 71 | goto err; |
71 | } | 72 | } |
72 | 73 | ||
73 | ret = match->alloc(host, &pdev->dev); | 74 | pwrseq = match->alloc(host, &pdev->dev); |
74 | if (!ret) | 75 | if (IS_ERR(pwrseq)) { |
75 | dev_info(host->parent, "allocated mmc-pwrseq\n"); | 76 | ret = PTR_ERR(pwrseq); |
77 | goto err; | ||
78 | } | ||
79 | |||
80 | host->pwrseq = pwrseq; | ||
81 | dev_info(host->parent, "allocated mmc-pwrseq\n"); | ||
76 | 82 | ||
77 | err: | 83 | err: |
78 | of_node_put(np); | 84 | of_node_put(np); |
@@ -109,4 +115,6 @@ void mmc_pwrseq_free(struct mmc_host *host) | |||
109 | 115 | ||
110 | if (pwrseq && pwrseq->ops && pwrseq->ops->free) | 116 | if (pwrseq && pwrseq->ops && pwrseq->ops->free) |
111 | pwrseq->ops->free(host); | 117 | pwrseq->ops->free(host); |
118 | |||
119 | host->pwrseq = NULL; | ||
112 | } | 120 | } |
diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h index aba3409e8d6e..096da48c6a7e 100644 --- a/drivers/mmc/core/pwrseq.h +++ b/drivers/mmc/core/pwrseq.h | |||
@@ -27,8 +27,10 @@ void mmc_pwrseq_post_power_on(struct mmc_host *host); | |||
27 | void mmc_pwrseq_power_off(struct mmc_host *host); | 27 | void mmc_pwrseq_power_off(struct mmc_host *host); |
28 | void mmc_pwrseq_free(struct mmc_host *host); | 28 | void mmc_pwrseq_free(struct mmc_host *host); |
29 | 29 | ||
30 | int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev); | 30 | struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, |
31 | int mmc_pwrseq_emmc_alloc(struct mmc_host *host, struct device *dev); | 31 | struct device *dev); |
32 | struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, | ||
33 | struct device *dev); | ||
32 | 34 | ||
33 | #else | 35 | #else |
34 | 36 | ||
diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c index a2d545904fbf..9d6d2fb21796 100644 --- a/drivers/mmc/core/pwrseq_emmc.c +++ b/drivers/mmc/core/pwrseq_emmc.c | |||
@@ -49,7 +49,6 @@ static void mmc_pwrseq_emmc_free(struct mmc_host *host) | |||
49 | unregister_restart_handler(&pwrseq->reset_nb); | 49 | unregister_restart_handler(&pwrseq->reset_nb); |
50 | gpiod_put(pwrseq->reset_gpio); | 50 | gpiod_put(pwrseq->reset_gpio); |
51 | kfree(pwrseq); | 51 | kfree(pwrseq); |
52 | host->pwrseq = NULL; | ||
53 | } | 52 | } |
54 | 53 | ||
55 | static struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { | 54 | static struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { |
@@ -67,14 +66,15 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, | |||
67 | return NOTIFY_DONE; | 66 | return NOTIFY_DONE; |
68 | } | 67 | } |
69 | 68 | ||
70 | int mmc_pwrseq_emmc_alloc(struct mmc_host *host, struct device *dev) | 69 | struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, |
70 | struct device *dev) | ||
71 | { | 71 | { |
72 | struct mmc_pwrseq_emmc *pwrseq; | 72 | struct mmc_pwrseq_emmc *pwrseq; |
73 | int ret = 0; | 73 | int ret = 0; |
74 | 74 | ||
75 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_emmc), GFP_KERNEL); | 75 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_emmc), GFP_KERNEL); |
76 | if (!pwrseq) | 76 | if (!pwrseq) |
77 | return -ENOMEM; | 77 | return ERR_PTR(-ENOMEM); |
78 | 78 | ||
79 | pwrseq->reset_gpio = gpiod_get_index(dev, "reset", 0, GPIOD_OUT_LOW); | 79 | pwrseq->reset_gpio = gpiod_get_index(dev, "reset", 0, GPIOD_OUT_LOW); |
80 | if (IS_ERR(pwrseq->reset_gpio)) { | 80 | if (IS_ERR(pwrseq->reset_gpio)) { |
@@ -92,10 +92,9 @@ int mmc_pwrseq_emmc_alloc(struct mmc_host *host, struct device *dev) | |||
92 | register_restart_handler(&pwrseq->reset_nb); | 92 | register_restart_handler(&pwrseq->reset_nb); |
93 | 93 | ||
94 | pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; | 94 | pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; |
95 | host->pwrseq = &pwrseq->pwrseq; | ||
96 | 95 | ||
97 | return 0; | 96 | return &pwrseq->pwrseq; |
98 | free: | 97 | free: |
99 | kfree(pwrseq); | 98 | kfree(pwrseq); |
100 | return ret; | 99 | return ERR_PTR(ret); |
101 | } | 100 | } |
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c index e9f1d8d84613..0b14b83a53d6 100644 --- a/drivers/mmc/core/pwrseq_simple.c +++ b/drivers/mmc/core/pwrseq_simple.c | |||
@@ -85,7 +85,6 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host) | |||
85 | clk_put(pwrseq->ext_clk); | 85 | clk_put(pwrseq->ext_clk); |
86 | 86 | ||
87 | kfree(pwrseq); | 87 | kfree(pwrseq); |
88 | host->pwrseq = NULL; | ||
89 | } | 88 | } |
90 | 89 | ||
91 | static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { | 90 | static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { |
@@ -95,7 +94,8 @@ static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { | |||
95 | .free = mmc_pwrseq_simple_free, | 94 | .free = mmc_pwrseq_simple_free, |
96 | }; | 95 | }; |
97 | 96 | ||
98 | int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) | 97 | struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, |
98 | struct device *dev) | ||
99 | { | 99 | { |
100 | struct mmc_pwrseq_simple *pwrseq; | 100 | struct mmc_pwrseq_simple *pwrseq; |
101 | int i, nr_gpios, ret = 0; | 101 | int i, nr_gpios, ret = 0; |
@@ -107,7 +107,7 @@ int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) | |||
107 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple) + nr_gpios * | 107 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple) + nr_gpios * |
108 | sizeof(struct gpio_desc *), GFP_KERNEL); | 108 | sizeof(struct gpio_desc *), GFP_KERNEL); |
109 | if (!pwrseq) | 109 | if (!pwrseq) |
110 | return -ENOMEM; | 110 | return ERR_PTR(-ENOMEM); |
111 | 111 | ||
112 | pwrseq->ext_clk = clk_get(dev, "ext_clock"); | 112 | pwrseq->ext_clk = clk_get(dev, "ext_clock"); |
113 | if (IS_ERR(pwrseq->ext_clk) && | 113 | if (IS_ERR(pwrseq->ext_clk) && |
@@ -124,7 +124,7 @@ int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) | |||
124 | PTR_ERR(pwrseq->reset_gpios[i]) != -ENOSYS) { | 124 | PTR_ERR(pwrseq->reset_gpios[i]) != -ENOSYS) { |
125 | ret = PTR_ERR(pwrseq->reset_gpios[i]); | 125 | ret = PTR_ERR(pwrseq->reset_gpios[i]); |
126 | 126 | ||
127 | while (--i) | 127 | while (i--) |
128 | gpiod_put(pwrseq->reset_gpios[i]); | 128 | gpiod_put(pwrseq->reset_gpios[i]); |
129 | 129 | ||
130 | goto clk_put; | 130 | goto clk_put; |
@@ -133,13 +133,12 @@ int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) | |||
133 | 133 | ||
134 | pwrseq->nr_gpios = nr_gpios; | 134 | pwrseq->nr_gpios = nr_gpios; |
135 | pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; | 135 | pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; |
136 | host->pwrseq = &pwrseq->pwrseq; | ||
137 | 136 | ||
138 | return 0; | 137 | return &pwrseq->pwrseq; |
139 | clk_put: | 138 | clk_put: |
140 | if (!IS_ERR(pwrseq->ext_clk)) | 139 | if (!IS_ERR(pwrseq->ext_clk)) |
141 | clk_put(pwrseq->ext_clk); | 140 | clk_put(pwrseq->ext_clk); |
142 | free: | 141 | free: |
143 | kfree(pwrseq); | 142 | kfree(pwrseq); |
144 | return ret; | 143 | return ERR_PTR(ret); |
145 | } | 144 | } |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index ad4d43eae99d..31a9ef256d06 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -1157,7 +1157,7 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host) | |||
1157 | 1157 | ||
1158 | err = _mmc_sd_suspend(host); | 1158 | err = _mmc_sd_suspend(host); |
1159 | if (err) | 1159 | if (err) |
1160 | pr_err("%s: error %d doing aggessive suspend\n", | 1160 | pr_err("%s: error %d doing aggressive suspend\n", |
1161 | mmc_hostname(host), err); | 1161 | mmc_hostname(host), err); |
1162 | 1162 | ||
1163 | return err; | 1163 | return err; |
@@ -1175,7 +1175,7 @@ static int mmc_sd_runtime_resume(struct mmc_host *host) | |||
1175 | 1175 | ||
1176 | err = _mmc_sd_resume(host); | 1176 | err = _mmc_sd_resume(host); |
1177 | if (err) | 1177 | if (err) |
1178 | pr_err("%s: error %d doing aggessive resume\n", | 1178 | pr_err("%s: error %d doing aggressive resume\n", |
1179 | mmc_hostname(host), err); | 1179 | mmc_hostname(host), err); |
1180 | 1180 | ||
1181 | return 0; | 1181 | return 0; |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index ce6cc47206b0..5bc6c7dbbd60 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -293,19 +293,22 @@ static int sdio_enable_4bit_bus(struct mmc_card *card) | |||
293 | int err; | 293 | int err; |
294 | 294 | ||
295 | if (card->type == MMC_TYPE_SDIO) | 295 | if (card->type == MMC_TYPE_SDIO) |
296 | return sdio_enable_wide(card); | 296 | err = sdio_enable_wide(card); |
297 | 297 | else if ((card->host->caps & MMC_CAP_4_BIT_DATA) && | |
298 | if ((card->host->caps & MMC_CAP_4_BIT_DATA) && | 298 | (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { |
299 | (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { | ||
300 | err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); | 299 | err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); |
301 | if (err) | 300 | if (err) |
302 | return err; | 301 | return err; |
302 | err = sdio_enable_wide(card); | ||
303 | if (err <= 0) | ||
304 | mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); | ||
303 | } else | 305 | } else |
304 | return 0; | 306 | return 0; |
305 | 307 | ||
306 | err = sdio_enable_wide(card); | 308 | if (err > 0) { |
307 | if (err <= 0) | 309 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); |
308 | mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); | 310 | err = 0; |
311 | } | ||
309 | 312 | ||
310 | return err; | 313 | return err; |
311 | } | 314 | } |
@@ -547,13 +550,8 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) | |||
547 | /* | 550 | /* |
548 | * Switch to wider bus (if supported). | 551 | * Switch to wider bus (if supported). |
549 | */ | 552 | */ |
550 | if (card->host->caps & MMC_CAP_4_BIT_DATA) { | 553 | if (card->host->caps & MMC_CAP_4_BIT_DATA) |
551 | err = sdio_enable_4bit_bus(card); | 554 | err = sdio_enable_4bit_bus(card); |
552 | if (err > 0) { | ||
553 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | ||
554 | err = 0; | ||
555 | } | ||
556 | } | ||
557 | 555 | ||
558 | /* Set the driver strength for the card */ | 556 | /* Set the driver strength for the card */ |
559 | sdio_select_driver_type(card); | 557 | sdio_select_driver_type(card); |
@@ -803,9 +801,7 @@ try_again: | |||
803 | * Switch to wider bus (if supported). | 801 | * Switch to wider bus (if supported). |
804 | */ | 802 | */ |
805 | err = sdio_enable_4bit_bus(card); | 803 | err = sdio_enable_4bit_bus(card); |
806 | if (err > 0) | 804 | if (err) |
807 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | ||
808 | else if (err) | ||
809 | goto remove; | 805 | goto remove; |
810 | } | 806 | } |
811 | finish: | 807 | finish: |
@@ -983,10 +979,6 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
983 | } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { | 979 | } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { |
984 | /* We may have switched to 1-bit mode during suspend */ | 980 | /* We may have switched to 1-bit mode during suspend */ |
985 | err = sdio_enable_4bit_bus(host->card); | 981 | err = sdio_enable_4bit_bus(host->card); |
986 | if (err > 0) { | ||
987 | mmc_set_bus_width(host, MMC_BUS_WIDTH_4); | ||
988 | err = 0; | ||
989 | } | ||
990 | } | 982 | } |
991 | 983 | ||
992 | if (!err && host->sdio_irqs) { | 984 | if (!err && host->sdio_irqs) { |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 61ac63a3776a..b1f837e749fe 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -132,7 +132,7 @@ config MMC_SDHCI_OF_ARASAN | |||
132 | config MMC_SDHCI_OF_ESDHC | 132 | config MMC_SDHCI_OF_ESDHC |
133 | tristate "SDHCI OF support for the Freescale eSDHC controller" | 133 | tristate "SDHCI OF support for the Freescale eSDHC controller" |
134 | depends on MMC_SDHCI_PLTFM | 134 | depends on MMC_SDHCI_PLTFM |
135 | depends on PPC_OF | 135 | depends on PPC |
136 | select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER | 136 | select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER |
137 | help | 137 | help |
138 | This selects the Freescale eSDHC controller support. | 138 | This selects the Freescale eSDHC controller support. |
@@ -144,7 +144,7 @@ config MMC_SDHCI_OF_ESDHC | |||
144 | config MMC_SDHCI_OF_HLWD | 144 | config MMC_SDHCI_OF_HLWD |
145 | tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers" | 145 | tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers" |
146 | depends on MMC_SDHCI_PLTFM | 146 | depends on MMC_SDHCI_PLTFM |
147 | depends on PPC_OF | 147 | depends on PPC |
148 | select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER | 148 | select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER |
149 | help | 149 | help |
150 | This selects the Secure Digital Host Controller Interface (SDHCI) | 150 | This selects the Secure Digital Host Controller Interface (SDHCI) |
@@ -230,7 +230,7 @@ config MMC_SDHCI_PXAV3 | |||
230 | tristate "Marvell MMP2 SD Host Controller support (PXAV3)" | 230 | tristate "Marvell MMP2 SD Host Controller support (PXAV3)" |
231 | depends on CLKDEV_LOOKUP | 231 | depends on CLKDEV_LOOKUP |
232 | depends on MMC_SDHCI_PLTFM | 232 | depends on MMC_SDHCI_PLTFM |
233 | depends on ARCH_MMP || COMPILE_TEST | 233 | depends on ARCH_BERLIN || ARCH_MMP || ARCH_MVEBU || COMPILE_TEST |
234 | default CPU_MMP2 | 234 | default CPU_MMP2 |
235 | help | 235 | help |
236 | This selects the Marvell(R) PXAV3 SD Host Controller. | 236 | This selects the Marvell(R) PXAV3 SD Host Controller. |
@@ -255,6 +255,7 @@ config MMC_SDHCI_PXAV2 | |||
255 | config MMC_SDHCI_SPEAR | 255 | config MMC_SDHCI_SPEAR |
256 | tristate "SDHCI support on ST SPEAr platform" | 256 | tristate "SDHCI support on ST SPEAr platform" |
257 | depends on MMC_SDHCI && PLAT_SPEAR | 257 | depends on MMC_SDHCI && PLAT_SPEAR |
258 | depends on OF | ||
258 | help | 259 | help |
259 | This selects the Secure Digital Host Controller Interface (SDHCI) | 260 | This selects the Secure Digital Host Controller Interface (SDHCI) |
260 | often referrered to as the HSMMC block in some of the ST SPEAR range | 261 | often referrered to as the HSMMC block in some of the ST SPEAR range |
@@ -307,6 +308,20 @@ config MMC_SDHCI_F_SDH30 | |||
307 | 308 | ||
308 | If unsure, say N. | 309 | If unsure, say N. |
309 | 310 | ||
311 | config MMC_SDHCI_IPROC | ||
312 | tristate "SDHCI platform support for the iProc SD/MMC Controller" | ||
313 | depends on ARCH_BCM_IPROC || COMPILE_TEST | ||
314 | depends on MMC_SDHCI_PLTFM | ||
315 | default ARCH_BCM_IPROC | ||
316 | select MMC_SDHCI_IO_ACCESSORS | ||
317 | help | ||
318 | This selects the iProc SD/MMC controller. | ||
319 | |||
320 | If you have an IPROC platform with SD or MMC devices, | ||
321 | say Y or M here. | ||
322 | |||
323 | If unsure, say N. | ||
324 | |||
310 | config MMC_MOXART | 325 | config MMC_MOXART |
311 | tristate "MOXART SD/MMC Host Controller support" | 326 | tristate "MOXART SD/MMC Host Controller support" |
312 | depends on ARCH_MOXART && MMC | 327 | depends on ARCH_MOXART && MMC |
@@ -393,14 +408,6 @@ config MMC_SDHCI_MSM | |||
393 | 408 | ||
394 | If unsure, say N. | 409 | If unsure, say N. |
395 | 410 | ||
396 | config MMC_MSM | ||
397 | tristate "Qualcomm SDCC Controller Support" | ||
398 | depends on MMC && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50) | ||
399 | help | ||
400 | This provides support for the SD/MMC cell found in the | ||
401 | MSM and QSD SOCs from Qualcomm. The controller also has | ||
402 | support for SDIO devices. | ||
403 | |||
404 | config MMC_MXC | 411 | config MMC_MXC |
405 | tristate "Freescale i.MX21/27/31 or MPC512x Multimedia Card support" | 412 | tristate "Freescale i.MX21/27/31 or MPC512x Multimedia Card support" |
406 | depends on ARCH_MXC || PPC_MPC512x | 413 | depends on ARCH_MXC || PPC_MPC512x |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 6a7cfe0de332..e3ab5b968651 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -24,7 +24,6 @@ obj-$(CONFIG_MMC_OMAP) += omap.o | |||
24 | obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o | 24 | obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o |
25 | obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o | 25 | obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o |
26 | obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o | 26 | obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o |
27 | obj-$(CONFIG_MMC_MSM) += msm_sdcc.o | ||
28 | obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o | 27 | obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o |
29 | obj-$(CONFIG_MMC_DAVINCI) += davinci_mmc.o | 28 | obj-$(CONFIG_MMC_DAVINCI) += davinci_mmc.o |
30 | obj-$(CONFIG_MMC_GOLDFISH) += android-goldfish.o | 29 | obj-$(CONFIG_MMC_GOLDFISH) += android-goldfish.o |
@@ -71,6 +70,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o | |||
71 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o | 70 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o |
72 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o | 71 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o |
73 | obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o | 72 | obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o |
73 | obj-$(CONFIG_MMC_SDHCI_IPROC) += sdhci-iproc.o | ||
74 | obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o | 74 | obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o |
75 | obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o | 75 | obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o |
76 | 76 | ||
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index c97001e15227..0aa44e679df4 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h | |||
@@ -135,10 +135,17 @@ | |||
135 | #define ATMCI_REGS_SIZE 0x100 | 135 | #define ATMCI_REGS_SIZE 0x100 |
136 | 136 | ||
137 | /* Register access macros */ | 137 | /* Register access macros */ |
138 | #define atmci_readl(port,reg) \ | 138 | #ifdef CONFIG_AVR32 |
139 | #define atmci_readl(port, reg) \ | ||
139 | __raw_readl((port)->regs + reg) | 140 | __raw_readl((port)->regs + reg) |
140 | #define atmci_writel(port,reg,value) \ | 141 | #define atmci_writel(port, reg, value) \ |
141 | __raw_writel((value), (port)->regs + reg) | 142 | __raw_writel((value), (port)->regs + reg) |
143 | #else | ||
144 | #define atmci_readl(port, reg) \ | ||
145 | readl_relaxed((port)->regs + reg) | ||
146 | #define atmci_writel(port, reg, value) \ | ||
147 | writel_relaxed((value), (port)->regs + reg) | ||
148 | #endif | ||
142 | 149 | ||
143 | /* On AVR chips the Peripheral DMA Controller is not connected to MCI. */ | 150 | /* On AVR chips the Peripheral DMA Controller is not connected to MCI. */ |
144 | #ifdef CONFIG_AVR32 | 151 | #ifdef CONFIG_AVR32 |
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index fe32948c6114..e761eb1b1441 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c | |||
@@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data { | |||
40 | u8 ciu_div; | 40 | u8 ciu_div; |
41 | u32 sdr_timing; | 41 | u32 sdr_timing; |
42 | u32 ddr_timing; | 42 | u32 ddr_timing; |
43 | u32 hs400_timing; | ||
44 | u32 tuned_sample; | ||
43 | u32 cur_speed; | 45 | u32 cur_speed; |
46 | u32 dqs_delay; | ||
47 | u32 saved_dqs_en; | ||
48 | u32 saved_strobe_ctrl; | ||
44 | }; | 49 | }; |
45 | 50 | ||
46 | static struct dw_mci_exynos_compatible { | 51 | static struct dw_mci_exynos_compatible { |
@@ -71,6 +76,21 @@ static struct dw_mci_exynos_compatible { | |||
71 | }, | 76 | }, |
72 | }; | 77 | }; |
73 | 78 | ||
79 | static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host) | ||
80 | { | ||
81 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
82 | |||
83 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) | ||
84 | return EXYNOS4412_FIXED_CIU_CLK_DIV; | ||
85 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) | ||
86 | return EXYNOS4210_FIXED_CIU_CLK_DIV; | ||
87 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || | ||
88 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) | ||
89 | return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1; | ||
90 | else | ||
91 | return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1; | ||
92 | } | ||
93 | |||
74 | static int dw_mci_exynos_priv_init(struct dw_mci *host) | 94 | static int dw_mci_exynos_priv_init(struct dw_mci *host) |
75 | { | 95 | { |
76 | struct dw_mci_exynos_priv_data *priv = host->priv; | 96 | struct dw_mci_exynos_priv_data *priv = host->priv; |
@@ -85,6 +105,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) | |||
85 | SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); | 105 | SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); |
86 | } | 106 | } |
87 | 107 | ||
108 | if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) { | ||
109 | priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL); | ||
110 | priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN); | ||
111 | priv->saved_dqs_en |= AXI_NON_BLOCKING_WR; | ||
112 | mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en); | ||
113 | if (!priv->dqs_delay) | ||
114 | priv->dqs_delay = | ||
115 | DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl); | ||
116 | } | ||
117 | |||
88 | return 0; | 118 | return 0; |
89 | } | 119 | } |
90 | 120 | ||
@@ -97,6 +127,26 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) | |||
97 | return 0; | 127 | return 0; |
98 | } | 128 | } |
99 | 129 | ||
130 | static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) | ||
131 | { | ||
132 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
133 | u32 clksel; | ||
134 | |||
135 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || | ||
136 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) | ||
137 | clksel = mci_readl(host, CLKSEL64); | ||
138 | else | ||
139 | clksel = mci_readl(host, CLKSEL); | ||
140 | |||
141 | clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing; | ||
142 | |||
143 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || | ||
144 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) | ||
145 | mci_writel(host, CLKSEL64, clksel); | ||
146 | else | ||
147 | mci_writel(host, CLKSEL, clksel); | ||
148 | } | ||
149 | |||
100 | #ifdef CONFIG_PM_SLEEP | 150 | #ifdef CONFIG_PM_SLEEP |
101 | static int dw_mci_exynos_suspend(struct device *dev) | 151 | static int dw_mci_exynos_suspend(struct device *dev) |
102 | { | 152 | { |
@@ -172,30 +222,38 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) | |||
172 | } | 222 | } |
173 | } | 223 | } |
174 | 224 | ||
175 | static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) | 225 | static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing) |
176 | { | 226 | { |
177 | struct dw_mci_exynos_priv_data *priv = host->priv; | 227 | struct dw_mci_exynos_priv_data *priv = host->priv; |
178 | unsigned int wanted = ios->clock; | 228 | u32 dqs, strobe; |
179 | unsigned long actual; | ||
180 | u8 div = priv->ciu_div + 1; | ||
181 | 229 | ||
182 | if (ios->timing == MMC_TIMING_MMC_DDR52) { | 230 | /* |
183 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || | 231 | * Not supported to configure register |
184 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) | 232 | * related to HS400 |
185 | mci_writel(host, CLKSEL64, priv->ddr_timing); | 233 | */ |
186 | else | 234 | if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420) |
187 | mci_writel(host, CLKSEL, priv->ddr_timing); | 235 | return; |
188 | /* Should be double rate for DDR mode */ | 236 | |
189 | if (ios->bus_width == MMC_BUS_WIDTH_8) | 237 | dqs = priv->saved_dqs_en; |
190 | wanted <<= 1; | 238 | strobe = priv->saved_strobe_ctrl; |
239 | |||
240 | if (timing == MMC_TIMING_MMC_HS400) { | ||
241 | dqs |= DATA_STROBE_EN; | ||
242 | strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay); | ||
191 | } else { | 243 | } else { |
192 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || | 244 | dqs &= ~DATA_STROBE_EN; |
193 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) | ||
194 | mci_writel(host, CLKSEL64, priv->sdr_timing); | ||
195 | else | ||
196 | mci_writel(host, CLKSEL, priv->sdr_timing); | ||
197 | } | 245 | } |
198 | 246 | ||
247 | mci_writel(host, HS400_DQS_EN, dqs); | ||
248 | mci_writel(host, HS400_DLINE_CTRL, strobe); | ||
249 | } | ||
250 | |||
251 | static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted) | ||
252 | { | ||
253 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
254 | unsigned long actual; | ||
255 | u8 div; | ||
256 | int ret; | ||
199 | /* | 257 | /* |
200 | * Don't care if wanted clock is zero or | 258 | * Don't care if wanted clock is zero or |
201 | * ciu clock is unavailable | 259 | * ciu clock is unavailable |
@@ -207,17 +265,52 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) | |||
207 | if (wanted < EXYNOS_CCLKIN_MIN) | 265 | if (wanted < EXYNOS_CCLKIN_MIN) |
208 | wanted = EXYNOS_CCLKIN_MIN; | 266 | wanted = EXYNOS_CCLKIN_MIN; |
209 | 267 | ||
210 | if (wanted != priv->cur_speed) { | 268 | if (wanted == priv->cur_speed) |
211 | int ret = clk_set_rate(host->ciu_clk, wanted * div); | 269 | return; |
212 | if (ret) | 270 | |
213 | dev_warn(host->dev, | 271 | div = dw_mci_exynos_get_ciu_div(host); |
214 | "failed to set clk-rate %u error: %d\n", | 272 | ret = clk_set_rate(host->ciu_clk, wanted * div); |
215 | wanted * div, ret); | 273 | if (ret) |
216 | actual = clk_get_rate(host->ciu_clk); | 274 | dev_warn(host->dev, |
217 | host->bus_hz = actual / div; | 275 | "failed to set clk-rate %u error: %d\n", |
218 | priv->cur_speed = wanted; | 276 | wanted * div, ret); |
219 | host->current_speed = 0; | 277 | actual = clk_get_rate(host->ciu_clk); |
278 | host->bus_hz = actual / div; | ||
279 | priv->cur_speed = wanted; | ||
280 | host->current_speed = 0; | ||
281 | } | ||
282 | |||
283 | static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) | ||
284 | { | ||
285 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
286 | unsigned int wanted = ios->clock; | ||
287 | u32 timing = ios->timing, clksel; | ||
288 | |||
289 | switch (timing) { | ||
290 | case MMC_TIMING_MMC_HS400: | ||
291 | /* Update tuned sample timing */ | ||
292 | clksel = SDMMC_CLKSEL_UP_SAMPLE( | ||
293 | priv->hs400_timing, priv->tuned_sample); | ||
294 | wanted <<= 1; | ||
295 | break; | ||
296 | case MMC_TIMING_MMC_DDR52: | ||
297 | clksel = priv->ddr_timing; | ||
298 | /* Should be double rate for DDR mode */ | ||
299 | if (ios->bus_width == MMC_BUS_WIDTH_8) | ||
300 | wanted <<= 1; | ||
301 | break; | ||
302 | default: | ||
303 | clksel = priv->sdr_timing; | ||
220 | } | 304 | } |
305 | |||
306 | /* Set clock timing for the requested speed mode*/ | ||
307 | dw_mci_exynos_set_clksel_timing(host, clksel); | ||
308 | |||
309 | /* Configure setting for HS400 */ | ||
310 | dw_mci_exynos_config_hs400(host, timing); | ||
311 | |||
312 | /* Configure clock rate */ | ||
313 | dw_mci_exynos_adjust_clock(host, wanted); | ||
221 | } | 314 | } |
222 | 315 | ||
223 | static int dw_mci_exynos_parse_dt(struct dw_mci *host) | 316 | static int dw_mci_exynos_parse_dt(struct dw_mci *host) |
@@ -260,6 +353,16 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host) | |||
260 | return ret; | 353 | return ret; |
261 | 354 | ||
262 | priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); | 355 | priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); |
356 | |||
357 | ret = of_property_read_u32_array(np, | ||
358 | "samsung,dw-mshc-hs400-timing", timing, 2); | ||
359 | if (!ret && of_property_read_u32(np, | ||
360 | "samsung,read-strobe-delay", &priv->dqs_delay)) | ||
361 | dev_dbg(host->dev, | ||
362 | "read-strobe-delay is not found, assuming usage of default value\n"); | ||
363 | |||
364 | priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], | ||
365 | HS400_FIXED_CIU_CLK_DIV); | ||
263 | host->priv = priv; | 366 | host->priv = priv; |
264 | return 0; | 367 | return 0; |
265 | } | 368 | } |
@@ -285,7 +388,7 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) | |||
285 | clksel = mci_readl(host, CLKSEL64); | 388 | clksel = mci_readl(host, CLKSEL64); |
286 | else | 389 | else |
287 | clksel = mci_readl(host, CLKSEL); | 390 | clksel = mci_readl(host, CLKSEL); |
288 | clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample); | 391 | clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); |
289 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || | 392 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || |
290 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) | 393 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) |
291 | mci_writel(host, CLKSEL64, clksel); | 394 | mci_writel(host, CLKSEL64, clksel); |
@@ -304,13 +407,16 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) | |||
304 | clksel = mci_readl(host, CLKSEL64); | 407 | clksel = mci_readl(host, CLKSEL64); |
305 | else | 408 | else |
306 | clksel = mci_readl(host, CLKSEL); | 409 | clksel = mci_readl(host, CLKSEL); |
410 | |||
307 | sample = (clksel + 1) & 0x7; | 411 | sample = (clksel + 1) & 0x7; |
308 | clksel = (clksel & ~0x7) | sample; | 412 | clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); |
413 | |||
309 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || | 414 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || |
310 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) | 415 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) |
311 | mci_writel(host, CLKSEL64, clksel); | 416 | mci_writel(host, CLKSEL64, clksel); |
312 | else | 417 | else |
313 | mci_writel(host, CLKSEL, clksel); | 418 | mci_writel(host, CLKSEL, clksel); |
419 | |||
314 | return sample; | 420 | return sample; |
315 | } | 421 | } |
316 | 422 | ||
@@ -343,6 +449,7 @@ out: | |||
343 | static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot) | 449 | static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot) |
344 | { | 450 | { |
345 | struct dw_mci *host = slot->host; | 451 | struct dw_mci *host = slot->host; |
452 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
346 | struct mmc_host *mmc = slot->mmc; | 453 | struct mmc_host *mmc = slot->mmc; |
347 | u8 start_smpl, smpl, candiates = 0; | 454 | u8 start_smpl, smpl, candiates = 0; |
348 | s8 found = -1; | 455 | s8 found = -1; |
@@ -360,14 +467,27 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot) | |||
360 | } while (start_smpl != smpl); | 467 | } while (start_smpl != smpl); |
361 | 468 | ||
362 | found = dw_mci_exynos_get_best_clksmpl(candiates); | 469 | found = dw_mci_exynos_get_best_clksmpl(candiates); |
363 | if (found >= 0) | 470 | if (found >= 0) { |
364 | dw_mci_exynos_set_clksmpl(host, found); | 471 | dw_mci_exynos_set_clksmpl(host, found); |
365 | else | 472 | priv->tuned_sample = found; |
473 | } else { | ||
366 | ret = -EIO; | 474 | ret = -EIO; |
475 | } | ||
367 | 476 | ||
368 | return ret; | 477 | return ret; |
369 | } | 478 | } |
370 | 479 | ||
480 | static int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host, | ||
481 | struct mmc_ios *ios) | ||
482 | { | ||
483 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
484 | |||
485 | dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing); | ||
486 | dw_mci_exynos_adjust_clock(host, (ios->clock) << 1); | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
371 | /* Common capabilities of Exynos4/Exynos5 SoC */ | 491 | /* Common capabilities of Exynos4/Exynos5 SoC */ |
372 | static unsigned long exynos_dwmmc_caps[4] = { | 492 | static unsigned long exynos_dwmmc_caps[4] = { |
373 | MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, | 493 | MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, |
@@ -384,6 +504,7 @@ static const struct dw_mci_drv_data exynos_drv_data = { | |||
384 | .set_ios = dw_mci_exynos_set_ios, | 504 | .set_ios = dw_mci_exynos_set_ios, |
385 | .parse_dt = dw_mci_exynos_parse_dt, | 505 | .parse_dt = dw_mci_exynos_parse_dt, |
386 | .execute_tuning = dw_mci_exynos_execute_tuning, | 506 | .execute_tuning = dw_mci_exynos_execute_tuning, |
507 | .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning, | ||
387 | }; | 508 | }; |
388 | 509 | ||
389 | static const struct of_device_id dw_mci_exynos_match[] = { | 510 | static const struct of_device_id dw_mci_exynos_match[] = { |
diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h index 7872ce586b55..595c934e6166 100644 --- a/drivers/mmc/host/dw_mmc-exynos.h +++ b/drivers/mmc/host/dw_mmc-exynos.h | |||
@@ -12,20 +12,36 @@ | |||
12 | #ifndef _DW_MMC_EXYNOS_H_ | 12 | #ifndef _DW_MMC_EXYNOS_H_ |
13 | #define _DW_MMC_EXYNOS_H_ | 13 | #define _DW_MMC_EXYNOS_H_ |
14 | 14 | ||
15 | /* Extended Register's Offset */ | ||
16 | #define SDMMC_CLKSEL 0x09C | 15 | #define SDMMC_CLKSEL 0x09C |
17 | #define SDMMC_CLKSEL64 0x0A8 | 16 | #define SDMMC_CLKSEL64 0x0A8 |
18 | 17 | ||
18 | /* Extended Register's Offset */ | ||
19 | #define SDMMC_HS400_DQS_EN 0x180 | ||
20 | #define SDMMC_HS400_ASYNC_FIFO_CTRL 0x184 | ||
21 | #define SDMMC_HS400_DLINE_CTRL 0x188 | ||
22 | |||
19 | /* CLKSEL register defines */ | 23 | /* CLKSEL register defines */ |
20 | #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) | 24 | #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) |
21 | #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16) | 25 | #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16) |
22 | #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24) | 26 | #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24) |
23 | #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7) | 27 | #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7) |
28 | #define SDMMC_CLKSEL_GET_DIV(x) (((x) >> 24) & 0x7) | ||
29 | #define SDMMC_CLKSEL_UP_SAMPLE(x, y) (((x) & ~SDMMC_CLKSEL_CCLK_SAMPLE(7)) |\ | ||
30 | SDMMC_CLKSEL_CCLK_SAMPLE(y)) | ||
24 | #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ | 31 | #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ |
25 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ | 32 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ |
26 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) | 33 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) |
34 | #define SDMMC_CLKSEL_TIMING_MASK SDMMC_CLKSEL_TIMING(0x7, 0x7, 0x7) | ||
27 | #define SDMMC_CLKSEL_WAKEUP_INT BIT(11) | 35 | #define SDMMC_CLKSEL_WAKEUP_INT BIT(11) |
28 | 36 | ||
37 | /* RCLK_EN register defines */ | ||
38 | #define DATA_STROBE_EN BIT(0) | ||
39 | #define AXI_NON_BLOCKING_WR BIT(7) | ||
40 | |||
41 | /* DLINE_CTRL register defines */ | ||
42 | #define DQS_CTRL_RD_DELAY(x, y) (((x) & ~0x3FF) | ((y) & 0x3FF)) | ||
43 | #define DQS_CTRL_GET_RD_DELAY(x) ((x) & 0x3FF) | ||
44 | |||
29 | /* Protector Register */ | 45 | /* Protector Register */ |
30 | #define SDMMC_EMMCP_BASE 0x1000 | 46 | #define SDMMC_EMMCP_BASE 0x1000 |
31 | #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) | 47 | #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) |
@@ -49,6 +65,7 @@ | |||
49 | /* Fixed clock divider */ | 65 | /* Fixed clock divider */ |
50 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 | 66 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 |
51 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 | 67 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 |
68 | #define HS400_FIXED_CIU_CLK_DIV 1 | ||
52 | 69 | ||
53 | /* Minimal required clock frequency for cclkin, unit: HZ */ | 70 | /* Minimal required clock frequency for cclkin, unit: HZ */ |
54 | #define EXYNOS_CCLKIN_MIN 50000000 | 71 | #define EXYNOS_CCLKIN_MIN 50000000 |
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index e2a726a503ee..dbf166f94f1b 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c | |||
@@ -76,12 +76,20 @@ static int dw_mci_rockchip_init(struct dw_mci *host) | |||
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* Common capabilities of RK3288 SoC */ | ||
80 | static unsigned long dw_mci_rk3288_dwmmc_caps[4] = { | ||
81 | MMC_CAP_RUNTIME_RESUME, /* emmc */ | ||
82 | MMC_CAP_RUNTIME_RESUME, /* sdmmc */ | ||
83 | MMC_CAP_RUNTIME_RESUME, /* sdio0 */ | ||
84 | MMC_CAP_RUNTIME_RESUME, /* sdio1 */ | ||
85 | }; | ||
79 | static const struct dw_mci_drv_data rk2928_drv_data = { | 86 | static const struct dw_mci_drv_data rk2928_drv_data = { |
80 | .prepare_command = dw_mci_rockchip_prepare_command, | 87 | .prepare_command = dw_mci_rockchip_prepare_command, |
81 | .init = dw_mci_rockchip_init, | 88 | .init = dw_mci_rockchip_init, |
82 | }; | 89 | }; |
83 | 90 | ||
84 | static const struct dw_mci_drv_data rk3288_drv_data = { | 91 | static const struct dw_mci_drv_data rk3288_drv_data = { |
92 | .caps = dw_mci_rk3288_dwmmc_caps, | ||
85 | .prepare_command = dw_mci_rockchip_prepare_command, | 93 | .prepare_command = dw_mci_rockchip_prepare_command, |
86 | .set_ios = dw_mci_rk3288_set_ios, | 94 | .set_ios = dw_mci_rk3288_set_ios, |
87 | .setup_clock = dw_mci_rk3288_setup_clock, | 95 | .setup_clock = dw_mci_rk3288_setup_clock, |
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 4d2e3c2e1830..38b29265cc7c 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -69,7 +69,8 @@ struct idmac_desc_64addr { | |||
69 | 69 | ||
70 | u32 des2; /*Buffer sizes */ | 70 | u32 des2; /*Buffer sizes */ |
71 | #define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \ | 71 | #define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \ |
72 | ((d)->des2 = ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff)) | 72 | ((d)->des2 = ((d)->des2 & cpu_to_le32(0x03ffe000)) | \ |
73 | ((cpu_to_le32(s)) & cpu_to_le32(0x1fff))) | ||
73 | 74 | ||
74 | u32 des3; /* Reserved */ | 75 | u32 des3; /* Reserved */ |
75 | 76 | ||
@@ -81,7 +82,7 @@ struct idmac_desc_64addr { | |||
81 | }; | 82 | }; |
82 | 83 | ||
83 | struct idmac_desc { | 84 | struct idmac_desc { |
84 | u32 des0; /* Control Descriptor */ | 85 | __le32 des0; /* Control Descriptor */ |
85 | #define IDMAC_DES0_DIC BIT(1) | 86 | #define IDMAC_DES0_DIC BIT(1) |
86 | #define IDMAC_DES0_LD BIT(2) | 87 | #define IDMAC_DES0_LD BIT(2) |
87 | #define IDMAC_DES0_FD BIT(3) | 88 | #define IDMAC_DES0_FD BIT(3) |
@@ -90,18 +91,19 @@ struct idmac_desc { | |||
90 | #define IDMAC_DES0_CES BIT(30) | 91 | #define IDMAC_DES0_CES BIT(30) |
91 | #define IDMAC_DES0_OWN BIT(31) | 92 | #define IDMAC_DES0_OWN BIT(31) |
92 | 93 | ||
93 | u32 des1; /* Buffer sizes */ | 94 | __le32 des1; /* Buffer sizes */ |
94 | #define IDMAC_SET_BUFFER1_SIZE(d, s) \ | 95 | #define IDMAC_SET_BUFFER1_SIZE(d, s) \ |
95 | ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff)) | 96 | ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff)) |
96 | 97 | ||
97 | u32 des2; /* buffer 1 physical address */ | 98 | __le32 des2; /* buffer 1 physical address */ |
98 | 99 | ||
99 | u32 des3; /* buffer 2 physical address */ | 100 | __le32 des3; /* buffer 2 physical address */ |
100 | }; | 101 | }; |
101 | #endif /* CONFIG_MMC_DW_IDMAC */ | 102 | #endif /* CONFIG_MMC_DW_IDMAC */ |
102 | 103 | ||
103 | static bool dw_mci_reset(struct dw_mci *host); | 104 | static bool dw_mci_reset(struct dw_mci *host); |
104 | static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset); | 105 | static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset); |
106 | static int dw_mci_card_busy(struct mmc_host *mmc); | ||
105 | 107 | ||
106 | #if defined(CONFIG_DEBUG_FS) | 108 | #if defined(CONFIG_DEBUG_FS) |
107 | static int dw_mci_req_show(struct seq_file *s, void *v) | 109 | static int dw_mci_req_show(struct seq_file *s, void *v) |
@@ -335,6 +337,31 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) | |||
335 | return cmdr; | 337 | return cmdr; |
336 | } | 338 | } |
337 | 339 | ||
340 | static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags) | ||
341 | { | ||
342 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | ||
343 | |||
344 | /* | ||
345 | * Databook says that before issuing a new data transfer command | ||
346 | * we need to check to see if the card is busy. Data transfer commands | ||
347 | * all have SDMMC_CMD_PRV_DAT_WAIT set, so we'll key off that. | ||
348 | * | ||
349 | * ...also allow sending for SDMMC_CMD_VOLT_SWITCH where busy is | ||
350 | * expected. | ||
351 | */ | ||
352 | if ((cmd_flags & SDMMC_CMD_PRV_DAT_WAIT) && | ||
353 | !(cmd_flags & SDMMC_CMD_VOLT_SWITCH)) { | ||
354 | while (mci_readl(host, STATUS) & SDMMC_STATUS_BUSY) { | ||
355 | if (time_after(jiffies, timeout)) { | ||
356 | /* Command will fail; we'll pass error then */ | ||
357 | dev_err(host->dev, "Busy; trying anyway\n"); | ||
358 | break; | ||
359 | } | ||
360 | udelay(10); | ||
361 | } | ||
362 | } | ||
363 | } | ||
364 | |||
338 | static void dw_mci_start_command(struct dw_mci *host, | 365 | static void dw_mci_start_command(struct dw_mci *host, |
339 | struct mmc_command *cmd, u32 cmd_flags) | 366 | struct mmc_command *cmd, u32 cmd_flags) |
340 | { | 367 | { |
@@ -345,6 +372,7 @@ static void dw_mci_start_command(struct dw_mci *host, | |||
345 | 372 | ||
346 | mci_writel(host, CMDARG, cmd->arg); | 373 | mci_writel(host, CMDARG, cmd->arg); |
347 | wmb(); | 374 | wmb(); |
375 | dw_mci_wait_while_busy(host, cmd_flags); | ||
348 | 376 | ||
349 | mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); | 377 | mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); |
350 | } | 378 | } |
@@ -477,23 +505,23 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data, | |||
477 | * Set the OWN bit and disable interrupts for this | 505 | * Set the OWN bit and disable interrupts for this |
478 | * descriptor | 506 | * descriptor |
479 | */ | 507 | */ |
480 | desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | | 508 | desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | |
481 | IDMAC_DES0_CH; | 509 | IDMAC_DES0_DIC | IDMAC_DES0_CH); |
482 | /* Buffer length */ | 510 | /* Buffer length */ |
483 | IDMAC_SET_BUFFER1_SIZE(desc, length); | 511 | IDMAC_SET_BUFFER1_SIZE(desc, length); |
484 | 512 | ||
485 | /* Physical address to DMA to/from */ | 513 | /* Physical address to DMA to/from */ |
486 | desc->des2 = mem_addr; | 514 | desc->des2 = cpu_to_le32(mem_addr); |
487 | } | 515 | } |
488 | 516 | ||
489 | /* Set first descriptor */ | 517 | /* Set first descriptor */ |
490 | desc = host->sg_cpu; | 518 | desc = host->sg_cpu; |
491 | desc->des0 |= IDMAC_DES0_FD; | 519 | desc->des0 |= cpu_to_le32(IDMAC_DES0_FD); |
492 | 520 | ||
493 | /* Set last descriptor */ | 521 | /* Set last descriptor */ |
494 | desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); | 522 | desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); |
495 | desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); | 523 | desc->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | IDMAC_DES0_DIC)); |
496 | desc->des0 |= IDMAC_DES0_LD; | 524 | desc->des0 |= cpu_to_le32(IDMAC_DES0_LD); |
497 | } | 525 | } |
498 | 526 | ||
499 | wmb(); | 527 | wmb(); |
@@ -562,12 +590,12 @@ static int dw_mci_idmac_init(struct dw_mci *host) | |||
562 | 590 | ||
563 | /* Forward link the descriptor list */ | 591 | /* Forward link the descriptor list */ |
564 | for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) | 592 | for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) |
565 | p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * | 593 | p->des3 = cpu_to_le32(host->sg_dma + |
566 | (i + 1)); | 594 | (sizeof(struct idmac_desc) * (i + 1))); |
567 | 595 | ||
568 | /* Set the last descriptor as the end-of-ring descriptor */ | 596 | /* Set the last descriptor as the end-of-ring descriptor */ |
569 | p->des3 = host->sg_dma; | 597 | p->des3 = cpu_to_le32(host->sg_dma); |
570 | p->des0 = IDMAC_DES0_ER; | 598 | p->des0 = cpu_to_le32(IDMAC_DES0_ER); |
571 | } | 599 | } |
572 | 600 | ||
573 | dw_mci_idmac_reset(host); | 601 | dw_mci_idmac_reset(host); |
@@ -737,6 +765,7 @@ static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data) | |||
737 | return; | 765 | return; |
738 | 766 | ||
739 | if (host->timing != MMC_TIMING_MMC_HS200 && | 767 | if (host->timing != MMC_TIMING_MMC_HS200 && |
768 | host->timing != MMC_TIMING_MMC_HS400 && | ||
740 | host->timing != MMC_TIMING_UHS_SDR104) | 769 | host->timing != MMC_TIMING_UHS_SDR104) |
741 | goto disable; | 770 | goto disable; |
742 | 771 | ||
@@ -876,6 +905,7 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) | |||
876 | 905 | ||
877 | mci_writel(host, CMDARG, arg); | 906 | mci_writel(host, CMDARG, arg); |
878 | wmb(); | 907 | wmb(); |
908 | dw_mci_wait_while_busy(host, cmd); | ||
879 | mci_writel(host, CMD, SDMMC_CMD_START | cmd); | 909 | mci_writel(host, CMD, SDMMC_CMD_START | cmd); |
880 | 910 | ||
881 | while (time_before(jiffies, timeout)) { | 911 | while (time_before(jiffies, timeout)) { |
@@ -992,6 +1022,26 @@ static void __dw_mci_start_request(struct dw_mci *host, | |||
992 | 1022 | ||
993 | dw_mci_start_command(host, cmd, cmdflags); | 1023 | dw_mci_start_command(host, cmd, cmdflags); |
994 | 1024 | ||
1025 | if (cmd->opcode == SD_SWITCH_VOLTAGE) { | ||
1026 | unsigned long irqflags; | ||
1027 | |||
1028 | /* | ||
1029 | * Databook says to fail after 2ms w/ no response, but evidence | ||
1030 | * shows that sometimes the cmd11 interrupt takes over 130ms. | ||
1031 | * We'll set to 500ms, plus an extra jiffy just in case jiffies | ||
1032 | * is just about to roll over. | ||
1033 | * | ||
1034 | * We do this whole thing under spinlock and only if the | ||
1035 | * command hasn't already completed (indicating the the irq | ||
1036 | * already ran so we don't want the timeout). | ||
1037 | */ | ||
1038 | spin_lock_irqsave(&host->irq_lock, irqflags); | ||
1039 | if (!test_bit(EVENT_CMD_COMPLETE, &host->pending_events)) | ||
1040 | mod_timer(&host->cmd11_timer, | ||
1041 | jiffies + msecs_to_jiffies(500) + 1); | ||
1042 | spin_unlock_irqrestore(&host->irq_lock, irqflags); | ||
1043 | } | ||
1044 | |||
995 | if (mrq->stop) | 1045 | if (mrq->stop) |
996 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); | 1046 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); |
997 | else | 1047 | else |
@@ -1084,7 +1134,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1084 | regs = mci_readl(slot->host, UHS_REG); | 1134 | regs = mci_readl(slot->host, UHS_REG); |
1085 | 1135 | ||
1086 | /* DDR mode set */ | 1136 | /* DDR mode set */ |
1087 | if (ios->timing == MMC_TIMING_MMC_DDR52) | 1137 | if (ios->timing == MMC_TIMING_MMC_DDR52 || |
1138 | ios->timing == MMC_TIMING_MMC_HS400) | ||
1088 | regs |= ((0x1 << slot->id) << 16); | 1139 | regs |= ((0x1 << slot->id) << 16); |
1089 | else | 1140 | else |
1090 | regs &= ~((0x1 << slot->id) << 16); | 1141 | regs &= ~((0x1 << slot->id) << 16); |
@@ -1101,12 +1152,6 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1101 | if (drv_data && drv_data->set_ios) | 1152 | if (drv_data && drv_data->set_ios) |
1102 | drv_data->set_ios(slot->host, ios); | 1153 | drv_data->set_ios(slot->host, ios); |
1103 | 1154 | ||
1104 | /* Slot specific timing and width adjustment */ | ||
1105 | dw_mci_setup_bus(slot, false); | ||
1106 | |||
1107 | if (slot->host->state == STATE_WAITING_CMD11_DONE && ios->clock != 0) | ||
1108 | slot->host->state = STATE_IDLE; | ||
1109 | |||
1110 | switch (ios->power_mode) { | 1155 | switch (ios->power_mode) { |
1111 | case MMC_POWER_UP: | 1156 | case MMC_POWER_UP: |
1112 | if (!IS_ERR(mmc->supply.vmmc)) { | 1157 | if (!IS_ERR(mmc->supply.vmmc)) { |
@@ -1125,23 +1170,39 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1125 | mci_writel(slot->host, PWREN, regs); | 1170 | mci_writel(slot->host, PWREN, regs); |
1126 | break; | 1171 | break; |
1127 | case MMC_POWER_ON: | 1172 | case MMC_POWER_ON: |
1128 | if (!IS_ERR(mmc->supply.vqmmc) && !slot->host->vqmmc_enabled) { | 1173 | if (!slot->host->vqmmc_enabled) { |
1129 | ret = regulator_enable(mmc->supply.vqmmc); | 1174 | if (!IS_ERR(mmc->supply.vqmmc)) { |
1130 | if (ret < 0) | 1175 | ret = regulator_enable(mmc->supply.vqmmc); |
1131 | dev_err(slot->host->dev, | 1176 | if (ret < 0) |
1132 | "failed to enable vqmmc regulator\n"); | 1177 | dev_err(slot->host->dev, |
1133 | else | 1178 | "failed to enable vqmmc\n"); |
1179 | else | ||
1180 | slot->host->vqmmc_enabled = true; | ||
1181 | |||
1182 | } else { | ||
1183 | /* Keep track so we don't reset again */ | ||
1134 | slot->host->vqmmc_enabled = true; | 1184 | slot->host->vqmmc_enabled = true; |
1185 | } | ||
1186 | |||
1187 | /* Reset our state machine after powering on */ | ||
1188 | dw_mci_ctrl_reset(slot->host, | ||
1189 | SDMMC_CTRL_ALL_RESET_FLAGS); | ||
1135 | } | 1190 | } |
1191 | |||
1192 | /* Adjust clock / bus width after power is up */ | ||
1193 | dw_mci_setup_bus(slot, false); | ||
1194 | |||
1136 | break; | 1195 | break; |
1137 | case MMC_POWER_OFF: | 1196 | case MMC_POWER_OFF: |
1197 | /* Turn clock off before power goes down */ | ||
1198 | dw_mci_setup_bus(slot, false); | ||
1199 | |||
1138 | if (!IS_ERR(mmc->supply.vmmc)) | 1200 | if (!IS_ERR(mmc->supply.vmmc)) |
1139 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); | 1201 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); |
1140 | 1202 | ||
1141 | if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled) { | 1203 | if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled) |
1142 | regulator_disable(mmc->supply.vqmmc); | 1204 | regulator_disable(mmc->supply.vqmmc); |
1143 | slot->host->vqmmc_enabled = false; | 1205 | slot->host->vqmmc_enabled = false; |
1144 | } | ||
1145 | 1206 | ||
1146 | regs = mci_readl(slot->host, PWREN); | 1207 | regs = mci_readl(slot->host, PWREN); |
1147 | regs &= ~(1 << slot->id); | 1208 | regs &= ~(1 << slot->id); |
@@ -1150,6 +1211,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1150 | default: | 1211 | default: |
1151 | break; | 1212 | break; |
1152 | } | 1213 | } |
1214 | |||
1215 | if (slot->host->state == STATE_WAITING_CMD11_DONE && ios->clock != 0) | ||
1216 | slot->host->state = STATE_IDLE; | ||
1153 | } | 1217 | } |
1154 | 1218 | ||
1155 | static int dw_mci_card_busy(struct mmc_host *mmc) | 1219 | static int dw_mci_card_busy(struct mmc_host *mmc) |
@@ -1323,6 +1387,18 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
1323 | return err; | 1387 | return err; |
1324 | } | 1388 | } |
1325 | 1389 | ||
1390 | static int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) | ||
1391 | { | ||
1392 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
1393 | struct dw_mci *host = slot->host; | ||
1394 | const struct dw_mci_drv_data *drv_data = host->drv_data; | ||
1395 | |||
1396 | if (drv_data && drv_data->prepare_hs400_tuning) | ||
1397 | return drv_data->prepare_hs400_tuning(host, ios); | ||
1398 | |||
1399 | return 0; | ||
1400 | } | ||
1401 | |||
1326 | static const struct mmc_host_ops dw_mci_ops = { | 1402 | static const struct mmc_host_ops dw_mci_ops = { |
1327 | .request = dw_mci_request, | 1403 | .request = dw_mci_request, |
1328 | .pre_req = dw_mci_pre_req, | 1404 | .pre_req = dw_mci_pre_req, |
@@ -1335,6 +1411,7 @@ static const struct mmc_host_ops dw_mci_ops = { | |||
1335 | .card_busy = dw_mci_card_busy, | 1411 | .card_busy = dw_mci_card_busy, |
1336 | .start_signal_voltage_switch = dw_mci_switch_voltage, | 1412 | .start_signal_voltage_switch = dw_mci_switch_voltage, |
1337 | .init_card = dw_mci_init_card, | 1413 | .init_card = dw_mci_init_card, |
1414 | .prepare_hs400_tuning = dw_mci_prepare_hs400_tuning, | ||
1338 | }; | 1415 | }; |
1339 | 1416 | ||
1340 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | 1417 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) |
@@ -1520,7 +1597,10 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1520 | if (test_and_clear_bit(EVENT_DATA_ERROR, | 1597 | if (test_and_clear_bit(EVENT_DATA_ERROR, |
1521 | &host->pending_events)) { | 1598 | &host->pending_events)) { |
1522 | dw_mci_stop_dma(host); | 1599 | dw_mci_stop_dma(host); |
1523 | send_stop_abort(host, data); | 1600 | if (data->stop || |
1601 | !(host->data_status & (SDMMC_INT_DRTO | | ||
1602 | SDMMC_INT_EBE))) | ||
1603 | send_stop_abort(host, data); | ||
1524 | state = STATE_DATA_ERROR; | 1604 | state = STATE_DATA_ERROR; |
1525 | break; | 1605 | break; |
1526 | } | 1606 | } |
@@ -1547,7 +1627,10 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1547 | if (test_and_clear_bit(EVENT_DATA_ERROR, | 1627 | if (test_and_clear_bit(EVENT_DATA_ERROR, |
1548 | &host->pending_events)) { | 1628 | &host->pending_events)) { |
1549 | dw_mci_stop_dma(host); | 1629 | dw_mci_stop_dma(host); |
1550 | send_stop_abort(host, data); | 1630 | if (data->stop || |
1631 | !(host->data_status & (SDMMC_INT_DRTO | | ||
1632 | SDMMC_INT_EBE))) | ||
1633 | send_stop_abort(host, data); | ||
1551 | state = STATE_DATA_ERROR; | 1634 | state = STATE_DATA_ERROR; |
1552 | break; | 1635 | break; |
1553 | } | 1636 | } |
@@ -1685,8 +1768,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) | |||
1685 | buf += len; | 1768 | buf += len; |
1686 | cnt -= len; | 1769 | cnt -= len; |
1687 | if (host->part_buf_count == 2) { | 1770 | if (host->part_buf_count == 2) { |
1688 | mci_writew(host, DATA(host->data_offset), | 1771 | mci_fifo_writew(host->fifo_reg, host->part_buf16); |
1689 | host->part_buf16); | ||
1690 | host->part_buf_count = 0; | 1772 | host->part_buf_count = 0; |
1691 | } | 1773 | } |
1692 | } | 1774 | } |
@@ -1703,15 +1785,14 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) | |||
1703 | cnt -= len; | 1785 | cnt -= len; |
1704 | /* push data from aligned buffer into fifo */ | 1786 | /* push data from aligned buffer into fifo */ |
1705 | for (i = 0; i < items; ++i) | 1787 | for (i = 0; i < items; ++i) |
1706 | mci_writew(host, DATA(host->data_offset), | 1788 | mci_fifo_writew(host->fifo_reg, aligned_buf[i]); |
1707 | aligned_buf[i]); | ||
1708 | } | 1789 | } |
1709 | } else | 1790 | } else |
1710 | #endif | 1791 | #endif |
1711 | { | 1792 | { |
1712 | u16 *pdata = buf; | 1793 | u16 *pdata = buf; |
1713 | for (; cnt >= 2; cnt -= 2) | 1794 | for (; cnt >= 2; cnt -= 2) |
1714 | mci_writew(host, DATA(host->data_offset), *pdata++); | 1795 | mci_fifo_writew(host->fifo_reg, *pdata++); |
1715 | buf = pdata; | 1796 | buf = pdata; |
1716 | } | 1797 | } |
1717 | /* put anything remaining in the part_buf */ | 1798 | /* put anything remaining in the part_buf */ |
@@ -1720,8 +1801,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) | |||
1720 | /* Push data if we have reached the expected data length */ | 1801 | /* Push data if we have reached the expected data length */ |
1721 | if ((data->bytes_xfered + init_cnt) == | 1802 | if ((data->bytes_xfered + init_cnt) == |
1722 | (data->blksz * data->blocks)) | 1803 | (data->blksz * data->blocks)) |
1723 | mci_writew(host, DATA(host->data_offset), | 1804 | mci_fifo_writew(host->fifo_reg, host->part_buf16); |
1724 | host->part_buf16); | ||
1725 | } | 1805 | } |
1726 | } | 1806 | } |
1727 | 1807 | ||
@@ -1736,8 +1816,7 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) | |||
1736 | int items = len >> 1; | 1816 | int items = len >> 1; |
1737 | int i; | 1817 | int i; |
1738 | for (i = 0; i < items; ++i) | 1818 | for (i = 0; i < items; ++i) |
1739 | aligned_buf[i] = mci_readw(host, | 1819 | aligned_buf[i] = mci_fifo_readw(host->fifo_reg); |
1740 | DATA(host->data_offset)); | ||
1741 | /* memcpy from aligned buffer into output buffer */ | 1820 | /* memcpy from aligned buffer into output buffer */ |
1742 | memcpy(buf, aligned_buf, len); | 1821 | memcpy(buf, aligned_buf, len); |
1743 | buf += len; | 1822 | buf += len; |
@@ -1748,11 +1827,11 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) | |||
1748 | { | 1827 | { |
1749 | u16 *pdata = buf; | 1828 | u16 *pdata = buf; |
1750 | for (; cnt >= 2; cnt -= 2) | 1829 | for (; cnt >= 2; cnt -= 2) |
1751 | *pdata++ = mci_readw(host, DATA(host->data_offset)); | 1830 | *pdata++ = mci_fifo_readw(host->fifo_reg); |
1752 | buf = pdata; | 1831 | buf = pdata; |
1753 | } | 1832 | } |
1754 | if (cnt) { | 1833 | if (cnt) { |
1755 | host->part_buf16 = mci_readw(host, DATA(host->data_offset)); | 1834 | host->part_buf16 = mci_fifo_readw(host->fifo_reg); |
1756 | dw_mci_pull_final_bytes(host, buf, cnt); | 1835 | dw_mci_pull_final_bytes(host, buf, cnt); |
1757 | } | 1836 | } |
1758 | } | 1837 | } |
@@ -1768,8 +1847,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) | |||
1768 | buf += len; | 1847 | buf += len; |
1769 | cnt -= len; | 1848 | cnt -= len; |
1770 | if (host->part_buf_count == 4) { | 1849 | if (host->part_buf_count == 4) { |
1771 | mci_writel(host, DATA(host->data_offset), | 1850 | mci_fifo_writel(host->fifo_reg, host->part_buf32); |
1772 | host->part_buf32); | ||
1773 | host->part_buf_count = 0; | 1851 | host->part_buf_count = 0; |
1774 | } | 1852 | } |
1775 | } | 1853 | } |
@@ -1786,15 +1864,14 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) | |||
1786 | cnt -= len; | 1864 | cnt -= len; |
1787 | /* push data from aligned buffer into fifo */ | 1865 | /* push data from aligned buffer into fifo */ |
1788 | for (i = 0; i < items; ++i) | 1866 | for (i = 0; i < items; ++i) |
1789 | mci_writel(host, DATA(host->data_offset), | 1867 | mci_fifo_writel(host->fifo_reg, aligned_buf[i]); |
1790 | aligned_buf[i]); | ||
1791 | } | 1868 | } |
1792 | } else | 1869 | } else |
1793 | #endif | 1870 | #endif |
1794 | { | 1871 | { |
1795 | u32 *pdata = buf; | 1872 | u32 *pdata = buf; |
1796 | for (; cnt >= 4; cnt -= 4) | 1873 | for (; cnt >= 4; cnt -= 4) |
1797 | mci_writel(host, DATA(host->data_offset), *pdata++); | 1874 | mci_fifo_writel(host->fifo_reg, *pdata++); |
1798 | buf = pdata; | 1875 | buf = pdata; |
1799 | } | 1876 | } |
1800 | /* put anything remaining in the part_buf */ | 1877 | /* put anything remaining in the part_buf */ |
@@ -1803,8 +1880,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) | |||
1803 | /* Push data if we have reached the expected data length */ | 1880 | /* Push data if we have reached the expected data length */ |
1804 | if ((data->bytes_xfered + init_cnt) == | 1881 | if ((data->bytes_xfered + init_cnt) == |
1805 | (data->blksz * data->blocks)) | 1882 | (data->blksz * data->blocks)) |
1806 | mci_writel(host, DATA(host->data_offset), | 1883 | mci_fifo_writel(host->fifo_reg, host->part_buf32); |
1807 | host->part_buf32); | ||
1808 | } | 1884 | } |
1809 | } | 1885 | } |
1810 | 1886 | ||
@@ -1819,8 +1895,7 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) | |||
1819 | int items = len >> 2; | 1895 | int items = len >> 2; |
1820 | int i; | 1896 | int i; |
1821 | for (i = 0; i < items; ++i) | 1897 | for (i = 0; i < items; ++i) |
1822 | aligned_buf[i] = mci_readl(host, | 1898 | aligned_buf[i] = mci_fifo_readl(host->fifo_reg); |
1823 | DATA(host->data_offset)); | ||
1824 | /* memcpy from aligned buffer into output buffer */ | 1899 | /* memcpy from aligned buffer into output buffer */ |
1825 | memcpy(buf, aligned_buf, len); | 1900 | memcpy(buf, aligned_buf, len); |
1826 | buf += len; | 1901 | buf += len; |
@@ -1831,11 +1906,11 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) | |||
1831 | { | 1906 | { |
1832 | u32 *pdata = buf; | 1907 | u32 *pdata = buf; |
1833 | for (; cnt >= 4; cnt -= 4) | 1908 | for (; cnt >= 4; cnt -= 4) |
1834 | *pdata++ = mci_readl(host, DATA(host->data_offset)); | 1909 | *pdata++ = mci_fifo_readl(host->fifo_reg); |
1835 | buf = pdata; | 1910 | buf = pdata; |
1836 | } | 1911 | } |
1837 | if (cnt) { | 1912 | if (cnt) { |
1838 | host->part_buf32 = mci_readl(host, DATA(host->data_offset)); | 1913 | host->part_buf32 = mci_fifo_readl(host->fifo_reg); |
1839 | dw_mci_pull_final_bytes(host, buf, cnt); | 1914 | dw_mci_pull_final_bytes(host, buf, cnt); |
1840 | } | 1915 | } |
1841 | } | 1916 | } |
@@ -1852,8 +1927,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) | |||
1852 | cnt -= len; | 1927 | cnt -= len; |
1853 | 1928 | ||
1854 | if (host->part_buf_count == 8) { | 1929 | if (host->part_buf_count == 8) { |
1855 | mci_writeq(host, DATA(host->data_offset), | 1930 | mci_fifo_writeq(host->fifo_reg, host->part_buf); |
1856 | host->part_buf); | ||
1857 | host->part_buf_count = 0; | 1931 | host->part_buf_count = 0; |
1858 | } | 1932 | } |
1859 | } | 1933 | } |
@@ -1870,15 +1944,14 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) | |||
1870 | cnt -= len; | 1944 | cnt -= len; |
1871 | /* push data from aligned buffer into fifo */ | 1945 | /* push data from aligned buffer into fifo */ |
1872 | for (i = 0; i < items; ++i) | 1946 | for (i = 0; i < items; ++i) |
1873 | mci_writeq(host, DATA(host->data_offset), | 1947 | mci_fifo_writeq(host->fifo_reg, aligned_buf[i]); |
1874 | aligned_buf[i]); | ||
1875 | } | 1948 | } |
1876 | } else | 1949 | } else |
1877 | #endif | 1950 | #endif |
1878 | { | 1951 | { |
1879 | u64 *pdata = buf; | 1952 | u64 *pdata = buf; |
1880 | for (; cnt >= 8; cnt -= 8) | 1953 | for (; cnt >= 8; cnt -= 8) |
1881 | mci_writeq(host, DATA(host->data_offset), *pdata++); | 1954 | mci_fifo_writeq(host->fifo_reg, *pdata++); |
1882 | buf = pdata; | 1955 | buf = pdata; |
1883 | } | 1956 | } |
1884 | /* put anything remaining in the part_buf */ | 1957 | /* put anything remaining in the part_buf */ |
@@ -1887,8 +1960,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) | |||
1887 | /* Push data if we have reached the expected data length */ | 1960 | /* Push data if we have reached the expected data length */ |
1888 | if ((data->bytes_xfered + init_cnt) == | 1961 | if ((data->bytes_xfered + init_cnt) == |
1889 | (data->blksz * data->blocks)) | 1962 | (data->blksz * data->blocks)) |
1890 | mci_writeq(host, DATA(host->data_offset), | 1963 | mci_fifo_writeq(host->fifo_reg, host->part_buf); |
1891 | host->part_buf); | ||
1892 | } | 1964 | } |
1893 | } | 1965 | } |
1894 | 1966 | ||
@@ -1903,8 +1975,8 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) | |||
1903 | int items = len >> 3; | 1975 | int items = len >> 3; |
1904 | int i; | 1976 | int i; |
1905 | for (i = 0; i < items; ++i) | 1977 | for (i = 0; i < items; ++i) |
1906 | aligned_buf[i] = mci_readq(host, | 1978 | aligned_buf[i] = mci_fifo_readq(host->fifo_reg); |
1907 | DATA(host->data_offset)); | 1979 | |
1908 | /* memcpy from aligned buffer into output buffer */ | 1980 | /* memcpy from aligned buffer into output buffer */ |
1909 | memcpy(buf, aligned_buf, len); | 1981 | memcpy(buf, aligned_buf, len); |
1910 | buf += len; | 1982 | buf += len; |
@@ -1915,11 +1987,11 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) | |||
1915 | { | 1987 | { |
1916 | u64 *pdata = buf; | 1988 | u64 *pdata = buf; |
1917 | for (; cnt >= 8; cnt -= 8) | 1989 | for (; cnt >= 8; cnt -= 8) |
1918 | *pdata++ = mci_readq(host, DATA(host->data_offset)); | 1990 | *pdata++ = mci_fifo_readq(host->fifo_reg); |
1919 | buf = pdata; | 1991 | buf = pdata; |
1920 | } | 1992 | } |
1921 | if (cnt) { | 1993 | if (cnt) { |
1922 | host->part_buf = mci_readq(host, DATA(host->data_offset)); | 1994 | host->part_buf = mci_fifo_readq(host->fifo_reg); |
1923 | dw_mci_pull_final_bytes(host, buf, cnt); | 1995 | dw_mci_pull_final_bytes(host, buf, cnt); |
1924 | } | 1996 | } |
1925 | } | 1997 | } |
@@ -2097,9 +2169,20 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
2097 | /* Check volt switch first, since it can look like an error */ | 2169 | /* Check volt switch first, since it can look like an error */ |
2098 | if ((host->state == STATE_SENDING_CMD11) && | 2170 | if ((host->state == STATE_SENDING_CMD11) && |
2099 | (pending & SDMMC_INT_VOLT_SWITCH)) { | 2171 | (pending & SDMMC_INT_VOLT_SWITCH)) { |
2172 | unsigned long irqflags; | ||
2173 | |||
2100 | mci_writel(host, RINTSTS, SDMMC_INT_VOLT_SWITCH); | 2174 | mci_writel(host, RINTSTS, SDMMC_INT_VOLT_SWITCH); |
2101 | pending &= ~SDMMC_INT_VOLT_SWITCH; | 2175 | pending &= ~SDMMC_INT_VOLT_SWITCH; |
2176 | |||
2177 | /* | ||
2178 | * Hold the lock; we know cmd11_timer can't be kicked | ||
2179 | * off after the lock is released, so safe to delete. | ||
2180 | */ | ||
2181 | spin_lock_irqsave(&host->irq_lock, irqflags); | ||
2102 | dw_mci_cmd_interrupt(host, pending); | 2182 | dw_mci_cmd_interrupt(host, pending); |
2183 | spin_unlock_irqrestore(&host->irq_lock, irqflags); | ||
2184 | |||
2185 | del_timer(&host->cmd11_timer); | ||
2103 | } | 2186 | } |
2104 | 2187 | ||
2105 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { | 2188 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { |
@@ -2156,6 +2239,10 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
2156 | /* Handle SDIO Interrupts */ | 2239 | /* Handle SDIO Interrupts */ |
2157 | for (i = 0; i < host->num_slots; i++) { | 2240 | for (i = 0; i < host->num_slots; i++) { |
2158 | struct dw_mci_slot *slot = host->slot[i]; | 2241 | struct dw_mci_slot *slot = host->slot[i]; |
2242 | |||
2243 | if (!slot) | ||
2244 | continue; | ||
2245 | |||
2159 | if (pending & SDMMC_INT_SDIO(slot->sdio_id)) { | 2246 | if (pending & SDMMC_INT_SDIO(slot->sdio_id)) { |
2160 | mci_writel(host, RINTSTS, | 2247 | mci_writel(host, RINTSTS, |
2161 | SDMMC_INT_SDIO(slot->sdio_id)); | 2248 | SDMMC_INT_SDIO(slot->sdio_id)); |
@@ -2506,6 +2593,20 @@ ciu_out: | |||
2506 | return ret; | 2593 | return ret; |
2507 | } | 2594 | } |
2508 | 2595 | ||
2596 | static void dw_mci_cmd11_timer(unsigned long arg) | ||
2597 | { | ||
2598 | struct dw_mci *host = (struct dw_mci *)arg; | ||
2599 | |||
2600 | if (host->state != STATE_SENDING_CMD11) { | ||
2601 | dev_warn(host->dev, "Unexpected CMD11 timeout\n"); | ||
2602 | return; | ||
2603 | } | ||
2604 | |||
2605 | host->cmd_status = SDMMC_INT_RTO; | ||
2606 | set_bit(EVENT_CMD_COMPLETE, &host->pending_events); | ||
2607 | tasklet_schedule(&host->tasklet); | ||
2608 | } | ||
2609 | |||
2509 | #ifdef CONFIG_OF | 2610 | #ifdef CONFIG_OF |
2510 | static struct dw_mci_of_quirks { | 2611 | static struct dw_mci_of_quirks { |
2511 | char *quirk; | 2612 | char *quirk; |
@@ -2574,6 +2675,34 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
2574 | } | 2675 | } |
2575 | #endif /* CONFIG_OF */ | 2676 | #endif /* CONFIG_OF */ |
2576 | 2677 | ||
2678 | static void dw_mci_enable_cd(struct dw_mci *host) | ||
2679 | { | ||
2680 | struct dw_mci_board *brd = host->pdata; | ||
2681 | unsigned long irqflags; | ||
2682 | u32 temp; | ||
2683 | int i; | ||
2684 | |||
2685 | /* No need for CD if broken card detection */ | ||
2686 | if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) | ||
2687 | return; | ||
2688 | |||
2689 | /* No need for CD if all slots have a non-error GPIO */ | ||
2690 | for (i = 0; i < host->num_slots; i++) { | ||
2691 | struct dw_mci_slot *slot = host->slot[i]; | ||
2692 | |||
2693 | if (IS_ERR_VALUE(mmc_gpio_get_cd(slot->mmc))) | ||
2694 | break; | ||
2695 | } | ||
2696 | if (i == host->num_slots) | ||
2697 | return; | ||
2698 | |||
2699 | spin_lock_irqsave(&host->irq_lock, irqflags); | ||
2700 | temp = mci_readl(host, INTMASK); | ||
2701 | temp |= SDMMC_INT_CD; | ||
2702 | mci_writel(host, INTMASK, temp); | ||
2703 | spin_unlock_irqrestore(&host->irq_lock, irqflags); | ||
2704 | } | ||
2705 | |||
2577 | int dw_mci_probe(struct dw_mci *host) | 2706 | int dw_mci_probe(struct dw_mci *host) |
2578 | { | 2707 | { |
2579 | const struct dw_mci_drv_data *drv_data = host->drv_data; | 2708 | const struct dw_mci_drv_data *drv_data = host->drv_data; |
@@ -2652,6 +2781,9 @@ int dw_mci_probe(struct dw_mci *host) | |||
2652 | } | 2781 | } |
2653 | } | 2782 | } |
2654 | 2783 | ||
2784 | setup_timer(&host->cmd11_timer, | ||
2785 | dw_mci_cmd11_timer, (unsigned long)host); | ||
2786 | |||
2655 | host->quirks = host->pdata->quirks; | 2787 | host->quirks = host->pdata->quirks; |
2656 | 2788 | ||
2657 | spin_lock_init(&host->lock); | 2789 | spin_lock_init(&host->lock); |
@@ -2731,9 +2863,9 @@ int dw_mci_probe(struct dw_mci *host) | |||
2731 | dev_info(host->dev, "Version ID is %04x\n", host->verid); | 2863 | dev_info(host->dev, "Version ID is %04x\n", host->verid); |
2732 | 2864 | ||
2733 | if (host->verid < DW_MMC_240A) | 2865 | if (host->verid < DW_MMC_240A) |
2734 | host->data_offset = DATA_OFFSET; | 2866 | host->fifo_reg = host->regs + DATA_OFFSET; |
2735 | else | 2867 | else |
2736 | host->data_offset = DATA_240A_OFFSET; | 2868 | host->fifo_reg = host->regs + DATA_240A_OFFSET; |
2737 | 2869 | ||
2738 | tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); | 2870 | tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); |
2739 | ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, | 2871 | ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, |
@@ -2747,13 +2879,13 @@ int dw_mci_probe(struct dw_mci *host) | |||
2747 | host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; | 2879 | host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; |
2748 | 2880 | ||
2749 | /* | 2881 | /* |
2750 | * Enable interrupts for command done, data over, data empty, card det, | 2882 | * Enable interrupts for command done, data over, data empty, |
2751 | * receive ready and error such as transmit, receive timeout, crc error | 2883 | * receive ready and error such as transmit, receive timeout, crc error |
2752 | */ | 2884 | */ |
2753 | mci_writel(host, RINTSTS, 0xFFFFFFFF); | 2885 | mci_writel(host, RINTSTS, 0xFFFFFFFF); |
2754 | mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | | 2886 | mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | |
2755 | SDMMC_INT_TXDR | SDMMC_INT_RXDR | | 2887 | SDMMC_INT_TXDR | SDMMC_INT_RXDR | |
2756 | DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); | 2888 | DW_MCI_ERROR_FLAGS); |
2757 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ | 2889 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ |
2758 | 2890 | ||
2759 | dev_info(host->dev, "DW MMC controller at irq %d, " | 2891 | dev_info(host->dev, "DW MMC controller at irq %d, " |
@@ -2778,6 +2910,9 @@ int dw_mci_probe(struct dw_mci *host) | |||
2778 | goto err_dmaunmap; | 2910 | goto err_dmaunmap; |
2779 | } | 2911 | } |
2780 | 2912 | ||
2913 | /* Now that slots are all setup, we can enable card detect */ | ||
2914 | dw_mci_enable_cd(host); | ||
2915 | |||
2781 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) | 2916 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) |
2782 | dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); | 2917 | dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); |
2783 | 2918 | ||
@@ -2864,7 +2999,7 @@ int dw_mci_resume(struct dw_mci *host) | |||
2864 | mci_writel(host, RINTSTS, 0xFFFFFFFF); | 2999 | mci_writel(host, RINTSTS, 0xFFFFFFFF); |
2865 | mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | | 3000 | mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | |
2866 | SDMMC_INT_TXDR | SDMMC_INT_RXDR | | 3001 | SDMMC_INT_TXDR | SDMMC_INT_RXDR | |
2867 | DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); | 3002 | DW_MCI_ERROR_FLAGS); |
2868 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); | 3003 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); |
2869 | 3004 | ||
2870 | for (i = 0; i < host->num_slots; i++) { | 3005 | for (i = 0; i < host->num_slots; i++) { |
@@ -2876,6 +3011,10 @@ int dw_mci_resume(struct dw_mci *host) | |||
2876 | dw_mci_setup_bus(slot, true); | 3011 | dw_mci_setup_bus(slot, true); |
2877 | } | 3012 | } |
2878 | } | 3013 | } |
3014 | |||
3015 | /* Now that slots are all setup, we can enable card detect */ | ||
3016 | dw_mci_enable_cd(host); | ||
3017 | |||
2879 | return 0; | 3018 | return 0; |
2880 | } | 3019 | } |
2881 | EXPORT_SYMBOL(dw_mci_resume); | 3020 | EXPORT_SYMBOL(dw_mci_resume); |
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 18c4afe683b8..f45ab91de339 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
@@ -169,24 +169,34 @@ | |||
169 | #define SDMMC_CTRL_ALL_RESET_FLAGS \ | 169 | #define SDMMC_CTRL_ALL_RESET_FLAGS \ |
170 | (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET) | 170 | (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET) |
171 | 171 | ||
172 | /* FIFO register access macros. These should not change the data endian-ness | ||
173 | * as they are written to memory to be dealt with by the upper layers */ | ||
174 | #define mci_fifo_readw(__reg) __raw_readw(__reg) | ||
175 | #define mci_fifo_readl(__reg) __raw_readl(__reg) | ||
176 | #define mci_fifo_readq(__reg) __raw_readq(__reg) | ||
177 | |||
178 | #define mci_fifo_writew(__value, __reg) __raw_writew(__reg, __value) | ||
179 | #define mci_fifo_writel(__value, __reg) __raw_writel(__reg, __value) | ||
180 | #define mci_fifo_writeq(__value, __reg) __raw_writeq(__reg, __value) | ||
181 | |||
172 | /* Register access macros */ | 182 | /* Register access macros */ |
173 | #define mci_readl(dev, reg) \ | 183 | #define mci_readl(dev, reg) \ |
174 | __raw_readl((dev)->regs + SDMMC_##reg) | 184 | readl_relaxed((dev)->regs + SDMMC_##reg) |
175 | #define mci_writel(dev, reg, value) \ | 185 | #define mci_writel(dev, reg, value) \ |
176 | __raw_writel((value), (dev)->regs + SDMMC_##reg) | 186 | writel_relaxed((value), (dev)->regs + SDMMC_##reg) |
177 | 187 | ||
178 | /* 16-bit FIFO access macros */ | 188 | /* 16-bit FIFO access macros */ |
179 | #define mci_readw(dev, reg) \ | 189 | #define mci_readw(dev, reg) \ |
180 | __raw_readw((dev)->regs + SDMMC_##reg) | 190 | readw_relaxed((dev)->regs + SDMMC_##reg) |
181 | #define mci_writew(dev, reg, value) \ | 191 | #define mci_writew(dev, reg, value) \ |
182 | __raw_writew((value), (dev)->regs + SDMMC_##reg) | 192 | writew_relaxed((value), (dev)->regs + SDMMC_##reg) |
183 | 193 | ||
184 | /* 64-bit FIFO access macros */ | 194 | /* 64-bit FIFO access macros */ |
185 | #ifdef readq | 195 | #ifdef readq |
186 | #define mci_readq(dev, reg) \ | 196 | #define mci_readq(dev, reg) \ |
187 | __raw_readq((dev)->regs + SDMMC_##reg) | 197 | readq_relaxed((dev)->regs + SDMMC_##reg) |
188 | #define mci_writeq(dev, reg, value) \ | 198 | #define mci_writeq(dev, reg, value) \ |
189 | __raw_writeq((value), (dev)->regs + SDMMC_##reg) | 199 | writeq_relaxed((value), (dev)->regs + SDMMC_##reg) |
190 | #else | 200 | #else |
191 | /* | 201 | /* |
192 | * Dummy readq implementation for architectures that don't define it. | 202 | * Dummy readq implementation for architectures that don't define it. |
@@ -200,6 +210,10 @@ | |||
200 | (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg)) | 210 | (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg)) |
201 | #define mci_writeq(dev, reg, value) \ | 211 | #define mci_writeq(dev, reg, value) \ |
202 | (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value)) | 212 | (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value)) |
213 | |||
214 | #define __raw_writeq(__value, __reg) \ | ||
215 | (*(volatile u64 __force *)(__reg) = (__value)) | ||
216 | #define __raw_readq(__reg) (*(volatile u64 __force *)(__reg)) | ||
203 | #endif | 217 | #endif |
204 | 218 | ||
205 | extern int dw_mci_probe(struct dw_mci *host); | 219 | extern int dw_mci_probe(struct dw_mci *host); |
@@ -271,5 +285,7 @@ struct dw_mci_drv_data { | |||
271 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); | 285 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); |
272 | int (*parse_dt)(struct dw_mci *host); | 286 | int (*parse_dt)(struct dw_mci *host); |
273 | int (*execute_tuning)(struct dw_mci_slot *slot); | 287 | int (*execute_tuning)(struct dw_mci_slot *slot); |
288 | int (*prepare_hs400_tuning)(struct dw_mci *host, | ||
289 | struct mmc_ios *ios); | ||
274 | }; | 290 | }; |
275 | #endif /* _DW_MMC_H_ */ | 291 | #endif /* _DW_MMC_H_ */ |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index e4a07546f8b6..ae19d83bb9de 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -1507,7 +1507,7 @@ static int mmc_spi_remove(struct spi_device *spi) | |||
1507 | return 0; | 1507 | return 0; |
1508 | } | 1508 | } |
1509 | 1509 | ||
1510 | static struct of_device_id mmc_spi_of_match_table[] = { | 1510 | static const struct of_device_id mmc_spi_of_match_table[] = { |
1511 | { .compatible = "mmc-spi-slot", }, | 1511 | { .compatible = "mmc-spi-slot", }, |
1512 | {}, | 1512 | {}, |
1513 | }; | 1513 | }; |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 7fe16194ebc8..fb266745f824 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -1613,7 +1613,10 @@ static int mmci_probe(struct amba_device *dev, | |||
1613 | dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); | 1613 | dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); |
1614 | 1614 | ||
1615 | /* Get regulators and the supported OCR mask */ | 1615 | /* Get regulators and the supported OCR mask */ |
1616 | mmc_regulator_get_supply(mmc); | 1616 | ret = mmc_regulator_get_supply(mmc); |
1617 | if (ret == -EPROBE_DEFER) | ||
1618 | goto clk_disable; | ||
1619 | |||
1617 | if (!mmc->ocr_avail) | 1620 | if (!mmc->ocr_avail) |
1618 | mmc->ocr_avail = plat->ocr_mask; | 1621 | mmc->ocr_avail = plat->ocr_mask; |
1619 | else if (plat->ocr_mask) | 1622 | else if (plat->ocr_mask) |
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c deleted file mode 100644 index 90c60fd4ff6e..000000000000 --- a/drivers/mmc/host/msm_sdcc.c +++ /dev/null | |||
@@ -1,1474 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/mmc/host/msm_sdcc.c - Qualcomm MSM 7X00A SDCC Driver | ||
3 | * | ||
4 | * Copyright (C) 2007 Google Inc, | ||
5 | * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. | ||
6 | * Copyright (C) 2009, Code Aurora Forum. All Rights Reserved. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Based on mmci.c | ||
13 | * | ||
14 | * Author: San Mehat (san@android.com) | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/highmem.h> | ||
27 | #include <linux/log2.h> | ||
28 | #include <linux/mmc/host.h> | ||
29 | #include <linux/mmc/card.h> | ||
30 | #include <linux/mmc/sdio.h> | ||
31 | #include <linux/clk.h> | ||
32 | #include <linux/scatterlist.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/dma-mapping.h> | ||
35 | #include <linux/debugfs.h> | ||
36 | #include <linux/io.h> | ||
37 | #include <linux/memory.h> | ||
38 | #include <linux/gfp.h> | ||
39 | #include <linux/gpio.h> | ||
40 | |||
41 | #include <asm/cacheflush.h> | ||
42 | #include <asm/div64.h> | ||
43 | #include <asm/sizes.h> | ||
44 | |||
45 | #include <linux/platform_data/mmc-msm_sdcc.h> | ||
46 | #include <mach/dma.h> | ||
47 | #include <mach/clk.h> | ||
48 | |||
49 | #include "msm_sdcc.h" | ||
50 | |||
51 | #define DRIVER_NAME "msm-sdcc" | ||
52 | |||
53 | #define BUSCLK_PWRSAVE 1 | ||
54 | #define BUSCLK_TIMEOUT (HZ) | ||
55 | static unsigned int msmsdcc_fmin = 144000; | ||
56 | static unsigned int msmsdcc_fmax = 50000000; | ||
57 | static unsigned int msmsdcc_4bit = 1; | ||
58 | static unsigned int msmsdcc_pwrsave = 1; | ||
59 | static unsigned int msmsdcc_piopoll = 1; | ||
60 | static unsigned int msmsdcc_sdioirq; | ||
61 | |||
62 | #define PIO_SPINMAX 30 | ||
63 | #define CMD_SPINMAX 20 | ||
64 | |||
65 | |||
66 | static inline void | ||
67 | msmsdcc_disable_clocks(struct msmsdcc_host *host, int deferr) | ||
68 | { | ||
69 | WARN_ON(!host->clks_on); | ||
70 | |||
71 | BUG_ON(host->curr.mrq); | ||
72 | |||
73 | if (deferr) { | ||
74 | mod_timer(&host->busclk_timer, jiffies + BUSCLK_TIMEOUT); | ||
75 | } else { | ||
76 | del_timer_sync(&host->busclk_timer); | ||
77 | /* Need to check clks_on again in case the busclk | ||
78 | * timer fired | ||
79 | */ | ||
80 | if (host->clks_on) { | ||
81 | clk_disable(host->clk); | ||
82 | clk_disable(host->pclk); | ||
83 | host->clks_on = 0; | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static inline int | ||
89 | msmsdcc_enable_clocks(struct msmsdcc_host *host) | ||
90 | { | ||
91 | int rc; | ||
92 | |||
93 | del_timer_sync(&host->busclk_timer); | ||
94 | |||
95 | if (!host->clks_on) { | ||
96 | rc = clk_enable(host->pclk); | ||
97 | if (rc) | ||
98 | return rc; | ||
99 | rc = clk_enable(host->clk); | ||
100 | if (rc) { | ||
101 | clk_disable(host->pclk); | ||
102 | return rc; | ||
103 | } | ||
104 | udelay(1 + ((3 * USEC_PER_SEC) / | ||
105 | (host->clk_rate ? host->clk_rate : msmsdcc_fmin))); | ||
106 | host->clks_on = 1; | ||
107 | } | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static inline unsigned int | ||
112 | msmsdcc_readl(struct msmsdcc_host *host, unsigned int reg) | ||
113 | { | ||
114 | return readl(host->base + reg); | ||
115 | } | ||
116 | |||
117 | static inline void | ||
118 | msmsdcc_writel(struct msmsdcc_host *host, u32 data, unsigned int reg) | ||
119 | { | ||
120 | writel(data, host->base + reg); | ||
121 | /* 3 clk delay required! */ | ||
122 | udelay(1 + ((3 * USEC_PER_SEC) / | ||
123 | (host->clk_rate ? host->clk_rate : msmsdcc_fmin))); | ||
124 | } | ||
125 | |||
126 | static void | ||
127 | msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, | ||
128 | u32 c); | ||
129 | |||
130 | static void msmsdcc_reset_and_restore(struct msmsdcc_host *host) | ||
131 | { | ||
132 | u32 mci_clk = 0; | ||
133 | u32 mci_mask0 = 0; | ||
134 | int ret = 0; | ||
135 | |||
136 | /* Save the controller state */ | ||
137 | mci_clk = readl(host->base + MMCICLOCK); | ||
138 | mci_mask0 = readl(host->base + MMCIMASK0); | ||
139 | |||
140 | /* Reset the controller */ | ||
141 | ret = clk_reset(host->clk, CLK_RESET_ASSERT); | ||
142 | if (ret) | ||
143 | pr_err("%s: Clock assert failed at %u Hz with err %d\n", | ||
144 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
145 | |||
146 | ret = clk_reset(host->clk, CLK_RESET_DEASSERT); | ||
147 | if (ret) | ||
148 | pr_err("%s: Clock deassert failed at %u Hz with err %d\n", | ||
149 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
150 | |||
151 | pr_info("%s: Controller has been re-initialiazed\n", | ||
152 | mmc_hostname(host->mmc)); | ||
153 | |||
154 | /* Restore the contoller state */ | ||
155 | writel(host->pwr, host->base + MMCIPOWER); | ||
156 | writel(mci_clk, host->base + MMCICLOCK); | ||
157 | writel(mci_mask0, host->base + MMCIMASK0); | ||
158 | ret = clk_set_rate(host->clk, host->clk_rate); | ||
159 | if (ret) | ||
160 | pr_err("%s: Failed to set clk rate %u Hz (%d)\n", | ||
161 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
162 | } | ||
163 | |||
164 | static void | ||
165 | msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq) | ||
166 | { | ||
167 | BUG_ON(host->curr.data); | ||
168 | |||
169 | host->curr.mrq = NULL; | ||
170 | host->curr.cmd = NULL; | ||
171 | |||
172 | if (mrq->data) | ||
173 | mrq->data->bytes_xfered = host->curr.data_xfered; | ||
174 | if (mrq->cmd->error == -ETIMEDOUT) | ||
175 | mdelay(5); | ||
176 | |||
177 | #if BUSCLK_PWRSAVE | ||
178 | msmsdcc_disable_clocks(host, 1); | ||
179 | #endif | ||
180 | /* | ||
181 | * Need to drop the host lock here; mmc_request_done may call | ||
182 | * back into the driver... | ||
183 | */ | ||
184 | spin_unlock(&host->lock); | ||
185 | mmc_request_done(host->mmc, mrq); | ||
186 | spin_lock(&host->lock); | ||
187 | } | ||
188 | |||
189 | static void | ||
190 | msmsdcc_stop_data(struct msmsdcc_host *host) | ||
191 | { | ||
192 | host->curr.data = NULL; | ||
193 | host->curr.got_dataend = 0; | ||
194 | } | ||
195 | |||
196 | uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host) | ||
197 | { | ||
198 | return host->memres->start + MMCIFIFO; | ||
199 | } | ||
200 | |||
201 | static inline void | ||
202 | msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c) { | ||
203 | msmsdcc_writel(host, arg, MMCIARGUMENT); | ||
204 | msmsdcc_writel(host, c, MMCICOMMAND); | ||
205 | } | ||
206 | |||
207 | static void | ||
208 | msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd) | ||
209 | { | ||
210 | struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->data; | ||
211 | |||
212 | msmsdcc_writel(host, host->cmd_timeout, MMCIDATATIMER); | ||
213 | msmsdcc_writel(host, (unsigned int)host->curr.xfer_size, | ||
214 | MMCIDATALENGTH); | ||
215 | msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) & | ||
216 | (~MCI_IRQ_PIO)) | host->cmd_pio_irqmask, MMCIMASK0); | ||
217 | msmsdcc_writel(host, host->cmd_datactrl, MMCIDATACTRL); | ||
218 | |||
219 | if (host->cmd_cmd) { | ||
220 | msmsdcc_start_command_exec(host, | ||
221 | (u32) host->cmd_cmd->arg, | ||
222 | (u32) host->cmd_c); | ||
223 | } | ||
224 | host->dma.active = 1; | ||
225 | } | ||
226 | |||
227 | static void | ||
228 | msmsdcc_dma_complete_tlet(unsigned long data) | ||
229 | { | ||
230 | struct msmsdcc_host *host = (struct msmsdcc_host *)data; | ||
231 | unsigned long flags; | ||
232 | struct mmc_request *mrq; | ||
233 | struct msm_dmov_errdata err; | ||
234 | |||
235 | spin_lock_irqsave(&host->lock, flags); | ||
236 | host->dma.active = 0; | ||
237 | |||
238 | err = host->dma.err; | ||
239 | mrq = host->curr.mrq; | ||
240 | BUG_ON(!mrq); | ||
241 | WARN_ON(!mrq->data); | ||
242 | |||
243 | if (!(host->dma.result & DMOV_RSLT_VALID)) { | ||
244 | pr_err("msmsdcc: Invalid DataMover result\n"); | ||
245 | goto out; | ||
246 | } | ||
247 | |||
248 | if (host->dma.result & DMOV_RSLT_DONE) { | ||
249 | host->curr.data_xfered = host->curr.xfer_size; | ||
250 | } else { | ||
251 | /* Error or flush */ | ||
252 | if (host->dma.result & DMOV_RSLT_ERROR) | ||
253 | pr_err("%s: DMA error (0x%.8x)\n", | ||
254 | mmc_hostname(host->mmc), host->dma.result); | ||
255 | if (host->dma.result & DMOV_RSLT_FLUSH) | ||
256 | pr_err("%s: DMA channel flushed (0x%.8x)\n", | ||
257 | mmc_hostname(host->mmc), host->dma.result); | ||
258 | |||
259 | pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n", | ||
260 | err.flush[0], err.flush[1], err.flush[2], | ||
261 | err.flush[3], err.flush[4], err.flush[5]); | ||
262 | |||
263 | msmsdcc_reset_and_restore(host); | ||
264 | if (!mrq->data->error) | ||
265 | mrq->data->error = -EIO; | ||
266 | } | ||
267 | dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents, | ||
268 | host->dma.dir); | ||
269 | |||
270 | host->dma.sg = NULL; | ||
271 | host->dma.busy = 0; | ||
272 | |||
273 | if (host->curr.got_dataend || mrq->data->error) { | ||
274 | |||
275 | /* | ||
276 | * If we've already gotten our DATAEND / DATABLKEND | ||
277 | * for this request, then complete it through here. | ||
278 | */ | ||
279 | msmsdcc_stop_data(host); | ||
280 | |||
281 | if (!mrq->data->error) | ||
282 | host->curr.data_xfered = host->curr.xfer_size; | ||
283 | if (!mrq->data->stop || mrq->cmd->error) { | ||
284 | host->curr.mrq = NULL; | ||
285 | host->curr.cmd = NULL; | ||
286 | mrq->data->bytes_xfered = host->curr.data_xfered; | ||
287 | |||
288 | spin_unlock_irqrestore(&host->lock, flags); | ||
289 | #if BUSCLK_PWRSAVE | ||
290 | msmsdcc_disable_clocks(host, 1); | ||
291 | #endif | ||
292 | mmc_request_done(host->mmc, mrq); | ||
293 | return; | ||
294 | } else | ||
295 | msmsdcc_start_command(host, mrq->data->stop, 0); | ||
296 | } | ||
297 | |||
298 | out: | ||
299 | spin_unlock_irqrestore(&host->lock, flags); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | static void | ||
304 | msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, | ||
305 | unsigned int result, | ||
306 | struct msm_dmov_errdata *err) | ||
307 | { | ||
308 | struct msmsdcc_dma_data *dma_data = | ||
309 | container_of(cmd, struct msmsdcc_dma_data, hdr); | ||
310 | struct msmsdcc_host *host = dma_data->host; | ||
311 | |||
312 | dma_data->result = result; | ||
313 | if (err) | ||
314 | memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata)); | ||
315 | |||
316 | tasklet_schedule(&host->dma_tlet); | ||
317 | } | ||
318 | |||
319 | static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data) | ||
320 | { | ||
321 | if (host->dma.channel == -1) | ||
322 | return -ENOENT; | ||
323 | |||
324 | if ((data->blksz * data->blocks) < MCI_FIFOSIZE) | ||
325 | return -EINVAL; | ||
326 | if ((data->blksz * data->blocks) % MCI_FIFOSIZE) | ||
327 | return -EINVAL; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data) | ||
332 | { | ||
333 | struct msmsdcc_nc_dmadata *nc; | ||
334 | dmov_box *box; | ||
335 | uint32_t rows; | ||
336 | uint32_t crci; | ||
337 | unsigned int n; | ||
338 | int i, rc; | ||
339 | struct scatterlist *sg = data->sg; | ||
340 | |||
341 | rc = validate_dma(host, data); | ||
342 | if (rc) | ||
343 | return rc; | ||
344 | |||
345 | host->dma.sg = data->sg; | ||
346 | host->dma.num_ents = data->sg_len; | ||
347 | |||
348 | BUG_ON(host->dma.num_ents > NR_SG); /* Prevent memory corruption */ | ||
349 | |||
350 | nc = host->dma.nc; | ||
351 | |||
352 | switch (host->pdev_id) { | ||
353 | case 1: | ||
354 | crci = MSMSDCC_CRCI_SDC1; | ||
355 | break; | ||
356 | case 2: | ||
357 | crci = MSMSDCC_CRCI_SDC2; | ||
358 | break; | ||
359 | case 3: | ||
360 | crci = MSMSDCC_CRCI_SDC3; | ||
361 | break; | ||
362 | case 4: | ||
363 | crci = MSMSDCC_CRCI_SDC4; | ||
364 | break; | ||
365 | default: | ||
366 | host->dma.sg = NULL; | ||
367 | host->dma.num_ents = 0; | ||
368 | return -ENOENT; | ||
369 | } | ||
370 | |||
371 | if (data->flags & MMC_DATA_READ) | ||
372 | host->dma.dir = DMA_FROM_DEVICE; | ||
373 | else | ||
374 | host->dma.dir = DMA_TO_DEVICE; | ||
375 | |||
376 | host->curr.user_pages = 0; | ||
377 | |||
378 | box = &nc->cmd[0]; | ||
379 | |||
380 | /* location of command block must be 64 bit aligned */ | ||
381 | BUG_ON(host->dma.cmd_busaddr & 0x07); | ||
382 | |||
383 | nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP; | ||
384 | host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST | | ||
385 | DMOV_CMD_ADDR(host->dma.cmdptr_busaddr); | ||
386 | host->dma.hdr.complete_func = msmsdcc_dma_complete_func; | ||
387 | |||
388 | n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg, | ||
389 | host->dma.num_ents, host->dma.dir); | ||
390 | if (n == 0) { | ||
391 | pr_err("%s: Unable to map in all sg elements\n", | ||
392 | mmc_hostname(host->mmc)); | ||
393 | host->dma.sg = NULL; | ||
394 | host->dma.num_ents = 0; | ||
395 | return -ENOMEM; | ||
396 | } | ||
397 | |||
398 | for_each_sg(host->dma.sg, sg, n, i) { | ||
399 | |||
400 | box->cmd = CMD_MODE_BOX; | ||
401 | |||
402 | if (i == n - 1) | ||
403 | box->cmd |= CMD_LC; | ||
404 | rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ? | ||
405 | (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 : | ||
406 | (sg_dma_len(sg) / MCI_FIFOSIZE) ; | ||
407 | |||
408 | if (data->flags & MMC_DATA_READ) { | ||
409 | box->src_row_addr = msmsdcc_fifo_addr(host); | ||
410 | box->dst_row_addr = sg_dma_address(sg); | ||
411 | |||
412 | box->src_dst_len = (MCI_FIFOSIZE << 16) | | ||
413 | (MCI_FIFOSIZE); | ||
414 | box->row_offset = MCI_FIFOSIZE; | ||
415 | |||
416 | box->num_rows = rows * ((1 << 16) + 1); | ||
417 | box->cmd |= CMD_SRC_CRCI(crci); | ||
418 | } else { | ||
419 | box->src_row_addr = sg_dma_address(sg); | ||
420 | box->dst_row_addr = msmsdcc_fifo_addr(host); | ||
421 | |||
422 | box->src_dst_len = (MCI_FIFOSIZE << 16) | | ||
423 | (MCI_FIFOSIZE); | ||
424 | box->row_offset = (MCI_FIFOSIZE << 16); | ||
425 | |||
426 | box->num_rows = rows * ((1 << 16) + 1); | ||
427 | box->cmd |= CMD_DST_CRCI(crci); | ||
428 | } | ||
429 | box++; | ||
430 | } | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static int | ||
436 | snoop_cccr_abort(struct mmc_command *cmd) | ||
437 | { | ||
438 | if ((cmd->opcode == 52) && | ||
439 | (cmd->arg & 0x80000000) && | ||
440 | (((cmd->arg >> 9) & 0x1ffff) == SDIO_CCCR_ABORT)) | ||
441 | return 1; | ||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | static void | ||
446 | msmsdcc_start_command_deferred(struct msmsdcc_host *host, | ||
447 | struct mmc_command *cmd, u32 *c) | ||
448 | { | ||
449 | *c |= (cmd->opcode | MCI_CPSM_ENABLE); | ||
450 | |||
451 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
452 | if (cmd->flags & MMC_RSP_136) | ||
453 | *c |= MCI_CPSM_LONGRSP; | ||
454 | *c |= MCI_CPSM_RESPONSE; | ||
455 | } | ||
456 | |||
457 | if (/*interrupt*/0) | ||
458 | *c |= MCI_CPSM_INTERRUPT; | ||
459 | |||
460 | if ((((cmd->opcode == 17) || (cmd->opcode == 18)) || | ||
461 | ((cmd->opcode == 24) || (cmd->opcode == 25))) || | ||
462 | (cmd->opcode == 53)) | ||
463 | *c |= MCI_CSPM_DATCMD; | ||
464 | |||
465 | if (host->prog_scan && (cmd->opcode == 12)) { | ||
466 | *c |= MCI_CPSM_PROGENA; | ||
467 | host->prog_enable = true; | ||
468 | } | ||
469 | |||
470 | if (cmd == cmd->mrq->stop) | ||
471 | *c |= MCI_CSPM_MCIABORT; | ||
472 | |||
473 | if (snoop_cccr_abort(cmd)) | ||
474 | *c |= MCI_CSPM_MCIABORT; | ||
475 | |||
476 | if (host->curr.cmd != NULL) { | ||
477 | pr_err("%s: Overlapping command requests\n", | ||
478 | mmc_hostname(host->mmc)); | ||
479 | } | ||
480 | host->curr.cmd = cmd; | ||
481 | } | ||
482 | |||
483 | static void | ||
484 | msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data, | ||
485 | struct mmc_command *cmd, u32 c) | ||
486 | { | ||
487 | unsigned int datactrl, timeout; | ||
488 | unsigned long long clks; | ||
489 | unsigned int pio_irqmask = 0; | ||
490 | |||
491 | host->curr.data = data; | ||
492 | host->curr.xfer_size = data->blksz * data->blocks; | ||
493 | host->curr.xfer_remain = host->curr.xfer_size; | ||
494 | host->curr.data_xfered = 0; | ||
495 | host->curr.got_dataend = 0; | ||
496 | |||
497 | memset(&host->pio, 0, sizeof(host->pio)); | ||
498 | |||
499 | datactrl = MCI_DPSM_ENABLE | (data->blksz << 4); | ||
500 | |||
501 | if (!msmsdcc_config_dma(host, data)) | ||
502 | datactrl |= MCI_DPSM_DMAENABLE; | ||
503 | else { | ||
504 | host->pio.sg = data->sg; | ||
505 | host->pio.sg_len = data->sg_len; | ||
506 | host->pio.sg_off = 0; | ||
507 | |||
508 | if (data->flags & MMC_DATA_READ) { | ||
509 | pio_irqmask = MCI_RXFIFOHALFFULLMASK; | ||
510 | if (host->curr.xfer_remain < MCI_FIFOSIZE) | ||
511 | pio_irqmask |= MCI_RXDATAAVLBLMASK; | ||
512 | } else | ||
513 | pio_irqmask = MCI_TXFIFOHALFEMPTYMASK; | ||
514 | } | ||
515 | |||
516 | if (data->flags & MMC_DATA_READ) | ||
517 | datactrl |= MCI_DPSM_DIRECTION; | ||
518 | |||
519 | clks = (unsigned long long)data->timeout_ns * host->clk_rate; | ||
520 | do_div(clks, NSEC_PER_SEC); | ||
521 | timeout = data->timeout_clks + (unsigned int)clks*2 ; | ||
522 | |||
523 | if (datactrl & MCI_DPSM_DMAENABLE) { | ||
524 | /* Save parameters for the exec function */ | ||
525 | host->cmd_timeout = timeout; | ||
526 | host->cmd_pio_irqmask = pio_irqmask; | ||
527 | host->cmd_datactrl = datactrl; | ||
528 | host->cmd_cmd = cmd; | ||
529 | |||
530 | host->dma.hdr.execute_func = msmsdcc_dma_exec_func; | ||
531 | host->dma.hdr.data = (void *)host; | ||
532 | host->dma.busy = 1; | ||
533 | |||
534 | if (cmd) { | ||
535 | msmsdcc_start_command_deferred(host, cmd, &c); | ||
536 | host->cmd_c = c; | ||
537 | } | ||
538 | msm_dmov_enqueue_cmd(host->dma.channel, &host->dma.hdr); | ||
539 | if (data->flags & MMC_DATA_WRITE) | ||
540 | host->prog_scan = true; | ||
541 | } else { | ||
542 | msmsdcc_writel(host, timeout, MMCIDATATIMER); | ||
543 | |||
544 | msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH); | ||
545 | |||
546 | msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) & | ||
547 | (~MCI_IRQ_PIO)) | pio_irqmask, MMCIMASK0); | ||
548 | |||
549 | msmsdcc_writel(host, datactrl, MMCIDATACTRL); | ||
550 | |||
551 | if (cmd) { | ||
552 | /* Daisy-chain the command if requested */ | ||
553 | msmsdcc_start_command(host, cmd, c); | ||
554 | } | ||
555 | } | ||
556 | } | ||
557 | |||
558 | static void | ||
559 | msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c) | ||
560 | { | ||
561 | if (cmd == cmd->mrq->stop) | ||
562 | c |= MCI_CSPM_MCIABORT; | ||
563 | |||
564 | host->stats.cmds++; | ||
565 | |||
566 | msmsdcc_start_command_deferred(host, cmd, &c); | ||
567 | msmsdcc_start_command_exec(host, cmd->arg, c); | ||
568 | } | ||
569 | |||
570 | static void | ||
571 | msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data, | ||
572 | unsigned int status) | ||
573 | { | ||
574 | if (status & MCI_DATACRCFAIL) { | ||
575 | pr_err("%s: Data CRC error\n", mmc_hostname(host->mmc)); | ||
576 | pr_err("%s: opcode 0x%.8x\n", __func__, | ||
577 | data->mrq->cmd->opcode); | ||
578 | pr_err("%s: blksz %d, blocks %d\n", __func__, | ||
579 | data->blksz, data->blocks); | ||
580 | data->error = -EILSEQ; | ||
581 | } else if (status & MCI_DATATIMEOUT) { | ||
582 | pr_err("%s: Data timeout\n", mmc_hostname(host->mmc)); | ||
583 | data->error = -ETIMEDOUT; | ||
584 | } else if (status & MCI_RXOVERRUN) { | ||
585 | pr_err("%s: RX overrun\n", mmc_hostname(host->mmc)); | ||
586 | data->error = -EIO; | ||
587 | } else if (status & MCI_TXUNDERRUN) { | ||
588 | pr_err("%s: TX underrun\n", mmc_hostname(host->mmc)); | ||
589 | data->error = -EIO; | ||
590 | } else { | ||
591 | pr_err("%s: Unknown error (0x%.8x)\n", | ||
592 | mmc_hostname(host->mmc), status); | ||
593 | data->error = -EIO; | ||
594 | } | ||
595 | } | ||
596 | |||
597 | |||
598 | static int | ||
599 | msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain) | ||
600 | { | ||
601 | uint32_t *ptr = (uint32_t *) buffer; | ||
602 | int count = 0; | ||
603 | |||
604 | if (remain % 4) | ||
605 | remain = ((remain >> 2) + 1) << 2; | ||
606 | |||
607 | while (msmsdcc_readl(host, MMCISTATUS) & MCI_RXDATAAVLBL) { | ||
608 | *ptr = msmsdcc_readl(host, MMCIFIFO + (count % MCI_FIFOSIZE)); | ||
609 | ptr++; | ||
610 | count += sizeof(uint32_t); | ||
611 | |||
612 | remain -= sizeof(uint32_t); | ||
613 | if (remain == 0) | ||
614 | break; | ||
615 | } | ||
616 | return count; | ||
617 | } | ||
618 | |||
619 | static int | ||
620 | msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer, | ||
621 | unsigned int remain, u32 status) | ||
622 | { | ||
623 | void __iomem *base = host->base; | ||
624 | char *ptr = buffer; | ||
625 | |||
626 | do { | ||
627 | unsigned int count, maxcnt, sz; | ||
628 | |||
629 | maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : | ||
630 | MCI_FIFOHALFSIZE; | ||
631 | count = min(remain, maxcnt); | ||
632 | |||
633 | sz = count % 4 ? (count >> 2) + 1 : (count >> 2); | ||
634 | writesl(base + MMCIFIFO, ptr, sz); | ||
635 | ptr += count; | ||
636 | remain -= count; | ||
637 | |||
638 | if (remain == 0) | ||
639 | break; | ||
640 | |||
641 | status = msmsdcc_readl(host, MMCISTATUS); | ||
642 | } while (status & MCI_TXFIFOHALFEMPTY); | ||
643 | |||
644 | return ptr - buffer; | ||
645 | } | ||
646 | |||
647 | static int | ||
648 | msmsdcc_spin_on_status(struct msmsdcc_host *host, uint32_t mask, int maxspin) | ||
649 | { | ||
650 | while (maxspin) { | ||
651 | if ((msmsdcc_readl(host, MMCISTATUS) & mask)) | ||
652 | return 0; | ||
653 | udelay(1); | ||
654 | --maxspin; | ||
655 | } | ||
656 | return -ETIMEDOUT; | ||
657 | } | ||
658 | |||
659 | static irqreturn_t | ||
660 | msmsdcc_pio_irq(int irq, void *dev_id) | ||
661 | { | ||
662 | struct msmsdcc_host *host = dev_id; | ||
663 | uint32_t status; | ||
664 | u32 mci_mask0; | ||
665 | |||
666 | status = msmsdcc_readl(host, MMCISTATUS); | ||
667 | mci_mask0 = msmsdcc_readl(host, MMCIMASK0); | ||
668 | |||
669 | if (((mci_mask0 & status) & MCI_IRQ_PIO) == 0) | ||
670 | return IRQ_NONE; | ||
671 | |||
672 | do { | ||
673 | unsigned long flags; | ||
674 | unsigned int remain, len; | ||
675 | char *buffer; | ||
676 | |||
677 | if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL))) { | ||
678 | if (host->curr.xfer_remain == 0 || !msmsdcc_piopoll) | ||
679 | break; | ||
680 | |||
681 | if (msmsdcc_spin_on_status(host, | ||
682 | (MCI_TXFIFOHALFEMPTY | | ||
683 | MCI_RXDATAAVLBL), | ||
684 | PIO_SPINMAX)) { | ||
685 | break; | ||
686 | } | ||
687 | } | ||
688 | |||
689 | /* Map the current scatter buffer */ | ||
690 | local_irq_save(flags); | ||
691 | buffer = kmap_atomic(sg_page(host->pio.sg)) | ||
692 | + host->pio.sg->offset; | ||
693 | buffer += host->pio.sg_off; | ||
694 | remain = host->pio.sg->length - host->pio.sg_off; | ||
695 | len = 0; | ||
696 | if (status & MCI_RXACTIVE) | ||
697 | len = msmsdcc_pio_read(host, buffer, remain); | ||
698 | if (status & MCI_TXACTIVE) | ||
699 | len = msmsdcc_pio_write(host, buffer, remain, status); | ||
700 | |||
701 | /* Unmap the buffer */ | ||
702 | kunmap_atomic(buffer); | ||
703 | local_irq_restore(flags); | ||
704 | |||
705 | host->pio.sg_off += len; | ||
706 | host->curr.xfer_remain -= len; | ||
707 | host->curr.data_xfered += len; | ||
708 | remain -= len; | ||
709 | |||
710 | if (remain == 0) { | ||
711 | /* This sg page is full - do some housekeeping */ | ||
712 | if (status & MCI_RXACTIVE && host->curr.user_pages) | ||
713 | flush_dcache_page(sg_page(host->pio.sg)); | ||
714 | |||
715 | if (!--host->pio.sg_len) { | ||
716 | memset(&host->pio, 0, sizeof(host->pio)); | ||
717 | break; | ||
718 | } | ||
719 | |||
720 | /* Advance to next sg */ | ||
721 | host->pio.sg++; | ||
722 | host->pio.sg_off = 0; | ||
723 | } | ||
724 | |||
725 | status = msmsdcc_readl(host, MMCISTATUS); | ||
726 | } while (1); | ||
727 | |||
728 | if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) | ||
729 | msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) | | ||
730 | MCI_RXDATAAVLBLMASK, MMCIMASK0); | ||
731 | |||
732 | if (!host->curr.xfer_remain) | ||
733 | msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) | 0, | ||
734 | MMCIMASK0); | ||
735 | |||
736 | return IRQ_HANDLED; | ||
737 | } | ||
738 | |||
739 | static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status) | ||
740 | { | ||
741 | struct mmc_command *cmd = host->curr.cmd; | ||
742 | |||
743 | host->curr.cmd = NULL; | ||
744 | cmd->resp[0] = msmsdcc_readl(host, MMCIRESPONSE0); | ||
745 | cmd->resp[1] = msmsdcc_readl(host, MMCIRESPONSE1); | ||
746 | cmd->resp[2] = msmsdcc_readl(host, MMCIRESPONSE2); | ||
747 | cmd->resp[3] = msmsdcc_readl(host, MMCIRESPONSE3); | ||
748 | |||
749 | if (status & MCI_CMDTIMEOUT) { | ||
750 | cmd->error = -ETIMEDOUT; | ||
751 | } else if (status & MCI_CMDCRCFAIL && | ||
752 | cmd->flags & MMC_RSP_CRC) { | ||
753 | pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc)); | ||
754 | cmd->error = -EILSEQ; | ||
755 | } | ||
756 | |||
757 | if (!cmd->data || cmd->error) { | ||
758 | if (host->curr.data && host->dma.sg) | ||
759 | msm_dmov_stop_cmd(host->dma.channel, | ||
760 | &host->dma.hdr, 0); | ||
761 | else if (host->curr.data) { /* Non DMA */ | ||
762 | msmsdcc_reset_and_restore(host); | ||
763 | msmsdcc_stop_data(host); | ||
764 | msmsdcc_request_end(host, cmd->mrq); | ||
765 | } else { /* host->data == NULL */ | ||
766 | if (!cmd->error && host->prog_enable) { | ||
767 | if (status & MCI_PROGDONE) { | ||
768 | host->prog_scan = false; | ||
769 | host->prog_enable = false; | ||
770 | msmsdcc_request_end(host, cmd->mrq); | ||
771 | } else { | ||
772 | host->curr.cmd = cmd; | ||
773 | } | ||
774 | } else { | ||
775 | if (host->prog_enable) { | ||
776 | host->prog_scan = false; | ||
777 | host->prog_enable = false; | ||
778 | } | ||
779 | msmsdcc_request_end(host, cmd->mrq); | ||
780 | } | ||
781 | } | ||
782 | } else if (cmd->data) | ||
783 | if (!(cmd->data->flags & MMC_DATA_READ)) | ||
784 | msmsdcc_start_data(host, cmd->data, | ||
785 | NULL, 0); | ||
786 | } | ||
787 | |||
788 | static void | ||
789 | msmsdcc_handle_irq_data(struct msmsdcc_host *host, u32 status, | ||
790 | void __iomem *base) | ||
791 | { | ||
792 | struct mmc_data *data = host->curr.data; | ||
793 | |||
794 | if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL | | ||
795 | MCI_CMDTIMEOUT | MCI_PROGDONE) && host->curr.cmd) { | ||
796 | msmsdcc_do_cmdirq(host, status); | ||
797 | } | ||
798 | |||
799 | if (!data) | ||
800 | return; | ||
801 | |||
802 | /* Check for data errors */ | ||
803 | if (status & (MCI_DATACRCFAIL | MCI_DATATIMEOUT | | ||
804 | MCI_TXUNDERRUN | MCI_RXOVERRUN)) { | ||
805 | msmsdcc_data_err(host, data, status); | ||
806 | host->curr.data_xfered = 0; | ||
807 | if (host->dma.sg) | ||
808 | msm_dmov_stop_cmd(host->dma.channel, | ||
809 | &host->dma.hdr, 0); | ||
810 | else { | ||
811 | msmsdcc_reset_and_restore(host); | ||
812 | if (host->curr.data) | ||
813 | msmsdcc_stop_data(host); | ||
814 | if (!data->stop) | ||
815 | msmsdcc_request_end(host, data->mrq); | ||
816 | else | ||
817 | msmsdcc_start_command(host, data->stop, 0); | ||
818 | } | ||
819 | } | ||
820 | |||
821 | /* Check for data done */ | ||
822 | if (!host->curr.got_dataend && (status & MCI_DATAEND)) | ||
823 | host->curr.got_dataend = 1; | ||
824 | |||
825 | /* | ||
826 | * If DMA is still in progress, we complete via the completion handler | ||
827 | */ | ||
828 | if (host->curr.got_dataend && !host->dma.busy) { | ||
829 | /* | ||
830 | * There appears to be an issue in the controller where | ||
831 | * if you request a small block transfer (< fifo size), | ||
832 | * you may get your DATAEND/DATABLKEND irq without the | ||
833 | * PIO data irq. | ||
834 | * | ||
835 | * Check to see if there is still data to be read, | ||
836 | * and simulate a PIO irq. | ||
837 | */ | ||
838 | if (readl(base + MMCISTATUS) & MCI_RXDATAAVLBL) | ||
839 | msmsdcc_pio_irq(1, host); | ||
840 | |||
841 | msmsdcc_stop_data(host); | ||
842 | if (!data->error) | ||
843 | host->curr.data_xfered = host->curr.xfer_size; | ||
844 | |||
845 | if (!data->stop) | ||
846 | msmsdcc_request_end(host, data->mrq); | ||
847 | else | ||
848 | msmsdcc_start_command(host, data->stop, 0); | ||
849 | } | ||
850 | } | ||
851 | |||
852 | static irqreturn_t | ||
853 | msmsdcc_irq(int irq, void *dev_id) | ||
854 | { | ||
855 | struct msmsdcc_host *host = dev_id; | ||
856 | void __iomem *base = host->base; | ||
857 | u32 status; | ||
858 | int ret = 0; | ||
859 | int cardint = 0; | ||
860 | |||
861 | spin_lock(&host->lock); | ||
862 | |||
863 | do { | ||
864 | status = msmsdcc_readl(host, MMCISTATUS); | ||
865 | status &= msmsdcc_readl(host, MMCIMASK0); | ||
866 | if ((status & (~MCI_IRQ_PIO)) == 0) | ||
867 | break; | ||
868 | msmsdcc_writel(host, status, MMCICLEAR); | ||
869 | |||
870 | if (status & MCI_SDIOINTR) | ||
871 | status &= ~MCI_SDIOINTR; | ||
872 | |||
873 | if (!status) | ||
874 | break; | ||
875 | |||
876 | msmsdcc_handle_irq_data(host, status, base); | ||
877 | |||
878 | if (status & MCI_SDIOINTOPER) { | ||
879 | cardint = 1; | ||
880 | status &= ~MCI_SDIOINTOPER; | ||
881 | } | ||
882 | ret = 1; | ||
883 | } while (status); | ||
884 | |||
885 | spin_unlock(&host->lock); | ||
886 | |||
887 | /* | ||
888 | * We have to delay handling the card interrupt as it calls | ||
889 | * back into the driver. | ||
890 | */ | ||
891 | if (cardint) | ||
892 | mmc_signal_sdio_irq(host->mmc); | ||
893 | |||
894 | return IRQ_RETVAL(ret); | ||
895 | } | ||
896 | |||
897 | static void | ||
898 | msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
899 | { | ||
900 | struct msmsdcc_host *host = mmc_priv(mmc); | ||
901 | unsigned long flags; | ||
902 | |||
903 | WARN_ON(host->curr.mrq != NULL); | ||
904 | WARN_ON(host->pwr == 0); | ||
905 | |||
906 | spin_lock_irqsave(&host->lock, flags); | ||
907 | |||
908 | host->stats.reqs++; | ||
909 | |||
910 | if (host->eject) { | ||
911 | if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) { | ||
912 | mrq->cmd->error = 0; | ||
913 | mrq->data->bytes_xfered = mrq->data->blksz * | ||
914 | mrq->data->blocks; | ||
915 | } else | ||
916 | mrq->cmd->error = -ENOMEDIUM; | ||
917 | |||
918 | spin_unlock_irqrestore(&host->lock, flags); | ||
919 | mmc_request_done(mmc, mrq); | ||
920 | return; | ||
921 | } | ||
922 | |||
923 | msmsdcc_enable_clocks(host); | ||
924 | |||
925 | host->curr.mrq = mrq; | ||
926 | |||
927 | if (mrq->data && mrq->data->flags & MMC_DATA_READ) | ||
928 | /* Queue/read data, daisy-chain command when data starts */ | ||
929 | msmsdcc_start_data(host, mrq->data, mrq->cmd, 0); | ||
930 | else | ||
931 | msmsdcc_start_command(host, mrq->cmd, 0); | ||
932 | |||
933 | if (host->cmdpoll && !msmsdcc_spin_on_status(host, | ||
934 | MCI_CMDRESPEND|MCI_CMDCRCFAIL|MCI_CMDTIMEOUT, | ||
935 | CMD_SPINMAX)) { | ||
936 | uint32_t status = msmsdcc_readl(host, MMCISTATUS); | ||
937 | msmsdcc_do_cmdirq(host, status); | ||
938 | msmsdcc_writel(host, | ||
939 | MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT, | ||
940 | MMCICLEAR); | ||
941 | host->stats.cmdpoll_hits++; | ||
942 | } else { | ||
943 | host->stats.cmdpoll_misses++; | ||
944 | } | ||
945 | spin_unlock_irqrestore(&host->lock, flags); | ||
946 | } | ||
947 | |||
948 | static void msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable) | ||
949 | { | ||
950 | struct msm_mmc_gpio_data *curr; | ||
951 | int i, rc = 0; | ||
952 | |||
953 | if (!host->plat->gpio_data || host->gpio_config_status == enable) | ||
954 | return; | ||
955 | |||
956 | curr = host->plat->gpio_data; | ||
957 | for (i = 0; i < curr->size; i++) { | ||
958 | if (enable) { | ||
959 | rc = gpio_request(curr->gpio[i].no, | ||
960 | curr->gpio[i].name); | ||
961 | if (rc) { | ||
962 | pr_err("%s: gpio_request(%d, %s) failed %d\n", | ||
963 | mmc_hostname(host->mmc), | ||
964 | curr->gpio[i].no, | ||
965 | curr->gpio[i].name, rc); | ||
966 | goto free_gpios; | ||
967 | } | ||
968 | } else { | ||
969 | gpio_free(curr->gpio[i].no); | ||
970 | } | ||
971 | } | ||
972 | host->gpio_config_status = enable; | ||
973 | return; | ||
974 | |||
975 | free_gpios: | ||
976 | for (; i >= 0; i--) | ||
977 | gpio_free(curr->gpio[i].no); | ||
978 | } | ||
979 | |||
980 | static void | ||
981 | msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
982 | { | ||
983 | struct msmsdcc_host *host = mmc_priv(mmc); | ||
984 | u32 clk = 0, pwr = 0; | ||
985 | int rc; | ||
986 | unsigned long flags; | ||
987 | |||
988 | spin_lock_irqsave(&host->lock, flags); | ||
989 | |||
990 | msmsdcc_enable_clocks(host); | ||
991 | |||
992 | spin_unlock_irqrestore(&host->lock, flags); | ||
993 | |||
994 | if (ios->clock) { | ||
995 | if (ios->clock != host->clk_rate) { | ||
996 | rc = clk_set_rate(host->clk, ios->clock); | ||
997 | if (rc < 0) | ||
998 | pr_err("%s: Error setting clock rate (%d)\n", | ||
999 | mmc_hostname(host->mmc), rc); | ||
1000 | else | ||
1001 | host->clk_rate = ios->clock; | ||
1002 | } | ||
1003 | clk |= MCI_CLK_ENABLE; | ||
1004 | } | ||
1005 | |||
1006 | if (ios->bus_width == MMC_BUS_WIDTH_4) | ||
1007 | clk |= (2 << 10); /* Set WIDEBUS */ | ||
1008 | |||
1009 | if (ios->clock > 400000 && msmsdcc_pwrsave) | ||
1010 | clk |= (1 << 9); /* PWRSAVE */ | ||
1011 | |||
1012 | clk |= (1 << 12); /* FLOW_ENA */ | ||
1013 | clk |= (1 << 15); /* feedback clock */ | ||
1014 | |||
1015 | if (host->plat->translate_vdd) | ||
1016 | pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); | ||
1017 | |||
1018 | switch (ios->power_mode) { | ||
1019 | case MMC_POWER_OFF: | ||
1020 | msmsdcc_setup_gpio(host, false); | ||
1021 | break; | ||
1022 | case MMC_POWER_UP: | ||
1023 | pwr |= MCI_PWR_UP; | ||
1024 | msmsdcc_setup_gpio(host, true); | ||
1025 | break; | ||
1026 | case MMC_POWER_ON: | ||
1027 | pwr |= MCI_PWR_ON; | ||
1028 | break; | ||
1029 | } | ||
1030 | |||
1031 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | ||
1032 | pwr |= MCI_OD; | ||
1033 | |||
1034 | msmsdcc_writel(host, clk, MMCICLOCK); | ||
1035 | |||
1036 | if (host->pwr != pwr) { | ||
1037 | host->pwr = pwr; | ||
1038 | msmsdcc_writel(host, pwr, MMCIPOWER); | ||
1039 | } | ||
1040 | #if BUSCLK_PWRSAVE | ||
1041 | spin_lock_irqsave(&host->lock, flags); | ||
1042 | msmsdcc_disable_clocks(host, 1); | ||
1043 | spin_unlock_irqrestore(&host->lock, flags); | ||
1044 | #endif | ||
1045 | } | ||
1046 | |||
1047 | static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
1048 | { | ||
1049 | struct msmsdcc_host *host = mmc_priv(mmc); | ||
1050 | unsigned long flags; | ||
1051 | u32 status; | ||
1052 | |||
1053 | spin_lock_irqsave(&host->lock, flags); | ||
1054 | if (msmsdcc_sdioirq == 1) { | ||
1055 | status = msmsdcc_readl(host, MMCIMASK0); | ||
1056 | if (enable) | ||
1057 | status |= MCI_SDIOINTOPERMASK; | ||
1058 | else | ||
1059 | status &= ~MCI_SDIOINTOPERMASK; | ||
1060 | host->saved_irq0mask = status; | ||
1061 | msmsdcc_writel(host, status, MMCIMASK0); | ||
1062 | } | ||
1063 | spin_unlock_irqrestore(&host->lock, flags); | ||
1064 | } | ||
1065 | |||
1066 | static void msmsdcc_init_card(struct mmc_host *mmc, struct mmc_card *card) | ||
1067 | { | ||
1068 | struct msmsdcc_host *host = mmc_priv(mmc); | ||
1069 | |||
1070 | if (host->plat->init_card) | ||
1071 | host->plat->init_card(card); | ||
1072 | } | ||
1073 | |||
1074 | static const struct mmc_host_ops msmsdcc_ops = { | ||
1075 | .request = msmsdcc_request, | ||
1076 | .set_ios = msmsdcc_set_ios, | ||
1077 | .enable_sdio_irq = msmsdcc_enable_sdio_irq, | ||
1078 | .init_card = msmsdcc_init_card, | ||
1079 | }; | ||
1080 | |||
1081 | static void | ||
1082 | msmsdcc_check_status(unsigned long data) | ||
1083 | { | ||
1084 | struct msmsdcc_host *host = (struct msmsdcc_host *)data; | ||
1085 | unsigned int status; | ||
1086 | |||
1087 | if (!host->plat->status) { | ||
1088 | mmc_detect_change(host->mmc, 0); | ||
1089 | goto out; | ||
1090 | } | ||
1091 | |||
1092 | status = host->plat->status(mmc_dev(host->mmc)); | ||
1093 | host->eject = !status; | ||
1094 | if (status ^ host->oldstat) { | ||
1095 | pr_info("%s: Slot status change detected (%d -> %d)\n", | ||
1096 | mmc_hostname(host->mmc), host->oldstat, status); | ||
1097 | if (status) | ||
1098 | mmc_detect_change(host->mmc, (5 * HZ) / 2); | ||
1099 | else | ||
1100 | mmc_detect_change(host->mmc, 0); | ||
1101 | } | ||
1102 | |||
1103 | host->oldstat = status; | ||
1104 | |||
1105 | out: | ||
1106 | if (host->timer.function) | ||
1107 | mod_timer(&host->timer, jiffies + HZ); | ||
1108 | } | ||
1109 | |||
1110 | static irqreturn_t | ||
1111 | msmsdcc_platform_status_irq(int irq, void *dev_id) | ||
1112 | { | ||
1113 | struct msmsdcc_host *host = dev_id; | ||
1114 | |||
1115 | pr_debug("%s: %d\n", __func__, irq); | ||
1116 | msmsdcc_check_status((unsigned long) host); | ||
1117 | return IRQ_HANDLED; | ||
1118 | } | ||
1119 | |||
1120 | static void | ||
1121 | msmsdcc_status_notify_cb(int card_present, void *dev_id) | ||
1122 | { | ||
1123 | struct msmsdcc_host *host = dev_id; | ||
1124 | |||
1125 | pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc), | ||
1126 | card_present); | ||
1127 | msmsdcc_check_status((unsigned long) host); | ||
1128 | } | ||
1129 | |||
1130 | static void | ||
1131 | msmsdcc_busclk_expired(unsigned long _data) | ||
1132 | { | ||
1133 | struct msmsdcc_host *host = (struct msmsdcc_host *) _data; | ||
1134 | |||
1135 | if (host->clks_on) | ||
1136 | msmsdcc_disable_clocks(host, 0); | ||
1137 | } | ||
1138 | |||
1139 | static int | ||
1140 | msmsdcc_init_dma(struct msmsdcc_host *host) | ||
1141 | { | ||
1142 | memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data)); | ||
1143 | host->dma.host = host; | ||
1144 | host->dma.channel = -1; | ||
1145 | |||
1146 | if (!host->dmares) | ||
1147 | return -ENODEV; | ||
1148 | |||
1149 | host->dma.nc = dma_alloc_coherent(NULL, | ||
1150 | sizeof(struct msmsdcc_nc_dmadata), | ||
1151 | &host->dma.nc_busaddr, | ||
1152 | GFP_KERNEL); | ||
1153 | if (host->dma.nc == NULL) { | ||
1154 | pr_err("Unable to allocate DMA buffer\n"); | ||
1155 | return -ENOMEM; | ||
1156 | } | ||
1157 | memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata)); | ||
1158 | host->dma.cmd_busaddr = host->dma.nc_busaddr; | ||
1159 | host->dma.cmdptr_busaddr = host->dma.nc_busaddr + | ||
1160 | offsetof(struct msmsdcc_nc_dmadata, cmdptr); | ||
1161 | host->dma.channel = host->dmares->start; | ||
1162 | |||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | static int | ||
1167 | msmsdcc_probe(struct platform_device *pdev) | ||
1168 | { | ||
1169 | struct msm_mmc_platform_data *plat = pdev->dev.platform_data; | ||
1170 | struct msmsdcc_host *host; | ||
1171 | struct mmc_host *mmc; | ||
1172 | struct resource *cmd_irqres = NULL; | ||
1173 | struct resource *stat_irqres = NULL; | ||
1174 | struct resource *memres = NULL; | ||
1175 | struct resource *dmares = NULL; | ||
1176 | int ret; | ||
1177 | |||
1178 | /* must have platform data */ | ||
1179 | if (!plat) { | ||
1180 | pr_err("%s: Platform data not available\n", __func__); | ||
1181 | ret = -EINVAL; | ||
1182 | goto out; | ||
1183 | } | ||
1184 | |||
1185 | if (pdev->id < 1 || pdev->id > 4) | ||
1186 | return -EINVAL; | ||
1187 | |||
1188 | if (pdev->resource == NULL || pdev->num_resources < 2) { | ||
1189 | pr_err("%s: Invalid resource\n", __func__); | ||
1190 | return -ENXIO; | ||
1191 | } | ||
1192 | |||
1193 | memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1194 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
1195 | cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
1196 | "cmd_irq"); | ||
1197 | stat_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
1198 | "status_irq"); | ||
1199 | |||
1200 | if (!cmd_irqres || !memres) { | ||
1201 | pr_err("%s: Invalid resource\n", __func__); | ||
1202 | return -ENXIO; | ||
1203 | } | ||
1204 | |||
1205 | /* | ||
1206 | * Setup our host structure | ||
1207 | */ | ||
1208 | |||
1209 | mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev); | ||
1210 | if (!mmc) { | ||
1211 | ret = -ENOMEM; | ||
1212 | goto out; | ||
1213 | } | ||
1214 | |||
1215 | host = mmc_priv(mmc); | ||
1216 | host->pdev_id = pdev->id; | ||
1217 | host->plat = plat; | ||
1218 | host->mmc = mmc; | ||
1219 | host->curr.cmd = NULL; | ||
1220 | init_timer(&host->busclk_timer); | ||
1221 | host->busclk_timer.data = (unsigned long) host; | ||
1222 | host->busclk_timer.function = msmsdcc_busclk_expired; | ||
1223 | |||
1224 | |||
1225 | host->cmdpoll = 1; | ||
1226 | |||
1227 | host->base = ioremap(memres->start, PAGE_SIZE); | ||
1228 | if (!host->base) { | ||
1229 | ret = -ENOMEM; | ||
1230 | goto host_free; | ||
1231 | } | ||
1232 | |||
1233 | host->cmd_irqres = cmd_irqres; | ||
1234 | host->memres = memres; | ||
1235 | host->dmares = dmares; | ||
1236 | spin_lock_init(&host->lock); | ||
1237 | |||
1238 | tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet, | ||
1239 | (unsigned long)host); | ||
1240 | |||
1241 | /* | ||
1242 | * Setup DMA | ||
1243 | */ | ||
1244 | if (host->dmares) { | ||
1245 | ret = msmsdcc_init_dma(host); | ||
1246 | if (ret) | ||
1247 | goto ioremap_free; | ||
1248 | } else { | ||
1249 | host->dma.channel = -1; | ||
1250 | } | ||
1251 | |||
1252 | /* Get our clocks */ | ||
1253 | host->pclk = clk_get(&pdev->dev, "sdc_pclk"); | ||
1254 | if (IS_ERR(host->pclk)) { | ||
1255 | ret = PTR_ERR(host->pclk); | ||
1256 | goto dma_free; | ||
1257 | } | ||
1258 | |||
1259 | host->clk = clk_get(&pdev->dev, "sdc_clk"); | ||
1260 | if (IS_ERR(host->clk)) { | ||
1261 | ret = PTR_ERR(host->clk); | ||
1262 | goto pclk_put; | ||
1263 | } | ||
1264 | |||
1265 | ret = clk_set_rate(host->clk, msmsdcc_fmin); | ||
1266 | if (ret) { | ||
1267 | pr_err("%s: Clock rate set failed (%d)\n", __func__, ret); | ||
1268 | goto clk_put; | ||
1269 | } | ||
1270 | |||
1271 | ret = clk_prepare(host->pclk); | ||
1272 | if (ret) | ||
1273 | goto clk_put; | ||
1274 | |||
1275 | ret = clk_prepare(host->clk); | ||
1276 | if (ret) | ||
1277 | goto clk_unprepare_p; | ||
1278 | |||
1279 | /* Enable clocks */ | ||
1280 | ret = msmsdcc_enable_clocks(host); | ||
1281 | if (ret) | ||
1282 | goto clk_unprepare; | ||
1283 | |||
1284 | host->pclk_rate = clk_get_rate(host->pclk); | ||
1285 | host->clk_rate = clk_get_rate(host->clk); | ||
1286 | |||
1287 | /* | ||
1288 | * Setup MMC host structure | ||
1289 | */ | ||
1290 | mmc->ops = &msmsdcc_ops; | ||
1291 | mmc->f_min = msmsdcc_fmin; | ||
1292 | mmc->f_max = msmsdcc_fmax; | ||
1293 | mmc->ocr_avail = plat->ocr_mask; | ||
1294 | |||
1295 | if (msmsdcc_4bit) | ||
1296 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
1297 | if (msmsdcc_sdioirq) | ||
1298 | mmc->caps |= MMC_CAP_SDIO_IRQ; | ||
1299 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; | ||
1300 | |||
1301 | mmc->max_segs = NR_SG; | ||
1302 | mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */ | ||
1303 | mmc->max_blk_count = 65536; | ||
1304 | |||
1305 | mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */ | ||
1306 | mmc->max_seg_size = mmc->max_req_size; | ||
1307 | |||
1308 | msmsdcc_writel(host, 0, MMCIMASK0); | ||
1309 | msmsdcc_writel(host, 0x5e007ff, MMCICLEAR); | ||
1310 | |||
1311 | msmsdcc_writel(host, MCI_IRQENABLE, MMCIMASK0); | ||
1312 | host->saved_irq0mask = MCI_IRQENABLE; | ||
1313 | |||
1314 | /* | ||
1315 | * Setup card detect change | ||
1316 | */ | ||
1317 | |||
1318 | memset(&host->timer, 0, sizeof(host->timer)); | ||
1319 | |||
1320 | if (stat_irqres && !(stat_irqres->flags & IORESOURCE_DISABLED)) { | ||
1321 | unsigned long irqflags = IRQF_SHARED | | ||
1322 | (stat_irqres->flags & IRQF_TRIGGER_MASK); | ||
1323 | |||
1324 | host->stat_irq = stat_irqres->start; | ||
1325 | ret = request_irq(host->stat_irq, | ||
1326 | msmsdcc_platform_status_irq, | ||
1327 | irqflags, | ||
1328 | DRIVER_NAME " (slot)", | ||
1329 | host); | ||
1330 | if (ret) { | ||
1331 | pr_err("%s: Unable to get slot IRQ %d (%d)\n", | ||
1332 | mmc_hostname(mmc), host->stat_irq, ret); | ||
1333 | goto clk_disable; | ||
1334 | } | ||
1335 | } else if (plat->register_status_notify) { | ||
1336 | plat->register_status_notify(msmsdcc_status_notify_cb, host); | ||
1337 | } else if (!plat->status) | ||
1338 | pr_err("%s: No card detect facilities available\n", | ||
1339 | mmc_hostname(mmc)); | ||
1340 | else { | ||
1341 | init_timer(&host->timer); | ||
1342 | host->timer.data = (unsigned long)host; | ||
1343 | host->timer.function = msmsdcc_check_status; | ||
1344 | host->timer.expires = jiffies + HZ; | ||
1345 | add_timer(&host->timer); | ||
1346 | } | ||
1347 | |||
1348 | if (plat->status) { | ||
1349 | host->oldstat = host->plat->status(mmc_dev(host->mmc)); | ||
1350 | host->eject = !host->oldstat; | ||
1351 | } | ||
1352 | |||
1353 | ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED, | ||
1354 | DRIVER_NAME " (cmd)", host); | ||
1355 | if (ret) | ||
1356 | goto stat_irq_free; | ||
1357 | |||
1358 | ret = request_irq(cmd_irqres->start, msmsdcc_pio_irq, IRQF_SHARED, | ||
1359 | DRIVER_NAME " (pio)", host); | ||
1360 | if (ret) | ||
1361 | goto cmd_irq_free; | ||
1362 | |||
1363 | platform_set_drvdata(pdev, mmc); | ||
1364 | mmc_add_host(mmc); | ||
1365 | |||
1366 | pr_info("%s: Qualcomm MSM SDCC at 0x%016llx irq %d,%d dma %d\n", | ||
1367 | mmc_hostname(mmc), (unsigned long long)memres->start, | ||
1368 | (unsigned int) cmd_irqres->start, | ||
1369 | (unsigned int) host->stat_irq, host->dma.channel); | ||
1370 | pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc), | ||
1371 | (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled")); | ||
1372 | pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n", | ||
1373 | mmc_hostname(mmc), msmsdcc_fmin, msmsdcc_fmax, host->pclk_rate); | ||
1374 | pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc), host->eject); | ||
1375 | pr_info("%s: Power save feature enable = %d\n", | ||
1376 | mmc_hostname(mmc), msmsdcc_pwrsave); | ||
1377 | |||
1378 | if (host->dma.channel != -1) { | ||
1379 | pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n", | ||
1380 | mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr); | ||
1381 | pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n", | ||
1382 | mmc_hostname(mmc), host->dma.cmd_busaddr, | ||
1383 | host->dma.cmdptr_busaddr); | ||
1384 | } else | ||
1385 | pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc)); | ||
1386 | if (host->timer.function) | ||
1387 | pr_info("%s: Polling status mode enabled\n", mmc_hostname(mmc)); | ||
1388 | |||
1389 | return 0; | ||
1390 | cmd_irq_free: | ||
1391 | free_irq(cmd_irqres->start, host); | ||
1392 | stat_irq_free: | ||
1393 | if (host->stat_irq) | ||
1394 | free_irq(host->stat_irq, host); | ||
1395 | clk_disable: | ||
1396 | msmsdcc_disable_clocks(host, 0); | ||
1397 | clk_unprepare: | ||
1398 | clk_unprepare(host->clk); | ||
1399 | clk_unprepare_p: | ||
1400 | clk_unprepare(host->pclk); | ||
1401 | clk_put: | ||
1402 | clk_put(host->clk); | ||
1403 | pclk_put: | ||
1404 | clk_put(host->pclk); | ||
1405 | dma_free: | ||
1406 | if (host->dmares) | ||
1407 | dma_free_coherent(NULL, sizeof(struct msmsdcc_nc_dmadata), | ||
1408 | host->dma.nc, host->dma.nc_busaddr); | ||
1409 | ioremap_free: | ||
1410 | tasklet_kill(&host->dma_tlet); | ||
1411 | iounmap(host->base); | ||
1412 | host_free: | ||
1413 | mmc_free_host(mmc); | ||
1414 | out: | ||
1415 | return ret; | ||
1416 | } | ||
1417 | |||
1418 | #ifdef CONFIG_PM | ||
1419 | static int | ||
1420 | msmsdcc_suspend(struct platform_device *dev, pm_message_t state) | ||
1421 | { | ||
1422 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
1423 | |||
1424 | if (mmc) { | ||
1425 | struct msmsdcc_host *host = mmc_priv(mmc); | ||
1426 | |||
1427 | if (host->stat_irq) | ||
1428 | disable_irq(host->stat_irq); | ||
1429 | |||
1430 | msmsdcc_writel(host, 0, MMCIMASK0); | ||
1431 | if (host->clks_on) | ||
1432 | msmsdcc_disable_clocks(host, 0); | ||
1433 | } | ||
1434 | return 0; | ||
1435 | } | ||
1436 | |||
1437 | static int | ||
1438 | msmsdcc_resume(struct platform_device *dev) | ||
1439 | { | ||
1440 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
1441 | |||
1442 | if (mmc) { | ||
1443 | struct msmsdcc_host *host = mmc_priv(mmc); | ||
1444 | |||
1445 | msmsdcc_enable_clocks(host); | ||
1446 | |||
1447 | msmsdcc_writel(host, host->saved_irq0mask, MMCIMASK0); | ||
1448 | |||
1449 | if (host->stat_irq) | ||
1450 | enable_irq(host->stat_irq); | ||
1451 | #if BUSCLK_PWRSAVE | ||
1452 | msmsdcc_disable_clocks(host, 1); | ||
1453 | #endif | ||
1454 | } | ||
1455 | return 0; | ||
1456 | } | ||
1457 | #else | ||
1458 | #define msmsdcc_suspend 0 | ||
1459 | #define msmsdcc_resume 0 | ||
1460 | #endif | ||
1461 | |||
1462 | static struct platform_driver msmsdcc_driver = { | ||
1463 | .probe = msmsdcc_probe, | ||
1464 | .suspend = msmsdcc_suspend, | ||
1465 | .resume = msmsdcc_resume, | ||
1466 | .driver = { | ||
1467 | .name = "msm_sdcc", | ||
1468 | }, | ||
1469 | }; | ||
1470 | |||
1471 | module_platform_driver(msmsdcc_driver); | ||
1472 | |||
1473 | MODULE_DESCRIPTION("Qualcomm MSM 7X00A Multimedia Card Interface driver"); | ||
1474 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h deleted file mode 100644 index 402028d16b86..000000000000 --- a/drivers/mmc/host/msm_sdcc.h +++ /dev/null | |||
@@ -1,256 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/mmc/host/msmsdcc.h - QCT MSM7K SDC Controller | ||
3 | * | ||
4 | * Copyright (C) 2008 Google, All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * - Based on mmci.h | ||
11 | */ | ||
12 | |||
13 | #ifndef _MSM_SDCC_H | ||
14 | #define _MSM_SDCC_H | ||
15 | |||
16 | #define MSMSDCC_CRCI_SDC1 6 | ||
17 | #define MSMSDCC_CRCI_SDC2 7 | ||
18 | #define MSMSDCC_CRCI_SDC3 12 | ||
19 | #define MSMSDCC_CRCI_SDC4 13 | ||
20 | |||
21 | #define MMCIPOWER 0x000 | ||
22 | #define MCI_PWR_OFF 0x00 | ||
23 | #define MCI_PWR_UP 0x02 | ||
24 | #define MCI_PWR_ON 0x03 | ||
25 | #define MCI_OD (1 << 6) | ||
26 | |||
27 | #define MMCICLOCK 0x004 | ||
28 | #define MCI_CLK_ENABLE (1 << 8) | ||
29 | #define MCI_CLK_PWRSAVE (1 << 9) | ||
30 | #define MCI_CLK_WIDEBUS (1 << 10) | ||
31 | #define MCI_CLK_FLOWENA (1 << 12) | ||
32 | #define MCI_CLK_INVERTOUT (1 << 13) | ||
33 | #define MCI_CLK_SELECTIN (1 << 14) | ||
34 | |||
35 | #define MMCIARGUMENT 0x008 | ||
36 | #define MMCICOMMAND 0x00c | ||
37 | #define MCI_CPSM_RESPONSE (1 << 6) | ||
38 | #define MCI_CPSM_LONGRSP (1 << 7) | ||
39 | #define MCI_CPSM_INTERRUPT (1 << 8) | ||
40 | #define MCI_CPSM_PENDING (1 << 9) | ||
41 | #define MCI_CPSM_ENABLE (1 << 10) | ||
42 | #define MCI_CPSM_PROGENA (1 << 11) | ||
43 | #define MCI_CSPM_DATCMD (1 << 12) | ||
44 | #define MCI_CSPM_MCIABORT (1 << 13) | ||
45 | #define MCI_CSPM_CCSENABLE (1 << 14) | ||
46 | #define MCI_CSPM_CCSDISABLE (1 << 15) | ||
47 | |||
48 | |||
49 | #define MMCIRESPCMD 0x010 | ||
50 | #define MMCIRESPONSE0 0x014 | ||
51 | #define MMCIRESPONSE1 0x018 | ||
52 | #define MMCIRESPONSE2 0x01c | ||
53 | #define MMCIRESPONSE3 0x020 | ||
54 | #define MMCIDATATIMER 0x024 | ||
55 | #define MMCIDATALENGTH 0x028 | ||
56 | |||
57 | #define MMCIDATACTRL 0x02c | ||
58 | #define MCI_DPSM_ENABLE (1 << 0) | ||
59 | #define MCI_DPSM_DIRECTION (1 << 1) | ||
60 | #define MCI_DPSM_MODE (1 << 2) | ||
61 | #define MCI_DPSM_DMAENABLE (1 << 3) | ||
62 | |||
63 | #define MMCIDATACNT 0x030 | ||
64 | #define MMCISTATUS 0x034 | ||
65 | #define MCI_CMDCRCFAIL (1 << 0) | ||
66 | #define MCI_DATACRCFAIL (1 << 1) | ||
67 | #define MCI_CMDTIMEOUT (1 << 2) | ||
68 | #define MCI_DATATIMEOUT (1 << 3) | ||
69 | #define MCI_TXUNDERRUN (1 << 4) | ||
70 | #define MCI_RXOVERRUN (1 << 5) | ||
71 | #define MCI_CMDRESPEND (1 << 6) | ||
72 | #define MCI_CMDSENT (1 << 7) | ||
73 | #define MCI_DATAEND (1 << 8) | ||
74 | #define MCI_DATABLOCKEND (1 << 10) | ||
75 | #define MCI_CMDACTIVE (1 << 11) | ||
76 | #define MCI_TXACTIVE (1 << 12) | ||
77 | #define MCI_RXACTIVE (1 << 13) | ||
78 | #define MCI_TXFIFOHALFEMPTY (1 << 14) | ||
79 | #define MCI_RXFIFOHALFFULL (1 << 15) | ||
80 | #define MCI_TXFIFOFULL (1 << 16) | ||
81 | #define MCI_RXFIFOFULL (1 << 17) | ||
82 | #define MCI_TXFIFOEMPTY (1 << 18) | ||
83 | #define MCI_RXFIFOEMPTY (1 << 19) | ||
84 | #define MCI_TXDATAAVLBL (1 << 20) | ||
85 | #define MCI_RXDATAAVLBL (1 << 21) | ||
86 | #define MCI_SDIOINTR (1 << 22) | ||
87 | #define MCI_PROGDONE (1 << 23) | ||
88 | #define MCI_ATACMDCOMPL (1 << 24) | ||
89 | #define MCI_SDIOINTOPER (1 << 25) | ||
90 | #define MCI_CCSTIMEOUT (1 << 26) | ||
91 | |||
92 | #define MMCICLEAR 0x038 | ||
93 | #define MCI_CMDCRCFAILCLR (1 << 0) | ||
94 | #define MCI_DATACRCFAILCLR (1 << 1) | ||
95 | #define MCI_CMDTIMEOUTCLR (1 << 2) | ||
96 | #define MCI_DATATIMEOUTCLR (1 << 3) | ||
97 | #define MCI_TXUNDERRUNCLR (1 << 4) | ||
98 | #define MCI_RXOVERRUNCLR (1 << 5) | ||
99 | #define MCI_CMDRESPENDCLR (1 << 6) | ||
100 | #define MCI_CMDSENTCLR (1 << 7) | ||
101 | #define MCI_DATAENDCLR (1 << 8) | ||
102 | #define MCI_DATABLOCKENDCLR (1 << 10) | ||
103 | |||
104 | #define MMCIMASK0 0x03c | ||
105 | #define MCI_CMDCRCFAILMASK (1 << 0) | ||
106 | #define MCI_DATACRCFAILMASK (1 << 1) | ||
107 | #define MCI_CMDTIMEOUTMASK (1 << 2) | ||
108 | #define MCI_DATATIMEOUTMASK (1 << 3) | ||
109 | #define MCI_TXUNDERRUNMASK (1 << 4) | ||
110 | #define MCI_RXOVERRUNMASK (1 << 5) | ||
111 | #define MCI_CMDRESPENDMASK (1 << 6) | ||
112 | #define MCI_CMDSENTMASK (1 << 7) | ||
113 | #define MCI_DATAENDMASK (1 << 8) | ||
114 | #define MCI_DATABLOCKENDMASK (1 << 10) | ||
115 | #define MCI_CMDACTIVEMASK (1 << 11) | ||
116 | #define MCI_TXACTIVEMASK (1 << 12) | ||
117 | #define MCI_RXACTIVEMASK (1 << 13) | ||
118 | #define MCI_TXFIFOHALFEMPTYMASK (1 << 14) | ||
119 | #define MCI_RXFIFOHALFFULLMASK (1 << 15) | ||
120 | #define MCI_TXFIFOFULLMASK (1 << 16) | ||
121 | #define MCI_RXFIFOFULLMASK (1 << 17) | ||
122 | #define MCI_TXFIFOEMPTYMASK (1 << 18) | ||
123 | #define MCI_RXFIFOEMPTYMASK (1 << 19) | ||
124 | #define MCI_TXDATAAVLBLMASK (1 << 20) | ||
125 | #define MCI_RXDATAAVLBLMASK (1 << 21) | ||
126 | #define MCI_SDIOINTMASK (1 << 22) | ||
127 | #define MCI_PROGDONEMASK (1 << 23) | ||
128 | #define MCI_ATACMDCOMPLMASK (1 << 24) | ||
129 | #define MCI_SDIOINTOPERMASK (1 << 25) | ||
130 | #define MCI_CCSTIMEOUTMASK (1 << 26) | ||
131 | |||
132 | #define MMCIMASK1 0x040 | ||
133 | #define MMCIFIFOCNT 0x044 | ||
134 | #define MCICCSTIMER 0x058 | ||
135 | |||
136 | #define MMCIFIFO 0x080 /* to 0x0bc */ | ||
137 | |||
138 | #define MCI_IRQENABLE \ | ||
139 | (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ | ||
140 | MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ | ||
141 | MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK|MCI_PROGDONEMASK) | ||
142 | |||
143 | #define MCI_IRQ_PIO \ | ||
144 | (MCI_RXDATAAVLBLMASK | MCI_TXDATAAVLBLMASK | MCI_RXFIFOEMPTYMASK | \ | ||
145 | MCI_TXFIFOEMPTYMASK | MCI_RXFIFOFULLMASK | MCI_TXFIFOFULLMASK | \ | ||
146 | MCI_RXFIFOHALFFULLMASK | MCI_TXFIFOHALFEMPTYMASK | \ | ||
147 | MCI_RXACTIVEMASK | MCI_TXACTIVEMASK) | ||
148 | /* | ||
149 | * The size of the FIFO in bytes. | ||
150 | */ | ||
151 | #define MCI_FIFOSIZE (16*4) | ||
152 | |||
153 | #define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2) | ||
154 | |||
155 | #define NR_SG 32 | ||
156 | |||
157 | struct clk; | ||
158 | |||
159 | struct msmsdcc_nc_dmadata { | ||
160 | dmov_box cmd[NR_SG]; | ||
161 | uint32_t cmdptr; | ||
162 | }; | ||
163 | |||
164 | struct msmsdcc_dma_data { | ||
165 | struct msmsdcc_nc_dmadata *nc; | ||
166 | dma_addr_t nc_busaddr; | ||
167 | dma_addr_t cmd_busaddr; | ||
168 | dma_addr_t cmdptr_busaddr; | ||
169 | |||
170 | struct msm_dmov_cmd hdr; | ||
171 | enum dma_data_direction dir; | ||
172 | |||
173 | struct scatterlist *sg; | ||
174 | int num_ents; | ||
175 | |||
176 | int channel; | ||
177 | struct msmsdcc_host *host; | ||
178 | int busy; /* Set if DM is busy */ | ||
179 | int active; | ||
180 | unsigned int result; | ||
181 | struct msm_dmov_errdata err; | ||
182 | }; | ||
183 | |||
184 | struct msmsdcc_pio_data { | ||
185 | struct scatterlist *sg; | ||
186 | unsigned int sg_len; | ||
187 | unsigned int sg_off; | ||
188 | }; | ||
189 | |||
190 | struct msmsdcc_curr_req { | ||
191 | struct mmc_request *mrq; | ||
192 | struct mmc_command *cmd; | ||
193 | struct mmc_data *data; | ||
194 | unsigned int xfer_size; /* Total data size */ | ||
195 | unsigned int xfer_remain; /* Bytes remaining to send */ | ||
196 | unsigned int data_xfered; /* Bytes acked by BLKEND irq */ | ||
197 | int got_dataend; | ||
198 | int user_pages; | ||
199 | }; | ||
200 | |||
201 | struct msmsdcc_stats { | ||
202 | unsigned int reqs; | ||
203 | unsigned int cmds; | ||
204 | unsigned int cmdpoll_hits; | ||
205 | unsigned int cmdpoll_misses; | ||
206 | }; | ||
207 | |||
208 | struct msmsdcc_host { | ||
209 | struct resource *cmd_irqres; | ||
210 | struct resource *memres; | ||
211 | struct resource *dmares; | ||
212 | void __iomem *base; | ||
213 | int pdev_id; | ||
214 | unsigned int stat_irq; | ||
215 | |||
216 | struct msmsdcc_curr_req curr; | ||
217 | |||
218 | struct mmc_host *mmc; | ||
219 | struct clk *clk; /* main MMC bus clock */ | ||
220 | struct clk *pclk; /* SDCC peripheral bus clock */ | ||
221 | unsigned int clks_on; /* set if clocks are enabled */ | ||
222 | struct timer_list busclk_timer; | ||
223 | |||
224 | unsigned int eject; /* eject state */ | ||
225 | |||
226 | spinlock_t lock; | ||
227 | |||
228 | unsigned int clk_rate; /* Current clock rate */ | ||
229 | unsigned int pclk_rate; | ||
230 | |||
231 | u32 pwr; | ||
232 | u32 saved_irq0mask; /* MMCIMASK0 reg value */ | ||
233 | struct msm_mmc_platform_data *plat; | ||
234 | |||
235 | struct timer_list timer; | ||
236 | unsigned int oldstat; | ||
237 | |||
238 | struct msmsdcc_dma_data dma; | ||
239 | struct msmsdcc_pio_data pio; | ||
240 | int cmdpoll; | ||
241 | struct msmsdcc_stats stats; | ||
242 | |||
243 | struct tasklet_struct dma_tlet; | ||
244 | /* Command parameters */ | ||
245 | unsigned int cmd_timeout; | ||
246 | unsigned int cmd_pio_irqmask; | ||
247 | unsigned int cmd_datactrl; | ||
248 | struct mmc_command *cmd_cmd; | ||
249 | u32 cmd_c; | ||
250 | bool gpio_config_status; | ||
251 | |||
252 | bool prog_scan; | ||
253 | bool prog_enable; | ||
254 | }; | ||
255 | |||
256 | #endif | ||
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 5316d9b9e7b4..317d709f7550 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -281,7 +281,7 @@ static inline void buffer_swap32(u32 *buf, int len) | |||
281 | int i; | 281 | int i; |
282 | 282 | ||
283 | for (i = 0; i < ((len + 3) / 4); i++) { | 283 | for (i = 0; i < ((len + 3) / 4); i++) { |
284 | st_le32(buf, *buf); | 284 | *buf = swab32(*buf); |
285 | buf++; | 285 | buf++; |
286 | } | 286 | } |
287 | } | 287 | } |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f84cfb01716d..9df2b6801f76 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -222,10 +222,6 @@ struct omap_hsmmc_host { | |||
222 | struct omap_hsmmc_next next_data; | 222 | struct omap_hsmmc_next next_data; |
223 | struct omap_hsmmc_platform_data *pdata; | 223 | struct omap_hsmmc_platform_data *pdata; |
224 | 224 | ||
225 | /* To handle board related suspend/resume functionality for MMC */ | ||
226 | int (*suspend)(struct device *dev); | ||
227 | int (*resume)(struct device *dev); | ||
228 | |||
229 | /* return MMC cover switch state, can be NULL if not supported. | 225 | /* return MMC cover switch state, can be NULL if not supported. |
230 | * | 226 | * |
231 | * possible return values: | 227 | * possible return values: |
@@ -234,12 +230,7 @@ struct omap_hsmmc_host { | |||
234 | */ | 230 | */ |
235 | int (*get_cover_state)(struct device *dev); | 231 | int (*get_cover_state)(struct device *dev); |
236 | 232 | ||
237 | /* Card detection IRQs */ | ||
238 | int card_detect_irq; | ||
239 | |||
240 | int (*card_detect)(struct device *dev); | 233 | int (*card_detect)(struct device *dev); |
241 | int (*get_ro)(struct device *dev); | ||
242 | |||
243 | }; | 234 | }; |
244 | 235 | ||
245 | struct omap_mmc_of_data { | 236 | struct omap_mmc_of_data { |
@@ -256,13 +247,6 @@ static int omap_hsmmc_card_detect(struct device *dev) | |||
256 | return mmc_gpio_get_cd(host->mmc); | 247 | return mmc_gpio_get_cd(host->mmc); |
257 | } | 248 | } |
258 | 249 | ||
259 | static int omap_hsmmc_get_wp(struct device *dev) | ||
260 | { | ||
261 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
262 | |||
263 | return mmc_gpio_get_ro(host->mmc); | ||
264 | } | ||
265 | |||
266 | static int omap_hsmmc_get_cover_state(struct device *dev) | 250 | static int omap_hsmmc_get_cover_state(struct device *dev) |
267 | { | 251 | { |
268 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 252 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
@@ -434,7 +418,7 @@ static inline int omap_hsmmc_have_reg(void) | |||
434 | 418 | ||
435 | #endif | 419 | #endif |
436 | 420 | ||
437 | static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id); | 421 | static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id); |
438 | 422 | ||
439 | static int omap_hsmmc_gpio_init(struct mmc_host *mmc, | 423 | static int omap_hsmmc_gpio_init(struct mmc_host *mmc, |
440 | struct omap_hsmmc_host *host, | 424 | struct omap_hsmmc_host *host, |
@@ -442,29 +426,25 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, | |||
442 | { | 426 | { |
443 | int ret; | 427 | int ret; |
444 | 428 | ||
445 | if (gpio_is_valid(pdata->switch_pin)) { | 429 | if (gpio_is_valid(pdata->gpio_cod)) { |
446 | if (pdata->cover) | 430 | ret = mmc_gpio_request_cd(mmc, pdata->gpio_cod, 0); |
447 | host->get_cover_state = | ||
448 | omap_hsmmc_get_cover_state; | ||
449 | else | ||
450 | host->card_detect = omap_hsmmc_card_detect; | ||
451 | host->card_detect_irq = | ||
452 | gpio_to_irq(pdata->switch_pin); | ||
453 | mmc_gpio_set_cd_isr(mmc, omap_hsmmc_detect); | ||
454 | ret = mmc_gpio_request_cd(mmc, pdata->switch_pin, 0); | ||
455 | if (ret) | 431 | if (ret) |
456 | return ret; | 432 | return ret; |
457 | } else { | 433 | |
458 | pdata->switch_pin = -EINVAL; | 434 | host->get_cover_state = omap_hsmmc_get_cover_state; |
435 | mmc_gpio_set_cd_isr(mmc, omap_hsmmc_cover_irq); | ||
436 | } else if (gpio_is_valid(pdata->gpio_cd)) { | ||
437 | ret = mmc_gpio_request_cd(mmc, pdata->gpio_cd, 0); | ||
438 | if (ret) | ||
439 | return ret; | ||
440 | |||
441 | host->card_detect = omap_hsmmc_card_detect; | ||
459 | } | 442 | } |
460 | 443 | ||
461 | if (gpio_is_valid(pdata->gpio_wp)) { | 444 | if (gpio_is_valid(pdata->gpio_wp)) { |
462 | host->get_ro = omap_hsmmc_get_wp; | ||
463 | ret = mmc_gpio_request_ro(mmc, pdata->gpio_wp); | 445 | ret = mmc_gpio_request_ro(mmc, pdata->gpio_wp); |
464 | if (ret) | 446 | if (ret) |
465 | return ret; | 447 | return ret; |
466 | } else { | ||
467 | pdata->gpio_wp = -EINVAL; | ||
468 | } | 448 | } |
469 | 449 | ||
470 | return 0; | 450 | return 0; |
@@ -882,6 +862,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req | |||
882 | return; | 862 | return; |
883 | host->mrq = NULL; | 863 | host->mrq = NULL; |
884 | mmc_request_done(host->mmc, mrq); | 864 | mmc_request_done(host->mmc, mrq); |
865 | pm_runtime_mark_last_busy(host->dev); | ||
866 | pm_runtime_put_autosuspend(host->dev); | ||
885 | } | 867 | } |
886 | 868 | ||
887 | /* | 869 | /* |
@@ -1252,26 +1234,16 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) | |||
1252 | } | 1234 | } |
1253 | 1235 | ||
1254 | /* | 1236 | /* |
1255 | * irq handler to notify the core about card insertion/removal | 1237 | * irq handler when (cell-phone) cover is mounted/removed |
1256 | */ | 1238 | */ |
1257 | static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) | 1239 | static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id) |
1258 | { | 1240 | { |
1259 | struct omap_hsmmc_host *host = dev_id; | 1241 | struct omap_hsmmc_host *host = dev_id; |
1260 | int carddetect; | ||
1261 | 1242 | ||
1262 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); | 1243 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); |
1263 | 1244 | ||
1264 | if (host->card_detect) | 1245 | omap_hsmmc_protect_card(host); |
1265 | carddetect = host->card_detect(host->dev); | 1246 | mmc_detect_change(host->mmc, (HZ * 200) / 1000); |
1266 | else { | ||
1267 | omap_hsmmc_protect_card(host); | ||
1268 | carddetect = -ENOSYS; | ||
1269 | } | ||
1270 | |||
1271 | if (carddetect) | ||
1272 | mmc_detect_change(host->mmc, (HZ * 200) / 1000); | ||
1273 | else | ||
1274 | mmc_detect_change(host->mmc, (HZ * 50) / 1000); | ||
1275 | return IRQ_HANDLED; | 1247 | return IRQ_HANDLED; |
1276 | } | 1248 | } |
1277 | 1249 | ||
@@ -1305,6 +1277,8 @@ static void omap_hsmmc_dma_callback(void *param) | |||
1305 | 1277 | ||
1306 | host->mrq = NULL; | 1278 | host->mrq = NULL; |
1307 | mmc_request_done(host->mmc, mrq); | 1279 | mmc_request_done(host->mmc, mrq); |
1280 | pm_runtime_mark_last_busy(host->dev); | ||
1281 | pm_runtime_put_autosuspend(host->dev); | ||
1308 | } | 1282 | } |
1309 | } | 1283 | } |
1310 | 1284 | ||
@@ -1537,6 +1511,7 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | |||
1537 | 1511 | ||
1538 | BUG_ON(host->req_in_progress); | 1512 | BUG_ON(host->req_in_progress); |
1539 | BUG_ON(host->dma_ch != -1); | 1513 | BUG_ON(host->dma_ch != -1); |
1514 | pm_runtime_get_sync(host->dev); | ||
1540 | if (host->protect_card) { | 1515 | if (host->protect_card) { |
1541 | if (host->reqs_blocked < 3) { | 1516 | if (host->reqs_blocked < 3) { |
1542 | /* | 1517 | /* |
@@ -1553,6 +1528,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | |||
1553 | req->data->error = -EBADF; | 1528 | req->data->error = -EBADF; |
1554 | req->cmd->retries = 0; | 1529 | req->cmd->retries = 0; |
1555 | mmc_request_done(mmc, req); | 1530 | mmc_request_done(mmc, req); |
1531 | pm_runtime_mark_last_busy(host->dev); | ||
1532 | pm_runtime_put_autosuspend(host->dev); | ||
1556 | return; | 1533 | return; |
1557 | } else if (host->reqs_blocked) | 1534 | } else if (host->reqs_blocked) |
1558 | host->reqs_blocked = 0; | 1535 | host->reqs_blocked = 0; |
@@ -1566,6 +1543,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | |||
1566 | req->data->error = err; | 1543 | req->data->error = err; |
1567 | host->mrq = NULL; | 1544 | host->mrq = NULL; |
1568 | mmc_request_done(mmc, req); | 1545 | mmc_request_done(mmc, req); |
1546 | pm_runtime_mark_last_busy(host->dev); | ||
1547 | pm_runtime_put_autosuspend(host->dev); | ||
1569 | return; | 1548 | return; |
1570 | } | 1549 | } |
1571 | if (req->sbc && !(host->flags & AUTO_CMD23)) { | 1550 | if (req->sbc && !(host->flags & AUTO_CMD23)) { |
@@ -1641,15 +1620,6 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) | |||
1641 | return host->card_detect(host->dev); | 1620 | return host->card_detect(host->dev); |
1642 | } | 1621 | } |
1643 | 1622 | ||
1644 | static int omap_hsmmc_get_ro(struct mmc_host *mmc) | ||
1645 | { | ||
1646 | struct omap_hsmmc_host *host = mmc_priv(mmc); | ||
1647 | |||
1648 | if (!host->get_ro) | ||
1649 | return -ENOSYS; | ||
1650 | return host->get_ro(host->dev); | ||
1651 | } | ||
1652 | |||
1653 | static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) | 1623 | static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) |
1654 | { | 1624 | { |
1655 | struct omap_hsmmc_host *host = mmc_priv(mmc); | 1625 | struct omap_hsmmc_host *host = mmc_priv(mmc); |
@@ -1778,25 +1748,6 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | |||
1778 | set_sd_bus_power(host); | 1748 | set_sd_bus_power(host); |
1779 | } | 1749 | } |
1780 | 1750 | ||
1781 | static int omap_hsmmc_enable_fclk(struct mmc_host *mmc) | ||
1782 | { | ||
1783 | struct omap_hsmmc_host *host = mmc_priv(mmc); | ||
1784 | |||
1785 | pm_runtime_get_sync(host->dev); | ||
1786 | |||
1787 | return 0; | ||
1788 | } | ||
1789 | |||
1790 | static int omap_hsmmc_disable_fclk(struct mmc_host *mmc) | ||
1791 | { | ||
1792 | struct omap_hsmmc_host *host = mmc_priv(mmc); | ||
1793 | |||
1794 | pm_runtime_mark_last_busy(host->dev); | ||
1795 | pm_runtime_put_autosuspend(host->dev); | ||
1796 | |||
1797 | return 0; | ||
1798 | } | ||
1799 | |||
1800 | static int omap_hsmmc_multi_io_quirk(struct mmc_card *card, | 1751 | static int omap_hsmmc_multi_io_quirk(struct mmc_card *card, |
1801 | unsigned int direction, int blk_size) | 1752 | unsigned int direction, int blk_size) |
1802 | { | 1753 | { |
@@ -1808,14 +1759,12 @@ static int omap_hsmmc_multi_io_quirk(struct mmc_card *card, | |||
1808 | } | 1759 | } |
1809 | 1760 | ||
1810 | static struct mmc_host_ops omap_hsmmc_ops = { | 1761 | static struct mmc_host_ops omap_hsmmc_ops = { |
1811 | .enable = omap_hsmmc_enable_fclk, | ||
1812 | .disable = omap_hsmmc_disable_fclk, | ||
1813 | .post_req = omap_hsmmc_post_req, | 1762 | .post_req = omap_hsmmc_post_req, |
1814 | .pre_req = omap_hsmmc_pre_req, | 1763 | .pre_req = omap_hsmmc_pre_req, |
1815 | .request = omap_hsmmc_request, | 1764 | .request = omap_hsmmc_request, |
1816 | .set_ios = omap_hsmmc_set_ios, | 1765 | .set_ios = omap_hsmmc_set_ios, |
1817 | .get_cd = omap_hsmmc_get_cd, | 1766 | .get_cd = omap_hsmmc_get_cd, |
1818 | .get_ro = omap_hsmmc_get_ro, | 1767 | .get_ro = mmc_gpio_get_ro, |
1819 | .init_card = omap_hsmmc_init_card, | 1768 | .init_card = omap_hsmmc_init_card, |
1820 | .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, | 1769 | .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, |
1821 | }; | 1770 | }; |
@@ -1937,7 +1886,8 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
1937 | if (of_find_property(np, "ti,dual-volt", NULL)) | 1886 | if (of_find_property(np, "ti,dual-volt", NULL)) |
1938 | pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; | 1887 | pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; |
1939 | 1888 | ||
1940 | pdata->switch_pin = -EINVAL; | 1889 | pdata->gpio_cd = -EINVAL; |
1890 | pdata->gpio_cod = -EINVAL; | ||
1941 | pdata->gpio_wp = -EINVAL; | 1891 | pdata->gpio_wp = -EINVAL; |
1942 | 1892 | ||
1943 | if (of_find_property(np, "ti,non-removable", NULL)) { | 1893 | if (of_find_property(np, "ti,non-removable", NULL)) { |
@@ -2179,9 +2129,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2179 | if (ret < 0) | 2129 | if (ret < 0) |
2180 | goto err_slot_name; | 2130 | goto err_slot_name; |
2181 | } | 2131 | } |
2182 | if (host->card_detect_irq && host->get_cover_state) { | 2132 | if (host->get_cover_state) { |
2183 | ret = device_create_file(&mmc->class_dev, | 2133 | ret = device_create_file(&mmc->class_dev, |
2184 | &dev_attr_cover_switch); | 2134 | &dev_attr_cover_switch); |
2185 | if (ret < 0) | 2135 | if (ret < 0) |
2186 | goto err_slot_name; | 2136 | goto err_slot_name; |
2187 | } | 2137 | } |
@@ -2236,7 +2186,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
2236 | return 0; | 2186 | return 0; |
2237 | } | 2187 | } |
2238 | 2188 | ||
2239 | #ifdef CONFIG_PM | 2189 | #ifdef CONFIG_PM_SLEEP |
2240 | static int omap_hsmmc_suspend(struct device *dev) | 2190 | static int omap_hsmmc_suspend(struct device *dev) |
2241 | { | 2191 | { |
2242 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 2192 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
@@ -2292,10 +2242,6 @@ static int omap_hsmmc_resume(struct device *dev) | |||
2292 | pm_runtime_put_autosuspend(host->dev); | 2242 | pm_runtime_put_autosuspend(host->dev); |
2293 | return 0; | 2243 | return 0; |
2294 | } | 2244 | } |
2295 | |||
2296 | #else | ||
2297 | #define omap_hsmmc_suspend NULL | ||
2298 | #define omap_hsmmc_resume NULL | ||
2299 | #endif | 2245 | #endif |
2300 | 2246 | ||
2301 | static int omap_hsmmc_runtime_suspend(struct device *dev) | 2247 | static int omap_hsmmc_runtime_suspend(struct device *dev) |
@@ -2376,8 +2322,7 @@ static int omap_hsmmc_runtime_resume(struct device *dev) | |||
2376 | } | 2322 | } |
2377 | 2323 | ||
2378 | static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { | 2324 | static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { |
2379 | .suspend = omap_hsmmc_suspend, | 2325 | SET_SYSTEM_SLEEP_PM_OPS(omap_hsmmc_suspend, omap_hsmmc_resume) |
2380 | .resume = omap_hsmmc_resume, | ||
2381 | .runtime_suspend = omap_hsmmc_runtime_suspend, | 2326 | .runtime_suspend = omap_hsmmc_runtime_suspend, |
2382 | .runtime_resume = omap_hsmmc_runtime_resume, | 2327 | .runtime_resume = omap_hsmmc_runtime_resume, |
2383 | }; | 2328 | }; |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index a45ed39d062c..22d929fa3371 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/mmc/host.h> | 40 | #include <linux/mmc/host.h> |
41 | #include <linux/mmc/pm.h> | 41 | #include <linux/mmc/pm.h> |
42 | #include <linux/mmc/slot-gpio.h> | 42 | #include <linux/mmc/slot-gpio.h> |
43 | #include <linux/mmc/sdhci.h> | ||
44 | 43 | ||
45 | #include "sdhci.h" | 44 | #include "sdhci.h" |
46 | 45 | ||
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 34bb8f92586e..2bd90fb35c75 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c | |||
@@ -54,7 +54,6 @@ | |||
54 | 54 | ||
55 | struct sdhci_bcm_kona_dev { | 55 | struct sdhci_bcm_kona_dev { |
56 | struct mutex write_lock; /* protect back to back writes */ | 56 | struct mutex write_lock; /* protect back to back writes */ |
57 | struct clk *external_clk; | ||
58 | }; | 57 | }; |
59 | 58 | ||
60 | 59 | ||
@@ -175,24 +174,6 @@ static void sdhci_bcm_kona_card_event(struct sdhci_host *host) | |||
175 | } | 174 | } |
176 | } | 175 | } |
177 | 176 | ||
178 | /* | ||
179 | * Get the base clock. Use central clock source for now. Not sure if different | ||
180 | * clock speed to each dev is allowed | ||
181 | */ | ||
182 | static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host) | ||
183 | { | ||
184 | struct sdhci_bcm_kona_dev *kona_dev; | ||
185 | struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); | ||
186 | kona_dev = sdhci_pltfm_priv(pltfm_priv); | ||
187 | |||
188 | return host->mmc->f_max; | ||
189 | } | ||
190 | |||
191 | static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host) | ||
192 | { | ||
193 | return sdhci_bcm_kona_get_max_clk(host); | ||
194 | } | ||
195 | |||
196 | static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, | 177 | static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, |
197 | u8 power_mode) | 178 | u8 power_mode) |
198 | { | 179 | { |
@@ -207,8 +188,8 @@ static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, | |||
207 | 188 | ||
208 | static struct sdhci_ops sdhci_bcm_kona_ops = { | 189 | static struct sdhci_ops sdhci_bcm_kona_ops = { |
209 | .set_clock = sdhci_set_clock, | 190 | .set_clock = sdhci_set_clock, |
210 | .get_max_clock = sdhci_bcm_kona_get_max_clk, | 191 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, |
211 | .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, | 192 | .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, |
212 | .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, | 193 | .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, |
213 | .set_bus_width = sdhci_set_bus_width, | 194 | .set_bus_width = sdhci_set_bus_width, |
214 | .reset = sdhci_reset, | 195 | .reset = sdhci_reset, |
@@ -264,21 +245,21 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev) | |||
264 | goto err_pltfm_free; | 245 | goto err_pltfm_free; |
265 | } | 246 | } |
266 | 247 | ||
267 | /* Get and enable the external clock */ | 248 | /* Get and enable the core clock */ |
268 | kona_dev->external_clk = devm_clk_get(dev, NULL); | 249 | pltfm_priv->clk = devm_clk_get(dev, NULL); |
269 | if (IS_ERR(kona_dev->external_clk)) { | 250 | if (IS_ERR(pltfm_priv->clk)) { |
270 | dev_err(dev, "Failed to get external clock\n"); | 251 | dev_err(dev, "Failed to get core clock\n"); |
271 | ret = PTR_ERR(kona_dev->external_clk); | 252 | ret = PTR_ERR(pltfm_priv->clk); |
272 | goto err_pltfm_free; | 253 | goto err_pltfm_free; |
273 | } | 254 | } |
274 | 255 | ||
275 | if (clk_set_rate(kona_dev->external_clk, host->mmc->f_max) != 0) { | 256 | if (clk_set_rate(pltfm_priv->clk, host->mmc->f_max) != 0) { |
276 | dev_err(dev, "Failed to set rate external clock\n"); | 257 | dev_err(dev, "Failed to set rate core clock\n"); |
277 | goto err_pltfm_free; | 258 | goto err_pltfm_free; |
278 | } | 259 | } |
279 | 260 | ||
280 | if (clk_prepare_enable(kona_dev->external_clk) != 0) { | 261 | if (clk_prepare_enable(pltfm_priv->clk) != 0) { |
281 | dev_err(dev, "Failed to enable external clock\n"); | 262 | dev_err(dev, "Failed to enable core clock\n"); |
282 | goto err_pltfm_free; | 263 | goto err_pltfm_free; |
283 | } | 264 | } |
284 | 265 | ||
@@ -333,7 +314,7 @@ err_reset: | |||
333 | sdhci_bcm_kona_sd_reset(host); | 314 | sdhci_bcm_kona_sd_reset(host); |
334 | 315 | ||
335 | err_clk_disable: | 316 | err_clk_disable: |
336 | clk_disable_unprepare(kona_dev->external_clk); | 317 | clk_disable_unprepare(pltfm_priv->clk); |
337 | 318 | ||
338 | err_pltfm_free: | 319 | err_pltfm_free: |
339 | sdhci_pltfm_free(pdev); | 320 | sdhci_pltfm_free(pdev); |
@@ -342,22 +323,6 @@ err_pltfm_free: | |||
342 | return ret; | 323 | return ret; |
343 | } | 324 | } |
344 | 325 | ||
345 | static int sdhci_bcm_kona_remove(struct platform_device *pdev) | ||
346 | { | ||
347 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
348 | struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); | ||
349 | struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); | ||
350 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); | ||
351 | |||
352 | sdhci_remove_host(host, dead); | ||
353 | |||
354 | clk_disable_unprepare(kona_dev->external_clk); | ||
355 | |||
356 | sdhci_pltfm_free(pdev); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static struct platform_driver sdhci_bcm_kona_driver = { | 326 | static struct platform_driver sdhci_bcm_kona_driver = { |
362 | .driver = { | 327 | .driver = { |
363 | .name = "sdhci-kona", | 328 | .name = "sdhci-kona", |
@@ -365,7 +330,7 @@ static struct platform_driver sdhci_bcm_kona_driver = { | |||
365 | .of_match_table = sdhci_bcm_kona_of_match, | 330 | .of_match_table = sdhci_bcm_kona_of_match, |
366 | }, | 331 | }, |
367 | .probe = sdhci_bcm_kona_probe, | 332 | .probe = sdhci_bcm_kona_probe, |
368 | .remove = sdhci_bcm_kona_remove, | 333 | .remove = sdhci_pltfm_unregister, |
369 | }; | 334 | }; |
370 | module_platform_driver(sdhci_bcm_kona_driver); | 335 | module_platform_driver(sdhci_bcm_kona_driver); |
371 | 336 | ||
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c index 439d259fdf1d..0ef0343c603a 100644 --- a/drivers/mmc/host/sdhci-bcm2835.c +++ b/drivers/mmc/host/sdhci-bcm2835.c | |||
@@ -180,11 +180,6 @@ err: | |||
180 | return ret; | 180 | return ret; |
181 | } | 181 | } |
182 | 182 | ||
183 | static int bcm2835_sdhci_remove(struct platform_device *pdev) | ||
184 | { | ||
185 | return sdhci_pltfm_unregister(pdev); | ||
186 | } | ||
187 | |||
188 | static const struct of_device_id bcm2835_sdhci_of_match[] = { | 183 | static const struct of_device_id bcm2835_sdhci_of_match[] = { |
189 | { .compatible = "brcm,bcm2835-sdhci" }, | 184 | { .compatible = "brcm,bcm2835-sdhci" }, |
190 | { } | 185 | { } |
@@ -198,7 +193,7 @@ static struct platform_driver bcm2835_sdhci_driver = { | |||
198 | .pm = SDHCI_PLTFM_PMOPS, | 193 | .pm = SDHCI_PLTFM_PMOPS, |
199 | }, | 194 | }, |
200 | .probe = bcm2835_sdhci_probe, | 195 | .probe = bcm2835_sdhci_probe, |
201 | .remove = bcm2835_sdhci_remove, | 196 | .remove = sdhci_pltfm_unregister, |
202 | }; | 197 | }; |
203 | module_platform_driver(bcm2835_sdhci_driver); | 198 | module_platform_driver(bcm2835_sdhci_driver); |
204 | 199 | ||
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index a7935a8d0922..59f2923f8054 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c | |||
@@ -98,18 +98,13 @@ static int sdhci_cns3xxx_probe(struct platform_device *pdev) | |||
98 | return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata, 0); | 98 | return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata, 0); |
99 | } | 99 | } |
100 | 100 | ||
101 | static int sdhci_cns3xxx_remove(struct platform_device *pdev) | ||
102 | { | ||
103 | return sdhci_pltfm_unregister(pdev); | ||
104 | } | ||
105 | |||
106 | static struct platform_driver sdhci_cns3xxx_driver = { | 101 | static struct platform_driver sdhci_cns3xxx_driver = { |
107 | .driver = { | 102 | .driver = { |
108 | .name = "sdhci-cns3xxx", | 103 | .name = "sdhci-cns3xxx", |
109 | .pm = SDHCI_PLTFM_PMOPS, | 104 | .pm = SDHCI_PLTFM_PMOPS, |
110 | }, | 105 | }, |
111 | .probe = sdhci_cns3xxx_probe, | 106 | .probe = sdhci_cns3xxx_probe, |
112 | .remove = sdhci_cns3xxx_remove, | 107 | .remove = sdhci_pltfm_unregister, |
113 | }; | 108 | }; |
114 | 109 | ||
115 | module_platform_driver(sdhci_cns3xxx_driver); | 110 | module_platform_driver(sdhci_cns3xxx_driver); |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index ca969d271a27..407c21f152b2 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
@@ -28,10 +28,6 @@ | |||
28 | 28 | ||
29 | #include "sdhci-pltfm.h" | 29 | #include "sdhci-pltfm.h" |
30 | 30 | ||
31 | struct sdhci_dove_priv { | ||
32 | struct clk *clk; | ||
33 | }; | ||
34 | |||
35 | static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) | 31 | static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) |
36 | { | 32 | { |
37 | u16 ret; | 33 | u16 ret; |
@@ -84,27 +80,17 @@ static int sdhci_dove_probe(struct platform_device *pdev) | |||
84 | { | 80 | { |
85 | struct sdhci_host *host; | 81 | struct sdhci_host *host; |
86 | struct sdhci_pltfm_host *pltfm_host; | 82 | struct sdhci_pltfm_host *pltfm_host; |
87 | struct sdhci_dove_priv *priv; | ||
88 | int ret; | 83 | int ret; |
89 | 84 | ||
90 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), | ||
91 | GFP_KERNEL); | ||
92 | if (!priv) { | ||
93 | dev_err(&pdev->dev, "unable to allocate private data"); | ||
94 | return -ENOMEM; | ||
95 | } | ||
96 | |||
97 | priv->clk = devm_clk_get(&pdev->dev, NULL); | ||
98 | |||
99 | host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0); | 85 | host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0); |
100 | if (IS_ERR(host)) | 86 | if (IS_ERR(host)) |
101 | return PTR_ERR(host); | 87 | return PTR_ERR(host); |
102 | 88 | ||
103 | pltfm_host = sdhci_priv(host); | 89 | pltfm_host = sdhci_priv(host); |
104 | pltfm_host->priv = priv; | 90 | pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); |
105 | 91 | ||
106 | if (!IS_ERR(priv->clk)) | 92 | if (!IS_ERR(pltfm_host->clk)) |
107 | clk_prepare_enable(priv->clk); | 93 | clk_prepare_enable(pltfm_host->clk); |
108 | 94 | ||
109 | ret = mmc_of_parse(host->mmc); | 95 | ret = mmc_of_parse(host->mmc); |
110 | if (ret) | 96 | if (ret) |
@@ -117,26 +103,11 @@ static int sdhci_dove_probe(struct platform_device *pdev) | |||
117 | return 0; | 103 | return 0; |
118 | 104 | ||
119 | err_sdhci_add: | 105 | err_sdhci_add: |
120 | if (!IS_ERR(priv->clk)) | 106 | clk_disable_unprepare(pltfm_host->clk); |
121 | clk_disable_unprepare(priv->clk); | ||
122 | sdhci_pltfm_free(pdev); | 107 | sdhci_pltfm_free(pdev); |
123 | return ret; | 108 | return ret; |
124 | } | 109 | } |
125 | 110 | ||
126 | static int sdhci_dove_remove(struct platform_device *pdev) | ||
127 | { | ||
128 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
129 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
130 | struct sdhci_dove_priv *priv = pltfm_host->priv; | ||
131 | |||
132 | sdhci_pltfm_unregister(pdev); | ||
133 | |||
134 | if (!IS_ERR(priv->clk)) | ||
135 | clk_disable_unprepare(priv->clk); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static const struct of_device_id sdhci_dove_of_match_table[] = { | 111 | static const struct of_device_id sdhci_dove_of_match_table[] = { |
141 | { .compatible = "marvell,dove-sdhci", }, | 112 | { .compatible = "marvell,dove-sdhci", }, |
142 | {} | 113 | {} |
@@ -150,7 +121,7 @@ static struct platform_driver sdhci_dove_driver = { | |||
150 | .of_match_table = sdhci_dove_of_match_table, | 121 | .of_match_table = sdhci_dove_of_match_table, |
151 | }, | 122 | }, |
152 | .probe = sdhci_dove_probe, | 123 | .probe = sdhci_dove_probe, |
153 | .remove = sdhci_dove_remove, | 124 | .remove = sdhci_pltfm_unregister, |
154 | }; | 125 | }; |
155 | 126 | ||
156 | module_platform_driver(sdhci_dove_driver); | 127 | module_platform_driver(sdhci_dove_driver); |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 10ef8244a239..82f512d87cb8 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -416,7 +416,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
416 | new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; | 416 | new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; |
417 | else | 417 | else |
418 | new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; | 418 | new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; |
419 | writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); | 419 | writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); |
420 | return; | 420 | return; |
421 | case SDHCI_HOST_CONTROL2: | 421 | case SDHCI_HOST_CONTROL2: |
422 | new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | 422 | new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); |
@@ -864,6 +864,7 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { | |||
864 | #ifdef CONFIG_OF | 864 | #ifdef CONFIG_OF |
865 | static int | 865 | static int |
866 | sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, | 866 | sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, |
867 | struct sdhci_host *host, | ||
867 | struct esdhc_platform_data *boarddata) | 868 | struct esdhc_platform_data *boarddata) |
868 | { | 869 | { |
869 | struct device_node *np = pdev->dev.of_node; | 870 | struct device_node *np = pdev->dev.of_node; |
@@ -900,11 +901,14 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, | |||
900 | if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) | 901 | if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) |
901 | boarddata->delay_line = 0; | 902 | boarddata->delay_line = 0; |
902 | 903 | ||
904 | mmc_of_parse_voltage(np, &host->ocr_mask); | ||
905 | |||
903 | return 0; | 906 | return 0; |
904 | } | 907 | } |
905 | #else | 908 | #else |
906 | static inline int | 909 | static inline int |
907 | sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, | 910 | sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, |
911 | struct sdhci_host *host, | ||
908 | struct esdhc_platform_data *boarddata) | 912 | struct esdhc_platform_data *boarddata) |
909 | { | 913 | { |
910 | return -ENODEV; | 914 | return -ENODEV; |
@@ -999,7 +1003,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
999 | host->ioaddr + ESDHC_TUNING_CTRL); | 1003 | host->ioaddr + ESDHC_TUNING_CTRL); |
1000 | 1004 | ||
1001 | boarddata = &imx_data->boarddata; | 1005 | boarddata = &imx_data->boarddata; |
1002 | if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { | 1006 | if (sdhci_esdhc_imx_probe_dt(pdev, host, boarddata) < 0) { |
1003 | if (!host->mmc->parent->platform_data) { | 1007 | if (!host->mmc->parent->platform_data) { |
1004 | dev_err(mmc_dev(host->mmc), "no board data!\n"); | 1008 | dev_err(mmc_dev(host->mmc), "no board data!\n"); |
1005 | err = -EINVAL; | 1009 | err = -EINVAL; |
@@ -1009,40 +1013,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
1009 | host->mmc->parent->platform_data); | 1013 | host->mmc->parent->platform_data); |
1010 | } | 1014 | } |
1011 | 1015 | ||
1012 | /* write_protect */ | ||
1013 | if (boarddata->wp_type == ESDHC_WP_GPIO) { | ||
1014 | err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); | ||
1015 | if (err) { | ||
1016 | dev_err(mmc_dev(host->mmc), | ||
1017 | "failed to request write-protect gpio!\n"); | ||
1018 | goto disable_clk; | ||
1019 | } | ||
1020 | host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; | ||
1021 | } | ||
1022 | |||
1023 | /* card_detect */ | 1016 | /* card_detect */ |
1024 | switch (boarddata->cd_type) { | 1017 | if (boarddata->cd_type == ESDHC_CD_CONTROLLER) |
1025 | case ESDHC_CD_GPIO: | ||
1026 | err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); | ||
1027 | if (err) { | ||
1028 | dev_err(mmc_dev(host->mmc), | ||
1029 | "failed to request card-detect gpio!\n"); | ||
1030 | goto disable_clk; | ||
1031 | } | ||
1032 | /* fall through */ | ||
1033 | |||
1034 | case ESDHC_CD_CONTROLLER: | ||
1035 | /* we have a working card_detect back */ | ||
1036 | host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; | 1018 | host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; |
1037 | break; | ||
1038 | |||
1039 | case ESDHC_CD_PERMANENT: | ||
1040 | host->mmc->caps |= MMC_CAP_NONREMOVABLE; | ||
1041 | break; | ||
1042 | |||
1043 | case ESDHC_CD_NONE: | ||
1044 | break; | ||
1045 | } | ||
1046 | 1019 | ||
1047 | switch (boarddata->max_bus_width) { | 1020 | switch (boarddata->max_bus_width) { |
1048 | case 8: | 1021 | case 8: |
@@ -1075,6 +1048,11 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
1075 | host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; | 1048 | host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; |
1076 | } | 1049 | } |
1077 | 1050 | ||
1051 | /* call to generic mmc_of_parse to support additional capabilities */ | ||
1052 | err = mmc_of_parse(host->mmc); | ||
1053 | if (err) | ||
1054 | goto disable_clk; | ||
1055 | |||
1078 | err = sdhci_add_host(host); | 1056 | err = sdhci_add_host(host); |
1079 | if (err) | 1057 | if (err) |
1080 | goto disable_clk; | 1058 | goto disable_clk; |
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c new file mode 100644 index 000000000000..3b423b0ad8e7 --- /dev/null +++ b/drivers/mmc/host/sdhci-iproc.c | |||
@@ -0,0 +1,241 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * iProc SDHCI platform driver | ||
16 | */ | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mmc/host.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | ||
23 | #include "sdhci-pltfm.h" | ||
24 | |||
25 | struct sdhci_iproc_data { | ||
26 | const struct sdhci_pltfm_data *pdata; | ||
27 | u32 caps; | ||
28 | u32 caps1; | ||
29 | }; | ||
30 | |||
31 | struct sdhci_iproc_host { | ||
32 | const struct sdhci_iproc_data *data; | ||
33 | u32 shadow_cmd; | ||
34 | u32 shadow_blk; | ||
35 | }; | ||
36 | |||
37 | #define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18) | ||
38 | |||
39 | static inline u32 sdhci_iproc_readl(struct sdhci_host *host, int reg) | ||
40 | { | ||
41 | u32 val = readl(host->ioaddr + reg); | ||
42 | |||
43 | pr_debug("%s: readl [0x%02x] 0x%08x\n", | ||
44 | mmc_hostname(host->mmc), reg, val); | ||
45 | return val; | ||
46 | } | ||
47 | |||
48 | static u16 sdhci_iproc_readw(struct sdhci_host *host, int reg) | ||
49 | { | ||
50 | u32 val = sdhci_iproc_readl(host, (reg & ~3)); | ||
51 | u16 word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff; | ||
52 | return word; | ||
53 | } | ||
54 | |||
55 | static u8 sdhci_iproc_readb(struct sdhci_host *host, int reg) | ||
56 | { | ||
57 | u32 val = sdhci_iproc_readl(host, (reg & ~3)); | ||
58 | u8 byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff; | ||
59 | return byte; | ||
60 | } | ||
61 | |||
62 | static inline void sdhci_iproc_writel(struct sdhci_host *host, u32 val, int reg) | ||
63 | { | ||
64 | pr_debug("%s: writel [0x%02x] 0x%08x\n", | ||
65 | mmc_hostname(host->mmc), reg, val); | ||
66 | |||
67 | writel(val, host->ioaddr + reg); | ||
68 | |||
69 | if (host->clock <= 400000) { | ||
70 | /* Round up to micro-second four SD clock delay */ | ||
71 | if (host->clock) | ||
72 | udelay((4 * 1000000 + host->clock - 1) / host->clock); | ||
73 | else | ||
74 | udelay(10); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * The Arasan has a bugette whereby it may lose the content of successive | ||
80 | * writes to the same register that are within two SD-card clock cycles of | ||
81 | * each other (a clock domain crossing problem). The data | ||
82 | * register does not have this problem, which is just as well - otherwise we'd | ||
83 | * have to nobble the DMA engine too. | ||
84 | * | ||
85 | * This wouldn't be a problem with the code except that we can only write the | ||
86 | * controller with 32-bit writes. So two different 16-bit registers are | ||
87 | * written back to back creates the problem. | ||
88 | * | ||
89 | * In reality, this only happens when SDHCI_BLOCK_SIZE and SDHCI_BLOCK_COUNT | ||
90 | * are written followed by SDHCI_TRANSFER_MODE and SDHCI_COMMAND. | ||
91 | * The BLOCK_SIZE and BLOCK_COUNT are meaningless until a command issued so | ||
92 | * the work around can be further optimized. We can keep shadow values of | ||
93 | * BLOCK_SIZE, BLOCK_COUNT, and TRANSFER_MODE until a COMMAND is issued. | ||
94 | * Then, write the BLOCK_SIZE+BLOCK_COUNT in a single 32-bit write followed | ||
95 | * by the TRANSFER+COMMAND in another 32-bit write. | ||
96 | */ | ||
97 | static void sdhci_iproc_writew(struct sdhci_host *host, u16 val, int reg) | ||
98 | { | ||
99 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
100 | struct sdhci_iproc_host *iproc_host = sdhci_pltfm_priv(pltfm_host); | ||
101 | u32 word_shift = REG_OFFSET_IN_BITS(reg); | ||
102 | u32 mask = 0xffff << word_shift; | ||
103 | u32 oldval, newval; | ||
104 | |||
105 | if (reg == SDHCI_COMMAND) { | ||
106 | /* Write the block now as we are issuing a command */ | ||
107 | if (iproc_host->shadow_blk != 0) { | ||
108 | sdhci_iproc_writel(host, iproc_host->shadow_blk, | ||
109 | SDHCI_BLOCK_SIZE); | ||
110 | iproc_host->shadow_blk = 0; | ||
111 | } | ||
112 | oldval = iproc_host->shadow_cmd; | ||
113 | } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) { | ||
114 | /* Block size and count are stored in shadow reg */ | ||
115 | oldval = iproc_host->shadow_blk; | ||
116 | } else { | ||
117 | /* Read reg, all other registers are not shadowed */ | ||
118 | oldval = sdhci_iproc_readl(host, (reg & ~3)); | ||
119 | } | ||
120 | newval = (oldval & ~mask) | (val << word_shift); | ||
121 | |||
122 | if (reg == SDHCI_TRANSFER_MODE) { | ||
123 | /* Save the transfer mode until the command is issued */ | ||
124 | iproc_host->shadow_cmd = newval; | ||
125 | } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) { | ||
126 | /* Save the block info until the command is issued */ | ||
127 | iproc_host->shadow_blk = newval; | ||
128 | } else { | ||
129 | /* Command or other regular 32-bit write */ | ||
130 | sdhci_iproc_writel(host, newval, reg & ~3); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void sdhci_iproc_writeb(struct sdhci_host *host, u8 val, int reg) | ||
135 | { | ||
136 | u32 oldval = sdhci_iproc_readl(host, (reg & ~3)); | ||
137 | u32 byte_shift = REG_OFFSET_IN_BITS(reg); | ||
138 | u32 mask = 0xff << byte_shift; | ||
139 | u32 newval = (oldval & ~mask) | (val << byte_shift); | ||
140 | |||
141 | sdhci_iproc_writel(host, newval, reg & ~3); | ||
142 | } | ||
143 | |||
144 | static const struct sdhci_ops sdhci_iproc_ops = { | ||
145 | .read_l = sdhci_iproc_readl, | ||
146 | .read_w = sdhci_iproc_readw, | ||
147 | .read_b = sdhci_iproc_readb, | ||
148 | .write_l = sdhci_iproc_writel, | ||
149 | .write_w = sdhci_iproc_writew, | ||
150 | .write_b = sdhci_iproc_writeb, | ||
151 | .set_clock = sdhci_set_clock, | ||
152 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | ||
153 | .set_bus_width = sdhci_set_bus_width, | ||
154 | .reset = sdhci_reset, | ||
155 | .set_uhs_signaling = sdhci_set_uhs_signaling, | ||
156 | }; | ||
157 | |||
158 | static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = { | ||
159 | .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, | ||
160 | .quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN, | ||
161 | .ops = &sdhci_iproc_ops, | ||
162 | }; | ||
163 | |||
164 | static const struct sdhci_iproc_data iproc_data = { | ||
165 | .pdata = &sdhci_iproc_pltfm_data, | ||
166 | .caps = 0x05E90000, | ||
167 | .caps1 = 0x00000064, | ||
168 | }; | ||
169 | |||
170 | static const struct of_device_id sdhci_iproc_of_match[] = { | ||
171 | { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_data }, | ||
172 | { } | ||
173 | }; | ||
174 | MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match); | ||
175 | |||
176 | static int sdhci_iproc_probe(struct platform_device *pdev) | ||
177 | { | ||
178 | const struct of_device_id *match; | ||
179 | const struct sdhci_iproc_data *iproc_data; | ||
180 | struct sdhci_host *host; | ||
181 | struct sdhci_iproc_host *iproc_host; | ||
182 | struct sdhci_pltfm_host *pltfm_host; | ||
183 | int ret; | ||
184 | |||
185 | match = of_match_device(sdhci_iproc_of_match, &pdev->dev); | ||
186 | if (!match) | ||
187 | return -EINVAL; | ||
188 | iproc_data = match->data; | ||
189 | |||
190 | host = sdhci_pltfm_init(pdev, iproc_data->pdata, sizeof(*iproc_host)); | ||
191 | if (IS_ERR(host)) | ||
192 | return PTR_ERR(host); | ||
193 | |||
194 | pltfm_host = sdhci_priv(host); | ||
195 | iproc_host = sdhci_pltfm_priv(pltfm_host); | ||
196 | |||
197 | iproc_host->data = iproc_data; | ||
198 | |||
199 | mmc_of_parse(host->mmc); | ||
200 | sdhci_get_of_property(pdev); | ||
201 | |||
202 | /* Enable EMMC 1/8V DDR capable */ | ||
203 | host->mmc->caps |= MMC_CAP_1_8V_DDR; | ||
204 | |||
205 | pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); | ||
206 | if (IS_ERR(pltfm_host->clk)) { | ||
207 | ret = PTR_ERR(pltfm_host->clk); | ||
208 | goto err; | ||
209 | } | ||
210 | |||
211 | if (iproc_host->data->pdata->quirks & SDHCI_QUIRK_MISSING_CAPS) { | ||
212 | host->caps = iproc_host->data->caps; | ||
213 | host->caps1 = iproc_host->data->caps1; | ||
214 | } | ||
215 | |||
216 | return sdhci_add_host(host); | ||
217 | |||
218 | err: | ||
219 | sdhci_pltfm_free(pdev); | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static int sdhci_iproc_remove(struct platform_device *pdev) | ||
224 | { | ||
225 | return sdhci_pltfm_unregister(pdev); | ||
226 | } | ||
227 | |||
228 | static struct platform_driver sdhci_iproc_driver = { | ||
229 | .driver = { | ||
230 | .name = "sdhci-iproc", | ||
231 | .of_match_table = sdhci_iproc_of_match, | ||
232 | .pm = SDHCI_PLTFM_PMOPS, | ||
233 | }, | ||
234 | .probe = sdhci_iproc_probe, | ||
235 | .remove = sdhci_iproc_remove, | ||
236 | }; | ||
237 | module_platform_driver(sdhci_iproc_driver); | ||
238 | |||
239 | MODULE_AUTHOR("Broadcom"); | ||
240 | MODULE_DESCRIPTION("IPROC SDHCI driver"); | ||
241 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 3d32ce896b09..4a09f7608c66 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c | |||
@@ -22,6 +22,11 @@ | |||
22 | 22 | ||
23 | #include "sdhci-pltfm.h" | 23 | #include "sdhci-pltfm.h" |
24 | 24 | ||
25 | #define CORE_MCI_VERSION 0x50 | ||
26 | #define CORE_VERSION_MAJOR_SHIFT 28 | ||
27 | #define CORE_VERSION_MAJOR_MASK (0xf << CORE_VERSION_MAJOR_SHIFT) | ||
28 | #define CORE_VERSION_MINOR_MASK 0xff | ||
29 | |||
25 | #define CORE_HC_MODE 0x78 | 30 | #define CORE_HC_MODE 0x78 |
26 | #define HC_MODE_EN 0x1 | 31 | #define HC_MODE_EN 0x1 |
27 | #define CORE_POWER 0x0 | 32 | #define CORE_POWER 0x0 |
@@ -41,6 +46,8 @@ | |||
41 | #define CORE_VENDOR_SPEC 0x10c | 46 | #define CORE_VENDOR_SPEC 0x10c |
42 | #define CORE_CLK_PWRSAVE BIT(1) | 47 | #define CORE_CLK_PWRSAVE BIT(1) |
43 | 48 | ||
49 | #define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c | ||
50 | |||
44 | #define CDR_SELEXT_SHIFT 20 | 51 | #define CDR_SELEXT_SHIFT 20 |
45 | #define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT) | 52 | #define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT) |
46 | #define CMUX_SHIFT_PHASE_SHIFT 24 | 53 | #define CMUX_SHIFT_PHASE_SHIFT 24 |
@@ -426,7 +433,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) | |||
426 | struct sdhci_msm_host *msm_host; | 433 | struct sdhci_msm_host *msm_host; |
427 | struct resource *core_memres; | 434 | struct resource *core_memres; |
428 | int ret; | 435 | int ret; |
429 | u16 host_version; | 436 | u16 host_version, core_minor; |
437 | u32 core_version, caps; | ||
438 | u8 core_major; | ||
430 | 439 | ||
431 | msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); | 440 | msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); |
432 | if (!msm_host) | 441 | if (!msm_host) |
@@ -516,6 +525,24 @@ static int sdhci_msm_probe(struct platform_device *pdev) | |||
516 | host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> | 525 | host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> |
517 | SDHCI_VENDOR_VER_SHIFT)); | 526 | SDHCI_VENDOR_VER_SHIFT)); |
518 | 527 | ||
528 | core_version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION); | ||
529 | core_major = (core_version & CORE_VERSION_MAJOR_MASK) >> | ||
530 | CORE_VERSION_MAJOR_SHIFT; | ||
531 | core_minor = core_version & CORE_VERSION_MINOR_MASK; | ||
532 | dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n", | ||
533 | core_version, core_major, core_minor); | ||
534 | |||
535 | /* | ||
536 | * Support for some capabilities is not advertised by newer | ||
537 | * controller versions and must be explicitly enabled. | ||
538 | */ | ||
539 | if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) { | ||
540 | caps = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES); | ||
541 | caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT; | ||
542 | writel_relaxed(caps, host->ioaddr + | ||
543 | CORE_VENDOR_SPEC_CAPABILITIES0); | ||
544 | } | ||
545 | |||
519 | ret = sdhci_add_host(host); | 546 | ret = sdhci_add_host(host); |
520 | if (ret) | 547 | if (ret) |
521 | goto clk_disable; | 548 | goto clk_disable; |
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index bcb51e9dfdcd..6287d426c96b 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c | |||
@@ -173,6 +173,12 @@ static int sdhci_arasan_probe(struct platform_device *pdev) | |||
173 | pltfm_host->priv = sdhci_arasan; | 173 | pltfm_host->priv = sdhci_arasan; |
174 | pltfm_host->clk = clk_xin; | 174 | pltfm_host->clk = clk_xin; |
175 | 175 | ||
176 | ret = mmc_of_parse(host->mmc); | ||
177 | if (ret) { | ||
178 | dev_err(&pdev->dev, "parsing dt failed (%u)\n", ret); | ||
179 | goto clk_disable_all; | ||
180 | } | ||
181 | |||
176 | ret = sdhci_add_host(host); | 182 | ret = sdhci_add_host(host); |
177 | if (ret) | 183 | if (ret) |
178 | goto err_pltfm_free; | 184 | goto err_pltfm_free; |
@@ -195,7 +201,6 @@ static int sdhci_arasan_remove(struct platform_device *pdev) | |||
195 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 201 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
196 | struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; | 202 | struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; |
197 | 203 | ||
198 | clk_disable_unprepare(pltfm_host->clk); | ||
199 | clk_disable_unprepare(sdhci_arasan->clk_ahb); | 204 | clk_disable_unprepare(sdhci_arasan->clk_ahb); |
200 | 205 | ||
201 | return sdhci_pltfm_unregister(pdev); | 206 | return sdhci_pltfm_unregister(pdev); |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 17fe02ed6672..22e9111b11ff 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -386,11 +386,6 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) | |||
386 | return ret; | 386 | return ret; |
387 | } | 387 | } |
388 | 388 | ||
389 | static int sdhci_esdhc_remove(struct platform_device *pdev) | ||
390 | { | ||
391 | return sdhci_pltfm_unregister(pdev); | ||
392 | } | ||
393 | |||
394 | static const struct of_device_id sdhci_esdhc_of_match[] = { | 389 | static const struct of_device_id sdhci_esdhc_of_match[] = { |
395 | { .compatible = "fsl,mpc8379-esdhc" }, | 390 | { .compatible = "fsl,mpc8379-esdhc" }, |
396 | { .compatible = "fsl,mpc8536-esdhc" }, | 391 | { .compatible = "fsl,mpc8536-esdhc" }, |
@@ -406,7 +401,7 @@ static struct platform_driver sdhci_esdhc_driver = { | |||
406 | .pm = ESDHC_PMOPS, | 401 | .pm = ESDHC_PMOPS, |
407 | }, | 402 | }, |
408 | .probe = sdhci_esdhc_probe, | 403 | .probe = sdhci_esdhc_probe, |
409 | .remove = sdhci_esdhc_remove, | 404 | .remove = sdhci_pltfm_unregister, |
410 | }; | 405 | }; |
411 | 406 | ||
412 | module_platform_driver(sdhci_esdhc_driver); | 407 | module_platform_driver(sdhci_esdhc_driver); |
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index be479279a1d5..4079a96ad37e 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c | |||
@@ -75,11 +75,6 @@ static int sdhci_hlwd_probe(struct platform_device *pdev) | |||
75 | return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0); | 75 | return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0); |
76 | } | 76 | } |
77 | 77 | ||
78 | static int sdhci_hlwd_remove(struct platform_device *pdev) | ||
79 | { | ||
80 | return sdhci_pltfm_unregister(pdev); | ||
81 | } | ||
82 | |||
83 | static const struct of_device_id sdhci_hlwd_of_match[] = { | 78 | static const struct of_device_id sdhci_hlwd_of_match[] = { |
84 | { .compatible = "nintendo,hollywood-sdhci" }, | 79 | { .compatible = "nintendo,hollywood-sdhci" }, |
85 | { } | 80 | { } |
@@ -93,7 +88,7 @@ static struct platform_driver sdhci_hlwd_driver = { | |||
93 | .pm = SDHCI_PLTFM_PMOPS, | 88 | .pm = SDHCI_PLTFM_PMOPS, |
94 | }, | 89 | }, |
95 | .probe = sdhci_hlwd_probe, | 90 | .probe = sdhci_hlwd_probe, |
96 | .remove = sdhci_hlwd_remove, | 91 | .remove = sdhci_pltfm_unregister, |
97 | }; | 92 | }; |
98 | 93 | ||
99 | module_platform_driver(sdhci_hlwd_driver); | 94 | module_platform_driver(sdhci_hlwd_driver); |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 29eaff78238e..7a3fc16d0a6c 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -650,6 +650,7 @@ static int rtsx_probe_slot(struct sdhci_pci_slot *slot) | |||
650 | 650 | ||
651 | static const struct sdhci_pci_fixes sdhci_rtsx = { | 651 | static const struct sdhci_pci_fixes sdhci_rtsx = { |
652 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | 652 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
653 | SDHCI_QUIRK2_BROKEN_64_BIT_DMA | | ||
653 | SDHCI_QUIRK2_BROKEN_DDR50, | 654 | SDHCI_QUIRK2_BROKEN_DDR50, |
654 | .probe_slot = rtsx_probe_slot, | 655 | .probe_slot = rtsx_probe_slot, |
655 | }; | 656 | }; |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index c5b01d6bb85d..a207f5aaf62f 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -75,43 +75,41 @@ void sdhci_get_of_property(struct platform_device *pdev) | |||
75 | u32 bus_width; | 75 | u32 bus_width; |
76 | int size; | 76 | int size; |
77 | 77 | ||
78 | if (of_device_is_available(np)) { | 78 | if (of_get_property(np, "sdhci,auto-cmd12", NULL)) |
79 | if (of_get_property(np, "sdhci,auto-cmd12", NULL)) | 79 | host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; |
80 | host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; | ||
81 | 80 | ||
82 | if (of_get_property(np, "sdhci,1-bit-only", NULL) || | 81 | if (of_get_property(np, "sdhci,1-bit-only", NULL) || |
83 | (of_property_read_u32(np, "bus-width", &bus_width) == 0 && | 82 | (of_property_read_u32(np, "bus-width", &bus_width) == 0 && |
84 | bus_width == 1)) | 83 | bus_width == 1)) |
85 | host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; | 84 | host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; |
86 | 85 | ||
87 | if (sdhci_of_wp_inverted(np)) | 86 | if (sdhci_of_wp_inverted(np)) |
88 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; | 87 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; |
89 | 88 | ||
90 | if (of_get_property(np, "broken-cd", NULL)) | 89 | if (of_get_property(np, "broken-cd", NULL)) |
91 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; | 90 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; |
92 | 91 | ||
93 | if (of_get_property(np, "no-1-8-v", NULL)) | 92 | if (of_get_property(np, "no-1-8-v", NULL)) |
94 | host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; | 93 | host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; |
95 | 94 | ||
96 | if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) | 95 | if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) |
97 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; | 96 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; |
98 | 97 | ||
99 | if (of_device_is_compatible(np, "fsl,p2020-esdhc") || | 98 | if (of_device_is_compatible(np, "fsl,p2020-esdhc") || |
100 | of_device_is_compatible(np, "fsl,p1010-esdhc") || | 99 | of_device_is_compatible(np, "fsl,p1010-esdhc") || |
101 | of_device_is_compatible(np, "fsl,t4240-esdhc") || | 100 | of_device_is_compatible(np, "fsl,t4240-esdhc") || |
102 | of_device_is_compatible(np, "fsl,mpc8536-esdhc")) | 101 | of_device_is_compatible(np, "fsl,mpc8536-esdhc")) |
103 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | 102 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; |
104 | 103 | ||
105 | clk = of_get_property(np, "clock-frequency", &size); | 104 | clk = of_get_property(np, "clock-frequency", &size); |
106 | if (clk && size == sizeof(*clk) && *clk) | 105 | if (clk && size == sizeof(*clk) && *clk) |
107 | pltfm_host->clock = be32_to_cpup(clk); | 106 | pltfm_host->clock = be32_to_cpup(clk); |
108 | 107 | ||
109 | if (of_find_property(np, "keep-power-in-suspend", NULL)) | 108 | if (of_find_property(np, "keep-power-in-suspend", NULL)) |
110 | host->mmc->pm_caps |= MMC_PM_KEEP_POWER; | 109 | host->mmc->pm_caps |= MMC_PM_KEEP_POWER; |
111 | 110 | ||
112 | if (of_find_property(np, "enable-sdio-wakeup", NULL)) | 111 | if (of_find_property(np, "enable-sdio-wakeup", NULL)) |
113 | host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | 112 | host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; |
114 | } | ||
115 | } | 113 | } |
116 | #else | 114 | #else |
117 | void sdhci_get_of_property(struct platform_device *pdev) {} | 115 | void sdhci_get_of_property(struct platform_device *pdev) {} |
@@ -225,9 +223,11 @@ EXPORT_SYMBOL_GPL(sdhci_pltfm_register); | |||
225 | int sdhci_pltfm_unregister(struct platform_device *pdev) | 223 | int sdhci_pltfm_unregister(struct platform_device *pdev) |
226 | { | 224 | { |
227 | struct sdhci_host *host = platform_get_drvdata(pdev); | 225 | struct sdhci_host *host = platform_get_drvdata(pdev); |
226 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
228 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); | 227 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); |
229 | 228 | ||
230 | sdhci_remove_host(host, dead); | 229 | sdhci_remove_host(host, dead); |
230 | clk_disable_unprepare(pltfm_host->clk); | ||
231 | sdhci_pltfm_free(pdev); | 231 | sdhci_pltfm_free(pdev); |
232 | 232 | ||
233 | return 0; | 233 | return 0; |
diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index f6f82ec3618d..32848eb7ad80 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c | |||
@@ -20,17 +20,9 @@ | |||
20 | #define SIRF_TUNING_COUNT 128 | 20 | #define SIRF_TUNING_COUNT 128 |
21 | 21 | ||
22 | struct sdhci_sirf_priv { | 22 | struct sdhci_sirf_priv { |
23 | struct clk *clk; | ||
24 | int gpio_cd; | 23 | int gpio_cd; |
25 | }; | 24 | }; |
26 | 25 | ||
27 | static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) | ||
28 | { | ||
29 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
30 | struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); | ||
31 | return clk_get_rate(priv->clk); | ||
32 | } | ||
33 | |||
34 | static void sdhci_sirf_set_bus_width(struct sdhci_host *host, int width) | 26 | static void sdhci_sirf_set_bus_width(struct sdhci_host *host, int width) |
35 | { | 27 | { |
36 | u8 ctrl; | 28 | u8 ctrl; |
@@ -56,7 +48,7 @@ static int sdhci_sirf_execute_tuning(struct sdhci_host *host, u32 opcode) | |||
56 | int tuning_seq_cnt = 3; | 48 | int tuning_seq_cnt = 3; |
57 | u8 phase, tuned_phases[SIRF_TUNING_COUNT]; | 49 | u8 phase, tuned_phases[SIRF_TUNING_COUNT]; |
58 | u8 tuned_phase_cnt = 0; | 50 | u8 tuned_phase_cnt = 0; |
59 | int rc, longest_range = 0; | 51 | int rc = 0, longest_range = 0; |
60 | int start = -1, end = 0, tuning_value = -1, range = 0; | 52 | int start = -1, end = 0, tuning_value = -1, range = 0; |
61 | u16 clock_setting; | 53 | u16 clock_setting; |
62 | struct mmc_host *mmc = host->mmc; | 54 | struct mmc_host *mmc = host->mmc; |
@@ -68,7 +60,7 @@ retry: | |||
68 | phase = 0; | 60 | phase = 0; |
69 | do { | 61 | do { |
70 | sdhci_writel(host, | 62 | sdhci_writel(host, |
71 | clock_setting | phase | (phase << 7) | (phase << 16), | 63 | clock_setting | phase, |
72 | SDHCI_CLK_DELAY_SETTING); | 64 | SDHCI_CLK_DELAY_SETTING); |
73 | 65 | ||
74 | if (!mmc_send_tuning(mmc)) { | 66 | if (!mmc_send_tuning(mmc)) { |
@@ -102,7 +94,7 @@ retry: | |||
102 | */ | 94 | */ |
103 | phase = tuning_value; | 95 | phase = tuning_value; |
104 | sdhci_writel(host, | 96 | sdhci_writel(host, |
105 | clock_setting | phase | (phase << 7) | (phase << 16), | 97 | clock_setting | phase, |
106 | SDHCI_CLK_DELAY_SETTING); | 98 | SDHCI_CLK_DELAY_SETTING); |
107 | 99 | ||
108 | dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", | 100 | dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", |
@@ -122,7 +114,7 @@ retry: | |||
122 | static struct sdhci_ops sdhci_sirf_ops = { | 114 | static struct sdhci_ops sdhci_sirf_ops = { |
123 | .platform_execute_tuning = sdhci_sirf_execute_tuning, | 115 | .platform_execute_tuning = sdhci_sirf_execute_tuning, |
124 | .set_clock = sdhci_set_clock, | 116 | .set_clock = sdhci_set_clock, |
125 | .get_max_clock = sdhci_sirf_get_max_clk, | 117 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, |
126 | .set_bus_width = sdhci_sirf_set_bus_width, | 118 | .set_bus_width = sdhci_sirf_set_bus_width, |
127 | .reset = sdhci_reset, | 119 | .reset = sdhci_reset, |
128 | .set_uhs_signaling = sdhci_set_uhs_signaling, | 120 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
@@ -162,13 +154,13 @@ static int sdhci_sirf_probe(struct platform_device *pdev) | |||
162 | return PTR_ERR(host); | 154 | return PTR_ERR(host); |
163 | 155 | ||
164 | pltfm_host = sdhci_priv(host); | 156 | pltfm_host = sdhci_priv(host); |
157 | pltfm_host->clk = clk; | ||
165 | priv = sdhci_pltfm_priv(pltfm_host); | 158 | priv = sdhci_pltfm_priv(pltfm_host); |
166 | priv->clk = clk; | ||
167 | priv->gpio_cd = gpio_cd; | 159 | priv->gpio_cd = gpio_cd; |
168 | 160 | ||
169 | sdhci_get_of_property(pdev); | 161 | sdhci_get_of_property(pdev); |
170 | 162 | ||
171 | ret = clk_prepare_enable(priv->clk); | 163 | ret = clk_prepare_enable(pltfm_host->clk); |
172 | if (ret) | 164 | if (ret) |
173 | goto err_clk_prepare; | 165 | goto err_clk_prepare; |
174 | 166 | ||
@@ -195,37 +187,24 @@ static int sdhci_sirf_probe(struct platform_device *pdev) | |||
195 | err_request_cd: | 187 | err_request_cd: |
196 | sdhci_remove_host(host, 0); | 188 | sdhci_remove_host(host, 0); |
197 | err_sdhci_add: | 189 | err_sdhci_add: |
198 | clk_disable_unprepare(priv->clk); | 190 | clk_disable_unprepare(pltfm_host->clk); |
199 | err_clk_prepare: | 191 | err_clk_prepare: |
200 | sdhci_pltfm_free(pdev); | 192 | sdhci_pltfm_free(pdev); |
201 | return ret; | 193 | return ret; |
202 | } | 194 | } |
203 | 195 | ||
204 | static int sdhci_sirf_remove(struct platform_device *pdev) | ||
205 | { | ||
206 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
207 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
208 | struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); | ||
209 | |||
210 | sdhci_pltfm_unregister(pdev); | ||
211 | |||
212 | clk_disable_unprepare(priv->clk); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | #ifdef CONFIG_PM_SLEEP | 196 | #ifdef CONFIG_PM_SLEEP |
217 | static int sdhci_sirf_suspend(struct device *dev) | 197 | static int sdhci_sirf_suspend(struct device *dev) |
218 | { | 198 | { |
219 | struct sdhci_host *host = dev_get_drvdata(dev); | 199 | struct sdhci_host *host = dev_get_drvdata(dev); |
220 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 200 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
221 | struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); | ||
222 | int ret; | 201 | int ret; |
223 | 202 | ||
224 | ret = sdhci_suspend_host(host); | 203 | ret = sdhci_suspend_host(host); |
225 | if (ret) | 204 | if (ret) |
226 | return ret; | 205 | return ret; |
227 | 206 | ||
228 | clk_disable(priv->clk); | 207 | clk_disable(pltfm_host->clk); |
229 | 208 | ||
230 | return 0; | 209 | return 0; |
231 | } | 210 | } |
@@ -234,10 +213,9 @@ static int sdhci_sirf_resume(struct device *dev) | |||
234 | { | 213 | { |
235 | struct sdhci_host *host = dev_get_drvdata(dev); | 214 | struct sdhci_host *host = dev_get_drvdata(dev); |
236 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 215 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
237 | struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); | ||
238 | int ret; | 216 | int ret; |
239 | 217 | ||
240 | ret = clk_enable(priv->clk); | 218 | ret = clk_enable(pltfm_host->clk); |
241 | if (ret) { | 219 | if (ret) { |
242 | dev_dbg(dev, "Resume: Error enabling clock\n"); | 220 | dev_dbg(dev, "Resume: Error enabling clock\n"); |
243 | return ret; | 221 | return ret; |
@@ -264,7 +242,7 @@ static struct platform_driver sdhci_sirf_driver = { | |||
264 | #endif | 242 | #endif |
265 | }, | 243 | }, |
266 | .probe = sdhci_sirf_probe, | 244 | .probe = sdhci_sirf_probe, |
267 | .remove = sdhci_sirf_remove, | 245 | .remove = sdhci_pltfm_unregister, |
268 | }; | 246 | }; |
269 | 247 | ||
270 | module_platform_driver(sdhci_sirf_driver); | 248 | module_platform_driver(sdhci_sirf_driver); |
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 22e58268545f..df088343d60f 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c | |||
@@ -26,14 +26,13 @@ | |||
26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/mmc/host.h> | 28 | #include <linux/mmc/host.h> |
29 | #include <linux/mmc/sdhci-spear.h> | ||
30 | #include <linux/mmc/slot-gpio.h> | 29 | #include <linux/mmc/slot-gpio.h> |
31 | #include <linux/io.h> | 30 | #include <linux/io.h> |
32 | #include "sdhci.h" | 31 | #include "sdhci.h" |
33 | 32 | ||
34 | struct spear_sdhci { | 33 | struct spear_sdhci { |
35 | struct clk *clk; | 34 | struct clk *clk; |
36 | struct sdhci_plat_data *data; | 35 | int card_int_gpio; |
37 | }; | 36 | }; |
38 | 37 | ||
39 | /* sdhci ops */ | 38 | /* sdhci ops */ |
@@ -44,38 +43,20 @@ static const struct sdhci_ops sdhci_pltfm_ops = { | |||
44 | .set_uhs_signaling = sdhci_set_uhs_signaling, | 43 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
45 | }; | 44 | }; |
46 | 45 | ||
47 | #ifdef CONFIG_OF | 46 | static void sdhci_probe_config_dt(struct device_node *np, |
48 | static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev) | 47 | struct spear_sdhci *host) |
49 | { | 48 | { |
50 | struct device_node *np = pdev->dev.of_node; | ||
51 | struct sdhci_plat_data *pdata = NULL; | ||
52 | int cd_gpio; | 49 | int cd_gpio; |
53 | 50 | ||
54 | cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); | 51 | cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); |
55 | if (!gpio_is_valid(cd_gpio)) | 52 | if (!gpio_is_valid(cd_gpio)) |
56 | cd_gpio = -1; | 53 | cd_gpio = -1; |
57 | 54 | ||
58 | /* If pdata is required */ | 55 | host->card_int_gpio = cd_gpio; |
59 | if (cd_gpio != -1) { | ||
60 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
61 | if (!pdata) | ||
62 | dev_err(&pdev->dev, "DT: kzalloc failed\n"); | ||
63 | else | ||
64 | pdata->card_int_gpio = cd_gpio; | ||
65 | } | ||
66 | |||
67 | return pdata; | ||
68 | } | ||
69 | #else | ||
70 | static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev) | ||
71 | { | ||
72 | return ERR_PTR(-ENOSYS); | ||
73 | } | 56 | } |
74 | #endif | ||
75 | 57 | ||
76 | static int sdhci_probe(struct platform_device *pdev) | 58 | static int sdhci_probe(struct platform_device *pdev) |
77 | { | 59 | { |
78 | struct device_node *np = pdev->dev.of_node; | ||
79 | struct sdhci_host *host; | 60 | struct sdhci_host *host; |
80 | struct resource *iomem; | 61 | struct resource *iomem; |
81 | struct spear_sdhci *sdhci; | 62 | struct spear_sdhci *sdhci; |
@@ -124,28 +105,18 @@ static int sdhci_probe(struct platform_device *pdev) | |||
124 | dev_dbg(&pdev->dev, "Error setting desired clk, clk=%lu\n", | 105 | dev_dbg(&pdev->dev, "Error setting desired clk, clk=%lu\n", |
125 | clk_get_rate(sdhci->clk)); | 106 | clk_get_rate(sdhci->clk)); |
126 | 107 | ||
127 | if (np) { | 108 | sdhci_probe_config_dt(pdev->dev.of_node, sdhci); |
128 | sdhci->data = sdhci_probe_config_dt(pdev); | ||
129 | if (IS_ERR(sdhci->data)) { | ||
130 | dev_err(&pdev->dev, "DT: Failed to get pdata\n"); | ||
131 | goto disable_clk; | ||
132 | } | ||
133 | } else { | ||
134 | sdhci->data = dev_get_platdata(&pdev->dev); | ||
135 | } | ||
136 | |||
137 | /* | 109 | /* |
138 | * It is optional to use GPIOs for sdhci card detection. If | 110 | * It is optional to use GPIOs for sdhci card detection. If |
139 | * sdhci->data is NULL, then use original sdhci lines otherwise | 111 | * sdhci->card_int_gpio < 0, then use original sdhci lines otherwise |
140 | * GPIO lines. We use the built-in GPIO support for this. | 112 | * GPIO lines. We use the built-in GPIO support for this. |
141 | */ | 113 | */ |
142 | if (sdhci->data && sdhci->data->card_int_gpio >= 0) { | 114 | if (sdhci->card_int_gpio >= 0) { |
143 | ret = mmc_gpio_request_cd(host->mmc, | 115 | ret = mmc_gpio_request_cd(host->mmc, sdhci->card_int_gpio, 0); |
144 | sdhci->data->card_int_gpio, 0); | ||
145 | if (ret < 0) { | 116 | if (ret < 0) { |
146 | dev_dbg(&pdev->dev, | 117 | dev_dbg(&pdev->dev, |
147 | "failed to request card-detect gpio%d\n", | 118 | "failed to request card-detect gpio%d\n", |
148 | sdhci->data->card_int_gpio); | 119 | sdhci->card_int_gpio); |
149 | goto disable_clk; | 120 | goto disable_clk; |
150 | } | 121 | } |
151 | } | 122 | } |
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 882b07e9667e..682f2bb0f4bf 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c | |||
@@ -23,9 +23,295 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/mmc/host.h> | 25 | #include <linux/mmc/host.h> |
26 | 26 | #include <linux/reset.h> | |
27 | #include "sdhci-pltfm.h" | 27 | #include "sdhci-pltfm.h" |
28 | 28 | ||
29 | struct st_mmc_platform_data { | ||
30 | struct reset_control *rstc; | ||
31 | void __iomem *top_ioaddr; | ||
32 | }; | ||
33 | |||
34 | /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */ | ||
35 | |||
36 | #define ST_MMC_CCONFIG_REG_1 0x400 | ||
37 | #define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24) | ||
38 | #define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12) | ||
39 | #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT BIT(8) | ||
40 | #define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0) | ||
41 | #define ST_MMC_CCONFIG_1_DEFAULT \ | ||
42 | ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \ | ||
43 | (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \ | ||
44 | (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT)) | ||
45 | |||
46 | #define ST_MMC_CCONFIG_REG_2 0x404 | ||
47 | #define ST_MMC_CCONFIG_HIGH_SPEED BIT(28) | ||
48 | #define ST_MMC_CCONFIG_ADMA2 BIT(24) | ||
49 | #define ST_MMC_CCONFIG_8BIT BIT(20) | ||
50 | #define ST_MMC_CCONFIG_MAX_BLK_LEN 16 | ||
51 | #define MAX_BLK_LEN_1024 1 | ||
52 | #define MAX_BLK_LEN_2048 2 | ||
53 | #define BASE_CLK_FREQ_200 0xc8 | ||
54 | #define BASE_CLK_FREQ_100 0x64 | ||
55 | #define BASE_CLK_FREQ_50 0x32 | ||
56 | #define ST_MMC_CCONFIG_2_DEFAULT \ | ||
57 | (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \ | ||
58 | ST_MMC_CCONFIG_8BIT | \ | ||
59 | (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN)) | ||
60 | |||
61 | #define ST_MMC_CCONFIG_REG_3 0x408 | ||
62 | #define ST_MMC_CCONFIG_EMMC_SLOT_TYPE BIT(28) | ||
63 | #define ST_MMC_CCONFIG_64BIT BIT(24) | ||
64 | #define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20) | ||
65 | #define ST_MMC_CCONFIG_1P8_VOLT BIT(16) | ||
66 | #define ST_MMC_CCONFIG_3P0_VOLT BIT(12) | ||
67 | #define ST_MMC_CCONFIG_3P3_VOLT BIT(8) | ||
68 | #define ST_MMC_CCONFIG_SUSP_RES_SUPPORT BIT(4) | ||
69 | #define ST_MMC_CCONFIG_SDMA BIT(0) | ||
70 | #define ST_MMC_CCONFIG_3_DEFAULT \ | ||
71 | (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \ | ||
72 | ST_MMC_CCONFIG_3P3_VOLT | \ | ||
73 | ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \ | ||
74 | ST_MMC_CCONFIG_SDMA) | ||
75 | |||
76 | #define ST_MMC_CCONFIG_REG_4 0x40c | ||
77 | #define ST_MMC_CCONFIG_D_DRIVER BIT(20) | ||
78 | #define ST_MMC_CCONFIG_C_DRIVER BIT(16) | ||
79 | #define ST_MMC_CCONFIG_A_DRIVER BIT(12) | ||
80 | #define ST_MMC_CCONFIG_DDR50 BIT(8) | ||
81 | #define ST_MMC_CCONFIG_SDR104 BIT(4) | ||
82 | #define ST_MMC_CCONFIG_SDR50 BIT(0) | ||
83 | #define ST_MMC_CCONFIG_4_DEFAULT 0 | ||
84 | |||
85 | #define ST_MMC_CCONFIG_REG_5 0x410 | ||
86 | #define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8) | ||
87 | #define RETUNING_TIMER_CNT_MAX 0xf | ||
88 | #define ST_MMC_CCONFIG_5_DEFAULT 0 | ||
89 | |||
90 | /* I/O configuration for Arasan IP */ | ||
91 | #define ST_MMC_GP_OUTPUT 0x450 | ||
92 | #define ST_MMC_GP_OUTPUT_CD BIT(12) | ||
93 | |||
94 | #define ST_MMC_STATUS_R 0x460 | ||
95 | |||
96 | #define ST_TOP_MMC_DLY_FIX_OFF(x) (x - 0x8) | ||
97 | |||
98 | /* TOP config registers to manage static and dynamic delay */ | ||
99 | #define ST_TOP_MMC_TX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0x8) | ||
100 | #define ST_TOP_MMC_RX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0xc) | ||
101 | /* MMC delay control register */ | ||
102 | #define ST_TOP_MMC_DLY_CTRL ST_TOP_MMC_DLY_FIX_OFF(0x18) | ||
103 | #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD BIT(0) | ||
104 | #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL BIT(1) | ||
105 | #define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE BIT(8) | ||
106 | #define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE BIT(9) | ||
107 | #define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY BIT(10) | ||
108 | #define ST_TOP_MMC_START_DLL_LOCK BIT(11) | ||
109 | |||
110 | /* register to provide the phase-shift value for DLL */ | ||
111 | #define ST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c) | ||
112 | #define ST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20) | ||
113 | #define ST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24) | ||
114 | |||
115 | /* phase shift delay on the tx clk 2.188ns */ | ||
116 | #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID 0x6 | ||
117 | |||
118 | #define ST_TOP_MMC_DLY_MAX 0xf | ||
119 | |||
120 | #define ST_TOP_MMC_DYN_DLY_CONF \ | ||
121 | (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \ | ||
122 | ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \ | ||
123 | ST_TOP_MMC_START_DLL_LOCK) | ||
124 | |||
125 | /* | ||
126 | * For clock speeds greater than 90MHz, we need to check that the | ||
127 | * DLL procedure has finished before switching to ultra-speed modes. | ||
128 | */ | ||
129 | #define CLK_TO_CHECK_DLL_LOCK 90000000 | ||
130 | |||
131 | static inline void st_mmcss_set_static_delay(void __iomem *ioaddr) | ||
132 | { | ||
133 | if (!ioaddr) | ||
134 | return; | ||
135 | |||
136 | writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL); | ||
137 | writel_relaxed(ST_TOP_MMC_DLY_MAX, | ||
138 | ioaddr + ST_TOP_MMC_TX_CLK_DLY); | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * st_mmcss_cconfig: configure the Arasan HC inside the flashSS. | ||
143 | * @np: dt device node. | ||
144 | * @host: sdhci host | ||
145 | * Description: this function is to configure the Arasan host controller. | ||
146 | * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated | ||
147 | * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5 | ||
148 | * or eMMC4.3. This has to be done before registering the sdhci host. | ||
149 | */ | ||
150 | static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host) | ||
151 | { | ||
152 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
153 | struct mmc_host *mhost = host->mmc; | ||
154 | u32 cconf2, cconf3, cconf4, cconf5; | ||
155 | |||
156 | if (!of_device_is_compatible(np, "st,sdhci-stih407")) | ||
157 | return; | ||
158 | |||
159 | cconf2 = ST_MMC_CCONFIG_2_DEFAULT; | ||
160 | cconf3 = ST_MMC_CCONFIG_3_DEFAULT; | ||
161 | cconf4 = ST_MMC_CCONFIG_4_DEFAULT; | ||
162 | cconf5 = ST_MMC_CCONFIG_5_DEFAULT; | ||
163 | |||
164 | writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT, | ||
165 | host->ioaddr + ST_MMC_CCONFIG_REG_1); | ||
166 | |||
167 | /* Set clock frequency, default to 50MHz if max-frequency is not | ||
168 | * provided */ | ||
169 | |||
170 | switch (mhost->f_max) { | ||
171 | case 200000000: | ||
172 | clk_set_rate(pltfm_host->clk, mhost->f_max); | ||
173 | cconf2 |= BASE_CLK_FREQ_200; | ||
174 | break; | ||
175 | case 100000000: | ||
176 | clk_set_rate(pltfm_host->clk, mhost->f_max); | ||
177 | cconf2 |= BASE_CLK_FREQ_100; | ||
178 | break; | ||
179 | default: | ||
180 | clk_set_rate(pltfm_host->clk, 50000000); | ||
181 | cconf2 |= BASE_CLK_FREQ_50; | ||
182 | } | ||
183 | |||
184 | writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2); | ||
185 | |||
186 | if (mhost->caps & MMC_CAP_NONREMOVABLE) | ||
187 | cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE; | ||
188 | else | ||
189 | /* CARD _D ET_CTRL */ | ||
190 | writel_relaxed(ST_MMC_GP_OUTPUT_CD, | ||
191 | host->ioaddr + ST_MMC_GP_OUTPUT); | ||
192 | |||
193 | if (mhost->caps & MMC_CAP_UHS_SDR50) { | ||
194 | /* use 1.8V */ | ||
195 | cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; | ||
196 | cconf4 |= ST_MMC_CCONFIG_SDR50; | ||
197 | /* Use tuning */ | ||
198 | cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50; | ||
199 | /* Max timeout for retuning */ | ||
200 | cconf5 |= RETUNING_TIMER_CNT_MAX; | ||
201 | } | ||
202 | |||
203 | if (mhost->caps & MMC_CAP_UHS_SDR104) { | ||
204 | /* | ||
205 | * SDR104 implies the HC can support HS200 mode, so | ||
206 | * it's mandatory to use 1.8V | ||
207 | */ | ||
208 | cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; | ||
209 | cconf4 |= ST_MMC_CCONFIG_SDR104; | ||
210 | /* Max timeout for retuning */ | ||
211 | cconf5 |= RETUNING_TIMER_CNT_MAX; | ||
212 | } | ||
213 | |||
214 | if (mhost->caps & MMC_CAP_UHS_DDR50) | ||
215 | cconf4 |= ST_MMC_CCONFIG_DDR50; | ||
216 | |||
217 | writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3); | ||
218 | writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4); | ||
219 | writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5); | ||
220 | } | ||
221 | |||
222 | static inline void st_mmcss_set_dll(void __iomem *ioaddr) | ||
223 | { | ||
224 | if (!ioaddr) | ||
225 | return; | ||
226 | |||
227 | writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, ioaddr + ST_TOP_MMC_DLY_CTRL); | ||
228 | writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID, | ||
229 | ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY); | ||
230 | } | ||
231 | |||
232 | static int st_mmcss_lock_dll(void __iomem *ioaddr) | ||
233 | { | ||
234 | unsigned long curr, value; | ||
235 | unsigned long finish = jiffies + HZ; | ||
236 | |||
237 | /* Checks if the DLL procedure is finished */ | ||
238 | do { | ||
239 | curr = jiffies; | ||
240 | value = readl(ioaddr + ST_MMC_STATUS_R); | ||
241 | if (value & 0x1) | ||
242 | return 0; | ||
243 | |||
244 | cpu_relax(); | ||
245 | } while (!time_after_eq(curr, finish)); | ||
246 | |||
247 | return -EBUSY; | ||
248 | } | ||
249 | |||
250 | static int sdhci_st_set_dll_for_clock(struct sdhci_host *host) | ||
251 | { | ||
252 | int ret = 0; | ||
253 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
254 | struct st_mmc_platform_data *pdata = pltfm_host->priv; | ||
255 | |||
256 | if (host->clock > CLK_TO_CHECK_DLL_LOCK) { | ||
257 | st_mmcss_set_dll(pdata->top_ioaddr); | ||
258 | ret = st_mmcss_lock_dll(host->ioaddr); | ||
259 | } | ||
260 | |||
261 | return ret; | ||
262 | } | ||
263 | |||
264 | static void sdhci_st_set_uhs_signaling(struct sdhci_host *host, | ||
265 | unsigned int uhs) | ||
266 | { | ||
267 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
268 | struct st_mmc_platform_data *pdata = pltfm_host->priv; | ||
269 | u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
270 | int ret = 0; | ||
271 | |||
272 | /* Select Bus Speed Mode for host */ | ||
273 | ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; | ||
274 | switch (uhs) { | ||
275 | /* | ||
276 | * Set V18_EN -- UHS modes do not work without this. | ||
277 | * does not change signaling voltage | ||
278 | */ | ||
279 | |||
280 | case MMC_TIMING_UHS_SDR12: | ||
281 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
282 | ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180; | ||
283 | break; | ||
284 | case MMC_TIMING_UHS_SDR25: | ||
285 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
286 | ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180; | ||
287 | break; | ||
288 | case MMC_TIMING_UHS_SDR50: | ||
289 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
290 | ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180; | ||
291 | ret = sdhci_st_set_dll_for_clock(host); | ||
292 | break; | ||
293 | case MMC_TIMING_UHS_SDR104: | ||
294 | case MMC_TIMING_MMC_HS200: | ||
295 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
296 | ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; | ||
297 | ret = sdhci_st_set_dll_for_clock(host); | ||
298 | break; | ||
299 | case MMC_TIMING_UHS_DDR50: | ||
300 | case MMC_TIMING_MMC_DDR52: | ||
301 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
302 | ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; | ||
303 | break; | ||
304 | } | ||
305 | |||
306 | if (ret) | ||
307 | dev_warn(mmc_dev(host->mmc), "Error setting dll for clock " | ||
308 | "(uhs %d)\n", uhs); | ||
309 | |||
310 | dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2); | ||
311 | |||
312 | sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); | ||
313 | } | ||
314 | |||
29 | static u32 sdhci_st_readl(struct sdhci_host *host, int reg) | 315 | static u32 sdhci_st_readl(struct sdhci_host *host, int reg) |
30 | { | 316 | { |
31 | u32 ret; | 317 | u32 ret; |
@@ -48,22 +334,33 @@ static const struct sdhci_ops sdhci_st_ops = { | |||
48 | .set_bus_width = sdhci_set_bus_width, | 334 | .set_bus_width = sdhci_set_bus_width, |
49 | .read_l = sdhci_st_readl, | 335 | .read_l = sdhci_st_readl, |
50 | .reset = sdhci_reset, | 336 | .reset = sdhci_reset, |
337 | .set_uhs_signaling = sdhci_st_set_uhs_signaling, | ||
51 | }; | 338 | }; |
52 | 339 | ||
53 | static const struct sdhci_pltfm_data sdhci_st_pdata = { | 340 | static const struct sdhci_pltfm_data sdhci_st_pdata = { |
54 | .ops = &sdhci_st_ops, | 341 | .ops = &sdhci_st_ops, |
55 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | | 342 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
56 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, | 343 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | |
344 | SDHCI_QUIRK_NO_HISPD_BIT, | ||
345 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | ||
346 | SDHCI_QUIRK2_STOP_WITH_TC, | ||
57 | }; | 347 | }; |
58 | 348 | ||
59 | 349 | ||
60 | static int sdhci_st_probe(struct platform_device *pdev) | 350 | static int sdhci_st_probe(struct platform_device *pdev) |
61 | { | 351 | { |
352 | struct device_node *np = pdev->dev.of_node; | ||
62 | struct sdhci_host *host; | 353 | struct sdhci_host *host; |
354 | struct st_mmc_platform_data *pdata; | ||
63 | struct sdhci_pltfm_host *pltfm_host; | 355 | struct sdhci_pltfm_host *pltfm_host; |
64 | struct clk *clk; | 356 | struct clk *clk; |
65 | int ret = 0; | 357 | int ret = 0; |
66 | u16 host_version; | 358 | u16 host_version; |
359 | struct resource *res; | ||
360 | |||
361 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
362 | if (!pdata) | ||
363 | return -ENOMEM; | ||
67 | 364 | ||
68 | clk = devm_clk_get(&pdev->dev, "mmc"); | 365 | clk = devm_clk_get(&pdev->dev, "mmc"); |
69 | if (IS_ERR(clk)) { | 366 | if (IS_ERR(clk)) { |
@@ -71,10 +368,17 @@ static int sdhci_st_probe(struct platform_device *pdev) | |||
71 | return PTR_ERR(clk); | 368 | return PTR_ERR(clk); |
72 | } | 369 | } |
73 | 370 | ||
371 | pdata->rstc = devm_reset_control_get(&pdev->dev, NULL); | ||
372 | if (IS_ERR(pdata->rstc)) | ||
373 | pdata->rstc = NULL; | ||
374 | else | ||
375 | reset_control_deassert(pdata->rstc); | ||
376 | |||
74 | host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0); | 377 | host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0); |
75 | if (IS_ERR(host)) { | 378 | if (IS_ERR(host)) { |
76 | dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n"); | 379 | dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n"); |
77 | return PTR_ERR(host); | 380 | ret = PTR_ERR(host); |
381 | goto err_pltfm_init; | ||
78 | } | 382 | } |
79 | 383 | ||
80 | ret = mmc_of_parse(host->mmc); | 384 | ret = mmc_of_parse(host->mmc); |
@@ -85,9 +389,22 @@ static int sdhci_st_probe(struct platform_device *pdev) | |||
85 | 389 | ||
86 | clk_prepare_enable(clk); | 390 | clk_prepare_enable(clk); |
87 | 391 | ||
392 | /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */ | ||
393 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
394 | "top-mmc-delay"); | ||
395 | pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res); | ||
396 | if (IS_ERR(pdata->top_ioaddr)) { | ||
397 | dev_warn(&pdev->dev, "FlashSS Top Dly registers not available"); | ||
398 | pdata->top_ioaddr = NULL; | ||
399 | } | ||
400 | |||
88 | pltfm_host = sdhci_priv(host); | 401 | pltfm_host = sdhci_priv(host); |
402 | pltfm_host->priv = pdata; | ||
89 | pltfm_host->clk = clk; | 403 | pltfm_host->clk = clk; |
90 | 404 | ||
405 | /* Configure the Arasan HC inside the flashSS */ | ||
406 | st_mmcss_cconfig(np, host); | ||
407 | |||
91 | ret = sdhci_add_host(host); | 408 | ret = sdhci_add_host(host); |
92 | if (ret) { | 409 | if (ret) { |
93 | dev_err(&pdev->dev, "Failed sdhci_add_host\n"); | 410 | dev_err(&pdev->dev, "Failed sdhci_add_host\n"); |
@@ -109,6 +426,9 @@ err_out: | |||
109 | clk_disable_unprepare(clk); | 426 | clk_disable_unprepare(clk); |
110 | err_of: | 427 | err_of: |
111 | sdhci_pltfm_free(pdev); | 428 | sdhci_pltfm_free(pdev); |
429 | err_pltfm_init: | ||
430 | if (pdata->rstc) | ||
431 | reset_control_assert(pdata->rstc); | ||
112 | 432 | ||
113 | return ret; | 433 | return ret; |
114 | } | 434 | } |
@@ -117,10 +437,15 @@ static int sdhci_st_remove(struct platform_device *pdev) | |||
117 | { | 437 | { |
118 | struct sdhci_host *host = platform_get_drvdata(pdev); | 438 | struct sdhci_host *host = platform_get_drvdata(pdev); |
119 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 439 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
440 | struct st_mmc_platform_data *pdata = pltfm_host->priv; | ||
441 | int ret; | ||
120 | 442 | ||
121 | clk_disable_unprepare(pltfm_host->clk); | 443 | ret = sdhci_pltfm_unregister(pdev); |
444 | |||
445 | if (pdata->rstc) | ||
446 | reset_control_assert(pdata->rstc); | ||
122 | 447 | ||
123 | return sdhci_pltfm_unregister(pdev); | 448 | return ret; |
124 | } | 449 | } |
125 | 450 | ||
126 | #ifdef CONFIG_PM_SLEEP | 451 | #ifdef CONFIG_PM_SLEEP |
@@ -128,11 +453,15 @@ static int sdhci_st_suspend(struct device *dev) | |||
128 | { | 453 | { |
129 | struct sdhci_host *host = dev_get_drvdata(dev); | 454 | struct sdhci_host *host = dev_get_drvdata(dev); |
130 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 455 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
456 | struct st_mmc_platform_data *pdata = pltfm_host->priv; | ||
131 | int ret = sdhci_suspend_host(host); | 457 | int ret = sdhci_suspend_host(host); |
132 | 458 | ||
133 | if (ret) | 459 | if (ret) |
134 | goto out; | 460 | goto out; |
135 | 461 | ||
462 | if (pdata->rstc) | ||
463 | reset_control_assert(pdata->rstc); | ||
464 | |||
136 | clk_disable_unprepare(pltfm_host->clk); | 465 | clk_disable_unprepare(pltfm_host->clk); |
137 | out: | 466 | out: |
138 | return ret; | 467 | return ret; |
@@ -142,9 +471,16 @@ static int sdhci_st_resume(struct device *dev) | |||
142 | { | 471 | { |
143 | struct sdhci_host *host = dev_get_drvdata(dev); | 472 | struct sdhci_host *host = dev_get_drvdata(dev); |
144 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 473 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
474 | struct st_mmc_platform_data *pdata = pltfm_host->priv; | ||
475 | struct device_node *np = dev->of_node; | ||
145 | 476 | ||
146 | clk_prepare_enable(pltfm_host->clk); | 477 | clk_prepare_enable(pltfm_host->clk); |
147 | 478 | ||
479 | if (pdata->rstc) | ||
480 | reset_control_deassert(pdata->rstc); | ||
481 | |||
482 | st_mmcss_cconfig(np, host); | ||
483 | |||
148 | return sdhci_resume_host(host); | 484 | return sdhci_resume_host(host); |
149 | } | 485 | } |
150 | #endif | 486 | #endif |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index f3778d58d1cd..ad28b49f0203 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
@@ -20,11 +20,10 @@ | |||
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/of_device.h> | 22 | #include <linux/of_device.h> |
23 | #include <linux/of_gpio.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/mmc/card.h> | 23 | #include <linux/mmc/card.h> |
26 | #include <linux/mmc/host.h> | 24 | #include <linux/mmc/host.h> |
27 | #include <linux/mmc/slot-gpio.h> | 25 | #include <linux/mmc/slot-gpio.h> |
26 | #include <linux/gpio/consumer.h> | ||
28 | 27 | ||
29 | #include "sdhci-pltfm.h" | 28 | #include "sdhci-pltfm.h" |
30 | 29 | ||
@@ -41,7 +40,6 @@ | |||
41 | #define NVQUIRK_DISABLE_SDR50 BIT(3) | 40 | #define NVQUIRK_DISABLE_SDR50 BIT(3) |
42 | #define NVQUIRK_DISABLE_SDR104 BIT(4) | 41 | #define NVQUIRK_DISABLE_SDR104 BIT(4) |
43 | #define NVQUIRK_DISABLE_DDR50 BIT(5) | 42 | #define NVQUIRK_DISABLE_DDR50 BIT(5) |
44 | #define NVQUIRK_SHADOW_XFER_MODE_REG BIT(6) | ||
45 | 43 | ||
46 | struct sdhci_tegra_soc_data { | 44 | struct sdhci_tegra_soc_data { |
47 | const struct sdhci_pltfm_data *pdata; | 45 | const struct sdhci_pltfm_data *pdata; |
@@ -50,7 +48,7 @@ struct sdhci_tegra_soc_data { | |||
50 | 48 | ||
51 | struct sdhci_tegra { | 49 | struct sdhci_tegra { |
52 | const struct sdhci_tegra_soc_data *soc_data; | 50 | const struct sdhci_tegra_soc_data *soc_data; |
53 | int power_gpio; | 51 | struct gpio_desc *power_gpio; |
54 | }; | 52 | }; |
55 | 53 | ||
56 | static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) | 54 | static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) |
@@ -71,23 +69,19 @@ static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) | |||
71 | static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg) | 69 | static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg) |
72 | { | 70 | { |
73 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 71 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
74 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
75 | const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; | ||
76 | 72 | ||
77 | if (soc_data->nvquirks & NVQUIRK_SHADOW_XFER_MODE_REG) { | 73 | switch (reg) { |
78 | switch (reg) { | 74 | case SDHCI_TRANSFER_MODE: |
79 | case SDHCI_TRANSFER_MODE: | 75 | /* |
80 | /* | 76 | * Postpone this write, we must do it together with a |
81 | * Postpone this write, we must do it together with a | 77 | * command write that is down below. |
82 | * command write that is down below. | 78 | */ |
83 | */ | 79 | pltfm_host->xfer_mode_shadow = val; |
84 | pltfm_host->xfer_mode_shadow = val; | 80 | return; |
85 | return; | 81 | case SDHCI_COMMAND: |
86 | case SDHCI_COMMAND: | 82 | writel((val << 16) | pltfm_host->xfer_mode_shadow, |
87 | writel((val << 16) | pltfm_host->xfer_mode_shadow, | 83 | host->ioaddr + SDHCI_TRANSFER_MODE); |
88 | host->ioaddr + SDHCI_TRANSFER_MODE); | 84 | return; |
89 | return; | ||
90 | } | ||
91 | } | 85 | } |
92 | 86 | ||
93 | writew(val, host->ioaddr + reg); | 87 | writew(val, host->ioaddr + reg); |
@@ -173,7 +167,6 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width) | |||
173 | static const struct sdhci_ops tegra_sdhci_ops = { | 167 | static const struct sdhci_ops tegra_sdhci_ops = { |
174 | .get_ro = tegra_sdhci_get_ro, | 168 | .get_ro = tegra_sdhci_get_ro, |
175 | .read_w = tegra_sdhci_readw, | 169 | .read_w = tegra_sdhci_readw, |
176 | .write_w = tegra_sdhci_writew, | ||
177 | .write_l = tegra_sdhci_writel, | 170 | .write_l = tegra_sdhci_writel, |
178 | .set_clock = sdhci_set_clock, | 171 | .set_clock = sdhci_set_clock, |
179 | .set_bus_width = tegra_sdhci_set_bus_width, | 172 | .set_bus_width = tegra_sdhci_set_bus_width, |
@@ -214,6 +207,18 @@ static struct sdhci_tegra_soc_data soc_data_tegra30 = { | |||
214 | NVQUIRK_DISABLE_SDR104, | 207 | NVQUIRK_DISABLE_SDR104, |
215 | }; | 208 | }; |
216 | 209 | ||
210 | static const struct sdhci_ops tegra114_sdhci_ops = { | ||
211 | .get_ro = tegra_sdhci_get_ro, | ||
212 | .read_w = tegra_sdhci_readw, | ||
213 | .write_w = tegra_sdhci_writew, | ||
214 | .write_l = tegra_sdhci_writel, | ||
215 | .set_clock = sdhci_set_clock, | ||
216 | .set_bus_width = tegra_sdhci_set_bus_width, | ||
217 | .reset = tegra_sdhci_reset, | ||
218 | .set_uhs_signaling = sdhci_set_uhs_signaling, | ||
219 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | ||
220 | }; | ||
221 | |||
217 | static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { | 222 | static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { |
218 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | 223 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | |
219 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | 224 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | |
@@ -221,15 +226,14 @@ static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { | |||
221 | SDHCI_QUIRK_NO_HISPD_BIT | | 226 | SDHCI_QUIRK_NO_HISPD_BIT | |
222 | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | | 227 | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | |
223 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, | 228 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, |
224 | .ops = &tegra_sdhci_ops, | 229 | .ops = &tegra114_sdhci_ops, |
225 | }; | 230 | }; |
226 | 231 | ||
227 | static struct sdhci_tegra_soc_data soc_data_tegra114 = { | 232 | static struct sdhci_tegra_soc_data soc_data_tegra114 = { |
228 | .pdata = &sdhci_tegra114_pdata, | 233 | .pdata = &sdhci_tegra114_pdata, |
229 | .nvquirks = NVQUIRK_DISABLE_SDR50 | | 234 | .nvquirks = NVQUIRK_DISABLE_SDR50 | |
230 | NVQUIRK_DISABLE_DDR50 | | 235 | NVQUIRK_DISABLE_DDR50 | |
231 | NVQUIRK_DISABLE_SDR104 | | 236 | NVQUIRK_DISABLE_SDR104, |
232 | NVQUIRK_SHADOW_XFER_MODE_REG, | ||
233 | }; | 237 | }; |
234 | 238 | ||
235 | static const struct of_device_id sdhci_tegra_dt_match[] = { | 239 | static const struct of_device_id sdhci_tegra_dt_match[] = { |
@@ -241,17 +245,6 @@ static const struct of_device_id sdhci_tegra_dt_match[] = { | |||
241 | }; | 245 | }; |
242 | MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); | 246 | MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); |
243 | 247 | ||
244 | static int sdhci_tegra_parse_dt(struct device *dev) | ||
245 | { | ||
246 | struct device_node *np = dev->of_node; | ||
247 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
248 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
249 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
250 | |||
251 | tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0); | ||
252 | return mmc_of_parse(host->mmc); | ||
253 | } | ||
254 | |||
255 | static int sdhci_tegra_probe(struct platform_device *pdev) | 248 | static int sdhci_tegra_probe(struct platform_device *pdev) |
256 | { | 249 | { |
257 | const struct of_device_id *match; | 250 | const struct of_device_id *match; |
@@ -281,21 +274,18 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
281 | tegra_host->soc_data = soc_data; | 274 | tegra_host->soc_data = soc_data; |
282 | pltfm_host->priv = tegra_host; | 275 | pltfm_host->priv = tegra_host; |
283 | 276 | ||
284 | rc = sdhci_tegra_parse_dt(&pdev->dev); | 277 | rc = mmc_of_parse(host->mmc); |
285 | if (rc) | 278 | if (rc) |
286 | goto err_parse_dt; | 279 | goto err_parse_dt; |
287 | 280 | ||
288 | if (gpio_is_valid(tegra_host->power_gpio)) { | 281 | tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", |
289 | rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); | 282 | GPIOD_OUT_HIGH); |
290 | if (rc) { | 283 | if (IS_ERR(tegra_host->power_gpio)) { |
291 | dev_err(mmc_dev(host->mmc), | 284 | rc = PTR_ERR(tegra_host->power_gpio); |
292 | "failed to allocate power gpio\n"); | 285 | goto err_power_req; |
293 | goto err_power_req; | ||
294 | } | ||
295 | gpio_direction_output(tegra_host->power_gpio, 1); | ||
296 | } | 286 | } |
297 | 287 | ||
298 | clk = clk_get(mmc_dev(host->mmc), NULL); | 288 | clk = devm_clk_get(mmc_dev(host->mmc), NULL); |
299 | if (IS_ERR(clk)) { | 289 | if (IS_ERR(clk)) { |
300 | dev_err(mmc_dev(host->mmc), "clk err\n"); | 290 | dev_err(mmc_dev(host->mmc), "clk err\n"); |
301 | rc = PTR_ERR(clk); | 291 | rc = PTR_ERR(clk); |
@@ -312,10 +302,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
312 | 302 | ||
313 | err_add_host: | 303 | err_add_host: |
314 | clk_disable_unprepare(pltfm_host->clk); | 304 | clk_disable_unprepare(pltfm_host->clk); |
315 | clk_put(pltfm_host->clk); | ||
316 | err_clk_get: | 305 | err_clk_get: |
317 | if (gpio_is_valid(tegra_host->power_gpio)) | ||
318 | gpio_free(tegra_host->power_gpio); | ||
319 | err_power_req: | 306 | err_power_req: |
320 | err_parse_dt: | 307 | err_parse_dt: |
321 | err_alloc_tegra_host: | 308 | err_alloc_tegra_host: |
@@ -323,26 +310,6 @@ err_alloc_tegra_host: | |||
323 | return rc; | 310 | return rc; |
324 | } | 311 | } |
325 | 312 | ||
326 | static int sdhci_tegra_remove(struct platform_device *pdev) | ||
327 | { | ||
328 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
329 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
330 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
331 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); | ||
332 | |||
333 | sdhci_remove_host(host, dead); | ||
334 | |||
335 | if (gpio_is_valid(tegra_host->power_gpio)) | ||
336 | gpio_free(tegra_host->power_gpio); | ||
337 | |||
338 | clk_disable_unprepare(pltfm_host->clk); | ||
339 | clk_put(pltfm_host->clk); | ||
340 | |||
341 | sdhci_pltfm_free(pdev); | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static struct platform_driver sdhci_tegra_driver = { | 313 | static struct platform_driver sdhci_tegra_driver = { |
347 | .driver = { | 314 | .driver = { |
348 | .name = "sdhci-tegra", | 315 | .name = "sdhci-tegra", |
@@ -350,7 +317,7 @@ static struct platform_driver sdhci_tegra_driver = { | |||
350 | .pm = SDHCI_PLTFM_PMOPS, | 317 | .pm = SDHCI_PLTFM_PMOPS, |
351 | }, | 318 | }, |
352 | .probe = sdhci_tegra_probe, | 319 | .probe = sdhci_tegra_probe, |
353 | .remove = sdhci_tegra_remove, | 320 | .remove = sdhci_pltfm_unregister, |
354 | }; | 321 | }; |
355 | 322 | ||
356 | module_platform_driver(sdhci_tegra_driver); | 323 | module_platform_driver(sdhci_tegra_driver); |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 0ad412a4876f..c80287a02735 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/mmc/mmc.h> | 28 | #include <linux/mmc/mmc.h> |
29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
30 | #include <linux/mmc/card.h> | 30 | #include <linux/mmc/card.h> |
31 | #include <linux/mmc/sdio.h> | ||
31 | #include <linux/mmc/slot-gpio.h> | 32 | #include <linux/mmc/slot-gpio.h> |
32 | 33 | ||
33 | #include "sdhci.h" | 34 | #include "sdhci.h" |
@@ -56,6 +57,7 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); | |||
56 | static int sdhci_pre_dma_transfer(struct sdhci_host *host, | 57 | static int sdhci_pre_dma_transfer(struct sdhci_host *host, |
57 | struct mmc_data *data, | 58 | struct mmc_data *data, |
58 | struct sdhci_host_next *next); | 59 | struct sdhci_host_next *next); |
60 | static int sdhci_do_get_cd(struct sdhci_host *host); | ||
59 | 61 | ||
60 | #ifdef CONFIG_PM | 62 | #ifdef CONFIG_PM |
61 | static int sdhci_runtime_pm_get(struct sdhci_host *host); | 63 | static int sdhci_runtime_pm_get(struct sdhci_host *host); |
@@ -931,7 +933,8 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, | |||
931 | * If we are sending CMD23, CMD12 never gets sent | 933 | * If we are sending CMD23, CMD12 never gets sent |
932 | * on successful completion (so no Auto-CMD12). | 934 | * on successful completion (so no Auto-CMD12). |
933 | */ | 935 | */ |
934 | if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) | 936 | if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && |
937 | (cmd->opcode != SD_IO_RW_EXTENDED)) | ||
935 | mode |= SDHCI_TRNS_AUTO_CMD12; | 938 | mode |= SDHCI_TRNS_AUTO_CMD12; |
936 | else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { | 939 | else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { |
937 | mode |= SDHCI_TRNS_AUTO_CMD23; | 940 | mode |= SDHCI_TRNS_AUTO_CMD23; |
@@ -1356,7 +1359,8 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1356 | 1359 | ||
1357 | sdhci_runtime_pm_get(host); | 1360 | sdhci_runtime_pm_get(host); |
1358 | 1361 | ||
1359 | present = mmc_gpio_get_cd(host->mmc); | 1362 | /* Firstly check card presence */ |
1363 | present = sdhci_do_get_cd(host); | ||
1360 | 1364 | ||
1361 | spin_lock_irqsave(&host->lock, flags); | 1365 | spin_lock_irqsave(&host->lock, flags); |
1362 | 1366 | ||
@@ -1379,22 +1383,6 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1379 | 1383 | ||
1380 | host->mrq = mrq; | 1384 | host->mrq = mrq; |
1381 | 1385 | ||
1382 | /* | ||
1383 | * Firstly check card presence from cd-gpio. The return could | ||
1384 | * be one of the following possibilities: | ||
1385 | * negative: cd-gpio is not available | ||
1386 | * zero: cd-gpio is used, and card is removed | ||
1387 | * one: cd-gpio is used, and card is present | ||
1388 | */ | ||
1389 | if (present < 0) { | ||
1390 | /* If polling, assume that the card is always present. */ | ||
1391 | if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) | ||
1392 | present = 1; | ||
1393 | else | ||
1394 | present = sdhci_readl(host, SDHCI_PRESENT_STATE) & | ||
1395 | SDHCI_CARD_PRESENT; | ||
1396 | } | ||
1397 | |||
1398 | if (!present || host->flags & SDHCI_DEVICE_DEAD) { | 1386 | if (!present || host->flags & SDHCI_DEVICE_DEAD) { |
1399 | host->mrq->cmd->error = -ENOMEDIUM; | 1387 | host->mrq->cmd->error = -ENOMEDIUM; |
1400 | tasklet_schedule(&host->finish_tasklet); | 1388 | tasklet_schedule(&host->finish_tasklet); |
@@ -3164,7 +3152,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
3164 | /* Auto-CMD23 stuff only works in ADMA or PIO. */ | 3152 | /* Auto-CMD23 stuff only works in ADMA or PIO. */ |
3165 | if ((host->version >= SDHCI_SPEC_300) && | 3153 | if ((host->version >= SDHCI_SPEC_300) && |
3166 | ((host->flags & SDHCI_USE_ADMA) || | 3154 | ((host->flags & SDHCI_USE_ADMA) || |
3167 | !(host->flags & SDHCI_USE_SDMA))) { | 3155 | !(host->flags & SDHCI_USE_SDMA)) && |
3156 | !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) { | ||
3168 | host->flags |= SDHCI_AUTO_CMD23; | 3157 | host->flags |= SDHCI_AUTO_CMD23; |
3169 | DBG("%s: Auto-CMD23 available\n", mmc_hostname(mmc)); | 3158 | DBG("%s: Auto-CMD23 available\n", mmc_hostname(mmc)); |
3170 | } else { | 3159 | } else { |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0315e1844330..e639b7f435e5 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | 20 | ||
21 | #include <linux/mmc/sdhci.h> | 21 | #include <linux/mmc/host.h> |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * Controller registers | 24 | * Controller registers |
@@ -309,6 +309,207 @@ struct sdhci_adma2_64_desc { | |||
309 | */ | 309 | */ |
310 | #define SDHCI_MAX_SEGS 128 | 310 | #define SDHCI_MAX_SEGS 128 |
311 | 311 | ||
312 | struct sdhci_host_next { | ||
313 | unsigned int sg_count; | ||
314 | s32 cookie; | ||
315 | }; | ||
316 | |||
317 | struct sdhci_host { | ||
318 | /* Data set by hardware interface driver */ | ||
319 | const char *hw_name; /* Hardware bus name */ | ||
320 | |||
321 | unsigned int quirks; /* Deviations from spec. */ | ||
322 | |||
323 | /* Controller doesn't honor resets unless we touch the clock register */ | ||
324 | #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) | ||
325 | /* Controller has bad caps bits, but really supports DMA */ | ||
326 | #define SDHCI_QUIRK_FORCE_DMA (1<<1) | ||
327 | /* Controller doesn't like to be reset when there is no card inserted. */ | ||
328 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) | ||
329 | /* Controller doesn't like clearing the power reg before a change */ | ||
330 | #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) | ||
331 | /* Controller has flaky internal state so reset it on each ios change */ | ||
332 | #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) | ||
333 | /* Controller has an unusable DMA engine */ | ||
334 | #define SDHCI_QUIRK_BROKEN_DMA (1<<5) | ||
335 | /* Controller has an unusable ADMA engine */ | ||
336 | #define SDHCI_QUIRK_BROKEN_ADMA (1<<6) | ||
337 | /* Controller can only DMA from 32-bit aligned addresses */ | ||
338 | #define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<7) | ||
339 | /* Controller can only DMA chunk sizes that are a multiple of 32 bits */ | ||
340 | #define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<8) | ||
341 | /* Controller can only ADMA chunks that are a multiple of 32 bits */ | ||
342 | #define SDHCI_QUIRK_32BIT_ADMA_SIZE (1<<9) | ||
343 | /* Controller needs to be reset after each request to stay stable */ | ||
344 | #define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<10) | ||
345 | /* Controller needs voltage and power writes to happen separately */ | ||
346 | #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11) | ||
347 | /* Controller provides an incorrect timeout value for transfers */ | ||
348 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) | ||
349 | /* Controller has an issue with buffer bits for small transfers */ | ||
350 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) | ||
351 | /* Controller does not provide transfer-complete interrupt when not busy */ | ||
352 | #define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) | ||
353 | /* Controller has unreliable card detection */ | ||
354 | #define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15) | ||
355 | /* Controller reports inverted write-protect state */ | ||
356 | #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) | ||
357 | /* Controller does not like fast PIO transfers */ | ||
358 | #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) | ||
359 | /* Controller has to be forced to use block size of 2048 bytes */ | ||
360 | #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) | ||
361 | /* Controller cannot do multi-block transfers */ | ||
362 | #define SDHCI_QUIRK_NO_MULTIBLOCK (1<<21) | ||
363 | /* Controller can only handle 1-bit data transfers */ | ||
364 | #define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) | ||
365 | /* Controller needs 10ms delay between applying power and clock */ | ||
366 | #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) | ||
367 | /* Controller uses SDCLK instead of TMCLK for data timeouts */ | ||
368 | #define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) | ||
369 | /* Controller reports wrong base clock capability */ | ||
370 | #define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25) | ||
371 | /* Controller cannot support End Attribute in NOP ADMA descriptor */ | ||
372 | #define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26) | ||
373 | /* Controller is missing device caps. Use caps provided by host */ | ||
374 | #define SDHCI_QUIRK_MISSING_CAPS (1<<27) | ||
375 | /* Controller uses Auto CMD12 command to stop the transfer */ | ||
376 | #define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28) | ||
377 | /* Controller doesn't have HISPD bit field in HI-SPEED SD card */ | ||
378 | #define SDHCI_QUIRK_NO_HISPD_BIT (1<<29) | ||
379 | /* Controller treats ADMA descriptors with length 0000h incorrectly */ | ||
380 | #define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30) | ||
381 | /* The read-only detection via SDHCI_PRESENT_STATE register is unstable */ | ||
382 | #define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1<<31) | ||
383 | |||
384 | unsigned int quirks2; /* More deviations from spec. */ | ||
385 | |||
386 | #define SDHCI_QUIRK2_HOST_OFF_CARD_ON (1<<0) | ||
387 | #define SDHCI_QUIRK2_HOST_NO_CMD23 (1<<1) | ||
388 | /* The system physically doesn't support 1.8v, even if the host does */ | ||
389 | #define SDHCI_QUIRK2_NO_1_8_V (1<<2) | ||
390 | #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) | ||
391 | #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) | ||
392 | /* Controller has a non-standard host control register */ | ||
393 | #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) | ||
394 | /* Controller does not support HS200 */ | ||
395 | #define SDHCI_QUIRK2_BROKEN_HS200 (1<<6) | ||
396 | /* Controller does not support DDR50 */ | ||
397 | #define SDHCI_QUIRK2_BROKEN_DDR50 (1<<7) | ||
398 | /* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */ | ||
399 | #define SDHCI_QUIRK2_STOP_WITH_TC (1<<8) | ||
400 | /* Controller does not support 64-bit DMA */ | ||
401 | #define SDHCI_QUIRK2_BROKEN_64_BIT_DMA (1<<9) | ||
402 | /* need clear transfer mode register before send cmd */ | ||
403 | #define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10) | ||
404 | /* Capability register bit-63 indicates HS400 support */ | ||
405 | #define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 (1<<11) | ||
406 | /* forced tuned clock */ | ||
407 | #define SDHCI_QUIRK2_TUNING_WORK_AROUND (1<<12) | ||
408 | /* disable the block count for single block transactions */ | ||
409 | #define SDHCI_QUIRK2_SUPPORT_SINGLE (1<<13) | ||
410 | /* Controller broken with using ACMD23 */ | ||
411 | #define SDHCI_QUIRK2_ACMD23_BROKEN (1<<14) | ||
412 | |||
413 | int irq; /* Device IRQ */ | ||
414 | void __iomem *ioaddr; /* Mapped address */ | ||
415 | |||
416 | const struct sdhci_ops *ops; /* Low level hw interface */ | ||
417 | |||
418 | /* Internal data */ | ||
419 | struct mmc_host *mmc; /* MMC structure */ | ||
420 | u64 dma_mask; /* custom DMA mask */ | ||
421 | |||
422 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) | ||
423 | struct led_classdev led; /* LED control */ | ||
424 | char led_name[32]; | ||
425 | #endif | ||
426 | |||
427 | spinlock_t lock; /* Mutex */ | ||
428 | |||
429 | int flags; /* Host attributes */ | ||
430 | #define SDHCI_USE_SDMA (1<<0) /* Host is SDMA capable */ | ||
431 | #define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ | ||
432 | #define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ | ||
433 | #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ | ||
434 | #define SDHCI_SDR50_NEEDS_TUNING (1<<4) /* SDR50 needs tuning */ | ||
435 | #define SDHCI_NEEDS_RETUNING (1<<5) /* Host needs retuning */ | ||
436 | #define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ | ||
437 | #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ | ||
438 | #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ | ||
439 | #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ | ||
440 | #define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */ | ||
441 | #define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ | ||
442 | #define SDHCI_USE_64_BIT_DMA (1<<12) /* Use 64-bit DMA */ | ||
443 | #define SDHCI_HS400_TUNING (1<<13) /* Tuning for HS400 */ | ||
444 | |||
445 | unsigned int version; /* SDHCI spec. version */ | ||
446 | |||
447 | unsigned int max_clk; /* Max possible freq (MHz) */ | ||
448 | unsigned int timeout_clk; /* Timeout freq (KHz) */ | ||
449 | unsigned int clk_mul; /* Clock Muliplier value */ | ||
450 | |||
451 | unsigned int clock; /* Current clock (MHz) */ | ||
452 | u8 pwr; /* Current voltage */ | ||
453 | |||
454 | bool runtime_suspended; /* Host is runtime suspended */ | ||
455 | bool bus_on; /* Bus power prevents runtime suspend */ | ||
456 | bool preset_enabled; /* Preset is enabled */ | ||
457 | |||
458 | struct mmc_request *mrq; /* Current request */ | ||
459 | struct mmc_command *cmd; /* Current command */ | ||
460 | struct mmc_data *data; /* Current data request */ | ||
461 | unsigned int data_early:1; /* Data finished before cmd */ | ||
462 | unsigned int busy_handle:1; /* Handling the order of Busy-end */ | ||
463 | |||
464 | struct sg_mapping_iter sg_miter; /* SG state for PIO */ | ||
465 | unsigned int blocks; /* remaining PIO blocks */ | ||
466 | |||
467 | int sg_count; /* Mapped sg entries */ | ||
468 | |||
469 | void *adma_table; /* ADMA descriptor table */ | ||
470 | void *align_buffer; /* Bounce buffer */ | ||
471 | |||
472 | size_t adma_table_sz; /* ADMA descriptor table size */ | ||
473 | size_t align_buffer_sz; /* Bounce buffer size */ | ||
474 | |||
475 | dma_addr_t adma_addr; /* Mapped ADMA descr. table */ | ||
476 | dma_addr_t align_addr; /* Mapped bounce buffer */ | ||
477 | |||
478 | unsigned int desc_sz; /* ADMA descriptor size */ | ||
479 | unsigned int align_sz; /* ADMA alignment */ | ||
480 | unsigned int align_mask; /* ADMA alignment mask */ | ||
481 | |||
482 | struct tasklet_struct finish_tasklet; /* Tasklet structures */ | ||
483 | |||
484 | struct timer_list timer; /* Timer for timeouts */ | ||
485 | |||
486 | u32 caps; /* Alternative CAPABILITY_0 */ | ||
487 | u32 caps1; /* Alternative CAPABILITY_1 */ | ||
488 | |||
489 | unsigned int ocr_avail_sdio; /* OCR bit masks */ | ||
490 | unsigned int ocr_avail_sd; | ||
491 | unsigned int ocr_avail_mmc; | ||
492 | u32 ocr_mask; /* available voltages */ | ||
493 | |||
494 | unsigned timing; /* Current timing */ | ||
495 | |||
496 | u32 thread_isr; | ||
497 | |||
498 | /* cached registers */ | ||
499 | u32 ier; | ||
500 | |||
501 | wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ | ||
502 | unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */ | ||
503 | |||
504 | unsigned int tuning_count; /* Timer count for re-tuning */ | ||
505 | unsigned int tuning_mode; /* Re-tuning mode supported by host */ | ||
506 | #define SDHCI_TUNING_MODE_1 0 | ||
507 | struct timer_list tuning_timer; /* Timer for tuning */ | ||
508 | |||
509 | struct sdhci_host_next next_data; | ||
510 | unsigned long private[0] ____cacheline_aligned; | ||
511 | }; | ||
512 | |||
312 | struct sdhci_ops { | 513 | struct sdhci_ops { |
313 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS | 514 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS |
314 | u32 (*read_l)(struct sdhci_host *host, int reg); | 515 | u32 (*read_l)(struct sdhci_host *host, int reg); |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 26b7889febb2..2b6ef6bd5d5f 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -872,6 +872,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | |||
872 | struct mmc_command *cmd = mrq->cmd; | 872 | struct mmc_command *cmd = mrq->cmd; |
873 | u32 opc = cmd->opcode; | 873 | u32 opc = cmd->opcode; |
874 | u32 mask; | 874 | u32 mask; |
875 | unsigned long flags; | ||
875 | 876 | ||
876 | switch (opc) { | 877 | switch (opc) { |
877 | /* response busy check */ | 878 | /* response busy check */ |
@@ -906,10 +907,12 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | |||
906 | /* set arg */ | 907 | /* set arg */ |
907 | sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); | 908 | sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); |
908 | /* set cmd */ | 909 | /* set cmd */ |
910 | spin_lock_irqsave(&host->lock, flags); | ||
909 | sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); | 911 | sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); |
910 | 912 | ||
911 | host->wait_for = MMCIF_WAIT_FOR_CMD; | 913 | host->wait_for = MMCIF_WAIT_FOR_CMD; |
912 | schedule_delayed_work(&host->timeout_work, host->timeout); | 914 | schedule_delayed_work(&host->timeout_work, host->timeout); |
915 | spin_unlock_irqrestore(&host->lock, flags); | ||
913 | } | 916 | } |
914 | 917 | ||
915 | static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, | 918 | static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, |
@@ -1168,6 +1171,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) | |||
1168 | struct sh_mmcif_host *host = dev_id; | 1171 | struct sh_mmcif_host *host = dev_id; |
1169 | struct mmc_request *mrq; | 1172 | struct mmc_request *mrq; |
1170 | bool wait = false; | 1173 | bool wait = false; |
1174 | unsigned long flags; | ||
1175 | int wait_work; | ||
1176 | |||
1177 | spin_lock_irqsave(&host->lock, flags); | ||
1178 | wait_work = host->wait_for; | ||
1179 | spin_unlock_irqrestore(&host->lock, flags); | ||
1171 | 1180 | ||
1172 | cancel_delayed_work_sync(&host->timeout_work); | 1181 | cancel_delayed_work_sync(&host->timeout_work); |
1173 | 1182 | ||
@@ -1185,7 +1194,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) | |||
1185 | * All handlers return true, if processing continues, and false, if the | 1194 | * All handlers return true, if processing continues, and false, if the |
1186 | * request has to be completed - successfully or not | 1195 | * request has to be completed - successfully or not |
1187 | */ | 1196 | */ |
1188 | switch (host->wait_for) { | 1197 | switch (wait_work) { |
1189 | case MMCIF_WAIT_FOR_REQUEST: | 1198 | case MMCIF_WAIT_FOR_REQUEST: |
1190 | /* We're too late, the timeout has already kicked in */ | 1199 | /* We're too late, the timeout has already kicked in */ |
1191 | mutex_unlock(&host->thread_lock); | 1200 | mutex_unlock(&host->thread_lock); |
@@ -1309,15 +1318,15 @@ static void mmcif_timeout_work(struct work_struct *work) | |||
1309 | /* Don't run after mmc_remove_host() */ | 1318 | /* Don't run after mmc_remove_host() */ |
1310 | return; | 1319 | return; |
1311 | 1320 | ||
1312 | dev_err(&host->pd->dev, "Timeout waiting for %u on CMD%u\n", | ||
1313 | host->wait_for, mrq->cmd->opcode); | ||
1314 | |||
1315 | spin_lock_irqsave(&host->lock, flags); | 1321 | spin_lock_irqsave(&host->lock, flags); |
1316 | if (host->state == STATE_IDLE) { | 1322 | if (host->state == STATE_IDLE) { |
1317 | spin_unlock_irqrestore(&host->lock, flags); | 1323 | spin_unlock_irqrestore(&host->lock, flags); |
1318 | return; | 1324 | return; |
1319 | } | 1325 | } |
1320 | 1326 | ||
1327 | dev_err(&host->pd->dev, "Timeout waiting for %u on CMD%u\n", | ||
1328 | host->wait_for, mrq->cmd->opcode); | ||
1329 | |||
1321 | host->state = STATE_TIMEOUT; | 1330 | host->state = STATE_TIMEOUT; |
1322 | spin_unlock_irqrestore(&host->lock, flags); | 1331 | spin_unlock_irqrestore(&host->lock, flags); |
1323 | 1332 | ||
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index e8a4218b5726..4d3e1ffe5508 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c | |||
@@ -293,7 +293,7 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, | |||
293 | struct mmc_data *data) | 293 | struct mmc_data *data) |
294 | { | 294 | { |
295 | struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; | 295 | struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; |
296 | struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma; | 296 | dma_addr_t next_desc = host->sg_dma; |
297 | int i, max_len = (1 << host->idma_des_size_bits); | 297 | int i, max_len = (1 << host->idma_des_size_bits); |
298 | 298 | ||
299 | for (i = 0; i < data->sg_len; i++) { | 299 | for (i = 0; i < data->sg_len; i++) { |
@@ -305,8 +305,9 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, | |||
305 | else | 305 | else |
306 | pdes[i].buf_size = data->sg[i].length; | 306 | pdes[i].buf_size = data->sg[i].length; |
307 | 307 | ||
308 | next_desc += sizeof(struct sunxi_idma_des); | ||
308 | pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]); | 309 | pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]); |
309 | pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1]; | 310 | pdes[i].buf_addr_ptr2 = (u32)next_desc; |
310 | } | 311 | } |
311 | 312 | ||
312 | pdes[0].config |= SDXC_IDMAC_DES0_FD; | 313 | pdes[0].config |= SDXC_IDMAC_DES0_FD; |
@@ -930,7 +931,9 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, | |||
930 | return PTR_ERR(host->clk_sample); | 931 | return PTR_ERR(host->clk_sample); |
931 | } | 932 | } |
932 | 933 | ||
933 | host->reset = devm_reset_control_get(&pdev->dev, "ahb"); | 934 | host->reset = devm_reset_control_get_optional(&pdev->dev, "ahb"); |
935 | if (PTR_ERR(host->reset) == -EPROBE_DEFER) | ||
936 | return PTR_ERR(host->reset); | ||
934 | 937 | ||
935 | ret = clk_prepare_enable(host->clk_ahb); | 938 | ret = clk_prepare_enable(host->clk_ahb); |
936 | if (ret) { | 939 | if (ret) { |
@@ -1028,7 +1031,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev) | |||
1028 | mmc->f_min = 400000; | 1031 | mmc->f_min = 400000; |
1029 | mmc->f_max = 50000000; | 1032 | mmc->f_max = 50000000; |
1030 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | | 1033 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | |
1031 | MMC_CAP_ERASE; | 1034 | MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ; |
1032 | 1035 | ||
1033 | ret = mmc_of_parse(mmc); | 1036 | ret = mmc_of_parse(mmc); |
1034 | if (ret) | 1037 | if (ret) |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index a31c3573d386..dba7e1c19dd7 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -1073,8 +1073,6 @@ EXPORT_SYMBOL(tmio_mmc_host_alloc); | |||
1073 | void tmio_mmc_host_free(struct tmio_mmc_host *host) | 1073 | void tmio_mmc_host_free(struct tmio_mmc_host *host) |
1074 | { | 1074 | { |
1075 | mmc_free_host(host->mmc); | 1075 | mmc_free_host(host->mmc); |
1076 | |||
1077 | host->mmc = NULL; | ||
1078 | } | 1076 | } |
1079 | EXPORT_SYMBOL(tmio_mmc_host_free); | 1077 | EXPORT_SYMBOL(tmio_mmc_host_free); |
1080 | 1078 | ||
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index dd2e1aa95ba3..5af00559e9d6 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c | |||
@@ -744,7 +744,7 @@ static struct wmt_mci_caps wm8505_caps = { | |||
744 | .max_blk_size = 2048, | 744 | .max_blk_size = 2048, |
745 | }; | 745 | }; |
746 | 746 | ||
747 | static struct of_device_id wmt_mci_dt_ids[] = { | 747 | static const struct of_device_id wmt_mci_dt_ids[] = { |
748 | { .compatible = "wm,wm8505-sdhc", .data = &wm8505_caps }, | 748 | { .compatible = "wm,wm8505-sdhc", .data = &wm8505_caps }, |
749 | { /* Sentinel */ }, | 749 | { /* Sentinel */ }, |
750 | }; | 750 | }; |