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/card | |
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/card')
-rw-r--r-- | drivers/mmc/card/block.c | 122 |
1 files changed, 121 insertions, 1 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); |