Commit 07888238 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-updates-for-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc

Pull MMC update from Chris Ball:
 "MMC highlights for 3.16:

  Core:
   - support HS400 mode of eMMC 5.0, via DT bindings mmc-hs400-1_{2,8}v
   - if card init at 3.3v doesn't work, try 1.8v and 1.2v too

  Drivers:
   - moxart: New driver for MOXA ART SoCs
   - rtsx_usb_sdmmc: New driver for Realtek USB card readers
   - sdhci: Large rework around IRQ/regulator handling, remove card_tasklet
   - sdhci-pci-o2micro: Add SeaBird SeaEagle SD3 support
   - sunxi: New driver for Allwinner sunxi SoCs
   - usdhi6rol0: New driver for Renesas SD/SDIO controller"

* tag 'mmc-updates-for-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (95 commits)
  mmc: sdhci-s3c: use mmc_of_parse and remove the card_tasklet
  mmc: add a driver for the Renesas usdhi6rol0 SD/SDIO host controller
  mmc: sdhci-of-esdhc: Fixup compile error
  mmc: tegra: fix reporting of base clock frequency
  mmc: tegra: disable UHS modes
  mmc: sdhci-dove: use mmc_of_parse() and remove card_tasklet CD handler
  MAINTAINERS: mmc: Add path to git tree
  mmc: dove: fix missing MACH_DOVE dependency
  mmc: sdhci: SD tuning is broken for some controllers
  mmc: sdhci-esdhc-imx: fix mmc ddr mode regression issue
  mmc: sdhci-pci-o2micro: Add SeaBird SeaEagle SD3 support
  mmc: omap_hsmmc: split omap-dma header file
  mmc: omap_hsmmc: fix cmd23 multiblock read/write
  mmc: omap_hsmmc: use devm_ioremap_resource
  mmc: omap_hsmmc: use devm_request_threaded_irq
  mmc: omap_hsmmc: use devm_request_irq
  mmc: omap_hsmmc: use devm_clk_get
  mmc: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs
  mmc: wmt-sdmmc: Use GFP_KERNEL instead of hard-coded value
  mmc: omap: Use DIV_ROUND_UP instead of open coded
  ...
