kishore kadiyala wrote:
Adding card detect callback function which gives the status of
the card .For MMC1 Controller, Card detect interrupt source is
twl6030 and card present/absent status is provided by MMCCTRL
register of twl6030.
Signed-off-by: Kishore Kadiyala <kishore.kadiy...@ti.com>
---
arch/arm/mach-omap2/board-4430sdp.c | 11 +++++--
arch/arm/mach-omap2/hsmmc.c | 1 +
arch/arm/plat-omap/include/plat/mmc.h | 1 +
drivers/mfd/twl6030-irq.c | 23 ++++++++++++++++
drivers/mmc/host/omap_hsmmc.c | 30 ++++++++++++++++++---
include/linux/i2c/twl.h | 46 +++++++++++++++++++++++++++++++++
6 files changed, 104 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-omap2/board-4430sdp.c
b/arch/arm/mach-omap2/board-4430sdp.c
index e4a5d66..1cf6f3b 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -144,6 +144,7 @@ static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
.wires = 8,
+ .cd_type = NON_GPIO,
.gpio_wp = -EINVAL,
},
{
@@ -174,10 +175,14 @@ static int omap4_twl6030_hsmmc_late_init(struct device
*dev)
struct platform_device, dev);
struct omap_mmc_platform_data *pdata = dev->platform_data;
- /* Setting MMC1 Card detect Irq */
- if (pdev->id == 0)
+ /* MMC1 Card detect Configuration */
+ if (pdev->id == 0) {
+ ret = omap4_hsmmc1_card_detect_config();
+ if (ret < 0)
+ pr_err("Unable to configure Card detect for MMC1\n");
pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
- MMCDETECT_INTR_OFFSET;
+ MMCDETECT_INTR_OFFSET;
+ }
return ret;
}
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 1ef54b0..8a8f7b1 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -265,6 +265,7 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info
*controllers)
mmc->get_context_loss_count = hsmmc_get_context_loss;
mmc->slots[0].switch_pin = c->gpio_cd;
+ mmc->slots[0].cd_type = c->cd_type;
mmc->slots[0].gpio_wp = c->gpio_wp;
mmc->slots[0].remux = c->remux;
diff --git a/arch/arm/plat-omap/include/plat/mmc.h
b/arch/arm/plat-omap/include/plat/mmc.h
index ed60c0f..cd42c77 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/device.h>
#include <linux/mmc/host.h>
+#include <linux/i2c/twl.h>
#include <plat/board.h>
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index 10bf228..f17e4e7 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -223,6 +223,29 @@ int twl6030_interrupt_mask(u8 bit_mask, u8 offset)
}
EXPORT_SYMBOL(twl6030_interrupt_mask);
+int twl6030_mmc_card_detect(int host_id, int slot)
+{
+ int ret = -ENOSYS;
+ u8 read_reg;
+
+ switch (host_id) {
+ case 0:
+ /*
+ * BIT0 of REG_MMC_CTRL
+ * 0 - Card not present ,1 - Card present
+ */
+ ret = twl_i2c_read_u8(TWL6030_MODULE_ID0,
+ &read_reg, TWL6030_MMCCTRL);
+ if (ret >= 0)
+ ret = read_reg & STS_MMC;
+ break;
+ default:
+ pr_err("Unkown MMC controller %d in %s\n", host_id, __func__);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(twl6030_mmc_card_detect);
+
int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
{
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index b032828..5d5bd29 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
As per my email 5/5/10, I would suggest the only change to omap_hsmmc is:
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index e9caf69..f792cff 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -465,8 +465,6 @@ static int omap_hsmmc_gpio_init(struct
omap_mmc_platform_data *pdata)
int ret;
if (gpio_is_valid(pdata->slots[0].switch_pin)) {
- pdata->suspend = omap_hsmmc_suspend_cdirq;
- pdata->resume = omap_hsmmc_resume_cdirq;
if (pdata->slots[0].cover)
pdata->slots[0].get_cover_state =
omap_hsmmc_get_cover_state;
@@ -2160,6 +2158,8 @@ static int __init omap_hsmmc_probe(struct platform_device
*pdev)
"Unable to grab MMC CD IRQ\n");
goto err_irq_cd;
}
+ pdata->suspend = omap_hsmmc_suspend_cdirq;
+ pdata->resume = omap_hsmmc_resume_cdirq;
}
OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
And that the late init function is used to do the rest e.g.
find a home for these 3 functions:
static int omap4_twl6030_hsmmc_late_init(struct device *dev)
{
int ret = 0;
struct platform_device *pdev = container_of(dev,
struct platform_device, dev);
struct omap_mmc_platform_data *pdata = dev->platform_data;
/* MMC1 Card detect Configuration */
if (pdev->id == 0) {
ret = omap4_hsmmc1_card_detect_config();
if (ret < 0)
pr_err("Unable to configure Card detect for MMC1\n");
pdata->slots[0].card_detect = twl6030_mmc_card_detect;
pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
MMCDETECT_INTR_OFFSET;
}
return ret;
}
static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
{
struct omap_mmc_platform_data *pdata = dev->platform_data;
pdata->init = omap4_twl6030_hsmmc_late_init;
}
void __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
{
struct omap2_hsmmc_info *c;
omap2_hsmmc_init(controllers);
for (c = controllers; c->mmc; c++)
omap4_twl6030_hsmmc_set_late_init(c->dev);
}
@@ -189,9 +189,16 @@ struct omap_hsmmc_host {
static int omap_hsmmc_card_detect(struct device *dev, int slot)
{
struct omap_mmc_platform_data *mmc = dev->platform_data;
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
+ int ret = -ENOSYS;
- /* NOTE: assumes card detect signal is active-low */
- return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
+ if (mmc->slots[0].cd_type == GPIO)
+ /* NOTE: assumes card detect signal is active-low */
+ ret = !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
+ else
+ ret = twl6030_mmc_card_detect(pdev->id, slot);
+ return ret;
}
static int omap_hsmmc_get_wp(struct device *dev, int slot)
@@ -464,8 +471,6 @@ static int omap_hsmmc_gpio_init(struct
omap_mmc_platform_data *pdata)
int ret;
if (gpio_is_valid(pdata->slots[0].switch_pin)) {
- pdata->suspend = omap_hsmmc_suspend_cdirq;
- pdata->resume = omap_hsmmc_resume_cdirq;
if (pdata->slots[0].cover)
pdata->slots[0].get_cover_state =
omap_hsmmc_get_cover_state;
@@ -504,6 +509,15 @@ err_free_sp:
return ret;
}
+static int omap_hsmmc_non_gpio_init(struct omap_mmc_platform_data *pdata)
+{
+ if (pdata->slots[0].switch_pin > 0) {
+ pdata->slots[0].card_detect = omap_hsmmc_card_detect;
+ pdata->slots[0].card_detect_irq = pdata->slots[0].switch_pin;
+ }
+ return 0;
+}
+
static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
{
if (gpio_is_valid(pdata->slots[0].gpio_wp))
@@ -1988,7 +2002,11 @@ static int __init omap_hsmmc_probe(struct
platform_device *pdev)
if (res == NULL)
return -EBUSY;
- ret = omap_hsmmc_gpio_init(pdata);
+ if (pdata->slots[0].cd_type == GPIO)
+ ret = omap_hsmmc_gpio_init(pdata);
+ else
+ ret = omap_hsmmc_non_gpio_init(pdata);
+
if (ret)
goto err;
@@ -2170,6 +2188,8 @@ static int __init omap_hsmmc_probe(struct platform_device
*pdev)
"Unable to grab MMC CD IRQ\n");
goto err_irq_cd;
}
+ pdata->suspend = omap_hsmmc_suspend_cdirq;
+ pdata->resume = omap_hsmmc_resume_cdirq;
}
omap_hsmmc_disable_irq(host);
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 6de90bf..38ef529 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -141,6 +141,14 @@
#define TWL6030_CHARGER_CTRL_INT_MASK 0x10
#define TWL6030_CHARGER_FAULT_INT_MASK 0x60
+#define TWL6030_MMCCTRL 0xEE
+#define VMMC_AUTO_OFF (0x1 << 3)
+#define SW_FC (0x1 << 2)
+#define STS_MMC 0x1
+
+#define TWL6030_CFG_INPUT_PUPD3 0xF2
+#define MMC_PU (0x1 << 3)
+#define MMC_PD (0x1 << 2)
#define TWL4030_CLASS_ID 0x4030
#define TWL6030_CLASS_ID 0x6030
@@ -173,6 +181,44 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned
num_bytes);
int twl6030_interrupt_unmask(u8 bit_mask, u8 offset);
int twl6030_interrupt_mask(u8 bit_mask, u8 offset);
+/* MMC1 Controller on OMAP4 uses Phoenix Irq for Card detect */
+int twl6030_mmc_card_detect(int host_id, int slot);
+
+/* Configuring Card Detect for MMC1 */
+static inline int omap4_hsmmc1_card_detect_config(void)
+{
+ int res = -1;
+ u8 reg_val = 0;
+
+ /* Unmasking the Card detect Interrupt line for MMC1 from Phoenix */
+ if (twl_class_is_6030()) {
+ twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
+ REG_INT_MSK_LINE_B);
+ twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
+ REG_INT_MSK_STS_B);
+ }
+
+ /*
+ * Intially Configuring MMC_CTRL for receving interrupts &
+ * Card status on TWL6030 for MMC1
+ */
+ res = twl_i2c_read_u8(TWL6030_MODULE_ID0, ®_val, TWL6030_MMCCTRL);
+ if (res < 0)
+ return res;
+ reg_val &= ~VMMC_AUTO_OFF;
+ reg_val |= SW_FC;
+ twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, TWL6030_MMCCTRL);
+
+ /* Configuring CFG_INPUT_PUPD3 */
+ res = twl_i2c_read_u8(TWL6030_MODULE_ID0, ®_val,
+ TWL6030_CFG_INPUT_PUPD3);
+ if (res < 0)
+ return res;
+ reg_val &= ~(MMC_PU | MMC_PD);
+ twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, TWL6030_CFG_INPUT_PUPD3);
+ return res;
+}
+
/*----------------------------------------------------------------------*/
/*
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html