ANDROID: mmc: sdio: Add concept of an 'embedded' SDIO device.
authorSan Mehat <san@android.com>
Mon, 14 Apr 2008 22:22:49 +0000 (15:22 -0700)
committerAmit Pundir <amit.pundir@linaro.org>
Mon, 18 Dec 2017 15:41:22 +0000 (21:11 +0530)
This is required to support chips which use SDIO for signaling/
communication but do not implement the various card enumeration registers
as required for full SD / SDIO cards.

mmc: sdio: Fix bug where we're freeing the CIS tables we never allocated when using EMBEDDED_SDIO
mmc: Add max_blksize to embedded SDIO data

Change-Id: Ibff2e3e991e5522f55ec8c6edc25ed09f2553736
Signed-off-by: San Mehat <san@google.com>
[AmitP: Rebased the original commit to align with the upstream commit
        5fc3d80ef496 ("mmc: sdio: don't use rocr to check if the card could support UHS mode")

        Also folded following android-4.9 commit changes into this patch
        d775b65ecaf6 ("ANDROID: mmc: core: Remove stray CONFIG_EXPERIMENTAL dependencies")]
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
drivers/mmc/core/Kconfig
drivers/mmc/core/core.c
drivers/mmc/core/sdio.c
drivers/mmc/core/sdio_bus.c
include/linux/amba/mmci.h
include/linux/mmc/host.h
include/linux/mmc/sdio_func.h

index 0b004586c80341ec7bb43a25b113ab8039aed9e6..b3faf1062d4eb5fb82e8aa1e2f7c749f4e463c64 100644 (file)
@@ -80,8 +80,15 @@ config MMC_TEST
          This driver is only of interest to those developing or
          testing a host driver. Most people should say N here.
 
+config MMC_EMBEDDED_SDIO
+       boolean "MMC embedded SDIO device support"
+       help
+         If you say Y here, support will be added for embedded SDIO
+         devices which do not contain the necessary enumeration
+         support in hardware to be properly detected.
+
 config MMC_PARANOID_SD_INIT
-       bool "Enable paranoid SD card initialization (EXPERIMENTAL)"
+       bool "Enable paranoid SD card initialization"
        help
          If you say Y here, the MMC layer will be extra paranoid
          about re-trying SD init requests. This can be a useful
