diff options
Diffstat (limited to 'target/linux/s3c24xx')
5 files changed, 325 insertions, 409 deletions
| diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-core.c b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-core.c index 1a6adcdea..60cfae843 100644 --- a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-core.c +++ b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-core.c @@ -76,6 +76,7 @@ struct reg_range {  	char *name;  	char dump;  }; +  struct reg_range reg_range[] = {  	{ 0x0000, 0x76,		"General",	1 },  	{ 0x0200, 0x18,		"Host Bus",	1 }, @@ -86,7 +87,7 @@ struct reg_range reg_range[] = {  /*		{ 0x0c00, 0xcc,		"MPEG",		0 }, */  	{ 0x1100, 0xb2,		"LCD 1",	1 },  	{ 0x1200, 0x64,		"LCD 2",	1 }, -	{ 0x1400, 0x40,		"MMC",		1 }, +	{ 0x1400, 0x42,		"MMC",		1 },  /*		{ 0x1500, 0x080,	"MPU 0",	0 },  	{ 0x1580, 0x080,	"MPU 1",	0 },  	{ 0x1600, 0x080,	"Cmd Queue",	0 }, @@ -478,7 +479,7 @@ int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)  		break;  	case GLAMO_ENGINE_2D:  			__reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D, -			                   GLAMO_CLOCK_2D_EN_M7CLK | +							   GLAMO_CLOCK_2D_EN_M7CLK |  							   GLAMO_CLOCK_2D_EN_GCLK |  							   GLAMO_CLOCK_2D_DG_M7CLK |  							   GLAMO_CLOCK_2D_DG_GCLK, @@ -544,7 +545,40 @@ u_int16_t glamo_engine_clkreg_get(struct glamo_core *glamo,  }  EXPORT_SYMBOL_GPL(glamo_engine_clkreg_get); -struct glamo_script reset_regs[] = { +static const struct glamo_script engine_div_regs[__NUM_GLAMO_ENGINES] = { +	[GLAMO_ENGINE_LCD] = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_DCLK}, +	[GLAMO_ENGINE_MMC] = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_TCLK}, +	[GLAMO_ENGINE_2D]  = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_GCLK}, +}; + +void glamo_engine_div_enable(struct glamo_core *glamo, enum glamo_engine engine) +{ +	uint16_t reg = engine_div_regs[engine].reg; +	uint16_t bit = engine_div_regs[engine].val; +	uint16_t val; + +	spin_lock(&glamo->lock); +	val = __reg_read(glamo, reg); +	__reg_write(glamo, reg, val | bit); +	spin_unlock(&glamo->lock); +	mdelay(5); +} +EXPORT_SYMBOL_GPL(glamo_engine_div_enable); + +void glamo_engine_div_disable(struct glamo_core *glamo, enum glamo_engine engine) +{ +	uint16_t reg = engine_div_regs[engine].reg; +	uint16_t bit = engine_div_regs[engine].val; +	uint16_t val; + +	spin_lock(&glamo->lock); +	val = __reg_read(glamo, reg); +	__reg_write(glamo, reg, val & ~bit); +	spin_unlock(&glamo->lock); +} +EXPORT_SYMBOL_GPL(glamo_engine_div_disable); + +static const struct glamo_script reset_regs[] = {  	[GLAMO_ENGINE_LCD] = {  		GLAMO_REG_CLOCK_LCD, GLAMO_CLOCK_LCD_RESET  	}, @@ -572,18 +606,18 @@ struct glamo_script reset_regs[] = {  void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine)  { -	struct glamo_script *rst; +    uint16_t reg = reset_regs[engine].reg; +    uint16_t val = reset_regs[engine].val;  	if (engine >= ARRAY_SIZE(reset_regs)) {  		dev_warn(&glamo->pdev->dev, "unknown engine %u ", engine);  		return;  	} -	rst = &reset_regs[engine];  	spin_lock(&glamo->lock); -	__reg_set_bit(glamo, rst->reg, rst->val); -	__reg_clear_bit(glamo, rst->reg, rst->val); +	__reg_set_bit(glamo, reg, val); +	__reg_clear_bit(glamo, reg, val);  	spin_unlock(&glamo->lock);  }  EXPORT_SYMBOL_GPL(glamo_engine_reset); @@ -599,21 +633,12 @@ void glamo_lcm_reset(struct platform_device *pdev, int level)  }  EXPORT_SYMBOL_GPL(glamo_lcm_reset); -enum glamo_pll { -	GLAMO_PLL1, -	GLAMO_PLL2, -}; - -static int glamo_pll_rate(struct glamo_core *glamo, +int glamo_pll_rate(struct glamo_core *glamo,  			  enum glamo_pll pll)  {  	u_int16_t reg; -	unsigned int div = 512;  	unsigned int osci = glamo->pdata->osci_clock_rate; -	if (osci == 32768) -		div = 1; -  	switch (pll) {  	case GLAMO_PLL1:  		reg = __reg_read(glamo, GLAMO_REG_PLL_GEN1); @@ -624,18 +649,19 @@ static int glamo_pll_rate(struct glamo_core *glamo,  	default:  		return -EINVAL;  	} -	return (osci/div)*reg; +	return osci*reg;  } +EXPORT_SYMBOL_GPL(glamo_pll_rate);  int glamo_engine_reclock(struct glamo_core *glamo,  			 enum glamo_engine engine, -			 int ps) +			 int hz)  { -	int pll, khz; -	u_int16_t reg, mask, val = 0; +	int pll; +	u_int16_t reg, mask, div; -	if (!ps) -		return 0; +	if (!hz) +		return -EINVAL;  	switch (engine) {  	case GLAMO_ENGINE_LCD: @@ -643,6 +669,11 @@ int glamo_engine_reclock(struct glamo_core *glamo,  		reg = GLAMO_REG_CLOCK_GEN7;  		mask = 0xff;  		break; +	case GLAMO_ENGINE_MMC: +		pll = GLAMO_PLL1; +		reg = GLAMO_REG_CLOCK_GEN8; +		mask = 0xff; +		break;  	default:  		dev_warn(&glamo->pdev->dev,  			 "reclock of engine 0x%x not supported\n", engine); @@ -651,23 +682,22 @@ int glamo_engine_reclock(struct glamo_core *glamo,  	}  	pll = glamo_pll_rate(glamo, pll); -	khz = 1000000000UL / ps; -	if (khz) -		val = (pll / khz) / 1000; +	div = pll / hz; + +	if (div != 0 && pll / div <= hz) +		--div; + +	if (div > mask) +		div = mask;  	dev_dbg(&glamo->pdev->dev, -			"PLL %d, kHZ %d, div %d\n", pll, khz, val); +			"PLL %d, kHZ %d, div %d\n", pll, hz / 1000, div); -	if (val) { -		val--; -		reg_set_bit_mask(glamo, reg, mask, val); -		mdelay(5); /* wait some time to stabilize */ +	reg_set_bit_mask(glamo, reg, mask, div); +	mdelay(5); /* wait some time to stabilize */ -		return 0; -	} else { -		return -EINVAL; -	} +	return pll / (div + 1);  }  EXPORT_SYMBOL_GPL(glamo_engine_reclock); @@ -675,7 +705,7 @@ EXPORT_SYMBOL_GPL(glamo_engine_reclock);   * script support   ***********************************************************************/ -int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script, +int glamo_run_script(struct glamo_core *glamo, const struct glamo_script *script,  		     int len, int may_sleep)  {  	int i; @@ -746,7 +776,7 @@ int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script,  }  EXPORT_SYMBOL(glamo_run_script); -static struct glamo_script glamo_init_script[] = { +static const struct glamo_script glamo_init_script[] = {  	{ GLAMO_REG_CLOCK_HOST,		0x1000 },  		{ 0xfffe, 2 },  	{ GLAMO_REG_CLOCK_MEMORY, 	0x1000 }, diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-core.h b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-core.h index 467537102..f0c2ec3ee 100644 --- a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-core.h +++ b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-core.h @@ -17,6 +17,11 @@  #define GLAMO_MMC_BUFFER_SIZE (64 * 1024)  #define GLAMO_FB_SIZE	(GLAMO_INTERNAL_RAM_SIZE - GLAMO_MMC_BUFFER_SIZE) +enum glamo_pll { +    GLAMO_PLL1, +    GLAMO_PLL2, +}; +  struct glamo_core {  	int irq;  	int irq_works; /* 0 means PCB does not support Glamo IRQ */ @@ -38,8 +43,14 @@ struct glamo_script {  	u_int16_t val;  }; +void glamo_engine_div_enable(struct glamo_core *glamo, enum glamo_engine engine); +void glamo_engine_div_disable(struct glamo_core *glamo, enum glamo_engine engine); + + +int glamo_pll_rate(struct glamo_core *glamo, enum glamo_pll pll); +  int glamo_run_script(struct glamo_core *glamo, -		     struct glamo_script *script, int len, int may_sleep); +		     const struct glamo_script *script, int len, int may_sleep);  int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine);  int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine); diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-fb.c b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-fb.c index 07a525174..59491720e 100644 --- a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-fb.c +++ b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-fb.c @@ -321,7 +321,7 @@ static void glamofb_program_mode(struct glamofb_handle* gfb) {  	if (var->pixclock)  		glamo_engine_reclock(gcore,  				     GLAMO_ENGINE_LCD, -				     gfb->fb->var.pixclock); +				     (1000000000UL / gfb->fb->var.pixclock) * 1000);  	reg_set_bit_mask(gfb,  			 GLAMO_REG_LCD_WIDTH, diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-mci.c b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-mci.c index ef39017ec..37373f5d1 100644 --- a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-mci.c +++ b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-mci.c @@ -23,15 +23,41 @@  #include <linux/crc7.h>  #include <linux/scatterlist.h>  #include <linux/io.h> +#include <linux/regulator/consumer.h>  #include <linux/mfd/glamo.h> -#include "glamo-mci.h"  #include "glamo-core.h"  #include "glamo-regs.h"  #define DRIVER_NAME "glamo-mci" -static void glamo_mci_send_request(struct mmc_host *mmc); +struct glamo_mci_host { +	struct platform_device *pdev; +	struct glamo_mmc_platform_data *pdata; +	struct mmc_host        *mmc; +	struct resource        *mmio_mem; +	struct resource        *data_mem; +	void __iomem           *mmio_base; +	u16 __iomem            *data_base; + +	struct regulator *regulator; +	struct mmc_request *mrq; + +	unsigned int clk_rate; + +	unsigned short vdd; +	char           power_mode; + +	unsigned char request_counter; + +	struct timer_list disable_timer; + +	struct work_struct irq_work; + +	unsigned clk_enabled : 1; +}; + +static void glamo_mci_send_request(struct mmc_host *mmc, struct mmc_request* mrq);  static void glamo_mci_send_command(struct glamo_mci_host *host,  				  struct mmc_command *cmd); @@ -48,7 +74,7 @@ static void glamo_mci_send_command(struct glamo_mci_host *host,   * for example   */ -static int sd_max_clk = 50000000 / 3; +static int sd_max_clk = 50000000;  module_param(sd_max_clk, int, 0644);  /* @@ -85,35 +111,6 @@ static int sd_post_power_clock = 1000000;  module_param(sd_post_power_clock, int, 0644); -/* - * SD Signal drive strength - * - * you can override this on kernel commandline using - * - *   glamo_mci.sd_drive=0 - * - * for example - */ - -static int sd_drive; -module_param(sd_drive, int, 0644); - -/* - * SD allow SD clock to run while idle - * - * you can override this on kernel commandline using - * - *   glamo_mci.sd_idleclk=0 - * - * for example - */ - -static int sd_idleclk = 0; /* disallow idle clock by default */ -module_param(sd_idleclk, int, 0644); - -/* used to stash real idleclk state in suspend: we force it to run in there */ -static int suspend_sd_idleclk; -  static inline void glamo_reg_write(struct glamo_mci_host *glamo,  				u_int16_t reg, u_int16_t val)  { @@ -140,11 +137,34 @@ static void glamo_reg_set_bit_mask(struct glamo_mci_host *glamo,  	glamo_reg_write(glamo, reg, tmp);  } -static void do_pio_read(struct glamo_mci_host *host) +static void glamo_mci_clock_disable(struct glamo_mci_host *host) { +	if (host->clk_enabled) { +/*		glamo_engine_div_disable(host->pdata->core, GLAMO_ENGINE_MMC);*/ +		host->clk_enabled = 0; +        printk("clk disabled\n"); +	} +} + +static void glamo_mci_clock_enable(struct glamo_mci_host *host) { +	del_timer_sync(&host->disable_timer); + +	if (!host->clk_enabled) { +		glamo_engine_div_enable(host->pdata->core, GLAMO_ENGINE_MMC); +		host->clk_enabled = 1; +        printk("clk enabled\n"); +	} +} + +static void glamo_mci_disable_timer(unsigned long data) { +	struct glamo_mci_host *host = (struct glamo_mci_host *)data; +	glamo_mci_clock_disable(host); +} + + +static void do_pio_read(struct glamo_mci_host *host, struct mmc_data *data)  {  	struct scatterlist *sg;  	u16 __iomem *from_ptr = host->data_base; -	struct mmc_data *data = host->mrq->data;  	void *sg_pointer;  	dev_dbg(&host->pdev->dev, "pio_read():\n"); @@ -159,14 +179,13 @@ static void do_pio_read(struct glamo_mci_host *host)  	}  	dev_dbg(&host->pdev->dev, "pio_read(): " -	        "complete (no more data).\n"); +			"complete (no more data).\n");  } -static void do_pio_write(struct glamo_mci_host *host) +static void do_pio_write(struct glamo_mci_host *host, struct mmc_data *data)  {  	struct scatterlist *sg;  	u16 __iomem *to_ptr = host->data_base; -	struct mmc_data *data = host->mrq->data;  	void *sg_pointer;  	dev_dbg(&host->pdev->dev, "pio_write():\n"); @@ -182,117 +201,41 @@ static void do_pio_write(struct glamo_mci_host *host)  	dev_dbg(&host->pdev->dev, "pio_write(): complete\n");  } -static void glamo_mci_fix_card_div(struct glamo_mci_host *host, int div) -{ -	unsigned long flags; - -	spin_lock_irqsave(&host->pdata->core->lock, flags); - -	if (div < 0) { -		/* stop clock - remove clock from divider input */ -		writew(readw(host->pdata->core->base + -		     GLAMO_REG_CLOCK_GEN5_1) & (~GLAMO_CLOCK_GEN51_EN_DIV_TCLK), -		     host->pdata->core->base + GLAMO_REG_CLOCK_GEN5_1); -	} else { - -		if (host->force_slow_during_powerup) -			div = host->clk_rate / sd_post_power_clock; -		else if (host->pdata->glamo_mmc_use_slow && -		         host->pdata->glamo_mmc_use_slow()) -			div = div * sd_slow_ratio; - -		if (div > 255) -			div = 255; -		/* -		 * set the nearest prescaler factor -		 * -		 * register shared with SCLK divisor -- no chance of race because -		 * we don't use sensor interface -		 */ -		writew((readw(host->pdata->core->base + -		              GLAMO_REG_CLOCK_GEN8) & 0xff00) | div, -		       host->pdata->core->base + GLAMO_REG_CLOCK_GEN8); -		/* enable clock to divider input */ -		writew(readw(host->pdata->core->base + -		             GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK, -		       host->pdata->core->base + GLAMO_REG_CLOCK_GEN5_1); -	} -	spin_unlock_irqrestore(&host->pdata->core->lock, flags); -	mdelay(5); -} -  static int glamo_mci_set_card_clock(struct glamo_mci_host *host, int freq)  { -	int div = 0;  	int real_rate = 0;  	if (freq) { -		/* Set clock */ -		for (div = 0; div < 255; div++) { -			real_rate = host->clk_rate / (div + 1); -			if (real_rate <= freq) -				break; -		} - -		host->clk_div = div; -		glamo_mci_fix_card_div(host, div); +		glamo_mci_clock_enable(host); +		real_rate = glamo_engine_reclock(host->pdata->core, GLAMO_ENGINE_MMC, freq);  	} else { -		/* stop clock */ -		host->clk_div = 0xff; - -		if (!sd_idleclk && !host->force_slow_during_powerup) -			/* clock off */ -			glamo_mci_fix_card_div(host, -1); +		glamo_mci_clock_disable(host);  	} -	host->real_rate = real_rate; +  	return real_rate;  } +static void glamo_mci_request_done(struct glamo_mci_host *host, struct +mmc_request *mrq) { +	mod_timer(&host->disable_timer, jiffies + HZ / 16); -static void glamo_mci_irq_worker(struct work_struct *work) -{ -	struct glamo_mci_host *host = -			    container_of(work, struct glamo_mci_host, irq_work); -	struct mmc_command *cmd = host->mrq->cmd; - -	if (cmd->data->flags & MMC_DATA_READ) { -		do_pio_read(host); -	} - -	/* issue STOP if we have been given one to use */ -	if (host->mrq->stop) { -		glamo_mci_send_command(host, host->mrq->stop); -	} - -	if (!sd_idleclk && !host->force_slow_during_powerup) -		/* clock off */ -		glamo_mci_fix_card_div(host, -1); - -	host->mrq = NULL; -	mmc_request_done(host->mmc, cmd->mrq); +	mmc_request_done(host->mmc, mrq);  } -static irqreturn_t glamo_mci_irq(int irq, void *devid) + +static void glamo_mci_irq_worker(struct work_struct *work)  { -	struct glamo_mci_host *host = (struct glamo_mci_host*)devid; -	u16 status; +	struct glamo_mci_host *host = container_of(work, struct glamo_mci_host, +												irq_work);  	struct mmc_command *cmd; -	unsigned long flags; +	uint16_t status; -	if (host->suspending) { /* bad news, dangerous time */ -		dev_err(&host->pdev->dev, "****glamo_mci_irq before resumed\n"); -		goto leave; -	} +	if (!host->mrq || !host->mrq->cmd) +		return; -	if (!host->mrq) -		goto leave;  	cmd = host->mrq->cmd; -	if (!cmd) -		goto leave; - -	spin_lock_irqsave(&host->lock, flags); -	status = readw(host->mmio_base + GLAMO_REG_MMC_RB_STAT1); +	status = glamo_reg_read(host, GLAMO_REG_MMC_RB_STAT1);  	dev_dbg(&host->pdev->dev, "status = 0x%04x\n", status);  	/* we ignore a data timeout report if we are also told the data came */ @@ -300,36 +243,34 @@ static irqreturn_t glamo_mci_irq(int irq, void *devid)  		status &= ~GLAMO_STAT1_MMC_DTOUT;  	if (status & (GLAMO_STAT1_MMC_RTOUT | -		      GLAMO_STAT1_MMC_DTOUT)) +			  GLAMO_STAT1_MMC_DTOUT))  		cmd->error = -ETIMEDOUT;  	if (status & (GLAMO_STAT1_MMC_BWERR | -		      GLAMO_STAT1_MMC_BRERR)) +			  GLAMO_STAT1_MMC_BRERR))  		cmd->error = -EILSEQ;  	if (cmd->error) {  		dev_info(&host->pdev->dev, "Error after cmd: 0x%x\n", status);  		goto done;  	} -	/* -	 * disable the initial slow start after first bulk transfer -	 */ -	if (host->force_slow_during_powerup) -		host->force_slow_during_powerup--; - -	/* -	 * we perform the memcpy out of Glamo memory outside of IRQ context -	 * so we don't block other interrupts -	 */ -	schedule_work(&host->irq_work); +	/* issue STOP if we have been given one to use */ +	if (host->mrq->stop) +		glamo_mci_send_command(host, host->mrq->stop); -	goto unlock; +	if (cmd->data->flags & MMC_DATA_READ) +		do_pio_read(host, cmd->data);  done:  	host->mrq = NULL; -	mmc_request_done(host->mmc, cmd->mrq); -unlock: -	spin_unlock_irqrestore(&host->lock, flags); -leave: +	glamo_mci_request_done(host, cmd->mrq); +} + +static irqreturn_t glamo_mci_irq(int irq, void *devid) +{ +	struct glamo_mci_host *host = (struct glamo_mci_host*)devid; + +	schedule_work(&host->irq_work); +  	return IRQ_HANDLED;  } @@ -341,13 +282,12 @@ static void glamo_mci_send_command(struct glamo_mci_host *host,  	unsigned int timeout = 1000000;  	u16 * reg_resp = (u16 *)(host->mmio_base + GLAMO_REG_MMC_CMD_RSP1);  	u16 status; +	int triggers_int = 1;  	/* if we can't do it, reject as busy */ -	if (!readw(host->mmio_base + GLAMO_REG_MMC_RB_STAT1) & -	     GLAMO_STAT1_MMC_IDLE) { -		host->mrq = NULL; +	if (!glamo_reg_read(host, GLAMO_REG_MMC_RB_STAT1) & +		 GLAMO_STAT1_MMC_IDLE) {  		cmd->error = -EBUSY; -		mmc_request_done(host->mmc, host->mrq);  		return;  	} @@ -360,9 +300,9 @@ static void glamo_mci_send_command(struct glamo_mci_host *host,  	u8a[5] = (crc7(0, u8a, 5) << 1) | 0x01; /* crc7 on first 5 bytes of packet */  	/* issue the wire-order array including CRC in register order */ -	writew((u8a[4] << 8) | u8a[5], host->mmio_base + GLAMO_REG_MMC_CMD_REG1); -	writew((u8a[2] << 8) | u8a[3], host->mmio_base + GLAMO_REG_MMC_CMD_REG2); -	writew((u8a[0] << 8) | u8a[1], host->mmio_base + GLAMO_REG_MMC_CMD_REG3); +	glamo_reg_write(host, GLAMO_REG_MMC_CMD_REG1, ((u8a[4] << 8) | u8a[5])); +	glamo_reg_write(host, GLAMO_REG_MMC_CMD_REG2, ((u8a[2] << 8) | u8a[3])); +	glamo_reg_write(host, GLAMO_REG_MMC_CMD_REG3, ((u8a[0] << 8) | u8a[1]));  	/* command index toggle */  	fire |= (host->request_counter & 1) << 12; @@ -440,27 +380,36 @@ static void glamo_mci_send_command(struct glamo_mci_host *host,  			 /* multiblock with stop */  			fire |= GLAMO_FIRE_MMC_CC_MBWS;  		else - 			 /* multiblock NO stop-- 'RESERVED'? */ +			 /* multiblock NO stop-- 'RESERVED'? */  			fire |= GLAMO_FIRE_MMC_CC_MBWNS;  		break;  	case MMC_STOP_TRANSMISSION:  		fire |= GLAMO_FIRE_MMC_CC_STOP; /* STOP */ +		triggers_int = 0;  		break;  	default:  		fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */ +		triggers_int = 0;  		break;  	} + +	if (triggers_int) +		host->mrq = cmd->mrq; +  	/* always largest timeout */ -	writew(0xfff, host->mmio_base + GLAMO_REG_MMC_TIMEOUT); +	glamo_reg_write(host, GLAMO_REG_MMC_TIMEOUT, 0xfff);  	/* Generate interrupt on txfer */ -	glamo_reg_set_bit_mask(host, GLAMO_REG_MMC_BASIC, ~0x3e, -		   0x0800 | GLAMO_BASIC_MMC_NO_CLK_RD_WAIT | -		   GLAMO_BASIC_MMC_EN_COMPL_INT | (sd_drive << 6)); +	glamo_reg_set_bit_mask(host, GLAMO_REG_MMC_BASIC, 0xff36, +			0x0800 | +			GLAMO_BASIC_MMC_NO_CLK_RD_WAIT | +			GLAMO_BASIC_MMC_EN_COMPL_INT | +			GLAMO_BASIC_MMC_EN_DATA_PUPS | +			GLAMO_BASIC_MMC_EN_CMD_PUP);  	/* send the command out on the wire */  	/* dev_info(&host->pdev->dev, "Using FIRE %04X\n", fire); */ -	writew(fire, host->mmio_base + GLAMO_REG_MMC_CMD_FIRE); +	glamo_reg_write(host, GLAMO_REG_MMC_CMD_FIRE, fire);  	/* we are deselecting card?  because it isn't going to ack then... */  	if ((cmd->opcode == 7) && (cmd->arg == 0)) @@ -470,15 +419,14 @@ static void glamo_mci_send_command(struct glamo_mci_host *host,  	 * we must spin until response is ready or timed out  	 * -- we don't get interrupts unless there is a bulk rx  	 */ -	udelay(5);  	do -		status = readw(host->mmio_base + GLAMO_REG_MMC_RB_STAT1); +		status = glamo_reg_read(host, GLAMO_REG_MMC_RB_STAT1);  	while (((((status >> 15) & 1) != (host->request_counter & 1)) ||  		(!(status & (GLAMO_STAT1_MMC_RB_RRDY | -			     GLAMO_STAT1_MMC_RTOUT | -			     GLAMO_STAT1_MMC_DTOUT | -			     GLAMO_STAT1_MMC_BWERR | -			     GLAMO_STAT1_MMC_BRERR)))) && (timeout--)); +				 GLAMO_STAT1_MMC_RTOUT | +				 GLAMO_STAT1_MMC_DTOUT | +				 GLAMO_STAT1_MMC_BWERR | +				 GLAMO_STAT1_MMC_BRERR)))) && (timeout--));  	if ((status & (GLAMO_STAT1_MMC_RTOUT |  				   GLAMO_STAT1_MMC_DTOUT)) || @@ -492,17 +440,17 @@ static void glamo_mci_send_command(struct glamo_mci_host *host,  	if (cmd->flags & MMC_RSP_PRESENT) {  		if (cmd->flags & MMC_RSP_136) {  			cmd->resp[3] = readw(®_resp[0]) | -			               (readw(®_resp[1]) << 16); +						   (readw(®_resp[1]) << 16);  			cmd->resp[2] = readw(®_resp[2]) | -			               (readw(®_resp[3]) << 16); +						   (readw(®_resp[3]) << 16);  			cmd->resp[1] = readw(®_resp[4]) | -			               (readw(®_resp[5]) << 16); +						   (readw(®_resp[5]) << 16);  			cmd->resp[0] = readw(®_resp[6]) | -			               (readw(®_resp[7]) << 16); +						   (readw(®_resp[7]) << 16);  		} else {  			cmd->resp[0] = (readw(®_resp[0]) >> 8) | -			               (readw(®_resp[1]) << 8) | -			               ((readw(®_resp[2])) << 24); +						   (readw(®_resp[1]) << 8) | +						   ((readw(®_resp[2])) << 24);  		}  	}  } @@ -511,28 +459,63 @@ static int glamo_mci_prepare_pio(struct glamo_mci_host *host,  				 struct mmc_data *data)  {  	/* set up the block info */ -	writew(data->blksz, host->mmio_base + GLAMO_REG_MMC_DATBLKLEN); -	writew(data->blocks, host->mmio_base + GLAMO_REG_MMC_DATBLKCNT); -	dev_dbg(&host->pdev->dev, "(blksz=%d, count=%d)\n", -				   data->blksz, data->blocks); +	glamo_reg_write(host, GLAMO_REG_MMC_DATBLKLEN, data->blksz); +	glamo_reg_write(host, GLAMO_REG_MMC_DATBLKCNT, data->blocks); +  	data->bytes_xfered = 0;  	/* if write, prep the write into the shared RAM before the command */  	if (data->flags & MMC_DATA_WRITE) { -		do_pio_write(host); +		do_pio_write(host, data); +	} + +	dev_dbg(&host->pdev->dev, "(blksz=%d, count=%d)\n", +				   data->blksz, data->blocks); +	return 0; +} + +static int glamo_mci_irq_poll(struct glamo_mci_host *host, +				struct mmc_command *cmd) +{ +	int timeout = 1000000; +	/* +	 * if the glamo INT# line isn't wired (*cough* it can happen) +	 * I'm afraid we have to spin on the IRQ status bit and "be +	 * our own INT# line" +	 */ +	/* +	 * we have faith we will get an "interrupt"... +	 * but something insane like suspend problems can mean +	 * we spin here forever, so we timeout after a LONG time +	 */ +	while ((!(readw(host->pdata->core->base + +		 GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC)) && +		   (timeout--)); + +	if (timeout < 0) { +		if (cmd->data->error) +			cmd->data->error = -ETIMEDOUT; +		dev_err(&host->pdev->dev, "Payload timeout\n"); +		return -ETIMEDOUT;  	} +	/* ack this interrupt source */ +	writew(GLAMO_IRQ_MMC, host->pdata->core->base + +		   GLAMO_REG_IRQ_CLEAR); + +	/* yay we are an interrupt controller! -- call the ISR +	 * it will stop clock to card +	 */ +	glamo_mci_irq(IRQ_GLAMO(GLAMO_IRQIDX_MMC), host); +  	return 0;  } -static void glamo_mci_send_request(struct mmc_host *mmc) +static void glamo_mci_send_request(struct mmc_host *mmc, struct mmc_request *mrq)  {  	struct glamo_mci_host *host = mmc_priv(mmc); -	struct mmc_request *mrq = host->mrq;  	struct mmc_command *cmd = mrq->cmd; -	int timeout = 1000000;  	host->request_counter++; -	/* this guy has data to read/write? */  	if (cmd->data) {  		if(glamo_mci_prepare_pio(host, cmd->data)) {  			cmd->data->error = -EIO; @@ -545,11 +528,7 @@ static void glamo_mci_send_request(struct mmc_host *mmc)  		 cmd->opcode, cmd->arg, cmd->data, cmd->mrq->stop,  		 cmd->flags); -	/* resume requested clock rate -	 * scale it down by sd_slow_ratio if platform requests it -	 */ -	glamo_mci_fix_card_div(host, host->clk_div); - +	glamo_mci_clock_enable(host);  	glamo_mci_send_command(host, cmd);  	/* @@ -558,6 +537,12 @@ static void glamo_mci_send_request(struct mmc_host *mmc)  	if (!cmd->data || cmd->error)  		goto done; + +	if (!host->pdata->core->irq_works) { +		if (glamo_mci_irq_poll(host, mrq->cmd)) +			goto done; +	} +  	/*  	 * Otherwise can can use the interrupt as async completion --  	 * if there is read data coming, or we wait for write data to complete, @@ -565,95 +550,30 @@ static void glamo_mci_send_request(struct mmc_host *mmc)  	 * will service it  	 */  	dev_dbg(&host->pdev->dev, "Waiting for payload data\n"); -	/* -	 * if the glamo INT# line isn't wired (*cough* it can happen) -	 * I'm afraid we have to spin on the IRQ status bit and "be -	 * our own INT# line" -	 */ -	if (!host->pdata->core->irq_works) { -		/* -		 * we have faith we will get an "interrupt"... -		 * but something insane like suspend problems can mean -		 * we spin here forever, so we timeout after a LONG time -		 */ -		while ((!(readw(host->pdata->core->base + -			 GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC)) && -		       (timeout--)); - -		if (timeout < 0) { -			if (cmd->data->error) -				cmd->data->error = -ETIMEDOUT; -			dev_err(&host->pdev->dev, "Payload timeout\n"); -			goto bail; -		} -		/* ack this interrupt source */ -		writew(GLAMO_IRQ_MMC, host->pdata->core->base + -		       GLAMO_REG_IRQ_CLEAR); - -		/* yay we are an interrupt controller! -- call the ISR -		 * it will stop clock to card -		 */ -		glamo_mci_irq(IRQ_GLAMO(GLAMO_IRQIDX_MMC), host); -	}  	return;  done: -	host->mrq = NULL; -	mmc_request_done(host->mmc, cmd->mrq); -bail: -	if (!sd_idleclk && !host->force_slow_during_powerup) -		/* stop the clock to card */ -		glamo_mci_fix_card_div(host, -1); +	glamo_mci_request_done(host, mrq);  } -static void glamo_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) -{ -	struct glamo_mci_host *host = mmc_priv(mmc); - -	host->mrq = mrq; -	glamo_mci_send_request(mmc); -} - -static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -{ -	struct glamo_mci_host *host = mmc_priv(mmc); -	int bus_width = 0; -	int powering = 0; +static void glamo_mci_set_power_mode(struct glamo_mci_host *host, +				unsigned char power_mode) {  	int ret; -	if (host->suspending) { -		dev_err(&host->pdev->dev, "IGNORING glamo_mci_set_ios while " -								 "suspended\n"); +	if (power_mode == host->power_mode)  		return; -	} -	/* Set power */ -	switch(ios->power_mode) { +	switch(power_mode) {  	case MMC_POWER_UP: -		ret = regulator_enable(host->regulator); -		if (ret) -			dev_err(&host->pdev->dev, "Failed to enable regulator: %d\n", ret); +		if (host->power_mode == MMC_POWER_OFF) { +			ret = regulator_enable(host->regulator); +			if (ret) +				dev_err(&host->pdev->dev, "Failed to enable regulator: %d\n", ret); +		}  		break;  	case MMC_POWER_ON: -		/* -		 * we should use very slow clock until first bulk -		 * transfer completes OK -		 */ -		host->force_slow_during_powerup = 1; - -		if (host->power_mode_current == MMC_POWER_OFF) { -			glamo_engine_enable(host->pdata->core, -							      GLAMO_ENGINE_MMC); -			powering = 1; -		}  		break; -  	case MMC_POWER_OFF:  	default: -		if (host->power_mode_current == MMC_POWER_OFF) -			break; -		/* never want clocking with dead card */ -		glamo_mci_fix_card_div(host, -1); -  		glamo_engine_disable(host->pdata->core,  				     GLAMO_ENGINE_MMC); @@ -662,44 +582,50 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  			dev_warn(&host->pdev->dev, "Failed to disable regulator: %d\n", ret);  		break;  	} -	host->power_mode_current = ios->power_mode; +	host->power_mode = power_mode; +} -	if (host->vdd_current != ios->vdd) { +static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ +	struct glamo_mci_host *host = mmc_priv(mmc); +	int bus_width = 0; +	int rate; +	int sd_drive; +	int ret; + +	/* Set power */ +	glamo_mci_set_power_mode(host, ios->power_mode); + +	if (host->vdd != ios->vdd) {  		ret = mmc_regulator_set_ocr(host->regulator, ios->vdd);  		if (ret)  			dev_err(&host->pdev->dev, "Failed to set regulator voltage: %d\n", ret);  		else -			host->vdd_current = ios->vdd; +			host->vdd = ios->vdd;  	} -	glamo_mci_set_card_clock(host, ios->clock); - -	/* after power-up, we are meant to give it >= 74 clocks so it can -	 * initialize itself.  Doubt any modern cards need it but anyway... -	 */ -	if (powering) -		mdelay(1); - -	if (!sd_idleclk && !host->force_slow_during_powerup) -		/* stop the clock to card, because we are idle until transfer */ -		glamo_mci_fix_card_div(host, -1); +	rate = glamo_mci_set_card_clock(host, ios->clock);  	if ((ios->power_mode == MMC_POWER_ON) ||  	    (ios->power_mode == MMC_POWER_UP)) {  		dev_info(&host->pdev->dev, -			"powered (vdd = %d) clk: %lukHz div=%d (req: %ukHz). " -			"Bus width=%d\n",(int)ios->vdd, -			host->real_rate / 1000, (int)host->clk_div, +			"powered (vdd = %hu) clk: %dkHz div=%hu (req: %ukHz). " +			"Bus width=%d\n", ios->vdd, +			rate / 1000, 0,  			ios->clock / 1000, (int)ios->bus_width); -	} else +	} else {  		dev_info(&host->pdev->dev, "glamo_mci_set_ios: power down.\n"); +	}  	/* set bus width */  	if (ios->bus_width == MMC_BUS_WIDTH_4)  		bus_width = GLAMO_BASIC_MMC_EN_4BIT_DATA; + +	sd_drive = (rate * 4) / host->clk_rate; +	if (sd_drive > 3) +		sd_drive = 3; +  	glamo_reg_set_bit_mask(host, GLAMO_REG_MMC_BASIC, -					       GLAMO_BASIC_MMC_EN_4BIT_DATA | -					       GLAMO_BASIC_MMC_EN_DR_STR0 | -					       GLAMO_BASIC_MMC_EN_DR_STR1, +					       GLAMO_BASIC_MMC_EN_4BIT_DATA | 0xb0,  						   bus_width | sd_drive << 6);  } @@ -713,7 +639,7 @@ static int glamo_mci_get_ro(struct mmc_host *mmc)  }  static struct mmc_host_ops glamo_mci_ops = { -	.request	= glamo_mci_request, +	.request	= glamo_mci_send_request,  	.set_ios	= glamo_mci_set_ios,  	.get_ro		= glamo_mci_get_ro,  }; @@ -736,9 +662,9 @@ static int glamo_mci_probe(struct platform_device *pdev)  	host->mmc = mmc;  	host->pdev = pdev;  	host->pdata = pdev->dev.platform_data; -	host->power_mode_current = MMC_POWER_OFF; +	host->power_mode = MMC_POWER_OFF; +	host->clk_enabled = 0; -	spin_lock_init(&host->lock);  	INIT_WORK(&host->irq_work, glamo_mci_irq_worker);  	host->regulator = regulator_get(pdev->dev.parent, "SD_3V3"); @@ -810,9 +736,8 @@ static int glamo_mci_probe(struct platform_device *pdev)  	} -	host->vdd_current = 0; -	host->clk_rate = 50000000; /* really it's 49152000 */ -	host->clk_div = 16; +	host->vdd = 0; +	host->clk_rate = glamo_pll_rate(host->pdata->core, GLAMO_PLL1);  	/* explain our host controller capabilities */  	mmc->ops       = &glamo_mci_ops; @@ -821,7 +746,7 @@ static int glamo_mci_probe(struct platform_device *pdev)  	                 MMC_CAP_MMC_HIGHSPEED |  	                 MMC_CAP_SD_HIGHSPEED;  	mmc->f_min     = host->clk_rate / 256; -	mmc->f_max     = sd_max_clk; +	mmc->f_max     = host->clk_rate;  	mmc->max_blk_count = (1 << 16) - 1; /* GLAMO_REG_MMC_RB_BLKCNT */  	mmc->max_blk_size  = (1 << 12) - 1; /* GLAMO_REG_MMC_RB_BLKLEN */ @@ -841,21 +766,24 @@ static int glamo_mci_probe(struct platform_device *pdev)  	glamo_engine_enable(host->pdata->core, GLAMO_ENGINE_MMC);  	glamo_engine_reset(host->pdata->core, GLAMO_ENGINE_MMC); +	glamo_reg_write(host, GLAMO_REG_MMC_WDATADS1, +			(u16)(host->data_mem->start)); +	glamo_reg_write(host, GLAMO_REG_MMC_WDATADS2, +			(u16)(host->data_mem->start >> 16)); + +	glamo_reg_write(host, GLAMO_REG_MMC_RDATADS1, +			(u16)(host->data_mem->start)); +	glamo_reg_write(host, GLAMO_REG_MMC_RDATADS2, +			(u16)(host->data_mem->start >> 16)); + +	setup_timer(&host->disable_timer, glamo_mci_disable_timer, +				(unsigned long)host); +  	if ((ret = mmc_add_host(mmc))) {  		dev_err(&pdev->dev, "failed to add mmc host.\n");  		goto probe_freeirq;  	} -	writew((u16)(host->data_mem->start), -	       host->mmio_base + GLAMO_REG_MMC_WDATADS1); -	writew((u16)((host->data_mem->start) >> 16), -	       host->mmio_base + GLAMO_REG_MMC_WDATADS2); - -	writew((u16)host->data_mem->start, host->mmio_base + -	       GLAMO_REG_MMC_RDATADS1); -	writew((u16)(host->data_mem->start >> 16), host->mmio_base + -	       GLAMO_REG_MMC_RDATADS2); -  	dev_info(&pdev->dev,"initialisation done.\n");  	return 0; @@ -904,51 +832,41 @@ static int glamo_mci_remove(struct platform_device *pdev)  static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)  {  	struct mmc_host *mmc = platform_get_drvdata(dev); -	struct glamo_mci_host 	*host = mmc_priv(mmc); +	struct glamo_mci_host *host = mmc_priv(mmc);  	int ret;  	cancel_work_sync(&host->irq_work); -	/* -	 * possible workaround for SD corruption during suspend - resume -	 * make sure the clock was running during suspend and consequently -	 * resume -	 */ -	glamo_mci_fix_card_div(host, host->clk_div); - -	/* we are going to do more commands to override this in -	 * mmc_suspend_host(), so we need to change sd_idleclk for the -	 * duration as well -	 */ -	suspend_sd_idleclk = sd_idleclk; -	sd_idleclk = 1; -  	ret = mmc_suspend_host(mmc, state); - -	host->suspending++; +	glamo_mci_clock_enable(host);  	return ret;  } -int glamo_mci_resume(struct platform_device *dev) +static int glamo_mci_resume(struct platform_device *dev)  {  	struct mmc_host *mmc = platform_get_drvdata(dev); -	struct glamo_mci_host 	*host = mmc_priv(mmc); +	struct glamo_mci_host *host = mmc_priv(mmc);  	int ret; -	sd_idleclk = 1; +    glamo_engine_enable(host->pdata->core, GLAMO_ENGINE_MMC); +    glamo_engine_reset(host->pdata->core, GLAMO_ENGINE_MMC); -	glamo_engine_enable(host->pdata->core, GLAMO_ENGINE_MMC); -	glamo_engine_reset(host->pdata->core, GLAMO_ENGINE_MMC); - -	host->suspending--; +	glamo_reg_write(host, GLAMO_REG_MMC_WDATADS1, +			(u16)(host->data_mem->start)); +	glamo_reg_write(host, GLAMO_REG_MMC_WDATADS2, +			(u16)(host->data_mem->start >> 16)); -	ret = mmc_resume_host(mmc); +	glamo_reg_write(host, GLAMO_REG_MMC_RDATADS1, +			(u16)(host->data_mem->start)); +	glamo_reg_write(host, GLAMO_REG_MMC_RDATADS2, +			(u16)(host->data_mem->start >> 16)); +    mdelay(5); -	/* put sd_idleclk back to pre-suspend state */ -	sd_idleclk = suspend_sd_idleclk; +	ret = mmc_resume_host(host->mmc); +/*	glamo_mci_clock_disable(host);*/ -	return ret; +	return 0;  }  EXPORT_SYMBOL_GPL(glamo_mci_resume); diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-mci.h b/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-mci.h deleted file mode 100644 index 52c3fe334..000000000 --- a/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-mci.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - *  linux/drivers/mmc/host/glamo-mmc.h - GLAMO MCI driver - * - *  Copyright (C) 2007-2008 Openmoko, Inc, Andy Green <andy@openmoko.com> - *   based on S3C MMC driver --> - *  Copyright (C) 2004-2006 Thomas Kleffel, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/regulator/consumer.h> - -struct glamo_mci_host { -	struct platform_device *pdev; -	struct glamo_mmc_platform_data *pdata; -	struct mmc_host        *mmc; -	struct resource        *mmio_mem; -	struct resource        *data_mem; -	void __iomem           *mmio_base; -	u16 __iomem            *data_base; - -	int suspending; - -	int          power_mode_current; -	unsigned int vdd_current; - -	unsigned long clk_rate; -	unsigned long clk_div; -	unsigned long real_rate; - -	int force_slow_during_powerup; - -	struct mmc_request *mrq; -	struct work_struct  irq_work; - -	spinlock_t lock; - -	unsigned int request_counter; - -	struct regulator *regulator; -}; | 
