Commit dc73d6a8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mmc-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC updates from Ulf Hansson:
 "MMC core:
   - Export host capabilities through debugfs
   - Export card RCA register via sysfs
   - Improve card initializing sequence while enabling 4-bit bus
   - Export a function to enable/disable wakeup for card detect IRQ

  MMC host:
   - dw_mmc: Add support for new hi3798cv200 variant
   - dw_mmc: Remove support for some deprecated DT properties
   - mediatek: Add support for new variant used on MT7622 SoC
   - sdhci: Improve wakeup support for SDIO IRQs
   - sdhci: Improve wakeup support for card detect IRQs
   - sdhci-omap: Add tuning support
   - sdhci_omap: Add UHS-I mode support
   - sunxi: Prepare for runtime PM support via a few re-factorings
   - tmio: deprecate "toshiba,mmc-wrprotect-disable" DT property
   - tmio/renesas_sdhi: Consolidate code supporting write protect
   - tmio: Improve DMA vs PIO handling
   - tmio: Add support for IP-builtin card detection logic"

* tag 'mmc-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (55 commits)
  mmc: renesas_sdhi: replace EXT_ACC with HOST_MODE
  mmc: update sdio_claim_irq documentation
  mmc: Export host capabilities to debugfs.
  mmc: core: Disable HPI for certain Micron (Numonyx) eMMC cards
  mmc: block: fix updating ext_csd caches on ioctl call
  mmc: sunxi: Set our device drvdata earlier
  mmc: sunxi: Move the reset deassertion before enabling the clocks
  mmc: sunxi: Move resources management to separate functions
  mmc: dw_mmc: add support for hi3798cv200 specific extensions of dw-mshc
  dt-bindings: mmc: add bindings for hi3798cv200-dw-mshc
  mmc: core: Export card RCA register via sysfs
  mmc: renesas_sdhi: fix WP detection
  mmc: core: Use memdup_user() rather than duplicating its implementation
  mmc: dw_mmc-rockchip: correct property names in debug
  mmc: sd: Remove redundant err assignment from mmc_read_switch
  mmc: sdio: Check the return value of sdio_enable_4bit_bus
  mmc: core: Don't try UHS-I mode if 4-bit mode isn't supported
  arm64: dts: hi3660: remove 'num-slots' property for dwmmc
  ARM: dts: lpc18xx: remove 'num-slots' property for dwmmc
  arm64: dts: stratix10: remove 'num-slots' property for dwmmc
  ...
