From b3bee6cb894a0066d95dd77073b9c2e652cb0634 Mon Sep 17 00:00:00 2001 From: Bitan Biswas Date: Thu, 29 Oct 2015 15:24:37 +0530 Subject: [PATCH] mmc: host: tegra: disable kso mode reg dump On platforms with Broadcom Wifi over SDIO support register dump in KSO sleep is disabled bug 200138403 Change-Id: I49bded4df12fd0ce83be5bd791f4a9bd2e98b5b7 Signed-off-by: Bitan Biswas Reviewed-on: http://git-master/r/824720 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Pavan Kunapuli Reviewed-by: Naveen Kumar Arepalli GVS: Gerrit_Virtual_Submit Reviewed-by: Venu Byravarasu --- drivers/mmc/host/sdhci-tegra.c | 42 +++++++++++++++++++ drivers/mmc/host/sdhci.c | 10 +++++ drivers/mmc/host/sdhci.h | 1 + include/linux/platform_data/mmc-sdhci-tegra.h | 2 + 4 files changed, 55 insertions(+) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 7a7db0ea827..9e127152b66 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -5116,6 +5116,44 @@ static void tegra_sdhci_set_max_pio_transfer_limits(struct sdhci_host *sdhci) } } +static bool sdhci_tegra_skip_register_dump(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_tegra *tegra_host = pltfm_host->priv; + const struct tegra_sdhci_platform_data *plat = tegra_host->plat; + unsigned int arg; + unsigned short cmd; + int i; + const unsigned short kso_cmd52_pattern = 0x341a; + const unsigned int arg_kso_patterns[] = { + 0x92003e01, + 0x12003e00 + }; + + /* + * Case: "bcm_sdio_suppress_kso_dump" + * For KSO sleep mode error pattern in host register dump corresponding + * to CMD52 case would be either of the following: + 1) + Argument: 0x92003e01 (Write) + Cmd: 0x0000341a (CMD52 indicated by 0x34) + 2) + Argument: 0x12003e00 (Read) + Cmd: 0x0000341a (CMD52 indicated by 0x34) + * + */ + if (plat->bcm_sdio_suppress_kso_dump) { + arg = sdhci_readl(host, SDHCI_ARGUMENT); + cmd = sdhci_readw(host, SDHCI_COMMAND); + if (cmd == kso_cmd52_pattern) { + for (i = 0; i < ARRAY_SIZE(arg_kso_patterns); i++) + if (arg_kso_patterns[i] == arg) + return true; + } + } + return false; +} + static const struct sdhci_ops tegra_sdhci_ops = { .get_ro = tegra_sdhci_get_ro, .get_cd = tegra_sdhci_get_cd, @@ -5149,6 +5187,7 @@ static const struct sdhci_ops tegra_sdhci_ops = { .config_tap_delay = tegra_sdhci_config_tap, .is_tuning_done = tegra_sdhci_is_tuning_done, .get_max_pio_transfer_limits = tegra_sdhci_set_max_pio_transfer_limits, + .skip_register_dump = sdhci_tegra_skip_register_dump, }; static struct sdhci_pltfm_data sdhci_tegra11_pdata = { @@ -5374,6 +5413,9 @@ static struct tegra_sdhci_platform_data *sdhci_tegra_dt_parse_pdata( plat->gpios[i].label = label; } } + plat->bcm_sdio_suppress_kso_dump = + of_property_read_bool(np, "nvidia,bcm-sdio-suppress-kso-dump"); + return plat; } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f9b7351f1ff..51a836e1acb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3230,6 +3230,8 @@ static void sdhci_tuning_timer(unsigned long data) static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) { + bool skip_dump = false; + BUG_ON(intmask == 0); if (!host->cmd) { @@ -3245,6 +3247,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { host->cmd->error = -EILSEQ; + + if (host->ops->skip_register_dump) + skip_dump = host->ops->skip_register_dump(host); + if (skip_dump && + (intmask & SDHCI_INT_INDEX)) + goto lbl_suppress_dump; + sdhci_dumpregs(host); if (intmask & SDHCI_INT_INDEX) pr_err("%s: Command INDEX error, intmask: %x Interface clock = %uHz\n", @@ -3257,6 +3266,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) mmc_hostname(host->mmc), intmask, host->max_clk); } +lbl_suppress_dump: if (host->cmd->error) { if (MMC_CHECK_CMDQ_MODE(host)) tasklet_schedule(&host->finish_cmd_tasklet); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index c0ee766bec5..24fd240a86a 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -392,6 +392,7 @@ struct sdhci_ops { int (*get_max_tuning_loop_counter)(struct sdhci_host *sdhci); void (*config_tap_delay)(struct sdhci_host *host, u8 option); bool (*is_tuning_done)(struct sdhci_host *sdhci); + bool (*skip_register_dump)(struct sdhci_host *sdhci); int (*validate_sd2_0)(struct sdhci_host *sdhci); void (*get_max_pio_transfer_limits)(struct sdhci_host *sdhci); }; diff --git a/include/linux/platform_data/mmc-sdhci-tegra.h b/include/linux/platform_data/mmc-sdhci-tegra.h index 51a09114244..e2c6e5da3e6 100644 --- a/include/linux/platform_data/mmc-sdhci-tegra.h +++ b/include/linux/platform_data/mmc-sdhci-tegra.h @@ -108,6 +108,8 @@ struct tegra_sdhci_platform_data { bool en_strobe; /* Enable enhance strobe mode for eMMC */ bool enb_feedback_clock; bool en_periodic_calib; + /* Flag when true disables register dump after KSO sleep mode */ + bool bcm_sdio_suppress_kso_dump; int pin_count; struct gpio gpios[6]; }; -- 2.39.2