MMC core:

- mmc: core: Fixup max_discard/trim calculations
  - mmc: core: Announce SD specs greater than 4.0
  - mmc: core: Add discard support for SD cards
  - mmc: core: Don't do retries for CMD6 (SWITCH command)
  - mmc: core: Various cleanups and re-structuring
 
 MMC host:
  - cqhci: Add maintainers for eMMC CQHCI driver
  - sdhci: Consolidate WP GPIO code
  - sdhci: Add ADMA3 DMA support for V4 enabled host
  - sdhci-pci-o2micro: Fixup card detect support
  - sdhci-tegra: Add support for CMDQ
  - sdhci-tegra: Support SDMMC pads auto-calibration
  - sdhci-esdhc-imx: Add DCMD support and CMDQ support
  - sdhci-esdhc-imx: Add support for i.MX6ULL variant
  - sdhci-esdhc-imx: Fixup HS400 timing issue
  - sdhci-esdhc-imx: Add HS400_ES support for i.MX8QXP
  - renesas_sdhi: Avoid CRC errors by adjusting settings to speed mode
  - renesas_sdhi: Fixup card initialization for high speed mode
  - omap: Fixup timeout settings
  - atmel-mci: Enable 8 bits bus-width support
  - jz4740: Convert some legacy code to use modern APIs
  - mmci: Send a CMD12 to clear DPSM at errors for STM32 sdmmc
 -----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAlx9H6IXHHVsZi5oYW5z
 c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjCmuXhAAvsaR7GvKGwuUNLN1aR+wHKA4
 toS8zG0bEF/mS+xDU/OYX6f96FBQ0rJURCr/LoskVVesw9Z7zU9sn1XQ3EogkM22
 EwhDJJ4yHkCMsF1GuCyx/ayeiV6ahMflJIMRJkujSD7S3XZdaAhWoHc0M/VvPM68
 2WLjFR185fZAshkvtfN1lLDDGOfsQL8Net/U560nNCVFU0QSPPQcXejfn2ikhtja
 P32XsUEVhll+zRAtbuU0IP2rJ0xx0Br5rKSE2fpfbtN51B8KN27BgQcj78IbZzLF
 MWqqDADLCXZMLMnN+U6RUKF65Bog6mxLhcuO1x+/GcMcIB5ypIF6DZP44mE+IVyp
 4M99Mm/07KxARfsJCwUTCCuVbI1C00T/fTmHiDHn7NhXXVmMq2s823Fvxxo3C59l
 5l23EXV/xEPw2doZP6fQp5Wi/uXG0guvWaXAeX7FMWOgatneRRfynOOnigk4zdfX
 LqQ17G7CNmNQR3NtP4pNQ0PQPVbQR3D9+Pn/Cecpg1tz5gvWGzJ5DUm3DxMhr66r
 CrR32+1PtmsM9SuwiMSADcXDV8H2Bg4OV/VFL6JKP82+2YkfeXYG/9W4FlemnM5L
 4zrT+cNuEHhDjQZDg15U7qcMVbNzFN9mUSSc6PLIZc1O5bIMl2NzlXXOHIsPrjb9
 TN8TINem5b65j43annE=
 =umka
 -----END PGP SIGNATURE-----

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

Pull MMC updates from Ulf Hansson:
 "MMC core:
   - Fixup max_discard/trim calculations
   - Announce SD specs greater than 4.0
   - Add discard support for SD cards
   - Don't do retries for CMD6 (SWITCH command)
   - Various cleanups and re-structuring

  MMC host:
   - cqhci:
      * Add maintainers for eMMC CQHCI driver
   - sdhci:
      * Consolidate WP GPIO code
      * Add ADMA3 DMA support for V4 enabled host
      * Fixup card detect support in pci-o2micro driver
      * Add support for CMDQ and SDMMC pads auto-calibration in tegra
        driver
      * Add DCMD support and CMDQ support, support for i.MX6ULL variant,
        fixup HS400 timing issue and add HS400_ES support for i.MX8QXP
        to esdhc-imx driver
      * Avoid CRC errors by adjusting settings to speed mode and fixup
        card initialization for high speed mode in renesas_sdhi
      * Fixup timeout settings for omap
      * Enable 8 bits bus-width support in atmel-mci
      * Convert some legacy code in jz4740 driver to use modern APIs
      * Send a CMD12 to clear DPSM at errors for STM32 sdmmc mmci
        driver"

* tag 'mmc-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (69 commits)
  mmc:fix a bug when max_discard is 0
  mmc: core: Add a debug print when the card may have been replaced
  mmc: core: Add sd discard timeout
  mmc: core: Add discard support to sd
  mmc: sdhci-esdhc-imx: clear the HALT bit when enable CQE
  mmc: core: do not retry CMD6 in __mmc_switch()
  mmc: core: Convert mmc_align_data_size() into an SDIO specific function
  mmc: core: Move mmc_of_parse_voltage() to host.c
  mmc: core: Convert mmc_regulator_get_ocrmask() to static
  mmc: core: Move regulator helpers to separate file
  mmc: of_mmc_spi: Convert to mmc_of_parse_voltage()
  mmc: core: Drop retries as in-parameter to mmc_wait_for_app_cmd()
  mmc: core: Convert mmc_wait_for_app_cmd() to static
  mmc: renesas_sdhi: Change HW adjustment register according to speed mode
  mmc: mmci: Send a CMD12 to clear the DPSM at errors
  mmc: sdhci-xenon: Fixup already marked switch fall-through
  mmc: sdhci-tegra: drop ->get_ro() implementation
  mmc: sdhci-omap: drop ->get_ro() implementation
  mmc: sdhci: use WP GPIO in sdhci_check_ro()
  mmc: wmt-sdmmc: Drop unused include
  ...
This commit is contained in:
Linus Torvalds 2019-03-04 19:07:02 -08:00
commit 42eaf1851e
59 changed files with 1198 additions and 686 deletions

View File

@ -15,6 +15,7 @@ Required properties:
"fsl,imx6q-usdhc"
"fsl,imx6sl-usdhc"
"fsl,imx6sx-usdhc"
"fsl,imx6ull-usdhc"
"fsl,imx7d-usdhc"
"fsl,imx8qxp-usdhc"

View File

@ -62,6 +62,8 @@ Optional properties:
be referred to mmc-pwrseq-simple.txt. But now it's reused as a tunable delay
waiting for I/O signalling and card power supply to be stable, regardless of
whether pwrseq-simple is used. Default to 10ms if no available.
- supports-cqe : The presence of this property indicates that the corresponding
MMC host controller supports HW command queue feature.
*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"

View File

@ -39,12 +39,16 @@ sdhci@c8000200 {
bus-width = <8>;
};
Optional properties for Tegra210 and Tegra186:
Optional properties for Tegra210, Tegra186 and Tegra194:
- pinctrl-names, pinctrl-0, pinctrl-1 : Specify pad voltage
configurations. Valid pinctrl-names are "sdmmc-3v3" and "sdmmc-1v8"
for controllers supporting multiple voltage levels. The order of names
should correspond to the pin configuration states in pinctrl-0 and
pinctrl-1.
- pinctrl-names : "sdmmc-3v3-drv" and "sdmmc-1v8-drv" are applicable for
Tegra210 where pad config registers are in the pinmux register domain
for pull-up-strength and pull-down-strength values configuration when
using pads at 3V3 and 1V8 levels.
- nvidia,only-1-8-v : The presence of this property indicates that the
controller operates at a 1.8 V fixed I/O voltage.
- nvidia,pad-autocal-pull-up-offset-3v3,

View File

@ -24,31 +24,3 @@ Examples:
dmas = <&sdma 61 &sdma 62>;
dma-names = "tx", "rx";
};
* TI MMC host controller for OMAP1 and 2420
The MMC Host Controller on TI OMAP1 and 2420 family provides
an interface for MMC, SD, and SDIO types of memory cards.
This file documents differences between the core properties described
by mmc.txt and the properties used by the omap mmc driver.
Note that this driver will not work with omap2430 or later omaps,
please see the omap hsmmc driver for the current omaps.
Required properties:
- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
instance starting 1
Examples:
msdi1: mmc@4809c000 {
compatible = "ti,omap2420-mmc";
ti,hwmods = "msdi1";
reg = <0x4809c000 0x80>;
interrupts = <83>;
dmas = <&sdma 61 &sdma 62>;
dma-names = "tx", "rx";
};

View File

@ -13616,11 +13616,18 @@ F: drivers/mmc/host/sdhci-brcmstb*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
M: Adrian Hunter <adrian.hunter@intel.com>
L: linux-mmc@vger.kernel.org
T: git git://git.infradead.org/users/ahunter/linux-sdhci.git
S: Maintained
F: drivers/mmc/host/sdhci*
F: include/linux/mmc/sdhci*
EMMC CMDQ HOST CONTROLLER INTERFACE (CQHCI) DRIVER
M: Adrian Hunter <adrian.hunter@intel.com>
M: Ritesh Harjani <riteshh@codeaurora.org>
M: Asutosh Das <asutoshd@codeaurora.org>
L: linux-mmc@vger.kernel.org
S: Maintained
F: drivers/mmc/host/cqhci*
SYNOPSYS SDHCI COMPLIANT DWC MSHC DRIVER
M: Prabu Thangamuthu <prabu.t@synopsys.com>
M: Manjunath M B <manjumb@synopsys.com>

View File

@ -8,7 +8,7 @@ mmc_core-y := core.o bus.o host.o \
mmc.o mmc_ops.o sd.o sd_ops.o \
sdio.o sdio_ops.o sdio_bus.o \
sdio_cis.o sdio_io.o sdio_irq.o \
slot-gpio.o
slot-gpio.o regulator.o
mmc_core-$(CONFIG_OF) += pwrseq.o
obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o
obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o

View File

@ -1124,7 +1124,7 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
{
struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg;
unsigned int from, nr;
int err = 0, type = MMC_BLK_DISCARD;
blk_status_t status = BLK_STS_OK;
@ -1136,24 +1136,18 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
if (mmc_can_discard(card))
arg = MMC_DISCARD_ARG;
else if (mmc_can_trim(card))
arg = MMC_TRIM_ARG;
else
arg = MMC_ERASE_ARG;
do {
err = 0;
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
INAND_CMD38_ARG_EXT_CSD,
arg == MMC_TRIM_ARG ?
card->erase_arg == MMC_TRIM_ARG ?
INAND_CMD38_ARG_TRIM :
INAND_CMD38_ARG_ERASE,
0);
}
if (!err)
err = mmc_erase(card, from, nr, arg);
err = mmc_erase(card, from, nr, card->erase_arg);
} while (err == -EIO && !mmc_blk_reset(md, card->host, type));
if (err)
status = BLK_STS_IOERR;
@ -2768,8 +2762,8 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
return ret;
}
DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
NULL, "%08llx\n");
DEFINE_DEBUGFS_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
NULL, "%08llx\n");
/* That is two digits * 512 + 1 for newline */
#define EXT_CSD_STR_LEN 1025
@ -2857,8 +2851,9 @@ static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
if (mmc_card_mmc(card) || mmc_card_sd(card)) {
md->status_dentry =
debugfs_create_file("status", S_IRUSR, root, card,
&mmc_dbg_card_status_fops);
debugfs_create_file_unsafe("status", 0400, root,
card,
&mmc_dbg_card_status_fops);
if (!md->status_dentry)
return -EIO;
}

View File

