From 35d7b3635215c09802f739b06521191b2eba2e31 Mon Sep 17 00:00:00 2001 From: xbw Date: Sun, 17 Jul 2011 20:41:08 -0700 Subject: [PATCH] Integrae the XBW-version of SDMMC-drver into RK29SDK, and the xbw-version is set to default --- arch/arm/mach-rk29/board-rk29sdk.c | 6 + drivers/mmc/card/block.c | 61 ++++++++- drivers/mmc/core/bus.c | 2 + drivers/mmc/core/core.c | 208 +++++++++++++++++++++++++++++ drivers/mmc/core/host.c | 11 +- drivers/mmc/core/mmc.c | 38 +++++- drivers/mmc/core/sd.c | 68 ++++++++++ drivers/mmc/core/sdio.c | 8 ++ drivers/mmc/host/Kconfig | 18 ++- drivers/mmc/host/Makefile | 5 + fs/partitions/check.c | 17 +++ fs/partitions/msdos.c | 51 ++++++- include/linux/mmc/host.h | 2 + include/linux/mmc/mmc.h | 13 ++ 14 files changed, 495 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index a9867898e0cc..9058b26641d3 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -1011,7 +1011,13 @@ static int rk29_sdmmc0_cfg_gpio(void) rk29_mux_api_set(GPIO1D3_SDMMC0DATA1_NAME, GPIO1H_SDMMC0_DATA1); rk29_mux_api_set(GPIO1D4_SDMMC0DATA2_NAME, GPIO1H_SDMMC0_DATA2); rk29_mux_api_set(GPIO1D5_SDMMC0DATA3_NAME, GPIO1H_SDMMC0_DATA3); + +#ifdef CONFIG_SDMMC_RK29_OLD rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_GPIO2A2); +#else + rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_SDMMC0_DETECT_N);//Modifyed by xbw. +#endif + rk29_mux_api_set(GPIO5D5_SDMMC0PWREN_NAME, GPIO5H_GPIO5D5); ///GPIO5H_SDMMC0_PWR_EN); ///GPIO5H_GPIO5D5); gpio_request(RK29_PIN5_PD5,"sdmmc"); #if 0 diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 98f74b0087b5..23a0e3f20d7e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -43,6 +43,10 @@ MODULE_ALIAS("mmc:block"); +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) +static DEFINE_MUTEX(block_mutex); //added by xbw at 2011-04-21 +#endif + /* * max 8 partitions per card */ @@ -105,6 +109,10 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) { struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); int ret = -ENXIO; + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + mutex_lock(&block_mutex); //added by xbw at 2011-04-21 +#endif if (md) { if (md->usage == 2) @@ -116,6 +124,9 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) ret = -EROFS; } } +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + mutex_unlock(&block_mutex); +#endif return ret; } @@ -123,8 +134,17 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) static int mmc_blk_release(struct gendisk *disk, fmode_t mode) { struct mmc_blk_data *md = disk->private_data; + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + mutex_lock(&block_mutex); //added by xbw at 2011-04-21 +#endif mmc_blk_put(md); + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + mutex_unlock(&block_mutex); +#endif + return 0; } @@ -224,6 +244,13 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) return result; } +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) //Deleted by xbw@2011-03-21 +//static u32 get_card_status(struct mmc_card *card, struct request *req) +//{ +// return 0; +//} + +#else static u32 get_card_status(struct mmc_card *card, struct request *req) { struct mmc_command cmd; @@ -240,6 +267,7 @@ static u32 get_card_status(struct mmc_card *card, struct request *req) req->rq_disk->disk_name, err); return cmd.resp[0]; } +#endif static int mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) @@ -285,13 +313,22 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) mmc_claim_host(card->host); do { - struct mmc_command cmd; + #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + //struct mmc_command cmd;//Deleted by xbw@2011-03-21 + #else + struct mmc_command cmd; + #endif + u32 readcmd, writecmd, status = 0; memset(&brq, 0, sizeof(struct mmc_blk_request)); brq.mrq.cmd = &brq.cmd; brq.mrq.data = &brq.data; - + + #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + brq.cmd.retries = 2; //suppot retry read-write; added by xbw@2011-03-21 + #endif + brq.cmd.arg = blk_rq_pos(req); if (!mmc_card_blockaddr(card)) brq.cmd.arg <<= 9; @@ -371,6 +408,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) mmc_queue_bounce_post(mq); + #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + //not turn CMD18 to CMD17. deleted by xbw at 2011-04-21 + + #else + /* * Check for errors here, but don't jump to cmd_err * until later as we need to wait for the card to leave @@ -387,7 +429,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) status = get_card_status(card, req); } else if (disable_multi == 1) { disable_multi = 0; - } + } + #endif if (brq.cmd.error) { printk(KERN_DEBUG "%s: error %d sending read/write " @@ -414,6 +457,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.stop.resp[0], status); } + #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + //Deleted by xbw@2011-03-21 + + #else if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { do { int err; @@ -443,8 +490,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) goto cmd_err; #endif } +#endif - if (brq.cmd.error || brq.stop.error || brq.data.error) { + if (brq.cmd.error || brq.stop.error || brq.data.error) { if (rq_data_dir(req) == READ) { /* * After an error, we redo I/O one sector at a @@ -572,6 +620,11 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) sprintf(md->disk->disk_name, "mmcblk%d", devidx); +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + printk("%s..%d **** devidx=%d, dev_use[0]=%lu, disk_name=%s *** ==xbw[%s]==\n",\ + __FUNCTION__,__LINE__, devidx, dev_use[0], md->disk->disk_name,mmc_hostname(card->host)); +#endif + blk_queue_logical_block_size(md->queue.queue, 512); if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 812b22035626..ab9a939963d8 100755 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -279,7 +279,9 @@ void mmc_remove_card(struct mmc_card *card) #endif if (mmc_card_present(card)) { +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) mmc_card_clr_present(card); +#endif if (mmc_host_is_spi(card->host)) { printk(KERN_INFO "%s: SPI card removed\n", mmc_hostname(card->host)); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5148f8e5ea71..dd2a7a006438 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -202,7 +202,11 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) mmc_start_request(host, mrq); +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + wait_for_completion_timeout(&complete,HZ*3); //for cmd dead. Modifyed by xbw at 2011-06-02 +#else wait_for_completion(&complete); +#endif } EXPORT_SYMBOL(mmc_wait_for_req); @@ -1059,7 +1063,155 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) EXPORT_SYMBOL(mmc_detect_change); +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) +void mmc_rescan(struct work_struct *work) +{ + struct mmc_host *host = + container_of(work, struct mmc_host, detect.work); + u32 ocr; + int err; + int extend_wakelock = 0; + + + mmc_bus_get(host); + + /* if there is a card registered, check whether it is still present */ + if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) + host->bus_ops->detect(host); + + /* If the card was removed the bus will be marked + * as dead - extend the wakelock so userspace + * can respond */ + if (host->bus_dead) + extend_wakelock = 1; + + mmc_bus_put(host); + + + mmc_bus_get(host); + + /* if there still is a card present, stop here */ + if (host->bus_ops != NULL) { + mmc_bus_put(host); + goto out; + } + + /* detect a newly inserted card */ + + /* + * Only we can add a new handler, so it's safe to + * release the lock here. + */ + mmc_bus_put(host); + printk("\n%s...%d.. ===== mmc_rescan Begin....======xbw[%s]=====\n",__FILE__, __LINE__, mmc_hostname(host)); + + if (host->ops->get_cd && host->ops->get_cd(host) == 0) + { + printk("\n=================\n%s..%d.. ====find no SDMMC host.====xbw[%s]=====\n", \ + __FUNCTION__, __LINE__, mmc_hostname(host)); + + goto out; + } + + mmc_claim_host(host); + + mmc_power_up(host); + + mmc_go_idle(host); + + /* + In oder to improve the initialization process in rockchip IC, I modify the following code about the the initialization process of SDIO-SD-MMC. + So I deleted the CMD8 and add a conditional to distinguish between the two card type,i.e.SDMMC process and SDIO process. + For detail,please refer to "RK29XX Technical Reference Manual" and "SD-MMC-SDIO Specifications". + Noted by xbw@2011-04-09 + */ + + //mmc_send_if_cond(host, host->ocr_avail); //deleted by xbw@2011-04-09 + + if( strncmp( mmc_hostname(host) ,"mmc0" , strlen("mmc0")) ){ + /* + * First we search for SDIO... + */ + err = mmc_send_io_op_cond(host, 0, &ocr); + if (!err) { + printk("\n%s..%d.. ===== Begin to identify card as SDIO-card===xbw[%s]===\n",__FUNCTION__, __LINE__, mmc_hostname(host)); + + if (mmc_attach_sdio(host, ocr)) + { + printk("\n=====\n %s..%d.. ===== Initialize SDIO-card unsuccessfully!!! ===xbw[%s]===\n=====\n",\ + __FUNCTION__, __LINE__, mmc_hostname(host)); + + mmc_power_off(host); + } + else + { + printk("%s..%d.. ===== Initialize SDIO successfully. ===xbw[%s]===\n",__FUNCTION__, __LINE__, mmc_hostname(host)); + } + extend_wakelock = 1; + goto out; + } + } + + + /* + * ...then normal SD... + */ + err = mmc_send_app_op_cond(host, 0, &ocr); + if (!err) { + printk("\n%s..%d.. ===== Begin to identify card as SD-card ===xbw[%s]===\n",__FUNCTION__, __LINE__, mmc_hostname(host)); + + if (mmc_attach_sd(host, ocr)) + { + printk("\n=====\n%s..%d.. ===== Initialize SD-card unsuccessfully!!! ===xbw[%s]===\n====\n",\ + __FUNCTION__, __LINE__, mmc_hostname(host)); + + mmc_power_off(host); + } + else + { + printk("%s..%d.. ===== Initialize SD-card successfully. ===xbw[%s]===\n",__FUNCTION__, __LINE__, mmc_hostname(host)); + } + extend_wakelock = 1; + goto out; + } + + /* + * ...and finally MMC. + */ + err = mmc_send_op_cond(host, 0, &ocr); + if (!err) { + printk("\n%s..%d.. ===== Begin to identify card as MMC-card ===xbw[%s]===\n", __FUNCTION__, __LINE__, mmc_hostname(host)); + + if (mmc_attach_mmc(host, ocr)) + { + printk("\n =====\n%s..%d.. ===== Initialize MMC-card unsuccessfully!!! ===xbw[%s]===\n======\n",\ + __FUNCTION__, __LINE__, mmc_hostname(host)); + + mmc_power_off(host); + } + else + { + printk("%s...%d.. ===== Initialize MMC-card successfully. ===xbw[%s]===\n",__FUNCTION__, __LINE__, mmc_hostname(host)); + } + extend_wakelock = 1; + goto out; + } + + mmc_release_host(host); + mmc_power_off(host); + +out: + + if (extend_wakelock) + wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); + else + wake_unlock(&mmc_delayed_work_wake_lock); + + if (host->caps & MMC_CAP_NEEDS_POLL) + mmc_schedule_delayed_work(&host->detect, HZ); +} +#else void mmc_rescan(struct work_struct *work) { struct mmc_host *host = @@ -1067,6 +1219,8 @@ void mmc_rescan(struct work_struct *work) u32 ocr; int err; int extend_wakelock = 0; + +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) unsigned long flags; spin_lock_irqsave(&host->lock, flags); @@ -1077,6 +1231,7 @@ void mmc_rescan(struct work_struct *work) } spin_unlock_irqrestore(&host->lock, flags); +#endif mmc_bus_get(host); @@ -1165,6 +1320,7 @@ out: if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); } +#endif void mmc_start_host(struct mmc_host *host) { @@ -1301,6 +1457,23 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); + +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) + //deleted all detail code. +#else + if (err == -ENOSYS || !host->bus_ops->resume) { + /* + * We simply "remove" the card in this case. + * It will be redetected on resume. + */ + if (host->bus_ops->remove) + host->bus_ops->remove(host); + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_release_host(host); + err = 0; + } +#endif } mmc_bus_put(host); @@ -1331,6 +1504,8 @@ int mmc_resume_host(struct mmc_host *host) mmc_power_up(host); mmc_select_voltage(host, host->ocr); BUG_ON(!host->bus_ops->resume); + +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) err = host->bus_ops->resume(host); if (err) { printk(KERN_WARNING "%s: error %d during resume " @@ -1338,13 +1513,44 @@ int mmc_resume_host(struct mmc_host *host) mmc_hostname(host), err); err = 0; } + +#elif defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + //panic if the card is being removed during the resume, deleted by xbw at 2011-06-20 + host->bus_ops->resume(host); + +#else + err = host->bus_ops->resume(host); + if (err) { + printk(KERN_WARNING "%s: error %d during resume " + "(card was removed?)\n", + mmc_hostname(host), err); + if (host->bus_ops->remove) + host->bus_ops->remove(host); + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_release_host(host); + /* no need to bother upper layers */ + err = 0; + } +#endif } mmc_bus_put(host); +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) + //delete the detect_change. +#else + /* + * We add a slight delay here so that resume can progress + * in parallel. + */ + mmc_detect_change(host, 1); +#endif return err; } EXPORT_SYMBOL(mmc_resume_host); +///old driver add the function reforming to kernel2.6.38 +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) /* Do the card removal on suspend if card is assumed removeable * Do that in pm notifier while userspace isn't yet frozen, so we will be able to sync the card. @@ -1390,6 +1596,8 @@ int mmc_pm_notify(struct notifier_block *notify_block, return 0; } +#endif// endif---defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) + #endif #ifdef CONFIG_MMC_EMBEDDED_SDIO diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 94f35ca5c413..07b4d72f27fe 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -16,8 +16,9 @@ #include #include #include +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) #include - +#endif #include #include "core.h" @@ -85,8 +86,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) init_waitqueue_head(&host->wq); INIT_DELAYED_WORK(&host->detect, mmc_rescan); INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) // old driver, add pm reform to kernel2.6.38 #ifdef CONFIG_PM host->pm_notify.notifier_call = mmc_pm_notify; +#endif #endif /* @@ -136,8 +139,11 @@ int mmc_add_host(struct mmc_host *host) #endif mmc_start_host(host); + +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) // old driver, add pm reform to kernel2.6.38 if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) register_pm_notifier(&host->pm_notify); +#endif return 0; } @@ -154,8 +160,11 @@ EXPORT_SYMBOL(mmc_add_host); */ void mmc_remove_host(struct mmc_host *host) { +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) // old driver, add pm reform to kernel2.6.38 if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) unregister_pm_notifier(&host->pm_notify); + #endif + mmc_stop_host(host); #ifdef CONFIG_DEBUG_FS diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 32af45c419f4..b6f8867fa076 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -321,7 +321,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, /* The extra bit indicates that we support high capacity */ err = mmc_send_op_cond(host, ocr | (1 << 30), NULL); if (err) + { +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + printk("%s..%d.. ====*Identify the card as MMC , but OCR error, so fail to initialize.===xbw[%s]===\n",\ + __FUNCTION__, __LINE__, mmc_hostname(host)); +#endif goto err; + } /* * For SPI, enable CRC as appropriate. @@ -438,6 +444,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, if (max_dtr > card->ext_csd.hs_max_dtr) max_dtr = card->ext_csd.hs_max_dtr; } else if (max_dtr > card->csd.max_dtr) { +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + //in order to expand the compatibility of card. Added by xbw@2011-03-21 + card->csd.max_dtr = (card->csd.max_dtr > MMC_FPP_FREQ) ? MMC_FPP_FREQ : (card->csd.max_dtr); +#endif max_dtr = card->csd.max_dtr; } @@ -660,6 +670,9 @@ static void mmc_attach_bus_ops(struct mmc_host *host) int mmc_attach_mmc(struct mmc_host *host, u32 ocr) { int err; +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + int retry_times = 3; +#endif BUG_ON(!host); WARN_ON(!host->claimed); @@ -704,10 +717,33 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) goto err; mmc_release_host(host); - + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) +//modifyed by xbw at 2011--04-11 +Retry_add: err = mmc_add_card(host->card); if (err) + { + //retry add the card; Added by xbw + if((--retry_times >= 0)) + { + printk("\n%s..%s..%d ****error in add partition, so retry. ===xbw[%s]===\n",__FUNCTION__,__FILE__,__LINE__, mmc_hostname(host)); + /* sleep some time */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/2); + + goto Retry_add; + } + goto remove_card; + + } +#else + err = mmc_add_card(host->card); + if (err) + goto remove_card; +#endif + return 0; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 8fe5e9ece251..cae635fc8ed8 100755 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -362,7 +362,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, err = mmc_send_app_op_cond(host, ocr, NULL); if (err) + { +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + printk("%s..%d.. ====*Identify the card as SD , but OCR error, so fail to initialize.===xbw[%s]===\n", \ + __FUNCTION__, __LINE__, mmc_hostname(host)); +#endif goto err; + } /* * Fetch CID from card. @@ -458,6 +464,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, printk(KERN_WARNING "%s: read switch failed (attempt %d)\n", mmc_hostname(host), retries); + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(0 == host->re_initialized_flags) + { + break; //Added by xbw at 2011-06-21 + } +#endif } } #else @@ -496,6 +509,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, if (max_dtr > card->sw_caps.hs_max_dtr) max_dtr = card->sw_caps.hs_max_dtr; } else if (max_dtr > card->csd.max_dtr) { + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + //in order to expand the compatibility of card. Added by xbw@2011-03-21 + card->csd.max_dtr = (card->csd.max_dtr > SD_FPP_FREQ) ? SD_FPP_FREQ : (card->csd.max_dtr); +#endif max_dtr = card->csd.max_dtr; } @@ -576,6 +594,15 @@ static void mmc_sd_detect(struct mmc_host *host) err = mmc_send_status(host->card, NULL); if (err) { retries--; + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(0 == host->re_initialized_flags) + { + retries = 0; + break; //Added by xbw at 2011-06-21 + } +#endif + udelay(5); continue; } @@ -643,6 +670,13 @@ static int mmc_sd_resume(struct mmc_host *host) mmc_hostname(host), err, retries); mdelay(5); retries--; + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(0 == host->re_initialized_flags) + { + break; //Added by xbw at 2011-06-21 + } +#endif continue; } break; @@ -715,6 +749,10 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host) int mmc_attach_sd(struct mmc_host *host, u32 ocr) { int err; +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + int retry_times = 3; +#endif + #ifdef CONFIG_MMC_PARANOID_SD_INIT int retries; #endif @@ -772,6 +810,14 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) err = mmc_sd_init_card(host, host->ocr, NULL); if (err) { retries--; + + #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(0 == host->re_initialized_flags) + { + retries = 0; + break; //Added by xbw at 2011-06-21 + } + #endif continue; } break; @@ -790,9 +836,31 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) mmc_release_host(host); +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) +//modifyed by xbw at 2011--04-11 +Retry_add: err = mmc_add_card(host->card); + if (err) + { + //retry add the card; Added by xbw + if((--retry_times >= 0)) + { + printk("\n%s..%s..%d ****error in add partition, so retry. ===xbw[%s]===\n",__FUNCTION__,__FILE__,__LINE__, mmc_hostname(host)); + /* sleep some time */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/2); + + goto Retry_add; + } + + goto remove_card; + + } +#else + err = mmc_add_card(host->card); if (err) goto remove_card; +#endif return 0; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 21fffa2094bd..7280140bfea7 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -241,7 +241,13 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, */ err = mmc_send_io_op_cond(host, host->ocr, &ocr); if (err) + { +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + printk("%s..%d.. ====*Identify the card as SDIO , but OCR error, so fail to initialize.===xbw[%s]===\n", \ + __FUNCTION__, __LINE__, mmc_hostname(host)); +#endif goto err; + } /* * For SPI, enable CRC as appropriate. @@ -278,6 +284,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, if (err) goto remove; +#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD) //old driver add the code ,reform to kernel2.6.38 /* * Update oldcard with the new RCA received from the SDIO * device -- we're doing this so that it's updated in the @@ -285,6 +292,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, */ if (oldcard) oldcard->rca = card->rca; +#endif mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index fa8f13bb5444..fd98a80234f3 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -35,18 +35,24 @@ config SDMMC_RK29 SDMMC0 used for sd/mmc card, and SDMMC1 used for sdio. if SDMMC_RK29 comment "Now, there are two SDMMC controllers selected, SDMMC0 and SDMMC1." + config SDMMC_RK29_OLD + bool "Old driver (DEPRECATED)" + help + You will select old,origin driver for your project if you say Yes. + It is not good to select the driver. + config SDMMC0_RK29 tristate "RK29 SDMMC0 controller support(sdmmc)" default y depends on ARCH_RK29 help This supports the use of the SDMMC0 controller on Rk29 processors. - config EMMC_RK29 - tristate "RK29 EMMC controller support(sdmmc)" - default y - depends on SDMMC0_RK29 - help - This supports the use of the EMMC controller on Rk29 processors. +# config EMMC_RK29 +# tristate "RK29 EMMC controller support(sdmmc)" +# default y +# depends on SDMMC0_RK29 +# help +# This supports the use of the EMMC controller on Rk29 processors. config SDMMC1_RK29 tristate "RK29 SDMMC1 controller support(sdio)" default y diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 8230c5f949b1..1fdec539bbea 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -6,7 +6,12 @@ ifeq ($(CONFIG_MMC_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif +ifeq ($(CONFIG_SDMMC_RK29_OLD),y) +obj-$(CONFIG_SDMMC_RK29) += rk29_sdmmc_old.o +else obj-$(CONFIG_SDMMC_RK29) += rk29_sdmmc.o +endif + obj-$(CONFIG_SDMMC_RK2818) += rk2818-sdmmc.o obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 5689a0a889a9..934637a9a6da 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -541,7 +541,16 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) int p, highest, res; if (bdev->bd_part_count) + { + #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s..%d.. The sdcard partition have been using.So device busy! ====xbw===\n",__FUNCTION__, __LINE__); + } + #endif + return -EBUSY; + } res = invalidate_partition(disk, 0); if (res) return res; @@ -556,7 +565,15 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) check_disk_size_change(disk, bdev); bdev->bd_invalidated = 0; if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) + { + #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s..%d... ==== check partition fail. partitionAddr=%x ====xbw===\n",__FUNCTION__, __LINE__, state); + } + #endif return 0; + } if (IS_ERR(state)) /* I/O error reading the partition table */ return -EIO; diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 90be97f1f5a8..630cd66c4e6d 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c @@ -440,6 +440,13 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) return 0; } +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("\n%s..%d... ==== Begin to parse sdcard-partition. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__); + } +#endif + /* * Now that the 55aa signature is present, this is probably * either the boot sector of a FAT filesystem or a DOS-type @@ -449,6 +456,12 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) p = (struct partition *) (data + 0x1be); for (slot = 1; slot <= 4; slot++, p++) { if (p->boot_ind != 0 && p->boot_ind != 0x80) { +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s..%d... ==== The sdcard has not MBR. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__); + } +#endif /* * Even without a valid boot inidicator value * its still possible this is valid FAT filesystem @@ -459,9 +472,21 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) && fat_valid_media(fb->media)) { printk("\n"); put_dev_sector(sect); +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s..%d... ==== The DBR(slot=%d) is valid. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot); + } +#endif return 1; } else { put_dev_sector(sect); +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s..%d... ==== The DBR is invalid. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__); + } +#endif return 0; } } @@ -484,13 +509,25 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) * First find the primary and DOS-type extended partitions. * On the second pass look inside *BSD, Unixware and Solaris partitions. */ - +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s..%d... ==== The sdcard has MBR. ====xbw[mmc0]===\n", __FUNCTION__, __LINE__); + } +#endif state->next = 5; for (slot = 1 ; slot <= 4 ; slot++, p++) { sector_t start = start_sect(p)*sector_size; sector_t size = nr_sects(p)*sector_size; if (!size) continue; +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s..%d... ==== partition-%d, size=%luKB ====xbw[mmc0]===\n",\ + __FUNCTION__, __LINE__, slot, size/2); + } +#endif if (is_extended_partition(p)) { /* * prevent someone doing mkfs or mkswap on an @@ -500,6 +537,12 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) */ sector_t n = 2; n = min(size, max(sector_size, n)); +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s...%d... ==== extend partition-%d....====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot); + } +#endif put_partition(state, slot, start, n); printk(" <"); @@ -507,6 +550,12 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) printk(" >"); continue; } +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + if(179 == MAJOR(bdev->bd_dev)) + { + printk("%s..%d... ==== main partition-%d....====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot); + } +#endif put_partition(state, slot, start, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[slot].flags = 1; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 01f21a50a2bf..f19c1cf7a66f 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -203,6 +203,8 @@ struct mmc_host { #define MMC_BUSRESUME_MANUAL_RESUME (1 << 0) #define MMC_BUSRESUME_NEEDS_RESUME (1 << 1) + unsigned int re_initialized_flags; //in order to begin the rescan ; added by xbw@2011-04-07 + unsigned int sdio_irqs; struct task_struct *sdio_irq_thread; atomic_t sdio_irq_thread_abort; diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index c02c8db73701..b96f110efbb4 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -282,5 +282,18 @@ struct _mmc_csd { #define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ #define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ + +/* +* some limit value of SDMMC about protocol ; Added by xbw at 2011-03-21 +*/ +#define FOD_FREQ (300000) // in the identify stage, unit: hz, max is 400Khz, + // the least frequency is FREQ_HCLK_MAX/8 +#define SD_FPP_FREQ (24000000) // normal sd freq, 25Mhz +#define SDHC_FPP_FREQ (49000000) // SDHC in the highspeed. unit is hz, max is 50Mhz. +#define MMC_FPP_FREQ (19000000) // MMC freq, unit is hz, max is 20MHz +#define MMCHS_26_FPP_FREQ (24000000) // highspeed mode support 26M HS-MMC, unit is hz, max is 26Mhz, +#define MMCHS_52_FPP_FREQ (49000000) // highspeed support 52M HS-MMC, unit is hz, max is 52Mhz, + + #endif /* MMC_MMC_PROTOCOL_H */ -- 2.34.1