]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
ARM: SAMSUNG: Add new s3c-sdhci card detection methods for Samsung SoCs
authorMarek Szyprowski <m.szyprowski@samsung.com>
Fri, 23 Jul 2010 00:27:18 +0000 (09:27 +0900)
committerKukjin Kim <kgene.kim@samsung.com>
Thu, 5 Aug 2010 09:32:50 +0000 (18:32 +0900)
On some Samsung SoCs not all SDHCI controllers have card detect (CD)
line. For some embedded designs it is not even needed, because ususally
the device (like SDIO flash memory or wifi controller) is permanently
wired to the controller. There are also systems which have a card detect
line connected to some of the external interrupt lines or the presence
of the card depends on some other actions (like enabling a power
regulator).

This patch adds all required changes to platform support code, so
another patch, which extends the driver with support for the new card
detection methods can be applied.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
[kgene.kim@samsung.com: minor title and coding-style fixes]
[kgene.kim@samsung.com: fix build errors]
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
arch/arm/mach-s3c64xx/setup-sdhci-gpio.c
arch/arm/mach-s5pc100/setup-sdhci-gpio.c
arch/arm/mach-s5pv210/setup-sdhci-gpio.c
arch/arm/plat-samsung/dev-hsmmc.c
arch/arm/plat-samsung/dev-hsmmc1.c
arch/arm/plat-samsung/dev-hsmmc2.c
arch/arm/plat-samsung/dev-hsmmc3.c
arch/arm/plat-samsung/include/plat/sdhci.h

index a58c0cc7ba5e63b8367232970c3e22da89f4707d..4a42ede9902570f33a19af2f4968c50eecf82ef4 100644 (file)
 
 #include <mach/gpio.h>
 #include <plat/gpio-cfg.h>
+#include <plat/sdhci.h>
 
 void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
 {
+       struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
        unsigned int gpio;
        unsigned int end;
 
@@ -33,12 +35,15 @@ void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
                s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
        }
 
-       s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
+               s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
+       }
 }
 
 void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
 {
+       struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
        unsigned int gpio;
        unsigned int end;
 
@@ -50,8 +55,10 @@ void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
                s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
        }
 
-       s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
+               s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
+       }
 }
 
 void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
index 7769c760c9ef525eeec0ff7dd35a5403c31b7587..dc7208c639ea0804a80700dd43a917c5b8ee5e01 100644 (file)
 
 #include <plat/gpio-cfg.h>
 #include <plat/regs-sdhci.h>
+#include <plat/sdhci.h>
 
 void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
 {
+       struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
        unsigned int gpio;
        unsigned int end;
        unsigned int num;
@@ -47,12 +49,15 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
                }
        }
 
-       s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S5PC100_GPG1(2), S3C_GPIO_SFN(2));
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP);
+               s3c_gpio_cfgpin(S5PC100_GPG1(2), S3C_GPIO_SFN(2));
+       }
 }
 
 void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
 {
+       struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
        unsigned int gpio;
        unsigned int end;
 
@@ -64,12 +69,15 @@ void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
                s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
        }
 
-       s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S5PC100_GPG2(6), S3C_GPIO_SFN(2));
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP);
+               s3c_gpio_cfgpin(S5PC100_GPG2(6), S3C_GPIO_SFN(2));
+       }
 }
 
 void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
 {
+       struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
        unsigned int gpio;
        unsigned int end;
 
@@ -81,6 +89,8 @@ void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
                s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
        }
 
-       s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S5PC100_GPG3(6), S3C_GPIO_SFN(2));
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP);
+               s3c_gpio_cfgpin(S5PC100_GPG3(6), S3C_GPIO_SFN(2));
+       }
 }
index fe7d86dad14cdc3524c842c0aed6600d75b95464..b3ad2439e34b3d4270062500f21d9cc4ade4d2b4 100644 (file)
 #include <mach/gpio.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-sdhci.h>
+#include <plat/sdhci.h>
 
 void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
 {
+       struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
        unsigned int gpio;
 
        /* Set all the necessary GPG0/GPG1 pins to special-function 2 */
@@ -48,12 +50,15 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
                break;
        }
 
-       s3c_gpio_setpull(S5PV210_GPG0(2), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S5PV210_GPG0(2), S3C_GPIO_SFN(2));
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               s3c_gpio_setpull(S5PV210_GPG0(2), S3C_GPIO_PULL_UP);
+               s3c_gpio_cfgpin(S5PV210_GPG0(2), S3C_GPIO_SFN(2));
+       }
 }
 
 void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
 {
+       struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
        unsigned int gpio;
 
        /* Set all the necessary GPG1[0:1] pins to special-function 2 */
@@ -68,12 +73,15 @@ void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
                s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
        }
 
-       s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S5PV210_GPG1(2), S3C_GPIO_SFN(2));
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
+               s3c_gpio_cfgpin(S5PV210_GPG1(2), S3C_GPIO_SFN(2));
+       }
 }
 
 void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
 {
+       struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
        unsigned int gpio;
 
        /* Set all the necessary GPG2[0:1] pins to special-function 2 */
@@ -99,6 +107,8 @@ void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
                break;
        }
 
