diff options
Diffstat (limited to 'drivers/mmc/omap_hsmmc.c')
| -rw-r--r-- | drivers/mmc/omap_hsmmc.c | 103 | 
1 files changed, 75 insertions, 28 deletions
| diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index afd9b30b5..67cfcc24d 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,40 @@ 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->getcd = omap_mmc_getcd; +	mmc->getwp = omap_mmc_getwp; +	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"); +	priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");  	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; |