summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenkat Gopalakrishnan <venkatg@codeaurora.org>2015-09-15 15:57:35 -0700
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-31 15:27:38 -0700
commitb78e1b402589663b584111e24b6756beccef4797 (patch)
tree9ac570a8d3d4c9efe8bfad99cb56c0a94fbb3a21
parent77da995311249747adf8b5e3b08e1ab415437f25 (diff)
mmc: debugfs: add debugfs entry to force raise host errors
The SDHC spec allows to force raise errors that is useful for debugging error handler routines. Add debugfs entry force_error to trigger host errors from userspace. Check SDHCI_SET_INT_ERROR register for error bitmask info. Usage: echo 0x1 > /sys/kernel/debug/mmcX/force_error X - denotes the slot id Change-Id: I9f67442a79b2645cbdc3020d1a10c0b32840ce32 Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org> [subhashj@codeaurora.org: fixed trivial merge conflicts] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
-rw-r--r--drivers/mmc/core/debugfs.c19
-rw-r--r--drivers/mmc/host/sdhci.c13
-rw-r--r--include/linux/mmc/host.h1
3 files changed, 33 insertions, 0 deletions
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 98b9e90e667a..7e3d82f658e7 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -313,6 +313,21 @@ out:
DEFINE_SIMPLE_ATTRIBUTE(mmc_max_clock_fops, mmc_max_clock_get,
mmc_max_clock_set, "%llu\n");
+static int mmc_force_err_set(void *data, u64 val)
+{
+ struct mmc_host *host = data;
+
+ if (host && host->ops && host->ops->force_err_irq) {
+ mmc_host_clk_hold(host);
+ host->ops->force_err_irq(host, val);
+ mmc_host_clk_release(host);
+ }
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(mmc_force_err_fops, NULL, mmc_force_err_set, "%llu\n");
+
void mmc_add_host_debugfs(struct mmc_host *host)
{
struct dentry *root;
@@ -362,6 +377,10 @@ void mmc_add_host_debugfs(struct mmc_host *host)
&host->fail_mmc_request)))
goto err_node;
#endif
+ if (!debugfs_create_file("force_error", S_IWUSR, root, host,
+ &mmc_force_err_fops))
+ goto err_node;
+
return;
err_node:
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 999bd8e839de..9761cd7f5a80 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2603,6 +2603,18 @@ static int sdhci_late_init(struct mmc_host *mmc)
return 0;
}
+
+static void sdhci_force_err_irq(struct mmc_host *mmc, u64 errmask)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u16 mask = errmask & 0xFFFF;
+
+ pr_err("%s: Force raise error mask:0x%04x\n", __func__, mask);
+ sdhci_runtime_pm_get(host);
+ sdhci_writew(host, mask, SDHCI_SET_INT_ERROR);
+ sdhci_runtime_pm_put(host);
+}
+
static const struct mmc_host_ops sdhci_ops = {
.init = sdhci_late_init,
.request = sdhci_request,
@@ -2625,6 +2637,7 @@ static const struct mmc_host_ops sdhci_ops = {
.notify_load = sdhci_notify_load,
.notify_halt = sdhci_notify_halt,
.detect = sdhci_detect,
+ .force_err_irq = sdhci_force_err_irq,
};
/*****************************************************************************\
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 87f90a7d061a..a312467be721 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -182,6 +182,7 @@ struct mmc_host_ops {
int (*notify_load)(struct mmc_host *, enum mmc_load);
void (*notify_halt)(struct mmc_host *mmc, bool halt);
void (*detect)(struct mmc_host *host, bool detected);
+ void (*force_err_irq)(struct mmc_host *host, u64 errmask);
};
struct mmc_card;