diff options
Diffstat (limited to 'drivers/mmc/arm_pl180_mmci.c')
| -rw-r--r-- | drivers/mmc/arm_pl180_mmci.c | 133 | 
1 files changed, 52 insertions, 81 deletions
| diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index 09d443ee3..af1380a45 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -32,14 +32,10 @@  #include "arm_pl180_mmci.h"  #include <malloc.h> -struct mmc_host { -	struct sdi_registers *base; -}; -  static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)  {  	u32 hoststatus, statusmask; -	struct mmc_host *host = dev->priv; +	struct pl180_mmc_host *host = dev->priv;  	statusmask = SDI_STA_CTIMEOUT | SDI_STA_CCRCFAIL;  	if ((cmd->resp_type & MMC_RSP_PRESENT)) @@ -53,10 +49,10 @@ static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)  	writel(statusmask, &host->base->status_clear);  	if (hoststatus & SDI_STA_CTIMEOUT) { -		printf("CMD%d time out\n", cmd->cmdidx); -		return -ETIMEDOUT; +		debug("CMD%d time out\n", cmd->cmdidx); +		return TIMEOUT;  	} else if ((hoststatus & SDI_STA_CCRCFAIL) && -		   (cmd->flags & MMC_RSP_CRC)) { +		   (cmd->resp_type & MMC_RSP_CRC)) {  		printf("CMD%d CRC error\n", cmd->cmdidx);  		return -EILSEQ;  	} @@ -80,7 +76,7 @@ static int do_command(struct mmc *dev, struct mmc_cmd *cmd)  {  	int result;  	u32 sdi_cmd = 0; -	struct mmc_host *host = dev->priv; +	struct pl180_mmc_host *host = dev->priv;  	sdi_cmd = ((cmd->cmdidx & SDI_CMD_CMDINDEX_MASK) | SDI_CMD_CPSMEN); @@ -112,7 +108,7 @@ static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize)  {  	u32 *tempbuff = dest;  	u64 xfercount = blkcount * blksize; -	struct mmc_host *host = dev->priv; +	struct pl180_mmc_host *host = dev->priv;  	u32 status, status_err;  	debug("read_bytes: blkcount=%u blksize=%u\n", blkcount, blksize); @@ -168,7 +164,7 @@ static int write_bytes(struct mmc *dev, u32 *src, u32 blkcount, u32 blksize)  	u32 *tempbuff = src;  	int i;  	u64 xfercount = blkcount * blksize; -	struct mmc_host *host = dev->priv; +	struct pl180_mmc_host *host = dev->priv;  	u32 status, status_err;  	debug("write_bytes: blkcount=%u blksize=%u\n", blkcount, blksize); @@ -227,14 +223,19 @@ static int do_data_transfer(struct mmc *dev,  			    struct mmc_data *data)  {  	int error = -ETIMEDOUT; -	struct mmc_host *host = dev->priv; +	struct pl180_mmc_host *host = dev->priv;  	u32 blksz = 0;  	u32 data_ctrl = 0;  	u32 data_len = (u32) (data->blocks * data->blocksize); -	blksz = (ffs(data->blocksize) - 1); -	data_ctrl |= ((blksz << 4) & SDI_DCTRL_DBLKSIZE_MASK); -	data_ctrl |= SDI_DCTRL_DTEN; +	if (!host->version2) { +		blksz = (ffs(data->blocksize) - 1); +		data_ctrl |= ((blksz << 4) & SDI_DCTRL_DBLKSIZE_MASK); +	} else { +		blksz = data->blocksize; +		data_ctrl |= (blksz << SDI_DCTRL_DBLOCKSIZE_V2_SHIFT); +	} +	data_ctrl |= SDI_DCTRL_DTEN | SDI_DCTRL_BUSYMODE;  	writel(SDI_DTIMER_DEFAULT, &host->base->datatimer);  	writel(data_len, &host->base->datalength); @@ -257,7 +258,7 @@ static int do_data_transfer(struct mmc *dev,  		writel(data_ctrl, &host->base->datactrl);  		error = write_bytes(dev, (u32 *)data->src, (u32)data->blocks, -				    (u32)data->blocksize); +							(u32)data->blocksize);  	}  	return error; @@ -280,17 +281,16 @@ static int host_request(struct mmc *dev,  /* MMC uses open drain drivers in the enumeration phase */  static int mmc_host_reset(struct mmc *dev)  { -	struct mmc_host *host = dev->priv; -	u32 sdi_u32 = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON; +	struct pl180_mmc_host *host = dev->priv; -	writel(sdi_u32, &host->base->power); +	writel(host->pwr_init, &host->base->power);  	return 0;  }  static void host_set_ios(struct mmc *dev)  { -	struct mmc_host *host = dev->priv; +	struct pl180_mmc_host *host = dev->priv;  	u32 sdi_clkcr;  	sdi_clkcr = readl(&host->base->clock); @@ -298,15 +298,26 @@ static void host_set_ios(struct mmc *dev)  	/* Ramp up the clock rate */  	if (dev->clock) {  		u32 clkdiv = 0; +		u32 tmp_clock; -		if (dev->clock >= dev->f_max) +		if (dev->clock >= dev->f_max) { +			clkdiv = 0;  			dev->clock = dev->f_max; +		} else { +			clkdiv = (host->clock_in / dev->clock) - 2; +		} -		clkdiv = ((ARM_MCLK / dev->clock) / 2) - 1; +		tmp_clock = host->clock_in / (clkdiv + 2); +		while (tmp_clock > dev->clock) { +			clkdiv++; +			tmp_clock = host->clock_in / (clkdiv + 2); +		}  		if (clkdiv > SDI_CLKCR_CLKDIV_MASK)  			clkdiv = SDI_CLKCR_CLKDIV_MASK; +		tmp_clock = host->clock_in / (clkdiv + 2); +		dev->clock = tmp_clock;  		sdi_clkcr &= ~(SDI_CLKCR_CLKDIV_MASK);  		sdi_clkcr |= clkdiv;  	} @@ -322,8 +333,11 @@ static void host_set_ios(struct mmc *dev)  		case 4:  			buswidth |= SDI_CLKCR_WIDBUS_4;  			break; +		case 8: +			buswidth |= SDI_CLKCR_WIDBUS_8; +			break;  		default: -			printf("Invalid bus width\n"); +			printf("Invalid bus width: %d\n", dev->bus_width);  			break;  		}  		sdi_clkcr &= ~(SDI_CLKCR_WIDBUS_MASK); @@ -334,83 +348,40 @@ static void host_set_ios(struct mmc *dev)  	udelay(CLK_CHANGE_DELAY);  } -struct mmc *alloc_mmc_struct(void) -{ -	struct mmc_host *host = NULL; -	struct mmc *mmc_device = NULL; - -	host = malloc(sizeof(struct mmc_host)); -	if (!host) -		return NULL; - -	mmc_device = malloc(sizeof(struct mmc)); -	if (!mmc_device) -		goto err; - -	mmc_device->priv = host; -	return mmc_device; - -err: -	free(host); -	return NULL; -} -  /*   * mmc_host_init - initialize the mmc controller.   * Set initial clock and power for mmc slot.   * Initialize mmc struct and register with mmc framework.   */ -static int arm_pl180_mmci_host_init(struct mmc *dev) +int arm_pl180_mmci_init(struct pl180_mmc_host *host)  { -	struct mmc_host *host = dev->priv; +	struct mmc *dev;  	u32 sdi_u32; -	host->base = (struct sdi_registers *)CONFIG_ARM_PL180_MMCI_BASE; +	dev = malloc(sizeof(struct mmc)); +	if (!dev) +		return -ENOMEM; -	/* Initially set power-on, full voltage & MMCI read */ -	sdi_u32 = INIT_PWR; -	writel(sdi_u32, &host->base->power); +	memset(dev, 0, sizeof(struct mmc)); +	dev->priv = host; -	/* setting clk freq 505KHz */ -	sdi_u32 = SDI_CLKCR_CLKDIV_INIT | SDI_CLKCR_CLKEN; -	writel(sdi_u32, &host->base->clock); +	writel(host->pwr_init, &host->base->power); +	writel(host->clkdiv_init, &host->base->clock);  	udelay(CLK_CHANGE_DELAY);  	/* Disable mmc interrupts */  	sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;  	writel(sdi_u32, &host->base->mask0); - -	sprintf(dev->name, "MMC"); -	dev->clock = ARM_MCLK / (2 * (SDI_CLKCR_CLKDIV_INIT + 1)); +	strncpy(dev->name, host->name, sizeof(dev->name));  	dev->send_cmd = host_request;  	dev->set_ios = host_set_ios;  	dev->init = mmc_host_reset;  	dev->getcd = NULL; -	dev->host_caps = 0; -	dev->voltages = VOLTAGE_WINDOW_MMC; -	dev->f_min = dev->clock; -	dev->f_max = CONFIG_ARM_PL180_MMCI_CLOCK_FREQ; - -	return 0; -} - -int arm_pl180_mmci_init(void) -{ -	int error; -	struct mmc *dev; - -	dev = alloc_mmc_struct(); -	if (!dev) -		return -1; - -	error = arm_pl180_mmci_host_init(dev); -	if (error) { -		printf("mmci_host_init error - %d\n", error); -		return -1; -	} - -	dev->b_max = 0; - +	dev->host_caps = host->caps; +	dev->voltages = host->voltages; +	dev->f_min = host->clock_min; +	dev->f_max = host->clock_max; +	dev->b_max = host->b_max;  	mmc_register(dev);  	debug("registered mmc interface number is:%d\n", dev->block_dev.dev); |