summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-imx/devices.c2
-rw-r--r--arch/arm/mach-imx/include/mach/devices-imx25.h2
-rw-r--r--arch/arm/mach-imx/include/mach/devices-imx35.h6
-rw-r--r--arch/arm/mach-imx/include/mach/devices-imx51.h4
-rw-r--r--arch/arm/mach-imx/include/mach/devices-imx53.h6
-rw-r--r--arch/arm/mach-imx/include/mach/devices.h3
-rw-r--r--arch/arm/mach-imx/include/mach/esdhc.h43
-rw-r--r--drivers/mci/imx-esdhc.c37
8 files changed, 92 insertions, 11 deletions
diff --git a/arch/arm/mach-imx/devices.c b/arch/arm/mach-imx/devices.c
index 5b062f5f0f..6cd50f31f5 100644
--- a/arch/arm/mach-imx/devices.c
+++ b/arch/arm/mach-imx/devices.c
@@ -48,7 +48,7 @@ struct device_d *imx_add_mmc(void *base, int id, void *pdata)
return imx_add_device("imx-mmc", id, base, 0x1000, pdata);
}
-struct device_d *imx_add_esdhc(void *base, int id, void *pdata)
+struct device_d *imx_add_esdhc(void *base, int id, struct esdhc_platform_data *pdata)
{
return imx_add_device("imx-esdhc", id, base, 0x1000, pdata);
}
diff --git a/arch/arm/mach-imx/include/mach/devices-imx25.h b/arch/arm/mach-imx/include/mach/devices-imx25.h
index eff59773f7..bd9dd0a914 100644
--- a/arch/arm/mach-imx/include/mach/devices-imx25.h
+++ b/arch/arm/mach-imx/include/mach/devices-imx25.h
@@ -36,7 +36,7 @@ static inline struct device_d *imx25_add_fec(struct fec_platform_data *pdata)
return imx_add_fec((void *)IMX_FEC_BASE, pdata);
}
-static inline struct device_d *imx25_add_mmc0(void *pdata)
+static inline struct device_d *imx25_add_mmc0(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)0x53fb4000, 0, pdata);
}
diff --git a/arch/arm/mach-imx/include/mach/devices-imx35.h b/arch/arm/mach-imx/include/mach/devices-imx35.h
index 69f4b36709..6c0d750050 100644
--- a/arch/arm/mach-imx/include/mach/devices-imx35.h
+++ b/arch/arm/mach-imx/include/mach/devices-imx35.h
@@ -41,17 +41,17 @@ static inline struct device_d *imx35_add_fec(struct fec_platform_data *pdata)
return imx_add_fec((void *)IMX_FEC_BASE, pdata);
}
-static inline struct device_d *imx35_add_mmc0(void *pdata)
+static inline struct device_d *imx35_add_mmc0(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)IMX_SDHC1_BASE, 0, pdata);
}
-static inline struct device_d *imx35_add_mmc1(void *pdata)
+static inline struct device_d *imx35_add_mmc1(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)IMX_SDHC2_BASE, 1, pdata);
}
-static inline struct device_d *imx35_add_mmc2(void *pdata)
+static inline struct device_d *imx35_add_mmc2(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)IMX_SDHC3_BASE, 2, pdata);
}
diff --git a/arch/arm/mach-imx/include/mach/devices-imx51.h b/arch/arm/mach-imx/include/mach/devices-imx51.h
index 23410a90d5..d9bed8c886 100644
--- a/arch/arm/mach-imx/include/mach/devices-imx51.h
+++ b/arch/arm/mach-imx/include/mach/devices-imx51.h
@@ -42,12 +42,12 @@ static inline struct device_d *imx51_add_fec(struct fec_platform_data *pdata)
return imx_add_fec((void *)MX51_MXC_FEC_BASE_ADDR, pdata);
}
-static inline struct device_d *imx51_add_mmc0(void *pdata)
+static inline struct device_d *imx51_add_mmc0(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)MX51_MMC_SDHC1_BASE_ADDR, 0, pdata);
}
-static inline struct device_d *imx51_add_mmc1(void *pdata)
+static inline struct device_d *imx51_add_mmc1(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)MX51_MMC_SDHC2_BASE_ADDR, 1, pdata);
}
diff --git a/arch/arm/mach-imx/include/mach/devices-imx53.h b/arch/arm/mach-imx/include/mach/devices-imx53.h
index bc32048180..bc01420161 100644
--- a/arch/arm/mach-imx/include/mach/devices-imx53.h
+++ b/arch/arm/mach-imx/include/mach/devices-imx53.h
@@ -36,17 +36,17 @@ static inline struct device_d *imx53_add_fec(struct fec_platform_data *pdata)
return imx_add_fec((void *)MX53_FEC_BASE_ADDR, pdata);
}
-static inline struct device_d *imx53_add_mmc0(void *pdata)
+static inline struct device_d *imx53_add_mmc0(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)MX53_ESDHC1_BASE_ADDR, 0, pdata);
}
-static inline struct device_d *imx53_add_mmc1(void *pdata)
+static inline struct device_d *imx53_add_mmc1(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)MX53_ESDHC2_BASE_ADDR, 1, pdata);
}
-static inline struct device_d *imx53_add_mmc2(void *pdata)
+static inline struct device_d *imx53_add_mmc2(struct esdhc_platform_data *pdata)
{
return imx_add_esdhc((void *)MX53_ESDHC3_BASE_ADDR, 2, pdata);
}
diff --git a/arch/arm/mach-imx/include/mach/devices.h b/arch/arm/mach-imx/include/mach/devices.h
index 7338ac56ed..f0f730a3c5 100644
--- a/arch/arm/mach-imx/include/mach/devices.h
+++ b/arch/arm/mach-imx/include/mach/devices.h
@@ -5,6 +5,7 @@
#include <mach/imx-nand.h>
#include <mach/imxfb.h>
#include <mach/imx-ipu-fb.h>
+#include <mach/esdhc.h>
struct device_d *imx_add_fec(void *base, struct fec_platform_data *pdata);
struct device_d *imx_add_spi(void *base, int id, struct spi_imx_master *pdata);
@@ -14,5 +15,5 @@ struct device_d *imx_add_nand(void *base, struct imx_nand_platform_data *pdata);
struct device_d *imx_add_fb(void *base, struct imx_fb_platform_data *pdata);
struct device_d *imx_add_ipufb(void *base, struct imx_ipu_fb_platform_data *pdata);
struct device_d *imx_add_mmc(void *base, int id, void *pdata);
-struct device_d *imx_add_esdhc(void *base, int id, void *pdata);
+struct device_d *imx_add_esdhc(void *base, int id, struct esdhc_platform_data *pdata);
diff --git a/arch/arm/mach-imx/include/mach/esdhc.h b/arch/arm/mach-imx/include/mach/esdhc.h
new file mode 100644
index 0000000000..aaf97481f4
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/esdhc.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010 Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifndef __ASM_ARCH_IMX_ESDHC_H
+#define __ASM_ARCH_IMX_ESDHC_H
+
+enum wp_types {
+ ESDHC_WP_NONE, /* no WP, neither controller nor gpio */
+ ESDHC_WP_CONTROLLER, /* mmc controller internal WP */
+ ESDHC_WP_GPIO, /* external gpio pin for WP */
+};
+
+enum cd_types {
+ ESDHC_CD_NONE, /* no CD, neither controller nor gpio */
+ ESDHC_CD_CONTROLLER, /* mmc controller internal CD */
+ ESDHC_CD_GPIO, /* external gpio pin for CD */
+ ESDHC_CD_PERMANENT, /* no CD, card permanently wired to host */
+};
+
+/**
+ * struct esdhc_platform_data - platform data for esdhc on i.MX
+ *
+ * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
+ *
+ * @wp_gpio: gpio for write_protect
+ * @cd_gpio: gpio for card_detect interrupt
+ * @wp_type: type of write_protect method (see wp_types enum above)
+ * @cd_type: type of card_detect method (see cd_types enum above)
+ */
+
+struct esdhc_platform_data {
+ unsigned int wp_gpio;
+ unsigned int cd_gpio;
+ enum wp_types wp_type;
+ enum cd_types cd_type;
+};
+#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index d19b6da4c5..fe55697638 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -36,6 +36,8 @@
#include <asm/mmu.h>
#include <mach/clock.h>
#include <mach/generic.h>
+#include <mach/esdhc.h>
+#include <gpio.h>
#include "imx-esdhc.h"
@@ -392,6 +394,31 @@ static void esdhc_set_ios(struct mci_host *mci, struct device_d *dev,
}
+static int esdhc_card_detect(struct fsl_esdhc_host *host)
+{
+ struct fsl_esdhc *regs = host->regs;
+ struct esdhc_platform_data *pdata = host->dev->platform_data;
+ int ret;
+
+ if (!pdata)
+ return 1;
+
+ switch (pdata->cd_type) {
+ case ESDHC_CD_NONE:
+ case ESDHC_CD_PERMANENT:
+ return 1;
+ case ESDHC_CD_CONTROLLER:
+ return !(esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL);
+ case ESDHC_CD_GPIO:
+ ret = gpio_direction_input(pdata->cd_gpio);
+ if (ret)
+ return ret;
+ return gpio_get_value(pdata->cd_gpio) ? 0 : 1;
+ }
+
+ return 0;
+}
+
static int esdhc_init(struct mci_host *mci, struct device_d *dev)
{
struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
@@ -399,6 +426,16 @@ static int esdhc_init(struct mci_host *mci, struct device_d *dev)
int timeout = 1000;
int ret = 0;
+ ret = esdhc_card_detect(host);
+
+ if (ret == 0)
+ return -ENODEV;
+
+ if (ret < 0)
+ return ret;
+
+ ret = 0;
+
/* Enable cache snooping */
if (host && !host->no_snoop)
esdhc_write32(&regs->scr, 0x00000040);