diff options
| author | kishore kadiyala <kishore.kadiyala@ti.com> | 2010-05-15 14:21:25 -0400 |
|---|---|---|
| committer | Tony Lindgren <tony@atomide.com> | 2010-05-20 14:21:22 -0400 |
| commit | c83c8e6cde35c51a120952f54b4e4ecda6fa58a5 (patch) | |
| tree | fa92fc248a25905730352d317bbf67a0c0e20602 | |
| parent | 717c1fbf7c139c3c5d5920b29bdf196d07a40c8a (diff) | |
omap4: Adding PBIAS Configuration for MMC1 Controller
In OMAP4, MMC1 PBIAS and its associated IO is software-controlled
by CONTROL_PBIAS and CONTROL_MMC1 registers. This patch adds PBIAS
configuration for MMC1 Controller during power-ON and power-OFF
of regulator.
Signed-off-by: Kishore Kadiyala <kishore.kadiyala@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
| -rw-r--r-- | arch/arm/mach-omap2/hsmmc.c | 97 | ||||
| -rw-r--r-- | arch/arm/plat-omap/include/plat/control.h | 20 |
2 files changed, 108 insertions, 9 deletions
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 2d36f3afbd4e..1ef54b036103 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | static u16 control_pbias_offset; | 25 | static u16 control_pbias_offset; |
| 26 | static u16 control_devconf1_offset; | 26 | static u16 control_devconf1_offset; |
| 27 | static u16 control_mmc1; | ||
| 27 | 28 | ||
| 28 | #define HSMMC_NAME_LEN 9 | 29 | #define HSMMC_NAME_LEN 9 |
| 29 | 30 | ||
| @@ -42,7 +43,7 @@ static int hsmmc_get_context_loss(struct device *dev) | |||
| 42 | #define hsmmc_get_context_loss NULL | 43 | #define hsmmc_get_context_loss NULL |
| 43 | #endif | 44 | #endif |
| 44 | 45 | ||
| 45 | static void hsmmc1_before_set_reg(struct device *dev, int slot, | 46 | static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, |
| 46 | int power_on, int vdd) | 47 | int power_on, int vdd) |
| 47 | { | 48 | { |
| 48 | u32 reg, prog_io; | 49 | u32 reg, prog_io; |
| @@ -95,7 +96,7 @@ static void hsmmc1_before_set_reg(struct device *dev, int slot, | |||
| 95 | } | 96 | } |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | static void hsmmc1_after_set_reg(struct device *dev, int slot, | 99 | static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, |
| 99 | int power_on, int vdd) | 100 | int power_on, int vdd) |
| 100 | { | 101 | { |
| 101 | u32 reg; | 102 | u32 reg; |
| @@ -119,6 +120,60 @@ static void hsmmc1_after_set_reg(struct device *dev, int slot, | |||
| 119 | } | 120 | } |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 123 | static void omap4_hsmmc1_before_set_reg(struct device *dev, int slot, | ||
| 124 | int power_on, int vdd) | ||
| 125 | { | ||
| 126 | u32 reg; | ||
| 127 | |||
| 128 | /* | ||
| 129 | * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the | ||
| 130 | * card with Vcc regulator (from twl4030 or whatever). OMAP has both | ||
| 131 | * 1.8V and 3.0V modes, controlled by the PBIAS register. | ||
| 132 | * | ||
| 133 | * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which | ||
| 134 | * is most naturally TWL VSIM; those pins also use PBIAS. | ||
| 135 | * | ||
| 136 | * FIXME handle VMMC1A as needed ... | ||
| 137 | */ | ||
| 138 | reg = omap_ctrl_readl(control_pbias_offset); | ||
| 139 | reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ | | ||
| 140 | OMAP4_USBC1_ICUSB_PWRDNZ); | ||
| 141 | omap_ctrl_writel(reg, control_pbias_offset); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, | ||
| 145 | int power_on, int vdd) | ||
| 146 | { | ||
| 147 | u32 reg; | ||
| 148 | |||
| 149 | if (power_on) { | ||
| 150 | reg = omap_ctrl_readl(control_pbias_offset); | ||
| 151 | reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ; | ||
| 152 | if ((1 << vdd) <= MMC_VDD_165_195) | ||
| 153 | reg &= ~OMAP4_MMC1_PBIASLITE_VMODE; | ||
| 154 | else | ||
| 155 | reg |= OMAP4_MMC1_PBIASLITE_VMODE; | ||
| 156 | reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ | | ||
| 157 | OMAP4_USBC1_ICUSB_PWRDNZ); | ||
| 158 | omap_ctrl_writel(reg, control_pbias_offset); | ||
| 159 | /* 4 microsec delay for comparator to generate an error*/ | ||
| 160 | udelay(4); | ||
| 161 | reg = omap_ctrl_readl(control_pbias_offset); | ||
| 162 | if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR) { | ||
| 163 | pr_err("Pbias Voltage is not same as LDO\n"); | ||
| 164 | /* Caution : On VMODE_ERROR Power Down MMC IO */ | ||
| 165 | reg &= ~(OMAP4_MMC1_PWRDNZ | OMAP4_USBC1_ICUSB_PWRDNZ); | ||
| 166 | omap_ctrl_writel(reg, control_pbias_offset); | ||
| 167 | } | ||
| 168 | } else { | ||
| 169 | reg = omap_ctrl_readl(control_pbias_offset); | ||
| 170 | reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ | | ||
| 171 | OMAP4_MMC1_PBIASLITE_VMODE | OMAP4_MMC1_PWRDNZ | | ||
| 172 | OMAP4_USBC1_ICUSB_PWRDNZ); | ||
| 173 | omap_ctrl_writel(reg, control_pbias_offset); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 122 | static void hsmmc23_before_set_reg(struct device *dev, int slot, | 177 | static void hsmmc23_before_set_reg(struct device *dev, int slot, |
| 123 | int power_on, int vdd) | 178 | int power_on, int vdd) |
| 124 | { | 179 | { |
| @@ -152,13 +207,28 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) | |||
| 152 | struct omap2_hsmmc_info *c; | 207 | struct omap2_hsmmc_info *c; |
| 153 | int nr_hsmmc = ARRAY_SIZE(hsmmc_data); | 208 | int nr_hsmmc = ARRAY_SIZE(hsmmc_data); |
| 154 | int i; | 209 | int i; |
| 210 | u32 reg; | ||
| 155 | 211 | ||
| 156 | if (cpu_is_omap2430()) { | 212 | if (!cpu_is_omap44xx()) { |
| 157 | control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; | 213 | if (cpu_is_omap2430()) { |
| 158 | control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1; | 214 | control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; |
| 215 | control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1; | ||
| 216 | } else { | ||
| 217 | control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE; | ||
| 218 | control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1; | ||
| 219 | } | ||
| 159 | } else { | 220 | } else { |
| 160 | control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE; | 221 | control_pbias_offset = OMAP44XX_CONTROL_PBIAS_LITE; |
| 161 | control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1; | 222 | control_mmc1 = OMAP44XX_CONTROL_MMC1; |
| 223 | reg = omap_ctrl_readl(control_mmc1); | ||
| 224 | reg |= (OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0 | | ||
| 225 | OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1); | ||
| 226 | reg &= ~(OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2 | | ||
| 227 | OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3); | ||
| 228 | reg |= (OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL | | ||
| 229 | OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL | | ||
| 230 | OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL); | ||
| 231 | omap_ctrl_writel(reg, control_mmc1); | ||
| 162 | } | 232 | } |
| 163 | 233 | ||
| 164 | for (c = controllers; c->mmc; c++) { | 234 | for (c = controllers; c->mmc; c++) { |
| @@ -231,8 +301,17 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) | |||
| 231 | case 1: | 301 | case 1: |
| 232 | if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { | 302 | if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { |
| 233 | /* on-chip level shifting via PBIAS0/PBIAS1 */ | 303 | /* on-chip level shifting via PBIAS0/PBIAS1 */ |
| 234 | mmc->slots[0].before_set_reg = hsmmc1_before_set_reg; | 304 | if (cpu_is_omap44xx()) { |
| 235 | mmc->slots[0].after_set_reg = hsmmc1_after_set_reg; | 305 | mmc->slots[0].before_set_reg = |
| 306 | omap4_hsmmc1_before_set_reg; | ||
| 307 | mmc->slots[0].after_set_reg = | ||
| 308 | omap4_hsmmc1_after_set_reg; | ||
| 309 | } else { | ||
| 310 | mmc->slots[0].before_set_reg = | ||
| 311 | omap_hsmmc1_before_set_reg; | ||
| 312 | mmc->slots[0].after_set_reg = | ||
| 313 | omap_hsmmc1_after_set_reg; | ||
| 314 | } | ||
| 236 | } | 315 | } |
| 237 | 316 | ||
| 238 | /* Omap3630 HSMMC1 supports only 4-bit */ | 317 | /* Omap3630 HSMMC1 supports only 4-bit */ |
diff --git a/arch/arm/plat-omap/include/plat/control.h b/arch/arm/plat-omap/include/plat/control.h index a56deee97676..131bf405c2f6 100644 --- a/arch/arm/plat-omap/include/plat/control.h +++ b/arch/arm/plat-omap/include/plat/control.h | |||
| @@ -207,6 +207,9 @@ | |||
| 207 | /* 44xx control status register offset */ | 207 | /* 44xx control status register offset */ |
| 208 | #define OMAP44XX_CONTROL_STATUS 0x2c4 | 208 | #define OMAP44XX_CONTROL_STATUS 0x2c4 |
| 209 | 209 | ||
| 210 | /* 44xx-only CONTROL_GENERAL register offsets */ | ||
| 211 | #define OMAP44XX_CONTROL_MMC1 0x628 | ||
| 212 | #define OMAP44XX_CONTROL_PBIAS_LITE 0x600 | ||
| 210 | /* | 213 | /* |
| 211 | * REVISIT: This list of registers is not comprehensive - there are more | 214 | * REVISIT: This list of registers is not comprehensive - there are more |
| 212 | * that should be added. | 215 | * that should be added. |
| @@ -252,6 +255,23 @@ | |||
| 252 | #define OMAP2_PBIASLITEPWRDNZ0 (1 << 1) | 255 | #define OMAP2_PBIASLITEPWRDNZ0 (1 << 1) |
| 253 | #define OMAP2_PBIASLITEVMODE0 (1 << 0) | 256 | #define OMAP2_PBIASLITEVMODE0 (1 << 0) |
| 254 | 257 | ||
| 258 | /* CONTROL_PBIAS_LITE bits for OMAP4 */ | ||
| 259 | #define OMAP4_MMC1_PWRDNZ (1 << 26) | ||
| 260 | #define OMAP4_MMC1_PBIASLITE_HIZ_MODE (1 << 25) | ||
| 261 | #define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT (1 << 24) | ||
| 262 | #define OMAP4_MMC1_PBIASLITE_VMODE_ERROR (1 << 23) | ||
| 263 | #define OMAP4_MMC1_PBIASLITE_PWRDNZ (1 << 22) | ||
| 264 | #define OMAP4_MMC1_PBIASLITE_VMODE (1 << 21) | ||
| 265 | #define OMAP4_USBC1_ICUSB_PWRDNZ (1 << 20) | ||
| 266 | |||
| 267 | #define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0 (1 << 31) | ||
| 268 | #define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1 (1 << 30) | ||
| 269 | #define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2 (1 << 29) | ||
| 270 | #define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3 (1 << 28) | ||
| 271 | #define OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL (1 << 27) | ||
| 272 | #define OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL (1 << 26) | ||
| 273 | #define OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL (1 << 25) | ||
| 274 | |||
| 255 | /* CONTROL_PROG_IO1 bits */ | 275 | /* CONTROL_PROG_IO1 bits */ |
| 256 | #define OMAP3630_PRG_SDMMC1_SPEEDCTRL (1 << 20) | 276 | #define OMAP3630_PRG_SDMMC1_SPEEDCTRL (1 << 20) |
| 257 | 277 | ||