@ -21,7 +21,6 @@
#include <linux/leds.h>
#include <linux/scatterlist.h>
#include <linux/log2.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeup.h>
#include <linux/suspend.h>
@ -52,6 +51,7 @@
/* The max erase timeout, used when host->max_busy_timeout isn't specified */
#define MMC_ERASE_TIMEOUT_MS (60 * 1000) /* 60 s */
#define SD_DISCARD_TIMEOUT_MS (250)
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
@ -758,33 +758,6 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_set_data_timeout);
/**
* mmc_align_data_size - pads a transfer size to a more optimal value
* @card: the MMC card associated with the data transfer
* @sz: original transfer size
*
* Pads the original data size with a number of extra bytes in
* order to avoid controller bugs and/or performance hits
* (e.g. some controllers revert to PIO for certain sizes).
*
* Returns the improved size, which might be unmodified.
*
* Note that this function is only relevant when issuing a
* single scatter gather entry.
*/
unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
{
/*
* FIXME: We don't have a system for the controller to tell
* the core about its problems yet, so for now we just 32-bit
* align the size.
*/
sz = ((sz + 3) / 4) * 4;
return sz;
}
EXPORT_SYMBOL(mmc_align_data_size);
/*
* Allow claiming an already claimed host if the context is the same or there is
* no context but the task is the same.
@ -1112,55 +1085,6 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
return mask;
}
EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
#ifdef CONFIG_OF
/**
* mmc_of_parse_voltage - return mask of supported voltages
* @np: The device node need to be parsed.
* @mask: mask of voltages available for MMC/SD/SDIO
*
* Parse the "voltage-ranges" DT property, returning zero if it is not
* found, negative errno if the voltage-range specification is invalid,
* or one if the voltage-range is specified and successfully parsed.
*/
int mmc_of_parse_voltage(struct device_node *np, u32 *mask)
{
const u32 *voltage_ranges;
int num_ranges, i;
voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
if (!voltage_ranges) {
pr_debug("%pOF: voltage-ranges unspecified\n", np);
return 0;
}
if (!num_ranges) {
pr_err("%pOF: voltage-ranges empty\n", np);
return -EINVAL;
}
for (i = 0; i < num_ranges; i++) {
const int j = i * 2;
u32 ocr_mask;
ocr_mask = mmc_vddrange_to_ocrmask(
be32_to_cpu(voltage_ranges[j]),
be32_to_cpu(voltage_ranges[j + 1]));
if (!ocr_mask) {
pr_err("%pOF: voltage-range #%d is invalid\n",
np, i);
return -EINVAL;
}
*mask |= ocr_mask;
}
return 1;
}
EXPORT_SYMBOL(mmc_of_parse_voltage);
#endif /* CONFIG_OF */
static int mmc_of_get_func_num(struct device_node *node)
{
@ -1190,246 +1114,6 @@ struct device_node *mmc_of_find_child_device(struct mmc_host *host,
return NULL;
}
#ifdef CONFIG_REGULATOR
/**
* mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage
* @vdd_bit: OCR bit number
* @min_uV: minimum voltage value (mV)
* @max_uV: maximum voltage value (mV)
*
* This function returns the voltage range according to the provided OCR
* bit number. If conversion is not possible a negative errno value returned.
*/
static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV)
{
int tmp;
if (!vdd_bit)
return -EINVAL;
/*
* REVISIT mmc_vddrange_to_ocrmask() may have set some
* bits this regulator doesn't quite support ... don't
* be too picky, most cards and regulators are OK with
* a 0.1V range goof (it's a small error percentage).
*/
tmp = vdd_bit - ilog2(MMC_VDD_165_195);
if (tmp == 0) {
*min_uV = 1650 * 1000;
*max_uV = 1950 * 1000;
} else {
*min_uV = 1900 * 1000 + tmp * 100 * 1000;
*max_uV = *min_uV + 100 * 1000;
}
return 0;
}
/**
* mmc_regulator_get_ocrmask - return mask of supported voltages
* @supply: regulator to use
*
* This returns either a negative errno, or a mask of voltages that
* can be provided to MMC/SD/SDIO devices using the specified voltage
* regulator. This would normally be called before registering the
* MMC host adapter.
*/
int mmc_regulator_get_ocrmask(struct regulator *supply)
{
int result = 0;
int count;
int i;
int vdd_uV;
int vdd_mV;
count = regulator_count_voltages(supply);
if (count < 0)
return count;
for (i = 0; i < count; i++) {
vdd_uV = regulator_list_voltage(supply, i);
if (vdd_uV <= 0)
continue;
vdd_mV = vdd_uV / 1000;
result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
}
if (!result) {
vdd_uV = regulator_get_voltage(supply);
if (vdd_uV <= 0)
return vdd_uV;
vdd_mV = vdd_uV / 1000;
result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
}
return result;
}
EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask);
/**
* mmc_regulator_set_ocr - set regulator to match host->ios voltage
* @mmc: the host to regulate
* @supply: regulator to use
* @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
*
* Returns zero on success, else negative errno.
*
* MMC host drivers may use this to enable or disable a regulator using
* a particular supply voltage. This would normally be called from the
* set_ios() method.
*/
int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit)
{
int result = 0;
int min_uV, max_uV;
if (vdd_bit) {
mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV);
result = regulator_set_voltage(supply, min_uV, max_uV);
if (result == 0 && !mmc->regulator_enabled) {
result = regulator_enable(supply);
if (!result)
mmc->regulator_enabled = true;
}
} else if (mmc->regulator_enabled) {
result = regulator_disable(supply);
if (result == 0)
mmc->regulator_enabled = false;
}
if (result)
dev_err(mmc_dev(mmc),
"could not set regulator OCR (%d)\n", result);
return result;
}
EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator,
int min_uV, int target_uV,
int max_uV)
{
/*
* Check if supported first to avoid errors since we may try several
* signal levels during power up and don't want to show errors.
*/
if (!regulator_is_supported_voltage(regulator, min_uV, max_uV))
return -EINVAL;
return regulator_set_voltage_triplet(regulator, min_uV, target_uV,
max_uV);
}
/**
* mmc_regulator_set_vqmmc - Set VQMMC as per the ios
*
* For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible.
* That will match the behavior of old boards where VQMMC and VMMC were supplied
* by the same supply. The Bus Operating conditions for 3.3V signaling in the
* SD card spec also define VQMMC in terms of VMMC.
* If this is not possible we'll try the full 2.7-3.6V of the spec.
*
* For 1.2V and 1.8V signaling we'll try to get as close as possible to the
* requested voltage. This is definitely a good idea for UHS where there's a
* separate regulator on the card that's trying to make 1.8V and it's best if
* we match.
*
* This function is expected to be used by a controller's
* start_signal_voltage_switch() function.
*/
int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct device *dev = mmc_dev(mmc);
int ret, volt, min_uV, max_uV;
/* If no vqmmc supply then we can't change the voltage */
if (IS_ERR(mmc->supply.vqmmc))
return -EINVAL;
switch (ios->signal_voltage) {
case MMC_SIGNAL_VOLTAGE_120:
return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
1100000, 1200000, 1300000);
case MMC_SIGNAL_VOLTAGE_180:
return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
1700000, 1800000, 1950000);
case MMC_SIGNAL_VOLTAGE_330:
ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV);
if (ret < 0)
return ret;
dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n",
__func__, volt, max_uV);
min_uV = max(volt - 300000, 2700000);
max_uV = min(max_uV + 200000, 3600000);
/*
* Due to a limitation in the current implementation of
* regulator_set_voltage_triplet() which is taking the lowest
* voltage possible if below the target, search for a suitable
* voltage in two steps and try to stay close to vmmc
* with a 0.3V tolerance at first.
*/
if (!mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
min_uV, volt, max_uV))
return 0;
return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
2700000, volt, 3600000);
default:
return -EINVAL;
}
}
EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc);
#endif /* CONFIG_REGULATOR */
/**
* mmc_regulator_get_supply - try to get VMMC and VQMMC regulators for a host
* @mmc: the host to regulate
*
* Returns 0 or errno. errno should be handled, it is either a critical error
* or -EPROBE_DEFER. 0 means no critical error but it does not mean all
* regulators have been found because they all are optional. If you require
* certain regulators, you need to check separately in your driver if they got
* populated after calling this function.
*/
int mmc_regulator_get_supply(struct mmc_host *mmc)
{
struct device *dev = mmc_dev(mmc);
int ret;
mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
if (IS_ERR(mmc->supply.vmmc)) {
if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_dbg(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);
}
if (IS_ERR(mmc->supply.vqmmc)) {
if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_dbg(dev, "No vqmmc regulator found\n");
}
return 0;
}
EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
/*
* Mask off any voltages we don't support and select
* the lowest voltage
@ -1936,6 +1620,12 @@ static unsigned int mmc_sd_erase_timeout(struct mmc_card *card,
{
unsigned int erase_timeout;
/* for DISCARD none of the below calculation applies.
* the busy timeout is 250msec per discard command.
*/
if (arg == SD_DISCARD_ARG)
return SD_DISCARD_TIMEOUT_MS;
if (card->ssr.erase_timeout) {
/* Erase timeout specified in SD Status Register (SSR) */
erase_timeout = card->ssr.erase_timeout * qty +
@ -2164,7 +1854,7 @@ static unsigned int mmc_align_erase_size(struct mmc_card *card,
* @card: card to erase
* @from: first sector to erase
* @nr: number of sectors to erase
* @arg: erase command argument (SD supports only %MMC_ERASE_ARG)
* @arg: erase command argument
*
* Caller must claim host before calling this function.
*/
@ -2181,14 +1871,14 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
if (!card->erase_size)
return -EOPNOTSUPP;
if (mmc_card_sd(card) && arg != MMC_ERASE_ARG)
if (mmc_card_sd(card) && arg != SD_ERASE_ARG && arg != SD_DISCARD_ARG)
return -EOPNOTSUPP;
if ((arg & MMC_SECURE_ARGS) &&
if (mmc_card_mmc(card) && (arg & MMC_SECURE_ARGS) &&
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN))
return -EOPNOTSUPP;
if ((arg & MMC_TRIM_ARGS) &&
if (mmc_card_mmc(card) && (arg & MMC_TRIM_ARGS) &&
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN))
return -EOPNOTSUPP;
@ -2381,9 +2071,9 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
return card->pref_erase;
max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG);
if (max_discard && mmc_can_trim(card)) {
if (mmc_can_trim(card)) {
max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG);
if (max_trim < max_discard)
if (max_trim < max_discard || max_discard == 0)
max_discard = max_trim;
} else if (max_discard < card->erase_size) {
max_discard = 0;

View File

@ -59,6 +59,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr);
void mmc_power_off(struct mmc_host *host);
void mmc_power_cycle(struct mmc_host *host, u32 ocr);
void mmc_set_initial_state(struct mmc_host *host);
u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
static inline void mmc_delay(unsigned int ms)
{

View File

@ -194,7 +194,7 @@ int mmc_of_parse(struct mmc_host *host)
switch (bus_width) {
case 8:
host->caps |= MMC_CAP_8_BIT_DATA;
/* Hosts capable of 8-bit transfers can also do 4 bits */
/* fall through - Hosts capable of 8-bit can also do 4 bits */
case 4:
host->caps |= MMC_CAP_4_BIT_DATA;
break;
@ -260,7 +260,7 @@ int mmc_of_parse(struct mmc_host *host)
/* Parse Write Protection */
ro_cap_invert = device_property_read_bool(dev, "wp-inverted");
ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert);
ret = mmc_gpiod_request_ro(host, "wp", 0, 0, &ro_gpio_invert);
if (!ret)
dev_info(host->parent, "Got WP GPIO\n");
else if (ret != -ENOENT && ret != -ENOSYS)
@ -348,6 +348,50 @@ int mmc_of_parse(struct mmc_host *host)
EXPORT_SYMBOL(mmc_of_parse);
/**
* mmc_of_parse_voltage - return mask of supported voltages
* @np: The device node need to be parsed.
* @mask: mask of voltages available for MMC/SD/SDIO
*
* Parse the "voltage-ranges" DT property, returning zero if it is not
* found, negative errno if the voltage-range specification is invalid,
* or one if the voltage-range is specified and successfully parsed.
*/
int mmc_of_parse_voltage(struct device_node *np, u32 *mask)
{
const u32 *voltage_ranges;
int num_ranges, i;
voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
if (!voltage_ranges) {
pr_debug("%pOF: voltage-ranges unspecified\n", np);
return 0;
}
if (!num_ranges) {
pr_err("%pOF: voltage-ranges empty\n", np);
return -EINVAL;
}
for (i = 0; i < num_ranges; i++) {
const int j = i * 2;
u32 ocr_mask;
ocr_mask = mmc_vddrange_to_ocrmask(
be32_to_cpu(voltage_ranges[j]),
be32_to_cpu(voltage_ranges[j + 1]));
if (!ocr_mask) {
pr_err("%pOF: voltage-range #%d is invalid\n",
np, i);
return -EINVAL;
}
*mask |= ocr_mask;
}
return 1;
}
EXPORT_SYMBOL(mmc_of_parse_voltage);
/**
* mmc_alloc_host - initialise the per-host structure.
* @extra: sizeof private data structure

View File

@ -1594,6 +1594,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
if (oldcard) {
if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
pr_debug("%s: Perhaps the card was replaced\n",
mmc_hostname(host));
err = -ENOENT;
goto err;
}
@ -1743,6 +1745,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
card->ext_csd.power_off_notification = EXT_CSD_POWER_ON;
}
/* set erase_arg */
if (mmc_can_discard(card))
card->erase_arg = MMC_DISCARD_ARG;
else if (mmc_can_trim(card))
card->erase_arg = MMC_TRIM_ARG;
else
card->erase_arg = MMC_ERASE_ARG;
/*
* Select timing interface
*/

View File

@ -562,7 +562,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
if (index == EXT_CSD_SANITIZE_START)
cmd.sanitize_busy = true;
err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
err = mmc_wait_for_cmd(host, &cmd, 0);
if (err)
goto out;

View File

@ -0,0 +1,260 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Helper functions for MMC regulators.
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/log2.h>
#include <linux/regulator/consumer.h>
#include <linux/mmc/host.h>
#include "core.h"
#include "host.h"
#ifdef CONFIG_REGULATOR
/**
* mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage
* @vdd_bit: OCR bit number
* @min_uV: minimum voltage value (mV)
* @max_uV: maximum voltage value (mV)
*
* This function returns the voltage range according to the provided OCR
* bit number. If conversion is not possible a negative errno value returned.
*/
static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV)
{
int tmp;
if (!vdd_bit)
return -EINVAL;
/*
* REVISIT mmc_vddrange_to_ocrmask() may have set some
* bits this regulator doesn't quite support ... don't
* be too picky, most cards and regulators are OK with
* a 0.1V range goof (it's a small error percentage).
*/
tmp = vdd_bit - ilog2(MMC_VDD_165_195);
if (tmp == 0) {
*min_uV = 1650 * 1000;
*max_uV = 1950 * 1000;
} else {
*min_uV = 1900 * 1000 + tmp * 100 * 1000;
*max_uV = *min_uV + 100 * 1000;
}
return 0;
}
/**
* mmc_regulator_get_ocrmask - return mask of supported voltages
* @supply: regulator to use
*
* This returns either a negative errno, or a mask of voltages that
* can be provided to MMC/SD/SDIO devices using the specified voltage
* regulator. This would normally be called before registering the
* MMC host adapter.
*/
static int mmc_regulator_get_ocrmask(struct regulator *supply)
{
int result = 0;
int count;
int i;
int vdd_uV;
int vdd_mV;
count = regulator_count_voltages(supply);
if (count < 0)
return count;
for (i = 0; i < count; i++) {
vdd_uV = regulator_list_voltage(supply, i);
if (vdd_uV <= 0)
continue;
vdd_mV = vdd_uV / 1000;
result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
}
if (!result) {
vdd_uV = regulator_get_voltage(supply);
if (vdd_uV <= 0)
return vdd_uV;
vdd_mV = vdd_uV / 1000;
result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
}
return result;
}
/**
* mmc_regulator_set_ocr - set regulator to match host->ios voltage
* @mmc: the host to regulate
* @supply: regulator to use
* @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
*
* Returns zero on success, else negative errno.
*
* MMC host drivers may use this to enable or disable a regulator using
* a particular supply voltage. This would normally be called from the
* set_ios() method.
*/
int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit)
{
int result = 0;
int min_uV, max_uV;
if (vdd_bit) {
mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV);
result = regulator_set_voltage(supply, min_uV, max_uV);
if (result == 0 && !mmc->regulator_enabled) {
result = regulator_enable(supply);
if (!result)
mmc->regulator_enabled = true;
}
} else if (mmc->regulator_enabled) {
result = regulator_disable(supply);
if (result == 0)
mmc->regulator_enabled = false;
}
if (result)
dev_err(mmc_dev(mmc),
"could not set regulator OCR (%d)\n", result);
return result;
}
EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator,
int min_uV, int target_uV,
int max_uV)
{
/*
* Check if supported first to avoid errors since we may try several
* signal levels during power up and don't want to show errors.
*/
if (!regulator_is_supported_voltage(regulator, min_uV, max_uV))
return -EINVAL;
return regulator_set_voltage_triplet(regulator, min_uV, target_uV,
max_uV);
}
/**
* mmc_regulator_set_vqmmc - Set VQMMC as per the ios
*
* For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible.
* That will match the behavior of old boards where VQMMC and VMMC were supplied
* by the same supply. The Bus Operating conditions for 3.3V signaling in the
* SD card spec also define VQMMC in terms of VMMC.
* If this is not possible we'll try the full 2.7-3.6V of the spec.
*
* For 1.2V and 1.8V signaling we'll try to get as close as possible to the
* requested voltage. This is definitely a good idea for UHS where there's a
* separate regulator on the card that's trying to make 1.8V and it's best if
* we match.
*
* This function is expected to be used by a controller's
* start_signal_voltage_switch() function.
*/
int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct device *dev = mmc_dev(mmc);
int ret, volt, min_uV, max_uV;
/* If no vqmmc supply then we can't change the voltage */
if (IS_ERR(mmc->supply.vqmmc))
return -EINVAL;
switch (ios->signal_voltage) {
case MMC_SIGNAL_VOLTAGE_120:
return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
1100000, 1200000, 1300000);
case MMC_SIGNAL_VOLTAGE_180:
return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
1700000, 1800000, 1950000);
case MMC_SIGNAL_VOLTAGE_330:
ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV);
if (ret < 0)
return ret;
dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n",
__func__, volt, max_uV);
min_uV = max(volt - 300000, 2700000);
max_uV = min(max_uV + 200000, 3600000);
/*
* Due to a limitation in the current implementation of
* regulator_set_voltage_triplet() which is taking the lowest
* voltage possible if below the target, search for a suitable
* voltage in two steps and try to stay close to vmmc
* with a 0.3V tolerance at first.
*/
if (!mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
min_uV, volt, max_uV))
return 0;
return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
2700000, volt, 3600000);
default:
return -EINVAL;
}
}
EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc);
#else
static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
{
return 0;
}
#endif /* CONFIG_REGULATOR */
/**
* mmc_regulator_get_supply - try to get VMMC and VQMMC regulators for a host
* @mmc: the host to regulate
*
* Returns 0 or errno. errno should be handled, it is either a critical error
* or -EPROBE_DEFER. 0 means no critical error but it does not mean all
* regulators have been found because they all are optional. If you require
* certain regulators, you need to check separately in your driver if they got
* populated after calling this function.
*/
int mmc_regulator_get_supply(struct mmc_host *mmc)
{
struct device *dev = mmc_dev(mmc);
int ret;
mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
if (IS_ERR(mmc->supply.vmmc)) {
if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_dbg(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);
}
if (IS_ERR(mmc->supply.vqmmc)) {
if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_dbg(dev, "No vqmmc regulator found\n");
}
return 0;
}
EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);

