Commit 19206b17 authored by Marek Szyprowski's avatar Marek Szyprowski Committed by Kukjin Kim

ARM: SAMSUNG: Add new s3c-sdhci card detection methods for Samsung SoCs

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: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: default avatarKyungmin 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: default avatarKukjin Kim <kgene.kim@samsung.com>
parent b3c674bc
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
#include <mach/gpio.h> #include <mach/gpio.h>
#include <plat/gpio-cfg.h> #include <plat/gpio-cfg.h>
#include <plat/sdhci.h>
void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) 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 gpio;
unsigned int end; unsigned int end;
...@@ -33,12 +35,15 @@ void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) ...@@ -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(gpio, S3C_GPIO_PULL_NONE);
} }
s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2)); 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) 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 gpio;
unsigned int end; unsigned int end;
...@@ -50,8 +55,10 @@ void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) ...@@ -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(gpio, S3C_GPIO_PULL_NONE);
} }
s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3)); 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) void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
......
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
#include <plat/gpio-cfg.h> #include <plat/gpio-cfg.h>
#include <plat/regs-sdhci.h> #include <plat/regs-sdhci.h>
#include <plat/sdhci.h>
void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) 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 gpio;
unsigned int end; unsigned int end;
unsigned int num; unsigned int num;
...@@ -47,12 +49,15 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) ...@@ -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); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_cfgpin(S5PC100_GPG1(2), S3C_GPIO_SFN(2)); 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) 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 gpio;
unsigned int end; unsigned int end;
...@@ -64,12 +69,15 @@ void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) ...@@ -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(gpio, S3C_GPIO_PULL_NONE);
} }
s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_cfgpin(S5PC100_GPG2(6), S3C_GPIO_SFN(2)); 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) 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 gpio;
unsigned int end; unsigned int end;
...@@ -81,6 +89,8 @@ void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) ...@@ -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(gpio, S3C_GPIO_PULL_NONE);
} }
s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_cfgpin(S5PC100_GPG3(6), S3C_GPIO_SFN(2)); s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PC100_GPG3(6), S3C_GPIO_SFN(2));
}
} }
...@@ -21,9 +21,11 @@ ...@@ -21,9 +21,11 @@
#include <mach/gpio.h> #include <mach/gpio.h>
#include <plat/gpio-cfg.h> #include <plat/gpio-cfg.h>
#include <plat/regs-sdhci.h> #include <plat/regs-sdhci.h>
#include <plat/sdhci.h>
void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
{ {
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio; unsigned int gpio;
/* Set all the necessary GPG0/GPG1 pins to special-function 2 */ /* 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) ...@@ -48,12 +50,15 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
break; break;
} }
s3c_gpio_setpull(S5PV210_GPG0(2), S3C_GPIO_PULL_UP); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_cfgpin(S5PV210_GPG0(2), S3C_GPIO_SFN(2)); 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) void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
{ {
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio; unsigned int gpio;
/* Set all the necessary GPG1[0:1] pins to special-function 2 */ /* 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) ...@@ -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(gpio, S3C_GPIO_PULL_NONE);
} }
s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_cfgpin(S5PV210_GPG1(2), S3C_GPIO_SFN(2)); 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) void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
{ {
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio; unsigned int gpio;
/* Set all the necessary GPG2[0:1] pins to special-function 2 */ /* 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) ...@@ -99,6 +107,8 @@ void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
break; break;
} }
s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2)); s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2));
}
} }
...@@ -60,6 +60,11 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd) ...@@ -60,6 +60,11 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata;
set->max_width = pd->max_width; 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) if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio; set->cfg_gpio = pd->cfg_gpio;
......
...@@ -60,6 +60,11 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd) ...@@ -60,6 +60,11 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata;
set->max_width = pd->max_width; 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) if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio; set->cfg_gpio = pd->cfg_gpio;
......
...@@ -61,6 +61,11 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd) ...@@ -61,6 +61,11 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata; struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata;
set->max_width = pd->max_width; 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) if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio; set->cfg_gpio = pd->cfg_gpio;
......
...@@ -64,6 +64,11 @@ void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd) ...@@ -64,6 +64,11 @@ void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata; struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata;
set->max_width = pd->max_width; 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) if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio; set->cfg_gpio = pd->cfg_gpio;
......
...@@ -20,10 +20,31 @@ struct mmc_host; ...@@ -20,10 +20,31 @@ struct mmc_host;
struct mmc_card; struct mmc_card;
struct mmc_ios; 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 * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
* @max_width: The maximum number of data bits supported. * @max_width: The maximum number of data bits supported.
* @host_caps: Standard MMC host capabilities bit field. * @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_gpio: Configure the GPIO for a specific card bit-width
* @cfg_card: Configure the interface for a specific card and speed. This * @cfg_card: Configure the interface for a specific card and speed. This
* is necessary the controllers and/or GPIO blocks require the * is necessary the controllers and/or GPIO blocks require the
...@@ -37,9 +58,17 @@ struct mmc_ios; ...@@ -37,9 +58,17 @@ struct mmc_ios;
struct s3c_sdhci_platdata { struct s3c_sdhci_platdata {
unsigned int max_width; unsigned int max_width;
unsigned int host_caps; unsigned int host_caps;
enum cd_types cd_type;
char **clocks; /* set of clock sources */ 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_gpio)(struct platform_device *dev, int width);
void (*cfg_card)(struct platform_device *dev, void (*cfg_card)(struct platform_device *dev,
void __iomem *regbase, void __iomem *regbase,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment