2 * linux/arch/arm/mach-omap2/board-sdp-hsmmc.c
4 * Copyright (C) 2007 Texas Instruments
5 * Author: Texas Instruments
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 #include <linux/err.h>
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/interrupt.h>
15 #include <linux/delay.h>
16 #include <asm/hardware.h>
17 #include <asm/arch/twl4030.h>
18 #include <asm/arch/mmc.h>
19 #include <asm/arch/board.h>
22 #ifdef CONFIG_MMC_OMAP_HS
24 #define VMMC1_DEV_GRP 0x27
25 #define P1_DEV_GRP 0x20
26 #define VMMC1_DEDICATED 0x2A
29 #define TWL_GPIO_PUPDCTR1 0x13
30 #define TWL_GPIO_IMR1A 0x1C
31 #define TWL_GPIO_ISR1A 0x19
33 #define VSEL_S2_CLR 0x40
34 #define GPIO_0_BIT_POS 1 << 0
38 static irqreturn_t mmc_omap_cd_handler(int irq, void *dev_id)
42 detect = twl4030_get_gpio_datain(MMC1_CD_IRQ);
43 omap_mmc_notify_card_detect(dev_id, 0, detect);
48 * MMC Slot Initialization.
50 static int sdp_mmc_late_init(struct device *dev)
55 * Configure TWL4030 GPIO parameters for MMC hotplug irq
57 ret = twl4030_request_gpio(MMC1_CD_IRQ);
61 ret = twl4030_set_gpio_edge_ctrl(MMC1_CD_IRQ,
62 TWL4030_GPIO_EDGE_RISING | TWL4030_GPIO_EDGE_FALLING);
66 ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x02,
71 ret = twl4030_set_gpio_debounce(MMC1_CD_IRQ, TWL4030_GPIO_IS_ENABLE);
75 ret = request_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ),
76 mmc_omap_cd_handler, IRQF_DISABLED, "MMC1_CD_IRQ", dev);
82 dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
87 static void sdp_mmc_cleanup(struct device *dev)
91 ret = twl4030_free_gpio(MMC1_CD_IRQ);
92 free_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ), dev);
94 dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
100 * To mask and unmask MMC Card Detect Interrupt
104 static int mask_cd_interrupt(int mask)
108 ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, ®, TWL_GPIO_IMR1A);
112 reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
114 ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_IMR1A);
118 ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, ®, TWL_GPIO_ISR1A);
122 reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
124 ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_ISR1A);
131 static int sdp_mmc_suspend(struct device *dev, int slot)
135 disable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
136 ret = mask_cd_interrupt(1);
141 static int sdp_mmc_resume(struct device *dev, int slot)
145 enable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
146 ret = mask_cd_interrupt(0);
153 static int sdp_mmc_set_power(struct device *dev, int slot, int power_on,
156 u32 vdd_sel = 0, devconf = 0, reg = 0;
159 /* REVISIT: Using address directly till the control.h defines
162 #if defined(CONFIG_ARCH_OMAP2430)
163 #define OMAP2_CONTROL_PBIAS 0x490024A0
165 #define OMAP2_CONTROL_PBIAS 0x48002520
169 if (cpu_is_omap24xx())
170 devconf = omap_readl(0x490022E8);
172 devconf = omap_readl(0x48002274);
178 if (cpu_is_omap24xx())
179 devconf = (devconf | (1 << 31));
181 case MMC_VDD_165_195:
183 if (cpu_is_omap24xx())
184 devconf = (devconf & ~(1 << 31));
187 if (cpu_is_omap24xx())
188 omap_writel(devconf, 0x490022E8);
190 omap_writel(devconf | 1 << 24, 0x48002274);
192 omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) | 1 << 2,
193 OMAP2_CONTROL_PBIAS);
194 omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) & ~(1 << 1),
195 OMAP2_CONTROL_PBIAS);
197 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
198 P1_DEV_GRP, VMMC1_DEV_GRP);
202 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
203 vdd_sel, VMMC1_DEDICATED);
208 reg = omap_readl(OMAP2_CONTROL_PBIAS);
209 reg = (vdd_sel == VSEL_18V) ? ((reg | 0x6) & ~0x1)
211 omap_writel(reg, OMAP2_CONTROL_PBIAS);
215 } else if (power_on == 0) {
218 /* For MMC1, Toggle PBIAS before every power up sequence */
219 omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) & ~(1 << 1),
220 OMAP2_CONTROL_PBIAS);
221 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
222 LDO_CLR, VMMC1_DEV_GRP);
226 ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
227 VSEL_S2_CLR, VMMC1_DEDICATED);
231 /* 100ms delay required for PBIAS configuration */
233 omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) | 0x7,
234 OMAP2_CONTROL_PBIAS);
245 static struct omap_mmc_platform_data sdp_mmc_data = {
248 .init = sdp_mmc_late_init,
249 .cleanup = sdp_mmc_cleanup,
251 .suspend = sdp_mmc_suspend,
252 .resume = sdp_mmc_resume,
255 .set_power = sdp_mmc_set_power,
256 .set_bus_mode = NULL,
258 .get_cover_state = NULL,
259 .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 |
261 .name = "first slot",
265 void __init sdp_mmc_init(void)
267 omap_set_mmc_info(1, &sdp_mmc_data);
272 void __init sdp_mmc_init(void)