parents dabe5184 4472f0fc
* Hisilicon Hi3798CV200 specific extensions to the Synopsys Designware Mobile
Storage Host Controller
Read synopsys-dw-mshc.txt for more details
The Synopsys designware mobile storage host controller is used to interface
a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
differences between the core Synopsys dw mshc controller properties described
by synopsys-dw-mshc.txt and the properties used by the Hisilicon Hi3798CV200
specific extensions to the Synopsys Designware Mobile Storage Host Controller.
Required Properties:
- compatible: Should contain "hisilicon,hi3798cv200-dw-mshc".
- clocks: A list of phandle + clock-specifier pairs for the clocks listed
in clock-names.
- clock-names: Should contain the following:
"ciu" - The ciu clock described in synopsys-dw-mshc.txt.
"biu" - The biu clock described in synopsys-dw-mshc.txt.
"ciu-sample" - Hi3798CV200 extended phase clock for ciu sampling.
"ciu-drive" - Hi3798CV200 extended phase clock for ciu driving.
Example:
emmc: mmc@9830000 {
compatible = "hisilicon,hi3798cv200-dw-mshc";
reg = <0x9830000 0x10000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&crg HISTB_MMC_CIU_CLK>,
<&crg HISTB_MMC_BIU_CLK>,
<&crg HISTB_MMC_SAMPLE_CLK>,
<&crg HISTB_MMC_DRV_CLK>;
clock-names = "ciu", "biu", "ciu-sample", "ciu-drive";
fifo-depth = <256>;
clock-frequency = <200000000>;
cap-mmc-highspeed;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
non-removable;
bus-width = <8>;
};
...@@ -12,6 +12,7 @@ Required properties: ...@@ -12,6 +12,7 @@ Required properties:
"mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173
"mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701
"mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712
"mediatek,mt7622-mmc": for MT7622 SoC
"mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC
- reg: physical base address of the controller and length - reg: physical base address of the controller and length
......
...@@ -59,15 +59,6 @@ Optional properties: ...@@ -59,15 +59,6 @@ Optional properties:
is specified and the ciu clock is specified then we'll try to set the ciu is specified and the ciu clock is specified then we'll try to set the ciu
clock to this at probe time. clock to this at probe time.
* clock-freq-min-max (DEPRECATED): Minimum and Maximum clock frequency for card output
clock(cclk_out). If it's not specified, max is 200MHZ and min is 400KHz by default.
(Use the "max-frequency" instead of "clock-freq-min-max".)
* num-slots (DEPRECATED): specifies the number of slots supported by the controller.
The number of physical slots actually used could be equal or less than the
value specified by num-slots. If this property is not specified, the value
of num-slot property is assumed to be 1.
* fifo-depth: The maximum size of the tx/rx fifo's. If this property is not * fifo-depth: The maximum size of the tx/rx fifo's. If this property is not
specified, the default value of the fifo size is determined from the specified, the default value of the fifo size is determined from the
controller registers. controller registers.
......
...@@ -50,7 +50,6 @@ Required properties: ...@@ -50,7 +50,6 @@ Required properties:
2: R7S72100 2: R7S72100
Optional properties: Optional properties:
- toshiba,mmc-wrprotect-disable: write-protect detection is unavailable
- pinctrl-names: should be "default", "state_uhs" - pinctrl-names: should be "default", "state_uhs"
- pinctrl-0: should contain default/high speed pin ctrl - pinctrl-0: should contain default/high speed pin ctrl
- pinctrl-1: should contain uhs mode pin ctrl - pinctrl-1: should contain uhs mode pin ctrl
......
...@@ -115,7 +115,6 @@ ...@@ -115,7 +115,6 @@
compatible = "snps,dw-mshc"; compatible = "snps,dw-mshc";
reg = <0x40004000 0x1000>; reg = <0x40004000 0x1000>;
interrupts = <6>; interrupts = <6>;
num-slots = <1>;
clocks = <&ccu2 CLK_SDIO>, <&ccu1 CLK_CPU_SDIO>; clocks = <&ccu2 CLK_SDIO>, <&ccu1 CLK_CPU_SDIO>;
clock-names = "ciu", "biu"; clock-names = "ciu", "biu";
resets = <&rgu 20>; resets = <&rgu 20>;
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
&mmc { &mmc {
status = "okay"; status = "okay";
num-slots = <1>;
cap-sd-highspeed; cap-sd-highspeed;
broken-cd; broken-cd;
bus-width = <4>; bus-width = <4>;
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
}; };
mmc0: dwmmc0@ff704000 { mmc0: dwmmc0@ff704000 {
num-slots = <1>;
broken-cd; broken-cd;
bus-width = <4>; bus-width = <4>;
cap-mmc-highspeed; cap-mmc-highspeed;
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
}; };
mmc0: dwmmc0@ff704000 { mmc0: dwmmc0@ff704000 {
num-slots = <1>;
broken-cd; broken-cd;
bus-width = <4>; bus-width = <4>;
cap-mmc-highspeed; cap-mmc-highspeed;
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
}; };
dwmmc0@ff704000 { dwmmc0@ff704000 {
num-slots = <1>;
broken-cd; broken-cd;
bus-width = <4>; bus-width = <4>;
cap-mmc-highspeed; cap-mmc-highspeed;
......
...@@ -88,7 +88,6 @@ ...@@ -88,7 +88,6 @@
&mmc { &mmc {
status = "okay"; status = "okay";
num-slots = <1>;
cap-sd-highspeed; cap-sd-highspeed;
broken-cd; broken-cd;
bus-width = <4>; bus-width = <4>;
......
...@@ -922,7 +922,6 @@ ...@@ -922,7 +922,6 @@
#size-cells = <0>; #size-cells = <0>;
cd-inverted; cd-inverted;
compatible = "hisilicon,hi3660-dw-mshc"; compatible = "hisilicon,hi3660-dw-mshc";
num-slots = <1>;
bus-width = <0x4>; bus-width = <0x4>;
disable-wp; disable-wp;
cap-sd-highspeed; cap-sd-highspeed;
...@@ -960,7 +959,6 @@ ...@@ -960,7 +959,6 @@
compatible = "hisilicon,hi3660-dw-mshc"; compatible = "hisilicon,hi3660-dw-mshc";
reg = <0x0 0xff3ff000 0x0 0x1000>; reg = <0x0 0xff3ff000 0x0 0x1000>;
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
num-slots = <1>;
clocks = <&crg_ctrl HI3660_CLK_GATE_SDIO0>, clocks = <&crg_ctrl HI3660_CLK_GATE_SDIO0>,
<&crg_ctrl HI3660_HCLK_GATE_SDIO0>; <&crg_ctrl HI3660_HCLK_GATE_SDIO0>;
clock-names = "ciu", "biu"; clock-names = "ciu", "biu";
......
...@@ -375,8 +375,8 @@ static struct resource kfr2r09_sh_sdhi0_resources[] = { ...@@ -375,8 +375,8 @@ static struct resource kfr2r09_sh_sdhi0_resources[] = {
static struct tmio_mmc_data sh7724_sdhi0_data = { static struct tmio_mmc_data sh7724_sdhi0_data = {
.chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
.chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
.flags = TMIO_MMC_WRPROTECT_DISABLE,
.capabilities = MMC_CAP_SDIO_IRQ, .capabilities = MMC_CAP_SDIO_IRQ,
.capabilities2 = MMC_CAP2_NO_WRITE_PROTECT,
}; };
static struct platform_device kfr2r09_sh_sdhi0_device = { static struct platform_device kfr2r09_sh_sdhi0_device = {
......
...@@ -376,22 +376,15 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user( ...@@ -376,22 +376,15 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
return idata; return idata;
} }
idata->buf = kmalloc(idata->buf_bytes, GFP_KERNEL); idata->buf = memdup_user((void __user *)(unsigned long)
if (!idata->buf) { idata->ic.data_ptr, idata->buf_bytes);
err = -ENOMEM; if (IS_ERR(idata->buf)) {
err = PTR_ERR(idata->buf);
goto idata_err; goto idata_err;
} }
if (copy_from_user(idata->buf, (void __user *)(unsigned long)
idata->ic.data_ptr, idata->buf_bytes)) {
err = -EFAULT;
goto copy_err;
}
return idata; return idata;
copy_err:
kfree(idata->buf);
idata_err: idata_err:
kfree(idata); kfree(idata);
out: out:
......
...@@ -2369,7 +2369,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) ...@@ -2369,7 +2369,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
return card->pref_erase; return card->pref_erase;
max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG); max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG);
if (mmc_can_trim(card)) { if (max_discard && mmc_can_trim(card)) {
max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG); max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG);
if (max_trim < max_discard) if (max_trim < max_discard)
max_discard = max_trim; max_discard = max_trim;
...@@ -2655,8 +2655,7 @@ void mmc_start_host(struct mmc_host *host) ...@@ -2655,8 +2655,7 @@ void mmc_start_host(struct mmc_host *host)
void mmc_stop_host(struct mmc_host *host) void mmc_stop_host(struct mmc_host *host)
{ {
if (host->slot.cd_irq >= 0) { if (host->slot.cd_irq >= 0) {
if (host->slot.cd_wake_enabled) mmc_gpio_set_cd_wake(host, false);
disable_irq_wake(host->slot.cd_irq);
disable_irq(host->slot.cd_irq); disable_irq(host->slot.cd_irq);
} }
......
...@@ -196,18 +196,7 @@ static int mmc_ios_show(struct seq_file *s, void *data) ...@@ -196,18 +196,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
return 0; return 0;
} }
DEFINE_SHOW_ATTRIBUTE(mmc_ios);
static int mmc_ios_open(struct inode *inode, struct file *file)
{
return single_open(file, mmc_ios_show, inode->i_private);
}
static const struct file_operations mmc_ios_fops = {
.open = mmc_ios_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int mmc_clock_opt_get(void *data, u64 *val) static int mmc_clock_opt_get(void *data, u64 *val)
{ {
...@@ -254,6 +243,12 @@ void mmc_add_host_debugfs(struct mmc_host *host) ...@@ -254,6 +243,12 @@ void mmc_add_host_debugfs(struct mmc_host *host)
if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops))
goto err_node; goto err_node;
if (!debugfs_create_x32("caps", S_IRUSR, root, &host->caps))
goto err_node;
if (!debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2))
goto err_node;
if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host,
&mmc_clock_fops)) &mmc_clock_fops))
goto err_node; goto err_node;
......
...@@ -56,7 +56,8 @@ static inline int mmc_host_uhs(struct mmc_host *host) ...@@ -56,7 +56,8 @@ static inline int mmc_host_uhs(struct mmc_host *host)
return host->caps & return host->caps &
(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_DDR50); MMC_CAP_UHS_DDR50) &&
host->caps & MMC_CAP_4_BIT_DATA;
} }
static inline bool mmc_card_hs200(struct mmc_card *card) static inline bool mmc_card_hs200(struct mmc_card *card)
......
...@@ -792,6 +792,7 @@ MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); ...@@ -792,6 +792,7 @@ MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr);
MMC_DEV_ATTR(rca, "0x%04x\n", card->rca);
MMC_DEV_ATTR(cmdq_en, "%d\n", card->ext_csd.cmdq_en); MMC_DEV_ATTR(cmdq_en, "%d\n", card->ext_csd.cmdq_en);
static ssize_t mmc_fwrev_show(struct device *dev, static ssize_t mmc_fwrev_show(struct device *dev,
...@@ -848,6 +849,7 @@ static struct attribute *mmc_std_attrs[] = { ...@@ -848,6 +849,7 @@ static struct attribute *mmc_std_attrs[] = {
&dev_attr_raw_rpmb_size_mult.attr, &dev_attr_raw_rpmb_size_mult.attr,
&dev_attr_rel_sectors.attr, &dev_attr_rel_sectors.attr,
&dev_attr_ocr.attr, &dev_attr_ocr.attr,
&dev_attr_rca.attr,
&dev_attr_dsr.attr, &dev_attr_dsr.attr,
&dev_attr_cmdq_en.attr, &dev_attr_cmdq_en.attr,
NULL, NULL,
......
...@@ -291,8 +291,6 @@ static int mmc_read_switch(struct mmc_card *card) ...@@ -291,8 +291,6 @@ static int mmc_read_switch(struct mmc_card *card)
return 0; return 0;
} }
err = -EIO;
status = kmalloc(64, GFP_KERNEL); status = kmalloc(64, GFP_KERNEL);
if (!status) if (!status)
return -ENOMEM; return -ENOMEM;
...@@ -582,9 +580,6 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) ...@@ -582,9 +580,6 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
int err; int err;
u8 *status; u8 *status;
if (!card->scr.sda_spec3)
return 0;
if (!(card->csd.cmdclass & CCC_SWITCH)) if (!(card->csd.cmdclass & CCC_SWITCH))
return 0; return 0;
...@@ -593,14 +588,11 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) ...@@ -593,14 +588,11 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
return -ENOMEM; return -ENOMEM;
/* Set 4-bit bus width */ /* Set 4-bit bus width */
if ((card->host->caps & MMC_CAP_4_BIT_DATA) && err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { if (err)
err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); goto out;
if (err)
goto out;
mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
}
/* /*
* Select the bus speed mode depending on host * Select the bus speed mode depending on host
...@@ -676,6 +668,7 @@ MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); ...@@ -676,6 +668,7 @@ MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr);
MMC_DEV_ATTR(rca, "0x%04x\n", card->rca);
static ssize_t mmc_dsr_show(struct device *dev, static ssize_t mmc_dsr_show(struct device *dev,
...@@ -709,6 +702,7 @@ static struct attribute *sd_std_attrs[] = { ...@@ -709,6 +702,7 @@ static struct attribute *sd_std_attrs[] = {
&dev_attr_oemid.attr, &dev_attr_oemid.attr,
&dev_attr_serial.attr, &dev_attr_serial.attr,
&dev_attr_ocr.attr, &dev_attr_ocr.attr,
&dev_attr_rca.attr,
&dev_attr_dsr.attr, &dev_attr_dsr.attr,
NULL, NULL,
}; };
...@@ -1033,7 +1027,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, ...@@ -1033,7 +1027,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
} }
/* Initialization sequence for UHS-I cards */ /* Initialization sequence for UHS-I cards */
if (rocr & SD_ROCR_S18A) { if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) {
err = mmc_sd_init_uhs_card(card); err = mmc_sd_init_uhs_card(card);
if (err) if (err)
goto free_card; goto free_card;
......
...@@ -518,11 +518,10 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) ...@@ -518,11 +518,10 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card)
if (!card->scr.sda_spec3) if (!card->scr.sda_spec3)
return 0; return 0;
/* /* Switch to wider bus */
* Switch to wider bus (if supported). err = sdio_enable_4bit_bus(card);
*/ if (err)
if (card->host->caps & MMC_CAP_4_BIT_DATA) goto out;
err = sdio_enable_4bit_bus(card);
/* Set the driver strength for the card */ /* Set the driver strength for the card */
sdio_select_driver_type(card); sdio_select_driver_type(card);
......
...@@ -277,8 +277,8 @@ static void sdio_single_irq_set(struct mmc_card *card) ...@@ -277,8 +277,8 @@ static void sdio_single_irq_set(struct mmc_card *card)
* *
* Claim and activate the IRQ for the given SDIO function. The provided * Claim and activate the IRQ for the given SDIO function. The provided
* handler will be called when that IRQ is asserted. The host is always * handler will be called when that IRQ is asserted. The host is always
* claimed already when the handler is called so the handler must not * claimed already when the handler is called so the handler should not
* call sdio_claim_host() nor sdio_release_host(). * call sdio_claim_host() or sdio_release_host().
*/ */
int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler)
{ {
......
...@@ -149,11 +149,30 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host) ...@@ -149,11 +149,30 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host)
if (irq < 0) if (irq < 0)
host->caps |= MMC_CAP_NEEDS_POLL; host->caps |= MMC_CAP_NEEDS_POLL;
else if ((host->caps & MMC_CAP_CD_WAKE) && !enable_irq_wake(irq))
host->slot.cd_wake_enabled = true;
} }
EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on)
{
int ret = 0;
if (!(host->caps & MMC_CAP_CD_WAKE) ||
host->slot.cd_irq < 0 ||
on == host->slot.cd_wake_enabled)
return 0;
if (on) {
ret = enable_irq_wake(host->slot.cd_irq);
host->slot.cd_wake_enabled = !ret;
} else {
disable_irq_wake(host->slot.cd_irq);
host->slot.cd_wake_enabled = false;
}
return ret;
}
EXPORT_SYMBOL(mmc_gpio_set_cd_wake);
/* Register an alternate interrupt service routine for /* Register an alternate interrupt service routine for
* the card-detect GPIO. * the card-detect GPIO.
*/ */
......
...@@ -699,6 +699,15 @@ config MMC_DW_EXYNOS ...@@ -699,6 +699,15 @@ config MMC_DW_EXYNOS
Synopsys DesignWare Memory Card Interface driver. Select this option Synopsys DesignWare Memory Card Interface driver. Select this option
for platforms based on Exynos4 and Exynos5 SoC's. for platforms based on Exynos4 and Exynos5 SoC's.
config MMC_DW_HI3798CV200
tristate "Hi3798CV200 specific extensions for Synopsys DW Memory Card Interface"
depends on MMC_DW
select MMC_DW_PLTFM
help
This selects support for HiSilicon Hi3798CV200 SoC specific extensions to the
Synopsys DesignWare Memory Card Interface driver. Select this option
for platforms based on HiSilicon Hi3798CV200 SoC.
config MMC_DW_K3 config MMC_DW_K3
tristate "K3 specific extensions for Synopsys DW Memory Card Interface" tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
depends on MMC_DW depends on MMC_DW
......
...@@ -50,6 +50,7 @@ obj-$(CONFIG_MMC_CAVIUM_THUNDERX) += thunderx-mmc.o ...@@ -50,6 +50,7 @@ obj-$(CONFIG_MMC_CAVIUM_THUNDERX) += thunderx-mmc.o
obj-$(CONFIG_MMC_DW) += dw_mmc.o obj-$(CONFIG_MMC_DW) += dw_mmc.o
obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o
obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o
obj-$(CONFIG_MMC_DW_HI3798CV200) += dw_mmc-hi3798cv200.o
obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o
obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o
obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 HiSilicon Technologies Co., Ltd.
*/
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include "dw_mmc.h"
#include "dw_mmc-pltfm.h"
#define ALL_INT_CLR 0x1ffff
struct hi3798cv200_priv {
struct clk *sample_clk;
struct clk *drive_clk;
};
static void dw_mci_hi3798cv200_set_ios(struct dw_mci *host, struct mmc_ios *ios)
{
struct hi3798cv200_priv *priv = host->priv;
u32 val;
val = mci_readl(host, UHS_REG);