diff mbox

[U-Boot,RFC,2/3,v2] mmc: SEND_OP_COND considers card capabilities (voltage)

Message ID 1299771783-4163-3-git-send-email-lamiaposta71@gmail.com
State Superseded, archived
Headers show

Commit Message

Raffaele Recalcati March 10, 2011, 3:43 p.m. UTC
From: Raffaele Recalcati <raffaele.recalcati@bticino.it>

The first SEND_OP_COND (CMD1) is used only to ask card capabilities, waiting
that the card is not busy.
After it, an AND operation is done between card capabilities and host
capabilities, (at the moment only for the voltage field).
Finally the correct value is sent to the MMC.

Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
---
 drivers/mmc/mmc.c |   21 +++++++++++++++++++--
 include/mmc.h     |    2 ++
 2 files changed, 21 insertions(+), 2 deletions(-)

Comments

Lei Wen March 10, 2011, 4:29 p.m. UTC | #1
Hi Raffaele,

On Thu, Mar 10, 2011 at 11:43 PM, Raffaele Recalcati
<lamiaposta71@gmail.com> wrote:
> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>
> The first SEND_OP_COND (CMD1) is used only to ask card capabilities, waiting
> that the card is not busy.
> After it, an AND operation is done between card capabilities and host
> capabilities, (at the moment only for the voltage field).
> Finally the correct value is sent to the MMC.
>
> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> ---
>  drivers/mmc/mmc.c |   21 +++++++++++++++++++--
>  include/mmc.h     |    2 ++
>  2 files changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 042653f..ded630b 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -347,17 +347,34 @@ sd_send_op_cond(struct mmc *mmc)
>
>  int mmc_send_op_cond(struct mmc *mmc)
>  {
> -       int timeout = 1000;
> +       int timeout = 10000;
>        struct mmc_cmd cmd;
>        int err;
>
>        /* Some cards seem to need this */
>        mmc_go_idle(mmc);
>
> +       /* Asking to the card its capabilities */
> +       do {
> +               cmd.cmdidx = MMC_CMD_SEND_OP_COND;
> +               cmd.resp_type = MMC_RSP_R3;
> +               cmd.cmdarg = 0;
> +               cmd.flags = 0;
> +
> +               err = mmc_send_cmd(mmc, &cmd, NULL);
> +
> +               if (err)
> +                       return err;
> +
> +               udelay(1000);
> +       } while (!(cmd.response[0] & OCR_BUSY) && timeout--);

I think you should not put the first probe a multi-time. In linux framework,
it would skip the first probing.

I test with this patch and fail to detect my emmc card...
While just let the first probe once, it works fine.

Best regards,
Lei
Raffaele Recalcati March 10, 2011, 4:59 p.m. UTC | #2
On Thu, Mar 10, 2011 at 5:29 PM, Lei Wen <adrian.wenl@gmail.com> wrote:
> Hi Raffaele,
>
> On Thu, Mar 10, 2011 at 11:43 PM, Raffaele Recalcati
> <lamiaposta71@gmail.com> wrote:
>> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>>
>> The first SEND_OP_COND (CMD1) is used only to ask card capabilities, waiting
>> that the card is not busy.
>> After it, an AND operation is done between card capabilities and host
>> capabilities, (at the moment only for the voltage field).
>> Finally the correct value is sent to the MMC.
>>
>> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>> ---
>>  drivers/mmc/mmc.c |   21 +++++++++++++++++++--
>>  include/mmc.h     |    2 ++
>>  2 files changed, 21 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index 042653f..ded630b 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -347,17 +347,34 @@ sd_send_op_cond(struct mmc *mmc)
>>
>>  int mmc_send_op_cond(struct mmc *mmc)
>>  {
>> -       int timeout = 1000;
>> +       int timeout = 10000;
>>        struct mmc_cmd cmd;
>>        int err;
>>
>>        /* Some cards seem to need this */
>>        mmc_go_idle(mmc);
>>
>> +       /* Asking to the card its capabilities */
>> +       do {
>> +               cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>> +               cmd.resp_type = MMC_RSP_R3;
>> +               cmd.cmdarg = 0;
>> +               cmd.flags = 0;
>> +
>> +               err = mmc_send_cmd(mmc, &cmd, NULL);
>> +
>> +               if (err)
>> +                       return err;
>> +
>> +               udelay(1000);
>> +       } while (!(cmd.response[0] & OCR_BUSY) && timeout--);
>
> I think you should not put the first probe a multi-time. In linux framework,
> it would skip the first probing.
>
> I test with this patch and fail to detect my emmc card...
> While just let the first probe once, it works fine.
>
> Best regards,
> Lei
>

Look at JEDEC Standard No. 84-A441 document at page 190.
It is normal to ask the card capabilities before setting.
But I understand also that in your case there is some issue.
I'm sorry, what does "multi-time" mean?

Thx,
Raffaele
Lei Wen March 11, 2011, 3:14 a.m. UTC | #3
On Fri, Mar 11, 2011 at 12:59 AM, Raffaele Recalcati
<lamiaposta71@gmail.com> wrote:
> On Thu, Mar 10, 2011 at 5:29 PM, Lei Wen <adrian.wenl@gmail.com> wrote:
>> Hi Raffaele,
>>
>> On Thu, Mar 10, 2011 at 11:43 PM, Raffaele Recalcati
>> <lamiaposta71@gmail.com> wrote:
>>> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>>>
>>> The first SEND_OP_COND (CMD1) is used only to ask card capabilities, waiting
>>> that the card is not busy.
>>> After it, an AND operation is done between card capabilities and host
>>> capabilities, (at the moment only for the voltage field).
>>> Finally the correct value is sent to the MMC.
>>>
>>> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>>> ---
>>>  drivers/mmc/mmc.c |   21 +++++++++++++++++++--
>>>  include/mmc.h     |    2 ++
>>>  2 files changed, 21 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>>> index 042653f..ded630b 100644
>>> --- a/drivers/mmc/mmc.c
>>> +++ b/drivers/mmc/mmc.c
>>> @@ -347,17 +347,34 @@ sd_send_op_cond(struct mmc *mmc)
>>>
>>>  int mmc_send_op_cond(struct mmc *mmc)
>>>  {
>>> -       int timeout = 1000;
>>> +       int timeout = 10000;
>>>        struct mmc_cmd cmd;
>>>        int err;
>>>
>>>        /* Some cards seem to need this */
>>>        mmc_go_idle(mmc);
>>>
>>> +       /* Asking to the card its capabilities */
>>> +       do {
>>> +               cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>>> +               cmd.resp_type = MMC_RSP_R3;
>>> +               cmd.cmdarg = 0;
>>> +               cmd.flags = 0;
>>> +
>>> +               err = mmc_send_cmd(mmc, &cmd, NULL);
>>> +
>>> +               if (err)
>>> +                       return err;
>>> +
>>> +               udelay(1000);
>>> +       } while (!(cmd.response[0] & OCR_BUSY) && timeout--);
>>
>> I think you should not put the first probe a multi-time. In linux framework,
>> it would skip the first probing.
>>
>> I test with this patch and fail to detect my emmc card...
>> While just let the first probe once, it works fine.
>>
>> Best regards,
>> Lei
>>
>
> Look at JEDEC Standard No. 84-A441 document at page 190.
> It is normal to ask the card capabilities before setting.
> But I understand also that in your case there is some issue.
> I'm sorry, what does "multi-time" mean?
>

I mean on my board I cannot get (!(cmd.response[0] & OCR_BUSY) to be
true for the first
MMC_CMD_SEND_OP_COND until its timeout, which lead to card init fail.

Best regards,
Lei
Raffaele Recalcati March 11, 2011, 6:30 a.m. UTC | #4
On Fri, Mar 11, 2011 at 4:14 AM, Lei Wen <adrian.wenl@gmail.com> wrote:
> On Fri, Mar 11, 2011 at 12:59 AM, Raffaele Recalcati
> <lamiaposta71@gmail.com> wrote:
>> On Thu, Mar 10, 2011 at 5:29 PM, Lei Wen <adrian.wenl@gmail.com> wrote:
>>> Hi Raffaele,
>>>
>>> On Thu, Mar 10, 2011 at 11:43 PM, Raffaele Recalcati
>>> <lamiaposta71@gmail.com> wrote:
>>>> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>>>>
>>>> The first SEND_OP_COND (CMD1) is used only to ask card capabilities, waiting
>>>> that the card is not busy.
>>>> After it, an AND operation is done between card capabilities and host
>>>> capabilities, (at the moment only for the voltage field).
>>>> Finally the correct value is sent to the MMC.
>>>>
>>>> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>>>> ---
>>>>  drivers/mmc/mmc.c |   21 +++++++++++++++++++--
>>>>  include/mmc.h     |    2 ++
>>>>  2 files changed, 21 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>>>> index 042653f..ded630b 100644
>>>> --- a/drivers/mmc/mmc.c
>>>> +++ b/drivers/mmc/mmc.c
>>>> @@ -347,17 +347,34 @@ sd_send_op_cond(struct mmc *mmc)
>>>>
>>>>  int mmc_send_op_cond(struct mmc *mmc)
>>>>  {
>>>> -       int timeout = 1000;
>>>> +       int timeout = 10000;
>>>>        struct mmc_cmd cmd;
>>>>        int err;
>>>>
>>>>        /* Some cards seem to need this */
>>>>        mmc_go_idle(mmc);
>>>>
>>>> +       /* Asking to the card its capabilities */
>>>> +       do {
>>>> +               cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>>>> +               cmd.resp_type = MMC_RSP_R3;
>>>> +               cmd.cmdarg = 0;
>>>> +               cmd.flags = 0;
>>>> +
>>>> +               err = mmc_send_cmd(mmc, &cmd, NULL);
>>>> +
>>>> +               if (err)
>>>> +                       return err;
>>>> +
>>>> +               udelay(1000);
>>>> +       } while (!(cmd.response[0] & OCR_BUSY) && timeout--);
>>>
>>> I think you should not put the first probe a multi-time. In linux framework,
>>> it would skip the first probing.
>>>
>>> I test with this patch and fail to detect my emmc card...
>>> While just let the first probe once, it works fine.
>>>
>>> Best regards,
>>> Lei
>>>
>>
>> Look at JEDEC Standard No. 84-A441 document at page 190.
>> It is normal to ask the card capabilities before setting.
>> But I understand also that in your case there is some issue.
>> I'm sorry, what does "multi-time" mean?
>>
>
> I mean on my board I cannot get (!(cmd.response[0] & OCR_BUSY) to be
> true for the first
> MMC_CMD_SEND_OP_COND until its timeout, which lead to card init fail.
>
> Best regards,
> Lei
>

This means 10msec are not enough.
Even if a board dependent value should be better, can you find please
the minimum value that it nice for your board?
With this value I'll resend the updated patch.
Can you also please test the trace patch (the third one), I think it
is quite useful to discover hw related problems.
Sorry for having sent a not nice patchset (two PATCH and one RFC).


Regards,
Raffaele
Lei Wen March 11, 2011, 6:52 a.m. UTC | #5
Hi Raffaele,


On Fri, Mar 11, 2011 at 2:30 PM, Raffaele Recalcati
<lamiaposta71@gmail.com> wrote:
> On Fri, Mar 11, 2011 at 4:14 AM, Lei Wen <adrian.wenl@gmail.com> wrote:
>> On Fri, Mar 11, 2011 at 12:59 AM, Raffaele Recalcati
>> <lamiaposta71@gmail.com> wrote:
>>> On Thu, Mar 10, 2011 at 5:29 PM, Lei Wen <adrian.wenl@gmail.com> wrote:
>>>> Hi Raffaele,
>>>>
>>>> On Thu, Mar 10, 2011 at 11:43 PM, Raffaele Recalcati
>>>> <lamiaposta71@gmail.com> wrote:
>>>>> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>>>>>
>>>>> The first SEND_OP_COND (CMD1) is used only to ask card capabilities, waiting
>>>>> that the card is not busy.
>>>>> After it, an AND operation is done between card capabilities and host
>>>>> capabilities, (at the moment only for the voltage field).
>>>>> Finally the correct value is sent to the MMC.
>>>>>
>>>>> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>>>>> ---
>>>>>  drivers/mmc/mmc.c |   21 +++++++++++++++++++--
>>>>>  include/mmc.h     |    2 ++
>>>>>  2 files changed, 21 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>>>>> index 042653f..ded630b 100644
>>>>> --- a/drivers/mmc/mmc.c
>>>>> +++ b/drivers/mmc/mmc.c
>>>>> @@ -347,17 +347,34 @@ sd_send_op_cond(struct mmc *mmc)
>>>>>
>>>>>  int mmc_send_op_cond(struct mmc *mmc)
>>>>>  {
>>>>> -       int timeout = 1000;
>>>>> +       int timeout = 10000;
>>>>>        struct mmc_cmd cmd;
>>>>>        int err;
>>>>>
>>>>>        /* Some cards seem to need this */
>>>>>        mmc_go_idle(mmc);
>>>>>
>>>>> +       /* Asking to the card its capabilities */
>>>>> +       do {
>>>>> +               cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>>>>> +               cmd.resp_type = MMC_RSP_R3;
>>>>> +               cmd.cmdarg = 0;
>>>>> +               cmd.flags = 0;
>>>>> +
>>>>> +               err = mmc_send_cmd(mmc, &cmd, NULL);
>>>>> +
>>>>> +               if (err)
>>>>> +                       return err;
>>>>> +
>>>>> +               udelay(1000);
>>>>> +       } while (!(cmd.response[0] & OCR_BUSY) && timeout--);
>>>>
>>>> I think you should not put the first probe a multi-time. In linux framework,
>>>> it would skip the first probing.
>>>>
>>>> I test with this patch and fail to detect my emmc card...
>>>> While just let the first probe once, it works fine.
>>>>
>>>> Best regards,
>>>> Lei
>>>>
>>>
>>> Look at JEDEC Standard No. 84-A441 document at page 190.
>>> It is normal to ask the card capabilities before setting.
>>> But I understand also that in your case there is some issue.
>>> I'm sorry, what does "multi-time" mean?
>>>
>>
>> I mean on my board I cannot get (!(cmd.response[0] & OCR_BUSY) to be
>> true for the first
>> MMC_CMD_SEND_OP_COND until its timeout, which lead to card init fail.
>>
>> Best regards,
>> Lei
>>
>
> This means 10msec are not enough.
> Even if a board dependent value should be better, can you find please
> the minimum value that it nice for your board?

It is not about the delay, it is about you shouldn't let the probe
perform multi-times.
As you also mention the JESD84-A44 doc, you could see the query mode only
perform _ONCE_, then continue to send SEND_OP_COND till card accept that.

So my point is that: in this patch, you shouldn't add a do{} while for
the first query.
Please remove it. As I test, my board works fine with the do{} while remove.

Best regards,
Lei
diff mbox

Patch

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 042653f..ded630b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -347,17 +347,34 @@  sd_send_op_cond(struct mmc *mmc)
 
 int mmc_send_op_cond(struct mmc *mmc)
 {
-	int timeout = 1000;
+	int timeout = 10000;
 	struct mmc_cmd cmd;
 	int err;
 
 	/* Some cards seem to need this */
 	mmc_go_idle(mmc);
 
+	/* Asking to the card its capabilities */
+	do {
+		cmd.cmdidx = MMC_CMD_SEND_OP_COND;
+		cmd.resp_type = MMC_RSP_R3;
+		cmd.cmdarg = 0;
+		cmd.flags = 0;
+
+		err = mmc_send_cmd(mmc, &cmd, NULL);
+
+		if (err)
+			return err;
+
+		udelay(1000);
+	} while (!(cmd.response[0] & OCR_BUSY) && timeout--);
+
 	do {
 		cmd.cmdidx = MMC_CMD_SEND_OP_COND;
 		cmd.resp_type = MMC_RSP_R3;
-		cmd.cmdarg = OCR_HCS | mmc->voltages;
+		cmd.cmdarg = ((mmc->voltages &
+			      (cmd.response[0] & OCR_VOLTAGE_MASK)) |
+			      (cmd.response[0] & OCR_ACCESS_MODE));
 		cmd.flags = 0;
 
 		err = mmc_send_cmd(mmc, &cmd, NULL);
diff --git a/include/mmc.h b/include/mmc.h
index 4ee8e1c..d18526d 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -93,6 +93,8 @@ 
 
 #define OCR_BUSY	0x80000000
 #define OCR_HCS		0x40000000
+#define OCR_VOLTAGE_MASK	0x007FFF80
+#define OCR_ACCESS_MODE		0x60000000
 
 #define MMC_STATUS_MASK		(~0x0206BF7F)
 #define MMC_STATUS_RDY_FOR_DATA (1<<8)