parents 23adbe12 11bc9381
...@@ -38,6 +38,8 @@ Optional properties: ...@@ -38,6 +38,8 @@ Optional properties:
- mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported - mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
- mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
- mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
- mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
- mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
polarity properties, we have to fix the meaning of the "normal" and "inverted" polarity properties, we have to fix the meaning of the "normal" and "inverted"
......
MOXA ART MMC Host Controller Interface
Inherits from mmc binding[1].
[1] Documentation/devicetree/bindings/mmc/mmc.txt
Required properties:
- compatible : Must be "moxa,moxart-mmc" or "faraday,ftsdc010"
- reg : Should contain registers location and length
- interrupts : Should contain the interrupt number
- clocks : Should contain phandle for the clock feeding the MMC controller
Optional properties:
- dmas : Should contain two DMA channels, line request number must be 5 for
both channels
- dma-names : Must be "tx", "rx"
Example:
mmc: mmc@98e00000 {
compatible = "moxa,moxart-mmc";
reg = <0x98e00000 0x5C>;
interrupts = <5 0>;
clocks = <&clk_apb>;
dmas = <&dma 5>,
<&dma 5>;
dma-names = "tx", "rx";
};
...@@ -69,10 +69,6 @@ Optional properties: ...@@ -69,10 +69,6 @@ Optional properties:
* supports-highspeed: Enables support for high speed cards (up to 50MHz) * supports-highspeed: Enables support for high speed cards (up to 50MHz)
* caps2-mmc-hs200-1_8v: Supports mmc HS200 SDR 1.8V mode
* caps2-mmc-hs200-1_2v: Supports mmc HS200 SDR 1.2V mode
* broken-cd: as documented in mmc core bindings. * broken-cd: as documented in mmc core bindings.
* vmmc-supply: The phandle to the regulator to use for vmmc. If this is * vmmc-supply: The phandle to the regulator to use for vmmc. If this is
...@@ -103,7 +99,6 @@ board specific portions as listed below. ...@@ -103,7 +99,6 @@ board specific portions as listed below.
clock-freq-min-max = <400000 200000000>; clock-freq-min-max = <400000 200000000>;
num-slots = <1>; num-slots = <1>;
supports-highspeed; supports-highspeed;
caps2-mmc-hs200-1_8v;
broken-cd; broken-cd;
fifo-depth = <0x80>; fifo-depth = <0x80>;
card-detect-delay = <200>; card-detect-delay = <200>;
......
* Renesas usdhi6rol0 SD/SDIO host controller
Required properties:
- compatible: must be
"renesas,usdhi6rol0"
- interrupts: 3 interrupts, named "card detect", "data" and "SDIO" must be
specified
- clocks: a clock binding for the IMCLK input
Optional properties:
- vmmc-supply: a phandle of a regulator, supplying Vcc to the card
- vqmmc-supply: a phandle of a regulator, supplying VccQ to the card
Additionally any standard mmc bindings from mmc.txt can be used.
Example:
sd0: sd@ab000000 {
compatible = "renesas,usdhi6rol0";
reg = <0xab000000 0x200>;
interrupts = <0 23 0x4
0 24 0x4
0 25 0x4>;
interrupt-names = "card detect", "data", "SDIO";
bus-width = <4>;
max-frequency = <50000000>;
cap-power-off-card;
clocks = <&imclk>;
vmmc-supply = <&vcc_sd0>;
vqmmc-supply = <&vccq_sd0>;
};
...@@ -5974,6 +5974,7 @@ M: Chris Ball <chris@printf.net> ...@@ -5974,6 +5974,7 @@ M: Chris Ball <chris@printf.net>
M: Ulf Hansson <ulf.hansson@linaro.org> M: Ulf Hansson <ulf.hansson@linaro.org>
L: linux-mmc@vger.kernel.org L: linux-mmc@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
T: git git://git.linaro.org/people/ulf.hansson/mmc.git
S: Maintained S: Maintained
F: drivers/mmc/ F: drivers/mmc/
F: include/linux/mmc/ F: include/linux/mmc/
...@@ -9103,7 +9104,7 @@ F: include/linux/toshiba.h ...@@ -9103,7 +9104,7 @@ F: include/linux/toshiba.h
F: include/uapi/linux/toshiba.h F: include/uapi/linux/toshiba.h
TMIO MMC DRIVER TMIO MMC DRIVER
M: Ian Molton <ian@mnementh.co.uk> M: Ian Molton <ian.molton@codethink.co.uk>
L: linux-mmc@vger.kernel.org L: linux-mmc@vger.kernel.org
S: Maintained S: Maintained
F: drivers/mmc/host/tmio_mmc* F: drivers/mmc/host/tmio_mmc*
......
...@@ -341,16 +341,17 @@ int mmc_add_card(struct mmc_card *card) ...@@ -341,16 +341,17 @@ int mmc_add_card(struct mmc_card *card)
if (mmc_host_is_spi(card->host)) { if (mmc_host_is_spi(card->host)) {
pr_info("%s: new %s%s%s card on SPI\n", pr_info("%s: new %s%s%s card on SPI\n",
mmc_hostname(card->host), mmc_hostname(card->host),
mmc_card_highspeed(card) ? "high speed " : "", mmc_card_hs(card) ? "high speed " : "",
mmc_card_ddr_mode(card) ? "DDR " : "", mmc_card_ddr52(card) ? "DDR " : "",
type); type);
} else { } else {
pr_info("%s: new %s%s%s%s%s card at address %04x\n", pr_info("%s: new %s%s%s%s%s card at address %04x\n",
mmc_hostname(card->host), mmc_hostname(card->host),
mmc_card_uhs(card) ? "ultra high speed " : mmc_card_uhs(card) ? "ultra high speed " :
(mmc_card_highspeed(card) ? "high speed " : ""), (mmc_card_hs(card) ? "high speed " : ""),
mmc_card_hs400(card) ? "HS400 " :
(mmc_card_hs200(card) ? "HS200 " : ""), (mmc_card_hs200(card) ? "HS200 " : ""),
mmc_card_ddr_mode(card) ? "DDR " : "", mmc_card_ddr52(card) ? "DDR " : "",
uhs_bus_speed_mode, type, card->rca); uhs_bus_speed_mode, type, card->rca);
} }
......
...@@ -800,6 +800,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) ...@@ -800,6 +800,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
data->timeout_ns = limit_us * 1000; data->timeout_ns = limit_us * 1000;
data->timeout_clks = 0; data->timeout_clks = 0;
} }
/* assign limit value if invalid */
if (timeout_us == 0)
data->timeout_ns = limit_us * 1000;
} }
/* /*
...@@ -1310,31 +1314,38 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, ...@@ -1310,31 +1314,38 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
} }
EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
#endif /* CONFIG_REGULATOR */
int mmc_regulator_get_supply(struct mmc_host *mmc) int mmc_regulator_get_supply(struct mmc_host *mmc)
{ {
struct device *dev = mmc_dev(mmc); struct device *dev = mmc_dev(mmc);
struct regulator *supply;
int ret; int ret;
supply = devm_regulator_get(dev, "vmmc"); mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
mmc->supply.vmmc = supply;
mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
if (IS_ERR(supply)) if (IS_ERR(mmc->supply.vmmc)) {
return PTR_ERR(supply); if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(dev, "No vmmc regulator found\n");
} else {
ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
if (ret > 0)
mmc->ocr_avail = ret;
else
dev_warn(dev, "Failed getting OCR mask: %d\n", ret);
}
ret = mmc_regulator_get_ocrmask(supply); if (IS_ERR(mmc->supply.vqmmc)) {
if (ret > 0) if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER)
mmc->ocr_avail = ret; return -EPROBE_DEFER;
else dev_info(dev, "No vqmmc regulator found\n");
dev_warn(mmc_dev(mmc), "Failed getting OCR mask: %d\n", ret); }
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
#endif /* CONFIG_REGULATOR */
/* /*
* Mask off any voltages we don't support and select * Mask off any voltages we don't support and select
* the lowest voltage * the lowest voltage
...@@ -1533,8 +1544,13 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) ...@@ -1533,8 +1544,13 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
host->ios.timing = MMC_TIMING_LEGACY; host->ios.timing = MMC_TIMING_LEGACY;
mmc_set_ios(host); mmc_set_ios(host);
/* Set signal voltage to 3.3V */ /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */
__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0)
dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n");
else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180) == 0)
dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n");
else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120) == 0)
dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n");
/* /*
* This delay should be sufficient to allow the power supply * This delay should be sufficient to allow the power supply
...@@ -2183,7 +2199,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) ...@@ -2183,7 +2199,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
{ {
struct mmc_command cmd = {0}; struct mmc_command cmd = {0};
if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
return 0; return 0;
cmd.opcode = MMC_SET_BLOCKLEN; cmd.opcode = MMC_SET_BLOCKLEN;
...@@ -2263,7 +2279,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check) ...@@ -2263,7 +2279,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
} }
} }
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
if (mmc_host_is_spi(host)) { if (mmc_host_is_spi(host)) {
host->ios.chip_select = MMC_CS_HIGH; host->ios.chip_select = MMC_CS_HIGH;
host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
...@@ -2403,6 +2418,11 @@ void mmc_rescan(struct work_struct *work) ...@@ -2403,6 +2418,11 @@ void mmc_rescan(struct work_struct *work)
container_of(work, struct mmc_host, detect.work); container_of(work, struct mmc_host, detect.work);
int i; int i;
if (host->trigger_card_event && host->ops->card_event) {
host->ops->card_event(host);
host->trigger_card_event = false;
}
if (host->rescan_disable) if (host->rescan_disable)
return; return;
......
...@@ -135,8 +135,14 @@ static int mmc_ios_show(struct seq_file *s, void *data) ...@@ -135,8 +135,14 @@ static int mmc_ios_show(struct seq_file *s, void *data)
case MMC_TIMING_UHS_DDR50: case MMC_TIMING_UHS_DDR50:
str = "sd uhs DDR50"; str = "sd uhs DDR50";
break; break;
case MMC_TIMING_MMC_DDR52:
str = "mmc DDR52";
break;
case MMC_TIMING_MMC_HS200: case MMC_TIMING_MMC_HS200:
str = "mmc high-speed SDR200"; str = "mmc HS200";
break;
case MMC_TIMING_MMC_HS400:
str = "mmc HS400";
break; break;
default: default:
str = "invalid"; str = "invalid";
......
...@@ -447,6 +447,10 @@ int mmc_of_parse(struct mmc_host *host) ...@@ -447,6 +447,10 @@ int mmc_of_parse(struct mmc_host *host)
host->caps2 |= MMC_CAP2_HS200_1_8V_SDR; host->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
if (of_find_property(np, "mmc-hs200-1_2v", &len)) if (of_find_property(np, "mmc-hs200-1_2v", &len))
host->caps2 |= MMC_CAP2_HS200_1_2V_SDR; host->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
if (of_find_property(np, "mmc-hs400-1_8v", &len))
host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR;
if (of_find_property(np, "mmc-hs400-1_2v", &len))
host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
return 0; return 0;
......
This diff is collapsed.
...@@ -707,18 +707,10 @@ static struct attribute *sd_std_attrs[] = { ...@@ -707,18 +707,10 @@ static struct attribute *sd_std_attrs[] = {
&dev_attr_serial.attr, &dev_attr_serial.attr,
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(sd_std);
static struct attribute_group sd_std_attr_group = {
.attrs = sd_std_attrs,
};
static const struct attribute_group *sd_attr_groups[] = {
&sd_std_attr_group,
NULL,
};
struct device_type sd_type = { struct device_type sd_type = {
.groups = sd_attr_groups, .groups = sd_std_groups,
}; };
/* /*
...@@ -895,7 +887,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card) ...@@ -895,7 +887,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
{ {
unsigned max_dtr = (unsigned int)-1; unsigned max_dtr = (unsigned int)-1;
if (mmc_card_highspeed(card)) { if (mmc_card_hs(card)) {
if (max_dtr > card->sw_caps.hs_max_dtr) if (max_dtr > card->sw_caps.hs_max_dtr)
max_dtr = card->sw_caps.hs_max_dtr; max_dtr = card->sw_caps.hs_max_dtr;
} else if (max_dtr > card->csd.max_dtr) { } else if (max_dtr > card->csd.max_dtr) {
...@@ -905,12 +897,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card) ...@@ -905,12 +897,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
return max_dtr; return max_dtr;
} }
void mmc_sd_go_highspeed(struct mmc_card *card)
{
mmc_card_set_highspeed(card);
mmc_set_timing(card->host, MMC_TIMING_SD_HS);
}
/* /*
* Handle the detection and initialisation of a card. * Handle the detection and initialisation of a card.
* *
...@@ -985,16 +971,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, ...@@ -985,16 +971,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
err = mmc_sd_init_uhs_card(card); err = mmc_sd_init_uhs_card(card);
if (err) if (err)
goto free_card; goto free_card;
/* Card is an ultra-high-speed card */
mmc_card_set_uhs(card);
} else { } else {
/* /*
* Attempt to change to high-speed (if supported) * Attempt to change to high-speed (if supported)
*/ */
err = mmc_sd_switch_hs(card); err = mmc_sd_switch_hs(card);
if (err > 0) if (err > 0)
mmc_sd_go_highspeed(card); mmc_set_timing(card->host, MMC_TIMING_SD_HS);
else if (err) else if (err)
goto free_card; goto free_card;
...@@ -1089,7 +1072,7 @@ static int _mmc_sd_suspend(struct mmc_host *host) ...@@ -1089,7 +1072,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
if (!mmc_host_is_spi(host)) if (!mmc_host_is_spi(host))
err = mmc_deselect_cards(host); err = mmc_deselect_cards(host);
host->card->state &= ~MMC_STATE_HIGHSPEED;
if (!err) { if (!err) {
mmc_power_off(host); mmc_power_off(host);
mmc_card_set_suspended(host->card); mmc_card_set_suspended(host->card);
...@@ -1198,7 +1181,6 @@ static int mmc_sd_power_restore(struct mmc_host *host) ...@@ -1198,7 +1181,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
{ {
int ret; int ret;
host->card->state &= ~MMC_STATE_HIGHSPEED;
mmc_claim_host(host); mmc_claim_host(host);
ret = mmc_sd_init_card(host, host->card->ocr, host->card); ret = mmc_sd_init_card(host, host->card->ocr, host->card);
mmc_release_host(host); mmc_release_host(host);
......
...@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, ...@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
bool reinit); bool reinit);
unsigned mmc_sd_get_max_clock(struct mmc_card *card); unsigned mmc_sd_get_max_clock(struct mmc_card *card);
int mmc_sd_switch_hs(struct mmc_card *card); int mmc_sd_switch_hs(struct mmc_card *card);
void mmc_sd_go_highspeed(struct mmc_card *card);
#endif #endif
...@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) ...@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
{ {
unsigned max_dtr; unsigned max_dtr;
if (mmc_card_highspeed(card)) { if (mmc_card_hs(card)) {
/* /*
* The SDIO specification doesn't mention how * The SDIO specification doesn't mention how
* the CIS transfer speed register relates to * the CIS transfer speed register relates to
...@@ -733,7 +733,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -733,7 +733,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
mmc_set_clock(host, card->cis.max_dtr); mmc_set_clock(host, card->cis.max_dtr);
if (card->cccr.high_speed) { if (card->cccr.high_speed) {
mmc_card_set_highspeed(card);
mmc_set_timing(card->host, MMC_TIMING_SD_HS); mmc_set_timing(card->host, MMC_TIMING_SD_HS);
} }
...@@ -792,16 +791,13 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -792,16 +791,13 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
err = mmc_sdio_init_uhs_card(card); err = mmc_sdio_init_uhs_card(card);
if (err) if (err)
goto remove; goto remove;
/* Card is an ultra-high-speed card */
mmc_card_set_uhs(card);
} else { } else {
/* /*
* Switch to high-speed (if supported). * Switch to high-speed (if supported).
*/ */
err = sdio_enable_hs(card); err = sdio_enable_hs(card);
if (err > 0) if (err > 0)
mmc_sd_go_highspeed(card); mmc_set_timing(card->host, MMC_TIMING_SD_HS);
else if (err) else if (err)
goto remove; goto remove;
...@@ -943,40 +939,21 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host) ...@@ -943,40 +939,21 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)
*/ */
static int mmc_sdio_suspend(struct mmc_host *host) static int mmc_sdio_suspend(struct mmc_host *host)
{ {
int i, err = 0; if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
for (i = 0; i < host->card->sdio_funcs; i++) {
struct sdio_func *func = host->card->sdio_func[i];
if (func && sdio_func_present(func) && func->dev.driver) {
const struct dev_pm_ops *pmops = func->dev.driver->pm;
err = pmops->suspend(&func->dev);
if (err)
break;
}
}
while (err && --i >= 0) {
struct sdio_func *func = host->card->sdio_func[i];
if (func && sdio_func_present(func) && func->dev.driver) {
const struct dev_pm_ops *pmops = func->dev.driver->pm;
pmops->resume(&func->dev);
}
}
if (!err && mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
mmc_claim_host(host); mmc_claim_host(host);
sdio_disable_wide(host->card); sdio_disable_wide(host->card);
mmc_release_host(host); mmc_release_host(host);
} }
if (!err && !mmc_card_keep_power(host)) if (!mmc_card_keep_power(host))
mmc_power_off(host); mmc_power_off(host);
return err; return 0;
} }
static int mmc_sdio_resume(struct mmc_host *host) static int mmc_sdio_resume(struct mmc_host *host)
{ {
int i, err = 0; int err = 0;
BUG_ON(!host); BUG_ON(!host);
BUG_ON(!host->card); BUG_ON(!host->card);
...@@ -1019,24 +996,6 @@ static int mmc_sdio_resume(struct mmc_host *host) ...@@ -1019,24 +996,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
wake_up_process(host->sdio_irq_thread); wake_up_process(host->sdio_irq_thread);
mmc_release_host(host); mmc_release_host(host);
/*
* If the card looked to be the same as before suspending, then
* we proceed to resume all card functions. If one of them returns
* an error then we simply return that error to the core and the
* card will be redetected as new. It is the responsibility of
* the function driver to perform further tests with the extra
* knowledge it has of the card to confirm the card is indeed the
* same as before suspending (same MAC address for network cards,
* etc.) and return an error otherwise.
*/
for (i = 0; !err && i < host->card->sdio_funcs; i++) {
struct sdio_func *func = host->card->sdio_func[i];
if (func && sdio_func_present(func) && func->dev.driver) {
const struct dev_pm_ops *pmops = func->dev.driver->pm;
err = pmops->resume(&func->dev);
}
}
host->pm_flags &= ~MMC_PM_KEEP_POWER; host->pm_flags &= ~MMC_PM_KEEP_POWER;
return err; return err;
} }
......
...@@ -197,20 +197,8 @@ static int sdio_bus_remove(struct device *dev) ...@@ -197,20 +197,8 @@ static int sdio_bus_remove(struct device *dev)
#ifdef CONFIG_PM #ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int pm_no_operation(struct device *dev)
{
/*
* Prevent the PM core from calling SDIO device drivers' suspend
* callback routines, which it is not supposed to do, by using this
* empty function as the bus type suspend callaback for SDIO.
*/
return 0;
}
#endif
static const struct dev_pm_ops sdio_bus_pm_ops = { static const struct dev_pm_ops sdio_bus_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation) SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
SET_RUNTIME_PM_OPS( SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend, pm_generic_runtime_suspend,
pm_generic_runtime_resume, pm_generic_runtime_resume,
......
...@@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host) ...@@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
return ret; return ret;
} }
void sdio_run_irqs(struct mmc_host *host)
{
mmc_claim_host(host);
host->sdio_irq_pending = true;
process_sdio_pending_irqs(host);
mmc_release_host(host);
}
EXPORT_SYMBOL_GPL(sdio_run_irqs);
static int sdio_irq_thread(void *_host) static int sdio_irq_thread(void *_host)
{ {
struct mmc_host *host = _host; struct mmc_host *host = _host;
...@@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card) ...@@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)
WARN_ON(!host->claimed); WARN_ON(!host->claimed);
if (!host->sdio_irqs++) { if (!host->sdio_irqs++) {
atomic_set(&host->sdio_irq_thread_abort, 0); if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
host->sdio_irq_thread = atomic_set(&host->sdio_irq_thread_abort, 0);
kthread_run(sdio_irq_thread, host, "ksdioirqd/%s", host->sdio_irq_thread =
mmc_hostname(host)); kthread_run(sdio_irq_thread, host,
if (IS_ERR(host->sdio_irq_thread)) { "ksdioirqd/%s", mmc_hostname(host));
int err = PTR_ERR(host->sdio_irq_thread); if (IS_ERR(host->sdio_irq_thread)) {
host->sdio_irqs--; int err = PTR_ERR(host->sdio_irq_thread);
return err; host->sdio_irqs--;
return err;
}
} else {
mmc_host_clk_hold(host);
host->ops->enable_sdio_irq(host, 1);
mmc_host_clk_release(host);
} }
} }
...@@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card) ...@@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)
BUG_ON(host->sdio_irqs < 1); BUG_ON(host->sdio_irqs < 1);
if (!--host->sdio_irqs) { if (!--host->sdio_irqs) {
atomic_set(&host->sdio_irq_thread_abort, 1); if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
kthread_stop(host->sdio_irq_thread); atomic_set(&host->sdio_irq_thread_abort, 1);
kthread_stop(host->sdio_irq_thread);
} else {
mmc_host_clk_hold(host);
host->ops->enable_sdio_irq(host, 0);
mmc_host_clk_release(host);
}
} }
return 0; return 0;
......
...@@ -32,9 +32,7 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) ...@@ -32,9 +32,7 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
/* Schedule a card detection after a debounce timeout */ /* Schedule a card detection after a debounce timeout */
struct mmc_host *host = dev_id; struct mmc_host *host = dev_id;
if (host->ops->card_event) host->trigger_card_event = true;
host->ops->card_event(host);
mmc_detect_change(host, msecs_to_jiffies(200)); mmc_detect_change(host, msecs_to_jiffies(200));
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -168,7 +168,7 @@ config MMC_SDHCI_ESDHC_IMX ...@@ -168,7 +168,7 @@ config MMC_SDHCI_ESDHC_IMX
config MMC_SDHCI_DOVE config MMC_SDHCI_DOVE
tristate "SDHCI support on Marvell's Dove SoC" tristate "SDHCI support on Marvell's Dove SoC"
depends on ARCH_DOVE depends on ARCH_DOVE || MACH_DOVE
depends on MMC_SDHCI_PLTFM depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS select MMC_SDHCI_IO_ACCESSORS
help help
...@@ -283,6 +283,15 @@ config MMC_SDHCI_BCM2835 ...@@ -283,6 +283,15 @@ config MMC_SDHCI_BCM2835
If unsure, say N. If unsure, say N.
config MMC_MOXART
tristate "MOXART SD/MMC Host Controller support"
depends on ARCH_MOXART && MMC
help
This selects support for the MOXART SD/MMC Host Controller.
MOXA provides one multi-functional card reader which can
be found on some embedded hardware such as UC-7112-LX.
If you have a controller with this interface, say Y here.
config MMC_OMAP config MMC_OMAP
tristate "TI OMAP Multimedia Card Interface support" tristate "TI OMAP Multimedia Card Interface support"
depends on ARCH_OMAP depends on ARCH_OMAP
...@@ -688,6 +697,12 @@ config MMC_WMT ...@@ -688,6 +697,12 @@ config MMC_WMT
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called wmt-sdmmc. module will be called wmt-sdmmc.
config MMC_USDHI6ROL0
tristate "Renesas USDHI6ROL0 SD/SDIO Host Controller support"
help
This selects support for the Renesas USDHI6ROL0 SD/SDIO
Host Controller
config MMC_REALTEK_PCI config MMC_REALTEK_PCI
tristate "Realtek PCI-E SD/MMC Card Interface Driver" tristate "Realtek PCI-E SD/MMC Card Interface Driver"
depends on MFD_RTSX_PCI depends on MFD_RTSX_PCI
......
...@@ -50,7 +50,9 @@ obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o ...@@ -50,7 +50,9 @@ obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
obj-$(CONFIG_MMC_VUB300) += vub300.o obj-$(CONFIG_MMC_VUB300) += vub300.o
obj-$(CONFIG_MMC_USHC) += ushc.o obj-$(CONFIG_MMC_USHC) += ushc.o
obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
obj-$(CONFIG_MMC_MOXART) += moxart-mmc.o
obj-$(CONFIG_MMC_SUNXI) += sunxi-mmc.o obj-$(CONFIG_MMC_SUNXI) += sunxi-mmc.o
obj-$(CONFIG_MMC_USDHI6ROL0) += usdhi6rol0.o
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o
......
...@@ -820,16 +820,9 @@ static void atmci_pdc_complete(struct atmel_mci *host) ...@@ -820,16 +820,9 @@ static void atmci_pdc_complete(struct atmel_mci *host)
atmci_pdc_cleanup(host); atmci_pdc_cleanup(host);
/* dev_dbg(&host->pdev->dev, "(%s) set pending xfer complete\n", __func__);
* If the card was removed, data will be NULL. No point trying atmci_set_pending(host, EVENT_XFER_COMPLETE);
* to send the stop command or waiting for NBUSY in this case. tasklet_schedule(&host->tasklet);
*/
if (host->data) {
dev_dbg(&host->pdev->dev,
"(%s) set pending xfer complete\n", __func__);
atmci_set_pending(host, EVENT_XFER_COMPLETE);
tasklet_schedule(&host->tasklet);
}
} }
static void atmci_dma_cleanup(struct atmel_mci *host) static void atmci_dma_cleanup(struct atmel_mci *host)
......
...@@ -187,7 +187,7 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) ...@@ -187,7 +187,7 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
unsigned long actual; unsigned long actual;
u8 div = priv->ciu_div + 1; u8 div = priv->ciu_div + 1;
if (ios->timing == MMC_TIMING_UHS_DDR50) { if (ios->timing == MMC_TIMING_MMC_DDR52) {
mci_writel(host, CLKSEL, priv->ddr_timing); mci_writel(host, CLKSEL, priv->ddr_timing);
/* Should be double rate for DDR mode */ /* Should be double rate for DDR mode */
if (ios->bus_width == MMC_BUS_WIDTH_8) if (ios->bus_width == MMC_BUS_WIDTH_8)
...@@ -386,8 +386,7 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode, ...@@ -386,8 +386,7 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
/* Common capabilities of Exynos4/Exynos5 SoC */ /* Common capabilities of Exynos4/Exynos5 SoC */
static unsigned long exynos_dwmmc_caps[4] = { static unsigned long exynos_dwmmc_caps[4] = {
MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
MMC_CAP_CMD23, MMC_CAP_CMD23,
MMC_CAP_CMD23, MMC_CAP_CMD23,
MMC_CAP_CMD23, MMC_CAP_CMD23,
...@@ -426,7 +425,7 @@ static int dw_mci_exynos_probe(struct platform_device *pdev) ...@@ -426,7 +425,7 @@ static int dw_mci_exynos_probe(struct platform_device *pdev)
return dw_mci_pltfm_register(pdev, drv_data); return dw_mci_pltfm_register(pdev, drv_data);
} }
const struct dev_pm_ops dw_mci_exynos_pmops = { static const struct dev_pm_ops dw_mci_exynos_pmops = {
SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume) SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume)
.resume_noirq = dw_mci_exynos_resume_noirq, .resume_noirq = dw_mci_exynos_resume_noirq,
.thaw_noirq = dw_mci_exynos_resume_noirq, .thaw_noirq = dw_mci_exynos_resume_noirq,
......
...@@ -235,12 +235,6 @@ static void dw_mci_init_debugfs(struct dw_mci_slot *slot) ...@@ -235,12 +235,6 @@ static void dw_mci_init_debugfs(struct dw_mci_slot *slot)
} }
#endif /* defined(CONFIG_DEBUG_FS) */ #endif /* defined(CONFIG_DEBUG_FS) */
static void dw_mci_set_timeout(struct dw_mci *host)
{
/* timeout (maximum) */
mci_writel(host, TMOUT, 0xffffffff);
}
static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
{ {
struct mmc_data *data; struct mmc_data *data;
...@@ -257,9 +251,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) ...@@ -257,9 +251,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
(cmd->opcode == SD_IO_RW_DIRECT && (cmd->opcode == SD_IO_RW_DIRECT &&
((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT)) ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT))
cmdr |= SDMMC_CMD_STOP; cmdr |= SDMMC_CMD_STOP;
else else if (cmd->opcode != MMC_SEND_STATUS && cmd->data)
if (cmd->opcode != MMC_SEND_STATUS && cmd->data) cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
if (cmd->flags & MMC_RSP_PRESENT) { if (cmd->flags & MMC_RSP_PRESENT) {
/* We expect a response, so set this bit */ /* We expect a response, so set this bit */
...@@ -850,8 +843,6 @@ static void __dw_mci_start_request(struct dw_mci *host, ...@@ -850,8 +843,6 @@ static void __dw_mci_start_request(struct dw_mci *host,
u32 cmdflags; u32 cmdflags;
mrq = slot->mrq; mrq = slot->mrq;
if (host->pdata->select_slot)
host->pdata->select_slot(slot->id);
host->cur_slot = slot; host->cur_slot = slot;
host->mrq = mrq; host->mrq = mrq;
...@@ -864,7 +855,7 @@ static void __dw_mci_start_request(struct dw_mci *host, ...@@ -864,7 +855,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
data = cmd->data; data = cmd->data;
if (data) { if (data) {
dw_mci_set_timeout(host); mci_writel(host, TMOUT, 0xFFFFFFFF);
mci_writel(host, BYTCNT, data->blksz*data->blocks); mci_writel(host, BYTCNT, data->blksz*data->blocks);
mci_writel(host, BLKSIZ, data->blksz); mci_writel(host, BLKSIZ, data->blksz);
} }
...@@ -962,7 +953,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -962,7 +953,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
regs = mci_readl(slot->host, UHS_REG); regs = mci_readl(slot->host, UHS_REG);
/* DDR mode set */ /* DDR mode set */
if (ios->timing == MMC_TIMING_UHS_DDR50) if (ios->timing == MMC_TIMING_MMC_DDR52)
regs |= ((0x1 << slot->id) << 16); regs |= ((0x1 << slot->id) << 16);
else else
regs &= ~((0x1 << slot->id) << 16); regs &= ~((0x1 << slot->id) << 16);
...@@ -985,17 +976,11 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -985,17 +976,11 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
switch (ios->power_mode) { switch (ios->power_mode) {
case MMC_POWER_UP: case MMC_POWER_UP:
set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
/* Power up slot */
if (slot->host->pdata->setpower)
slot->host->pdata->setpower(slot->id, mmc->ocr_avail);
regs = mci_readl(slot->host, PWREN); regs = mci_readl(slot->host, PWREN);
regs |= (1 << slot->id); regs |= (1 << slot->id);
mci_writel(slot->host, PWREN, regs); mci_writel(slot->host, PWREN, regs);
break; break;
case MMC_POWER_OFF: case MMC_POWER_OFF:
/* Power down slot */
if (slot->host->pdata->setpower)
slot->host->pdata->setpower(slot->id, 0);
regs = mci_readl(slot->host, PWREN); regs = mci_readl(slot->host, PWREN);
regs &= ~(1 << slot->id); regs &= ~(1 << slot->id);
mci_writel(slot->host, PWREN, regs); mci_writel(slot->host, PWREN, regs);
...@@ -1009,15 +994,13 @@ static int dw_mci_get_ro(struct mmc_host *mmc) ...@@ -1009,15 +994,13 @@ static int dw_mci_get_ro(struct mmc_host *mmc)
{ {
int read_only; int read_only;
struct dw_mci_slot *slot = mmc_priv(mmc); struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci_board *brd = slot->host->pdata; int gpio_ro = mmc_gpio_get_ro(mmc);
/* Use platform get_ro function, else try on board write protect */ /* Use platform get_ro function, else try on board write protect */
if (slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT) if (slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT)
read_only = 0; read_only = 0;
else if (brd->get_ro) else if (!IS_ERR_VALUE(gpio_ro))
read_only = brd->get_ro(slot->id); read_only = gpio_ro;
else if (gpio_is_valid(slot->wp_gpio))
read_only = gpio_get_value(slot->wp_gpio);
else else
read_only = read_only =
mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0; mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0;
...@@ -1039,8 +1022,6 @@ static int dw_mci_get_cd(struct mmc_host *mmc) ...@@ -1039,8 +1022,6 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
/* Use platform get_cd function, else try onboard card detect */ /* Use platform get_cd function, else try onboard card detect */
if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
present = 1; present = 1;
else if (brd->get_cd)
present = !brd->get_cd(slot->id);
else if (!IS_ERR_VALUE(gpio_cd)) else if (!IS_ERR_VALUE(gpio_cd))
present = gpio_cd; present = gpio_cd;
else else
...@@ -1248,7 +1229,7 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data) ...@@ -1248,7 +1229,7 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)
data->error = -EIO; data->error = -EIO;
} }
dev_err(host->dev, "data error, status 0x%08x\n", status); dev_dbg(host->dev, "data error, status 0x%08x\n", status);
/* /*
* After an error, there may be data lingering * After an error, there may be data lingering
...@@ -2045,86 +2026,15 @@ static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) ...@@ -2045,86 +2026,15 @@ static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
return quirks; return quirks;
} }
/* find out bus-width for a given slot */
static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
{
struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
u32 bus_wd = 1;
if (!np)
return 1;
if (of_property_read_u32(np, "bus-width", &bus_wd))
dev_err(dev, "bus-width property not found, assuming width"
" as 1\n");
return bus_wd;
}
/* find the write protect gpio for a given slot; or -1 if none specified */
static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
{
struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
int gpio;
if (!np)
return -EINVAL;
gpio = of_get_named_gpio(np, "wp-gpios", 0);
/* Having a missing entry is valid; return silently */
if (!gpio_is_valid(gpio))
return -EINVAL;
if (devm_gpio_request(dev, gpio, "dw-mci-wp")) {
dev_warn(dev, "gpio [%d] request failed\n", gpio);
return -EINVAL;
}
return gpio;
}
/* find the cd gpio for a given slot */
static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
struct mmc_host *mmc)
{
struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
int gpio;
if (!np)
return;
gpio = of_get_named_gpio(np, "cd-gpios", 0);
/* Having a missing entry is valid; return silently */
if (!gpio_is_valid(gpio))
return;
if (mmc_gpio_request_cd(mmc, gpio, 0))
dev_warn(dev, "gpio [%d] request failed\n", gpio);
}
#else /* CONFIG_OF */ #else /* CONFIG_OF */
static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
{ {
return 0; return 0;
} }
static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
{
return 1;
}
static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
{ {
return NULL; return NULL;
} }
static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
{
return -EINVAL;
}
static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
struct mmc_host *mmc)
{
return;
}
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
...@@ -2134,7 +2044,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -2134,7 +2044,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
const struct dw_mci_drv_data *drv_data = host->drv_data; const struct dw_mci_drv_data *drv_data = host->drv_data;
int ctrl_id, ret; int ctrl_id, ret;
u32 freq[2]; u32 freq[2];
u8 bus_width;
mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
if (!mmc) if (!mmc)
...@@ -2158,17 +2067,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -2158,17 +2067,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
mmc->f_max = freq[1]; mmc->f_max = freq[1];
} }
if (host->pdata->get_ocr) mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->ocr_avail = host->pdata->get_ocr(id);
else
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
/*
* Start with slot power disabled, it will be enabled when a card
* is detected.
*/
if (host->pdata->setpower)
host->pdata->setpower(id, 0);
if (host->pdata->caps) if (host->pdata->caps)
mmc->caps = host->pdata->caps; mmc->caps = host->pdata->caps;
...@@ -2189,19 +2088,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -2189,19 +2088,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
if (host->pdata->caps2) if (host->pdata->caps2)
mmc->caps2 = host->pdata->caps2; mmc->caps2 = host->pdata->caps2;
if (host->pdata->get_bus_wd) mmc_of_parse(mmc);
bus_width = host->pdata->get_bus_wd(slot->id);
else if (host->dev->of_node)
bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id);
else
bus_width = 1;
switch (bus_width) {
case 8:
mmc->caps |= MMC_CAP_8_BIT_DATA;
case 4:
mmc->caps |= MMC_CAP_4_BIT_DATA;
}
if (host->pdata->blk_settings) { if (host->pdata->blk_settings) {
mmc->max_segs = host->pdata->blk_settings->max_segs; mmc->max_segs = host->pdata->blk_settings->max_segs;
...@@ -2226,8 +2113,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -2226,8 +2113,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
#endif /* CONFIG_MMC_DW_IDMAC */ #endif /* CONFIG_MMC_DW_IDMAC */
} }
slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id); if (dw_mci_get_cd(mmc))
dw_mci_of_get_cd_gpio(host->dev, slot->id, mmc); set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
else
clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
ret = mmc_add_host(mmc); ret = mmc_add_host(mmc);
if (ret) if (ret)
...@@ -2249,10 +2138,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -2249,10 +2138,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
{ {
/* Shutdown detect IRQ */
if (slot->host->pdata->exit)
slot->host->pdata->exit(id);
/* Debugfs stuff is cleaned up by mmc core */ /* Debugfs stuff is cleaned up by mmc core */
mmc_remove_host(slot->mmc); mmc_remove_host(slot->mmc);
slot->host->slot[id] = NULL; slot->host->slot[id] = NULL;
...@@ -2399,24 +2284,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) ...@@ -2399,24 +2284,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
return ERR_PTR(ret); return ERR_PTR(ret);
} }
if (of_find_property(np, "keep-power-in-suspend", NULL))
pdata->pm_caps |= MMC_PM_KEEP_POWER;
if (of_find_property(np, "enable-sdio-wakeup", NULL))
pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
if (of_find_property(np, "supports-highspeed", NULL)) if (of_find_property(np, "supports-highspeed", NULL))
pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
if (of_find_property(np, "caps2-mmc-hs200-1_8v", NULL))
pdata->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
if (of_get_property(np, "cd-inverted", NULL))
pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
return pdata; return pdata;
} }
...@@ -2442,9 +2312,9 @@ int dw_mci_probe(struct dw_mci *host) ...@@ -2442,9 +2312,9 @@ int dw_mci_probe(struct dw_mci *host)
} }
} }
if (!host->pdata->select_slot && host->pdata->num_slots > 1) { if (host->pdata->num_slots > 1) {
dev_err(host->dev, dev_err(host->dev,
"Platform data must supply select_slot function\n"); "Platform data must supply num_slots.\n");
return -ENODEV; return -ENODEV;
} }
...@@ -2474,12 +2344,19 @@ int dw_mci_probe(struct dw_mci *host) ...@@ -2474,12 +2344,19 @@ int dw_mci_probe(struct dw_mci *host)
ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz); ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz);
if (ret) if (ret)
dev_warn(host->dev, dev_warn(host->dev,
"Unable to set bus rate to %ul\n", "Unable to set bus rate to %uHz\n",
host->pdata->bus_hz); host->pdata->bus_hz);
} }
host->bus_hz = clk_get_rate(host->ciu_clk); host->bus_hz = clk_get_rate(host->ciu_clk);
} }
if (!host->bus_hz) {
dev_err(host->dev,
"Platform data must supply bus speed\n");
ret = -ENODEV;
goto err_clk_ciu;
}
if (drv_data && drv_data->init) { if (drv_data && drv_data->init) {
ret = drv_data->init(host); ret = drv_data->init(host);
if (ret) { if (ret) {
...@@ -2516,13 +2393,6 @@ int dw_mci_probe(struct dw_mci *host) ...@@ -2516,13 +2393,6 @@ int dw_mci_probe(struct dw_mci *host)
} }
} }
if (!host->bus_hz) {
dev_err(host->dev,
"Platform data must supply bus speed\n");
ret = -ENODEV;
goto err_regulator;
}
host->quirks = host->pdata->quirks; host->quirks = host->pdata->quirks;
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
...@@ -2666,8 +2536,6 @@ int dw_mci_probe(struct dw_mci *host) ...@@ -2666,8 +2536,6 @@ int dw_mci_probe(struct dw_mci *host)
err_dmaunmap: err_dmaunmap:
if (host->use_dma && host->dma_ops->exit) if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host); host->dma_ops->exit(host);
err_regulator:
if (host->vmmc) if (host->vmmc)
regulator_disable(host->vmmc); regulator_disable(host->vmmc);
......
...@@ -195,7 +195,6 @@ extern int dw_mci_resume(struct dw_mci *host); ...@@ -195,7 +195,6 @@ extern int dw_mci_resume(struct dw_mci *host);
* @mmc: The mmc_host representing this slot. * @mmc: The mmc_host representing this slot.
* @host: The MMC controller this slot is using. * @host: The MMC controller this slot is using.
* @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX) * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX)
* @wp_gpio: If gpio_is_valid() we'll use this to read write protect.
* @ctype: Card type for this slot. * @ctype: Card type for this slot.
* @mrq: mmc_request currently being processed or waiting to be * @mrq: mmc_request currently being processed or waiting to be
* processed, or NULL when the slot is idle. * processed, or NULL when the slot is idle.
...@@ -214,7 +213,6 @@ struct dw_mci_slot { ...@@ -214,7 +213,6 @@ struct dw_mci_slot {
struct dw_mci *host; struct dw_mci *host;
int quirks; int quirks;
int wp_gpio;
u32 ctype; u32 ctype;
......
...@@ -515,10 +515,13 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) ...@@ -515,10 +515,13 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid)
jz4740_mmc_send_command(host, req->stop); jz4740_mmc_send_command(host, req->stop);
timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_PRG_DONE); if (mmc_resp_type(req->stop) & MMC_RSP_BUSY) {
if (timeout) { timeout = jz4740_mmc_poll_irq(host,
host->state = JZ4740_MMC_STATE_DONE; JZ_MMC_IRQ_PRG_DONE);
break; if (timeout) {
host->state = JZ4740_MMC_STATE_DONE;
break;
}
} }
case JZ4740_MMC_STATE_DONE: case JZ4740_MMC_STATE_DONE:
break; break;
......
...@@ -301,7 +301,8 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) ...@@ -301,7 +301,8 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8)
clk |= MCI_ST_8BIT_BUS; clk |= MCI_ST_8BIT_BUS;
if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50) if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50 ||
host->mmc->ios.timing == MMC_TIMING_MMC_DDR52)
clk |= MCI_ST_UX500_NEG_EDGE; clk |= MCI_ST_UX500_NEG_EDGE;
mmci_write_clkreg(host, clk); mmci_write_clkreg(host, clk);
...@@ -764,7 +765,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) ...@@ -764,7 +765,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
mmci_write_clkreg(host, clk); mmci_write_clkreg(host, clk);
} }
if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50) if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50 ||
host->mmc->ios.timing == MMC_TIMING_MMC_DDR52)
datactrl |= MCI_ST_DPSM_DDRMODE; datactrl |= MCI_ST_DPSM_DDRMODE;
/* /*
......
This diff is collapsed.
...@@ -354,6 +354,20 @@ static irqreturn_t mvsd_irq(int irq, void *dev) ...@@ -354,6 +354,20 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
intr_status, mvsd_read(MVSD_NOR_INTR_EN), intr_status, mvsd_read(MVSD_NOR_INTR_EN),
mvsd_read(MVSD_HW_STATE)); mvsd_read(MVSD_HW_STATE));
/*
* It looks like, SDIO IP can issue one late, spurious irq
* although all irqs should be disabled. To work around this,
* bail out early, if we didn't expect any irqs to occur.
*/
if (!mvsd_read(MVSD_NOR_INTR_EN) && !mvsd_read(MVSD_ERR_INTR_EN)) {
dev_dbg(host->dev, "spurious irq detected intr 0x%04x intr_en 0x%04x erri 0x%04x erri_en 0x%04x\n",
mvsd_read(MVSD_NOR_INTR_STATUS),
mvsd_read(MVSD_NOR_INTR_EN),
mvsd_read(MVSD_ERR_INTR_STATUS),
mvsd_read(MVSD_ERR_INTR_EN));
return IRQ_HANDLED;
}
spin_lock(&host->lock); spin_lock(&host->lock);
/* PIO handling, if needed. Messy business... */ /* PIO handling, if needed. Messy business... */
...@@ -801,10 +815,10 @@ static int mvsd_probe(struct platform_device *pdev) ...@@ -801,10 +815,10 @@ static int mvsd_probe(struct platform_device *pdev)
goto out; goto out;
if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) if (!(mmc->caps & MMC_CAP_NEEDS_POLL))
dev_notice(&pdev->dev, "using GPIO for card detection\n"); dev_dbg(&pdev->dev, "using GPIO for card detection\n");
else else
dev_notice(&pdev->dev, dev_dbg(&pdev->dev, "lacking card detect (fall back to polling)\n");
"lacking card detect (fall back to polling)\n");
return 0; return 0;
out: out:
......
...@@ -124,9 +124,8 @@ enum mxcmci_type { ...@@ -124,9 +124,8 @@ enum mxcmci_type {
struct mxcmci_host { struct mxcmci_host {
struct mmc_host *mmc; struct mmc_host *mmc;
struct resource *res;
void __iomem *base; void __iomem *base;
int irq; dma_addr_t phys_base;
int detect_irq; int detect_irq;
struct dma_chan *dma; struct dma_chan *dma;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
...@@ -154,8 +153,6 @@ struct mxcmci_host { ...@@ -154,8 +153,6 @@ struct mxcmci_host {
struct work_struct datawork; struct work_struct datawork;
spinlock_t lock; spinlock_t lock;
struct regulator *vcc;
int burstlen; int burstlen;
int dmareq; int dmareq;
struct dma_slave_config dma_slave_config; struct dma_slave_config dma_slave_config;
...@@ -241,37 +238,15 @@ static inline void mxcmci_writew(struct mxcmci_host *host, u16 val, int reg) ...@@ -241,37 +238,15 @@ static inline void mxcmci_writew(struct mxcmci_host *host, u16 val, int reg)
static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
static inline void mxcmci_init_ocr(struct mxcmci_host *host) static void mxcmci_set_power(struct mxcmci_host *host, unsigned int vdd)
{
host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
if (IS_ERR(host->vcc)) {
host->vcc = NULL;
} else {
host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc);
if (host->pdata && host->pdata->ocr_avail)
dev_warn(mmc_dev(host->mmc),
"pdata->ocr_avail will not be used\n");
}
if (host->vcc == NULL) {
/* fall-back to platform data */
if (host->pdata && host->pdata->ocr_avail)
host->mmc->ocr_avail = host->pdata->ocr_avail;
else
host->mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
}
}
static inline void mxcmci_set_power(struct mxcmci_host *host,
unsigned char power_mode,
unsigned int vdd)
{ {
if (host->vcc) { if (!IS_ERR(host->mmc->supply.vmmc)) {
if (power_mode == MMC_POWER_UP) if (host->power_mode == MMC_POWER_UP)
mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); mmc_regulator_set_ocr(host->mmc,
else if (power_mode == MMC_POWER_OFF) host->mmc->supply.vmmc, vdd);
mmc_regulator_set_ocr(host->mmc, host->vcc, 0); else if (host->power_mode == MMC_POWER_OFF)
mmc_regulator_set_ocr(host->mmc,
host->mmc->supply.vmmc, 0);
} }
if (host->pdata && host->pdata->setpower) if (host->pdata && host->pdata->setpower)
...@@ -299,7 +274,6 @@ static void mxcmci_softreset(struct mxcmci_host *host) ...@@ -299,7 +274,6 @@ static void mxcmci_softreset(struct mxcmci_host *host)
mxcmci_writew(host, 0xff, MMC_REG_RES_TO); mxcmci_writew(host, 0xff, MMC_REG_RES_TO);
} }
static int mxcmci_setup_dma(struct mmc_host *mmc);
#if IS_ENABLED(CONFIG_PPC_MPC512x) #if IS_ENABLED(CONFIG_PPC_MPC512x)
static inline void buffer_swap32(u32 *buf, int len) static inline void buffer_swap32(u32 *buf, int len)
...@@ -868,8 +842,8 @@ static int mxcmci_setup_dma(struct mmc_host *mmc) ...@@ -868,8 +842,8 @@ static int mxcmci_setup_dma(struct mmc_host *mmc)
struct mxcmci_host *host = mmc_priv(mmc); struct mxcmci_host *host = mmc_priv(mmc);
struct dma_slave_config *config = &host->dma_slave_config; struct dma_slave_config *config = &host->dma_slave_config;
config->dst_addr = host->res->start + MMC_REG_BUFFER_ACCESS; config->dst_addr = host->phys_base + MMC_REG_BUFFER_ACCESS;
config->src_addr = host->res->start + MMC_REG_BUFFER_ACCESS; config->src_addr = host->phys_base + MMC_REG_BUFFER_ACCESS;
config->dst_addr_width = 4; config->dst_addr_width = 4;
config->src_addr_width = 4; config->src_addr_width = 4;
config->dst_maxburst = host->burstlen; config->dst_maxburst = host->burstlen;
...@@ -911,8 +885,8 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -911,8 +885,8 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4;
if (host->power_mode != ios->power_mode) { if (host->power_mode != ios->power_mode) {
mxcmci_set_power(host, ios->power_mode, ios->vdd);
host->power_mode = ios->power_mode; host->power_mode = ios->power_mode;
mxcmci_set_power(host, ios->vdd);
if (ios->power_mode == MMC_POWER_ON) if (ios->power_mode == MMC_POWER_ON)
host->cmdat |= CMD_DAT_CONT_INIT; host->cmdat |= CMD_DAT_CONT_INIT;
...@@ -1040,8 +1014,8 @@ static const struct mmc_host_ops mxcmci_ops = { ...@@ -1040,8 +1014,8 @@ static const struct mmc_host_ops mxcmci_ops = {
static int mxcmci_probe(struct platform_device *pdev) static int mxcmci_probe(struct platform_device *pdev)
{ {
struct mmc_host *mmc; struct mmc_host *mmc;
struct mxcmci_host *host = NULL; struct mxcmci_host *host;
struct resource *iores, *r; struct resource *res;
int ret = 0, irq; int ret = 0, irq;
bool dat3_card_detect = false; bool dat3_card_detect = false;
dma_cap_mask_t mask; dma_cap_mask_t mask;
...@@ -1052,21 +1026,25 @@ static int mxcmci_probe(struct platform_device *pdev) ...@@ -1052,21 +1026,25 @@ static int mxcmci_probe(struct platform_device *pdev)
of_id = of_match_device(mxcmci_of_match, &pdev->dev); of_id = of_match_device(mxcmci_of_match, &pdev->dev);
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (!iores || irq < 0) if (irq < 0)
return -EINVAL; return -EINVAL;
r = request_mem_region(iores->start, resource_size(iores), pdev->name); mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
if (!r) if (!mmc)
return -EBUSY; return -ENOMEM;
host = mmc_priv(mmc);
mmc = mmc_alloc_host(sizeof(struct mxcmci_host), &pdev->dev); host->base = devm_ioremap_resource(&pdev->dev, res);
if (!mmc) { if (IS_ERR(host->base)) {
ret = -ENOMEM; ret = PTR_ERR(host->base);
goto out_release_mem; goto out_free;
} }
host->phys_base = res->start;
ret = mmc_of_parse(mmc); ret = mmc_of_parse(mmc);
if (ret) if (ret)
goto out_free; goto out_free;
...@@ -1084,13 +1062,6 @@ static int mxcmci_probe(struct platform_device *pdev) ...@@ -1084,13 +1062,6 @@ static int mxcmci_probe(struct platform_device *pdev)
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
mmc->max_seg_size = mmc->max_req_size; mmc->max_seg_size = mmc->max_req_size;
host = mmc_priv(mmc);
host->base = ioremap(r->start, resource_size(r));
if (!host->base) {
ret = -ENOMEM;
goto out_free;
}
if (of_id) { if (of_id) {
const struct platform_device_id *id_entry = of_id->data; const struct platform_device_id *id_entry = of_id->data;
host->devtype = id_entry->driver_data; host->devtype = id_entry->driver_data;
...@@ -1112,7 +1083,14 @@ static int mxcmci_probe(struct platform_device *pdev) ...@@ -1112,7 +1083,14 @@ static int mxcmci_probe(struct platform_device *pdev)
&& !of_property_read_bool(pdev->dev.of_node, "cd-gpios")) && !of_property_read_bool(pdev->dev.of_node, "cd-gpios"))
dat3_card_detect = true; dat3_card_detect = true;
mxcmci_init_ocr(host); ret = mmc_regulator_get_supply(mmc);
if (ret) {
if (pdata && ret != -EPROBE_DEFER)
mmc->ocr_avail = pdata->ocr_avail ? :
MMC_VDD_32_33 | MMC_VDD_33_34;
else
goto out_free;
}
if (dat3_card_detect) if (dat3_card_detect)
host->default_irq_mask = host->default_irq_mask =
...@@ -1120,19 +1098,16 @@ static int mxcmci_probe(struct platform_device *pdev) ...@@ -1120,19 +1098,16 @@ static int mxcmci_probe(struct platform_device *pdev)
else else
host->default_irq_mask = 0; host->default_irq_mask = 0;
host->res = r;
host->irq = irq;
host->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); host->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(host->clk_ipg)) { if (IS_ERR(host->clk_ipg)) {
ret = PTR_ERR(host->clk_ipg); ret = PTR_ERR(host->clk_ipg);
goto out_iounmap; goto out_free;
} }
host->clk_per = devm_clk_get(&pdev->dev, "per"); host->clk_per = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(host->clk_per)) { if (IS_ERR(host->clk_per)) {
ret = PTR_ERR(host->clk_per); ret = PTR_ERR(host->clk_per);
goto out_iounmap; goto out_free;
} }
clk_prepare_enable(host->clk_per); clk_prepare_enable(host->clk_per);
...@@ -1159,9 +1134,9 @@ static int mxcmci_probe(struct platform_device *pdev) ...@@ -1159,9 +1134,9 @@ static int mxcmci_probe(struct platform_device *pdev)
if (!host->pdata) { if (!host->pdata) {
host->dma = dma_request_slave_channel(&pdev->dev, "rx-tx"); host->dma = dma_request_slave_channel(&pdev->dev, "rx-tx");
} else { } else {
r = platform_get_resource(pdev, IORESOURCE_DMA, 0); res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (r) { if (res) {
host->dmareq = r->start; host->dmareq = res->start;
host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; host->dma_data.peripheral_type = IMX_DMATYPE_SDHC;
host->dma_data.priority = DMA_PRIO_LOW; host->dma_data.priority = DMA_PRIO_LOW;
host->dma_data.dma_request = host->dmareq; host->dma_data.dma_request = host->dmareq;
...@@ -1178,7 +1153,8 @@ static int mxcmci_probe(struct platform_device *pdev) ...@@ -1178,7 +1153,8 @@ static int mxcmci_probe(struct platform_device *pdev)
INIT_WORK(&host->datawork, mxcmci_datawork); INIT_WORK(&host->datawork, mxcmci_datawork);
ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host); ret = devm_request_irq(&pdev->dev, irq, mxcmci_irq, 0,
dev_name(&pdev->dev), host);
if (ret) if (ret)
goto out_free_dma; goto out_free_dma;
...@@ -1188,7 +1164,7 @@ static int mxcmci_probe(struct platform_device *pdev) ...@@ -1188,7 +1164,7 @@ static int mxcmci_probe(struct platform_device *pdev)
ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq, ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq,
host->mmc); host->mmc);
if (ret) if (ret)
goto out_free_irq; goto out_free_dma;
} }
init_timer(&host->watchdog); init_timer(&host->watchdog);
...@@ -1199,20 +1175,17 @@ static int mxcmci_probe(struct platform_device *pdev) ...@@ -1199,20 +1175,17 @@ static int mxcmci_probe(struct platform_device *pdev)
return 0; return 0;
out_free_irq:
free_irq(host->irq, host);
out_free_dma: out_free_dma:
if (host->dma) if (host->dma)
dma_release_channel(host->dma); dma_release_channel(host->dma);
out_clk_put: out_clk_put:
clk_disable_unprepare(host->clk_per); clk_disable_unprepare(host->clk_per);
clk_disable_unprepare(host->clk_ipg); clk_disable_unprepare(host->clk_ipg);
out_iounmap:
iounmap(host->base);
out_free: out_free:
mmc_free_host(mmc); mmc_free_host(mmc);
out_release_mem:
release_mem_region(iores->start, resource_size(iores));
return ret; return ret;
} }
...@@ -1223,30 +1196,21 @@ static int mxcmci_remove(struct platform_device *pdev) ...@@ -1223,30 +1196,21 @@ static int mxcmci_remove(struct platform_device *pdev)
mmc_remove_host(mmc); mmc_remove_host(mmc);
if (host->vcc)
regulator_put(host->vcc);
if (host->pdata && host->pdata->exit) if (host->pdata && host->pdata->exit)
host->pdata->exit(&pdev->dev, mmc); host->pdata->exit(&pdev->dev, mmc);
free_irq(host->irq, host);
iounmap(host->base);
if (host->dma) if (host->dma)
dma_release_channel(host->dma); dma_release_channel(host->dma);
clk_disable_unprepare(host->clk_per); clk_disable_unprepare(host->clk_per);
clk_disable_unprepare(host->clk_ipg); clk_disable_unprepare(host->clk_ipg);
release_mem_region(host->res->start, resource_size(host->res));
mmc_free_host(mmc); mmc_free_host(mmc);
return 0; return 0;
} }
#ifdef CONFIG_PM static int __maybe_unused mxcmci_suspend(struct device *dev)
static int mxcmci_suspend(struct device *dev)
{ {
struct mmc_host *mmc = dev_get_drvdata(dev); struct mmc_host *mmc = dev_get_drvdata(dev);
struct mxcmci_host *host = mmc_priv(mmc); struct mxcmci_host *host = mmc_priv(mmc);
...@@ -1256,7 +1220,7 @@ static int mxcmci_suspend(struct device *dev) ...@@ -1256,7 +1220,7 @@ static int mxcmci_suspend(struct device *dev)
return 0; return 0;
} }
static int mxcmci_resume(struct device *dev) static int __maybe_unused mxcmci_resume(struct device *dev)
{ {
struct mmc_host *mmc = dev_get_drvdata(dev); struct mmc_host *mmc = dev_get_drvdata(dev);
struct mxcmci_host *host = mmc_priv(mmc); struct mxcmci_host *host = mmc_priv(mmc);
...@@ -1266,11 +1230,7 @@ static int mxcmci_resume(struct device *dev) ...@@ -1266,11 +1230,7 @@ static int mxcmci_resume(struct device *dev)
return 0; return 0;
} }
static const struct dev_pm_ops mxcmci_pm_ops = { static SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume);
.suspend = mxcmci_suspend,
.resume = mxcmci_resume,
};
#endif
static struct platform_driver mxcmci_driver = { static struct platform_driver mxcmci_driver = {
.probe = mxcmci_probe, .probe = mxcmci_probe,
...@@ -1279,9 +1239,7 @@ static struct platform_driver mxcmci_driver = { ...@@ -1279,9 +1239,7 @@ static struct platform_driver mxcmci_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &mxcmci_pm_ops, .pm = &mxcmci_pm_ops,
#endif
.of_match_table = mxcmci_of_match, .of_match_table = mxcmci_of_match,
} }
}; };
......
...@@ -70,6 +70,7 @@ struct mxs_mmc_host { ...@@ -70,6 +70,7 @@ struct mxs_mmc_host {
unsigned char bus_width; unsigned char bus_width;
spinlock_t lock; spinlock_t lock;
int sdio_irq_en; int sdio_irq_en;
bool broken_cd;
}; };
static int mxs_mmc_get_cd(struct mmc_host *mmc) static int mxs_mmc_get_cd(struct mmc_host *mmc)
...@@ -78,6 +79,9 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc) ...@@ -78,6 +79,9 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc)
struct mxs_ssp *ssp = &host->ssp; struct mxs_ssp *ssp = &host->ssp;
int present, ret; int present, ret;
if (host->broken_cd)
return -ENOSYS;
ret = mmc_gpio_get_cd(mmc); ret = mmc_gpio_get_cd(mmc);
if (ret >= 0) if (ret >= 0)
return ret; return ret;
...@@ -568,6 +572,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) ...@@ -568,6 +572,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
{ {
const struct of_device_id *of_id = const struct of_device_id *of_id =
of_match_device(mxs_mmc_dt_ids, &pdev->dev); of_match_device(mxs_mmc_dt_ids, &pdev->dev);
struct device_node *np = pdev->dev.of_node;
struct mxs_mmc_host *host; struct mxs_mmc_host *host;
struct mmc_host *mmc; struct mmc_host *mmc;
struct resource *iores; struct resource *iores;
...@@ -634,6 +639,8 @@ static int mxs_mmc_probe(struct platform_device *pdev) ...@@ -634,6 +639,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL;
host->broken_cd = of_property_read_bool(np, "broken-cd");
mmc->f_min = 400000; mmc->f_min = 400000;
mmc->f_max = 288000000; mmc->f_max = 288000000;
......
...@@ -177,7 +177,7 @@ static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) ...@@ -177,7 +177,7 @@ static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
unsigned long tick_ns; unsigned long tick_ns;
if (slot != NULL && slot->host->fclk_enabled && slot->fclk_freq > 0) { if (slot != NULL && slot->host->fclk_enabled && slot->fclk_freq > 0) {
tick_ns = (1000000000 + slot->fclk_freq - 1) / slot->fclk_freq; tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, slot->fclk_freq);
ndelay(8 * tick_ns); ndelay(8 * tick_ns);
} }
} }
...@@ -435,7 +435,7 @@ static void mmc_omap_send_stop_work(struct work_struct *work) ...@@ -435,7 +435,7 @@ static void mmc_omap_send_stop_work(struct work_struct *work)
struct mmc_data *data = host->stop_data; struct mmc_data *data = host->stop_data;
unsigned long tick_ns; unsigned long tick_ns;
tick_ns = (1000000000 + slot->fclk_freq - 1)/slot->fclk_freq; tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, slot->fclk_freq);
ndelay(8*tick_ns); ndelay(8*tick_ns);
mmc_omap_start_command(host, data->stop); mmc_omap_start_command(host, data->stop);
...@@ -477,7 +477,7 @@ mmc_omap_send_abort(struct mmc_omap_host *host, int maxloops) ...@@ -477,7 +477,7 @@ mmc_omap_send_abort(struct mmc_omap_host *host, int maxloops)
u16 stat = 0; u16 stat = 0;
/* Sending abort takes 80 clocks. Have some extra and round up */ /* Sending abort takes 80 clocks. Have some extra and round up */
timeout = (120*1000000 + slot->fclk_freq - 1)/slot->fclk_freq; timeout = DIV_ROUND_UP(120 * USEC_PER_SEC, slot->fclk_freq);
restarts = 0; restarts = 0;
while (restarts < maxloops) { while (restarts < maxloops) {
OMAP_MMC_WRITE(host, STAT, 0xFFFF); OMAP_MMC_WRITE(host, STAT, 0xFFFF);
...@@ -677,8 +677,8 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) ...@@ -677,8 +677,8 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
if (n > host->buffer_bytes_left) if (n > host->buffer_bytes_left)
n = host->buffer_bytes_left; n = host->buffer_bytes_left;
nwords = n / 2; /* Round up to handle odd number of bytes to transfer */
nwords += n & 1; /* handle odd number of bytes to transfer */ nwords = DIV_ROUND_UP(n, 2);
host->buffer_bytes_left -= n; host->buffer_bytes_left -= n;
host->total_bytes_left -= n; host->total_bytes_left -= n;
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/omap-dma.h> #include <linux/omap-dmaengine.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/core.h> #include <linux/mmc/core.h>
#include <linux/mmc/mmc.h> #include <linux/mmc/mmc.h>
...@@ -582,7 +582,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) ...@@ -582,7 +582,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
* - MMC/SD clock coming out of controller > 25MHz * - MMC/SD clock coming out of controller > 25MHz
*/ */
if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) && if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) &&
(ios->timing != MMC_TIMING_UHS_DDR50) && (ios->timing != MMC_TIMING_MMC_DDR52) &&
((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) { ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) {
regval = OMAP_HSMMC_READ(host->base, HCTL); regval = OMAP_HSMMC_READ(host->base, HCTL);
if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000) if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000)
...@@ -602,7 +602,7 @@ static void omap_hsmmc_set_bus_width(struct omap_hsmmc_host *host) ...@@ -602,7 +602,7 @@ static void omap_hsmmc_set_bus_width(struct omap_hsmmc_host *host)
u32 con; u32 con;
con = OMAP_HSMMC_READ(host->base, CON); con = OMAP_HSMMC_READ(host->base, CON);
if (ios->timing == MMC_TIMING_UHS_DDR50) if (ios->timing == MMC_TIMING_MMC_DDR52)
con |= DDR; /* configure in DDR mode */ con |= DDR; /* configure in DDR mode */
else else
con &= ~DDR; con &= ~DDR;
...@@ -920,16 +920,17 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) ...@@ -920,16 +920,17 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data)
static void static void
omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
{ {
host->cmd = NULL;
if (host->mrq->sbc && (host->cmd == host->mrq->sbc) && if (host->mrq->sbc && (host->cmd == host->mrq->sbc) &&
!host->mrq->sbc->error && !(host->flags & AUTO_CMD23)) { !host->mrq->sbc->error && !(host->flags & AUTO_CMD23)) {
host->cmd = NULL;
omap_hsmmc_start_dma_transfer(host); omap_hsmmc_start_dma_transfer(host);
omap_hsmmc_start_command(host, host->mrq->cmd, omap_hsmmc_start_command(host, host->mrq->cmd,
host->mrq->data); host->mrq->data);
return; return;
} }
host->cmd = NULL;
if (cmd->flags & MMC_RSP_PRESENT) { if (cmd->flags & MMC_RSP_PRESENT) {
if (cmd->flags & MMC_RSP_136) { if (cmd->flags & MMC_RSP_136) {
/* response type 2 */ /* response type 2 */
...@@ -1851,6 +1852,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1851,6 +1852,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
unsigned tx_req, rx_req; unsigned tx_req, rx_req;
struct pinctrl *pinctrl; struct pinctrl *pinctrl;
const struct omap_mmc_of_data *data; const struct omap_mmc_of_data *data;
void __iomem *base;
match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
if (match) { if (match) {
...@@ -1881,9 +1883,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1881,9 +1883,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
if (res == NULL || irq < 0) if (res == NULL || irq < 0)
return -ENXIO; return -ENXIO;
res = request_mem_region(res->start, resource_size(res), pdev->name); base = devm_ioremap_resource(&pdev->dev, res);
if (res == NULL) if (IS_ERR(base))
return -EBUSY; return PTR_ERR(base);
ret = omap_hsmmc_gpio_init(pdata); ret = omap_hsmmc_gpio_init(pdata);
if (ret) if (ret)
...@@ -1904,7 +1906,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1904,7 +1906,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
host->irq = irq; host->irq = irq;
host->slot_id = 0; host->slot_id = 0;
host->mapbase = res->start + pdata->reg_offset; host->mapbase = res->start + pdata->reg_offset;
host->base = ioremap(host->mapbase, SZ_4K); host->base = base + pdata->reg_offset;
host->power_mode = MMC_POWER_OFF; host->power_mode = MMC_POWER_OFF;
host->next_data.cookie = 1; host->next_data.cookie = 1;
host->pbias_enabled = 0; host->pbias_enabled = 0;
...@@ -1922,7 +1924,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1922,7 +1924,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
spin_lock_init(&host->irq_lock); spin_lock_init(&host->irq_lock);
host->fclk = clk_get(&pdev->dev, "fck"); host->fclk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(host->fclk)) { if (IS_ERR(host->fclk)) {
ret = PTR_ERR(host->fclk); ret = PTR_ERR(host->fclk);
host->fclk = NULL; host->fclk = NULL;
...@@ -1941,7 +1943,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1941,7 +1943,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
omap_hsmmc_context_save(host); omap_hsmmc_context_save(host);
host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); host->dbclk = devm_clk_get(&pdev->dev, "mmchsdb_fck");
/* /*
* MMC can still work without debounce clock. * MMC can still work without debounce clock.
*/ */
...@@ -1949,7 +1951,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1949,7 +1951,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
host->dbclk = NULL; host->dbclk = NULL;
} else if (clk_prepare_enable(host->dbclk) != 0) { } else if (clk_prepare_enable(host->dbclk) != 0) {
dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n"); dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n");
clk_put(host->dbclk);
host->dbclk = NULL; host->dbclk = NULL;
} }
...@@ -2018,7 +2019,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -2018,7 +2019,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
} }
/* Request IRQ for MMC operations */ /* Request IRQ for MMC operations */
ret = request_irq(host->irq, omap_hsmmc_irq, 0, ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
mmc_hostname(mmc), host); mmc_hostname(mmc), host);
if (ret) { if (ret) {
dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n"); dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
...@@ -2029,7 +2030,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -2029,7 +2030,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
if (pdata->init(&pdev->dev) != 0) { if (pdata->init(&pdev->dev) != 0) {
dev_err(mmc_dev(host->mmc), dev_err(mmc_dev(host->mmc),
"Unable to configure MMC IRQs\n"); "Unable to configure MMC IRQs\n");
goto err_irq_cd_init; goto err_irq;
} }
} }
...@@ -2044,9 +2045,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -2044,9 +2045,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
/* Request IRQ for card detect */ /* Request IRQ for card detect */
if ((mmc_slot(host).card_detect_irq)) { if ((mmc_slot(host).card_detect_irq)) {
ret = request_threaded_irq(mmc_slot(host).card_detect_irq, ret = devm_request_threaded_irq(&pdev->dev,
NULL, mmc_slot(host).card_detect_irq,
omap_hsmmc_detect, NULL, omap_hsmmc_detect,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
mmc_hostname(mmc), host); mmc_hostname(mmc), host);
if (ret) { if (ret) {
...@@ -2089,15 +2090,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -2089,15 +2090,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
err_slot_name: err_slot_name:
mmc_remove_host(mmc); mmc_remove_host(mmc);
free_irq(mmc_slot(host).card_detect_irq, host);
err_irq_cd: err_irq_cd:
if (host->use_reg) if (host->use_reg)
omap_hsmmc_reg_put(host); omap_hsmmc_reg_put(host);
err_reg: err_reg:
if (host->pdata->cleanup) if (host->pdata->cleanup)
host->pdata->cleanup(&pdev->dev); host->pdata->cleanup(&pdev->dev);
err_irq_cd_init:
free_irq(host->irq, host);
err_irq: err_irq:
if (host->tx_chan) if (host->tx_chan)
dma_release_channel(host->tx_chan); dma_release_channel(host->tx_chan);
...@@ -2105,27 +2103,19 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -2105,27 +2103,19 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
dma_release_channel(host->rx_chan); dma_release_channel(host->rx_chan);
pm_runtime_put_sync(host->dev); pm_runtime_put_sync(host->dev);
pm_runtime_disable(host->dev); pm_runtime_disable(host->dev);
clk_put(host->fclk); if (host->dbclk)
if (host->dbclk) {
clk_disable_unprepare(host->dbclk); clk_disable_unprepare(host->dbclk);
clk_put(host->dbclk);
}
err1: err1:
iounmap(host->base);
mmc_free_host(mmc); mmc_free_host(mmc);
err_alloc: err_alloc:
omap_hsmmc_gpio_free(pdata); omap_hsmmc_gpio_free(pdata);
err: err:
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
release_mem_region(res->start, resource_size(res));
return ret; return ret;
} }
static int omap_hsmmc_remove(struct platform_device *pdev) static int omap_hsmmc_remove(struct platform_device *pdev)
{ {
struct omap_hsmmc_host *host = platform_get_drvdata(pdev); struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
struct resource *res;
pm_runtime_get_sync(host->dev); pm_runtime_get_sync(host->dev);
mmc_remove_host(host->mmc); mmc_remove_host(host->mmc);
...@@ -2133,9 +2123,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) ...@@ -2133,9 +2123,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
omap_hsmmc_reg_put(host); omap_hsmmc_reg_put(host);
if (host->pdata->cleanup) if (host->pdata->cleanup)
host->pdata->cleanup(&pdev->dev); host->pdata->cleanup(&pdev->dev);
free_irq(host->irq, host);
if (mmc_slot(host).card_detect_irq)
free_irq(mmc_slot(host).card_detect_irq, host);
if (host->tx_chan) if (host->tx_chan)
dma_release_channel(host->tx_chan); dma_release_channel(host->tx_chan);
...@@ -2144,20 +2131,12 @@ static int omap_hsmmc_remove(struct platform_device *pdev) ...@@ -2144,20 +2131,12 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
pm_runtime_put_sync(host->dev); pm_runtime_put_sync(host->dev);
pm_runtime_disable(host->dev); pm_runtime_disable(host->dev);
clk_put(host->fclk); if (host->dbclk)
if (host->dbclk) {
clk_disable_unprepare(host->dbclk); clk_disable_unprepare(host->dbclk);
clk_put(host->dbclk);
}
omap_hsmmc_gpio_free(host->pdata); omap_hsmmc_gpio_free(host->pdata);
iounmap(host->base);
mmc_free_host(host->mmc); mmc_free_host(host->mmc);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
release_mem_region(res->start, resource_size(res));
return 0; return 0;
} }
......
...@@ -236,6 +236,9 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, ...@@ -236,6 +236,9 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
case MMC_RSP_R1: case MMC_RSP_R1:
rsp_type = SD_RSP_TYPE_R1; rsp_type = SD_RSP_TYPE_R1;
break; break;
case MMC_RSP_R1 & ~MMC_RSP_CRC:
rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7;
break;
case MMC_RSP_R1B: case MMC_RSP_R1B:
rsp_type = SD_RSP_TYPE_R1b; rsp_type = SD_RSP_TYPE_R1b;
break; break;
...@@ -816,6 +819,7 @@ static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing) ...@@ -816,6 +819,7 @@ static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
break; break;
case MMC_TIMING_MMC_DDR52:
case MMC_TIMING_UHS_DDR50: case MMC_TIMING_UHS_DDR50:
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
0x0C | SD_ASYNC_FIFO_NOT_RST, 0x0C | SD_ASYNC_FIFO_NOT_RST,
...@@ -896,6 +900,7 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -896,6 +900,7 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->vpclk = true; host->vpclk = true;
host->double_clk = false; host->double_clk = false;
break; break;
case MMC_TIMING_MMC_DDR52:
case MMC_TIMING_UHS_DDR50: case MMC_TIMING_UHS_DDR50:
case MMC_TIMING_UHS_SDR25: case MMC_TIMING_UHS_SDR25:
host->ssc_depth = RTSX_SSC_DEPTH_1M; host->ssc_depth = RTSX_SSC_DEPTH_1M;
......
...@@ -34,7 +34,8 @@ ...@@ -34,7 +34,8 @@
#include <linux/mfd/rtsx_usb.h> #include <linux/mfd/rtsx_usb.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) #if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \
defined(CONFIG_MMC_REALTEK_USB_MODULE))
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#define RTSX_USB_USE_LEDS_CLASS #define RTSX_USB_USE_LEDS_CLASS
...@@ -59,7 +60,7 @@ struct rtsx_usb_sdmmc { ...@@ -59,7 +60,7 @@ struct rtsx_usb_sdmmc {
unsigned char power_mode; unsigned char power_mode;
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) #ifdef RTSX_USB_USE_LEDS_CLASS
struct led_classdev led; struct led_classdev led;
char led_name[32]; char led_name[32];
struct work_struct led_work; struct work_struct led_work;
......
...@@ -102,11 +102,19 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) ...@@ -102,11 +102,19 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
} }
static const struct sdhci_ops sdhci_acpi_ops_dflt = { static const struct sdhci_ops sdhci_acpi_ops_dflt = {
.set_clock = sdhci_set_clock,
.enable_dma = sdhci_acpi_enable_dma, .enable_dma = sdhci_acpi_enable_dma,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static const struct sdhci_ops sdhci_acpi_ops_int = { static const struct sdhci_ops sdhci_acpi_ops_int = {
.set_clock = sdhci_set_clock,
.enable_dma = sdhci_acpi_enable_dma, .enable_dma = sdhci_acpi_enable_dma,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
.hw_reset = sdhci_acpi_int_hw_reset, .hw_reset = sdhci_acpi_int_hw_reset,
}; };
......
...@@ -206,9 +206,13 @@ static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, ...@@ -206,9 +206,13 @@ static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
} }
static struct sdhci_ops sdhci_bcm_kona_ops = { static struct sdhci_ops sdhci_bcm_kona_ops = {
.set_clock = sdhci_set_clock,
.get_max_clock = sdhci_bcm_kona_get_max_clk, .get_max_clock = sdhci_bcm_kona_get_max_clk,
.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
.card_event = sdhci_bcm_kona_card_event, .card_event = sdhci_bcm_kona_card_event,
}; };
......
...@@ -131,8 +131,12 @@ static const struct sdhci_ops bcm2835_sdhci_ops = { ...@@ -131,8 +131,12 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
.read_l = bcm2835_sdhci_readl, .read_l = bcm2835_sdhci_readl,
.read_w = bcm2835_sdhci_readw, .read_w = bcm2835_sdhci_readw,
.read_b = bcm2835_sdhci_readb, .read_b = bcm2835_sdhci_readb,
.set_clock = sdhci_set_clock,
.get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_min_clock = bcm2835_sdhci_get_min_clock, .get_min_clock = bcm2835_sdhci_get_min_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = { static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
......
...@@ -30,13 +30,12 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -30,13 +30,12 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
u16 clk; u16 clk;
unsigned long timeout; unsigned long timeout;
if (clock == host->clock) host->mmc->actual_clock = 0;
return;
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
if (clock == 0) if (clock == 0)
goto out; return;
while (host->max_clk / div > clock) { while (host->max_clk / div > clock) {
/* /*
...@@ -75,13 +74,14 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -75,13 +74,14 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
clk |= SDHCI_CLOCK_CARD_EN; clk |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
out:
host->clock = clock;
} }
static const struct sdhci_ops sdhci_cns3xxx_ops = { static const struct sdhci_ops sdhci_cns3xxx_ops = {
.get_max_clock = sdhci_cns3xxx_get_max_clk, .get_max_clock = sdhci_cns3xxx_get_max_clk,
.set_clock = sdhci_cns3xxx_set_clock, .set_clock = sdhci_cns3xxx_set_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
...@@ -90,8 +90,7 @@ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { ...@@ -90,8 +90,7 @@ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
SDHCI_QUIRK_INVERTED_WRITE_PROTECT | SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
SDHCI_QUIRK_NONSTANDARD_CLOCK,
}; };
static int sdhci_cns3xxx_probe(struct platform_device *pdev) static int sdhci_cns3xxx_probe(struct platform_device *pdev)
......
...@@ -21,28 +21,17 @@ ...@@ -21,28 +21,17 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h>
#include "sdhci-pltfm.h" #include "sdhci-pltfm.h"
struct sdhci_dove_priv { struct sdhci_dove_priv {
struct clk *clk; struct clk *clk;
int gpio_cd;
}; };
static irqreturn_t sdhci_dove_carddetect_irq(int irq, void *data)
{
struct sdhci_host *host = data;
tasklet_schedule(&host->card_tasklet);
return IRQ_HANDLED;
}
static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
{ {
u16 ret; u16 ret;
...@@ -60,8 +49,6 @@ static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) ...@@ -60,8 +49,6 @@ static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
static u32 sdhci_dove_readl(struct sdhci_host *host, int reg) static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
{ {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_dove_priv *priv = pltfm_host->priv;
u32 ret; u32 ret;
ret = readl(host->ioaddr + reg); ret = readl(host->ioaddr + reg);
...@@ -71,14 +58,6 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg) ...@@ -71,14 +58,6 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
/* Mask the support for 3.0V */ /* Mask the support for 3.0V */
ret &= ~SDHCI_CAN_VDD_300; ret &= ~SDHCI_CAN_VDD_300;
break; break;
case SDHCI_PRESENT_STATE:
if (gpio_is_valid(priv->gpio_cd)) {
if (gpio_get_value(priv->gpio_cd) == 0)
ret |= SDHCI_CARD_PRESENT;
else
ret &= ~SDHCI_CARD_PRESENT;
}
break;
} }
return ret; return ret;
} }
...@@ -86,6 +65,10 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg) ...@@ -86,6 +65,10 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
static const struct sdhci_ops sdhci_dove_ops = { static const struct sdhci_ops sdhci_dove_ops = {
.read_w = sdhci_dove_readw, .read_w = sdhci_dove_readw,
.read_l = sdhci_dove_readl, .read_l = sdhci_dove_readl,
.set_clock = sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static const struct sdhci_pltfm_data sdhci_dove_pdata = { static const struct sdhci_pltfm_data sdhci_dove_pdata = {
...@@ -113,28 +96,9 @@ static int sdhci_dove_probe(struct platform_device *pdev) ...@@ -113,28 +96,9 @@ static int sdhci_dove_probe(struct platform_device *pdev)
priv->clk = devm_clk_get(&pdev->dev, NULL); priv->clk = devm_clk_get(&pdev->dev, NULL);
if (pdev->dev.of_node) {
priv->gpio_cd = of_get_named_gpio(pdev->dev.of_node,
"cd-gpios", 0);
} else {
priv->gpio_cd = -EINVAL;
}
if (gpio_is_valid(priv->gpio_cd)) {
ret = gpio_request(priv->gpio_cd, "sdhci-cd");
if (ret) {
dev_err(&pdev->dev, "card detect gpio request failed: %d\n",
ret);
return ret;
}
gpio_direction_input(priv->gpio_cd);
}
host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0); host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0);
if (IS_ERR(host)) { if (IS_ERR(host))
ret = PTR_ERR(host); return PTR_ERR(host);
goto err_sdhci_pltfm_init;
}
pltfm_host = sdhci_priv(host); pltfm_host = sdhci_priv(host);
pltfm_host->priv = priv; pltfm_host->priv = priv;
...@@ -142,39 +106,20 @@ static int sdhci_dove_probe(struct platform_device *pdev) ...@@ -142,39 +106,20 @@ static int sdhci_dove_probe(struct platform_device *pdev)
if (!IS_ERR(priv->clk)) if (!IS_ERR(priv->clk))
clk_prepare_enable(priv->clk); clk_prepare_enable(priv->clk);
sdhci_get_of_property(pdev); ret = mmc_of_parse(host->mmc);
if (ret)
goto err_sdhci_add;
ret = sdhci_add_host(host); ret = sdhci_add_host(host);
if (ret) if (ret)
goto err_sdhci_add; goto err_sdhci_add;
/*
* We must request the IRQ after sdhci_add_host(), as the tasklet only
* gets setup in sdhci_add_host() and we oops.
*/
if (gpio_is_valid(priv->gpio_cd)) {
ret = request_irq(gpio_to_irq(priv->gpio_cd),
sdhci_dove_carddetect_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
mmc_hostname(host->mmc), host);
if (ret) {
dev_err(&pdev->dev, "card detect irq request failed: %d\n",
ret);
goto err_request_irq;
}
}
return 0; return 0;
err_request_irq:
sdhci_remove_host(host, 0);
err_sdhci_add: err_sdhci_add:
if (!IS_ERR(priv->clk)) if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
sdhci_pltfm_free(pdev); sdhci_pltfm_free(pdev);
err_sdhci_pltfm_init:
if (gpio_is_valid(priv->gpio_cd))
gpio_free(priv->gpio_cd);
return ret; return ret;
} }
...@@ -186,11 +131,6 @@ static int sdhci_dove_remove(struct platform_device *pdev) ...@@ -186,11 +131,6 @@ static int sdhci_dove_remove(struct platform_device *pdev)
sdhci_pltfm_unregister(pdev); sdhci_pltfm_unregister(pdev);
if (gpio_is_valid(priv->gpio_cd)) {
free_irq(gpio_to_irq(priv->gpio_cd), host);
gpio_free(priv->gpio_cd);
}
if (!IS_ERR(priv->clk)) if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
......
...@@ -160,7 +160,6 @@ struct pltfm_imx_data { ...@@ -160,7 +160,6 @@ struct pltfm_imx_data {
MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */ MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
WAIT_FOR_INT, /* sent CMD12, waiting for response INT */ WAIT_FOR_INT, /* sent CMD12, waiting for response INT */
} multiblock_status; } multiblock_status;
u32 uhs_mode;
u32 is_ddr; u32 is_ddr;
}; };
...@@ -382,7 +381,6 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) ...@@ -382,7 +381,6 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
if (val & ESDHC_MIX_CTRL_SMPCLK_SEL) if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
ret |= SDHCI_CTRL_TUNED_CLK; ret |= SDHCI_CTRL_TUNED_CLK;
ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
return ret; return ret;
...@@ -429,7 +427,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) ...@@ -429,7 +427,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
else else
new_val &= ~ESDHC_VENDOR_SPEC_VSELECT; new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
if (val & SDHCI_CTRL_TUNED_CLK) if (val & SDHCI_CTRL_TUNED_CLK)
...@@ -600,12 +597,14 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, ...@@ -600,12 +597,14 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
u32 temp, val; u32 temp, val;
if (clock == 0) { if (clock == 0) {
host->mmc->actual_clock = 0;
if (esdhc_is_usdhc(imx_data)) { if (esdhc_is_usdhc(imx_data)) {
val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
host->ioaddr + ESDHC_VENDOR_SPEC); host->ioaddr + ESDHC_VENDOR_SPEC);
} }
goto out; return;
} }
if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr) if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr)
...@@ -645,8 +644,6 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, ...@@ -645,8 +644,6 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
} }
mdelay(1); mdelay(1);
out:
host->clock = clock;
} }
static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
...@@ -668,7 +665,7 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) ...@@ -668,7 +665,7 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
return -ENOSYS; return -ENOSYS;
} }
static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width) static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
{ {
u32 ctrl; u32 ctrl;
...@@ -686,8 +683,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width) ...@@ -686,8 +683,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
esdhc_clrset_le(host, ESDHC_CTRL_BUSWIDTH_MASK, ctrl, esdhc_clrset_le(host, ESDHC_CTRL_BUSWIDTH_MASK, ctrl,
SDHCI_HOST_CONTROL); SDHCI_HOST_CONTROL);
return 0;
} }
static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
...@@ -697,6 +692,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) ...@@ -697,6 +692,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
/* FIXME: delay a bit for card to be ready for next tuning due to errors */ /* FIXME: delay a bit for card to be ready for next tuning due to errors */
mdelay(1); mdelay(1);
/* This is balanced by the runtime put in sdhci_tasklet_finish */
pm_runtime_get_sync(host->mmc->parent); pm_runtime_get_sync(host->mmc->parent);
reg = readl(host->ioaddr + ESDHC_MIX_CTRL); reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
...@@ -713,13 +709,12 @@ static void esdhc_request_done(struct mmc_request *mrq) ...@@ -713,13 +709,12 @@ static void esdhc_request_done(struct mmc_request *mrq)
complete(&mrq->completion); complete(&mrq->completion);
} }
static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode,
struct scatterlist *sg)
{ {
struct mmc_command cmd = {0}; struct mmc_command cmd = {0};
struct mmc_request mrq = {NULL}; struct mmc_request mrq = {NULL};
struct mmc_data data = {0}; struct mmc_data data = {0};
struct scatterlist sg;
char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN];
cmd.opcode = opcode; cmd.opcode = opcode;
cmd.arg = 0; cmd.arg = 0;
...@@ -728,11 +723,9 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) ...@@ -728,11 +723,9 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN; data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN;
data.blocks = 1; data.blocks = 1;
data.flags = MMC_DATA_READ; data.flags = MMC_DATA_READ;
data.sg = &sg; data.sg = sg;
data.sg_len = 1; data.sg_len = 1;
sg_init_one(&sg, tuning_pattern, sizeof(tuning_pattern));
mrq.cmd = &cmd; mrq.cmd = &cmd;
mrq.cmd->mrq = &mrq; mrq.cmd->mrq = &mrq;
mrq.data = &data; mrq.data = &data;
...@@ -742,14 +735,12 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) ...@@ -742,14 +735,12 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
mrq.done = esdhc_request_done; mrq.done = esdhc_request_done;
init_completion(&(mrq.completion)); init_completion(&(mrq.completion));
disable_irq(host->irq); spin_lock_irq(&host->lock);
spin_lock(&host->lock);
host->mrq = &mrq; host->mrq = &mrq;
sdhci_send_command(host, mrq.cmd); sdhci_send_command(host, mrq.cmd);
spin_unlock(&host->lock); spin_unlock_irq(&host->lock);
enable_irq(host->irq);
wait_for_completion(&mrq.completion); wait_for_completion(&mrq.completion);
...@@ -772,13 +763,21 @@ static void esdhc_post_tuning(struct sdhci_host *host) ...@@ -772,13 +763,21 @@ static void esdhc_post_tuning(struct sdhci_host *host)
static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
{ {
struct scatterlist sg;
char *tuning_pattern;
int min, max, avg, ret; int min, max, avg, ret;
tuning_pattern = kmalloc(ESDHC_TUNING_BLOCK_PATTERN_LEN, GFP_KERNEL);
if (!tuning_pattern)
return -ENOMEM;
sg_init_one(&sg, tuning_pattern, ESDHC_TUNING_BLOCK_PATTERN_LEN);
/* find the mininum delay first which can pass tuning */ /* find the mininum delay first which can pass tuning */
min = ESDHC_TUNE_CTRL_MIN; min = ESDHC_TUNE_CTRL_MIN;
while (min < ESDHC_TUNE_CTRL_MAX) { while (min < ESDHC_TUNE_CTRL_MAX) {
esdhc_prepare_tuning(host, min); esdhc_prepare_tuning(host, min);
if (!esdhc_send_tuning_cmd(host, opcode)) if (!esdhc_send_tuning_cmd(host, opcode, &sg))
break; break;
min += ESDHC_TUNE_CTRL_STEP; min += ESDHC_TUNE_CTRL_STEP;
} }
...@@ -787,7 +786,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) ...@@ -787,7 +786,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
max = min + ESDHC_TUNE_CTRL_STEP; max = min + ESDHC_TUNE_CTRL_STEP;
while (max < ESDHC_TUNE_CTRL_MAX) { while (max < ESDHC_TUNE_CTRL_MAX) {
esdhc_prepare_tuning(host, max); esdhc_prepare_tuning(host, max);
if (esdhc_send_tuning_cmd(host, opcode)) { if (esdhc_send_tuning_cmd(host, opcode, &sg)) {
max -= ESDHC_TUNE_CTRL_STEP; max -= ESDHC_TUNE_CTRL_STEP;
break; break;
} }
...@@ -797,9 +796,11 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) ...@@ -797,9 +796,11 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
/* use average delay to get the best timing */ /* use average delay to get the best timing */
avg = (min + max) / 2; avg = (min + max) / 2;
esdhc_prepare_tuning(host, avg); esdhc_prepare_tuning(host, avg);
ret = esdhc_send_tuning_cmd(host, opcode); ret = esdhc_send_tuning_cmd(host, opcode, &sg);
esdhc_post_tuning(host); esdhc_post_tuning(host);
kfree(tuning_pattern);
dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n", dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
ret ? "failed" : "passed", avg, ret); ret ? "failed" : "passed", avg, ret);
...@@ -837,28 +838,21 @@ static int esdhc_change_pinstate(struct sdhci_host *host, ...@@ -837,28 +838,21 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
return pinctrl_select_state(imx_data->pinctrl, pinctrl); return pinctrl_select_state(imx_data->pinctrl, pinctrl);
} }
static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
{ {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv; struct pltfm_imx_data *imx_data = pltfm_host->priv;
struct esdhc_platform_data *boarddata = &imx_data->boarddata; struct esdhc_platform_data *boarddata = &imx_data->boarddata;
switch (uhs) { switch (timing) {
case MMC_TIMING_UHS_SDR12: case MMC_TIMING_UHS_SDR12:
imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12;
break;
case MMC_TIMING_UHS_SDR25: case MMC_TIMING_UHS_SDR25:
imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25;
break;
case MMC_TIMING_UHS_SDR50: case MMC_TIMING_UHS_SDR50:
imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50;
break;
case MMC_TIMING_UHS_SDR104: case MMC_TIMING_UHS_SDR104:
case MMC_TIMING_MMC_HS200: case MMC_TIMING_MMC_HS200:
imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104;
break; break;
case MMC_TIMING_UHS_DDR50: case MMC_TIMING_UHS_DDR50:
imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50; case MMC_TIMING_MMC_DDR52:
writel(readl(host->ioaddr + ESDHC_MIX_CTRL) | writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
ESDHC_MIX_CTRL_DDREN, ESDHC_MIX_CTRL_DDREN,
host->ioaddr + ESDHC_MIX_CTRL); host->ioaddr + ESDHC_MIX_CTRL);
...@@ -875,7 +869,15 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) ...@@ -875,7 +869,15 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
break; break;
} }
return esdhc_change_pinstate(host, uhs); esdhc_change_pinstate(host, timing);
}
static void esdhc_reset(struct sdhci_host *host, u8 mask)
{
sdhci_reset(host, mask);
sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
} }
static struct sdhci_ops sdhci_esdhc_ops = { static struct sdhci_ops sdhci_esdhc_ops = {
...@@ -888,8 +890,9 @@ static struct sdhci_ops sdhci_esdhc_ops = { ...@@ -888,8 +890,9 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.get_max_clock = esdhc_pltfm_get_max_clock, .get_max_clock = esdhc_pltfm_get_max_clock,
.get_min_clock = esdhc_pltfm_get_min_clock, .get_min_clock = esdhc_pltfm_get_min_clock,
.get_ro = esdhc_pltfm_get_ro, .get_ro = esdhc_pltfm_get_ro,
.platform_bus_width = esdhc_pltfm_bus_width, .set_bus_width = esdhc_pltfm_set_bus_width,
.set_uhs_signaling = esdhc_set_uhs_signaling, .set_uhs_signaling = esdhc_set_uhs_signaling,
.reset = esdhc_reset,
}; };
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
...@@ -1170,8 +1173,10 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev) ...@@ -1170,8 +1173,10 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev)
ret = sdhci_runtime_suspend_host(host); ret = sdhci_runtime_suspend_host(host);
clk_disable_unprepare(imx_data->clk_per); if (!sdhci_sdio_irq_enabled(host)) {
clk_disable_unprepare(imx_data->clk_ipg); clk_disable_unprepare(imx_data->clk_per);
clk_disable_unprepare(imx_data->clk_ipg);
}
clk_disable_unprepare(imx_data->clk_ahb); clk_disable_unprepare(imx_data->clk_ahb);
return ret; return ret;
...@@ -1183,8 +1188,10 @@ static int sdhci_esdhc_runtime_resume(struct device *dev) ...@@ -1183,8 +1188,10 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv; struct pltfm_imx_data *imx_data = pltfm_host->priv;
clk_prepare_enable(imx_data->clk_per); if (!sdhci_sdio_irq_enabled(host)) {
clk_prepare_enable(imx_data->clk_ipg); clk_prepare_enable(imx_data->clk_per);
clk_prepare_enable(imx_data->clk_ipg);
}
clk_prepare_enable(imx_data->clk_ahb); clk_prepare_enable(imx_data->clk_ahb);
return sdhci_runtime_resume_host(host); return sdhci_runtime_resume_host(host);
......
...@@ -20,10 +20,8 @@ ...@@ -20,10 +20,8 @@
#define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \ #define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
SDHCI_QUIRK_NO_BUSY_IRQ | \ SDHCI_QUIRK_NO_BUSY_IRQ | \
SDHCI_QUIRK_NONSTANDARD_CLOCK | \
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
SDHCI_QUIRK_PIO_NEEDS_DELAY | \ SDHCI_QUIRK_PIO_NEEDS_DELAY)
SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
#define ESDHC_SYSTEM_CONTROL 0x2c #define ESDHC_SYSTEM_CONTROL 0x2c
#define ESDHC_CLOCK_MASK 0x0000fff0 #define ESDHC_CLOCK_MASK 0x0000fff0
......
...@@ -52,8 +52,12 @@ static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host) ...@@ -52,8 +52,12 @@ static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)
} }
static struct sdhci_ops sdhci_arasan_ops = { static struct sdhci_ops sdhci_arasan_ops = {
.set_clock = sdhci_set_clock,
.get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_timeout_clock = sdhci_arasan_get_timeout_clock, .get_timeout_clock = sdhci_arasan_get_timeout_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static struct sdhci_pltfm_data sdhci_arasan_pdata = { static struct sdhci_pltfm_data sdhci_arasan_pdata = {
......
...@@ -199,13 +199,14 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) ...@@ -199,13 +199,14 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
{ {
int pre_div = 2; int pre_div = 2;
int div = 1; int div = 1;
u32 temp; u32 temp;
host->mmc->actual_clock = 0;
if (clock == 0) if (clock == 0)
goto out; return;
/* Workaround to reduce the clock frequency for p1010 esdhc */ /* Workaround to reduce the clock frequency for p1010 esdhc */
if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) { if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
...@@ -238,24 +239,8 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -238,24 +239,8 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
| (pre_div << ESDHC_PREDIV_SHIFT)); | (pre_div << ESDHC_PREDIV_SHIFT));
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
mdelay(1); mdelay(1);
out:
host->clock = clock;
}
#ifdef CONFIG_PM
static u32 esdhc_proctl;
static void esdhc_of_suspend(struct sdhci_host *host)
{
esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
} }
static void esdhc_of_resume(struct sdhci_host *host)
{
esdhc_of_enable_dma(host);
sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
}
#endif
static void esdhc_of_platform_init(struct sdhci_host *host) static void esdhc_of_platform_init(struct sdhci_host *host)
{ {
u32 vvn; u32 vvn;
...@@ -269,7 +254,7 @@ static void esdhc_of_platform_init(struct sdhci_host *host) ...@@ -269,7 +254,7 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
} }
static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width) static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
{ {
u32 ctrl; u32 ctrl;
...@@ -289,8 +274,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width) ...@@ -289,8 +274,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL, clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL,
ESDHC_CTRL_BUSWIDTH_MASK, ctrl); ESDHC_CTRL_BUSWIDTH_MASK, ctrl);
return 0;
} }
static const struct sdhci_ops sdhci_esdhc_ops = { static const struct sdhci_ops sdhci_esdhc_ops = {
...@@ -305,13 +288,46 @@ static const struct sdhci_ops sdhci_esdhc_ops = { ...@@ -305,13 +288,46 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
.get_max_clock = esdhc_of_get_max_clock, .get_max_clock = esdhc_of_get_max_clock,
.get_min_clock = esdhc_of_get_min_clock, .get_min_clock = esdhc_of_get_min_clock,
.platform_init = esdhc_of_platform_init, .platform_init = esdhc_of_platform_init,
#ifdef CONFIG_PM
.platform_suspend = esdhc_of_suspend,
.platform_resume = esdhc_of_resume,
#endif
.adma_workaround = esdhci_of_adma_workaround, .adma_workaround = esdhci_of_adma_workaround,
.platform_bus_width = esdhc_pltfm_bus_width, .set_bus_width = esdhc_pltfm_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
};
#ifdef CONFIG_PM
static u32 esdhc_proctl;
static int esdhc_of_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
return sdhci_suspend_host(host);
}
static int esdhc_of_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
int ret = sdhci_resume_host(host);
if (ret == 0) {
/* Isn't this already done by sdhci_resume_host() ? --rmk */
esdhc_of_enable_dma(host);
sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
}
return ret;
}
static const struct dev_pm_ops esdhc_pmops = {
.suspend = esdhc_of_suspend,
.resume = esdhc_of_resume,
}; };
#define ESDHC_PMOPS (&esdhc_pmops)
#else
#define ESDHC_PMOPS NULL
#endif
static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
/* /*
...@@ -374,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = { ...@@ -374,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = {
.name = "sdhci-esdhc", .name = "sdhci-esdhc",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = sdhci_esdhc_of_match, .of_match_table = sdhci_esdhc_of_match,
.pm = SDHCI_PLTFM_PMOPS, .pm = ESDHC_PMOPS,
}, },
.probe = sdhci_esdhc_probe, .probe = sdhci_esdhc_probe,
.remove = sdhci_esdhc_remove, .remove = sdhci_esdhc_remove,
......
...@@ -58,6 +58,10 @@ static const struct sdhci_ops sdhci_hlwd_ops = { ...@@ -58,6 +58,10 @@ static const struct sdhci_ops sdhci_hlwd_ops = {
.write_l = sdhci_hlwd_writel, .write_l = sdhci_hlwd_writel,
.write_w = sdhci_hlwd_writew, .write_w = sdhci_hlwd_writew,
.write_b = sdhci_hlwd_writeb, .write_b = sdhci_hlwd_writeb,
.set_clock = sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static const struct sdhci_pltfm_data sdhci_hlwd_pdata = { static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
......
...@@ -21,6 +21,45 @@ ...@@ -21,6 +21,45 @@
#include "sdhci-pci.h" #include "sdhci-pci.h"
#include "sdhci-pci-o2micro.h" #include "sdhci-pci-o2micro.h"
static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value)
{
u32 scratch_32;
pci_read_config_dword(chip->pdev,
O2_SD_PLL_SETTING, &scratch_32);
scratch_32 &= 0x0000FFFF;
scratch_32 |= value;
pci_write_config_dword(chip->pdev,
O2_SD_PLL_SETTING, scratch_32);
}
static void o2_pci_led_enable(struct sdhci_pci_chip *chip)
{
int ret;
u32 scratch_32;
/* Set led of SD host function enable */
ret = pci_read_config_dword(chip->pdev,
O2_SD_FUNC_REG0, &scratch_32);
if (ret)
return;
scratch_32 &= ~O2_SD_FREG0_LEDOFF;
pci_write_config_dword(chip->pdev,
O2_SD_FUNC_REG0, scratch_32);
ret = pci_read_config_dword(chip->pdev,
O2_SD_TEST_REG, &scratch_32);
if (ret)
return;
scratch_32 |= O2_SD_LED_ENABLE;
pci_write_config_dword(chip->pdev,
O2_SD_TEST_REG, scratch_32);
}
void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
{ {
u32 scratch_32; u32 scratch_32;
...@@ -216,6 +255,40 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) ...@@ -216,6 +255,40 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
scratch &= 0x7f; scratch &= 0x7f;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
/* DevId=8520 subId= 0x11 or 0x12 Type Chip support */
if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) {
ret = pci_read_config_dword(chip->pdev,
O2_SD_FUNC_REG0,
&scratch_32);
scratch_32 = ((scratch_32 & 0xFF000000) >> 24);
/* Check Whether subId is 0x11 or 0x12 */
if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) {
scratch_32 = 0x2c280000;
/* Set Base Clock to 208MZ */
o2_pci_set_baseclk(chip, scratch_32);
ret = pci_read_config_dword(chip->pdev,
O2_SD_FUNC_REG4,
&scratch_32);
/* Enable Base Clk setting change */
scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET;
pci_write_config_dword(chip->pdev,
O2_SD_FUNC_REG4,
scratch_32);
/* Set Tuning Window to 4 */
pci_write_config_byte(chip->pdev,
O2_SD_TUNING_CTRL, 0x44);
break;
}
}
/* Enable 8520 led function */
o2_pci_led_enable(chip);
/* Set timeout CLK */ /* Set timeout CLK */
ret = pci_read_config_dword(chip->pdev, ret = pci_read_config_dword(chip->pdev,
O2_SD_CLK_SETTING, &scratch_32); O2_SD_CLK_SETTING, &scratch_32);
...@@ -276,7 +349,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) ...@@ -276,7 +349,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
ret = pci_read_config_dword(chip->pdev, ret = pci_read_config_dword(chip->pdev,
O2_SD_FUNC_REG0, &scratch_32); O2_SD_PLL_SETTING, &scratch_32);
if ((scratch_32 & 0xff000000) == 0x01000000) { if ((scratch_32 & 0xff000000) == 0x01000000) {
scratch_32 &= 0x0000FFFF; scratch_32 &= 0x0000FFFF;
...@@ -299,6 +372,9 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) ...@@ -299,6 +372,9 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
O2_SD_FUNC_REG4, scratch_32); O2_SD_FUNC_REG4, scratch_32);
} }
/* Set Tuning Windows to 5 */
pci_write_config_byte(chip->pdev,
O2_SD_TUNING_CTRL, 0x55);
/* Lock WP */ /* Lock WP */
ret = pci_read_config_byte(chip->pdev, ret = pci_read_config_byte(chip->pdev,
O2_SD_LOCK_WP, &scratch); O2_SD_LOCK_WP, &scratch);
......
...@@ -57,6 +57,9 @@ ...@@ -57,6 +57,9 @@
#define O2_SD_UHS2_L1_CTRL 0x35C #define O2_SD_UHS2_L1_CTRL 0x35C
#define O2_SD_FUNC_REG3 0x3E0 #define O2_SD_FUNC_REG3 0x3E0
#define O2_SD_FUNC_REG4 0x3E4 #define O2_SD_FUNC_REG4 0x3E4
#define O2_SD_LED_ENABLE BIT(6)
#define O2_SD_FREG0_LEDOFF BIT(13)
#define O2_SD_FREG4_ENABLE_CLK_SET BIT(22)
#define O2_SD_VENDOR_SETTING 0x110 #define O2_SD_VENDOR_SETTING 0x110
#define O2_SD_VENDOR_SETTING2 0x1C8 #define O2_SD_VENDOR_SETTING2 0x1C8
......
...@@ -1031,7 +1031,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host) ...@@ -1031,7 +1031,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
return 0; return 0;
} }
static int sdhci_pci_bus_width(struct sdhci_host *host, int width) static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width)
{ {
u8 ctrl; u8 ctrl;
...@@ -1052,8 +1052,6 @@ static int sdhci_pci_bus_width(struct sdhci_host *host, int width) ...@@ -1052,8 +1052,6 @@ static int sdhci_pci_bus_width(struct sdhci_host *host, int width)
} }
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
return 0;
} }
static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host) static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host)
...@@ -1080,8 +1078,11 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host) ...@@ -1080,8 +1078,11 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
} }
static const struct sdhci_ops sdhci_pci_ops = { static const struct sdhci_ops sdhci_pci_ops = {
.set_clock = sdhci_set_clock,
.enable_dma = sdhci_pci_enable_dma, .enable_dma = sdhci_pci_enable_dma,
.platform_bus_width = sdhci_pci_bus_width, .set_bus_width = sdhci_pci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
.hw_reset = sdhci_pci_hw_reset, .hw_reset = sdhci_pci_hw_reset,
}; };
......
...@@ -45,6 +45,10 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host) ...@@ -45,6 +45,10 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host)
EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock); EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
static const struct sdhci_ops sdhci_pltfm_ops = { static const struct sdhci_ops sdhci_pltfm_ops = {
.set_clock = sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -51,11 +51,13 @@ ...@@ -51,11 +51,13 @@
#define MMC_CARD 0x1000 #define MMC_CARD 0x1000
#define MMC_WIDTH 0x0100 #define MMC_WIDTH 0x0100
static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) static void pxav2_reset(struct sdhci_host *host, u8 mask)
{ {
struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
sdhci_reset(host, mask);
if (mask == SDHCI_RESET_ALL) { if (mask == SDHCI_RESET_ALL) {
u16 tmp = 0; u16 tmp = 0;
...@@ -88,7 +90,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) ...@@ -88,7 +90,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
} }
} }
static int pxav2_mmc_set_width(struct sdhci_host *host, int width) static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
{ {
u8 ctrl; u8 ctrl;
u16 tmp; u16 tmp;
...@@ -107,14 +109,14 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width) ...@@ -107,14 +109,14 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
} }
writew(tmp, host->ioaddr + SD_CE_ATA_2); writew(tmp, host->ioaddr + SD_CE_ATA_2);
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
return 0;
} }
static const struct sdhci_ops pxav2_sdhci_ops = { static const struct sdhci_ops pxav2_sdhci_ops = {
.set_clock = sdhci_set_clock,
.get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock,
.platform_reset_exit = pxav2_set_private_registers, .set_bus_width = pxav2_mmc_set_bus_width,
.platform_bus_width = pxav2_mmc_set_width, .reset = pxav2_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -112,11 +112,13 @@ static int mv_conf_mbus_windows(struct platform_device *pdev, ...@@ -112,11 +112,13 @@ static int mv_conf_mbus_windows(struct platform_device *pdev,
return 0; return 0;
} }
static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask) static void pxav3_reset(struct sdhci_host *host, u8 mask)
{ {
struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
sdhci_reset(host, mask);
if (mask == SDHCI_RESET_ALL) { if (mask == SDHCI_RESET_ALL) {
/* /*
* tune timing of read data/command when crc error happen * tune timing of read data/command when crc error happen
...@@ -184,7 +186,7 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode) ...@@ -184,7 +186,7 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
pxa->power_mode = power_mode; pxa->power_mode = power_mode;
} }
static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
{ {
u16 ctrl_2; u16 ctrl_2;
...@@ -218,15 +220,16 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) ...@@ -218,15 +220,16 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
dev_dbg(mmc_dev(host->mmc), dev_dbg(mmc_dev(host->mmc),
"%s uhs = %d, ctrl_2 = %04X\n", "%s uhs = %d, ctrl_2 = %04X\n",
__func__, uhs, ctrl_2); __func__, uhs, ctrl_2);
return 0;
} }
static const struct sdhci_ops pxav3_sdhci_ops = { static const struct sdhci_ops pxav3_sdhci_ops = {
.platform_reset_exit = pxav3_set_private_registers, .set_clock = sdhci_set_clock,
.set_uhs_signaling = pxav3_set_uhs_signaling, .set_uhs_signaling = pxav3_set_uhs_signaling,
.platform_send_init_74_clocks = pxav3_gen_init_74_clocks, .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
.get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = pxav3_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static struct sdhci_pltfm_data sdhci_pxav3_pdata = { static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
......
...@@ -33,9 +33,6 @@ ...@@ -33,9 +33,6 @@
#define MAX_BUS_CLK (4) #define MAX_BUS_CLK (4)
/* Number of gpio's used is max data bus width + command and clock lines */
#define NUM_GPIOS(x) (x + 2)
/** /**
* struct sdhci_s3c - S3C SDHCI instance * struct sdhci_s3c - S3C SDHCI instance
* @host: The SDHCI host created * @host: The SDHCI host created
...@@ -58,6 +55,8 @@ struct sdhci_s3c { ...@@ -58,6 +55,8 @@ struct sdhci_s3c {
struct clk *clk_io; struct clk *clk_io;
struct clk *clk_bus[MAX_BUS_CLK]; struct clk *clk_bus[MAX_BUS_CLK];
unsigned long clk_rates[MAX_BUS_CLK]; unsigned long clk_rates[MAX_BUS_CLK];
bool no_divider;
}; };
/** /**
...@@ -70,6 +69,7 @@ struct sdhci_s3c { ...@@ -70,6 +69,7 @@ struct sdhci_s3c {
*/ */
struct sdhci_s3c_drv_data { struct sdhci_s3c_drv_data {
unsigned int sdhci_quirks; unsigned int sdhci_quirks;
bool no_divider;
}; };
static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
...@@ -119,7 +119,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, ...@@ -119,7 +119,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
* If controller uses a non-standard clock division, find the best clock * If controller uses a non-standard clock division, find the best clock
* speed possible with selected clock source and skip the division. * speed possible with selected clock source and skip the division.
*/ */
if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) { if (ourhost->no_divider) {
rate = clk_round_rate(clksrc, wanted); rate = clk_round_rate(clksrc, wanted);
return wanted - rate; return wanted - rate;
} }
...@@ -161,9 +161,13 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -161,9 +161,13 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
int src; int src;
u32 ctrl; u32 ctrl;
host->mmc->actual_clock = 0;
/* don't bother if the clock is going off. */ /* don't bother if the clock is going off. */
if (clock == 0) if (clock == 0) {
sdhci_set_clock(host, clock);
return; return;
}
for (src = 0; src < MAX_BUS_CLK; src++) { for (src = 0; src < MAX_BUS_CLK; src++) {
delta = sdhci_s3c_consider_clock(ourhost, src, clock); delta = sdhci_s3c_consider_clock(ourhost, src, clock);
...@@ -215,6 +219,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -215,6 +219,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
if (clock < 25 * 1000000) if (clock < 25 * 1000000)
ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2); ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2);
writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3); writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3);
sdhci_set_clock(host, clock);
} }
/** /**
...@@ -295,10 +301,11 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -295,10 +301,11 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
unsigned long timeout; unsigned long timeout;
u16 clk = 0; u16 clk = 0;
host->mmc->actual_clock = 0;
/* If the clock is going off, set to 0 at clock control register */ /* If the clock is going off, set to 0 at clock control register */
if (clock == 0) { if (clock == 0) {
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
host->clock = clock;
return; return;
} }
...@@ -306,8 +313,6 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -306,8 +313,6 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
host->clock = clock;
clk = SDHCI_CLOCK_INT_EN; clk = SDHCI_CLOCK_INT_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
...@@ -329,14 +334,14 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -329,14 +334,14 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
} }
/** /**
* sdhci_s3c_platform_bus_width - support 8bit buswidth * sdhci_s3c_set_bus_width - support 8bit buswidth
* @host: The SDHCI host being queried * @host: The SDHCI host being queried
* @width: MMC_BUS_WIDTH_ macro for the bus width being requested * @width: MMC_BUS_WIDTH_ macro for the bus width being requested
* *
* We have 8-bit width support but is not a v3 controller. * We have 8-bit width support but is not a v3 controller.
* So we add platform_bus_width() and support 8bit width. * So we add platform_bus_width() and support 8bit width.
*/ */
static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width) static void sdhci_s3c_set_bus_width(struct sdhci_host *host, int width)
{ {
u8 ctrl; u8 ctrl;
...@@ -358,93 +363,23 @@ static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width) ...@@ -358,93 +363,23 @@ static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width)
} }
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
return 0;
} }
static struct sdhci_ops sdhci_s3c_ops = { static struct sdhci_ops sdhci_s3c_ops = {
.get_max_clock = sdhci_s3c_get_max_clk, .get_max_clock = sdhci_s3c_get_max_clk,
.set_clock = sdhci_s3c_set_clock, .set_clock = sdhci_s3c_set_clock,
.get_min_clock = sdhci_s3c_get_min_clock, .get_min_clock = sdhci_s3c_get_min_clock,
.platform_bus_width = sdhci_s3c_platform_bus_width, .set_bus_width = sdhci_s3c_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
{
struct sdhci_host *host = platform_get_drvdata(dev);
#ifdef CONFIG_PM_RUNTIME
struct sdhci_s3c *sc = sdhci_priv(host);
#endif
unsigned long flags;
if (host) {
spin_lock_irqsave(&host->lock, flags);
if (state) {
dev_dbg(&dev->dev, "card inserted.\n");
#ifdef CONFIG_PM_RUNTIME
clk_prepare_enable(sc->clk_io);
#endif
host->flags &= ~SDHCI_DEVICE_DEAD;
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
} else {
dev_dbg(&dev->dev, "card removed.\n");
host->flags |= SDHCI_DEVICE_DEAD;
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
#ifdef CONFIG_PM_RUNTIME
clk_disable_unprepare(sc->clk_io);
#endif
}
tasklet_schedule(&host->card_tasklet);
spin_unlock_irqrestore(&host->lock, flags);
}
}
static irqreturn_t sdhci_s3c_gpio_card_detect_thread(int irq, void *dev_id)
{
struct sdhci_s3c *sc = dev_id;
int status = gpio_get_value(sc->ext_cd_gpio);
if (sc->pdata->ext_cd_gpio_invert)
status = !status;
sdhci_s3c_notify_change(sc->pdev, status);
return IRQ_HANDLED;
}
static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
{
struct s3c_sdhci_platdata *pdata = sc->pdata;
struct device *dev = &sc->pdev->dev;
if (devm_gpio_request(dev, pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) {
sc->ext_cd_gpio = pdata->ext_cd_gpio;
sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio);
if (sc->ext_cd_irq &&
request_threaded_irq(sc->ext_cd_irq, NULL,
sdhci_s3c_gpio_card_detect_thread,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT,
dev_name(dev), sc) == 0) {
int status = gpio_get_value(sc->ext_cd_gpio);
if (pdata->ext_cd_gpio_invert)
status = !status;
sdhci_s3c_notify_change(sc->pdev, status);
} else {
dev_warn(dev, "cannot request irq for card detect\n");
sc->ext_cd_irq = 0;
}
} else {
dev_err(dev, "cannot request gpio for card detect\n");
}
}
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int sdhci_s3c_parse_dt(struct device *dev, static int sdhci_s3c_parse_dt(struct device *dev,
struct sdhci_host *host, struct s3c_sdhci_platdata *pdata) struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
{ {
struct device_node *node = dev->of_node; struct device_node *node = dev->of_node;
struct sdhci_s3c *ourhost = to_s3c(host);
u32 max_width; u32 max_width;
int gpio;
/* if the bus-width property is not specified, assume width as 1 */ /* if the bus-width property is not specified, assume width as 1 */
if (of_property_read_u32(node, "bus-width", &max_width)) if (of_property_read_u32(node, "bus-width", &max_width))
...@@ -462,18 +397,8 @@ static int sdhci_s3c_parse_dt(struct device *dev, ...@@ -462,18 +397,8 @@ static int sdhci_s3c_parse_dt(struct device *dev,
return 0; return 0;
} }
gpio = of_get_named_gpio(node, "cd-gpios", 0); if (of_get_named_gpio(node, "cd-gpios", 0))
if (gpio_is_valid(gpio)) {
pdata->cd_type = S3C_SDHCI_CD_GPIO;
pdata->ext_cd_gpio = gpio;
ourhost->ext_cd_gpio = -1;
if (of_get_property(node, "cd-inverted", NULL))
pdata->ext_cd_gpio_invert = 1;
return 0; return 0;
} else if (gpio != -ENOENT) {
dev_err(dev, "invalid card detect gpio specified\n");
return -EINVAL;
}
/* assuming internal card detect that will be configured by pinctrl */ /* assuming internal card detect that will be configured by pinctrl */
pdata->cd_type = S3C_SDHCI_CD_INTERNAL; pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
...@@ -606,8 +531,10 @@ static int sdhci_s3c_probe(struct platform_device *pdev) ...@@ -606,8 +531,10 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
/* Setup quirks for the controller */ /* Setup quirks for the controller */
host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
if (drv_data) if (drv_data) {
host->quirks |= drv_data->sdhci_quirks; host->quirks |= drv_data->sdhci_quirks;
sc->no_divider = drv_data->no_divider;
}
#ifndef CONFIG_MMC_SDHCI_S3C_DMA #ifndef CONFIG_MMC_SDHCI_S3C_DMA
...@@ -656,7 +583,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev) ...@@ -656,7 +583,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
* If controller does not have internal clock divider, * If controller does not have internal clock divider,
* we can use overriding functions instead of default. * we can use overriding functions instead of default.
*/ */
if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) { if (sc->no_divider) {
sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
...@@ -674,6 +601,8 @@ static int sdhci_s3c_probe(struct platform_device *pdev) ...@@ -674,6 +601,8 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
pm_suspend_ignore_children(&pdev->dev, 1); pm_suspend_ignore_children(&pdev->dev, 1);
mmc_of_parse(host->mmc);
ret = sdhci_add_host(host); ret = sdhci_add_host(host);
if (ret) { if (ret) {
dev_err(dev, "sdhci_add_host() failed\n"); dev_err(dev, "sdhci_add_host() failed\n");
...@@ -682,15 +611,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev) ...@@ -682,15 +611,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
goto err_req_regs; goto err_req_regs;
} }
/* The following two methods of card detection might call
sdhci_s3c_notify_change() immediately, so they can be called
only after sdhci_add_host(). Setup errors are ignored. */
if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_init)
pdata->ext_cd_init(&sdhci_s3c_notify_change);
if (pdata->cd_type == S3C_SDHCI_CD_GPIO &&
gpio_is_valid(pdata->ext_cd_gpio))
sdhci_s3c_setup_card_detect_gpio(sc);
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
clk_disable_unprepare(sc->clk_io); clk_disable_unprepare(sc->clk_io);
...@@ -711,16 +631,12 @@ static int sdhci_s3c_remove(struct platform_device *pdev) ...@@ -711,16 +631,12 @@ static int sdhci_s3c_remove(struct platform_device *pdev)
{ {
struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_s3c *sc = sdhci_priv(host); struct sdhci_s3c *sc = sdhci_priv(host);
struct s3c_sdhci_platdata *pdata = sc->pdata;
if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);
if (sc->ext_cd_irq) if (sc->ext_cd_irq)
free_irq(sc->ext_cd_irq, sc); free_irq(sc->ext_cd_irq, sc);
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) if (sc->pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
clk_prepare_enable(sc->clk_io); clk_prepare_enable(sc->clk_io);
#endif #endif
sdhci_remove_host(host, 1); sdhci_remove_host(host, 1);
...@@ -797,7 +713,7 @@ static const struct dev_pm_ops sdhci_s3c_pmops = { ...@@ -797,7 +713,7 @@ static const struct dev_pm_ops sdhci_s3c_pmops = {
#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) #if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = { static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
.sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK, .no_divider = true,
}; };
#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data) #define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
#else #else
......
...@@ -28,7 +28,11 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) ...@@ -28,7 +28,11 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
} }
static struct sdhci_ops sdhci_sirf_ops = { static struct sdhci_ops sdhci_sirf_ops = {
.set_clock = sdhci_set_clock,
.get_max_clock = sdhci_sirf_get_max_clk, .get_max_clock = sdhci_sirf_get_max_clk,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
static struct sdhci_pltfm_data sdhci_sirf_pdata = { static struct sdhci_pltfm_data sdhci_sirf_pdata = {
......
...@@ -38,7 +38,10 @@ struct spear_sdhci { ...@@ -38,7 +38,10 @@ struct spear_sdhci {
/* sdhci ops */ /* sdhci ops */
static const struct sdhci_ops sdhci_pltfm_ops = { static const struct sdhci_ops sdhci_pltfm_ops = {
/* Nothing to do for now. */ .set_clock = sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -32,11 +32,17 @@ ...@@ -32,11 +32,17 @@
/* Tegra SDHOST controller vendor register definitions */ /* Tegra SDHOST controller vendor register definitions */
#define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120 #define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120
#define SDHCI_MISC_CTRL_ENABLE_SDR104 0x8
#define SDHCI_MISC_CTRL_ENABLE_SDR50 0x10
#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20
#define SDHCI_MISC_CTRL_ENABLE_DDR50 0x200
#define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) #define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0)
#define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) #define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1)
#define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2)
#define NVQUIRK_DISABLE_SDR50 BIT(3)
#define NVQUIRK_DISABLE_SDR104 BIT(4)
#define NVQUIRK_DISABLE_DDR50 BIT(5)
struct sdhci_tegra_soc_data { struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata; const struct sdhci_pltfm_data *pdata;
...@@ -48,19 +54,6 @@ struct sdhci_tegra { ...@@ -48,19 +54,6 @@ struct sdhci_tegra {
int power_gpio; int power_gpio;
}; };
static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
{
u32 val;
if (unlikely(reg == SDHCI_PRESENT_STATE)) {
/* Use wp_gpio here instead? */
val = readl(host->ioaddr + reg);
return val | SDHCI_WRITE_PROTECT;
}
return readl(host->ioaddr + reg);
}
static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
{ {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
...@@ -108,26 +101,33 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) ...@@ -108,26 +101,33 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
return mmc_gpio_get_ro(host->mmc); return mmc_gpio_get_ro(host->mmc);
} }
static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask) static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
{ {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = pltfm_host->priv; struct sdhci_tegra *tegra_host = pltfm_host->priv;
const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
u32 misc_ctrl;
sdhci_reset(host, mask);
if (!(mask & SDHCI_RESET_ALL)) if (!(mask & SDHCI_RESET_ALL))
return; return;
misc_ctrl = sdhci_readw(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
/* Erratum: Enable SDHCI spec v3.00 support */ /* Erratum: Enable SDHCI spec v3.00 support */
if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) { if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
u32 misc_ctrl;
misc_ctrl = sdhci_readb(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
sdhci_writeb(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL); /* Don't advertise UHS modes which aren't supported yet */
} if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR50)
misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR50;
if (soc_data->nvquirks & NVQUIRK_DISABLE_DDR50)
misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_DDR50;
if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR104)
misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR104;
sdhci_writew(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
} }
static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width) static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
{ {
u32 ctrl; u32 ctrl;
...@@ -144,23 +144,25 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width) ...@@ -144,23 +144,25 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
ctrl &= ~SDHCI_CTRL_4BITBUS; ctrl &= ~SDHCI_CTRL_4BITBUS;
} }
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
return 0;
} }
static const struct sdhci_ops tegra_sdhci_ops = { static const struct sdhci_ops tegra_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro, .get_ro = tegra_sdhci_get_ro,
.read_l = tegra_sdhci_readl,
.read_w = tegra_sdhci_readw, .read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel, .write_l = tegra_sdhci_writel,
.platform_bus_width = tegra_sdhci_buswidth, .set_clock = sdhci_set_clock,
.platform_reset_exit = tegra_sdhci_reset_exit, .set_bus_width = tegra_sdhci_set_bus_width,
.reset = tegra_sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
}; };
static const struct sdhci_pltfm_data sdhci_tegra20_pdata = { static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_SINGLE_POWER_WRITE | SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_NO_HISPD_BIT |
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.ops = &tegra_sdhci_ops, .ops = &tegra_sdhci_ops,
}; };
...@@ -175,13 +177,16 @@ static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { ...@@ -175,13 +177,16 @@ static const struct sdhci_pltfm_data sdhci_tegra30_pdata = {
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
SDHCI_QUIRK_SINGLE_POWER_WRITE | SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_NO_HISPD_BIT |
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.ops = &tegra_sdhci_ops, .ops = &tegra_sdhci_ops,
}; };
static struct sdhci_tegra_soc_data soc_data_tegra30 = { static struct sdhci_tegra_soc_data soc_data_tegra30 = {
.pdata = &sdhci_tegra30_pdata, .pdata = &sdhci_tegra30_pdata,
.nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300, .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 |
NVQUIRK_DISABLE_SDR50 |
NVQUIRK_DISABLE_SDR104,
}; };
static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
...@@ -189,12 +194,16 @@ static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { ...@@ -189,12 +194,16 @@ static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
SDHCI_QUIRK_SINGLE_POWER_WRITE | SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_NO_HISPD_BIT |
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.ops = &tegra_sdhci_ops, .ops = &tegra_sdhci_ops,
}; };
static struct sdhci_tegra_soc_data soc_data_tegra114 = { static struct sdhci_tegra_soc_data soc_data_tegra114 = {
.pdata = &sdhci_tegra114_pdata, .pdata = &sdhci_tegra114_pdata,
.nvquirks = NVQUIRK_DISABLE_SDR50 |
NVQUIRK_DISABLE_DDR50 |
NVQUIRK_DISABLE_SDR104,
}; };
static const struct of_device_id sdhci_tegra_dt_match[] = { static const struct of_device_id sdhci_tegra_dt_match[] = {
......
This diff is collapsed.
...@@ -281,18 +281,14 @@ struct sdhci_ops { ...@@ -281,18 +281,14 @@ struct sdhci_ops {
unsigned int (*get_max_clock)(struct sdhci_host *host); unsigned int (*get_max_clock)(struct sdhci_host *host);
unsigned int (*get_min_clock)(struct sdhci_host *host); unsigned int (*get_min_clock)(struct sdhci_host *host);
unsigned int (*get_timeout_clock)(struct sdhci_host *host); unsigned int (*get_timeout_clock)(struct sdhci_host *host);
int (*platform_bus_width)(struct sdhci_host *host, void (*set_bus_width)(struct sdhci_host *host, int width);
int width);
void (*platform_send_init_74_clocks)(struct sdhci_host *host, void (*platform_send_init_74_clocks)(struct sdhci_host *host,
u8 power_mode); u8 power_mode);
unsigned int (*get_ro)(struct sdhci_host *host); unsigned int (*get_ro)(struct sdhci_host *host);
void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); void (*reset)(struct sdhci_host *host, u8 mask);
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
void (*hw_reset)(struct sdhci_host *host); void (*hw_reset)(struct sdhci_host *host);
void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host);
void (*adma_workaround)(struct sdhci_host *host, u32 intmask); void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
void (*platform_init)(struct sdhci_host *host); void (*platform_init)(struct sdhci_host *host);
void (*card_event)(struct sdhci_host *host); void (*card_event)(struct sdhci_host *host);
...@@ -397,6 +393,16 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead); ...@@ -397,6 +393,16 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead);
extern void sdhci_send_command(struct sdhci_host *host, extern void sdhci_send_command(struct sdhci_host *host,
struct mmc_command *cmd); struct mmc_command *cmd);
static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
{
return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED);
}
void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
void sdhci_set_bus_width(struct sdhci_host *host, int width);
void sdhci_reset(struct sdhci_host *host, u8 mask);
void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern int sdhci_suspend_host(struct sdhci_host *host); extern int sdhci_suspend_host(struct sdhci_host *host);
extern int sdhci_resume_host(struct sdhci_host *host); extern int sdhci_resume_host(struct sdhci_host *host);
......
...@@ -803,12 +803,13 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, ...@@ -803,12 +803,13 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
break; break;
} }
switch (host->timing) { switch (host->timing) {
case MMC_TIMING_UHS_DDR50: case MMC_TIMING_MMC_DDR52:
/* /*
* MMC core will only set this timing, if the host * MMC core will only set this timing, if the host
* advertises the MMC_CAP_UHS_DDR50 capability. MMCIF * advertises the MMC_CAP_1_8V_DDR/MMC_CAP_1_2V_DDR
* implementations with this capability, e.g. sh73a0, * capability. MMCIF implementations with this
* will have to set it in their platform data. * capability, e.g. sh73a0, will have to set it
* in their platform data.
*/ */
tmp |= CMD_SET_DARS; tmp |= CMD_SET_DARS;
break; break;
......
This diff is collapsed.
...@@ -840,7 +840,7 @@ static int wmt_mci_probe(struct platform_device *pdev) ...@@ -840,7 +840,7 @@ static int wmt_mci_probe(struct platform_device *pdev)
priv->dma_desc_buffer = dma_alloc_coherent(&pdev->dev, priv->dma_desc_buffer = dma_alloc_coherent(&pdev->dev,
mmc->max_blk_count * 16, mmc->max_blk_count * 16,
&priv->dma_desc_device_addr, &priv->dma_desc_device_addr,
208); GFP_KERNEL);
if (!priv->dma_desc_buffer) { if (!priv->dma_desc_buffer) {
dev_err(&pdev->dev, "DMA alloc fail\n"); dev_err(&pdev->dev, "DMA alloc fail\n");
ret = -EPERM; ret = -EPERM;
......
...@@ -285,7 +285,6 @@ static void rsi_reset_card(struct sdio_func *pfunction) ...@@ -285,7 +285,6 @@ static void rsi_reset_card(struct sdio_func *pfunction)
if (err) { if (err) {
rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n", rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n",
__func__, err); __func__, err);
card->state &= ~MMC_STATE_HIGHSPEED;
} else { } else {
err = rsi_cmd52writebyte(card, err = rsi_cmd52writebyte(card,
SDIO_CCCR_SPEED, SDIO_CCCR_SPEED,
...@@ -296,14 +295,13 @@ static void rsi_reset_card(struct sdio_func *pfunction) ...@@ -296,14 +295,13 @@ static void rsi_reset_card(struct sdio_func *pfunction)
__func__, err); __func__, err);
return; return;
} }
mmc_card_set_highspeed(card);
host->ios.timing = MMC_TIMING_SD_HS; host->ios.timing = MMC_TIMING_SD_HS;
host->ops->set_ios(host, &host->ios); host->ops->set_ios(host, &host->ios);
} }
} }
/* Set clock */ /* Set clock */
if (mmc_card_highspeed(card)) if (mmc_card_hs(card))
clock = 50000000; clock = 50000000;
else else
clock = card->cis.max_dtr; clock = card->cis.max_dtr;
......
...@@ -63,12 +63,12 @@ struct mmc_ext_csd { ...@@ -63,12 +63,12 @@ struct mmc_ext_csd {
unsigned int power_off_longtime; /* Units: ms */ unsigned int power_off_longtime; /* Units: ms */
u8 power_off_notification; /* state */ u8 power_off_notification; /* state */
unsigned int hs_max_dtr; unsigned int hs_max_dtr;
unsigned int hs200_max_dtr;
#define MMC_HIGH_26_MAX_DTR 26000000 #define MMC_HIGH_26_MAX_DTR 26000000
#define MMC_HIGH_52_MAX_DTR 52000000 #define MMC_HIGH_52_MAX_DTR 52000000
#define MMC_HIGH_DDR_MAX_DTR 52000000 #define MMC_HIGH_DDR_MAX_DTR 52000000
#define MMC_HS200_MAX_DTR 200000000 #define MMC_HS200_MAX_DTR 200000000
unsigned int sectors; unsigned int sectors;
unsigned int card_type;
unsigned int hc_erase_size; /* In sectors */ unsigned int hc_erase_size; /* In sectors */
unsigned int hc_erase_timeout; /* In milliseconds */ unsigned int hc_erase_timeout; /* In milliseconds */
unsigned int sec_trim_mult; /* Secure trim multiplier */ unsigned int sec_trim_mult; /* Secure trim multiplier */
...@@ -110,6 +110,7 @@ struct mmc_ext_csd { ...@@ -110,6 +110,7 @@ struct mmc_ext_csd {
u8 raw_pwr_cl_200_360; /* 237 */ u8 raw_pwr_cl_200_360; /* 237 */
u8 raw_pwr_cl_ddr_52_195; /* 238 */ u8 raw_pwr_cl_ddr_52_195; /* 238 */
u8 raw_pwr_cl_ddr_52_360; /* 239 */ u8 raw_pwr_cl_ddr_52_360; /* 239 */
u8 raw_pwr_cl_ddr_200_360; /* 253 */
u8 raw_bkops_status; /* 246 */ u8 raw_bkops_status; /* 246 */
u8 raw_sectors[4]; /* 212 - 4 bytes */ u8 raw_sectors[4]; /* 212 - 4 bytes */
...@@ -194,6 +195,7 @@ struct sdio_cis { ...@@ -194,6 +195,7 @@ struct sdio_cis {
}; };
struct mmc_host; struct mmc_host;
struct mmc_ios;
struct sdio_func; struct sdio_func;
struct sdio_func_tuple; struct sdio_func_tuple;
...@@ -250,15 +252,11 @@ struct mmc_card { ...@@ -250,15 +252,11 @@ struct mmc_card {
unsigned int state; /* (our) card state */ unsigned int state; /* (our) card state */
#define MMC_STATE_PRESENT (1<<0) /* present in sysfs */ #define MMC_STATE_PRESENT (1<<0) /* present in sysfs */
#define MMC_STATE_READONLY (1<<1) /* card is read-only */ #define MMC_STATE_READONLY (1<<1) /* card is read-only */
#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ #define MMC_STATE_BLOCKADDR (1<<2) /* card uses block-addressing */
#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ #define MMC_CARD_SDXC (1<<3) /* card is SDXC */
#define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */ #define MMC_CARD_REMOVED (1<<4) /* card has been removed */
#define MMC_STATE_ULTRAHIGHSPEED (1<<5) /* card is in ultra high speed mode */ #define MMC_STATE_DOING_BKOPS (1<<5) /* card is doing BKOPS */
#define MMC_CARD_SDXC (1<<6) /* card is SDXC */ #define MMC_STATE_SUSPENDED (1<<6) /* card is suspended */
#define MMC_CARD_REMOVED (1<<7) /* card has been removed */
#define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */
#define MMC_STATE_DOING_BKOPS (1<<10) /* card is doing BKOPS */
#define MMC_STATE_SUSPENDED (1<<11) /* card is suspended */
unsigned int quirks; /* card quirks */ unsigned int quirks; /* card quirks */
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
...@@ -301,6 +299,7 @@ struct mmc_card { ...@@ -301,6 +299,7 @@ struct mmc_card {
struct sdio_func_tuple *tuples; /* unknown common tuples */ struct sdio_func_tuple *tuples; /* unknown common tuples */
unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */ unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */
unsigned int mmc_avail_type; /* supported device type by both host and card */
struct dentry *debugfs_root; struct dentry *debugfs_root;
struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */ struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
...@@ -353,7 +352,7 @@ struct mmc_fixup { ...@@ -353,7 +352,7 @@ struct mmc_fixup {
#define CID_OEMID_ANY ((unsigned short) -1) #define CID_OEMID_ANY ((unsigned short) -1)
#define CID_NAME_ANY (NULL) #define CID_NAME_ANY (NULL)
#define END_FIXUP { 0 } #define END_FIXUP { NULL }
#define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \ #define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \
_cis_vendor, _cis_device, \ _cis_vendor, _cis_device, \
...@@ -418,11 +417,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) ...@@ -418,11 +417,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
#define mmc_card_hs200(c) ((c)->state & MMC_STATE_HIGHSPEED_200)
#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
#define mmc_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
#define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
#define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) #define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS)
...@@ -430,11 +425,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) ...@@ -430,11 +425,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
#define mmc_card_set_hs200(c) ((c)->state |= MMC_STATE_HIGHSPEED_200)
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
#define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
#define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) #define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS)
......
...@@ -248,20 +248,6 @@ struct dw_mci_board { ...@@ -248,20 +248,6 @@ struct dw_mci_board {
/* delay in mS before detecting cards after interrupt */ /* delay in mS before detecting cards after interrupt */
u32 detect_delay_ms; u32 detect_delay_ms;
int (*init)(u32 slot_id, irq_handler_t , void *);
int (*get_ro)(u32 slot_id);
int (*get_cd)(u32 slot_id);
int (*get_ocr)(u32 slot_id);
int (*get_bus_wd)(u32 slot_id);
/*
* Enable power to selected slot and set voltage to desired level.
* Voltage levels are specified using MMC_VDD_xxx defines defined
* in linux/mmc/host.h file.
*/
void (*setpower)(u32 slot_id, u32 volt);
void (*exit)(u32 slot_id);
void (*select_slot)(u32 slot_id);
struct dw_mci_dma_ops *dma_ops; struct dw_mci_dma_ops *dma_ops;
struct dma_pdata *data; struct dma_pdata *data;
struct block_settings *blk_settings; struct block_settings *blk_settings;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/fault-inject.h> #include <linux/fault-inject.h>
#include <linux/mmc/core.h> #include <linux/mmc/core.h>
#include <linux/mmc/card.h>
#include <linux/mmc/pm.h> #include <linux/mmc/pm.h>
struct mmc_ios { struct mmc_ios {
...@@ -58,13 +59,9 @@ struct mmc_ios { ...@@ -58,13 +59,9 @@ struct mmc_ios {
#define MMC_TIMING_UHS_SDR50 5 #define MMC_TIMING_UHS_SDR50 5
#define MMC_TIMING_UHS_SDR104 6 #define MMC_TIMING_UHS_SDR104 6
#define MMC_TIMING_UHS_DDR50 7 #define MMC_TIMING_UHS_DDR50 7
#define MMC_TIMING_MMC_HS200 8 #define MMC_TIMING_MMC_DDR52 8
#define MMC_TIMING_MMC_HS200 9
#define MMC_SDR_MODE 0 #define MMC_TIMING_MMC_HS400 10
#define MMC_1_2V_DDR_MODE 1
#define MMC_1_8V_DDR_MODE 2
#define MMC_1_2V_SDR_MODE 3
#define MMC_1_8V_SDR_MODE 4
unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */
...@@ -136,6 +133,9 @@ struct mmc_host_ops { ...@@ -136,6 +133,9 @@ struct mmc_host_ops {
/* The tuning command opcode value is different for SD and eMMC cards */ /* The tuning command opcode value is different for SD and eMMC cards */
int (*execute_tuning)(struct mmc_host *host, u32 opcode); int (*execute_tuning)(struct mmc_host *host, u32 opcode);
/* Prepare HS400 target operating frequency depending host driver */
int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv); int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
void (*hw_reset)(struct mmc_host *host); void (*hw_reset)(struct mmc_host *host);
void (*card_event)(struct mmc_host *host); void (*card_event)(struct mmc_host *host);
...@@ -278,6 +278,11 @@ struct mmc_host { ...@@ -278,6 +278,11 @@ struct mmc_host {
#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
MMC_CAP2_PACKED_WR) MMC_CAP2_PACKED_WR)
#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */
#define MMC_CAP2_HS400_1_8V (1 << 15) /* Can support HS400 1.8V */
#define MMC_CAP2_HS400_1_2V (1 << 16) /* Can support HS400 1.2V */
#define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | \
MMC_CAP2_HS400_1_2V)
#define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
mmc_pm_flag_t pm_caps; /* supported pm features */ mmc_pm_flag_t pm_caps; /* supported pm features */
...@@ -318,6 +323,8 @@ struct mmc_host { ...@@ -318,6 +323,8 @@ struct mmc_host {
int rescan_disable; /* disable card detection */ int rescan_disable; /* disable card detection */
int rescan_entered; /* used with nonremovable devices */ int rescan_entered; /* used with nonremovable devices */
bool trigger_card_event; /* card_event necessary */
struct mmc_card *card; /* device attached to this host */ struct mmc_card *card; /* device attached to this host */
wait_queue_head_t wq; wait_queue_head_t wq;
...@@ -391,12 +398,13 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host) ...@@ -391,12 +398,13 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
wake_up_process(host->sdio_irq_thread); wake_up_process(host->sdio_irq_thread);
} }
void sdio_run_irqs(struct mmc_host *host);
#ifdef CONFIG_REGULATOR #ifdef CONFIG_REGULATOR
int mmc_regulator_get_ocrmask(struct regulator *supply); int mmc_regulator_get_ocrmask(struct regulator *supply);
int mmc_regulator_set_ocr(struct mmc_host *mmc, int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply, struct regulator *supply,
unsigned short vdd_bit); unsigned short vdd_bit);
int mmc_regulator_get_supply(struct mmc_host *mmc);
#else #else
static inline int mmc_regulator_get_ocrmask(struct regulator *supply) static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
{ {
...@@ -409,13 +417,10 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc, ...@@ -409,13 +417,10 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
{ {
return 0; return 0;
} }
static inline int mmc_regulator_get_supply(struct mmc_host *mmc)
{
return 0;
}
#endif #endif
int mmc_regulator_get_supply(struct mmc_host *mmc);
int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
static inline int mmc_card_is_removable(struct mmc_host *host) static inline int mmc_card_is_removable(struct mmc_host *host)
...@@ -475,4 +480,32 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) ...@@ -475,4 +480,32 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
return host->ios.clock; return host->ios.clock;
} }
#endif #endif
static inline int mmc_card_hs(struct mmc_card *card)
{
return card->host->ios.timing == MMC_TIMING_SD_HS ||
card->host->ios.timing == MMC_TIMING_MMC_HS;
}
static inline int mmc_card_uhs(struct mmc_card *card)
{
return card->host->ios.timing >= MMC_TIMING_UHS_SDR12 &&
card->host->ios.timing <= MMC_TIMING_UHS_DDR50;
}
static inline bool mmc_card_hs200(struct mmc_card *card)
{
return card->host->ios.timing == MMC_TIMING_MMC_HS200;
}
static inline bool mmc_card_ddr52(struct mmc_card *card)
{
return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
}
static inline bool mmc_card_hs400(struct mmc_card *card)
{
return card->host->ios.timing == MMC_TIMING_MMC_HS400;
}
#endif /* LINUX_MMC_HOST_H */ #endif /* LINUX_MMC_HOST_H */
...@@ -325,6 +325,7 @@ struct _mmc_csd { ...@@ -325,6 +325,7 @@ struct _mmc_csd {
#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ #define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ #define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ #define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ #define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ #define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
...@@ -354,18 +355,25 @@ struct _mmc_csd { ...@@ -354,18 +355,25 @@ struct _mmc_csd {
#define EXT_CSD_CMD_SET_SECURE (1<<1) #define EXT_CSD_CMD_SET_SECURE (1<<1)
#define EXT_CSD_CMD_SET_CPSECURE (1<<2) #define EXT_CSD_CMD_SET_CPSECURE (1<<2)
#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ #define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */
#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ #define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */
#define EXT_CSD_CARD_TYPE_MASK 0x3F /* Mask out reserved bits */ #define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \
EXT_CSD_CARD_TYPE_HS_52)
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */ #define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
/* DDR mode @1.8V or 3V I/O */ /* DDR mode @1.8V or 3V I/O */
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */ #define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
/* DDR mode @1.2V I/O */ /* DDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ #define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
| EXT_CSD_CARD_TYPE_DDR_1_2V) | EXT_CSD_CARD_TYPE_DDR_1_2V)
#define EXT_CSD_CARD_TYPE_SDR_1_8V (1<<4) /* Card can run at 200MHz */ #define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */
#define EXT_CSD_CARD_TYPE_SDR_1_2V (1<<5) /* Card can run at 200MHz */ #define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */
/* SDR mode @1.2V I/O */ /* SDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \
EXT_CSD_CARD_TYPE_HS200_1_2V)
#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */
#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \
EXT_CSD_CARD_TYPE_HS400_1_2V)
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
...@@ -373,6 +381,11 @@ struct _mmc_csd { ...@@ -373,6 +381,11 @@ struct _mmc_csd {
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ #define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ #define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */
#define EXT_CSD_TIMING_HS 1 /* High speed */
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
#define EXT_CSD_SEC_ER_EN BIT(0) #define EXT_CSD_SEC_ER_EN BIT(0)
#define EXT_CSD_SEC_BD_BLK_EN BIT(2) #define EXT_CSD_SEC_BD_BLK_EN BIT(2)
#define EXT_CSD_SEC_GB_CL_EN BIT(4) #define EXT_CSD_SEC_GB_CL_EN BIT(4)
......
...@@ -57,12 +57,8 @@ struct sdhci_host { ...@@ -57,12 +57,8 @@ struct sdhci_host {
#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15) #define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15)
/* Controller reports inverted write-protect state */ /* Controller reports inverted write-protect state */
#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16)
/* Controller has nonstandard clock management */
#define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<17)
/* Controller does not like fast PIO transfers */ /* Controller does not like fast PIO transfers */
#define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18)
/* Controller losing signal/interrupt enable states after reset */
#define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19)
/* Controller has to be forced to use block size of 2048 bytes */ /* Controller has to be forced to use block size of 2048 bytes */
#define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20)
/* Controller cannot do multi-block transfers */ /* Controller cannot do multi-block transfers */
...@@ -147,6 +143,7 @@ struct sdhci_host { ...@@ -147,6 +143,7 @@ struct sdhci_host {
bool runtime_suspended; /* Host is runtime suspended */ bool runtime_suspended; /* Host is runtime suspended */
bool bus_on; /* Bus power prevents runtime suspend */ bool bus_on; /* Bus power prevents runtime suspend */
bool preset_enabled; /* Preset is enabled */
struct mmc_request *mrq; /* Current request */ struct mmc_request *mrq; /* Current request */
struct mmc_command *cmd; /* Current command */ struct mmc_command *cmd; /* Current command */
...@@ -164,8 +161,7 @@ struct sdhci_host { ...@@ -164,8 +161,7 @@ struct sdhci_host {
dma_addr_t adma_addr; /* Mapped ADMA descr. table */ dma_addr_t adma_addr; /* Mapped ADMA descr. table */
dma_addr_t align_addr; /* Mapped bounce buffer */ dma_addr_t align_addr; /* Mapped bounce buffer */
struct tasklet_struct card_tasklet; /* Tasklet structures */ struct tasklet_struct finish_tasklet; /* Tasklet structures */
struct tasklet_struct finish_tasklet;
struct timer_list timer; /* Timer for timeouts */ struct timer_list timer; /* Timer for timeouts */
...@@ -177,6 +173,13 @@ struct sdhci_host { ...@@ -177,6 +173,13 @@ struct sdhci_host {
unsigned int ocr_avail_mmc; unsigned int ocr_avail_mmc;
u32 ocr_mask; /* available voltages */ u32 ocr_mask; /* available voltages */
unsigned timing; /* Current timing */
u32 thread_isr;
/* cached registers */
u32 ier;
wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */ unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */
......
/*
* OMAP DMA Engine support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_OMAP_DMA_H #ifndef __LINUX_OMAP_DMA_H
#define __LINUX_OMAP_DMA_H #define __LINUX_OMAP_DMA_H
#include <linux/omap-dmaengine.h>
struct dma_chan;
#if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE))
bool omap_dma_filter_fn(struct dma_chan *, void *);
#else
static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d)
{
return false;
}
#endif
/* /*
* Legacy OMAP DMA handling defines and functions * Legacy OMAP DMA handling defines and functions
......
/*
* OMAP DMA Engine support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_OMAP_DMAENGINE_H
#define __LINUX_OMAP_DMAENGINE_H
struct dma_chan;
#if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE))
bool omap_dma_filter_fn(struct dma_chan *, void *);
#else
static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d)
{
return false;
}
#endif
#endif /* __LINUX_OMAP_DMAENGINE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment