diff options
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); |
