diff options
| -rwxr-xr-x | MAKEALL | 39 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-exynos/mmc.h | 93 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-s5pc1xx/mmc.h | 93 | ||||
| -rw-r--r-- | drivers/mmc/Makefile | 2 | ||||
| -rw-r--r-- | drivers/mmc/fsl_esdhc.c | 39 | ||||
| -rw-r--r-- | drivers/mmc/mmc.c | 4 | ||||
| -rw-r--r-- | drivers/mmc/mxsmmc.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/omap_hsmmc.c | 55 | ||||
| -rw-r--r-- | drivers/mmc/s5p_mmc.c | 490 | ||||
| -rw-r--r-- | drivers/mmc/s5p_sdhci.c | 98 | ||||
| -rw-r--r-- | drivers/mmc/sdhci.c | 24 | ||||
| -rw-r--r-- | include/configs/origen.h | 7 | ||||
| -rw-r--r-- | include/configs/s5p_goni.h | 7 | ||||
| -rw-r--r-- | include/configs/s5pc210_universal.h | 7 | ||||
| -rw-r--r-- | include/configs/smdk5250.h | 3 | ||||
| -rw-r--r-- | include/configs/smdkv310.h | 7 | ||||
| -rw-r--r-- | include/configs/trats.h | 3 | ||||
| -rw-r--r-- | include/fsl_esdhc.h | 4 | ||||
| -rw-r--r-- | include/mmc.h | 53 | ||||
| -rw-r--r-- | include/sdhci.h | 7 | 
20 files changed, 358 insertions, 679 deletions
| @@ -340,12 +340,7 @@ LIST_ARM9="$(boards_by_cpu arm920t)	\  #########################################################################  ## ARM11 Systems  ######################################################################### -LIST_ARM11="$(boards_by_cpu arm1136)	\ -	imx31_phycore		\ -	imx31_phycore_eet	\ -	mx31pdk			\ -	smdk6400		\ -" +LIST_ARM11="$(boards_by_cpu arm1136)"  #########################################################################  ## ARMV7 Systems @@ -365,10 +360,7 @@ LIST_at91="$(boards_by_soc at91)"  LIST_pxa="$(boards_by_cpu pxa)" -LIST_ixp="$(boards_by_cpu ixp) -	pdnb3		\ -	scpu		\ -" +LIST_ixp="$(boards_by_cpu ixp)"  #########################################################################  ## ARM groups @@ -618,6 +610,11 @@ build_target() {  	target=$1  	build_idx=$2 +	if [ "$ONLY_LIST" == 'y' ] ; then +		list_target ${target} +		return +	fi +  	if [ $BUILD_MANY == 1 ] ; then  		output_dir="${OUTPUT_PREFIX}/${target}"  		mkdir -p "${output_dir}" @@ -627,11 +624,6 @@ build_target() {  	export BUILD_DIR="${output_dir}" -	if [ "$ONLY_LIST" == 'y' ] ; then -		list_target ${target} -		return -	fi -  	${MAKE} distclean >/dev/null  	${MAKE} -s ${target}_config @@ -669,16 +661,15 @@ build_target() {  	[ -e "${LOG_DIR}/${target}.ERR" ] && cat "${LOG_DIR}/${target}.ERR" -	#echo "Writing ${donep}${build_idx}"  	touch "${donep}${build_idx}"  }  manage_builds() {  	search_idx=${OLDEST_IDX} -	#echo "Searching ${OLDEST_IDX} to ${TOTAL_CNT}" +	if [ "$ONLY_LIST" == 'y' ] ; then return ; fi +  	while true; do  		if [ -e "${donep}${search_idx}" ] ; then -	#		echo "Found ${donep}${search_idx}"  			: $(( CURRENT_CNT-- ))  			[ ${OLDEST_IDX} -eq ${search_idx} ] &&  				: $(( OLDEST_IDX++ )) @@ -690,10 +681,8 @@ manage_builds() {  			[ ${OLDEST_IDX} -eq ${search_idx} ] &&  				: $(( OLDEST_IDX++ ))  		fi -		#echo "Checking search ${search_idx} vs ${TOTAL_CNT}"  		: $(( search_idx++ ))  		if [ ${search_idx} -gt ${TOTAL_CNT} ] ; then -			#echo "Checking current ${CURRENT_CNT} vs ${BUILD_NBUILDS}"  			if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then  				search_idx=${OLDEST_IDX}  				sleep 1 @@ -742,6 +731,12 @@ build_targets() {  #----------------------------------------------------------------------- +kill_children() { +	kill -- "-$1" + +	exit +} +  print_stats() {  	if [ "$ONLY_LIST" == 'y' ] ; then return ; fi @@ -762,6 +757,10 @@ print_stats() {  	fi  	echo "----------------------------------------------------------" +	if [ $BUILD_MANY == 1 ] ; then +		kill_children $$ & +	fi +  	exit $RC  } diff --git a/arch/arm/include/asm/arch-exynos/mmc.h b/arch/arm/include/asm/arch-exynos/mmc.h index 30f82b8aa..0f701c901 100644 --- a/arch/arm/include/asm/arch-exynos/mmc.h +++ b/arch/arm/include/asm/arch-exynos/mmc.h @@ -21,53 +21,54 @@  #ifndef __ASM_ARCH_MMC_H_  #define __ASM_ARCH_MMC_H_ -#ifndef __ASSEMBLY__ -struct s5p_mmc { -	unsigned int	sysad; -	unsigned short	blksize; -	unsigned short	blkcnt; -	unsigned int	argument; -	unsigned short	trnmod; -	unsigned short	cmdreg; -	unsigned int	rspreg0; -	unsigned int	rspreg1; -	unsigned int	rspreg2; -	unsigned int	rspreg3; -	unsigned int	bdata; -	unsigned int	prnsts; -	unsigned char	hostctl; -	unsigned char	pwrcon; -	unsigned char	blkgap; -	unsigned char	wakcon; -	unsigned short	clkcon; -	unsigned char	timeoutcon; -	unsigned char	swrst; -	unsigned int	norintsts;	/* errintsts */ -	unsigned int	norintstsen;	/* errintstsen */ -	unsigned int	norintsigen;	/* errintsigen */ -	unsigned short	acmd12errsts; -	unsigned char	res1[2]; -	unsigned int	capareg; -	unsigned char	res2[4]; -	unsigned int	maxcurr; -	unsigned char	res3[0x34]; -	unsigned int	control2; -	unsigned int	control3; -	unsigned char	res4[4]; -	unsigned int	control4; -	unsigned char	res5[0x6e]; -	unsigned short	hcver; -	unsigned char	res6[0xFF00]; -}; +#define SDHCI_CONTROL2		0x80 +#define SDHCI_CONTROL3		0x84 +#define SDHCI_CONTROL4		0x8C -struct mmc_host { -	struct s5p_mmc *reg; -	unsigned int version;	/* SDHCI spec. version */ -	unsigned int clock;	/* Current clock (MHz) */ -	int dev_index; -}; +#define SDHCI_CTRL2_ENSTAASYNCCLR	(1 << 31) +#define SDHCI_CTRL2_ENCMDCNFMSK		(1 << 30) +#define SDHCI_CTRL2_CDINVRXD3		(1 << 29) +#define SDHCI_CTRL2_SLCARDOUT		(1 << 28) -int s5p_mmc_init(int dev_index, int bus_width); +#define SDHCI_CTRL2_FLTCLKSEL_MASK	(0xf << 24) +#define SDHCI_CTRL2_FLTCLKSEL_SHIFT	(24) +#define SDHCI_CTRL2_FLTCLKSEL(_x)	((_x) << 24) -#endif	/* __ASSEMBLY__ */ +#define SDHCI_CTRL2_LVLDAT_MASK		(0xff << 16) +#define SDHCI_CTRL2_LVLDAT_SHIFT	(16) +#define SDHCI_CTRL2_LVLDAT(_x)		((_x) << 16) + +#define SDHCI_CTRL2_ENFBCLKTX		(1 << 15) +#define SDHCI_CTRL2_ENFBCLKRX		(1 << 14) +#define SDHCI_CTRL2_SDCDSEL		(1 << 13) +#define SDHCI_CTRL2_SDSIGPC		(1 << 12) +#define SDHCI_CTRL2_ENBUSYCHKTXSTART	(1 << 11) + +#define SDHCI_CTRL2_DFCNT_MASK(_x)	((_x) << 9) +#define SDHCI_CTRL2_DFCNT_SHIFT		(9) + +#define SDHCI_CTRL2_ENCLKOUTHOLD	(1 << 8) +#define SDHCI_CTRL2_RWAITMODE		(1 << 7) +#define SDHCI_CTRL2_DISBUFRD		(1 << 6) +#define SDHCI_CTRL2_SELBASECLK_MASK(_x)	((_x) << 4) +#define SDHCI_CTRL2_SELBASECLK_SHIFT	(4) +#define SDHCI_CTRL2_PWRSYNC		(1 << 3) +#define SDHCI_CTRL2_ENCLKOUTMSKCON	(1 << 1) +#define SDHCI_CTRL2_HWINITFIN		(1 << 0) + +#define SDHCI_CTRL3_FCSEL3		(1 << 31) +#define SDHCI_CTRL3_FCSEL2		(1 << 23) +#define SDHCI_CTRL3_FCSEL1		(1 << 15) +#define SDHCI_CTRL3_FCSEL0		(1 << 7) + +#define SDHCI_CTRL4_DRIVE_MASK(_x)	((_x) << 16) +#define SDHCI_CTRL4_DRIVE_SHIFT		(16) + +int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks); + +static inline unsigned int s5p_mmc_init(int index, int bus_width) +{ +	unsigned int base = samsung_get_base_mmc() + (0x10000 * index); +	return s5p_sdhci_init(base, 52000000, 400000, index); +}  #endif diff --git a/arch/arm/include/asm/arch-s5pc1xx/mmc.h b/arch/arm/include/asm/arch-s5pc1xx/mmc.h index adef4ee21..0f701c901 100644 --- a/arch/arm/include/asm/arch-s5pc1xx/mmc.h +++ b/arch/arm/include/asm/arch-s5pc1xx/mmc.h @@ -21,53 +21,54 @@  #ifndef __ASM_ARCH_MMC_H_  #define __ASM_ARCH_MMC_H_ -#ifndef __ASSEMBLY__ -struct s5p_mmc { -	unsigned int	sysad; -	unsigned short	blksize; -	unsigned short	blkcnt; -	unsigned int	argument; -	unsigned short	trnmod; -	unsigned short	cmdreg; -	unsigned int	rspreg0; -	unsigned int	rspreg1; -	unsigned int	rspreg2; -	unsigned int	rspreg3; -	unsigned int	bdata; -	unsigned int	prnsts; -	unsigned char	hostctl; -	unsigned char	pwrcon; -	unsigned char	blkgap; -	unsigned char	wakcon; -	unsigned short	clkcon; -	unsigned char	timeoutcon; -	unsigned char	swrst; -	unsigned int	norintsts;	/* errintsts */ -	unsigned int	norintstsen;	/* errintstsen */ -	unsigned int	norintsigen;	/* errintsigen */ -	unsigned short	acmd12errsts; -	unsigned char	res1[2]; -	unsigned int	capareg; -	unsigned char	res2[4]; -	unsigned int	maxcurr; -	unsigned char	res3[0x34]; -	unsigned int	control2; -	unsigned int	control3; -	unsigned char	res4[4]; -	unsigned int	control4; -	unsigned char	res5[0x6e]; -	unsigned short	hcver; -	unsigned char	res6[0xFFF00]; -}; +#define SDHCI_CONTROL2		0x80 +#define SDHCI_CONTROL3		0x84 +#define SDHCI_CONTROL4		0x8C -struct mmc_host { -	struct s5p_mmc *reg; -	unsigned int version;	/* SDHCI spec. version */ -	unsigned int clock;	/* Current clock (MHz) */ -	int dev_index; -}; +#define SDHCI_CTRL2_ENSTAASYNCCLR	(1 << 31) +#define SDHCI_CTRL2_ENCMDCNFMSK		(1 << 30) +#define SDHCI_CTRL2_CDINVRXD3		(1 << 29) +#define SDHCI_CTRL2_SLCARDOUT		(1 << 28) -int s5p_mmc_init(int dev_index, int bus_width); +#define SDHCI_CTRL2_FLTCLKSEL_MASK	(0xf << 24) +#define SDHCI_CTRL2_FLTCLKSEL_SHIFT	(24) +#define SDHCI_CTRL2_FLTCLKSEL(_x)	((_x) << 24) -#endif	/* __ASSEMBLY__ */ +#define SDHCI_CTRL2_LVLDAT_MASK		(0xff << 16) +#define SDHCI_CTRL2_LVLDAT_SHIFT	(16) +#define SDHCI_CTRL2_LVLDAT(_x)		((_x) << 16) + +#define SDHCI_CTRL2_ENFBCLKTX		(1 << 15) +#define SDHCI_CTRL2_ENFBCLKRX		(1 << 14) +#define SDHCI_CTRL2_SDCDSEL		(1 << 13) +#define SDHCI_CTRL2_SDSIGPC		(1 << 12) +#define SDHCI_CTRL2_ENBUSYCHKTXSTART	(1 << 11) + +#define SDHCI_CTRL2_DFCNT_MASK(_x)	((_x) << 9) +#define SDHCI_CTRL2_DFCNT_SHIFT		(9) + +#define SDHCI_CTRL2_ENCLKOUTHOLD	(1 << 8) +#define SDHCI_CTRL2_RWAITMODE		(1 << 7) +#define SDHCI_CTRL2_DISBUFRD		(1 << 6) +#define SDHCI_CTRL2_SELBASECLK_MASK(_x)	((_x) << 4) +#define SDHCI_CTRL2_SELBASECLK_SHIFT	(4) +#define SDHCI_CTRL2_PWRSYNC		(1 << 3) +#define SDHCI_CTRL2_ENCLKOUTMSKCON	(1 << 1) +#define SDHCI_CTRL2_HWINITFIN		(1 << 0) + +#define SDHCI_CTRL3_FCSEL3		(1 << 31) +#define SDHCI_CTRL3_FCSEL2		(1 << 23) +#define SDHCI_CTRL3_FCSEL1		(1 << 15) +#define SDHCI_CTRL3_FCSEL0		(1 << 7) + +#define SDHCI_CTRL4_DRIVE_MASK(_x)	((_x) << 16) +#define SDHCI_CTRL4_DRIVE_SHIFT		(16) + +int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks); + +static inline unsigned int s5p_mmc_init(int index, int bus_width) +{ +	unsigned int base = samsung_get_base_mmc() + (0x10000 * index); +	return s5p_sdhci_init(base, 52000000, 400000, index); +}  #endif diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index c245352ac..a8e681c2f 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -39,8 +39,8 @@ COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o  COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o  COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o  COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o -COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o  COBJS-$(CONFIG_SDHCI) += sdhci.o +COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o  COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o  COBJS-$(CONFIG_TEGRA2_MMC) += tegra2_mmc.o diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index a2f35e3e9..07370b572 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -307,19 +307,56 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)  #else  	esdhc_write32(®s->xfertyp, xfertyp);  #endif + +	/* Mask all irqs */ +	esdhc_write32(®s->irqsigen, 0); +  	/* Wait for the command to complete */ -	while (!(esdhc_read32(®s->irqstat) & IRQSTAT_CC)) +	while (!(esdhc_read32(®s->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE)))  		;  	irqstat = esdhc_read32(®s->irqstat);  	esdhc_write32(®s->irqstat, irqstat); +	/* Reset CMD and DATA portions on error */ +	if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) { +		esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) | +			      SYSCTL_RSTC); +		while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) +			; + +		if (data) { +			esdhc_write32(®s->sysctl, +				      esdhc_read32(®s->sysctl) | +				      SYSCTL_RSTD); +			while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) +				; +		} +	} +  	if (irqstat & CMD_ERR)  		return COMM_ERR;  	if (irqstat & IRQSTAT_CTOE)  		return TIMEOUT; +	/* Workaround for ESDHC errata ENGcm03648 */ +	if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { +		int timeout = 2500; + +		/* Poll on DATA0 line for cmd with busy signal for 250 ms */ +		while (timeout > 0 && !(esdhc_read32(®s->prsstat) & +					PRSSTAT_DAT0)) { +			udelay(100); +			timeout--; +		} + +		if (timeout <= 0) { +			printf("Timeout waiting for DAT0 to go high!\n"); +			return TIMEOUT; +		} +	} +  	/* Copy the response to the response buffer */  	if (cmd->resp_type & MMC_RSP_136) {  		u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 596732e80..aebe578ff 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1199,7 +1199,9 @@ int mmc_startup(struct mmc *mmc)  		else  			mmc_set_clock(mmc, 25000000);  	} else { -		for (width = EXT_CSD_BUS_WIDTH_8; width >= 0; width--) { +		width = ((mmc->host_caps & MMC_MODE_MASK_WIDTH_BITS) >> +			 MMC_MODE_WIDTH_BITS_SHIFT); +		for (; width >= 0; width--) {  			/* Set the card to use 4 bit*/  			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,  					EXT_CSD_BUS_WIDTH, width); diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index c7200ee71..4187a9412 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -407,7 +407,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))  	 */  	mmc->f_min = 400000;  	mmc->f_max = mxc_get_clock(MXC_SSP0_CLK + id) * 1000 / 2; -	mmc->b_max = 0x40; +	mmc->b_max = 0x20;  	mmc_register(mmc);  	return 0; diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index e3670d4ad..afd9b30b5 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -34,6 +34,10 @@  #include <asm/arch/mmc_host_def.h>  #include <asm/arch/sys_proto.h> +/* common definitions for all OMAPs */ +#define SYSCTL_SRC	(1 << 25) +#define SYSCTL_SRD	(1 << 26) +  /* If we fail after 1 second wait, something is really bad */  #define MAX_RETRY_MS	1000 @@ -91,15 +95,21 @@ static void omap5_pbias_config(struct mmc *mmc)  unsigned char mmc_board_init(struct mmc *mmc)  { -#if defined(CONFIG_TWL4030_POWER) -	twl4030_power_mmc_init(); -#endif -  #if defined(CONFIG_OMAP34XX)  	t2_t *t2_base = (t2_t *)T2_BASE;  	struct prcm *prcm_base = (struct prcm *)PRCM_BASE; +	u32 pbias_lite; -	writel(readl(&t2_base->pbias_lite) | PBIASLITEPWRDNZ1 | +	pbias_lite = readl(&t2_base->pbias_lite); +	pbias_lite &= ~(PBIASLITEPWRDNZ1 | PBIASLITEPWRDNZ0); +	writel(pbias_lite, &t2_base->pbias_lite); +#endif +#if defined(CONFIG_TWL4030_POWER) +	twl4030_power_mmc_init(); +	mdelay(100);	/* ramp-up delay from Linux code */ +#endif +#if defined(CONFIG_OMAP34XX) +	writel(pbias_lite | PBIASLITEPWRDNZ1 |  		PBIASSPEEDCTRL0 | PBIASLITEPWRDNZ0,  		&t2_base->pbias_lite); @@ -227,6 +237,27 @@ static int mmc_init_setup(struct mmc *mmc)  	return 0;  } +/* + * MMC controller internal finite state machine reset + * + * Used to reset command or data internal state machines, using respectively + * SRC or SRD bit of SYSCTL register + */ +static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit) +{ +	ulong start; + +	mmc_reg_out(&mmc_base->sysctl, bit, bit); + +	start = get_timer(0); +	while ((readl(&mmc_base->sysctl) & bit) != 0) { +		if (get_timer(0) - start > MAX_RETRY_MS) { +			printf("%s: timedout waiting for sysctl %x to clear\n", +				__func__, bit); +			return; +		} +	} +}  static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,  			struct mmc_data *data) @@ -247,7 +278,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,  	start = get_timer(0);  	while (readl(&mmc_base->stat)) {  		if (get_timer(0) - start > MAX_RETRY_MS) { -			printf("%s: timedout waiting for stat!\n", __func__); +			printf("%s: timedout waiting for STAT (%x) to clear\n", +				__func__, readl(&mmc_base->stat));  			return TIMEOUT;  		}  	} @@ -315,9 +347,10 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,  		}  	} while (!mmc_stat); -	if ((mmc_stat & IE_CTO) != 0) +	if ((mmc_stat & IE_CTO) != 0) { +		mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);  		return TIMEOUT; -	else if ((mmc_stat & ERRI_MASK) != 0) +	} else if ((mmc_stat & ERRI_MASK) != 0)  		return -1;  	if (mmc_stat & CC_MASK) { @@ -368,6 +401,9 @@ static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size)  			}  		} while (mmc_stat == 0); +		if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0) +			mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD); +  		if ((mmc_stat & ERRI_MASK) != 0)  			return 1; @@ -420,6 +456,9 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,  			}  		} while (mmc_stat == 0); +		if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0) +			mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD); +  		if ((mmc_stat & ERRI_MASK) != 0)  			return 1; diff --git a/drivers/mmc/s5p_mmc.c b/drivers/mmc/s5p_mmc.c deleted file mode 100644 index 4ae3aaf77..000000000 --- a/drivers/mmc/s5p_mmc.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * (C) Copyright 2009 SAMSUNG Electronics - * Minkyu Kang <mk7.kang@samsung.com> - * Jaehoon Chung <jh80.chung@samsung.com> - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA - */ - -#include <common.h> -#include <mmc.h> -#include <asm/io.h> -#include <asm/arch/mmc.h> -#include <asm/arch/clk.h> - -/* support 4 mmc hosts */ -struct mmc mmc_dev[4]; -struct mmc_host mmc_host[4]; - -static inline struct s5p_mmc *s5p_get_base_mmc(int dev_index) -{ -	unsigned long offset = dev_index * sizeof(struct s5p_mmc); -	return (struct s5p_mmc *)(samsung_get_base_mmc() + offset); -} - -static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data) -{ -	unsigned char ctrl; - -	debug("data->dest: %08x\n", (u32)data->dest); -	writel((u32)data->dest, &host->reg->sysad); -	/* -	 * DMASEL[4:3] -	 * 00 = Selects SDMA -	 * 01 = Reserved -	 * 10 = Selects 32-bit Address ADMA2 -	 * 11 = Selects 64-bit Address ADMA2 -	 */ -	ctrl = readb(&host->reg->hostctl); -	ctrl &= ~(3 << 3); -	writeb(ctrl, &host->reg->hostctl); - -	/* We do not handle DMA boundaries, so set it to max (512 KiB) */ -	writew((7 << 12) | (data->blocksize & 0xFFF), &host->reg->blksize); -	writew(data->blocks, &host->reg->blkcnt); -} - -static void mmc_set_transfer_mode(struct mmc_host *host, struct mmc_data *data) -{ -	unsigned short mode; - -	/* -	 * TRNMOD -	 * MUL1SIN0[5]	: Multi/Single Block Select -	 * RD1WT0[4]	: Data Transfer Direction Select -	 *	1 = read -	 *	0 = write -	 * ENACMD12[2]	: Auto CMD12 Enable -	 * ENBLKCNT[1]	: Block Count Enable -	 * ENDMA[0]	: DMA Enable -	 */ -	mode = (1 << 1) | (1 << 0); -	if (data->blocks > 1) -		mode |= (1 << 5); -	if (data->flags & MMC_DATA_READ) -		mode |= (1 << 4); - -	writew(mode, &host->reg->trnmod); -} - -static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, -			struct mmc_data *data) -{ -	struct mmc_host *host = (struct mmc_host *)mmc->priv; -	int flags, i; -	unsigned int timeout; -	unsigned int mask; -	unsigned int retry = 0x100000; - -	/* Wait max 10 ms */ -	timeout = 10; - -	/* -	 * PRNSTS -	 * CMDINHDAT[1]	: Command Inhibit (DAT) -	 * CMDINHCMD[0]	: Command Inhibit (CMD) -	 */ -	mask = (1 << 0); -	if ((data != NULL) || (cmd->resp_type & MMC_RSP_BUSY)) -		mask |= (1 << 1); - -	/* -	 * We shouldn't wait for data inihibit for stop commands, even -	 * though they might use busy signaling -	 */ -	if (data) -		mask &= ~(1 << 1); - -	while (readl(&host->reg->prnsts) & mask) { -		if (timeout == 0) { -			printf("%s: timeout error\n", __func__); -			return -1; -		} -		timeout--; -		udelay(1000); -	} - -	if (data) -		mmc_prepare_data(host, data); - -	debug("cmd->arg: %08x\n", cmd->cmdarg); -	writel(cmd->cmdarg, &host->reg->argument); - -	if (data) -		mmc_set_transfer_mode(host, data); - -	if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) -		return -1; - -	/* -	 * CMDREG -	 * CMDIDX[13:8]	: Command index -	 * DATAPRNT[5]	: Data Present Select -	 * ENCMDIDX[4]	: Command Index Check Enable -	 * ENCMDCRC[3]	: Command CRC Check Enable -	 * RSPTYP[1:0] -	 *	00 = No Response -	 *	01 = Length 136 -	 *	10 = Length 48 -	 *	11 = Length 48 Check busy after response -	 */ -	if (!(cmd->resp_type & MMC_RSP_PRESENT)) -		flags = 0; -	else if (cmd->resp_type & MMC_RSP_136) -		flags = (1 << 0); -	else if (cmd->resp_type & MMC_RSP_BUSY) -		flags = (3 << 0); -	else -		flags = (2 << 0); - -	if (cmd->resp_type & MMC_RSP_CRC) -		flags |= (1 << 3); -	if (cmd->resp_type & MMC_RSP_OPCODE) -		flags |= (1 << 4); -	if (data) -		flags |= (1 << 5); - -	debug("cmd: %d\n", cmd->cmdidx); - -	writew((cmd->cmdidx << 8) | flags, &host->reg->cmdreg); - -	for (i = 0; i < retry; i++) { -		mask = readl(&host->reg->norintsts); -		/* Command Complete */ -		if (mask & (1 << 0)) { -			if (!data) -				writel(mask, &host->reg->norintsts); -			break; -		} -	} - -	if (i == retry) { -		printf("%s: waiting for status update\n", __func__); -		return TIMEOUT; -	} - -	if (mask & (1 << 16)) { -		/* Timeout Error */ -		debug("timeout: %08x cmd %d\n", mask, cmd->cmdidx); -		return TIMEOUT; -	} else if (mask & (1 << 15)) { -		/* Error Interrupt */ -		debug("error: %08x cmd %d\n", mask, cmd->cmdidx); -		return -1; -	} - -	if (cmd->resp_type & MMC_RSP_PRESENT) { -		if (cmd->resp_type & MMC_RSP_136) { -			/* CRC is stripped so we need to do some shifting. */ -			for (i = 0; i < 4; i++) { -				unsigned int offset = -					(unsigned int)(&host->reg->rspreg3 - i); -				cmd->response[i] = readl(offset) << 8; - -				if (i != 3) { -					cmd->response[i] |= -						readb(offset - 1); -				} -				debug("cmd->resp[%d]: %08x\n", -						i, cmd->response[i]); -			} -		} else if (cmd->resp_type & MMC_RSP_BUSY) { -			for (i = 0; i < retry; i++) { -				/* PRNTDATA[23:20] : DAT[3:0] Line Signal */ -				if (readl(&host->reg->prnsts) -					& (1 << 20))	/* DAT[0] */ -					break; -			} - -			if (i == retry) { -				printf("%s: card is still busy\n", __func__); -				return TIMEOUT; -			} - -			cmd->response[0] = readl(&host->reg->rspreg0); -			debug("cmd->resp[0]: %08x\n", cmd->response[0]); -		} else { -			cmd->response[0] = readl(&host->reg->rspreg0); -			debug("cmd->resp[0]: %08x\n", cmd->response[0]); -		} -	} - -	if (data) { -		while (1) { -			mask = readl(&host->reg->norintsts); - -			if (mask & (1 << 15)) { -				/* Error Interrupt */ -				writel(mask, &host->reg->norintsts); -				printf("%s: error during transfer: 0x%08x\n", -						__func__, mask); -				return -1; -			} else if (mask & (1 << 3)) { -				/* -				 * DMA Interrupt, restart the transfer where -				 * it was interrupted. -				 */ -				unsigned int address = readl(&host->reg->sysad); - -				debug("DMA end\n"); -				writel((1 << 3), &host->reg->norintsts); -				writel(address, &host->reg->sysad); -			} else if (mask & (1 << 1)) { -				/* Transfer Complete */ -				debug("r/w is done\n"); -				break; -			} -		} -		writel(mask, &host->reg->norintsts); -	} - -	udelay(1000); -	return 0; -} - -static void mmc_change_clock(struct mmc_host *host, uint clock) -{ -	int div; -	unsigned short clk; -	unsigned long timeout; -	unsigned long ctrl2; - -	/* -	 * SELBASECLK[5:4] -	 * 00/01 = HCLK -	 * 10 = EPLL -	 * 11 = XTI or XEXTCLK -	 */ -	ctrl2 = readl(&host->reg->control2); -	ctrl2 &= ~(3 << 4); -	ctrl2 |= (2 << 4); -	writel(ctrl2, &host->reg->control2); - -	writew(0, &host->reg->clkcon); - -	/* XXX: we assume that clock is between 40MHz and 50MHz */ -	if (clock == 0) -		goto out; -	else if (clock <= 400000) -		div = 0x100; -	else if (clock <= 20000000) -		div = 4; -	else if (clock <= 26000000) -		div = 2; -	else -		div = 1; -	debug("div: %d\n", div); - -	div >>= 1; -	/* -	 * CLKCON -	 * SELFREQ[15:8]	: base clock divied by value -	 * ENSDCLK[2]		: SD Clock Enable -	 * STBLINTCLK[1]	: Internal Clock Stable -	 * ENINTCLK[0]		: Internal Clock Enable -	 */ -	clk = (div << 8) | (1 << 0); -	writew(clk, &host->reg->clkcon); - -	set_mmc_clk(host->dev_index, div); - -	/* Wait max 10 ms */ -	timeout = 10; -	while (!(readw(&host->reg->clkcon) & (1 << 1))) { -		if (timeout == 0) { -			printf("%s: timeout error\n", __func__); -			return; -		} -		timeout--; -		udelay(1000); -	} - -	clk |= (1 << 2); -	writew(clk, &host->reg->clkcon); - -out: -	host->clock = clock; -} - -static void mmc_set_ios(struct mmc *mmc) -{ -	struct mmc_host *host = mmc->priv; -	unsigned char ctrl; -	unsigned long val; - -	debug("bus_width: %x, clock: %d\n", mmc->bus_width, mmc->clock); - -	/* -	 * SELCLKPADDS[17:16] -	 * 00 = 2mA -	 * 01 = 4mA -	 * 10 = 7mA -	 * 11 = 9mA -	 */ -	writel(0x3 << 16, &host->reg->control4); - -	val = readl(&host->reg->control2); -	val &= (0x3 << 4); - -	val |=	(1 << 31) |	/* write status clear async mode enable */ -		(1 << 30) |	/* command conflict mask enable */ -		(1 << 14) |	/* Feedback Clock Enable for Rx Clock */ -		(1 << 8);	/* SDCLK hold enable */ - -	writel(val, &host->reg->control2); - -	/* -	 * FCSEL1[15] FCSEL0[7] -	 * FCSel[1:0] : Rx Feedback Clock Delay Control -	 *	Inverter delay means10ns delay if SDCLK 50MHz setting -	 *	01 = Delay1 (basic delay) -	 *	11 = Delay2 (basic delay + 2ns) -	 *	00 = Delay3 (inverter delay) -	 *	10 = Delay4 (inverter delay + 2ns) -	 */ -	writel(0x8080, &host->reg->control3); - -	mmc_change_clock(host, mmc->clock); - -	ctrl = readb(&host->reg->hostctl); - -	/* -	 * WIDE8[5] -	 * 0 = Depend on WIDE4 -	 * 1 = 8-bit mode -	 * WIDE4[1] -	 * 1 = 4-bit mode -	 * 0 = 1-bit mode -	 */ -	if (mmc->bus_width == 8) -		ctrl |= (1 << 5); -	else if (mmc->bus_width == 4) -		ctrl |= (1 << 1); -	else -		ctrl &= ~(1 << 1); - -	/* -	 * OUTEDGEINV[2] -	 * 1 = Riging edge output -	 * 0 = Falling edge output -	 */ -	ctrl &= ~(1 << 2); - -	writeb(ctrl, &host->reg->hostctl); -} - -static void mmc_reset(struct mmc_host *host) -{ -	unsigned int timeout; - -	/* -	 * RSTALL[0] : Software reset for all -	 * 1 = reset -	 * 0 = work -	 */ -	writeb((1 << 0), &host->reg->swrst); - -	host->clock = 0; - -	/* Wait max 100 ms */ -	timeout = 100; - -	/* hw clears the bit when it's done */ -	while (readb(&host->reg->swrst) & (1 << 0)) { -		if (timeout == 0) { -			printf("%s: timeout error\n", __func__); -			return; -		} -		timeout--; -		udelay(1000); -	} -} - -static int mmc_core_init(struct mmc *mmc) -{ -	struct mmc_host *host = (struct mmc_host *)mmc->priv; -	unsigned int mask; - -	mmc_reset(host); - -	host->version = readw(&host->reg->hcver); - -	/* mask all */ -	writel(0xffffffff, &host->reg->norintstsen); -	writel(0xffffffff, &host->reg->norintsigen); - -	writeb(0xe, &host->reg->timeoutcon);	/* TMCLK * 2^27 */ - -	/* -	 * NORMAL Interrupt Status Enable Register init -	 * [5] ENSTABUFRDRDY : Buffer Read Ready Status Enable -	 * [4] ENSTABUFWTRDY : Buffer write Ready Status Enable -	 * [3] ENSTADMAINT : DMA Interrupt Status Enable -	 * [1] ENSTASTANSCMPLT : Transfre Complete Status Enable -	 * [0] ENSTACMDCMPLT : Command Complete Status Enable -	 */ -	mask = readl(&host->reg->norintstsen); -	mask &= ~(0xffff); -	mask |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1) | (1 << 0); -	writel(mask, &host->reg->norintstsen); - -	/* -	 * NORMAL Interrupt Signal Enable Register init -	 * [1] ENSTACMDCMPLT : Transfer Complete Signal Enable -	 */ -	mask = readl(&host->reg->norintsigen); -	mask &= ~(0xffff); -	mask |= (1 << 1); -	writel(mask, &host->reg->norintsigen); - -	return 0; -} - -static int s5p_mmc_initialize(int dev_index, int bus_width) -{ -	struct mmc *mmc; - -	mmc = &mmc_dev[dev_index]; - -	sprintf(mmc->name, "SAMSUNG SD/MMC"); -	mmc->priv = &mmc_host[dev_index]; -	mmc->send_cmd = mmc_send_cmd; -	mmc->set_ios = mmc_set_ios; -	mmc->init = mmc_core_init; -	mmc->getcd = NULL; - -	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; -	if (bus_width == 8) -		mmc->host_caps = MMC_MODE_8BIT; -	else -		mmc->host_caps = MMC_MODE_4BIT; -	mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; - -	mmc->f_min = 400000; -	mmc->f_max = 52000000; - -	mmc_host[dev_index].dev_index = dev_index; -	mmc_host[dev_index].clock = 0; -	mmc_host[dev_index].reg = s5p_get_base_mmc(dev_index); -	mmc->b_max = 0; -	mmc_register(mmc); - -	return 0; -} - -int s5p_mmc_init(int dev_index, int bus_width) -{ -	return s5p_mmc_initialize(dev_index, bus_width); -} diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c new file mode 100644 index 000000000..1d4481b97 --- /dev/null +++ b/drivers/mmc/s5p_sdhci.c @@ -0,0 +1,98 @@ +/* + * (C) Copyright 2012 SAMSUNG Electronics + * Jaehoon Chung <jh80.chung@samsung.com> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include <common.h> +#include <malloc.h> +#include <sdhci.h> +#include <asm/arch/mmc.h> + +static char *S5P_NAME = "SAMSUNG SDHCI"; +static void s5p_sdhci_set_control_reg(struct sdhci_host *host) +{ +	unsigned long val, ctrl; +	/* +	 * SELCLKPADDS[17:16] +	 * 00 = 2mA +	 * 01 = 4mA +	 * 10 = 7mA +	 * 11 = 9mA +	 */ +	sdhci_writel(host, SDHCI_CTRL4_DRIVE_MASK(0x3), SDHCI_CONTROL4); + +	val = sdhci_readl(host, SDHCI_CONTROL2); +	val &= SDHCI_CTRL2_SELBASECLK_SHIFT; + +	val |=	SDHCI_CTRL2_ENSTAASYNCCLR | +		SDHCI_CTRL2_ENCMDCNFMSK | +		SDHCI_CTRL2_ENFBCLKRX | +		SDHCI_CTRL2_ENCLKOUTHOLD; + +	sdhci_writel(host, val, SDHCI_CONTROL2); + +	/* +	 * FCSEL3[31] FCSEL2[23] FCSEL1[15] FCSEL0[7] +	 * FCSel[1:0] : Rx Feedback Clock Delay Control +	 *	Inverter delay means10ns delay if SDCLK 50MHz setting +	 *	01 = Delay1 (basic delay) +	 *	11 = Delay2 (basic delay + 2ns) +	 *	00 = Delay3 (inverter delay) +	 *	10 = Delay4 (inverter delay + 2ns) +	 */ +	val = SDHCI_CTRL3_FCSEL3 | SDHCI_CTRL3_FCSEL1; +	sdhci_writel(host, val, SDHCI_CONTROL3); + +	/* +	 * SELBASECLK[5:4] +	 * 00/01 = HCLK +	 * 10 = EPLL +	 * 11 = XTI or XEXTCLK +	 */ +	ctrl = sdhci_readl(host, SDHCI_CONTROL2); +	ctrl &= ~SDHCI_CTRL2_SELBASECLK_MASK(0x3); +	ctrl |= SDHCI_CTRL2_SELBASECLK_MASK(0x2); +	sdhci_writel(host, ctrl, SDHCI_CONTROL2); +} + +int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks) +{ +	struct sdhci_host *host = NULL; +	host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); +	if (!host) { +		printf("sdhci__host malloc fail!\n"); +		return 1; +	} + +	host->name = S5P_NAME; +	host->ioaddr = (void *)regbase; +	host->quirks = quirks; + +	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE; +	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; +	if (quirks & SDHCI_QUIRK_REG32_RW) +		host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16; +	else +		host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + +	host->set_control_reg = &s5p_sdhci_set_control_reg; + +	host->host_caps = MMC_MODE_HC; + +	add_sdhci(host, max_clk, min_clk); +	return 0; +} diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index fc904b530..1709643da 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -128,6 +128,7 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,  	int trans_bytes = 0, is_aligned = 1;  	u32 mask, flags, mode;  	unsigned int timeout, start_addr = 0; +	unsigned int retry = 10000;  	/* Wait max 10 ms */  	timeout = 10; @@ -210,8 +211,19 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,  		stat = sdhci_readl(host, SDHCI_INT_STATUS);  		if (stat & SDHCI_INT_ERROR)  			break; +		if (--retry == 0) +			break;  	} while ((stat & mask) != mask); +	if (retry == 0) { +		if (host->quirks & SDHCI_QUIRK_BROKEN_R1B) +			return 0; +		else { +			printf("Timeout for status update!\n"); +			return TIMEOUT; +		} +	} +  	if ((stat & (SDHCI_INT_ERROR | mask)) == mask) {  		sdhci_cmd_done(host, cmd);  		sdhci_writel(host, mask, SDHCI_INT_STATUS); @@ -325,6 +337,9 @@ void sdhci_set_ios(struct mmc *mmc)  	u32 ctrl;  	struct sdhci_host *host = (struct sdhci_host *)mmc->priv; +	if (host->set_control_reg) +		host->set_control_reg(host); +  	if (mmc->clock != host->clock)  		sdhci_set_clock(mmc, mmc->clock); @@ -348,6 +363,9 @@ void sdhci_set_ios(struct mmc *mmc)  	else  		ctrl &= ~SDHCI_CTRL_HISPD; +	if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT) +		ctrl &= ~SDHCI_CTRL_HISPD; +  	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);  } @@ -431,9 +449,15 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)  		mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;  	if (caps & SDHCI_CAN_VDD_180)  		mmc->voltages |= MMC_VDD_165_195; + +	if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE) +		mmc->voltages |= host->voltages; +  	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;  	if (caps & SDHCI_CAN_DO_8BIT)  		mmc->host_caps |= MMC_MODE_8BIT; +	if (host->host_caps) +		mmc->host_caps |= host->host_caps;  	sdhci_reset(host, SDHCI_RESET_ALL);  	mmc_register(mmc); diff --git a/include/configs/origen.h b/include/configs/origen.h index 8ede82575..367f99184 100644 --- a/include/configs/origen.h +++ b/include/configs/origen.h @@ -69,9 +69,10 @@  #define EXYNOS4_DEFAULT_UART_OFFSET	0x020000  /* SD/MMC configuration */ -#define CONFIG_GENERIC_MMC		1 -#define CONFIG_MMC			1 -#define CONFIG_S5P_MMC			1 +#define CONFIG_GENERIC_MMC +#define CONFIG_MMC +#define CONFIG_SDHCI +#define CONFIG_S5P_SDHCI  /* PWM */  #define CONFIG_PWM			1 diff --git a/include/configs/s5p_goni.h b/include/configs/s5p_goni.h index 56b5547fd..e133a1725 100644 --- a/include/configs/s5p_goni.h +++ b/include/configs/s5p_goni.h @@ -63,9 +63,10 @@  #define CONFIG_BAUDRATE			115200  /* MMC */ -#define CONFIG_GENERIC_MMC		1 -#define CONFIG_MMC			1 -#define CONFIG_S5P_MMC			1 +#define CONFIG_GENERIC_MMC +#define CONFIG_MMC +#define CONFIG_SDHCI +#define CONFIG_S5P_SDHCI  /* PWM */  #define CONFIG_PWM			1 diff --git a/include/configs/s5pc210_universal.h b/include/configs/s5pc210_universal.h index 13012756a..00db37418 100644 --- a/include/configs/s5pc210_universal.h +++ b/include/configs/s5pc210_universal.h @@ -66,9 +66,10 @@  #define CONFIG_BAUDRATE		115200  /* MMC */ -#define CONFIG_GENERIC_MMC	1 -#define CONFIG_MMC		1 -#define CONFIG_S5P_MMC		1 +#define CONFIG_GENERIC_MMC +#define CONFIG_MMC +#define CONFIG_SDHCI +#define CONFIG_S5P_SDHCI  /* PWM */  #define CONFIG_PWM			1 diff --git a/include/configs/smdk5250.h b/include/configs/smdk5250.h index 9659f9ebd..0f63040d2 100644 --- a/include/configs/smdk5250.h +++ b/include/configs/smdk5250.h @@ -78,7 +78,8 @@  /* SD/MMC configuration */  #define CONFIG_GENERIC_MMC  #define CONFIG_MMC -#define CONFIG_S5P_MMC +#define CONFIG_SDHCI +#define CONFIG_S5P_SDHCI  #define CONFIG_BOARD_EARLY_INIT_F diff --git a/include/configs/smdkv310.h b/include/configs/smdkv310.h index 93c25da1c..702134bda 100644 --- a/include/configs/smdkv310.h +++ b/include/configs/smdkv310.h @@ -68,9 +68,10 @@  #define EXYNOS4_DEFAULT_UART_OFFSET	0x010000  /* SD/MMC configuration */ -#define CONFIG_GENERIC_MMC		1 -#define CONFIG_MMC			1 -#define CONFIG_S5P_MMC			1 +#define CONFIG_GENERIC_MMC +#define CONFIG_MMC +#define CONFIG_SDHCI +#define CONFIG_S5P_SDHCI  /* PWM */  #define CONFIG_PWM			1 diff --git a/include/configs/trats.h b/include/configs/trats.h index 5f913ca9a..ef6510e67 100644 --- a/include/configs/trats.h +++ b/include/configs/trats.h @@ -73,7 +73,8 @@  /* MMC */  #define CONFIG_GENERIC_MMC  #define CONFIG_MMC -#define CONFIG_S5P_MMC +#define CONFIG_S5P_SDHCI +#define CONFIG_SDHCI  /* PWM */  #define CONFIG_PWM diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h index 8418bf7f4..0e265584b 100644 --- a/include/fsl_esdhc.h +++ b/include/fsl_esdhc.h @@ -34,12 +34,13 @@  #define SYSCTL_INITA		0x08000000  #define SYSCTL_TIMEOUT_MASK	0x000f0000  #define SYSCTL_CLOCK_MASK	0x0000fff0 -#define SYSCTL_RSTA		0x01000000  #define SYSCTL_CKEN		0x00000008  #define SYSCTL_PEREN		0x00000004  #define SYSCTL_HCKEN		0x00000002  #define SYSCTL_IPGEN		0x00000001  #define SYSCTL_RSTA		0x01000000 +#define SYSCTL_RSTC		0x02000000 +#define SYSCTL_RSTD		0x04000000  #define IRQSTAT			0x0002e030  #define IRQSTAT_DMAE		(0x10000000) @@ -85,6 +86,7 @@  #define IRQSTATEN_CC		(0x00000001)  #define PRSSTAT			0x0002e024 +#define PRSSTAT_DAT0		(0x01000000)  #define PRSSTAT_CLSL		(0x00800000)  #define PRSSTAT_WPSPL		(0x00080000)  #define PRSSTAT_CDPL		(0x00040000) diff --git a/include/mmc.h b/include/mmc.h index f52df70ad..230598654 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -47,6 +47,9 @@  #define MMC_MODE_SPI		0x400  #define MMC_MODE_HC		0x800 +#define MMC_MODE_MASK_WIDTH_BITS (MMC_MODE_4BIT | MMC_MODE_8BIT) +#define MMC_MODE_WIDTH_BITS_SHIFT 8 +  #define SD_DATA_4BIT	0x00040000  #define IS_SD(x) (x->version & SD_VERSION_SD) @@ -205,56 +208,6 @@ struct mmc_cid {  	char pnm[7];  }; -/* - * WARNING! - * - * This structure is used by atmel_mci.c only. - * It works for the AVR32 architecture but NOT - * for ARM/AT91 architectures. - * Its use is highly depreciated. - * After the atmel_mci.c driver for AVR32 has - * been replaced this structure will be removed. - */ -struct mmc_csd -{ -	u8	csd_structure:2, -		spec_vers:4, -		rsvd1:2; -	u8	taac; -	u8	nsac; -	u8	tran_speed; -	u16	ccc:12, -		read_bl_len:4; -	u64	read_bl_partial:1, -		write_blk_misalign:1, -		read_blk_misalign:1, -		dsr_imp:1, -		rsvd2:2, -		c_size:12, -		vdd_r_curr_min:3, -		vdd_r_curr_max:3, -		vdd_w_curr_min:3, -		vdd_w_curr_max:3, -		c_size_mult:3, -		sector_size:5, -		erase_grp_size:5, -		wp_grp_size:5, -		wp_grp_enable:1, -		default_ecc:2, -		r2w_factor:3, -		write_bl_len:4, -		write_bl_partial:1, -		rsvd3:5; -	u8	file_format_grp:1, -		copy:1, -		perm_write_protect:1, -		tmp_write_protect:1, -		file_format:2, -		ecc:2; -	u8	crc:7; -	u8	one:1; -}; -  struct mmc_cmd {  	ushort cmdidx;  	uint resp_type; diff --git a/include/sdhci.h b/include/sdhci.h index 800f9d9c0..9d3718324 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -216,6 +216,9 @@   */  #define SDHCI_QUIRK_32BIT_DMA_ADDR	(1 << 0)  #define SDHCI_QUIRK_REG32_RW		(1 << 1) +#define SDHCI_QUIRK_BROKEN_R1B		(1 << 2) +#define SDHCI_QUIRK_NO_HISPD_BIT	(1 << 3) +#define SDHCI_QUIRK_BROKEN_VOLTAGE	(1 << 4)  /* to make gcc happy */  struct sdhci_host; @@ -240,10 +243,14 @@ struct sdhci_host {  	char *name;  	void *ioaddr;  	unsigned int quirks; +	unsigned int host_caps;  	unsigned int version;  	unsigned int clock;  	struct mmc *mmc;  	const struct sdhci_ops *ops; + +	void (*set_control_reg)(struct sdhci_host *host); +	uint	voltages;  };  #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS |