]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/hsmmc.c
f711d7bf13cb8891d2a5d8bbfb1ebaed84e1aeb7
[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/gpio.h>
19 #include <linux/i2c/twl4030.h>
20
21 #include <mach/hardware.h>
22 #include <mach/control.h>
23 #include <mach/mmc.h>
24 #include <mach/board.h>
25
26 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
27
28 #define TWL_GPIO_IMR1A          0x1C
29 #define TWL_GPIO_ISR1A          0x19
30 #define LDO_CLR                 0x00
31 #define VSEL_S2_CLR             0x40
32 #define GPIO_0_BIT_POS          (1 << 0)
33
34 #define VMMC1_DEV_GRP           0x27
35 #define VMMC1_DEV_GRP_P1        0x20
36 #define VMMC1_DEDICATED         0x2A
37 #define VMMC1_CLR               0x00
38 #define VMMC1_315V              0x03
39 #define VMMC1_300V              0x02
40 #define VMMC1_285V              0x01
41 #define VMMC1_185V              0x00
42
43 static u16 control_pbias_offset;
44
45 static struct hsmmc_controller {
46         u16             control_devconf_offset;
47         u32             devconf_loopback_clock;
48         int             card_detect_gpio;
49 } hsmmc[] = {
50         {
51                 .control_devconf_offset         = OMAP2_CONTROL_DEVCONF0,
52                 .devconf_loopback_clock         = OMAP2_MMCSDIO1ADPCLKISEL,
53                 .card_detect_gpio               = OMAP_MAX_GPIO_LINES,
54         },
55         {
56                 /* control_devconf_offset set dynamically */
57                 .devconf_loopback_clock         = OMAP2_MMCSDIO2ADPCLKISEL,
58         },
59 };
60
61 static int hsmmc1_card_detect(int irq)
62 {
63         return gpio_get_value_cansleep(hsmmc[0].card_detect_gpio);
64 }
65
66 /*
67  * MMC Slot Initialization.
68  */
69 static int hsmmc1_late_init(struct device *dev)
70 {
71         int ret = 0;
72
73         /*
74          * Configure TWL4030 GPIO parameters for MMC hotplug irq
75          */
76         ret = gpio_request(hsmmc[0].card_detect_gpio, "mmc0_cd");
77         if (ret)
78                 goto err;
79
80         ret = twl4030_set_gpio_debounce(0, true);
81         if (ret)
82                 goto err;
83
84         return ret;
85
86 err:
87         dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
88         return ret;
89 }
90
91 static void hsmmc1_cleanup(struct device *dev)
92 {
93         gpio_free(hsmmc[0].card_detect_gpio);
94 }
95
96 #ifdef CONFIG_PM
97
98 /*
99  * To mask and unmask MMC Card Detect Interrupt
100  * mask : 1
101  * unmask : 0
102  */
103 static int mask_cd_interrupt(int mask)
104 {
105         u8 reg = 0, ret = 0;
106
107         ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &reg, TWL_GPIO_IMR1A);
108         if (ret)
109                 goto err;
110
111         reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
112
113         ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_IMR1A);
114         if (ret)
115                 goto err;
116
117         ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &reg, TWL_GPIO_ISR1A);
118         if (ret)
119                 goto err;
120
121         reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
122
123         ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_ISR1A);
124         if (ret)
125                 goto err;
126
127 err:
128         return ret;
129 }
130
131 static int hsmmc1_suspend(struct device *dev, int slot)
132 {
133         int ret = 0;
134
135         disable_irq(TWL4030_GPIO_IRQ_NO(0));
136         ret = mask_cd_interrupt(1);
137
138         return ret;
139 }
140
141 static int hsmmc1_resume(struct device *dev, int slot)
142 {
143         int ret = 0;
144
145         enable_irq(TWL4030_GPIO_IRQ_NO(0));
146         ret = mask_cd_interrupt(0);
147
148         return ret;
149 }
150
151 #endif
152
153 static int hsmmc1_set_power(struct device *dev, int slot, int power_on,
154                                 int vdd)
155 {
156         u32 reg;
157         int ret = 0;
158         u16 control_devconf_offset = hsmmc[0].control_devconf_offset;
159
160         if (power_on) {
161                 u32 vdd_sel = 0;
162
163                 switch (1 << vdd) {
164                 case MMC_VDD_33_34:
165                 case MMC_VDD_32_33:
166                 case MMC_VDD_31_32:
167                 case MMC_VDD_30_31:
168                         vdd_sel = VMMC1_315V;
169                         break;
170                 case MMC_VDD_29_30:
171                         vdd_sel = VMMC1_300V;
172                         break;
173                 case MMC_VDD_165_195:
174                         vdd_sel = VMMC1_185V;
175                 }
176
177                 if (cpu_is_omap2430()) {
178                         reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1);
179                         if (vdd_sel >= VMMC1_300V)
180                                 reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE;
181                         else
182                                 reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE;
183                         omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1);
184                 }
185
186                 /* REVISIT: Loop back clock not needed for 2430? */
187                 if (!cpu_is_omap2430()) {
188                         reg = omap_ctrl_readl(control_devconf_offset);
189                         reg |= OMAP2_MMCSDIO1ADPCLKISEL;
190                         omap_ctrl_writel(reg, control_devconf_offset);
191                 }
192
193                 reg = omap_ctrl_readl(control_pbias_offset);
194                 reg |= OMAP2_PBIASSPEEDCTRL0;
195                 reg &= ~OMAP2_PBIASLITEPWRDNZ0;
196                 omap_ctrl_writel(reg, control_pbias_offset);
197
198                 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
199                                                 VMMC1_DEV_GRP_P1, VMMC1_DEV_GRP);
200                 if (ret)
201                         goto err;
202
203                 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
204                                                 vdd_sel, VMMC1_DEDICATED);
205                 if (ret)
206                         goto err;
207
208                 /* 100ms delay required for PBIAS configuration */
209                 msleep(100);
210
211                 reg = omap_ctrl_readl(control_pbias_offset);
212                 reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0);
213                 if (vdd_sel == VMMC1_185V)
214                         reg &= ~OMAP2_PBIASLITEVMODE0;
215                 else
216                         reg |= OMAP2_PBIASLITEVMODE0;
217                 omap_ctrl_writel(reg, control_pbias_offset);
218
219                 return ret;
220
221         } else {
222                 /* Power OFF */
223
224                 /* For MMC1, Toggle PBIAS before every power up sequence */
225                 reg = omap_ctrl_readl(control_pbias_offset);
226                 reg &= ~OMAP2_PBIASLITEPWRDNZ0;
227                 omap_ctrl_writel(reg, control_pbias_offset);
228
229                 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
230                                                 LDO_CLR, VMMC1_DEV_GRP);
231                 if (ret)
232                         goto err;
233
234                 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
235                                                 VSEL_S2_CLR, VMMC1_DEDICATED);
236                 if (ret)
237                         goto err;
238
239                 /* 100ms delay required for PBIAS configuration */
240                 msleep(100);
241
242                 reg = omap_ctrl_readl(control_pbias_offset);
243                 reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 |
244                         OMAP2_PBIASLITEVMODE0);
245                 omap_ctrl_writel(reg, control_pbias_offset);
246         }
247
248         return 0;
249
250 err:
251         return 1;
252 }
253
254 static struct omap_mmc_platform_data mmc1_data = {
255         .nr_slots                       = 1,
256         .init                           = hsmmc1_late_init,
257         .cleanup                        = hsmmc1_cleanup,
258 #ifdef CONFIG_PM
259         .suspend                        = hsmmc1_suspend,
260         .resume                         = hsmmc1_resume,
261 #endif
262         .dma_mask                       = 0xffffffff,
263         .slots[0] = {
264                 .wire4                  = 1,
265                 .set_power              = hsmmc1_set_power,
266                 .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34 |
267                                                 MMC_VDD_165_195,
268                 .name                   = "first slot",
269
270                 .card_detect_irq        = TWL4030_GPIO_IRQ_NO(0),
271                 .card_detect            = hsmmc1_card_detect,
272         },
273 };
274
275 static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC];
276
277 void __init hsmmc_init(void)
278 {
279         if (cpu_is_omap2430()) {
280                 control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
281                 hsmmc[1].control_devconf_offset = OMAP243X_CONTROL_DEVCONF1;
282         } else {
283                 control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
284                 hsmmc[1].control_devconf_offset = OMAP343X_CONTROL_DEVCONF1;
285         }
286
287         hsmmc_data[0] = &mmc1_data;
288         omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
289 }
290
291 #else
292
293 void __init hsmmc_init(void)
294 {
295
296 }
297
298 #endif