2 * linux/arch/arm/mach-omap2/board-sdp-hsmmc.c
4 * Copyright (C) 2007-2008 Texas Instruments
5 * Copyright (C) 2008 Nokia Corporation
6 * Author: Texas Instruments
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.
12 #include <linux/err.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>
21 #include <mach/board.h>
23 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
25 #define VMMC1_DEV_GRP 0x27
26 #define P1_DEV_GRP 0x20
27 #define VMMC1_DEDICATED 0x2A
30 #define TWL_GPIO_PUPDCTR1 0x13
31 #define TWL_GPIO_IMR1A 0x1C
32 #define TWL_GPIO_ISR1A 0x19
34 #define VSEL_S2_CLR 0x40
35 #define GPIO_0_BIT_POS (1 << 0)
39 #define OMAP2_CONTROL_DEVCONF0 0x48002274
40 #define OMAP2_CONTROL_DEVCONF1 0x490022E8
42 #define OMAP2_CONTROL_DEVCONF0_LBCLK (1 << 24)
43 #define OMAP2_CONTROL_DEVCONF1_ACTOV (1 << 31)
45 #define OMAP2_CONTROL_PBIAS_VMODE (1 << 0)
46 #define OMAP2_CONTROL_PBIAS_PWRDNZ (1 << 1)
47 #define OMAP2_CONTROL_PBIAS_SCTRL (1 << 2)
49 static int hsmmc_card_detect(int irq)
51 return twl4030_get_gpio_datain(irq - TWL4030_GPIO_IRQ_BASE);
55 * MMC Slot Initialization.
57 static int hsmmc_late_init(struct device *dev)
62 * Configure TWL4030 GPIO parameters for MMC hotplug irq
64 ret = twl4030_request_gpio(MMC1_CD_IRQ);
68 ret = twl4030_set_gpio_edge_ctrl(MMC1_CD_IRQ,
69 TWL4030_GPIO_EDGE_RISING | TWL4030_GPIO_EDGE_FALLING);
73 ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x02,
78 ret = twl4030_set_gpio_debounce(MMC1_CD_IRQ, TWL4030_GPIO_IS_ENABLE);
85 dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
89 static void hsmmc_cleanup(struct device *dev)
93 ret = twl4030_free_gpio(MMC1_CD_IRQ);
95 dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
101 * To mask and unmask MMC Card Detect Interrupt
105 static int mask_cd_interrupt(int mask)
109 ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, ®, TWL_GPIO_IMR1A);
113 reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
115 ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_IMR1A);
119 ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, ®, TWL_GPIO_ISR1A);
123 reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
125 ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_ISR1A);
133 static int hsmmc_suspend(struct device *dev, int slot)
137 disable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
138 ret = mask_cd_interrupt(1);
143 static int hsmmc_resume(struct device *dev, int slot)
147 enable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
148 ret = mask_cd_interrupt(0);
155 static int hsmmc_set_power(struct device *dev, int slot, int power_on,
158 u32 vdd_sel = 0, devconf = 0, reg = 0;
161 /* REVISIT: Using address directly till the control.h defines
164 #if defined(CONFIG_ARCH_OMAP2430)
165 #define OMAP2_CONTROL_PBIAS 0x490024A0
167 #define OMAP2_CONTROL_PBIAS 0x48002520
171 if (cpu_is_omap24xx())
172 devconf = omap_readl(OMAP2_CONTROL_DEVCONF1);
174 devconf = omap_readl(OMAP2_CONTROL_DEVCONF0);
180 if (cpu_is_omap24xx())
181 devconf |= OMAP2_CONTROL_DEVCONF1_ACTOV;
183 case MMC_VDD_165_195:
185 if (cpu_is_omap24xx())
186 devconf &= ~OMAP2_CONTROL_DEVCONF1_ACTOV;
189 if (cpu_is_omap24xx())
190 omap_writel(devconf, OMAP2_CONTROL_DEVCONF1);
192 omap_writel(devconf | OMAP2_CONTROL_DEVCONF0_LBCLK,
193 OMAP2_CONTROL_DEVCONF0);
195 reg = omap_readl(OMAP2_CONTROL_PBIAS);
196 reg |= OMAP2_CONTROL_PBIAS_SCTRL;
197 omap_writel(reg, OMAP2_CONTROL_PBIAS);
199 reg = omap_readl(OMAP2_CONTROL_PBIAS);
200 reg &= ~OMAP2_CONTROL_PBIAS_PWRDNZ;
201 omap_writel(reg, OMAP2_CONTROL_PBIAS);
203 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
204 P1_DEV_GRP, VMMC1_DEV_GRP);
208 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
209 vdd_sel, VMMC1_DEDICATED);
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;
220 reg |= OMAP2_CONTROL_PBIAS_VMODE;
221 omap_writel(reg, OMAP2_CONTROL_PBIAS);
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);
233 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
234 LDO_CLR, VMMC1_DEV_GRP);
238 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
239 VSEL_S2_CLR, VMMC1_DEDICATED);
243 /* 100ms delay required for PBIAS configuration */
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);
258 static struct omap_mmc_platform_data mmc1_data = {
260 .init = hsmmc_late_init,
261 .cleanup = hsmmc_cleanup,
263 .suspend = hsmmc_suspend,
264 .resume = hsmmc_resume,
266 .dma_mask = 0xffffffff,
269 .set_power = hsmmc_set_power,
270 .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 |
272 .name = "first slot",
274 .card_detect_irq = TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ),
275 .card_detect = hsmmc_card_detect,
279 static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC];
281 void __init hsmmc_init(void)
283 hsmmc_data[0] = &mmc1_data;
284 omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
289 void __init hsmmc_init(void)