diff mbox

mmc: sdhci-sirf: add sirf tuning function (cmd 19)

Message ID CAGsJ_4xzQJ-v7mM8_gD299EN=Hb9aShY5HcR6R8XyEwXB+Ofzg@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Barry Song Nov. 20, 2014, 9:25 a.m. UTC
>>> 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:


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(+)

 #define MMC_ERASE_ARG 0x00000000

Comments

Ulf Hansson Nov. 21, 2014, 11:17 a.m. UTC | #1
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 mbox

Patch

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);