aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-s3c2410/mach-gta01.c63
-rw-r--r--drivers/mmc/host/s3cmci.c53
2 files changed, 68 insertions, 48 deletions
diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c
index 629fb7a49b6..6eb8eb3ac46 100644
--- a/arch/arm/mach-s3c2410/mach-gta01.c
+++ b/arch/arm/mach-s3c2410/mach-gta01.c
@@ -279,7 +279,6 @@ static void gta01_pmu_regulator_registered(struct pcf50606 *pcf, int id)
break;
case PCF50606_REGULATOR_D2REG:
gps_registered_regulators++;
- platform_device_register(&s3c_device_sdi);
break;
case PCF50606_REGULATOR_IOREG:
case PCF50606_REGULATOR_DCD:
@@ -551,6 +550,7 @@ static struct platform_device *gta01_devices[] __initdata = {
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
+ &s3c_device_sdi,
&s3c_device_usbgadget,
&s3c_device_nand,
&s3c_device_ts,
@@ -572,8 +572,69 @@ static struct s3c2410_platform_nand gta01_nand_info = {
.sets = gta01_nand_sets,
};
+static struct regulator *s3c_sdi_regulator;
+
+static void gta01_mmc_set_power(unsigned char power_mode, unsigned short vdd)
+{
+ int bit;
+ int mv = 1700; /* 1.7V for MMC_VDD_165_195 */
+ struct regulator *regulator;
+
+ printk(KERN_DEBUG "mmc_set_power(power_mode=%u, vdd=%u)\n",
+ power_mode, vdd);
+
+ if (!s3c_sdi_regulator) {
+ s3c_sdi_regulator =
+ regulator_get(&s3c_device_sdi.dev, "SD_3V3");
+ if (!s3c_sdi_regulator) {
+ printk(KERN_ERR "gta01_mmc_set_power : Cannot get regulator");
+ return;
+ }
+ }
+
+ regulator = s3c_sdi_regulator;
+
+ return;
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ switch (power_mode) {
+ case MMC_POWER_OFF:
+ regulator_disable(regulator);
+ break;
+ case MMC_POWER_ON:
+ /* translate MMC_VDD_* VDD bit to mv */
+ for (bit = 8; bit != 24; bit++)
+ if (vdd == (1 << bit))
+ mv += 100 * (bit - 4);
+ regulator_set_voltage(regulator, mv * 1000, mv * 10000);
+ break;
+ case MMC_POWER_UP:
+ regulator_enable(regulator);
+ break;
+ }
+ break;
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ switch (power_mode) {
+ case MMC_POWER_OFF:
+ neo1973_gpb_setpin(GTA01_GPIO_SDMMC_ON, 1);
+ break;
+ case MMC_POWER_ON:
+ neo1973_gpb_setpin(GTA01_GPIO_SDMMC_ON, 0);
+ break;
+ }
+ break;
+ }
+
+ if (regulator)
+ regulator_put(regulator);
+}
+
static struct s3c24xx_mci_pdata gta01_mmc_cfg = {
.gpio_detect = GTA01_GPIO_nSD_DETECT,
+ .set_power = &gta01_mmc_set_power,
.ocr_avail = MMC_VDD_165_195|MMC_VDD_20_21|
MMC_VDD_21_22|MMC_VDD_22_23|MMC_VDD_23_24|
MMC_VDD_24_25|MMC_VDD_25_26|MMC_VDD_26_27|
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 46414ce2f31..40522d62aac 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1109,42 +1109,18 @@ static void s3cmci_set_clk(struct s3cmci_host *host, struct mmc_ios *ios)
host->real_rate = 0;
}
-static int s3cmci_get_mv(int vdd)
-{
- int mv = 1700; /* 1.7V for MMC_VDD_165_195 */
- int bit;
-
- for (bit = 0; bit != 24; bit++)
- if (vdd == (1 << bit))
- mv += 100 * (bit - 4);
-
- return mv;
-}
-
static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct s3cmci_host *host = mmc_priv(mmc);
u32 mci_con;
- struct regulator *regulator;
- int mv;
/* Set the power state */
mci_con = readl(host->base + S3C2410_SDICON);
- regulator = host->regulator;
-
switch (ios->power_mode) {
- case MMC_POWER_UP:
- if (regulator) {
- mv = s3cmci_get_mv(ios->vdd);
- regulator_set_voltage(regulator, mv * 1000, mv * 1000);
- regulator_enable(regulator);
- } else if (host->pdata->set_power) {
- host->pdata->set_power(ios->power_mode, ios->vdd);
- } else
- dev_err(&host->pdev->dev, "Can't MMC_POWERUP\n");
case MMC_POWER_ON:
+ case MMC_POWER_UP:
s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
@@ -1152,37 +1128,26 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
- if (regulator) {
- mv = s3cmci_get_mv(ios->vdd);
- regulator_set_voltage(regulator, mv * 1000, mv * 1000);
- } else if (host->pdata->set_power) {
+ if (host->pdata->set_power)
host->pdata->set_power(ios->power_mode, ios->vdd);
- } else
- dev_err(&host->pdev->dev, "Can't MMC_POWERON\n");
-
+
if (!host->is2440)
mci_con |= S3C2410_SDICON_FIFORESET;
break;
case MMC_POWER_OFF:
+ default:
s3c2410_gpio_setpin(S3C2410_GPE5, 0);
s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
if (host->is2440)
mci_con |= S3C2440_SDICON_SDRESET;
- if (regulator) {
- if (regulator_is_enabled(regulator))
- regulator_disable(regulator);
- } else if (host->pdata->set_power) {
+ if (host->pdata->set_power)
host->pdata->set_power(ios->power_mode, ios->vdd);
- } else
- dev_err(&host->pdev->dev, "Can't MMC_POWEROFF\n");
-
+
break;
- default:
- printk(KERN_ERR "No such power mode %d\n", ios->power_mode);
}
s3cmci_set_clk(host, ios);
@@ -1464,12 +1429,6 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
goto free_dmabuf;
}
- host->regulator = regulator_get(&pdev->dev, "SD_3V3");
- if (IS_ERR(host->regulator)) {
- dev_err(&pdev->dev, "Regulator for SD_3V3 unavilable \n");
- host->regulator = NULL;
- }
-
ret = mmc_add_host(mmc);
if (ret) {
dev_err(&pdev->dev, "failed to add mmc host.\n");