View File

@ -209,6 +209,11 @@ static int mmc_decode_scr(struct mmc_card *card)
/* Check if Physical Layer Spec v3.0 is supported */
scr->sda_spec3 = UNSTUFF_BITS(resp, 47, 1);
if (scr->sda_spec3) {
scr->sda_spec4 = UNSTUFF_BITS(resp, 42, 1);
scr->sda_specx = UNSTUFF_BITS(resp, 38, 4);
}
if (UNSTUFF_BITS(resp, 55, 1))
card->erased_byte = 0xFF;
else
@ -226,6 +231,8 @@ static int mmc_read_ssr(struct mmc_card *card)
{
unsigned int au, es, et, eo;
__be32 *raw_ssr;
u32 resp[4] = {};
u8 discard_support;
int i;
if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
@ -271,6 +278,14 @@ static int mmc_read_ssr(struct mmc_card *card)
}
}
/*
* starting SD5.1 discard is supported if DISCARD_SUPPORT (b313) is set
*/
resp[3] = card->raw_ssr[6];
discard_support = UNSTUFF_BITS(resp, 313 - 288, 1);
card->erase_arg = (card->scr.sda_specx && discard_support) ?
SD_DISCARD_ARG : SD_ERASE_ARG;
return 0;
}
@ -936,8 +951,11 @@ retry:
return err;
if (oldcard) {
if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
pr_debug("%s: Perhaps the card was replaced\n",
mmc_hostname(host));
return -ENOENT;
}
card = oldcard;
} else {

View File

@ -52,36 +52,17 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
}
EXPORT_SYMBOL_GPL(mmc_app_cmd);
/**
* mmc_wait_for_app_cmd - start an application command and wait for
completion
* @host: MMC host to start command
* @card: Card to send MMC_APP_CMD to
* @cmd: MMC command to start
* @retries: maximum number of retries
*
* Sends a MMC_APP_CMD, checks the card response, sends the command
* in the parameter and waits for it to complete. Return any error
* that occurred while the command was executing. Do not attempt to
* parse the response.
*/
int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
struct mmc_command *cmd, int retries)
static int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
struct mmc_command *cmd)
{
struct mmc_request mrq = {};
int i, err;
if (retries < 0)
retries = MMC_CMD_RETRIES;
err = -EIO;
int i, err = -EIO;
/*
* We have to resend MMC_APP_CMD for each attempt so
* we cannot use the retries field in mmc_command.
*/
for (i = 0;i <= retries;i++) {
for (i = 0; i <= MMC_CMD_RETRIES; i++) {
err = mmc_app_cmd(host, card);
if (err) {
/* no point in retrying; no APP commands allowed */
@ -116,8 +97,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
return err;
}
EXPORT_SYMBOL(mmc_wait_for_app_cmd);
int mmc_app_set_bus_width(struct mmc_card *card, int width)
{
struct mmc_command cmd = {};
@ -136,7 +115,7 @@ int mmc_app_set_bus_width(struct mmc_card *card, int width)
return -EINVAL;
}
return mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES);
return mmc_wait_for_app_cmd(card->host, card, &cmd);
}
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
@ -152,7 +131,7 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
for (i = 100; i; i--) {
err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES);
err = mmc_wait_for_app_cmd(host, NULL, &cmd);
if (err)
break;

View File

@ -16,7 +16,6 @@
struct mmc_card;
struct mmc_host;
struct mmc_command;
int mmc_app_set_bus_width(struct mmc_card *card, int width);
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
@ -27,8 +26,6 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group,
u8 value, u8 *resp);
int mmc_app_sd_status(struct mmc_card *card, void *ssr);
int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
struct mmc_command *cmd, int retries);
#endif

View File

@ -617,6 +617,8 @@ try_again:
if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||
memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) {
mmc_remove_card(card);
pr_debug("%s: Perhaps the card was replaced\n",
mmc_hostname(host));
return -ENOENT;
}
} else {
@ -624,6 +626,8 @@ try_again:
if (oldcard && oldcard->type != MMC_TYPE_SDIO) {
mmc_remove_card(card);
pr_debug("%s: Perhaps the card was replaced\n",
mmc_hostname(host));
return -ENOENT;
}
}
@ -736,8 +740,11 @@ try_again:
int same = (card->cis.vendor == oldcard->cis.vendor &&
card->cis.device == oldcard->cis.device);
mmc_remove_card(card);
if (!same)
if (!same) {
pr_debug("%s: Perhaps the card was replaced\n",
mmc_hostname(host));
return -ENOENT;
}
card = oldcard;
}

View File