-       s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2));
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP);
+               s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2));
+       }
 }
index 4c05b39810e27f49bd26e36189e5fd07861a8ec2..b0f93f11e281877dbfb69407d8506f7c1433051d 100644 (file)
@@ -60,6 +60,11 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
        struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata;
 
        set->max_width = pd->max_width;
+       set->cd_type = pd->cd_type;
+       set->ext_cd_init = pd->ext_cd_init;
+       set->ext_cd_cleanup = pd->ext_cd_cleanup;
+       set->ext_cd_gpio = pd->ext_cd_gpio;
+       set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
 
        if (pd->cfg_gpio)
                set->cfg_gpio = pd->cfg_gpio;
index e49bc4cd0ee6a0412177f4f48ceb1a105ac0c3d0..1504fd802865c3917fea63059604b95ee302db1b 100644 (file)
@@ -60,6 +60,11 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
        struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata;
 
        set->max_width = pd->max_width;
+       set->cd_type = pd->cd_type;
+       set->ext_cd_init = pd->ext_cd_init;
+       set->ext_cd_cleanup = pd->ext_cd_cleanup;
+       set->ext_cd_gpio = pd->ext_cd_gpio;
+       set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
 
        if (pd->cfg_gpio)
                set->cfg_gpio = pd->cfg_gpio;
index 824580bc0e06d4761c7a13d3994159eb4a76e754..b28ef173444d282676e86370737d41da5d073e7c 100644 (file)
@@ -61,6 +61,11 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
        struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata;
 
        set->max_width = pd->max_width;
+       set->cd_type = pd->cd_type;
+       set->ext_cd_init = pd->ext_cd_init;
+       set->ext_cd_cleanup = pd->ext_cd_cleanup;
+       set->ext_cd_gpio = pd->ext_cd_gpio;
+       set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
 
        if (pd->cfg_gpio)
                set->cfg_gpio = pd->cfg_gpio;
index 57bd394123cd4bb2760aeeab04de72f12d79a02a..85aaf0f2842f8ac1e214a3ecdd8d6102b9fffc26 100644 (file)
@@ -64,6 +64,11 @@ void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
        struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata;
 
        set->max_width = pd->max_width;
+       set->cd_type = pd->cd_type;
+       set->ext_cd_init = pd->ext_cd_init;
+       set->ext_cd_cleanup = pd->ext_cd_cleanup;
+       set->ext_cd_gpio = pd->ext_cd_gpio;
+       set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
 
        if (pd->cfg_gpio)
                set->cfg_gpio = pd->cfg_gpio;
index 3994a875473bbbac1f1743878554823381b19300..3880cc736a984e3d0720c7411d43211f450acc9c 100644 (file)
@@ -20,10 +20,31 @@ struct mmc_host;
 struct mmc_card;
 struct mmc_ios;
 
+enum cd_types {
+       S3C_SDHCI_CD_INTERNAL,  /* use mmc internal CD line */
+       S3C_SDHCI_CD_EXTERNAL,  /* use external callback */
+       S3C_SDHCI_CD_GPIO,      /* use external gpio pin for CD line */
+       S3C_SDHCI_CD_NONE,      /* no CD line, use polling to detect card */
+       S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */
+};
+
 /**
  * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
  * @max_width: The maximum number of data bits supported.
  * @host_caps: Standard MMC host capabilities bit field.
+ * @cd_type: Type of Card Detection method (see cd_types enum above)
+ * @ext_cd_init: Initialize external card detect subsystem. Called on
+ *              sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL.
+ *              notify_func argument is a callback to the sdhci-s3c driver
+ *              that triggers the card detection event. Callback arguments:
+ *              dev is pointer to platform device of the host controller,
+ *              state is new state of the card (0 - removed, 1 - inserted).
+ * @ext_cd_cleanup: Cleanup external card detect subsystem. Called on
+ *              sdhci-s3c driver remove when cd_type == S3C_SDHCI_CD_EXTERNAL.
+ *              notify_func argument is the same callback as for ext_cd_init.
+ * @ext_cd_gpio: gpio pin used for external CD line, valid only if
+ *              cd_type == S3C_SDHCI_CD_GPIO
+ * @ext_cd_gpio_invert: invert values for external CD gpio line
  * @cfg_gpio: Configure the GPIO for a specific card bit-width
  * @cfg_card: Configure the interface for a specific card and speed. This
  *            is necessary the controllers and/or GPIO blocks require the
@@ -37,9 +58,17 @@ struct mmc_ios;
 struct s3c_sdhci_platdata {
        unsigned int    max_width;
        unsigned int    host_caps;
+       enum cd_types   cd_type;
 
        char            **clocks;       /* set of clock sources */
 
+       int             ext_cd_gpio;
+       bool            ext_cd_gpio_invert;
+       int     (*ext_cd_init)(void (*notify_func)(struct platform_device *,
+                                                  int state));
+       int     (*ext_cd_cleanup)(void (*notify_func)(struct platform_device *,
+                                                     int state));
+
        void    (*cfg_gpio)(struct platform_device *dev, int width);
        void    (*cfg_card)(struct platform_device *dev,
                            void __iomem *regbase,