* [PATCH] mmc: core: add core-level function for sending tuning commands
@ 2014-11-21 14:46 Barry Song
2014-11-24 11:44 ` Ulf Hansson
0 siblings, 1 reply; 4+ messages in thread
From: Barry Song @ 2014-11-21 14:46 UTC (permalink / raw)
To: linux-arm-kernel
From: Minda Chen <Minda.Chen@csr.com>
According to the SD card spec, Add a manual tuning command function
for SDR104/HS200 by sending command 19 or command 21 to read data
and compare with the tuning block pattern.
this patch will help to decrease some platform private codes in
SDHCI platform_execute_tuning() callbacks.
Signed-off-by: Minda Chen <Minda.Chen@csr.com>
Signed-off-by: Barry Song <Baohua.Song@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
--
2.1.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH] mmc: core: add core-level function for sending tuning commands
2014-11-21 14:46 [PATCH] mmc: core: add core-level function for sending tuning commands Barry Song
@ 2014-11-24 11:44 ` Ulf Hansson
2014-11-25 3:19 ` Barry Song
0 siblings, 1 reply; 4+ messages in thread
From: Ulf Hansson @ 2014-11-24 11:44 UTC (permalink / raw)
To: linux-arm-kernel
On 21 November 2014 at 15:46, Barry Song <21cnbao@gmail.com> wrote:
> From: Minda Chen <Minda.Chen@csr.com>
>
> According to the SD card spec, Add a manual tuning command function
> for SDR104/HS200 by sending command 19 or command 21 to read data
> and compare with the tuning block pattern.
>
> this patch will help to decrease some platform private codes in
> SDHCI platform_execute_tuning() callbacks.
>
> Signed-off-by: Minda Chen <Minda.Chen@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@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) {
I don't think we need to care about the opcode. Let's just check the bus_width.
> + 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);
You should use kzalloc() to get the zeroed buffer you want.
> + 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;
These needs to be assigned as well:
data.sg = &sg;
data.sg_len = 1;
> +
> + mmc_set_data_timeout(&data, card);
mmc_set_data_timeout() doesn't handle CMD21/19.
The specs tells us about 40 commands should be executed within 150ms.
I would pick a value of 150ms, just to be sure we are inside that
range. Also, assign "data->timeout_ns" here, instead of relying on
mmc_set_data_timeout().
> + 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
> --
> 2.1.1
>
Kind regards
Uffe
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] mmc: core: add core-level function for sending tuning commands
2014-11-24 11:44 ` Ulf Hansson
@ 2014-11-25 3:19 ` Barry Song
2014-11-25 10:32 ` Ulf Hansson
0 siblings, 1 reply; 4+ messages in thread
From: Barry Song @ 2014-11-25 3:19 UTC (permalink / raw)
To: linux-arm-kernel
2014-11-24 19:44 GMT+08:00 Ulf Hansson <ulf.hansson@linaro.org>:
> On 21 November 2014 at 15:46, Barry Song <21cnbao@gmail.com> wrote:
>> From: Minda Chen <Minda.Chen@csr.com>
>>
>> According to the SD card spec, Add a manual tuning command function
>> for SDR104/HS200 by sending command 19 or command 21 to read data
>> and compare with the tuning block pattern.
>>
>> this patch will help to decrease some platform private codes in
>> SDHCI platform_execute_tuning() callbacks.
>>
>> Signed-off-by: Minda Chen <Minda.Chen@csr.com>
>> Signed-off-by: Barry Song <Baohua.Song@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) {
>
> I don't think we need to care about the opcode. Let's just check the bus_width.
>
>> + 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);
>
> You should use kzalloc() to get the zeroed buffer you want.
>
>> + 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;
>
> These needs to be assigned as well:
>
> data.sg = &sg;
> data.sg_len = 1;
>
>> +
>> + mmc_set_data_timeout(&data, card);
>
> mmc_set_data_timeout() doesn't handle CMD21/19.
>
> The specs tells us about 40 commands should be executed within 150ms.
> I would pick a value of 150ms, just to be sure we are inside that
> range. Also, assign "data->timeout_ns" here, instead of relying on
> mmc_set_data_timeout().
>
>> + 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
>> --
>> 2.1.1
>>
What about?
546 int mmc_send_tuning(struct mmc_card *card)
547 {
548 struct mmc_request mrq = {NULL};
549 struct mmc_command cmd = {0};
550 struct mmc_data data = {0};
551 struct scatterlist sg;
552 struct mmc_host *mmc = card->host;
553 struct mmc_ios *ios = &mmc->ios;
554 const u8 *tuning_block_pattern;
555 int size, err = 0;
556 u8 *data_buf;
557 u32 opcode;
558
559 if (ios->bus_width == MMC_BUS_WIDTH_8) {
560 tuning_block_pattern = tuning_blk_pattern_8bit;
561 size = sizeof(tuning_blk_pattern_8bit);
562 opcode = MMC_SEND_TUNING_BLOCK_HS200;
563 } else if (ios->bus_width == MMC_BUS_WIDTH_4) {
564 tuning_block_pattern = tuning_blk_pattern_4bit;
565 size = sizeof(tuning_blk_pattern_4bit);
566 opcode = MMC_SEND_TUNING_BLOCK;
567 } else
568 return -EINVAL;
569
570 data_buf = kzalloc(size, GFP_KERNEL);
571 if (!data_buf)
572 return -ENOMEM;
573
574 mrq.cmd = &cmd;
575 mrq.data = &data;
576
577 cmd.opcode = opcode;
578 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
579
580 data.blksz = size;
581 data.blocks = 1;
582 data.flags = MMC_DATA_READ;
583
584 /*
585 * According to the tuning specs, Tuning process
586 * is normally shorter 40 executions of CMD19,
587 * and timeout value should be shorter than 150 ms
588 */
589 data.timeout_ns = 150 * NSEC_PER_MSEC;
590
591 data.sg = &sg;
592 data.sg_len = 1;
593 sg_init_one(&sg, data_buf, size);
594
595 mmc_wait_for_req(mmc, &mrq);
596
597 if (cmd.error) {
598 err = cmd.error;
599 goto out;
600 }
601
602 if (data.error) {
603 err = data.error;
604 goto out;
605 }
606
607 if (memcmp(data_buf, tuning_block_pattern, size))
608 err = -EIO;
609
610 out:
611 kfree(data_buf);
612 return err;
613 }
614 EXPORT_SYMBOL_GPL(mmc_send_tuning);
>
> Kind regards
> Uffe
-barry
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] mmc: core: add core-level function for sending tuning commands
2014-11-25 3:19 ` Barry Song
@ 2014-11-25 10:32 ` Ulf Hansson
0 siblings, 0 replies; 4+ messages in thread
From: Ulf Hansson @ 2014-11-25 10:32 UTC (permalink / raw)
To: linux-arm-kernel
On 25 November 2014 at 04:19, Barry Song <21cnbao@gmail.com> wrote:
> 2014-11-24 19:44 GMT+08:00 Ulf Hansson <ulf.hansson@linaro.org>:
>> On 21 November 2014 at 15:46, Barry Song <21cnbao@gmail.com> wrote:
>>> From: Minda Chen <Minda.Chen@csr.com>
>>>
>>> According to the SD card spec, Add a manual tuning command function
>>> for SDR104/HS200 by sending command 19 or command 21 to read data
>>> and compare with the tuning block pattern.
>>>
>>> this patch will help to decrease some platform private codes in
>>> SDHCI platform_execute_tuning() callbacks.
>>>
>>> Signed-off-by: Minda Chen <Minda.Chen@csr.com>
>>> Signed-off-by: Barry Song <Baohua.Song@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) {
>>
>> I don't think we need to care about the opcode. Let's just check the bus_width.
>>
>>> + 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);
>>
>> You should use kzalloc() to get the zeroed buffer you want.
>>
>>> + 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;
>>
>> These needs to be assigned as well:
>>
>> data.sg = &sg;
>> data.sg_len = 1;
>>
>>> +
>>> + mmc_set_data_timeout(&data, card);
>>
>> mmc_set_data_timeout() doesn't handle CMD21/19.
>>
>> The specs tells us about 40 commands should be executed within 150ms.
>> I would pick a value of 150ms, just to be sure we are inside that
>> range. Also, assign "data->timeout_ns" here, instead of relying on
>> mmc_set_data_timeout().
>>
>>> + 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
>>> --
>>> 2.1.1
>>>
>
> What about?
>
> 546 int mmc_send_tuning(struct mmc_card *card)
> 547 {
> 548 struct mmc_request mrq = {NULL};
> 549 struct mmc_command cmd = {0};
> 550 struct mmc_data data = {0};
> 551 struct scatterlist sg;
> 552 struct mmc_host *mmc = card->host;
> 553 struct mmc_ios *ios = &mmc->ios;
> 554 const u8 *tuning_block_pattern;
> 555 int size, err = 0;
> 556 u8 *data_buf;
> 557 u32 opcode;
> 558
> 559 if (ios->bus_width == MMC_BUS_WIDTH_8) {
> 560 tuning_block_pattern = tuning_blk_pattern_8bit;
> 561 size = sizeof(tuning_blk_pattern_8bit);
> 562 opcode = MMC_SEND_TUNING_BLOCK_HS200;
> 563 } else if (ios->bus_width == MMC_BUS_WIDTH_4) {
> 564 tuning_block_pattern = tuning_blk_pattern_4bit;
> 565 size = sizeof(tuning_blk_pattern_4bit);
> 566 opcode = MMC_SEND_TUNING_BLOCK;
> 567 } else
> 568 return -EINVAL;
> 569
> 570 data_buf = kzalloc(size, GFP_KERNEL);
> 571 if (!data_buf)
> 572 return -ENOMEM;
> 573
> 574 mrq.cmd = &cmd;
> 575 mrq.data = &data;
> 576
> 577 cmd.opcode = opcode;
> 578 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> 579
> 580 data.blksz = size;
> 581 data.blocks = 1;
> 582 data.flags = MMC_DATA_READ;
> 583
> 584 /*
> 585 * According to the tuning specs, Tuning process
> 586 * is normally shorter 40 executions of CMD19,
> 587 * and timeout value should be shorter than 150 ms
> 588 */
> 589 data.timeout_ns = 150 * NSEC_PER_MSEC;
> 590
> 591 data.sg = &sg;
> 592 data.sg_len = 1;
> 593 sg_init_one(&sg, data_buf, size);
> 594
> 595 mmc_wait_for_req(mmc, &mrq);
> 596
> 597 if (cmd.error) {
> 598 err = cmd.error;
> 599 goto out;
> 600 }
> 601
> 602 if (data.error) {
> 603 err = data.error;
> 604 goto out;
> 605 }
> 606
> 607 if (memcmp(data_buf, tuning_block_pattern, size))
> 608 err = -EIO;
> 609
> 610 out:
> 611 kfree(data_buf);
> 612 return err;
> 613 }
> 614 EXPORT_SYMBOL_GPL(mmc_send_tuning);
>
Looks good!
Kind regards
Uffe
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-11-25 10:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-21 14:46 [PATCH] mmc: core: add core-level function for sending tuning commands Barry Song
2014-11-24 11:44 ` Ulf Hansson
2014-11-25 3:19 ` Barry Song
2014-11-25 10:32 ` Ulf Hansson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).