ARM: 7218/1: mmc: mmci: Provide option to configure bus signal direction
authorUlf Hansson <ulf.hansson@stericsson.com>
Tue, 13 Dec 2011 15:57:07 +0000 (16:57 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 20 Jan 2012 00:00:56 +0000 (00:00 +0000)
The ST Micro variant supports bus signal direction indication. A new
member in the variant struct is added for this.

Moreover the actual signal direction configuration is board specific,
thus the amba mmci platform data is extended with a new member to be
able provide mmci with these specific board configurations.

This patch is based upon a patch from Sebastian Rasmussen.

Tested-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sebastian Rasmussen <sebastian.rasmussen@stericsson.com>
Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
drivers/mmc/host/mmci.c
drivers/mmc/host/mmci.h
include/linux/amba/mmci.h

index 7cc89beee87fa09dd576802d4590593debb4be63..eb11ce61941ddcdedb796c26dc0894898e9fa2b5 100644 (file)
@@ -54,6 +54,7 @@ static unsigned int fmax = 515633;
  * @st_clkdiv: true if using a ST-specific clock divider algorithm
  * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register
  * @pwrreg_powerup: power up value for MMCIPOWER register
+ * @signal_direction: input/out direction of bus signals can be indicated
  */
 struct variant_data {
        unsigned int            clkreg;
@@ -65,6 +66,7 @@ struct variant_data {
        bool                    st_clkdiv;
        bool                    blksz_datactrl16;
        u32                     pwrreg_powerup;
+       bool                    signal_direction;
 };
 
 static struct variant_data variant_arm = {
@@ -88,6 +90,7 @@ static struct variant_data variant_u300 = {
        .datalength_bits        = 16,
        .sdio                   = true,
        .pwrreg_powerup         = MCI_PWR_ON,
+       .signal_direction       = true,
 };
 
 static struct variant_data variant_ux500 = {
@@ -99,6 +102,7 @@ static struct variant_data variant_ux500 = {
        .sdio                   = true,
        .st_clkdiv              = true,
        .pwrreg_powerup         = MCI_PWR_ON,
+       .signal_direction       = true,
 };
 
 static struct variant_data variant_ux500v2 = {
@@ -111,6 +115,7 @@ static struct variant_data variant_ux500v2 = {
        .st_clkdiv              = true,
        .blksz_datactrl16       = true,
        .pwrreg_powerup         = MCI_PWR_ON,
+       .signal_direction       = true,
 };
 
 /*
@@ -1057,6 +1062,22 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                break;
        }
 
+       if (variant->signal_direction && ios->power_mode != MMC_POWER_OFF) {
+               /*
+                * The ST Micro variant has some additional bits
+                * indicating signal direction for the signals in
+                * the SD/MMC bus and feedback-clock usage.
+                */
+               pwr |= host->plat->sigdir;
+
+               if (ios->bus_width == MMC_BUS_WIDTH_4)
+                       pwr &= ~MCI_ST_DATA74DIREN;
+               else if (ios->bus_width == MMC_BUS_WIDTH_1)
+                       pwr &= (~MCI_ST_DATA74DIREN &
+                               ~MCI_ST_DATA31DIREN &
+                               ~MCI_ST_DATA2DIREN);
+       }
+
        if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
                if (host->hw_designer != AMBA_VENDOR_ST)
                        pwr |= MCI_ROD;
index 49f153e6ef7ab85969ae31f9fd82b350a70a589f..89eb2e3556d3a0c77a44d84d05a568963d6adcf4 100644 (file)
 #define MCI_PWR_ON             0x03
 #define MCI_OD                 (1 << 6)
 #define MCI_ROD                        (1 << 7)
-/*
- * The ST Micro version does not have ROD and reuse the voltage registers
- * for direction settings
- */
-#define MCI_ST_DATA2DIREN      (1 << 2)
-#define MCI_ST_CMDDIREN                (1 << 3)
-#define MCI_ST_DATA0DIREN      (1 << 4)
-#define MCI_ST_DATA31DIREN     (1 << 5)
-#define MCI_ST_FBCLKEN         (1 << 7)
-#define MCI_ST_DATA74DIREN     (1 << 8)
 
 #define MMCICLOCK              0x004
 #define MCI_CLK_ENABLE         (1 << 8)
index 0101e9c17fa1ec022c75f3655646c16aca9dd948..b51bf5fa85f89a5b6889837d51292cf263b17abd 100644 (file)
@@ -6,6 +6,19 @@
 
 #include <linux/mmc/host.h>
 
+
+/*
+ * These defines is places here due to access is needed from machine
+ * configuration files. The ST Micro version does not have ROD and
+ * reuse the voltage registers for direction settings.
+ */
+#define MCI_ST_DATA2DIREN      (1 << 2)
+#define MCI_ST_CMDDIREN                (1 << 3)
+#define MCI_ST_DATA0DIREN      (1 << 4)
+#define MCI_ST_DATA31DIREN     (1 << 5)
+#define MCI_ST_FBCLKEN         (1 << 7)
+#define MCI_ST_DATA74DIREN     (1 << 8)
+
 /* Just some dummy forwarding */
 struct dma_chan;
 
@@ -31,6 +44,8 @@ struct dma_chan;
  * @capabilities: the capabilities of the block as implemented in
  * this platform, signify anything MMC_CAP_* from mmc/host.h
  * @capabilities2: more capabilities, MMC_CAP2_* from mmc/host.h
+ * @sigdir: a bit field indicating for what bits in the MMC bus the host
+ * should enable signal direction indication.
  * @dma_filter: function used to select an appropriate RX and TX
  * DMA channel to be used for DMA, if and only if you're deploying the
  * generic DMA engine
@@ -54,6 +69,7 @@ struct mmci_platform_data {
        bool    cd_invert;
        unsigned long capabilities;
        unsigned long capabilities2;
+       u32 sigdir;
        bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
        void *dma_rx_param;
        void *dma_tx_param;