summaryrefslogtreecommitdiff
path: root/drivers/mmc/omap_hsmmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/omap_hsmmc.c')
-rw-r--r--drivers/mmc/omap_hsmmc.c107
1 files changed, 79 insertions, 28 deletions
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index afd9b30b51..166744c320 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -30,6 +30,7 @@
#include <twl4030.h>
#include <twl6030.h>
#include <twl6035.h>
+#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/mmc_host_def.h>
#include <asm/arch/sys_proto.h>
@@ -38,30 +39,71 @@
#define SYSCTL_SRC (1 << 25)
#define SYSCTL_SRD (1 << 26)
+struct omap_hsmmc_data {
+ struct hsmmc *base_addr;
+ int cd_gpio;
+ int wp_gpio;
+};
+
/* If we fail after 1 second wait, something is really bad */
#define MAX_RETRY_MS 1000
static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
unsigned int siz);
-static struct mmc hsmmc_dev[2];
+static struct mmc hsmmc_dev[3];
+static struct omap_hsmmc_data hsmmc_dev_data[3];
+
+#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \
+ (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
+static int omap_mmc_setup_gpio_in(int gpio, const char *label)
+{
+ if (!gpio_is_valid(gpio))
+ return -1;
+
+ if (gpio_request(gpio, label) < 0)
+ return -1;
+
+ if (gpio_direction_input(gpio) < 0)
+ return -1;
+
+ return gpio;
+}
+
+static int omap_mmc_getcd(struct mmc *mmc)
+{
+ int cd_gpio = ((struct omap_hsmmc_data *)mmc->priv)->cd_gpio;
+ return gpio_get_value(cd_gpio);
+}
+
+static int omap_mmc_getwp(struct mmc *mmc)
+{
+ int wp_gpio = ((struct omap_hsmmc_data *)mmc->priv)->wp_gpio;
+ return gpio_get_value(wp_gpio);
+}
+#else
+static inline int omap_mmc_setup_gpio_in(int gpio, const char *label)
+{
+ return -1;
+}
+
+#define omap_mmc_getcd NULL
+#define omap_mmc_getwp NULL
+#endif
#if defined(CONFIG_OMAP44XX) && defined(CONFIG_TWL6030_POWER)
static void omap4_vmmc_pbias_config(struct mmc *mmc)
{
u32 value = 0;
- struct omap_sys_ctrl_regs *const ctrl =
- (struct omap_sys_ctrl_regs *) SYSCTRL_GENERAL_CORE_BASE;
-
- value = readl(&ctrl->control_pbiaslite);
+ value = readl((*ctrl)->control_pbiaslite);
value &= ~(MMC1_PBIASLITE_PWRDNZ | MMC1_PWRDNZ);
- writel(value, &ctrl->control_pbiaslite);
+ writel(value, (*ctrl)->control_pbiaslite);
/* set VMMC to 3V */
twl6030_power_mmc_init();
- value = readl(&ctrl->control_pbiaslite);
+ value = readl((*ctrl)->control_pbiaslite);
value |= MMC1_PBIASLITE_VMODE | MMC1_PBIASLITE_PWRDNZ | MMC1_PWRDNZ;
- writel(value, &ctrl->control_pbiaslite);
+ writel(value, (*ctrl)->control_pbiaslite);
}
#endif
@@ -69,26 +111,24 @@ static void omap4_vmmc_pbias_config(struct mmc *mmc)
static void omap5_pbias_config(struct mmc *mmc)
{
u32 value = 0;
- struct omap_sys_ctrl_regs *const ctrl =
- (struct omap_sys_ctrl_regs *) SYSCTRL_GENERAL_CORE_BASE;
- value = readl(&ctrl->control_pbias);
+ value = readl((*ctrl)->control_pbias);
value &= ~(SDCARD_PWRDNZ | SDCARD_BIAS_PWRDNZ);
value |= SDCARD_BIAS_HIZ_MODE;
- writel(value, &ctrl->control_pbias);
+ writel(value, (*ctrl)->control_pbias);
twl6035_mmc1_poweron_ldo();
- value = readl(&ctrl->control_pbias);
+ value = readl((*ctrl)->control_pbias);
value &= ~SDCARD_BIAS_HIZ_MODE;
value |= SDCARD_PBIASLITE_VMODE | SDCARD_PWRDNZ | SDCARD_BIAS_PWRDNZ;
- writel(value, &ctrl->control_pbias);
+ writel(value, (*ctrl)->control_pbias);
- value = readl(&ctrl->control_pbias);
+ value = readl((*ctrl)->control_pbias);
if (value & (1 << 23)) {
value &= ~(SDCARD_PWRDNZ | SDCARD_BIAS_PWRDNZ);
value |= SDCARD_BIAS_HIZ_MODE;
- writel(value, &ctrl->control_pbias);
+ writel(value, (*ctrl)->control_pbias);
}
}
#endif
@@ -177,11 +217,12 @@ void mmc_init_stream(struct hsmmc *mmc_base)
static int mmc_init_setup(struct mmc *mmc)
{
- struct hsmmc *mmc_base = (struct hsmmc *)mmc->priv;
+ struct hsmmc *mmc_base;
unsigned int reg_val;
unsigned int dsor;
ulong start;
+ mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
mmc_board_init(mmc);
writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET,
@@ -262,10 +303,11 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit)
static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
- struct hsmmc *mmc_base = (struct hsmmc *)mmc->priv;
+ struct hsmmc *mmc_base;
unsigned int flags, mmc_stat;
ulong start;
+ mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
start = get_timer(0);
while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK)) != 0) {
if (get_timer(0) - start > MAX_RETRY_MS) {
@@ -489,10 +531,11 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
static void mmc_set_ios(struct mmc *mmc)
{
- struct hsmmc *mmc_base = (struct hsmmc *)mmc->priv;
+ struct hsmmc *mmc_base;
unsigned int dsor = 0;
ulong start;
+ mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
/* configue bus width */
switch (mmc->bus_width) {
case 8:
@@ -540,36 +583,44 @@ static void mmc_set_ios(struct mmc *mmc)
writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
}
-int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max)
+int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
+ int wp_gpio)
{
- struct mmc *mmc;
-
- mmc = &hsmmc_dev[dev_index];
+ struct mmc *mmc = &hsmmc_dev[dev_index];
+ struct omap_hsmmc_data *priv_data = &hsmmc_dev_data[dev_index];
sprintf(mmc->name, "OMAP SD/MMC");
mmc->send_cmd = mmc_send_cmd;
mmc->set_ios = mmc_set_ios;
mmc->init = mmc_init_setup;
- mmc->getcd = NULL;
+ mmc->priv = priv_data;
switch (dev_index) {
case 0:
- mmc->priv = (struct hsmmc *)OMAP_HSMMC1_BASE;
+ priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
break;
#ifdef OMAP_HSMMC2_BASE
case 1:
- mmc->priv = (struct hsmmc *)OMAP_HSMMC2_BASE;
+ priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE;
break;
#endif
#ifdef OMAP_HSMMC3_BASE
case 2:
- mmc->priv = (struct hsmmc *)OMAP_HSMMC3_BASE;
+ priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE;
break;
#endif
default:
- mmc->priv = (struct hsmmc *)OMAP_HSMMC1_BASE;
+ priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
return 1;
}
+ priv_data->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd");
+ if (priv_data->cd_gpio != -1)
+ mmc->getcd = omap_mmc_getcd;
+
+ priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
+ if (priv_data->wp_gpio != -1)
+ mmc->getwp = omap_mmc_getwp;
+
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
mmc->host_caps = (MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
MMC_MODE_HC) & ~host_caps_mask;