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