]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/hsmmc.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / hsmmc.c
1 /*
2  * linux/arch/arm/mach-omap2/board-sdp-hsmmc.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/i2c/twl4030.h>
19 #include <mach/hardware.h>
20 #include <mach/mmc.h>
21 #include <mach/board.h>
22
23 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
24
25 #define VMMC1_DEV_GRP           0x27
26 #define P1_DEV_GRP              0x20
27 #define VMMC1_DEDICATED         0x2A
28 #define VSEL_3V                 0x02
29 #define VSEL_18V                0x00
30 #define TWL_GPIO_PUPDCTR1       0x13
31 #define TWL_GPIO_IMR1A          0x1C
32 #define TWL_GPIO_ISR1A          0x19
33 #define LDO_CLR                 0x00
34 #define VSEL_S2_CLR             0x40
35 #define GPIO_0_BIT_POS          (1 << 0)
36 #define MMC1_CD_IRQ             0
37 #define MMC2_CD_IRQ             1
38
39 #define OMAP2_CONTROL_DEVCONF0  0x48002274
40 #define OMAP2_CONTROL_DEVCONF1  0x490022E8
41
42 #define OMAP2_CONTROL_DEVCONF0_LBCLK    (1 << 24)
43 #define OMAP2_CONTROL_DEVCONF1_ACTOV    (1 << 31)
44
45 #define OMAP2_CONTROL_PBIAS_VMODE       (1 << 0)
46 #define OMAP2_CONTROL_PBIAS_PWRDNZ      (1 << 1)
47 #define OMAP2_CONTROL_PBIAS_SCTRL       (1 << 2)
48
49 static int hsmmc_card_detect(int irq)
50 {
51         return twl4030_get_gpio_datain(irq - TWL4030_GPIO_IRQ_BASE);
52 }
53
54 /*
55  * MMC Slot Initialization.
56  */
57 static int hsmmc_late_init(struct device *dev)
58 {
59         int ret = 0;
60
61         /*
62          * Configure TWL4030 GPIO parameters for MMC hotplug irq
63          */
64         ret = twl4030_request_gpio(MMC1_CD_IRQ);
65         if (ret)
66                 goto err;
67
68         ret = twl4030_set_gpio_edge_ctrl(MMC1_CD_IRQ,
69                         TWL4030_GPIO_EDGE_RISING | TWL4030_GPIO_EDGE_FALLING);
70         if (ret)
71                 goto err;
72
73         ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x02,
74                                                 TWL_GPIO_PUPDCTR1);
75         if (ret)
76                 goto err;
77
78         ret = twl4030_set_gpio_debounce(MMC1_CD_IRQ, TWL4030_GPIO_IS_ENABLE);
79         if (ret)
80                 goto err;
81
82         return ret;
83
84 err:
85         dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
86         return ret;
87 }
88
89 static void hsmmc_cleanup(struct device *dev)
90 {
91         int ret = 0;
92
93         ret = twl4030_free_gpio(MMC1_CD_IRQ);
94         if (ret)
95                 dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
96 }
97
98 #ifdef CONFIG_PM
99
100 /*
101  * To mask and unmask MMC Card Detect Interrupt
102  * mask : 1
103  * unmask : 0
104  */
105 static int mask_cd_interrupt(int mask)
106 {
107         u8 reg = 0, ret = 0;
108
109         ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &reg, TWL_GPIO_IMR1A);
110         if (ret)
111                 goto err;
112
113         reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
114
115         ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_IMR1A);
116         if (ret)
117                 goto err;
118
119         ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &reg, TWL_GPIO_ISR1A);
120         if (ret)
121                 goto err;
122
123         reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
124
125         ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_ISR1A);
126         if (ret)
127                 goto err;
128
129 err:
130         return ret;
131 }
132
133 static int hsmmc_suspend(struct device *dev, int slot)
134 {
135         int ret = 0;
136
137         disable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
138         ret = mask_cd_interrupt(1);
139
140         return ret;
141 }
142
143 static int hsmmc_resume(struct device *dev, int slot)
144 {
145         int ret = 0;
146
147         enable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
148         ret = mask_cd_interrupt(0);
149
150         return ret;
151 }
152
153 #endif
154
155 static int hsmmc_set_power(struct device *dev, int slot, int power_on,
156                                 int vdd)
157 {
158         u32 vdd_sel = 0, devconf = 0, reg = 0;
159         int ret = 0;
160
161         /* REVISIT: Using address directly till the control.h defines
162          * are settled.
163          */
164 #if defined(CONFIG_ARCH_OMAP2430)
165         #define OMAP2_CONTROL_PBIAS 0x490024A0
166 #else
167         #define OMAP2_CONTROL_PBIAS 0x48002520
168 #endif
169
170         if (power_on) {
171                 if (cpu_is_omap24xx())
172                         devconf = omap_readl(OMAP2_CONTROL_DEVCONF1);
173                 else
174                         devconf = omap_readl(OMAP2_CONTROL_DEVCONF0);
175
176                 switch (1 << vdd) {
177                 case MMC_VDD_33_34:
178                 case MMC_VDD_32_33:
179                         vdd_sel = VSEL_3V;
180                         if (cpu_is_omap24xx())
181                                 devconf |= OMAP2_CONTROL_DEVCONF1_ACTOV;
182                         break;
183                 case MMC_VDD_165_195:
184                         vdd_sel = VSEL_18V;
185                         if (cpu_is_omap24xx())
186                                 devconf &= ~OMAP2_CONTROL_DEVCONF1_ACTOV;
187                 }
188
189                 if (cpu_is_omap24xx())
190                         omap_writel(devconf, OMAP2_CONTROL_DEVCONF1);
191                 else
192                         omap_writel(devconf | OMAP2_CONTROL_DEVCONF0_LBCLK,
193                                     OMAP2_CONTROL_DEVCONF0);
194
195                 reg = omap_readl(OMAP2_CONTROL_PBIAS);
196                 reg |= OMAP2_CONTROL_PBIAS_SCTRL;
197                 omap_writel(reg, OMAP2_CONTROL_PBIAS);
198
199                 reg = omap_readl(OMAP2_CONTROL_PBIAS);
200                 reg &= ~OMAP2_CONTROL_PBIAS_PWRDNZ;
201                 omap_writel(reg, OMAP2_CONTROL_PBIAS);
202
203                 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
204                                                 P1_DEV_GRP, VMMC1_DEV_GRP);
205                 if (ret)
206                         goto err;
207
208                 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
209                                                 vdd_sel, VMMC1_DEDICATED);
210                 if (ret)
211                         goto err;
212
213                 msleep(100);
214                 reg = omap_readl(OMAP2_CONTROL_PBIAS);
215                 reg |= (OMAP2_CONTROL_PBIAS_SCTRL |
216                         OMAP2_CONTROL_PBIAS_PWRDNZ);
217                 if (vdd_sel == VSEL_18V)
218                         reg &= ~OMAP2_CONTROL_PBIAS_VMODE;
219                 else
220                         reg |= OMAP2_CONTROL_PBIAS_VMODE;
221                 omap_writel(reg, OMAP2_CONTROL_PBIAS);
222
223                 return ret;
224
225         } else {
226                 /* Power OFF */
227
228                 /* For MMC1, Toggle PBIAS before every power up sequence */
229                 reg = omap_readl(OMAP2_CONTROL_PBIAS);
230                 reg &= ~OMAP2_CONTROL_PBIAS_PWRDNZ;
231                 omap_writel(reg, OMAP2_CONTROL_PBIAS);
232
233                 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
234                                                 LDO_CLR, VMMC1_DEV_GRP);
235                 if (ret)
236                         goto err;
237
238                 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
239                                                 VSEL_S2_CLR, VMMC1_DEDICATED);
240                 if (ret)
241                         goto err;
242
243                 /* 100ms delay required for PBIAS configuration */
244                 msleep(100);
245                 reg = omap_readl(OMAP2_CONTROL_PBIAS);
246                 reg |= (OMAP2_CONTROL_PBIAS_VMODE |
247                         OMAP2_CONTROL_PBIAS_PWRDNZ |
248                         OMAP2_CONTROL_PBIAS_SCTRL);
249                 omap_writel(reg, OMAP2_CONTROL_PBIAS);
250         }
251
252         return 0;
253
254 err:
255         return 1;
256 }
257
258 static struct omap_mmc_platform_data hsmmc_data = {
259         .nr_slots                       = 1,
260         .switch_slot                    = NULL,
261         .init                           = hsmmc_late_init,
262         .cleanup                        = hsmmc_cleanup,
263 #ifdef CONFIG_PM
264         .suspend                        = hsmmc_suspend,
265         .resume                         = hsmmc_resume,
266 #endif
267         .slots[0] = {
268                 .set_power              = hsmmc_set_power,
269                 .set_bus_mode           = NULL,
270                 .get_ro                 = NULL,
271                 .get_cover_state        = NULL,
272                 .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34 |
273                                                 MMC_VDD_165_195,
274                 .name                   = "first slot",
275
276                 .card_detect_irq        = TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ),
277                 .card_detect            = hsmmc_card_detect,
278         },
279 };
280
281 void __init hsmmc_init(void)
282 {
283         omap_set_mmc_info(1, &hsmmc_data);
284 }
285
286 #else
287
288 void __init hsmmc_init(void)
289 {
290
291 }
292
293 #endif