Commit 17319295 authored by Linus Torvalds's avatar Linus Torvalds

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

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

  Core:
   - Introduce MMC_CAP2_NO_PRESCAN_POWERUP to allow skipping
     mmc_power_up() at boot/initialization time if it's already
     happened, for performance (faster boot time) reasons.
   - Fix a bit width test failure that resulted in old eMMC cards being
     put into 1-bit mode when 4-bit mode was available.
   - Expose fwrev/hwrev for MMCv4 parts.
   - Improve card removal logic in the case where the card's removed
     slowly; we were missing card removal events if the card retained
     contact with the slot pads for long enough to reply to a CMD13
     while being removed.

  Drivers:
   - davinci_mmc: Support using PIO instead of DMA.
   - dw_mmc: Add support for Exynos4412.
   - mxcmmc: DT support, use slot-gpio API.
   - mxs-mmc: Add broken-cd/cd-inverted/non-removable DT property
     support.
   - sdhci-sirf: New sdhci-pltfm driver for CSR SiRF SoCs:
       SiRFprimaII: unicore ARM Cortex-A9
       SiRFatlas6: unicore ARM Cortex-A9
       SiRFmarco: dual core ARM Cortex-A9 SMP
   - sdhci-tegra: Add support for Tegra114 platforms, use
     mmc_of_parse()"

* tag 'mmc-updates-for-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (66 commits)
  mmc: sdhci-tegra: fix MODULE_DEVICE_TABLE
  mmc: core: fix init controller performance regression, updated patch
  mmc: mxcmmc: enable DMA support on mpc512x
  mmc: mxcmmc: constify mxcmci_devtype
  mmc: mxcmmc: use slot-gpio API for write-protect detection
  mmc: mxcmmc: add mpc512x SDHC support
  mmc: mxcmmc: fix race conditions for host->req and host->data access
  mmc: mxcmmc: DT support
  mmc: dw_mmc: let device core setup the default pin configuration
  mmc: mxs-mmc: add broken-cd property
  mmc: mxs-mmc: add non-removable property
  mmc: mxs-mmc: add cd-inverted property
  mmc: core: call pm_runtime_put_noidle in pm_runtime_get_sync failed case
  mmc: mxcmmc: Fix bug when card is present during boot
  mmc: core: fix performance regression initializing MMC host controllers
  Revert "mmc: core: wait while adding MMC host to ensure root mounts successfully"
  mmc: atmel-mci: pio hang on block errors
  mmc: core: Fix bit width test failing on old eMMC cards
  mmc: dw_mmc: Use pr_info instead of printk
  mmc: dw_mmc: Check return value of regulator_enable
  ...
