Commit | Line | Data |
---|---|---|
90c62bf0 TL |
1 | /* |
2 | * linux/arch/arm/mach-omap2/mmc-twl4030.c | |
3 | * | |
4 | * Copyright (C) 2007-2008 Texas Instruments | |
5 | * Copyright (C) 2008 Nokia Corporation | |
6 | * Author: Texas Instruments | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | */ | |
12 | #include <linux/err.h> | |
13 | #include <linux/io.h> | |
14 | #include <linux/module.h> | |
15 | #include <linux/platform_device.h> | |
16 | #include <linux/interrupt.h> | |
17 | #include <linux/delay.h> | |
18 | #include <linux/gpio.h> | |
b583f26d DB |
19 | #include <linux/mmc/host.h> |
20 | #include <linux/regulator/consumer.h> | |
90c62bf0 TL |
21 | |
22 | #include <mach/hardware.h> | |
23 | #include <mach/control.h> | |
24 | #include <mach/mmc.h> | |
25 | #include <mach/board.h> | |
26 | ||
27 | #include "mmc-twl4030.h" | |
28 | ||
90c62bf0 | 29 | |
b583f26d DB |
30 | #if defined(CONFIG_REGULATOR) && \ |
31 | (defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) | |
90c62bf0 TL |
32 | |
33 | static u16 control_pbias_offset; | |
34 | static u16 control_devconf1_offset; | |
35 | ||
36 | #define HSMMC_NAME_LEN 9 | |
37 | ||
38 | static struct twl_mmc_controller { | |
39 | struct omap_mmc_platform_data *mmc; | |
b583f26d DB |
40 | /* Vcc == configured supply |
41 | * Vcc_alt == optional | |
42 | * - MMC1, supply for DAT4..DAT7 | |
43 | * - MMC2/MMC2, external level shifter voltage supply, for | |
44 | * chip (SDIO, eMMC, etc) or transceiver (MMC2 only) | |
45 | */ | |
46 | struct regulator *vcc; | |
47 | struct regulator *vcc_aux; | |
48 | char name[HSMMC_NAME_LEN + 1]; | |
49 | } hsmmc[OMAP34XX_NR_MMC]; | |
90c62bf0 TL |
50 | |
51 | static int twl_mmc_card_detect(int irq) | |
52 | { | |
53 | unsigned i; | |
54 | ||
55 | for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { | |
56 | struct omap_mmc_platform_data *mmc; | |
57 | ||
58 | mmc = hsmmc[i].mmc; | |
59 | if (!mmc) | |
60 | continue; | |
61 | if (irq != mmc->slots[0].card_detect_irq) | |
62 | continue; | |
63 | ||
64 | /* NOTE: assumes card detect signal is active-low */ | |
65 | return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); | |
66 | } | |
67 | return -ENOSYS; | |
68 | } | |
69 | ||
70 | static int twl_mmc_get_ro(struct device *dev, int slot) | |
71 | { | |
72 | struct omap_mmc_platform_data *mmc = dev->platform_data; | |
73 | ||
74 | /* NOTE: assumes write protect signal is active-high */ | |
75 | return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); | |
76 | } | |
77 | ||
8d75e98b AH |
78 | static int twl_mmc_get_cover_state(struct device *dev, int slot) |
79 | { | |
80 | struct omap_mmc_platform_data *mmc = dev->platform_data; | |
81 | ||
82 | /* NOTE: assumes card detect signal is active-low */ | |
83 | return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); | |
84 | } | |
85 | ||
90c62bf0 TL |
86 | /* |
87 | * MMC Slot Initialization. | |
88 | */ | |
89 | static int twl_mmc_late_init(struct device *dev) | |
90 | { | |
91 | struct omap_mmc_platform_data *mmc = dev->platform_data; | |
92 | int ret = 0; | |
93 | int i; | |
94 | ||
b583f26d DB |
95 | /* MMC/SD/SDIO doesn't require a card detect switch */ |
96 | if (gpio_is_valid(mmc->slots[0].switch_pin)) { | |
97 | ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd"); | |
98 | if (ret) | |
99 | goto done; | |
100 | ret = gpio_direction_input(mmc->slots[0].switch_pin); | |
101 | if (ret) | |
102 | goto err; | |
103 | } | |
90c62bf0 | 104 | |
b583f26d | 105 | /* require at least main regulator */ |
90c62bf0 TL |
106 | for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { |
107 | if (hsmmc[i].name == mmc->slots[0].name) { | |
b583f26d DB |
108 | struct regulator *reg; |
109 | ||
90c62bf0 | 110 | hsmmc[i].mmc = mmc; |
b583f26d DB |
111 | |
112 | reg = regulator_get(dev, "vmmc"); | |
113 | if (IS_ERR(reg)) { | |
114 | dev_dbg(dev, "vmmc regulator missing\n"); | |
115 | /* HACK: until fixed.c regulator is usable, | |
116 | * we don't require a main regulator | |
117 | * for MMC2 or MMC3 | |
118 | */ | |
119 | if (i != 0) | |
120 | break; | |
121 | ret = PTR_ERR(reg); | |
22833044 | 122 | hsmmc[i].vcc = NULL; |
b583f26d DB |
123 | goto err; |
124 | } | |
125 | hsmmc[i].vcc = reg; | |
126 | mmc->slots[0].ocr_mask = mmc_regulator_get_ocrmask(reg); | |
127 | ||
128 | /* allow an aux regulator */ | |
129 | reg = regulator_get(dev, "vmmc_aux"); | |
130 | hsmmc[i].vcc_aux = IS_ERR(reg) ? NULL : reg; | |
131 | ||
132 | /* UGLY HACK: workaround regulator framework bugs. | |
133 | * When the bootloader leaves a supply active, it's | |
134 | * initialized with zero usecount ... and we can't | |
135 | * disable it without first enabling it. Until the | |
136 | * framework is fixed, we need a workaround like this | |
137 | * (which is safe for MMC, but not in general). | |
138 | */ | |
139 | if (regulator_is_enabled(hsmmc[i].vcc) > 0) { | |
140 | regulator_enable(hsmmc[i].vcc); | |
141 | regulator_disable(hsmmc[i].vcc); | |
142 | } | |
143 | if (hsmmc[i].vcc_aux) { | |
144 | if (regulator_is_enabled(reg) > 0) { | |
145 | regulator_enable(reg); | |
146 | regulator_disable(reg); | |
147 | } | |
148 | } | |
149 | ||
90c62bf0 TL |
150 | break; |
151 | } | |
152 | } | |
153 | ||
154 | return 0; | |
155 | ||
156 | err: | |
157 | gpio_free(mmc->slots[0].switch_pin); | |
158 | done: | |
159 | mmc->slots[0].card_detect_irq = 0; | |
160 | mmc->slots[0].card_detect = NULL; | |
161 | ||
162 | dev_err(dev, "err %d configuring card detect\n", ret); | |
163 | return ret; | |
164 | } | |
165 | ||
166 | static void twl_mmc_cleanup(struct device *dev) | |
167 | { | |
168 | struct omap_mmc_platform_data *mmc = dev->platform_data; | |
22833044 | 169 | int i; |
90c62bf0 TL |
170 | |
171 | gpio_free(mmc->slots[0].switch_pin); | |
22833044 RQ |
172 | for(i = 0; i < ARRAY_SIZE(hsmmc); i++) { |
173 | regulator_put(hsmmc[i].vcc); | |
174 | regulator_put(hsmmc[i].vcc_aux); | |
175 | } | |
90c62bf0 TL |
176 | } |
177 | ||
178 | #ifdef CONFIG_PM | |
179 | ||
180 | static int twl_mmc_suspend(struct device *dev, int slot) | |
181 | { | |
182 | struct omap_mmc_platform_data *mmc = dev->platform_data; | |
183 | ||
184 | disable_irq(mmc->slots[0].card_detect_irq); | |
185 | return 0; | |
186 | } | |
187 | ||
188 | static int twl_mmc_resume(struct device *dev, int slot) | |
189 | { | |
190 | struct omap_mmc_platform_data *mmc = dev->platform_data; | |
191 | ||
192 | enable_irq(mmc->slots[0].card_detect_irq); | |
193 | return 0; | |
194 | } | |
195 | ||
196 | #else | |
197 | #define twl_mmc_suspend NULL | |
198 | #define twl_mmc_resume NULL | |
199 | #endif | |
200 | ||
90c62bf0 TL |
201 | static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, |
202 | int vdd) | |
203 | { | |
204 | u32 reg; | |
205 | int ret = 0; | |
206 | struct twl_mmc_controller *c = &hsmmc[0]; | |
207 | struct omap_mmc_platform_data *mmc = dev->platform_data; | |
208 | ||
0329c377 DB |
209 | /* |
210 | * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the | |
b583f26d | 211 | * card with Vcc regulator (from twl4030 or whatever). OMAP has both |
0329c377 DB |
212 | * 1.8V and 3.0V modes, controlled by the PBIAS register. |
213 | * | |
214 | * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which | |
215 | * is most naturally TWL VSIM; those pins also use PBIAS. | |
b583f26d DB |
216 | * |
217 | * FIXME handle VMMC1A as needed ... | |
0329c377 | 218 | */ |
90c62bf0 TL |
219 | if (power_on) { |
220 | if (cpu_is_omap2430()) { | |
221 | reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1); | |
222 | if ((1 << vdd) >= MMC_VDD_30_31) | |
223 | reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE; | |
224 | else | |
225 | reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE; | |
226 | omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1); | |
227 | } | |
228 | ||
229 | if (mmc->slots[0].internal_clock) { | |
230 | reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); | |
231 | reg |= OMAP2_MMCSDIO1ADPCLKISEL; | |
232 | omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0); | |
233 | } | |
234 | ||
235 | reg = omap_ctrl_readl(control_pbias_offset); | |
236 | reg |= OMAP2_PBIASSPEEDCTRL0; | |
237 | reg &= ~OMAP2_PBIASLITEPWRDNZ0; | |
238 | omap_ctrl_writel(reg, control_pbias_offset); | |
239 | ||
b583f26d | 240 | ret = mmc_regulator_set_ocr(c->vcc, vdd); |
90c62bf0 TL |
241 | |
242 | /* 100ms delay required for PBIAS configuration */ | |
243 | msleep(100); | |
244 | reg = omap_ctrl_readl(control_pbias_offset); | |
245 | reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0); | |
246 | if ((1 << vdd) <= MMC_VDD_165_195) | |
247 | reg &= ~OMAP2_PBIASLITEVMODE0; | |
248 | else | |
249 | reg |= OMAP2_PBIASLITEVMODE0; | |
250 | omap_ctrl_writel(reg, control_pbias_offset); | |
251 | } else { | |
252 | reg = omap_ctrl_readl(control_pbias_offset); | |
253 | reg &= ~OMAP2_PBIASLITEPWRDNZ0; | |
254 | omap_ctrl_writel(reg, control_pbias_offset); | |
255 | ||
b583f26d | 256 | ret = mmc_regulator_set_ocr(c->vcc, 0); |
90c62bf0 TL |
257 | |
258 | /* 100ms delay required for PBIAS configuration */ | |
259 | msleep(100); | |
260 | reg = omap_ctrl_readl(control_pbias_offset); | |
261 | reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 | | |
262 | OMAP2_PBIASLITEVMODE0); | |
263 | omap_ctrl_writel(reg, control_pbias_offset); | |
264 | } | |
265 | ||
266 | return ret; | |
267 | } | |
268 | ||
b583f26d | 269 | static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int vdd) |
90c62bf0 | 270 | { |
b583f26d | 271 | int ret = 0; |
762ad3a4 | 272 | struct twl_mmc_controller *c = NULL; |
90c62bf0 | 273 | struct omap_mmc_platform_data *mmc = dev->platform_data; |
762ad3a4 GI |
274 | int i; |
275 | ||
276 | for (i = 1; i < ARRAY_SIZE(hsmmc); i++) { | |
277 | if (mmc == hsmmc[i].mmc) { | |
278 | c = &hsmmc[i]; | |
279 | break; | |
280 | } | |
281 | } | |
282 | ||
283 | if (c == NULL) | |
284 | return -ENODEV; | |
90c62bf0 | 285 | |
b583f26d DB |
286 | /* If we don't see a Vcc regulator, assume it's a fixed |
287 | * voltage always-on regulator. | |
288 | */ | |
289 | if (!c->vcc) | |
290 | return 0; | |
291 | ||
0329c377 | 292 | /* |
b583f26d | 293 | * Assume Vcc regulator is used only to power the card ... OMAP |
0329c377 DB |
294 | * VDDS is used to power the pins, optionally with a transceiver to |
295 | * support cards using voltages other than VDDS (1.8V nominal). When a | |
296 | * transceiver is used, DAT3..7 are muxed as transceiver control pins. | |
b583f26d DB |
297 | * |
298 | * In some cases this regulator won't support enable/disable; | |
299 | * e.g. it's a fixed rail for a WLAN chip. | |
300 | * | |
301 | * In other cases vcc_aux switches interface power. Example, for | |
302 | * eMMC cards it represents VccQ. Sometimes transceivers or SDIO | |
303 | * chips/cards need an interface voltage rail too. | |
0329c377 | 304 | */ |
90c62bf0 | 305 | if (power_on) { |
b583f26d | 306 | /* only MMC2 supports a CLKIN */ |
90c62bf0 TL |
307 | if (mmc->slots[0].internal_clock) { |
308 | u32 reg; | |
309 | ||
310 | reg = omap_ctrl_readl(control_devconf1_offset); | |
311 | reg |= OMAP2_MMCSDIO2ADPCLKISEL; | |
312 | omap_ctrl_writel(reg, control_devconf1_offset); | |
313 | } | |
b583f26d DB |
314 | ret = mmc_regulator_set_ocr(c->vcc, vdd); |
315 | /* enable interface voltage rail, if needed */ | |
316 | if (ret == 0 && c->vcc_aux) { | |
317 | ret = regulator_enable(c->vcc_aux); | |
318 | if (ret < 0) | |
319 | ret = mmc_regulator_set_ocr(c->vcc, 0); | |
320 | } | |
90c62bf0 | 321 | } else { |
b583f26d DB |
322 | if (c->vcc_aux && (ret = regulator_is_enabled(c->vcc_aux)) > 0) |
323 | ret = regulator_disable(c->vcc_aux); | |
324 | if (ret == 0) | |
325 | ret = mmc_regulator_set_ocr(c->vcc, 0); | |
90c62bf0 TL |
326 | } |
327 | ||
328 | return ret; | |
329 | } | |
330 | ||
331 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; | |
332 | ||
333 | void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |
334 | { | |
335 | struct twl4030_hsmmc_info *c; | |
336 | int nr_hsmmc = ARRAY_SIZE(hsmmc_data); | |
337 | ||
338 | if (cpu_is_omap2430()) { | |
339 | control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; | |
340 | control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1; | |
341 | nr_hsmmc = 2; | |
342 | } else { | |
343 | control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE; | |
344 | control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1; | |
345 | } | |
346 | ||
347 | for (c = controllers; c->mmc; c++) { | |
348 | struct twl_mmc_controller *twl = hsmmc + c->mmc - 1; | |
349 | struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1]; | |
350 | ||
351 | if (!c->mmc || c->mmc > nr_hsmmc) { | |
352 | pr_debug("MMC%d: no such controller\n", c->mmc); | |
353 | continue; | |
354 | } | |
355 | if (mmc) { | |
356 | pr_debug("MMC%d: already configured\n", c->mmc); | |
357 | continue; | |
358 | } | |
359 | ||
360 | mmc = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); | |
361 | if (!mmc) { | |
362 | pr_err("Cannot allocate memory for mmc device!\n"); | |
363 | return; | |
364 | } | |
365 | ||
e51151a5 AH |
366 | if (c->name) |
367 | strncpy(twl->name, c->name, HSMMC_NAME_LEN); | |
368 | else | |
369 | snprintf(twl->name, ARRAY_SIZE(twl->name), | |
370 | "mmc%islot%i", c->mmc, 1); | |
90c62bf0 TL |
371 | mmc->slots[0].name = twl->name; |
372 | mmc->nr_slots = 1; | |
90c62bf0 TL |
373 | mmc->slots[0].wires = c->wires; |
374 | mmc->slots[0].internal_clock = !c->ext_clock; | |
375 | mmc->dma_mask = 0xffffffff; | |
b583f26d | 376 | mmc->init = twl_mmc_late_init; |
90c62bf0 | 377 | |
b583f26d | 378 | /* note: twl4030 card detect GPIOs can disable VMMCx ... */ |
90c62bf0 | 379 | if (gpio_is_valid(c->gpio_cd)) { |
90c62bf0 TL |
380 | mmc->cleanup = twl_mmc_cleanup; |
381 | mmc->suspend = twl_mmc_suspend; | |
382 | mmc->resume = twl_mmc_resume; | |
383 | ||
384 | mmc->slots[0].switch_pin = c->gpio_cd; | |
385 | mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd); | |
8d75e98b AH |
386 | if (c->cover_only) |
387 | mmc->slots[0].get_cover_state = twl_mmc_get_cover_state; | |
388 | else | |
389 | mmc->slots[0].card_detect = twl_mmc_card_detect; | |
90c62bf0 TL |
390 | } else |
391 | mmc->slots[0].switch_pin = -EINVAL; | |
392 | ||
393 | /* write protect normally uses an OMAP gpio */ | |
394 | if (gpio_is_valid(c->gpio_wp)) { | |
395 | gpio_request(c->gpio_wp, "mmc_wp"); | |
396 | gpio_direction_input(c->gpio_wp); | |
397 | ||
398 | mmc->slots[0].gpio_wp = c->gpio_wp; | |
399 | mmc->slots[0].get_ro = twl_mmc_get_ro; | |
400 | } else | |
401 | mmc->slots[0].gpio_wp = -EINVAL; | |
402 | ||
b583f26d DB |
403 | /* NOTE: MMC slots should have a Vcc regulator set up. |
404 | * This may be from a TWL4030-family chip, another | |
405 | * controllable regulator, or a fixed supply. | |
406 | * | |
407 | * temporary HACK: ocr_mask instead of fixed supply | |
90c62bf0 | 408 | */ |
b583f26d | 409 | mmc->slots[0].ocr_mask = c->ocr_mask; |
90c62bf0 TL |
410 | |
411 | switch (c->mmc) { | |
412 | case 1: | |
b583f26d | 413 | /* on-chip level shifting via PBIAS0/PBIAS1 */ |
90c62bf0 TL |
414 | mmc->slots[0].set_power = twl_mmc1_set_power; |
415 | break; | |
416 | case 2: | |
b583f26d DB |
417 | if (c->ext_clock) |
418 | c->transceiver = 1; | |
419 | if (c->transceiver && c->wires > 4) | |
420 | c->wires = 4; | |
421 | /* FALLTHROUGH */ | |
07d83cc9 | 422 | case 3: |
b583f26d DB |
423 | /* off-chip level shifting, or none */ |
424 | mmc->slots[0].set_power = twl_mmc23_set_power; | |
07d83cc9 | 425 | break; |
90c62bf0 TL |
426 | default: |
427 | pr_err("MMC%d configuration not supported!\n", c->mmc); | |
07d83cc9 | 428 | kfree(mmc); |
90c62bf0 TL |
429 | continue; |
430 | } | |
431 | hsmmc_data[c->mmc - 1] = mmc; | |
432 | } | |
433 | ||
434 | omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC); | |
01971f65 DB |
435 | |
436 | /* pass the device nodes back to board setup code */ | |
437 | for (c = controllers; c->mmc; c++) { | |
438 | struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1]; | |
439 | ||
440 | if (!c->mmc || c->mmc > nr_hsmmc) | |
441 | continue; | |
442 | c->dev = mmc->dev; | |
443 | } | |
90c62bf0 TL |
444 | } |
445 | ||
446 | #endif |