@ -179,7 +179,6 @@ static int sdio_bus_remove(struct device *dev)
{
struct sdio_driver *drv = to_sdio_driver(dev->driver);
struct sdio_func *func = dev_to_sdio_func(dev);
int ret = 0;
/* Make sure card is powered before invoking ->remove() */
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
@ -205,7 +204,7 @@ static int sdio_bus_remove(struct device *dev)
dev_pm_domain_detach(dev, false);
return ret;
return 0;
}
static const struct dev_pm_ops sdio_bus_pm_ops = {

View File

@ -10,6 +10,7 @@
*/
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio.h>
@ -203,6 +204,21 @@ static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
return min(mval, 512u); /* maximum size for byte mode */
}
/*
* This is legacy code, which needs to be re-worked some day. Basically we need
* to take into account the properties of the host, as to enable the SDIO func
* driver layer to allocate optimal buffers.
*/
static inline unsigned int _sdio_align_size(unsigned int sz)
{
/*
* FIXME: We don't have a system for the controller to tell
* the core about its problems yet, so for now we just 32-bit
* align the size.
*/
return ALIGN(sz, 4);
}
/**
* sdio_align_size - pads a transfer size to a more optimal value
* @func: SDIO function
@ -230,7 +246,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
* wants to increase the size up to a point where it
* might need more than one block.
*/
sz = mmc_align_data_size(func->card, sz);
sz = _sdio_align_size(sz);
/*
* If we can still do this with just a byte transfer, then
@ -252,7 +268,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
*/
blk_sz = ((sz + func->cur_blksize - 1) /
func->cur_blksize) * func->cur_blksize;
blk_sz = mmc_align_data_size(func->card, blk_sz);
blk_sz = _sdio_align_size(blk_sz);
/*
* This value is only good if it is still just
@ -265,8 +281,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
* We failed to do one request, but at least try to
* pad the remainder properly.
*/
byte_sz = mmc_align_data_size(func->card,
sz % func->cur_blksize);
byte_sz = _sdio_align_size(sz % func->cur_blksize);
if (byte_sz <= sdio_max_byte_size(func)) {
blk_sz = sz / func->cur_blksize;
return blk_sz * func->cur_blksize + byte_sz;
@ -276,16 +291,14 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
* We need multiple requests, so first check that the
* controller can handle the chunk size;
*/
chunk_sz = mmc_align_data_size(func->card,
sdio_max_byte_size(func));
chunk_sz = _sdio_align_size(sdio_max_byte_size(func));
if (chunk_sz == sdio_max_byte_size(func)) {
/*
* Fix up the size of the remainder (if any)
*/
byte_sz = orig_sz % chunk_sz;
if (byte_sz) {
byte_sz = mmc_align_data_size(func->card,
byte_sz);
byte_sz = _sdio_align_size(byte_sz);
}
return (orig_sz / chunk_sz) * chunk_sz + byte_sz;

View File

@ -25,7 +25,6 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
int sdio_reset(struct mmc_host *host);
unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz);
void sdio_irq_work(struct work_struct *work);
static inline bool sdio_is_io_busy(u32 opcode, u32 arg)

View File

@ -22,7 +22,6 @@
struct mmc_gpio {
struct gpio_desc *ro_gpio;
struct gpio_desc *cd_gpio;
bool override_ro_active_level;
bool override_cd_active_level;
irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id);
char *ro_label;
@ -71,10 +70,6 @@ int mmc_gpio_get_ro(struct mmc_host *host)
if (!ctx || !ctx->ro_gpio)
return -ENOSYS;
if (ctx->override_ro_active_level)
return !gpiod_get_raw_value_cansleep(ctx->ro_gpio) ^
!!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
return gpiod_get_value_cansleep(ctx->ro_gpio);
}
EXPORT_SYMBOL(mmc_gpio_get_ro);
@ -225,7 +220,6 @@ EXPORT_SYMBOL(mmc_can_gpio_cd);
* @host: mmc host
* @con_id: function within the GPIO consumer
* @idx: index of the GPIO to obtain in the consumer
* @override_active_level: ignore %GPIO_ACTIVE_LOW flag
* @debounce: debounce time in microseconds
* @gpio_invert: will return whether the GPIO line is inverted or not,
* set to NULL to ignore
@ -233,7 +227,7 @@ EXPORT_SYMBOL(mmc_can_gpio_cd);
* Returns zero on success, else an error.
*/
int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
unsigned int idx, bool override_active_level,
unsigned int idx,
unsigned int debounce, bool *gpio_invert)
{
struct mmc_gpio *ctx = host->slot.handler_priv;
@ -253,7 +247,6 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
if (gpio_invert)
*gpio_invert = !gpiod_is_active_low(desc);
ctx->override_ro_active_level = override_active_level;
ctx->ro_gpio = desc;
return 0;

View File

@ -224,6 +224,7 @@ config MMC_SDHCI_ESDHC_IMX
depends on ARCH_MXC
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
select MMC_CQHCI
help
This selects the Freescale eSDHC/uSDHC controller support
found on i.MX25, i.MX35 i.MX5x and i.MX6x.
@ -250,6 +251,7 @@ config MMC_SDHCI_TEGRA
depends on ARCH_TEGRA
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
select MMC_CQHCI
help
This selects the Tegra SD/MMC controller. If you have a Tegra
platform with SD or MMC devices, say Y or M here.

View File

@ -1410,6 +1410,9 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_BUS_WIDTH_4:
slot->sdc_reg |= ATMCI_SDCBUS_4BIT;
break;
case MMC_BUS_WIDTH_8:
slot->sdc_reg |= ATMCI_SDCBUS_8BIT;
break;
}
if (ios->clock) {
@ -2275,8 +2278,11 @@ static int atmci_init_slot(struct atmel_mci *host,
* use only one bit for data to prevent fifo underruns and overruns
* which will corrupt data.
*/
if ((slot_data->bus_width >= 4) && host->caps.has_rwproof)
if ((slot_data->bus_width >= 4) && host->caps.has_rwproof) {
mmc->caps |= MMC_CAP_4_BIT_DATA;
if (slot_data->bus_width >= 8)
mmc->caps |= MMC_CAP_8_BIT_DATA;
}
if (atmci_get_version(host) < 0x200) {
mmc->max_segs = 256;

View File

@ -148,7 +148,6 @@ struct bcm2835_host {
void __iomem *ioaddr;
u32 phys_addr;
struct mmc_host *mmc;
struct platform_device *pdev;
int clock; /* Current clock speed */
@ -618,7 +617,7 @@ static void bcm2835_finish_request(struct bcm2835_host *host)
"failed to terminate DMA (%d)\n", err);
}
mmc_request_done(host->mmc, mrq);
mmc_request_done(mmc_from_priv(host), mrq);
}
static
@ -837,7 +836,7 @@ static void bcm2835_timeout(struct work_struct *work)
dev_err(dev, "timeout waiting for hardware interrupt.\n");
bcm2835_dumpregs(host);
bcm2835_reset(host->mmc);
bcm2835_reset(mmc_from_priv(host));
if (host->data) {
host->data->error = -ETIMEDOUT;
@ -1100,6 +1099,7 @@ static void bcm2835_dma_complete_work(struct work_struct *work)
static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
{
struct mmc_host *mmc = mmc_from_priv(host);
int div;
/* The SDCDIV register has 11 bits, and holds (div - 2). But
@ -1143,18 +1143,18 @@ static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
div = SDCDIV_MAX_CDIV;
clock = host->max_clk / (div + 2);
host->mmc->actual_clock = clock;
mmc->actual_clock = clock;
/* Calibrate some delays */
host->ns_per_fifo_word = (1000000000 / clock) *
((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
((mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
host->cdiv = div;
writel(host->cdiv, host->ioaddr + SDCDIV);
/* Set the timeout to 500ms */
writel(host->mmc->actual_clock / 2, host->ioaddr + SDTOUT);
writel(mmc->actual_clock / 2, host->ioaddr + SDTOUT);
}
static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
@ -1264,7 +1264,7 @@ static const struct mmc_host_ops bcm2835_ops = {
static int bcm2835_add_host(struct bcm2835_host *host)
{
struct mmc_host *mmc = host->mmc;
struct mmc_host *mmc = mmc_from_priv(host);
struct device *dev = &host->pdev->dev;
char pio_limit_string[20];
int ret;
@ -1286,7 +1286,7 @@ static int bcm2835_add_host(struct bcm2835_host *host)
spin_lock_init(&host->lock);
mutex_init(&host->mutex);
if (IS_ERR_OR_NULL(host->dma_chan_rxtx)) {
if (!host->dma_chan_rxtx) {
dev_warn(dev, "unable to initialise DMA channel. Falling back to PIO\n");
host->use_dma = false;
} else {
@ -1370,7 +1370,6 @@ static int bcm2835_probe(struct platform_device *pdev)
mmc->ops = &bcm2835_ops;
host = mmc_priv(mmc);
host->mmc = mmc;
host->pdev = pdev;
spin_lock_init(&host->lock);
@ -1441,8 +1440,9 @@ err:
static int bcm2835_remove(struct platform_device *pdev)
{
struct bcm2835_host *host = platform_get_drvdata(pdev);
struct mmc_host *mmc = mmc_from_priv(host);
mmc_remove_host(host->mmc);
mmc_remove_host(mmc);
writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD);
@ -1454,8 +1454,7 @@ static int bcm2835_remove(struct platform_device *pdev)
if (host->dma_chan_rxtx)
dma_release_channel(host->dma_chan_rxtx);
mmc_free_host(host->mmc);
platform_set_drvdata(pdev, NULL);
mmc_free_host(mmc);
return 0;
}

View File

@ -566,30 +566,32 @@ static void cb710_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
cb710_mmc_select_clock_divider(mmc, ios->clock);
if (ios->power_mode != reader->last_power_mode)
switch (ios->power_mode) {
case MMC_POWER_ON:
err = cb710_mmc_powerup(slot);
if (err) {
dev_warn(cb710_slot_dev(slot),
"powerup failed (%d)- retrying\n", err);
cb710_mmc_powerdown(slot);
udelay(1);
if (ios->power_mode != reader->last_power_mode) {
switch (ios->power_mode) {
case MMC_POWER_ON:
err = cb710_mmc_powerup(slot);
if (err)
if (err) {
dev_warn(cb710_slot_dev(slot),
"powerup retry failed (%d) - expect errors\n",
"powerup failed (%d)- retrying\n", err);
cb710_mmc_powerdown(slot);
udelay(1);
err = cb710_mmc_powerup(slot);
if (err)
dev_warn(cb710_slot_dev(slot),
"powerup retry failed (%d) - expect errors\n",
err);
}
reader->last_power_mode = MMC_POWER_ON;
break;
case MMC_POWER_OFF:
cb710_mmc_powerdown(slot);
reader->last_power_mode = MMC_POWER_OFF;
break;
case MMC_POWER_UP:
default:
/* ignore */
break;
}
reader->last_power_mode = MMC_POWER_ON;
break;
case MMC_POWER_OFF:
cb710_mmc_powerdown(slot);
reader->last_power_mode = MMC_POWER_OFF;
break;
case MMC_POWER_UP:
default:
/* ignore */;
}
cb710_mmc_enable_4bit_data(slot, ios->bus_width != MMC_BUS_WIDTH_1);

View File

@ -1193,7 +1193,7 @@ static int mmc_davinci_parse_pdata(struct mmc_host *mmc)
else if (ret)
mmc->caps |= MMC_CAP_NEEDS_POLL;
ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL);
if (ret == -EPROBE_DEFER)
return ret;

View File

@ -21,7 +21,6 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
@ -36,7 +35,6 @@
#include <asm/cacheflush.h>
#include <asm/mach-jz4740/dma.h>
#include <asm/mach-jz4740/jz4740_mmc.h>
#define JZ_REG_MMC_STRPCL 0x00
#define JZ_REG_MMC_STATUS 0x04
@ -148,9 +146,7 @@ enum jz4780_cookie {
struct jz4740_mmc_host {
struct mmc_host *mmc;
struct platform_device *pdev;
struct jz4740_mmc_platform_data *pdata;
struct clk *clk;
struct gpio_desc *power;
enum jz4740_mmc_version version;
@ -743,6 +739,7 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid)
break;
jz_mmc_prepare_data_transfer(host);
/* fall through */
case JZ4740_MMC_STATE_TRANSFER_DATA:
if (host->use_dma) {
@ -777,6 +774,7 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid)
break;
}
jz4740_mmc_write_irq_reg(host, JZ_MMC_IRQ_DATA_TRAN_DONE);
/* fall through */
case JZ4740_MMC_STATE_SEND_STOP:
if (!req->stop)
@ -894,16 +892,16 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
switch (ios->power_mode) {
case MMC_POWER_UP:
jz4740_mmc_reset(host);
if (host->power)
gpiod_set_value(host->power, 1);
if (!IS_ERR(mmc->supply.vmmc))
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
host->cmdat |= JZ_MMC_CMDAT_INIT;
clk_prepare_enable(host->clk);
break;
case MMC_POWER_ON:
break;
default:
if (host->power)
gpiod_set_value(host->power, 0);
if (!IS_ERR(mmc->supply.vmmc))
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
clk_disable_unprepare(host->clk);
break;
}
@ -936,38 +934,6 @@ static const struct mmc_host_ops jz4740_mmc_ops = {
.enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
};
static int jz4740_mmc_request_gpios(struct jz4740_mmc_host *host,
struct mmc_host *mmc,
struct platform_device *pdev)
{
struct jz4740_mmc_platform_data *pdata = dev_get_platdata(&pdev->dev);
int ret = 0;
if (!pdata)
return 0;
if (!pdata->card_detect_active_low)
mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
if (!pdata->read_only_active_low)
mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
/*
* Get optional card detect and write protect GPIOs,
* only back out on probe deferral.
*/
ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL);
if (ret == -EPROBE_DEFER)
return ret;
ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
if (ret == -EPROBE_DEFER)
return ret;
host->power = devm_gpiod_get_optional(&pdev->dev, "power",
GPIOD_OUT_HIGH);
return PTR_ERR_OR_ZERO(host->power);
}
static const struct of_device_id jz4740_mmc_of_match[] = {
{ .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 },
{ .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B },
@ -982,9 +948,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
struct mmc_host *mmc;
struct jz4740_mmc_host *host;
const struct of_device_id *match;
struct jz4740_mmc_platform_data *pdata;
pdata = dev_get_platdata(&pdev->dev);
mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), &pdev->dev);
if (!mmc) {
@ -993,29 +956,25 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
}
host = mmc_priv(mmc);
host->pdata = pdata;
match = of_match_device(jz4740_mmc_of_match, &pdev->dev);
if (match) {
host->version = (enum jz4740_mmc_version)match->data;
ret = mmc_of_parse(mmc);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"could not parse of data: %d\n", ret);
goto err_free_host;
}
} else {
/* JZ4740 should be the only one using legacy probe */
host->version = JZ_MMC_JZ4740;
mmc->caps |= MMC_CAP_SDIO_IRQ;
if (!(pdata && pdata->data_1bit))
mmc->caps |= MMC_CAP_4_BIT_DATA;
ret = jz4740_mmc_request_gpios(host, mmc, pdev);
if (ret)
goto err_free_host;
}
ret = mmc_of_parse(mmc);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"could not parse device properties: %d\n", ret);
goto err_free_host;
}
mmc_regulator_get_supply(mmc);
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
ret = host->irq;

View File

@ -1453,7 +1453,7 @@ static int mmc_spi_probe(struct spi_device *spi)
mmc_detect_change(mmc, 0);
/* Index 1 is write protect/read only */
status = mmc_gpiod_request_ro(mmc, NULL, 1, false, 0, NULL);
status = mmc_gpiod_request_ro(mmc, NULL, 1, 0, NULL);
if (status == -EPROBE_DEFER)
goto fail_add_host;
if (!status)

View File

@ -1127,6 +1127,12 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
writel(c, base + MMCICOMMAND);
}
static void mmci_stop_command(struct mmci_host *host)
{
host->stop_abort.error = 0;
mmci_start_command(host, &host->stop_abort, 0);
}
static void
mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
unsigned int status)
@ -1196,10 +1202,16 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
/* The error clause is handled above, success! */
data->bytes_xfered = data->blksz * data->blocks;
if (!data->stop || (host->mrq->sbc && !data->error))
if (!data->stop) {
if (host->variant->cmdreg_stop && data->error)
mmci_stop_command(host);
else
mmci_request_end(host, data->mrq);
} else if (host->mrq->sbc && !data->error) {
mmci_request_end(host, data->mrq);
else
} else {
mmci_start_command(host, data->stop, 0);
}
}
}
@ -1298,6 +1310,10 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
mmci_dma_error(host);
mmci_stop_data(host);
if (host->variant->cmdreg_stop && cmd->error) {
mmci_stop_command(host);
return;
}
}
mmci_request_end(host, host->mrq);
} else if (sbc) {
@ -1956,6 +1972,11 @@ static int mmci_probe(struct amba_device *dev,
mmc->max_busy_timeout = 0;
}
/* Prepare a CMD12 - needed to clear the DPSM on some variants. */
host->stop_abort.opcode = MMC_STOP_TRANSMISSION;
host->stop_abort.arg = 0;
host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC;
mmc->ops = &mmci_ops;
/* We support these PM capabilities. */
@ -2011,7 +2032,7 @@ static int mmci_probe(struct amba_device *dev,
if (ret == -EPROBE_DEFER)
goto clk_disable;
ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL);
if (ret == -EPROBE_DEFER)
goto clk_disable;
}

