diff options
author | Dorian Snyder <dastin1015@gmail.com> | 2013-06-12 02:24:45 -0700 |
---|---|---|
committer | Dorian Snyder <dastin1015@gmail.com> | 2013-06-20 00:06:04 -0700 |
commit | 4b2308ce699b9c599dd6e6acf57ac11f483381d9 (patch) | |
tree | 4c31179b06d094887b1c8ca70264cf8f184a5981 /drivers/mmc | |
parent | 855d6a6c1f7c54ef073caac3f6c5f9b1ed72eb4d (diff) | |
download | kernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.zip kernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.tar.gz kernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.tar.bz2 |
d710: initial support for the Epic 4G Touch (SPH-D710)
Change-Id: Iafbd9fb45253b02d539ac0ba114f57b3bf9eeed4
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 122 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 14 | ||||
-rw-r--r-- | drivers/mmc/core/host.c | 36 | ||||
-rw-r--r-- | drivers/mmc/core/host.h | 20 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 61 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 4 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 116 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_ops.c | 24 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_ops.h | 1 | ||||
-rw-r--r-- | drivers/mmc/host/mshci-s3c.c | 9 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-s3c.c | 28 |
11 files changed, 415 insertions, 20 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index f49e92c..1c63296 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1166,12 +1166,14 @@ static int mmc_blk_err_check(struct mmc_card *card, if ((!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) || (mq_mrq->packed_cmd == MMC_PACKED_WR_HDR)) { u32 status; +#ifndef CONFIG_WIMAX_CMC /* timeout value set 0x30000 : It works just SDcard case. * It means send CMD sequencially about 7.8sec. * If SDcard's data line stays low, timeout is about 4sec. * max timeout is up to 300ms */ u32 timeout = 0x30000; +#endif do { int err = get_card_status(card, &status, 5); if (err) { @@ -1184,6 +1186,10 @@ static int mmc_blk_err_check(struct mmc_card *card, * so make sure to check both the busy * indication and the card state. */ +#ifdef CONFIG_WIMAX_CMC + } while (!(status & R1_READY_FOR_DATA) || + (R1_CURRENT_STATE(status) == R1_STATE_PRG)); +#else /* Just SDcard case, decrease timeout */ if (mmc_card_sd(card)) timeout--; @@ -1198,6 +1204,7 @@ static int mmc_blk_err_check(struct mmc_card *card, req->rq_disk->disk_name); return MMC_BLK_DATA_ERR; } +#endif } if (brq->data.error) { @@ -1534,6 +1541,88 @@ no_packed: return 0; } +#ifdef CONFIG_WIMAX_CMC +static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, + struct mmc_card *card, + struct mmc_queue *mq, + u8 reqs) +{ + struct mmc_blk_request *brq = &mqrq->brq; + struct request *req = mqrq->req; + struct request *prq; + struct mmc_blk_data *md = mq->data; + bool do_rel_wr; + u32 *packed_cmd_hdr = mqrq->packed_cmd_hdr; + u8 i = 1; + + mqrq->packed_cmd = (rq_data_dir(req) == READ) ? + MMC_PACKED_WR_HDR : MMC_PACKED_WRITE; + mqrq->packed_blocks = 0; + mqrq->packed_fail_idx = -1; + + memset(packed_cmd_hdr, 0, sizeof(mqrq->packed_cmd_hdr)); + packed_cmd_hdr[0] = (reqs << 16) | + (((rq_data_dir(req) == READ) ? + PACKED_CMD_RD : PACKED_CMD_WR) << 8) | + PACKED_CMD_VER; + + + /* + * Argument for each entry of packed group + */ + list_for_each_entry(prq, &mqrq->packed_list, queuelist) { + do_rel_wr = mmc_req_rel_wr(prq) && (md->flags & MMC_BLK_REL_WR); + /* Argument of CMD23*/ + packed_cmd_hdr[(i * 2)] = (do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) | + blk_rq_sectors(prq); + /* Argument of CMD18 or CMD25 */ + packed_cmd_hdr[((i * 2)) + 1] = mmc_card_blockaddr(card) ? + blk_rq_pos(prq) : blk_rq_pos(prq) << 9; + mqrq->packed_blocks += blk_rq_sectors(prq); + i++; + } + + memset(brq, 0, sizeof(struct mmc_blk_request)); + brq->mrq.cmd = &brq->cmd; + brq->mrq.data = &brq->data; + brq->mrq.sbc = &brq->sbc; + brq->mrq.stop = &brq->stop; + + brq->sbc.opcode = MMC_SET_BLOCK_COUNT; + brq->sbc.arg = MMC_CMD23_ARG_PACKED | + ((rq_data_dir(req) == READ) ? 1 : mqrq->packed_blocks + 1); + brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; + + brq->cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; + brq->cmd.arg = blk_rq_pos(req); + if (!mmc_card_blockaddr(card)) + brq->cmd.arg <<= 9; + brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + + brq->data.blksz = 512; + /* + * Write separately the packd command header only for packed read. + * In case of packed write, header is sent with blocks of data. + */ + brq->data.blocks = (rq_data_dir(req) == READ) ? + 1 : mqrq->packed_blocks + 1; + brq->data.flags |= MMC_DATA_WRITE; + + brq->stop.opcode = MMC_STOP_TRANSMISSION; + brq->stop.arg = 0; + brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + + mmc_set_data_timeout(&brq->data, card); + + brq->data.sg = mqrq->sg; + brq->data.sg_len = mmc_queue_map_sg(mq, mqrq); + + mqrq->mmc_active.mrq = &brq->mrq; + mqrq->mmc_active.err_check = mmc_blk_packed_err_check; + + mmc_queue_bounce_pre(mqrq); +} +#else static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, struct mmc_card *card, struct mmc_queue *mq) @@ -1612,7 +1701,7 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, mmc_queue_bounce_pre(mqrq); } - +#endif static void mmc_blk_packed_rrq_prep(struct mmc_queue_req *mqrq, struct mmc_card *card, struct mmc_queue *mq) @@ -1722,7 +1811,11 @@ static int mmc_blk_issue_packed_rd(struct mmc_queue *mq, ret = mmc_blk_chk_hdr_err(mq, status); if (ret) break; +#ifdef CONFIG_WIMAX_CMC + mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq, mq_rq->packed_num); +#else mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq); +#endif mmc_start_req(card->host, &mq_rq->mmc_active, NULL); } else { mmc_blk_packed_rrq_prep(mq_rq, card, mq); @@ -1762,9 +1855,14 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) struct mmc_command cmd; #endif if (rqc) { +#ifdef CONFIG_WIMAX_CMC + if (reqs >= 2) + mmc_blk_packed_hdr_wrq_prep(mq->mqrq_cur, card, mq, reqs); +#else if (reqs >= packed_num) { mmc_blk_packed_hdr_wrq_prep(mq->mqrq_cur, card, mq); } +#endif else mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); areq = &mq->mqrq_cur->mmc_active; @@ -1920,22 +2018,36 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) if (idx == i) { /* retry from error index */ mq_rq->packed_num -= idx; +#ifdef CONFIG_WIMAX_CMC + if (mq_rq->packed_num == 1) { + printk(KERN_ERR "SBRISSEN - I AM HERE\n"); + mq_rq->packed_cmd = MMC_PACKED_NONE; + mq_rq->packed_num = 0; + } +#endif mq_rq->req = prq; ret = 1; break; } +#ifndef CONFIG_WIMAX_CMC list_del_init(&prq->queuelist); +#endif spin_lock_irq(&md->lock); __blk_end_request(prq, 0, blk_rq_bytes(prq)); spin_unlock_irq(&md->lock); i++; } +#ifdef CONFIG_WIMAX_CMC + if (idx == -1) + mq_rq->packed_num = 0; +#else if (mq_rq->packed_num == MMC_PACKED_N_SINGLE) { prq = list_entry_rq(mq_rq->packed_list.next); list_del_init(&prq->queuelist); mq_rq->packed_cmd = MMC_PACKED_NONE; mq_rq->packed_num = MMC_PACKED_N_ZERO; } +#endif break; } else { spin_lock_irq(&md->lock); @@ -2015,7 +2127,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq); mmc_start_req(card->host, &mq_rq->mmc_active, NULL); } else { +#ifdef CONFIG_WIMAX_CMC + mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq, mq_rq->packed_num); +#else mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq); +#endif mmc_start_req(card->host, &mq_rq->mmc_active, NULL); if (mq_rq->packed_cmd == MMC_PACKED_WR_HDR) { if (mmc_blk_issue_packed_rd(mq, mq_rq)) @@ -2478,6 +2594,10 @@ static int mmc_blk_probe(struct mmc_card *card) printk(KERN_INFO "%s: %s %s %s %s\n", md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), cap_str, md->read_only ? "(ro)" : ""); +#ifdef CONFIG_WIMAX_CMC + if (mmc_blk_alloc_parts(card, md)) + goto out; +#endif mmc_set_drvdata(card, md); mmc_fixup_device(card, blk_fixups); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index ddd6d50..8252d44 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -275,12 +275,22 @@ static void mmc_wait_for_req_done(struct mmc_host *host, /* if card is mmc type and nonremovable, and there are erros after issuing r/w command, then init eMMC and mshc */ +#ifdef CONFIG_WIMAX_CMC + if (((host->card) && mmc_card_mmc(host->card) && \ + (host->caps & MMC_CAP_NONREMOVABLE)) && \ + (mrq->cmd->error == -ENOTRECOVERABLE || \ + ((mrq->cmd->opcode == 17 || mrq->cmd->opcode == 18 || \ + mrq->cmd->opcode == 24 || mrq->cmd->opcode == 25) && \ + ((mrq->data->error) || mrq->cmd->error || \ + (mrq->sbc && mrq->sbc->error))))) { +#else if (((host->card) && mmc_card_mmc(host->card) && \ (host->caps & MMC_CAP_NONREMOVABLE)) && \ (mrq->cmd->error == -ENOTRECOVERABLE || \ ((mrq->cmd->opcode == 17 || mrq->cmd->opcode == 18) && \ ((mrq->data->error) || mrq->cmd->error || \ (mrq->sbc && mrq->sbc->error))))) { +#endif int rt_err = -1,count = 3; printk(KERN_ERR "%s: it occurs a critical error on eMMC " @@ -2440,6 +2450,7 @@ int mmc_suspend_host(struct mmc_host *host) wake_unlock(&host->detect_wake_lock); mmc_flush_scheduled_work(); if (mmc_try_claim_host(host)) { +#ifndef CONFIG_WIMAX_CMC u32 status; u32 count=300000; /* up to 300ms */ @@ -2453,7 +2464,9 @@ int mmc_suspend_host(struct mmc_host *host) "flushing emmc's cache\n", mmc_hostname(host),ret); } +#endif err = mmc_cache_ctrl(host, 0); +#ifndef CONFIG_WIMAX_CMC /* to make sure that emmc is not working. should check emmc's state */ @@ -2469,6 +2482,7 @@ int mmc_suspend_host(struct mmc_host *host) count--; } while (count && R1_CURRENT_STATE(status) == 7); } +#endif mmc_do_release_host(host); } else { err = -EBUSY; diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 3664c49..7966957 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -53,6 +53,7 @@ static DEFINE_IDR(mmc_host_idr); static DEFINE_SPINLOCK(mmc_host_lock); #ifdef CONFIG_MMC_CLKGATE +#ifndef CONFIG_WIMAX_CMC static ssize_t clkgate_delay_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -74,6 +75,7 @@ static ssize_t clkgate_delay_store(struct device *dev, spin_unlock_irqrestore(&host->clk_lock, flags); return count; } +#endif /* * Enabling clock gating will make the core call out to the host * once up and once down when it performs a request or card operation @@ -108,10 +110,14 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host) if (!host->clk_requests) { spin_unlock_irqrestore(&host->clk_lock, flags); /* wait only when clk_gate_delay is 0 */ +#ifdef CONFIG_WIMAX_CMC if (!host->clkgate_delay) { +#endif tick_ns = DIV_ROUND_UP(1000000000, freq); ndelay(host->clk_delay * tick_ns); +#ifdef CONFIG_WIMAX_CMC } +#endif } else { /* New users appeared while waiting for this work */ spin_unlock_irqrestore(&host->clk_lock, flags); @@ -135,9 +141,13 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host) */ static void mmc_host_clk_gate_work(struct work_struct *work) { +#ifdef CONFIG_WIMAX_CMC + struct mmc_host *host = container_of(work, struct mmc_host, + clk_gate_work); +#else struct mmc_host *host = container_of(work, struct mmc_host, clk_gate_work.work); - +#endif mmc_host_clk_gate_delayed(host); } @@ -152,9 +162,10 @@ static void mmc_host_clk_gate_work(struct work_struct *work) void mmc_host_clk_hold(struct mmc_host *host) { unsigned long flags; - +#ifndef CONFIG_WIMAX_CMC /* cancel any clock gating work scheduled by mmc_host_clk_release() */ cancel_delayed_work_sync(&host->clk_gate_work); +#endif mutex_lock(&host->clk_gate_mutex); spin_lock_irqsave(&host->clk_lock, flags); if (host->clk_gated) { @@ -204,9 +215,12 @@ void mmc_host_clk_release(struct mmc_host *host) host->clk_requests--; if (mmc_host_may_gate_card(host->card) && !host->clk_requests) +#ifdef CONFIG_WIMAX_CMC + queue_work(system_nrt_wq, &host->clk_gate_work); +#else queue_delayed_work(system_nrt_wq, &host->clk_gate_work, msecs_to_jiffies(host->clkgate_delay)); - +#endif spin_unlock_irqrestore(&host->clk_lock, flags); } @@ -239,13 +253,19 @@ static inline void mmc_host_clk_init(struct mmc_host *host) host->clk_requests = 0; /* Hold MCI clock for 8 cycles by default */ host->clk_delay = 8; +#ifndef CONFIG_WIMAX_CMC /* * Default clock gating delay is 0ms to avoid wasting power. * This value can be tuned by writing into sysfs entry. */ host->clkgate_delay = 3; +#endif host->clk_gated = false; +#ifdef CONFIG_WIMAX_CMC + INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); +#else INIT_DELAYED_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); +#endif spin_lock_init(&host->clk_lock); mutex_init(&host->clk_gate_mutex); } @@ -260,14 +280,18 @@ static inline void mmc_host_clk_exit(struct mmc_host *host) * Wait for any outstanding gate and then make sure we're * ungated before exiting. */ +#ifdef CONFIG_WIMAX_CMC + if (cancel_work_sync(&host->clk_gate_work)) +#else if (cancel_delayed_work_sync(&host->clk_gate_work)) +#endif mmc_host_clk_gate_delayed(host); if (host->clk_gated) mmc_host_clk_hold(host); /* There should be only one user now */ WARN_ON(host->clk_requests > 1); } - +#ifndef CONFIG_WIMAX_CMC static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) { host->clkgate_delay_attr.show = clkgate_delay_show; @@ -279,7 +303,7 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) pr_err("%s: Failed to create clkgate_delay sysfs entry\n", mmc_hostname(host)); } - +#endif #else static inline void mmc_host_clk_init(struct mmc_host *host) @@ -384,7 +408,9 @@ int mmc_add_host(struct mmc_host *host) mmc_add_host_debugfs(host); #endif +#ifndef CONFIG_WIMAX_CMC mmc_host_clk_sysfs_init(host); +#endif mmc_start_host(host); if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index 08a7852..df7d2cd 100644 --- a/drivers/mmc/core/host.h +++ b/drivers/mmc/core/host.h @@ -12,6 +12,26 @@ #define _MMC_CORE_HOST_H #include <linux/mmc/host.h> +#if defined(CONFIG_MMC_CLKGATE) +void mmc_host_clk_hold(struct mmc_host *host); +void mmc_host_clk_release(struct mmc_host *host); +unsigned int mmc_host_clk_rate(struct mmc_host *host); + +#else +static inline void mmc_host_clk_hold(struct mmc_host *host) +{ +} + +static inline void mmc_host_clk_release(struct mmc_host *host) +{ +} + +static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) +{ + return host->ios.clock; +} +#endif + int mmc_register_host_class(void); void mmc_unregister_host_class(void); void mmc_host_deeper_disable(struct work_struct *work); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 506a4e3..1622bbb 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -30,10 +30,12 @@ #else /* For debugging about ext_csd register value */ #if 0 +#ifndef CONFIG_WIMAX_CMC #define MMC_CHECK_EXT_CSD #endif #endif #endif +#endif /* * If moviNAND VHX 4.41 device @@ -216,7 +218,7 @@ static int mmc_decode_csd(struct mmc_card *card) return 0; } -#if defined(MMC_CHECK_EXT_CSD) +#if defined(MMC_CHECK_EXT_CSD) && !defined(CONFIG_WIMAX_CMC) /* For debugging about ext_csd register value */ static u8 *ext_csd_backup; static void mmc_error_ext_csd(struct mmc_card *card, u8 *ext_csd, @@ -340,7 +342,7 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) } else *new_ext_csd = ext_csd; -#if defined(MMC_CHECK_EXT_CSD) +#if defined(MMC_CHECK_EXT_CSD) && !defined(CONFIG_WIMAX_CMC) /* For debugging about ext_csd register value */ mmc_error_ext_csd(card, ext_csd, 1, 0); #endif @@ -369,7 +371,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) "version %d\n", mmc_hostname(card->host), card->ext_csd.raw_ext_csd_structure); err = -EINVAL; -#if defined(MMC_CHECK_EXT_CSD) +#if defined(MMC_CHECK_EXT_CSD) && !defined(CONFIG_WIMAX_CMC) /* For debugging about ext_csd register value */ mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_STRUCTURE); #endif @@ -386,7 +388,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; -#if defined(MMC_CHECK_EXT_CSD) +#if defined(MMC_CHECK_EXT_CSD) && !defined(CONFIG_WIMAX_CMC) /* For debugging about ext_csd register value */ mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_REV); #endif @@ -409,6 +411,35 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) mmc_card_set_blockaddr(card); } card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; +#ifdef CONFIG_WIMAX_CMC + switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { + case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; + break; + case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; + break; + case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; + break; + case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + break; + case EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 26000000; + break; + default: + /* MMC v4 spec says this cannot happen */ + printk(KERN_WARNING "%s: card is mmc v4 but doesn't " + "support any high-speed modes.\n", + mmc_hostname(card->host)); +#else if (card->host->caps2 & MMC_CAP2_HS200) { switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { case EXT_CSD_CARD_TYPE_SDR_ALL: @@ -507,6 +538,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) goto out; #endif } +#endif } card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; @@ -608,12 +640,12 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) card->host->card = card; movi_ver_check = mmc_start_movi_smart(card); } - +#ifndef CONFIG_WIMAX_CMC /* enable discard feature if emmc is 4.41+ moviNand */ if ((ext_csd[EXT_CSD_VENDOR_SPECIFIC_FIELD + 0] & 0x1) && (card->cid.manfid == 0x15)) card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; - +#endif /* enable PON feature if moviNAND VHX/VMX devices */ if (CHECK_MOVI_PON_SUPPORT) { if ((movi_ver_check & MMC_MOVI_VER_VHX0) && @@ -890,6 +922,7 @@ static int mmc_select_powerclass(struct mmc_card *card, return err; } +#ifndef CONFIG_WIMAX_CMC /* * Selects the desired buswidth and switch to the HS200 mode * if bus width set without error @@ -962,7 +995,7 @@ static int mmc_select_hs200(struct mmc_card *card) err: return err; } - +#endif /* * Handle the detection and initialisation of a card. * @@ -1076,7 +1109,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, /* * Fetch and process extended CSD. */ -#if defined(MMC_RETRY_READ_EXT_CSD) +#if defined(MMC_RETRY_READ_EXT_CSD) && !defined(CONFIG_WIMAX_CMC) { int i = 0; for (i = 0 ; i < 3 ; i++) { @@ -1180,6 +1213,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) goto free_card; +#ifdef CONFIG_WIMAX_CMC + if (!err) +#else + if (!err && (host->caps2 & MMC_CAP2_POWEROFF_NOTIFY)) +#endif /* * The err can be -EBADMSG or 0, * so check for success and update the flag @@ -1192,13 +1230,20 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * Activate high speed (if supported) */ if (card->ext_csd.hs_max_dtr != 0) { +#ifndef CONFIG_WIMAX_CMC err = 0; if (card->ext_csd.hs_max_dtr > 52000000 && host->caps2 & MMC_CAP2_HS200) err = mmc_select_hs200(card); else if (host->caps & MMC_CAP_MMC_HIGHSPEED) +#else + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_HS_TIMING, 1, card->ext_csd.generic_cmd6_time); +#endif +#ifndef CONFIG_WIMAX_CMC err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1, 0); +#endif if (err && err != -EBADMSG) goto free_card; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 3cec450..e0c3c88 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -788,7 +788,11 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) opcode = card->ext_csd.hpi_cmd; if (opcode == MMC_STOP_TRANSMISSION) +#ifdef CONFIG_WIMAX_CMC + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; +#else cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; +#endif else if (opcode == MMC_SEND_STATUS) cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index fa2a8b4..1e9c109 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -147,10 +147,14 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) } if (cccr_vsn >= SDIO_CCCR_REV_1_20) { +#ifdef CONFIG_WIMAX_CMC + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &data); +#else ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); +#endif if (ret) goto out; - +#ifndef CONFIG_WIMAX_CMC card->scr.sda_spec3 = 0; card->sw_caps.sd3_bus_mode = 0; card->sw_caps.sd3_drv_type = 0; @@ -201,6 +205,10 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) card->sw_caps.hs_max_dtr = 25000000; } } +#else + if (data & SDIO_SPEED_SHS) + card->cccr.high_speed = 1; +#endif } out: @@ -382,6 +390,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) return max_dtr; } +#ifndef CONFIG_WIMAX_CMC static unsigned char host_drive_to_sdio_drive(int host_strength) { switch (host_strength) { @@ -569,7 +578,7 @@ out: return err; } - +#endif /* * Handle the detection and initialisation of a card. * @@ -636,6 +645,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, if (host->ops->init_card) host->ops->init_card(host, card); +#ifndef CONFIG_WIMAX_CMC /* * If the host and card support UHS-I mode request the card * to switch to 1.8V signaling level. No 1.8v signalling if @@ -659,7 +669,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ocr &= ~R4_18V_PRESENT; host->ocr &= ~R4_18V_PRESENT; } - +#endif /* * For native busses: set card RCA and quit open drain mode. */ @@ -776,7 +786,30 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, err = sdio_disable_cd(card); if (err) goto remove; +#ifdef CONFIG_WIMAX_CMC + /* + * Switch to high-speed (if supported). + */ + err = sdio_enable_hs(card); + if (err > 0) + mmc_sd_go_highspeed(card); + else if (err) + goto remove; + + /* + * Change to the card's maximum speed. + */ + mmc_set_clock(host, mmc_sdio_get_max_clock(card)); + /* + * Switch to wider bus (if supported). + */ + err = sdio_enable_4bit_bus(card); + if (err > 0) + mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); + else if (err) + goto remove; +#else /* Initialization sequence for UHS-I cards */ /* Only if card supports 1.8v and UHS signaling */ if ((ocr & R4_18V_PRESENT) && card->sw_caps.sd3_bus_mode) { @@ -810,6 +843,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, else if (err) goto remove; } +#endif finish: if (!oldcard) host->card = card; @@ -911,6 +945,11 @@ out: static int mmc_sdio_suspend(struct mmc_host *host) { int i, err = 0; + +#ifdef CONFIG_WIMAX_CMC + if (host->pm_flags & MMC_PM_IGNORE_SUSPEND_RESUME) + return err; +#endif for (i = 0; i < host->card->sdio_funcs; i++) { struct sdio_func *func = host->card->sdio_func[i]; @@ -933,8 +972,7 @@ static int mmc_sdio_suspend(struct mmc_host *host) } } -#ifdef CONFIG_MACH_PX -#else +#ifndef CONFIG_MACH_PX if (!err && mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { mmc_claim_host(host); sdio_disable_wide(host->card); @@ -948,6 +986,11 @@ static int mmc_sdio_suspend(struct mmc_host *host) static int mmc_sdio_resume(struct mmc_host *host) { int i, err = 0; + +#ifdef CONFIG_WIMAX_CMC + if (host->pm_flags & MMC_PM_IGNORE_SUSPEND_RESUME) + return err; +#endif BUG_ON(!host); BUG_ON(!host->card); @@ -1299,3 +1342,66 @@ err: return err; } EXPORT_SYMBOL(sdio_reset_comm); + +#ifdef CONFIG_WIMAX_CMC +int cmc732_sdio_reset_comm(struct mmc_card *card) +{ + struct mmc_host *host = card->host; + u32 ocr; + int err; + printk("%s():\n",__func__); + cmc732_sdio_reset(host); + err = mmc_send_io_op_cond(host, 0, &ocr); + if (err) + goto err; +#if 1//refer to mmc_attach_sdio() + if (!host->index) + ocr |= 0x00000080; //correct cmc ocr to show support for 1.8v operation + host->ocr = mmc_select_voltage(host, ocr); + if (!host->index) + host->ocr = 0x8000;//lie to cmc card that 2.8v operation selected +#else + host->ocr = mmc_select_voltage(host, ocr); +#endif + if (!host->ocr) { + err = -EINVAL; + goto err; + } + err = mmc_send_io_op_cond(host, host->ocr, &ocr); + if (err) + goto err; + if (mmc_host_is_spi(host)) { + err = mmc_spi_set_crc(host, use_spi_crc); + if (err) + goto err; + } + if (!mmc_host_is_spi(host)) { + err = mmc_send_relative_addr(host, &card->rca); + if (err) + goto err; + mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); + } + if (!mmc_host_is_spi(host)) { + err = mmc_select_card(card); + if (err) + goto err; + } + err = sdio_enable_hs(card); + if (err) + goto err; + if (mmc_card_highspeed(card)) { + mmc_set_clock(host, 50000000); + } else { + mmc_set_clock(host, card->cis.max_dtr); + } + err = sdio_enable_wide(card); + if (err) + goto err; + return 0; +err: + printk("%s: Error resetting SDIO communications (%d)\n", + mmc_hostname(host), err); + return err; +} +EXPORT_SYMBOL(cmc732_sdio_reset_comm); +#endif diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index f087d87..42f7810 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c @@ -198,3 +198,27 @@ int sdio_reset(struct mmc_host *host) return ret; } +#ifdef CONFIG_WIMAX_CMC +int cmc732_sdio_reset(struct mmc_host *host) +{ + int ret; + u8 abort; + ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort); + if (ret) + abort = 0x01; + else + abort |= 0x01; + ret = mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL); + ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort); + abort &= 0xFE; + ret = mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL); + ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort); + if (ret) + abort = 0x08; + else + abort |= 0x08; + ret = mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL); + return ret; +} +#endif + diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h index 12a4d3a..ba07370 100644 --- a/drivers/mmc/core/sdio_ops.h +++ b/drivers/mmc/core/sdio_ops.h @@ -18,6 +18,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); int sdio_reset(struct mmc_host *host); +int cmc732_sdio_reset(struct mmc_host *host); #endif diff --git a/drivers/mmc/host/mshci-s3c.c b/drivers/mmc/host/mshci-s3c.c index 58670ca..2c890c9 100644 --- a/drivers/mmc/host/mshci-s3c.c +++ b/drivers/mmc/host/mshci-s3c.c @@ -488,6 +488,7 @@ static int __devinit mshci_s3c_probe(struct platform_device *pdev) if (pdata->cd_type == S3C_MSHCI_CD_PERMANENT) { host->quirks |= MSHCI_QUIRK_BROKEN_PRESENT_BIT; host->mmc->caps |= MMC_CAP_NONREMOVABLE; +#ifndef CONFIG_WIMAX_CMC if (pdata->int_power_gpio) { gpio_set_value(pdata->int_power_gpio, 1); s3c_gpio_cfgpin(pdata->int_power_gpio, @@ -495,6 +496,7 @@ static int __devinit mshci_s3c_probe(struct platform_device *pdev) s3c_gpio_setpull(pdata->int_power_gpio, S3C_GPIO_PULL_NONE); } +#endif } /* IF SD controller's WP pin donsn't connected with SD card and there @@ -511,12 +513,15 @@ static int __devinit mshci_s3c_probe(struct platform_device *pdev) if (pdata->cd_type == S3C_MSHCI_CD_GPIO && gpio_is_valid(pdata->ext_cd_gpio)) { +#ifdef CONFIG_WIMAX_CMC + gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD"); +#else ret = gpio_request(pdata->ext_cd_gpio, "MSHCI EXT CD"); if (ret) { dev_err(&pdev->dev, "cannot request gpio for card detect\n"); goto err_add_host; } - +#endif sc->ext_cd_gpio = pdata->ext_cd_gpio; sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio); @@ -537,7 +542,9 @@ static int __devinit mshci_s3c_probe(struct platform_device *pdev) goto err_add_host; } +#ifndef CONFIG_WIMAX_CMC device_enable_async_suspend(dev); +#endif return 0; diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 712c8c6..eba9825 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -608,6 +608,11 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; + +#ifdef CONFIG_WIMAX_CMC + /* This host supports the Auto CMD12 */ + host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; +#endif if (pdata->cd_type == S3C_SDHCI_CD_NONE) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; @@ -706,6 +711,10 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) pdata->ext_pdev(pdev); #endif } +#ifdef CONFIG_MACH_U1_NA_SPR + if (pdata->cd_type == S3C_SDHCI_CD_GPIO && pdata->ext_cd_init) + pdata->ext_cd_init(&sdhci_s3c_notify_change); +#endif if (pdata->cd_type == S3C_SDHCI_CD_GPIO && gpio_is_valid(pdata->ext_cd_gpio)) sdhci_s3c_setup_card_detect_gpio(sc); @@ -742,6 +751,10 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) pdata->ext_cd_cleanup(&sdhci_s3c_notify_change); +#ifdef CONFIG_MACH_U1_NA_SPR + if (pdata->cd_type == S3C_SDHCI_CD_GPIO && pdata->ext_cd_cleanup) + pdata->ext_cd_cleanup(&sdhci_s3c_notify_change); +#endif if (sc->ext_cd_irq) free_irq(sc->ext_cd_irq, sc); @@ -792,9 +805,24 @@ static void sdhci_s3c_shutdown(struct platform_device *dev) static int sdhci_s3c_resume(struct platform_device *dev) { struct sdhci_host *host = platform_get_drvdata(dev); +#if defined(CONFIG_WIMAX_CMC)/* && defined(CONFIG_TARGET_LOCALE_NA)*/ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + u32 ier; +#endif int ret = 0; ret = sdhci_resume_host(host); + +#if defined(CONFIG_WIMAX_CMC)/* && defined(CONFIG_TARGET_LOCALE_NA)*/ + + + if (pdata->enable_intr_on_resume) { + ier = sdhci_readl(host, SDHCI_INT_ENABLE); + ier |= SDHCI_INT_CARD_INT; + sdhci_writel(host, ier, SDHCI_INT_ENABLE); + sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); + } +#endif return ret; } |