From 5c81d131c6870bf1e76d4e199b27dc209fb344b5 Mon Sep 17 00:00:00 2001 From: kfx Date: Sat, 9 Apr 2011 15:10:55 +0800 Subject: [PATCH] update sdmmc drivers: case of no detect gpio and update i2c driver: read/wirte delay --- arch/arm/mach-rk29/board-rk29sdk.c | 4 +++- drivers/i2c/busses/i2c-rk29.c | 8 +++++++- drivers/mmc/host/rk29_sdmmc.c | 15 +++++++++++++-- include/linux/i2c.h | 5 ++++- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index 566d342b50aa..e47c97617e7e 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -604,9 +604,10 @@ static struct i2c_board_info __initdata board_i2c2_devices[] = { { .type = "p1003_touch", .addr = 0x04, - .flags = 0, + .flags = 0, //I2C_M_NEED_DELAY .irq = RK29_PIN0_PA2, .platform_data = &p1003_info, + //.udelay = 100 }, #endif #if defined (CONFIG_EETI_EGALAX) @@ -1209,6 +1210,7 @@ struct rk29_sdmmc_platform_data default_sdmmc0_data = { #else .use_dma = 0, #endif + .detect_irq = INVALID_GPIO,//RK29_PIN2_PA2 // INVALID_GPIO }; #endif #ifdef CONFIG_SDMMC1_RK29 diff --git a/drivers/i2c/busses/i2c-rk29.c b/drivers/i2c/busses/i2c-rk29.c index efc129f0e0fa..1b8e6c73c1b8 100755 --- a/drivers/i2c/busses/i2c-rk29.c +++ b/drivers/i2c/busses/i2c-rk29.c @@ -103,6 +103,7 @@ struct rk29_i2c_data { unsigned int msg_idx; unsigned int msg_num; + int udelay; int (*io_init)(void); #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; @@ -427,6 +428,7 @@ static int rk29_i2c_send_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg) lsr = readl(i2c->regs + I2C_LSR); if((lsr & I2C_LSR_RCV_NAK) && (i != msg->len -1) && !(msg->flags & I2C_M_IGNORE_NAK)) return -EINVAL; + udelay(i2c->udelay); } return ret; @@ -454,6 +456,7 @@ static int rk29_i2c_recv_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg) rk29_set_nak(i2c); else rk29_set_ack(i2c); + udelay(i2c->udelay); i2c_dbg(i2c->dev, "i2c recv >>>>>>>>>>>> buf[%d]: %x\n", i, msg->buf[i]); } return ret; @@ -470,7 +473,10 @@ static int rk29_xfer_msg(struct i2c_adapter *adap, i2c_err(i2c->dev, "msg->len = %d\n", msg->len); goto exit; } - + if(msg->flags & I2C_M_NEED_DELAY) + i2c->udelay = msg->udelay; + else + i2c->udelay = 0; if((ret = rk29_send_address(i2c, msg, start))!= 0) { rk29_set_nak(i2c); diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c index 44c83b2873a3..6a1b7c929d28 100755 --- a/drivers/mmc/host/rk29_sdmmc.c +++ b/drivers/mmc/host/rk29_sdmmc.c @@ -117,6 +117,7 @@ struct rk29_sdmmc { unsigned int oldstatus; int gpio_irq; + int gpio_det; }; #define rk29_sdmmc_test_and_clear_pending(host, event) \ @@ -666,6 +667,8 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) mmc_request_done(mmc, mrq); return; } + clk_enable(host->clk); + rk29_sdmmc_write(host->regs, SDMMC_CLKENA, 1); rk29_sdmmc_queue_request(host,mrq); } @@ -719,7 +722,12 @@ static int rk29_sdmmc_get_ro(struct mmc_host *mmc) static int rk29_sdmmc_get_cd(struct mmc_host *mmc) { struct rk29_sdmmc *host = mmc_priv(mmc); - u32 cdetect = rk29_sdmmc_read(host->regs, SDMMC_CDETECT); + u32 cdetect; + + if(host->gpio_det == INVALID_GPIO) + return 1; + + cdetect = rk29_sdmmc_read(host->regs, SDMMC_CDETECT); return (cdetect & SDMMC_CARD_DETECT_N)?0:1; } @@ -794,6 +802,8 @@ static void rk29_sdmmc_request_end(struct rk29_sdmmc *host, struct mmc_request * //rk29_sdmmc_write(host->regs, SDMMC_CMD, host->stop_cmdr | SDMMC_CMD_START); dev_info(&host->pdev->dev, "data error, request done!\n"); } + rk29_sdmmc_write(host->regs, SDMMC_CLKENA, 0); + clk_disable(host->clk); mmc_request_done(prev_mmc, mrq); spin_lock(&host->lock); @@ -1444,6 +1454,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) ret = -ENODEV; goto err_freehost; } + host->gpio_det = pdata->detect_irq; if(pdata->io_init) pdata->io_init(); spin_lock_init(&host->lock); @@ -1663,7 +1674,7 @@ static int rk29_sdmmc_resume(struct platform_device *pdev) dev_info(&host->pdev->dev, "Exit rk29_sdmmc_suspend\n"); clk_enable(host->clk); - rk29_sdmmc_write(host->regs, SDMMC_CLKENA, 1); + rk29_sdmmc_write(host->regs, SDMMC_CLKENA, 1); if(host->mmc && (strncmp(host->dma_name, "sdio", strlen("sdio")) != 0)){ rk29_sdmmc_sdcard_resume(host); ret = mmc_resume_host(host->mmc); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 28af1f86cdc8..61bacb773bc7 100755 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -255,6 +255,7 @@ struct i2c_board_info { void *platform_data; struct dev_archdata *archdata; int irq; + int udelay; //add by kfx }; /** @@ -520,9 +521,11 @@ struct i2c_msg { #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ +#define I2C_M_NEED_DELAY 0x8000 // add by kfx __u16 len; /* msg length */ __u8 *buf; /* pointer to msg data */ - __u32 scl_rate; + __u32 scl_rate; // add by kfx + int udelay; //add by kfx __u16 read_type; }; -- 2.34.1