View File

@ -377,6 +377,7 @@ struct mmci_host {
void __iomem *base;
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_command stop_abort;
struct mmc_data *data;
struct mmc_host *mmc;
struct clk *clk;

View File

@ -31,14 +31,12 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/dmaengine.h>
#include <linux/types.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/of_gpio.h>
#include <linux/mmc/slot-gpio.h>
#include <asm/dma.h>

View File

@ -25,7 +25,6 @@
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@ -39,7 +38,6 @@
#include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/stmp_device.h>

View File

@ -61,9 +61,6 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
struct device *dev = &spi->dev;
struct device_node *np = dev->of_node;
struct of_mmc_spi *oms;
const __be32 *voltage_ranges;
int num_ranges;
int i;
if (dev->platform_data || !np)
return dev->platform_data;
@ -72,25 +69,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
if (!oms)
return NULL;
voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
if (!voltage_ranges || !num_ranges) {
dev_err(dev, "OF: voltage-ranges unspecified\n");
if (mmc_of_parse_voltage(np, &oms->pdata.ocr_mask) <= 0)
goto err_ocr;
}
for (i = 0; i < num_ranges; i++) {
const int j = i * 2;
u32 mask;
mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
be32_to_cpu(voltage_ranges[j + 1]));
if (!mask) {
dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
goto err_ocr;
}
oms->pdata.ocr_mask |= mask;
}
oms->detect_irq = irq_of_parse_and_map(np, 0);
if (oms->detect_irq != 0) {

View File

@ -920,7 +920,7 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques
reg &= ~(1 << 5);
OMAP_MMC_WRITE(host, SDIO, reg);
/* Set maximum timeout */
OMAP_MMC_WRITE(host, CTO, 0xff);
OMAP_MMC_WRITE(host, CTO, 0xfd);
}
static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)

View File

