diff options
Diffstat (limited to 'arch/arm/mach-omap2/mmc-twl4030.c')
-rw-r--r-- | arch/arm/mach-omap2/mmc-twl4030.c | 187 |
1 files changed, 131 insertions, 56 deletions
diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 437f52073f6e..dc40b3e72206 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
19 | #include <linux/i2c/twl4030.h> | 19 | #include <linux/i2c/twl4030.h> |
20 | #include <linux/regulator/machine.h> | ||
20 | 21 | ||
21 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
22 | #include <mach/control.h> | 23 | #include <mach/control.h> |
@@ -44,6 +45,7 @@ | |||
44 | #define VMMC2_315V 0x0c | 45 | #define VMMC2_315V 0x0c |
45 | #define VMMC2_300V 0x0b | 46 | #define VMMC2_300V 0x0b |
46 | #define VMMC2_285V 0x0a | 47 | #define VMMC2_285V 0x0a |
48 | #define VMMC2_280V 0x09 | ||
47 | #define VMMC2_260V 0x08 | 49 | #define VMMC2_260V 0x08 |
48 | #define VMMC2_185V 0x06 | 50 | #define VMMC2_185V 0x06 |
49 | #define VMMC2_DEDICATED 0x2E | 51 | #define VMMC2_DEDICATED 0x2E |
@@ -59,8 +61,8 @@ static struct twl_mmc_controller { | |||
59 | struct omap_mmc_platform_data *mmc; | 61 | struct omap_mmc_platform_data *mmc; |
60 | u8 twl_vmmc_dev_grp; | 62 | u8 twl_vmmc_dev_grp; |
61 | u8 twl_mmc_dedicated; | 63 | u8 twl_mmc_dedicated; |
62 | char name[HSMMC_NAME_LEN]; | 64 | char name[HSMMC_NAME_LEN + 1]; |
63 | } hsmmc[] = { | 65 | } hsmmc[OMAP34XX_NR_MMC] = { |
64 | { | 66 | { |
65 | .twl_vmmc_dev_grp = VMMC1_DEV_GRP, | 67 | .twl_vmmc_dev_grp = VMMC1_DEV_GRP, |
66 | .twl_mmc_dedicated = VMMC1_DEDICATED, | 68 | .twl_mmc_dedicated = VMMC1_DEDICATED, |
@@ -98,6 +100,14 @@ static int twl_mmc_get_ro(struct device *dev, int slot) | |||
98 | return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); | 100 | return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); |
99 | } | 101 | } |
100 | 102 | ||
103 | static int twl_mmc_get_cover_state(struct device *dev, int slot) | ||
104 | { | ||
105 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
106 | |||
107 | /* NOTE: assumes card detect signal is active-low */ | ||
108 | return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); | ||
109 | } | ||
110 | |||
101 | /* | 111 | /* |
102 | * MMC Slot Initialization. | 112 | * MMC Slot Initialization. |
103 | */ | 113 | */ |
@@ -166,66 +176,85 @@ static int twl_mmc_resume(struct device *dev, int slot) | |||
166 | /* | 176 | /* |
167 | * Sets the MMC voltage in twl4030 | 177 | * Sets the MMC voltage in twl4030 |
168 | */ | 178 | */ |
179 | |||
180 | #define MMC1_OCR (MMC_VDD_165_195 \ | ||
181 | |MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32) | ||
182 | #define MMC2_OCR (MMC_VDD_165_195 \ | ||
183 | |MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28 \ | ||
184 | |MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32) | ||
185 | |||
169 | static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) | 186 | static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) |
170 | { | 187 | { |
171 | int ret; | 188 | int ret; |
172 | u8 vmmc, dev_grp_val; | 189 | u8 vmmc = 0, dev_grp_val; |
173 | 190 | ||
174 | switch (1 << vdd) { | 191 | if (!vdd) |
175 | case MMC_VDD_35_36: | 192 | goto doit; |
176 | case MMC_VDD_34_35: | 193 | |
177 | case MMC_VDD_33_34: | 194 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) { |
178 | case MMC_VDD_32_33: | 195 | /* VMMC1: max 220 mA. And for 8-bit mode, |
179 | case MMC_VDD_31_32: | 196 | * VSIM: max 50 mA |
180 | case MMC_VDD_30_31: | 197 | */ |
181 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | 198 | switch (1 << vdd) { |
182 | vmmc = VMMC1_315V; | 199 | case MMC_VDD_165_195: |
183 | else | ||
184 | vmmc = VMMC2_315V; | ||
185 | break; | ||
186 | case MMC_VDD_29_30: | ||
187 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
188 | vmmc = VMMC1_315V; | ||
189 | else | ||
190 | vmmc = VMMC2_300V; | ||
191 | break; | ||
192 | case MMC_VDD_27_28: | ||
193 | case MMC_VDD_26_27: | ||
194 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
195 | vmmc = VMMC1_285V; | ||
196 | else | ||
197 | vmmc = VMMC2_285V; | ||
198 | break; | ||
199 | case MMC_VDD_25_26: | ||
200 | case MMC_VDD_24_25: | ||
201 | case MMC_VDD_23_24: | ||
202 | case MMC_VDD_22_23: | ||
203 | case MMC_VDD_21_22: | ||
204 | case MMC_VDD_20_21: | ||
205 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
206 | vmmc = VMMC1_285V; | ||
207 | else | ||
208 | vmmc = VMMC2_260V; | ||
209 | break; | ||
210 | case MMC_VDD_165_195: | ||
211 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
212 | vmmc = VMMC1_185V; | 200 | vmmc = VMMC1_185V; |
213 | else | 201 | /* and VSIM_180V */ |
202 | break; | ||
203 | case MMC_VDD_28_29: | ||
204 | vmmc = VMMC1_285V; | ||
205 | /* and VSIM_280V */ | ||
206 | break; | ||
207 | case MMC_VDD_29_30: | ||
208 | case MMC_VDD_30_31: | ||
209 | vmmc = VMMC1_300V; | ||
210 | /* and VSIM_300V */ | ||
211 | break; | ||
212 | case MMC_VDD_31_32: | ||
213 | vmmc = VMMC1_315V; | ||
214 | /* error if VSIM needed */ | ||
215 | break; | ||
216 | default: | ||
217 | return -EINVAL; | ||
218 | } | ||
219 | } else if (c->twl_vmmc_dev_grp == VMMC2_DEV_GRP) { | ||
220 | /* VMMC2: max 100 mA */ | ||
221 | switch (1 << vdd) { | ||
222 | case MMC_VDD_165_195: | ||
214 | vmmc = VMMC2_185V; | 223 | vmmc = VMMC2_185V; |
215 | break; | 224 | break; |
216 | default: | 225 | case MMC_VDD_25_26: |
217 | vmmc = 0; | 226 | case MMC_VDD_26_27: |
218 | break; | 227 | vmmc = VMMC2_260V; |
228 | break; | ||
229 | case MMC_VDD_27_28: | ||
230 | vmmc = VMMC2_280V; | ||
231 | break; | ||
232 | case MMC_VDD_28_29: | ||
233 | vmmc = VMMC2_285V; | ||
234 | break; | ||
235 | case MMC_VDD_29_30: | ||
236 | case MMC_VDD_30_31: | ||
237 | vmmc = VMMC2_300V; | ||
238 | break; | ||
239 | case MMC_VDD_31_32: | ||
240 | vmmc = VMMC2_315V; | ||
241 | break; | ||
242 | default: | ||
243 | return -EINVAL; | ||
244 | } | ||
245 | } else { | ||
246 | return -EINVAL; | ||
219 | } | 247 | } |
220 | 248 | ||
221 | if (vmmc) | 249 | doit: |
250 | if (vdd) | ||
222 | dev_grp_val = VMMC_DEV_GRP_P1; /* Power up */ | 251 | dev_grp_val = VMMC_DEV_GRP_P1; /* Power up */ |
223 | else | 252 | else |
224 | dev_grp_val = LDO_CLR; /* Power down */ | 253 | dev_grp_val = LDO_CLR; /* Power down */ |
225 | 254 | ||
226 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | 255 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, |
227 | dev_grp_val, c->twl_vmmc_dev_grp); | 256 | dev_grp_val, c->twl_vmmc_dev_grp); |
228 | if (ret) | 257 | if (ret || !vdd) |
229 | return ret; | 258 | return ret; |
230 | 259 | ||
231 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | 260 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, |
@@ -242,6 +271,14 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, | |||
242 | struct twl_mmc_controller *c = &hsmmc[0]; | 271 | struct twl_mmc_controller *c = &hsmmc[0]; |
243 | struct omap_mmc_platform_data *mmc = dev->platform_data; | 272 | struct omap_mmc_platform_data *mmc = dev->platform_data; |
244 | 273 | ||
274 | /* | ||
275 | * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the | ||
276 | * card using the same TWL VMMC1 supply (hsmmc[0]); OMAP has both | ||
277 | * 1.8V and 3.0V modes, controlled by the PBIAS register. | ||
278 | * | ||
279 | * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which | ||
280 | * is most naturally TWL VSIM; those pins also use PBIAS. | ||
281 | */ | ||
245 | if (power_on) { | 282 | if (power_on) { |
246 | if (cpu_is_omap2430()) { | 283 | if (cpu_is_omap2430()) { |
247 | reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1); | 284 | reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1); |
@@ -298,6 +335,12 @@ static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vd | |||
298 | struct twl_mmc_controller *c = &hsmmc[1]; | 335 | struct twl_mmc_controller *c = &hsmmc[1]; |
299 | struct omap_mmc_platform_data *mmc = dev->platform_data; | 336 | struct omap_mmc_platform_data *mmc = dev->platform_data; |
300 | 337 | ||
338 | /* | ||
339 | * Assume TWL VMMC2 (hsmmc[1]) is used only to power the card ... OMAP | ||
340 | * VDDS is used to power the pins, optionally with a transceiver to | ||
341 | * support cards using voltages other than VDDS (1.8V nominal). When a | ||
342 | * transceiver is used, DAT3..7 are muxed as transceiver control pins. | ||
343 | */ | ||
301 | if (power_on) { | 344 | if (power_on) { |
302 | if (mmc->slots[0].internal_clock) { | 345 | if (mmc->slots[0].internal_clock) { |
303 | u32 reg; | 346 | u32 reg; |
@@ -314,6 +357,16 @@ static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vd | |||
314 | return ret; | 357 | return ret; |
315 | } | 358 | } |
316 | 359 | ||
360 | static int twl_mmc3_set_power(struct device *dev, int slot, int power_on, | ||
361 | int vdd) | ||
362 | { | ||
363 | /* | ||
364 | * Assume MMC3 has self-powered device connected, for example on-board | ||
365 | * chip with external power source. | ||
366 | */ | ||
367 | return 0; | ||
368 | } | ||
369 | |||
317 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; | 370 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; |
318 | 371 | ||
319 | void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | 372 | void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) |
@@ -349,13 +402,13 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
349 | return; | 402 | return; |
350 | } | 403 | } |
351 | 404 | ||
352 | sprintf(twl->name, "mmc%islot%i", c->mmc, 1); | 405 | if (c->name) |
406 | strncpy(twl->name, c->name, HSMMC_NAME_LEN); | ||
407 | else | ||
408 | snprintf(twl->name, ARRAY_SIZE(twl->name), | ||
409 | "mmc%islot%i", c->mmc, 1); | ||
353 | mmc->slots[0].name = twl->name; | 410 | mmc->slots[0].name = twl->name; |
354 | mmc->nr_slots = 1; | 411 | mmc->nr_slots = 1; |
355 | mmc->slots[0].ocr_mask = MMC_VDD_165_195 | | ||
356 | MMC_VDD_26_27 | MMC_VDD_27_28 | | ||
357 | MMC_VDD_29_30 | | ||
358 | MMC_VDD_30_31 | MMC_VDD_31_32; | ||
359 | mmc->slots[0].wires = c->wires; | 412 | mmc->slots[0].wires = c->wires; |
360 | mmc->slots[0].internal_clock = !c->ext_clock; | 413 | mmc->slots[0].internal_clock = !c->ext_clock; |
361 | mmc->dma_mask = 0xffffffff; | 414 | mmc->dma_mask = 0xffffffff; |
@@ -369,7 +422,10 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
369 | 422 | ||
370 | mmc->slots[0].switch_pin = c->gpio_cd; | 423 | mmc->slots[0].switch_pin = c->gpio_cd; |
371 | mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd); | 424 | mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd); |
372 | mmc->slots[0].card_detect = twl_mmc_card_detect; | 425 | if (c->cover_only) |
426 | mmc->slots[0].get_cover_state = twl_mmc_get_cover_state; | ||
427 | else | ||
428 | mmc->slots[0].card_detect = twl_mmc_card_detect; | ||
373 | } else | 429 | } else |
374 | mmc->slots[0].switch_pin = -EINVAL; | 430 | mmc->slots[0].switch_pin = -EINVAL; |
375 | 431 | ||
@@ -385,24 +441,43 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
385 | 441 | ||
386 | /* NOTE: we assume OMAP's MMC1 and MMC2 use | 442 | /* NOTE: we assume OMAP's MMC1 and MMC2 use |
387 | * the TWL4030's VMMC1 and VMMC2, respectively; | 443 | * the TWL4030's VMMC1 and VMMC2, respectively; |
388 | * and that OMAP's MMC3 isn't used. | 444 | * and that MMC3 device has it's own power source. |
389 | */ | 445 | */ |
390 | 446 | ||
391 | switch (c->mmc) { | 447 | switch (c->mmc) { |
392 | case 1: | 448 | case 1: |
393 | mmc->slots[0].set_power = twl_mmc1_set_power; | 449 | mmc->slots[0].set_power = twl_mmc1_set_power; |
450 | mmc->slots[0].ocr_mask = MMC1_OCR; | ||
394 | break; | 451 | break; |
395 | case 2: | 452 | case 2: |
396 | mmc->slots[0].set_power = twl_mmc2_set_power; | 453 | mmc->slots[0].set_power = twl_mmc2_set_power; |
454 | if (c->transceiver) | ||
455 | mmc->slots[0].ocr_mask = MMC2_OCR; | ||
456 | else | ||
457 | mmc->slots[0].ocr_mask = MMC_VDD_165_195; | ||
458 | break; | ||
459 | case 3: | ||
460 | mmc->slots[0].set_power = twl_mmc3_set_power; | ||
461 | mmc->slots[0].ocr_mask = MMC_VDD_165_195; | ||
397 | break; | 462 | break; |
398 | default: | 463 | default: |
399 | pr_err("MMC%d configuration not supported!\n", c->mmc); | 464 | pr_err("MMC%d configuration not supported!\n", c->mmc); |
465 | kfree(mmc); | ||
400 | continue; | 466 | continue; |
401 | } | 467 | } |
402 | hsmmc_data[c->mmc - 1] = mmc; | 468 | hsmmc_data[c->mmc - 1] = mmc; |
403 | } | 469 | } |
404 | 470 | ||
405 | omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC); | 471 | omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC); |
472 | |||
473 | /* pass the device nodes back to board setup code */ | ||
474 | for (c = controllers; c->mmc; c++) { | ||
475 | struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1]; | ||
476 | |||
477 | if (!c->mmc || c->mmc > nr_hsmmc) | ||
478 | continue; | ||
479 | c->dev = mmc->dev; | ||
480 | } | ||
406 | } | 481 | } |
407 | 482 | ||
408 | #endif | 483 | #endif |