diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-26 14:00:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-26 14:00:41 -0500 |
commit | ccc039d65f24172eebab5e0160462d3417799af5 (patch) | |
tree | c02513223bebadd57da5b6648a497f99684111e2 | |
parent | 1c2948380b699dfdbb25a7de740392dd9e6f0613 (diff) | |
parent | 945be38caa287b177b8c17ffaae7754cab6a658f (diff) |
Merge tag 'mmc-updates-for-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC updates from Chris Ball:
"MMC highlights for 3.14:
Core:
- Avoid get_cd() on cards marked nonremovable
Drivers:
- arasan: New driver for controllers found in e.g. Xilinx Zynq SoC
- dwmmc: Support Hisilicon K3 SoC controllers
- esdhc-imx: Support for HS200 mode, DDR modes on MX6, runtime PM
- sdhci-pci: Support O2Micro/BayHubTech controllers used in laptops
like Lenovo ThinkPad W540, Dell Latitude E5440, Dell Latitude E6540
- tegra: Support Tegra124 SoCs"
* tag 'mmc-updates-for-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (55 commits)
mmc: sdhci-pci: Fix possibility of chip->fixes being null
mmc: sdhci-pci: Fix BYT sd card getting stuck in runtime suspend
mmc: sdhci: Allow for long command timeouts
mmc: sdio: add a quirk for broken SDIO_CCCR_INTx polling
mmc: sdhci: fix lockdep error in tuning routine
mmc: dw_mmc: k3: remove clk_table
mmc: dw_mmc: fix dw_mci_get_cd
mmc: dw_mmc: fix sparse non static symbol warning
mmc: sdhci-esdhc-imx: fix warning during module remove function
mmc: sdhci-esdhc-imx: fix access hardirq-unsafe lock in atomic context
mmc: core: sd: implement proper support for sd3.0 au sizes
mmc: atmel-mci: add vmmc-supply support
mmc: sdhci-pci: add broken HS200 quirk for Intel Merrifield
mmc: sdhci: add quirk for broken HS200 support
mmc: arasan: Add driver for Arasan SDHCI
mmc: dw_mmc: add dw_mmc-k3 for k3 platform
mmc: dw_mmc: use slot-gpio to handle cd pin
mmc: sdhci-pci: add support of O2Micro/BayHubTech SD hosts
mmc: sdhci-pci: break out definitions to header file
mmc: tmio: fixup compile error
...
Conflicts:
MAINTAINERS
36 files changed, 1343 insertions, 341 deletions
diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt new file mode 100644 index 000000000000..98ee2abbe138 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt | |||
@@ -0,0 +1,27 @@ | |||
1 | Device Tree Bindings for the Arasan SDHCI Controller | ||
2 | |||
3 | The bindings follow the mmc[1], clock[2] and interrupt[3] bindings. Only | ||
4 | deviations are documented here. | ||
5 | |||
6 | [1] Documentation/devicetree/bindings/mmc/mmc.txt | ||
7 | [2] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
8 | [3] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt | ||
9 | |||
10 | Required Properties: | ||
11 | - compatible: Compatibility string. Must be 'arasan,sdhci-8.9a' | ||
12 | - reg: From mmc bindings: Register location and length. | ||
13 | - clocks: From clock bindings: Handles to clock inputs. | ||
14 | - clock-names: From clock bindings: Tuple including "clk_xin" and "clk_ahb" | ||
15 | - interrupts: Interrupt specifier | ||
16 | - interrupt-parent: Phandle for the interrupt controller that services | ||
17 | interrupts for this device. | ||
18 | |||
19 | Example: | ||
20 | sdhci@e0100000 { | ||
21 | compatible = "arasan,sdhci-8.9a"; | ||
22 | reg = <0xe0100000 0x1000>; | ||
23 | clock-names = "clk_xin", "clk_ahb"; | ||
24 | clocks = <&clkc 21>, <&clkc 32>; | ||
25 | interrupt-parent = <&gic>; | ||
26 | interrupts = <0 24 4>; | ||
27 | } ; | ||
diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt new file mode 100644 index 000000000000..b8653ea97957 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt | |||
@@ -0,0 +1,46 @@ | |||
1 | * Hisilicon specific extensions to the Synopsys Designware Mobile | ||
2 | Storage Host Controller | ||
3 | |||
4 | Read synopsys-dw-mshc.txt for more details | ||
5 | |||
6 | The Synopsys designware mobile storage host controller is used to interface | ||
7 | a SoC with storage medium such as eMMC or SD/MMC cards. This file documents | ||
8 | differences between the core Synopsys dw mshc controller properties described | ||
9 | by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific | ||
10 | extensions to the Synopsys Designware Mobile Storage Host Controller. | ||
11 | |||
12 | Required Properties: | ||
13 | |||
14 | * compatible: should be one of the following. | ||
15 | - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions. | ||
16 | |||
17 | Example: | ||
18 | |||
19 | /* for Hi3620 */ | ||
20 | |||
21 | /* SoC portion */ | ||
22 | dwmmc_0: dwmmc0@fcd03000 { | ||
23 | compatible = "hisilicon,hi4511-dw-mshc"; | ||
24 | reg = <0xfcd03000 0x1000>; | ||
25 | interrupts = <0 16 4>; | ||
26 | #address-cells = <1>; | ||
27 | #size-cells = <0>; | ||
28 | clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>; | ||
29 | clock-names = "ciu", "biu"; | ||
30 | }; | ||
31 | |||
32 | /* Board portion */ | ||
33 | dwmmc0@fcd03000 { | ||
34 | num-slots = <1>; | ||
35 | vmmc-supply = <&ldo12>; | ||
36 | fifo-depth = <0x100>; | ||
37 | supports-highspeed; | ||
38 | pinctrl-names = "default"; | ||
39 | pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>; | ||
40 | slot@0 { | ||
41 | reg = <0>; | ||
42 | bus-width = <4>; | ||
43 | disable-wp; | ||
44 | cd-gpios = <&gpio10 3 0>; | ||
45 | }; | ||
46 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 1912139a59a1..2507f38b208f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1409,6 +1409,7 @@ F: drivers/cpuidle/cpuidle-zynq.c | |||
1409 | N: zynq | 1409 | N: zynq |
1410 | N: xilinx | 1410 | N: xilinx |
1411 | F: drivers/clocksource/cadence_ttc_timer.c | 1411 | F: drivers/clocksource/cadence_ttc_timer.c |
1412 | F: drivers/mmc/host/sdhci-of-arasan.c | ||
1412 | 1413 | ||
1413 | ARM SMMU DRIVER | 1414 | ARM SMMU DRIVER |
1414 | M: Will Deacon <will.deacon@arm.com> | 1415 | M: Will Deacon <will.deacon@arm.com> |
@@ -5782,7 +5783,7 @@ F: drivers/mfd/ | |||
5782 | F: include/linux/mfd/ | 5783 | F: include/linux/mfd/ |
5783 | 5784 | ||
5784 | MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM | 5785 | MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM |
5785 | M: Chris Ball <cjb@laptop.org> | 5786 | M: Chris Ball <chris@printf.net> |
5786 | L: linux-mmc@vger.kernel.org | 5787 | L: linux-mmc@vger.kernel.org |
5787 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git | 5788 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git |
5788 | S: Maintained | 5789 | S: Maintained |
@@ -7609,7 +7610,7 @@ S: Maintained | |||
7609 | F: drivers/mmc/host/sdricoh_cs.c | 7610 | F: drivers/mmc/host/sdricoh_cs.c |
7610 | 7611 | ||
7611 | SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER | 7612 | SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER |
7612 | M: Chris Ball <cjb@laptop.org> | 7613 | M: Chris Ball <chris@printf.net> |
7613 | L: linux-mmc@vger.kernel.org | 7614 | L: linux-mmc@vger.kernel.org |
7614 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git | 7615 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git |
7615 | S: Maintained | 7616 | S: Maintained |
@@ -8768,7 +8769,6 @@ F: include/linux/toshiba.h | |||
8768 | F: include/uapi/linux/toshiba.h | 8769 | F: include/uapi/linux/toshiba.h |
8769 | 8770 | ||
8770 | TMIO MMC DRIVER | 8771 | TMIO MMC DRIVER |
8771 | M: Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
8772 | M: Ian Molton <ian@mnementh.co.uk> | 8772 | M: Ian Molton <ian@mnementh.co.uk> |
8773 | L: linux-mmc@vger.kernel.org | 8773 | L: linux-mmc@vger.kernel.org |
8774 | S: Maintained | 8774 | S: Maintained |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 29d5d988a51c..7b5424f398ac 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -1959,6 +1959,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
1959 | struct mmc_card *card = md->queue.card; | 1959 | struct mmc_card *card = md->queue.card; |
1960 | struct mmc_host *host = card->host; | 1960 | struct mmc_host *host = card->host; |
1961 | unsigned long flags; | 1961 | unsigned long flags; |
1962 | unsigned int cmd_flags = req ? req->cmd_flags : 0; | ||
1962 | 1963 | ||
1963 | if (req && !mq->mqrq_prev->req) | 1964 | if (req && !mq->mqrq_prev->req) |
1964 | /* claim host only for the first request */ | 1965 | /* claim host only for the first request */ |
@@ -1974,7 +1975,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
1974 | } | 1975 | } |
1975 | 1976 | ||
1976 | mq->flags &= ~MMC_QUEUE_NEW_REQUEST; | 1977 | mq->flags &= ~MMC_QUEUE_NEW_REQUEST; |
1977 | if (req && req->cmd_flags & REQ_DISCARD) { | 1978 | if (cmd_flags & REQ_DISCARD) { |
1978 | /* complete ongoing async transfer before issuing discard */ | 1979 | /* complete ongoing async transfer before issuing discard */ |
1979 | if (card->host->areq) | 1980 | if (card->host->areq) |
1980 | mmc_blk_issue_rw_rq(mq, NULL); | 1981 | mmc_blk_issue_rw_rq(mq, NULL); |
@@ -1983,7 +1984,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
1983 | ret = mmc_blk_issue_secdiscard_rq(mq, req); | 1984 | ret = mmc_blk_issue_secdiscard_rq(mq, req); |
1984 | else | 1985 | else |
1985 | ret = mmc_blk_issue_discard_rq(mq, req); | 1986 | ret = mmc_blk_issue_discard_rq(mq, req); |
1986 | } else if (req && req->cmd_flags & REQ_FLUSH) { | 1987 | } else if (cmd_flags & REQ_FLUSH) { |
1987 | /* complete ongoing async transfer before issuing flush */ | 1988 | /* complete ongoing async transfer before issuing flush */ |
1988 | if (card->host->areq) | 1989 | if (card->host->areq) |
1989 | mmc_blk_issue_rw_rq(mq, NULL); | 1990 | mmc_blk_issue_rw_rq(mq, NULL); |
@@ -1999,7 +2000,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
1999 | 2000 | ||
2000 | out: | 2001 | out: |
2001 | if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || | 2002 | if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || |
2002 | (req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK))) | 2003 | (cmd_flags & MMC_REQ_SPECIAL_MASK)) |
2003 | /* | 2004 | /* |
2004 | * Release host when there are no more requests | 2005 | * Release host when there are no more requests |
2005 | * and after special request(discard, flush) is done. | 2006 | * and after special request(discard, flush) is done. |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 57a2b403bf8e..098374b1ab2b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -2460,7 +2460,8 @@ void mmc_rescan(struct work_struct *work) | |||
2460 | */ | 2460 | */ |
2461 | mmc_bus_put(host); | 2461 | mmc_bus_put(host); |
2462 | 2462 | ||
2463 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) { | 2463 | if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->get_cd && |
2464 | host->ops->get_cd(host) == 0) { | ||
2464 | mmc_claim_host(host); | 2465 | mmc_claim_host(host); |
2465 | mmc_power_off(host); | 2466 | mmc_power_off(host); |
2466 | mmc_release_host(host); | 2467 | mmc_release_host(host); |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f631f5a9bf79..98e9eb0f6643 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -1119,14 +1119,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
1119 | */ | 1119 | */ |
1120 | if (mmc_card_highspeed(card)) { | 1120 | if (mmc_card_highspeed(card)) { |
1121 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) | 1121 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) |
1122 | && ((host->caps & (MMC_CAP_1_8V_DDR | | 1122 | && (host->caps & MMC_CAP_1_8V_DDR)) |
1123 | MMC_CAP_UHS_DDR50)) | ||
1124 | == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50))) | ||
1125 | ddr = MMC_1_8V_DDR_MODE; | 1123 | ddr = MMC_1_8V_DDR_MODE; |
1126 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) | 1124 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) |
1127 | && ((host->caps & (MMC_CAP_1_2V_DDR | | 1125 | && (host->caps & MMC_CAP_1_2V_DDR)) |
1128 | MMC_CAP_UHS_DDR50)) | ||
1129 | == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50))) | ||
1130 | ddr = MMC_1_2V_DDR_MODE; | 1126 | ddr = MMC_1_2V_DDR_MODE; |
1131 | } | 1127 | } |
1132 | 1128 | ||
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c index 06ee1aeaacec..6c36fccaa1ec 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/export.h> | 14 | #include <linux/export.h> |
15 | #include <linux/mmc/card.h> | 15 | #include <linux/mmc/card.h> |
16 | #include <linux/mmc/sdio_ids.h> | ||
16 | 17 | ||
17 | #ifndef SDIO_VENDOR_ID_TI | 18 | #ifndef SDIO_VENDOR_ID_TI |
18 | #define SDIO_VENDOR_ID_TI 0x0097 | 19 | #define SDIO_VENDOR_ID_TI 0x0097 |
@@ -30,6 +31,10 @@ | |||
30 | #define SDIO_DEVICE_ID_STE_CW1200 0x2280 | 31 | #define SDIO_DEVICE_ID_STE_CW1200 0x2280 |
31 | #endif | 32 | #endif |
32 | 33 | ||
34 | #ifndef SDIO_DEVICE_ID_MARVELL_8797_F0 | ||
35 | #define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128 | ||
36 | #endif | ||
37 | |||
33 | /* | 38 | /* |
34 | * This hook just adds a quirk for all sdio devices | 39 | * This hook just adds a quirk for all sdio devices |
35 | */ | 40 | */ |
@@ -58,6 +63,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = { | |||
58 | SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200, | 63 | SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200, |
59 | add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512), | 64 | add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512), |
60 | 65 | ||
66 | SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0, | ||
67 | add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING), | ||
68 | |||
61 | END_FIXUP | 69 | END_FIXUP |
62 | }; | 70 | }; |
63 | 71 | ||
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 6f42050b7ccc..692fdb177294 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/sizes.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> |
@@ -45,6 +46,13 @@ static const unsigned int tacc_mant[] = { | |||
45 | 35, 40, 45, 50, 55, 60, 70, 80, | 46 | 35, 40, 45, 50, 55, 60, 70, 80, |
46 | }; | 47 | }; |
47 | 48 | ||
49 | static const unsigned int sd_au_size[] = { | ||
50 | 0, SZ_16K / 512, SZ_32K / 512, SZ_64K / 512, | ||
51 | SZ_128K / 512, SZ_256K / 512, SZ_512K / 512, SZ_1M / 512, | ||
52 | SZ_2M / 512, SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512, | ||
53 | SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, | ||
54 | }; | ||
55 | |||
48 | #define UNSTUFF_BITS(resp,start,size) \ | 56 | #define UNSTUFF_BITS(resp,start,size) \ |
49 | ({ \ | 57 | ({ \ |
50 | const int __size = size; \ | 58 | const int __size = size; \ |
@@ -216,7 +224,7 @@ static int mmc_decode_scr(struct mmc_card *card) | |||
216 | static int mmc_read_ssr(struct mmc_card *card) | 224 | static int mmc_read_ssr(struct mmc_card *card) |
217 | { | 225 | { |
218 | unsigned int au, es, et, eo; | 226 | unsigned int au, es, et, eo; |
219 | int err, i, max_au; | 227 | int err, i; |
220 | u32 *ssr; | 228 | u32 *ssr; |
221 | 229 | ||
222 | if (!(card->csd.cmdclass & CCC_APP_SPEC)) { | 230 | if (!(card->csd.cmdclass & CCC_APP_SPEC)) { |
@@ -240,26 +248,25 @@ static int mmc_read_ssr(struct mmc_card *card) | |||
240 | for (i = 0; i < 16; i++) | 248 | for (i = 0; i < 16; i++) |
241 | ssr[i] = be32_to_cpu(ssr[i]); | 249 | ssr[i] = be32_to_cpu(ssr[i]); |
242 | 250 | ||
243 | /* SD3.0 increases max AU size to 64MB (0xF) from 4MB (0x9) */ | ||
244 | max_au = card->scr.sda_spec3 ? 0xF : 0x9; | ||
245 | |||
246 | /* | 251 | /* |
247 | * UNSTUFF_BITS only works with four u32s so we have to offset the | 252 | * UNSTUFF_BITS only works with four u32s so we have to offset the |
248 | * bitfield positions accordingly. | 253 | * bitfield positions accordingly. |
249 | */ | 254 | */ |
250 | au = UNSTUFF_BITS(ssr, 428 - 384, 4); | 255 | au = UNSTUFF_BITS(ssr, 428 - 384, 4); |
251 | if (au > 0 && au <= max_au) { | 256 | if (au) { |
252 | card->ssr.au = 1 << (au + 4); | 257 | if (au <= 9 || card->scr.sda_spec3) { |
253 | es = UNSTUFF_BITS(ssr, 408 - 384, 16); | 258 | card->ssr.au = sd_au_size[au]; |
254 | et = UNSTUFF_BITS(ssr, 402 - 384, 6); | 259 | es = UNSTUFF_BITS(ssr, 408 - 384, 16); |
255 | eo = UNSTUFF_BITS(ssr, 400 - 384, 2); | 260 | et = UNSTUFF_BITS(ssr, 402 - 384, 6); |
256 | if (es && et) { | 261 | if (es && et) { |
257 | card->ssr.erase_timeout = (et * 1000) / es; | 262 | eo = UNSTUFF_BITS(ssr, 400 - 384, 2); |
258 | card->ssr.erase_offset = eo * 1000; | 263 | card->ssr.erase_timeout = (et * 1000) / es; |
264 | card->ssr.erase_offset = eo * 1000; | ||
265 | } | ||
266 | } else { | ||
267 | pr_warning("%s: SD Status: Invalid Allocation Unit size.\n", | ||
268 | mmc_hostname(card->host)); | ||
259 | } | 269 | } |
260 | } else { | ||
261 | pr_warning("%s: SD Status: Invalid Allocation Unit " | ||
262 | "size.\n", mmc_hostname(card->host)); | ||
263 | } | 270 | } |
264 | out: | 271 | out: |
265 | kfree(ssr); | 272 | kfree(ssr); |
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 3d8ceb4084de..aaa90460ed23 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c | |||
@@ -53,6 +53,17 @@ static int process_sdio_pending_irqs(struct mmc_host *host) | |||
53 | return ret; | 53 | return ret; |
54 | } | 54 | } |
55 | 55 | ||
56 | if (pending && mmc_card_broken_irq_polling(card) && | ||
57 | !(host->caps & MMC_CAP_SDIO_IRQ)) { | ||
58 | unsigned char dummy; | ||
59 | |||
60 | /* A fake interrupt could be created when we poll SDIO_CCCR_INTx | ||
61 | * register with a Marvell SD8797 card. A dummy CMD52 read to | ||
62 | * function 0 register 0xff can avoid this. | ||
63 | */ | ||
64 | mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy); | ||
65 | } | ||
66 | |||
56 | count = 0; | 67 | count = 0; |
57 | for (i = 1; i <= 7; i++) { | 68 | for (i = 1; i <= 7; i++) { |
58 | if (pending & (1 << i)) { | 69 | if (pending & (1 << i)) { |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 4e8ca9d5570f..1384f67abe21 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -104,6 +104,18 @@ config MMC_SDHCI_PLTFM | |||
104 | 104 | ||
105 | If unsure, say N. | 105 | If unsure, say N. |
106 | 106 | ||
107 | config MMC_SDHCI_OF_ARASAN | ||
108 | tristate "SDHCI OF support for the Arasan SDHCI controllers" | ||
109 | depends on MMC_SDHCI_PLTFM | ||
110 | depends on OF | ||
111 | help | ||
112 | This selects the Arasan Secure Digital Host Controller Interface | ||
113 | (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC. | ||
114 | |||
115 | If you have a controller with this interface, say Y or M here. | ||
116 | |||
117 | If unsure, say N. | ||
118 | |||
107 | config MMC_SDHCI_OF_ESDHC | 119 | config MMC_SDHCI_OF_ESDHC |
108 | tristate "SDHCI OF support for the Freescale eSDHC controller" | 120 | tristate "SDHCI OF support for the Freescale eSDHC controller" |
109 | depends on MMC_SDHCI_PLTFM | 121 | depends on MMC_SDHCI_PLTFM |
@@ -479,7 +491,8 @@ config MMC_TMIO | |||
479 | 491 | ||
480 | config MMC_SDHI | 492 | config MMC_SDHI |
481 | tristate "SH-Mobile SDHI SD/SDIO controller support" | 493 | tristate "SH-Mobile SDHI SD/SDIO controller support" |
482 | depends on SUPERH || ARCH_SHMOBILE | 494 | depends on SUPERH || ARM |
495 | depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST | ||
483 | select MMC_TMIO_CORE | 496 | select MMC_TMIO_CORE |
484 | help | 497 | help |
485 | This provides support for the SDHI SD/SDIO controller found in | 498 | This provides support for the SDHI SD/SDIO controller found in |
@@ -575,6 +588,16 @@ config MMC_DW_SOCFPGA | |||
575 | This selects support for Altera SoCFPGA specific extensions to the | 588 | This selects support for Altera SoCFPGA specific extensions to the |
576 | Synopsys DesignWare Memory Card Interface driver. | 589 | Synopsys DesignWare Memory Card Interface driver. |
577 | 590 | ||
591 | config MMC_DW_K3 | ||
592 | tristate "K3 specific extensions for Synopsys DW Memory Card Interface" | ||
593 | depends on MMC_DW | ||
594 | select MMC_DW_PLTFM | ||
595 | select MMC_DW_IDMAC | ||
596 | help | ||
597 | This selects support for Hisilicon K3 SoC specific extensions to the | ||
598 | Synopsys DesignWare Memory Card Interface driver. Select this option | ||
599 | for platforms based on Hisilicon K3 SoC's. | ||
600 | |||
578 | config MMC_DW_PCI | 601 | config MMC_DW_PCI |
579 | tristate "Synopsys Designware MCI support on PCI bus" | 602 | tristate "Synopsys Designware MCI support on PCI bus" |
580 | depends on MMC_DW && PCI | 603 | depends on MMC_DW && PCI |
@@ -588,7 +611,8 @@ config MMC_DW_PCI | |||
588 | 611 | ||
589 | config MMC_SH_MMCIF | 612 | config MMC_SH_MMCIF |
590 | tristate "SuperH Internal MMCIF support" | 613 | tristate "SuperH Internal MMCIF support" |
591 | depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) | 614 | depends on MMC_BLOCK |
615 | depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST | ||
592 | help | 616 | help |
593 | This selects the MMC Host Interface controller (MMCIF). | 617 | This selects the MMC Host Interface controller (MMCIF). |
594 | 618 | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index c41d0c364509..3483b6b6b880 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXS) += mxs-mmc.o | |||
9 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 9 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
10 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 10 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
11 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o | 11 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o |
12 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-o2micro.o | ||
12 | obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o | 13 | obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o |
13 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o | 14 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o |
14 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o | 15 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o |
@@ -43,6 +44,7 @@ obj-$(CONFIG_MMC_DW) += dw_mmc.o | |||
43 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o | 44 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o |
44 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o | 45 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o |
45 | obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o | 46 | obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o |
47 | obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o | ||
46 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o | 48 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o |
47 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 49 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
48 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o | 50 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o |
@@ -57,6 +59,7 @@ obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o | |||
57 | obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o | 59 | obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o |
58 | obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o | 60 | obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o |
59 | obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o | 61 | obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o |
62 | obj-$(CONFIG_MMC_SDHCI_OF_ARASAN) += sdhci-of-arasan.o | ||
60 | obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o | 63 | obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o |
61 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o | 64 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o |
62 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o | 65 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 2cbb4516d353..42706ea0ba85 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -1192,11 +1192,22 @@ static void atmci_start_request(struct atmel_mci *host, | |||
1192 | iflags |= ATMCI_CMDRDY; | 1192 | iflags |= ATMCI_CMDRDY; |
1193 | cmd = mrq->cmd; | 1193 | cmd = mrq->cmd; |
1194 | cmdflags = atmci_prepare_command(slot->mmc, cmd); | 1194 | cmdflags = atmci_prepare_command(slot->mmc, cmd); |
1195 | atmci_send_command(host, cmd, cmdflags); | 1195 | |
1196 | /* | ||
1197 | * DMA transfer should be started before sending the command to avoid | ||
1198 | * unexpected errors especially for read operations in SDIO mode. | ||
1199 | * Unfortunately, in PDC mode, command has to be sent before starting | ||
1200 | * the transfer. | ||
1201 | */ | ||
1202 | if (host->submit_data != &atmci_submit_data_dma) | ||
1203 | atmci_send_command(host, cmd, cmdflags); | ||
1196 | 1204 | ||
1197 | if (data) | 1205 | if (data) |
1198 | host->submit_data(host, data); | 1206 | host->submit_data(host, data); |
1199 | 1207 | ||
1208 | if (host->submit_data == &atmci_submit_data_dma) | ||
1209 | atmci_send_command(host, cmd, cmdflags); | ||
1210 | |||
1200 | if (mrq->stop) { | 1211 | if (mrq->stop) { |
1201 | host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); | 1212 | host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); |
1202 | host->stop_cmdr |= ATMCI_CMDR_STOP_XFER; | 1213 | host->stop_cmdr |= ATMCI_CMDR_STOP_XFER; |
@@ -1391,8 +1402,14 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1391 | clk_unprepare(host->mck); | 1402 | clk_unprepare(host->mck); |
1392 | 1403 | ||
1393 | switch (ios->power_mode) { | 1404 | switch (ios->power_mode) { |
1405 | case MMC_POWER_OFF: | ||
1406 | if (!IS_ERR(mmc->supply.vmmc)) | ||
1407 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); | ||
1408 | break; | ||
1394 | case MMC_POWER_UP: | 1409 | case MMC_POWER_UP: |
1395 | set_bit(ATMCI_CARD_NEED_INIT, &slot->flags); | 1410 | set_bit(ATMCI_CARD_NEED_INIT, &slot->flags); |
1411 | if (!IS_ERR(mmc->supply.vmmc)) | ||
1412 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); | ||
1396 | break; | 1413 | break; |
1397 | default: | 1414 | default: |
1398 | /* | 1415 | /* |
@@ -2204,6 +2221,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, | |||
2204 | } | 2221 | } |
2205 | 2222 | ||
2206 | host->slot[id] = slot; | 2223 | host->slot[id] = slot; |
2224 | mmc_regulator_get_supply(mmc); | ||
2207 | mmc_add_host(mmc); | 2225 | mmc_add_host(mmc); |
2208 | 2226 | ||
2209 | if (gpio_is_valid(slot->detect_pin)) { | 2227 | if (gpio_is_valid(slot->detect_pin)) { |
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c new file mode 100644 index 000000000000..f567c219cff4 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-k3.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Linaro Ltd. | ||
3 | * Copyright (c) 2013 Hisilicon Limited. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/mmc/host.h> | ||
15 | #include <linux/mmc/dw_mmc.h> | ||
16 | #include <linux/of_address.h> | ||
17 | |||
18 | #include "dw_mmc.h" | ||
19 | #include "dw_mmc-pltfm.h" | ||
20 | |||
21 | static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios) | ||
22 | { | ||
23 | int ret; | ||
24 | |||
25 | ret = clk_set_rate(host->ciu_clk, ios->clock); | ||
26 | if (ret) | ||
27 | dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock); | ||
28 | |||
29 | host->bus_hz = clk_get_rate(host->ciu_clk); | ||
30 | } | ||
31 | |||
32 | static const struct dw_mci_drv_data k3_drv_data = { | ||
33 | .set_ios = dw_mci_k3_set_ios, | ||
34 | }; | ||
35 | |||
36 | static const struct of_device_id dw_mci_k3_match[] = { | ||
37 | { .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, }, | ||
38 | {}, | ||
39 | }; | ||
40 | MODULE_DEVICE_TABLE(of, dw_mci_k3_match); | ||
41 | |||
42 | static int dw_mci_k3_probe(struct platform_device *pdev) | ||
43 | { | ||
44 | const struct dw_mci_drv_data *drv_data; | ||
45 | const struct of_device_id *match; | ||
46 | |||
47 | match = of_match_node(dw_mci_k3_match, pdev->dev.of_node); | ||
48 | drv_data = match->data; | ||
49 | |||
50 | return dw_mci_pltfm_register(pdev, drv_data); | ||
51 | } | ||
52 | |||
53 | static int dw_mci_k3_suspend(struct device *dev) | ||
54 | { | ||
55 | struct dw_mci *host = dev_get_drvdata(dev); | ||
56 | int ret; | ||
57 | |||
58 | ret = dw_mci_suspend(host); | ||
59 | if (!ret) | ||
60 | clk_disable_unprepare(host->ciu_clk); | ||
61 | |||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | static int dw_mci_k3_resume(struct device *dev) | ||
66 | { | ||
67 | struct dw_mci *host = dev_get_drvdata(dev); | ||
68 | int ret; | ||
69 | |||
70 | ret = clk_prepare_enable(host->ciu_clk); | ||
71 | if (ret) { | ||
72 | dev_err(host->dev, "failed to enable ciu clock\n"); | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | return dw_mci_resume(host); | ||
77 | } | ||
78 | |||
79 | static SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume); | ||
80 | |||
81 | static struct platform_driver dw_mci_k3_pltfm_driver = { | ||
82 | .probe = dw_mci_k3_probe, | ||
83 | .remove = dw_mci_pltfm_remove, | ||
84 | .driver = { | ||
85 | .name = "dwmmc_k3", | ||
86 | .of_match_table = dw_mci_k3_match, | ||
87 | .pm = &dw_mci_k3_pmops, | ||
88 | }, | ||
89 | }; | ||
90 | |||
91 | module_platform_driver(dw_mci_k3_pltfm_driver); | ||
92 | |||
93 | MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension"); | ||
94 | MODULE_LICENSE("GPL v2"); | ||
95 | MODULE_ALIAS("platform:dwmmc-k3"); | ||
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 4bce0deec362..55cd110a49c4 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | #include <linux/of.h> | 37 | #include <linux/of.h> |
38 | #include <linux/of_gpio.h> | 38 | #include <linux/of_gpio.h> |
39 | #include <linux/mmc/slot-gpio.h> | ||
39 | 40 | ||
40 | #include "dw_mmc.h" | 41 | #include "dw_mmc.h" |
41 | 42 | ||
@@ -1032,20 +1033,29 @@ static int dw_mci_get_cd(struct mmc_host *mmc) | |||
1032 | int present; | 1033 | int present; |
1033 | struct dw_mci_slot *slot = mmc_priv(mmc); | 1034 | struct dw_mci_slot *slot = mmc_priv(mmc); |
1034 | struct dw_mci_board *brd = slot->host->pdata; | 1035 | struct dw_mci_board *brd = slot->host->pdata; |
1036 | struct dw_mci *host = slot->host; | ||
1037 | int gpio_cd = mmc_gpio_get_cd(mmc); | ||
1035 | 1038 | ||
1036 | /* Use platform get_cd function, else try onboard card detect */ | 1039 | /* Use platform get_cd function, else try onboard card detect */ |
1037 | if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) | 1040 | if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) |
1038 | present = 1; | 1041 | present = 1; |
1039 | else if (brd->get_cd) | 1042 | else if (brd->get_cd) |
1040 | present = !brd->get_cd(slot->id); | 1043 | present = !brd->get_cd(slot->id); |
1044 | else if (!IS_ERR_VALUE(gpio_cd)) | ||
1045 | present = gpio_cd; | ||
1041 | else | 1046 | else |
1042 | present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) | 1047 | present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) |
1043 | == 0 ? 1 : 0; | 1048 | == 0 ? 1 : 0; |
1044 | 1049 | ||
1045 | if (present) | 1050 | spin_lock_bh(&host->lock); |
1051 | if (present) { | ||
1052 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
1046 | dev_dbg(&mmc->class_dev, "card is present\n"); | 1053 | dev_dbg(&mmc->class_dev, "card is present\n"); |
1047 | else | 1054 | } else { |
1055 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
1048 | dev_dbg(&mmc->class_dev, "card is not present\n"); | 1056 | dev_dbg(&mmc->class_dev, "card is not present\n"); |
1057 | } | ||
1058 | spin_unlock_bh(&host->lock); | ||
1049 | 1059 | ||
1050 | return present; | 1060 | return present; |
1051 | } | 1061 | } |
@@ -1926,10 +1936,6 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1926 | /* Card change detected */ | 1936 | /* Card change detected */ |
1927 | slot->last_detect_state = present; | 1937 | slot->last_detect_state = present; |
1928 | 1938 | ||
1929 | /* Mark card as present if applicable */ | ||
1930 | if (present != 0) | ||
1931 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
1932 | |||
1933 | /* Clean up queue if present */ | 1939 | /* Clean up queue if present */ |
1934 | mrq = slot->mrq; | 1940 | mrq = slot->mrq; |
1935 | if (mrq) { | 1941 | if (mrq) { |
@@ -1977,8 +1983,6 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1977 | 1983 | ||
1978 | /* Power down slot */ | 1984 | /* Power down slot */ |
1979 | if (present == 0) { | 1985 | if (present == 0) { |
1980 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
1981 | |||
1982 | /* Clear down the FIFO */ | 1986 | /* Clear down the FIFO */ |
1983 | dw_mci_fifo_reset(host); | 1987 | dw_mci_fifo_reset(host); |
1984 | #ifdef CONFIG_MMC_DW_IDMAC | 1988 | #ifdef CONFIG_MMC_DW_IDMAC |
@@ -2079,6 +2083,26 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot) | |||
2079 | 2083 | ||
2080 | return gpio; | 2084 | return gpio; |
2081 | } | 2085 | } |
2086 | |||
2087 | /* find the cd gpio for a given slot */ | ||
2088 | static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot, | ||
2089 | struct mmc_host *mmc) | ||
2090 | { | ||
2091 | struct device_node *np = dw_mci_of_find_slot_node(dev, slot); | ||
2092 | int gpio; | ||
2093 | |||
2094 | if (!np) | ||
2095 | return; | ||
2096 | |||
2097 | gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
2098 | |||
2099 | /* Having a missing entry is valid; return silently */ | ||
2100 | if (!gpio_is_valid(gpio)) | ||
2101 | return; | ||
2102 | |||
2103 | if (mmc_gpio_request_cd(mmc, gpio, 0)) | ||
2104 | dev_warn(dev, "gpio [%d] request failed\n", gpio); | ||
2105 | } | ||
2082 | #else /* CONFIG_OF */ | 2106 | #else /* CONFIG_OF */ |
2083 | static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) | 2107 | static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) |
2084 | { | 2108 | { |
@@ -2096,6 +2120,11 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot) | |||
2096 | { | 2120 | { |
2097 | return -EINVAL; | 2121 | return -EINVAL; |
2098 | } | 2122 | } |
2123 | static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot, | ||
2124 | struct mmc_host *mmc) | ||
2125 | { | ||
2126 | return; | ||
2127 | } | ||
2099 | #endif /* CONFIG_OF */ | 2128 | #endif /* CONFIG_OF */ |
2100 | 2129 | ||
2101 | static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | 2130 | static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) |
@@ -2197,12 +2226,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
2197 | #endif /* CONFIG_MMC_DW_IDMAC */ | 2226 | #endif /* CONFIG_MMC_DW_IDMAC */ |
2198 | } | 2227 | } |
2199 | 2228 | ||
2200 | if (dw_mci_get_cd(mmc)) | ||
2201 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
2202 | else | ||
2203 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
2204 | |||
2205 | slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id); | 2229 | slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id); |
2230 | dw_mci_of_get_cd_gpio(host->dev, slot->id, mmc); | ||
2206 | 2231 | ||
2207 | ret = mmc_add_host(mmc); | 2232 | ret = mmc_add_host(mmc); |
2208 | if (ret) | 2233 | if (ret) |
@@ -2389,6 +2414,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
2389 | if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL)) | 2414 | if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL)) |
2390 | pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR; | 2415 | pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR; |
2391 | 2416 | ||
2417 | if (of_get_property(np, "cd-inverted", NULL)) | ||
2418 | pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | ||
2419 | |||
2392 | return pdata; | 2420 | return pdata; |
2393 | } | 2421 | } |
2394 | 2422 | ||
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 50fc9df791b2..073e871a0fc8 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/mmc/host.h> | 38 | #include <linux/mmc/host.h> |
39 | #include <linux/mmc/mmc.h> | 39 | #include <linux/mmc/mmc.h> |
40 | #include <linux/mmc/sdio.h> | 40 | #include <linux/mmc/sdio.h> |
41 | #include <linux/mmc/slot-gpio.h> | ||
41 | #include <linux/gpio.h> | 42 | #include <linux/gpio.h> |
42 | #include <linux/regulator/consumer.h> | 43 | #include <linux/regulator/consumer.h> |
43 | #include <linux/module.h> | 44 | #include <linux/module.h> |
@@ -69,37 +70,25 @@ struct mxs_mmc_host { | |||
69 | unsigned char bus_width; | 70 | unsigned char bus_width; |
70 | spinlock_t lock; | 71 | spinlock_t lock; |
71 | int sdio_irq_en; | 72 | int sdio_irq_en; |
72 | int wp_gpio; | ||
73 | bool wp_inverted; | ||
74 | bool cd_inverted; | ||
75 | bool broken_cd; | ||
76 | bool non_removable; | ||
77 | }; | 73 | }; |
78 | 74 | ||
79 | static int mxs_mmc_get_ro(struct mmc_host *mmc) | 75 | static int mxs_mmc_get_cd(struct mmc_host *mmc) |
80 | { | 76 | { |
81 | struct mxs_mmc_host *host = mmc_priv(mmc); | 77 | struct mxs_mmc_host *host = mmc_priv(mmc); |
82 | int ret; | 78 | struct mxs_ssp *ssp = &host->ssp; |
83 | 79 | int present, ret; | |
84 | if (!gpio_is_valid(host->wp_gpio)) | ||
85 | return -EINVAL; | ||
86 | |||
87 | ret = gpio_get_value(host->wp_gpio); | ||
88 | 80 | ||
89 | if (host->wp_inverted) | 81 | ret = mmc_gpio_get_cd(mmc); |
90 | ret = !ret; | 82 | if (ret >= 0) |
83 | return ret; | ||
91 | 84 | ||
92 | return ret; | 85 | present = !(readl(ssp->base + HW_SSP_STATUS(ssp)) & |
93 | } | 86 | BM_SSP_STATUS_CARD_DETECT); |
94 | 87 | ||
95 | static int mxs_mmc_get_cd(struct mmc_host *mmc) | 88 | if (mmc->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) |
96 | { | 89 | present = !present; |
97 | struct mxs_mmc_host *host = mmc_priv(mmc); | ||
98 | struct mxs_ssp *ssp = &host->ssp; | ||
99 | 90 | ||
100 | return host->non_removable || host->broken_cd || | 91 | return present; |
101 | !(readl(ssp->base + HW_SSP_STATUS(ssp)) & | ||
102 | BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted; | ||
103 | } | 92 | } |
104 | 93 | ||
105 | static int mxs_mmc_reset(struct mxs_mmc_host *host) | 94 | static int mxs_mmc_reset(struct mxs_mmc_host *host) |
@@ -549,7 +538,7 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
549 | 538 | ||
550 | static const struct mmc_host_ops mxs_mmc_ops = { | 539 | static const struct mmc_host_ops mxs_mmc_ops = { |
551 | .request = mxs_mmc_request, | 540 | .request = mxs_mmc_request, |
552 | .get_ro = mxs_mmc_get_ro, | 541 | .get_ro = mmc_gpio_get_ro, |
553 | .get_cd = mxs_mmc_get_cd, | 542 | .get_cd = mxs_mmc_get_cd, |
554 | .set_ios = mxs_mmc_set_ios, | 543 | .set_ios = mxs_mmc_set_ios, |
555 | .enable_sdio_irq = mxs_mmc_enable_sdio_irq, | 544 | .enable_sdio_irq = mxs_mmc_enable_sdio_irq, |
@@ -579,15 +568,12 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
579 | { | 568 | { |
580 | const struct of_device_id *of_id = | 569 | const struct of_device_id *of_id = |
581 | of_match_device(mxs_mmc_dt_ids, &pdev->dev); | 570 | of_match_device(mxs_mmc_dt_ids, &pdev->dev); |
582 | struct device_node *np = pdev->dev.of_node; | ||
583 | struct mxs_mmc_host *host; | 571 | struct mxs_mmc_host *host; |
584 | struct mmc_host *mmc; | 572 | struct mmc_host *mmc; |
585 | struct resource *iores; | 573 | struct resource *iores; |
586 | int ret = 0, irq_err; | 574 | int ret = 0, irq_err; |
587 | struct regulator *reg_vmmc; | 575 | struct regulator *reg_vmmc; |
588 | enum of_gpio_flags flags; | ||
589 | struct mxs_ssp *ssp; | 576 | struct mxs_ssp *ssp; |
590 | u32 bus_width = 0; | ||
591 | 577 | ||
592 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 578 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
593 | irq_err = platform_get_irq(pdev, 0); | 579 | irq_err = platform_get_irq(pdev, 0); |
@@ -648,23 +634,13 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
648 | mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | | 634 | mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | |
649 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; | 635 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; |
650 | 636 | ||
651 | of_property_read_u32(np, "bus-width", &bus_width); | ||
652 | if (bus_width == 4) | ||
653 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
654 | else if (bus_width == 8) | ||
655 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; | ||
656 | host->broken_cd = of_property_read_bool(np, "broken-cd"); | ||
657 | host->non_removable = of_property_read_bool(np, "non-removable"); | ||
658 | if (host->non_removable) | ||
659 | mmc->caps |= MMC_CAP_NONREMOVABLE; | ||
660 | host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); | ||
661 | if (flags & OF_GPIO_ACTIVE_LOW) | ||
662 | host->wp_inverted = 1; | ||
663 | |||
664 | host->cd_inverted = of_property_read_bool(np, "cd-inverted"); | ||
665 | |||
666 | mmc->f_min = 400000; | 637 | mmc->f_min = 400000; |
667 | mmc->f_max = 288000000; | 638 | mmc->f_max = 288000000; |
639 | |||
640 | ret = mmc_of_parse(mmc); | ||
641 | if (ret) | ||
642 | goto out_clk_disable; | ||
643 | |||
668 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 644 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
669 | 645 | ||
670 | mmc->max_segs = 52; | 646 | mmc->max_segs = 52; |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 4ede2307b293..9ce17f6e4014 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
@@ -143,6 +143,7 @@ static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { | |||
143 | { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, | 143 | { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, |
144 | { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, | 144 | { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, |
145 | { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, | 145 | { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, |
146 | { "INT3436" , NULL, &sdhci_acpi_slot_int_sdio }, | ||
146 | { "PNP0D40" }, | 147 | { "PNP0D40" }, |
147 | { }, | 148 | { }, |
148 | }; | 149 | }; |
@@ -151,6 +152,7 @@ static const struct acpi_device_id sdhci_acpi_ids[] = { | |||
151 | { "80860F14" }, | 152 | { "80860F14" }, |
152 | { "INT33BB" }, | 153 | { "INT33BB" }, |
153 | { "INT33C6" }, | 154 | { "INT33C6" }, |
155 | { "INT3436" }, | ||
154 | { "PNP0D40" }, | 156 | { "PNP0D40" }, |
155 | { }, | 157 | { }, |
156 | }; | 158 | }; |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 461a4c3f4ef7..b841bb7cd371 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/of_gpio.h> | 27 | #include <linux/of_gpio.h> |
28 | #include <linux/pinctrl/consumer.h> | 28 | #include <linux/pinctrl/consumer.h> |
29 | #include <linux/platform_data/mmc-esdhc-imx.h> | 29 | #include <linux/platform_data/mmc-esdhc-imx.h> |
30 | #include <linux/pm_runtime.h> | ||
30 | #include "sdhci-pltfm.h" | 31 | #include "sdhci-pltfm.h" |
31 | #include "sdhci-esdhc.h" | 32 | #include "sdhci-esdhc.h" |
32 | 33 | ||
@@ -45,6 +46,8 @@ | |||
45 | #define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) | 46 | #define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) |
46 | /* Bits 3 and 6 are not SDHCI standard definitions */ | 47 | /* Bits 3 and 6 are not SDHCI standard definitions */ |
47 | #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 | 48 | #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 |
49 | /* Tuning bits */ | ||
50 | #define ESDHC_MIX_CTRL_TUNING_MASK 0x03c00000 | ||
48 | 51 | ||
49 | /* dll control register */ | 52 | /* dll control register */ |
50 | #define ESDHC_DLL_CTRL 0x60 | 53 | #define ESDHC_DLL_CTRL 0x60 |
@@ -385,6 +388,22 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) | |||
385 | return ret; | 388 | return ret; |
386 | } | 389 | } |
387 | 390 | ||
391 | if (unlikely(reg == SDHCI_TRANSFER_MODE)) { | ||
392 | if (esdhc_is_usdhc(imx_data)) { | ||
393 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
394 | ret = m & ESDHC_MIX_CTRL_SDHCI_MASK; | ||
395 | /* Swap AC23 bit */ | ||
396 | if (m & ESDHC_MIX_CTRL_AC23EN) { | ||
397 | ret &= ~ESDHC_MIX_CTRL_AC23EN; | ||
398 | ret |= SDHCI_TRNS_AUTO_CMD23; | ||
399 | } | ||
400 | } else { | ||
401 | ret = readw(host->ioaddr + SDHCI_TRANSFER_MODE); | ||
402 | } | ||
403 | |||
404 | return ret; | ||
405 | } | ||
406 | |||
388 | return readw(host->ioaddr + reg); | 407 | return readw(host->ioaddr + reg); |
389 | } | 408 | } |
390 | 409 | ||
@@ -421,24 +440,20 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
421 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { | 440 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { |
422 | u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); | 441 | u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); |
423 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); | 442 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); |
424 | new_val = readl(host->ioaddr + ESDHC_TUNING_CTRL); | 443 | if (val & SDHCI_CTRL_TUNED_CLK) { |
444 | v |= ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
445 | } else { | ||
446 | v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
447 | m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; | ||
448 | } | ||
449 | |||
425 | if (val & SDHCI_CTRL_EXEC_TUNING) { | 450 | if (val & SDHCI_CTRL_EXEC_TUNING) { |
426 | new_val |= ESDHC_STD_TUNING_EN | | ||
427 | ESDHC_TUNING_START_TAP; | ||
428 | v |= ESDHC_MIX_CTRL_EXE_TUNE; | 451 | v |= ESDHC_MIX_CTRL_EXE_TUNE; |
429 | m |= ESDHC_MIX_CTRL_FBCLK_SEL; | 452 | m |= ESDHC_MIX_CTRL_FBCLK_SEL; |
430 | } else { | 453 | } else { |
431 | new_val &= ~ESDHC_STD_TUNING_EN; | ||
432 | v &= ~ESDHC_MIX_CTRL_EXE_TUNE; | 454 | v &= ~ESDHC_MIX_CTRL_EXE_TUNE; |
433 | m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; | ||
434 | } | 455 | } |
435 | 456 | ||
436 | if (val & SDHCI_CTRL_TUNED_CLK) | ||
437 | v |= ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
438 | else | ||
439 | v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
440 | |||
441 | writel(new_val, host->ioaddr + ESDHC_TUNING_CTRL); | ||
442 | writel(v, host->ioaddr + SDHCI_ACMD12_ERR); | 457 | writel(v, host->ioaddr + SDHCI_ACMD12_ERR); |
443 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); | 458 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); |
444 | } | 459 | } |
@@ -546,7 +561,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) | |||
546 | * Do it manually here. | 561 | * Do it manually here. |
547 | */ | 562 | */ |
548 | if (esdhc_is_usdhc(imx_data)) { | 563 | if (esdhc_is_usdhc(imx_data)) { |
549 | writel(0, host->ioaddr + ESDHC_MIX_CTRL); | 564 | /* the tuning bits should be kept during reset */ |
565 | new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
566 | writel(new_val & ESDHC_MIX_CTRL_TUNING_MASK, | ||
567 | host->ioaddr + ESDHC_MIX_CTRL); | ||
550 | imx_data->is_ddr = 0; | 568 | imx_data->is_ddr = 0; |
551 | } | 569 | } |
552 | } | 570 | } |
@@ -558,19 +576,17 @@ static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) | |||
558 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | 576 | struct pltfm_imx_data *imx_data = pltfm_host->priv; |
559 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; | 577 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; |
560 | 578 | ||
561 | u32 f_host = clk_get_rate(pltfm_host->clk); | 579 | if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock)) |
562 | |||
563 | if (boarddata->f_max && (boarddata->f_max < f_host)) | ||
564 | return boarddata->f_max; | 580 | return boarddata->f_max; |
565 | else | 581 | else |
566 | return f_host; | 582 | return pltfm_host->clock; |
567 | } | 583 | } |
568 | 584 | ||
569 | static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) | 585 | static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) |
570 | { | 586 | { |
571 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 587 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
572 | 588 | ||
573 | return clk_get_rate(pltfm_host->clk) / 256 / 16; | 589 | return pltfm_host->clock / 256 / 16; |
574 | } | 590 | } |
575 | 591 | ||
576 | static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | 592 | static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, |
@@ -578,7 +594,7 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | |||
578 | { | 594 | { |
579 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 595 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
580 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | 596 | struct pltfm_imx_data *imx_data = pltfm_host->priv; |
581 | unsigned int host_clock = clk_get_rate(pltfm_host->clk); | 597 | unsigned int host_clock = pltfm_host->clock; |
582 | int pre_div = 2; | 598 | int pre_div = 2; |
583 | int div = 1; | 599 | int div = 1; |
584 | u32 temp, val; | 600 | u32 temp, val; |
@@ -681,6 +697,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) | |||
681 | /* FIXME: delay a bit for card to be ready for next tuning due to errors */ | 697 | /* FIXME: delay a bit for card to be ready for next tuning due to errors */ |
682 | mdelay(1); | 698 | mdelay(1); |
683 | 699 | ||
700 | pm_runtime_get_sync(host->mmc->parent); | ||
684 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); | 701 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); |
685 | reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | | 702 | reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | |
686 | ESDHC_MIX_CTRL_FBCLK_SEL; | 703 | ESDHC_MIX_CTRL_FBCLK_SEL; |
@@ -699,7 +716,7 @@ static void esdhc_request_done(struct mmc_request *mrq) | |||
699 | static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) | 716 | static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) |
700 | { | 717 | { |
701 | struct mmc_command cmd = {0}; | 718 | struct mmc_command cmd = {0}; |
702 | struct mmc_request mrq = {0}; | 719 | struct mmc_request mrq = {NULL}; |
703 | struct mmc_data data = {0}; | 720 | struct mmc_data data = {0}; |
704 | struct scatterlist sg; | 721 | struct scatterlist sg; |
705 | char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN]; | 722 | char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN]; |
@@ -809,6 +826,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host, | |||
809 | pinctrl = imx_data->pins_100mhz; | 826 | pinctrl = imx_data->pins_100mhz; |
810 | break; | 827 | break; |
811 | case MMC_TIMING_UHS_SDR104: | 828 | case MMC_TIMING_UHS_SDR104: |
829 | case MMC_TIMING_MMC_HS200: | ||
812 | pinctrl = imx_data->pins_200mhz; | 830 | pinctrl = imx_data->pins_200mhz; |
813 | break; | 831 | break; |
814 | default: | 832 | default: |
@@ -836,6 +854,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) | |||
836 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50; | 854 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50; |
837 | break; | 855 | break; |
838 | case MMC_TIMING_UHS_SDR104: | 856 | case MMC_TIMING_UHS_SDR104: |
857 | case MMC_TIMING_MMC_HS200: | ||
839 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104; | 858 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104; |
840 | break; | 859 | break; |
841 | case MMC_TIMING_UHS_DDR50: | 860 | case MMC_TIMING_UHS_DDR50: |
@@ -976,7 +995,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
976 | } | 995 | } |
977 | 996 | ||
978 | pltfm_host->clk = imx_data->clk_per; | 997 | pltfm_host->clk = imx_data->clk_per; |
979 | 998 | pltfm_host->clock = clk_get_rate(pltfm_host->clk); | |
980 | clk_prepare_enable(imx_data->clk_per); | 999 | clk_prepare_enable(imx_data->clk_per); |
981 | clk_prepare_enable(imx_data->clk_ipg); | 1000 | clk_prepare_enable(imx_data->clk_ipg); |
982 | clk_prepare_enable(imx_data->clk_ahb); | 1001 | clk_prepare_enable(imx_data->clk_ahb); |
@@ -1009,11 +1028,18 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
1009 | if (esdhc_is_usdhc(imx_data)) { | 1028 | if (esdhc_is_usdhc(imx_data)) { |
1010 | writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); | 1029 | writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); |
1011 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; | 1030 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; |
1031 | host->mmc->caps |= MMC_CAP_1_8V_DDR; | ||
1012 | } | 1032 | } |
1013 | 1033 | ||
1014 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) | 1034 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) |
1015 | sdhci_esdhc_ops.platform_execute_tuning = | 1035 | sdhci_esdhc_ops.platform_execute_tuning = |
1016 | esdhc_executing_tuning; | 1036 | esdhc_executing_tuning; |
1037 | |||
1038 | if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) | ||
1039 | writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) | | ||
1040 | ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP, | ||
1041 | host->ioaddr + ESDHC_TUNING_CTRL); | ||
1042 | |||
1017 | boarddata = &imx_data->boarddata; | 1043 | boarddata = &imx_data->boarddata; |
1018 | if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { | 1044 | if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { |
1019 | if (!host->mmc->parent->platform_data) { | 1045 | if (!host->mmc->parent->platform_data) { |
@@ -1053,7 +1079,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
1053 | break; | 1079 | break; |
1054 | 1080 | ||
1055 | case ESDHC_CD_PERMANENT: | 1081 | case ESDHC_CD_PERMANENT: |
1056 | host->mmc->caps = MMC_CAP_NONREMOVABLE; | 1082 | host->mmc->caps |= MMC_CAP_NONREMOVABLE; |
1057 | break; | 1083 | break; |
1058 | 1084 | ||
1059 | case ESDHC_CD_NONE: | 1085 | case ESDHC_CD_NONE: |
@@ -1094,6 +1120,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
1094 | if (err) | 1120 | if (err) |
1095 | goto disable_clk; | 1121 | goto disable_clk; |
1096 | 1122 | ||
1123 | pm_runtime_set_active(&pdev->dev); | ||
1124 | pm_runtime_enable(&pdev->dev); | ||
1125 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); | ||
1126 | pm_runtime_use_autosuspend(&pdev->dev); | ||
1127 | pm_suspend_ignore_children(&pdev->dev, 1); | ||
1128 | |||
1097 | return 0; | 1129 | return 0; |
1098 | 1130 | ||
1099 | disable_clk: | 1131 | disable_clk: |
@@ -1114,21 +1146,63 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev) | |||
1114 | 1146 | ||
1115 | sdhci_remove_host(host, dead); | 1147 | sdhci_remove_host(host, dead); |
1116 | 1148 | ||
1149 | pm_runtime_dont_use_autosuspend(&pdev->dev); | ||
1150 | pm_runtime_disable(&pdev->dev); | ||
1151 | |||
1152 | if (!IS_ENABLED(CONFIG_PM_RUNTIME)) { | ||
1153 | clk_disable_unprepare(imx_data->clk_per); | ||
1154 | clk_disable_unprepare(imx_data->clk_ipg); | ||
1155 | clk_disable_unprepare(imx_data->clk_ahb); | ||
1156 | } | ||
1157 | |||
1158 | sdhci_pltfm_free(pdev); | ||
1159 | |||
1160 | return 0; | ||
1161 | } | ||
1162 | |||
1163 | #ifdef CONFIG_PM_RUNTIME | ||
1164 | static int sdhci_esdhc_runtime_suspend(struct device *dev) | ||
1165 | { | ||
1166 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
1167 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
1168 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
1169 | int ret; | ||
1170 | |||
1171 | ret = sdhci_runtime_suspend_host(host); | ||
1172 | |||
1117 | clk_disable_unprepare(imx_data->clk_per); | 1173 | clk_disable_unprepare(imx_data->clk_per); |
1118 | clk_disable_unprepare(imx_data->clk_ipg); | 1174 | clk_disable_unprepare(imx_data->clk_ipg); |
1119 | clk_disable_unprepare(imx_data->clk_ahb); | 1175 | clk_disable_unprepare(imx_data->clk_ahb); |
1120 | 1176 | ||
1121 | sdhci_pltfm_free(pdev); | 1177 | return ret; |
1178 | } | ||
1122 | 1179 | ||
1123 | return 0; | 1180 | static int sdhci_esdhc_runtime_resume(struct device *dev) |
1181 | { | ||
1182 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
1183 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
1184 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
1185 | |||
1186 | clk_prepare_enable(imx_data->clk_per); | ||
1187 | clk_prepare_enable(imx_data->clk_ipg); | ||
1188 | clk_prepare_enable(imx_data->clk_ahb); | ||
1189 | |||
1190 | return sdhci_runtime_resume_host(host); | ||
1124 | } | 1191 | } |
1192 | #endif | ||
1193 | |||
1194 | static const struct dev_pm_ops sdhci_esdhc_pmops = { | ||
1195 | SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume) | ||
1196 | SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend, | ||
1197 | sdhci_esdhc_runtime_resume, NULL) | ||
1198 | }; | ||
1125 | 1199 | ||
1126 | static struct platform_driver sdhci_esdhc_imx_driver = { | 1200 | static struct platform_driver sdhci_esdhc_imx_driver = { |
1127 | .driver = { | 1201 | .driver = { |
1128 | .name = "sdhci-esdhc-imx", | 1202 | .name = "sdhci-esdhc-imx", |
1129 | .owner = THIS_MODULE, | 1203 | .owner = THIS_MODULE, |
1130 | .of_match_table = imx_esdhc_dt_ids, | 1204 | .of_match_table = imx_esdhc_dt_ids, |
1131 | .pm = SDHCI_PLTFM_PMOPS, | 1205 | .pm = &sdhci_esdhc_pmops, |
1132 | }, | 1206 | }, |
1133 | .id_table = imx_esdhc_devtype, | 1207 | .id_table = imx_esdhc_devtype, |
1134 | .probe = sdhci_esdhc_imx_probe, | 1208 | .probe = sdhci_esdhc_imx_probe, |
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c new file mode 100644 index 000000000000..f7c7cf62437d --- /dev/null +++ b/drivers/mmc/host/sdhci-of-arasan.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Arasan Secure Digital Host Controller Interface. | ||
3 | * Copyright (C) 2011 - 2012 Michal Simek <monstr@monstr.eu> | ||
4 | * Copyright (c) 2012 Wind River Systems, Inc. | ||
5 | * Copyright (C) 2013 Pengutronix e.K. | ||
6 | * Copyright (C) 2013 Xilinx Inc. | ||
7 | * | ||
8 | * Based on sdhci-of-esdhc.c | ||
9 | * | ||
10 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | ||
11 | * Copyright (c) 2009 MontaVista Software, Inc. | ||
12 | * | ||
13 | * Authors: Xiaobo Xie <X.Xie@freescale.com> | ||
14 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or (at | ||
19 | * your option) any later version. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include "sdhci-pltfm.h" | ||
24 | |||
25 | #define SDHCI_ARASAN_CLK_CTRL_OFFSET 0x2c | ||
26 | |||
27 | #define CLK_CTRL_TIMEOUT_SHIFT 16 | ||
28 | #define CLK_CTRL_TIMEOUT_MASK (0xf << CLK_CTRL_TIMEOUT_SHIFT) | ||
29 | #define CLK_CTRL_TIMEOUT_MIN_EXP 13 | ||
30 | |||
31 | /** | ||
32 | * struct sdhci_arasan_data | ||
33 | * @clk_ahb: Pointer to the AHB clock | ||
34 | */ | ||
35 | struct sdhci_arasan_data { | ||
36 | struct clk *clk_ahb; | ||
37 | }; | ||
38 | |||
39 | static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host) | ||
40 | { | ||
41 | u32 div; | ||
42 | unsigned long freq; | ||
43 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
44 | |||
45 | div = readl(host->ioaddr + SDHCI_ARASAN_CLK_CTRL_OFFSET); | ||
46 | div = (div & CLK_CTRL_TIMEOUT_MASK) >> CLK_CTRL_TIMEOUT_SHIFT; | ||
47 | |||
48 | freq = clk_get_rate(pltfm_host->clk); | ||
49 | freq /= 1 << (CLK_CTRL_TIMEOUT_MIN_EXP + div); | ||
50 | |||
51 | return freq; | ||
52 | } | ||
53 | |||
54 | static struct sdhci_ops sdhci_arasan_ops = { | ||
55 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | ||
56 | .get_timeout_clock = sdhci_arasan_get_timeout_clock, | ||
57 | }; | ||
58 | |||
59 | static struct sdhci_pltfm_data sdhci_arasan_pdata = { | ||
60 | .ops = &sdhci_arasan_ops, | ||
61 | }; | ||
62 | |||
63 | #ifdef CONFIG_PM_SLEEP | ||
64 | /** | ||
65 | * sdhci_arasan_suspend - Suspend method for the driver | ||
66 | * @dev: Address of the device structure | ||
67 | * Returns 0 on success and error value on error | ||
68 | * | ||
69 | * Put the device in a low power state. | ||
70 | */ | ||
71 | static int sdhci_arasan_suspend(struct device *dev) | ||
72 | { | ||
73 | struct platform_device *pdev = to_platform_device(dev); | ||
74 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
75 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
76 | struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; | ||
77 | int ret; | ||
78 | |||
79 | ret = sdhci_suspend_host(host); | ||
80 | if (ret) | ||
81 | return ret; | ||
82 | |||
83 | clk_disable(pltfm_host->clk); | ||
84 | clk_disable(sdhci_arasan->clk_ahb); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * sdhci_arasan_resume - Resume method for the driver | ||
91 | * @dev: Address of the device structure | ||
92 | * Returns 0 on success and error value on error | ||
93 | * | ||
94 | * Resume operation after suspend | ||
95 | */ | ||
96 | static int sdhci_arasan_resume(struct device *dev) | ||
97 | { | ||
98 | struct platform_device *pdev = to_platform_device(dev); | ||
99 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
100 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
101 | struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; | ||
102 | int ret; | ||
103 | |||
104 | ret = clk_enable(sdhci_arasan->clk_ahb); | ||
105 | if (ret) { | ||
106 | dev_err(dev, "Cannot enable AHB clock.\n"); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | ret = clk_enable(pltfm_host->clk); | ||
111 | if (ret) { | ||
112 | dev_err(dev, "Cannot enable SD clock.\n"); | ||
113 | clk_disable(sdhci_arasan->clk_ahb); | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | return sdhci_resume_host(host); | ||
118 | } | ||
119 | #endif /* ! CONFIG_PM_SLEEP */ | ||
120 | |||
121 | static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend, | ||
122 | sdhci_arasan_resume); | ||
123 | |||
124 | static int sdhci_arasan_probe(struct platform_device *pdev) | ||
125 | { | ||
126 | int ret; | ||
127 | struct clk *clk_xin; | ||
128 | struct sdhci_host *host; | ||
129 | struct sdhci_pltfm_host *pltfm_host; | ||
130 | struct sdhci_arasan_data *sdhci_arasan; | ||
131 | |||
132 | sdhci_arasan = devm_kzalloc(&pdev->dev, sizeof(*sdhci_arasan), | ||
133 | GFP_KERNEL); | ||
134 | if (!sdhci_arasan) | ||
135 | return -ENOMEM; | ||
136 | |||
137 | sdhci_arasan->clk_ahb = devm_clk_get(&pdev->dev, "clk_ahb"); | ||
138 | if (IS_ERR(sdhci_arasan->clk_ahb)) { | ||
139 | dev_err(&pdev->dev, "clk_ahb clock not found.\n"); | ||
140 | return PTR_ERR(sdhci_arasan->clk_ahb); | ||
141 | } | ||
142 | |||
143 | clk_xin = devm_clk_get(&pdev->dev, "clk_xin"); | ||
144 | if (IS_ERR(clk_xin)) { | ||
145 | dev_err(&pdev->dev, "clk_xin clock not found.\n"); | ||
146 | return PTR_ERR(clk_xin); | ||
147 | } | ||
148 | |||
149 | ret = clk_prepare_enable(sdhci_arasan->clk_ahb); | ||
150 | if (ret) { | ||
151 | dev_err(&pdev->dev, "Unable to enable AHB clock.\n"); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | ret = clk_prepare_enable(clk_xin); | ||
156 | if (ret) { | ||
157 | dev_err(&pdev->dev, "Unable to enable SD clock.\n"); | ||
158 | goto clk_dis_ahb; | ||
159 | } | ||
160 | |||
161 | host = sdhci_pltfm_init(pdev, &sdhci_arasan_pdata, 0); | ||
162 | if (IS_ERR(host)) { | ||
163 | ret = PTR_ERR(host); | ||
164 | dev_err(&pdev->dev, "platform init failed (%u)\n", ret); | ||
165 | goto clk_disable_all; | ||
166 | } | ||
167 | |||
168 | sdhci_get_of_property(pdev); | ||
169 | pltfm_host = sdhci_priv(host); | ||
170 | pltfm_host->priv = sdhci_arasan; | ||
171 | pltfm_host->clk = clk_xin; | ||
172 | |||
173 | ret = sdhci_add_host(host); | ||
174 | if (ret) { | ||
175 | dev_err(&pdev->dev, "platform register failed (%u)\n", ret); | ||
176 | goto err_pltfm_free; | ||
177 | } | ||
178 | |||
179 | return 0; | ||
180 | |||
181 | err_pltfm_free: | ||
182 | sdhci_pltfm_free(pdev); | ||
183 | clk_disable_all: | ||
184 | clk_disable_unprepare(clk_xin); | ||
185 | clk_dis_ahb: | ||
186 | clk_disable_unprepare(sdhci_arasan->clk_ahb); | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static int sdhci_arasan_remove(struct platform_device *pdev) | ||
192 | { | ||
193 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
194 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
195 | struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; | ||
196 | |||
197 | clk_disable_unprepare(pltfm_host->clk); | ||
198 | clk_disable_unprepare(sdhci_arasan->clk_ahb); | ||
199 | |||
200 | return sdhci_pltfm_unregister(pdev); | ||
201 | } | ||
202 | |||
203 | static const struct of_device_id sdhci_arasan_of_match[] = { | ||
204 | { .compatible = "arasan,sdhci-8.9a" }, | ||
205 | { } | ||
206 | }; | ||
207 | MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match); | ||
208 | |||
209 | static struct platform_driver sdhci_arasan_driver = { | ||
210 | .driver = { | ||
211 | .name = "sdhci-arasan", | ||
212 | .owner = THIS_MODULE, | ||
213 | .of_match_table = sdhci_arasan_of_match, | ||
214 | .pm = &sdhci_arasan_dev_pm_ops, | ||
215 | }, | ||
216 | .probe = sdhci_arasan_probe, | ||
217 | .remove = sdhci_arasan_remove, | ||
218 | }; | ||
219 | |||
220 | module_platform_driver(sdhci_arasan_driver); | ||
221 | |||
222 | MODULE_DESCRIPTION("Driver for the Arasan SDHCI Controller"); | ||
223 | MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com>"); | ||
224 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c new file mode 100644 index 000000000000..f49666bcc52a --- /dev/null +++ b/drivers/mmc/host/sdhci-pci-o2micro.c | |||
@@ -0,0 +1,321 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 BayHub Technology Ltd. | ||
3 | * | ||
4 | * Authors: Peter Guo <peter.guo@bayhubtech.com> | ||
5 | * Adam Lee <adam.lee@canonical.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/pci.h> | ||
19 | |||
20 | #include "sdhci.h" | ||
21 | #include "sdhci-pci.h" | ||
22 | #include "sdhci-pci-o2micro.h" | ||
23 | |||
24 | void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) | ||
25 | { | ||
26 | u32 scratch_32; | ||
27 | int ret; | ||
28 | /* Improve write performance for SD3.0 */ | ||
29 | ret = pci_read_config_dword(chip->pdev, O2_SD_DEV_CTRL, &scratch_32); | ||
30 | if (ret) | ||
31 | return; | ||
32 | scratch_32 &= ~((1 << 12) | (1 << 13) | (1 << 14)); | ||
33 | pci_write_config_dword(chip->pdev, O2_SD_DEV_CTRL, scratch_32); | ||
34 | |||
35 | /* Enable Link abnormal reset generating Reset */ | ||
36 | ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_REG5, &scratch_32); | ||
37 | if (ret) | ||
38 | return; | ||
39 | scratch_32 &= ~((1 << 19) | (1 << 11)); | ||
40 | scratch_32 |= (1 << 10); | ||
41 | pci_write_config_dword(chip->pdev, O2_SD_MISC_REG5, scratch_32); | ||
42 | |||
43 | /* set card power over current protection */ | ||
44 | ret = pci_read_config_dword(chip->pdev, O2_SD_TEST_REG, &scratch_32); | ||
45 | if (ret) | ||
46 | return; | ||
47 | scratch_32 |= (1 << 4); | ||
48 | pci_write_config_dword(chip->pdev, O2_SD_TEST_REG, scratch_32); | ||
49 | |||
50 | /* adjust the output delay for SD mode */ | ||
51 | pci_write_config_dword(chip->pdev, O2_SD_DELAY_CTRL, 0x00002492); | ||
52 | |||
53 | /* Set the output voltage setting of Aux 1.2v LDO */ | ||
54 | ret = pci_read_config_dword(chip->pdev, O2_SD_LD0_CTRL, &scratch_32); | ||
55 | if (ret) | ||
56 | return; | ||
57 | scratch_32 &= ~(3 << 12); | ||
58 | pci_write_config_dword(chip->pdev, O2_SD_LD0_CTRL, scratch_32); | ||
59 | |||
60 | /* Set Max power supply capability of SD host */ | ||
61 | ret = pci_read_config_dword(chip->pdev, O2_SD_CAP_REG0, &scratch_32); | ||
62 | if (ret) | ||
63 | return; | ||
64 | scratch_32 &= ~(0x01FE); | ||
65 | scratch_32 |= 0x00CC; | ||
66 | pci_write_config_dword(chip->pdev, O2_SD_CAP_REG0, scratch_32); | ||
67 | /* Set DLL Tuning Window */ | ||
68 | ret = pci_read_config_dword(chip->pdev, | ||
69 | O2_SD_TUNING_CTRL, &scratch_32); | ||
70 | if (ret) | ||
71 | return; | ||
72 | scratch_32 &= ~(0x000000FF); | ||
73 | scratch_32 |= 0x00000066; | ||
74 | pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, scratch_32); | ||
75 | |||
76 | /* Set UHS2 T_EIDLE */ | ||
77 | ret = pci_read_config_dword(chip->pdev, | ||
78 | O2_SD_UHS2_L1_CTRL, &scratch_32); | ||
79 | if (ret) | ||
80 | return; | ||
81 | scratch_32 &= ~(0x000000FC); | ||
82 | scratch_32 |= 0x00000084; | ||
83 | pci_write_config_dword(chip->pdev, O2_SD_UHS2_L1_CTRL, scratch_32); | ||
84 | |||
85 | /* Set UHS2 Termination */ | ||
86 | ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG3, &scratch_32); | ||
87 | if (ret) | ||
88 | return; | ||
89 | scratch_32 &= ~((1 << 21) | (1 << 30)); | ||
90 | |||
91 | /* Set RTD3 function disabled */ | ||
92 | scratch_32 |= ((1 << 29) | (1 << 28)); | ||
93 | pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32); | ||
94 | |||
95 | /* Set L1 Entrance Timer */ | ||
96 | ret = pci_read_config_dword(chip->pdev, O2_SD_CAPS, &scratch_32); | ||
97 | if (ret) | ||
98 | return; | ||
99 | scratch_32 &= ~(0xf0000000); | ||
100 | scratch_32 |= 0x30000000; | ||
101 | pci_write_config_dword(chip->pdev, O2_SD_CAPS, scratch_32); | ||
102 | |||
103 | ret = pci_read_config_dword(chip->pdev, | ||
104 | O2_SD_MISC_CTRL4, &scratch_32); | ||
105 | if (ret) | ||
106 | return; | ||
107 | scratch_32 &= ~(0x000f0000); | ||
108 | scratch_32 |= 0x00080000; | ||
109 | pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32); | ||
110 | } | ||
111 | EXPORT_SYMBOL_GPL(sdhci_pci_o2_fujin2_pci_init); | ||
112 | |||
113 | int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) | ||
114 | { | ||
115 | struct sdhci_pci_chip *chip; | ||
116 | struct sdhci_host *host; | ||
117 | u32 reg; | ||
118 | |||
119 | chip = slot->chip; | ||
120 | host = slot->host; | ||
121 | switch (chip->pdev->device) { | ||
122 | case PCI_DEVICE_ID_O2_SDS0: | ||
123 | case PCI_DEVICE_ID_O2_SEABIRD0: | ||
124 | case PCI_DEVICE_ID_O2_SEABIRD1: | ||
125 | case PCI_DEVICE_ID_O2_SDS1: | ||
126 | case PCI_DEVICE_ID_O2_FUJIN2: | ||
127 | reg = sdhci_readl(host, O2_SD_VENDOR_SETTING); | ||
128 | if (reg & 0x1) | ||
129 | host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; | ||
130 | |||
131 | if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) | ||
132 | break; | ||
133 | /* set dll watch dog timer */ | ||
134 | reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2); | ||
135 | reg |= (1 << 12); | ||
136 | sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2); | ||
137 | |||
138 | break; | ||
139 | default: | ||
140 | break; | ||
141 | } | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | EXPORT_SYMBOL_GPL(sdhci_pci_o2_probe_slot); | ||
146 | |||
147 | int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) | ||
148 | { | ||
149 | int ret; | ||
150 | u8 scratch; | ||
151 | u32 scratch_32; | ||
152 | |||
153 | switch (chip->pdev->device) { | ||
154 | case PCI_DEVICE_ID_O2_8220: | ||
155 | case PCI_DEVICE_ID_O2_8221: | ||
156 | case PCI_DEVICE_ID_O2_8320: | ||
157 | case PCI_DEVICE_ID_O2_8321: | ||
158 | /* This extra setup is required due to broken ADMA. */ | ||
159 | ret = pci_read_config_byte(chip->pdev, | ||
160 | O2_SD_LOCK_WP, &scratch); | ||
161 | if (ret) | ||
162 | return ret; | ||
163 | scratch &= 0x7f; | ||
164 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
165 | |||
166 | /* Set Multi 3 to VCC3V# */ | ||
167 | pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); | ||
168 | |||
169 | /* Disable CLK_REQ# support after media DET */ | ||
170 | ret = pci_read_config_byte(chip->pdev, | ||
171 | O2_SD_CLKREQ, &scratch); | ||
172 | if (ret) | ||
173 | return ret; | ||
174 | scratch |= 0x20; | ||
175 | pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); | ||
176 | |||
177 | /* Choose capabilities, enable SDMA. We have to write 0x01 | ||
178 | * to the capabilities register first to unlock it. | ||
179 | */ | ||
180 | ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); | ||
181 | if (ret) | ||
182 | return ret; | ||
183 | scratch |= 0x01; | ||
184 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); | ||
185 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); | ||
186 | |||
187 | /* Disable ADMA1/2 */ | ||
188 | pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); | ||
189 | pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); | ||
190 | |||
191 | /* Disable the infinite transfer mode */ | ||
192 | ret = pci_read_config_byte(chip->pdev, | ||
193 | O2_SD_INF_MOD, &scratch); | ||
194 | if (ret) | ||
195 | return ret; | ||
196 | scratch |= 0x08; | ||
197 | pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); | ||
198 | |||
199 | /* Lock WP */ | ||
200 | ret = pci_read_config_byte(chip->pdev, | ||
201 | O2_SD_LOCK_WP, &scratch); | ||
202 | if (ret) | ||
203 | return ret; | ||
204 | scratch |= 0x80; | ||
205 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
206 | break; | ||
207 | case PCI_DEVICE_ID_O2_SDS0: | ||
208 | case PCI_DEVICE_ID_O2_SDS1: | ||
209 | case PCI_DEVICE_ID_O2_FUJIN2: | ||
210 | /* UnLock WP */ | ||
211 | ret = pci_read_config_byte(chip->pdev, | ||
212 | O2_SD_LOCK_WP, &scratch); | ||
213 | if (ret) | ||
214 | return ret; | ||
215 | |||
216 | scratch &= 0x7f; | ||
217 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
218 | |||
219 | /* Set timeout CLK */ | ||
220 | ret = pci_read_config_dword(chip->pdev, | ||
221 | O2_SD_CLK_SETTING, &scratch_32); | ||
222 | if (ret) | ||
223 | return ret; | ||
224 | |||
225 | scratch_32 &= ~(0xFF00); | ||
226 | scratch_32 |= 0x07E0C800; | ||
227 | pci_write_config_dword(chip->pdev, | ||
228 | O2_SD_CLK_SETTING, scratch_32); | ||
229 | |||
230 | ret = pci_read_config_dword(chip->pdev, | ||
231 | O2_SD_CLKREQ, &scratch_32); | ||
232 | if (ret) | ||
233 | return ret; | ||
234 | scratch_32 |= 0x3; | ||
235 | pci_write_config_dword(chip->pdev, O2_SD_CLKREQ, scratch_32); | ||
236 | |||
237 | ret = pci_read_config_dword(chip->pdev, | ||
238 | O2_SD_PLL_SETTING, &scratch_32); | ||
239 | if (ret) | ||
240 | return ret; | ||
241 | |||
242 | scratch_32 &= ~(0x1F3F070E); | ||
243 | scratch_32 |= 0x18270106; | ||
244 | pci_write_config_dword(chip->pdev, | ||
245 | O2_SD_PLL_SETTING, scratch_32); | ||
246 | |||
247 | /* Disable UHS1 funciton */ | ||
248 | ret = pci_read_config_dword(chip->pdev, | ||
249 | O2_SD_CAP_REG2, &scratch_32); | ||
250 | if (ret) | ||
251 | return ret; | ||
252 | scratch_32 &= ~(0xE0); | ||
253 | pci_write_config_dword(chip->pdev, | ||
254 | O2_SD_CAP_REG2, scratch_32); | ||
255 | |||
256 | if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) | ||
257 | sdhci_pci_o2_fujin2_pci_init(chip); | ||
258 | |||
259 | /* Lock WP */ | ||
260 | ret = pci_read_config_byte(chip->pdev, | ||
261 | O2_SD_LOCK_WP, &scratch); | ||
262 | if (ret) | ||
263 | return ret; | ||
264 | scratch |= 0x80; | ||
265 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
266 | break; | ||
267 | case PCI_DEVICE_ID_O2_SEABIRD0: | ||
268 | case PCI_DEVICE_ID_O2_SEABIRD1: | ||
269 | /* UnLock WP */ | ||
270 | ret = pci_read_config_byte(chip->pdev, | ||
271 | O2_SD_LOCK_WP, &scratch); | ||
272 | if (ret) | ||
273 | return ret; | ||
274 | |||
275 | scratch &= 0x7f; | ||
276 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
277 | |||
278 | ret = pci_read_config_dword(chip->pdev, | ||
279 | O2_SD_FUNC_REG0, &scratch_32); | ||
280 | |||
281 | if ((scratch_32 & 0xff000000) == 0x01000000) { | ||
282 | scratch_32 &= 0x0000FFFF; | ||
283 | scratch_32 |= 0x1F340000; | ||
284 | |||
285 | pci_write_config_dword(chip->pdev, | ||
286 | O2_SD_PLL_SETTING, scratch_32); | ||
287 | } else { | ||
288 | scratch_32 &= 0x0000FFFF; | ||
289 | scratch_32 |= 0x2c280000; | ||
290 | |||
291 | pci_write_config_dword(chip->pdev, | ||
292 | O2_SD_PLL_SETTING, scratch_32); | ||
293 | |||
294 | ret = pci_read_config_dword(chip->pdev, | ||
295 | O2_SD_FUNC_REG4, | ||
296 | &scratch_32); | ||
297 | scratch_32 |= (1 << 22); | ||
298 | pci_write_config_dword(chip->pdev, | ||
299 | O2_SD_FUNC_REG4, scratch_32); | ||
300 | } | ||
301 | |||
302 | /* Lock WP */ | ||
303 | ret = pci_read_config_byte(chip->pdev, | ||
304 | O2_SD_LOCK_WP, &scratch); | ||
305 | if (ret) | ||
306 | return ret; | ||
307 | scratch |= 0x80; | ||
308 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
309 | break; | ||
310 | } | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | EXPORT_SYMBOL_GPL(sdhci_pci_o2_probe); | ||
315 | |||
316 | int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip) | ||
317 | { | ||
318 | sdhci_pci_o2_probe(chip); | ||
319 | return 0; | ||
320 | } | ||
321 | EXPORT_SYMBOL_GPL(sdhci_pci_o2_resume); | ||
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.h b/drivers/mmc/host/sdhci-pci-o2micro.h new file mode 100644 index 000000000000..dbec4c933488 --- /dev/null +++ b/drivers/mmc/host/sdhci-pci-o2micro.h | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 BayHub Technology Ltd. | ||
3 | * | ||
4 | * Authors: Peter Guo <peter.guo@bayhubtech.com> | ||
5 | * Adam Lee <adam.lee@canonical.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __SDHCI_PCI_O2MICRO_H | ||
19 | #define __SDHCI_PCI_O2MICRO_H | ||
20 | |||
21 | #include "sdhci-pci.h" | ||
22 | |||
23 | /* | ||
24 | * O2Micro device IDs | ||
25 | */ | ||
26 | |||
27 | #define PCI_DEVICE_ID_O2_SDS0 0x8420 | ||
28 | #define PCI_DEVICE_ID_O2_SDS1 0x8421 | ||
29 | #define PCI_DEVICE_ID_O2_FUJIN2 0x8520 | ||
30 | #define PCI_DEVICE_ID_O2_SEABIRD0 0x8620 | ||
31 | #define PCI_DEVICE_ID_O2_SEABIRD1 0x8621 | ||
32 | |||
33 | /* | ||
34 | * O2Micro device registers | ||
35 | */ | ||
36 | |||
37 | #define O2_SD_MISC_REG5 0x64 | ||
38 | #define O2_SD_LD0_CTRL 0x68 | ||
39 | #define O2_SD_DEV_CTRL 0x88 | ||
40 | #define O2_SD_LOCK_WP 0xD3 | ||
41 | #define O2_SD_TEST_REG 0xD4 | ||
42 | #define O2_SD_FUNC_REG0 0xDC | ||
43 | #define O2_SD_MULTI_VCC3V 0xEE | ||
44 | #define O2_SD_CLKREQ 0xEC | ||
45 | #define O2_SD_CAPS 0xE0 | ||
46 | #define O2_SD_ADMA1 0xE2 | ||
47 | #define O2_SD_ADMA2 0xE7 | ||
48 | #define O2_SD_INF_MOD 0xF1 | ||
49 | #define O2_SD_MISC_CTRL4 0xFC | ||
50 | #define O2_SD_TUNING_CTRL 0x300 | ||
51 | #define O2_SD_PLL_SETTING 0x304 | ||
52 | #define O2_SD_CLK_SETTING 0x328 | ||
53 | #define O2_SD_CAP_REG2 0x330 | ||
54 | #define O2_SD_CAP_REG0 0x334 | ||
55 | #define O2_SD_UHS1_CAP_SETTING 0x33C | ||
56 | #define O2_SD_DELAY_CTRL 0x350 | ||
57 | #define O2_SD_UHS2_L1_CTRL 0x35C | ||
58 | #define O2_SD_FUNC_REG3 0x3E0 | ||
59 | #define O2_SD_FUNC_REG4 0x3E4 | ||
60 | |||
61 | #define O2_SD_VENDOR_SETTING 0x110 | ||
62 | #define O2_SD_VENDOR_SETTING2 0x1C8 | ||
63 | |||
64 | extern void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip); | ||
65 | |||
66 | extern int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot); | ||
67 | |||
68 | extern int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip); | ||
69 | |||
70 | extern int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip); | ||
71 | |||
72 | #endif /* __SDHCI_PCI_O2MICRO_H */ | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 8f753811fc7a..0955777b6c7e 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -27,79 +27,8 @@ | |||
27 | #include <linux/mmc/sdhci-pci-data.h> | 27 | #include <linux/mmc/sdhci-pci-data.h> |
28 | 28 | ||
29 | #include "sdhci.h" | 29 | #include "sdhci.h" |
30 | 30 | #include "sdhci-pci.h" | |
31 | /* | 31 | #include "sdhci-pci-o2micro.h" |
32 | * PCI device IDs | ||
33 | */ | ||
34 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 | ||
35 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a | ||
36 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 | ||
37 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 | ||
38 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 | ||
39 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 | ||
40 | #define PCI_DEVICE_ID_INTEL_MRFL_MMC 0x1190 | ||
41 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO0 0x08f9 | ||
42 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO1 0x08fa | ||
43 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb | ||
44 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 | ||
45 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 | ||
46 | |||
47 | /* | ||
48 | * PCI registers | ||
49 | */ | ||
50 | |||
51 | #define PCI_SDHCI_IFPIO 0x00 | ||
52 | #define PCI_SDHCI_IFDMA 0x01 | ||
53 | #define PCI_SDHCI_IFVENDOR 0x02 | ||
54 | |||
55 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ | ||
56 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) | ||
57 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 | ||
58 | |||
59 | #define MAX_SLOTS 8 | ||
60 | |||
61 | struct sdhci_pci_chip; | ||
62 | struct sdhci_pci_slot; | ||
63 | |||
64 | struct sdhci_pci_fixes { | ||
65 | unsigned int quirks; | ||
66 | unsigned int quirks2; | ||
67 | bool allow_runtime_pm; | ||
68 | |||
69 | int (*probe) (struct sdhci_pci_chip *); | ||
70 | |||
71 | int (*probe_slot) (struct sdhci_pci_slot *); | ||
72 | void (*remove_slot) (struct sdhci_pci_slot *, int); | ||
73 | |||
74 | int (*suspend) (struct sdhci_pci_chip *); | ||
75 | int (*resume) (struct sdhci_pci_chip *); | ||
76 | }; | ||
77 | |||
78 | struct sdhci_pci_slot { | ||
79 | struct sdhci_pci_chip *chip; | ||
80 | struct sdhci_host *host; | ||
81 | struct sdhci_pci_data *data; | ||
82 | |||
83 | int pci_bar; | ||
84 | int rst_n_gpio; | ||
85 | int cd_gpio; | ||
86 | int cd_irq; | ||
87 | |||
88 | void (*hw_reset)(struct sdhci_host *host); | ||
89 | }; | ||
90 | |||
91 | struct sdhci_pci_chip { | ||
92 | struct pci_dev *pdev; | ||
93 | |||
94 | unsigned int quirks; | ||
95 | unsigned int quirks2; | ||
96 | bool allow_runtime_pm; | ||
97 | const struct sdhci_pci_fixes *fixes; | ||
98 | |||
99 | int num_slots; /* Slots on controller */ | ||
100 | struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */ | ||
101 | }; | ||
102 | |||
103 | 32 | ||
104 | /*****************************************************************************\ | 33 | /*****************************************************************************\ |
105 | * * | 34 | * * |
@@ -296,6 +225,7 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = { | |||
296 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { | 225 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { |
297 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 226 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
298 | .allow_runtime_pm = true, | 227 | .allow_runtime_pm = true, |
228 | .own_cd_for_runtime_pm = true, | ||
299 | }; | 229 | }; |
300 | 230 | ||
301 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { | 231 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { |
@@ -360,6 +290,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | |||
360 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | 290 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { |
361 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, | 291 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, |
362 | .allow_runtime_pm = true, | 292 | .allow_runtime_pm = true, |
293 | .own_cd_for_runtime_pm = true, | ||
363 | }; | 294 | }; |
364 | 295 | ||
365 | /* Define Host controllers for Intel Merrifield platform */ | 296 | /* Define Host controllers for Intel Merrifield platform */ |
@@ -381,6 +312,7 @@ static int intel_mrfl_mmc_probe_slot(struct sdhci_pci_slot *slot) | |||
381 | 312 | ||
382 | static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { | 313 | static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { |
383 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 314 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
315 | .quirks2 = SDHCI_QUIRK2_BROKEN_HS200, | ||
384 | .probe_slot = intel_mrfl_mmc_probe_slot, | 316 | .probe_slot = intel_mrfl_mmc_probe_slot, |
385 | }; | 317 | }; |
386 | 318 | ||
@@ -393,65 +325,6 @@ static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { | |||
393 | #define O2_SD_ADMA2 0xE7 | 325 | #define O2_SD_ADMA2 0xE7 |
394 | #define O2_SD_INF_MOD 0xF1 | 326 | #define O2_SD_INF_MOD 0xF1 |
395 | 327 | ||
396 | static int o2_probe(struct sdhci_pci_chip *chip) | ||
397 | { | ||
398 | int ret; | ||
399 | u8 scratch; | ||
400 | |||
401 | switch (chip->pdev->device) { | ||
402 | case PCI_DEVICE_ID_O2_8220: | ||
403 | case PCI_DEVICE_ID_O2_8221: | ||
404 | case PCI_DEVICE_ID_O2_8320: | ||
405 | case PCI_DEVICE_ID_O2_8321: | ||
406 | /* This extra setup is required due to broken ADMA. */ | ||
407 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | ||
408 | if (ret) | ||
409 | return ret; | ||
410 | scratch &= 0x7f; | ||
411 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
412 | |||
413 | /* Set Multi 3 to VCC3V# */ | ||
414 | pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); | ||
415 | |||
416 | /* Disable CLK_REQ# support after media DET */ | ||
417 | ret = pci_read_config_byte(chip->pdev, O2_SD_CLKREQ, &scratch); | ||
418 | if (ret) | ||
419 | return ret; | ||
420 | scratch |= 0x20; | ||
421 | pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); | ||
422 | |||
423 | /* Choose capabilities, enable SDMA. We have to write 0x01 | ||
424 | * to the capabilities register first to unlock it. | ||
425 | */ | ||
426 | ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); | ||
427 | if (ret) | ||
428 | return ret; | ||
429 | scratch |= 0x01; | ||
430 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); | ||
431 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); | ||
432 | |||
433 | /* Disable ADMA1/2 */ | ||
434 | pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); | ||
435 | pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); | ||
436 | |||
437 | /* Disable the infinite transfer mode */ | ||
438 | ret = pci_read_config_byte(chip->pdev, O2_SD_INF_MOD, &scratch); | ||
439 | if (ret) | ||
440 | return ret; | ||
441 | scratch |= 0x08; | ||
442 | pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); | ||
443 | |||
444 | /* Lock WP */ | ||
445 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | ||
446 | if (ret) | ||
447 | return ret; | ||
448 | scratch |= 0x80; | ||
449 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
450 | } | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) | 328 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) |
456 | { | 329 | { |
457 | u8 scratch; | 330 | u8 scratch; |
@@ -642,7 +515,10 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) | |||
642 | } | 515 | } |
643 | 516 | ||
644 | static const struct sdhci_pci_fixes sdhci_o2 = { | 517 | static const struct sdhci_pci_fixes sdhci_o2 = { |
645 | .probe = o2_probe, | 518 | .probe = sdhci_pci_o2_probe, |
519 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | ||
520 | .probe_slot = sdhci_pci_o2_probe_slot, | ||
521 | .resume = sdhci_pci_o2_resume, | ||
646 | }; | 522 | }; |
647 | 523 | ||
648 | static const struct sdhci_pci_fixes sdhci_jmicron = { | 524 | static const struct sdhci_pci_fixes sdhci_jmicron = { |
@@ -1055,6 +931,46 @@ static const struct pci_device_id pci_ids[] = { | |||
1055 | .driver_data = (kernel_ulong_t)&sdhci_o2, | 931 | .driver_data = (kernel_ulong_t)&sdhci_o2, |
1056 | }, | 932 | }, |
1057 | 933 | ||
934 | { | ||
935 | .vendor = PCI_VENDOR_ID_O2, | ||
936 | .device = PCI_DEVICE_ID_O2_FUJIN2, | ||
937 | .subvendor = PCI_ANY_ID, | ||
938 | .subdevice = PCI_ANY_ID, | ||
939 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
940 | }, | ||
941 | |||
942 | { | ||
943 | .vendor = PCI_VENDOR_ID_O2, | ||
944 | .device = PCI_DEVICE_ID_O2_SDS0, | ||
945 | .subvendor = PCI_ANY_ID, | ||
946 | .subdevice = PCI_ANY_ID, | ||
947 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
948 | }, | ||
949 | |||
950 | { | ||
951 | .vendor = PCI_VENDOR_ID_O2, | ||
952 | .device = PCI_DEVICE_ID_O2_SDS1, | ||
953 | .subvendor = PCI_ANY_ID, | ||
954 | .subdevice = PCI_ANY_ID, | ||
955 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
956 | }, | ||
957 | |||
958 | { | ||
959 | .vendor = PCI_VENDOR_ID_O2, | ||
960 | .device = PCI_DEVICE_ID_O2_SEABIRD0, | ||
961 | .subvendor = PCI_ANY_ID, | ||
962 | .subdevice = PCI_ANY_ID, | ||
963 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
964 | }, | ||
965 | |||
966 | { | ||
967 | .vendor = PCI_VENDOR_ID_O2, | ||
968 | .device = PCI_DEVICE_ID_O2_SEABIRD1, | ||
969 | .subvendor = PCI_ANY_ID, | ||
970 | .subdevice = PCI_ANY_ID, | ||
971 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
972 | }, | ||
973 | |||
1058 | { /* Generic SD host controller */ | 974 | { /* Generic SD host controller */ |
1059 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | 975 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) |
1060 | }, | 976 | }, |
@@ -1457,6 +1373,15 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( | |||
1457 | 1373 | ||
1458 | sdhci_pci_add_own_cd(slot); | 1374 | sdhci_pci_add_own_cd(slot); |
1459 | 1375 | ||
1376 | /* | ||
1377 | * Check if the chip needs a separate GPIO for card detect to wake up | ||
1378 | * from runtime suspend. If it is not there, don't allow runtime PM. | ||
1379 | * Note sdhci_pci_add_own_cd() sets slot->cd_gpio to -EINVAL on failure. | ||
1380 | */ | ||
1381 | if (chip->fixes && chip->fixes->own_cd_for_runtime_pm && | ||
1382 | !gpio_is_valid(slot->cd_gpio)) | ||
1383 | chip->allow_runtime_pm = false; | ||
1384 | |||
1460 | return slot; | 1385 | return slot; |
1461 | 1386 | ||
1462 | remove: | 1387 | remove: |
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h new file mode 100644 index 000000000000..6d718719659e --- /dev/null +++ b/drivers/mmc/host/sdhci-pci.h | |||
@@ -0,0 +1,78 @@ | |||
1 | #ifndef __SDHCI_PCI_H | ||
2 | #define __SDHCI_PCI_H | ||
3 | |||
4 | /* | ||
5 | * PCI device IDs | ||
6 | */ | ||
7 | |||
8 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 | ||
9 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a | ||
10 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 | ||
11 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 | ||
12 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 | ||
13 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 | ||
14 | #define PCI_DEVICE_ID_INTEL_MRFL_MMC 0x1190 | ||
15 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO0 0x08f9 | ||
16 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO1 0x08fa | ||
17 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb | ||
18 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 | ||
19 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 | ||
20 | |||
21 | /* | ||
22 | * PCI registers | ||
23 | */ | ||
24 | |||
25 | #define PCI_SDHCI_IFPIO 0x00 | ||
26 | #define PCI_SDHCI_IFDMA 0x01 | ||
27 | #define PCI_SDHCI_IFVENDOR 0x02 | ||
28 | |||
29 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ | ||
30 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) | ||
31 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 | ||
32 | |||
33 | #define MAX_SLOTS 8 | ||
34 | |||
35 | struct sdhci_pci_chip; | ||
36 | struct sdhci_pci_slot; | ||
37 | |||
38 | struct sdhci_pci_fixes { | ||
39 | unsigned int quirks; | ||
40 | unsigned int quirks2; | ||
41 | bool allow_runtime_pm; | ||
42 | bool own_cd_for_runtime_pm; | ||
43 | |||
44 | int (*probe) (struct sdhci_pci_chip *); | ||
45 | |||
46 | int (*probe_slot) (struct sdhci_pci_slot *); | ||
47 | void (*remove_slot) (struct sdhci_pci_slot *, int); | ||
48 | |||
49 | int (*suspend) (struct sdhci_pci_chip *); | ||
50 | int (*resume) (struct sdhci_pci_chip *); | ||
51 | }; | ||
52 | |||
53 | struct sdhci_pci_slot { | ||
54 | struct sdhci_pci_chip *chip; | ||
55 | struct sdhci_host *host; | ||
56 | struct sdhci_pci_data *data; | ||
57 | |||
58 | int pci_bar; | ||
59 | int rst_n_gpio; | ||
60 | int cd_gpio; | ||
61 | int cd_irq; | ||
62 | |||
63 | void (*hw_reset)(struct sdhci_host *host); | ||
64 | }; | ||
65 | |||
66 | struct sdhci_pci_chip { | ||
67 | struct pci_dev *pdev; | ||
68 | |||
69 | unsigned int quirks; | ||
70 | unsigned int quirks2; | ||
71 | bool allow_runtime_pm; | ||
72 | const struct sdhci_pci_fixes *fixes; | ||
73 | |||
74 | int num_slots; /* Slots on controller */ | ||
75 | struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */ | ||
76 | }; | ||
77 | |||
78 | #endif /* __SDHCI_PCI_H */ | ||
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index e2065a44dffc..bef250e95418 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -237,19 +237,21 @@ int sdhci_pltfm_unregister(struct platform_device *pdev) | |||
237 | EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister); | 237 | EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister); |
238 | 238 | ||
239 | #ifdef CONFIG_PM | 239 | #ifdef CONFIG_PM |
240 | static int sdhci_pltfm_suspend(struct device *dev) | 240 | int sdhci_pltfm_suspend(struct device *dev) |
241 | { | 241 | { |
242 | struct sdhci_host *host = dev_get_drvdata(dev); | 242 | struct sdhci_host *host = dev_get_drvdata(dev); |
243 | 243 | ||
244 | return sdhci_suspend_host(host); | 244 | return sdhci_suspend_host(host); |
245 | } | 245 | } |
246 | EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend); | ||
246 | 247 | ||
247 | static int sdhci_pltfm_resume(struct device *dev) | 248 | int sdhci_pltfm_resume(struct device *dev) |
248 | { | 249 | { |
249 | struct sdhci_host *host = dev_get_drvdata(dev); | 250 | struct sdhci_host *host = dev_get_drvdata(dev); |
250 | 251 | ||
251 | return sdhci_resume_host(host); | 252 | return sdhci_resume_host(host); |
252 | } | 253 | } |
254 | EXPORT_SYMBOL_GPL(sdhci_pltfm_resume); | ||
253 | 255 | ||
254 | const struct dev_pm_ops sdhci_pltfm_pmops = { | 256 | const struct dev_pm_ops sdhci_pltfm_pmops = { |
255 | .suspend = sdhci_pltfm_suspend, | 257 | .suspend = sdhci_pltfm_suspend, |
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index e15ced79f7ed..04bc2481e5c3 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h | |||
@@ -111,6 +111,8 @@ static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | #ifdef CONFIG_PM | 113 | #ifdef CONFIG_PM |
114 | extern int sdhci_pltfm_suspend(struct device *dev); | ||
115 | extern int sdhci_pltfm_resume(struct device *dev); | ||
114 | extern const struct dev_pm_ops sdhci_pltfm_pmops; | 116 | extern const struct dev_pm_ops sdhci_pltfm_pmops; |
115 | #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) | 117 | #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) |
116 | #else | 118 | #else |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 5b7b2eba8a54..a835898a68dd 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
@@ -198,6 +198,7 @@ static struct sdhci_tegra_soc_data soc_data_tegra114 = { | |||
198 | }; | 198 | }; |
199 | 199 | ||
200 | static const struct of_device_id sdhci_tegra_dt_match[] = { | 200 | static const struct of_device_id sdhci_tegra_dt_match[] = { |
201 | { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 }, | ||
201 | { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, | 202 | { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, |
202 | { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, | 203 | { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, |
203 | { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, | 204 | { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bd8a0982aec3..9ddef4763541 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -898,8 +898,13 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, | |||
898 | u16 mode; | 898 | u16 mode; |
899 | struct mmc_data *data = cmd->data; | 899 | struct mmc_data *data = cmd->data; |
900 | 900 | ||
901 | if (data == NULL) | 901 | if (data == NULL) { |
902 | /* clear Auto CMD settings for no data CMDs */ | ||
903 | mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); | ||
904 | sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | | ||
905 | SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); | ||
902 | return; | 906 | return; |
907 | } | ||
903 | 908 | ||
904 | WARN_ON(!host->data); | 909 | WARN_ON(!host->data); |
905 | 910 | ||
@@ -1013,7 +1018,12 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
1013 | mdelay(1); | 1018 | mdelay(1); |
1014 | } | 1019 | } |
1015 | 1020 | ||
1016 | mod_timer(&host->timer, jiffies + 10 * HZ); | 1021 | timeout = jiffies; |
1022 | if (!cmd->data && cmd->cmd_timeout_ms > 9000) | ||
1023 | timeout += DIV_ROUND_UP(cmd->cmd_timeout_ms, 1000) * HZ + HZ; | ||
1024 | else | ||
1025 | timeout += 10 * HZ; | ||
1026 | mod_timer(&host->timer, timeout); | ||
1017 | 1027 | ||
1018 | host->cmd = cmd; | 1028 | host->cmd = cmd; |
1019 | 1029 | ||
@@ -1391,6 +1401,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1391 | mmc->card->type == MMC_TYPE_MMC ? | 1401 | mmc->card->type == MMC_TYPE_MMC ? |
1392 | MMC_SEND_TUNING_BLOCK_HS200 : | 1402 | MMC_SEND_TUNING_BLOCK_HS200 : |
1393 | MMC_SEND_TUNING_BLOCK; | 1403 | MMC_SEND_TUNING_BLOCK; |
1404 | |||
1405 | /* Here we need to set the host->mrq to NULL, | ||
1406 | * in case the pending finish_tasklet | ||
1407 | * finishes it incorrectly. | ||
1408 | */ | ||
1409 | host->mrq = NULL; | ||
1410 | |||
1394 | spin_unlock_irqrestore(&host->lock, flags); | 1411 | spin_unlock_irqrestore(&host->lock, flags); |
1395 | sdhci_execute_tuning(mmc, tuning_opcode); | 1412 | sdhci_execute_tuning(mmc, tuning_opcode); |
1396 | spin_lock_irqsave(&host->lock, flags); | 1413 | spin_lock_irqsave(&host->lock, flags); |
@@ -1845,12 +1862,12 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
1845 | unsigned long timeout; | 1862 | unsigned long timeout; |
1846 | int err = 0; | 1863 | int err = 0; |
1847 | bool requires_tuning_nonuhs = false; | 1864 | bool requires_tuning_nonuhs = false; |
1865 | unsigned long flags; | ||
1848 | 1866 | ||
1849 | host = mmc_priv(mmc); | 1867 | host = mmc_priv(mmc); |
1850 | 1868 | ||
1851 | sdhci_runtime_pm_get(host); | 1869 | sdhci_runtime_pm_get(host); |
1852 | disable_irq(host->irq); | 1870 | spin_lock_irqsave(&host->lock, flags); |
1853 | spin_lock(&host->lock); | ||
1854 | 1871 | ||
1855 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1872 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
1856 | 1873 | ||
@@ -1870,15 +1887,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
1870 | requires_tuning_nonuhs) | 1887 | requires_tuning_nonuhs) |
1871 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | 1888 | ctrl |= SDHCI_CTRL_EXEC_TUNING; |
1872 | else { | 1889 | else { |
1873 | spin_unlock(&host->lock); | 1890 | spin_unlock_irqrestore(&host->lock, flags); |
1874 | enable_irq(host->irq); | ||
1875 | sdhci_runtime_pm_put(host); | 1891 | sdhci_runtime_pm_put(host); |
1876 | return 0; | 1892 | return 0; |
1877 | } | 1893 | } |
1878 | 1894 | ||
1879 | if (host->ops->platform_execute_tuning) { | 1895 | if (host->ops->platform_execute_tuning) { |
1880 | spin_unlock(&host->lock); | 1896 | spin_unlock_irqrestore(&host->lock, flags); |
1881 | enable_irq(host->irq); | ||
1882 | err = host->ops->platform_execute_tuning(host, opcode); | 1897 | err = host->ops->platform_execute_tuning(host, opcode); |
1883 | sdhci_runtime_pm_put(host); | 1898 | sdhci_runtime_pm_put(host); |
1884 | return err; | 1899 | return err; |
@@ -1951,15 +1966,12 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
1951 | host->cmd = NULL; | 1966 | host->cmd = NULL; |
1952 | host->mrq = NULL; | 1967 | host->mrq = NULL; |
1953 | 1968 | ||
1954 | spin_unlock(&host->lock); | 1969 | spin_unlock_irqrestore(&host->lock, flags); |
1955 | enable_irq(host->irq); | ||
1956 | |||
1957 | /* Wait for Buffer Read Ready interrupt */ | 1970 | /* Wait for Buffer Read Ready interrupt */ |
1958 | wait_event_interruptible_timeout(host->buf_ready_int, | 1971 | wait_event_interruptible_timeout(host->buf_ready_int, |
1959 | (host->tuning_done == 1), | 1972 | (host->tuning_done == 1), |
1960 | msecs_to_jiffies(50)); | 1973 | msecs_to_jiffies(50)); |
1961 | disable_irq(host->irq); | 1974 | spin_lock_irqsave(&host->lock, flags); |
1962 | spin_lock(&host->lock); | ||
1963 | 1975 | ||
1964 | if (!host->tuning_done) { | 1976 | if (!host->tuning_done) { |
1965 | pr_info(DRIVER_NAME ": Timeout waiting for " | 1977 | pr_info(DRIVER_NAME ": Timeout waiting for " |
@@ -2034,8 +2046,7 @@ out: | |||
2034 | err = 0; | 2046 | err = 0; |
2035 | 2047 | ||
2036 | sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); | 2048 | sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); |
2037 | spin_unlock(&host->lock); | 2049 | spin_unlock_irqrestore(&host->lock, flags); |
2038 | enable_irq(host->irq); | ||
2039 | sdhci_runtime_pm_put(host); | 2050 | sdhci_runtime_pm_put(host); |
2040 | 2051 | ||
2041 | return err; | 2052 | return err; |
@@ -3004,7 +3015,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
3004 | /* SD3.0: SDR104 is supported so (for eMMC) the caps2 | 3015 | /* SD3.0: SDR104 is supported so (for eMMC) the caps2 |
3005 | * field can be promoted to support HS200. | 3016 | * field can be promoted to support HS200. |
3006 | */ | 3017 | */ |
3007 | mmc->caps2 |= MMC_CAP2_HS200; | 3018 | if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) |
3019 | mmc->caps2 |= MMC_CAP2_HS200; | ||
3008 | } else if (caps[1] & SDHCI_SUPPORT_SDR50) | 3020 | } else if (caps[1] & SDHCI_SUPPORT_SDR50) |
3009 | mmc->caps |= MMC_CAP_UHS_SDR50; | 3021 | mmc->caps |= MMC_CAP_UHS_SDR50; |
3010 | 3022 | ||
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index d032b080ac4d..54730f4aac87 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -381,73 +381,75 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) | |||
381 | desc, cookie); | 381 | desc, cookie); |
382 | } | 382 | } |
383 | 383 | ||
384 | static void sh_mmcif_request_dma(struct sh_mmcif_host *host, | 384 | static struct dma_chan * |
385 | struct sh_mmcif_plat_data *pdata) | 385 | sh_mmcif_request_dma_one(struct sh_mmcif_host *host, |
386 | struct sh_mmcif_plat_data *pdata, | ||
387 | enum dma_transfer_direction direction) | ||
386 | { | 388 | { |
387 | struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); | ||
388 | struct dma_slave_config cfg; | 389 | struct dma_slave_config cfg; |
390 | struct dma_chan *chan; | ||
391 | unsigned int slave_id; | ||
392 | struct resource *res; | ||
389 | dma_cap_mask_t mask; | 393 | dma_cap_mask_t mask; |
390 | int ret; | 394 | int ret; |
391 | 395 | ||
392 | host->dma_active = false; | ||
393 | |||
394 | if (pdata) { | ||
395 | if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) | ||
396 | return; | ||
397 | } else if (!host->pd->dev.of_node) { | ||
398 | return; | ||
399 | } | ||
400 | |||
401 | /* We can only either use DMA for both Tx and Rx or not use it at all */ | ||
402 | dma_cap_zero(mask); | 396 | dma_cap_zero(mask); |
403 | dma_cap_set(DMA_SLAVE, mask); | 397 | dma_cap_set(DMA_SLAVE, mask); |
404 | 398 | ||
405 | host->chan_tx = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 399 | if (pdata) |
406 | pdata ? (void *)pdata->slave_id_tx : NULL, | 400 | slave_id = direction == DMA_MEM_TO_DEV |
407 | &host->pd->dev, "tx"); | 401 | ? pdata->slave_id_tx : pdata->slave_id_rx; |
408 | dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, | 402 | else |
409 | host->chan_tx); | 403 | slave_id = 0; |
410 | 404 | ||
411 | if (!host->chan_tx) | 405 | chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, |
412 | return; | 406 | (void *)(unsigned long)slave_id, &host->pd->dev, |
407 | direction == DMA_MEM_TO_DEV ? "tx" : "rx"); | ||
408 | |||
409 | dev_dbg(&host->pd->dev, "%s: %s: got channel %p\n", __func__, | ||
410 | direction == DMA_MEM_TO_DEV ? "TX" : "RX", chan); | ||
411 | |||
412 | if (!chan) | ||
413 | return NULL; | ||
414 | |||
415 | res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); | ||
413 | 416 | ||
414 | /* In the OF case the driver will get the slave ID from the DT */ | 417 | /* In the OF case the driver will get the slave ID from the DT */ |
415 | if (pdata) | 418 | cfg.slave_id = slave_id; |
416 | cfg.slave_id = pdata->slave_id_tx; | 419 | cfg.direction = direction; |
417 | cfg.direction = DMA_MEM_TO_DEV; | ||
418 | cfg.dst_addr = res->start + MMCIF_CE_DATA; | 420 | cfg.dst_addr = res->start + MMCIF_CE_DATA; |
419 | cfg.src_addr = 0; | 421 | cfg.src_addr = 0; |
420 | ret = dmaengine_slave_config(host->chan_tx, &cfg); | 422 | ret = dmaengine_slave_config(chan, &cfg); |
421 | if (ret < 0) | 423 | if (ret < 0) { |
422 | goto ecfgtx; | 424 | dma_release_channel(chan); |
425 | return NULL; | ||
426 | } | ||
423 | 427 | ||
424 | host->chan_rx = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 428 | return chan; |
425 | pdata ? (void *)pdata->slave_id_rx : NULL, | 429 | } |
426 | &host->pd->dev, "rx"); | ||
427 | dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, | ||
428 | host->chan_rx); | ||
429 | 430 | ||
430 | if (!host->chan_rx) | 431 | static void sh_mmcif_request_dma(struct sh_mmcif_host *host, |
431 | goto erqrx; | 432 | struct sh_mmcif_plat_data *pdata) |
433 | { | ||
434 | host->dma_active = false; | ||
432 | 435 | ||
433 | if (pdata) | 436 | if (pdata) { |
434 | cfg.slave_id = pdata->slave_id_rx; | 437 | if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) |
435 | cfg.direction = DMA_DEV_TO_MEM; | 438 | return; |
436 | cfg.dst_addr = 0; | 439 | } else if (!host->pd->dev.of_node) { |
437 | cfg.src_addr = res->start + MMCIF_CE_DATA; | 440 | return; |
438 | ret = dmaengine_slave_config(host->chan_rx, &cfg); | 441 | } |
439 | if (ret < 0) | ||
440 | goto ecfgrx; | ||
441 | 442 | ||
442 | return; | 443 | /* We can only either use DMA for both Tx and Rx or not use it at all */ |
444 | host->chan_tx = sh_mmcif_request_dma_one(host, pdata, DMA_MEM_TO_DEV); | ||
445 | if (!host->chan_tx) | ||
446 | return; | ||
443 | 447 | ||
444 | ecfgrx: | 448 | host->chan_rx = sh_mmcif_request_dma_one(host, pdata, DMA_DEV_TO_MEM); |
445 | dma_release_channel(host->chan_rx); | 449 | if (!host->chan_rx) { |
446 | host->chan_rx = NULL; | 450 | dma_release_channel(host->chan_tx); |
447 | erqrx: | 451 | host->chan_tx = NULL; |
448 | ecfgtx: | 452 | } |
449 | dma_release_channel(host->chan_tx); | ||
450 | host->chan_tx = NULL; | ||
451 | } | 453 | } |
452 | 454 | ||
453 | static void sh_mmcif_release_dma(struct sh_mmcif_host *host) | 455 | static void sh_mmcif_release_dma(struct sh_mmcif_host *host) |
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index f344659dceac..2d6ce257a273 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c | |||
@@ -33,6 +33,8 @@ | |||
33 | 33 | ||
34 | #include "tmio_mmc.h" | 34 | #include "tmio_mmc.h" |
35 | 35 | ||
36 | #define EXT_ACC 0xe4 | ||
37 | |||
36 | struct sh_mobile_sdhi_of_data { | 38 | struct sh_mobile_sdhi_of_data { |
37 | unsigned long tmio_flags; | 39 | unsigned long tmio_flags; |
38 | }; | 40 | }; |
@@ -54,7 +56,7 @@ static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int | |||
54 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 56 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
55 | struct tmio_mmc_host *host = mmc_priv(mmc); | 57 | struct tmio_mmc_host *host = mmc_priv(mmc); |
56 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 58 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); |
57 | int ret = clk_enable(priv->clk); | 59 | int ret = clk_prepare_enable(priv->clk); |
58 | if (ret < 0) | 60 | if (ret < 0) |
59 | return ret; | 61 | return ret; |
60 | 62 | ||
@@ -67,7 +69,7 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) | |||
67 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 69 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
68 | struct tmio_mmc_host *host = mmc_priv(mmc); | 70 | struct tmio_mmc_host *host = mmc_priv(mmc); |
69 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 71 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); |
70 | clk_disable(priv->clk); | 72 | clk_disable_unprepare(priv->clk); |
71 | } | 73 | } |
72 | 74 | ||
73 | static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) | 75 | static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) |
@@ -133,9 +135,15 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
133 | struct tmio_mmc_data *mmc_data; | 135 | struct tmio_mmc_data *mmc_data; |
134 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; | 136 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; |
135 | struct tmio_mmc_host *host; | 137 | struct tmio_mmc_host *host; |
138 | struct resource *res; | ||
136 | int irq, ret, i = 0; | 139 | int irq, ret, i = 0; |
137 | bool multiplexed_isr = true; | 140 | bool multiplexed_isr = true; |
138 | struct tmio_mmc_dma *dma_priv; | 141 | struct tmio_mmc_dma *dma_priv; |
142 | u16 ver; | ||
143 | |||
144 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
145 | if (!res) | ||
146 | return -EINVAL; | ||
139 | 147 | ||
140 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); | 148 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); |
141 | if (priv == NULL) { | 149 | if (priv == NULL) { |
@@ -206,11 +214,22 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
206 | mmc_data->flags |= of_data->tmio_flags; | 214 | mmc_data->flags |= of_data->tmio_flags; |
207 | } | 215 | } |
208 | 216 | ||
217 | /* SD control register space size is 0x100, 0x200 for bus_shift=1 */ | ||
218 | mmc_data->bus_shift = resource_size(res) >> 9; | ||
219 | |||
209 | ret = tmio_mmc_host_probe(&host, pdev, mmc_data); | 220 | ret = tmio_mmc_host_probe(&host, pdev, mmc_data); |
210 | if (ret < 0) | 221 | if (ret < 0) |
211 | goto eprobe; | 222 | goto eprobe; |
212 | 223 | ||
213 | /* | 224 | /* |
225 | * FIXME: | ||
226 | * this Workaround can be more clever method | ||
227 | */ | ||
228 | ver = sd_ctrl_read16(host, CTL_VERSION); | ||
229 | if (ver == 0xCB0D) | ||
230 | sd_ctrl_write16(host, EXT_ACC, 1); | ||
231 | |||
232 | /* | ||
214 | * Allow one or more specific (named) ISRs or | 233 | * Allow one or more specific (named) ISRs or |
215 | * one or more multiplexed (un-named) ISRs. | 234 | * one or more multiplexed (un-named) ISRs. |
216 | */ | 235 | */ |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 8860d4d2bc22..1900abb04236 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
@@ -62,6 +62,7 @@ static int tmio_mmc_probe(struct platform_device *pdev) | |||
62 | const struct mfd_cell *cell = mfd_get_cell(pdev); | 62 | const struct mfd_cell *cell = mfd_get_cell(pdev); |
63 | struct tmio_mmc_data *pdata; | 63 | struct tmio_mmc_data *pdata; |
64 | struct tmio_mmc_host *host; | 64 | struct tmio_mmc_host *host; |
65 | struct resource *res; | ||
65 | int ret = -EINVAL, irq; | 66 | int ret = -EINVAL, irq; |
66 | 67 | ||
67 | if (pdev->num_resources != 2) | 68 | if (pdev->num_resources != 2) |
@@ -84,6 +85,14 @@ static int tmio_mmc_probe(struct platform_device *pdev) | |||
84 | goto out; | 85 | goto out; |
85 | } | 86 | } |
86 | 87 | ||
88 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
89 | if (!res) | ||
90 | return -EINVAL; | ||
91 | |||
92 | /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ | ||
93 | pdata->bus_shift = resource_size(res) >> 10; | ||
94 | pdata->flags |= TMIO_MMC_HAVE_HIGH_REG; | ||
95 | |||
87 | ret = tmio_mmc_host_probe(&host, pdev, pdata); | 96 | ret = tmio_mmc_host_probe(&host, pdev, pdata); |
88 | if (ret) | 97 | if (ret) |
89 | goto cell_disable; | 98 | goto cell_disable; |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 86fd21e00099..aaa9c7e9e730 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
@@ -58,7 +58,6 @@ enum tmio_mmc_power { | |||
58 | 58 | ||
59 | struct tmio_mmc_host { | 59 | struct tmio_mmc_host { |
60 | void __iomem *ctl; | 60 | void __iomem *ctl; |
61 | unsigned long bus_shift; | ||
62 | struct mmc_command *cmd; | 61 | struct mmc_command *cmd; |
63 | struct mmc_request *mrq; | 62 | struct mmc_request *mrq; |
64 | struct mmc_data *data; | 63 | struct mmc_data *data; |
@@ -176,19 +175,19 @@ int tmio_mmc_host_runtime_resume(struct device *dev); | |||
176 | 175 | ||
177 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) | 176 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) |
178 | { | 177 | { |
179 | return readw(host->ctl + (addr << host->bus_shift)); | 178 | return readw(host->ctl + (addr << host->pdata->bus_shift)); |
180 | } | 179 | } |
181 | 180 | ||
182 | static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, | 181 | static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, |
183 | u16 *buf, int count) | 182 | u16 *buf, int count) |
184 | { | 183 | { |
185 | readsw(host->ctl + (addr << host->bus_shift), buf, count); | 184 | readsw(host->ctl + (addr << host->pdata->bus_shift), buf, count); |
186 | } | 185 | } |
187 | 186 | ||
188 | static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) | 187 | static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) |
189 | { | 188 | { |
190 | return readw(host->ctl + (addr << host->bus_shift)) | | 189 | return readw(host->ctl + (addr << host->pdata->bus_shift)) | |
191 | readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16; | 190 | readw(host->ctl + ((addr + 2) << host->pdata->bus_shift)) << 16; |
192 | } | 191 | } |
193 | 192 | ||
194 | static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) | 193 | static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) |
@@ -198,19 +197,19 @@ static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val | |||
198 | */ | 197 | */ |
199 | if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr)) | 198 | if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr)) |
200 | return; | 199 | return; |
201 | writew(val, host->ctl + (addr << host->bus_shift)); | 200 | writew(val, host->ctl + (addr << host->pdata->bus_shift)); |
202 | } | 201 | } |
203 | 202 | ||
204 | static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, | 203 | static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, |
205 | u16 *buf, int count) | 204 | u16 *buf, int count) |
206 | { | 205 | { |
207 | writesw(host->ctl + (addr << host->bus_shift), buf, count); | 206 | writesw(host->ctl + (addr << host->pdata->bus_shift), buf, count); |
208 | } | 207 | } |
209 | 208 | ||
210 | static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) | 209 | static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) |
211 | { | 210 | { |
212 | writew(val, host->ctl + (addr << host->bus_shift)); | 211 | writew(val, host->ctl + (addr << host->pdata->bus_shift)); |
213 | writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); | 212 | writew(val >> 16, host->ctl + ((addr + 2) << host->pdata->bus_shift)); |
214 | } | 213 | } |
215 | 214 | ||
216 | 215 | ||
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 65edb4a62452..03e7b280cb4c 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c | |||
@@ -293,7 +293,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat | |||
293 | if (pdata->dma->chan_priv_tx) | 293 | if (pdata->dma->chan_priv_tx) |
294 | cfg.slave_id = pdata->dma->slave_id_tx; | 294 | cfg.slave_id = pdata->dma->slave_id_tx; |
295 | cfg.direction = DMA_MEM_TO_DEV; | 295 | cfg.direction = DMA_MEM_TO_DEV; |
296 | cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->bus_shift); | 296 | cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->pdata->bus_shift); |
297 | cfg.src_addr = 0; | 297 | cfg.src_addr = 0; |
298 | ret = dmaengine_slave_config(host->chan_tx, &cfg); | 298 | ret = dmaengine_slave_config(host->chan_tx, &cfg); |
299 | if (ret < 0) | 299 | if (ret < 0) |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index f3b2d8ca1eca..8d8abf23a611 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -161,10 +161,8 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) | |||
161 | 161 | ||
162 | static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) | 162 | static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) |
163 | { | 163 | { |
164 | struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); | ||
165 | |||
166 | /* implicit BUG_ON(!res) */ | 164 | /* implicit BUG_ON(!res) */ |
167 | if (resource_size(res) > 0x100) { | 165 | if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) { |
168 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); | 166 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); |
169 | msleep(10); | 167 | msleep(10); |
170 | } | 168 | } |
@@ -176,14 +174,12 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) | |||
176 | 174 | ||
177 | static void tmio_mmc_clk_start(struct tmio_mmc_host *host) | 175 | static void tmio_mmc_clk_start(struct tmio_mmc_host *host) |
178 | { | 176 | { |
179 | struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); | ||
180 | |||
181 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | | 177 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | |
182 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); | 178 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); |
183 | msleep(10); | 179 | msleep(10); |
184 | 180 | ||
185 | /* implicit BUG_ON(!res) */ | 181 | /* implicit BUG_ON(!res) */ |
186 | if (resource_size(res) > 0x100) { | 182 | if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) { |
187 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); | 183 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); |
188 | msleep(10); | 184 | msleep(10); |
189 | } | 185 | } |
@@ -191,16 +187,14 @@ static void tmio_mmc_clk_start(struct tmio_mmc_host *host) | |||
191 | 187 | ||
192 | static void tmio_mmc_reset(struct tmio_mmc_host *host) | 188 | static void tmio_mmc_reset(struct tmio_mmc_host *host) |
193 | { | 189 | { |
194 | struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); | ||
195 | |||
196 | /* FIXME - should we set stop clock reg here */ | 190 | /* FIXME - should we set stop clock reg here */ |
197 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); | 191 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); |
198 | /* implicit BUG_ON(!res) */ | 192 | /* implicit BUG_ON(!res) */ |
199 | if (resource_size(res) > 0x100) | 193 | if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) |
200 | sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000); | 194 | sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000); |
201 | msleep(10); | 195 | msleep(10); |
202 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); | 196 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); |
203 | if (resource_size(res) > 0x100) | 197 | if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) |
204 | sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001); | 198 | sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001); |
205 | msleep(10); | 199 | msleep(10); |
206 | } | 200 | } |
@@ -944,17 +938,25 @@ static const struct mmc_host_ops tmio_mmc_ops = { | |||
944 | .enable_sdio_irq = tmio_mmc_enable_sdio_irq, | 938 | .enable_sdio_irq = tmio_mmc_enable_sdio_irq, |
945 | }; | 939 | }; |
946 | 940 | ||
947 | static void tmio_mmc_init_ocr(struct tmio_mmc_host *host) | 941 | static int tmio_mmc_init_ocr(struct tmio_mmc_host *host) |
948 | { | 942 | { |
949 | struct tmio_mmc_data *pdata = host->pdata; | 943 | struct tmio_mmc_data *pdata = host->pdata; |
950 | struct mmc_host *mmc = host->mmc; | 944 | struct mmc_host *mmc = host->mmc; |
951 | 945 | ||
952 | mmc_regulator_get_supply(mmc); | 946 | mmc_regulator_get_supply(mmc); |
953 | 947 | ||
948 | /* use ocr_mask if no regulator */ | ||
954 | if (!mmc->ocr_avail) | 949 | if (!mmc->ocr_avail) |
955 | mmc->ocr_avail = pdata->ocr_mask ? : MMC_VDD_32_33 | MMC_VDD_33_34; | 950 | mmc->ocr_avail = pdata->ocr_mask; |
956 | else if (pdata->ocr_mask) | 951 | |
957 | dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); | 952 | /* |
953 | * try again. | ||
954 | * There is possibility that regulator has not been probed | ||
955 | */ | ||
956 | if (!mmc->ocr_avail) | ||
957 | return -EPROBE_DEFER; | ||
958 | |||
959 | return 0; | ||
958 | } | 960 | } |
959 | 961 | ||
960 | static void tmio_mmc_of_parse(struct platform_device *pdev, | 962 | static void tmio_mmc_of_parse(struct platform_device *pdev, |
@@ -1005,8 +1007,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
1005 | _host->set_pwr = pdata->set_pwr; | 1007 | _host->set_pwr = pdata->set_pwr; |
1006 | _host->set_clk_div = pdata->set_clk_div; | 1008 | _host->set_clk_div = pdata->set_clk_div; |
1007 | 1009 | ||
1008 | /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ | 1010 | ret = tmio_mmc_init_ocr(_host); |
1009 | _host->bus_shift = resource_size(res_ctl) >> 10; | 1011 | if (ret < 0) |
1012 | goto host_free; | ||
1010 | 1013 | ||
1011 | _host->ctl = ioremap(res_ctl->start, resource_size(res_ctl)); | 1014 | _host->ctl = ioremap(res_ctl->start, resource_size(res_ctl)); |
1012 | if (!_host->ctl) { | 1015 | if (!_host->ctl) { |
@@ -1016,14 +1019,13 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
1016 | 1019 | ||
1017 | mmc->ops = &tmio_mmc_ops; | 1020 | mmc->ops = &tmio_mmc_ops; |
1018 | mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; | 1021 | mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; |
1019 | mmc->caps2 = pdata->capabilities2; | 1022 | mmc->caps2 |= pdata->capabilities2; |
1020 | mmc->max_segs = 32; | 1023 | mmc->max_segs = 32; |
1021 | mmc->max_blk_size = 512; | 1024 | mmc->max_blk_size = 512; |
1022 | mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) * | 1025 | mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) * |
1023 | mmc->max_segs; | 1026 | mmc->max_segs; |
1024 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1027 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
1025 | mmc->max_seg_size = mmc->max_req_size; | 1028 | mmc->max_seg_size = mmc->max_req_size; |
1026 | tmio_mmc_init_ocr(_host); | ||
1027 | 1029 | ||
1028 | _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD || | 1030 | _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD || |
1029 | mmc->caps & MMC_CAP_NEEDS_POLL || | 1031 | mmc->caps & MMC_CAP_NEEDS_POLL || |
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index b22883d60500..8f6f2e91e7ae 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h | |||
@@ -76,6 +76,13 @@ | |||
76 | */ | 76 | */ |
77 | #define TMIO_MMC_USE_GPIO_CD (1 << 5) | 77 | #define TMIO_MMC_USE_GPIO_CD (1 << 5) |
78 | 78 | ||
79 | /* | ||
80 | * Some controllers doesn't have over 0x100 register. | ||
81 | * it is used to checking accessibility of | ||
82 | * CTL_SD_CARD_CLK_CTL / CTL_CLK_AND_WAIT_CTL | ||
83 | */ | ||
84 | #define TMIO_MMC_HAVE_HIGH_REG (1 << 6) | ||
85 | |||
79 | int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); | 86 | int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); |
80 | int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); | 87 | int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); |
81 | void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state); | 88 | void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state); |
@@ -102,6 +109,7 @@ struct tmio_mmc_data { | |||
102 | unsigned long capabilities; | 109 | unsigned long capabilities; |
103 | unsigned long capabilities2; | 110 | unsigned long capabilities2; |
104 | unsigned long flags; | 111 | unsigned long flags; |
112 | unsigned long bus_shift; | ||
105 | u32 ocr_mask; /* available voltages */ | 113 | u32 ocr_mask; /* available voltages */ |
106 | struct tmio_mmc_dma *dma; | 114 | struct tmio_mmc_dma *dma; |
107 | struct device *dev; | 115 | struct device *dev; |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 176fdf824b14..b73027298b3a 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -271,9 +271,10 @@ struct mmc_card { | |||
271 | #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */ | 271 | #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */ |
272 | #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ | 272 | #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ |
273 | #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ | 273 | #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ |
274 | /* byte mode */ | ||
274 | #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ | 275 | #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ |
275 | #define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ | 276 | #define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ |
276 | /* byte mode */ | 277 | #define MMC_QUIRK_BROKEN_IRQ_POLLING (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */ |
277 | 278 | ||
278 | unsigned int erase_size; /* erase size in sectors */ | 279 | unsigned int erase_size; /* erase size in sectors */ |
279 | unsigned int erase_shift; /* if erase unit is power 2 */ | 280 | unsigned int erase_shift; /* if erase unit is power 2 */ |
@@ -505,6 +506,11 @@ static inline int mmc_card_long_read_time(const struct mmc_card *c) | |||
505 | return c->quirks & MMC_QUIRK_LONG_READ_TIME; | 506 | return c->quirks & MMC_QUIRK_LONG_READ_TIME; |
506 | } | 507 | } |
507 | 508 | ||
509 | static inline int mmc_card_broken_irq_polling(const struct mmc_card *c) | ||
510 | { | ||
511 | return c->quirks & MMC_QUIRK_BROKEN_IRQ_POLLING; | ||
512 | } | ||
513 | |||
508 | #define mmc_card_name(c) ((c)->cid.prod_name) | 514 | #define mmc_card_name(c) ((c)->cid.prod_name) |
509 | #define mmc_card_id(c) (dev_name(&(c)->dev)) | 515 | #define mmc_card_id(c) (dev_name(&(c)->dev)) |
510 | 516 | ||
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 3e781b8c0be7..362927c48f97 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h | |||
@@ -98,6 +98,8 @@ struct sdhci_host { | |||
98 | #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) | 98 | #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) |
99 | /* Controller has a non-standard host control register */ | 99 | /* Controller has a non-standard host control register */ |
100 | #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) | 100 | #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) |
101 | /* Controller does not support HS200 */ | ||
102 | #define SDHCI_QUIRK2_BROKEN_HS200 (1<<6) | ||
101 | 103 | ||
102 | int irq; /* Device IRQ */ | 104 | int irq; /* Device IRQ */ |
103 | void __iomem *ioaddr; /* Mapped address */ | 105 | void __iomem *ioaddr; /* Mapped address */ |
diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h index a1c1f321e519..84d9053b5dca 100644 --- a/include/linux/mmc/tmio.h +++ b/include/linux/mmc/tmio.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define CTL_SDIO_IRQ_MASK 0x38 | 33 | #define CTL_SDIO_IRQ_MASK 0x38 |
34 | #define CTL_DMA_ENABLE 0xd8 | 34 | #define CTL_DMA_ENABLE 0xd8 |
35 | #define CTL_RESET_SD 0xe0 | 35 | #define CTL_RESET_SD 0xe0 |
36 | #define CTL_VERSION 0xe2 | ||
36 | #define CTL_SDIO_REGS 0x100 | 37 | #define CTL_SDIO_REGS 0x100 |
37 | #define CTL_CLK_AND_WAIT_CTL 0x138 | 38 | #define CTL_CLK_AND_WAIT_CTL 0x138 |
38 | #define CTL_RESET_SDIO 0x1e0 | 39 | #define CTL_RESET_SDIO 0x1e0 |