@ -743,7 +743,7 @@ static int pxamci_probe(struct platform_device *pdev)
goto out;
}
ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL);
if (ret && ret != -ENOENT) {
dev_err(dev, "Failed requesting gpio_ro\n");
goto out;

View File

@ -15,6 +15,7 @@
struct renesas_sdhi_scc {
unsigned long clk_rate; /* clock rate for SDR104 */
u32 tap; /* sampling clock position for SDR104 */
u32 tap_hs400; /* sampling clock position for HS400 */
};
struct renesas_sdhi_of_data {
@ -49,6 +50,7 @@ struct renesas_sdhi {
struct pinctrl_state *pins_default, *pins_uhs;
void __iomem *scc_ctl;
u32 scc_tappos;
u32 scc_tappos_hs400;
};
#define host_to_priv(host) \

View File

@ -337,6 +337,10 @@ static void renesas_sdhi_hs400_complete(struct tmio_mmc_host *host)
/* Set HS400 mode */
sd_ctrl_write16(host, CTL_SDIF_MODE, 0x0001 |
sd_ctrl_read16(host, CTL_SDIF_MODE));
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF,
priv->scc_tappos_hs400);
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2,
(SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN |
SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) |
@ -396,6 +400,9 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host,
/* Reset HS400 mode */
sd_ctrl_write16(host, CTL_SDIF_MODE, ~0x0001 &
sd_ctrl_read16(host, CTL_SDIF_MODE));
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos);
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2,
~(SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN |
SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) &
@ -723,6 +730,13 @@ int renesas_sdhi_probe(struct platform_device *pdev,
host->ops.start_signal_voltage_switch =
renesas_sdhi_start_signal_voltage_switch;
host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27;
/* SDR and HS200/400 registers requires HW reset */
if (of_data && of_data->scc_offset) {
priv->scc_ctl = host->ctl + of_data->scc_offset;
host->mmc->caps |= MMC_CAP_HW_RESET;
host->hw_reset = renesas_sdhi_hw_reset;
}
}
/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */
@ -775,12 +789,11 @@ int renesas_sdhi_probe(struct platform_device *pdev,
const struct renesas_sdhi_scc *taps = of_data->taps;
bool hit = false;
host->mmc->caps |= MMC_CAP_HW_RESET;
for (i = 0; i < of_data->taps_num; i++) {
if (taps[i].clk_rate == 0 ||
taps[i].clk_rate == host->mmc->f_max) {
priv->scc_tappos = taps->tap;
priv->scc_tappos_hs400 = taps->tap_hs400;
hit = true;
break;
}
@ -789,12 +802,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,
if (!hit)
dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n");
priv->scc_ctl = host->ctl + of_data->scc_offset;
host->init_tuning = renesas_sdhi_init_tuning;
host->prepare_tuning = renesas_sdhi_prepare_tuning;
host->select_tuning = renesas_sdhi_select_tuning;
host->check_scc_error = renesas_sdhi_check_scc_error;
host->hw_reset = renesas_sdhi_hw_reset;
host->prepare_hs400_tuning =
renesas_sdhi_prepare_hs400_tuning;
host->hs400_downgrade = renesas_sdhi_disable_scc;

View File

@ -81,6 +81,7 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = {
{
.clk_rate = 0,
.tap = 0x00000300,
.tap_hs400 = 0x00000704,
},
};

View File

@ -1530,7 +1530,7 @@ static int s3cmci_probe_pdata(struct s3cmci_host *host)
return ret;
}
ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, false, 0, NULL);
ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL);
if (ret != -ENOENT) {
dev_err(&pdev->dev, "error requesting GPIO for WP %d\n",
ret);

View File

@ -18,12 +18,10 @@
#include <linux/platform_device.h>
#include <linux/mmc/host.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/mmc/slot-gpio.h>
#include "sdhci-pltfm.h"

View File

@ -55,7 +55,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
}
sdhci_get_of_property(pdev);
mmc_of_parse(host->mmc);
res = mmc_of_parse(host->mmc);
if (res)
goto err;
/*
* Supply the existing CAPS, but clear the UHS modes. This

View File

@ -25,6 +25,7 @@
#include <linux/pm_runtime.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
#include "cqhci.h"
#define ESDHC_SYS_CTRL_DTOCV_MASK 0x0f
#define ESDHC_CTRL_D3CD 0x08
@ -50,6 +51,7 @@
#define ESDHC_MIX_CTRL_AUTO_TUNE_EN (1 << 24)
#define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25)
#define ESDHC_MIX_CTRL_HS400_EN (1 << 26)
#define ESDHC_MIX_CTRL_HS400_ES_EN (1 << 27)
/* Bits 3 and 6 are not SDHCI standard definitions */
#define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7
/* Tuning bits */
@ -76,6 +78,9 @@
#define ESDHC_STROBE_DLL_STS_REF_LOCK (1 << 1)
#define ESDHC_STROBE_DLL_STS_SLV_LOCK 0x1
#define ESDHC_VEND_SPEC2 0xc8
#define ESDHC_VEND_SPEC2_EN_BUSY_IRQ (1 << 8)
#define ESDHC_TUNING_CTRL 0xcc
#define ESDHC_STD_TUNING_EN (1 << 24)
/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
@ -103,6 +108,9 @@
*/
#define ESDHC_INT_VENDOR_SPEC_DMA_ERR (1 << 28)
/* the address offset of CQHCI */
#define ESDHC_CQHCI_ADDR_OFFSET 0x100
/*
* The CMDTYPE of the CMD register (offset 0xE) should be set to
* "11" when the STOP CMD12 is issued on imx53 to abort one
@ -138,51 +146,71 @@
#define ESDHC_FLAG_HS200 BIT(8)
/* The IP supports HS400 mode */
#define ESDHC_FLAG_HS400 BIT(9)
/* A clock frequency higher than this rate requires strobe dll control */
#define ESDHC_STROBE_DLL_CLK_FREQ 100000000
/*
* The IP has errata ERR010450
* uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't
* exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
*/
#define ESDHC_FLAG_ERR010450 BIT(10)
/* The IP supports HS400ES mode */
#define ESDHC_FLAG_HS400_ES BIT(11)
/* The IP has Host Controller Interface for Command Queuing */
#define ESDHC_FLAG_CQHCI BIT(12)
struct esdhc_soc_data {
u32 flags;
};
static struct esdhc_soc_data esdhc_imx25_data = {
static const struct esdhc_soc_data esdhc_imx25_data = {
.flags = ESDHC_FLAG_ERR004536,
};
static struct esdhc_soc_data esdhc_imx35_data = {
static const struct esdhc_soc_data esdhc_imx35_data = {
.flags = ESDHC_FLAG_ERR004536,
};
static struct esdhc_soc_data esdhc_imx51_data = {
static const struct esdhc_soc_data esdhc_imx51_data = {
.flags = 0,
};
static struct esdhc_soc_data esdhc_imx53_data = {
static const struct esdhc_soc_data esdhc_imx53_data = {
.flags = ESDHC_FLAG_MULTIBLK_NO_INT,
};
static struct esdhc_soc_data usdhc_imx6q_data = {
static const struct esdhc_soc_data usdhc_imx6q_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING,
};
static struct esdhc_soc_data usdhc_imx6sl_data = {
static const struct esdhc_soc_data usdhc_imx6sl_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536
| ESDHC_FLAG_HS200,
};
static struct esdhc_soc_data usdhc_imx6sx_data = {
static const struct esdhc_soc_data usdhc_imx6sx_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200,
};
static struct esdhc_soc_data usdhc_imx7d_data = {
static const struct esdhc_soc_data usdhc_imx6ull_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
| ESDHC_FLAG_ERR010450,
};
static const struct esdhc_soc_data usdhc_imx7d_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
| ESDHC_FLAG_HS400,
};
static struct esdhc_soc_data usdhc_imx8qxp_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
| ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES
| ESDHC_FLAG_CQHCI,
};
struct pltfm_imx_data {
u32 scratchpad;
struct pinctrl *pinctrl;
@ -227,7 +255,9 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
{ .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, },
{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
{ .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
{ .compatible = "fsl,imx6ull-usdhc", .data = &usdhc_imx6ull_data, },
{ .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, },
{ .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
@ -733,6 +763,14 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) {
unsigned int max_clock;
max_clock = imx_data->is_ddr ? 45000000 : 150000000;
clock = min(clock, max_clock);
}
while (host_clock / (16 * pre_div * ddr_pre_div) > clock &&
pre_div < 256)
pre_div *= 2;
@ -801,6 +839,20 @@ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
SDHCI_HOST_CONTROL);
}
static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host = mmc_priv(mmc);
/*
* i.MX uSDHC internally already uses a fixed optimized timing for
* DDR50, normally does not require tuning for DDR50 mode.
*/
if (host->timing == MMC_TIMING_UHS_DDR50)
return 0;
return sdhci_execute_tuning(mmc, opcode);
}
static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
{
u32 reg;
@ -864,6 +916,19 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
return ret;
}
static void esdhc_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sdhci_host *host = mmc_priv(mmc);
u32 m;
m = readl(host->ioaddr + ESDHC_MIX_CTRL);
if (ios->enhanced_strobe)
m |= ESDHC_MIX_CTRL_HS400_ES_EN;
else
m &= ~ESDHC_MIX_CTRL_HS400_ES_EN;
writel(m, host->ioaddr + ESDHC_MIX_CTRL);
}
static int esdhc_change_pinstate(struct sdhci_host *host,
unsigned int uhs)
{
@ -905,39 +970,35 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
* edge of data_strobe line. Due to the time delay between CLK line and
* data_strobe line, if the delay time is larger than one clock cycle,
* then CLK and data_strobe line will be misaligned, read error shows up.
* So when the CLK is higher than 100MHz, each clock cycle is short enough,
* host should configure the delay target.
*/
static void esdhc_set_strobe_dll(struct sdhci_host *host)
{
u32 v;
if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
/* disable clock before enabling strobe dll */
writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
host->ioaddr + ESDHC_VENDOR_SPEC);
/* disable clock before enabling strobe dll */
writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
host->ioaddr + ESDHC_VENDOR_SPEC);
/* force a reset on strobe dll */
writel(ESDHC_STROBE_DLL_CTRL_RESET,
host->ioaddr + ESDHC_STROBE_DLL_CTRL);
/*
* enable strobe dll ctrl and adjust the delay target
* for the uSDHC loopback read clock
*/
v = ESDHC_STROBE_DLL_CTRL_ENABLE |
(7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
/* wait 1us to make sure strobe dll status register stable */
udelay(1);
v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
dev_warn(mmc_dev(host->mmc),
"warning! HS400 strobe DLL status REF not lock!\n");
if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
dev_warn(mmc_dev(host->mmc),
"warning! HS400 strobe DLL status SLV not lock!\n");
}
/* force a reset on strobe dll */
writel(ESDHC_STROBE_DLL_CTRL_RESET,
host->ioaddr + ESDHC_STROBE_DLL_CTRL);
/*
* enable strobe dll ctrl and adjust the delay target
* for the uSDHC loopback read clock
*/
v = ESDHC_STROBE_DLL_CTRL_ENABLE |
(7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
/* wait 1us to make sure strobe dll status register stable */
udelay(1);
v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
dev_warn(mmc_dev(host->mmc),
"warning! HS400 strobe DLL status REF not lock!\n");
if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
dev_warn(mmc_dev(host->mmc),
"warning! HS400 strobe DLL status SLV not lock!\n");
}
static void esdhc_reset_tuning(struct sdhci_host *host)
@ -979,6 +1040,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
case MMC_TIMING_UHS_SDR25:
case MMC_TIMING_UHS_SDR50:
case MMC_TIMING_UHS_SDR104:
case MMC_TIMING_MMC_HS:
case MMC_TIMING_MMC_HS200:
writel(m, host->ioaddr + ESDHC_MIX_CTRL);
break;
@ -1042,6 +1104,19 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
SDHCI_TIMEOUT_CONTROL);
}
static u32 esdhc_cqhci_irq(struct sdhci_host *host, u32 intmask)
{
int cmd_error = 0;
int data_error = 0;
if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
return intmask;
cqhci_irq(host->mmc, intmask, cmd_error, data_error);
return 0;
}
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
@ -1058,6 +1133,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.set_bus_width = esdhc_pltfm_set_bus_width,
.set_uhs_signaling = esdhc_set_uhs_signaling,
.reset = esdhc_reset,
.irq = esdhc_cqhci_irq,
};
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@ -1106,6 +1182,23 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
/* disable DLL_CTRL delay line settings */
writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
/*
* For the case of command with busy, if set the bit
* ESDHC_VEND_SPEC2_EN_BUSY_IRQ, USDHC will generate a
* transfer complete interrupt when busy is deasserted.
* When CQHCI use DCMD to send a CMD need R1b respons,
* CQHCI require to set ESDHC_VEND_SPEC2_EN_BUSY_IRQ,
* otherwise DCMD will always meet timeout waiting for
* hardware interrupt issue.
*/
if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) {
tmp = readl(host->ioaddr + ESDHC_VEND_SPEC2);
tmp |= ESDHC_VEND_SPEC2_EN_BUSY_IRQ;
writel(tmp, host->ioaddr + ESDHC_VEND_SPEC2);
host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
}
if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
tmp |= ESDHC_STD_TUNING_EN |
@ -1121,10 +1214,81 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
<< ESDHC_TUNING_STEP_SHIFT;
}
writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
} else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
/*
* ESDHC_STD_TUNING_EN may be configed in bootloader
* or ROM code, so clear this bit here to make sure
* the manual tuning can work.
*/
tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
tmp &= ~ESDHC_STD_TUNING_EN;
writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
}
}
}
static void esdhc_cqe_enable(struct mmc_host *mmc)
{
struct sdhci_host *host = mmc_priv(mmc);
struct cqhci_host *cq_host = mmc->cqe_private;
u32 reg;
u16 mode;
int count = 10;
/*
* CQE gets stuck if it sees Buffer Read Enable bit set, which can be
* the case after tuning, so ensure the buffer is drained.
*/
reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
while (reg & SDHCI_DATA_AVAILABLE) {
sdhci_readl(host, SDHCI_BUFFER);
reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
if (count-- == 0) {
dev_warn(mmc_dev(host->mmc),
"CQE may get stuck because the Buffer Read Enable bit is set\n");
break;
}
mdelay(1);
}
/*
* Runtime resume will reset the entire host controller, which
* will also clear the DMAEN/BCEN of register ESDHC_MIX_CTRL.
* Here set DMAEN and BCEN when enable CMDQ.
*/
mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
if (host->flags & SDHCI_REQ_USE_DMA)
mode |= SDHCI_TRNS_DMA;
if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE))
mode |= SDHCI_TRNS_BLK_CNT_EN;
sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
/*
* Though Runtime resume reset the entire host controller,
* but do not impact the CQHCI side, need to clear the
* HALT bit, avoid CQHCI stuck in the first request when
* system resume back.
*/
cqhci_writel(cq_host, 0, CQHCI_CTL);
if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT)
dev_err(mmc_dev(host->mmc),
"failed to exit halt state when enable CQE\n");
sdhci_cqe_enable(mmc);
}
static void esdhc_sdhci_dumpregs(struct mmc_host *mmc)
{
sdhci_dumpregs(mmc_priv(mmc));
}
static const struct cqhci_host_ops esdhc_cqhci_ops = {
.enable = esdhc_cqe_enable,
.disable = sdhci_cqe_disable,
.dumpregs = esdhc_sdhci_dumpregs,
};
#ifdef CONFIG_OF
static int
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
@ -1201,7 +1365,7 @@ static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev,
host->mmc->parent->platform_data);
/* write_protect */
if (boarddata->wp_type == ESDHC_WP_GPIO) {
err = mmc_gpiod_request_ro(host->mmc, "wp", 0, false, 0, NULL);
err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL);
if (err) {
dev_err(mmc_dev(host->mmc),
"failed to request write-protect gpio!\n");
@ -1256,6 +1420,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
of_match_device(imx_esdhc_dt_ids, &pdev->dev);
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_host *host;
struct cqhci_host *cq_host;
int err;
struct pltfm_imx_data *imx_data;
@ -1322,6 +1487,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
writel(0x0, host->ioaddr + ESDHC_MIX_CTRL);
writel(0x0, host->ioaddr + SDHCI_AUTO_CMD_STATUS);
writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
/*
* Link usdhc specific mmc_host_ops execute_tuning function,
* to replace the standard one in sdhci_ops.
*/
host->mmc_host_ops.execute_tuning = usdhc_execute_tuning;
}
if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
@ -1334,6 +1505,28 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400;
if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
host->mmc->caps2 |= MMC_CAP2_HS400_ES;
host->mmc_host_ops.hs400_enhanced_strobe =
esdhc_hs400_enhanced_strobe;
}
if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) {
host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
cq_host = devm_kzalloc(&pdev->dev, sizeof(*cq_host), GFP_KERNEL);
if (!cq_host) {
err = -ENOMEM;
goto disable_ahb_clk;
}
cq_host->mmio = host->ioaddr + ESDHC_CQHCI_ADDR_OFFSET;
cq_host->ops = &esdhc_cqhci_ops;
err = cqhci_init(cq_host, host->mmc, false);
if (err)
goto disable_ahb_clk;
}
if (of_id)
err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
else
@ -1341,6 +1534,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (err)
goto disable_ahb_clk;
host->tuning_delay = 1;
sdhci_esdhc_imx_hwinit(host);
err = sdhci_add_host(host);
@ -1392,6 +1587,13 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
static int sdhci_esdhc_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
int ret;
if (host->mmc->caps2 & MMC_CAP2_CQE) {
ret = cqhci_suspend(host->mmc);
if (ret)
return ret;
}
if (host->tuning_mode != SDHCI_TUNING_MODE_3)
mmc_retune_needed(host->mmc);
@ -1402,11 +1604,19 @@ static int sdhci_esdhc_suspend(struct device *dev)
static int sdhci_esdhc_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
int ret;
/* re-initialize hw state in case it's lost in low power mode */
sdhci_esdhc_imx_hwinit(host);
return sdhci_resume_host(host);
ret = sdhci_resume_host(host);
if (ret)
return ret;
if (host->mmc->caps2 & MMC_CAP2_CQE)
ret = cqhci_resume(host->mmc);
return ret;
}
#endif
@ -1418,6 +1628,12 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev)
struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
int ret;
if (host->mmc->caps2 & MMC_CAP2_CQE) {
ret = cqhci_suspend(host->mmc);
if (ret)
return ret;
}
ret = sdhci_runtime_suspend_host(host);
if (ret)
return ret;
@ -1461,7 +1677,10 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
if (err)
goto disable_ipg_clk;
return 0;
if (host->mmc->caps2 & MMC_CAP2_CQE)
err = cqhci_resume(host->mmc);
return err;
disable_ipg_clk:
if (!sdhci_sdio_irq_enabled(host))

View File

@ -1097,7 +1097,6 @@ static int sdhci_omap_probe(struct platform_device *pdev)
goto err_put_sync;
}
host->mmc_host_ops.get_ro = mmc_gpio_get_ro;
host->mmc_host_ops.start_signal_voltage_switch =
sdhci_omap_start_signal_voltage_switch;
host->mmc_host_ops.set_ios = sdhci_omap_set_ios;

View File

@ -1257,16 +1257,6 @@ static int jmicron_resume(struct sdhci_pci_chip *chip)
}
#endif
static const struct sdhci_pci_fixes sdhci_o2 = {
.probe = sdhci_pci_o2_probe,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD,
.probe_slot = sdhci_pci_o2_probe_slot,
#ifdef CONFIG_PM_SLEEP
.resume = sdhci_pci_o2_resume,
#endif
};
static const struct sdhci_pci_fixes sdhci_jmicron = {
.probe = jmicron_probe,

View File

@ -60,6 +60,13 @@
#define O2_SD_VENDOR_SETTING2 0x1C8
#define O2_SD_HW_TUNING_DISABLE BIT(4)
#define O2_PLL_WDT_CONTROL1 0x1CC
#define O2_PLL_FORCE_ACTIVE BIT(18)
#define O2_PLL_LOCK_STATUS BIT(14)
#define O2_PLL_SOFT_RESET BIT(12)
#define O2_SD_DETECT_SETTING 0x324
static void sdhci_o2_set_tuning_mode(struct sdhci_host *host)
{
u16 reg;
@ -283,6 +290,113 @@ static void sdhci_pci_o2_enable_msi(struct sdhci_pci_chip *chip,
host->irq = pci_irq_vector(chip->pdev, 0);
}
static void sdhci_o2_wait_card_detect_stable(struct sdhci_host *host)
{
ktime_t timeout;
u32 scratch32;
/* Wait max 50 ms */
timeout = ktime_add_ms(ktime_get(), 50);
while (1) {
bool timedout = ktime_after(ktime_get(), timeout);
scratch32 = sdhci_readl(host, SDHCI_PRESENT_STATE);
if ((scratch32 & SDHCI_CARD_PRESENT) >> SDHCI_CARD_PRES_SHIFT
== (scratch32 & SDHCI_CD_LVL) >> SDHCI_CD_LVL_SHIFT)
break;
if (timedout) {
pr_err("%s: Card Detect debounce never finished.\n",
mmc_hostname(host->mmc));
sdhci_dumpregs(host);
return;
}
udelay(10);
}
}
static void sdhci_o2_enable_internal_clock(struct sdhci_host *host)
{
ktime_t timeout;
u16 scratch;
u32 scratch32;
/* PLL software reset */
scratch32 = sdhci_readl(host, O2_PLL_WDT_CONTROL1);
scratch32 |= O2_PLL_SOFT_RESET;
sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1);
udelay(1);
scratch32 &= ~(O2_PLL_SOFT_RESET);
sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1);
/* PLL force active */
scratch32 |= O2_PLL_FORCE_ACTIVE;
sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1);
/* Wait max 20 ms */
timeout = ktime_add_ms(ktime_get(), 20);
while (1) {
bool timedout = ktime_after(ktime_get(), timeout);
scratch = sdhci_readw(host, O2_PLL_WDT_CONTROL1);
if (scratch & O2_PLL_LOCK_STATUS)
break;
if (timedout) {
pr_err("%s: Internal clock never stabilised.\n",
mmc_hostname(host->mmc));
sdhci_dumpregs(host);
goto out;
}
udelay(10);
}
/* Wait for card detect finish */
udelay(1);
sdhci_o2_wait_card_detect_stable(host);
out:
/* Cancel PLL force active */
scratch32 = sdhci_readl(host, O2_PLL_WDT_CONTROL1);
scratch32 &= ~O2_PLL_FORCE_ACTIVE;
sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1);
}
static int sdhci_o2_get_cd(struct mmc_host *mmc)
{
struct sdhci_host *host = mmc_priv(mmc);
sdhci_o2_enable_internal_clock(host);
return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
}
static void sdhci_o2_enable_clk(struct sdhci_host *host, u16 clk)
{
/* Enable internal clock */
clk |= SDHCI_CLOCK_INT_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
if (sdhci_o2_get_cd(host->mmc)) {
clk |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
}
}
void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock)
{
u16 clk;
host->mmc->actual_clock = 0;
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
if (clock == 0)
return;
clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
sdhci_o2_enable_clk(host, clk);
}
int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
{
struct sdhci_pci_chip *chip;
@ -314,9 +428,14 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
mmc_hostname(host->mmc));
host->flags &= ~SDHCI_SIGNALING_330;
host->flags |= SDHCI_SIGNALING_180;
host->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
host->mmc->caps2 |= MMC_CAP2_NO_SD;
host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
pci_write_config_dword(chip->pdev,
O2_SD_DETECT_SETTING, 3);
}
slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd;
}
host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning;
@ -490,9 +609,6 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
break;
case PCI_DEVICE_ID_O2_SEABIRD0:
if (chip->pdev->revision == 0x01)
chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER;
/* fall through */
case PCI_DEVICE_ID_O2_SEABIRD1:
/* UnLock WP */
ret = pci_read_config_byte(chip->pdev,
@ -550,3 +666,21 @@ int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip)
return sdhci_pci_resume_host(chip);
}
#endif
static const struct sdhci_ops sdhci_pci_o2_ops = {
.set_clock = sdhci_pci_o2_set_clock,
.enable_dma = sdhci_pci_enable_dma,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
};
const struct sdhci_pci_fixes sdhci_o2 = {
.probe = sdhci_pci_o2_probe,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.probe_slot = sdhci_pci_o2_probe_slot,
#ifdef CONFIG_PM_SLEEP
.resume = sdhci_pci_o2_resume,
#endif
.ops = &sdhci_pci_o2_ops,
};

View File

@ -179,13 +179,9 @@ static inline void *sdhci_pci_priv(struct sdhci_pci_slot *slot)
int sdhci_pci_resume_host(struct sdhci_pci_chip *chip);
#endif
int sdhci_pci_enable_dma(struct sdhci_host *host);
int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot);
int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip);
#ifdef CONFIG_PM_SLEEP
int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip);
#endif
extern const struct sdhci_pci_fixes sdhci_arasan;
extern const struct sdhci_pci_fixes sdhci_snps;
extern const struct sdhci_pci_fixes sdhci_o2;
#endif /* __SDHCI_PCI_H */

View File

@ -23,7 +23,6 @@
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/platform_data/pxa_sdhci.h>

View File

@ -33,6 +33,7 @@
#include <linux/ktime.h>
#include "sdhci-pltfm.h"
#include "cqhci.h"
/* Tegra SDHOST controller vendor register definitions */
#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100
@ -75,6 +76,7 @@
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK 0x0000000f
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL 0x7
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD BIT(31)
#define SDHCI_COMP_PADCTRL_DRVUPDN_OFFSET_MASK 0x07FFF000
#define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec
#define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)
@ -89,6 +91,9 @@
#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7)
#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8)
/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */
#define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000
struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
u32 nvquirks;
@ -121,6 +126,8 @@ struct sdhci_tegra {
struct pinctrl *pinctrl_sdmmc;
struct pinctrl_state *pinctrl_state_3v3;
struct pinctrl_state *pinctrl_state_1v8;
struct pinctrl_state *pinctrl_state_3v3_drv;
struct pinctrl_state *pinctrl_state_1v8_drv;
struct sdhci_tegra_autocal_offsets autocal_offsets;
ktime_t last_calib;
@ -128,6 +135,7 @@ struct sdhci_tegra {
u32 default_tap;
u32 default_trim;
u32 dqs_trim;
bool enable_hwcq;
};
static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@ -237,11 +245,6 @@ static void tegra210_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
}
}
static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
{
return mmc_gpio_get_ro(host->mmc);
}
static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -411,6 +414,76 @@ static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,
sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
}
static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage,
bool state_drvupdn)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
struct sdhci_tegra_autocal_offsets *offsets =
&tegra_host->autocal_offsets;
struct pinctrl_state *pinctrl_drvupdn = NULL;
int ret = 0;
u8 drvup = 0, drvdn = 0;
u32 reg;
if (!state_drvupdn) {
/* PADS Drive Strength */
if (voltage == MMC_SIGNAL_VOLTAGE_180) {
if (tegra_host->pinctrl_state_1v8_drv) {
pinctrl_drvupdn =
tegra_host->pinctrl_state_1v8_drv;
} else {
drvup = offsets->pull_up_1v8_timeout;
drvdn = offsets->pull_down_1v8_timeout;
}
} else {
if (tegra_host->pinctrl_state_3v3_drv) {
pinctrl_drvupdn =
tegra_host->pinctrl_state_3v3_drv;
} else {
drvup = offsets->pull_up_3v3_timeout;
drvdn = offsets->pull_down_3v3_timeout;
}
}
if (pinctrl_drvupdn != NULL) {
ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
pinctrl_drvupdn);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"failed pads drvupdn, ret: %d\n", ret);
} else if ((drvup) || (drvdn)) {
reg = sdhci_readl(host,
SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
reg &= ~SDHCI_COMP_PADCTRL_DRVUPDN_OFFSET_MASK;
reg |= (drvup << 20) | (drvdn << 12);
sdhci_writel(host, reg,
SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
}
} else {
/* Dual Voltage PADS Voltage selection */
if (!tegra_host->pad_control_available)
return 0;
if (voltage == MMC_SIGNAL_VOLTAGE_180) {
ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
tegra_host->pinctrl_state_1v8);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"setting 1.8V failed, ret: %d\n", ret);
} else {
ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
tegra_host->pinctrl_state_3v3);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"setting 3.3V failed, ret: %d\n", ret);
}
}
return ret;
}
static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -437,6 +510,7 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
pdpu = offsets.pull_down_3v3 << 8 | offsets.pull_up_3v3;
}
/* Set initial offset before auto-calibration */
tegra_sdhci_set_pad_autocal_offset(host, pdpu);
card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
@ -460,19 +534,15 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
if (ret) {
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
pdpu = offsets.pull_down_1v8_timeout << 8 |
offsets.pull_up_1v8_timeout;
else
pdpu = offsets.pull_down_3v3_timeout << 8 |
offsets.pull_up_3v3_timeout;
/* Disable automatic calibration and use fixed offsets */
/* Disable automatic cal and use fixed Drive Strengths */
reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
reg &= ~SDHCI_AUTO_CAL_ENABLE;
sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
tegra_sdhci_set_pad_autocal_offset(host, pdpu);
ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, false);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"Setting drive strengths failed: %d\n", ret);
}
}
@ -511,26 +581,46 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-up-offset-3v3-timeout",
&autocal->pull_up_3v3_timeout);
if (err)
if (err) {
if (!IS_ERR(tegra_host->pinctrl_state_3v3) &&
(tegra_host->pinctrl_state_3v3_drv == NULL))
pr_warn("%s: Missing autocal timeout 3v3-pad drvs\n",
mmc_hostname(host->mmc));
autocal->pull_up_3v3_timeout = 0;
}
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-down-offset-3v3-timeout",
&autocal->pull_down_3v3_timeout);
if (err)
if (err) {
if (!IS_ERR(tegra_host->pinctrl_state_3v3) &&
(tegra_host->pinctrl_state_3v3_drv == NULL))
pr_warn("%s: Missing autocal timeout 3v3-pad drvs\n",
mmc_hostname(host->mmc));
autocal->pull_down_3v3_timeout = 0;
}
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-up-offset-1v8-timeout",
&autocal->pull_up_1v8_timeout);
if (err)
if (err) {
if (!IS_ERR(tegra_host->pinctrl_state_1v8) &&
(tegra_host->pinctrl_state_1v8_drv == NULL))
pr_warn("%s: Missing autocal timeout 1v8-pad drvs\n",
mmc_hostname(host->mmc));
autocal->pull_up_1v8_timeout = 0;
}
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-down-offset-1v8-timeout",
&autocal->pull_down_1v8_timeout);
if (err)
if (err) {
if (!IS_ERR(tegra_host->pinctrl_state_1v8) &&
(tegra_host->pinctrl_state_1v8_drv == NULL))
pr_warn("%s: Missing autocal timeout 1v8-pad drvs\n",
mmc_hostname(host->mmc));
autocal->pull_down_1v8_timeout = 0;
}
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-up-offset-sdr104",
@ -595,6 +685,20 @@ static void tegra_sdhci_parse_tap_and_trim(struct sdhci_host *host)
tegra_host->dqs_trim = 0x11;
}
static void tegra_sdhci_parse_dt(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
if (device_property_read_bool(host->mmc->parent, "supports-cqe"))
tegra_host->enable_hwcq = true;
else
tegra_host->enable_hwcq = false;
tegra_sdhci_parse_pad_autocal_dt(host);
tegra_sdhci_parse_tap_and_trim(host);
}
static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -743,32 +847,6 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
return mmc_send_tuning(host->mmc, opcode, NULL);
}
static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
int ret;
if (!tegra_host->pad_control_available)
return 0;
if (voltage == MMC_SIGNAL_VOLTAGE_180) {
ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
tegra_host->pinctrl_state_1v8);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"setting 1.8V failed, ret: %d\n", ret);
} else {
ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
tegra_host->pinctrl_state_3v3);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"setting 3.3V failed, ret: %d\n", ret);
}
return ret;
}
static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
struct mmc_ios *ios)
{
@ -778,7 +856,7 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
int ret = 0;
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, true);
if (ret < 0)
return ret;
ret = sdhci_start_signal_voltage_switch(mmc, ios);
@ -786,7 +864,7 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
ret = sdhci_start_signal_voltage_switch(mmc, ios);
if (ret < 0)
return ret;
ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, true);
}
if (tegra_host->pad_calib_required)
@ -805,6 +883,20 @@ static int tegra_sdhci_init_pinctrl_info(struct device *dev,
return -1;
}
tegra_host->pinctrl_state_1v8_drv = pinctrl_lookup_state(
tegra_host->pinctrl_sdmmc, "sdmmc-1v8-drv");
if (IS_ERR(tegra_host->pinctrl_state_1v8_drv)) {
if (PTR_ERR(tegra_host->pinctrl_state_1v8_drv) == -ENODEV)
tegra_host->pinctrl_state_1v8_drv = NULL;
}
tegra_host->pinctrl_state_3v3_drv = pinctrl_lookup_state(
tegra_host->pinctrl_sdmmc, "sdmmc-3v3-drv");
if (IS_ERR(tegra_host->pinctrl_state_3v3_drv)) {
if (PTR_ERR(tegra_host->pinctrl_state_3v3_drv) == -ENODEV)
tegra_host->pinctrl_state_3v3_drv = NULL;
}
tegra_host->pinctrl_state_3v3 =
pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-3v3");
if (IS_ERR(tegra_host->pinctrl_state_3v3)) {
@ -836,8 +928,50 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host)
tegra_host->pad_calib_required = true;
}
static void sdhci_tegra_cqe_enable(struct mmc_host *mmc)
{
struct cqhci_host *cq_host = mmc->cqe_private;
u32 cqcfg = 0;
/*
* Tegra SDMMC Controller design prevents write access to BLOCK_COUNT
* registers when CQE is enabled.
*/
cqcfg = cqhci_readl(cq_host, CQHCI_CFG);
if (cqcfg & CQHCI_ENABLE)
cqhci_writel(cq_host, (cqcfg & ~CQHCI_ENABLE), CQHCI_CFG);
sdhci_cqe_enable(mmc);
if (cqcfg & CQHCI_ENABLE)
cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
}
static void sdhci_tegra_dumpregs(struct mmc_host *mmc)
{
sdhci_dumpregs(mmc_priv(mmc));
}
static u32 sdhci_tegra_cqhci_irq(struct sdhci_host *host, u32 intmask)
{
int cmd_error = 0;
int data_error = 0;
if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
return intmask;
cqhci_irq(host->mmc, intmask, cmd_error, data_error);
return 0;
}
static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = {
.enable = sdhci_tegra_cqe_enable,
.disable = sdhci_cqe_disable,
.dumpregs = sdhci_tegra_dumpregs,
};
static const struct sdhci_ops tegra_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
.set_clock = tegra_sdhci_set_clock,
@ -893,7 +1027,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra30 = {
};
static const struct sdhci_ops tegra114_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_w = tegra_sdhci_writew,
.write_l = tegra_sdhci_writel,
@ -947,7 +1080,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 = {
};
static const struct sdhci_ops tegra210_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_w = tegra210_sdhci_writew,
.write_l = tegra_sdhci_writel,
@ -980,7 +1112,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
};
static const struct sdhci_ops tegra186_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
.set_clock = tegra_sdhci_set_clock,
@ -989,6 +1120,7 @@ static const struct sdhci_ops tegra186_sdhci_ops = {
.set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
.voltage_switch = tegra_sdhci_voltage_switch,
.get_max_clock = tegra_sdhci_get_max_clock,
.irq = sdhci_tegra_cqhci_irq,
};
static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
@ -1030,6 +1162,54 @@ static const struct of_device_id sdhci_tegra_dt_match[] = {
};
MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
static int sdhci_tegra_add_host(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
struct cqhci_host *cq_host;
bool dma64;
int ret;
if (!tegra_host->enable_hwcq)
return sdhci_add_host(host);
sdhci_enable_v4_mode(host);
ret = sdhci_setup_host(host);
if (ret)
return ret;
host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
cq_host = devm_kzalloc(host->mmc->parent,
sizeof(*cq_host), GFP_KERNEL);
if (!cq_host) {
ret = -ENOMEM;
goto cleanup;
}
cq_host->mmio = host->ioaddr + SDHCI_TEGRA_CQE_BASE_ADDR;
cq_host->ops = &sdhci_tegra_cqhci_ops;
dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
if (dma64)
cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
ret = cqhci_init(cq_host, host->mmc, dma64);
if (ret)
goto cleanup;
ret = __sdhci_add_host(host);
if (ret)
goto cleanup;
return 0;
cleanup:
sdhci_cleanup_host(host);
return ret;
}
static int sdhci_tegra_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
@ -1077,9 +1257,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
host->mmc->caps |= MMC_CAP_1_8V_DDR;
tegra_sdhci_parse_pad_autocal_dt(host);
tegra_sdhci_parse_tap_and_trim(host);
tegra_sdhci_parse_dt(host);
tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
GPIOD_OUT_HIGH);
@ -1117,7 +1295,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
usleep_range(2000, 4000);
rc = sdhci_add_host(host);
rc = sdhci_tegra_add_host(host);
if (rc)
goto err_add_host;

View File

@ -530,7 +530,7 @@ static bool xenon_emmc_phy_slow_mode(struct sdhci_host *host,
ret = true;
break;
}
/* else: fall through */
/* fall through */
default:
reg &= ~XENON_TIMING_ADJUST_SLOW_MODE;
ret = false;

View File

@ -883,7 +883,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
bool *too_big)
{
u8 count;
struct mmc_data *data = cmd->data;
struct mmc_data *data;
unsigned target_timeout, current_timeout;
*too_big = true;
@ -897,6 +897,11 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
return 0xE;
/* Unspecified command, asume max */
if (cmd == NULL)
return 0xE;
data = cmd->data;
/* Unspecified timeout, assume max */
if (!data && !cmd->busy_timeout)
return 0xE;
@ -2048,6 +2053,8 @@ static int sdhci_check_ro(struct sdhci_host *host)
is_readonly = 0;
else if (host->ops->get_ro)
is_readonly = host->ops->get_ro(host);
else if (mmc_can_gpio_ro(host->mmc))
is_readonly = mmc_gpio_get_ro(host->mmc);
else
is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
& SDHCI_WRITE_PROTECT);
@ -2376,6 +2383,10 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
return -ETIMEDOUT;
}
/* Spec does not require a delay between tuning cycles */
if (host->tuning_delay > 0)
mdelay(host->tuning_delay);
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
if (ctrl & SDHCI_CTRL_TUNED_CLK)
@ -2383,9 +2394,6 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
break;
}
/* Spec does not require a delay between tuning cycles */
if (host->tuning_delay > 0)
mdelay(host->tuning_delay);
}
pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
@ -3353,7 +3361,14 @@ void sdhci_cqe_enable(struct mmc_host *mmc)
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
ctrl &= ~SDHCI_CTRL_DMA_MASK;
if (host->flags & SDHCI_USE_64_BIT_DMA)
/*
* Host from V4.10 supports ADMA3 DMA type.
* ADMA3 performs integrated descriptor which is more suitable
* for cmd queuing to fetch both command and transfer descriptors.
*/
if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3))
ctrl |= SDHCI_CTRL_ADMA3;
else if (host->flags & SDHCI_USE_64_BIT_DMA)
ctrl |= SDHCI_CTRL_ADMA64;
else
ctrl |= SDHCI_CTRL_ADMA32;
@ -3363,7 +3378,7 @@ void sdhci_cqe_enable(struct mmc_host *mmc)
SDHCI_BLOCK_SIZE);
/* Set maximum timeout */
sdhci_writeb(host, 0xE, SDHCI_TIMEOUT_CONTROL);
sdhci_set_timeout(host, NULL);
host->ier = host->cqe_ier;

View File

@ -73,6 +73,10 @@
#define SDHCI_SPACE_AVAILABLE 0x00000400
#define SDHCI_DATA_AVAILABLE 0x00000800
#define SDHCI_CARD_PRESENT 0x00010000
#define SDHCI_CARD_PRES_SHIFT 16
#define SDHCI_CD_STABLE 0x00020000
#define SDHCI_CD_LVL 0x00040000
#define SDHCI_CD_LVL_SHIFT 18
#define SDHCI_WRITE_PROTECT 0x00080000
#define SDHCI_DATA_LVL_MASK 0x00F00000
#define SDHCI_DATA_LVL_SHIFT 20
@ -88,6 +92,7 @@
#define SDHCI_CTRL_ADMA1 0x08
#define SDHCI_CTRL_ADMA32 0x10
#define SDHCI_CTRL_ADMA64 0x18
#define SDHCI_CTRL_ADMA3 0x18
#define SDHCI_CTRL_8BITBUS 0x20
#define SDHCI_CTRL_CDTEST_INS 0x40
#define SDHCI_CTRL_CDTEST_EN 0x80
@ -230,6 +235,7 @@
#define SDHCI_RETUNING_MODE_SHIFT 14
#define SDHCI_CLOCK_MUL_MASK 0x00FF0000
#define SDHCI_CLOCK_MUL_SHIFT 16
#define SDHCI_CAN_DO_ADMA3 0x08000000
#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */
#define SDHCI_CAPABILITIES_1 0x44

View File

@ -158,7 +158,7 @@ static void sdhci_am654_set_power(struct sdhci_host *host, unsigned char mode,
sdhci_set_power_noreg(host, mode, vdd);
}
struct sdhci_ops sdhci_am654_ops = {
static struct sdhci_ops sdhci_am654_ops = {
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
.set_uhs_signaling = sdhci_set_uhs_signaling,

View File

@ -19,7 +19,6 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
@ -32,7 +31,6 @@
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>

View File

@ -1073,7 +1073,7 @@ static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
/* use ocr_mask if no regulator */
if (!mmc->ocr_avail)
mmc->ocr_avail = pdata->ocr_mask;
mmc->ocr_avail = pdata->ocr_mask;
/*
* try again.
@ -1294,6 +1294,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
cancel_delayed_work_sync(&host->delayed_reset_work);
tmio_mmc_release_dma(host);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
}

View File

@ -19,7 +19,6 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/of.h>

View File

@ -133,6 +133,8 @@ struct mmc_ext_csd {
struct sd_scr {
unsigned char sda_vsn;
unsigned char sda_spec3;
unsigned char sda_spec4;
unsigned char sda_specx;
unsigned char bus_widths;
#define SD_SCR_BUS_WIDTH_1 (1<<0)
#define SD_SCR_BUS_WIDTH_4 (1<<2)
@ -277,6 +279,7 @@ struct mmc_card {
unsigned int erase_shift; /* if erase unit is power 2 */
unsigned int pref_erase; /* in sectors */
unsigned int eg_boundary; /* don't cross erase-group boundaries */
unsigned int erase_arg; /* erase / trim / discard */
u8 erased_byte; /* value of erased bytes */
u32 raw_cid[4]; /* raw card CID */

View File

@ -478,6 +478,11 @@ static inline void *mmc_priv(struct mmc_host *host)
return (void *)host->private;
}
static inline struct mmc_host *mmc_from_priv(void *priv)
{
return container_of(priv, struct mmc_host, private);
}
#define mmc_host_is_spi(host) ((host)->caps & MMC_CAP_SPI)
#define mmc_dev(x) ((x)->parent)
@ -502,17 +507,11 @@ void sdio_run_irqs(struct mmc_host *host);
void sdio_signal_irq(struct mmc_host *host);
#ifdef CONFIG_REGULATOR
int mmc_regulator_get_ocrmask(struct regulator *supply);
int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit);
int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios);
#else
static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
{
return 0;
}
static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit)
@ -527,7 +526,6 @@ static inline int mmc_regulator_set_vqmmc(struct mmc_host *mmc,
}
#endif
u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
int mmc_regulator_get_supply(struct mmc_host *mmc);
static inline int mmc_card_is_removable(struct mmc_host *host)

View File

@ -91,4 +91,10 @@
#define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1
/*
* Erase/discard
*/
#define SD_ERASE_ARG 0x00000000
#define SD_DISCARD_ARG 0x00000001
#endif /* LINUX_MMC_SD_H */

View File

@ -22,7 +22,7 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
unsigned int idx, bool override_active_level,
unsigned int debounce, bool *gpio_invert);
int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
unsigned int idx, bool override_active_level,
unsigned int idx,
unsigned int debounce, bool *gpio_invert);
void mmc_gpio_set_cd_isr(struct mmc_host *host,
irqreturn_t (*isr)(int irq, void *dev_id));