diff options
-rw-r--r-- | arch/arm/mach-s3c2410/mach-gta01.c | 63 | ||||
-rw-r--r-- | drivers/mmc/host/s3cmci.c | 53 |
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 = >a01_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"); |