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 /arch/arm/mach-omap2/hsmmc.c | |
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>
Diffstat (limited to 'arch/arm/mach-omap2/hsmmc.c')
-rw-r--r-- | arch/arm/mach-omap2/hsmmc.c | 97 |
1 files changed, 88 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 */ |