index 66c9cf49ad2f11fe59de05eae716b6b797766cc4..41ac8292192268313a773e8d1041f11c7709fc9f 100644 (file)
@@ -2802,6 +2802,22 @@ void mmc_init_context_info(struct mmc_host *host)
        init_waitqueue_head(&host->context_info.wait);
 }
 
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+void mmc_set_embedded_sdio_data(struct mmc_host *host,
+                               struct sdio_cis *cis,
+                               struct sdio_cccr *cccr,
+                               struct sdio_embedded_func *funcs,
+                               int num_funcs)
+{
+       host->embedded_sdio_data.cis = cis;
+       host->embedded_sdio_data.cccr = cccr;
+       host->embedded_sdio_data.funcs = funcs;
+       host->embedded_sdio_data.num_funcs = num_funcs;
+}
+
+EXPORT_SYMBOL(mmc_set_embedded_sdio_data);
+#endif
+
 static int __init mmc_init(void)
 {
        int ret;
index cc43687ca241918fe40d8511eab5fe6ecb848d52..c42e3cd537f288c477eaa48a705659cda6694024 100644 (file)
 #include "sdio_ops.h"
 #include "sdio_cis.h"
 
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+#include <linux/mmc/sdio_ids.h>
+#endif
+
 static int sdio_read_fbr(struct sdio_func *func)
 {
        int ret;
@@ -706,28 +710,44 @@ try_again:
                goto finish;
        }
 
-       /*
-        * Read the common registers. Note that we should try to
-        * validate whether UHS would work or not.
-        */
-       err = sdio_read_cccr(card, ocr);
-       if (err) {
-               mmc_sdio_resend_if_cond(host, card);
-               if (ocr & R4_18V_PRESENT) {
-                       /* Retry init sequence, but without R4_18V_PRESENT. */
-                       retries = 0;
-                       goto try_again;
-               } else {
-                       goto remove;
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+       if (host->embedded_sdio_data.cccr)
+               memcpy(&card->cccr, host->embedded_sdio_data.cccr, sizeof(struct sdio_cccr));
+       else {
+#endif
+               /*
+                * Read the common registers. Note that we should try to
+                * validate whether UHS would work or not.
+                */
+               err = sdio_read_cccr(card, ocr);
+               if (err) {
+                       mmc_sdio_resend_if_cond(host, card);
+                       if (ocr & R4_18V_PRESENT) {
+                               /* Retry init sequence, but without R4_18V_PRESENT. */
+                               retries = 0;
+                               goto try_again;
+                       } else {
+                               goto remove;
+                       }
                }
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
        }
+#endif
 
-       /*
-        * Read the common CIS tuples.
-        */
-       err = sdio_read_common_cis(card);
-       if (err)
-               goto remove;
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+       if (host->embedded_sdio_data.cis)
+               memcpy(&card->cis, host->embedded_sdio_data.cis, sizeof(struct sdio_cis));
+       else {
+#endif
+               /*
+                * Read the common CIS tuples.
+                */
+               err = sdio_read_common_cis(card);
+               if (err)
+                       goto remove;
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+       }
+#endif
 
        if (oldcard) {
                int same = (card->cis.vendor == oldcard->cis.vendor &&
@@ -1129,14 +1149,36 @@ int mmc_attach_sdio(struct mmc_host *host)
        funcs = (ocr & 0x70000000) >> 28;
        card->sdio_funcs = 0;
 
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+       if (host->embedded_sdio_data.funcs)
+               card->sdio_funcs = funcs = host->embedded_sdio_data.num_funcs;
+#endif
+
        /*
         * Initialize (but don't add) all present functions.
         */
        for (i = 0; i < funcs; i++, card->sdio_funcs++) {
-               err = sdio_init_func(host->card, i + 1);
-               if (err)
-                       goto remove;
-
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+               if (host->embedded_sdio_data.funcs) {
+                       struct sdio_func *tmp;
+
+                       tmp = sdio_alloc_func(host->card);
+                       if (IS_ERR(tmp))
+                               goto remove;
+                       tmp->num = (i + 1);
+                       card->sdio_func[i] = tmp;
+                       tmp->class = host->embedded_sdio_data.funcs[i].f_class;
+                       tmp->max_blksize = host->embedded_sdio_data.funcs[i].f_maxblksize;
+                       tmp->vendor = card->cis.vendor;
+                       tmp->device = card->cis.device;
+               } else {
+#endif
+                       err = sdio_init_func(host->card, i + 1);
+                       if (err)
+                               goto remove;
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+               }
+#endif
                /*
                 * Enable Runtime PM for this func (if supported)
                 */
index 2b32b88949ba40dfb3901cf9588f670b7aad8441..997d556fccf1ca5675317ad6955ea146a3b21003 100644 (file)
 #include "sdio_cis.h"
 #include "sdio_bus.h"
 
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+#include <linux/mmc/host.h>
+#endif
+
 #define to_sdio_driver(d)      container_of(d, struct sdio_driver, drv)
 
 /* show configuration fields */
@@ -264,7 +268,14 @@ static void sdio_release_func(struct device *dev)
 {
        struct sdio_func *func = dev_to_sdio_func(dev);
 
-       sdio_free_func_cis(func);
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+       /*
+        * If this device is embedded then we never allocated
+        * cis tables for this func
+        */
+       if (!func->card->host->embedded_sdio_data.funcs)
+#endif
+               sdio_free_func_cis(func);
 
        kfree(func->info);
        kfree(func->tmpbuf);
index da8357ba11bcb45b52a2c23d2e0aedb9c51096e0..02dc2f3a76f74a472ab1dde8567fe21ad06487c7 100644 (file)
@@ -6,6 +6,15 @@
 #define AMBA_MMCI_H
 
 #include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+
+struct embedded_sdio_data {
+        struct sdio_cis cis;
+        struct sdio_cccr cccr;
+        struct sdio_embedded_func *funcs;
+        int num_funcs;
+};
 
 /**
  * struct mmci_platform_data - platform configuration for the MMCI
@@ -32,6 +41,7 @@ struct mmci_platform_data {
        int     gpio_wp;
        int     gpio_cd;
        bool    cd_invert;
+       struct embedded_sdio_data *embedded_sdio;
 };
 
 #endif
index 9a43763a68adb3e998ec942300688f99e065489b..227961c5011b523e820b78c11cb70e0f33506504 100644 (file)
@@ -439,6 +439,15 @@ struct mmc_host {
        bool                    cqe_enabled;
        bool                    cqe_on;
 
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+       struct {
+               struct sdio_cis                 *cis;
+               struct sdio_cccr                *cccr;
+               struct sdio_embedded_func       *funcs;
+               int                             num_funcs;
+       } embedded_sdio_data;
+#endif
+
        unsigned long           private[0] ____cacheline_aligned;
 };
 
@@ -451,6 +460,14 @@ void mmc_free_host(struct mmc_host *);
 int mmc_of_parse(struct mmc_host *host);
 int mmc_of_parse_voltage(struct device_node *np, u32 *mask);
 
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+extern void mmc_set_embedded_sdio_data(struct mmc_host *host,
+                                      struct sdio_cis *cis,
+                                      struct sdio_cccr *cccr,
+                                      struct sdio_embedded_func *funcs,
+                                      int num_funcs);
+#endif
+
 static inline void *mmc_priv(struct mmc_host *host)
 {
        return (void *)host->private;
index 97ca105347a6c5e608297ae1a3562925dc6f6834..f466f381ad25cfb87ed96dd3457b168ee42c1c21 100644 (file)
@@ -22,6 +22,14 @@ struct sdio_func;
 
 typedef void (sdio_irq_handler_t)(struct sdio_func *);
 
+/*
+ * Structure used to hold embedded SDIO device data from platform layer
+ */
+struct sdio_embedded_func {
+       uint8_t f_class;
+       uint32_t f_maxblksize;
+};
+
 /*
  * SDIO function CIS tuple (unknown to the core)
  */