|
@@ -13,6 +13,7 @@
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/ioport.h>
|
|
|
#include <linux/device.h>
|
|
|
+#include <linux/io.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
#include <linux/kernel.h>
|
|
|
#include <linux/slab.h>
|
|
@@ -23,6 +24,7 @@
|
|
|
#include <linux/mmc/pm.h>
|
|
|
#include <linux/mmc/host.h>
|
|
|
#include <linux/mmc/card.h>
|
|
|
+#include <linux/mmc/slot-gpio.h>
|
|
|
#include <linux/amba/bus.h>
|
|
|
#include <linux/clk.h>
|
|
|
#include <linux/scatterlist.h>
|
|
@@ -364,7 +366,6 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
|
|
|
#ifdef CONFIG_DMA_ENGINE
|
|
|
static void mmci_dma_setup(struct mmci_host *host)
|
|
|
{
|
|
|
- struct mmci_platform_data *plat = host->plat;
|
|
|
const char *rxname, *txname;
|
|
|
dma_cap_mask_t mask;
|
|
|
|
|
@@ -378,25 +379,6 @@ static void mmci_dma_setup(struct mmci_host *host)
|
|
|
dma_cap_zero(mask);
|
|
|
dma_cap_set(DMA_SLAVE, mask);
|
|
|
|
|
|
- if (plat && plat->dma_filter) {
|
|
|
- if (!host->dma_rx_channel && plat->dma_rx_param) {
|
|
|
- host->dma_rx_channel = dma_request_channel(mask,
|
|
|
- plat->dma_filter,
|
|
|
- plat->dma_rx_param);
|
|
|
- /* E.g if no DMA hardware is present */
|
|
|
- if (!host->dma_rx_channel)
|
|
|
- dev_err(mmc_dev(host->mmc), "no RX DMA channel\n");
|
|
|
- }
|
|
|
-
|
|
|
- if (!host->dma_tx_channel && plat->dma_tx_param) {
|
|
|
- host->dma_tx_channel = dma_request_channel(mask,
|
|
|
- plat->dma_filter,
|
|
|
- plat->dma_tx_param);
|
|
|
- if (!host->dma_tx_channel)
|
|
|
- dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
* If only an RX channel is specified, the driver will
|
|
|
* attempt to use it bidirectionally, however if it is
|
|
@@ -444,11 +426,9 @@ static void mmci_dma_setup(struct mmci_host *host)
|
|
|
*/
|
|
|
static inline void mmci_dma_release(struct mmci_host *host)
|
|
|
{
|
|
|
- struct mmci_platform_data *plat = host->plat;
|
|
|
-
|
|
|
if (host->dma_rx_channel)
|
|
|
dma_release_channel(host->dma_rx_channel);
|
|
|
- if (host->dma_tx_channel && plat->dma_tx_param)
|
|
|
+ if (host->dma_tx_channel)
|
|
|
dma_release_channel(host->dma_tx_channel);
|
|
|
host->dma_rx_channel = host->dma_tx_channel = NULL;
|
|
|
}
|
|
@@ -1285,7 +1265,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|
|
* indicating signal direction for the signals in
|
|
|
* the SD/MMC bus and feedback-clock usage.
|
|
|
*/
|
|
|
- pwr |= host->plat->sigdir;
|
|
|
+ pwr |= host->pwr_reg_add;
|
|
|
|
|
|
if (ios->bus_width == MMC_BUS_WIDTH_4)
|
|
|
pwr &= ~MCI_ST_DATA74DIREN;
|
|
@@ -1326,35 +1306,18 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|
|
pm_runtime_put_autosuspend(mmc_dev(mmc));
|
|
|
}
|
|
|
|
|
|
-static int mmci_get_ro(struct mmc_host *mmc)
|
|
|
-{
|
|
|
- struct mmci_host *host = mmc_priv(mmc);
|
|
|
-
|
|
|
- if (host->gpio_wp == -ENOSYS)
|
|
|
- return -ENOSYS;
|
|
|
-
|
|
|
- return gpio_get_value_cansleep(host->gpio_wp);
|
|
|
-}
|
|
|
-
|
|
|
static int mmci_get_cd(struct mmc_host *mmc)
|
|
|
{
|
|
|
struct mmci_host *host = mmc_priv(mmc);
|
|
|
struct mmci_platform_data *plat = host->plat;
|
|
|
- unsigned int status;
|
|
|
+ unsigned int status = mmc_gpio_get_cd(mmc);
|
|
|
|
|
|
- if (host->gpio_cd == -ENOSYS) {
|
|
|
+ if (status == -ENOSYS) {
|
|
|
if (!plat->status)
|
|
|
return 1; /* Assume always present */
|
|
|
|
|
|
status = plat->status(mmc_dev(host->mmc));
|
|
|
- } else
|
|
|
- status = !!gpio_get_value_cansleep(host->gpio_cd)
|
|
|
- ^ plat->cd_invert;
|
|
|
-
|
|
|
- /*
|
|
|
- * Use positive logic throughout - status is zero for no card,
|
|
|
- * non-zero for card inserted.
|
|
|
- */
|
|
|
+ }
|
|
|
return status;
|
|
|
}
|
|
|
|
|
@@ -1391,70 +1354,44 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
|
|
|
-{
|
|
|
- struct mmci_host *host = dev_id;
|
|
|
-
|
|
|
- mmc_detect_change(host->mmc, msecs_to_jiffies(500));
|
|
|
-
|
|
|
- return IRQ_HANDLED;
|
|
|
-}
|
|
|
-
|
|
|
static struct mmc_host_ops mmci_ops = {
|
|
|
.request = mmci_request,
|
|
|
.pre_req = mmci_pre_request,
|
|
|
.post_req = mmci_post_request,
|
|
|
.set_ios = mmci_set_ios,
|
|
|
- .get_ro = mmci_get_ro,
|
|
|
+ .get_ro = mmc_gpio_get_ro,
|
|
|
.get_cd = mmci_get_cd,
|
|
|
.start_signal_voltage_switch = mmci_sig_volt_switch,
|
|
|
};
|
|
|
|
|
|
-#ifdef CONFIG_OF
|
|
|
-static void mmci_dt_populate_generic_pdata(struct device_node *np,
|
|
|
- struct mmci_platform_data *pdata)
|
|
|
+static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc)
|
|
|
{
|
|
|
- int bus_width = 0;
|
|
|
-
|
|
|
- pdata->gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
|
|
|
- pdata->gpio_cd = of_get_named_gpio(np, "cd-gpios", 0);
|
|
|
+ struct mmci_host *host = mmc_priv(mmc);
|
|
|
+ int ret = mmc_of_parse(mmc);
|
|
|
|
|
|
- if (of_get_property(np, "cd-inverted", NULL))
|
|
|
- pdata->cd_invert = true;
|
|
|
- else
|
|
|
- pdata->cd_invert = false;
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
- of_property_read_u32(np, "max-frequency", &pdata->f_max);
|
|
|
- if (!pdata->f_max)
|
|
|
- pr_warn("%s has no 'max-frequency' property\n", np->full_name);
|
|
|
+ if (of_get_property(np, "st,sig-dir-dat0", NULL))
|
|
|
+ host->pwr_reg_add |= MCI_ST_DATA0DIREN;
|
|
|
+ if (of_get_property(np, "st,sig-dir-dat2", NULL))
|
|
|
+ host->pwr_reg_add |= MCI_ST_DATA2DIREN;
|
|
|
+ if (of_get_property(np, "st,sig-dir-dat31", NULL))
|
|
|
+ host->pwr_reg_add |= MCI_ST_DATA31DIREN;
|
|
|
+ if (of_get_property(np, "st,sig-dir-dat74", NULL))
|
|
|
+ host->pwr_reg_add |= MCI_ST_DATA74DIREN;
|
|
|
+ if (of_get_property(np, "st,sig-dir-cmd", NULL))
|
|
|
+ host->pwr_reg_add |= MCI_ST_CMDDIREN;
|
|
|
+ if (of_get_property(np, "st,sig-pin-fbclk", NULL))
|
|
|
+ host->pwr_reg_add |= MCI_ST_FBCLKEN;
|
|
|
|
|
|
if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL))
|
|
|
- pdata->capabilities |= MMC_CAP_MMC_HIGHSPEED;
|
|
|
+ mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
|
|
|
if (of_get_property(np, "mmc-cap-sd-highspeed", NULL))
|
|
|
- pdata->capabilities |= MMC_CAP_SD_HIGHSPEED;
|
|
|
+ mmc->caps |= MMC_CAP_SD_HIGHSPEED;
|
|
|
|
|
|
- of_property_read_u32(np, "bus-width", &bus_width);
|
|
|
- switch (bus_width) {
|
|
|
- case 0 :
|
|
|
- /* No bus-width supplied. */
|
|
|
- break;
|
|
|
- case 4 :
|
|
|
- pdata->capabilities |= MMC_CAP_4_BIT_DATA;
|
|
|
- break;
|
|
|
- case 8 :
|
|
|
- pdata->capabilities |= MMC_CAP_8_BIT_DATA;
|
|
|
- break;
|
|
|
- default :
|
|
|
- pr_warn("%s: Unsupported bus width\n", np->full_name);
|
|
|
- }
|
|
|
-}
|
|
|
-#else
|
|
|
-static void mmci_dt_populate_generic_pdata(struct device_node *np,
|
|
|
- struct mmci_platform_data *pdata)
|
|
|
-{
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
static int mmci_probe(struct amba_device *dev,
|
|
|
const struct amba_id *id)
|
|
@@ -1478,26 +1415,17 @@ static int mmci_probe(struct amba_device *dev,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- if (np)
|
|
|
- mmci_dt_populate_generic_pdata(np, plat);
|
|
|
+ mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
|
|
|
+ if (!mmc)
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
- ret = amba_request_regions(dev, DRIVER_NAME);
|
|
|
+ ret = mmci_of_parse(np, mmc);
|
|
|
if (ret)
|
|
|
- goto out;
|
|
|
-
|
|
|
- mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
|
|
|
- if (!mmc) {
|
|
|
- ret = -ENOMEM;
|
|
|
- goto rel_regions;
|
|
|
- }
|
|
|
+ goto host_free;
|
|
|
|
|
|
host = mmc_priv(mmc);
|
|
|
host->mmc = mmc;
|
|
|
|
|
|
- host->gpio_wp = -ENOSYS;
|
|
|
- host->gpio_cd = -ENOSYS;
|
|
|
- host->gpio_cd_irq = -1;
|
|
|
-
|
|
|
host->hw_designer = amba_manf(dev);
|
|
|
host->hw_revision = amba_rev(dev);
|
|
|
dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer);
|
|
@@ -1529,10 +1457,11 @@ static int mmci_probe(struct amba_device *dev,
|
|
|
dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n",
|
|
|
host->mclk);
|
|
|
}
|
|
|
+
|
|
|
host->phybase = dev->res.start;
|
|
|
- host->base = ioremap(dev->res.start, resource_size(&dev->res));
|
|
|
- if (!host->base) {
|
|
|
- ret = -ENOMEM;
|
|
|
+ host->base = devm_ioremap_resource(&dev->dev, &dev->res);
|
|
|
+ if (IS_ERR(host->base)) {
|
|
|
+ ret = PTR_ERR(host->base);
|
|
|
goto clk_disable;
|
|
|
}
|
|
|
|
|
@@ -1546,15 +1475,13 @@ static int mmci_probe(struct amba_device *dev,
|
|
|
else
|
|
|
mmc->f_min = DIV_ROUND_UP(host->mclk, 512);
|
|
|
/*
|
|
|
- * If the platform data supplies a maximum operating
|
|
|
- * frequency, this takes precedence. Else, we fall back
|
|
|
- * to using the module parameter, which has a (low)
|
|
|
- * default value in case it is not specified. Either
|
|
|
- * value must not exceed the clock rate into the block,
|
|
|
- * of course.
|
|
|
+ * If no maximum operating frequency is supplied, fall back to use
|
|
|
+ * the module parameter, which has a (low) default value in case it
|
|
|
+ * is not specified. Either value must not exceed the clock rate into
|
|
|
+ * the block, of course.
|
|
|
*/
|
|
|
- if (plat->f_max)
|
|
|
- mmc->f_max = min(host->mclk, plat->f_max);
|
|
|
+ if (mmc->f_max)
|
|
|
+ mmc->f_max = min(host->mclk, mmc->f_max);
|
|
|
else
|
|
|
mmc->f_max = min(host->mclk, fmax);
|
|
|
dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
|
|
@@ -1566,8 +1493,15 @@ static int mmci_probe(struct amba_device *dev,
|
|
|
else if (plat->ocr_mask)
|
|
|
dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
|
|
|
|
|
|
- mmc->caps = plat->capabilities;
|
|
|
- mmc->caps2 = plat->capabilities2;
|
|
|
+ /* DT takes precedence over platform data. */
|
|
|
+ if (!np) {
|
|
|
+ if (!plat->cd_invert)
|
|
|
+ mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
|
|
|
+ mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* We support these capabilities. */
|
|
|
+ mmc->caps |= MMC_CAP_CMD23;
|
|
|
|
|
|
if (variant->busy_detect) {
|
|
|
mmci_ops.card_busy = mmci_card_busy;
|
|
@@ -1579,7 +1513,7 @@ static int mmci_probe(struct amba_device *dev,
|
|
|
mmc->ops = &mmci_ops;
|
|
|
|
|
|
/* We support these PM capabilities. */
|
|
|
- mmc->pm_caps = MMC_PM_KEEP_POWER;
|
|
|
+ mmc->pm_caps |= MMC_PM_KEEP_POWER;
|
|
|
|
|
|
/*
|
|
|
* We can do SGIO
|
|
@@ -1616,62 +1550,30 @@ static int mmci_probe(struct amba_device *dev,
|
|
|
writel(0, host->base + MMCIMASK1);
|
|
|
writel(0xfff, host->base + MMCICLEAR);
|
|
|
|
|
|
- if (plat->gpio_cd == -EPROBE_DEFER) {
|
|
|
- ret = -EPROBE_DEFER;
|
|
|
- goto err_gpio_cd;
|
|
|
- }
|
|
|
- if (gpio_is_valid(plat->gpio_cd)) {
|
|
|
- ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)");
|
|
|
- if (ret == 0)
|
|
|
- ret = gpio_direction_input(plat->gpio_cd);
|
|
|
- if (ret == 0)
|
|
|
- host->gpio_cd = plat->gpio_cd;
|
|
|
- else if (ret != -ENOSYS)
|
|
|
- goto err_gpio_cd;
|
|
|
-
|
|
|
- /*
|
|
|
- * A gpio pin that will detect cards when inserted and removed
|
|
|
- * will most likely want to trigger on the edges if it is
|
|
|
- * 0 when ejected and 1 when inserted (or mutatis mutandis
|
|
|
- * for the inverted case) so we request triggers on both
|
|
|
- * edges.
|
|
|
- */
|
|
|
- ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
|
|
|
- mmci_cd_irq,
|
|
|
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
|
|
- DRIVER_NAME " (cd)", host);
|
|
|
- if (ret >= 0)
|
|
|
- host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
|
|
|
- }
|
|
|
- if (plat->gpio_wp == -EPROBE_DEFER) {
|
|
|
- ret = -EPROBE_DEFER;
|
|
|
- goto err_gpio_wp;
|
|
|
+ /* If DT, cd/wp gpios must be supplied through it. */
|
|
|
+ if (!np && gpio_is_valid(plat->gpio_cd)) {
|
|
|
+ ret = mmc_gpio_request_cd(mmc, plat->gpio_cd, 0);
|
|
|
+ if (ret)
|
|
|
+ goto clk_disable;
|
|
|
}
|
|
|
- if (gpio_is_valid(plat->gpio_wp)) {
|
|
|
- ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)");
|
|
|
- if (ret == 0)
|
|
|
- ret = gpio_direction_input(plat->gpio_wp);
|
|
|
- if (ret == 0)
|
|
|
- host->gpio_wp = plat->gpio_wp;
|
|
|
- else if (ret != -ENOSYS)
|
|
|
- goto err_gpio_wp;
|
|
|
+ if (!np && gpio_is_valid(plat->gpio_wp)) {
|
|
|
+ ret = mmc_gpio_request_ro(mmc, plat->gpio_wp);
|
|
|
+ if (ret)
|
|
|
+ goto clk_disable;
|
|
|
}
|
|
|
|
|
|
- if ((host->plat->status || host->gpio_cd != -ENOSYS)
|
|
|
- && host->gpio_cd_irq < 0)
|
|
|
- mmc->caps |= MMC_CAP_NEEDS_POLL;
|
|
|
-
|
|
|
- ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
|
|
|
+ ret = devm_request_irq(&dev->dev, dev->irq[0], mmci_irq, IRQF_SHARED,
|
|
|
+ DRIVER_NAME " (cmd)", host);
|
|
|
if (ret)
|
|
|
- goto unmap;
|
|
|
+ goto clk_disable;
|
|
|
|
|
|
if (!dev->irq[1])
|
|
|
host->singleirq = true;
|
|
|
else {
|
|
|
- ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED,
|
|
|
- DRIVER_NAME " (pio)", host);
|
|
|
+ ret = devm_request_irq(&dev->dev, dev->irq[1], mmci_pio_irq,
|
|
|
+ IRQF_SHARED, DRIVER_NAME " (pio)", host);
|
|
|
if (ret)
|
|
|
- goto irq0_free;
|
|
|
+ goto clk_disable;
|
|
|
}
|
|
|
|
|
|
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
|
@@ -1693,25 +1595,10 @@ static int mmci_probe(struct amba_device *dev,
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
- irq0_free:
|
|
|
- free_irq(dev->irq[0], host);
|
|
|
- unmap:
|
|
|
- if (host->gpio_wp != -ENOSYS)
|
|
|
- gpio_free(host->gpio_wp);
|
|
|
- err_gpio_wp:
|
|
|
- if (host->gpio_cd_irq >= 0)
|
|
|
- free_irq(host->gpio_cd_irq, host);
|
|
|
- if (host->gpio_cd != -ENOSYS)
|
|
|
- gpio_free(host->gpio_cd);
|
|
|
- err_gpio_cd:
|
|
|
- iounmap(host->base);
|
|
|
clk_disable:
|
|
|
clk_disable_unprepare(host->clk);
|
|
|
host_free:
|
|
|
mmc_free_host(mmc);
|
|
|
- rel_regions:
|
|
|
- amba_release_regions(dev);
|
|
|
- out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -1737,92 +1624,46 @@ static int mmci_remove(struct amba_device *dev)
|
|
|
writel(0, host->base + MMCIDATACTRL);
|
|
|
|
|
|
mmci_dma_release(host);
|
|
|
- free_irq(dev->irq[0], host);
|
|
|
- if (!host->singleirq)
|
|
|
- free_irq(dev->irq[1], host);
|
|
|
-
|
|
|
- if (host->gpio_wp != -ENOSYS)
|
|
|
- gpio_free(host->gpio_wp);
|
|
|
- if (host->gpio_cd_irq >= 0)
|
|
|
- free_irq(host->gpio_cd_irq, host);
|
|
|
- if (host->gpio_cd != -ENOSYS)
|
|
|
- gpio_free(host->gpio_cd);
|
|
|
-
|
|
|
- iounmap(host->base);
|
|
|
clk_disable_unprepare(host->clk);
|
|
|
-
|
|
|
mmc_free_host(mmc);
|
|
|
-
|
|
|
- amba_release_regions(dev);
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-#ifdef CONFIG_SUSPEND
|
|
|
-static int mmci_suspend(struct device *dev)
|
|
|
-{
|
|
|
- struct amba_device *adev = to_amba_device(dev);
|
|
|
- struct mmc_host *mmc = amba_get_drvdata(adev);
|
|
|
-
|
|
|
- if (mmc) {
|
|
|
- struct mmci_host *host = mmc_priv(mmc);
|
|
|
- pm_runtime_get_sync(dev);
|
|
|
- writel(0, host->base + MMCIMASK0);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int mmci_resume(struct device *dev)
|
|
|
-{
|
|
|
- struct amba_device *adev = to_amba_device(dev);
|
|
|
- struct mmc_host *mmc = amba_get_drvdata(adev);
|
|
|
-
|
|
|
- if (mmc) {
|
|
|
- struct mmci_host *host = mmc_priv(mmc);
|
|
|
- writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
|
|
- pm_runtime_put(dev);
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef CONFIG_PM_RUNTIME
|
|
|
+#ifdef CONFIG_PM
|
|
|
static void mmci_save(struct mmci_host *host)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
|
|
|
- if (host->variant->pwrreg_nopower) {
|
|
|
- spin_lock_irqsave(&host->lock, flags);
|
|
|
+ spin_lock_irqsave(&host->lock, flags);
|
|
|
|
|
|
- writel(0, host->base + MMCIMASK0);
|
|
|
+ writel(0, host->base + MMCIMASK0);
|
|
|
+ if (host->variant->pwrreg_nopower) {
|
|
|
writel(0, host->base + MMCIDATACTRL);
|
|
|
writel(0, host->base + MMCIPOWER);
|
|
|
writel(0, host->base + MMCICLOCK);
|
|
|
- mmci_reg_delay(host);
|
|
|
-
|
|
|
- spin_unlock_irqrestore(&host->lock, flags);
|
|
|
}
|
|
|
+ mmci_reg_delay(host);
|
|
|
|
|
|
+ spin_unlock_irqrestore(&host->lock, flags);
|
|
|
}
|
|
|
|
|
|
static void mmci_restore(struct mmci_host *host)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
|
|
|
- if (host->variant->pwrreg_nopower) {
|
|
|
- spin_lock_irqsave(&host->lock, flags);
|
|
|
+ spin_lock_irqsave(&host->lock, flags);
|
|
|
|
|
|
+ if (host->variant->pwrreg_nopower) {
|
|
|
writel(host->clk_reg, host->base + MMCICLOCK);
|
|
|
writel(host->datactrl_reg, host->base + MMCIDATACTRL);
|
|
|
writel(host->pwr_reg, host->base + MMCIPOWER);
|
|
|
- writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
|
|
- mmci_reg_delay(host);
|
|
|
-
|
|
|
- spin_unlock_irqrestore(&host->lock, flags);
|
|
|
}
|
|
|
+ writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
|
|
+ mmci_reg_delay(host);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&host->lock, flags);
|
|
|
}
|
|
|
|
|
|
static int mmci_runtime_suspend(struct device *dev)
|
|
@@ -1857,8 +1698,9 @@ static int mmci_runtime_resume(struct device *dev)
|
|
|
#endif
|
|
|
|
|
|
static const struct dev_pm_ops mmci_dev_pm_ops = {
|
|
|
- SET_SYSTEM_SLEEP_PM_OPS(mmci_suspend, mmci_resume)
|
|
|
- SET_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
|
|
|
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
|
|
+ pm_runtime_force_resume)
|
|
|
+ SET_PM_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
|
|
|
};
|
|
|
|
|
|
static struct amba_id mmci_ids[] = {
|