aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkishore kadiyala <kishore.kadiyala@ti.com>2010-09-24 13:13:20 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2010-10-28 18:29:59 -0400
commit72f2e2c763edc41f8eead042b6ff933acb0378e2 (patch)
treeb31ca0ae6be04e9191fdd99fa157c9ec4b4598a2
parent8e00593557c3c5a7bc6f636412a1cadcf4624232 (diff)
mfd: Adding twl6030 mmc card detect support for MMC1
Adding card detect callback function and card detect configuration function for MMC1 Controller on OMAP4. Card detect configuration function does initial configuration of the MMC Control & PullUp-PullDown registers of Phoenix. For MMC1 Controller, card detect interrupt source is twl6030 which is non-gpio. The card detect call back function provides card present/absent status by reading MMC Control register present on twl6030. Since OMAP4 doesn't use any GPIO line as used in OMAP3 for card detect, the suspend/resume initialization which was done in omap_hsmmc_gpio_init previously is moved to the probe thus making it generic for both OMAP3 & OMAP4. Cc: Tony Lindgren <tony@atomide.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Madhusudhan Chikkature <madhu.cr@ti.com> Cc: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Kishore Kadiyala <kishore.kadiyala@ti.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c7
-rw-r--r--drivers/mfd/twl6030-irq.c73
-rw-r--r--drivers/mmc/host/omap_hsmmc.c4
-rw-r--r--include/linux/i2c/twl.h31
4 files changed, 112 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 69a4ae971e41..df5a425a49d1 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -269,9 +269,14 @@ static int omap4_twl6030_hsmmc_late_init(struct device *dev)
269 struct omap_mmc_platform_data *pdata = dev->platform_data; 269 struct omap_mmc_platform_data *pdata = dev->platform_data;
270 270
271 /* Setting MMC1 Card detect Irq */ 271 /* Setting MMC1 Card detect Irq */
272 if (pdev->id == 0) 272 if (pdev->id == 0) {
273 ret = twl6030_mmc_card_detect_config();
274 if (ret)
275 pr_err("Failed configuring MMC1 card detect\n");
273 pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE + 276 pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
274 MMCDETECT_INTR_OFFSET; 277 MMCDETECT_INTR_OFFSET;
278 pdata->slots[0].card_detect = twl6030_mmc_card_detect;
279 }
275 return ret; 280 return ret;
276} 281}
277 282
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index 10bf228ad626..2d3bb82dbf24 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -36,6 +36,7 @@
36#include <linux/irq.h> 36#include <linux/irq.h>
37#include <linux/kthread.h> 37#include <linux/kthread.h>
38#include <linux/i2c/twl.h> 38#include <linux/i2c/twl.h>
39#include <linux/platform_device.h>
39 40
40/* 41/*
41 * TWL6030 (unlike its predecessors, which had two level interrupt handling) 42 * TWL6030 (unlike its predecessors, which had two level interrupt handling)
@@ -223,6 +224,78 @@ int twl6030_interrupt_mask(u8 bit_mask, u8 offset)
223} 224}
224EXPORT_SYMBOL(twl6030_interrupt_mask); 225EXPORT_SYMBOL(twl6030_interrupt_mask);
225 226
227int twl6030_mmc_card_detect_config(void)
228{
229 int ret;
230 u8 reg_val = 0;
231
232 /* Unmasking the Card detect Interrupt line for MMC1 from Phoenix */
233 twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
234 REG_INT_MSK_LINE_B);
235 twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
236 REG_INT_MSK_STS_B);
237 /*
238 * Intially Configuring MMC_CTRL for receving interrupts &
239 * Card status on TWL6030 for MMC1
240 */
241 ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &reg_val, TWL6030_MMCCTRL);
242 if (ret < 0) {
243 pr_err("twl6030: Failed to read MMCCTRL, error %d\n", ret);
244 return ret;
245 }
246 reg_val &= ~VMMC_AUTO_OFF;
247 reg_val |= SW_FC;
248 ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, TWL6030_MMCCTRL);
249 if (ret < 0) {
250 pr_err("twl6030: Failed to write MMCCTRL, error %d\n", ret);
251 return ret;
252 }
253
254 /* Configuring PullUp-PullDown register */
255 ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &reg_val,
256 TWL6030_CFG_INPUT_PUPD3);
257 if (ret < 0) {
258 pr_err("twl6030: Failed to read CFG_INPUT_PUPD3, error %d\n",
259 ret);
260 return ret;
261 }
262 reg_val &= ~(MMC_PU | MMC_PD);
263 ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val,
264 TWL6030_CFG_INPUT_PUPD3);
265 if (ret < 0) {
266 pr_err("twl6030: Failed to write CFG_INPUT_PUPD3, error %d\n",
267 ret);
268 return ret;
269 }
270 return 0;
271}
272EXPORT_SYMBOL(twl6030_mmc_card_detect_config);
273
274int twl6030_mmc_card_detect(struct device *dev, int slot)
275{
276 int ret = -EIO;
277 u8 read_reg = 0;
278 struct platform_device *pdev = to_platform_device(dev);
279
280 if (pdev->id) {
281 /* TWL6030 provide's Card detect support for
282 * only MMC1 controller.
283 */
284 pr_err("Unkown MMC controller %d in %s\n", pdev->id, __func__);
285 return ret;
286 }
287 /*
288 * BIT0 of MMC_CTRL on TWL6030 provides card status for MMC1
289 * 0 - Card not present ,1 - Card present
290 */
291 ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &read_reg,
292 TWL6030_MMCCTRL);
293 if (ret >= 0)
294 ret = read_reg & STS_MMC;
295 return ret;
296}
297EXPORT_SYMBOL(twl6030_mmc_card_detect);
298
226int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) 299int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
227{ 300{
228 301
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index e865032a52eb..82a1079bbdc7 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -483,8 +483,6 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
483 int ret; 483 int ret;
484 484
485 if (gpio_is_valid(pdata->slots[0].switch_pin)) { 485 if (gpio_is_valid(pdata->slots[0].switch_pin)) {
486 pdata->suspend = omap_hsmmc_suspend_cdirq;
487 pdata->resume = omap_hsmmc_resume_cdirq;
488 if (pdata->slots[0].cover) 486 if (pdata->slots[0].cover)
489 pdata->slots[0].get_cover_state = 487 pdata->slots[0].get_cover_state =
490 omap_hsmmc_get_cover_state; 488 omap_hsmmc_get_cover_state;
@@ -2218,6 +2216,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
2218 "Unable to grab MMC CD IRQ\n"); 2216 "Unable to grab MMC CD IRQ\n");
2219 goto err_irq_cd; 2217 goto err_irq_cd;
2220 } 2218 }
2219 pdata->suspend = omap_hsmmc_suspend_cdirq;
2220 pdata->resume = omap_hsmmc_resume_cdirq;
2221 } 2221 }
2222 2222
2223 omap_hsmmc_disable_irq(host); 2223 omap_hsmmc_disable_irq(host);
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 53089516c17a..c760991b354a 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -141,6 +141,16 @@
141#define TWL6030_CHARGER_CTRL_INT_MASK 0x10 141#define TWL6030_CHARGER_CTRL_INT_MASK 0x10
142#define TWL6030_CHARGER_FAULT_INT_MASK 0x60 142#define TWL6030_CHARGER_FAULT_INT_MASK 0x60
143 143
144#define TWL6030_MMCCTRL 0xEE
145#define VMMC_AUTO_OFF (0x1 << 3)
146#define SW_FC (0x1 << 2)
147#define STS_MMC 0x1
148
149#define TWL6030_CFG_INPUT_PUPD3 0xF2
150#define MMC_PU (0x1 << 3)
151#define MMC_PD (0x1 << 2)
152
153
144 154
145#define TWL4030_CLASS_ID 0x4030 155#define TWL4030_CLASS_ID 0x4030
146#define TWL6030_CLASS_ID 0x6030 156#define TWL6030_CLASS_ID 0x6030
@@ -173,6 +183,27 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
173int twl6030_interrupt_unmask(u8 bit_mask, u8 offset); 183int twl6030_interrupt_unmask(u8 bit_mask, u8 offset);
174int twl6030_interrupt_mask(u8 bit_mask, u8 offset); 184int twl6030_interrupt_mask(u8 bit_mask, u8 offset);
175 185
186/* Card detect Configuration for MMC1 Controller on OMAP4 */
187#ifdef CONFIG_TWL4030_CORE
188int twl6030_mmc_card_detect_config(void);
189#else
190static inline int twl6030_mmc_card_detect_config(void)
191{
192 pr_debug("twl6030_mmc_card_detect_config not supported\n");
193 return 0;
194}
195#endif
196
197/* MMC1 Controller on OMAP4 uses Phoenix irq for Card detect */
198#ifdef CONFIG_TWL4030_CORE
199int twl6030_mmc_card_detect(struct device *dev, int slot);
200#else
201static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
202{
203 pr_debug("Call back twl6030_mmc_card_detect not supported\n");
204 return -EIO;
205}
206#endif
176/*----------------------------------------------------------------------*/ 207/*----------------------------------------------------------------------*/
177 208
178/* 209/*