diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-03 15:17:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-03 15:17:25 -0400 |
commit | dc73d6a8d42d208c027b4bcca59a77d045895977 (patch) | |
tree | 1c6e135caa45d2e085ec0e5b106459a73359905c | |
parent | dabe51840e2790aa7e66c53990d15c663b0d628a (diff) | |
parent | 4472f0fc248e3f0573301f725eff9dc9cde5cb62 (diff) |
Merge tag 'mmc-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"MMC core:
- Export host capabilities through debugfs
- Export card RCA register via sysfs
- Improve card initializing sequence while enabling 4-bit bus
- Export a function to enable/disable wakeup for card detect IRQ
MMC host:
- dw_mmc: Add support for new hi3798cv200 variant
- dw_mmc: Remove support for some deprecated DT properties
- mediatek: Add support for new variant used on MT7622 SoC
- sdhci: Improve wakeup support for SDIO IRQs
- sdhci: Improve wakeup support for card detect IRQs
- sdhci-omap: Add tuning support
- sdhci_omap: Add UHS-I mode support
- sunxi: Prepare for runtime PM support via a few re-factorings
- tmio: deprecate "toshiba,mmc-wrprotect-disable" DT property
- tmio/renesas_sdhi: Consolidate code supporting write protect
- tmio: Improve DMA vs PIO handling
- tmio: Add support for IP-builtin card detection logic"
* tag 'mmc-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (55 commits)
mmc: renesas_sdhi: replace EXT_ACC with HOST_MODE
mmc: update sdio_claim_irq documentation
mmc: Export host capabilities to debugfs.
mmc: core: Disable HPI for certain Micron (Numonyx) eMMC cards
mmc: block: fix updating ext_csd caches on ioctl call
mmc: sunxi: Set our device drvdata earlier
mmc: sunxi: Move the reset deassertion before enabling the clocks
mmc: sunxi: Move resources management to separate functions
mmc: dw_mmc: add support for hi3798cv200 specific extensions of dw-mshc
dt-bindings: mmc: add bindings for hi3798cv200-dw-mshc
mmc: core: Export card RCA register via sysfs
mmc: renesas_sdhi: fix WP detection
mmc: core: Use memdup_user() rather than duplicating its implementation
mmc: dw_mmc-rockchip: correct property names in debug
mmc: sd: Remove redundant err assignment from mmc_read_switch
mmc: sdio: Check the return value of sdio_enable_4bit_bus
mmc: core: Don't try UHS-I mode if 4-bit mode isn't supported
arm64: dts: hi3660: remove 'num-slots' property for dwmmc
ARM: dts: lpc18xx: remove 'num-slots' property for dwmmc
arm64: dts: stratix10: remove 'num-slots' property for dwmmc
...
42 files changed, 885 insertions, 277 deletions
diff --git a/Documentation/devicetree/bindings/mmc/hi3798cv200-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/hi3798cv200-dw-mshc.txt new file mode 100644 index 000000000000..a0693b7145f2 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/hi3798cv200-dw-mshc.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | * Hisilicon Hi3798CV200 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 Hi3798CV200 | ||
10 | specific extensions to the Synopsys Designware Mobile Storage Host Controller. | ||
11 | |||
12 | Required Properties: | ||
13 | - compatible: Should contain "hisilicon,hi3798cv200-dw-mshc". | ||
14 | - clocks: A list of phandle + clock-specifier pairs for the clocks listed | ||
15 | in clock-names. | ||
16 | - clock-names: Should contain the following: | ||
17 | "ciu" - The ciu clock described in synopsys-dw-mshc.txt. | ||
18 | "biu" - The biu clock described in synopsys-dw-mshc.txt. | ||
19 | "ciu-sample" - Hi3798CV200 extended phase clock for ciu sampling. | ||
20 | "ciu-drive" - Hi3798CV200 extended phase clock for ciu driving. | ||
21 | |||
22 | Example: | ||
23 | |||
24 | emmc: mmc@9830000 { | ||
25 | compatible = "hisilicon,hi3798cv200-dw-mshc"; | ||
26 | reg = <0x9830000 0x10000>; | ||
27 | interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; | ||
28 | clocks = <&crg HISTB_MMC_CIU_CLK>, | ||
29 | <&crg HISTB_MMC_BIU_CLK>, | ||
30 | <&crg HISTB_MMC_SAMPLE_CLK>, | ||
31 | <&crg HISTB_MMC_DRV_CLK>; | ||
32 | clock-names = "ciu", "biu", "ciu-sample", "ciu-drive"; | ||
33 | fifo-depth = <256>; | ||
34 | clock-frequency = <200000000>; | ||
35 | cap-mmc-highspeed; | ||
36 | mmc-ddr-1_8v; | ||
37 | mmc-hs200-1_8v; | ||
38 | non-removable; | ||
39 | bus-width = <8>; | ||
40 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt index 9b8017670870..f33467a54a05 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt | |||
@@ -12,6 +12,7 @@ Required properties: | |||
12 | "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 | 12 | "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 |
13 | "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 | 13 | "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 |
14 | "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 | 14 | "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 |
15 | "mediatek,mt7622-mmc": for MT7622 SoC | ||
15 | "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC | 16 | "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC |
16 | 17 | ||
17 | - reg: physical base address of the controller and length | 18 | - reg: physical base address of the controller and length |
diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt index ef3e5f14067a..7e5e427a22ce 100644 --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | |||
@@ -59,15 +59,6 @@ Optional properties: | |||
59 | is specified and the ciu clock is specified then we'll try to set the ciu | 59 | is specified and the ciu clock is specified then we'll try to set the ciu |
60 | clock to this at probe time. | 60 | clock to this at probe time. |
61 | 61 | ||
62 | * clock-freq-min-max (DEPRECATED): Minimum and Maximum clock frequency for card output | ||
63 | clock(cclk_out). If it's not specified, max is 200MHZ and min is 400KHz by default. | ||
64 | (Use the "max-frequency" instead of "clock-freq-min-max".) | ||
65 | |||
66 | * num-slots (DEPRECATED): specifies the number of slots supported by the controller. | ||
67 | The number of physical slots actually used could be equal or less than the | ||
68 | value specified by num-slots. If this property is not specified, the value | ||
69 | of num-slot property is assumed to be 1. | ||
70 | |||
71 | * fifo-depth: The maximum size of the tx/rx fifo's. If this property is not | 62 | * fifo-depth: The maximum size of the tx/rx fifo's. If this property is not |
72 | specified, the default value of the fifo size is determined from the | 63 | specified, the default value of the fifo size is determined from the |
73 | controller registers. | 64 | controller registers. |
diff --git a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt index d8685cb83325..2d5287eeed95 100644 --- a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt +++ b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt | |||
@@ -50,7 +50,6 @@ Required properties: | |||
50 | 2: R7S72100 | 50 | 2: R7S72100 |
51 | 51 | ||
52 | Optional properties: | 52 | Optional properties: |
53 | - toshiba,mmc-wrprotect-disable: write-protect detection is unavailable | ||
54 | - pinctrl-names: should be "default", "state_uhs" | 53 | - pinctrl-names: should be "default", "state_uhs" |
55 | - pinctrl-0: should contain default/high speed pin ctrl | 54 | - pinctrl-0: should contain default/high speed pin ctrl |
56 | - pinctrl-1: should contain uhs mode pin ctrl | 55 | - pinctrl-1: should contain uhs mode pin ctrl |
diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index 7cae9c5e27db..10b8249b8ab6 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi | |||
@@ -115,7 +115,6 @@ | |||
115 | compatible = "snps,dw-mshc"; | 115 | compatible = "snps,dw-mshc"; |
116 | reg = <0x40004000 0x1000>; | 116 | reg = <0x40004000 0x1000>; |
117 | interrupts = <6>; | 117 | interrupts = <6>; |
118 | num-slots = <1>; | ||
119 | clocks = <&ccu2 CLK_SDIO>, <&ccu1 CLK_CPU_SDIO>; | 118 | clocks = <&ccu2 CLK_SDIO>, <&ccu1 CLK_CPU_SDIO>; |
120 | clock-names = "ciu", "biu"; | 119 | clock-names = "ciu", "biu"; |
121 | resets = <&rgu 20>; | 120 | resets = <&rgu 20>; |
diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts index 040a164ba148..5822fd2085db 100644 --- a/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts +++ b/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts | |||
@@ -20,7 +20,6 @@ | |||
20 | 20 | ||
21 | &mmc { | 21 | &mmc { |
22 | status = "okay"; | 22 | status = "okay"; |
23 | num-slots = <1>; | ||
24 | cap-sd-highspeed; | 23 | cap-sd-highspeed; |
25 | broken-cd; | 24 | broken-cd; |
26 | bus-width = <4>; | 25 | bus-width = <4>; |
diff --git a/arch/arm/boot/dts/socfpga_arria5.dtsi b/arch/arm/boot/dts/socfpga_arria5.dtsi index 8c037297296c..e59461f5416e 100644 --- a/arch/arm/boot/dts/socfpga_arria5.dtsi +++ b/arch/arm/boot/dts/socfpga_arria5.dtsi | |||
@@ -30,7 +30,6 @@ | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | mmc0: dwmmc0@ff704000 { | 32 | mmc0: dwmmc0@ff704000 { |
33 | num-slots = <1>; | ||
34 | broken-cd; | 33 | broken-cd; |
35 | bus-width = <4>; | 34 | bus-width = <4>; |
36 | cap-mmc-highspeed; | 35 | cap-mmc-highspeed; |
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dtsi b/arch/arm/boot/dts/socfpga_cyclone5.dtsi index a05e3df23103..68ced67f8bfb 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5.dtsi +++ b/arch/arm/boot/dts/socfpga_cyclone5.dtsi | |||
@@ -31,7 +31,6 @@ | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | mmc0: dwmmc0@ff704000 { | 33 | mmc0: dwmmc0@ff704000 { |
34 | num-slots = <1>; | ||
35 | broken-cd; | 34 | broken-cd; |
36 | bus-width = <4>; | 35 | bus-width = <4>; |
37 | cap-mmc-highspeed; | 36 | cap-mmc-highspeed; |
diff --git a/arch/arm/boot/dts/socfpga_vt.dts b/arch/arm/boot/dts/socfpga_vt.dts index dfe2193cd4d5..547c38632c68 100644 --- a/arch/arm/boot/dts/socfpga_vt.dts +++ b/arch/arm/boot/dts/socfpga_vt.dts | |||
@@ -42,7 +42,6 @@ | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | dwmmc0@ff704000 { | 44 | dwmmc0@ff704000 { |
45 | num-slots = <1>; | ||
46 | broken-cd; | 45 | broken-cd; |
47 | bus-width = <4>; | 46 | bus-width = <4>; |
48 | cap-mmc-highspeed; | 47 | cap-mmc-highspeed; |
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts index 000756429b77..51ce5832ee1d 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts | |||
@@ -88,7 +88,6 @@ | |||
88 | 88 | ||
89 | &mmc { | 89 | &mmc { |
90 | status = "okay"; | 90 | status = "okay"; |
91 | num-slots = <1>; | ||
92 | cap-sd-highspeed; | 91 | cap-sd-highspeed; |
93 | broken-cd; | 92 | broken-cd; |
94 | bus-width = <4>; | 93 | bus-width = <4>; |
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi index 63d4f9dca77f..a7ecd9074ea2 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi | |||
@@ -922,7 +922,6 @@ | |||
922 | #size-cells = <0>; | 922 | #size-cells = <0>; |
923 | cd-inverted; | 923 | cd-inverted; |
924 | compatible = "hisilicon,hi3660-dw-mshc"; | 924 | compatible = "hisilicon,hi3660-dw-mshc"; |
925 | num-slots = <1>; | ||
926 | bus-width = <0x4>; | 925 | bus-width = <0x4>; |
927 | disable-wp; | 926 | disable-wp; |
928 | cap-sd-highspeed; | 927 | cap-sd-highspeed; |
@@ -960,7 +959,6 @@ | |||
960 | compatible = "hisilicon,hi3660-dw-mshc"; | 959 | compatible = "hisilicon,hi3660-dw-mshc"; |
961 | reg = <0x0 0xff3ff000 0x0 0x1000>; | 960 | reg = <0x0 0xff3ff000 0x0 0x1000>; |
962 | interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>; | 961 | interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>; |
963 | num-slots = <1>; | ||
964 | clocks = <&crg_ctrl HI3660_CLK_GATE_SDIO0>, | 962 | clocks = <&crg_ctrl HI3660_CLK_GATE_SDIO0>, |
965 | <&crg_ctrl HI3660_HCLK_GATE_SDIO0>; | 963 | <&crg_ctrl HI3660_HCLK_GATE_SDIO0>; |
966 | clock-names = "ciu", "biu"; | 964 | clock-names = "ciu", "biu"; |
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 5deb2d82f19f..6af7777332fc 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c | |||
@@ -375,8 +375,8 @@ static struct resource kfr2r09_sh_sdhi0_resources[] = { | |||
375 | static struct tmio_mmc_data sh7724_sdhi0_data = { | 375 | static struct tmio_mmc_data sh7724_sdhi0_data = { |
376 | .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX, | 376 | .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX, |
377 | .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX, | 377 | .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX, |
378 | .flags = TMIO_MMC_WRPROTECT_DISABLE, | ||
379 | .capabilities = MMC_CAP_SDIO_IRQ, | 378 | .capabilities = MMC_CAP_SDIO_IRQ, |
379 | .capabilities2 = MMC_CAP2_NO_WRITE_PROTECT, | ||
380 | }; | 380 | }; |
381 | 381 | ||
382 | static struct platform_device kfr2r09_sh_sdhi0_device = { | 382 | static struct platform_device kfr2r09_sh_sdhi0_device = { |
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 2cfb963d9f37..a2b9c2500c4c 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c | |||
@@ -376,22 +376,15 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user( | |||
376 | return idata; | 376 | return idata; |
377 | } | 377 | } |
378 | 378 | ||
379 | idata->buf = kmalloc(idata->buf_bytes, GFP_KERNEL); | 379 | idata->buf = memdup_user((void __user *)(unsigned long) |
380 | if (!idata->buf) { | 380 | idata->ic.data_ptr, idata->buf_bytes); |
381 | err = -ENOMEM; | 381 | if (IS_ERR(idata->buf)) { |
382 | err = PTR_ERR(idata->buf); | ||
382 | goto idata_err; | 383 | goto idata_err; |
383 | } | 384 | } |
384 | 385 | ||
385 | if (copy_from_user(idata->buf, (void __user *)(unsigned long) | ||
386 | idata->ic.data_ptr, idata->buf_bytes)) { | ||
387 | err = -EFAULT; | ||
388 | goto copy_err; | ||
389 | } | ||
390 | |||
391 | return idata; | 386 | return idata; |
392 | 387 | ||
393 | copy_err: | ||
394 | kfree(idata->buf); | ||
395 | idata_err: | 388 | idata_err: |
396 | kfree(idata); | 389 | kfree(idata); |
397 | out: | 390 | out: |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index c0ba6d8823b7..121ce50b6d5e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -2369,7 +2369,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) | |||
2369 | return card->pref_erase; | 2369 | return card->pref_erase; |
2370 | 2370 | ||
2371 | max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG); | 2371 | max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG); |
2372 | if (mmc_can_trim(card)) { | 2372 | if (max_discard && mmc_can_trim(card)) { |
2373 | max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG); | 2373 | max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG); |
2374 | if (max_trim < max_discard) | 2374 | if (max_trim < max_discard) |
2375 | max_discard = max_trim; | 2375 | max_discard = max_trim; |
@@ -2655,8 +2655,7 @@ void mmc_start_host(struct mmc_host *host) | |||
2655 | void mmc_stop_host(struct mmc_host *host) | 2655 | void mmc_stop_host(struct mmc_host *host) |
2656 | { | 2656 | { |
2657 | if (host->slot.cd_irq >= 0) { | 2657 | if (host->slot.cd_irq >= 0) { |
2658 | if (host->slot.cd_wake_enabled) | 2658 | mmc_gpio_set_cd_wake(host, false); |
2659 | disable_irq_wake(host->slot.cd_irq); | ||
2660 | disable_irq(host->slot.cd_irq); | 2659 | disable_irq(host->slot.cd_irq); |
2661 | } | 2660 | } |
2662 | 2661 | ||
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 0f4a7d7b2626..d2275c5a2311 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c | |||
@@ -196,18 +196,7 @@ static int mmc_ios_show(struct seq_file *s, void *data) | |||
196 | 196 | ||
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | 199 | DEFINE_SHOW_ATTRIBUTE(mmc_ios); | |
200 | static int mmc_ios_open(struct inode *inode, struct file *file) | ||
201 | { | ||
202 | return single_open(file, mmc_ios_show, inode->i_private); | ||
203 | } | ||
204 | |||
205 | static const struct file_operations mmc_ios_fops = { | ||
206 | .open = mmc_ios_open, | ||
207 | .read = seq_read, | ||
208 | .llseek = seq_lseek, | ||
209 | .release = single_release, | ||
210 | }; | ||
211 | 200 | ||
212 | static int mmc_clock_opt_get(void *data, u64 *val) | 201 | static int mmc_clock_opt_get(void *data, u64 *val) |
213 | { | 202 | { |
@@ -254,6 +243,12 @@ void mmc_add_host_debugfs(struct mmc_host *host) | |||
254 | if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) | 243 | if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) |
255 | goto err_node; | 244 | goto err_node; |
256 | 245 | ||
246 | if (!debugfs_create_x32("caps", S_IRUSR, root, &host->caps)) | ||
247 | goto err_node; | ||
248 | |||
249 | if (!debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2)) | ||
250 | goto err_node; | ||
251 | |||
257 | if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, | 252 | if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, |
258 | &mmc_clock_fops)) | 253 | &mmc_clock_fops)) |
259 | goto err_node; | 254 | goto err_node; |
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index 06ec19b5bf9f..4805438c02ff 100644 --- a/drivers/mmc/core/host.h +++ b/drivers/mmc/core/host.h | |||
@@ -56,7 +56,8 @@ static inline int mmc_host_uhs(struct mmc_host *host) | |||
56 | return host->caps & | 56 | return host->caps & |
57 | (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | | 57 | (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | |
58 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | | 58 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | |
59 | MMC_CAP_UHS_DDR50); | 59 | MMC_CAP_UHS_DDR50) && |
60 | host->caps & MMC_CAP_4_BIT_DATA; | ||
60 | } | 61 | } |
61 | 62 | ||
62 | static inline bool mmc_card_hs200(struct mmc_card *card) | 63 | static inline bool mmc_card_hs200(struct mmc_card *card) |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 208a762b87ef..6f8ebd6caa4c 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -792,6 +792,7 @@ MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); | |||
792 | MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); | 792 | MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); |
793 | MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); | 793 | MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); |
794 | MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); | 794 | MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); |
795 | MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); | ||
795 | MMC_DEV_ATTR(cmdq_en, "%d\n", card->ext_csd.cmdq_en); | 796 | MMC_DEV_ATTR(cmdq_en, "%d\n", card->ext_csd.cmdq_en); |
796 | 797 | ||
797 | static ssize_t mmc_fwrev_show(struct device *dev, | 798 | static ssize_t mmc_fwrev_show(struct device *dev, |
@@ -848,6 +849,7 @@ static struct attribute *mmc_std_attrs[] = { | |||
848 | &dev_attr_raw_rpmb_size_mult.attr, | 849 | &dev_attr_raw_rpmb_size_mult.attr, |
849 | &dev_attr_rel_sectors.attr, | 850 | &dev_attr_rel_sectors.attr, |
850 | &dev_attr_ocr.attr, | 851 | &dev_attr_ocr.attr, |
852 | &dev_attr_rca.attr, | ||
851 | &dev_attr_dsr.attr, | 853 | &dev_attr_dsr.attr, |
852 | &dev_attr_cmdq_en.attr, | 854 | &dev_attr_cmdq_en.attr, |
853 | NULL, | 855 | NULL, |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 62b84dd8f9fe..baf3d5da4ccb 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -291,8 +291,6 @@ static int mmc_read_switch(struct mmc_card *card) | |||
291 | return 0; | 291 | return 0; |
292 | } | 292 | } |
293 | 293 | ||
294 | err = -EIO; | ||
295 | |||
296 | status = kmalloc(64, GFP_KERNEL); | 294 | status = kmalloc(64, GFP_KERNEL); |
297 | if (!status) | 295 | if (!status) |
298 | return -ENOMEM; | 296 | return -ENOMEM; |
@@ -582,9 +580,6 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) | |||
582 | int err; | 580 | int err; |
583 | u8 *status; | 581 | u8 *status; |
584 | 582 | ||
585 | if (!card->scr.sda_spec3) | ||
586 | return 0; | ||
587 | |||
588 | if (!(card->csd.cmdclass & CCC_SWITCH)) | 583 | if (!(card->csd.cmdclass & CCC_SWITCH)) |
589 | return 0; | 584 | return 0; |
590 | 585 | ||
@@ -593,14 +588,11 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) | |||
593 | return -ENOMEM; | 588 | return -ENOMEM; |
594 | 589 | ||
595 | /* Set 4-bit bus width */ | 590 | /* Set 4-bit bus width */ |
596 | if ((card->host->caps & MMC_CAP_4_BIT_DATA) && | 591 | err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); |
597 | (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { | 592 | if (err) |
598 | err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); | 593 | goto out; |
599 | if (err) | ||
600 | goto out; | ||
601 | 594 | ||
602 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | 595 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); |
603 | } | ||
604 | 596 | ||
605 | /* | 597 | /* |
606 | * Select the bus speed mode depending on host | 598 | * Select the bus speed mode depending on host |
@@ -676,6 +668,7 @@ MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); | |||
676 | MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); | 668 | MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); |
677 | MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); | 669 | MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); |
678 | MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); | 670 | MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); |
671 | MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); | ||
679 | 672 | ||
680 | 673 | ||
681 | static ssize_t mmc_dsr_show(struct device *dev, | 674 | static ssize_t mmc_dsr_show(struct device *dev, |
@@ -709,6 +702,7 @@ static struct attribute *sd_std_attrs[] = { | |||
709 | &dev_attr_oemid.attr, | 702 | &dev_attr_oemid.attr, |
710 | &dev_attr_serial.attr, | 703 | &dev_attr_serial.attr, |
711 | &dev_attr_ocr.attr, | 704 | &dev_attr_ocr.attr, |
705 | &dev_attr_rca.attr, | ||
712 | &dev_attr_dsr.attr, | 706 | &dev_attr_dsr.attr, |
713 | NULL, | 707 | NULL, |
714 | }; | 708 | }; |
@@ -1033,7 +1027,7 @@ retry: | |||
1033 | } | 1027 | } |
1034 | 1028 | ||
1035 | /* Initialization sequence for UHS-I cards */ | 1029 | /* Initialization sequence for UHS-I cards */ |
1036 | if (rocr & SD_ROCR_S18A) { | 1030 | if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { |
1037 | err = mmc_sd_init_uhs_card(card); | 1031 | err = mmc_sd_init_uhs_card(card); |
1038 | if (err) | 1032 | if (err) |
1039 | goto free_card; | 1033 | goto free_card; |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index cc43687ca241..c599a628a387 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -518,11 +518,10 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) | |||
518 | if (!card->scr.sda_spec3) | 518 | if (!card->scr.sda_spec3) |
519 | return 0; | 519 | return 0; |
520 | 520 | ||
521 | /* | 521 | /* Switch to wider bus */ |
522 | * Switch to wider bus (if supported). | 522 | err = sdio_enable_4bit_bus(card); |
523 | */ | 523 | if (err) |
524 | if (card->host->caps & MMC_CAP_4_BIT_DATA) | 524 | goto out; |
525 | err = sdio_enable_4bit_bus(card); | ||
526 | 525 | ||
527 | /* Set the driver strength for the card */ | 526 | /* Set the driver strength for the card */ |
528 | sdio_select_driver_type(card); | 527 | sdio_select_driver_type(card); |
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 7a2eaf8410a3..7ca7b99413f0 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c | |||
@@ -277,8 +277,8 @@ static void sdio_single_irq_set(struct mmc_card *card) | |||
277 | * | 277 | * |
278 | * Claim and activate the IRQ for the given SDIO function. The provided | 278 | * Claim and activate the IRQ for the given SDIO function. The provided |
279 | * handler will be called when that IRQ is asserted. The host is always | 279 | * handler will be called when that IRQ is asserted. The host is always |
280 | * claimed already when the handler is called so the handler must not | 280 | * claimed already when the handler is called so the handler should not |
281 | * call sdio_claim_host() nor sdio_release_host(). | 281 | * call sdio_claim_host() or sdio_release_host(). |
282 | */ | 282 | */ |
283 | int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) | 283 | int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) |
284 | { | 284 | { |
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 3698b0576009..31f7dbb15668 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c | |||
@@ -149,11 +149,30 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host) | |||
149 | 149 | ||
150 | if (irq < 0) | 150 | if (irq < 0) |
151 | host->caps |= MMC_CAP_NEEDS_POLL; | 151 | host->caps |= MMC_CAP_NEEDS_POLL; |
152 | else if ((host->caps & MMC_CAP_CD_WAKE) && !enable_irq_wake(irq)) | ||
153 | host->slot.cd_wake_enabled = true; | ||
154 | } | 152 | } |
155 | EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); | 153 | EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); |
156 | 154 | ||
155 | int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on) | ||
156 | { | ||
157 | int ret = 0; | ||
158 | |||
159 | if (!(host->caps & MMC_CAP_CD_WAKE) || | ||
160 | host->slot.cd_irq < 0 || | ||
161 | on == host->slot.cd_wake_enabled) | ||
162 | return 0; | ||
163 | |||
164 | if (on) { | ||
165 | ret = enable_irq_wake(host->slot.cd_irq); | ||
166 | host->slot.cd_wake_enabled = !ret; | ||
167 | } else { | ||
168 | disable_irq_wake(host->slot.cd_irq); | ||
169 | host->slot.cd_wake_enabled = false; | ||
170 | } | ||
171 | |||
172 | return ret; | ||
173 | } | ||
174 | EXPORT_SYMBOL(mmc_gpio_set_cd_wake); | ||
175 | |||
157 | /* Register an alternate interrupt service routine for | 176 | /* Register an alternate interrupt service routine for |
158 | * the card-detect GPIO. | 177 | * the card-detect GPIO. |
159 | */ | 178 | */ |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index b4fd5d48dd35..9589f9c9046f 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -699,6 +699,15 @@ config MMC_DW_EXYNOS | |||
699 | Synopsys DesignWare Memory Card Interface driver. Select this option | 699 | Synopsys DesignWare Memory Card Interface driver. Select this option |
700 | for platforms based on Exynos4 and Exynos5 SoC's. | 700 | for platforms based on Exynos4 and Exynos5 SoC's. |
701 | 701 | ||
702 | config MMC_DW_HI3798CV200 | ||
703 | tristate "Hi3798CV200 specific extensions for Synopsys DW Memory Card Interface" | ||
704 | depends on MMC_DW | ||
705 | select MMC_DW_PLTFM | ||
706 | help | ||
707 | This selects support for HiSilicon Hi3798CV200 SoC specific extensions to the | ||
708 | Synopsys DesignWare Memory Card Interface driver. Select this option | ||
709 | for platforms based on HiSilicon Hi3798CV200 SoC. | ||
710 | |||
702 | config MMC_DW_K3 | 711 | config MMC_DW_K3 |
703 | tristate "K3 specific extensions for Synopsys DW Memory Card Interface" | 712 | tristate "K3 specific extensions for Synopsys DW Memory Card Interface" |
704 | depends on MMC_DW | 713 | depends on MMC_DW |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index f563cc0b7f93..6aead24879b4 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -50,6 +50,7 @@ obj-$(CONFIG_MMC_CAVIUM_THUNDERX) += thunderx-mmc.o | |||
50 | obj-$(CONFIG_MMC_DW) += dw_mmc.o | 50 | obj-$(CONFIG_MMC_DW) += dw_mmc.o |
51 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o | 51 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o |
52 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o | 52 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o |
53 | obj-$(CONFIG_MMC_DW_HI3798CV200) += dw_mmc-hi3798cv200.o | ||
53 | obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o | 54 | obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o |
54 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o | 55 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o |
55 | obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o | 56 | obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o |
diff --git a/drivers/mmc/host/dw_mmc-hi3798cv200.c b/drivers/mmc/host/dw_mmc-hi3798cv200.c new file mode 100644 index 000000000000..f9b333ff259e --- /dev/null +++ b/drivers/mmc/host/dw_mmc-hi3798cv200.c | |||
@@ -0,0 +1,202 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright (c) 2018 HiSilicon Technologies Co., Ltd. | ||
4 | */ | ||
5 | |||
6 | #include <linux/clk.h> | ||
7 | #include <linux/mfd/syscon.h> | ||
8 | #include <linux/mmc/host.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/of_address.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/pm_runtime.h> | ||
13 | #include <linux/regmap.h> | ||
14 | #include <linux/regulator/consumer.h> | ||
15 | |||
16 | #include "dw_mmc.h" | ||
17 | #include "dw_mmc-pltfm.h" | ||
18 | |||
19 | #define ALL_INT_CLR 0x1ffff | ||
20 | |||
21 | struct hi3798cv200_priv { | ||
22 | struct clk *sample_clk; | ||
23 | struct clk *drive_clk; | ||
24 | }; | ||
25 | |||
26 | static void dw_mci_hi3798cv200_set_ios(struct dw_mci *host, struct mmc_ios *ios) | ||
27 | { | ||
28 | struct hi3798cv200_priv *priv = host->priv; | ||
29 | u32 val; | ||
30 | |||
31 | val = mci_readl(host, UHS_REG); | ||
32 | if (ios->timing == MMC_TIMING_MMC_DDR52 || | ||
33 | ios->timing == MMC_TIMING_UHS_DDR50) | ||
34 | val |= SDMMC_UHS_DDR; | ||
35 | else | ||
36 | val &= ~SDMMC_UHS_DDR; | ||
37 | mci_writel(host, UHS_REG, val); | ||
38 | |||
39 | val = mci_readl(host, ENABLE_SHIFT); | ||
40 | if (ios->timing == MMC_TIMING_MMC_DDR52) | ||
41 | val |= SDMMC_ENABLE_PHASE; | ||
42 | else | ||
43 | val &= ~SDMMC_ENABLE_PHASE; | ||
44 | mci_writel(host, ENABLE_SHIFT, val); | ||
45 | |||
46 | val = mci_readl(host, DDR_REG); | ||
47 | if (ios->timing == MMC_TIMING_MMC_HS400) | ||
48 | val |= SDMMC_DDR_HS400; | ||
49 | else | ||
50 | val &= ~SDMMC_DDR_HS400; | ||
51 | mci_writel(host, DDR_REG, val); | ||
52 | |||
53 | if (ios->timing == MMC_TIMING_MMC_HS || | ||
54 | ios->timing == MMC_TIMING_LEGACY) | ||
55 | clk_set_phase(priv->drive_clk, 180); | ||
56 | else if (ios->timing == MMC_TIMING_MMC_HS200) | ||
57 | clk_set_phase(priv->drive_clk, 135); | ||
58 | } | ||
59 | |||
60 | static int dw_mci_hi3798cv200_execute_tuning(struct dw_mci_slot *slot, | ||
61 | u32 opcode) | ||
62 | { | ||
63 | int degrees[] = { 0, 45, 90, 135, 180, 225, 270, 315 }; | ||
64 | struct dw_mci *host = slot->host; | ||
65 | struct hi3798cv200_priv *priv = host->priv; | ||
66 | int raise_point = -1, fall_point = -1; | ||
67 | int err, prev_err = -1; | ||
68 | int found = 0; | ||
69 | int i; | ||
70 | |||
71 | for (i = 0; i < ARRAY_SIZE(degrees); i++) { | ||
72 | clk_set_phase(priv->sample_clk, degrees[i]); | ||
73 | mci_writel(host, RINTSTS, ALL_INT_CLR); | ||
74 | |||
75 | err = mmc_send_tuning(slot->mmc, opcode, NULL); | ||
76 | if (!err) | ||
77 | found = 1; | ||
78 | |||
79 | if (i > 0) { | ||
80 | if (err && !prev_err) | ||
81 | fall_point = i - 1; | ||
82 | if (!err && prev_err) | ||
83 | raise_point = i; | ||
84 | } | ||
85 | |||
86 | if (raise_point != -1 && fall_point != -1) | ||
87 | goto tuning_out; | ||
88 | |||
89 | prev_err = err; | ||
90 | err = 0; | ||
91 | } | ||
92 | |||
93 | tuning_out: | ||
94 | if (found) { | ||
95 | if (raise_point == -1) | ||
96 | raise_point = 0; | ||
97 | if (fall_point == -1) | ||
98 | fall_point = ARRAY_SIZE(degrees) - 1; | ||
99 | if (fall_point < raise_point) { | ||
100 | if ((raise_point + fall_point) > | ||
101 | (ARRAY_SIZE(degrees) - 1)) | ||
102 | i = fall_point / 2; | ||
103 | else | ||
104 | i = (raise_point + ARRAY_SIZE(degrees) - 1) / 2; | ||
105 | } else { | ||
106 | i = (raise_point + fall_point) / 2; | ||
107 | } | ||
108 | |||
109 | clk_set_phase(priv->sample_clk, degrees[i]); | ||
110 | dev_dbg(host->dev, "Tuning clk_sample[%d, %d], set[%d]\n", | ||
111 | raise_point, fall_point, degrees[i]); | ||
112 | } else { | ||
113 | dev_err(host->dev, "No valid clk_sample shift! use default\n"); | ||
114 | err = -EINVAL; | ||
115 | } | ||
116 | |||
117 | mci_writel(host, RINTSTS, ALL_INT_CLR); | ||
118 | return err; | ||
119 | } | ||
120 | |||
121 | static int dw_mci_hi3798cv200_init(struct dw_mci *host) | ||
122 | { | ||
123 | struct hi3798cv200_priv *priv; | ||
124 | int ret; | ||
125 | |||
126 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | ||
127 | if (!priv) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | priv->sample_clk = devm_clk_get(host->dev, "ciu-sample"); | ||
131 | if (IS_ERR(priv->sample_clk)) { | ||
132 | dev_err(host->dev, "failed to get ciu-sample clock\n"); | ||
133 | return PTR_ERR(priv->sample_clk); | ||
134 | } | ||
135 | |||
136 | priv->drive_clk = devm_clk_get(host->dev, "ciu-drive"); | ||
137 | if (IS_ERR(priv->drive_clk)) { | ||
138 | dev_err(host->dev, "failed to get ciu-drive clock\n"); | ||
139 | return PTR_ERR(priv->drive_clk); | ||
140 | } | ||
141 | |||
142 | ret = clk_prepare_enable(priv->sample_clk); | ||
143 | if (ret) { | ||
144 | dev_err(host->dev, "failed to enable ciu-sample clock\n"); | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | ret = clk_prepare_enable(priv->drive_clk); | ||
149 | if (ret) { | ||
150 | dev_err(host->dev, "failed to enable ciu-drive clock\n"); | ||
151 | goto disable_sample_clk; | ||
152 | } | ||
153 | |||
154 | host->priv = priv; | ||
155 | return 0; | ||
156 | |||
157 | disable_sample_clk: | ||
158 | clk_disable_unprepare(priv->sample_clk); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | static const struct dw_mci_drv_data hi3798cv200_data = { | ||
163 | .init = dw_mci_hi3798cv200_init, | ||
164 | .set_ios = dw_mci_hi3798cv200_set_ios, | ||
165 | .execute_tuning = dw_mci_hi3798cv200_execute_tuning, | ||
166 | }; | ||
167 | |||
168 | static int dw_mci_hi3798cv200_probe(struct platform_device *pdev) | ||
169 | { | ||
170 | return dw_mci_pltfm_register(pdev, &hi3798cv200_data); | ||
171 | } | ||
172 | |||
173 | static int dw_mci_hi3798cv200_remove(struct platform_device *pdev) | ||
174 | { | ||
175 | struct dw_mci *host = platform_get_drvdata(pdev); | ||
176 | struct hi3798cv200_priv *priv = host->priv; | ||
177 | |||
178 | clk_disable_unprepare(priv->drive_clk); | ||
179 | clk_disable_unprepare(priv->sample_clk); | ||
180 | |||
181 | return dw_mci_pltfm_remove(pdev); | ||
182 | } | ||
183 | |||
184 | static const struct of_device_id dw_mci_hi3798cv200_match[] = { | ||
185 | { .compatible = "hisilicon,hi3798cv200-dw-mshc", }, | ||
186 | {}, | ||
187 | }; | ||
188 | |||
189 | MODULE_DEVICE_TABLE(of, dw_mci_hi3798cv200_match); | ||
190 | static struct platform_driver dw_mci_hi3798cv200_driver = { | ||
191 | .probe = dw_mci_hi3798cv200_probe, | ||
192 | .remove = dw_mci_hi3798cv200_remove, | ||
193 | .driver = { | ||
194 | .name = "dwmmc_hi3798cv200", | ||
195 | .of_match_table = dw_mci_hi3798cv200_match, | ||
196 | }, | ||
197 | }; | ||
198 | module_platform_driver(dw_mci_hi3798cv200_driver); | ||
199 | |||
200 | MODULE_DESCRIPTION("HiSilicon Hi3798CV200 Specific DW-MSHC Driver Extension"); | ||
201 | MODULE_LICENSE("GPL v2"); | ||
202 | MODULE_ALIAS("platform:dwmmc_hi3798cv200"); | ||
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c index ab8713297edb..3ad07d7b2c97 100644 --- a/drivers/mmc/host/dw_mmc-pci.c +++ b/drivers/mmc/host/dw_mmc-pci.c | |||
@@ -29,7 +29,6 @@ | |||
29 | MMC_CAP_SDIO_IRQ) | 29 | MMC_CAP_SDIO_IRQ) |
30 | 30 | ||
31 | static struct dw_mci_board pci_board_data = { | 31 | static struct dw_mci_board pci_board_data = { |
32 | .num_slots = 1, | ||
33 | .caps = DW_MCI_CAPABILITIES, | 32 | .caps = DW_MCI_CAPABILITIES, |
34 | .bus_hz = 33 * 1000 * 1000, | 33 | .bus_hz = 33 * 1000 * 1000, |
35 | .detect_delay_ms = 200, | 34 | .detect_delay_ms = 200, |
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index 339295212935..40d7de2eea12 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c | |||
@@ -282,11 +282,11 @@ static int dw_mci_rk3288_parse_dt(struct dw_mci *host) | |||
282 | 282 | ||
283 | priv->drv_clk = devm_clk_get(host->dev, "ciu-drive"); | 283 | priv->drv_clk = devm_clk_get(host->dev, "ciu-drive"); |
284 | if (IS_ERR(priv->drv_clk)) | 284 | if (IS_ERR(priv->drv_clk)) |
285 | dev_dbg(host->dev, "ciu_drv not available\n"); | 285 | dev_dbg(host->dev, "ciu-drive not available\n"); |
286 | 286 | ||
287 | priv->sample_clk = devm_clk_get(host->dev, "ciu-sample"); | 287 | priv->sample_clk = devm_clk_get(host->dev, "ciu-sample"); |
288 | if (IS_ERR(priv->sample_clk)) | 288 | if (IS_ERR(priv->sample_clk)) |
289 | dev_dbg(host->dev, "ciu_sample not available\n"); | 289 | dev_dbg(host->dev, "ciu-sample not available\n"); |
290 | 290 | ||
291 | host->priv = priv; | 291 | host->priv = priv; |
292 | 292 | ||
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 06d47414d0c1..29a1afa81f66 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -147,19 +147,7 @@ static int dw_mci_req_show(struct seq_file *s, void *v) | |||
147 | 147 | ||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | DEFINE_SHOW_ATTRIBUTE(dw_mci_req); | |
151 | static int dw_mci_req_open(struct inode *inode, struct file *file) | ||
152 | { | ||
153 | return single_open(file, dw_mci_req_show, inode->i_private); | ||
154 | } | ||
155 | |||
156 | static const struct file_operations dw_mci_req_fops = { | ||
157 | .owner = THIS_MODULE, | ||
158 | .open = dw_mci_req_open, | ||
159 | .read = seq_read, | ||
160 | .llseek = seq_lseek, | ||
161 | .release = single_release, | ||
162 | }; | ||
163 | 151 | ||
164 | static int dw_mci_regs_show(struct seq_file *s, void *v) | 152 | static int dw_mci_regs_show(struct seq_file *s, void *v) |
165 | { | 153 | { |
@@ -178,19 +166,7 @@ static int dw_mci_regs_show(struct seq_file *s, void *v) | |||
178 | 166 | ||
179 | return 0; | 167 | return 0; |
180 | } | 168 | } |
181 | 169 | DEFINE_SHOW_ATTRIBUTE(dw_mci_regs); | |
182 | static int dw_mci_regs_open(struct inode *inode, struct file *file) | ||
183 | { | ||
184 | return single_open(file, dw_mci_regs_show, inode->i_private); | ||
185 | } | ||
186 | |||
187 | static const struct file_operations dw_mci_regs_fops = { | ||
188 | .owner = THIS_MODULE, | ||
189 | .open = dw_mci_regs_open, | ||
190 | .read = seq_read, | ||
191 | .llseek = seq_lseek, | ||
192 | .release = single_release, | ||
193 | }; | ||
194 | 170 | ||
195 | static void dw_mci_init_debugfs(struct dw_mci_slot *slot) | 171 | static void dw_mci_init_debugfs(struct dw_mci_slot *slot) |
196 | { | 172 | { |
@@ -2030,7 +2006,6 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
2030 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); | 2006 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); |
2031 | err = dw_mci_command_complete(host, cmd); | 2007 | err = dw_mci_command_complete(host, cmd); |
2032 | if (cmd == mrq->sbc && !err) { | 2008 | if (cmd == mrq->sbc && !err) { |
2033 | prev_state = state = STATE_SENDING_CMD; | ||
2034 | __dw_mci_start_request(host, host->slot, | 2009 | __dw_mci_start_request(host, host->slot, |
2035 | mrq->cmd); | 2010 | mrq->cmd); |
2036 | goto unlock; | 2011 | goto unlock; |
@@ -2826,6 +2801,10 @@ static int dw_mci_init_slot_caps(struct dw_mci_slot *slot) | |||
2826 | if (host->pdata->caps2) | 2801 | if (host->pdata->caps2) |
2827 | mmc->caps2 = host->pdata->caps2; | 2802 | mmc->caps2 = host->pdata->caps2; |
2828 | 2803 | ||
2804 | mmc->f_min = DW_MCI_FREQ_MIN; | ||
2805 | if (!mmc->f_max) | ||
2806 | mmc->f_max = DW_MCI_FREQ_MAX; | ||
2807 | |||
2829 | /* Process SDIO IRQs through the sdio_irq_work. */ | 2808 | /* Process SDIO IRQs through the sdio_irq_work. */ |
2830 | if (mmc->caps & MMC_CAP_SDIO_IRQ) | 2809 | if (mmc->caps & MMC_CAP_SDIO_IRQ) |
2831 | mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; | 2810 | mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; |
@@ -2838,7 +2817,6 @@ static int dw_mci_init_slot(struct dw_mci *host) | |||
2838 | struct mmc_host *mmc; | 2817 | struct mmc_host *mmc; |
2839 | struct dw_mci_slot *slot; | 2818 | struct dw_mci_slot *slot; |
2840 | int ret; | 2819 | int ret; |
2841 | u32 freq[2]; | ||
2842 | 2820 | ||
2843 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); | 2821 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); |
2844 | if (!mmc) | 2822 | if (!mmc) |
@@ -2852,16 +2830,6 @@ static int dw_mci_init_slot(struct dw_mci *host) | |||
2852 | host->slot = slot; | 2830 | host->slot = slot; |
2853 | 2831 | ||
2854 | mmc->ops = &dw_mci_ops; | 2832 | mmc->ops = &dw_mci_ops; |
2855 | if (device_property_read_u32_array(host->dev, "clock-freq-min-max", | ||
2856 | freq, 2)) { | ||
2857 | mmc->f_min = DW_MCI_FREQ_MIN; | ||
2858 | mmc->f_max = DW_MCI_FREQ_MAX; | ||
2859 | } else { | ||
2860 | dev_info(host->dev, | ||
2861 | "'clock-freq-min-max' property was deprecated.\n"); | ||
2862 | mmc->f_min = freq[0]; | ||
2863 | mmc->f_max = freq[1]; | ||
2864 | } | ||
2865 | 2833 | ||
2866 | /*if there are external regulators, get them*/ | 2834 | /*if there are external regulators, get them*/ |
2867 | ret = mmc_regulator_get_supply(mmc); | 2835 | ret = mmc_regulator_get_supply(mmc); |
@@ -3160,10 +3128,6 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
3160 | return ERR_PTR(-EPROBE_DEFER); | 3128 | return ERR_PTR(-EPROBE_DEFER); |
3161 | } | 3129 | } |
3162 | 3130 | ||
3163 | /* find out number of slots supported */ | ||
3164 | if (!device_property_read_u32(dev, "num-slots", &pdata->num_slots)) | ||
3165 | dev_info(dev, "'num-slots' was deprecated.\n"); | ||
3166 | |||
3167 | if (device_property_read_u32(dev, "fifo-depth", &pdata->fifo_depth)) | 3131 | if (device_property_read_u32(dev, "fifo-depth", &pdata->fifo_depth)) |
3168 | dev_info(dev, | 3132 | dev_info(dev, |
3169 | "fifo-depth property not found, using value of FIFOTH register as default\n"); | 3133 | "fifo-depth property not found, using value of FIFOTH register as default\n"); |
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 1424bd490dd1..46e9f8ec5398 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
@@ -65,8 +65,7 @@ struct dw_mci_dma_slave { | |||
65 | * @fifo_reg: Pointer to MMIO registers for data FIFO | 65 | * @fifo_reg: Pointer to MMIO registers for data FIFO |
66 | * @sg: Scatterlist entry currently being processed by PIO code, if any. | 66 | * @sg: Scatterlist entry currently being processed by PIO code, if any. |
67 | * @sg_miter: PIO mapping scatterlist iterator. | 67 | * @sg_miter: PIO mapping scatterlist iterator. |
68 | * @cur_slot: The slot which is currently using the controller. | 68 | * @mrq: The request currently being processed on @slot, |
69 | * @mrq: The request currently being processed on @cur_slot, | ||
70 | * or NULL if the controller is idle. | 69 | * or NULL if the controller is idle. |
71 | * @cmd: The command currently being sent to the card, or NULL. | 70 | * @cmd: The command currently being sent to the card, or NULL. |
72 | * @data: The data currently being transferred, or NULL if no data | 71 | * @data: The data currently being transferred, or NULL if no data |
@@ -102,7 +101,6 @@ struct dw_mci_dma_slave { | |||
102 | * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus | 101 | * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus |
103 | * rate and timeout calculations. | 102 | * rate and timeout calculations. |
104 | * @current_speed: Configured rate of the controller. | 103 | * @current_speed: Configured rate of the controller. |
105 | * @num_slots: Number of slots available. | ||
106 | * @fifoth_val: The value of FIFOTH register. | 104 | * @fifoth_val: The value of FIFOTH register. |
107 | * @verid: Denote Version ID. | 105 | * @verid: Denote Version ID. |
108 | * @dev: Device associated with the MMC controller. | 106 | * @dev: Device associated with the MMC controller. |
@@ -134,17 +132,17 @@ struct dw_mci_dma_slave { | |||
134 | * ======= | 132 | * ======= |
135 | * | 133 | * |
136 | * @lock is a softirq-safe spinlock protecting @queue as well as | 134 | * @lock is a softirq-safe spinlock protecting @queue as well as |
135 | * @slot, @mrq and @state. These must always be updated | ||
137 | * at the same time while holding @lock. | 136 | * at the same time while holding @lock. |
137 | * The @mrq field of struct dw_mci_slot is also protected by @lock, | ||
138 | * and must always be written at the same time as the slot is added to | ||
139 | * @queue. | ||
138 | * | 140 | * |
139 | * @irq_lock is an irq-safe spinlock protecting the INTMASK register | 141 | * @irq_lock is an irq-safe spinlock protecting the INTMASK register |
140 | * to allow the interrupt handler to modify it directly. Held for only long | 142 | * to allow the interrupt handler to modify it directly. Held for only long |
141 | * enough to read-modify-write INTMASK and no other locks are grabbed when | 143 | * enough to read-modify-write INTMASK and no other locks are grabbed when |
142 | * holding this one. | 144 | * holding this one. |
143 | * | 145 | * |
144 | * The @mrq field of struct dw_mci_slot is also protected by @lock, | ||
145 | * and must always be written at the same time as the slot is added to | ||
146 | * @queue. | ||
147 | * | ||
148 | * @pending_events and @completed_events are accessed using atomic bit | 146 | * @pending_events and @completed_events are accessed using atomic bit |
149 | * operations, so they don't need any locking. | 147 | * operations, so they don't need any locking. |
150 | * | 148 | * |
@@ -253,8 +251,6 @@ struct dma_pdata; | |||
253 | 251 | ||
254 | /* Board platform data */ | 252 | /* Board platform data */ |
255 | struct dw_mci_board { | 253 | struct dw_mci_board { |
256 | u32 num_slots; | ||
257 | |||
258 | unsigned int bus_hz; /* Clock speed at the cclk_in pad */ | 254 | unsigned int bus_hz; /* Clock speed at the cclk_in pad */ |
259 | 255 | ||
260 | u32 caps; /* Capabilities */ | 256 | u32 caps; /* Capabilities */ |
@@ -318,11 +314,12 @@ struct dw_mci_board { | |||
318 | #define SDMMC_BUFADDR 0x098 | 314 | #define SDMMC_BUFADDR 0x098 |
319 | #define SDMMC_CDTHRCTL 0x100 | 315 | #define SDMMC_CDTHRCTL 0x100 |
320 | #define SDMMC_UHS_REG_EXT 0x108 | 316 | #define SDMMC_UHS_REG_EXT 0x108 |
317 | #define SDMMC_DDR_REG 0x10c | ||
321 | #define SDMMC_ENABLE_SHIFT 0x110 | 318 | #define SDMMC_ENABLE_SHIFT 0x110 |
322 | #define SDMMC_DATA(x) (x) | 319 | #define SDMMC_DATA(x) (x) |
323 | /* | 320 | /* |
324 | * Registers to support idmac 64-bit address mode | 321 | * Registers to support idmac 64-bit address mode |
325 | */ | 322 | */ |
326 | #define SDMMC_DBADDRL 0x088 | 323 | #define SDMMC_DBADDRL 0x088 |
327 | #define SDMMC_DBADDRU 0x08c | 324 | #define SDMMC_DBADDRU 0x08c |
328 | #define SDMMC_IDSTS64 0x090 | 325 | #define SDMMC_IDSTS64 0x090 |
@@ -443,13 +440,19 @@ struct dw_mci_board { | |||
443 | #define SDMMC_CARD_WR_THR_EN BIT(2) | 440 | #define SDMMC_CARD_WR_THR_EN BIT(2) |
444 | #define SDMMC_CARD_RD_THR_EN BIT(0) | 441 | #define SDMMC_CARD_RD_THR_EN BIT(0) |
445 | /* UHS-1 register defines */ | 442 | /* UHS-1 register defines */ |
443 | #define SDMMC_UHS_DDR BIT(16) | ||
446 | #define SDMMC_UHS_18V BIT(0) | 444 | #define SDMMC_UHS_18V BIT(0) |
445 | /* DDR register defines */ | ||
446 | #define SDMMC_DDR_HS400 BIT(31) | ||
447 | /* Enable shift register defines */ | ||
448 | #define SDMMC_ENABLE_PHASE BIT(0) | ||
447 | /* All ctrl reset bits */ | 449 | /* All ctrl reset bits */ |
448 | #define SDMMC_CTRL_ALL_RESET_FLAGS \ | 450 | #define SDMMC_CTRL_ALL_RESET_FLAGS \ |
449 | (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET) | 451 | (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET) |
450 | 452 | ||
451 | /* FIFO register access macros. These should not change the data endian-ness | 453 | /* FIFO register access macros. These should not change the data endian-ness |
452 | * as they are written to memory to be dealt with by the upper layers */ | 454 | * as they are written to memory to be dealt with by the upper layers |
455 | */ | ||
453 | #define mci_fifo_readw(__reg) __raw_readw(__reg) | 456 | #define mci_fifo_readw(__reg) __raw_readw(__reg) |
454 | #define mci_fifo_readl(__reg) __raw_readl(__reg) | 457 | #define mci_fifo_readl(__reg) __raw_readl(__reg) |
455 | #define mci_fifo_readq(__reg) __raw_readq(__reg) | 458 | #define mci_fifo_readq(__reg) __raw_readq(__reg) |
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 6457a7d8880f..cb274e822293 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c | |||
@@ -438,11 +438,23 @@ static const struct mtk_mmc_compatible mt2712_compat = { | |||
438 | .enhance_rx = true, | 438 | .enhance_rx = true, |
439 | }; | 439 | }; |
440 | 440 | ||
441 | static const struct mtk_mmc_compatible mt7622_compat = { | ||
442 | .clk_div_bits = 12, | ||
443 | .hs400_tune = false, | ||
444 | .pad_tune_reg = MSDC_PAD_TUNE0, | ||
445 | .async_fifo = true, | ||
446 | .data_tune = true, | ||
447 | .busy_check = true, | ||
448 | .stop_clk_fix = true, | ||
449 | .enhance_rx = true, | ||
450 | }; | ||
451 | |||
441 | static const struct of_device_id msdc_of_ids[] = { | 452 | static const struct of_device_id msdc_of_ids[] = { |
442 | { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, | 453 | { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, |
443 | { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, | 454 | { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, |
444 | { .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat}, | 455 | { .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat}, |
445 | { .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat}, | 456 | { .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat}, |
457 | { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, | ||
446 | {} | 458 | {} |
447 | }; | 459 | }; |
448 | MODULE_DEVICE_TABLE(of, msdc_of_ids); | 460 | MODULE_DEVICE_TABLE(of, msdc_of_ids); |
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 80943fa07db6..51e01f03fb99 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "renesas_sdhi.h" | 38 | #include "renesas_sdhi.h" |
39 | #include "tmio_mmc.h" | 39 | #include "tmio_mmc.h" |
40 | 40 | ||
41 | #define EXT_ACC 0xe4 | 41 | #define HOST_MODE 0xe4 |
42 | 42 | ||
43 | #define SDHI_VER_GEN2_SDR50 0x490c | 43 | #define SDHI_VER_GEN2_SDR50 0x490c |
44 | #define SDHI_VER_RZ_A1 0x820b | 44 | #define SDHI_VER_RZ_A1 0x820b |
@@ -76,7 +76,7 @@ static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width) | |||
76 | return; | 76 | return; |
77 | } | 77 | } |
78 | 78 | ||
79 | sd_ctrl_write16(host, EXT_ACC, val); | 79 | sd_ctrl_write16(host, HOST_MODE, val); |
80 | } | 80 | } |
81 | 81 | ||
82 | static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host) | 82 | static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host) |
@@ -417,7 +417,7 @@ static int renesas_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) | |||
417 | case CTL_SD_MEM_CARD_OPT: | 417 | case CTL_SD_MEM_CARD_OPT: |
418 | case CTL_TRANSACTION_CTL: | 418 | case CTL_TRANSACTION_CTL: |
419 | case CTL_DMA_ENABLE: | 419 | case CTL_DMA_ENABLE: |
420 | case EXT_ACC: | 420 | case HOST_MODE: |
421 | if (host->pdata->flags & TMIO_MMC_HAVE_CBSY) | 421 | if (host->pdata->flags & TMIO_MMC_HAVE_CBSY) |
422 | bit = TMIO_STAT_CMD_BUSY; | 422 | bit = TMIO_STAT_CMD_BUSY; |
423 | /* fallthrough */ | 423 | /* fallthrough */ |
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 7c03cfead6f9..8e0acd197c43 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c | |||
@@ -71,9 +71,8 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { | |||
71 | }; | 71 | }; |
72 | 72 | ||
73 | static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { | 73 | static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { |
74 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | | 74 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | |
75 | TMIO_MMC_CLK_ACTUAL | TMIO_MMC_HAVE_CBSY | | 75 | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2, |
76 | TMIO_MMC_MIN_RCAR2, | ||
77 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | | 76 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | |
78 | MMC_CAP_CMD23, | 77 | MMC_CAP_CMD23, |
79 | .bus_shift = 2, | 78 | .bus_shift = 2, |
@@ -145,7 +144,6 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host, | |||
145 | u32 dtran_mode = DTRAN_MODE_BUS_WID_TH | DTRAN_MODE_ADDR_MODE; | 144 | u32 dtran_mode = DTRAN_MODE_BUS_WID_TH | DTRAN_MODE_ADDR_MODE; |
146 | enum dma_data_direction dir; | 145 | enum dma_data_direction dir; |
147 | int ret; | 146 | int ret; |
148 | u32 irq_mask; | ||
149 | 147 | ||
150 | /* This DMAC cannot handle if sg_len is not 1 */ | 148 | /* This DMAC cannot handle if sg_len is not 1 */ |
151 | WARN_ON(host->sg_len > 1); | 149 | WARN_ON(host->sg_len > 1); |
@@ -157,11 +155,9 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host, | |||
157 | if (data->flags & MMC_DATA_READ) { | 155 | if (data->flags & MMC_DATA_READ) { |
158 | dtran_mode |= DTRAN_MODE_CH_NUM_CH1; | 156 | dtran_mode |= DTRAN_MODE_CH_NUM_CH1; |
159 | dir = DMA_FROM_DEVICE; | 157 | dir = DMA_FROM_DEVICE; |
160 | irq_mask = TMIO_STAT_RXRDY; | ||
161 | } else { | 158 | } else { |
162 | dtran_mode |= DTRAN_MODE_CH_NUM_CH0; | 159 | dtran_mode |= DTRAN_MODE_CH_NUM_CH0; |
163 | dir = DMA_TO_DEVICE; | 160 | dir = DMA_TO_DEVICE; |
164 | irq_mask = TMIO_STAT_TXRQ; | ||
165 | } | 161 | } |
166 | 162 | ||
167 | ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, dir); | 163 | ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, dir); |
@@ -170,9 +166,6 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host, | |||
170 | 166 | ||
171 | renesas_sdhi_internal_dmac_enable_dma(host, true); | 167 | renesas_sdhi_internal_dmac_enable_dma(host, true); |
172 | 168 | ||
173 | /* disable PIO irqs to avoid "PIO IRQ in DMA mode!" */ | ||
174 | tmio_mmc_disable_mmc_irqs(host, irq_mask); | ||
175 | |||
176 | /* set dma parameters */ | 169 | /* set dma parameters */ |
177 | renesas_sdhi_internal_dmac_dm_write(host, DM_CM_DTRAN_MODE, | 170 | renesas_sdhi_internal_dmac_dm_write(host, DM_CM_DTRAN_MODE, |
178 | dtran_mode); | 171 | dtran_mode); |
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index 82d757c480b2..848e50c1638a 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c | |||
@@ -40,8 +40,7 @@ static const struct renesas_sdhi_of_data of_rz_compatible = { | |||
40 | }; | 40 | }; |
41 | 41 | ||
42 | static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = { | 42 | static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = { |
43 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | | 43 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL, |
44 | TMIO_MMC_CLK_ACTUAL, | ||
45 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, | 44 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, |
46 | }; | 45 | }; |
47 | 46 | ||
@@ -58,9 +57,8 @@ static struct renesas_sdhi_scc rcar_gen2_scc_taps[] = { | |||
58 | }; | 57 | }; |
59 | 58 | ||
60 | static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = { | 59 | static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = { |
61 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | | 60 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | |
62 | TMIO_MMC_CLK_ACTUAL | TMIO_MMC_HAVE_CBSY | | 61 | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2, |
63 | TMIO_MMC_MIN_RCAR2, | ||
64 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | | 62 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | |
65 | MMC_CAP_CMD23, | 63 | MMC_CAP_CMD23, |
66 | .dma_buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES, | 64 | .dma_buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES, |
@@ -79,9 +77,8 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { | |||
79 | }; | 77 | }; |
80 | 78 | ||
81 | static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { | 79 | static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { |
82 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | | 80 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | |
83 | TMIO_MMC_CLK_ACTUAL | TMIO_MMC_HAVE_CBSY | | 81 | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2, |
84 | TMIO_MMC_MIN_RCAR2, | ||
85 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | | 82 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | |
86 | MMC_CAP_CMD23, | 83 | MMC_CAP_CMD23, |
87 | .bus_shift = 2, | 84 | .bus_shift = 2, |
@@ -205,8 +202,6 @@ static void renesas_sdhi_sys_dmac_start_dma_rx(struct tmio_mmc_host *host) | |||
205 | return; | 202 | return; |
206 | } | 203 | } |
207 | 204 | ||
208 | tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_RXRDY); | ||
209 | |||
210 | /* The only sg element can be unaligned, use our bounce buffer then */ | 205 | /* The only sg element can be unaligned, use our bounce buffer then */ |
211 | if (!aligned) { | 206 | if (!aligned) { |
212 | sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length); | 207 | sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length); |
@@ -280,8 +275,6 @@ static void renesas_sdhi_sys_dmac_start_dma_tx(struct tmio_mmc_host *host) | |||
280 | return; | 275 | return; |
281 | } | 276 | } |
282 | 277 | ||
283 | tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_TXRQ); | ||
284 | |||
285 | /* The only sg element can be unaligned, use our bounce buffer then */ | 278 | /* The only sg element can be unaligned, use our bounce buffer then */ |
286 | if (!aligned) { | 279 | if (!aligned) { |
287 | unsigned long flags; | 280 | unsigned long flags; |
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index 61666d269771..0ef741bc515d 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c | |||
@@ -214,6 +214,7 @@ static const struct sdhci_pltfm_data sdhci_bcm2835_pltfm_data = { | |||
214 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | 214 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | |
215 | SDHCI_QUIRK_MISSING_CAPS | | 215 | SDHCI_QUIRK_MISSING_CAPS | |
216 | SDHCI_QUIRK_NO_HISPD_BIT, | 216 | SDHCI_QUIRK_NO_HISPD_BIT, |
217 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, | ||
217 | .ops = &sdhci_iproc_32only_ops, | 218 | .ops = &sdhci_iproc_32only_ops, |
218 | }; | 219 | }; |
219 | 220 | ||
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 628bfe9a3d17..1456abd5eeb9 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c | |||
@@ -25,17 +25,32 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
28 | #include <linux/pinctrl/consumer.h> | ||
28 | 29 | ||
29 | #include "sdhci-pltfm.h" | 30 | #include "sdhci-pltfm.h" |
30 | 31 | ||
31 | #define SDHCI_OMAP_CON 0x12c | 32 | #define SDHCI_OMAP_CON 0x12c |
32 | #define CON_DW8 BIT(5) | 33 | #define CON_DW8 BIT(5) |
33 | #define CON_DMA_MASTER BIT(20) | 34 | #define CON_DMA_MASTER BIT(20) |
35 | #define CON_DDR BIT(19) | ||
36 | #define CON_CLKEXTFREE BIT(16) | ||
37 | #define CON_PADEN BIT(15) | ||
34 | #define CON_INIT BIT(1) | 38 | #define CON_INIT BIT(1) |
35 | #define CON_OD BIT(0) | 39 | #define CON_OD BIT(0) |
36 | 40 | ||
41 | #define SDHCI_OMAP_DLL 0x0134 | ||
42 | #define DLL_SWT BIT(20) | ||
43 | #define DLL_FORCE_SR_C_SHIFT 13 | ||
44 | #define DLL_FORCE_SR_C_MASK (0x7f << DLL_FORCE_SR_C_SHIFT) | ||
45 | #define DLL_FORCE_VALUE BIT(12) | ||
46 | #define DLL_CALIB BIT(1) | ||
47 | |||
37 | #define SDHCI_OMAP_CMD 0x20c | 48 | #define SDHCI_OMAP_CMD 0x20c |
38 | 49 | ||
50 | #define SDHCI_OMAP_PSTATE 0x0224 | ||
51 | #define PSTATE_DLEV_DAT0 BIT(20) | ||
52 | #define PSTATE_DATI BIT(1) | ||
53 | |||
39 | #define SDHCI_OMAP_HCTL 0x228 | 54 | #define SDHCI_OMAP_HCTL 0x228 |
40 | #define HCTL_SDBP BIT(8) | 55 | #define HCTL_SDBP BIT(8) |
41 | #define HCTL_SDVS_SHIFT 9 | 56 | #define HCTL_SDVS_SHIFT 9 |
@@ -56,12 +71,16 @@ | |||
56 | 71 | ||
57 | #define SDHCI_OMAP_AC12 0x23c | 72 | #define SDHCI_OMAP_AC12 0x23c |
58 | #define AC12_V1V8_SIGEN BIT(19) | 73 | #define AC12_V1V8_SIGEN BIT(19) |
74 | #define AC12_SCLK_SEL BIT(23) | ||
59 | 75 | ||
60 | #define SDHCI_OMAP_CAPA 0x240 | 76 | #define SDHCI_OMAP_CAPA 0x240 |
61 | #define CAPA_VS33 BIT(24) | 77 | #define CAPA_VS33 BIT(24) |
62 | #define CAPA_VS30 BIT(25) | 78 | #define CAPA_VS30 BIT(25) |
63 | #define CAPA_VS18 BIT(26) | 79 | #define CAPA_VS18 BIT(26) |
64 | 80 | ||
81 | #define SDHCI_OMAP_CAPA2 0x0244 | ||
82 | #define CAPA2_TSDR50 BIT(13) | ||
83 | |||
65 | #define SDHCI_OMAP_TIMEOUT 1 /* 1 msec */ | 84 | #define SDHCI_OMAP_TIMEOUT 1 /* 1 msec */ |
66 | 85 | ||
67 | #define SYSCTL_CLKD_MAX 0x3FF | 86 | #define SYSCTL_CLKD_MAX 0x3FF |
@@ -70,8 +89,14 @@ | |||
70 | #define IOV_3V0 3000000 /* 300000 uV */ | 89 | #define IOV_3V0 3000000 /* 300000 uV */ |
71 | #define IOV_3V3 3300000 /* 330000 uV */ | 90 | #define IOV_3V3 3300000 /* 330000 uV */ |
72 | 91 | ||
92 | #define MAX_PHASE_DELAY 0x7C | ||
93 | |||
94 | /* sdhci-omap controller flags */ | ||
95 | #define SDHCI_OMAP_REQUIRE_IODELAY BIT(0) | ||
96 | |||
73 | struct sdhci_omap_data { | 97 | struct sdhci_omap_data { |
74 | u32 offset; | 98 | u32 offset; |
99 | u8 flags; | ||
75 | }; | 100 | }; |
76 | 101 | ||
77 | struct sdhci_omap_host { | 102 | struct sdhci_omap_host { |
@@ -82,8 +107,16 @@ struct sdhci_omap_host { | |||
82 | struct sdhci_host *host; | 107 | struct sdhci_host *host; |
83 | u8 bus_mode; | 108 | u8 bus_mode; |
84 | u8 power_mode; | 109 | u8 power_mode; |
110 | u8 timing; | ||
111 | u8 flags; | ||
112 | |||
113 | struct pinctrl *pinctrl; | ||
114 | struct pinctrl_state **pinctrl_state; | ||
85 | }; | 115 | }; |
86 | 116 | ||
117 | static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host); | ||
118 | static void sdhci_omap_stop_clock(struct sdhci_omap_host *omap_host); | ||
119 | |||
87 | static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host, | 120 | static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host, |
88 | unsigned int offset) | 121 | unsigned int offset) |
89 | { | 122 | { |
@@ -191,6 +224,178 @@ static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host, | |||
191 | } | 224 | } |
192 | } | 225 | } |
193 | 226 | ||
227 | static inline void sdhci_omap_set_dll(struct sdhci_omap_host *omap_host, | ||
228 | int count) | ||
229 | { | ||
230 | int i; | ||
231 | u32 reg; | ||
232 | |||
233 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL); | ||
234 | reg |= DLL_FORCE_VALUE; | ||
235 | reg &= ~DLL_FORCE_SR_C_MASK; | ||
236 | reg |= (count << DLL_FORCE_SR_C_SHIFT); | ||
237 | sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg); | ||
238 | |||
239 | reg |= DLL_CALIB; | ||
240 | sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg); | ||
241 | for (i = 0; i < 1000; i++) { | ||
242 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL); | ||
243 | if (reg & DLL_CALIB) | ||
244 | break; | ||
245 | } | ||
246 | reg &= ~DLL_CALIB; | ||
247 | sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg); | ||
248 | } | ||
249 | |||
250 | static void sdhci_omap_disable_tuning(struct sdhci_omap_host *omap_host) | ||
251 | { | ||
252 | u32 reg; | ||
253 | |||
254 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); | ||
255 | reg &= ~AC12_SCLK_SEL; | ||
256 | sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg); | ||
257 | |||
258 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL); | ||
259 | reg &= ~(DLL_FORCE_VALUE | DLL_SWT); | ||
260 | sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg); | ||
261 | } | ||
262 | |||
263 | static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) | ||
264 | { | ||
265 | struct sdhci_host *host = mmc_priv(mmc); | ||
266 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
267 | struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); | ||
268 | struct device *dev = omap_host->dev; | ||
269 | struct mmc_ios *ios = &mmc->ios; | ||
270 | u32 start_window = 0, max_window = 0; | ||
271 | u8 cur_match, prev_match = 0; | ||
272 | u32 length = 0, max_len = 0; | ||
273 | u32 ier = host->ier; | ||
274 | u32 phase_delay = 0; | ||
275 | int ret = 0; | ||
276 | u32 reg; | ||
277 | |||
278 | pltfm_host = sdhci_priv(host); | ||
279 | omap_host = sdhci_pltfm_priv(pltfm_host); | ||
280 | dev = omap_host->dev; | ||
281 | |||
282 | /* clock tuning is not needed for upto 52MHz */ | ||
283 | if (ios->clock <= 52000000) | ||
284 | return 0; | ||
285 | |||
286 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA2); | ||
287 | if (ios->timing == MMC_TIMING_UHS_SDR50 && !(reg & CAPA2_TSDR50)) | ||
288 | return 0; | ||
289 | |||
290 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL); | ||
291 | reg |= DLL_SWT; | ||
292 | sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg); | ||
293 | |||
294 | /* | ||
295 | * OMAP5/DRA74X/DRA72x Errata i802: | ||
296 | * DCRC error interrupts (MMCHS_STAT[21] DCRC=0x1) can occur | ||
297 | * during the tuning procedure. So disable it during the | ||
298 | * tuning procedure. | ||
299 | */ | ||
300 | ier &= ~SDHCI_INT_DATA_CRC; | ||
301 | sdhci_writel(host, ier, SDHCI_INT_ENABLE); | ||
302 | sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); | ||
303 | |||
304 | while (phase_delay <= MAX_PHASE_DELAY) { | ||
305 | sdhci_omap_set_dll(omap_host, phase_delay); | ||
306 | |||
307 | cur_match = !mmc_send_tuning(mmc, opcode, NULL); | ||
308 | if (cur_match) { | ||
309 | if (prev_match) { | ||
310 | length++; | ||
311 | } else { | ||
312 | start_window = phase_delay; | ||
313 | length = 1; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | if (length > max_len) { | ||
318 | max_window = start_window; | ||
319 | max_len = length; | ||
320 | } | ||
321 | |||
322 | prev_match = cur_match; | ||
323 | phase_delay += 4; | ||
324 | } | ||
325 | |||
326 | if (!max_len) { | ||
327 | dev_err(dev, "Unable to find match\n"); | ||
328 | ret = -EIO; | ||
329 | goto tuning_error; | ||
330 | } | ||
331 | |||
332 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); | ||
333 | if (!(reg & AC12_SCLK_SEL)) { | ||
334 | ret = -EIO; | ||
335 | goto tuning_error; | ||
336 | } | ||
337 | |||
338 | phase_delay = max_window + 4 * (max_len >> 1); | ||
339 | sdhci_omap_set_dll(omap_host, phase_delay); | ||
340 | |||
341 | goto ret; | ||
342 | |||
343 | tuning_error: | ||
344 | dev_err(dev, "Tuning failed\n"); | ||
345 | sdhci_omap_disable_tuning(omap_host); | ||
346 | |||
347 | ret: | ||
348 | sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); | ||
349 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | ||
350 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | ||
351 | return ret; | ||
352 | } | ||
353 | |||
354 | static int sdhci_omap_card_busy(struct mmc_host *mmc) | ||
355 | { | ||
356 | u32 reg, ac12; | ||
357 | int ret = false; | ||
358 | struct sdhci_host *host = mmc_priv(mmc); | ||
359 | struct sdhci_pltfm_host *pltfm_host; | ||
360 | struct sdhci_omap_host *omap_host; | ||
361 | u32 ier = host->ier; | ||
362 | |||
363 | pltfm_host = sdhci_priv(host); | ||
364 | omap_host = sdhci_pltfm_priv(pltfm_host); | ||
365 | |||
366 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); | ||
367 | ac12 = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); | ||
368 | reg &= ~CON_CLKEXTFREE; | ||
369 | if (ac12 & AC12_V1V8_SIGEN) | ||
370 | reg |= CON_CLKEXTFREE; | ||
371 | reg |= CON_PADEN; | ||
372 | sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); | ||
373 | |||
374 | disable_irq(host->irq); | ||
375 | ier |= SDHCI_INT_CARD_INT; | ||
376 | sdhci_writel(host, ier, SDHCI_INT_ENABLE); | ||
377 | sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); | ||
378 | |||
379 | /* | ||
380 | * Delay is required for PSTATE to correctly reflect | ||
381 | * DLEV/CLEV values after PADEN is set. | ||
382 | */ | ||
383 | usleep_range(50, 100); | ||
384 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_PSTATE); | ||
385 | if ((reg & PSTATE_DATI) || !(reg & PSTATE_DLEV_DAT0)) | ||
386 | ret = true; | ||
387 | |||
388 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); | ||
389 | reg &= ~(CON_CLKEXTFREE | CON_PADEN); | ||
390 | sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); | ||
391 | |||
392 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | ||
393 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | ||
394 | enable_irq(host->irq); | ||
395 | |||
396 | return ret; | ||
397 | } | ||
398 | |||
194 | static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc, | 399 | static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc, |
195 | struct mmc_ios *ios) | 400 | struct mmc_ios *ios) |
196 | { | 401 | { |
@@ -244,6 +449,39 @@ static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc, | |||
244 | return 0; | 449 | return 0; |
245 | } | 450 | } |
246 | 451 | ||
452 | static void sdhci_omap_set_timing(struct sdhci_omap_host *omap_host, u8 timing) | ||
453 | { | ||
454 | int ret; | ||
455 | struct pinctrl_state *pinctrl_state; | ||
456 | struct device *dev = omap_host->dev; | ||
457 | |||
458 | if (!(omap_host->flags & SDHCI_OMAP_REQUIRE_IODELAY)) | ||
459 | return; | ||
460 | |||
461 | if (omap_host->timing == timing) | ||
462 | return; | ||
463 | |||
464 | sdhci_omap_stop_clock(omap_host); | ||
465 | |||
466 | pinctrl_state = omap_host->pinctrl_state[timing]; | ||
467 | ret = pinctrl_select_state(omap_host->pinctrl, pinctrl_state); | ||
468 | if (ret) { | ||
469 | dev_err(dev, "failed to select pinctrl state\n"); | ||
470 | return; | ||
471 | } | ||
472 | |||
473 | sdhci_omap_start_clock(omap_host); | ||
474 | omap_host->timing = timing; | ||
475 | } | ||
476 | |||
477 | static void sdhci_omap_set_power_mode(struct sdhci_omap_host *omap_host, | ||
478 | u8 power_mode) | ||
479 | { | ||
480 | if (omap_host->bus_mode == MMC_POWER_OFF) | ||
481 | sdhci_omap_disable_tuning(omap_host); | ||
482 | omap_host->power_mode = power_mode; | ||
483 | } | ||
484 | |||
247 | static void sdhci_omap_set_bus_mode(struct sdhci_omap_host *omap_host, | 485 | static void sdhci_omap_set_bus_mode(struct sdhci_omap_host *omap_host, |
248 | unsigned int mode) | 486 | unsigned int mode) |
249 | { | 487 | { |
@@ -272,7 +510,9 @@ static void sdhci_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
272 | omap_host = sdhci_pltfm_priv(pltfm_host); | 510 | omap_host = sdhci_pltfm_priv(pltfm_host); |
273 | 511 | ||
274 | sdhci_omap_set_bus_mode(omap_host, ios->bus_mode); | 512 | sdhci_omap_set_bus_mode(omap_host, ios->bus_mode); |
513 | sdhci_omap_set_timing(omap_host, ios->timing); | ||
275 | sdhci_set_ios(mmc, ios); | 514 | sdhci_set_ios(mmc, ios); |
515 | sdhci_omap_set_power_mode(omap_host, ios->power_mode); | ||
276 | } | 516 | } |
277 | 517 | ||
278 | static u16 sdhci_omap_calc_divisor(struct sdhci_pltfm_host *host, | 518 | static u16 sdhci_omap_calc_divisor(struct sdhci_pltfm_host *host, |
@@ -401,8 +641,26 @@ static void sdhci_omap_init_74_clocks(struct sdhci_host *host, u8 power_mode) | |||
401 | sdhci_omap_writel(omap_host, SDHCI_OMAP_STAT, INT_CC_EN); | 641 | sdhci_omap_writel(omap_host, SDHCI_OMAP_STAT, INT_CC_EN); |
402 | 642 | ||
403 | enable_irq(host->irq); | 643 | enable_irq(host->irq); |
644 | } | ||
404 | 645 | ||
405 | omap_host->power_mode = power_mode; | 646 | static void sdhci_omap_set_uhs_signaling(struct sdhci_host *host, |
647 | unsigned int timing) | ||
648 | { | ||
649 | u32 reg; | ||
650 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
651 | struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); | ||
652 | |||
653 | sdhci_omap_stop_clock(omap_host); | ||
654 | |||
655 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); | ||
656 | if (timing == MMC_TIMING_UHS_DDR50 || timing == MMC_TIMING_MMC_DDR52) | ||
657 | reg |= CON_DDR; | ||
658 | else | ||
659 | reg &= ~CON_DDR; | ||
660 | sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); | ||
661 | |||
662 | sdhci_set_uhs_signaling(host, timing); | ||
663 | sdhci_omap_start_clock(omap_host); | ||
406 | } | 664 | } |
407 | 665 | ||
408 | static struct sdhci_ops sdhci_omap_ops = { | 666 | static struct sdhci_ops sdhci_omap_ops = { |
@@ -414,7 +672,7 @@ static struct sdhci_ops sdhci_omap_ops = { | |||
414 | .set_bus_width = sdhci_omap_set_bus_width, | 672 | .set_bus_width = sdhci_omap_set_bus_width, |
415 | .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, | 673 | .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, |
416 | .reset = sdhci_reset, | 674 | .reset = sdhci_reset, |
417 | .set_uhs_signaling = sdhci_set_uhs_signaling, | 675 | .set_uhs_signaling = sdhci_omap_set_uhs_signaling, |
418 | }; | 676 | }; |
419 | 677 | ||
420 | static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host) | 678 | static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host) |
@@ -453,14 +711,15 @@ static const struct sdhci_pltfm_data sdhci_omap_pdata = { | |||
453 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | | 711 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | |
454 | SDHCI_QUIRK_NO_HISPD_BIT | | 712 | SDHCI_QUIRK_NO_HISPD_BIT | |
455 | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, | 713 | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, |
456 | .quirks2 = SDHCI_QUIRK2_NO_1_8_V | | 714 | .quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN | |
457 | SDHCI_QUIRK2_ACMD23_BROKEN | | 715 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
458 | SDHCI_QUIRK2_RSP_136_HAS_CRC, | 716 | SDHCI_QUIRK2_RSP_136_HAS_CRC, |
459 | .ops = &sdhci_omap_ops, | 717 | .ops = &sdhci_omap_ops, |
460 | }; | 718 | }; |
461 | 719 | ||
462 | static const struct sdhci_omap_data dra7_data = { | 720 | static const struct sdhci_omap_data dra7_data = { |
463 | .offset = 0x200, | 721 | .offset = 0x200, |
722 | .flags = SDHCI_OMAP_REQUIRE_IODELAY, | ||
464 | }; | 723 | }; |
465 | 724 | ||
466 | static const struct of_device_id omap_sdhci_match[] = { | 725 | static const struct of_device_id omap_sdhci_match[] = { |
@@ -469,6 +728,108 @@ static const struct of_device_id omap_sdhci_match[] = { | |||
469 | }; | 728 | }; |
470 | MODULE_DEVICE_TABLE(of, omap_sdhci_match); | 729 | MODULE_DEVICE_TABLE(of, omap_sdhci_match); |
471 | 730 | ||
731 | static struct pinctrl_state | ||
732 | *sdhci_omap_iodelay_pinctrl_state(struct sdhci_omap_host *omap_host, char *mode, | ||
733 | u32 *caps, u32 capmask) | ||
734 | { | ||
735 | struct device *dev = omap_host->dev; | ||
736 | struct pinctrl_state *pinctrl_state = ERR_PTR(-ENODEV); | ||
737 | |||
738 | if (!(*caps & capmask)) | ||
739 | goto ret; | ||
740 | |||
741 | pinctrl_state = pinctrl_lookup_state(omap_host->pinctrl, mode); | ||
742 | if (IS_ERR(pinctrl_state)) { | ||
743 | dev_err(dev, "no pinctrl state for %s mode", mode); | ||
744 | *caps &= ~capmask; | ||
745 | } | ||
746 | |||
747 | ret: | ||
748 | return pinctrl_state; | ||
749 | } | ||
750 | |||
751 | static int sdhci_omap_config_iodelay_pinctrl_state(struct sdhci_omap_host | ||
752 | *omap_host) | ||
753 | { | ||
754 | struct device *dev = omap_host->dev; | ||
755 | struct sdhci_host *host = omap_host->host; | ||
756 | struct mmc_host *mmc = host->mmc; | ||
757 | u32 *caps = &mmc->caps; | ||
758 | u32 *caps2 = &mmc->caps2; | ||
759 | struct pinctrl_state *state; | ||
760 | struct pinctrl_state **pinctrl_state; | ||
761 | |||
762 | if (!(omap_host->flags & SDHCI_OMAP_REQUIRE_IODELAY)) | ||
763 | return 0; | ||
764 | |||
765 | pinctrl_state = devm_kzalloc(dev, sizeof(*pinctrl_state) * | ||
766 | (MMC_TIMING_MMC_HS200 + 1), GFP_KERNEL); | ||
767 | if (!pinctrl_state) | ||
768 | return -ENOMEM; | ||
769 | |||
770 | omap_host->pinctrl = devm_pinctrl_get(omap_host->dev); | ||
771 | if (IS_ERR(omap_host->pinctrl)) { | ||
772 | dev_err(dev, "Cannot get pinctrl\n"); | ||
773 | return PTR_ERR(omap_host->pinctrl); | ||
774 | } | ||
775 | |||
776 | state = pinctrl_lookup_state(omap_host->pinctrl, "default"); | ||
777 | if (IS_ERR(state)) { | ||
778 | dev_err(dev, "no pinctrl state for default mode\n"); | ||
779 | return PTR_ERR(state); | ||
780 | } | ||
781 | pinctrl_state[MMC_TIMING_LEGACY] = state; | ||
782 | |||
783 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "sdr104", caps, | ||
784 | MMC_CAP_UHS_SDR104); | ||
785 | if (!IS_ERR(state)) | ||
786 | pinctrl_state[MMC_TIMING_UHS_SDR104] = state; | ||
787 | |||
788 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "ddr50", caps, | ||
789 | MMC_CAP_UHS_DDR50); | ||
790 | if (!IS_ERR(state)) | ||
791 | pinctrl_state[MMC_TIMING_UHS_DDR50] = state; | ||
792 | |||
793 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "sdr50", caps, | ||
794 | MMC_CAP_UHS_SDR50); | ||
795 | if (!IS_ERR(state)) | ||
796 | pinctrl_state[MMC_TIMING_UHS_SDR50] = state; | ||
797 | |||
798 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "sdr25", caps, | ||
799 | MMC_CAP_UHS_SDR25); | ||
800 | if (!IS_ERR(state)) | ||
801 | pinctrl_state[MMC_TIMING_UHS_SDR25] = state; | ||
802 | |||
803 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "sdr12", caps, | ||
804 | MMC_CAP_UHS_SDR12); | ||
805 | if (!IS_ERR(state)) | ||
806 | pinctrl_state[MMC_TIMING_UHS_SDR12] = state; | ||
807 | |||
808 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "ddr_1_8v", caps, | ||
809 | MMC_CAP_1_8V_DDR); | ||
810 | if (!IS_ERR(state)) | ||
811 | pinctrl_state[MMC_TIMING_MMC_DDR52] = state; | ||
812 | |||
813 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "hs", caps, | ||
814 | MMC_CAP_SD_HIGHSPEED); | ||
815 | if (!IS_ERR(state)) | ||
816 | pinctrl_state[MMC_TIMING_SD_HS] = state; | ||
817 | |||
818 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "hs", caps, | ||
819 | MMC_CAP_MMC_HIGHSPEED); | ||
820 | if (!IS_ERR(state)) | ||
821 | pinctrl_state[MMC_TIMING_MMC_HS] = state; | ||
822 | |||
823 | state = sdhci_omap_iodelay_pinctrl_state(omap_host, "hs200_1_8v", caps2, | ||
824 | MMC_CAP2_HS200_1_8V_SDR); | ||
825 | if (!IS_ERR(state)) | ||
826 | pinctrl_state[MMC_TIMING_MMC_HS200] = state; | ||
827 | |||
828 | omap_host->pinctrl_state = pinctrl_state; | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | |||
472 | static int sdhci_omap_probe(struct platform_device *pdev) | 833 | static int sdhci_omap_probe(struct platform_device *pdev) |
473 | { | 834 | { |
474 | int ret; | 835 | int ret; |
@@ -504,6 +865,9 @@ static int sdhci_omap_probe(struct platform_device *pdev) | |||
504 | omap_host->host = host; | 865 | omap_host->host = host; |
505 | omap_host->base = host->ioaddr; | 866 | omap_host->base = host->ioaddr; |
506 | omap_host->dev = dev; | 867 | omap_host->dev = dev; |
868 | omap_host->power_mode = MMC_POWER_UNDEFINED; | ||
869 | omap_host->timing = MMC_TIMING_LEGACY; | ||
870 | omap_host->flags = data->flags; | ||
507 | host->ioaddr += offset; | 871 | host->ioaddr += offset; |
508 | 872 | ||
509 | mmc = host->mmc; | 873 | mmc = host->mmc; |
@@ -552,10 +916,16 @@ static int sdhci_omap_probe(struct platform_device *pdev) | |||
552 | goto err_put_sync; | 916 | goto err_put_sync; |
553 | } | 917 | } |
554 | 918 | ||
919 | ret = sdhci_omap_config_iodelay_pinctrl_state(omap_host); | ||
920 | if (ret) | ||
921 | goto err_put_sync; | ||
922 | |||
555 | host->mmc_host_ops.get_ro = mmc_gpio_get_ro; | 923 | host->mmc_host_ops.get_ro = mmc_gpio_get_ro; |
556 | host->mmc_host_ops.start_signal_voltage_switch = | 924 | host->mmc_host_ops.start_signal_voltage_switch = |
557 | sdhci_omap_start_signal_voltage_switch; | 925 | sdhci_omap_start_signal_voltage_switch; |
558 | host->mmc_host_ops.set_ios = sdhci_omap_set_ios; | 926 | host->mmc_host_ops.set_ios = sdhci_omap_set_ios; |
927 | host->mmc_host_ops.card_busy = sdhci_omap_card_busy; | ||
928 | host->mmc_host_ops.execute_tuning = sdhci_omap_execute_tuning; | ||
559 | 929 | ||
560 | sdhci_read_caps(host); | 930 | sdhci_read_caps(host); |
561 | host->caps |= SDHCI_CAN_DO_ADMA2; | 931 | host->caps |= SDHCI_CAN_DO_ADMA2; |
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 82c4f05f91d8..787434e5589d 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c | |||
@@ -41,18 +41,25 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host); | |||
41 | static int sdhci_pci_init_wakeup(struct sdhci_pci_chip *chip) | 41 | static int sdhci_pci_init_wakeup(struct sdhci_pci_chip *chip) |
42 | { | 42 | { |
43 | mmc_pm_flag_t pm_flags = 0; | 43 | mmc_pm_flag_t pm_flags = 0; |
44 | bool cap_cd_wake = false; | ||
44 | int i; | 45 | int i; |
45 | 46 | ||
46 | for (i = 0; i < chip->num_slots; i++) { | 47 | for (i = 0; i < chip->num_slots; i++) { |
47 | struct sdhci_pci_slot *slot = chip->slots[i]; | 48 | struct sdhci_pci_slot *slot = chip->slots[i]; |
48 | 49 | ||
49 | if (slot) | 50 | if (slot) { |
50 | pm_flags |= slot->host->mmc->pm_flags; | 51 | pm_flags |= slot->host->mmc->pm_flags; |
52 | if (slot->host->mmc->caps & MMC_CAP_CD_WAKE) | ||
53 | cap_cd_wake = true; | ||
54 | } | ||
51 | } | 55 | } |
52 | 56 | ||
53 | return device_set_wakeup_enable(&chip->pdev->dev, | 57 | if ((pm_flags & MMC_PM_KEEP_POWER) && (pm_flags & MMC_PM_WAKE_SDIO_IRQ)) |
54 | (pm_flags & MMC_PM_KEEP_POWER) && | 58 | return device_wakeup_enable(&chip->pdev->dev); |
55 | (pm_flags & MMC_PM_WAKE_SDIO_IRQ)); | 59 | else if (!cap_cd_wake) |
60 | return device_wakeup_disable(&chip->pdev->dev); | ||
61 | |||
62 | return 0; | ||
56 | } | 63 | } |
57 | 64 | ||
58 | static int sdhci_pci_suspend_host(struct sdhci_pci_chip *chip) | 65 | static int sdhci_pci_suspend_host(struct sdhci_pci_chip *chip) |
@@ -76,6 +83,9 @@ static int sdhci_pci_suspend_host(struct sdhci_pci_chip *chip) | |||
76 | ret = sdhci_suspend_host(host); | 83 | ret = sdhci_suspend_host(host); |
77 | if (ret) | 84 | if (ret) |
78 | goto err_pci_suspend; | 85 | goto err_pci_suspend; |
86 | |||
87 | if (device_may_wakeup(&chip->pdev->dev)) | ||
88 | mmc_gpio_set_cd_wake(host->mmc, true); | ||
79 | } | 89 | } |
80 | 90 | ||
81 | return 0; | 91 | return 0; |
@@ -99,6 +109,8 @@ int sdhci_pci_resume_host(struct sdhci_pci_chip *chip) | |||
99 | ret = sdhci_resume_host(slot->host); | 109 | ret = sdhci_resume_host(slot->host); |
100 | if (ret) | 110 | if (ret) |
101 | return ret; | 111 | return ret; |
112 | |||
113 | mmc_gpio_set_cd_wake(slot->host->mmc, false); | ||
102 | } | 114 | } |
103 | 115 | ||
104 | return 0; | 116 | return 0; |
@@ -712,26 +724,8 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot) | |||
712 | return ret; | 724 | return ret; |
713 | } | 725 | } |
714 | 726 | ||
715 | static void glk_cqe_enable(struct mmc_host *mmc) | ||
716 | { | ||
717 | struct sdhci_host *host = mmc_priv(mmc); | ||
718 | u32 reg; | ||
719 | |||
720 | /* | ||
721 | * CQE gets stuck if it sees Buffer Read Enable bit set, which can be | ||
722 | * the case after tuning, so ensure the buffer is drained. | ||
723 | */ | ||
724 | reg = sdhci_readl(host, SDHCI_PRESENT_STATE); | ||
725 | while (reg & SDHCI_DATA_AVAILABLE) { | ||
726 | sdhci_readl(host, SDHCI_BUFFER); | ||
727 | reg = sdhci_readl(host, SDHCI_PRESENT_STATE); | ||
728 | } | ||
729 | |||
730 | sdhci_cqe_enable(mmc); | ||
731 | } | ||
732 | |||
733 | static const struct cqhci_host_ops glk_cqhci_ops = { | 727 | static const struct cqhci_host_ops glk_cqhci_ops = { |
734 | .enable = glk_cqe_enable, | 728 | .enable = sdhci_cqe_enable, |
735 | .disable = sdhci_cqe_disable, | 729 | .disable = sdhci_cqe_disable, |
736 | .dumpregs = sdhci_pci_dumpregs, | 730 | .dumpregs = sdhci_pci_dumpregs, |
737 | }; | 731 | }; |
@@ -1716,6 +1710,9 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( | |||
1716 | if (device_can_wakeup(&pdev->dev)) | 1710 | if (device_can_wakeup(&pdev->dev)) |
1717 | host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | 1711 | host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; |
1718 | 1712 | ||
1713 | if (host->mmc->caps & MMC_CAP_CD_WAKE) | ||
1714 | device_init_wakeup(&pdev->dev, true); | ||
1715 | |||
1719 | if (slot->cd_idx >= 0) { | 1716 | if (slot->cd_idx >= 0) { |
1720 | ret = mmc_gpiod_request_cd(host->mmc, NULL, slot->cd_idx, | 1717 | ret = mmc_gpiod_request_cd(host->mmc, NULL, slot->cd_idx, |
1721 | slot->cd_override_level, 0, NULL); | 1718 | slot->cd_override_level, 0, NULL); |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2020e57ffa7e..2ededa7f43df 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -2899,6 +2899,14 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) | |||
2899 | \*****************************************************************************/ | 2899 | \*****************************************************************************/ |
2900 | 2900 | ||
2901 | #ifdef CONFIG_PM | 2901 | #ifdef CONFIG_PM |
2902 | |||
2903 | static bool sdhci_cd_irq_can_wakeup(struct sdhci_host *host) | ||
2904 | { | ||
2905 | return mmc_card_is_removable(host->mmc) && | ||
2906 | !(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && | ||
2907 | !mmc_can_gpio_cd(host->mmc); | ||
2908 | } | ||
2909 | |||
2902 | /* | 2910 | /* |
2903 | * To enable wakeup events, the corresponding events have to be enabled in | 2911 | * To enable wakeup events, the corresponding events have to be enabled in |
2904 | * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal | 2912 | * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal |
@@ -2915,13 +2923,18 @@ static bool sdhci_enable_irq_wakeups(struct sdhci_host *host) | |||
2915 | u8 wake_val = 0; | 2923 | u8 wake_val = 0; |
2916 | u8 val; | 2924 | u8 val; |
2917 | 2925 | ||
2918 | if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)) { | 2926 | if (sdhci_cd_irq_can_wakeup(host)) { |
2919 | wake_val |= SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE; | 2927 | wake_val |= SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE; |
2920 | irq_val |= SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE; | 2928 | irq_val |= SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE; |
2921 | } | 2929 | } |
2922 | 2930 | ||
2923 | wake_val |= SDHCI_WAKE_ON_INT; | 2931 | if (mmc_card_wake_sdio_irq(host->mmc)) { |
2924 | irq_val |= SDHCI_INT_CARD_INT; | 2932 | wake_val |= SDHCI_WAKE_ON_INT; |
2933 | irq_val |= SDHCI_INT_CARD_INT; | ||
2934 | } | ||
2935 | |||
2936 | if (!irq_val) | ||
2937 | return false; | ||
2925 | 2938 | ||
2926 | val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); | 2939 | val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); |
2927 | val &= ~mask; | 2940 | val &= ~mask; |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 7bb00c68a756..4c2a1f8ddbf3 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -7,13 +7,6 @@ | |||
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License. | 9 | * the Free Software Foundation; either version 2 of the License. |
10 | * | ||
11 | * | ||
12 | * TODO | ||
13 | * 1. DMA | ||
14 | * 2. Power management | ||
15 | * 3. Handle MMC errors better | ||
16 | * | ||
17 | */ | 10 | */ |
18 | 11 | ||
19 | /* | 12 | /* |
@@ -67,7 +60,6 @@ | |||
67 | #include <linux/module.h> | 60 | #include <linux/module.h> |
68 | 61 | ||
69 | #define DRIVER_NAME "sh_mmcif" | 62 | #define DRIVER_NAME "sh_mmcif" |
70 | #define DRIVER_VERSION "2010-04-28" | ||
71 | 63 | ||
72 | /* CE_CMD_SET */ | 64 | /* CE_CMD_SET */ |
73 | #define CMD_MASK 0x3f000000 | 65 | #define CMD_MASK 0x3f000000 |
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index bad612d6f879..20cfb20418f3 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c | |||
@@ -268,6 +268,7 @@ struct sunxi_mmc_cfg { | |||
268 | }; | 268 | }; |
269 | 269 | ||
270 | struct sunxi_mmc_host { | 270 | struct sunxi_mmc_host { |
271 | struct device *dev; | ||
271 | struct mmc_host *mmc; | 272 | struct mmc_host *mmc; |
272 | struct reset_control *reset; | 273 | struct reset_control *reset; |
273 | const struct sunxi_mmc_cfg *cfg; | 274 | const struct sunxi_mmc_cfg *cfg; |
@@ -1165,6 +1166,80 @@ static const struct of_device_id sunxi_mmc_of_match[] = { | |||
1165 | }; | 1166 | }; |
1166 | MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); | 1167 | MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); |
1167 | 1168 | ||
1169 | static int sunxi_mmc_enable(struct sunxi_mmc_host *host) | ||
1170 | { | ||
1171 | int ret; | ||
1172 | |||
1173 | if (!IS_ERR(host->reset)) { | ||
1174 | ret = reset_control_reset(host->reset); | ||
1175 | if (ret) { | ||
1176 | dev_err(host->dev, "Couldn't reset the MMC controller (%d)\n", | ||
1177 | ret); | ||
1178 | return ret; | ||
1179 | } | ||
1180 | } | ||
1181 | |||
1182 | ret = clk_prepare_enable(host->clk_ahb); | ||
1183 | if (ret) { | ||
1184 | dev_err(host->dev, "Couldn't enable the bus clocks (%d)\n", ret); | ||
1185 | goto error_assert_reset; | ||
1186 | } | ||
1187 | |||
1188 | ret = clk_prepare_enable(host->clk_mmc); | ||
1189 | if (ret) { | ||
1190 | dev_err(host->dev, "Enable mmc clk err %d\n", ret); | ||
1191 | goto error_disable_clk_ahb; | ||
1192 | } | ||
1193 | |||
1194 | ret = clk_prepare_enable(host->clk_output); | ||
1195 | if (ret) { | ||
1196 | dev_err(host->dev, "Enable output clk err %d\n", ret); | ||
1197 | goto error_disable_clk_mmc; | ||
1198 | } | ||
1199 | |||
1200 | ret = clk_prepare_enable(host->clk_sample); | ||
1201 | if (ret) { | ||
1202 | dev_err(host->dev, "Enable sample clk err %d\n", ret); | ||
1203 | goto error_disable_clk_output; | ||
1204 | } | ||
1205 | |||
1206 | /* | ||
1207 | * Sometimes the controller asserts the irq on boot for some reason, | ||
1208 | * make sure the controller is in a sane state before enabling irqs. | ||
1209 | */ | ||
1210 | ret = sunxi_mmc_reset_host(host); | ||
1211 | if (ret) | ||
1212 | goto error_disable_clk_sample; | ||
1213 | |||
1214 | return 0; | ||
1215 | |||
1216 | error_disable_clk_sample: | ||
1217 | clk_disable_unprepare(host->clk_sample); | ||
1218 | error_disable_clk_output: | ||
1219 | clk_disable_unprepare(host->clk_output); | ||
1220 | error_disable_clk_mmc: | ||
1221 | clk_disable_unprepare(host->clk_mmc); | ||
1222 | error_disable_clk_ahb: | ||
1223 | clk_disable_unprepare(host->clk_ahb); | ||
1224 | error_assert_reset: | ||
1225 | if (!IS_ERR(host->reset)) | ||
1226 | reset_control_assert(host->reset); | ||
1227 | return ret; | ||
1228 | } | ||
1229 | |||
1230 | static void sunxi_mmc_disable(struct sunxi_mmc_host *host) | ||
1231 | { | ||
1232 | sunxi_mmc_reset_host(host); | ||
1233 | |||
1234 | clk_disable_unprepare(host->clk_sample); | ||
1235 | clk_disable_unprepare(host->clk_output); | ||
1236 | clk_disable_unprepare(host->clk_mmc); | ||
1237 | clk_disable_unprepare(host->clk_ahb); | ||
1238 | |||
1239 | if (!IS_ERR(host->reset)) | ||
1240 | reset_control_assert(host->reset); | ||
1241 | } | ||
1242 | |||
1168 | static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, | 1243 | static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, |
1169 | struct platform_device *pdev) | 1244 | struct platform_device *pdev) |
1170 | { | 1245 | { |
@@ -1214,66 +1289,21 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, | |||
1214 | if (PTR_ERR(host->reset) == -EPROBE_DEFER) | 1289 | if (PTR_ERR(host->reset) == -EPROBE_DEFER) |
1215 | return PTR_ERR(host->reset); | 1290 | return PTR_ERR(host->reset); |
1216 | 1291 | ||
1217 | ret = clk_prepare_enable(host->clk_ahb); | 1292 | ret = sunxi_mmc_enable(host); |
1218 | if (ret) { | ||
1219 | dev_err(&pdev->dev, "Enable ahb clk err %d\n", ret); | ||
1220 | return ret; | ||
1221 | } | ||
1222 | |||
1223 | ret = clk_prepare_enable(host->clk_mmc); | ||
1224 | if (ret) { | ||
1225 | dev_err(&pdev->dev, "Enable mmc clk err %d\n", ret); | ||
1226 | goto error_disable_clk_ahb; | ||
1227 | } | ||
1228 | |||
1229 | ret = clk_prepare_enable(host->clk_output); | ||
1230 | if (ret) { | ||
1231 | dev_err(&pdev->dev, "Enable output clk err %d\n", ret); | ||
1232 | goto error_disable_clk_mmc; | ||
1233 | } | ||
1234 | |||
1235 | ret = clk_prepare_enable(host->clk_sample); | ||
1236 | if (ret) { | ||
1237 | dev_err(&pdev->dev, "Enable sample clk err %d\n", ret); | ||
1238 | goto error_disable_clk_output; | ||
1239 | } | ||
1240 | |||
1241 | if (!IS_ERR(host->reset)) { | ||
1242 | ret = reset_control_reset(host->reset); | ||
1243 | if (ret) { | ||
1244 | dev_err(&pdev->dev, "reset err %d\n", ret); | ||
1245 | goto error_disable_clk_sample; | ||
1246 | } | ||
1247 | } | ||
1248 | |||
1249 | /* | ||
1250 | * Sometimes the controller asserts the irq on boot for some reason, | ||
1251 | * make sure the controller is in a sane state before enabling irqs. | ||
1252 | */ | ||
1253 | ret = sunxi_mmc_reset_host(host); | ||
1254 | if (ret) | 1293 | if (ret) |
1255 | goto error_assert_reset; | 1294 | return ret; |
1256 | 1295 | ||
1257 | host->irq = platform_get_irq(pdev, 0); | 1296 | host->irq = platform_get_irq(pdev, 0); |
1258 | if (host->irq <= 0) { | 1297 | if (host->irq <= 0) { |
1259 | ret = -EINVAL; | 1298 | ret = -EINVAL; |
1260 | goto error_assert_reset; | 1299 | goto error_disable_mmc; |
1261 | } | 1300 | } |
1262 | 1301 | ||
1263 | return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq, | 1302 | return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq, |
1264 | sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host); | 1303 | sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host); |
1265 | 1304 | ||
1266 | error_assert_reset: | 1305 | error_disable_mmc: |
1267 | if (!IS_ERR(host->reset)) | 1306 | sunxi_mmc_disable(host); |
1268 | reset_control_assert(host->reset); | ||
1269 | error_disable_clk_sample: | ||
1270 | clk_disable_unprepare(host->clk_sample); | ||
1271 | error_disable_clk_output: | ||
1272 | clk_disable_unprepare(host->clk_output); | ||
1273 | error_disable_clk_mmc: | ||
1274 | clk_disable_unprepare(host->clk_mmc); | ||
1275 | error_disable_clk_ahb: | ||
1276 | clk_disable_unprepare(host->clk_ahb); | ||
1277 | return ret; | 1307 | return ret; |
1278 | } | 1308 | } |
1279 | 1309 | ||
@@ -1288,8 +1318,10 @@ static int sunxi_mmc_probe(struct platform_device *pdev) | |||
1288 | dev_err(&pdev->dev, "mmc alloc host failed\n"); | 1318 | dev_err(&pdev->dev, "mmc alloc host failed\n"); |
1289 | return -ENOMEM; | 1319 | return -ENOMEM; |
1290 | } | 1320 | } |
1321 | platform_set_drvdata(pdev, mmc); | ||
1291 | 1322 | ||
1292 | host = mmc_priv(mmc); | 1323 | host = mmc_priv(mmc); |
1324 | host->dev = &pdev->dev; | ||
1293 | host->mmc = mmc; | 1325 | host->mmc = mmc; |
1294 | spin_lock_init(&host->lock); | 1326 | spin_lock_init(&host->lock); |
1295 | 1327 | ||
@@ -1353,7 +1385,6 @@ static int sunxi_mmc_probe(struct platform_device *pdev) | |||
1353 | goto error_free_dma; | 1385 | goto error_free_dma; |
1354 | 1386 | ||
1355 | dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); | 1387 | dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); |
1356 | platform_set_drvdata(pdev, mmc); | ||
1357 | return 0; | 1388 | return 0; |
1358 | 1389 | ||
1359 | error_free_dma: | 1390 | error_free_dma: |
@@ -1370,16 +1401,7 @@ static int sunxi_mmc_remove(struct platform_device *pdev) | |||
1370 | 1401 | ||
1371 | mmc_remove_host(mmc); | 1402 | mmc_remove_host(mmc); |
1372 | disable_irq(host->irq); | 1403 | disable_irq(host->irq); |
1373 | sunxi_mmc_reset_host(host); | 1404 | sunxi_mmc_disable(host); |
1374 | |||
1375 | if (!IS_ERR(host->reset)) | ||
1376 | reset_control_assert(host->reset); | ||
1377 | |||
1378 | clk_disable_unprepare(host->clk_sample); | ||
1379 | clk_disable_unprepare(host->clk_output); | ||
1380 | clk_disable_unprepare(host->clk_mmc); | ||
1381 | clk_disable_unprepare(host->clk_ahb); | ||
1382 | |||
1383 | dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); | 1405 | dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); |
1384 | mmc_free_host(mmc); | 1406 | mmc_free_host(mmc); |
1385 | 1407 | ||
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 33494241245a..e30df9ad8197 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c | |||
@@ -278,7 +278,6 @@ static void tmio_mmc_reset_work(struct work_struct *work) | |||
278 | 278 | ||
279 | host->cmd = NULL; | 279 | host->cmd = NULL; |
280 | host->data = NULL; | 280 | host->data = NULL; |
281 | host->force_pio = false; | ||
282 | 281 | ||
283 | spin_unlock_irqrestore(&host->lock, flags); | 282 | spin_unlock_irqrestore(&host->lock, flags); |
284 | 283 | ||
@@ -350,8 +349,6 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, | |||
350 | c |= TRANSFER_READ; | 349 | c |= TRANSFER_READ; |
351 | } | 350 | } |
352 | 351 | ||
353 | if (!host->native_hotplug) | ||
354 | irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); | ||
355 | tmio_mmc_enable_mmc_irqs(host, irq_mask); | 352 | tmio_mmc_enable_mmc_irqs(host, irq_mask); |
356 | 353 | ||
357 | /* Fire off the command */ | 354 | /* Fire off the command */ |
@@ -623,15 +620,21 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, unsigned int stat) | |||
623 | */ | 620 | */ |
624 | if (host->data && (!cmd->error || cmd->error == -EILSEQ)) { | 621 | if (host->data && (!cmd->error || cmd->error == -EILSEQ)) { |
625 | if (host->data->flags & MMC_DATA_READ) { | 622 | if (host->data->flags & MMC_DATA_READ) { |
626 | if (host->force_pio || !host->chan_rx) | 623 | if (host->force_pio || !host->chan_rx) { |
627 | tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_READOP); | 624 | tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_READOP); |
628 | else | 625 | } else { |
626 | tmio_mmc_disable_mmc_irqs(host, | ||
627 | TMIO_MASK_READOP); | ||
629 | tasklet_schedule(&host->dma_issue); | 628 | tasklet_schedule(&host->dma_issue); |
629 | } | ||
630 | } else { | 630 | } else { |
631 | if (host->force_pio || !host->chan_tx) | 631 | if (host->force_pio || !host->chan_tx) { |
632 | tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_WRITEOP); | 632 | tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_WRITEOP); |
633 | else | 633 | } else { |
634 | tmio_mmc_disable_mmc_irqs(host, | ||
635 | TMIO_MASK_WRITEOP); | ||
634 | tasklet_schedule(&host->dma_issue); | 636 | tasklet_schedule(&host->dma_issue); |
637 | } | ||
635 | } | 638 | } |
636 | } else { | 639 | } else { |
637 | schedule_work(&host->done); | 640 | schedule_work(&host->done); |
@@ -755,6 +758,7 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host, | |||
755 | 758 | ||
756 | tmio_mmc_init_sg(host, data); | 759 | tmio_mmc_init_sg(host, data); |
757 | host->data = data; | 760 | host->data = data; |
761 | host->force_pio = false; | ||
758 | 762 | ||
759 | /* Set transfer length / blocksize */ | 763 | /* Set transfer length / blocksize */ |
760 | sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz); | 764 | sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz); |
@@ -846,7 +850,6 @@ static void tmio_process_mrq(struct tmio_mmc_host *host, | |||
846 | return; | 850 | return; |
847 | 851 | ||
848 | fail: | 852 | fail: |
849 | host->force_pio = false; | ||
850 | host->mrq = NULL; | 853 | host->mrq = NULL; |
851 | mrq->cmd->error = ret; | 854 | mrq->cmd->error = ret; |
852 | mmc_request_done(host->mmc, mrq); | 855 | mmc_request_done(host->mmc, mrq); |
@@ -896,7 +899,6 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) | |||
896 | if (host->cmd != mrq->sbc) { | 899 | if (host->cmd != mrq->sbc) { |
897 | host->cmd = NULL; | 900 | host->cmd = NULL; |
898 | host->data = NULL; | 901 | host->data = NULL; |
899 | host->force_pio = false; | ||
900 | host->mrq = NULL; | 902 | host->mrq = NULL; |
901 | } | 903 | } |
902 | 904 | ||
@@ -1061,10 +1063,17 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1061 | static int tmio_mmc_get_ro(struct mmc_host *mmc) | 1063 | static int tmio_mmc_get_ro(struct mmc_host *mmc) |
1062 | { | 1064 | { |
1063 | struct tmio_mmc_host *host = mmc_priv(mmc); | 1065 | struct tmio_mmc_host *host = mmc_priv(mmc); |
1064 | struct tmio_mmc_data *pdata = host->pdata; | ||
1065 | 1066 | ||
1066 | return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || | 1067 | return !(sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) & |
1067 | (sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); | 1068 | TMIO_STAT_WRPROTECT); |
1069 | } | ||
1070 | |||
1071 | static int tmio_mmc_get_cd(struct mmc_host *mmc) | ||
1072 | { | ||
1073 | struct tmio_mmc_host *host = mmc_priv(mmc); | ||
1074 | |||
1075 | return !!(sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) & | ||
1076 | TMIO_STAT_SIGSTATE); | ||
1068 | } | 1077 | } |
1069 | 1078 | ||
1070 | static int tmio_multi_io_quirk(struct mmc_card *card, | 1079 | static int tmio_multi_io_quirk(struct mmc_card *card, |
@@ -1082,7 +1091,7 @@ static const struct mmc_host_ops tmio_mmc_ops = { | |||
1082 | .request = tmio_mmc_request, | 1091 | .request = tmio_mmc_request, |
1083 | .set_ios = tmio_mmc_set_ios, | 1092 | .set_ios = tmio_mmc_set_ios, |
1084 | .get_ro = tmio_mmc_get_ro, | 1093 | .get_ro = tmio_mmc_get_ro, |
1085 | .get_cd = mmc_gpio_get_cd, | 1094 | .get_cd = tmio_mmc_get_cd, |
1086 | .enable_sdio_irq = tmio_mmc_enable_sdio_irq, | 1095 | .enable_sdio_irq = tmio_mmc_enable_sdio_irq, |
1087 | .multi_io_quirk = tmio_multi_io_quirk, | 1096 | .multi_io_quirk = tmio_multi_io_quirk, |
1088 | .hw_reset = tmio_mmc_hw_reset, | 1097 | .hw_reset = tmio_mmc_hw_reset, |
@@ -1114,15 +1123,20 @@ static int tmio_mmc_init_ocr(struct tmio_mmc_host *host) | |||
1114 | } | 1123 | } |
1115 | 1124 | ||
1116 | static void tmio_mmc_of_parse(struct platform_device *pdev, | 1125 | static void tmio_mmc_of_parse(struct platform_device *pdev, |
1117 | struct tmio_mmc_data *pdata) | 1126 | struct mmc_host *mmc) |
1118 | { | 1127 | { |
1119 | const struct device_node *np = pdev->dev.of_node; | 1128 | const struct device_node *np = pdev->dev.of_node; |
1120 | 1129 | ||
1121 | if (!np) | 1130 | if (!np) |
1122 | return; | 1131 | return; |
1123 | 1132 | ||
1133 | /* | ||
1134 | * DEPRECATED: | ||
1135 | * For new platforms, please use "disable-wp" instead of | ||
1136 | * "toshiba,mmc-wrprotect-disable" | ||
1137 | */ | ||
1124 | if (of_get_property(np, "toshiba,mmc-wrprotect-disable", NULL)) | 1138 | if (of_get_property(np, "toshiba,mmc-wrprotect-disable", NULL)) |
1125 | pdata->flags |= TMIO_MMC_WRPROTECT_DISABLE; | 1139 | mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; |
1126 | } | 1140 | } |
1127 | 1141 | ||
1128 | struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev, | 1142 | struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev, |
@@ -1157,7 +1171,7 @@ struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev, | |||
1157 | goto free; | 1171 | goto free; |
1158 | } | 1172 | } |
1159 | 1173 | ||
1160 | tmio_mmc_of_parse(pdev, pdata); | 1174 | tmio_mmc_of_parse(pdev, mmc); |
1161 | 1175 | ||
1162 | platform_set_drvdata(pdev, host); | 1176 | platform_set_drvdata(pdev, host); |
1163 | 1177 | ||
@@ -1181,7 +1195,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) | |||
1181 | struct tmio_mmc_data *pdata = _host->pdata; | 1195 | struct tmio_mmc_data *pdata = _host->pdata; |
1182 | struct mmc_host *mmc = _host->mmc; | 1196 | struct mmc_host *mmc = _host->mmc; |
1183 | int ret; | 1197 | int ret; |
1184 | u32 irq_mask = TMIO_MASK_CMD; | ||
1185 | 1198 | ||
1186 | /* | 1199 | /* |
1187 | * Check the sanity of mmc->f_min to prevent tmio_mmc_set_clock() from | 1200 | * Check the sanity of mmc->f_min to prevent tmio_mmc_set_clock() from |
@@ -1230,6 +1243,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) | |||
1230 | if (mmc_can_gpio_ro(mmc)) | 1243 | if (mmc_can_gpio_ro(mmc)) |
1231 | _host->ops.get_ro = mmc_gpio_get_ro; | 1244 | _host->ops.get_ro = mmc_gpio_get_ro; |
1232 | 1245 | ||
1246 | if (mmc_can_gpio_cd(mmc)) | ||
1247 | _host->ops.get_cd = mmc_gpio_get_cd; | ||
1248 | |||
1233 | _host->native_hotplug = !(mmc_can_gpio_cd(mmc) || | 1249 | _host->native_hotplug = !(mmc_can_gpio_cd(mmc) || |
1234 | mmc->caps & MMC_CAP_NEEDS_POLL || | 1250 | mmc->caps & MMC_CAP_NEEDS_POLL || |
1235 | !mmc_card_is_removable(mmc)); | 1251 | !mmc_card_is_removable(mmc)); |
@@ -1260,15 +1276,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) | |||
1260 | _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); | 1276 | _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); |
1261 | tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); | 1277 | tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); |
1262 | 1278 | ||
1263 | /* Unmask the IRQs we want to know about */ | 1279 | if (_host->native_hotplug) |
1264 | if (!_host->chan_rx) | 1280 | tmio_mmc_enable_mmc_irqs(_host, |
1265 | irq_mask |= TMIO_MASK_READOP; | 1281 | TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); |
1266 | if (!_host->chan_tx) | ||
1267 | irq_mask |= TMIO_MASK_WRITEOP; | ||
1268 | if (!_host->native_hotplug) | ||
1269 | irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); | ||
1270 | |||
1271 | _host->sdcard_irq_mask &= ~irq_mask; | ||
1272 | 1282 | ||
1273 | spin_lock_init(&_host->lock); | 1283 | spin_lock_init(&_host->lock); |
1274 | mutex_init(&_host->ios_lock); | 1284 | mutex_init(&_host->ios_lock); |
@@ -1367,6 +1377,10 @@ int tmio_mmc_host_runtime_resume(struct device *dev) | |||
1367 | if (host->clk_cache) | 1377 | if (host->clk_cache) |
1368 | tmio_mmc_set_clock(host, host->clk_cache); | 1378 | tmio_mmc_set_clock(host, host->clk_cache); |
1369 | 1379 | ||
1380 | if (host->native_hotplug) | ||
1381 | tmio_mmc_enable_mmc_irqs(host, | ||
1382 | TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); | ||
1383 | |||
1370 | tmio_mmc_enable_dma(host, true); | 1384 | tmio_mmc_enable_dma(host, true); |
1371 | 1385 | ||
1372 | if (tmio_mmc_can_retune(host) && host->select_tuning(host)) | 1386 | if (tmio_mmc_can_retune(host) && host->select_tuning(host)) |
diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c index 1d843357422e..81dac17064d7 100644 --- a/drivers/mmc/host/ushc.c +++ b/drivers/mmc/host/ushc.c | |||
@@ -309,8 +309,6 @@ static void ushc_request(struct mmc_host *mmc, struct mmc_request *req) | |||
309 | 309 | ||
310 | /* Submit CSW. */ | 310 | /* Submit CSW. */ |
311 | ret = usb_submit_urb(ushc->csw_urb, GFP_ATOMIC); | 311 | ret = usb_submit_urb(ushc->csw_urb, GFP_ATOMIC); |
312 | if (ret < 0) | ||
313 | goto out; | ||
314 | 312 | ||
315 | out: | 313 | out: |
316 | spin_unlock_irqrestore(&ushc->lock, flags); | 314 | spin_unlock_irqrestore(&ushc->lock, flags); |
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 396a103c8bc6..91f92215ca74 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h | |||
@@ -36,7 +36,6 @@ | |||
36 | } while (0) | 36 | } while (0) |
37 | 37 | ||
38 | /* tmio MMC platform flags */ | 38 | /* tmio MMC platform flags */ |
39 | #define TMIO_MMC_WRPROTECT_DISABLE BIT(0) | ||
40 | /* | 39 | /* |
41 | * Some controllers can support a 2-byte block size when the bus width | 40 | * Some controllers can support a 2-byte block size when the bus width |
42 | * is configured in 4-bit mode. | 41 | * is configured in 4-bit mode. |
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h index 91f1ba0663c8..06607c59c4d0 100644 --- a/include/linux/mmc/slot-gpio.h +++ b/include/linux/mmc/slot-gpio.h | |||
@@ -31,6 +31,7 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, | |||
31 | unsigned int debounce, bool *gpio_invert); | 31 | unsigned int debounce, bool *gpio_invert); |
32 | void mmc_gpio_set_cd_isr(struct mmc_host *host, | 32 | void mmc_gpio_set_cd_isr(struct mmc_host *host, |
33 | irqreturn_t (*isr)(int irq, void *dev_id)); | 33 | irqreturn_t (*isr)(int irq, void *dev_id)); |
34 | int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on); | ||
34 | void mmc_gpiod_request_cd_irq(struct mmc_host *host); | 35 | void mmc_gpiod_request_cd_irq(struct mmc_host *host); |
35 | bool mmc_can_gpio_cd(struct mmc_host *host); | 36 | bool mmc_can_gpio_cd(struct mmc_host *host); |
36 | bool mmc_can_gpio_ro(struct mmc_host *host); | 37 | bool mmc_can_gpio_ro(struct mmc_host *host); |