Hi Scott,

Am 07.11.2014 um 19:31 schrieb Scott Branden:
> On 14-11-05 09:01 PM, Stephen Warren wrote:
>> On 11/05/2014 12:00 AM, Scott Branden wrote:
>>> On 14-11-04 08:59 PM, Stephen Warren wrote:
>>>> On 10/30/2014 12:36 AM, Scott Branden wrote:
>>>>> Add a verify option to driver to print out an error message if a
>>>>> potential back to back write could cause a clock domain issue.
>>>>
>>>>> index f8c450a..11af27f 100644
>>>>
>>>>> +#ifdef CONFIG_MMC_SDHCI_BCM2835_VERIFY_WORKAROUND
>>>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>>>> +    struct bcm2835_sdhci_host *bcm2835_host = pltfm_host->priv;
>>>>> +
>>>>> +    if (bcm2835_host->previous_reg == reg) {
>>>>> +        if ((reg != SDHCI_HOST_CONTROL)
>>>>> +            && (reg != SDHCI_CLOCK_CONTROL)) {
>>>>
>>>> The comment in patch 3 says the problem doesn't apply to the data
>>>> register. Why does this check for these two registers rather than data?
>>> This Verify workaround patch still a work in progress.  I'm still
>>> getting more info from the silicon designers on the back-to-back
>>> register writes that are affect.  The spew of 0x20 or 0x28 or 0x2c
>>> register writes are all ok locations that don't need to be worked
>>> around.  This patch needs to be corrected with the proper register rules
>>> still.
> Thanks for testing.  Yes, I have work to do on the verify patch above
> still.

do you still have plans to submit a V3 of this patch series?

I attached an improved version of this patch which avoids a possible
endless loop caused by the dev_err call. So only the first occurence
of a specific register will be logged.

Regards
Stefan


-------------------8<-------------------------------------------

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1526b8a..7b0990f 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -306,6 +306,15 @@ config MMC_SDHCI_BCM2835

          If unsure, say N.

+config MMC_SDHCI_BCM2835_VERIFY_WORKAROUND
+       bool "Verify BCM2835 workaround does not do back to back writes"
+       depends on MMC_SDHCI_BCM2835
+       default y
+       help
+         This enables code that verifies the bcm2835 workaround.
+         The verification code checks that back to back writes to the same
+         register do not occur.
+
 config MMC_SDHCI_F_SDH30
        tristate "SDHCI support for Fujitsu Semiconductor F_SDH30"
        depends on MMC_SDHCI_PLTFM
diff --git a/drivers/mmc/host/sdhci-bcm2835.c
b/drivers/mmc/host/sdhci-bcm2835.c
index 01ce193d..c1c70df 100644
--- a/drivers/mmc/host/sdhci-bcm2835.c
+++ b/drivers/mmc/host/sdhci-bcm2835.c
@@ -20,15 +20,27 @@
  */

 #include <linux/delay.h>
+#include <linux/hashtable.h>
 #include <linux/module.h>
 #include <linux/mmc/host.h>
+#include <linux/slab.h>
 #include "sdhci-pltfm.h"

 struct bcm2835_sdhci_host {
        u32 shadow_cmd;
        u32 shadow_blk;
+       int previous_reg;
 };

+struct reg_hash {
+       struct hlist_node node;
+       int reg;
+};
+
+#define BCM2835_REG_HT_BITS 4
+
+static DEFINE_HASHTABLE(bcm2835_used_regs, BCM2835_REG_HT_BITS);
+
 #define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)

 static inline u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg)
@@ -56,8 +68,37 @@ static u8 bcm2835_sdhci_readb(struct sdhci_host
*host, int reg)
 }

 static inline void bcm2835_sdhci_writel(struct sdhci_host *host,
+                                       u32 val, int reg)
+{
+       writel(val, host->ioaddr + reg);
+}
+
+static inline void bcm2835_sdhci_writel_verify(struct sdhci_host *host,
                                                u32 val, int reg)
 {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct bcm2835_sdhci_host *bcm2835_host = pltfm_host->priv;
+       struct reg_hash *rh;
+       struct hlist_head *head;
+
+       head = &bcm2835_used_regs[hash_min(reg, BCM2835_REG_HT_BITS)];
+
+       if (bcm2835_host->previous_reg == reg) {
+               if ((reg != SDHCI_HOST_CONTROL) &&
+                   (reg != SDHCI_CLOCK_CONTROL) &&
+                   (hlist_empty(head))) {
+                       rh = kzalloc(sizeof(*rh), GFP_KERNEL);
+                       if (WARN_ON(!rh))
+                               return;
+
+                       rh->reg = reg;
+                       hash_add(bcm2835_used_regs, &rh->node, rh->reg);
+                       dev_err(mmc_dev(host->mmc), "back-to-back write to 
0x%x\n",
+                               reg);
+               }
+       }
+       bcm2835_host->previous_reg = reg;
+
        writel(val, host->ioaddr + reg);
 }

@@ -131,7 +172,11 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
        .read_l = bcm2835_sdhci_readl,
        .read_w = bcm2835_sdhci_readw,
        .read_b = bcm2835_sdhci_readb,
+#ifdef CONFIG_MMC_SDHCI_BCM2835_VERIFY_WORKAROUND
+       .write_l = bcm2835_sdhci_writel_verify,
+#else
        .write_l = bcm2835_sdhci_writel,
+#endif
        .write_w = bcm2835_sdhci_writew,
        .write_b = bcm2835_sdhci_writeb,
        .set_clock = sdhci_set_clock,



--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to