Message ID | CAGsJ_4xzQJ-v7mM8_gD299EN=Hb9aShY5HcR6R8XyEwXB+Ofzg@mail.gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 20 November 2014 10:25, Barry Song <21cnbao@gmail.com> wrote: >>>> These piece of code, which sends the tuning command don't belong in >>>> the host driver. Instead I would like this to be handled from a helper >>>> function from the mmc core. >>>> >>>> I realize that there already a few existing host drivers that >>>> implemented similar code and I don't like it. We should convert them >>>> to use a common helper function from the core instead. >>> yes. that is fine. >>> >>> our engineering is currently very busy and might have no time to >>> handle this for this moment. >>> do you think we can move your requirement to a new refine task of next >>> window after you pick up this in this window? >> >> No. >> >> You don't have to adopt the other host drivers at this point, only to >> fix yours accordingly. The rest we can take care of later. >> > > Uffe, how do you think about we provide a core-level function at first: That's exactly what I had in mind. :-) Please resend as a separate patch. Kind regards Uffe > > > From 3f47dfd577ef3ff8c41dbb44d71d383a9e620ada Mon Sep 17 00:00:00 2001 > From: Minda Chen <Minda.Chen@csr.com> > Date: Thu, 20 Nov 2014 10:42:41 +0800 > Subject: [PATCH] mmc: ops: Add mmc_send_tuning function > > According to the SD card spec, Add a manual > tuning command function for SDR104/HS200 > Sending command 19 or command 21 to read data > and compare with the tunning block. > > Change-Id: Ic481b78b1e247c88942788ff0d10746779f672c0 > Signed-off-by: Minda Chen <Minda.Chen@csr.com> > --- > drivers/mmc/core/mmc_ops.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/mmc/core.h | 1 + > 2 files changed, 66 insertions(+) > > diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c > index 7911e05..ecc7789 100644 > --- a/drivers/mmc/core/mmc_ops.c > +++ b/drivers/mmc/core/mmc_ops.c > @@ -543,6 +543,71 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 > index, u8 value, > } > EXPORT_SYMBOL_GPL(mmc_switch); > > +int mmc_send_tuning(struct mmc_card *card, u32 opcode) > +{ > + struct mmc_request mrq = {NULL}; > + struct mmc_command cmd = {0}; > + struct mmc_data data = {0}; > + struct scatterlist sg; > + struct mmc_host *mmc = card->host; > + struct mmc_ios *ios = &mmc->ios; > + const u8 *tuning_block_pattern; > + int size, err = 0; > + u8 *data_buf; > + > + if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { > + if (ios->bus_width == MMC_BUS_WIDTH_8) { > + tuning_block_pattern = tuning_blk_pattern_8bit; > + size = sizeof(tuning_blk_pattern_8bit); > + } else if (ios->bus_width == MMC_BUS_WIDTH_4) { > + tuning_block_pattern = tuning_blk_pattern_4bit; > + size = sizeof(tuning_blk_pattern_4bit); > + } else > + return -EINVAL; > + } else if (opcode == MMC_SEND_TUNING_BLOCK) { > + tuning_block_pattern = tuning_blk_pattern_4bit; > + size = sizeof(tuning_blk_pattern_4bit); > + } else > + return -EINVAL; > + > + data_buf = kmalloc(size, GFP_KERNEL); > + if (!data_buf) > + return -ENOMEM; > + > + mrq.cmd = &cmd; > + mrq.data = &data; > + > + cmd.opcode = opcode; > + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; > + > + data.blksz = size; > + data.blocks = 1; > + data.flags = MMC_DATA_READ; > + > + mmc_set_data_timeout(&data, card); > + sg_init_one(&sg, data_buf, size); > + memset(data_buf, 0, size); > + mmc_wait_for_req(mmc, &mrq); > + > + if (cmd.error) { > + err = cmd.error; > + goto out; > + } > + > + if (data.error) { > + err = data.error; > + goto out; > + } > + > + if (memcmp(data_buf, tuning_block_pattern, size)) > + err = -EIO; > + > +out: > + kfree(data_buf); > + return err; > +} > +EXPORT_SYMBOL_GPL(mmc_send_tuning); > + > static int > mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, > u8 len) > diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h > index f206e29..82a0119 100644 > --- a/include/linux/mmc/core.h > +++ b/include/linux/mmc/core.h > @@ -154,6 +154,7 @@ extern void mmc_start_bkops(struct mmc_card *card, > bool from_exception); > extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, > bool, bool); > extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); > +extern int mmc_send_tuning(struct mmc_card *, u32); > extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); > > #define MMC_ERASE_ARG 0x00000000 > -- > 1.9.1 > > >> Br >> Uffe -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 7911e05..ecc7789 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -543,6 +543,71 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, } EXPORT_SYMBOL_GPL(mmc_switch); +int mmc_send_tuning(struct mmc_card *card, u32 opcode) +{ + struct mmc_request mrq = {NULL}; + struct mmc_command cmd = {0}; + struct mmc_data data = {0}; + struct scatterlist sg; + struct mmc_host *mmc = card->host; + struct mmc_ios *ios = &mmc->ios; + const u8 *tuning_block_pattern; + int size, err = 0; + u8 *data_buf; + + if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { + if (ios->bus_width == MMC_BUS_WIDTH_8) { + tuning_block_pattern = tuning_blk_pattern_8bit; + size = sizeof(tuning_blk_pattern_8bit); + } else if (ios->bus_width == MMC_BUS_WIDTH_4) { + tuning_block_pattern = tuning_blk_pattern_4bit; + size = sizeof(tuning_blk_pattern_4bit); + } else + return -EINVAL; + } else if (opcode == MMC_SEND_TUNING_BLOCK) { + tuning_block_pattern = tuning_blk_pattern_4bit; + size = sizeof(tuning_blk_pattern_4bit); + } else + return -EINVAL; + + data_buf = kmalloc(size, GFP_KERNEL); + if (!data_buf) + return -ENOMEM; + + mrq.cmd = &cmd; + mrq.data = &data; + + cmd.opcode = opcode; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + data.blksz = size; + data.blocks = 1; + data.flags = MMC_DATA_READ; + + mmc_set_data_timeout(&data, card); + sg_init_one(&sg, data_buf, size); + memset(data_buf, 0, size); + mmc_wait_for_req(mmc, &mrq); + + if (cmd.error) { + err = cmd.error; + goto out; + } + + if (data.error) { + err = data.error; + goto out; + } + + if (memcmp(data_buf, tuning_block_pattern, size)) + err = -EIO; + +out: + kfree(data_buf); + return err; +} +EXPORT_SYMBOL_GPL(mmc_send_tuning); + static int mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, u8 len) diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index f206e29..82a0119 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -154,6 +154,7 @@ extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, bool, bool); extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); +extern int mmc_send_tuning(struct mmc_card *, u32); extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);