Merge "msm_serial_hs: Donot register UART device as PM runtime active"
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index cb036dd..15e36a8 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -38,6 +38,7 @@
#include <linux/dma-mapping.h>
#include <mach/gpio.h>
#include <mach/msm_bus.h>
+#include <linux/iopoll.h>
#include "sdhci-pltfm.h"
@@ -81,6 +82,31 @@
#define CORE_CLK_PWRSAVE (1 << 1)
#define CORE_IO_PAD_PWR_SWITCH (1 << 16)
+#define CORE_MCI_DATA_CTRL 0x2C
+#define CORE_MCI_DPSM_ENABLE (1 << 0)
+
+#define CORE_TESTBUS_CONFIG 0x0CC
+#define CORE_TESTBUS_ENA (1 << 3)
+#define CORE_TESTBUS_SEL2 (1 << 4)
+
+/*
+ * Waiting until end of potential AHB access for data:
+ * 16 AHB cycles (160ns for 100MHz and 320ns for 50MHz) +
+ * delay on AHB (2us) = maximum 2.32us
+ * Taking x10 times margin
+ */
+#define CORE_AHB_DATA_DELAY_US 23
+/* Waiting until end of potential AHB access for descriptor:
+ * Single (1 AHB cycle) + delay on AHB bus = max 2us
+ * INCR4 (4 AHB cycles) + delay on AHB bus = max 2us
+ * Single (1 AHB cycle) + delay on AHB bus = max 2us
+ * Total 8 us delay with margin
+ */
+#define CORE_AHB_DESC_DELAY_US 8
+
+#define CORE_SDCC_DEBUG_REG 0x124
+#define CORE_DEBUG_REG_AHB_HTRANS (3 << 12)
+
/* 8KB descriptors */
#define SDHCI_MSM_MAX_SEGMENTS (1 << 13)
#define SDHCI_MSM_MMC_CLK_GATE_DELAY 200 /* msecs */
@@ -2044,6 +2070,51 @@
return 0;
}
+/*
+ * sdhci_msm_disable_data_xfer - disable undergoing AHB bus data transfer
+ *
+ * Write 0 to bit 0 in MCI_DATA_CTL (offset 0x2C) - clearing TxActive bit by
+ * access to legacy registers. It will stop current burst and prevent start of
+ * the next on.
+ *
+ * Polling CORE_AHB_DATA_DELAY_US timeout, by reading bit 13:12 until they are 0
+ * in CORE_SDCC_DEBUG_REG (offset 0x124) will validate that AHB burst was
+ * completed and a new one didn't start.
+ *
+ * Waiting for 4us while AHB finishes descriptors fetch.
+ */
+static void sdhci_msm_disable_data_xfer(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ u32 value;
+ int ret;
+
+ value = readl_relaxed(msm_host->core_mem + CORE_MCI_DATA_CTRL);
+ value &= ~(u32)CORE_MCI_DPSM_ENABLE;
+ writel_relaxed(value, msm_host->core_mem + CORE_MCI_DATA_CTRL);
+
+ /* Enable the test bus for device slot */
+ writel_relaxed(CORE_TESTBUS_ENA | CORE_TESTBUS_SEL2,
+ msm_host->core_mem + CORE_TESTBUS_CONFIG);
+
+ ret = readl_poll_timeout_noirq(msm_host->core_mem
+ + CORE_SDCC_DEBUG_REG, value,
+ !(value & CORE_DEBUG_REG_AHB_HTRANS),
+ CORE_AHB_DATA_DELAY_US, 1);
+ if (ret) {
+ pr_err("%s: %s: can't stop ongoing AHB bus access by ADMA\n",
+ mmc_hostname(host->mmc), __func__);
+ BUG();
+ }
+ /* Disable the test bus for device slot */
+ value = readl_relaxed(msm_host->core_mem + CORE_TESTBUS_CONFIG);
+ value &= ~CORE_TESTBUS_ENA;
+ writel_relaxed(value, msm_host->core_mem + CORE_TESTBUS_CONFIG);
+
+ udelay(CORE_AHB_DESC_DELAY_US);
+}
+
static struct sdhci_ops sdhci_msm_ops = {
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
.check_power_status = sdhci_msm_check_power_status,
@@ -2054,6 +2125,7 @@
.platform_bus_voting = sdhci_msm_bus_voting,
.get_min_clock = sdhci_msm_get_min_clock,
.get_max_clock = sdhci_msm_get_max_clock,
+ .disable_data_xfer = sdhci_msm_disable_data_xfer,
};
static int __devinit sdhci_msm_probe(struct platform_device *pdev)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0549b4a..3efea77 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2126,7 +2126,49 @@
static int sdhci_stop_request(struct mmc_host *mmc)
{
- return -ENOSYS;
+ struct sdhci_host *host = mmc_priv(mmc);
+ unsigned long flags;
+ struct mmc_data *data;
+
+ spin_lock_irqsave(&host->lock, flags);
+ if (!host->mrq || !host->data)
+ goto out;
+
+ data = host->data;
+
+ if (host->ops->disable_data_xfer)
+ host->ops->disable_data_xfer(host);
+
+ sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+
+ if (host->flags & SDHCI_REQ_USE_DMA) {
+ if (host->flags & SDHCI_USE_ADMA) {
+ sdhci_adma_table_post(host, data);
+ } else {
+ if (!data->host_cookie)
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len,
+ (data->flags & MMC_DATA_READ) ?
+ DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+ }
+ del_timer(&host->timer);
+ host->mrq = NULL;
+ host->cmd = NULL;
+ host->data = NULL;
+out:
+ spin_unlock_irqrestore(&host->lock, flags);
+ return 0;
+}
+
+static unsigned int sdhci_get_xfer_remain(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u32 present_state = 0;
+
+ present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
+
+ return present_state & SDHCI_DOING_WRITE;
}
static const struct mmc_host_ops sdhci_ops = {
@@ -2143,6 +2185,7 @@
.enable = sdhci_enable,
.disable = sdhci_disable,
.stop_request = sdhci_stop_request,
+ .get_xfer_remain = sdhci_get_xfer_remain,
};
/*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index c6bef8a..a3d8442 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -286,6 +286,7 @@
void (*toggle_cdr)(struct sdhci_host *host, bool enable);
unsigned int (*get_max_segments)(void);
void (*platform_bus_voting)(struct sdhci_host *host, u32 enable);
+ void (*disable_data_xfer)(struct sdhci_host *host);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 570c257..fe8bdd0 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -691,9 +691,9 @@
/* Lookup the 'APPS' partition's first page address */
for (i = 0; i < FLASH_PTABLE_MAX_PARTS_V4; i++) {
- if (!strncmp("apps", ptable.part_entry[i].name,
- strlen(ptable.part_entry[i].name))) {
- page_address = ptable.part_entry[i].offset << 6;
+ if (!strncmp("apps", mtd_part[i].name,
+ strlen(mtd_part[i].name))) {
+ page_address = mtd_part[i].offset << 6;
break;
}
}