parents e72a5d1c e4404fab
* Freescale Secure Digital Host Controller for i.MX2/3 series
This file documents differences to the properties defined in mmc.txt.
Required properties:
- compatible : Should be "fsl,<chip>-mmc", chip can be imx21 or imx31
Optional properties:
- dmas: One DMA phandle with arguments as defined by the devicetree bindings
of the used DMA controller.
- dma-names: Has to be "rx-tx".
Example:
sdhci1: sdhci@10014000 {
compatible = "fsl,imx27-mmc", "fsl,imx21-mmc";
reg = <0x10014000 0x1000>;
interrupts = <11>;
dmas = <&dma 7>;
dma-names = "rx-tx";
bus-width = <4>;
cd-gpios = <&gpio3 29>;
status = "okay";
};
......@@ -5,13 +5,6 @@ MMC, SD and eMMC storage mediums. This file documents differences between the
core mmc properties described by mmc.txt and the properties used by the
Samsung implmentation of the SDHCI controller.
Note: The mmc core bindings documentation states that if none of the core
card-detect bindings are used, then the standard sdhci card detect mechanism
is used. The Samsung's SDHCI controller bindings extends this as listed below.
[A] The property "samsung,cd-pinmux-gpio" can be used as stated in the
"Optional Board Specific Properties" section below.
Required SoC Specific Properties:
- compatible: should be one of the following
- "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
......@@ -20,18 +13,8 @@ Required SoC Specific Properties:
controller.
Required Board Specific Properties:
- Samsung GPIO variant (will be completely replaced by pinctrl):
- gpios: Should specify the gpios used for clock, command and data lines. The
gpio specifier format depends on the gpio controller.
- Pinctrl variant (preferred if available):
- pinctrl-0: Should specify pin control groups used for this controller.
- pinctrl-names: Should contain only one value - "default".
Optional Board Specific Properties:
- samsung,cd-pinmux-gpio: Specifies the card detect line that is routed
through a pinmux to the card-detect pin of the card slot. This property
should be used only if none of the mmc core card-detect properties are
used. Only for Samsung GPIO variant.
- pinctrl-0: Should specify pin control groups used for this controller.
- pinctrl-names: Should contain only one value - "default".
Example:
sdhci@12530000 {
......@@ -39,19 +22,9 @@ Example:
reg = <0x12530000 0x100>;
interrupts = <0 75 0>;
bus-width = <4>;
cd-gpios = <&gpk2 2 2 3 3>;
/* Samsung GPIO variant */
gpios = <&gpk2 0 2 0 3>, /* clock line */
<&gpk2 1 2 0 3>, /* command line */
<&gpk2 3 2 3 3>, /* data line 0 */
<&gpk2 4 2 3 3>, /* data line 1 */
<&gpk2 5 2 3 3>, /* data line 2 */
<&gpk2 6 2 3 3>; /* data line 3 */
/* Pinctrl variant */
pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
cd-gpios = <&gpk2 2 0>;
pinctrl-names = "default";
pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
};
Note: This example shows both SoC specific and board specific properties
......
* SiRFprimII/marco/atlas6 SDHCI Controller
This file documents differences between the core properties in mmc.txt
and the properties used by the sdhci-sirf driver.
Required properties:
- compatible: sirf,prima2-sdhc
Optional properties:
- cd-gpios: card detect gpio, with zero flags.
Example:
sd0: sdhci@56000000 {
compatible = "sirf,prima2-sdhc";
reg = <0xcd000000 0x100000>;
cd-gpios = <&gpio 6 0>;
};
......@@ -22,6 +22,7 @@ All attributes are read-only.
manfid Manufacturer ID (from CID Register)
name Product Name (from CID Register)
oemid OEM/Application ID (from CID Register)
prv Product Revision (from CID Register) (SD and MMCv4 only)
serial Product Serial Number (from CID Register)
erase_size Erase group size
preferred_erase_size Preferred erase size
......
......@@ -801,6 +801,7 @@ S: Maintained
F: arch/arm/mach-prima2/
F: drivers/dma/sirf-dma.c
F: drivers/i2c/busses/i2c-sirf.c
F: drivers/mmc/host/sdhci-sirf.c
F: drivers/pinctrl/pinctrl-sirf.c
F: drivers/spi/spi-sirf.c
......
......@@ -173,7 +173,6 @@ CONFIG_MMC=y
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_SDIO_UART=m
CONFIG_MMC_ATMELMCI=y
CONFIG_MMC_ATMELMCI_DMA=y
CONFIG_LEDS_ATMEL_PWM=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGER_TIMER=y
......
......@@ -122,7 +122,6 @@ CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y
CONFIG_MMC_ATMELMCI_DMA=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_ATMEL_PWM=m
......
......@@ -102,7 +102,6 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y
CONFIG_MMC_ATMELMCI_DMA=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_ATMEL_PWM=y
......
......@@ -152,6 +152,8 @@ sdhc@1500 {
compatible = "fsl,mpc5121-sdhc";
reg = <0x1500 0x100>;
interrupts = <8 0x8>;
dmas = <&dma0 30>;
dma-names = "rx-tx";
};
i2c@1700 {
......
......@@ -1932,8 +1932,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
}
out:
if (!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST))
/* release host only when there are no more requests */
if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
(req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK)))
/*
* Release host when there are no more requests
* and after special request(discard, flush) is done.
* In case sepecial request, there is no reentry to
* the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
*/
mmc_release_host(card->host);
return ret;
}
......
......@@ -22,9 +22,6 @@
#define MMC_QUEUE_BOUNCESZ 65536
#define MMC_REQ_SPECIAL_MASK (REQ_DISCARD | REQ_FLUSH)
/*
* Prepare a MMC request. This just filters out odd stuff.
*/
......
#ifndef MMC_QUEUE_H
#define MMC_QUEUE_H
#define MMC_REQ_SPECIAL_MASK (REQ_DISCARD | REQ_FLUSH)
struct request;
struct task_struct;
......
......@@ -2289,6 +2289,19 @@ int _mmc_detect_card_removed(struct mmc_host *host)
return 1;
ret = host->bus_ops->alive(host);
/*
* Card detect status and alive check may be out of sync if card is
* removed slowly, when card detect switch changes while card/slot
* pads are still contacted in hardware (refer to "SD Card Mechanical
* Addendum, Appendix C: Card Detection Switch"). So reschedule a
* detect work 200ms later for this case.
*/
if (!ret && host->ops->get_cd && !host->ops->get_cd(host)) {
mmc_detect_change(host, msecs_to_jiffies(200));
pr_debug("%s: card removed too slowly\n", mmc_hostname(host));
}
if (ret) {
mmc_card_set_removed(host->card);
pr_debug("%s: card remove detected\n", mmc_hostname(host));
......@@ -2403,7 +2416,10 @@ void mmc_start_host(struct mmc_host *host)
{
host->f_init = max(freqs[0], host->f_min);
host->rescan_disable = 0;
mmc_power_up(host);
if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)
mmc_power_off(host);
else
mmc_power_up(host);
mmc_detect_change(host, 0);
}
......
......@@ -96,6 +96,7 @@ static int mmc_decode_cid(struct mmc_card *card)
card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
card->cid.prv = UNSTUFF_BITS(resp, 48, 8);
card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
card->cid.month = UNSTUFF_BITS(resp, 12, 4);
card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
......@@ -368,13 +369,13 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
card->ext_csd.raw_trim_mult =
ext_csd[EXT_CSD_TRIM_MULT];
card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
if (card->ext_csd.rev >= 4) {
/*
* Enhanced area feature support -- check whether the eMMC
* card has the Enhanced area enabled. If so, export enhanced
* area offset and size to user by adding sysfs interface.
*/
card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
hc_erase_grp_sz =
......@@ -627,6 +628,7 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv);
MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
card->ext_csd.enhanced_area_offset);
......@@ -645,6 +647,7 @@ static struct attribute *mmc_std_attrs[] = {
&dev_attr_manfid.attr,
&dev_attr_name.attr,
&dev_attr_oemid.attr,
&dev_attr_prv.attr,
&dev_attr_serial.attr,
&dev_attr_enhanced_area_offset.attr,
&dev_attr_enhanced_area_size.attr,
......
......@@ -861,8 +861,10 @@ static void mmc_sdio_detect(struct mmc_host *host)
/* Make sure card is powered before detecting it */
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
err = pm_runtime_get_sync(&host->card->dev);
if (err < 0)
if (err < 0) {
pm_runtime_put_noidle(&host->card->dev);
goto out;
}
}
mmc_claim_host(host);
......
......@@ -16,6 +16,7 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/acpi.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
......@@ -137,7 +138,7 @@ static int sdio_bus_probe(struct device *dev)
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto out;
goto disable_runtimepm;
}
/* Set the default block size so the driver is sure it's something
......@@ -157,7 +158,6 @@ static int sdio_bus_probe(struct device *dev)
disable_runtimepm:
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_noidle(dev);
out:
return ret;
}
......@@ -299,6 +299,19 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
return func;
}
#ifdef CONFIG_ACPI
static void sdio_acpi_set_handle(struct sdio_func *func)
{
struct mmc_host *host = func->card->host;
u64 addr = (host->slotno << 16) | func->num;
ACPI_HANDLE_SET(&func->dev,
acpi_get_child(ACPI_HANDLE(host->parent), addr));
}
#else
static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
#endif
/*
* Register a new SDIO function with the driver model.
*/
......@@ -308,9 +321,12 @@ int sdio_add_func(struct sdio_func *func)
dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
sdio_acpi_set_handle(func);
ret = device_add(&func->dev);
if (ret == 0)
if (ret == 0) {
sdio_func_set_present(func);
acpi_dev_pm_attach(&func->dev, false);
}
return ret;
}
......@@ -326,6 +342,7 @@ void sdio_remove_func(struct sdio_func *func)
if (!sdio_func_present(func))
return;
acpi_dev_pm_detach(&func->dev, false);
device_del(&func->dev);
put_device(&func->dev);
}
......
......@@ -190,6 +190,17 @@ config MMC_SDHCI_S3C
If unsure, say N.
config MMC_SDHCI_SIRF
tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
depends on ARCH_SIRF
depends on MMC_SDHCI_PLTFM
help
This selects the SDHCI support for SiRF System-on-Chip devices.
If you have a controller with this interface, say Y or M here.
If unsure, say N.
config MMC_SDHCI_PXAV3
tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
depends on CLKDEV_LOOKUP
......@@ -300,16 +311,6 @@ config MMC_ATMELMCI
If unsure, say N.
config MMC_ATMELMCI_DMA
bool "Atmel MCI DMA support"
depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE
help
Say Y here to have the Atmel MCI driver use a DMA engine to
do data transfers and thus increase the throughput and
reduce the CPU utilization.
If unsure, say N.
config MMC_MSM
tristate "Qualcomm SDCC Controller Support"
depends on MMC && ARCH_MSM
......@@ -319,12 +320,12 @@ config MMC_MSM
support for SDIO devices.
config MMC_MXC
tristate "Freescale i.MX21/27/31 Multimedia Card Interface support"
depends on ARCH_MXC
tristate "Freescale i.MX21/27/31 or MPC512x Multimedia Card support"
depends on ARCH_MXC || PPC_MPC512x
help
This selects the Freescale i.MX21, i.MX27 and i.MX31 Multimedia card
Interface. If you have a i.MX platform with a Multimedia Card slot,
say Y or M here.
This selects the Freescale i.MX21, i.MX27, i.MX31 or MPC512x
Multimedia Card Interface. If you have an i.MX or MPC512x platform
with a Multimedia Card slot, say Y or M here.
If unsure, say N.
......
......@@ -13,6 +13,7 @@ obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o
obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
......
......@@ -476,7 +476,7 @@ static int goldfish_mmc_probe(struct platform_device *pdev)
host->mmc = mmc;
pr_err("mmc: Mapping %lX to %lX\n", (long)res->start, (long)res->end);
host->reg_base = ioremap(res->start, res->end - res->start + 1);
host->reg_base = ioremap(res->start, resource_size(res));
if (host->reg_base == NULL) {
ret = -ENOMEM;
goto ioremap_failed;
......
......@@ -178,6 +178,7 @@ struct atmel_mci {
void __iomem *regs;
struct scatterlist *sg;
unsigned int sg_len;
unsigned int pio_offset;
unsigned int *buffer;
unsigned int buf_size;
......@@ -892,6 +893,7 @@ static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data)
data->error = -EINPROGRESS;
host->sg = data->sg;
host->sg_len = data->sg_len;
host->data = data;
host->data_chan = NULL;
......@@ -1826,7 +1828,8 @@ static void atmci_read_data_pio(struct atmel_mci *host)
if (offset == sg->length) {
flush_dcache_page(sg_page(sg));
host->sg = sg = sg_next(sg);
if (!sg)
host->sg_len--;
if (!sg || !host->sg_len)
goto done;
offset = 0;
......@@ -1839,7 +1842,8 @@ static void atmci_read_data_pio(struct atmel_mci *host)
flush_dcache_page(sg_page(sg));
host->sg = sg = sg_next(sg);
if (!sg)
host->sg_len--;
if (!sg || !host->sg_len)
goto done;
offset = 4 - remaining;
......@@ -1890,7 +1894,8 @@ static void atmci_write_data_pio(struct atmel_mci *host)
nbytes += 4;
if (offset == sg->length) {
host->sg = sg = sg_next(sg);
if (!sg)
host->sg_len--;
if (!sg || !host->sg_len)
goto done;
offset = 0;
......@@ -1904,7 +1909,8 @@ static void atmci_write_data_pio(struct atmel_mci *host)
nbytes += remaining;
host->sg = sg = sg_next(sg);
if (!sg) {
host->sg_len--;
if (!sg || !host->sg_len) {
atmci_writel(host, ATMCI_TDR, value);
goto done;
}
......@@ -2487,10 +2493,8 @@ static int __exit atmci_remove(struct platform_device *pdev)
atmci_readl(host, ATMCI_SR);
clk_disable(host->mck);
#ifdef CONFIG_MMC_ATMELMCI_DMA
if (host->dma.chan)
dma_release_channel(host->dma.chan);
#endif
free_irq(platform_get_irq(pdev, 0), host);
iounmap(host->regs);
......
......@@ -1264,13 +1264,15 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!r)
goto out;
host->rxdma = r->start;
dev_warn(&pdev->dev, "RX DMA resource not specified\n");
else
host->rxdma = r->start;
r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (!r)
goto out;
host->txdma = r->start;
dev_warn(&pdev->dev, "TX DMA resource not specified\n");
else
host->txdma = r->start;
host->mem_res = mem;
host->base = ioremap(mem->start, mem_size);
......@@ -1488,18 +1490,7 @@ static struct platform_driver davinci_mmcsd_driver = {
.id_table = davinci_mmc_devtype,
};
static int __init davinci_mmcsd_init(void)
{
return platform_driver_probe(&davinci_mmcsd_driver,
davinci_mmcsd_probe);
}
module_init(davinci_mmcsd_init);
static void __exit davinci_mmcsd_exit(void)
{
platform_driver_unregister(&davinci_mmcsd_driver);
}
module_exit(davinci_mmcsd_exit);
module_platform_driver_probe(davinci_mmcsd_driver, davinci_mmcsd_probe);
MODULE_AUTHOR("Texas Instruments India");
MODULE_LICENSE("GPL");
......
......@@ -152,45 +152,8 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
return 0;
}
static int dw_mci_exynos_setup_bus(struct dw_mci *host,
struct device_node *slot_np, u8 bus_width)
{
int idx, gpio, ret;
if (!slot_np)
return -EINVAL;
/* cmd + clock + bus-width pins */
for (idx = 0; idx < NUM_PINS(bus_width); idx++) {
gpio = of_get_gpio(slot_np, idx);
if (!gpio_is_valid(gpio)) {
dev_err(host->dev, "invalid gpio: %d\n", gpio);
return -EINVAL;
}
ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus");
if (ret) {
dev_err(host->dev, "gpio [%d] request failed\n", gpio);
return -EBUSY;
}
}
if (host->pdata->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
return 0;
gpio = of_get_named_gpio(slot_np, "samsung,cd-pinmux-gpio", 0);
if (gpio_is_valid(gpio)) {
if (devm_gpio_request(host->dev, gpio, "dw-mci-cd"))
dev_err(host->dev, "gpio [%d] request failed\n", gpio);
} else {
dev_info(host->dev, "cd gpio not available");
}
return 0;
}
/* Exynos5250 controller specific capabilities */
static unsigned long exynos5250_dwmmc_caps[4] = {
/* Common capabilities of Exynos4/Exynos5 SoC */
static unsigned long exynos_dwmmc_caps[4] = {
MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR |
MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
MMC_CAP_CMD23,
......@@ -198,24 +161,25 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
MMC_CAP_CMD23,
};
static const struct dw_mci_drv_data exynos5250_drv_data = {
.caps = exynos5250_dwmmc_caps,
static const struct dw_mci_drv_data exynos_drv_data = {
.caps = exynos_dwmmc_caps,
.init = dw_mci_exynos_priv_init,
.setup_clock = dw_mci_exynos_setup_clock,
.prepare_command = dw_mci_exynos_prepare_command,
.set_ios = dw_mci_exynos_set_ios,
.parse_dt = dw_mci_exynos_parse_dt,
.setup_bus = dw_mci_exynos_setup_bus,
};
static const struct of_device_id dw_mci_exynos_match[] = {
{ .compatible = "samsung,exynos4412-dw-mshc",
.data = &exynos_drv_data, },
{ .compatible = "samsung,exynos5250-dw-mshc",
.data = &exynos5250_drv_data, },
.data = &exynos_drv_data, },
{},
};
MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
int dw_mci_exynos_probe(struct platform_device *pdev)
static int dw_mci_exynos_probe(struct platform_device *pdev)
{
const struct dw_mci_drv_data *drv_data;
const struct of_device_id *match;
......@@ -230,7 +194,7 @@ static struct platform_driver dw_mci_exynos_pltfm_driver = {
.remove = __exit_p(dw_mci_pltfm_remove),
.driver = {
.name = "dwmmc_exynos",
.of_match_table = of_match_ptr(dw_mci_exynos_match),
.of_match_table = dw_mci_exynos_match,
.pm = &dw_mci_pltfm_pmops,
},
};
......
This diff is collapsed.
......@@ -190,7 +190,6 @@ extern int dw_mci_resume(struct dw_mci *host);
* @prepare_command: handle CMD register extensions.
* @set_ios: handle bus specific extensions.
* @parse_dt: parse implementation specific device tree properties.
* @setup_bus: initialize io-interface
*
* Provide controller implementation specific extensions. The usage of this
* data structure is fully optional and usage of each member in this structure
......@@ -203,7 +202,5 @@ struct dw_mci_drv_data {
void (*prepare_command)(struct dw_mci *host, u32 *cmdr);
void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
int (*parse_dt)(struct dw_mci *host);
int (*setup_bus)(struct dw_mci *host,
struct device_node *slot_np, u8 bus_width);
};
#endif /* _DW_MMC_H_ */
......@@ -119,10 +119,8 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)
host->pio_size = data->blocks * data->blksz;
host->pio_ptr = sg_virt(data->sg);
if (!nodma)
pr_debug("%s: fallback to PIO for data "
"at 0x%p size %d\n",
mmc_hostname(host->mmc),
host->pio_ptr, host->pio_size);
dev_dbg(host->dev, "fallback to PIO for data at 0x%p size %d\n",
host->pio_ptr, host->pio_size);
return 1;
} else {
dma_addr_t phys_addr;
......@@ -473,8 +471,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
if (mrq->data)
err_status = mvsd_finish_data(host, mrq->data, err_status);
if (err_status) {
pr_err("%s: unhandled error status %#04x\n",
mmc_hostname(host->mmc), err_status);
dev_err(host->dev, "unhandled error status %#04x\n",
err_status);
cmd->error = -ENOMSG;
}
......@@ -491,9 +489,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
if (irq_handled)
return IRQ_HANDLED;
pr_err("%s: unhandled interrupt status=0x%04x en=0x%04x "
"pio=%d\n", mmc_hostname(host->mmc), intr_status,
host->intr_en, host->pio_size);
dev_err(host->dev, "unhandled interrupt status=0x%04x en=0x%04x pio=%d\n",
intr_status, host->intr_en, host->pio_size);
return IRQ_NONE;
}
......@@ -507,13 +504,11 @@ static void mvsd_timeout_timer(unsigned long data)
spin_lock_irqsave(&host->lock, flags);
mrq = host->mrq;
if (mrq) {
pr_err("%s: Timeout waiting for hardware interrupt.\n",
mmc_hostname(host->mmc));
pr_err("%s: hw_state=0x%04x, intr_status=0x%04x "
"intr_en=0x%04x\n", mmc_hostname(host->mmc),
mvsd_read(MVSD_HW_STATE),
mvsd_read(MVSD_NOR_INTR_STATUS),
mvsd_read(MVSD_NOR_INTR_EN));
dev_err(host->dev, "Timeout waiting for hardware interrupt.\n");
dev_err(host->dev, "hw_state=0x%04x, intr_status=0x%04x intr_en=0x%04x\n",
mvsd_read(MVSD_HW_STATE),
mvsd_read(MVSD_NOR_INTR_STATUS),
mvsd_read(MVSD_NOR_INTR_EN));
host->mrq = NULL;
......@@ -741,8 +736,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
goto out;
}
host->base_clock = mvsd_data->clock / 2;
gpio_card_detect = mvsd_data->gpio_card_detect;
gpio_write_protect = mvsd_data->gpio_write_protect;
gpio_card_detect = mvsd_data->gpio_card_detect ? : -EINVAL;
gpio_write_protect = mvsd_data->gpio_write_protect ? : -EINVAL;
}
mmc->ops = &mvsd_ops;
......@@ -778,7 +773,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host);
if (ret) {
pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq);
dev_err(&pdev->dev, "cannot assign irq %d\n", irq);
goto out;
}
......@@ -797,13 +792,11 @@ static int __init mvsd_probe(struct platform_device *pdev)
if (ret)
goto out;
pr_notice("%s: %s driver initialized, ",
mmc_hostname(mmc), DRIVER_NAME);
if (!(mmc->caps & MMC_CAP_NEEDS_POLL))
printk("using GPIO %d for card detection\n",
gpio_card_detect);
dev_notice(&pdev->dev, "using GPIO %d for card detection\n",
gpio_card_detect);
else
printk("lacking card detect (fall back to polling)\n");
dev_notice(&pdev->dev, "lacking card detect (fall back to polling)\n");
return 0;
out:
......@@ -881,18 +874,7 @@ static struct platform_driver mvsd_driver = {
},
};
static int __init mvsd_init(void)
{
return platform_driver_probe(&mvsd_driver, mvsd_probe);
}
static void __exit mvsd_exit(void)
{
platform_driver_unregister(&mvsd_driver);
}
module_init(mvsd_init);
module_exit(mvsd_exit);
module_platform_driver_probe(mvsd_driver, mvsd_probe);
/* maximum card clock frequency (default 50MHz) */
module_param(maxfreq, int, 0);
......
This diff is collapsed.
......@@ -72,6 +72,9 @@ struct mxs_mmc_host {
int sdio_irq_en;
int wp_gpio;
bool wp_inverted;
bool cd_inverted;
bool broken_cd;
bool non_removable;
};
static int mxs_mmc_get_ro(struct mmc_host *mmc)
......@@ -95,8 +98,9 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc)
struct mxs_mmc_host *host = mmc_priv(mmc);
struct mxs_ssp *ssp = &host->ssp;
return !(readl(ssp->base + HW_SSP_STATUS(ssp)) &
BM_SSP_STATUS_CARD_DETECT);
return host->non_removable || host->broken_cd ||
!(readl(ssp->base + HW_SSP_STATUS(ssp)) &
BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted;
}
static void mxs_mmc_reset(struct mxs_mmc_host *host)
......@@ -686,11 +690,16 @@ static int mxs_mmc_probe(struct platform_device *pdev)
mmc->caps |= MMC_CAP_4_BIT_DATA;
else if (bus_width == 8)
mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
host->broken_cd = of_property_read_bool(np, "broken-cd");
host->non_removable = of_property_read_bool(np, "non-removable");
if (host->non_removable)
mmc->caps |= MMC_CAP_NONREMOVABLE;
host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags);
if (flags & OF_GPIO_ACTIVE_LOW)
host->wp_inverted = 1;
host->cd_inverted = of_property_read_bool(np, "cd-inverted");
mmc->f_min = 400000;
mmc->f_max = 288000000;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
......
......@@ -1717,6 +1717,12 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
struct omap_mmc_platform_data *pdata;
struct device_node *np = dev->of_node;
u32 bus_width, max_freq;
int cd_gpio, wp_gpio;
cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
if (cd_gpio == -EPROBE_DEFER || wp_gpio == -EPROBE_DEFER)
return ERR_PTR(-EPROBE_DEFER);
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
......@@ -1727,8 +1733,8 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
/* This driver only supports 1 slot */
pdata->nr_slots = 1;
pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0);
pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
pdata->slots[0].switch_pin = cd_gpio;
pdata->slots[0].gpio_wp = wp_gpio;
if (of_find_property(np, "ti,non-removable", NULL)) {
pdata->slots[0].nonremovable = true;
......@@ -1774,6 +1780,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
if (match) {
pdata = of_get_hsmmc_pdata(&pdev->dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
if (match->data) {
const u16 *offsetp = match->data;
pdata->reg_offset = *offsetp;
......
......@@ -57,6 +57,9 @@ struct realtek_pci_sdmmc {
bool eject;
bool initial_mode;
bool ddr_mode;
int power_state;
#define SDMMC_POWER_ON 1
#define SDMMC_POWER_OFF 0
};
static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
......@@ -765,6 +768,9 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
struct rtsx_pcr *pcr = host->pcr;
int err;
if (host->power_state == SDMMC_POWER_ON)
return 0;
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
......@@ -787,6 +793,7 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
if (err < 0)
return err;
host->power_state = SDMMC_POWER_ON;
return 0;
}
......@@ -795,6 +802,8 @@ static int sd_power_off(struct realtek_pci_sdmmc *host)
struct rtsx_pcr *pcr = host->pcr;
int err;
host->power_state = SDMMC_POWER_OFF;
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0);
......@@ -1260,6 +1269,7 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
host->pcr = pcr;
host->mmc = mmc;
host->pdev = pdev;
host->power_state = SDMMC_POWER_OFF;
platform_set_drvdata(pdev, host);
pcr->slots[RTSX_SD_CARD].p_dev = pdev;
pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
......
......@@ -195,6 +195,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
host->mmc->pm_caps |= c->slot->pm_caps;
}
host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
err = sdhci_add_host(host);
if (err)
goto err_free;
......
......@@ -124,7 +124,7 @@ unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
return MIN_FREQ;
}
static struct sdhci_ops bcm2835_sdhci_ops = {
static const struct sdhci_ops bcm2835_sdhci_ops = {
.write_l = bcm2835_sdhci_writel,
.write_w = bcm2835_sdhci_writew,
.write_b = bcm2835_sdhci_writeb,
......@@ -135,7 +135,7 @@ static struct sdhci_ops bcm2835_sdhci_ops = {
.get_min_clock = bcm2835_sdhci_get_min_clock,
};
static struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
.ops = &bcm2835_sdhci_ops,
......
......@@ -79,12 +79,12 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
host->clock = clock;
}
static struct sdhci_ops sdhci_cns3xxx_ops = {
static const struct sdhci_ops sdhci_cns3xxx_ops = {
.get_max_clock = sdhci_cns3xxx_get_max_clk,
.set_clock = sdhci_cns3xxx_set_clock,
};
static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
.ops = &sdhci_cns3xxx_ops,
.quirks = SDHCI_QUIRK_BROKEN_DMA |
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
......
......@@ -83,12 +83,12 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
return ret;
}
static struct sdhci_ops sdhci_dove_ops = {
static const struct sdhci_ops sdhci_dove_ops = {
.read_w = sdhci_dove_readw,
.read_l = sdhci_dove_readl,
};
static struct sdhci_pltfm_data sdhci_dove_pdata = {
static const struct sdhci_pltfm_data sdhci_dove_pdata = {
.ops = &sdhci_dove_ops,
.quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
SDHCI_QUIRK_NO_BUSY_IRQ |
......
......@@ -399,7 +399,7 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
return 0;
}
static struct sdhci_ops sdhci_esdhc_ops = {
static const struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
.write_l = esdhc_writel_le,
......@@ -412,7 +412,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.platform_bus_width = esdhc_pltfm_bus_width,
};
static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT
| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
| SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC
......
......@@ -230,7 +230,7 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
}
static struct sdhci_ops sdhci_esdhc_ops = {
static const struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl,
.read_w = esdhc_readw,
.read_b = esdhc_readb,
......@@ -249,7 +249,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.adma_workaround = esdhci_of_adma_workaround,
};
static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
/*
* card detection could be handled via GPIO
* eSDHC cannot support End Attribute in NOP ADMA descriptor
......
......@@ -51,7 +51,7 @@ static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg)
udelay(SDHCI_HLWD_WRITE_DELAY);
}
static struct sdhci_ops sdhci_hlwd_ops = {
static const struct sdhci_ops sdhci_hlwd_ops = {
.read_l = sdhci_be32bs_readl,
.read_w = sdhci_be32bs_readw,
.read_b = sdhci_be32bs_readb,
......@@ -60,7 +60,7 @@ static struct sdhci_ops sdhci_hlwd_ops = {
.write_b = sdhci_hlwd_writeb,
};
static struct sdhci_pltfm_data sdhci_hlwd_pdata = {
static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_32BIT_DMA_SIZE,
.ops = &sdhci_hlwd_ops,
......
......@@ -975,7 +975,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
usleep_range(300, 1000);
}
static struct sdhci_ops sdhci_pci_ops = {
static const struct sdhci_ops sdhci_pci_ops = {
.enable_dma = sdhci_pci_enable_dma,
.platform_bus_width = sdhci_pci_bus_width,
.hw_reset = sdhci_pci_hw_reset,
......@@ -1279,6 +1279,8 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
}
host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
host->mmc->slotno = slotno;
host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
ret = sdhci_add_host(host);
if (ret)
......
......@@ -44,7 +44,7 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host)
}
EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
static struct sdhci_ops sdhci_pltfm_ops = {
static const struct sdhci_ops sdhci_pltfm_ops = {
};
#ifdef CONFIG_OF
......@@ -94,6 +94,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
if (of_device_is_compatible(np, "fsl,p2020-esdhc") ||
of_device_is_compatible(np, "fsl,p1010-esdhc") ||
of_device_is_compatible(np, "fsl,t4240-esdhc") ||
of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
......@@ -114,7 +115,7 @@ void sdhci_get_of_property(struct platform_device *pdev) {}
EXPORT_SYMBOL_GPL(sdhci_get_of_property);
struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
struct sdhci_pltfm_data *pdata)
const struct sdhci_pltfm_data *pdata)
{
struct sdhci_host *host;
struct sdhci_pltfm_host *pltfm_host;
......@@ -201,7 +202,7 @@ void sdhci_pltfm_free(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(sdhci_pltfm_free);
int sdhci_pltfm_register(struct platform_device *pdev,
struct sdhci_pltfm_data *pdata)
const struct sdhci_pltfm_data *pdata)
{
struct sdhci_host *host;
int ret = 0;
......
......@@ -16,7 +16,7 @@
#include "sdhci.h"
struct sdhci_pltfm_data {
struct sdhci_ops *ops;
const struct sdhci_ops *ops;
unsigned int quirks;
};
......@@ -91,11 +91,11 @@ static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
extern void sdhci_get_of_property(struct platform_device *pdev);
extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
struct sdhci_pltfm_data *pdata);
const struct sdhci_pltfm_data *pdata);
extern void sdhci_pltfm_free(struct platform_device *pdev);
extern int sdhci_pltfm_register(struct platform_device *pdev,
struct sdhci_pltfm_data *pdata);
const struct sdhci_pltfm_data *pdata);
extern int sdhci_pltfm_unregister(struct platform_device *pdev);
extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
......
......@@ -111,7 +111,7 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
return 0;
}
static struct sdhci_ops pxav2_sdhci_ops = {
static const struct sdhci_ops pxav2_sdhci_ops = {
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.platform_reset_exit = pxav2_set_private_registers,
.platform_bus_width = pxav2_mmc_set_width,
......
......@@ -167,13 +167,21 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
return 0;
}
static struct sdhci_ops pxav3_sdhci_ops = {
static const struct sdhci_ops pxav3_sdhci_ops = {
.platform_reset_exit = pxav3_set_private_registers,
.set_uhs_signaling = pxav3_set_uhs_signaling,
.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
};
static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
| SDHCI_QUIRK_32BIT_ADMA_SIZE
| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.ops = &pxav3_sdhci_ops,
};
#ifdef CONFIG_OF
static const struct of_device_id sdhci_pxav3_of_match[] = {
{
......@@ -187,29 +195,16 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
{
struct sdhci_pxa_platdata *pdata;
struct device_node *np = dev->of_node;
u32 bus_width;
u32 clk_delay_cycles;
enum of_gpio_flags gpio_flags;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
if (of_find_property(np, "non-removable", NULL))
pdata->flags |= PXA_FLAG_CARD_PERMANENT;
of_property_read_u32(np, "bus-width", &bus_width);
if (bus_width == 8)
pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT;
of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
if (clk_delay_cycles > 0)
pdata->clk_delay_cycles = clk_delay_cycles;
pdata->ext_cd_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &gpio_flags);
if (gpio_flags != OF_GPIO_ACTIVE_LOW)
pdata->host_caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
return pdata;
}
#else
......@@ -235,7 +230,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
if (!pxa)
return -ENOMEM;
host = sdhci_pltfm_init(pdev, NULL);
host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata);
if (IS_ERR(host)) {
kfree(pxa);
return PTR_ERR(host);
......@@ -252,24 +247,18 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
pltfm_host->clk = clk;
clk_prepare_enable(clk);
host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
| SDHCI_QUIRK_32BIT_ADMA_SIZE
| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
/* enable 1/8V DDR capable */
host->mmc->caps |= MMC_CAP_1_8V_DDR;
match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev);
if (match)
if (match) {
mmc_of_parse(host->mmc);
sdhci_get_of_property(pdev);
pdata = pxav3_get_mmc_pdata(dev);
if (pdata) {
if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
/* on-chip device */
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
} else if (pdata) {
/* on-chip device */
if (pdata->flags & PXA_FLAG_CARD_PERMANENT)
host->mmc->caps |= MMC_CAP_NONREMOVABLE;
}
/* If slot design supports 8 bit data, indicate this to MMC. */
if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
......@@ -296,10 +285,6 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
}
}
host->ops = &pxav3_sdhci_ops;
sdhci_get_of_property(pdev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS);
......@@ -317,7 +302,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
if (pdata->pm_caps & MMC_PM_KEEP_POWER) {
if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) {
device_init_wakeup(&pdev->dev, 1);
host->mmc->pm_flags |= MMC_PM_WAKE_SDIO_IRQ;
} else {
......
......@@ -25,7 +25,6 @@
#include <linux/of_gpio.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>
#include <linux/mmc/host.h>
......@@ -44,7 +43,6 @@
* @ioarea: The resource created when we claimed the IO area.
* @pdata: The platform data for this controller.
* @cur_clk: The index of the current bus clock.
* @gpios: List of gpio numbers parsed from device tree.
* @clk_io: The clock for the internal bus interface.
* @clk_bus: The clocks that are available for the SD/MMC bus clock.
*/
......@@ -56,8 +54,6 @@ struct sdhci_s3c {
unsigned int cur_clk;
int ext_cd_irq;
int ext_cd_gpio;
int *gpios;
struct pinctrl *pctrl;
struct clk *clk_io;
struct clk *clk_bus[MAX_BUS_CLK];
......@@ -446,88 +442,39 @@ static int sdhci_s3c_parse_dt(struct device *dev,
struct device_node *node = dev->of_node;
struct sdhci_s3c *ourhost = to_s3c(host);
u32 max_width;
int gpio, cnt, ret;
int gpio;
/* if the bus-width property is not specified, assume width as 1 */
if (of_property_read_u32(node, "bus-width", &max_width))
max_width = 1;
pdata->max_width = max_width;
ourhost->gpios = devm_kzalloc(dev, NUM_GPIOS(pdata->max_width) *
sizeof(int), GFP_KERNEL);
if (!ourhost->gpios)
return -ENOMEM;
/* get the card detection method */
if (of_get_property(node, "broken-cd", NULL)) {
pdata->cd_type = S3C_SDHCI_CD_NONE;
goto setup_bus;
return 0;
}
if (of_get_property(node, "non-removable", NULL)) {
pdata->cd_type = S3C_SDHCI_CD_PERMANENT;
goto setup_bus;
return 0;
}
gpio = of_get_named_gpio(node, "cd-gpios", 0);
if (gpio_is_valid(gpio)) {
pdata->cd_type = S3C_SDHCI_CD_GPIO;
goto found_cd;
} else if (gpio != -ENOENT) {
dev_err(dev, "invalid card detect gpio specified\n");
return -EINVAL;
}
gpio = of_get_named_gpio(node, "samsung,cd-pinmux-gpio", 0);
if (gpio_is_valid(gpio)) {
pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
goto found_cd;
} else if (gpio != -ENOENT) {
dev_err(dev, "invalid card detect gpio specified\n");
return -EINVAL;
}
/* assuming internal card detect that will be configured by pinctrl */
pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
goto setup_bus;
found_cd:
if (pdata->cd_type == S3C_SDHCI_CD_GPIO) {
pdata->ext_cd_gpio = gpio;
ourhost->ext_cd_gpio = -1;
if (of_get_property(node, "cd-inverted", NULL))
pdata->ext_cd_gpio_invert = 1;
} else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
ret = devm_gpio_request(dev, gpio, "sdhci-cd");
if (ret) {
dev_err(dev, "card detect gpio request failed\n");
return -EINVAL;
}
ourhost->ext_cd_gpio = gpio;
}
setup_bus:
if (!IS_ERR(ourhost->pctrl))
return 0;
/* get the gpios for command, clock and data lines */
for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
gpio = of_get_gpio(node, cnt);
if (!gpio_is_valid(gpio)) {
dev_err(dev, "invalid gpio[%d]\n", cnt);
return -EINVAL;
}
ourhost->gpios[cnt] = gpio;
}
for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
ret = devm_gpio_request(dev, ourhost->gpios[cnt], "sdhci-gpio");
if (ret) {
dev_err(dev, "gpio[%d] request failed\n", cnt);
return -EINVAL;
}
} else if (gpio != -ENOENT) {
dev_err(dev, "invalid card detect gpio specified\n");
return -EINVAL;
}
/* assuming internal card detect that will be configured by pinctrl */
pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
return 0;
}
#else
......@@ -588,8 +535,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
goto err_pdata_io_clk;
}
sc->pctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (pdev->dev.of_node) {
ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata);
if (ret)
......@@ -607,7 +552,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
sc->clk_io = clk_get(dev, "hsmmc");
sc->clk_io = devm_clk_get(dev, "hsmmc");
if (IS_ERR(sc->clk_io)) {
dev_err(dev, "failed to get io clock\n");
ret = PTR_ERR(sc->clk_io);
......@@ -622,7 +567,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
char name[14];
snprintf(name, 14, "mmc_busclk.%d", ptr);
clk = clk_get(dev, name);
clk = devm_clk_get(dev, name);
if (IS_ERR(clk))
continue;
......@@ -763,15 +708,9 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
#ifndef CONFIG_PM_RUNTIME
clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
#endif
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
if (sc->clk_bus[ptr]) {
clk_put(sc->clk_bus[ptr]);
}
}
err_no_busclks:
clk_disable_unprepare(sc->clk_io);
clk_put(sc->clk_io);
err_pdata_io_clk:
sdhci_free_host(host);
......@@ -784,7 +723,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev)
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_s3c *sc = sdhci_priv(host);
struct s3c_sdhci_platdata *pdata = sc->pdata;
int ptr;
if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);
......@@ -804,13 +742,7 @@ static int sdhci_s3c_remove(struct platform_device *pdev)
#ifndef CONFIG_PM_RUNTIME
clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
#endif
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
if (sc->clk_bus[ptr]) {
clk_put(sc->clk_bus[ptr]);
}
}
clk_disable_unprepare(sc->clk_io);
clk_put(sc->clk_io);
sdhci_free_host(host);
platform_set_drvdata(pdev, NULL);
......
/*
* SDHCI support for SiRF primaII and marco SoCs
*
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
*
* Licensed under GPLv2 or later.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/pinctrl/consumer.h>
#include "sdhci-pltfm.h"
struct sdhci_sirf_priv {
struct clk *clk;
int gpio_cd;
};
static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_sirf_priv *priv = pltfm_host->priv;
return clk_get_rate(priv->clk);
}
static struct sdhci_ops sdhci_sirf_ops = {
.get_max_clock = sdhci_sirf_get_max_clk,
};
static struct sdhci_pltfm_data sdhci_sirf_pdata = {
.ops = &sdhci_sirf_ops,
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
SDHCI_QUIRK_DELAY_AFTER_POWER,
};
static int sdhci_sirf_probe(struct platform_device *pdev)
{
struct sdhci_host *host;
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_sirf_priv *priv;
struct pinctrl *pinctrl;
int ret;
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) {
dev_err(&pdev->dev, "unable to get pinmux");
return PTR_ERR(pinctrl);
}
priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_sirf_priv),
GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "unable to allocate private data");
return -ENOMEM;
}
priv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "unable to get clock");
return PTR_ERR(priv->clk);
}
if (pdev->dev.of_node) {
priv->gpio_cd = of_get_named_gpio(pdev->dev.of_node,
"cd-gpios", 0);
} else {
priv->gpio_cd = -EINVAL;
}
host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata);
if (IS_ERR(host)) {
ret = PTR_ERR(host);
goto err_sdhci_pltfm_init;
}
pltfm_host = sdhci_priv(host);
pltfm_host->priv = priv;
sdhci_get_of_property(pdev);
clk_prepare_enable(priv->clk);
ret = sdhci_add_host(host);
if (ret)
goto err_sdhci_add;
/*
* We must request the IRQ after sdhci_add_host(), as the tasklet only
* gets setup in sdhci_add_host() and we oops.
*/
if (gpio_is_valid(priv->gpio_cd)) {
ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd);
if (ret) {
dev_err(&pdev->dev, "card detect irq request failed: %d\n",
ret);
goto err_request_cd;
}
}
return 0;
err_request_cd:
sdhci_remove_host(host, 0);
err_sdhci_add:
clk_disable_unprepare(priv->clk);
sdhci_pltfm_free(pdev);
err_sdhci_pltfm_init:
return ret;
}
static int sdhci_sirf_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_sirf_priv *priv = pltfm_host->priv;
sdhci_pltfm_unregister(pdev);
if (gpio_is_valid(priv->gpio_cd))
mmc_gpio_free_cd(host->mmc);
clk_disable_unprepare(priv->clk);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int sdhci_sirf_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_sirf_priv *priv = pltfm_host->priv;
int ret;
ret = sdhci_suspend_host(host);
if (ret)
return ret;
clk_disable(priv->clk);
return 0;
}
static int sdhci_sirf_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_sirf_priv *priv = pltfm_host->priv;
int ret;
ret = clk_enable(priv->clk);
if (ret) {
dev_dbg(dev, "Resume: Error enabling clock\n");
return ret;
}
return sdhci_resume_host(host);
}
static SIMPLE_DEV_PM_OPS(sdhci_sirf_pm_ops, sdhci_sirf_suspend, sdhci_sirf_resume);
#endif
static const struct of_device_id sdhci_sirf_of_match[] = {
{ .compatible = "sirf,prima2-sdhc" },
{ }
};
MODULE_DEVICE_TABLE(of, sdhci_sirf_of_match);
static struct platform_driver sdhci_sirf_driver = {
.driver = {
.name = "sdhci-sirf",
.owner = THIS_MODULE,
.of_match_table = sdhci_sirf_of_match,
#ifdef CONFIG_PM_SLEEP
.pm = &sdhci_sirf_pm_ops,
#endif
},
.probe = sdhci_sirf_probe,
.remove = sdhci_sirf_remove,
};
module_platform_driver(sdhci_sirf_driver);
MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco");
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_LICENSE("GPL v2");
......@@ -36,7 +36,7 @@ struct spear_sdhci {
};
/* sdhci ops */
static struct sdhci_ops sdhci_pltfm_ops = {
static const struct sdhci_ops sdhci_pltfm_ops = {
/* Nothing to do for now. */
};
......@@ -291,7 +291,7 @@ static int sdhci_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int sdhci_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
......
......@@ -24,6 +24,7 @@
#include <linux/gpio.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/mmc/slot-gpio.h>
#include <asm/gpio.h>
......@@ -38,16 +39,13 @@
#define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2)
struct sdhci_tegra_soc_data {
struct sdhci_pltfm_data *pdata;
const struct sdhci_pltfm_data *pdata;
u32 nvquirks;
};
struct sdhci_tegra {
const struct sdhci_tegra_soc_data *soc_data;
int cd_gpio;
int wp_gpio;
int power_gpio;
int is_8bit;
};
static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
......@@ -107,23 +105,9 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
if (!gpio_is_valid(tegra_host->wp_gpio))
return -1;
return gpio_get_value(tegra_host->wp_gpio);
return mmc_gpio_get_ro(host->mmc);
}
static irqreturn_t carddetect_irq(int irq, void *data)
{
struct sdhci_host *sdhost = (struct sdhci_host *)data;
tasklet_schedule(&sdhost->card_tasklet);
return IRQ_HANDLED;
};
static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
......@@ -145,12 +129,11 @@ static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
u32 ctrl;
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
if (tegra_host->is_8bit && bus_width == MMC_BUS_WIDTH_8) {
if ((host->mmc->caps & MMC_CAP_8_BIT_DATA) &&
(bus_width == MMC_BUS_WIDTH_8)) {
ctrl &= ~SDHCI_CTRL_4BITBUS;
ctrl |= SDHCI_CTRL_8BITBUS;
} else {
......@@ -164,7 +147,7 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
return 0;
}
static struct sdhci_ops tegra_sdhci_ops = {
static const struct sdhci_ops tegra_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_l = tegra_sdhci_readl,
.read_w = tegra_sdhci_readw,
......@@ -173,8 +156,7 @@ static struct sdhci_ops tegra_sdhci_ops = {
.platform_reset_exit = tegra_sdhci_reset_exit,
};
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
static struct sdhci_pltfm_data sdhci_tegra20_pdata = {
static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_NO_HISPD_BIT |
......@@ -187,10 +169,8 @@ static struct sdhci_tegra_soc_data soc_data_tegra20 = {
.nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 |
NVQUIRK_ENABLE_BLOCK_GAP_DET,
};
#endif
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
static struct sdhci_pltfm_data sdhci_tegra30_pdata = {
static const struct sdhci_pltfm_data sdhci_tegra30_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
SDHCI_QUIRK_SINGLE_POWER_WRITE |
......@@ -203,32 +183,37 @@ static struct sdhci_tegra_soc_data soc_data_tegra30 = {
.pdata = &sdhci_tegra30_pdata,
.nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300,
};
#endif
static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_NO_HISPD_BIT |
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
.ops = &tegra_sdhci_ops,
};
static struct sdhci_tegra_soc_data soc_data_tegra114 = {
.pdata = &sdhci_tegra114_pdata,
};
static const struct of_device_id sdhci_tegra_dt_match[] = {
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
#endif
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
{ .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 },
#endif
{}
};
MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
static void sdhci_tegra_parse_dt(struct device *dev,
struct sdhci_tegra *tegra_host)
static void sdhci_tegra_parse_dt(struct device *dev)
{
struct device_node *np = dev->of_node;
u32 bus_width;
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
tegra_host->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
tegra_host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0);
if (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
bus_width == 8)
tegra_host->is_8bit = 1;
mmc_of_parse(host->mmc);
}
static int sdhci_tegra_probe(struct platform_device *pdev)
......@@ -260,7 +245,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
tegra_host->soc_data = soc_data;
pltfm_host->priv = tegra_host;
sdhci_tegra_parse_dt(&pdev->dev, tegra_host);
sdhci_tegra_parse_dt(&pdev->dev);
if (gpio_is_valid(tegra_host->power_gpio)) {
rc = gpio_request(tegra_host->power_gpio, "sdhci_power");
......@@ -272,37 +257,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
gpio_direction_output(tegra_host->power_gpio, 1);
}
if (gpio_is_valid(tegra_host->cd_gpio)) {
rc = gpio_request(tegra_host->cd_gpio, "sdhci_cd");
if (rc) {
dev_err(mmc_dev(host->mmc),
"failed to allocate cd gpio\n");
goto err_cd_req;
}
gpio_direction_input(tegra_host->cd_gpio);
rc = request_irq(gpio_to_irq(tegra_host->cd_gpio),
carddetect_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
mmc_hostname(host->mmc), host);
if (rc) {
dev_err(mmc_dev(host->mmc), "request irq error\n");
goto err_cd_irq_req;
}
}
if (gpio_is_valid(tegra_host->wp_gpio)) {
rc = gpio_request(tegra_host->wp_gpio, "sdhci_wp");
if (rc) {
dev_err(mmc_dev(host->mmc),
"failed to allocate wp gpio\n");
goto err_wp_req;
}
gpio_direction_input(tegra_host->wp_gpio);
}
clk = clk_get(mmc_dev(host->mmc), NULL);
if (IS_ERR(clk)) {
dev_err(mmc_dev(host->mmc), "clk err\n");
......@@ -312,9 +266,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
clk_prepare_enable(clk);
pltfm_host->clk = clk;
if (tegra_host->is_8bit)
host->mmc->caps |= MMC_CAP_8_BIT_DATA;
rc = sdhci_add_host(host);
if (rc)
goto err_add_host;
......@@ -325,15 +276,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
clk_disable_unprepare(pltfm_host->clk);
clk_put(pltfm_host->clk);
err_clk_get:
if (gpio_is_valid(tegra_host->wp_gpio))
gpio_free(tegra_host->wp_gpio);
err_wp_req:
if (gpio_is_valid(tegra_host->cd_gpio))
free_irq(gpio_to_irq(tegra_host->cd_gpio), host);
err_cd_irq_req:
if (gpio_is_valid(tegra_host->cd_gpio))
gpio_free(tegra_host->cd_gpio);
err_cd_req:
if (gpio_is_valid(tegra_host->power_gpio))
gpio_free(tegra_host->power_gpio);
err_power_req:
......@@ -351,14 +293,6 @@ static int sdhci_tegra_remove(struct platform_device *pdev)
sdhci_remove_host(host, dead);
if (gpio_is_valid(tegra_host->wp_gpio))
gpio_free(tegra_host->wp_gpio);
if (gpio_is_valid(tegra_host->cd_gpio)) {
free_irq(gpio_to_irq(tegra_host->cd_gpio), host);
gpio_free(tegra_host->cd_gpio);
}
if (gpio_is_valid(tegra_host->power_gpio))
gpio_free(tegra_host->power_gpio);
......
......@@ -1581,6 +1581,37 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_runtime_pm_put(host);
}
static int sdhci_do_get_cd(struct sdhci_host *host)
{
int gpio_cd = mmc_gpio_get_cd(host->mmc);
if (host->flags & SDHCI_DEVICE_DEAD)
return 0;
/* If polling/nonremovable, assume that the card is always present. */
if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
(host->mmc->caps & MMC_CAP_NONREMOVABLE))
return 1;
/* Try slot gpio detect */
if (!IS_ERR_VALUE(gpio_cd))
return !!gpio_cd;
/* Host native card detect */
return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
}
static int sdhci_get_cd(struct mmc_host *mmc)
{
struct sdhci_host *host = mmc_priv(mmc);
int ret;
sdhci_runtime_pm_get(host);
ret = sdhci_do_get_cd(host);
sdhci_runtime_pm_put(host);
return ret;
}
static int sdhci_check_ro(struct sdhci_host *host)
{
unsigned long flags;
......@@ -2038,6 +2069,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
static const struct mmc_host_ops sdhci_ops = {
.request = sdhci_request,
.set_ios = sdhci_set_ios,
.get_cd = sdhci_get_cd,
.get_ro = sdhci_get_ro,
.hw_reset = sdhci_hw_reset,
.enable_sdio_irq = sdhci_enable_sdio_irq,
......@@ -2907,12 +2939,17 @@ int sdhci_add_host(struct sdhci_host *host)
host->vqmmc = NULL;
}
} else {
regulator_enable(host->vqmmc);
ret = regulator_enable(host->vqmmc);
if (!regulator_is_supported_voltage(host->vqmmc, 1700000,
1950000))
caps[1] &= ~(SDHCI_SUPPORT_SDR104 |
SDHCI_SUPPORT_SDR50 |
SDHCI_SUPPORT_DDR50);
if (ret) {
pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
mmc_hostname(mmc), ret);
host->vqmmc = NULL;
}
}
if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
......
......@@ -348,13 +348,11 @@ static void wmt_complete_data_request(struct wmt_mci_priv *priv)
static irqreturn_t wmt_mci_dma_isr(int irq_num, void *data)
{
struct mmc_host *mmc;
struct wmt_mci_priv *priv;
int status;
priv = (struct wmt_mci_priv *)data;
mmc = priv->mmc;
status = readl(priv->sdmmc_base + SDDMA_CCR) & 0x0F;
......@@ -925,7 +923,7 @@ static int wmt_mci_remove(struct platform_device *pdev)
clk_put(priv->clk_sdmmc);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, res->end - res->start + 1);
release_mem_region(res->start, resource_size(res));
mmc_free_host(mmc);
......
......@@ -17,6 +17,7 @@
struct mmc_cid {
unsigned int manfid;
char prod_name[8];
unsigned char prv;
unsigned int serial;
unsigned short oemid;
unsigned short year;
......
......@@ -280,6 +280,7 @@ struct mmc_host {
#define MMC_CAP2_PACKED_WR (1 << 13) /* Allow packed write */
#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
MMC_CAP2_PACKED_WR)
#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */
mmc_pm_flag_t pm_caps; /* supported pm features */
......@@ -361,6 +362,8 @@ struct mmc_host {
unsigned int actual_clock; /* Actual HC clock rate */
unsigned int slotno; /* used for sdio acpi binding */
unsigned long private[0] ____cacheline_aligned;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment